Kubernetes的幾種主流部署方式02-kubeadm部署高可用集羣

在上篇文章minikube部署中,有提到Minikube部署Kubernetes的核心就是Kubeadm,這篇文章來詳細說明下Kubeadm原理及部署步驟。寫這篇文章的時候,Kubernetes1.14剛剛發佈,因此部署步驟以1.14版爲主。前端

Kubeadm原理簡述

Kubeadm工具的出發點很簡單,就是儘量簡單的部署一個生產可用的Kubernetes集羣。實際也確實很簡單,只須要兩條命令:node

# 建立一個 Master 節點
$ kubeadm init

# 將一個 Node 節點加入到當前集羣中
$ kubeadm join <Master 節點的 IP 和端口 >

kubeadm作了這些事
執行 kubeadm init時:linux

  • 自動化的集羣機器合規檢查
  • 自動化生成集羣運行所需的各種證書及各種配置,並將Master節點信息保存在名爲cluster-info的ConfigMap中。
  • 經過static Pod方式,運行API server, controller manager 、scheduler及etcd組件。
  • 生成Token以便其餘節點加入集羣

執行 kubeadm join時:git

  • 節點經過token訪問kube-apiserver,獲取cluster-info中信息,主要是apiserver的受權信息(節點信任集羣)。
  • 經過受權信息,kubelet可執行TLS bootstrapping,與apiserver真正創建互信任關係(集羣信任節點)。

簡單來講,kubeadm作的事就是把大部分組件都容器化,經過StaticPod方式運行,並自動化了大部分的集羣配置及認證等工做,簡單幾步便可搭建一個可用Kubernetes的集羣。github

這裏有個問題,爲何不把kubelet組件也容器化呢,是由於,kubelet在配置容器網絡、管理容器數據卷時,都須要直接操做宿主機,而若是如今 kubelet 自己就運行在一個容器裏,那麼直接操做宿主機就會變得很麻煩。好比,容器內要作NFS的掛載,須要kubelet先在宿主機執行mount掛載NFS。若是kubelet運行在容器中問題來了,若是kubectl運行在容器中,要操做宿主機的Mount Namespace是很是複雜的。因此,kubeadm選擇把kubelet運行直接運行在宿主機中,使用容器部署其餘Kubernetes組件。因此,Kubeadm部署要安裝的組件有Kubeadm、kubelet、kubectl三個。web

上面說的是kubeadm部署方式的通常步驟,kubeadm部署是能夠自由定製的,包括要容器化哪些組件,所用的鏡像,是否用外部etcd,是否使用用戶證書認證等以及集羣的配置等等,都是能夠靈活定製的,這也是kubeadm可以快速部署一個高可用的集羣的基礎。詳細的說明能夠參考官方Reference。可是,kubeadm最重要的做用仍是解決集羣部署問題,而不是集羣配置管理的問題,官方也建議把Kubeadm做爲一個基礎工具,在其上層再去量身定製適合本身的集羣的管理工具(例如minikube)。docker

Kubeadm部署一個高可用集羣

Kubernetes的高可用

Kubernetes的高可用主要指的是控制平面的高可用,簡單說,就是有多套Master節點組件和Etcd組件,工做節點經過負載均衡鏈接到各Master。HA有兩種作法,一種是將etcd與Master節點組件混布在一塊兒:bootstrap

clipboard.png

另一種方式是,使用獨立的Etcd集羣,不與Master節點混布:segmentfault

clipboard.png

兩種方式的相同之處在於都提供了控制平面的冗餘,實現了集羣高能夠用,區別在於:
Etcd混布方式:後端

  • 所需機器資源少
  • 部署簡單,利於管理
  • 容易進行橫向擴展
  • 風險大,一臺宿主機掛了,master和etcd就都少了一套,集羣冗餘度受到的影響比較大。

Etcd獨立部署方式:

  • 所需機器資源多(按照Etcd集羣的奇數原則,這種拓撲的集羣關控制平面最少就要6臺宿主機了)。
  • 部署相對複雜,要獨立管理etcd集羣和和master集羣。
  • 解耦了控制平面和Etcd,集羣風險小健壯性強,單獨掛了一臺master或etcd對集羣的影響很小。

部署環境

因爲機器資源不足,下面的部署測試,只會以混布的方式部署一個1*haproxy,2*master,2*node,共5臺機器的集羣,實際上因爲etcd選舉要過半數,至少要3臺master節點才能構成高可用,在生產環境,仍是要根據實際狀況,儘可能選擇風險低的拓撲結構。

  • 機器:

master-1:192.168.41.230 (控制平面節點1)
master-2:192.168.41.231 (控制平面節點2)
node-1:172.16.201.108 (工做節點1)
node-2:172.16.201.109 (工做節點2)
haproxy:192.168.41.231 (haproxy)

  • 系統內核版本:
