第
1
則
介紹
k8s的node預設已經有高可用了,因為在pod會随機配置設定到各個node上,如果有pod挂了,就會配置設定到其他node上,是以這裡主要是做一下master的高可用
kube-controller-manager
與kube-scheduler高可用
這兩項服務是Master節點的一部分,他們的高可用相對容易,僅需要運作多份執行個體即可。這兩項服務是有狀态的服務,這些執行個體會通過向apiserver中的Endpoint加鎖的方式來進行leader election, 當目前拿到leader的執行個體無法正常工作時,别的執行個體會拿到鎖,變為新的leader。
這種選舉操作是通過在kube-system名稱空間中建立一個與程式同名的Endpoints資源對象來實作。各執行個體通過apiserver去擷取endpoint的狀态,通過競争的方式去搶占指定的Endpoint資源鎖,勝利者将成為leader。
[root@k8s-master-101 ~]# kubectl get endpoints -n kube-system
NAME ENDPOINTS AGE
kube-controller-manager <none> 23d
kube-scheduler <none> 23d
在搭建完後實驗,一開始111這台master為leader,然後把111上的kube-controller關閉後可以看到101這台master變為了leader,實作了高可用。
[root@k8s-master-101 ~]# kubectl describe endpoints kube-controller-manager -n kube-system Name: kube-controller-manager
Namespace: kube-system
Labels: <none>
Annotations: control-plane.alpha.kubernetes.io/leader:
{"holderIdentity":"k8s-master-101_c6cd4e97-53ba-11e9-9694-000c293313a6","leaseDurationSeconds":15,"acquireTime":"2019-03-31T14:14:51Z","re...
Subsets:
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal LeaderElection 34m kube-controller-manager k8s-master-111_3fa9e034-53ba-11e9-9ba6-000c29785034 became leader
Normal LeaderElection 29s kube-controller-manager k8s-master-101_c6cd4e97-53ba-11e9-9694-000c293313a6 became leader
kube-scheduler和controller-manager不需要做高可用,因為它們預設會通過選舉産生。
2
apiserver的高可用也有三種基本思路:
一是使用外部負載均衡器。不管是使用公有雲提供的負載均衡器服務或是在私有雲中使用LVS或者HaProxy自建負載均衡器都可以歸到這一類。 負載均衡器是非常成熟的方案,在這裡略過不做過多介紹。如何保證負載均衡器的高可用,則是選擇這一方案需要考慮的新問題。
二是在網絡層做負載均衡。比如在Master節點上用BGP做ECMP,或者在Node節點上用iptables做NAT都可以實作。采用這一方案不需要額外的外部服務,但是對網絡配置有一定的要求。
三是在Node節點上使用反向代理對多個Master做負載均衡。這一方案同樣不需要依賴外部的元件,但是當Master節點有增減時,如何動态配置Node節點上的負載均衡器成為了另外一個需要解決的問題。
3
官方的master節點高可用架構

可以看出,使用者通過kubectl發送指令經過LB進行負載均衡到後端的master上的apiserver,再由具體的某一個master進行向叢集内部的節點的轉發。
同理,節點也是通過LB進行負載均衡連接配接到master上的apiserver,去擷取到apiserver中配置的資訊。
4
其他高可用叢集架構
可以看到,每一台node上都部署了 nginx做負載均衡到master的apiserver。
高可用部署(node節點部署nginx代理方式)
将master節點擴充至2個,新增加的master的ip為:10.0.0.111
在原先的master上的server-csr.json中增加
新增master的ip:
vim server-csr.json
[root@k8s-master-101 ssl]# cat server-csr.json
{
"CN": "kubernetes",
"hosts": [
"127.0.0.1",
"10.10.10.1",
"10.0.0.101",
"10.0.0.102",
"10.0.0.103",
"10.0.0.111",
"kubernetes",
"kubernetes.default",
"kubernetes.default.svc",
"kubernetes.default.svc.cluster",
"kubernetes.default.svc.cluster.local"
],
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "CN",
"L":"Shenzhen",
"ST": "Guangzhou",
"O": "k8s",
"OU": "System"
}
]
}
重新生成server證書:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=kubernetes server-csr.json | cfssljson -bare server
cp -p server-key.pem server.pem /opt/kubernetes/ssl/
systemctl restart kube-apiserver
将原先master上的/opt/kubernetes發送到
新的master節點上:
scp -r /opt/kubernetes/ [email protected]:/opt
從原先的master上拷貝服務的配置檔案到
新的master上:
scp /usr/lib/systemd/system/{kube-apiserver,kube-scheduler,kube-controller-manager}.service [email protected]:/usr/lib/systemd/system/
5
修改新master節點上的kube-apiserver
配置檔案:
将advertise-address和bind-address改為新master本機的ip
vim /opt/kubernetes/cfg/kube-apiserver
[root@k8s-master-111 ~]# cat /opt/kubernetes/cfg/kube-apiserver
KUBE_APISERVER_OPTS="--logtostderr=true \--v=4 \
--etcd-servers=https://10.0.0.101:2379,https://10.0.0.102:2379,https://10.0.0.103:2379 \
--insecure-bind-address=127.0.0.1 \
--bind-address=10.0.0.111 \
--insecure-port=8080 \
--secure-port=6443 \
--advertise-address=10.0.0.111 \
--allow-privileged=true \
--service-cluster-ip-range=10.10.10.0/24 \
--admission-control=NamespaceLifecycle,LimitRanger,SecurityContextDeny,ServiceAccount,ResourceQuota,NodeRestriction --authorization-mode=RBAC,Node \
--kubelet-https=true \
--enable-bootstrap-token-auth \
--token-auth-file=/opt/kubernetes/cfg/token.csv \
--service-node-port-range=30000-50000 \
--tls-cert-file=/opt/kubernetes/ssl/server.pem \
--tls-private-key-file=/opt/kubernetes/ssl/server-key.pem \
--client-ca-file=/opt/kubernetes/ssl/ca.pem \
--service-account-key-file=/opt/kubernetes/ssl/ca-key.pem \
--etcd-cafile=/opt/kubernetes/ssl/ca.pem \
--etcd-certfile=/opt/kubernetes/ssl/server.pem \
--etcd-keyfile=/opt/kubernetes/ssl/server-key.pem"
6
啟動服務
systemctl daemon-reloadsystemctl start kube-apiserver.service
systemctl enable kube-apiserver.service
systemctl start kube-scheduler.service
systemctl enable kube-scheduler.service
systemctl start kube-controller-manager.service
systemctl enable kube-controller-manager.service
7
在新的master上使用kubectl檢視
叢集中的節點:
echo PATH=$PATH:/opt/kubernetes/bin >> /etc/profile
source /etc/profile
kubectl get node
[root@k8s-master-111 ~]# kubectl get node
NAME STATUS ROLES AGE VERSION
10.0.0.102 Ready <none> 23d v1.12.2
10.0.0.103 Ready <none> 23d v1.12.2
node節點配置
首先在兩台node節點上
安裝nginx做4層負載均衡:
添加nginx源
vim /etc/yum.repos.d/nginx.repo
[root@k8s-node1-102 ~]# cat /etc/yum.repos.d/nginx.repo
[nginx]
name=nginx
repobaseurl=http://nginx.org/packages/centos/7/\$basearch/
gpgcheck=0
yum install -y nginx
配置nginx
把對本機127.0.0.1:6443的請求代理到兩個master幾點的6443節點上
vim /etc/nginx/nginx.conf
[root@k8s-node1-102 ~]# cat /etc/nginx/nginx.conf
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
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 10.0.0.101:6443;
server 10.0.0.111:6443;
server {
listen 127.0.0.1:6443;
proxy_pass k8s-apiserver;
}
在node節點上修改
bootstrap.kubeconfig kubelet
kubeconfig kube-proxy.kubeconfig中的apiserver位址為本地:server: https://127.0.0.1:6443,這樣node節點向apiserver的請求會先發向本機127.0.0.1:6443,然後經過代理轉發到兩個master節點上的apiserver端口
cd /opt/kubernetes/cfg
ls *config | xargs -i sed -i 's/10.0.0.101/127.0.0.1/' {}
在node節點上重新開機服務
systemctl restart kubelet.service
systemctl restart kube-proxy.service
在node節點上啟動nginx:
systemctl start nginx
systemctl enable nginx
檢查nginx日志有沒有代理記錄: