# Setup K3D on Alpine Linux ## 1. Prerequest - [x] 已安裝 Alpine Linux 3.20.x ## 2. 環境準備 以下環境設定會使用 `Podman` 而不是 `Docker`,因為 Podman 有 [Docker API compatibility layer](https://podman.io/blogs/2020/06/29/podman-v2-announce.html#restful-api)。 k3d 使用 Docker API 與 Podman v4 或更新版相容. ```bash! # 2.1. 新增套件儲存庫 (請使用 root 執行) $ echo 'http://dl-cdn.alpinelinux.org/alpine/latest-stable/main/ http://dl-cdn.alpinelinux.org/alpine/latest-stable/community/' > /etc/apk/repositories # 2.2. 更新套件,並安裝 Podman $ apk update && apk upgrade && \ apk add podman curl nano iptables-legacy sudo && exit # 2.3. 確認 CGroup 版本為 v2 $ cat /etc/rc.conf | grep "rc_cgroup_mode" #rc_cgroup_mode="unified" > [註] "unified" mounts cgroups version 2 on /sys/fs/cgroup # 2.4. Enable and start the cgroups and podman services $ sudo rc-update add cgroups && \ sudo rc-service cgroups start && \ sudo rc-update add podman # 2.5. Setup rootless mode with Podman $ echo "$USER":500000:65536 | sudo tee /etc/subuid && \ echo "$USER":500000:65536 | sudo tee /etc/subgid # 2.6. load needed kernel modules $ echo -e "tun\nfuse\nip_tables\nip_vs\nbridge\nbr_netfilter" | sudo tee -a /etc/modules # 2.7. 設定開機自動建置 Podman Socket 軟連結 $ sudo rc-update add local && \ echo '[[ -h /var/run/docker.sock ]] || ln -s /run/podman/podman.sock /var/run/docker.sock' | sudo tee /etc/local.d/rc.local.start && \ sudo chmod +x /etc/local.d/rc.local.start # 2.8. 重啟主機 $ sudo reboot # 2.9. 檢查需要的 Service 開機會自動啟動 $ sudo rc-status | grep -Ew "podman|local|cgroups" cgroups [ started ] podman [ started 00:03:15 (0) ] local [ started ] # 2.10. 檢查 Podman Socket 軟連結是否存在 $ ls -l /var/run/docker.sock lrwxrwxrwx 1 root root 23 Jul 22 09:59 /var/run/docker.sock -> /run/podman/podman.sock # 2.11. 下載與設定 kubectl 命令 $ curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl" && \ sudo chmod +x kubectl && \ sudo mv kubectl /usr/local/bin/ # 2.12. 確認 kubectl 版本 $ kubectl version --client Client Version: v1.30.3 Kustomize Version: v5.0.4-0.20230601165947-6ce0bf390ce3 # 2.13. 安裝當前最新版本的 k3d $ wget -q -O - https://raw.githubusercontent.com/k3d-io/k3d/main/install.sh | bash # 2.14. 檢查 k3d 版本 $ k3d version k3d version v5.7.2 k3s version v1.29.6-k3s2 (default) # 2.15. 設定 IPVS Mode $ sudo apk add dpkg && \ sudo update-alternatives --install /sbin/ip6tables ip6tables /sbin/iptables-legacy 10 --slave /sbin/ip6tables-restore ip6tables-restore /sbin/ip6tables-legacy-restore --slave /sbin/ip6tables-save ip6tables-save /sbin/ip6tables-legacy-save # 2.16. 建立 Podman Network $ sudo podman network create --subnet 172.22.1.0/24 --gateway 172.22.1.254 --subnet fd52:2a5a:747e:3acd::/64 --gateway fd52:2a5a:747e:3acd::10 c29-network ``` ## 3. Building a customized K3s image ```! # 1. 建立工作目錄區 $ mkdir -p k3d/{bin,config/{c24/addon,c29/addon},wulin} > [註] 以上命令需要由 Bash Shell 執行才會在 k3d 目錄區底下分別建立那 3 個子目錄 # 2. 設定 K3s 的 Containerd 能夠到 dkreg 下載 Container Images $ echo 'server = "http://dkreg.kube-system:5000" [host."http://dkreg.kube-system:5000"] capabilities = ["pull", "resolve", "push"] skip_verify = true' > ~/k3d/config/c29/hosts.toml # 3. $ echo '{{ template "base" . }} # RuntimeClass Handler [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc] runtime_type = "io.containerd.runsc.v1" [plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runsc.options] BinaryName = "/usr/bin/runsc"' > ~/k3d/config/c29/config.toml.tmpl # 3. 編輯 Containerfile $ nano config/c29/Containerfile # 4. Build Container Image $ sudo podman build --no-cache -t k3s-add-runtime:v1.29.6-k3s1 ~/k3d/config/c29/ ``` ### 3.1. Containerfile: ```yaml! ARG K3S_TAG="v1.29.6-k3s1" ARG ALPINE_TAG="3.20.2" FROM docker.io/rancher/k3s:$K3S_TAG as k3s FROM docker.io/library/alpine:$ALPINE_TAG # Install OCI runtime spec (crun, runsc) RUN apk -U add crun bash && \ ARCH=$(uname -m); URL=https://storage.googleapis.com/gvisor/releases/release/latest/${ARCH} && \ wget ${URL}/runsc ${URL}/runsc.sha512 ${URL}/containerd-shim-runsc-v1 ${URL}/containerd-shim-runsc-v1.sha512 && \ rm -f *.sha512 && \ chmod a+rx runsc containerd-shim-runsc-v1; mv runsc containerd-shim-runsc-v1 /usr/bin COPY --from=k3s / / # Configuring containerd with Base template RUN mkdir -p /var/lib/rancher/k3s/agent/etc/containerd/cert.d/dkreg.kube-system:5000 COPY config.toml.tmpl /var/lib/rancher/k3s/agent/etc/containerd/ COPY hosts.toml /var/lib/rancher/k3s/agent/etc/containerd/cert.d/dkreg.kube-system:5000/ VOLUME /var/lib/kubelet VOLUME /var/lib/rancher/k3s VOLUME /var/lib/cni VOLUME /var/log ENV PATH="$PATH:/bin/aux" ENTRYPOINT ["/bin/k3s"] CMD ["agent"] ``` ## 4. 撰寫 k3d 叢集設定檔 ```bash! # 4.1. 編輯 k3d 叢集設定檔 $ nano ~/k3d/config/c29/c29.yaml apiVersion: k3d.io/v1alpha5 kind: Simple metadata: name: c29 servers: 1 agents: 2 kubeAPI: host: "k1.org" hostIP: "0.0.0.0" hostPort: "6443" #image: docker.io/rancher/k3s:v1.29.6-k3s1 image: localhost/k3s-add-runtime:v1.29.6-k3s1 network: c29-network token: c29Token volumes: - volume: /home/bigred/k3d/wulin:/opt/kadm nodeFilters: - "server:0" # - volume: /home/bigred/k3d/cni:/opt/cni/bin # nodeFilters: # - "server:*" # - "agent:*" # - volume: /lib/modules:/lib/modules # nodeFilters: # - "server:*" # - "agent:*" files: - description: 'Canal v1.27.3 Manifests' source: addon/canal-v1.27.3.yaml destination: /var/lib/rancher/k3s/server/manifests/canal.yaml nodeFilters: - "server:0" - description: 'Runtime Class: crun, runsc' source: addon/runtimeclass.yaml destination: /var/lib/rancher/k3s/server/manifests/runtimeclass.yaml nodeFilters: - "server:0" ports: - port: 22100:22100 nodeFilters: - "server:0" - port: 5000:5000 nodeFilters: - "server:0" - port: 8080:8080 nodeFilters: - "server:0" - port: 9000:9000 nodeFilters: - "server:0" - port: 80:80 nodeFilters: - "server:0" - port: 443:443 nodeFilters: - "server:0" hostAliases: - ip: 1.1.1.1 hostnames: - cloud.flare.dns options: k3d: wait: true timeout: "60s" disableLoadbalancer: false disableImageVolume: false disableRollback: true k3s: extraArgs: - arg: "--cluster-cidr=10.244.0.0/16" nodeFilters: - server:* - arg: "--service-cidr=10.98.0.0/16" nodeFilters: - server:* # - arg: "--kube-proxy-arg=proxy-mode=ipvs" # nodeFilters: # - server:* # - agent:* - arg: "--egress-selector-mode=disabled" nodeFilters: - server:* - arg: "--disable=traefik" nodeFilters: - server:* - arg: "--flannel-backend=none" nodeFilters: - server:* - arg: "--disable-network-policy" nodeFilters: - server:* nodeLabels: - label: app=taroko nodeFilters: - "server:0" kubeconfig: updateDefaultKubeconfig: true switchCurrentContext: true ``` ### 4.1. 設定檔欄位解釋 - `apiVersion: k3d.io/v1alpha5`,設定檔的版本,這將會在未來改變,因為我們會讓一切變得更穩定,這是必填的欄位。 - `kind: Simple`,定義要使用的設定檔案類型,在內部也有 Cluster 的設定,但尚未對外提供,這是必填的欄位。 - `metadata`,定義設定檔的重要資訊。 - `name`,要賦予 K3D 叢集的名稱 (仍將以 `k3d-` 為前綴)。 - `servers`,定義要幾台 Control-plane 節點。 - `agents`,定義要幾台 Worker 節點。 - `kubeAPI` - `host`,定義 K3D 叢集的 Domain name - `hostIP`,將監聽 Kubernetes API 的位置 - `hostPort`,Kubernetes API 在 Host 主機系統上監聽連接埠的對應位置 - `image`,定義要使用哪一個版本 Container Image 來建立 K3s - `network`,使用已經存在的 Podman Netwrok,如果沒有則會建立新的 Podman Netwrok - `subnet`,為新建立的 Cotainer 網路定義子網路 - `token`,指定叢集的 Token,K3s 使用 Token 來保護節點加入過程,Token 會在叢集加入新節點時進行身分驗證的動作。 - `volumes`,定義在 Host 主機有哪些 Volume 要掛載進 K3D 的節點。 - `volume`,指定 Host 主機的目錄區,將之掛載到 K3D 的節點中。 - 格式 : `/my/host/path:/path/in/node` - `nodeFilters`,定義要將 Volume 掛載到哪些 K3D 的節點中。 - 格式 : `server:0` (第一台 Control-plane),也可以用 `*` 代表每一台 Control-plane。 - `ports`,定義 K3d 叢集有哪些 Ports 要 Mapping 出來到 Host 主機。 - `port`,將 K3s 節點 (Container) 的 ports 透過 serverlb 這台 Loadbalancer Maping 到 Host 主機的 ports (via the serverlb) - 格式 : `HOSTPORT:CONTAINERPORT` - `nodeFilters`,定義要將哪一台 K3s 的節點中的 Port Mapping 到 Host 主機上。 - 格式 : `loadbalancer` - `env`,將環境變數加入節點。 - `envVar`,宣告要定義的環境變數。 - Example: `bar=baz` - `nodeFilters`,定義要將環境變數加入哪台 K3d 節點。 - Example: `server:0` - `files`,定義要自動部屬哪些 Workload 在 K3d 叢集中。 - `description`,描述 Workload 的字串 - `source`,Workload 的 Yaml 檔內容,格式可以直接是檔案內容,或給檔案名稱。 - Example1 : ``` source: | apiVersion: v1 kind: Namespace metadata: name: foo ``` - Example2 : ``` source: ns-baz.yaml ``` - `destination`,Workload 的 Yaml 檔儲存在 K3d 節點中的哪個目錄區。 - 格式: 可以是絕對路徑或相對路徑。 - Example1 : ``` destination: k3s-manifests-custom/foo.yaml ``` Workload 的 Yaml 檔實際會被存儲存成 `/var/lib/rancher/k3s/server/manifests/custom/foo.yaml` - Example2 : ``` destination: /var/lib/rancher/k3s/server/manifests/baz.yaml nodeFilters: - "server:*" ``` 用絕對路徑定義 Workload 的 Yaml 檔,並指定要儲存在哪些 K3d 的節點上。 - `hostAliases`,定義要寫入到 K3D 叢集結點中的 `/etc/hosts` 檔案內容和 CoreDNS 的 NodeHosts 部分中 - `ip`,服務的 IP Address - `hostnames`,服務的名稱 - `options` - `k3d`,k3d runtime 的設定 - `wait: true`,等待群集可用後才返回 - `timeout: "60s"`,定義建置 K3D 叢集超時的時間,如果超過時間會停止建立的動作。 - `disableLoadbalancer: false`,停用在 Contol-plane 節點前面建立 LoadBalancer。 - `disableImageVolume: false`,不要為 K3D 節點的根檔案系統建立永存的 Volume - `disableRollback: false`,如果叢集建立失敗,不要回溯變更。 - `loadbalancer`,設定 Nginx Loadbalancer 的設定檔 - `configOverrides`,要覆蓋的設定值 - Example: `settings.workerConnections=2048` - `k3s`,設定 K3s 本身 - `extraArgs`,傳給 `k3s server|agent` 指令的附加參數;與 `--k3s-arg` 相同 - Example: ``` k3s: extraArgs: - arg: "--tls-san=my.host.domain" nodeFilters: - server:* ``` - `nodeLabels`,定義要對哪一台 K3s 的節點貼上標籤 - Example: ``` nodeLabels: - label: foo=bar nodeFilters: - agent:1 ``` - `kubeconfig`,設定 KubeConfig - `updateDefaultKubeconfig: true`,會把建立好的 K3s 叢集加到預設的 KubeConfig 檔案中。 - `switchCurrentContext: true`,會將 KubeConfig 檔中的 Current Context 切換到新建立好的叢集。 - `runtime`,設定 Container Runtime (Podman/Docker) - `gpuRequest: all`,要新增至 K3s 叢集節點的 GPU 裝置。 - `all` 會把所有 GPU 裝置都掛載進去。 - `labels`,要對 Host 主機上的 K3s 節點 (Conttainer) 貼哪些標籤。 - Example: ``` labels: - label: bar=baz nodeFilters: - agent:1 ``` - `ulimits`,設定 Process 的資源 - `name: nofile`,限制 Open File 的數量 (max number of open file descriptors) - `soft: 26677`,在任何指定時間內,允許一個程序使用的最大的 Open File 數量。 - `hard: 26677`,即使暫時超過 soft limit,程序仍可使用的最大的 Open File 數量。 > 例如,預設情況下,一個程序可以擁有的開啟檔案數量的 soft limit 是 1024。這表示一個程序在任何時候最多可以有 1024 個開啟的檔案。但是,如果程序嘗試開啟超過 1024 個檔案,則不允許這樣做。預設開啟檔案數量的 hard limit 為 4096。這表示,即使暫時超過 1024 的 soft limit,程序開啟的檔案也不會超過 4096 個。 > soft limit 之所以有用,是因為它們允許程序暫時超過其限制而不會造成問題。例如,Web 伺服器在處理大量流量時,可能需要開啟大量檔案。soft limit 允許網頁伺服器在不當機的情況下執行此動作。但是,hard limit 可以防止 Web 伺服器使用過多資源而導致系統出現問題。 > soft limit 和 hard limit 可以為每個使用者和每個程序設定。預設限制由系統管理員設定,但使用者可以變更自己的限制。要變更 soft limit 或hard limit,可以使用 `ulimit` 指令。 ## 5. 準備 Auto-Deploying Manifests ```! $ wget --no-check-certificate --no-cache -P ~/k3d/config/c29/addon/ https://raw.githubusercontent.com/projectcalico/calico/v3.28.0/manifests/canal.yaml ``` ## 6. 在 K3s 中甚麼是 Tunnel Proxy? 為什麼要使用它? K8s 為什麼沒有? 在 K3s 中預設都會有 Tunnel Proxy,它的功能是讓 API Server 和 Worker Node 節點之間做溝通。 因為 K3s 在設計的時候是給
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up