# cat /etc/redhat-release
CentOS Linux release 7.6.1810 (Core) 
# uname -r               
5.0.5-1.el7.elrepo.x86_64
  • 集羣版本

kubeadm:1.14.0
Kubernetes:1.14.0
Docker:Community 18.09.4
haproxy: 1.5.18

部署步驟

機器準備

在全部節點上操做:
  • 關閉selinux,firewall
setenforce  0
sed -i 's/SELINUX=enforcing/SELINUX=permissive/' /etc/selinux/config 
systemctl stop firewalld
systemctl disable firewalld
  • 關閉swap,(1.8版本後的要求,目的應該是不想讓swap干擾pod可以使用的內存limit)
swapoff -a
  • 修改下面內核參數,不然請求數據通過iptables的路由可能有問題
cat <<EOF >  /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sysctl --system

安裝kubeadm、docker

在除了haproxy之外全部節點上操做
  • 將Kubernetes安裝源改成阿里雲,方便國內網絡環境安裝
cat << EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64/
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
  • 安裝docker-ce
wget -O /etc/yum.repos.d/docker-ce.repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo

yum install -y docker-ce
  • 安裝kubelet kubeadm kubectl
yum install -y  kubelet kubeadm kubectl

安裝配置負載均衡

在haproxy節點操做:
# 安裝haproxy
yum install haproxy -y 

# 修改haproxy配置
cat << EOF > /etc/haproxy/haproxy.cfg
global
    log         127.0.0.1 local2
    chroot      /var/lib/haproxy
    pidfile     /var/run/haproxy.pid
    maxconn     4000
    user        haproxy
    group       haproxy
    daemon

defaults
    mode                    tcp
    log                     global
    retries                 3
    timeout connect         10s
    timeout client          1m
    timeout server          1m

frontend kube-apiserver
    bind *:6443 # 指定前端端口
    mode tcp
    default_backend master

backend master # 指定後端機器及端口,負載方式爲輪詢
    balance roundrobin
    server master-1  192.168.41.230:6443 check maxconn 2000
    server master-2  192.168.41.231:6443 check maxconn 2000
EOF

# 開機默認啓動haproxy,開啓服務
systemctl enable haproxy
systemctl start haproxy

# 檢查服務端口狀況:
# netstat -lntup | grep 6443
tcp        0      0 0.0.0.0:6443            0.0.0.0:*               LISTEN      3110/haproxy

部署Kubernetes

在master-1節點操做:
  • 準備集羣配置文件,目前用的api版本爲v1beta1,具體配置能夠參考官方reference
cat << EOF > /root/kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta1
kind: ClusterConfiguration
kubernetesVersion: v1.14.0 # 指定1.14版本
controlPlaneEndpoint: 192.168.41.232:6443 # haproxy地址及端口
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers # 指定鏡像源爲阿里源
networking:
  podSubnet: 10.244.0.0/16 # 計劃使用flannel網絡插件,指定pod網段及掩碼
EOF
  • 執行節點初始化
systemctl enable kubelet
systemctl start kubelet
kubeadm  config images pull  --config kubeadm-config.yaml  # 經過阿里源預先拉鏡像
kubeadm init --config=kubeadm-config.yaml --experimental-upload-certs

安裝成功,能夠看到輸出

You can now join any number of the control-plane node running the following command on each as root:
# master節點用如下命令加入集羣:

  kubeadm join 192.168.41.232:6443 --token ocb5tz.pv252zn76rl4l3f6 \
    --discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2 \
    --experimental-control-plane --certificate-key 20366c9cdbfdc1435a6f6d616d988d027f2785e34e2df9383f784cf61bab9826

Then you can join any number of worker nodes by running the following on each as root:
# 工做節點用如下命令加入集羣:
kubeadm join 192.168.41.232:6443 --token ocb5tz.pv252zn76rl4l3f6 \
    --discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2

原來的kubeadm版本,join命令只用於工做節點的加入,而新版本加入了 --experimental-contaol-plane 參數後,控制平面(master)節點也能夠經過kubeadm join命令加入集羣了。

  • 加入另一個master節點
在master-2操做:
kubeadm join 192.168.41.232:6443 --token ocb5tz.pv252zn76rl4l3f6 \
--discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2 \
--experimental-control-plane --certificate-key 20366c9cdbfdc1435a6f6d616d988d027f2785e34e2df9383f784cf61bab9826

mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

如今,在任何一個master 節點,執行kubectl get no,能夠看到,集羣中已經有2臺master節點了

# kubectl get no
NAME       STATUS     ROLES    AGE     VERSION
master-1   NotReady   master   34m     v1.14.0
master-2   NotReady   master   4m52s   v1.14.0
  • 加入兩個工做節點
分別在兩個node節點操做:
kubeadm join 192.168.41.232:6443 --token ocb5tz.pv252zn76rl4l3f6 \
    --discovery-token-ca-cert-hash sha256:141bbeb79bf58d81d551f33ace207c7b19bee1cfd7790112ce26a6a300eee5a2

