Kubernetes探祕-etcd節點和例項擴容
Kubernetes使用kubeadm安裝預設只有一個etcd例項,存在單點故障的風險。提升Kubernetes叢集可用性的方法包括:1、備份(Kubernetes探祕—etcd狀態資料及其備份 );2、etcd節點和例項擴容;3、apiserver的多節點服務和負載均衡。這裡主要實驗etcd節點和例項的擴容。
一、etcd擴容,主要思路
etcd是一個獨立的服務,在kubernetes中使用時將配置引數和資料目錄分別對映到了宿主機目錄,而且使用hostnetwork網路(本主機網路)。其中,/etc/kubernetes/manifest/etcd.yaml 為啟動引數檔案,/etc/kubernetes/pki/etcd
對於已用kubeadm安裝的單Master節點Kubernetes叢集,其etcd執行例項只有一個。我們希望將其etcd例項擴充套件到多個,以降低單點失效風險。Kubernetes中etcd的擴容的思路如下:
- 所有節點安裝kubeadm/kubectl/kubelet,按照獨立master節點安裝。
- 建立etcd叢集的證書,並複製到各個節點。
- 在各節點修改etcd啟動配置檔案,啟動etcd例項。有多種方式(執行結果一樣、管理方式不同):
- 通過 kubectl 部署,讓kubernetes控制啟動。通過nodeSelector指定執行的節點。
- 通過 kubelet 服務來啟動,作業系統通過systemd啟動kubelet服務。這是k8s的標準過程。
- 通過docker的--restart引數讓容器自行啟動,由容器服務來進行管理。
- 把etcd作為宿主機服務來直接啟動,不使用Docker或者k8s管理。
- 將所有節點kube-apiserver.yaml的etcd服務指向本地的etcd服務例項。
- etcd是分散式的儲存,所有節點的資料將會自動同步,從任何節點訪問都是一樣的。
二、etcd擴容,實驗步驟
第一步:安裝多個節點
準備好安裝etcd的節點。我使用ubuntu 18.04LTS,然後安裝Docker CE 18.06和kubernetes 1.12.3。
我這裡的三個節點分別為:
- podc01, 10.1.1.201
- podc02, 10.1.1.202
- podc03, 10.1.1.203
需要提前把k8s用到的容器映象拉取下來到每一個節點。參考:
- Kubernetes 1.12.3快速升級
- Kubernetes 版本鎖定到1.12.3
- 多網絡卡Ubuntu伺服器安裝Kubernetes
- Ubuntu 18.04 設定多網絡卡多埠聚合
- 快速建立Kubernetes叢集,從零開始
第二步:建立etcd證書
本想嘗試複製主節點的/etc/kubernetes/kpi和/etc/kubernetes/manifest目錄到所有副(mate)節點,啟動後出現各種問題無法正常訪問,提示是ca證書問題。最後,準備從頭開始建立自己的證書和部署yaml檔案。
建立證書使用cfssl來建立,需要下載模版檔案和修改定義檔案,包括ca機構、ca-config配置、ca-key私鑰、csr請求、server/peer/client等證書的配置模版檔案等。需要將裡面的資訊按照自己的環境進行修改。
- 最後生成cert-file證書檔案、key-file公鑰檔案和trusted-ca-file證書機構檔案(因為我們這裡用的是自簽名,所以建立自己的證書機構檔案)。
- 這三個檔案在etcd例項啟動時配置進去(注意:API2和API3的引數名稱有些不同),需要放到每一個節點的相應目錄,並對映到etcd容器卷中。
- 使用etcdctl作為服務客戶端訪問時也需要指定相應的引數,其它對端(Peer)etcd例項也需要使用這些引數來相互訪問、組成叢集、同步資料。
下面說明具體過程(更多資訊參考 https://segmentfault.com/a/1190000016010980)。
1、準備cfssl證書工具
mkdir ~/cfssl && cd ~/cfssl
mkdir bin && cd bin
wget https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 -O cfssl
wget https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 -O cfssljson
chmod +x {cfssl,cfssljson}
export PATH=$PATH:~/cfssl/bin
- 可選:為了方便,可以將path新增到~/.profile檔案中,或者複製到/usr/local/bin目錄。
2、建立證書配置檔案
建立證書配置檔案目錄:
mkdir -p ~/cfssl/etcd-certs && cd ~/cfssl/etcd-certs
生成證書配置檔案放到~/cfssl/etcd-certs目錄中,檔案模版如下:
# ==============================================
# ca-config.json
{
"signing": {
"default": {
"expiry": "43800h"
},
"profiles": {
"server": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth"
]
},
"client": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"client auth"
]
},
"peer": {
"expiry": "43800h",
"usages": [
"signing",
"key encipherment",
"server auth",
"client auth"
]
}
}
}
}
# ==============================================
# ca-csr.json
{
"CN": "My own CA",
"key": {
"algo": "rsa",
"size": 2048
},
"names": [
{
"C": "US",
"L": "CA",
"O": "My Company Name",
"ST": "San Francisco",
"OU": "Org Unit 1",
"OU": "Org Unit 2"
}
]
}
# ==============================================
# server.json
{
"CN": "etcd0",
"hosts": [
"127.0.0.1",
"0.0.0.0",
"10.1.1.201",
"10.1.1.202",
"10.1.1.203"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
# ==============================================
# peer1.json # 填本機IP
{
"CN": "etcd0",
"hosts": [
"10.1.1.201"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
# ==============================================
# client.json
{
"CN": "client",
"hosts": [
""
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
3、建立etcd叢集的證書
操作如下:
cd ~/cfssl/etcd-certs
cfssl gencert -initca ca-csr.json | cfssljson -bare ca -
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server server.json | cfssljson -bare server
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer peer1.json | cfssljson -bare peer1
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client
檢視所產生的證書檔案:
ls -l ~/cfssl/etcd-certs
檔案包括:
...
第三步:啟動etcd多例項
啟動etcd例項之前,務必將/var/lib/etcd目錄清空,否則一些設定的引數將不會起作用,仍然保留原來的狀態。
注意,etcd的下面幾個引數只在第一次啟動(初始化)時起作用,包括:
- - --initial-advertise-peer-urls=http://10.1.1.202:2380
- - --initial-cluster=podc02=http://10.1.1.202:2380,podc03=http://10.1.1.203:2380
- - --initial-cluster-token=etcd-cluster
- - --initial-cluster-state=new
1、上傳證書檔案
將cfssl/etcd-certs目錄拷貝到/etc/kubernetes/pki/etcd-certs 目錄,可以使用scp或sftp上傳。
2、編輯啟動檔案
編輯/etc/kubernetes/manifests/etcd.yaml檔案,這是kubelet啟動etcd例項的配置檔案。
# /etc/kubernetes/manifests/etcd.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://10.1.1.201:2379
- --cert-file=/etc/kubernetes/pki/etcd-certs/server.pem
- --client-cert-auth=true
- --data-dir=/var/lib/etcd
- --initial-advertise-peer-urls=https://10.1.1.201:2380
- --initial-cluster=etcd0=https://10.1.1.201:2380
- --key-file=/etc/kubernetes/pki/etcd-certs/server-key.pem
- --listen-client-urls=https://10.1.1.201:2379
- --listen-peer-urls=https://10.1.1.201:2380
- --name=etcd1
- --peer-cert-file=/etc/kubernetes/pki/etcd-certs/peer1.pem
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd-certs/peer1-key.pem
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd-certs/ca.pem
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd-certs/ca.pem
image: k8s.gcr.io/etcd-amd64:3.2.18
imagePullPolicy: IfNotPresent
#livenessProbe:
# exec:
# command:
# - /bin/sh
# - -ec
# - ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.201]:2379 --cacert=/etc/kubernetes/pki/etcd-certs/ca.pem
# --cert=/etc/kubernetes/pki/etcd-certs/client.pem --key=/etc/kubernetes/pki/etcd-certs/client-key.pem
# get foo
# failureThreshold: 8
# initialDelaySeconds: 15
# timeoutSeconds: 15
name: etcd
resources: {}
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-data
- hostPath:
path: /etc/kubernetes/pki/etcd-certs
type: DirectoryOrCreate
name: etcd-certs
status: {}
參照上面的模式,在各個副節點修改etcd啟動引數/etc/kubernetes/manifest/etcd.yaml檔案內容。
- 注意:IP地址需要修改多個地方,不要遺漏、錯誤。
- 重啟kubelet服務。
- sudo systemctl restart kubelet。
- 檢查etcd服務。
- ectdctl 連線到例項,etcdctl member list。
- 最終,多節點的etcd例項連結為一個叢集。
3、驗證執行狀態
進入etcd容器執行:
alias etcdv3="ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.201]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.pem --cert=/etc/kubernetes/pki/etcd/client.pem --key=/etc/kubernetes/pki/etcd/client-key.pem"
etcdv3 member add etcd1 --peer-urls="https://10.1.1.202:2380"
4、增加etcd節點
拷貝etcd1(10.1.1.201)節點上的證書到etcd1(10.1.1.202)節點上,複製peer1.json到etcd2的peer2.json,修改peer2.json。
# peer2.json
{
"CN": "etcd1",
"hosts": [
"10.1.86.202"
],
"key": {
"algo": "ecdsa",
"size": 256
},
"names": [
{
"C": "US",
"L": "CA",
"ST": "San Francisco"
}
]
}
重新生成在etcd1上生成peer1證書:
cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer peer1.json | cfssljson -bare peer1
啟動etcd1,配置檔案如下:
# etcd02 etcd.yaml
apiVersion: v1
kind: Pod
metadata:
annotations:
scheduler.alpha.kubernetes.io/critical-pod: ""
creationTimestamp: null
labels:
component: etcd
tier: control-plane
name: etcd
namespace: kube-system
spec:
containers:
- command:
- etcd
- --advertise-client-urls=https://10.1.1.202:2379
- --cert-file=/etc/kubernetes/pki/etcd-certs/server.pem
- --data-dir=/var/lib/etcd
- --initial-advertise-peer-urls=https://10.1.1.202:2380
- --initial-cluster=etcd01=https://10.1.1.201:2380,etcd02=https://10.1.1.202:2380
- --key-file=/etc/kubernetes/pki/etcd-certs/server-key.pem
- --listen-client-urls=https://10.1.1.202:2379
- --listen-peer-urls=https://10.1.1.202:2380
- --name=etcd02
- --peer-cert-file=/etc/kubernetes/pki/etcd-certs/peer2.pem
- --peer-client-cert-auth=true
- --peer-key-file=/etc/kubernetes/pki/etcd-certs/peer2-key.pem
- --peer-trusted-ca-file=/etc/kubernetes/pki/etcd-certs/ca.pem
- --snapshot-count=10000
- --trusted-ca-file=/etc/kubernetes/pki/etcd-certs/ca.pem
- --initial-cluster-state=existing # 千萬別加雙引號,被坑死
image: k8s.gcr.io/etcd-amd64:3.2.18
imagePullPolicy: IfNotPresent
# livenessProbe:
# exec:
# command:
# - /bin/sh
# - -ec
# - ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.1.202]:2379 --cacert=/etc/kubernetes/pki/etcd-certs/ca.crt
# --cert=/etc/kubernetes/pki/etcd/healthcheck-client.crt --key=/etc/kubernetes/pki/etcd-certs/healthcheck-client.key
# get foo
# failureThreshold: 8
# initialDelaySeconds: 15
# timeoutSeconds: 15
name: etcd
resources: {}
volumeMounts:
- mountPath: /var/lib/etcd
name: etcd-data
- mountPath: /etc/kubernetes/pki/etcd
name: etcd-certs
hostNetwork: true
priorityClassName: system-cluster-critical
volumes:
- hostPath:
path: /var/lib/etcd
type: DirectoryOrCreate
name: etcd-data
- hostPath:
path: /etc/kubernetes/pki/etcd-certs
type: DirectoryOrCreate
name: etcd-certs
status: {}
進入etcd容器執行:
alias etcdv3="ETCDCTL_API=3 etcdctl --endpoints=https://[10.1.86.201]:2379 --cacert=/etc/kubernetes/pki/etcd/ca.pem --cert=/etc/kubernetes/pki/etcd/client.pem --key=/etc/kubernetes/pki/etcd/client-key.pem"
etcdv3 member add etcd1 --peer-urls="https://10.1.1.203:2380"
按照以上步驟,增加etcd03。
5、etcd叢集健康檢查
# etcdctl --endpoints=https://[10.1.1.201]:2379 --ca-file=/etc/kubernetes/pki/etcd-certs/ca.pem --cert-file=/etc/kubernetes/pki/etcd-certs/client.pem --key-file=/etc/kubernetes/pki/etcd-certs/client-key.pem cluster-health
member 5856099674401300 is healthy: got healthy result from https://10.1.86.201:2379
member df99f445ac908d15 is healthy: got healthy result from https://10.1.86.202:2379
cluster is healthy
第四步:修改apiserver服務指向
- --etcd-cafile=/etc/kubernetes/pki/etcd-certs/ca.pem
- --etcd-certfile=/etc/kubernetes/pki/etcd-certs/client.pem
- --etcd-keyfile=/etc/kubernetes/pki/etcd-certs/client-key.pem
至此,etcd已經擴充套件成多節點的分散式叢集,而且各個節點的kubernetes都是可以訪問的。
注意:
- 上面的流程適合剛建立的k8s叢集。
- 如果已經有kubeadm的多節點叢集,可以先建立node2/node3的etcd叢集,然後將node1的資料同步過來,再新增node1叢集,就能保留原來的資料。
上面所部署的工作節點還只能連線到一個apiserver,其它副節點的apiserver雖然可用但是無法被工作節點連線到。
下一步需要實現多master節點的容錯,遇主節點故障時可以轉移訪問其它的副節點。
更多參考
- etcd動態擴容,https://blog.csdn.net/ShouTouDeXingFu/article/details/81172308
- kube-keepalived-vip,https://github.com/kubernetes/contrib/tree/master/keepalived-vip
- 基於Kubeadm的高可用Kubernetes叢集,https://tonybai.com/2017/05/15/setup-a-ha-kubernetes-cluster-based-on-kubeadm-part1/