使用kubeadm進行單master(single master)和高可用(HA)kubernetes叢集部署

xinkun發表於2019-06-18

kubeadm部署k8s

使用kubeadm進行k8s的部署主要分為以下幾個步驟:

  • 環境預裝: 主要安裝docker、kubeadm等相關工具。
  • 叢集部署: 叢集部署分為single master(單master,只有一個master節點)和高可用HA叢集部署兩種模式。主要部署k8s的相關元件。本文將分別做介紹。
  • 網路部署: 部署網路環境。本文以flannel為例進行部署。

環境預裝

在所有節點上都先要做好環境的準備,這裡以debian為例,整理了安裝docker和kubeadm的相關命令。這個裡面主要需要解決的是國內源的問題。

## 準備環境
swapoff -a
systemctl stop firewalld
systemctl disable firewalld

echo "net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
net.ipv4.ip_forward = 1" > /etc/sysctl.d/k8s.conf
sysctl -p /etc/sysctl.d/k8s.conf
modprobe br_netfilter

## 更換apt源
mv /etc/apt/sources.list /etc/apt/sources.list.bak
echo "deb http://mirrors.163.com/debian/ stretch main non-free contrib
deb http://mirrors.163.com/debian/ stretch-updates main non-free contrib
deb http://mirrors.163.com/debian/ stretch-backports main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch-updates main non-free contrib
deb-src http://mirrors.163.com/debian/ stretch-backports main non-free contrib
deb http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib
deb-src http://mirrors.163.com/debian-security/ stretch/updates main non-free contrib" > /etc/apt/sources.list

## 安裝docker
apt-get update
apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg2 \
    software-properties-common -y --force-yes
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -

apt-key fingerprint 0EBFCD88

add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/debian \
   $(lsb_release -cs) \
   stable"
   
apt-get update
apt-get install docker-ce containerd.io -y

## 使用阿里雲安裝kubeadm
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl

## 關閉swap
echo "vm.swappiness=0" >> /etc/sysctl.d/k8s.conf
sysctl -p /etc/sysctl.d/k8s.conf

以上命令在所有節點上都需要執行下。

單master叢集部署

單master叢集部署是以一個節點作為master節點,其他的節點作為node角色加入到叢集中。

首先在master節點上,通過kubeadm進行叢集的初始化。

nodename預設會使用hostname,這裡使用ip作為nodename,在檢視node節點時會更加直觀一些。
這裡面基本都使用的是國內的azure提供的映象源,映象下載速度比較快一些

cat << EOF > /root/kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: InitConfiguration
nodeRegistration:
  kubeletExtraArgs:
    pod-infra-container-image: gcr.azk8s.cn/google_containers/pause-amd64:3.1
---
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
imageRepository: gcr.azk8s.cn/google_containers
kubernetesVersion: v1.14.2
networking:
  podSubnet: 10.244.0.0/16
EOF

nodename=`ip -4 route get 8.8.8.8|head -n 1|awk -F ' ' '{print $NF}'`
echo $nodename
kubeadm init --config=kubeadm-config.yaml --apiserver-advertise-address=kubemaster.cluster.local --node-name $nodename > kubeadm.log

在master中檢視kubeadm.log中的最後幾行,可以看到其他節點加入叢集的命令。

root@i-5i2nhchleypb9h6oofb9h5suy:~# tail -n 5 kubeadm.log 
Then you can join any number of worker nodes by running the following on each as root:

kubeadm join kubemaster.cluster.local:6443 --token br1lyz.kgnz5d6apvtcvdlg \
--discovery-token-ca-cert-hash sha256:a8a80875b68ddd8d8e0cd794daa1b81a7893eebceca77c3d5f9074b2dc7e109b 

這時切換到其他的node節點,可以直接使用以下命令,加入叢集。

nodename=`ip -4 route get 8.8.8.8|head -n 1|awk -F ' ' '{print $NF}'`
echo $nodename
kubeadm join kubemaster.cluster.local:6443 --token bbnth6.tyxpf0ec27r5y5b8 \
    --discovery-token-ca-cert-hash sha256:5a9d6d25558c0e5031d4d6a69b555f0db8dd0ac7e798b9f823f7f33352748ae6 --node-name $nodename

node節點全部加入後,即完成節點的部署。

高可用(HA)叢集部署

高可用叢集目前支援兩種拓撲結構,一種是etcd在master節點中部署,一種是etcd在另外的節點中進行部署。在小規模叢集中,其實採用前者就可以了。本文也是採用這種方式。

高可用叢集一般需要三個以上的master節點組成,以及若干個node節點組成。其中master節點需要一個負載均衡器進行流量的分發。但是在小規模叢集中,額外再部署一個負載均衡器無疑會增加部署的複雜度。這裡我使用了一個偷懶的方式,就是不使用真實的負載均衡器,而是使用域名。這裡我有三個節點,我在每個節點的/etc/hosts中做了如下配置。這樣kubemaster.cluster.local就可以解析到三個節點上。

11.62.68.3    kubemaster.cluster.local
11.62.68.4    kubemaster.cluster.local
11.62.68.5    kubemaster.cluster.local

這裡為了防止連線都壓到同一臺上,可以在不同的節點上調整hosts中的配置順序。

這裡同前面相似,用以下命令進行叢集的初始化。這裡特別注意下在配置中同上面最大的區別在於加入了controlPlaneEndpoint: "kubemaster.cluster.local:6443"配置。實現對於叢集控制面的負載均衡器的配置。

cat << EOF > /root/kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: InitConfiguration
nodeRegistration:
  kubeletExtraArgs:
    pod-infra-container-image: gcr.azk8s.cn/google_containers/pause-amd64:3.1
