By 胡濤 (@daniel-hutao) | 18.04.2022
從零開始快速搭建本地 Kubernetes 測試環(huán)境
從零開始姥宝?從零開始晾嘶!
var 零=99 // 別緊張眶掌,Just a jok荒吏。
Let’s Get Started!
概述
“Kubernetes 集群部署”嚴(yán)格來說是一個(gè)復(fù)雜的技術(shù)活驱还,有很多的可選方案涛碑。要交付一套靠攏“最佳實(shí)踐”的高可用集群有很多需要考慮的技術(shù)細(xì)節(jié)精堕。關(guān)于如何部署“真正高可用的 Kubernetes 集群”不在本文的討論范圍,所以今天我們的目標(biāo)是使用一種簡單的方式快速部署一個(gè)可用的 Kubernetes 環(huán)境蒲障。這套環(huán)境主要用于滿足 DevStream 的開發(fā)測試需求歹篓。
快速部署 Kubernetes 有好幾種可選方案,比如 Minikube 和 Kind揉阎。 Minikube最先基于虛擬化實(shí)現(xiàn)(新版本也支持容器化實(shí)現(xiàn)了)庄撮,也就是通過 virtualbox 或者 kvm 等工具在本地創(chuàng)建若干虛擬機(jī),然后在虛擬機(jī)中運(yùn)行 Kubernetes 集群毙籽,一個(gè)節(jié)點(diǎn)也就對應(yīng)一臺(tái)虛擬機(jī)洞斯。Kind 通過容器化實(shí)現(xiàn),也就是通過 Docker 在本地啟動(dòng)若干容器坑赡,每個(gè)容器充當(dāng) Kubernetes 的一個(gè)節(jié)點(diǎn)烙如,在容器內(nèi)再運(yùn)行容器化應(yīng)用。本文我們選擇用 Kind 這種“容器中跑容器”的方式來搭建 Kubernetes 環(huán)境毅否。當(dāng)然如果大家有其他擅長的工具亚铁,也完全可以用,我們的目的僅僅是快速部署一套可用的 Kubernetes 集群環(huán)境螟加。
本文以 macOS 作為開發(fā)環(huán)境徘溢,使用 Linux 或者 Windows 系統(tǒng)作為開發(fā)環(huán)境的同學(xué)可以參考本文的方法,相應(yīng)地做一些靈活調(diào)整仰迁。
Docker 的安裝
在 Linux 下安裝 Docker 是一件非常簡單的事情甸昏,Docker 的核心原理就是基于 Linux 的 Namespace 和 Cgroup 等機(jī)制。不過在 macOS 和 Windows 下就需要通過虛擬化技術(shù)間接使用 Docker 了徐许。當(dāng)然我們現(xiàn)在已經(jīng)不需要先安裝虛擬化軟件然后自己安裝 Linux 虛擬機(jī)施蜜,再使用 Docker 了。我們可以直接在 docker.com 下載 Docker Desktop 來跑 Docker 程序雌隅。
我們在 https://www.docker.com/products/docker-desktop 尋找合適的 Docker Desktop 版本翻默,主要是看清楚 cpu 架構(gòu)是 Intel Chip 還是 Apple Chip,前者對應(yīng) amd64 架構(gòu)版本 Mac恰起,后者是 arm 架構(gòu)的 M1 芯片版本 Mac修械。 下載頁面大致如下:
下載完成后雙擊 Docker.dmg 文件,可以看到安裝頁面:
我們把 Docker 圖標(biāo)拖到 Applications 里检盼,稍等不到半分鐘肯污,就可以在“啟動(dòng)臺(tái)”里看到 Docker 圖標(biāo)了,然后點(diǎn)擊“啟動(dòng)臺(tái)”里的 Docker 打開 Docker Desktop:
稍等幾秒鐘,就可以看到啟動(dòng)頁面了:
我們可以點(diǎn)擊右上角的“齒輪??”按鈕來修改 Docker Desktop 的一些配置蹦渣,比如調(diào)整 Docker 可以使用的資源等哄芜。如果后面我們需要啟動(dòng)的容器稍多一些,內(nèi)存不夠用了柬唯,可以回到這里來調(diào)整认臊,比如我這里把 Memory 調(diào)大到 4.00 GB:
修改后記得點(diǎn)擊右下角的“Apply & Restart”才會(huì)生效。
Kind 介紹
Kind(Kubernetes-in-docker) 是一個(gè)使用 Docker 容器作為“節(jié)點(diǎn)”實(shí)現(xiàn)部署 Kubernetes 集群環(huán)境的工具锄奢。Kind 工具主要用于 Kubernetes 本身的測試失晴,目前在很多需要部署到 Kubernetes 環(huán)境測試的項(xiàng)目在 ci 流程中都會(huì)選擇用 Kind 來快速拉起一個(gè) Kubernetes 環(huán)境,然后運(yùn)行相關(guān)測試用例拘央。
Kind 本身很簡單涂屁,只包含一個(gè)簡單的命令行工具“kind”和一個(gè)用來啟動(dòng) Kubernetes 和 systemd等的 Docker 鏡像。我們可以這樣理解 Kind 的原理:它通過 Host 主機(jī)上的 Docker 使用封裝了 Kubernetes 等工具的容器鏡像拉起一個(gè)容器堪滨,這個(gè)容器里運(yùn)行了 systemd胯陋,容器中的 systemd 進(jìn)一步可以運(yùn)行 Docker 和 Kubelet 等 Kubernetes 節(jié)點(diǎn)所需基礎(chǔ)進(jìn)程,然后這些進(jìn)程就可以進(jìn)一步運(yùn)行 kube-apiserver袱箱、kube-controller-manager、kube-scheduler义矛、kube-proxy发笔、CoreDNS 等集群所需組件,從而一個(gè)這樣的容器就組成了一個(gè) Kubernetes 集群的“節(jié)點(diǎn)”凉翻。
所以 Kind 可以通過一個(gè)容器運(yùn)行“單節(jié)點(diǎn) Kubernetes 集群”了讨,也可以進(jìn)一步通過運(yùn)行三個(gè)或更多容器實(shí)現(xiàn)在一臺(tái)主機(jī)上運(yùn)行一個(gè)“多節(jié)點(diǎn)Kubernetes 集群”。
一鍵搭建 Kind 測試環(huán)節(jié)
秘籍:
- 下載 DevStream 項(xiàng)目主庫:https://github.com/devstream-io/devstream
- 在 devstream 目錄內(nèi)執(zhí)行一條命令:
make e2e-up
結(jié)束了制轰?結(jié)束了前计。
發(fā)生了啥?大家可以打開 Makefile垃杖,在里面可以看到 e2e-up 其實(shí)是執(zhí)行了 sh hack/e2e/e2e-up.sh
這個(gè)命令男杈,在 e2e-up.sh 這個(gè)腳本中,我們完成了基于 Kind 的 Kubernetes 測試環(huán)境的搭建调俘。
似乎行文至此伶棒,已經(jīng)可以 AFK and have a cup of coffee 了!
但是好像沒發(fā)揮盡興彩库。
好吧肤无,那就詳細(xì)掰扯掰扯 Kind 的玩法吧。
今天不用系安全帶骇钦,我要嚴(yán)肅起來了宛渐。
使用 Kind “兩鍵”搭建 Kubernetes 環(huán)境
現(xiàn)在我們來搭建 Kind 開發(fā)環(huán)境,在 GitHub 上可以看到 Kind最新的 Release 版本和對應(yīng)的 Node 鏡像:https://github.com/kubernetes-sigs/kind/releases
可以選擇編譯好的版本,也可以直接通過 go get 命令來下載編譯 Kind窥翩。我們盡量選擇較新的版本业岁,然后通過下面命令下載安裝(記得改成你需要的版本號(hào))。
# 方式一:選擇編譯好的可執(zhí)行文件
cd /tmp
curl -Lo ./kind https://github.com/kubernetes-sigs/kind/releases/download/v0.12.0/kind-darwin-arm64
chmod +x ./kind
sudo mv kind /usr/local/bin/
# 方式二:通過 go get 來下載編譯
go get sigs.k8s.io/kind@v0.12.1
可以提前下載所需鏡像鳍烁,這里我們選擇使用 1.22 版本的 Kubernetes 對應(yīng)鏡像:
kindest/node:v1.22.0@sha256:b8bda84bb3a190e6e028b1760d277454a72267a5454b57db34437c34a588d047
然后通過下面一條命令就可以快速拉起來一套 Kubernetes 環(huán)境:
kind create cluster --image=kindest/node:v1.22.0 --name=dev
上述執(zhí)行輸出大致如下:
Creating cluster "dev" ...
? Ensuring node image (kindest/node:v1.22.0) ??
? Preparing nodes ??
? Writing configuration ??
? Starting control-plane ???
? Installing CNI ??
? Installing StorageClass ??
Set kubectl context to "kind-dev"
You can now use your cluster with:
kubectl cluster-info --context kind-dev
Have a question, bug, or feature request? Let us know! https://kind.sigs.k8s.io/#community ??
按照命令行輸出提示叨襟,接著我們需要執(zhí)行 kubectl cluster-info –context kind-dev 來切換 context ,其實(shí)當(dāng)前直接執(zhí)行 kubectl get就可以看到新起來的 Kubernetes 環(huán)境了幔荒,多套集群的時(shí)候才需要這樣切換糊闽。
$ kubectl get node
NAME STATUS ROLES AGE VERSION
dev-control-plane Ready control-plane,master 7m4s v1.22.0
$ kubectl get pod -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-78fcd69978-hch75 1/1 Running 0 10m
coredns-78fcd69978-ztqn4 1/1 Running 0 10m
etcd-dev-control-plane 1/1 Running 0 10m
kindnet-l8qxq 1/1 Running 0 10m
kube-apiserver-dev-control-plane 1/1 Running 0 10m
kube-controller-manager-dev-control-plane 1/1 Running 0 10m
kube-proxy-mzfgc 1/1 Running 0 10m
kube-scheduler-dev-control-plane 1/1 Running 0 10m
這樣我們就快速收獲了一個(gè)可以用來測試或者學(xué)習(xí) Kubernetes 的環(huán)境了。
使用 Kind “三鍵”搭建多節(jié)點(diǎn) Kubernetes 集群環(huán)境
最小的 Kubernetes HA 集群需要有 3 個(gè) Master節(jié)點(diǎn)爹梁,當(dāng)然我們也可以把 1 個(gè)節(jié)點(diǎn)的 all-in-one 環(huán)境稱為“單節(jié)點(diǎn)集群”右犹。這一小節(jié)我們接著看一下如何通過 Kind 來快速搭建多節(jié)點(diǎn)的 Kubernetes 集群環(huán)境。
Kind 集群配置文件
Kind 環(huán)境搭建的時(shí)候可以自定義配置姚垃,通過 –config 來指定自定義配置文件路徑念链。Kind 支持的配置格式如下:
# this config file contains all config fields with comments
# NOTE: this is not a particularly useful config file
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
# patch the generated kubeadm config with some extra settings
kubeadmConfigPatches:
- |
apiVersion: kubelet.config.k8s.io/v1beta1
kind: KubeletConfiguration
evictionHard:
nodefs.available: "0%"
# patch it further using a JSON 6902 patch
kubeadmConfigPatchesJSON6902:
- group: kubeadm.k8s.io
version: v1beta2
kind: ClusterConfiguration
patch: |
- op: add
path: /apiServer/certSANs/-
value: my-hostname
# 1 control plane node and 3 workers
nodes:
# the control plane node config
- role: control-plane
# the three workers
- role: worker
- role: worker
- role: worker
可以看到這里的配置項(xiàng)分為兩個(gè)部分,上面是和 Kubeadm 如何配置 Kubernetes 相關(guān)的配置項(xiàng)积糯,下面是和 Nodes 角色和規(guī)模相關(guān)的配置項(xiàng)掂墓。不難猜到,我們需要部署多個(gè)節(jié)點(diǎn)的 Kubernetes 集群看成,可以通過指定 nodes 部分配置的方式來實(shí)現(xiàn)君编。
一主三從集群搭建
我們準(zhǔn)備一份對應(yīng)的配置文件,命名為multi-node-config.yaml川慌,內(nèi)容如下:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: worker
- role: worker
- role: worker
接著執(zhí)行如下命令拉起集群:
$ kind create cluster --config multi-node-config.yaml \
--image=kindest/node:v1.22.0 --name=dev4
等待命令執(zhí)行結(jié)束吃嘿,我們可以看到類似前面單節(jié)點(diǎn)環(huán)境搭建時(shí)看到的輸出結(jié)果,有個(gè)主要區(qū)別是步驟多了一個(gè)“Joining worker nodes”:
Creating cluster "dev4" ...
? Ensuring node image (kindest/node:v1.22.0) ??
? Preparing nodes ?? ?? ?? ??
? Writing configuration ??
? Starting control-plane ???
? Installing CNI ??
? Installing StorageClass ??
? Joining worker nodes ??
Set kubectl context to "kind-dev4"
You can now use your cluster with:
kubectl cluster-info --context kind-dev4
Thanks for using kind! ??
可以通過如下命令查看新創(chuàng)建的集群:
$ kubectl cluster-info --context kind-dev4
Kubernetes control plane is running at https://127.0.0.1:51851
CoreDNS is running at https://127.0.0.1:51851/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
$ kubectl get node
NAME STATUS ROLES AGE VERSION
dev4-control-plane Ready control-plane,master 3m28s v1.22.0
dev4-worker Ready <none> 2m54s v1.22.0
dev4-worker2 Ready <none> 2m54s v1.22.0
dev4-worker3 Ready <none> 2m54s v1.22.0
上述命令執(zhí)行結(jié)果可以很清晰看到這個(gè) dev4 集群有1個(gè) Master 節(jié)點(diǎn)和 3 個(gè) Worker 節(jié)點(diǎn)梦重。
三主三從 HA 集群搭建
當(dāng)然我們這里的 HA 只是表示 Master 節(jié)點(diǎn)組件會(huì)運(yùn)行 3 副本兑燥,一定程度上實(shí)現(xiàn) Master 節(jié)點(diǎn)沒有單點(diǎn)故障,并不是嚴(yán)格意義上的“高可用”琴拧。
同樣準(zhǔn)備一份配置文件 ha-config.yaml降瞳,內(nèi)容如下:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
- role: control-plane
- role: control-plane
- role: worker
- role: worker
- role: worker
接著執(zhí)行如下命令拉起集群:
$ kind create cluster --config ha-config.yaml \
--image=kindest/node:v1.22.0 --name=dev6
等待命令執(zhí)行結(jié)束,我們依舊可以看到熟悉的日志輸出結(jié)果艾蓝,和上面稍有不同力崇,這里主要是多了“Configuring the external load balancer”和“Joining more control-plane nodes”:
Creating cluster "dev6" ...
? Ensuring node image (kindest/node:v1.22.0) ??
? Preparing nodes ?? ?? ?? ?? ?? ??
? Configuring the external load balancer ??
? Writing configuration ??
? Starting control-plane ???
? Installing CNI ??
? Installing StorageClass ??
? Joining more control-plane nodes ??
? Joining worker nodes ??
Set kubectl context to "kind-dev6"
You can now use your cluster with:
kubectl cluster-info --context kind-dev6
Have a nice day! ??
這里也可以看到幾個(gè)很有趣的細(xì)節(jié),比如“Preparing nodes”步驟后面小盒子數(shù)量和節(jié)點(diǎn)數(shù)是相等的赢织;另外最后一句問候語也不是固定的亮靴。比如前面是“Thanks for using kind! ??”,這里又變成了“Have a nice day! ??”于置,可見 Kind背后的開發(fā)者是一群“可愛”又“有趣”的工程師茧吊!
同樣我們通過幾個(gè)命令看一下剛才創(chuàng)建的集群:
$ kubectl cluster-info --context kind-dev6
Kubernetes control plane is running at https://127.0.0.1:52937
CoreDNS is running at https://127.0.0.1:52937/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy
To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
$ kubectl get node
NAME STATUS ROLES AGE VERSION
dev6-control-plane Ready control-plane,master 8m19s v1.22.0
dev6-control-plane2 Ready control-plane,master 7m46s v1.22.0
dev6-control-plane3 Ready control-plane,master 7m20s v1.22.0
dev6-worker Ready <none> 7m v1.22.0
dev6-worker2 Ready <none> 7m v1.22.0
dev6-worker3 Ready <none> 7m v1.22.0
上述命令執(zhí)行結(jié)果可以很清晰看到這個(gè) dev6 集群有3個(gè) Master 節(jié)點(diǎn)和 3 個(gè) Worker 節(jié)點(diǎn)贞岭。
到這里我們就掌握了通過 Kind 來非常輕松地搭建多節(jié)點(diǎn)的 Kubernetes 集群環(huán)境,后面大家可以根據(jù)自己的需要來選擇節(jié)點(diǎn)規(guī)模和角色搓侄,搭建合適的測試環(huán)境瞄桨。
Kind 用法進(jìn)階
通過前面幾節(jié)的學(xué)習(xí),我們已經(jīng)掌握了用 Kind 搭建各種類型的集群讶踪。但是要用好這些集群芯侥,還需要掌握一些運(yùn)維技巧,本小節(jié)我們來學(xué)習(xí)一下 Kind 集群的的一些進(jìn)階操作乳讥。
端口映射
設(shè)想一種場景:我們在 Kind 集群中運(yùn)行一個(gè) Nginx 容器服務(wù)柱查,監(jiān)聽 80 端口對外暴露,這時(shí)候在另外一臺(tái)機(jī)器上能不能訪問到 Kind 集群所在機(jī)器的 80 端口進(jìn)而訪問到這個(gè) Nginx 服務(wù)呢云石?其實(shí)不行唉工,這兩個(gè) 80 端口明顯不在一個(gè)網(wǎng)絡(luò)命名空間。我們可以通過如下方式來配置端口映射汹忠,解決這類問題淋硝。
在配置文件中增加 extraPortMappings 配置項(xiàng):
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
- role: control-plane
extraPortMappings:
- containerPort: 80
hostPort: 80
listenAddress: "0.0.0.0"
protocol: tcp
這樣我們搭建出來到 Kubernetes 集群中使用 NodePort 暴露的 80 端口或者是 hostNetwork 方式暴露 80 端口的 Pod 就可以通過主機(jī)的 80 端口來訪問到了。
暴露 kube-apiserver
有時(shí)候我們會(huì)在一臺(tái)機(jī)子上使用 Kind 搭建一套 Kubernetes 環(huán)境宽菜,在另外一臺(tái)機(jī)器上寫代碼谣膳,這時(shí)候會(huì)發(fā)現(xiàn)我們無法連接到 Kind 集群中的 kube-apiserver 來調(diào)試程序。其實(shí)是因?yàn)槟J(rèn)配置下 kube-apiserver 監(jiān)聽 127.0.0.1 加隨機(jī)端口铅乡,我們要從外部訪問就需要把 kube-apiserver 監(jiān)聽的網(wǎng)卡改成非 lo 的對外網(wǎng)卡参歹,比如 eth0。
同樣我們通過配置文件自定義來實(shí)現(xiàn)隆判,添加 networking.apiServerAddress 配置項(xiàng),值是本地網(wǎng)卡 ip僧界,根據(jù)實(shí)際情況修改:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
networking:
apiServerAddress: "192.168.39.1"
啟用 Feature Gates
如果我們要使用一些 alpha 階段的特性侨嘀,就需要通過配置 Feature Gates 來實(shí)現(xiàn)了。在使用 kubeadm 搭建環(huán)境的時(shí)候捂襟,是可以通過配置 ClusterConfiguration 來實(shí)現(xiàn)這個(gè)需求的咬腕,kubeadm 被 Kind 封裝后,我們在 Kind 里如何啟用 Feature Gates 呢葬荷?
方案如下涨共,F(xiàn)eatureGateName 就是我們需要啟用的 Feature Gate 名字:
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
featureGates:
FeatureGateName: true
導(dǎo)入鏡像
通過 kind 搭建的環(huán)境本質(zhì)是運(yùn)行在一個(gè)容器內(nèi),宿主機(jī)上的鏡像默認(rèn)不能被 Kind 環(huán)境所識(shí)別到宠漩,這時(shí)我們可以通過如下方式導(dǎo)入鏡像:
# 假如需要的鏡像是 my-image:v1
kind load docker-image my-image:v1 --name dev
# 假如需要的鏡像是一個(gè) tar 包 my-image.tar
kind load image-archive my-image.tar --name dev
知道了這個(gè)方法后举反,我們構(gòu)建一個(gè)新鏡像需要放到 Kind 環(huán)境里運(yùn)行,就可以通過類似如下步驟來實(shí)現(xiàn)了:
docker build -t my-image:v1 ./my-image-dir
kind load docker-image my-image:v1
kubectl apply -f my-image.yaml
怎么查看當(dāng)前 Kind 環(huán)境里有哪些鏡像呢扒吁?也很簡單火鼻,可以這樣:
docker exec -it dev-control-plane crictl images
其中 dev-control-plane 是 node 容器名,有多套環(huán)境時(shí)這個(gè)名字需要對應(yīng)靈活切換。另外可以通過 crictl -h 查看 crictl 所支持的其他命令魁索,比如 crictl rmi <image_name> 可以用于刪除鏡像等融撞。
小結(jié)
沒啥好總結(jié)的,總之希望大家搭環(huán)境順利粗蔚!
I have to AFK and have a cup of coffee NOW!
歡迎閱讀原文尝偎!
本文由博客群發(fā)一文多發(fā)等運(yùn)營工具平臺(tái) OpenWrite 發(fā)布