搭建K8S叢集(kubeadm篇)
搭建K8S叢集(kubeadm篇)
一、K8S概述
K8S是當下最火熱的容器執行時編排工具,不僅僅提供了使用者應用的容器映象執行解決方案,還提供了路由閘道器、水平擴充套件、多副本容災等能力。在Kubernetes專案中,master節點由負責api服務的kube-apiserver、負責排程的kube-scheduler、負責編排的kebu-controller-manager三者組成。node節點上,最核心的部分是kubelet元件。kubelet主要負責同容器執行時(比如Docker專案)互動,而互動依賴的是CRI(Container Runtime Interface)的遠端呼叫介面。這個介面定義了容器執行時的各項核心操作。具體的容器執行時,則通過OCI這個容器標準,把CRI請求翻譯成對Linux系統的底層呼叫。
話不多說,我們用最簡單的方式,即kubeadm來搭建一個K8S叢集吧。
二、如何使用kubeadm搭建叢集
2.1 機器準備
我們需要準備3臺機器,配置是4核8G,提前做好部署規劃和網路規劃。考慮到雲上機器的網路條件較好,我這裡用的是騰訊雲的機器,讀者們也可以使用3臺2核4G的機器來完成搭建。
每臺機器都需要關閉防火牆,配置好DNS域名解析,並且時間上已配置同步。
- master節點
- node1節點
- node2節點
2.2 準備程式包
由於我們本次使用的是kubeadm工具搭建叢集,我們先要下載相關的程式包。但是!由於大中華網路等原因,部分包下載會有問題。那怎麼辦呢,我們找一臺海外的機器來下載這部分程式包即可。
安裝kubeadm所需的程式包有以下幾個
- kubelet
- kubeadm
- kubectl
- kubernetes-cni
- cri-tools
# 安裝yum-utils工具,這樣我們就可以將包下載到本地 yum install -y yum-utils # 配置yum源,讓我們能夠下載相關程式包 cat >> /etc/yum.repos.d/kubernetes.repo << EOF [kubernetes] name=Kubernetes baseurl=http://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64 enabled=1 gpgcheck=1 repo_gpgcheck=1 gpgkey=http://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg EOF # 將相關程式包下載 kubelet kubeadm kubectl kubernetes-cni cri-tools yumdownloader kubelet kubeadm kubectl kubernetes-cni cri-tools # 打包這幾個rpm程式包,上傳到我們的叢集機器上去 tar zcf k8s-deploy.tgz *.rpm
備註: 作者知道有些同學可能還沒有海外的伺服器,這幾個服務的包我已經打包好放在網盤上,大家可以直接下載使用。https://share.weiyun.com/g8sbwcWA
2.3 安裝kubeadm
我們已經有了相關軟體包了,安裝就很簡單了
# 解壓軟體包
tar xf k8s-deploy.tgz
# 執行安裝
yum localinstall -y *.rpm
2.4 下載映象
最早期的時候,K8S叢集是直接部署在裸金屬伺服器上面的,這個部署過程有一系列繁瑣的操作(如手動生成配置證書等操作),非常的不友好。後面呢大家考慮,既然K8S能力這麼強大,那為何不把kube-apiserver、kube-controller-manager、kube-scheduler這些都做成容器映象,然後通過K8S直接管理起來呢。事實上,kubeadm就是這樣做的。但是這裡有一點需要注意的是,並不是每個元件都事宜做成容器映象的,比方說像kubelet。因為kubelet需要與宿主機打交道,比方說配置宿主機網路、儲存系統等。假如kubelet是一個容器,那麼其執行在自己的Namespace中,是很難對宿主機進行操作的。因此,kubelet是需要手動在宿主機上安裝的。
我們開始下載K8S元件的容器映象,糟糕這裡似乎有被大中華的網路攔截了。這裡我們就需要依賴阿里雲映象倉庫,這裡有我們所需的全部映象,我們可以從阿里雲映象倉庫下載映象,然後打tag將映象改成kubeadm所需的即可。
# 檢視kubeadm部署叢集所需的映象
kubeadm config images list
#k8s.gcr.io/kube-apiserver:v1.23.1
#k8s.gcr.io/kube-controller-manager:v1.23.1
#k8s.gcr.io/kube-scheduler:v1.23.1
#k8s.gcr.io/kube-proxy:v1.23.1
#k8s.gcr.io/pause:3.6
#k8s.gcr.io/etcd:3.5.1-0
#k8s.gcr.io/coredns/coredns:v1.8.6
# 下載所需映象並修改tag,這裡的coredns我們稍後單獨處理
for item in `kubeadm config images list | egrep -v "coredns|grep"` ; do image=` echo $item | sed -e "[email protected]@registry.aliyuncs.com/google_containers@g"`; docker pull $image ; docker tag $image `echo $image | sed -e "[email protected]/[email protected]@g"` ; docker rmi $image ; done ;
# 下載coredns映象
for item in `kubeadm config images list | egrep "coredns" | grep -v grep ` ; do image=` echo $item | sed -e "[email protected]/[email protected]/google_containers@g"` ; docker pull $image ; docker tag $image `echo $image | sed -e "[email protected]/[email protected]/coredns@g"` ; docker rmi $image ; done ;
# 檢視我們下載的所有映象,此時看看是不是和我們通過kubeadm config images list查詢出來的一樣啦
docker images
2.5 部署master節點
到了這裡,我們就可以使用kubeadm來部署master節點。部署命令非常簡單,只需要執行kubeadm init
即可。部署完成之後,出現如下提示就說明kubeadm執行完成了。
Your Kubernetes control-plane 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
Alternatively, if you are the root user, you can run:
export KUBECONFIG=/etc/kubernetes/admin.conf
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/
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join IP:6443 --token ltfaw0.yci1z7zqdrll2ixp \
--discovery-token-ca-cert-hash sha256:145415d491d67daeb13910ffb49e5a8608863225a13cfdc794b85cc5aca46972
在這裡可能有些同學會碰到kubelet相關的異常,通過執行journalctl -xeu kubelet
可以看到,最常見的就是kubelet提示“kubelet cgroup driver: "systemd" is different from docker cgroup driver: "cgroupfs"”,這是什麼意思呢?
意思就是說docker使用的cgroup驅動和kubelet使用的驅動不一致,我們知道cgroup全稱為Linux Control Group,是用來控制一個程序組使用系統資源的上限。kubelet是通過CRI這個遠端呼叫介面來操作容器執行時(即Docker),驅動不一致會導致相關限制能力無法執行。所以,我們需要修改Docker(建議,當然也可以修改kubelet)的cgroup驅動。具體如下:
# 修改docker的配置檔案
cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
# 核心重新載入程序配置
systemctl daemon-reload
# 重啟docker程序
systemctl restart docker
# 檢查docker的cgroup驅動
docker info
2.6 部署網路外掛
此時我們部署好了K8S叢集的master節點,根據輸出提示export KUBECONFIG=/etc/kubernetes/admin.conf
在機器上執行,然後我們通過kubectl get po -n kube-system
檢查各個Pod的執行情況。突然發現咋不對勁呢,怎麼有些Pod始終處於Pending狀態呢?
[root@VM-62-206-centos ~]# kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-64897985d-9nrqf 0/1 Pending 0 31s
coredns-64897985d-ms4jr 0/1 Pending 0 31s
etcd-vm-62-206-centos 1/1 Running 0 35s
kube-apiserver-vm-62-206-centos 1/1 Running 0 35s
kube-controller-manager-vm-62-206-centos 1/1 Running 0 37s
kube-proxy-zkxln 1/1 Running 0 31s
kube-scheduler-vm-62-206-centos 1/1 Running 0 35s
其實這是正常的,DNS和什麼相關,和網路相關對吧。我們現在都還沒有網路外掛,肯定是有問題啊。話不多說,我們立馬把網路外掛部署上去,在這裡我們使用的網路外掛是weave
。
# 部署網路外掛,非常簡單一條命令就可以搞定
# 執行完之後需要等一段時間,因為在下載映象
kubectl apply -n kube-system -f "https://cloud.weave.works/k8s/net?k8s-version=$(kubectl version | base64 | tr -d '\n')"
這裡可能有些同學在部署過程中會碰到,網路外掛weave在啟動的過程在提示“CrashLoopBackOff”,我們開啟日誌檢查
kubectl logs weave-net-k966t -c weave -n kube-system
# Network 10.32.0.0/12 overlaps with existing route 10.0.0.0/8 on host
我們從這裡看到了啥,是不是說weave需要配置10.32.0.0/12這個網段的路由表,但是和現有機器上面的路由表衝突了。怎麼辦呢,其實比較簡單的解決辦法是把現有衝突的網段調整一下。調整完之後,我們再列印下Pod執行情況,可以看到Pod全部都正常運行了。
kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-64897985d-9nrqf 1/1 Running 0 92m
coredns-64897985d-ms4jr 1/1 Running 0 92m
etcd-vm-62-206-centos 1/1 Running 0 92m
kube-apiserver-vm-62-206-centos 1/1 Running 0 92m
kube-controller-manager-vm-62-206-centos 1/1 Running 0 92m
kube-proxy-zkxln 1/1 Running 0 92m
kube-scheduler-vm-62-206-centos 1/1 Running 0 92m
weave-net-k966t 2/2 Running 11 (21m ago) 59m
2.7 部署node節點
部署node節點比較簡單,我們在node節點上面安裝好docker-ce、kubeadm、上傳相關映象後,只需要將部署master節點系統提示的命令複製過去即可。
# 執行部署node節點命令
kubeadm join IP:6443 --token ltfaw0.yci1z7zqdrll2ixp --discovery-token-ca-cert-hash sha256:145415d491d67daeb13910ffb49e5a8608863225a13cfdc794b85cc5aca46972
此時我們等一段時間,等待weave外掛在node節點上面安裝完成,就可以看到整個叢集Pod均執行情況。
kubectl get po -n kube-system
NAME READY STATUS RESTARTS AGE
coredns-64897985d-9nrqf 1/1 Running 0 130m
coredns-64897985d-ms4jr 1/1 Running 0 130m
etcd-vm-62-206-centos 1/1 Running 0 130m
kube-apiserver-vm-62-206-centos 1/1 Running 0 130m
kube-controller-manager-vm-62-206-centos 1/1 Running 0 130m
kube-proxy-ftr7m 1/1 Running 0 30m
kube-proxy-mcxt5 1/1 Running 0 29m
kube-proxy-zkxln 1/1 Running 0 130m
kube-scheduler-vm-62-206-centos 1/1 Running 0 130m
weave-net-9rpsv 2/2 Running 0 30m
weave-net-dd9nr 2/2 Running 0 29m
weave-net-k966t 2/2 Running 11 (58m ago) 97m
2.8 一些收尾工作
到目前為止,我們已經部署好一個非生產環境的K8S叢集,做做實驗還是綽綽有餘的。不過,大家有沒有發現,kubectl
命令只有在master節點上管用,在其他的node節點似乎不起作用,始終提示“The connection to the server localhost:8080 was refused - did you specify the right host or port?”。這個如何修復呢,其實很簡單,我們只需要把master節點的/etc/kubernetes/admin.conf
拷貝到node節點的對應位置,在執行export命令即可。
scp /etc/kubernetes/admin.conf root@node_ip:/etc/kubernetes/admin.conf
export KUBECONFIG=/etc/kubernetes/admin.conf
三、控制器模式下執行Pod例項
現在我們已經有了完整可用的K8S叢集,我們就開始部署一個簡答的Nginx服務吧。
3.1 編寫YAML檔案
我已經編寫好一個最簡單的案例檔案
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
3.2 執行應用
我們執行kubectl apply -f nginx.yaml
來將我們編寫好的YAML提交到K8S,使用apply
操作的好處在於,K8S可以自動識別到檔案的變化,並根據物件的變化自動執行響應的操作(增加或者減少副本數量、修改應用映象等)。
過了幾分鐘,我們可以看到應用順利執行起來了。
kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-deployment-5fcc5d8c6d-6fr2b 1/1 Running 0 12m
nginx-deployment-5fcc5d8c6d-79r2w 1/1 Running 0 11m