---
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
imageRepository: gcr.azk8s.cn/google_containers
kubernetesVersion: v1.14.2
controlPlaneEndpoint: "kubemaster.cluster.local:6443"
networking:
  podSubnet: 10.244.0.0/16
EOF

nodename=`ip -4 route get 8.8.8.8|head -n 1|awk -F ' ' '{print $NF}'`
echo $nodename
kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs --node-name $nodename > kubeadm.log

在完成初始化後,可以檢視相關日誌。可以看到同單master部署模式的情況不同,高可用叢集中有兩個命令。

root@i-5i2nhchleypb9h6oofb9h5suy:~# tail -n 15 kubeadm.log 
You can now join any number of the control-plane node running the following command on each as root:

  kubeadm join kubemaster.cluster.local:6443 --token woebfo.mwj26odtpe2q0taj \
    --discovery-token-ca-cert-hash sha256:a09c6ac9ff8da73e0d5e19cea1d0df524a7e289ef7b144a6ede2b0052da87edb \
    --experimental-control-plane --certificate-key b73eba61d73c35ca4de43b9dd10a7db88023cbd767c98cc1d19489829ea0fc03

Please note that the certificate-key gives access to cluster sensitive data, keep it secret!
As a safeguard, uploaded-certs will be deleted in two hours; If necessary, you can use 
"kubeadm init phase upload-certs --experimental-upload-certs" to reload certs afterward.

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join kubemaster.cluster.local:6443 --token woebfo.mwj26odtpe2q0taj \
    --discovery-token-ca-cert-hash sha256:a09c6ac9ff8da73e0d5e19cea1d0df524a7e289ef7b144a6ede2b0052da87edb 

第一個是加入master的方式。也就是說,通過第一個命令加入後,該節點將會作為master加入到叢集中。這裡我們使用該命令即可將節點加入到master中,作為master的節點之一。

nodename=`ip -4 route get 8.8.8.8|head -n 1|awk -F ' ' '{print $NF}'`
echo $nodename
kubeadm join kubemaster.cluster.local:6443 --token pcumbv.qwa7uwzr7m7cijxy \
    --discovery-token-ca-cert-hash sha256:bae4c6e70cc92cc6cba66bc96d48bf0c5a45fddf83e90b89eea519fc4bad16ac \
    --experimental-control-plane --certificate-key 33f387801d51c0a743353357b138cf4ad70fd3acaa7a6ccec9835627773f1cb7 --node-name $nodename

當然,第二個同單master模式就相似了。

nodename=`ip -4 route get 8.8.8.8|head -n 1|awk -F ' ' '{print $NF}'`
echo $nodename
kubeadm join kubemaster.cluster.local:6443 --token woebfo.mwj26odtpe2q0taj \
    --discovery-token-ca-cert-hash sha256:a09c6ac9ff8da73e0d5e19cea1d0df524a7e289ef7b144a6ede2b0052da87edb --node-name $nodename

master節點準備

在master節點上可以做一些相關的準備,方便後面使用kubectl等命令。

systemctl enable kubelet.service

## 為kubectl準備config
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config

## 去掉master的汙點,使得master節點也可以建立容器
## 該命令可選。如果不想讓master執行node的角色,也可以不執行
kubectl taint nodes --all node-role.kubernetes.io/master-

網路安裝

這裡使用flannel網路。

mkdir -p ~/k8s/
cd ~/k8s
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml

## 這裡使用quay.azk8s.cn進行進行加速。該命令可選。
sed -i "s/quay.io/quay.azk8s.cn/g" kube-flannel.yml

kubectl apply -f kube-flannel.yml

測試

這裡我們嘗試在每個節點建立一個容器,然後進行叢集部署驗證。這裡給了一個樣例。

cat << EOF > /root/daemonset.yaml
apiVersion: extensions/v1beta1
kind: DaemonSet
metadata:
  name: debian
spec:
  template:
    metadata:
      labels:
        debian: debian
    spec:
      containers:
      - name: debian
        image: dockerhub.azk8s.cn/library/debian
        command: ["sleep", "999999d"]
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
EOF

kubectl create -f /root/daemonset.yaml

這裡我寫了一個小工具可以自動進行各個節點的容器之間的網路驗證,自動統計哪些節點還沒有正常執行。後面我會再開源出來放到部落格裡。

清理命令

有時候安裝失敗或者清理環境時一些常用的命令,也整理在了下面。

清理環境

該命令主要用於將kubeadm安裝的本節點恢復到安裝前。需要輸入yes確認。該命令適用於master和node節點。

kubeadm reset

清理cni0網橋

重複安裝有時候會導致cni0的配置錯誤,可以通過刪除cni0網橋,然後重新建立實現故障恢復。

apt-get install bridge-utils -y
ifconfig cni0 down
brctl delbr cni0
systemctl restart kubelet

清理iptables

kubeadm清理時不會清理iptables,裡面會有很多冗餘的規則,可以使用該命令清理。該命令慎用。

iptables -F && iptables -t nat -F && iptables -t mangle -F && iptables -X

清理bridge的殘餘資訊

在使用flannel時,有時mac資訊過時沒能更新,導致無法將訊息轉發到目標機器的flannel.1。可以在檢查後,通過bridge命令清理過期的mac資訊。

flannel的具體原理和排障可以參考我之前的部落格,《flannel vxlan工作基本原理及常見排障思路》。其中介紹更為詳細。

route -n 
arp -e
bridge fdb show
bridge fdb del 76:21:60:e5:ea:0b dev flannel.1

參考資料

相關文章