0%

使用kubeadm安装部署K8S集群——CentOS篇

kubeadm简介

《使用kubeadm升级K8S集群》一文中,了解了k8s集群中常见组件,并且使用kubeadm对k8s集群进行了升级。本文中,会学习使用kubeadm安装部署k8s集群。

Kubeadm is a tool built to provide kubeadm init and kubeadm join as best-practice “fast paths” for creating Kubernetes clusters.

更多内容,参考Overview of kubeadmInstalling kubeadm

安装流程

目标:搭建一个k8s集群,包括master和node01两个节点,节点系统为centos7.6.1810。
master节点ip为192.168.56.200,node01节点ip为192.168.56.201。

1、环境准备。

2、在master节点和node01节点安装kubeadm。

3、初始化master节点,创建k8s集群(记得安装网络插件)。

4、node01节点加入到k8s集群。

5、验证安装。

环境准备

1、配置主机名

2、配置IP地址

3、允许 iptables 检查桥接流量

1
2
3
4
5
6
7
8
9
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
br_netfilter
EOF

cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-ip6tables = 1
net.bridge.bridge-nf-call-iptables = 1
EOF
sudo sysctl --system

4、参考Docker入门,安装Docker

安装kubeadm

参考安装kubeadm

1、确认系统版本
cat /etc/redhat-release

2、执行安装kubeadm、kubelet和kubectl(两个节点都要执行)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
cat <<EOF | sudo tee /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-\$basearch
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kubelet kubeadm kubectl
EOF

# 将 SELinux 设置为 permissive 模式(相当于将其禁用)
sudo setenforce 0
sudo sed -i 's/^SELINUX=enforcing$/SELINUX=permissive/' /etc/selinux/config

sudo yum install -y kubelet kubeadm kubectl --disableexcludes=kubernetes

sudo systemctl enable --now kubelet

centos安装这些组件时如果报错:[Errno -1] repomd.xml signature could not be verified for kubernetes
不考虑安全性的话,最简单的解决办法是修改 /etc/yum.repos.d/kubernetes.repo 文件,设置 repo_gpgcheck=0

3、查看kubelet版本
kubelet --version

初始化master节点

参考Installing kubeadm on your hosts

下载镜像文件

下载必须的镜像文件(默认从gcr.io下载)
kubeadm config images pull

下载失败处理办法

如果下载镜像文件失败,那么需要科学上网,或者更改为国内源。这里选择更改为国内源。

1、导出一份默认配置文件
kubeadm config print init-defaults > kubeadm.conf

2、改为国内源
编辑kubeadm.conf,imageRepository改为:

1
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers

3、指定配置文件,重新执行下载
kubeadm config images pull --config kubeadm.conf

