自己搭建一個 k8s 環境
背景
Kubernetes 是時下流行的容器編排引擎,因爲字母太多,且掐頭去尾後剩下 8 個字母,於是被大家親切的縮寫爲 k8s。
Kubernetes https://kubernetes.io/
另外所謂 “雲原生” 概念火爆,各大雲廠商也紛紛推出了自己的容器服務,例如阿里雲的 ACK、騰訊雲的 TKE、微軟雲的 AKS 等,無不是基於 Kubernetes 。
阿里雲 ACK https://www.aliyun.com/product/kubernetes
騰訊雲 TKE https://cloud.tencent.com/product/tke
微軟雲 AKS https://azure.microsoft.com/services/kubernetes-service/
由於我個人博客搭建在騰訊雲上,大概是去年(2021 年)11、12 月的時候萌生的 “要不把博客搬到 k8s 上?” 的想法。雲廠商提供的容器服務一般都支持從原有_雲服務器_轉換爲 Kubernetes 的 worker 節點;不過當然也有一些限制,例如騰訊雲價格相對低廉的_輕量應用服務器_則不支持轉換。不過正巧我的博客使用的是雲服務器,那就試試騰訊雲的 TKE 吧。
結果懶惰使人省錢,從學習到實戰的腳步總是異常的緩慢,在此期間騰訊雲發生了 2 件大事:
-
負載均衡實例升級調價公告
https://cloud.tencent.com/document/product/214/59398 -
騰訊雲容器服務於 2022 年 3 月 21 日 10:00(北京時間)對託管集羣計費通知
https://cloud.tencent.com/document/product/457/68706
運行在 k8s 裏的程序想要暴露到公網上,在雲廠商的環境中最常用的就是通過負載均衡實現,騰訊雲這一調價直接從原來的每小時 0.02 元漲到了 0.2 元,個人用戶應該很少用這麼貴的服務。(相較而言,阿里雲則提供廉價版的負載均衡,個人用戶的福音。)
另外徹底阻止我使用 TKE 的是,我們知道 k8s 集羣需要有 master 和 worker 節點分工合作,雲廠商會提供託管 master 節點的服務,用戶只需要自己照料好 worker 節點即可。騰訊雲也不例外,不過原來託管是免費的,即將要開始收費了!而不使用託管,意味着我必須再準備一臺雲服務器,又是一筆開銷……
雖然上雲等於花錢,但是貧窮就能阻止我們上雲嗎?答案是否定的,我們可以自己搭建 k8s 集羣!甚至還能從中收穫許多,如:
-
複習了 k8s 網絡相關的知識
-
加深了對 ingress 的瞭解,ingress 是從容器外部訪問容器內相對而言比較方便的手段
-
折騰的快感和解決問題的喜悅
話雖如此,但強烈建議沒有接觸過 Kubernetes 的朋友們,先通過官方文檔 和 minikube 在本地學習後,再繼續深入。
ingress https://kubernetes.io/docs/concepts/services-networking/ingress/
官方文檔 https://kubernetes.io/zh/docs/setup/
minikube https://minikube.sigs.k8s.io/docs/
我計劃通過幾篇文章來介紹:
-
k8s 集羣的搭建(本篇)
-
配置 ingress 通過域名訪問容器內的站點
-
使用 cert-manager 爲站點自動生成和更新 HTTPS 證書
-
使用 k8s 的本地卷 (local volume)
cert-manager https://cert-manager.io/
本地卷 https://kubernetes.io/docs/concepts/storage/volumes/#local
好了,廢話說的太多,現在就開始進行 k8s 集羣的搭建吧~
環境介紹
本文下面的操作都是在騰訊雲裏進行的,使用的是 1 臺雲服務器 CVM 和 1 臺輕量應用服務器 TencentCloud Lighthouse 進行。(一般雲廠商都會給新用戶很大的優惠力度,特別是第一臺雲服務器和輕量應用服務器,意味着前 3 年可以以很低的成本體驗。)
雲服務器 CVM https://cloud.tencent.com/product/cvm
輕量應用服務器 TencentCloud Lighthouse https://cloud.tencent.com/product/lighthouse
我使用的具體配置和規劃如下:
-
master 節點
bun-master-01
,內網 IP10.0.16.13/22
:4C4G 輕量應用服務器(本來是 2 核的,前幾天騰訊雲免費升級…),master 節點是控制節點,管理其它的節點,以及運行 k8s 依賴的 etcd 等 -
worker 節點
bun-worker-01
,內網 IP172.17.0.2/20
:4C8G 雲服務器,未來應用程序就跑在這個節點上
操作系統都使用的是 Debian 11.1,上述機器都在同一地域。
Debian http://debian.org/
請注意,不應將這樣的配置使用在生產環境,因爲這不能保證可用性。不過自己玩兒的話,一臺機器也可以(建議至少 2C2G),將 master 和 worker 部署在同一機器內,但這麼做會增加不穩定的因素,另外都上 (hua) 雲(qian)了,新用戶購買輕量應用服務器約等於不要錢,當然配置拉滿整上。
當然,雖然你使用的可能不是騰訊雲或者 Debian,但這並不是你繼續閱讀的障礙,因爲雲基礎設施、Linux 命令都是類似的,下文在具體的地方會進行標註。
沒有具體標明在哪臺機器上進行的,則所有機器都需要進行這些步驟,例如內網配置、Debian 配置、安裝 docker、kubeadm 等。
集羣網絡配置
請查看你使用的雲廠商沒有類似的限制或配置,以免內網不通導致 master 和 worker 節點無法通信。
內網網段配置
要組建集羣,首先機器之間得能互相訪問。最理想的情況是機器都處在同一個網段,但省錢的方案並不能做到這一點,我的兩臺主機位於完全不同的兩個網段,Lighthouse 甚至不支持修改內網 IP 地址。
好在騰訊雲的 CVM 和 Lighthouse 之間雖然默認不能連通,但位於同一地域的機器可以通過內網互聯功能,享受 5Gbps 帶寬免費互通(不同地域需要收費),可以參考騰訊雲文檔進行操作,本文不多贅述。
內網互聯 https://cloud.tencent.com/document/product/1207/56847
雲服務器防火牆配置
另外需要注意的是雲廠商提供的防火牆的配置(不是系統裏的防火牆),需要在每臺主機的入站規則中添加上其它主機的 IP 地址,騰訊雲的配置入口位於 實例詳情 - 安全組(Lighthouse 爲防火牆)。
例如,我直接選擇放行整個網段,這樣未來如果增加機器就不用再來回改配置了:
因爲我是全部放行,可以使用 ping
命令查看機器是否連通了,例如在我的 worker 上 ping master:
> ping 10.0.16.13
PING 10.0.16.13 (10.0.16.13) 56(84) bytes of data.
64 bytes from 10.0.16.13: icmp_seq=1 ttl=64 time=0.288 ms
64 bytes from 10.0.16.13: icmp_seq=2 ttl=64 time=0.240 ms
64 bytes from 10.0.16.13: icmp_seq=3 ttl=64 time=0.264 ms
允許訪問公網
由於安裝 k8s 過程中需要拉取一些鏡像或下載一些文件,而這些鏡像或文件在騰訊雲內網鏡像服務中並沒有提供,所以至少安裝階段需要訪問公網。
Debian 基礎配置
如果你使用的是其它 Linux 發行版本,那麼通過互聯網搜索相關操作,能很快找到對應的命令。
配置機器名稱和 hosts
使用統一一致的機器名稱利於管理:
hostnamectl set-hostname bun-master-01
配置 hosts 文件讓機器名稱可以被訪問:
cat >> /etc/hosts << EOF
10.0.16.13 bun-master-01
172.17.0.2 bun-worker-01
EOF
關閉防火牆等配置
安裝 k8s 前需要將 Linux 的防火牆、安全配置(SELinux)、交換分區(Swap,類似於 Windows 的虛擬內存)關閉。不過這些內容默認情況下都是禁用的,如果你曾經開啓過記得關閉。
允許 iptables 檢查橋接流量
cat > /etc/sysctl.d/k8s.conf << EOF
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system
配置時間同步
確保每臺機器時間都是正確的,我使用騰訊雲內網提供的 NTP 服務。
NTP 服務 https://cloud.tencent.com/document/product/213/30392
如果你的雲廠商沒有提供類似服務,可以採用公網上的 NTP 服務。
安裝 ntp:
apt-get install -y ntp
修改 ntp 配置:
vi /etc/ntp.conf
將騰訊雲的 NTP 服務器地址替換掉配置文件中默認的:
重啓 ntp 並查看效果:
service ntp restart
service ntp status
ntpq -p
最後設置 ntp 開機啓動:
systemctl enable ntp
安裝 docker
注意:所有節點都需要安裝 docker。
我們使用官方腳本安裝 docker,在此之前先把一些必要的程序安裝一下:
apt-get update
apt-get install -y \
ca-certificates \
curl \
gnupg \
lsb-release
接着使用騰訊雲內網鏡像來進行下載:
http://mirrors.tencentyun.com
只能在騰訊雲內網訪問,你需要將它們換成你可用的,例如http://mirrors.tencent.com
。本文優先使用騰訊雲內網鏡像,因爲這樣高速,且不會產生任何公網流量和費用。
curl -fsSL http://mirrors.tencentyun.com/docker-ce/linux/debian/gpg \
| sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] http://mirrors.tencentyun.com/docker-ce/linux/debian \
$(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
接下來開始安裝 docker:
apt-get update
apt-get install -y \
docker-ce \
docker-ce-cli \
containerd.io
檢查 docker 網絡
安裝好之後,使用 ip a
命令檢查一下 docker 新建的網卡,避免 docker 新建的網卡導致網段衝突,內網機器無法訪問。
例如在 bun-master-01
機器上執行 ip a
得到如下返回:
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc mq state UP group default qlen 1000
link/ether 52:54:00:19:8b:e4 brd ff:ff:ff:ff:ff:ff
altname enp0s5
altname ens5
inet 10.0.16.13/22 brd 10.0.19.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::5054:ff:fe19:8be4/64 scope link
valid_lft forever preferred_lft forever
3: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN group default
link/ether 02:42:c3:bf:8b:a6 brd ff:ff:ff:ff:ff:ff
inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
valid_lft forever preferred_lft forever
docker 創建的虛擬網卡 docker0
使用了 172.17.0.1
地址,而我的另一臺機器 bun-worker-01
則是 172.17.0.2
。這樣導致無法從 bun-master-01
訪問 bun-worker-01
。
我們可以修改 docker 的配置文件指定它的虛擬網卡地址,例如我希望 docker 使用 192.168.0.1/16
網段,這樣和誰都不衝突:
cat >> /etc/docker/daemon.json << EOF
{
"bip": "192.168.0.1/16"
}
EOF
然後重啓 docker,並重新運行 ip a
檢查配置是否生效,以及重新 ping
一下測試連通性:
service docker restart
配置 docker 鏡像加速源
https://mirror.ccs.tencentyun.com
只能在騰訊雲內網訪問,你需要將它們換成你可用的,例如使用阿里雲鏡像加速。阿里雲鏡像加速 https://help.aliyun.com/document_detail/60750.html
修改 /etc/docker/daemon.json
文件,新增 registry-mirrors
的配置:
{
"bip": "192.168.0.1/16",
"registry-mirrors": ["https://mirror.ccs.tencentyun.com"]
}
接下來重啓 docker 應用配置:
service docker restart
如果一切正常,讓我們跑一下 docker 的 hello-world 試試:
docker run hello-world
如果看到 Hello from Docker!
則說明一切順利,繼續進行下一步吧。
docker 啓動失敗常見問題
如果在重啓 docker 時不幸遇到了這樣的提示:
Job for docker.service failed because the control process exited with error code.
See "systemctl status docker.service" and "journalctl -xe" for details.
不要慌,請運行 journalctl -xe
查看具體錯誤。例如我嘗試將 docker 的虛擬網卡 IP 修改爲了一個非法的值:
Mar 23 21:44:28 master-01.bun.local dockerd[186689]: time="2022-03-23T21:44:28.584331774+08:00" level=info msg="[graphdriver] using prior storage driver: overlay2"
Mar 23 21:44:28 master-01.bun.local dockerd[186689]: time="2022-03-23T21:44:28.589151624+08:00" level=info msg="Loading containers: start."
Mar 23 21:44:28 master-01.bun.local dockerd[186689]: time="2022-03-23T21:44:28.643081791+08:00" level=info msg="stopping event stream following graceful shutdown" error="<nil>" module=libcontainerd namespace=moby
Mar 23 21:44:28 master-01.bun.local dockerd[186689]: failed to start daemon: Error initializing network controller: Error creating default "bridge" network: failed to allocate gateway (192.168.0.0): Address already in use
docker 要求配置的值是一個真實的 IP 地址,所以不能配置爲 192.168.0.0/16
,需要配置爲 192.168.0.1/16
。
如果是其它問題,可以在網上進行搜索。
安裝 kubeadm, kubelet 以及 kubectl
注意:所有節點都需要安裝 kubeadm, kubelet 以及 kubectl。
由於 Google 無法訪問,騰訊雲的鏡像又沒有 gpg 文件,只好從阿里雲的鏡像下載 pgp 文件😓感謝友商
curl -fsSLo /usr/share/keyrings/kubernetes-archive-keyring.gpg https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg
不過騰訊雲的鏡像有相關的軟件包:
有熟悉 Debian 的小夥伴會注意到,這裏指定了 Debian 的
xenial
版本,它其實表示 Debian 的 k8s 最新版。這個 issue 解釋了背後的故事。這個 issue https://github.com/kubernetes/kubernetes/issues/66300
echo "deb [signed-by=/usr/share/keyrings/kubernetes-archive-keyring.gpg] http://mirrors.tencentyun.com/kubernetes/apt/ kubernetes-xenial main" \
| sudo tee /etc/apt/sources.list.d/kubernetes.list
接下來把它們統統安裝上,並固定住版本,避免不小心升級造成問題:
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl
部署 master 節點
網段的設置注意不要和現有網段衝突。
使用 kubeadm init
來部署 master 節點,下面的參數中:
-
將
apiserver-advertise-address
設置爲當前機器的內網 ip 地址 -
service-cidr
表示 k8s Service 使用的 IP 地址段,設置一個自己喜歡的 -
pod-network
表示 k8s Pod 使用的 IP 地址段,設置一個自己喜歡的,但對於 pod 儘量劃分容量大一點的網段 -
image-repository
使用阿里雲提供的鏡像registry.cn-hangzhou.aliyuncs.com/google_containers
,再次感謝友商(騰訊雲內網的ccr.ccs.tencentyun.com
似乎只有用戶公開的,且並不是最新的,沒法用)
kubeadm init \
--apiserver-advertise-address=10.0.16.13 \
--service-cidr=10.1.0.0/16 \
--pod-network-cidr=10.10.0.0/16 \
--image-repository=registry.cn-hangzhou.aliyuncs.com/google_containers
稍等片刻,便可以部署成功:
[init] Using Kubernetes version: v1.23.5
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster
...
Your Kubernetes control-plane has initialized successfully!
To start using your cluster, you need to run the following as a regular user:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 10.0.16.13:6443 --token 5x8l46.p5716s1ezcgqt3n2 \
--discovery-token-ca-cert-hash sha256:f775a880cff6c4bd250420931726a8bcb9344b0dd335aa9be52a315f65616e16
根據上面 To start using your cluster ...
部分的指引,繼續執行它下面的 3 條命令,好讓 kubectl
工作:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
接着把最後兩行 kubeadm
命令複製下來備用。到此,master 節點就配置完成了。
部署 worker 節點
執行從 master 節點執行成功後返回的 kubeadm
命令(就是剛剛複製的那個),當前機器就會加入到 master 的集羣:
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
回到 master 節點,通過 kubectl get nodes
命令查看集羣內節點的情況:
NAME STATUS ROLES AGE VERSION
bun-master-01 NotReady control-plane,master 4m13s v1.23.5
bun-worker-01 NotReady <none> 51s v1.23.5
可以看到 bun-worker-01
節點已經加入集羣,amazing!不過爲啥是 NotReady
狀態?
別急,還有最後一步,配置 CNI (Container Network Interface) 插件 —— 它爲容器管理系統(如 docker、k8s)提供網絡功能。
CNI https://github.com/containernetworking/cni
安裝 CNI 插件:Calico
Calico 是一款被廣泛使用的 k8s CNI 插件,先下載它的配置文件,因爲一會兒需要修改裏面的內容:
wget https://docs.projectcalico.org/manifests/calico.yaml
在 calico.yaml
文件中找到 CALICO_IPV4POOL_CIDR
的配置,將其設置爲執行 kubeadm init
時指定的 pod-network
一樣的值:
然後安裝 Calico:
kubectl apply -f calico.yaml
安裝好後,可以通過 ip a
命令在 master 和 worker 節點上查看到 Calico 創建的 tunl0
網卡。並且再檢查一下 master 和 worker 之間是否還能連通,避免因爲配置錯誤之類的問題導致內網不通。
現在再運行 kubectl get nodes
命令,就能看到 master 和 worker 節點已經處於 Ready
狀態。
參考
- Installing kubeadm
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/install-kubeadm
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/trcfXfO4x745FKTRzKbCuQ