再次執行kubectl get no

# kubectl  get no
NAME       STATUS     ROLES    AGE     VERSION
master-1   NotReady   master   45m     v1.14.0
master-2   NotReady   master   15m     v1.14.0
node-1     NotReady   <none>   6m19s   v1.14.0
node-2     NotReady   <none>   4m59s   v1.14.0

能夠看到兩個node節點都加入集羣了。但是,各個節點狀態爲何都是NotReady呢。經過執行kubectl describe master-1,能夠看到這樣的提示:

runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

原來是由於網絡插件沒有就緒致使的。因此 ,咱們來安裝一波

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/a70459be0084506e4ec919aa1c114638878db11b/Documentation/kube-flannel.yml

再次查看節點狀態,能夠看到全部節點都已經ready了。

# kubectl  get no
NAME       STATUS   ROLES    AGE    VERSION
master-1   Ready    master   134m   v1.14.0
master-2   Ready    master   104m   v1.14.0
node-1     Ready    <none>   94m    v1.14.0
node-2     Ready    <none>   93m    v1.14.0

至此,一個2主節點2工做節點的k8s集羣已經搭建完畢。若是要加入更多的master或node節點,只要屢次執行kubeadm join命令加入集羣就好,不須要額外配置,很是方便。

token過時問題

使用kubeadm join命令新增節點,須要2個參數,--token與--discovery-token-ca-cert-hash。其中,token有限期通常是24小時,若是超過期間要新增節點,就須要從新生成token。

# 從新建立token,建立完也能夠經過kubeadm token list命令查看token列表
$ kubeadm token create
s058gw.c5x6eeze28****

# 經過如下命令查看sha256格式的證書hash
$ openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //' 
9592464b295699696ce35e5d1dd155580ee29d9bd0884b*****

# 在新節點執行join
$  kubeadm join api-serverip:port --token s058gw.c5x6eeze28**** --discovery-token-ca-cert-hash 9592464b295699696ce35e5d1dd155580ee29d9bd0884b*****

集羣測試

跟上篇文章minikube部署同樣,這裏部署一個簡單的goweb服務來測試集羣,運行時暴露8000端口,同時訪問/info路徑會顯示容器的主機名。

  • 準備deployment和svc的yaml:
# deployment-goweb.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: goweb
spec:
  selector:
    matchLabels:
      app: goweb
  replicas: 4
  template:
    metadata:
      labels:
        app: goweb
    spec: 
      containers: 
      - image: lingtony/goweb
        name: goweb
        ports: 
        - containerPort: 8000
# svc-goweb.yaml
apiVersion: v1
kind: Service
metadata:
  name: gowebsvc
spec:
  selector:
    app: goweb
  ports:
  - name: default
    protocol: TCP
    port: 80
    targetPort: 8000
  • 部署服務
kubectl apply -f deployment-goweb.yaml
kubectl  apply -y svc-goweb.yaml
  • 查看pod及服務
[root@master-1 ~]# kubectl  get po -o wide
NAME                    READY   STATUS    RESTARTS   AGE   IP           NODE     NOMINATED NODE   READINESS GATES
goweb-6c569f884-67z89   1/1     Running   0          25m   10.244.1.2   node-1   <none>           <none>
goweb-6c569f884-bt4p6   1/1     Running   0          25m   10.244.1.3   node-1   <none>           <none>
goweb-6c569f884-dltww   1/1     Running   0          25m   10.244.1.4   node-1   <none>           <none>
goweb-6c569f884-vshkm   1/1     Running   0          25m   10.244.3.4   node-2   <none>           <none>
# 能夠看到,4個pod分佈在不一樣的node上
[root@master-1 ~]# kubectl  get svc
NAME         TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
gowebsvc     ClusterIP   10.106.202.0   <none>        80/TCP    11m
kubernetes   ClusterIP   10.96.0.1      <none>        443/TCP   21h
# 暴露80端口
  • 測試訪問
[root@master-1 ~]# curl http://10.106.202.0/info
Hostname: goweb-6c569f884-bt4p6
[root@master-1 ~]# curl http://10.106.202.0/info
Hostname: goweb-6c569f884-67z89
[root@master-1 ~]# curl http://10.106.202.0/info
Hostname: goweb-6c569f884-vshkm
#能夠看到,對SVC的請求會在pod間負載均衡。

小結

本文簡單介紹了kubeadm工具原理,以及如何用它部署一個高可用的kubernetes集羣。須要注意的是,kubeadm工具整體已經GA,能夠在生產環境使用了。可是文中經過"kubeadm join -experimental-contaol-plane"參數增長主節點的方式,仍是在alpha階段,實際在生產環境仍是用init方式來增長主節點比較穩定。kubeadm更多詳細配置能夠參考官方文檔

相關文章
相關標籤/搜索