單master節點升級為高可用集群
對於生產環境來說,單節點master風險太大了。 非常有必要做一個高可用的集群,這里的高可用主要是針對控制面板來說的,比如 kube-apiserver、etcd、kube-comtroller-manager、kube-scheduler 這幾個組件,其中 kube-controller-manager 與 kube-scheduler 組件是 kubernetes 集群自己去實現的高可用,apiserver 和 etcd 就需要手動去搭建高可集群了。 高可用的架構有很多,比如典型的 haproxy+keepalived架構,或者使用 nginx來做代理實現。我們這里為了聲明如何將單 master 升級為高可用的集群,采用相對就更簡單的 nginx 模式,當然這種模式也有一些缺點,但是足以說明高可用的實現方式了。
從上圖可以看出,我們需要在所有控制節點上安裝 nginx、keepalived服務。 來代理 apiserver,這里我准備了2個節點作為控制平面節點: k8s-master1、k8s-master2, 這里我默認所有節點都已經正常安裝配置好了docker, 以及節點初始化操作。
在所有節點 hosts配置文件中添加如下內容:
$ cat /etc/hosts 127.0.0.1 api.k8s.local 192.168.166.128 k8s-master1 192.168.166.129 k8s-master2 192.168.166.130 k8s-node1 192.168.166.131 k8s-node2
1、更新證書
由於我們需要將集群替換成高可用的集群,那么勢必會想到我們會用一個負載均衡器來代理 APIServer, 也就是這個負載均衡器訪問 APIServer 的時候需要能正常訪問,所以默認安裝的 APIServer 證書就需要更新,因為里面沒有包含我們需要的地址,需要保證在 SAN 列表中包含一些額外的名稱。
首先我們一個 kubeadn 的配置文件,如果一開始安裝集群的時候你就是使用的配置文件,那么我們可以直接更新這個配置文件,但是我們你沒有使用這個配置文件,直接使用 kubeadm init 來安裝的集群,那么我們可以從集群中獲取 kubeadm 的配置信息來插件一個配置文件,因為 kubeadm 會將其配置寫入到 kube-system 命名空間下面的名為 kubeadm-config 的 ConfigMap 中。可以直接執行如下所示的命令將該配置導出:會生成一個 kubeadm.yam的配置文件
$ kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' > kubeadm.yaml
生成的kubeadm.yaml 文件中並沒有列出額外的 SAN 信息,我們需要添加一個新的數據,需要在 apiserver 屬性下面添加一個 certsSANs 的列表。如果你在啟動集群的時候就使用的 kubeadm 的配置文件,可能就已經包含 certsSANs 列表了,如果沒有我們就需要添加它,比如我們這里要添加一個新的域名 api.k8s,local 以及 k8s-master 和 k8s-master2 這兩個主機名和IP地址 192.168,.166.128、192.168.166.129、192.168.168.100。可以添加多個IP,192.168.166.100為虛擬VIP,那么我們需要在 apiServer 下面添加如下的所示的數據:
apiServer: certSANs: - api.k8s.local - k8s-master1 - k8s-master2 - 192.168.166.128 - 192.168.166.129 - 192.168.166.100 extraArgs: authorization-mode: Node,RBAC timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta2 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: type: CoreDNS etcd: local: dataDir: /var/lib/etcd imageRepository: registry.aliyuncs.com/k8sxio kind: ClusterConfiguration kubernetesVersion: v1.17.11 networking: dnsDomain: cluster.local podSubnet: 10.244.0.0/16 serviceSubnet: 10.96.0.0/12 scheduler: {}
上面我只列出了 apiServer 下面新增的 certSANs 信息,這些信息是包括在標准的 SAN 列表之外的,所以不用擔心這里沒有添加 kubernetes、kubernetes.default 等等這些信息,因為這些都是標准的 SAN 列表中的。
更新完 kubeadm 配置文件后我們就可以更新證書了,首先我們移動現有的 APIServer 的證書和密鑰,因為 kubeadm 檢測到他們已經存在於指定的位置,它就不會創建新的了。
$ mv /etc/kubernetes/pki/apiserver.{crt,key} ~
然后直接使用 kubeadm 命令生成一個新的證書:
$ kubeadm init phase certs apiserver --config kubeadm.yaml W0902 10:05:28.006627 832 validation.go:28] Cannot validate kubelet config - no validator is available W0902 10:05:28.006754 832 validation.go:28] Cannot validate kube-proxy config - no validator is available [certs] Generating "apiserver" certificate and key [certs] apiserver serving cert is signed for DNS names [ydzs-master kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local api.k8s.local k8s-master1 k8s-master2] and IPs [10.96.0.1 192.168.166.128 192.168.166.129 192.168.166.100]
通過上面的命令可以查看到 APIServer 簽名的 DNS 和 IP 地址信息,一定要和自己的目標簽名信息進行對比,如果缺失了數據就需要在上面的 certSANs 中補齊,重新生成證書。
該命令會使用上面指定的 kubeadm 配置文件為 APIServer 生成一個新的證書和密鑰,由於指定的配置文件中包含了 certSANs 列表,那么 kubeadm 會在創建新證書的時候自動添加這些 SANs。
最后一步是重啟 APIServer 來接收新的證書,最簡單的方法是直接殺死 APIServer 的容器:
$ docker ps | grep kube-apiserver | grep -v pause 7fe227a5dd3c aa63290ccd50 "kube-apiserver --ad…" 14 hours ago Up 14 hours k8s_kube-apiserver_kube-apiserver-ydzs-master_kube-system_6aa38ee2d66b7d9b6660a88700d00581_0 $ docker kill 7fe227a5dd3c 7fe227a5dd3c
容器被殺掉后,kubelet 會自動重啟容器,然后容器將接收新的證書,一旦 APIServer 重啟后,我們就可以使用新添加的 IP 地址或者主機名來連接它了,比如我們新添加的 api.k8s.local
。
驗證證書
要驗證證書是否更新我們可以直接去編輯 kubeconfig 文件中的 APIServer 地址,將其更換為新添加的 IP 地址或者主機名,然后去使用 kubectl 操作集群,查看是否可以正常工作。
當然我們可以使用 openssl 命令去查看生成的證書信息是否包含我們新添加的 SAN 列表數據:
$ openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text Certificate: ...... Subject: CN=kube-apiserver ...... X509v3 Subject Alternative Name: DNS:ydzs-master, DNS:kubernetes, DNS:kubernetes.default, DNS:kubernetes.default.svc, DNS:kubernetes.default.svc.cluster.local, DNS:api.k8s.local, DNS:k8s-master1, DNS:k8s-master2, IP Address:10.96.0.1, IP Address:192.168.166.128 IP Address:192.168.166.129, IP Address:192.168.166.100 ......
如果上面的操作都一切順利,最后一步是將上面的集群配置信息保存到集群的 kubeadm-config 這個 ConfigMap 中去,這一點非常重要,這樣以后當我們使用 kubeadm 來操作集群的時候,相關的數據不會丟失,比如升級的時候還是會帶上 certSANs 中的數據進行簽名的。
$ kubeadm config upload from-file --config kubeadm.yaml
# 如果上面命令報錯,可以直接編輯修改 添加需要的內容即可
$ kubectl -n kube-system edit configmap kubeadm-config
使用上面的命令保存配置后,我們同樣可以用下面的命令來驗證是否保存成功了:
$ kubectl -n kube-system get configmap kubeadm-config -o yaml
更新 APIServer 證書的名稱在很多場景下都會使用到,比如在控制平面前面添加一個負載均衡器,或者添加新的 DNS 名稱或 IP 地址來使用控制平面的端點,所以掌握更新集群證書的方法也是非常有必要的。
2、部署 nginx + keepalived 高可用負載均衡器
Kubernetes作為容器集群系統,通過健康檢查+重啟策略實現了Pod故障自我修復能力,通過調度算法實現將Pod分布式部署,並保持預期副本數,根據Node失效狀態自動在其他Node拉起Pod,實現了應用層的高可用性。
針對Kubernetes集群,高可用性還應包含以下兩個層面的考慮:Etcd數據庫的高可用性和Kubernetes Master組件的高可用性。 而kubeadm搭建的K8s集群,Etcd只起了一個,存在單點,所以我們這里會獨立搭建一個Etcd集群。
Master節點扮演着總控中心的角色,通過不斷與工作節點上的Kubelet和kube-proxy進行通信來維護整個集群的健康工作狀態。如果Master節點故障,將無法使用kubectl工具或者API做任何集群管理。
Master節點主要有三個服務kube-apiserver、kube-controller-manager和kube-scheduler,其中kube-controller-manager和kube-scheduler組件自身通過選擇機制已經實現了高可用,所以Master高可用主要針對kube-apiserver組件,而該組件是以HTTP API提供服務,因此對他高可用與Web服務器類似,增加負載均衡器對其負載均衡即可,並且可水平擴容。
kube-apiserver高可用架構圖:
- Nginx是一個主流Web服務和反向代理服務器,這里用四層實現對apiserver實現負載均衡。
- Keepalived是一個主流高可用軟件,基於VIP綁定實現服務器雙機熱備,在上述拓撲中,Keepalived主要根據Nginx運行狀態判斷是否需要故障轉移(偏移VIP),例如當Nginx主節點掛掉,VIP會自動綁定在Nginx備節點,從而保證VIP一直可用,實現Nginx高可用。
注:為了節省機器,這里與K8s master節點機器復用。也可以獨立於k8s集群之外部署,只要nginx與apiserver能通信就行。
2.1 安裝軟件包(主/備)
yum install epel-release -y
yum install nginx keepalived -y
2.2 Nginx配置文件(主/備一樣)
cat > /etc/nginx/nginx.conf << "EOF" user nginx; worker_processes auto; error_log /var/log/nginx/error.log; pid /run/nginx.pid; include /usr/share/nginx/modules/*.conf; events { worker_connections 1024; } # 四層負載均衡,為兩台Master apiserver組件提供負載均衡 stream { log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent'; access_log /var/log/nginx/k8s-access.log main; upstream k8s-apiserver { server 192.168.166.128:6443; # Master1 APISERVER IP:PORT server 192.168.166.129:6443; # Master2 APISERVER IP:PORT } server { listen 16443; # 由於nginx與master節點復用,這個監聽端口不能是6443,否則會沖突 proxy_pass k8s-apiserver; } } http { log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"'; access_log /var/log/nginx/access.log main; sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; include /etc/nginx/mime.types; default_type application/octet-stream; server { listen 80 default_server; server_name _; location / { } } } EOF
2.3 keepalived配置文件(Nginx Master)
cat > /etc/keepalived/keepalived.conf << EOF global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_MASTER } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } vrrp_instance VI_1 { state MASTER interface ens33 # 修改為實際網卡名 virtual_router_id 51 # VRRP 路由 ID實例,每個實例是唯一的 priority 100 # 優先級,備服務器設置 90 advert_int 1 # 指定VRRP 心跳包通告間隔時間,默認1秒 authentication { auth_type PASS auth_pass 1111 } # 虛擬IP virtual_ipaddress { 192.168.166.100/24 } track_script { check_nginx } } EOF
- vrrp_script:指定檢查nginx工作狀態腳本(根據nginx狀態判斷是否故障轉移)
- virtual_ipaddress:虛擬IP(VIP)
准備上述配置文件中檢查nginx運行狀態的腳本:
cat > /etc/keepalived/check_nginx.sh << "EOF" #!/bin/bash count=$(ss -antp |grep 16443 |egrep -cv "grep|$$") if [ "$count" -eq 0 ];then exit 1 else exit 0 fi EOF chmod +x /etc/keepalived/check_nginx.sh
2.4 keepalived配置文件(Nginx Backup)
cat > /etc/keepalived/keepalived.conf << EOF global_defs { notification_email { acassen@firewall.loc failover@firewall.loc sysadmin@firewall.loc } notification_email_from Alexandre.Cassen@firewall.loc smtp_server 127.0.0.1 smtp_connect_timeout 30 router_id NGINX_BACKUP } vrrp_script check_nginx { script "/etc/keepalived/check_nginx.sh" } vrrp_instance VI_1 { state BACKUP interface ens33 virtual_router_id 51 # VRRP 路由 ID實例,每個實例是唯一的 priority 90 advert_int 1 authentication { auth_type PASS auth_pass 1111 } virtual_ipaddress { 192.168.166.100/24 } track_script { check_nginx } } EOF
准備上述配置文件中檢查nginx運行狀態的腳本:
cat > /etc/keepalived/check_nginx.sh << "EOF" #!/bin/bash count=$(ss -antp |grep 16443 |egrep -cv "grep|$$") if [ "$count" -eq 0 ];then exit 1 else exit 0 fi EOF chmod +x /etc/keepalived/check_nginx.sh
注:keepalived根據腳本返回狀態碼(0為工作正常,非0不正常)判斷是否故障轉移。
2.5 啟動並設置開機啟動
systemctl daemon-reload
systemctl start nginx
systemctl start keepalived
systemctl enable nginx
systemctl enable keepalived
2.6 查看keepalived工作狀態
[root@k8s-master1 install]# ip add |grep ens33 2: ens33: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000 inet 192.168.166.128/24 brd 192.168.166.255 scope global noprefixroute ens33 inet 192.168.166.100/24 scope global secondary ens33
可以看到,在ens33網卡綁定了192.168.31.88 虛擬IP,說明工作正常。
2.7 Nginx+Keepalived高可用測試
關閉主節點Nginx,測試VIP是否漂移到備節點服務器。
在Nginx Master執行 pkill nginx
在Nginx Backup,ip addr命令查看已成功綁定VIP。
啟動成功后 apiserver 的負載均衡地址就成了 https://192.168.166.100:16443
。然后我們將 kubeconfig 文件中的 apiserver 地址替換成負載均衡器的地址。
# 修改 kubelet 配置 $ vi /etc/kubernetes/kubelet.conf ...... server: https://192.168.166.100:16443 name: kubernetes ...... $ systemctl restart kubelet # 修改 controller-manager $ vi /etc/kubernetes/controller-manager.conf ...... server: https://192.168.166.100:16443 name: kubernetes ...... # 重啟 $ docker kill $(docker ps | grep kube-controller-manager | \ grep -v pause | cut -d' ' -f1) # 修改 scheduler $ vi /etc/kubernetes/scheduler.conf ...... server: https://192.168.166.100:16443 name: kubernetes ...... # 重啟 $ docker kill $(docker ps | grep kube-scheduler | grep -v pause | \ cut -d' ' -f1)
然后更新 kube-proxy
$ kubectl -n kube-system edit cm kube-proxy ...... kubeconfig.conf: |- apiVersion: v1 kind: Config clusters: - cluster: certificate-authority: /var/run/secrets/kubernetes.io/serviceaccount/ca.crt server: https://api.k8s.local:8443 name: default ......
當然還有 kubectl 訪問集群的 ~/.kube/config
文件也需要修改。
3、更新控制面板
由於我們現在已經在控制平面的前面添加了一個負載平衡器,因此我們需要使用正確的信息更新此 ConfigMap。(您很快就會將控制平面節點添加到集群中,因此在此ConfigMap中擁有正確的信息很重要。)
首先,使用以下命令從 ConfigMap 中獲取當前配置:
$ kubectl -n kube-system get configmap kubeadm-config -o jsonpath='{.data.ClusterConfiguration}' > kubeadm.yaml
# 或者直接編輯添加
$ kubectl -n kube-system edit configmap kubeadm-config
然后在當前配置文件里面里面添加 controlPlaneEndpoint
屬性,用於指定控制面板的負載均衡器的地址。
$ vi kubeadm.yaml
apiVersion: v1
data:
ClusterConfiguration: |
apiServer:
certSANs:
- api.k8s.local
- k8s-master1
- k8s-master2
- 192.168.166.128
- 192.168.166.129
- 192.168.166.100
extraArgs:
authorization-mode: Node,RBAC
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controlPlaneEndpoint: 192.168.166.100:16443 # 添加改配置
controllerManager: {}
......
然后需要在 kube-public
命名空間中更新 cluster-info
這個 ConfigMap,該命名空間包含一個Kubeconfig 文件,該文件的 server:
一行指向單個控制平面節點。只需使用kubectl -n kube-public edit cm cluster-info
更新該 server:
行以指向控制平面的負載均衡器即可。
$ kubectl -n kube-public edit cm cluster-info ...... server: https://192.168.166.100:16443 name: "" ...... $ kubectl cluster-info Kubernetes master is running at https://192.168.166.100:16443 KubeDNS is running at https://api.k8s.local:8443/api/v1/namespaces/kube-system/services/kube-dns:dns/proxy KubeDNSUpstream is running at https://api.k8s.local:8443/api/v1/namespaces/kube-system/services/kube-dns-upstream:dns/proxy Metrics-server is running at https://api.k8s.local:8443/api/v1/namespaces/kube-system/services/https:metrics-server:/proxy To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.
更新完成就可以看到 cluster-info 的信息變成了負載均衡器的地址了。
添加控制平面
接下來我們來添加額外的控制平面節點,首先使用如下命令來將集群的證書上傳到集群中,供其他控制節點使用:
$ kubeadm init phase upload-certs --upload-certs I0903 15:13:24.192467 20533 version.go:251] remote version is much newer: v1.19.0; falling back to: stable-1.17 W0903 15:13:25.739892 20533 validation.go:28] Cannot validate kube-proxy config - no validator is available W0903 15:13:25.739966 20533 validation.go:28] Cannot validate kubelet config - no validator is available [upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace [upload-certs] Using certificate key: e71ef7ede98e49f5f094b150d604c7ad50f125279180a7320b1b14ef3ccc3a34
上面的命令會生成一個新的證書密鑰,但是只有2小時有效期。由於我們現有的集群已經運行一段時間了,所以之前的啟動 Token 也已經失效了(Token 的默認生存期為24小時),所以我們也需要創建一個新的 Token 來添加新的控制平面節點:
$ kubeadm token create --print-join-command --config kubeadm.yaml W0903 15:29:10.958329 25049 validation.go:28] Cannot validate kube-proxy config - no validator is available W0903 15:29:10.958457 25049 validation.go:28] Cannot validate kubelet config - no validator is available kubeadm join 192.168.166.100:16443 --token f27w7m.adelvl3waw9kqdhp --discovery-token-ca-cert-hash sha256:6917cbf7b0e73ecfef77217e9a27e76ef9270aa379c34af30201abd0f1088c34
上面的命令最后給出的提示是添加 node 節點的命令,我們這里要添加控制平面節點就要使用如下所示的命令:
$ kubeadm join <DNS CNAME of load balancer>:<lb port> \ --token <bootstrap-token> \ --discovery-token-ca-cert-hash sha256:<CA certificate hash> \ --control-plane --certificate-key <certificate-key>
獲得了上面的添加命令過后,登錄到 ydzs-master2 節點進行相關的操作,在 ydzs-master2 節點上安裝軟件:
$ yum install -y kubeadm-1.19.0 kubelet-1.19.0 kubectl-1.19.0
要加入控制平面,我們可以先拉取相關鏡像:
$ kubeadm config images pull --image-repository registry.aliyuncs.com/k8sxio
然后執行上面生成的 join 命令,將參數替換后如下所示:
$ kubeadm join 192.168.166.100:16443 \ --token f27w7m.adelvl3waw9kqdhp \ --discovery-token-ca-cert-hash sha256:6917cbf7b0e73ecfef77217e9a27e76ef9270aa379c34af30201abd0f1088c34 \ --control-plane --certificate-key e71ef7ede98e49f5f094b150d604c7ad50f125279180a7320b1b14ef3ccc3a34 [preflight] Running pre-flight checks [preflight] Reading configuration from the cluster... [preflight] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' [preflight] Running pre-flight checks before initializing the new control plane instance [preflight] Pulling images required for setting up a Kubernetes cluster [preflight] This might take a minute or two, depending on the speed of your internet connection [preflight] You can also perform this action in beforehand using 'kubeadm config images pull' [download-certs] Downloading the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace [certs] Using certificateDir folder "/etc/kubernetes/pki" [certs] Generating "apiserver-kubelet-client" certificate and key [certs] Generating "apiserver" certificate and key [certs] apiserver serving cert is signed for DNS names [ydzs-master2 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local api.k8s.local api.k8s.local ydzs-master2 ydzs-master3] and IPs [10.96.0.1 10.151.30.70 10.151.30.11 10.151.30.70 10.151.30.71] [certs] Generating "front-proxy-client" certificate and key [certs] Generating "etcd/healthcheck-client" certificate and key [certs] Generating "etcd/server" certificate and key [certs] etcd/server serving cert is signed for DNS names [ydzs-master2 localhost] and IPs [10.151.30.70 127.0.0.1 ::1] [certs] Generating "etcd/peer" certificate and key [certs] etcd/peer serving cert is signed for DNS names [ydzs-master2 localhost] and IPs [10.151.30.70 127.0.0.1 ::1] [certs] Generating "apiserver-etcd-client" certificate and key [certs] Valid certificates and keys now exist in "/etc/kubernetes/pki" [certs] Using the existing "sa" key [kubeconfig] Generating kubeconfig files [kubeconfig] Using kubeconfig folder "/etc/kubernetes" [endpoint] WARNING: port specified in controlPlaneEndpoint overrides bindPort in the controlplane address [kubeconfig] Writing "admin.conf" kubeconfig file [kubeconfig] Writing "controller-manager.conf" kubeconfig file [kubeconfig] Writing "scheduler.conf" kubeconfig file [control-plane] Using manifest folder "/etc/kubernetes/manifests" [control-plane] Creating static Pod manifest for "kube-apiserver" W0903 15:55:08.444989 4353 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC" [control-plane] Creating static Pod manifest for "kube-controller-manager" W0903 15:55:08.457787 4353 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC" [control-plane] Creating static Pod manifest for "kube-scheduler" W0903 15:55:08.459829 4353 manifests.go:214] the default kube-apiserver authorization-mode is "Node,RBAC"; using "Node,RBAC" [check-etcd] Checking that the etcd cluster is healthy ...... This node has joined the cluster and a new control plane instance was created: * Certificate signing request was sent to apiserver and approval was received. * The Kubelet was informed of the new secure connection details. * Control plane (master) label and taint were applied to the new node. * The Kubernetes control plane instances scaled up. * A new etcd member was added to the local/stacked etcd cluster. To start administering your cluster from this node, 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 Run 'kubectl get nodes' to see this node join the cluster.
查看etcd
$ cat /etc/kubernetes/manifests/etcd.yaml ...... - --initial-cluster=k8s-master2=https://192.168.166.129:2380,k8s-master1=https://192.168.166.128:2380 - --initial-cluster-state=existing ......
查看集群是否正常:
[root@k8s-master2 ~]# kubectl get node NAME STATUS ROLES AGE VERSION k8s-master1 Ready master 4h29m v1.19.0 k8s-master2 Ready master 3h47m v1.19.0 k8s-node1 Ready <none> 4h15m v1.19.0 k8s-node2 Ready <none> 4h14m v1.19.0
這里我們就可以看到 k8s-master1、k8s-master2 2個節點變成了 master 節點,我們也就完成了將單 master 升級為多 master 的高可用集群了。
最后負載均衡訪問測試:
找K8s集群中任意一個節點,使用curl查看K8s版本測試,使用VIP訪問:
$ curl -k https://192.168.166.100:16443/version { "major": "1", "minor": "20", "gitVersion": "v1.20.0", "gitCommit": "e87da0bd6e03ec3fea7933c4b5263d151aafd07c", "gitTreeState": "clean", "buildDate": "2021-02-18T16:03:00Z", "goVersion": "go1.15.8", "compiler": "gc", "platform": "linux/amd64" }
可以正確獲取到K8s版本信息,說明負載均衡器搭建正常。該請求數據流程:curl -> vip(nginx) -> apiserver
通過查看Nginx日志也可以看到轉發apiserver IP:
$ tail /var/log/nginx/k8s-access.log -f 192.168.166.130 192.168.166.129:6443 - [13/Jun/2021:15:06:15 +0800] 200 423 192.168.166.130 192.168.166.128:6443 - [13/Jun/2021:15:06:15 +0800] 200 423 192.168.166.130 192.168.166.128:6443 - [13/Jun/2021:15:06:15 +0800] 200 423 192.168.166.130 192.168.166.129:6443 - [13/Jun/2021:15:06:15 +0800] 200 423 192.168.166.130 192.168.166.129:6443 - [13/Jun/2021:15:06:15 +0800] 200 423