1. 程式人生 > >搭建K8S叢集

搭建K8S叢集

一、前言

我們將現有的虛擬機器稱之為Node1,用作主節點。為了減少工作量,在Node1安裝Kubernetes後,我們利用VirtualBox的虛擬機器複製功能,複製出兩個完全一樣的虛擬機器作為工作節點。三者角色為:

  • Node1:Master

  • Node2:Woker

  • Node3:Woker

二、安裝Kubernetes

還是那句話,官方文件永遠是最好的參考資料:https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/

但是,僅供參考,因為牆的原因,並不完全適用於我們天朝子民。下面將詳細介紹在Node1上安裝Kubernetes的過程,安裝完畢後,再進行虛擬機器的複製出Node2、Node3即可。

配置K8S的yum源

官方倉庫無法使用,建議使用阿里源的倉庫,執行以下命令新增kubernetes.repo倉庫:

cat <<EOF > /etc/yum.repos.d/kubernetes.repo

[kubernetes]

name=Kubernetes

baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg

        http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF

關閉swap、防火牆

上一篇文章已介紹關閉

關閉SeLinux

執行:setenforce 0

安裝K8S元件

執行以下命令安裝kubelet、kubeadm、kubectl:

yum install -y kubelet kubeadm kubectl

如下圖所示:

 

image.png

配置kubelet的cgroup drive

確保docker 的cgroup drive 和kubelet的cgroup drive一樣:

docker info | grep -i cgroup

cat /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

若顯示不一樣,則執行:

sed -i "s/cgroup-driver=systemd/cgroup-driver=cgroupfs/g" /etc/systemd/system/kubelet.service.d/10-kubeadm.conf
systemctl daemon-reload

如圖:

 

image.png

啟動kubelet

注意,根據官方文件描述,安裝kubelet、kubeadm、kubectl三者後,要求啟動kubelet:
systemctl enable kubelet && systemctl start kubelet
但實際測試發現,無法啟動,報如下錯誤:

image.png

 

檢視日誌發現是沒有證書:

unable to load client CA file /etc/kubernetes/pki/ca.crt: open /etc/kubernetes/pki/ca.crt: no such file or directory

image.png

我在網上沒有找到解決方法,但無意測試中發現,後面的kubeadm init操作會建立證書。也就是說,現在無法啟動並不影響後續操作,繼續!

下載K8S的Docker映象

本文使用的是K8S官方提供的kubeadm工具來初始化K8S叢集,而初始化操作kubeadm init會預設去訪問谷歌的伺服器,以下載叢集所依賴的Docker映象,因此也會超時失敗,你懂得。

但是,只要我們可以提前匯入這些映象,kubeadm init操作就會發現這些映象已經存在,就不會再去訪問谷歌。網上有一些方法可以獲得這些映象,如利用Docker Hub製作映象等,但稍顯繁瑣。

這裡,我已將初始化時用到的所有Docker映象整理好了,映象版本是V1.10.0。推薦大家使用。

  • 地址:https://pan.baidu.com/s/11AheivJxFzc4X6Q5_qCw8A

  • 密碼:2zov

準備好的映象如下圖所示:

 

image.png

K8S更新速度很快,截止目前最新版本是V1.10.2。本人提供的映象會越來越舊,需要最新版本的讀者可以根據網上教材自行製作

指令碼docker_images_load.sh用於匯入映象:

docker load < quay.io#calico#node.tardocker load < quay.io#calico#cni.tardocker load < quay.io#calico#kube-controllers.tardocker load < k8s.gcr.io#kube-proxy-amd64.tardocker load < k8s.gcr.io#kube-scheduler-amd64.tardocker load < k8s.gcr.io#kube-controller-manager-amd64.tardocker load < k8s.gcr.io#kube-apiserver-amd64.tardocker load < k8s.gcr.io#etcd-amd64.tardocker load < k8s.gcr.io#k8s-dns-dnsmasq-nanny-amd64.tardocker load < k8s.gcr.io#k8s-dns-sidecar-amd64.tardocker load < k8s.gcr.io#k8s-dns-kube-dns-amd64.tardocker load < k8s.gcr.io#pause-amd64.tardocker load < quay.io#coreos#etcd.tardocker load < quay.io#calico#node.tardocker load < quay.io#calico#cni.tardocker load < quay.io#calico#kube-policy-controller.tardocker load < gcr.io#google_containers#etcd.tar

將映象與該指令碼放置同一目錄,執行即可匯入Docker映象。執行docker images,如下圖所示,即表示映象匯入成功:

image.png

 

三、複製虛擬機器

前言中提到,當Node1的Kubernetes安裝完畢後,就需要進行虛擬機器的複製了。

複製

複製前需要退出虛擬機器,我們選擇“正常關機”。右鍵虛擬機器點選複製:

 

image.png

如上,新的節點命名為CentOS-Node2,注意一定要勾選"重新初始化網絡卡Mac地址"。點選“複製”,稍等幾分鐘,即可完成複製:

image.png

 

