自己搭建一个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,內網 IP?10.0.16.13/22:4C4G 輕量應用服務器(本來是2核的,前幾天騰訊云免費升級…),master 節點是控制節點,管理其它的節點,以及運行 k8s 依賴的 etcd 等
worker 節點?bun-worker-01,內網 IP?172.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.13PING 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.gpgecho \"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 1000link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00inet 127.0.0.1/8 scope host lovalid_lft forever preferred_lft foreverinet6 ::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 1000link/ether 52:54:00:19:8b:e4 brd ff:ff:ff:ff:ff:ffaltname enp0s5altname ens5inet 10.0.16.13/22 brd 10.0.19.255 scope global eth0valid_lft forever preferred_lft foreverinet6 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:ffinet 172.17.0.1/16 brd 172.17.255.255 scope global docker0valid_lft forever preferred_lft foreverdocker 創建的虛擬網卡?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 usedocker 要求配置的值是一個真實的 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?似乎只有用戶公開的,且并不是最新的,沒法用)
稍等片刻,便可以部署成功:
[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/.kubesudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/configsudo chown $(id -u):$(id -g) $HOME/.kube/configAlternatively, if you are the root user, you can run:export KUBECONFIG=/etc/kubernetes/admin.confYou 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
總結
以上是生活随笔為你收集整理的自己搭建一个k8s环境的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: .NetCore使用NETCore.Ma
- 下一篇: Xamarin效果第十六篇之GIS添加M