[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-apiserver:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-controller-manager:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-scheduler:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/kube-proxy:v1.23.0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/pause:3.6
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/etcd:3.5.1-0
[config/images] Pulled registry.cn-hangzhou.aliyuncs.com/google_containers/coredns:v1.8.6

执行初始化

1
2
3
kubeadm init
# or
kubeadm init --config kubeadm.conf

完成后,屏幕输出会提示创建配置文件,以及添加worker node的join命令,记录下来。
例如:

1
2
kubeadm join 192.168.56.200:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:6743eaae41ba8fd99e495e3df94ff9a996878e7c9cf8ac590a3c52b97ea8012e

PS:如果忘记了添加worker node的join命令,可以重新生成。

1
2
kubeadm token create --help
kubeadm token create --print-join-command

生成新的join命令后,之前的join命令同样可以使用。

初始化报错解决办法

执行初始化报错:
[kubelet-check] It seems like the kubelet isn’t running or healthy.
The kubelet is not running
The kubelet is unhealthy due to a misconfiguration of the node in some way (required cgroups disabled)

看着是 cgroup 问题,确认一下。

1
2
docker system info | grep -i driver
cat /var/lib/kubelet/config.yaml | grep cgroup

发现 docker 和 kubelet 服务中的cgroup不一致。

方法一:修改docker配置和kubelet保持一致。
编辑 /etc/docker/daemon.json ,添加:

1
2
3
4
5
{
"exec-opts": [
"native.cgroupdriver=systemd"
]
}

方法二:修改kubelet配置和docker保持一致。
kubeadm.conf中添加:

1
2
3
4
5
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
#cgroupDriver: systemd
cgroupDriver: cgroupfs

重启docker,然后重新执行初始化:

1
2
3
4
5
systemctl daemon-reload
systemctl restart docker
#rm -rf /etc/kubernetes/manifests/
kubeadm reset
kubeadm init --config kubeadm.conf

还是报同样的错误。查看错误详情:

1
2
3
4
systemctl status kubelet
journalctl -xeu kubelet
#systemctl daemon-reload
#systemctl restart kubelet

“–cgroups-per-qos enabled, but –cgroup-root was not specified. defaulting to /“
“Failed to run kubelet” err=”failed to run Kubelet: running with swap on is not supported, please disable swap!

看这个提示,问题就很明显了,不支持swap,需要关闭。
swapoff -a
编辑 /etc/fstab,注释掉swap配置。

1
#/dev/mapper/centos-swap swap swap defaults 0 0

再次重新执行初始化:

1
2
kubeadm reset
kubeadm init --config kubeadm.conf

出现新的报错:
Error getting node” err=”node "node" not found

编辑kubeadm.conf,修改apiserver地址。

1
advertiseAddress: 192.168.56.200

再次重新执行初始化:

1
2
kubeadm reset
kubeadm init --config kubeadm.conf

至此,终于成功初始化!

避免初始化报错的方法

1、修改kubelet配置和docker保持一致。
kubeadm.conf中添加:

1
2
3
4
5
---
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
#cgroupDriver: systemd
cgroupDriver: cgroupfs

2、修改apiserver地址为本机地址
编辑kubeadm.conf,修改advertiseAddress字段。

1
advertiseAddress: 192.168.56.200

3、关闭swap
swapoff -a
编辑 /etc/fstab,注释掉swap配置。

1
#/dev/mapper/centos-swap swap swap defaults 0 0

4、执行初始化

1
2
#kubeadm reset
kubeadm init --config kubeadm.conf

创建配置文件

1
2
3
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config

验证安装

1
2
3
docker ps -a
kubectl get nodes
kubectl get pods --namespace kube-system

验证发现问题

问题一:master节点的名字叫node
问题不大,这是因为在初始化的时候没有指定节点名字。在kubeadm.conf里指定即可(需要重新安装)。

1
2
3
4
5
nodeRegistration:
criSocket: /var/run/dockershim.sock
imagePullPolicy: IfNotPresent
name: master
taints: null

不重新安装的话,是否可以直接编辑修改节点的名称?
kubectl edit nodes/node,修改如下:

1
2
3
4
metadata:
labels:
kubernetes.io/hostname: master
name: master

很遗憾,不可以,报错:
error: At least one of apiVersion, kind and name was changed

没关系,就这么着吧,不改了。

问题二:coredns处于pending状态
查看coredns报错信息:

1
2
3
4
kubectl get deployment/coredns -n kube-system -o yaml
kubectl get pods -n kube-system
kubectl describe pods coredns-65c54cc984-srzl4 -n kube-system
kubectl logs pods coredns-65c54cc984-srzl4 -n kube-system

Warning FailedScheduling 2m57s (x36 over 38m) default-scheduler 0/1 nodes are available: 1 node(s) had taint {node.kubernetes.io/not-ready: }, that the pod didn’t tolerate.
原来是coredns默认无法部署在master节点,因为没有配置容忍。参考污点和容忍度进行配置即可。
kubectl edit deployment/coredns -n kube-system -o yaml
tolerations部分添加:

1
2
3
tolerations:
- effect: NoSchedule
key: node.kubernetes.io/not-ready

问题三:coredns无法启动
问题二解决后,coredns可以调度了,但是无法启动。
kubectl describe pods/coredns-55b7b56cf8-jv2dc -n kube-system
network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:docker: network plugin is not ready: cni config uninitialized

仔细研读使用 kubeadm 创建集群,原来问题二是符合预期的,master节点还没有ready,因为缺少cni插件。

参考集群网络系统选择一个cni插件,这里我们选择flannel。

1
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

问题四:kube-flannel无法启动
Error registering network: failed to acquire lease: node “node” pod cidr not assigned
看来是初始化的时候没有加 pod-network-cidr 参数导致的,在kubeadm.conf中添加配置即可(需要重新安装)。

1
2
networking:
podSubnet: "10.244.0.0/16"

不重新安装的话,怎么补救呢?
编辑 /etc/kubernetes/manifests/kube-controller-manager.yaml ,添加参数:

1
2
3
- command:
- --allocate-node-cidrs=true
- --cluster-cidr=10.244.0.0/16

然后重启kubelet:
systemctl restart kubelet

kubectl get pods --all-namespaces
至此,所有组件全部启动成功。

避免验证发现错误的办法

1、在kubeadm.conf里指定节点名称

1
2
3
4
5
nodeRegistration:
criSocket: /var/run/dockershim.sock
imagePullPolicy: IfNotPresent
name: master
taints: null

2、在kubeadm.conf中添加pod网络配置

1
2
networking:
podSubnet: "10.244.0.0/16"

3、安装cni插件

1
kubectl apply -f https://raw.githubusercontent.com/flannel-io/flannel/master/Documentation/kube-flannel.yml

node01加入k8s集群

1、使用join命令,添加node01节点到集群

1
2
kubeadm join 192.168.56.200:6443 --token abcdef.0123456789abcdef \
--discovery-token-ca-cert-hash sha256:6743eaae41ba8fd99e495e3df94ff9a996878e7c9cf8ac590a3c52b97ea8012e

2、验证结果
在master节点执行:
kubectl get nodes
看到master节点和node01节点都是Ready的状态,说明安装成功。

开发模式

出于安全原因,k8s集群默认不会在控制节点(master节点)上调度Pod。如果我们希望可以在master节点上调度Pod,比如在开发测试时,可以去掉master节点的污点。
kubectl taint nodes --all node-role.kubernetes.io/master-

验证安装

手动验证

1
2
3
4
5
6
7
kubectl get nodes
kubectl get pods --all-namespaces
service kube-apiserver status
service kube-controller-manager status
service kube-scheduler status
service kubelet status
service kube-proxy status
1
2
3
4
5
6
7
kubectl run nginx
kubectl get pods
kubectl scale --replicas=3 deploy/nginx
kubectl get pods
kubectl expose deployment nginx --port=80 --type=NodePort
kubectl get service
curl http://node01:31850

test-infra

源码地址:kubernetes/test-infra

1、拉取源码
go get -u k8s.io/test-infra/kubetest

2、执行kubetest

1
2
3
4
5
6
7
kubetest --extract=v1.11.3
cd kubernetes
export KUBE_MASTER_IP="192.168.56.200:6443"
export KUBE_MASTER=kube-master
kubetest --test --provider=skeleton > testout.txt
kubetest --test --provider=skeleton --test_args="ginkgo.focus=Secrets" > testout.txt
cat testout.txt

Smoke Test

按照Smoke Test文档操作一遍。

sonobuoy

官网地址:sonobuoy
源码地址:vmware-tanzu/sonobuoy

节点重启后coredns启动问题

master节点重启后,发现coredns无法正常启动。
Warning Unhealthy 2m1s (x22 over 5m) kubelet Readiness probe failed: HTTP probe failed with statuscode: 503
[ERROR] plugin/errors: HINFO: read udp 10.244.0.7:48010->202.106.195.68:53: i/o timeout
[INFO] plugin/ready: Still waiting on: “kubernetes”

参考How to solve CoreDNS always stuck at “waiting for kubernetes”?,发现需要关闭防火墙,低级错误!

1
2
3
systemctl status firewalld
systemctl stop firewalld
systemctl disable firewalld