依此法再複製一個節點命名為CentOS-Node3

新增網絡卡

複製結束後,如果直接啟動三個虛擬機器,你會發現每個機子的IP地址(網絡卡enp0s3)都是一樣的:

 

image.png

 

這是因為複製虛擬機器時連同網絡卡的地址也複製了,這樣的話,三個節點之間是無法訪問的。因此,我建議複製結束後,不要馬上啟動虛擬機器,而先要為每一個虛擬機器新增一個網絡卡,用於節點間的互通訪問。

如下圖所示,連線方式選擇“Host-Only”模式:

 

image.png

網絡卡新增結束後,啟動三個虛擬機器,檢視各個IP。以主節點Node1為例,執行ip addr

image.png


可以看到,網絡卡enp0s8為新新增的網絡卡2,IP地址為192.168.56.101。三個節點IP分別為:

 

  • Node1:192.168.56.101

  • Node2:192.168.56.102

  • Node3:192.168.56.103

在這三個節點中,可以使用這些IP互相ping一下,確保網路連通正常。

另外,同上一節所述,建議啟用埠轉發功能,使用Xshell連線到Node1和Node2的終端。

設定虛擬機器

網絡卡新增結束後,即可啟動三個虛擬機器,我們需要進行一些簡單的設定,以主節點Node1為例:

  • 編輯/etc/hostname,將hostname修改為k8s-node1

  • 編輯/etc/hosts,追加內容 IP k8s-node1

以上IP為網絡卡2的IP地址,修改後重啟生效。另外兩個節點修改同理,主機名分別為k8s-node2k8s-node3

四、建立叢集

kubeadm介紹

前面的工作都準備好後,我們就可以真正的建立叢集了。這裡使用的是官方提供的kubeadm工具,它可以快速、方便的建立一個K8S叢集。kubeadm的具體介紹大家可以參考官方文件:https://kubernetes.io/docs/setup/independent/create-cluster-kubeadm/

截止目前,kubeadm尚處於beta狀態,官方暫時不推薦在生產環境使用,但是預計今年會推出GA版本。這裡,我建議大家儘量使用kubeadm,相對於純手動部署效率更高,也不容易出錯。

建立叢集

在Master主節點(k8s-node1)上執行:
kubeadm init --pod-network-cidr=192.168.0.0/16 --kubernetes-version=v1.10.0 --apiserver-advertise-address=192.168.56.101

含義:
1.選項--pod-network-cidr=192.168.0.0/16表示叢集將使用Calico網路,這裡需要提前指定Calico的子網範圍
2.選項--kubernetes-version=v1.10.0指定K8S版本,這裡必須與之前匯入到Docker映象版本v1.10.0一致,否則會訪問谷歌去重新下載K8S最新版的Docker映象
3.選項--apiserver-advertise-address表示繫結的網絡卡IP,這裡一定要繫結前面提到的enp0s8網絡卡,否則會預設使用enp0s3網絡卡
4.若執行kubeadm init出錯或強制終止,則再需要執行該命令時,需要先執行kubeadm reset重置

執行結果:

[[email protected] ~]# kubeadm init --pod-network-cidr=192.168.0.0/16 --kubernetes-version=v1.10.0 --apiserver-advertise-address=192.168.56.101[init] Using Kubernetes version: v1.10.0[init] Using Authorization modes: [Node RBAC]
[preflight] Running pre-flight checks.
    [WARNING SystemVerification]: docker version is greater than the most recently validated version. Docker version: 18.03.1-ce. Max validated version: 17.03
    [WARNING FileExisting-crictl]: crictl not found in system path
