2018/4/24html
僅供測試用途
前言:
高可用一直是重要的話題,須要持續研究。
最近關注到 k8s 官網文檔有更新,其中一篇部署高可用集羣的文章思路不錯,簡潔給力,但願能分享給有須要的小夥伴一塊兒研究下。node
步驟linux
有2種方式可供選擇git
##### 配置節點之間的 ssh 登陸(略) ##### 準備 docker, k8s 相關的 rpm 包 和鏡像(略) > 使用kubeadm部署k8s集羣00-緩存gcr.io鏡像 > 使用kubeadm部署k8s集羣01-初始化 ##### 準備工具 cfssl, cfssljson, etcd, etcdctl(全部節點上須要) curl -o /usr/local/bin/cfssl https://pkg.cfssl.org/R1.2/cfssl_linux-amd64 curl -o /usr/local/bin/cfssljson https://pkg.cfssl.org/R1.2/cfssljson_linux-amd64 chmod +x /usr/local/bin/cfssl* ##### 下載 etcd 和 etcdctl export ETCD_VERSION=v3.1.10 curl -sSL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz | tar -xzv --strip-components=1 -C /usr/local/bin/ rm -rf etcd-$ETCD_VERSION-linux-amd64* ##### 同步到另外2個節點 rsync -avzP /usr/local/bin/* 10.222.0.101:/usr/local/bin/ rsync -avzP /usr/local/bin/* 10.222.0.102:/usr/local/bin/
##### 在 master-100 上操做 mkdir -p /etc/kubernetes/pki/etcd cd /etc/kubernetes/pki/etcd/ cat >ca-config.json <<_EOF { "signing": { "default": { "expiry": "43800h" }, "profiles": { "server": { "expiry": "43800h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] }, "client": { "expiry": "43800h", "usages": [ "signing", "key encipherment", "client auth" ] }, "peer": { "expiry": "43800h", "usages": [ "signing", "key encipherment", "server auth", "client auth" ] } } } } _EOF cat >ca-csr.json <<_EOF { "CN": "etcd", "key": { "algo": "rsa", "size": 2048 } } _EOF ##### 生成 CA 證書 cfssl gencert -initca ca-csr.json | cfssljson -bare ca - ##### 輸出 ca.pem ca-key.pem
cat >client.json <<_EOF { "CN": "client", "key": { "algo": "ecdsa", "size": 256 } } _EOF ##### 生成 client 證書 cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=client client.json | cfssljson -bare client ##### 輸出 client.pem client-key.pem
rsync -avzP /etc/kubernetes/pki 10.222.0.101:/etc/kubernetes/ rsync -avzP /etc/kubernetes/pki 10.222.0.102:/etc/kubernetes/
##### 設置環境變量 export PEER_NAME=$(ip addr show eth0 | grep -Po 'inet \K[\d.]+' |awk -F'.' '{print "master-"$4}') export PRIVATE_IP=$(ip addr show eth0 | grep -Po 'inet \K[\d.]+') cfssl print-defaults csr > config.json sed -i '0,/CN/{s/example\.net/'"$PEER_NAME"'/}' config.json sed -i 's/www\.example\.net/'"$PRIVATE_IP"'/' config.json sed -i 's/example\.net/'"$PEER_NAME"'/' config.json cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=server config.json | cfssljson -bare server cfssl gencert -ca=ca.pem -ca-key=ca-key.pem -config=ca-config.json -profile=peer config.json | cfssljson -bare peer
##### 準備 etcd 服務依賴的環境變量 echo "PEER_NAME=$PEER_NAME" > /etc/etcd.env echo "PRIVATE_IP=$PRIVATE_IP" >> /etc/etcd.env ##### 準備 etcd 服務的配置文件 cat >/etc/systemd/system/etcd.service <<_EOF [Unit] Description=etcd Documentation=https://github.com/coreos/etcd Conflicts=etcd.service Conflicts=etcd2.service [Service] EnvironmentFile=/etc/etcd.env Type=notify Restart=always RestartSec=5s LimitNOFILE=40000 TimeoutStartSec=0 ExecStart=/usr/local/bin/etcd --name ${PEER_NAME} \ --data-dir /var/lib/etcd \ --listen-client-urls https://${PRIVATE_IP}:2379 \ --advertise-client-urls https://${PRIVATE_IP}:2379 \ --listen-peer-urls https://${PRIVATE_IP}:2380 \ --initial-advertise-peer-urls https://${PRIVATE_IP}:2380 \ --cert-file=/etc/kubernetes/pki/etcd/server.pem \ --key-file=/etc/kubernetes/pki/etcd/server-key.pem \ --client-cert-auth \ --trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem \ --peer-cert-file=/etc/kubernetes/pki/etcd/peer.pem \ --peer-key-file=/etc/kubernetes/pki/etcd/peer-key.pem \ --peer-client-cert-auth \ --peer-trusted-ca-file=/etc/kubernetes/pki/etcd/ca.pem \ --initial-cluster master-100=https://10.222.0.100:2380,master-101=https://10.222.0.101:2380,master-102=https://10.222.0.102:2380 \ --initial-cluster-token my-etcd-token \ --initial-cluster-state new [Install] WantedBy=multi-user.target _EOF ##### 激活 etcd 服務 systemctl daemon-reload systemctl enable etcd ##### 啓動 systemctl start etcd systemctl status etcd ##### 測試 export ETCDCTL_DIAL_TIMEOUT=3s export ETCDCTL_CACERT=/etc/kubernetes/pki/etcd/ca.pem export ETCDCTL_CERT=/etc/kubernetes/pki/etcd/client.pem export ETCDCTL_KEY=/etc/kubernetes/pki/etcd/client-key.pem export ETCDCTL_API=3 export ENDPOINTS="https://10.222.0.100:2379,https://10.222.0.101:2379,https://10.222.0.102:2379" etcdctl --endpoints=${ENDPOINTS} -w table endpoint status etcdctl --endpoints=${ENDPOINTS} put foo bar etcdctl --endpoints=${ENDPOINTS} get --prefix ''
mkdir -p ~/k8s_install/master/init cd ~/k8s_install/master/init ##### 備份 etcd 證書(該 etcd 集羣的全部節點都要備份本身的證書) cp -a /etc/kubernetes/pki/etcd ~/k8s_install/master/init/ ##### 後續若是 kubeadm reset 將致使 pki 目錄被清空,此時能夠恢復證書 cp -a ~/k8s_install/master/init/etcd /etc/kubernetes/pki/ ##### 準備配置用於初始化 export PRIVATE_IP=$(ip addr show eth0 | grep -Po 'inet \K[\d.]+') cat >config.yaml <<_EOF apiVersion: kubeadm.k8s.io/v1alpha1 kind: MasterConfiguration api: advertiseAddress: ${PRIVATE_IP} etcd: endpoints: - https://10.222.0.100:2379 - https://10.222.0.101:2379 - https://10.222.0.102:2379 caFile: /etc/kubernetes/pki/etcd/ca.pem certFile: /etc/kubernetes/pki/etcd/client.pem keyFile: /etc/kubernetes/pki/etcd/client-key.pem networking: podSubnet: 172.30.0.0/16 apiServerCertSANs: - 10.222.0.88 kubernetesVersion: v1.9.0 apiServerExtraArgs: endpoint-reconciler-type: lease _EOF ##### 開始初始化 master kubeadm init --config=config.yaml ##### 使用 kubectl mkdir -p $HOME/.kube cp -i /etc/kubernetes/admin.conf $HOME/.kube/config ##### 查看狀態 kubectl get ds,deploy,svc,pods --all-namespaces kubectl get nodes
##### 關於 calico 的更多內容,請參考筆記:使用kubeadm部署k8s集羣01-初始化 [root@master-100 ~]# mkdir -p ~/k8s_install/network/calico [root@master-100 ~]# cd ~/k8s_install/network/calico [root@master-100 calico]# curl -so calico-v3.0.yaml https://docs.projectcalico.org/v3.0/getting-started/kubernetes/installation/hosted/kubeadm/1.7/calico.yaml ##### 全部節點提早準備好鏡像,相似下述實例中,緩存 `calico-v3.0.yaml` 使用的鏡像,並打包同步到集羣全部節點上 [root@master-100 calico]# grep 'image' calico-v3.0.yaml |uniq |sed -e 's#^.*image: quay.io#docker pull quay.io#g' docker pull quay.io/coreos/etcd:v3.1.10 docker pull quay.io/calico/node:v3.0.4 docker pull quay.io/calico/cni:v2.0.3 docker pull quay.io/calico/kube-controllers:v2.0.2 [root@master-100 calico]# docker save -o calico-v3.0.tar quay.io/coreos/etcd:v3.1.10 quay.io/calico/node:v3.0.4 quay.io/calico/cni:v2.0.3 quay.io/calico/kube-controllers:v2.0.2 [root@master-100 calico]# scp calico-v3.0.tar 10.222.0.100:~/k8s_install/network/calico/ [root@master-102 calico]# docker load -i ~/k8s_install/network/calico/calico-v3.0.tar ##### 注意 CALICO_IPV4POOL_CIDR 是否和 podSubnet 一致,默認的須要替換: [root@master-100 calico]# sed -i 's#192.168.0.0/16#172.30.0.0/16#' calico-v3.0.yaml ##### 啓用 [root@master-100 calico]# kubectl apply -f calico-v3.0.yaml ##### 驗證網絡正常的方法是:檢查 deploy/kube-dns 是否上線
[警告]github
來自今天(2018-04-24)的實驗結果: 從下一步開始,加入多個 master 節點後,經過驗證 `calico` 和 `kube-dns` 並不能代表網絡可用。
實際上,須要驗證業務,由於我在實驗過程當中發現一個問題:web
業務 t1 部署後,運行在節點 worker-201 上,此時能經過 worker-201 的 ip:port 訪問,但沒法經過集羣的其餘節點來訪問docker
小結: 新的 master 節點在加入過程當中,對 iptables 規則的變化產生了影響。可能緣由是:新的服務上線後,更新了節點 worker-201 上的 iptables 規則,但遇到權限異常,沒法寫入 calico-etcd 集羣中,從而更新其餘節點上的 iptables 規則json
訴求: 請你們仔細驗證業務,確認網絡是否有異常!!後續將抽空研究該問題。後端
##### 初始化 master-101 master-102 > 將 master-101 加入集羣( 因 master-102 的操做同理,略過) > 同步在 master-100 上生成的 pki 相關的證書文件(除了 etcd 這個目錄因爲已經存在不會被 scp 同步),實際上,咱們只須要重建 `apiserver.*` 相關的證書 ```bash scp 10.222.0.100:/etc/kubernetes/pki/* /etc/kubernetes/pki rm apiserver.*
接下來,重複前述操做中,初始化 master-100 的指令便可將該節點加入集羣。api
提示:只是同步
ca.*
和sa.*
證書(照着Option 2: Copy paste
描述的操做)多是錯誤的,至少在個人實驗環境中,遇到了異常,致使 kube-dns 沒法上線,若是你也遇到相似的場景,請仔細查看 apiserver 的 pod 的日誌輸出是否有異常。
##### 這裏以清理 master-102 這個節點爲例說明: ##### 先在 master-100 上操做 kubectl drain master-102 --delete-local-data --force --ignore-daemonsets kubectl delete node master-102 ##### 而後在 master-102 上操做 kubeadm reset ##### 還原 etcd 相關的證書(由於 master-102 恰好也是 etcd 集羣的節點) cp -a ~/k8s_install/master/init/etcd /etc/kubernetes/pki/
##### 加入集羣 kubeadm join --token xxx.xxxxxxx 10.222.0.100:6443 --discovery-token-ca-cert-hash sha256:xxx
[警告]
(註明:未完成,下述內容待驗證)
kubectl get configmap -n kube-system kube-proxy -o yaml > kube-proxy-cm.yaml sed -i 's#server:.*#server: https://10.222.0.88:6443#g' kube-proxy-cm.yaml kubectl apply -f kube-proxy-cm.yaml --force kubectl delete pod -n kube-system -l k8s-app=kube-proxy ##### 更新 worker 上 kubelet 服務 sed -i 's#server:.*#server: https://10.222.0.88:6443#g' /etc/kubernetes/kubelet.conf systemctl restart kubelet
上述 kube-proxy 是一個 daemonset 類型的服務,也就是說 master 節點上也會有該服務,此時思考下述數據流向是否會有異常:
kube-proxy(on master-100) -> LB(backend to master-100)
上述場景,若是是 LVS/DR 模式的 LB 則意味着
RS1 -> LB1 -> RS1 致使: RS1 -> RS1
引用來自阿里雲 SLB 的文檔片斷(實際遇到的一個坑)
- 後端ECS實例爲何訪問不了負載均衡服務?
這和負載均衡TCP的實現機制有關。在四層TCP協議服務中,不支持後端ECS實例既做爲Real Server又做爲客戶端向所在的負載均衡實例發送請求。由於返回的數據包只在雲服務器內部轉發,不通過負載均衡,因此在後端ECS實例上去訪問負載均衡的服務地址是不通的。
結論1:若是從 master 節點的 IP 來訪問 k8s 中的訪問,可能出現異常。
結論2:僅將 worker 節點的 IP 添加到 SLB 中做爲後端,預計能避免上述異常。