1. 程式人生 > 其它 >搭建K8S叢集(kubeadm篇)

搭建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