搭建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-node2
、k8s-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叢集就搭建成功了。走!去按摩一下頸椎,放鬆一下,真累啊!