---
# System prepended metadata

title: K3S 寶典
tags: [work]

---

# 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`