1. 程式人生 > 其它 >k8s-單節點升級為叢集(高可用)

k8s-單節點升級為叢集(高可用)

單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 { 
     [email protected] 
     [email protected] 
     [email protected] 
   } 
   notification_email_from [email protected]  
   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 { 
     [email protected] 
     [email protected] 
     [email protected] 
   } 
   notification_email_from [email protected]  
   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