在學習《kubernets 權威指南》的時候,遇到了kubeadm安裝k8s叢集的問題。看書過了一遍,感覺似乎并沒有啥難點。本來想就不再手動去安裝一次了,但糾結了半天,我該死的強迫症還是讓我又回頭手動搭建了一次。這一搭建才發現,原來坑還是挺多的,是以就把自己的搭建過程寫了下來,供學習交流使用。
1.環境初始化(每個節點都要安裝)
1.1 安裝并配置docker
1.1.1 docker安裝
參考docker安裝安裝docker
1.1.2 配置cgroup driver
為啥要配置cgroup driver?因為使用systemd作為init system的Linux的發行版,使用systemd作為docker的cgroup driver可以確定伺服器節點在資源緊張的情況更加穩定。
編輯/etc/docker/daemon.json檔案(如果沒有則建立),添加如下内容:
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
1.1.3 配置國内registery
在/etc/docker/daemon.json的json段中,添加如下内容:
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registery-mirrors":["https://http://hub-mirror.c.163.com"]
}
最終如下:
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registery-mirrors":["https://http://hub-mirror.c.163.com"]
}
1.1.4 啟動檢查服務
啟動docker。
檢查cgroup driver是否生效:
docker info |grep Cgroup
Cgroup Driver: systemd
1.2 初始化主機名和hosts
1.2.1 初始化主機名
有時候,某些伺服器的主機名會帶一些奇怪的字元串,為了環境更标準,我們非常建議将主機名初始化一下,比如:
hostnamectl set-hostname --static kubadmcli
1.2.2 配置hosts
根據初始化主機名那一步的主機名配置hosts:
172.24.15.212 kubadmcli
注:主機名或者hosts沒有的話,可能會出現如下提示:
[WARNING Hostname]: hostname "kubadmcli.novalocal" could not be reached
[WARNING Hostname]: hostname "kubadmcli.novalocal": lookup kubadmcli.novalocal on 114.114.114.114:53: no such host
2. 安裝配置master節點
2.1 安裝kubeadm
2.1.1 配置yum源
在/etc/yum.repos.d/目錄下,建立kubernetes.repo檔案,添加如下内容:
[kubernetes]
name=kubernetes
baseurl=https://mirrors.tuna.tsinghua.edu.cn/kubernetes/yum/repos/kubernetes-el7-$basearch
enabled=1
gpgcheck=0
重建緩存:
yum clean all
yum makecache
2.1.2 安裝kubeadm
yum -y install kubelet kubeadm kubectl
注:這裡沒有指定版本,安裝後預設為最新版本。在配置kubeadm config的時候,我們會指定kubernetesVersion的版本。如果指定的版本和這裡安裝的版本不一緻,會出現如下報錯:
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR KubeletVersion]: the kubelet version is higher than the control plane version. This is not a supported version skew and may lead to a malfunctional cluster. Kubelet version: "1.21.0" Control plane version: "1.20.5"
[preflight] If you know what you are doing, you can make a check non-fatal with `--ignore-preflight-errors=...`
To see the stack trace of this error execute with --v=5 or higher
是以,我們建議,安裝kubelet、kubeadm和kubectl的時候,可以通過如下方式指定版本:
yum -y install kubelet-1.20.5 kubeadm-1.20.5 kubectl-1.20.5
安裝完成以後,由于叢集還沒有建立,是以目前還無法啟動kubelet服務。這個和《kubernets權威指南》上是不一樣的,指南上是說安裝完以後,就可以啟動kubelet服務了,但實際不行。我們可以把kubelet服務暫時加入開機啟動:
systemctl enable kubelet
2.2 配置kubeadm config
kubeadm config可以如下2種方式:
- 配置檔案方式
- 指令行傳參
2.2.1 配置檔案方式
我們可以通過如下方式,擷取預設配置:
kubeadm config print init-defaults > init.default.yaml
會在目前目錄下生成init.default.yaml檔案,内容如下:
apiVersion: kubeadm.k8s.io/v1beta2
bootstrapTokens:
- groups:
- system:bootstrappers:kubeadm:default-node-token
token: abcdef.0123456789abcdef
ttl: 24h0m0s
usages:
- signing
- authentication
kind: InitConfiguration
localAPIEndpoint:
advertiseAddress: 1.2.3.4
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: master
taints:
- effect: NoSchedule
key: node-role.kubernetes.io/master
---
apiServer:
timeoutForControlPlane: 4m0s
apiVersion: kubeadm.k8s.io/v1beta2
certificatesDir: /etc/kubernetes/pki
clusterName: kubernetes
controllerManager: {}
dns:
type: CoreDNS
etcd:
local:
dataDir: /var/lib/etcd
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.20.0
networking:
dnsDomain: cluster.local
serviceSubnet: 10.96.0.0/12
scheduler: {}
這裡,我們主要關注以下幾個内容:
apiVersion: kubeadm.k8s.io/v1beta2
imageRepository: k8s.gcr.io
kind: ClusterConfiguration
kubernetesVersion: v1.20.0
networking:
serviceSubnet: 10.96.0.0/12
從預設配置中,我們可以看到
- imageRepository使用的是k8s.gcr.io,我們建議改成國内的鏡像站
- kubernetesVersion使用的是v1.20.0,我們可以改成自己想要的版本
- networking中隻有serviceSubnet,可能我們還關心pod的網絡,pod網絡可以使用podSubnet指定
2.2.1.1 我們使用如下配置:
apiVersion: kubeadm.k8s.io/v1beta2
imageRepository: registry.aliyuncs.com/google_containers
kind: ClusterConfiguration
kubernetesVersion: v1.20.5
networking:
podSubnet: 192.168.16.0/20
serviceSubnet: 192.168.0.0/20
2.2.2 指令參數方法
對應到config方式,猶如下幾個參數預支對應:
- –kubernetes-version:指定Kubernetes版本
- –image-repository:由于kubeadm預設是從官網k8s.grc.io下載下傳所需鏡像,國内無法通路,是以這裡通過–image-repository指定為163鏡像站
- –pod-network-cidr:指定pod網絡段
- –service-cidr:指定service網絡段
- –ignore-preflight-errors=Swap 将報錯資訊設定為Swap。當然,如果你環境配置得當,不需要它
指令行參數的方式,需要在下一步kubeadm init的時候一起執行
2.3 拉取鏡像
kubeadm config images pull --config=init.yaml
注:這一步在指南上是有的,不過我們也可以不執行,這樣在kubeadm init的時候,會自動下載下傳鏡像。
結果如下
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.20.5
[config/images] Pulled registry.aliyuncs.com/google_containers/pause:3.2
[config/images] Pulled registry.aliyuncs.com/google_containers/etcd:3.4.13-0
[config/images] Pulled registry.aliyuncs.com/google_containers/coredns:1.7.0
通過[docker images]檢視本地鏡像:
[[email protected] ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.aliyuncs.com/google_containers/kube-proxy v1.20.5 5384b1650507 2 weeks ago 118MB
registry.aliyuncs.com/google_containers/kube-apiserver v1.20.5 d7e24aeb3b10 2 weeks ago 122MB
registry.aliyuncs.com/google_containers/kube-controller-manager v1.20.5 6f0c3da8c99e 2 weeks ago 116MB
registry.aliyuncs.com/google_containers/kube-scheduler v1.20.5 8d13f1db8bfb 2 weeks ago 47.3MB
registry.aliyuncs.com/google_containers/etcd 3.4.13-0 0369cf4303ff 7 months ago 253MB
registry.aliyuncs.com/google_containers/coredns 1.7.0 bfe3a36ebd25 9 months ago 45.2MB
registry.aliyuncs.com/google_containers/pause 3.2 80d28bedfe5d 13 months ago 683kB
2.4 初始化master
2.4.1 使用配置檔案方式
kubeadm init --config=init.yaml
2.4.2 使用指令行傳參方式
kubeadm init --kubernetes-version=v1.20.5 \
--image-repository=registry.aliyuncs.com/google_containers \
--pod-network-cidr=192.168.16.0/20 \
--service-cidr=192.168.0.0/20 \
#--ignore-preflight-errors=Swap
結果如下:
init] Using Kubernetes version: v1.20.5
[preflight] Running pre-flight checks
[preflight] Pulling images required for setting up a Kubernetes cluster[certs]
......
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 172.24.14.91:6443 --token yvhauq.sxcuhh300d5vpvhy \
--discovery-token-ca-cert-hash sha256:439f9df853943ead685dc63d8af0d04c32e7b9b8dc4e148e0fb41dab33997c11
從上述提示中我們可以獲得一下資訊:
- initialize successfully說明已經初始化完
- 叢集能被正常使用者正常使用,還需要執行提示中所說的内容。
- kubectl apply -f 可以讓我們初始化網插件。支援網絡插件可以在給出的url裡查到
- 最後一段包含了後面我們需要使用kubeadm join指令将來node加入到叢集所需要token等資訊
注:執行完kubeadm init以後,我們會發現,kubelet服務已經正常啟動了。如下:
[[email protected] ~]# systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
Drop-In: /usr/lib/systemd/system/kubelet.service.d
└─10-kubeadm.conf
Active: active (running) since Wed 2021-05-12 10:38:33 CST; 7s ago
Docs: https://kubernetes.io/docs/
Main PID: 2949 (kubelet)
Tasks: 18
Memory: 38.0M
CGroup: /system.slice/kubelet.service
└─2949 /usr/bin/kubelet --bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --k...
May 12 10:38:34 kubeadmcli kubelet[2949]: I0512 10:38:34.433442 2949 reconciler.go:224] opera...46")
......
May 12 10:38:39 kubeadmcli kubelet[2949]: E0512 10:38:39.213486 2949 kubelet.go:2188] Contain...ized
Hint: Some lines were ellipsized, use -l to show in full.
2.4.3 配置使用者環境
以root使用者為例,我們在/root/目錄下執行如下指令:
#root用的$HOME變量為/root
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
這個時候,我們使用如下指令,檢視一下叢集節點:
kubectl get nodes
結果如下:
NAME STATUS ROLES AGE VERSION
kubeadmcli NotReady control-plane,master 3m30s v1.20.5
從輸出中,我們可以發現,STATUS還處于[NotReady]的狀态,這是因為我們還沒有初始化網絡插件
2.5 初始網絡插件
以flannel為例,從提示文本中,我們可以看到,支援的網絡插件都位于:
https://kubernetes.io/docs/concepts/cluster-administration/addons/
打開以後,我們選擇flannel,會跳轉到flanne項目的githu位址。我們選擇進入到flannel項目的主目錄,裡面有flannel插件的使用方式。從說明中,我們可以看到**大于1.17**版本的k8s,使用如下yml檔案:
https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
注:如果網絡不好,可以使用wget或者curl先把yaml檔案下載下傳下來,放到本地執行。
注:該yaml配置檔案中, 有flannel的image倉庫位址。預設為**quay.io/coreos/**,如果自己的網絡不通,可以将改位址替換掉:
sed -i ‘s/quay.io\/coreos/registry.aliyuncs.com\/google_containers/g’ flannel.yaml。不過實際情況好像阿裡并沒有flannel的鏡像,可能是我使用的姿勢不對,後面慢慢研究吧。好在預設位址是通的。
我們将yml檔案儲存到本地,名為flannel.yaml。執行如下指令初始化flannel:
kubectl apply -f flannel.yaml
輸出如下:
podsecuritypolicy.policy/psp.flannel.unprivileged created
clusterrole.rbac.authorization.k8s.io/flannel created
clusterrolebinding.rbac.authorization.k8s.io/flannel created
serviceaccount/flannel created
configmap/kube-flannel-cfg created
daemonset.apps/kube-flannel-ds created
完成以後,本地鏡像會多出來flannel的鏡像:
[[email protected] ~]# docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
...
quay.io/coreos/flannel v0.13.1-rc2 dee1cac4dd20 2 months ago 64.3MB
...
這時候,我們再kubectl get nodes會發現,STATUS已經處于[Ready]狀态了
NAME STATUS ROLES AGE VERSION
kubeadmcli Ready control-plane,master 111m v1.20.5
3 初始化node
3.1 安裝kubelet和kubeadm
和主節點不一樣的是,node不需要安裝kubectl
yum -y install kubelet-1.20.5 kubeadm-1.20.5
3.2 初始化node
和初始化master一樣,我們可以通過如下兩種方式,來初始化node節點:
- 使用配置檔案方式
- 指令行傳參方式
3.2.1 指令行方式
初始化master節點的時候,從輸出資訊中,已經給出了初始化node節點的方式:
kubeadm join 172.24.15.212:6443 --token yvhauq.sxcuhh300d5vpvhy \
--discovery-token-ca-cert-hash sha256:439f9df853943ead685dc63d8af0d04c32e7b9b8dc4e148e0fb41dab33997c11
3.1.2 配置檔案方式
同樣,我們可以通過kubeadm config print指令輸出init node節點的預設配置:
kubeadm config print join-defaults
輸出如下:
apiVersion: kubeadm.k8s.io/v1beta2
caCertPath: /etc/kubernetes/pki/ca.crt
discovery:
bootstrapToken:
apiServerEndpoint: kube-apiserver:6443
token: abcdef.0123456789abcdef
unsafeSkipCAVerification: true
timeout: 5m0s
tlsBootstrapToken: abcdef.0123456789abcdef
kind: JoinConfiguration
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: kubeadmclinode02
taints: null
我們主要關注如下幾項,并将apiServerEndpoint、token、tlsBootstrapToken改成master節點資訊。
apiVersion: kubeadm.k8s.io/v1beta2
discovery:
bootstrapToken:
apiServerEndpoint: 172.24.14.91:6443
token: yvhauq.sxcuhh300d5vpvhy
unsafeSkipCAVerification: true
tlsBootstrapToken: yvhauq.sxcuhh300d5vpvhy
kind: JoinConfiguration
将上述内容儲存為init_node.yaml.然後使用如下指令初始化節點:
kubeadm join --config=init_node.yaml
上面兩種方法都出現如下輸出的時候,說明正确了:
This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.
Run 'kubectl get nodes' on the control-plane to see this node join the cluster.
此時node上的kubelet也将正常運作。可能這時候你在master上執行[kubelet get nodes]的時候,該node還處于NotReady的狀态,别着急,一會就回重新整理過來。
4 安裝dashboard
以後有時間再說
5 删除節點
如果我們的某個節點出故障了,我們可以将節點剔出叢集,剔出叢集使用如下指令:
kubectl drain [your-node-name] --delete-local-data --force --ignore-daemonsets
kubectl delete node [your-node-name]
然後在節點上執行:
kubeadm reset
問題
問題1:kubeadm報錯:cannot automatically set CgroupDriver when starting the Kubelet: cannot execute ‘docker info -f {{.CgroupDriver}}’: executable file not found in $PATH
kubeadm的架構是:kubeapi、prox、ctl、manager等元件都是使用容器。是以主節點也是需要正确安裝容器服務的。并且需要配置容器伺服器的cgroup driver。
根據文檔CRI installation中的内容,對于使用systemd作為init system的Linux的發行版,使用systemd作為docker的cgroup driver可以確定伺服器節點在資源緊張的情況更加穩定,是以這裡修改各個節點上docker的cgroup driver為systemd。
解決方法
建立/etc/docker/daemon.json檔案,添加如下内容:
{
"exec-opts": ["native.cgroupdriver=systemd"]
}
注:docker預設使用的cgroup driver為cgroupfs
配置以後,需要重新開機docker服務。
問題2:The connection to the server localhost:8080 was refused - did you specify the right host or port?
需要配置k8s的使用者環境:
#root用的$HOME變量為/root
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config