配置高可用K3s集群完全攻略
前 言
在本文中,我們將簡要介紹在高可用性(HA)配置中設(shè)置K3s的參考架構(gòu)。這意味著你的K3s集群可以容忍故障,并保持啟動(dòng)和運(yùn)行,為你的用戶提供流量。你的應(yīng)用程序也應(yīng)該針對高可用性進(jìn)行構(gòu)建和配置,但這部分內(nèi)容不在本文的范圍內(nèi)。
在本教程中,我們將使用CLI工具在DigitalOcean上配置一個(gè)HA K3s集群。我們將使用MySQL進(jìn)行數(shù)據(jù)存儲,并使用TCP負(fù)載均衡器為Kubernetes API server提供一個(gè)穩(wěn)定的IP地址。
那么,為什么我們需要高可用?我們可以創(chuàng)建的K3s集群是通過在一個(gè)有公共IP地址的虛擬機(jī)上部署一個(gè)K3s server。不幸的是,如果該虛擬機(jī)崩潰,我們的應(yīng)用程序?qū)l(fā)生故障。通過添加多個(gè)server并配置它們協(xié)調(diào)工作,可以使得集群容忍一個(gè)或多個(gè)節(jié)點(diǎn)的故障。這就是所謂的高可用性。
控制平面的高可用性
對于K3s 1.19版本來說,以下兩種方法都可以實(shí)現(xiàn)高可用:
SQL數(shù)據(jù)存儲:SQL數(shù)據(jù)庫可以用于存儲集群狀態(tài),但SQL數(shù)據(jù)庫也必須在高可用配置下運(yùn)行才有效。
嵌入式etcd:與Kubernetes的傳統(tǒng)配置方式最為類似,需要使用諸如kops和kubedam等工具
在本文中,我們將了解第一種方法,該方法中使用SQL數(shù)據(jù)庫來存儲狀態(tài)。我們之所以采用SQL的原因是單個(gè)數(shù)據(jù)庫可以擴(kuò)展到支持多個(gè)集群。
API Server的高可用
Kubernetes API server配置為端口 6443 的 TCP 流量。外部流量(如來自kubectl客戶端的流量)使用KUBECONFIG文件中的IP地址或DNS條目連接到API server。
該配置引入了我們所有server之間的TCP負(fù)載均衡器的需求,因?yàn)槿绻覀兪褂闷渲幸慌_server的IP地址,這臺server崩潰,我們將無法使用kubectl。Agent也是如此,需要連接到某個(gè)IP地址和端口6443的server上才能與集群通信。
在上圖中,運(yùn)行kubectl的用戶和兩個(gè)agent都連接到TCP 負(fù)載均衡器。負(fù)載均衡器使用私有IP地址列表來平衡三個(gè)server之間的流量。如果其中一個(gè)server崩潰,它將從IP地址列表中刪除。
Server使用SQL數(shù)據(jù)存儲來同步集群的狀態(tài)。
前期準(zhǔn)備
你也許需要一個(gè)DigtalOcean的賬號來進(jìn)行以下步驟,不過以下大多數(shù)內(nèi)容也可以從其他云提供商中獲取,此前我們發(fā)布過一篇使用阿里云進(jìn)行K3s高可用的教程,歡迎你參考:
3個(gè)VM作為K3s server運(yùn)行
2個(gè)VM作為K3s agent運(yùn)行
托管的MySQL服務(wù)
托管的TCP 負(fù)載均衡器
如果你正在使用沒有托管的TCP負(fù)載均衡器的云服務(wù),可以考慮使用keepalived或kube-vip等工具。這些工具是通過發(fā)布“虛擬IP地址”來實(shí)現(xiàn)的,KUBECONFIG文件指向這個(gè)地址,而不是單個(gè)server。
這些說明需要與Windows上的Git Bash,MacOS Terminal,WSL1或2或Linux Terminal等終端一起運(yùn)行。
確保您已下載并安裝:
DigitalOcean CLI (doctl)
Kubernetes CLI (kubectl)
K3sup:一個(gè)被廣泛使用的開源工具,用于通過SSH安裝K3s
以上3個(gè)CLI都可以通過arkade get NAME命令或使用brew install NAME來安裝。
Arkade:https://github.com/alexellis/arkade
brew:https://brew.sh/
如果你使用的是arkade,運(yùn)行以下命令:
arkade get doctlarkade get kubectlarkade get k3sup
你安裝了doctl之后,你需要在DigitalOcean的儀表盤上創(chuàng)建一個(gè)帶有讀寫權(quán)限的API key,然后運(yùn)行doctl auth init進(jìn)行認(rèn)證。
添加你的SSH key到你的Digital Ocean儀表盤上,然后查找SSH key的ID。當(dāng)我們使用SSH來安裝K3s時(shí),我們需要使用它。
如果這是你第一次使用SSH key或者如果你想了解如何配置它們,你可以訪問以下鏈接查看教程:
https://www.digitalocean.com/docs/droplets/how-to/add-ssh-keys/
現(xiàn)在列出你的SSH key并復(fù)制以下ID:
doctl compute ssh-key listID Name FingerPrint24824545 work e2:31:91:12:31:ad:c7:20:0b:d2:b1:f2:96:2a:22:da
運(yùn)行以下命令:
export SSH_KEY='24824545'
詳細(xì)步驟
配置我們在教程中所需要的資源最簡單的方式是使用DigitalOcean的儀表盤或CLI(doctl)進(jìn)行配置。你完成了教程之后,你可能會需要使用類似Terraform的工具來自動(dòng)化各種步驟。
你可以通過以下鏈接了解DigitalOcean的規(guī)模和區(qū)域選擇:
https://www.digitalocean.com/docs/apis-clis/doctl/reference/compute/droplet/create/
創(chuàng)建節(jié)點(diǎn)
創(chuàng)建三臺服務(wù)器,內(nèi)存為2GB,vCPU為1:
doctl compute droplet create --image ubuntu-20-04-x64 --size s-1vcpu-2gb --region lon1 k3s-server-1 --tag-names k3s,k3s-server --ssh-keys $SSH_KEYdoctl compute droplet create --image ubuntu-20-04-x64 --size s-1vcpu-2gb --region lon1 k3s-server-2 --tag-names k3s,k3s-server --ssh-keys $SSH_KEYdoctl compute droplet create --image ubuntu-20-04-x64 --size s-1vcpu-2gb --region lon1 k3s-server-3 --tag-names k3s,k3s-server --ssh-keys $SSH_KEY
使用相同的配置創(chuàng)建2個(gè)worker:
doctl compute droplet create --image ubuntu-20-04-x64 --size s-1vcpu-2gb --region lon1 k3s-agent-1 --tag-names k3s,k3s-agent --ssh-keys $SSH_KEYdoctl compute droplet create --image ubuntu-20-04-x64 --size s-1vcpu-2gb --region lon1 k3s-agent-2 --tag-names k3s,k3s-agent --ssh-keys $SSH_KEY
附帶的標(biāo)簽會和負(fù)載均衡器一起使用,這樣我們就不用指定節(jié)點(diǎn)IP了,以后如果需要的話可以增加更多的server。
創(chuàng)建負(fù)載均衡器
doctl compute load-balancer create --name k3s-api-server \--region lon1 --tag-name k3s-server \--forwarding-rules entry_protocol:tcp,entry_port:6443,target_protocol:tcp,target_port:6443 \--forwarding-rules entry_protocol:tcp,entry_port:22,target_protocol:tcp,target_port:22 \--health-check protocol:tcp,port:6443,check_interval_seconds:10,response_timeout_seconds:5,healthy_threshold:5,unhealthy_threshold:3
我們需要為Kubernetes API Server轉(zhuǎn)發(fā)6443端口,22端口給k3sup稍后使用,以獲取集群的”join token“。
這條規(guī)則將接收LB的IP上的傳入流量,并將其轉(zhuǎn)發(fā)到帶有“k3s-server”標(biāo)簽的虛擬機(jī)上。
記下你獲取的ID:
export LB_ID='da247aaa-157d-4758-bad9-3b1516588ac5'
接下來,查找負(fù)載均衡器的IP地址:
doctl compute load-balancer get $LB_ID
記下IP欄中的數(shù)值:
export LB_IP='157.245.29.149'
配置一個(gè)托管的SQL數(shù)據(jù)庫
doctl databases create k3s-data --region lon1 --engine mysql
以上命令將創(chuàng)建一個(gè)版本8的MySQL數(shù)據(jù)庫。
你還會看到輸出的URI與連接字符串,包括連接所需的密碼。
exportDATASTORE=mysql://doadmin:z42q6ovclcwjjqwq@tcpk3s-data-do-user-2197152-0.a.db.ondigitalocean.com:25060/defaultdb&sslmode=require"
要使用K3s,我們需要修改字符串如下:
exportDATASTORE='mysql://doadmin:z42q6ovclcwjjqwq@tcp(k3s-data-do-user-2197152-0.a.db.ondigitalocean.com:25060)/defaultdb' INSTALL_K3S_VERSION='v1.19.1+k3s1'
我們移除了“?sslmode=require”后綴并在主機(jī)名和端口周圍添加了tcp()。
啟動(dòng)集群
讓我們使用k3sup來通過SSH啟動(dòng)K3s。
在k3sup中最重要的兩個(gè)命令是:
install:安裝K3s到新server并為集群創(chuàng)建join token
join:從server上獲取“join token”,然后用它來安裝k3s到agent上。
與其他方法相比,使用k3sup的優(yōu)勢在于它往往不那么繁瑣,而且通過直觀的標(biāo)志更容易使用。
你可以通過運(yùn)行:k3sup install --help 或 k3sup join --help 來找到這些標(biāo)志和附加選項(xiàng)。
安裝K3s到server
將channel設(shè)置到最新,撰寫本文時(shí)最新版本為1.19
export CHANNEL=latest
在繼續(xù)之前,請檢查你的環(huán)境變量是否在之前被填充,如果沒有請回溯并填充它們。
echo $DATASTOREecho $LB_IPecho $CHANNEL
在下面的命令中,用Public IPv4一欄填寫下面的IP地址:
doctl compute droplet ls --tag-name k3sexport SERVER1=134.209.16.225export SERVER2=167.99.198.45export SERVER3=157.245.39.44export AGENT1=161.35.32.107export AGENT2=161.35.36.40
既然你已經(jīng)填充了環(huán)境變量,請運(yùn)行以下命令:
k3sup install --user root --ip $SERVER1 \--k3s-channel $CHANNEL \--print-command \--datastore='${DATASTORE}' \--tls-san $LB_IPk3sup install --user root --ip $SERVER2 \--k3s-channel $CHANNEL \--print-command \--datastore='${DATASTORE}' \--tls-san $LB_IPk3sup install --user root --ip $SERVER3 \--k3s-channel $CHANNEL \--print-command \--datastore='${DATASTORE}' \--tls-san $LB_IPk3sup join --user root --server-ip $LB_IP --ip $AGENT1 \--k3s-channel $CHANNEL \--print-commandk3sup join --user root --server-ip $LB_IP --ip $AGENT2 \--k3s-channel $CHANNEL \--print-command
檢查節(jié)點(diǎn)是否加入
export KUBECONFIG=`pwd`/kubeconfigNAME STATUS ROLES AGE VERSIONk3s-server-2 Ready master 18m v1.19.3+k3s1k3s-server-3 Ready master 18m v1.19.3+k3s1k3s-agent-1 Ready <none> 2m39s v1.19.3+k3s1k3s-server-1 Ready master 23m v1.19.1+k3s1k3s-agent-2 Ready <none> 2m36s v1.19.3+k3s1
打開KUBECONFIG文件,找到IP地址,應(yīng)該是負(fù)載均衡器的地址。
片刻之后,你可以在DigitalOcean的儀表盤上看到負(fù)載均衡器的狀態(tài)。
模擬故障
要模擬故障,需要在一個(gè)或多個(gè)k3s server上停止K3s服務(wù),然后運(yùn)行kubectl get nodes命令:
ssh root@SERVER1 'systemctl stop k3s'ssh root@SERVER2 'systemctl stop k3s'
此時(shí),第三個(gè)server將會接管。
kubectl get nodes
然后在其他兩個(gè)server上重啟服務(wù):
ssh root@SERVER1 'systemctl start k3s'ssh root@SERVER2 'systemctl start k3s'
如果你還想了解更多關(guān)于Kubernetes如何處理節(jié)點(diǎn)中斷的信息,請查看以下鏈接:
https://kubernetes.io/docs/concepts/workloads/pods/disruptions/
此時(shí),你可以使用集群來部署一個(gè)應(yīng)用程序,或者繼續(xù)清理你配置的資源,這樣你就不會因?yàn)槿魏晤~外的使用而被收取費(fèi)用。
清理
刪除droplets
doctl compute droplet rm --tag-name k3s
對于負(fù)載均衡器和數(shù)據(jù)庫,你需要獲取ID,然后使用刪除命令。
doctl compute load-balancer list/deletedoctl databases list/delete
總 結(jié)
我們現(xiàn)在已經(jīng)配置了一個(gè)容錯(cuò)、高可用性的K3s集群,并為用戶提供了一個(gè)TCP負(fù)載均衡器,這樣即使其中一臺服務(wù)器宕機(jī)或崩潰,用戶也可以訪問kubectl。使用 "tag "也意味著我們可以添加更多的服務(wù)器,而不用擔(dān)心必須手動(dòng)更新負(fù)載平衡器的IP列表。
我們在這里使用的工具和技術(shù)也可以應(yīng)用于其他支持托管數(shù)據(jù)庫和托管負(fù)載均衡器的云平臺,如AWS、谷歌云和Azure。
正如你可能已經(jīng)從我們所經(jīng)歷的步驟中所注意到的那樣,高可用性是一個(gè)需要花費(fèi)一些時(shí)間和思考才能夠進(jìn)行正確配置。如果你打算創(chuàng)建許多HA K3s集群,那么使用Terraform自動(dòng)化步驟可能會有好處。
你也可以使用k3sup使用嵌入式etcd,而不是托管數(shù)據(jù)庫來配置HA K3s集群。這降低了成本,但增加了服務(wù)器的負(fù)載。
如果你想進(jìn)一步了解K3s,歡迎查看以下文檔:
https://docs.rancher.cn/k3s/
你也可以從GitHub上的倉庫中找到更多關(guān)于k3sup如何工作的信息,包括使用etcd進(jìn)行HA的替代方法:
https://k3sup.dev/
推薦閱讀
掃碼添加k3s中文社區(qū)助手
加入官方中文技術(shù)社區(qū)
官網(wǎng):https://k3s.io
