Kind: 如何快速搭建本地 K8s 開(kāi)發(fā)環(huán)境?
上篇文章中我們講到了 k8s 中有哪些擴(kuò)展點(diǎn),開(kāi)始 Operator 開(kāi)發(fā)相關(guān)之前我們需要先把本地環(huán)境搭建好
一、依賴檢查
開(kāi)始之前需要先檢查一下
1.是否已經(jīng)安裝好了 Docker 環(huán)境
- 如果還沒(méi)安裝 Mac/Windows 的用戶可以直接安裝 Docker Desktop
- Windows 用戶推薦使用 WSL2
2.是否已經(jīng)安裝好了 Golang 環(huán)境, Go 版本最好 >= 1.15
- 如果沒(méi)有可以參考官方文檔進(jìn)行安裝
二、使用 Kind 搭建本地開(kāi)發(fā)環(huán)境
2.1 安裝
如果本地存在 Golang 環(huán)境可以直接執(zhí)行下方命令進(jìn)行安裝
- GO111MODULE="on" go get sigs.k8s.io/kind@v0.10.0 && kind create cluster
如果不想通過(guò)源碼安裝可以查看官方文檔直接安裝編譯好的二進(jìn)制文件
執(zhí)行下方命令可以輸出 kind 的版本就表示安裝好了
- ❯ kind version
- kind v0.10.0 go1.16 linux/amd64
2.2 創(chuàng)建一個(gè) K8s 集群
使用下方命令即可創(chuàng)建一個(gè)簡(jiǎn)單的單節(jié)點(diǎn) K8s 集群
- node create clutser
集群的創(chuàng)建時(shí)間和你的網(wǎng)絡(luò)環(huán)境以及機(jī)器的性能有關(guān)系,kind 會(huì)去 docker hub 上拉取 kindest/node 鏡像,這個(gè)鏡像大概有 400M 的大小,當(dāng)出現(xiàn)下方的提示的時(shí)候就說(shuō)明集群創(chuàng)建好了
- ❯ kind create cluster
- Creating cluster "kind" ...
- ✓ Ensuring node image (kindest/node:v1.20.2) 🖼
- ✓ Preparing nodes 📦
- ✓ Writing configuration 📜
- ✓ Starting control-plane 🕹️
- ✓ Installing CNI 🔌
- ✓ Installing StorageClass 💾
- Set kubectl context to "kind-kind"
- You can now use your cluster with:
- kubectl cluster-info --context kind-kind
- Thanks for using kind! 😊
我們可以使用 kind get clusters 獲取我們創(chuàng)建的集群列表,kind 支持創(chuàng)建多個(gè)集群,不手動(dòng)指定集群名稱的時(shí)候默認(rèn)名為 kind ,我們也可以像下面一樣在創(chuàng)建集群的時(shí)候使用 --name 指定集群名稱
- kind create cluster --name mohuishou
可以看到我們兩個(gè)集群都創(chuàng)建好了
- ❯ kind get clusters
- kind
- mohuishou
現(xiàn)在我們只需要一個(gè)集群,所以可以先使用 kind delete clusters mohuishou 將剛剛創(chuàng)建的集群先刪除掉
2.3 使用集群
下面我們來(lái)看一下 kubectl 的常用命令是否都可以正常使用,并且部署一個(gè)簡(jiǎn)單的 web 服務(wù)試試
查看集群信息
- ❯ kubectl cluster-info --context kind-kind
- Kubernetes master is running at https://127.0.0.1:41801
- KubeDNS is running at https://127.0.0.1:41801/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
- To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
可以看到我們 k8s master 地址和 dns 的地址,注意一般情況下我們只創(chuàng)建一個(gè)集群不需要指定 --context cluster name 但是創(chuàng)建了多個(gè)集群時(shí)這個(gè)基本就是必須的一個(gè)命令了。如果不加這個(gè)參數(shù)可能會(huì)報(bào)下面的錯(cuò)誤
- The connection to the server localhost:8080 was refused - did you specify the right host or port?
這是因?yàn)?kubectl默認(rèn)連接的 apiserver 地址是 localhost:8080但是我們的 apiserver 地址不是這個(gè)所以報(bào)錯(cuò)。
為什么我們使用 --context cluster-name 就可以了呢?
這是因?yàn)?kind 在創(chuàng)建集群的時(shí)候會(huì)修改 $HOME/.kube/config 的配置,將集群的 apiserver 地址,證書等相關(guān)信息都自動(dòng)寫入進(jìn)去了
每次命令都要加上這個(gè)參數(shù)好麻煩怎么辦?
我們可以使用 kubectl config use-context context-name 來(lái)進(jìn)行設(shè)置,設(shè)置好了之后我們后續(xù)就不用每次都加上 –context 的參數(shù)了,同時(shí)還可以通過(guò) kubectl config current-context 查詢我們當(dāng)前默認(rèn)操作的集群是哪一個(gè)
查看集群節(jié)點(diǎn)列表
可以發(fā)現(xiàn)我們部署的是一個(gè)單節(jié)點(diǎn)的 v1.20.2 的集群
- ❯ kubectl get no
- NAME STATUS ROLES AGE VERSION
- kind-control-plane Ready control-plane,master 20m v1.20.2
部署一個(gè) Nginx 服務(wù)
使用下方代碼創(chuàng)建一個(gè) nginx.yml 文件,然后使用 kubectl apply -f nginx.yml 就可以完成部署了
- apiVersion: apps/v1
- kind: Deployment
- metadata:
- name: nginx-deployment
- labels:
- app: nginx
- spec:
- replicas: 3
- selector:
- matchLabels:
- app: nginx
- template:
- metadata:
- labels:
- app: nginx
- spec:
- containers:
- - name: nginx
- image: nginx:1.14.2
- ports:
- - containerPort: 80
查看當(dāng)前 deployment 的狀態(tài)
- ❯ kubectl get deployment
- NAME READY UP-TO-DATE AVAILABLE AGE
- nginx-deployment 0/3 3 0 39s
查看 pod 的狀態(tài)
- ❯ kubectl get pods
- NAME READY STATUS RESTARTS AGE
- nginx-deployment-66b6c48dd5-2s5cb 1/1 Running 0 84s
- nginx-deployment-66b6c48dd5-8wf8b 1/1 Running 0 84s
- nginx-deployment-66b6c48dd5-zc6vd 1/1 Running 0 84s
由于我們沒(méi)有做服務(wù)暴露,所以是不能直接訪問(wèn)對(duì)應(yīng)的服務(wù)的,我們可以用 kubectl提供的端口轉(zhuǎn)發(fā)功能來(lái)講流量從本地轉(zhuǎn)發(fā)給 k8s 集群
- ❯ kubectl port-forward nginx-deployment-66b6c48dd5-2s5cb 30080:80
- Forwarding from 127.0.0.1:30080 -> 80
- Forwarding from [::1]:30080 -> 80
- Handling connection for 30080
我們?cè)L問(wèn) http://localhost:30080 就會(huì)發(fā)現(xiàn)這個(gè)熟悉的 nginx 界面
image-20210424210804343
到這里可以發(fā)現(xiàn)我們集群已經(jīng)是可以使用了
2.4 進(jìn)階使用
2.4.1 創(chuàng)建一個(gè)多節(jié)點(diǎn)的集群
kind 默認(rèn)創(chuàng)建的是一個(gè)單節(jié)點(diǎn)的集群,我們可以通過(guò)修改配置創(chuàng)建一個(gè)高可用的集群,我們創(chuàng)建一個(gè) 3 個(gè) master 節(jié)點(diǎn),兩個(gè) worker 節(jié)點(diǎn)的集群
- kind create cluster --name mohuishou-ha --config kind-ha.yml
- kind: Cluster
- apiVersion: kind.x-k8s.io/v1alpha4
- nodes:
- - role: control-plane
- - role: control-plane
- - role: control-plane
- - role: worker
- - role: worker
看一下節(jié)點(diǎn)即可驗(yàn)證
- ❯ kubectl --context kind-mohuishou-ha get no
- NAME STATUS ROLES AGE VERSION
- mohuishou-ha-control-plane Ready control-plane,master 16m v1.20.2
- mohuishou-ha-control-plane2 Ready control-plane,master 14m v1.20.2
- mohuishou-ha-control-plane3 Ready control-plane,master 13m v1.20.2
- mohuishou-ha-worker Ready <none> 5m52s v1.20.2
- mohuishou-ha-worker2 Ready <none> 5m52s v1.20.2
2.4.2 Load Image
一般來(lái)說(shuō)我們?cè)?k8s 內(nèi)部署應(yīng)用需要先把容器鏡像推送到到鏡像倉(cāng)庫(kù)當(dāng)中,這樣在本地開(kāi)發(fā)的時(shí)候相對(duì)來(lái)說(shuō)會(huì)比較麻煩,特別是鏡像比較大的時(shí)候,往返會(huì)有兩次網(wǎng)絡(luò)消耗,為了解決這個(gè)問(wèn)題我們可以使用 kind load 鏡像的功能直接把鏡像。
- kind load docker-image my-custom-image-0 my-custom-image-1 --name kind
排坑指南:load image 成功,但是部署 pod 報(bào)錯(cuò)
- Failed to pull image "controller:latest": rpc error: code = Unknown desc = failed to pull and unpack image "docker.io/library/controller:latest": failed to resolve reference "docker.io/library/controller:latest": pull access denied, repository does not exist or may require authorization: server message: insufficient_scope: authorization failed
這個(gè)問(wèn)題之前卡了我很久,還是有點(diǎn)坑
1.進(jìn)入節(jié)點(diǎn)查看: 鏡像是否存在
- 獲取節(jié)點(diǎn)名
- ▶ kubectl get nodes
- NAME STATUS ROLES AGE VERSION
- kind-control-plane Ready control-plane,master 2d1h v1.20.2
- 進(jìn)入終端
- docker exec -it kind-control-plane bash
- 查看鏡像是否存在,kind 創(chuàng)建的集群使用的是 containerd 所以我們使用 crictl 命令來(lái)獲取
- crictl img | grep controller
- docker.io/library/controller latest 421cbf77618ba 72.1MB
2.如果鏡像存在,也就是我們上面看到的情況,這時(shí)候就要檢查一下我們部署的 yaml 文件
- kubectl -n node-pool-operator-system get deployment -o yaml | grep imagePullPolicy
是否存在: imagePullPolicy: Always 如果我們沒(méi)有改 yaml 的話默認(rèn)會(huì)是這個(gè)配置,這個(gè)配置會(huì)導(dǎo)致每次都去鏡像倉(cāng)庫(kù)拉取鏡像,改成 imagePullPolicy: IfNotPresent 就可以了
3.如果鏡像不存在:這時(shí)候要檢查一下有沒(méi)有指定 cluster-name,在存在多個(gè)集群的情況下可能沒(méi)有加載到我們想要的集群,加上 --name cluster-name 即可
總結(jié)
kind 在創(chuàng)建集群的時(shí)候?qū)嶋H上使用的是 kubeadm 所以還可以修改 kubeadm 的配置來(lái)修改默認(rèn)的鏡像地址,節(jié)點(diǎn)標(biāo)簽污點(diǎn)等信息,除此之外還可以配置 PV/PVC CNI 插件等配置,如果有需求的話可以查閱 kind 的官方文檔
不過(guò)要注意的是 kind 不支持給運(yùn)行的集群添加節(jié)點(diǎn),如果需要多節(jié)點(diǎn)集群的話得提前規(guī)劃好節(jié)點(diǎn)數(shù)量
參考文獻(xiàn)
- kind – Configurationhttps://kind.sigs.k8s.io/docs/user/configuration/
- Docker Desktophttps://www.docker.com/products/docker-desktop
- WSL2https://docs.microsoft.com/en-us/windows/wsl/install-win10
- Getting Started - go.dev https://learn.go.dev/
- 使用 Kind 搭建你的本地 Kubernetes 集群https://segmentfault.com/a/1190000018720465