1. 前言
kubernetes版本更新疊代非常快,上一篇寫kubernetes搭建時,版本還是v1.15.0,現在已經更新到v1.18。看kubernetes在github的官方倉庫,8月14日小版本已經到了v1.18.8。本篇文章基于kubeadm搭建kubernetes v1.18.8版。
本篇文章與上篇文章幾點不同之處:
- 作業系統采用CentOS。
- master采用單節點,如果要搭建多master高可用叢集可以參考上篇文章。
- 解決無法通路kubernetes官方容器鏡像倉庫問題,上篇文章直接從kubernetes官方拉取鏡像。
- docker加速,解決從dockerhub拉鏡像慢問題。
- kube-proxy開啟ivps,使用ipvs替代iptables轉發流量。
-
給出了一些常見的錯誤及排錯思路。
話不多說,那就直奔主題,走起~~~
2. 環境準備
機器名稱 | 機器配置 | 機器系統 | IP位址 | 角色 |
---|---|---|---|---|
master1 | 2C4G | CentOS7.6 | 10.13.1.11 | 主節點 |
node1 | 10.13.1.15 | 工作節點1 | ||
node2 | 10.13.1.16 | 工作節點2 |
說明:
硬體配置要求:2C2G +;
作業系統要求:CentOS7 +
防火牆說明:如果使用的是雲廠商的虛拟機,主節點安全組需放行tcp端口6443、2379-2380、10250-12025,工作節點安全組需放行tcp端口:10250、30000-32767
3. 實操過程
3.1 關閉防火牆和selinux
[root@master1 ~]# systemctl stop firewalld
[root@master1 ~]# setenforce 0
[root@master1 ~]# sed -i 's/^SELINUX=.*/SELINUX=disabled/' /etc/selinux/config
3.2 關閉交換分區
[root@master1 ~]# swapoff -a
永久關閉,修改/etc/fstab,注釋掉swap一行
3.3 修改hosts檔案
[root@master1 ~]# cat >> /etc/hosts << EOF
10.13.1.11 master1
10.13.1.15 node1
10.13.1.16 node2
3.4 時間同步
[root@master1 ~]# yum install chrony -y
[root@master1 ~]# systemctl start chronyd
[root@master1 ~]# systemctl enable chronyd
[root@master1 ~]# chronyc sources
3.5 修改核心參數
讓iptables能檢視橋接流量
[root@master1 ~]# cat > /etc/sysctl.d/k8s.conf << EOF
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
[root@master1 ~]# sysctl --system
3.6 加載ipvs子產品
[root@master1 ~]# modprobe -- ip_vs
[root@master1 ~]# modprobe -- ip_vs_rr
[root@master1 ~]# modprobe -- ip_vs_wrr
[root@master1 ~]# modprobe -- ip_vs_sh
[root@master1 ~]# modprobe -- nf_conntrack_ipv4
[root@master1 ~]# lsmod | grep ip_vs
[root@master1 ~]# lsmod | grep nf_conntrack_ipv4
[root@master1 ~]# yum install -y ipvsadm
3.7 安裝并配置docker
3.7.1 修改docker的yum源為阿裡源
[root@master1 ~]# wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O /etc/yum.repos.d/docker-ce.repo
或者
[root@master1 ~]# yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
3.7.2 安裝docker
[root@master1 ~]# yum install -y docker-ce
[root@master1 ~]# docker --version
Docker version 19.03.12, build 48a66213fe
[root@master1 ~]# systemctl enable docker
[root@master1 ~]# systemctl start docker
3.7.3 配置docker加速并修改驅動
網上有很多大佬無私地提供了一些dockerhub加速位址,可以選擇幾個使用。
[root@master1 ~]# cat /etc/docker/daemon.json
{
"exec-opts": ["native.cgroupdriver=systemd"],
"registry-mirrors": [
"https://1nj0zren.mirror.aliyuncs.com",
"https://kfwkfulq.mirror.aliyuncs.com",
"https://2lqq34jg.mirror.aliyuncs.com",
"https://pee6w651.mirror.aliyuncs.com",
"http://hub-mirror.c.163.com",
"https://docker.mirrors.ustc.edu.cn",
"http://f1361db2.m.daocloud.io",
"https://registry.docker-cn.com"
]
}
[root@master1 ~]# systemctl restart docker
[root@master1 ~]# docker info | grep "Cgroup Driver"
Cgroup Driver: systemd
kubernetes官方建議docker驅動采用systemd,當然可以不修改,隻是kubeadm init時會有warning([WARNING IsDockerSystemdCheck]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/)
可以忽略,生産環境建議修改,因為更穩定。
3.8 安裝kubernents元件
3.8.1 配置kubernentes的yum源為阿裡源
因為國内無法通路kubernents的官方yum源,是以需要修改
[root@master1 ~]# cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
3.8.2 安裝元件
[root@master1 ~]# yum -y install kubelet kubeadm kubectl
[root@master1 ~]# kubelet --version
Kubernetes v1.18.8
[root@master1 ~]# systemctl start kubelet
此時kubelet處于不斷重新開機狀态,因為叢集還沒有初始化,kubelet等待kubeadm初始化完成後運作狀态正常。
3.9 初始化叢集
3.9.1 檢視初始化需要的鏡像
[root@master1 ~]# kubeadm config images list
W0822 15:58:54.182176 25602 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
k8s.gcr.io/kube-apiserver:v1.18.8
k8s.gcr.io/kube-controller-manager:v1.18.8
k8s.gcr.io/kube-scheduler:v1.18.8
k8s.gcr.io/kube-proxy:v1.18.8
k8s.gcr.io/pause:3.2
k8s.gcr.io/etcd:3.4.3-0
k8s.gcr.io/coredns:1.6.7
3.9.2 kubeadm init介紹
初始化叢集需使用kubeadm init指令,可以指定具體參數初始化,也可以指定配置檔案初始化。
可選參數:
--apiserver-advertise-address apiserver的監聽位址,有多塊網卡時需要指定
--apiserver-bind-port apiserver的監聽端口,預設是6443
--cert-dir 通訊的ssl證書檔案,預設/etc/kubernetes/pki
--control-plane-endpoint 控制台平面的共享終端,可以是負載均衡的ip位址或者dns域名,高可用叢集時需要添加
--image-repository 拉取鏡像的鏡像倉庫,預設是k8s.gcr.io
--kubernetes-version 指定kubernetes版本
--pod-network-cidr pod資源的網段,需與pod網絡插件的值設定一緻
--service-cidr service資源的網段
--service-dns-domain service全域名的字尾,預設是cluster.local
3.9.3 kubeadm指定具體參數初始化
因為以上鏡像都需要從kubernetes官方鏡像倉庫拉取,國内無法通路,是以需要設定國内的阿裡鏡像倉庫。
但是目前至發稿為止,阿裡的kube-apiserver、kube-controller、proxy鏡像隻更新到v1.18.6是以無法拉取到v1.18.8版鏡像。
如果你需要安裝的kubernetes版本是v1.18.6及以下那麼請繼續往下走,如果是v1.18.7及以上請跳過這一步進入下一步。
3.9.3.1 初始化
[root@master1 ~]# kubeadm init --kubernetes-version=v1.18.6 --apiserver-advertise-address 0.0.0.0 --image-repository registry.aliyuncs.com/google_containers --pod-network-cidr 192.168.0.0/16 --service-cidr 10.10.0.0/16
--kubernetes-version 請指定為你需要安裝的v1.18.6及以下的版本。
初始化成功後會出現如下資訊
3.9.3.2 開啟ipvs
修改kube-proxy的configmap
[root@master1 ~]# kubectl edit cm kube-proxy -n=kube-system
修改mode: ipvs
3.9.4 kubeadm指定配置檔案初始化
3.9.4.1 下載下傳kubernetes所需的全部鏡像
dockerhub上面已經有大佬已經上傳了最新的1.18.8鏡像,這裡我們直接下載下傳下來即可。
編寫下載下傳腳本
[root@master1 ~]# vim images.txt
kube-apiserver:v1.18.8 # node節點不需要
kube-controller-manager:v1.18.8 # node節點不需要
kube-scheduler:v1.18.8 # node節點不需要
kube-proxy:v1.18.8
pause:3.2
etcd:3.4.3-0 # node節點不需要
coredns:1.6.7 # node節點不需要
[root@master1 ~]# vim images.sh
for image in `cat images.txt`
do
docker pull gotok8s/$image
docker tag gotok8s/$image k8s.gcr.io/$image
docker rmi gotok8s/$image
done
[root@master1 ~]# sh images.sh
3.9.4.2 配置初始化檔案
[root@master1 ~]# kubeadm config print init-defaults > kubeadm.yaml
[root@master1 ~]# vim kubeadm.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: 0.0.0.0 # 修改為本機ip位址,多塊網卡可以指定具體ip
bindPort: 6443
nodeRegistration:
criSocket: /var/run/dockershim.sock
name: master1
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.18.8 # 修改為最新版本
networking:
dnsDomain: cluster.local
serviceSubnet: 10.10.0.0/16 # service網段
podSubnet: 192.168.0.0/16 # pod網段,需與網絡插件網段一緻
scheduler: {}
---
apiVersion: kubeproxy.config.k8s.io/v1alpha1
kind: KubeProxyConfiguration
mode: ipvs # 開啟ipvs
[root@master1 ~]# kubeadm init --config=kubeadm.yaml
可以看到久違的成功
3.9.4.3 配置kubectl與kube-apiserver互動
[root@master1 ~]# mkdir -p $HOME/.kube
[root@master1 ~]# sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
[root@master1 ~]# sudo chown $(id -u):$(id -g) $HOME/.kube/config
至此可以使用kubectl檢視叢集節點狀态了
[root@master1 ~]# kubectl get nodes
可以看到版本是v1.18.8最新版,但是master狀态是NotReady,因為此時還沒有安裝網絡元件。
3.9.5 安裝網絡元件
[root@master1 ~]# wget https://docs.projectcalico.org/v3.14/manifests/calico.yaml
[root@master1 ~]# kubectl apply -f calico.yaml
此時再來看節點狀态,已經正常
查元件狀态
[root@master1 ~]# kubectl get cs
3.10 worker節點加入叢集
[root@node1 ~]# kubeadm join 10.13.1.11:6443 --token abcdef.0123456789abcdef --discovery-token-ca-cert-hash sha256:c214cf4c42766dd3d4ab2842c11efbefd54aa445993708ccdbdb8f111658445e
同樣的第二個worker節點加入叢集
此次檢視叢集狀态
[root@master1 ~]# kubectl get nodes
[root@master1 ~]# kubectl get pods -A
如果join的token之前沒有記住,沒關系,在master重新生成一下
[root@master1 ~]# kubeadm token create --print-join-command
可以看到節點和個元件的pod狀态均正常,至此叢集搭建完畢!
4. trouble shooting
出現了問題不可怕,因為如果不非常仔細,按照文檔敲下來很有可能會出錯。可怕的是,出錯了連去網上多搜尋一下都懶得搜,甚至開始抱怨。kubernets已經很成熟了,網上的資料非常多,出現的問題很多人也遇到過,在網上基本都有大佬給出回答。
4.1 初始化叢集長期卡住,最終報錯
拉鏡像失敗
[ERROR ImagePull]: failed to pull image k8s.gcr.io/kube-apiserver:v1.18.8: output: Error response from daemon: Get https://k8s.gcr.io/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
, error: exit status 1
執行拉鏡像腳本
[root@master1 ~]# sh images.sh
4.2 網橋報錯
W0822 17:05:25.135752 3367 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
[init] Using Kubernetes version: v1.18.8
[preflight] Running pre-flight checks
[WARNING Service-Kubelet]: kubelet service is not enabled, please run 'systemctl enable kubelet.service'
error execution phase preflight: [preflight] Some fatal errors occurred:
[ERROR FileContent--proc-sys-net-bridge-bridge-nf-call-iptables]: /proc/sys/net/bridge/bridge-nf-call-iptables contents are not set to 1
[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
檢查前面的核心參數是否修改
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
4.3 kubelet-check健康檢查報錯
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp: lookup localhost on 198.18.254.40:53: no such host.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp: lookup localhost on 198.18.254.40:53: no such host.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp: lookup localhost on 198.18.254.40:53: no such host.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp: lookup localhost on 198.18.254.40:53: no such host.
[kubelet-check] It seems like the kubelet isn't running or healthy.
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp: lookup localhost on 198.18.254.40:53: no such host.
檢查hosts檔案,本機位址解析是否被删除了
127.0.0.1 localhost
4.4 檢視元件處于不健康狀态
[root@master1 ~]# kubectl get cs
發現controller-manager和scheduler狀态是不健康
如果節點都處于Ready後,實際上該狀态是不影響的。
因為kubeadm v1.18.6及以後的版本,是預設不開啟controller-manager的10252和scheduler的10251端口的,一般10251和10252是監聽在http上面,不需要證書認證,屬于不安全的端口。
檢視機器監聽端口,發現預設這兩個端口沒有監聽
可以将/etc/kubernetes/manifests/kube-controller-manager.yaml、/etc/kubernetes/manifests/kube-scheduler.yaml中--port=0注釋掉,再次kubect get cs元件狀态,這時都是ok了。
預設不監聽http端口,但是用戶端檢視元件狀态有預設是檢查http端口,不知道這算不算是kuberadm的一個小bug呢,哈哈~~~
4.5 worker節點加入叢集後長期處于NotReady
檢視node
檢視pod狀态,kube-proxy一直處于建立狀态,網絡元件calico一直處于初始化
kubect describe pod檢視報錯:FailedCreatePodSandBox
說明節點沒有pull基礎鏡像pause,到相應節點上面去拉取pause鏡像即可。
4.6 node節點運作一段時間後出現錯誤
檢視pod狀态
檢視報錯的pod,發現cgroup報錯
到node節點檢視kubelet也在報錯
原因是docker的驅動改為了systemd,但是kubelet的驅動沒有改
kubelet的驅動是在kubeadm join初始化的時候與docker保持一緻的,docker修改了,kubelet也需要修改
[root@node2 ~]# sed -i 's/--cgroup-driver=cgroupfs/--cgroup-driver=systemd/g' /var/lib/kubelet/kubeadm-flags.env
[root@node2 ~]# systemctl restart kubelet
同樣如果node節點處于NotReady,kubelet一直在重新開機,也需要檢查kubelet的cgroup驅動是否和docker的一緻。