搭建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 "s@k8s.gcr.io@registry.aliyuncs.com/google_containers@g"`; docker pull $image ; docker tag $image `echo $image | sed -e "s@registry.aliyuncs.com/google_containers@k8s.gcr.io@g"` ; docker rmi $image ; done ;
# 下載coredns鏡像
for item in `kubeadm config images list | egrep "coredns" | grep -v grep ` ; do image=` echo $item | sed -e "s@k8s.gcr.io/coredns@registry.aliyuncs.com/google_containers@g"` ; docker pull $image ; docker tag $image `echo $image | sed -e "s@registry.aliyuncs.com/google_containers@k8s.gcr.io/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
