吳東軒
  • NEW!
    NEW!  Connect Ideas Across Notes
    Save time and share insights. With Paragraph Citation, you can quote others’ work with source info built in. If someone cites your note, you’ll see a card showing where it’s used—bringing notes closer together.
    Got it
      • Create new note
      • Create a note from template
        • Sharing URL Link copied
        • /edit
        • View mode
          • Edit mode
          • View mode
          • Book mode
          • Slide mode
          Edit mode View mode Book mode Slide mode
        • Customize slides
        • Note Permission
        • Read
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Write
          • Only me
          • Signed-in users
          • Everyone
          Only me Signed-in users Everyone
        • Engagement control Commenting, Suggest edit, Emoji Reply
      • Invite by email
        Invitee

        This note has no invitees

      • Publish Note

        Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

        Your note will be visible on your profile and discoverable by anyone.
        Your note is now live.
        This note is visible on your profile and discoverable online.
        Everyone on the web can find and read all notes of this public team.

        Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

        Explore these features while you wait
        Complete general settings
        Bookmark and like published notes
        Write a few more notes
        Complete general settings
        Write a few more notes
        See published notes
        Unpublish note
        Please check the box to agree to the Community Guidelines.
        View profile
      • Commenting
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
        • Everyone
      • Suggest edit
        Permission
        Disabled Forbidden Owners Signed-in users Everyone
      • Enable
      • Permission
        • Forbidden
        • Owners
        • Signed-in users
      • Emoji Reply
      • Enable
      • Versions and GitHub Sync
      • Note settings
      • Note Insights New
      • Engagement control
      • Make a copy
      • Transfer ownership
      • Delete this note
      • Save as template
      • Insert from template
      • Import from
        • Dropbox
        • Google Drive
        • Gist
        • Clipboard
      • Export to
        • Dropbox
        • Google Drive
        • Gist
      • Download
        • Markdown
        • HTML
        • Raw HTML
    Menu Note settings Note Insights Versions and GitHub Sync Sharing URL Create Help
    Create Create new note Create a note from template
    Menu
    Options
    Engagement control Make a copy Transfer ownership Delete this note
    Import from
    Dropbox Google Drive Gist Clipboard
    Export to
    Dropbox Google Drive Gist
    Download
    Markdown HTML Raw HTML
    Back
    Sharing URL Link copied
    /edit
    View mode
    • Edit mode
    • View mode
    • Book mode
    • Slide mode
    Edit mode View mode Book mode Slide mode
    Customize slides
    Note Permission
    Read
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Write
    Only me
    • Only me
    • Signed-in users
    • Everyone
    Only me Signed-in users Everyone
    Engagement control Commenting, Suggest edit, Emoji Reply
  • Invite by email
    Invitee

    This note has no invitees

  • Publish Note

    Share your work with the world Congratulations! 🎉 Your note is out in the world Publish Note No publishing access yet

    Your note will be visible on your profile and discoverable by anyone.
    Your note is now live.
    This note is visible on your profile and discoverable online.
    Everyone on the web can find and read all notes of this public team.

    Your account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Your team account was recently created. Publishing will be available soon, allowing you to share notes on your public page and in search results.

    Explore these features while you wait
    Complete general settings
    Bookmark and like published notes
    Write a few more notes
    Complete general settings
    Write a few more notes
    See published notes
    Unpublish note
    Please check the box to agree to the Community Guidelines.
    View profile
    Engagement control
    Commenting
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    • Everyone
    Suggest edit
    Permission
    Disabled Forbidden Owners Signed-in users Everyone
    Enable
    Permission
    • Forbidden
    • Owners
    • Signed-in users
    Emoji Reply
    Enable
    Import from Dropbox Google Drive Gist Clipboard
       Owned this note    Owned this note      
    Published Linked with GitHub
    1
    • Any changes
      Be notified of any changes
    • Mention me
      Be notified of mention me
    • Unsubscribe
    # K3S 寶典 ![](https://i.imgur.com/trCCPWr.png) * 安裝 ``` $ curl -sfL https://get.k3s.io/ | INSTALL_K3S_VERSION=v1.27.4+k3s1 K3S_KUBECONFIG_MODE="644" sh -s - --disable=local-storage --disable=metrics-server ``` * K3s 的二進制文件大小約為 70MB,相較於標準的 Kubernetes 發行版來說非常小。它使用的系統資源也更少,適合在邊緣計算、嵌入式系統或資源受限的虛擬機器上運行。K3s 的部署速度也非常迅速,只需幾分鐘就可以啟動一個 Kubernetes 叢集。 * Kine 是 k3s 專門為了達到輕量化和效能優化而開發的自有儲存解決方案,它不使用傳統的儲存後端(例如 etcd 或 Consul)。相反,Kine 使用 SQLite 數據庫作為儲存引擎,通過在每個節點上存儲資源狀態的方式,實現 Kubernetes API 的持久化存儲。 * 因為 k8s 只會把叢集 metadata 存到 etcd,而透過 kine 可以把叢集 metadata 資料存到異質性的資料庫,讓企業可以選擇自己的資料庫,像是 mysql、sqlite、etcd 等。 * 因為 k3s 通常都是建置在 edge 環境,所以 k3s 透過 Tunnel proxy 來找到 node,而不是讓 kubelet 直接開對外的 port,建立的 tunnel 就是加密資料,可以保護傳輸的資料不被攻擊。不過加密會吃許多 CPU、記憶體資源,因為加密就是在做壓縮和解壓縮。 ``` $ curl -sfL https://get.k3s.io/ | INSTALL_K3S_VERSION=v1.25.7+k3s1 K3S_KUBECONFIG_MODE="644" sh - $ kubectl get no NAME STATUS ROLES AGE VERSION test Ready control-plane,master 36s v1.25.7+k3s1 $ kubectl api-resources NAME SHORTNAMES APIVERSION NAMESPACED KIND bindings v1 true Binding componentstatuses cs v1 false ComponentStatus configmaps cm v1 true ConfigMap ........ $ kubectl top node NAME CPU(cores) CPU% MEMORY(bytes) MEMORY% test 28m 1% 1483Mi 42% ``` * kubectl 是透過 `/etc/rancher/k3s/k3s.yaml` 這個檔案跟 k3s 溝通,並不是放在 `.kube/config` * 但是如果要使用 helm ,就會需要把 `k3s.yaml` 複製到 `.kube/config` ``` $ ls -l /etc/rancher/k3s/k3s.yaml -rw-r--r-- 1 root root 2957 Nov 30 03:48 /etc/rancher/k3s/k3s.yaml ``` ## 加入 worker * worker 上安裝 k3s 執行檔 * 注意執行檔版本要跟 k8s 一致 ``` $ wget https://github.com/k3s-io/k3s/releases/download/v1.27.4%2Bk3s1/k3s $ chmod +x k3s ``` * 在 master 上查看 token ``` $ sudo cat /var/lib/rancher/k3s/server/node-token K10f057c1ce3e24e2e851ff966d7494e0e038528f310979eaf634eff1ac51daf885::server:0b57d1704f199965bd3866b5e6330f26 ``` * 在 worker 上執行,指定要加入 master 的 ipw ``` $ sudo ./k3s agent --server https://192.168.11.105:6443 --token K10f057c1ce3e24e2e851ff966d7494e0e038528f310979eaf634eff1ac51daf885::server:0b57d1704f199965bd3866b5e6330f26 & [sudo] password for root: INFO[0000] Acquiring lock file /var/lib/rancher/k3s/data/.lock INFO[0000] Preparing data dir /var/lib/rancher/k3s/data/dc43f496a0a9ac19d3b2444d390db38e0cfb38e672721f838b075422b8734994 INFO[0000] Starting k3s agent v1.27.4+k3s1 (36645e73) ...... ``` * 幫 worker 些上標籤 ``` $ kubectl label node dw1 node-role.kubernetes.io/worker= node/dw1 labeled ``` ``` $ kubectl get no NAME STATUS ROLES AGE VERSION dm1 Ready control-plane,master 23m v1.27.4+k3s1 dw1 Ready worker 5m44s v1.27.4+k3s1 ``` * suse linux reboot 時自動啟動 k3s ``` # 要給執行權限 $ sudo cat /etc/init.d/boot.local #!/bin/bash sudo /home/rancher/k3s agent --server https://192.168.11.105:6443 --token K10f057c1ce3e24e2e851ff966d7494e0e038528f310979eaf634eff1ac51daf885::server:0b57d1704f199965b ``` ## alpine up board 加入 worker ``` $ wget https://github.com/k3s-io/k3s/releases/download/v1.27.4%2Bk3s1/k3s $ chmod +x k3s $ echo "cgroup_memory=1 cgroup_enable=memory" >> /boot/cmdline.txt # alpine 需要開啟 cgroup $ sudo rc-update add cgroups $ sudo rc-service cgroups start ``` ## 加入 worker ``` $ sudo ./k3s agent --server https://10.40.41.101:6443 --token K108bf39e8fc757dfe3a713e5a38dbbe987c1f242bba6334f82487ac5a626422f3f::server:53b04590aa6263f92c9d2218ec4bff45 & ``` ## 樹梅派設定 cgroup ``` # 新增 cgroup_memory=1 cgroup_enable=memory $ cat /boot/cmdline.txt console=serial0,115200 console=tty1 root=PARTUUID=d7d3c80e-02 rootfstype=ext4 fsck.repair=yes rootwait quiet splash plymouth.ignore-serial-consoles cfg80211.ieee80211_regdom=TW cgroup_memory=1 cgroup_enable=memory $ reboot ``` ## 移除 k3s * 刪除 master ``` # systemctl stop k3s.service # /usr/local/bin/k3s-killall.sh # /usr/local/bin/k3s-uninstall.sh * 移除目錄 $ sudo rm -rf /etc/ceph \ /etc/cni \ /etc/kubernetes \ /etc/rancher \ /opt/cni \ /opt/rke \ /run/secrets/kubernetes.io \ /run/calico \ /run/flannel \ /var/lib/calico \ /var/lib/etcd \ /var/lib/cni \ /var/lib/kubelet \ /var/lib/rancher\ /var/log/containers \ /var/log/kube-audit \ /var/log/pods \ /var/run/calico # reboot ``` * 刪除 worker ``` # /usr/local/bin/k3s-agent-uninstall.sh ``` ## 參數設定 ``` curl -sfL https://get.k3s.io | INSTALL_K3S_VERSION=${K3S_VERSION} \ INSTALL_K3S_EXEC="\ --flannel-backend=none \ --disable=servicelb \ --disable=traefik \ --disable-network-policy \ --cluster-cidr=$CLUSTER_CIDR \ --service-cidr=$SERVICE_CIDR \ --cluster-dns=$CLUSTER_DNS \ --datastore-endpoint=etcd \ --node-ip=$NODE_IP \ --data-dir=/opt/rancher/k3s \ --write-kubeconfig-mode=$K3S_KUBECONFIG_MODE \ --kube-apiserver-arg=default-not-ready-toleration-seconds=5 \ --kube-apiserver-arg=default-unreachable-toleration-seconds=5 \ --kube-controller-manager-arg=node-monitor-period=2s \ --kube-controller-manager-arg=node-monitor-grace-period=20s \ --kube-controller-manager-arg=pod-eviction-timeout=5s \ --kubelet-arg=node-status-update-frequency=4s \ --kube-proxy-arg=proxy-mode=ipvs \ " \ sh -s - server --cluster-init ``` ## 查看資源 ``` $ ps -eo user,pid,cmd,%mem,%cpu | head -n 1;ps -eo user,pid,cmd,%mem,%cpu | grep -v grep | grep "/usr/local/bin/k3s server" USER PID CMD %MEM %CPU root 12176 /usr/local/bin/k3s server 10.1 25.2 ``` ## k3s 自我檢查 * 使用 k3s 命令檢查 ``` $ k3s check-config cat: /sys/kernel/security/apparmor/profiles: No such file or directory Verifying binaries in /var/lib/rancher/k3s/data/862d15a37357a297d9e0dbbd282cb581265660f14ec13667a58a7ccb63ce3da5/bin: - sha256sum: good - links: good ...... STATUS: pass ``` ## 檢查 k3s 的 etcd * 撰寫安裝腳本 ``` $ cat <<EOF > install-etcd.sh #!/bin/bash ETCD_VER=v3.4.13 # choose either URL GOOGLE_URL=https://storage.googleapis.com/etcd GITHUB_URL=https://github.com/etcd-io/etcd/releases/download DOWNLOAD_URL=${GOOGLE_URL} rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz rm -rf /tmp/etcd-download-test && mkdir -p /tmp/etcd-download-test curl -L ${DOWNLOAD_URL}/${ETCD_VER}/etcd-${ETCD_VER}-linux-amd64.tar.gz -o /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz tar xzvf /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz -C /usr/local/bin --strip-components=1 rm -f /tmp/etcd-${ETCD_VER}-linux-amd64.tar.gz etcd --version etcdctl version EOF ``` * 開始安裝 ``` $ chmod +x install-etcd.sh $ ./install-etcd.sh ``` * 檢查 etcd 效能 ``` $ ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl check perf ``` * 檢查 etcd endpoint 狀態 ``` $ ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl endpoint status --cluster --write-out=table ``` * 檢查 etcd endpoint 是否健康 ``` $ ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl endpoint health --cluster --write-out=table ``` * 列出 etcd 告警 ``` $ ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl alarm list ``` * 執行壓縮操作 etcd ``` $ rev=$(ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl endpoint status --write-out fields | grep Revision | cut -d: -f2) ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl compact $rev ``` * etcd 碎片整理,將分散在磁盤上的數據塊重新排列,使其更加緊湊,從而提高 etcd 的讀寫性能和磁盤空間利用率。 ``` $ ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl defrag --cluster ``` * etcd 集群中獲取以 "/" 為前綴的所有鍵名,並以列表形式輸出 ``` $ ETCDCTL_ENDPOINTS='https://127.0.0.1:2379' ETCDCTL_CACERT='/var/lib/rancher/k3s/server/tls/etcd/server-ca.crt' ETCDCTL_CERT='/var/lib/rancher/k3s/server/tls/etcd/server-client.crt' ETCDCTL_KEY='/var/lib/rancher/k3s/server/tls/etcd/server-client.key' ETCDCTL_API=3 etcdctl get / --prefix --keys-only ``` * 列出 etcd 版本 ``` $ curl -L --cacert /var/lib/rancher/k3s/server/tls/etcd/server-ca.crt --cert /var/lib/rancher/k3s/server/tls/etcd/server-client.crt --key /var/lib/rancher/k3s/server/tls/etcd/server-client.key https://127.0.0.1:2379/version ``` ## k3s troubleshooting(阿胖寶解決) ![image](https://hackmd.io/_uploads/Sy-xAvfe0.png) * 解決辦法,加入 `INSTALL_K3S_SKIP_SELINUX_RPM=true INSTALL_K3S_SELINUX_WARN=true` ``` $ curl -sfL https://get.k3s.io | INSTALL_K3S_SKIP_SELINUX_RPM=true INSTALL_K3S_SELINUX_WARN=true K3S_KUBECONFIG_MODE="644" sh - ``` ## Backup and Restore(SQLite) * 建立測試用 pod ``` $ kubectl run test --image=nginx $ kubectl get po NAME READY STATUS RESTARTS AGE test 1/1 Running 0 41s ``` * SQLite 只需要備份 `/var/lib/rancher/k3s/server` 這個目錄即可 ``` $ ls -l /var/lib/rancher/k3s/server total 12 drwx------ 1 root root 240 Aug 16 13:52 cred drwx------ 1 root root 64 Aug 16 13:52 db srw------- 1 root root 0 Aug 16 13:52 kine.sock drwx------ 1 root root 162 Aug 16 13:52 manifests lrwxrwxrwx 1 root root 33 Aug 16 13:52 node-token -> /var/lib/rancher/k3s/server/token drwx------ 1 root root 12 Aug 16 13:52 static drwx------ 1 root root 1180 Aug 16 13:52 tls -rw------- 1 root root 109 Aug 16 13:52 token $ tar czvf k3sbk.tar.gz /var/lib/rancher/k3s/server $ ls -lah k3sbk.tar.gz -rw-r--r-- 1 root root 1.4M Aug 16 13:56 k3sbk.tar.gz ``` * 測試還原,將 pod 刪除 ``` $ kubectl delete po test pod "test" deleted ``` ``` $ tar zxvf k3sbk.tar.gz -C / $ ls -l /var/lib/rancher/k3s/server/ total 12 drwx------ 1 root root 240 Aug 16 13:52 cred drwx------ 1 root root 64 Aug 16 13:52 db srw------- 1 root root 0 Aug 16 14:06 kine.sock drwx------ 1 root root 162 Aug 16 13:52 manifests lrwxrwxrwx 1 root root 33 Aug 16 13:52 node-token -> /var/lib/rancher/k3s/server/token drwx------ 1 root root 12 Aug 16 13:52 static drwx------ 1 root root 1180 Aug 16 13:52 tls -rw------- 1 root root 109 Aug 16 14:06 token ``` * 重啟 k3s 並確認 pod 是否恢復 ``` $ systemctl restart k3s $ kubectl get po NAME READY STATUS RESTARTS AGE test 1/1 Running 0 13m ``` ## k3s 高可用安裝 * 建立第一個 K3S Master ``` $ curl -sfL https://get.k3s.io | K3S_TOKEN="mysecret" K3S_KUBECONFIG_MODE="644" sh -s server --cluster-init ``` * 建立其他 K3S Master ``` $ curl -sfL https://get.k3s.io | K3S_TOKEN="mysecret" K3S_URL="https://192.168.11.52:6443" K3S_KUBECONFIG_MODE="644" sh -s server ``` * 建立 K3S worker ``` $ curl -sfL https://get.k3s.io | K3S_TOKEN="mysecret" K3S_URL="https://192.168.11.52:6443" K3S_KUBECONFIG_MODE="644" sh -s - ``` ## 檢視憑證 ``` $ ls -l /var/lib/rancher/k3s/server/tls/ total 112 -rw-r--r-- 1 root root 1177 Oct 16 2025 client-admin.crt -rw------- 1 root root 227 Oct 16 2025 client-admin.key -rw-r--r-- 1 root root 1178 Oct 16 2025 client-auth-proxy.crt -rw------- 1 root root 227 Oct 16 2025 client-auth-proxy.key -rw-r--r-- 1 root root 570 Aug 22 13:33 client-ca.crt -rw------- 1 root root 227 Aug 22 13:33 client-ca.key -rw-r--r-- 1 root root 1165 Oct 16 2025 client-controller.crt -rw------- 1 root root 227 Oct 16 2025 client-controller.key -rw-r--r-- 1 root root 1161 Oct 16 2025 client-k3s-cloud-controller.crt -rw------- 1 root root 227 Oct 16 2025 client-k3s-cloud-controller.key -rw-r--r-- 1 root root 1153 Oct 16 2025 client-k3s-controller.crt -rw------- 1 root root 227 Oct 16 2025 client-k3s-controller.key -rw-r--r-- 1 root root 1177 Oct 16 2025 client-kube-apiserver.crt -rw------- 1 root root 227 Oct 16 2025 client-kube-apiserver.key -rw------- 1 root root 227 Aug 22 13:33 client-kubelet.key -rw-r--r-- 1 root root 1149 Oct 16 2025 client-kube-proxy.crt -rw------- 1 root root 227 Oct 16 2025 client-kube-proxy.key -rw-r--r-- 1 root root 1153 Oct 16 2025 client-scheduler.crt -rw------- 1 root root 227 Oct 16 2025 client-scheduler.key -rw-r--r-- 1 root root 3357 Aug 22 13:36 dynamic-cert.json drwxr-xr-x 1 root root 292 Aug 22 13:33 etcd -rw-r--r-- 1 root root 591 Aug 22 13:33 request-header-ca.crt -rw------- 1 root root 227 Aug 22 13:33 request-header-ca.key -rw-r--r-- 1 root root 566 Aug 22 13:33 server-ca.crt -rw------- 1 root root 227 Aug 22 13:33 server-ca.key -rw------- 1 root root 1679 Aug 22 13:33 service.key -rw-r--r-- 1 root root 1356 Oct 16 2025 serving-kube-apiserver.crt -rw------- 1 root root 227 Oct 16 2025 serving-kube-apiserver.key -rw------- 1 root root 227 Aug 22 13:33 serving-kubelet.key drwx------ 1 root root 124 Aug 22 13:33 temporary-certs $ openssl x509 -in /var/lib/rancher/k3s/server/tls/server-ca.crt -noout -text ``` ## 開啟 debug ``` $ vim /etc/rancher/k3s/config.yaml debug: true $ systemctl restart k3s.service ``` #### 連結 https://gist.github.com/superseb/0c06164eef5a097c66e810fe91a9d408 ###### tags: `work`

    Import from clipboard

    Paste your markdown or webpage here...

    Advanced permission required

    Your current role can only read. Ask the system administrator to acquire write and comment permission.

    This team is disabled

    Sorry, this team is disabled. You can't edit this note.

    This note is locked

    Sorry, only owner can edit this note.

    Reach the limit

    Sorry, you've reached the max length this note can be.
    Please reduce the content or divide it to more notes, thank you!

    Import from Gist

    Import from Snippet

    or

    Export to Snippet

    Are you sure?

    Do you really want to delete this note?
    All users will lose their connection.

    Create a note from template

    Create a note from template

    Oops...
    This template has been removed or transferred.
    Upgrade
    All
    • All
    • Team
    No template.

    Create a template

    Upgrade

    Delete template

    Do you really want to delete this template?
    Turn this template into a regular note and keep its content, versions, and comments.

    This page need refresh

    You have an incompatible client version.
    Refresh to update.
    New version available!
    See releases notes here
    Refresh to enjoy new features.
    Your user state has changed.
    Refresh to load new user state.

    Sign in

    Forgot password
    or
    Sign in via Google Sign in via Facebook Sign in via X(Twitter) Sign in via GitHub Sign in via Dropbox Sign in with Wallet
    Wallet ( )
    Connect another wallet

    New to HackMD? Sign up

    By signing in, you agree to our terms of service.

    Help

    • English
    • 中文
    • Français
    • Deutsch
    • 日本語
    • Español
    • Català
    • Ελληνικά
    • Português
    • italiano
    • Türkçe
    • Русский
    • Nederlands
    • hrvatski jezik
    • język polski
    • Українська
    • हिन्दी
    • svenska
    • Esperanto
    • dansk

    Documents

    Help & Tutorial

    How to use Book mode

    Slide Example

    API Docs

    Edit in VSCode

    Install browser extension

    Contacts

    Feedback

    Discord

    Send us email

    Resources

    Releases

    Pricing

    Blog

    Policy

    Terms

    Privacy

    Cheatsheet

    Syntax Example Reference
    # Header Header 基本排版
    - Unordered List
    • Unordered List
    1. Ordered List
    1. Ordered List
    - [ ] Todo List
    • Todo List
    > Blockquote
    Blockquote
    **Bold font** Bold font
    *Italics font* Italics font
    ~~Strikethrough~~ Strikethrough
    19^th^ 19th
    H~2~O H2O
    ++Inserted text++ Inserted text
    ==Marked text== Marked text
    [link text](https:// "title") Link
    ![image alt](https:// "title") Image
    `Code` Code 在筆記中貼入程式碼
    ```javascript
    var i = 0;
    ```
    var i = 0;
    :smile: :smile: Emoji list
    {%youtube youtube_id %} Externals
    $L^aT_eX$ LaTeX
    :::info
    This is a alert area.
    :::

    This is a alert area.

    Versions and GitHub Sync
    Get Full History Access

    • Edit version name
    • Delete

    revision author avatar     named on  

    More Less

    Note content is identical to the latest version.
    Compare
      Choose a version
      No search result
      Version not found
    Sign in to link this note to GitHub
    Learn more
    This note is not linked with GitHub
     

    Feedback

    Submission failed, please try again

    Thanks for your support.

    On a scale of 0-10, how likely is it that you would recommend HackMD to your friends, family or business associates?

    Please give us some advice and help us improve HackMD.

     

    Thanks for your feedback

    Remove version name

    Do you want to remove this version name and description?

    Transfer ownership

    Transfer to
      Warning: is a public team. If you transfer note to this team, everyone on the web can find and read this note.

        Link with GitHub

        Please authorize HackMD on GitHub
        • Please sign in to GitHub and install the HackMD app on your GitHub repo.
        • HackMD links with GitHub through a GitHub App. You can choose which repo to install our App.
        Learn more  Sign in to GitHub

        Push the note to GitHub Push to GitHub Pull a file from GitHub

          Authorize again
         

        Choose which file to push to

        Select repo
        Refresh Authorize more repos
        Select branch
        Select file
        Select branch
        Choose version(s) to push
        • Save a new version and push
        • Choose from existing versions
        Include title and tags
        Available push count

        Pull from GitHub

         
        File from GitHub
        File from HackMD

        GitHub Link Settings

        File linked

        Linked by
        File path
        Last synced branch
        Available push count

        Danger Zone

        Unlink
        You will no longer receive notification when GitHub file changes after unlink.

        Syncing

        Push failed

        Push successfully