Suggestion: go get github.com/kubernetes-incubator/cri-tools/cmd/crictl
[certificates] Generated ca certificate and key.
[certificates] Generated apiserver certificate and key.
[certificates] apiserver serving cert is signed for DNS names [k8s-node1 kubernetes kubernetes.default kubernetes.default.svc kubernetes.default.svc.cluster.local] and IPs [10.96.0.1 192.168.56.101]
[certificates] Generated apiserver-kubelet-client certificate and key.
[certificates] Generated etcd/ca certificate and key.
[certificates] Generated etcd/server certificate and key.
[certificates] etcd/server serving cert is signed for DNS names [localhost] and IPs [127.0.0.1]
[certificates] Generated etcd/peer certificate and key.
[certificates] etcd/peer serving cert is signed for DNS names [k8s-node1] and IPs [192.168.56.101]
[certificates] Generated etcd/healthcheck-client certificate and key.
[certificates] Generated apiserver-etcd-client certificate and key.
[certificates] Generated sa key and public key.
[certificates] Generated front-proxy-ca certificate and key.
[certificates] Generated front-proxy-client certificate and key.
[certificates] Valid certificates and keys now exist in "/etc/kubernetes/pki"[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/admin.conf"[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/kubelet.conf"[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/controller-manager.conf"[kubeconfig] Wrote KubeConfig file to disk: "/etc/kubernetes/scheduler.conf"[controlplane] Wrote Static Pod manifest for component kube-apiserver to "/etc/kubernetes/manifests/kube-apiserver.yaml"[controlplane] Wrote Static Pod manifest for component kube-controller-manager to "/etc/kubernetes/manifests/kube-controller-manager.yaml"[controlplane] Wrote Static Pod manifest for component kube-scheduler to "/etc/kubernetes/manifests/kube-scheduler.yaml"[etcd] Wrote Static Pod manifest for a local etcd instance to "/etc/kubernetes/manifests/etcd.yaml"[init] Waiting for the kubelet to boot up the control plane as Static Pods from directory "/etc/kubernetes/manifests".
[init] This might take a minute or longer if the control plane images have to be pulled.
[apiclient] All control plane components are healthy after 24.006116 seconds
[uploadconfig] Storing the configuration used in ConfigMap "kubeadm-config" in the "kube-system" Namespace
[markmaster] Will mark node k8s-node1 as master by adding a label and a taint
[markmaster] Master k8s-node1 tainted and labelled with key/value: node-role.kubernetes.io/master=""[bootstraptoken] Using token: kt62dw.q99dfynu1kuf4wgy
[bootstraptoken] Configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials
[bootstraptoken] Configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token
[bootstraptoken] Configured RBAC rules to allow certificate rotation for all node client certificates in the cluster
[bootstraptoken] Creating the "cluster-info" ConfigMap in the "kube-public" namespace
[addons] Applied essential addon: kube-dns
[addons] Applied essential addon: kube-proxy

Your Kubernetes master has initialized successfully!

To start using your cluster, you need to run the following as a regular user:

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

You should now deploy a pod network to the cluster.
Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at:
  https://kubernetes.io/docs/concepts/cluster-administration/addons/

You can now join any number of machines by running the following on each nodeas root:

  kubeadm join 192.168.56.101:6443 --token kt62dw.q99dfynu1kuf4wgy --discovery-token-ca-cert-hash sha256:5404bcccc1ade37e9d80831ce82590e6079c1a3ea52a941f3077b40ba19f2c68

可以看到,提示叢集成功初始化,並且我們需要執行以下命令:

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

另外, 提示我們還需要建立網路,並且讓其他節點執行kubeadm join...加入叢集。

建立網路

如果不建立網路,檢視pod狀態時,可以看到kube-dns元件是阻塞狀態,叢集時不可用的:

 

image.png

大家可以參考官方文件,根據需求選擇適合的網路,這裡,我們使用Calico(在前面初始化叢集的時候就已經確定了)。

根據官方文件,在主節點上,需要執行如下命令:
kubectl apply -f https://docs.projectcalico.org/v3.1/getting-started/kubernetes/installation/hosted/kubeadm/1.7/calico.yaml

但需要注意的是:

本文實驗時所使用的calico的docker映象版本為v3.1.0,如下圖所示

image.png


但截至本文撰寫時, calico.yaml檔案中版本已升級為v3.1.1。因此我們需要下載 calico.yaml,手動編輯檔案修改為v3.1.0並重新建立網路。否則,執行 kubectl apply命令時,會重新拉取v3.1.1的映象導致超時失敗。同時,kube-dns模組也會因為網路無法建立而Pending:

image.png

 

確保版本一致後,執行成功則提示:

 

image.png

image.png

五、叢集設定

將Master作為工作節點

K8S叢集預設不會將Pod排程到Master上,這樣Master的資源就浪費了。在Master(即k8s-node1)上,可以執行以下命令使其作為一個工作節點:
kubectl taint nodes --all node-role.kubernetes.io/master-

利用該方法,我們可以不使用minikube而建立一個單節點的K8S叢集

執行成功後提示:

 

image.png

將其他節點加入叢集

在其他兩個節點k8s-node2和k8s-node3上,執行主節點生成的kubeadm join命令即可加入叢集:
kubeadm join 192.168.56.101:6443 --token kt62dw.q99dfynu1kuf4wgy --discovery-token-ca-cert-hash sha256:5404bcccc1ade37e9d80831ce82590e6079c1a3ea52a941f3077b40ba19f2c68

加入成功後,提示:

 

image.png

驗證叢集是否正常

當所有節點加入集群后,稍等片刻,在主節點上執行kubectl get nodes可以看到:

image.png

 

如上,若提示notReady則表示節點尚未準備好,可能正在進行其他初始化操作,等待全部變為Ready即可。

大家可能會好奇,我們前面使用的是v1.10.0,為何這裡版本是v1.10.2。實際上,這裡顯示是每個節點上kubelet程式的版本,即先前使用yum安裝時的預設版本,是向下相容的。而v.1.10.0指的是K8S依賴的Docker映象版本,與kubeadm init命令中一定要保持一致。

另外,建議檢視所有pod狀態,執行kubectl get pods -n kube-system

image.png

 

如上,全部Running則表示叢集正常。至此,我們的K8S叢集就搭建成功了。走!去按摩一下頸椎,放鬆一下,真累啊!