kubeadm初始化单控制平面集群内网排坑
2024-04-10 07:30:46  阅读数 728

关键字:k8s, init, containerd, docker
单控制平面集群就是只有一个 master 节点的 k8s 集群
实验版本:kube套件 v1.25.2
时间:2022年10月

1. 离线安装 kubectl,kubeadm,kubelet,container.io,docker

环境: CentOS 8

下载所需的离线包

# 提示:通过 yum 下载的包,每执行一次,都需要备份下载的包,因为下次执行会删除本次下载的内容
sudo yum install --downloadonly --downloaddir=./kd yum-utils device-mapper-persistent-data lvm2 net-tools
sudo yum-config-manager --add-repo https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
# 这一步会自动下载 container.io
sudo yum install --downloadonly --downloaddir=./kd docker-ce --allowerasing
# 下载 kubernetes 套件
vim /etc/yum.repos.d/kubernetes.repo
cat /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

sudo yum install --downloadonly --downloadaddr=./kd kubectl kubelet kubeadm

# 此时总共下载的包有:
ll kd
-rw-r--r--. 1 root root  385600 Sep 28 01:26 device-mapper-1.02.177-10.el8.x86_64.rpm
-rw-r--r--. 1 root root  277096 Sep 28 01:26 device-mapper-event-1.02.177-10.el8.x86_64.rpm
-rw-r--r--. 1 root root  276140 Sep 28 01:26 device-mapper-event-libs-1.02.177-10.el8.x86_64.rpm
-rw-r--r--. 1 root root  418904 Sep 28 01:26 device-mapper-libs-1.02.177-10.el8.x86_64.rpm
-rw-r--r--. 1 root root  946764 Sep 28 01:26 device-mapper-persistent-data-0.9.0-4.el8.x86_64.rpm
-rw-r--r--. 1 root root 1713492 Sep 28 01:26 lvm2-2.03.12-10.el8.x86_64.rpm
-rw-r--r--. 1 root root 1224952 Sep 28 01:26 lvm2-libs-2.03.12-10.el8.x86_64.rpm
-rw-r--r--. 1 root root 34668844 Sep 28 00:36 containerd.io-1.6.8-3.1.el8.x86_64.rpm
-rw-r--r--. 1 root root 21953108 Sep 28 00:35 docker-ce-20.10.18-3.el8.x86_64.rpm
-rw-r--r--. 1 root root 30951856 Sep 28 00:36 docker-ce-cli-20.10.18-3.el8.x86_64.rpm
-rw-r--r--. 1 root root  4855528 Sep 28 00:35 docker-ce-rootless-extras-20.10.18-3.el8.x86_64.rpm
-rw-r--r--. 1 root root  3933420 Sep 28 00:35 docker-scan-plugin-0.17.0-3.el8.x86_64.rpm
-rw-r--r--. 1 root root    71256 Sep 28 00:35 libcgroup-0.41-19.el8.x86_64.rpm
-rw-r--r--. 1 root root 16049626 Sep 28 01:39 14083ac8b11792469524dae98ebb6905b3921923937d6d733b8abb58113082b7-kubernetes-cni-1.1.1-0.x86_64.rpm
-rw-r--r--. 1 root root 10234290 Sep 28 01:39 3062280e93933954707f9a6a31d36dbcc0856ecae323c12146c94d51641e28da-kubeadm-1.25.2-0.x86_64.rpm
-rw-r--r--. 1 root root 21793274 Sep 28 01:39 74b96e0afbbeb02ee0f0cfcdb7f0138984c4e62fff8329d49cc8131271c2cc12-kubelet-1.25.2-0.x86_64.rpm
-rw-r--r--. 1 root root 10607794 Sep 28 01:39 856b98e0a67e4f6d62f284f83fcba535087a6b5530d348775fd84f8bd294dbd9-kubectl-1.25.2-0.x86_64.rpm
-rw-r--r--. 1 root root   208824 Sep 28 01:39 conntrack-tools-1.4.4-10.el8.x86_64.rpm
-rw-r--r--. 1 root root  8552778 Sep 28 01:39 e382ead81273ab8ebcddf14cc15bf977e44e1fd541a2cfda6ebe5741c255e59f-cri-tools-1.25.0-0.x86_64.rpm
-rw-r--r--. 1 root root    24660 Sep 28 01:39 libnetfilter_cthelper-1.0.0-15.el8.x86_64.rpm
-rw-r--r--. 1 root root    24700 Sep 28 01:39 libnetfilter_cttimeout-1.0.0-11.el8.x86_64.rpm
-rw-r--r--. 1 root root    31976 Sep 28 01:39 libnetfilter_queue-1.0.4-3.el8.x86_64.rpm
-rw-r--r--. 1 root root   330692 Sep 28 01:39 socat-1.7.4.1-1.el8.x86_64.rpm

离线安装

# -U用于更新系统已经安装的包
rpm -Uvh device-mapper-1.02.177-10.el8.x86_64.rpm device-mapper-event-1.02.177-10.el8.x86_64.rpm device-mapper-event-libs-1.02.177-10.el8.x86_64.rpm device-mapper-libs-1.02.177-10.el8.x86_64.rpm device-mapper-persistent-data-0.9.0-4.el8.x86_64.rpm lvm2-2.03.12-10.el8.x86_64.rpm lvm2-libs-2.03.12-10.el8.x86_64.rpm
# 安装 docker-ce
rpm -q buildah
#查出 buildah 包名
#同理查出cockpit-podman,containers-common,podman,podman-catatonit ,然后
rpm -e xxx yyy
# 擦除上面5个包
rpm -q runc
rpm -e runc-xxx
rpm -ivh containerd.io-1.6.8-3.1.el8.x86_64.rpm docker-ce-20.10.18-3.el8.x86_64.rpm docker-ce-cli-20.10.18-3.el8.x86_64.rpm docker-ce-rootless-extras-20.10.18-3.el8.x86_64.rpm docker-scan-plugin-0.17.0-3.el8.x86_64.rpm libcgroup-0.41-19.el8.x86_64.rpm
# 安装 kube 套件
rpm -ivh 14083ac8b11792469524dae98ebb6905b3921923937d6d733b8abb58113082b7-kubernetes-cni-1.1.1-0.x86_64.rpm 3062280e93933954707f9a6a31d36dbcc0856ecae323c12146c94d51641e28da-kubeadm-1.25.2-0.x86_64.rpm 74b96e0afbbeb02ee0f0cfcdb7f0138984c4e62fff8329d49cc8131271c2cc12-kubelet-1.25.2-0.x86_64.rpm 856b98e0a67e4f6d62f284f83fcba535087a6b5530d348775fd84f8bd294dbd9-kubectl-1.25.2-0.x86_64.rpm conntrack-tools-1.4.4-10.el8.x86_64.rpm e382ead81273ab8ebcddf14cc15bf977e44e1fd541a2cfda6ebe5741c255e59f-cri-tools-1.25.0-0.x86_64.rpm libnetfilter_cthelper-1.0.0-15.el8.x86_64.rpm libnetfilter_cttimeout-1.0.0-11.el8.x86_64.rpm libnetfilter_queue-1.0.4-3.el8.x86_64.rpm socat-1.7.4.1-1.el8.x86_64.rpm

vim /etc/sysconfig/kubelet
# 设置 KUBELET_EXTRA_ARGS="--cgroup-driver=systemd"
vi /usr/lib/systemd/system/kubelet.service.d/10-kubeadm.conf
# Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf --cgroup-driver=systemd"
systemctl daemon-reload  
systemctl enable kubelet  
systemctl restart kubelet

2. 本地镜像仓库搭建

首先搭建本地镜像仓库,例如Docker的仓库registry,不需要开启 tls,因为开启了也没啥用,很多程序不支持自签名 https

# 互联网
docker pull registry
docker save <image id> > ./registry.tar
# 内网
docker load -i registry.tar
docker tag <image id> registry:2.7
vim /etc/docker/daemon.json # 配置 docker 的本地仓库地址,方便 docker 操作仓库的拉取和上传
cat /etc/docker/daemon.json
{
"insecure-registries":["10.x.x.x:5000"]
}
systemctl daemon-reload
systemctl restart docker
docker run -itd -v /data/registry:/var/lib/registry -p 5000:5000 --restart=always --name registry registry:2.7
# 查看私有仓库
curl http://ip:5000/v2/_catalog

3. 配置 containerd 【排坑1】

Containerd 运行时是 k8s 在运行时自动找到的 cri,默认使用 containerd 管理镜像和容器

之前以为 k8s 的镜像操作( push\pull)是使用 Docker 体系,后来才发现,其实使用的是 containerd,这个区别在于,指定私有镜像仓库后,即时 Docker 配置了 insecure-registries,在 containerd 未设置有关私有仓库配置的情况下,k8s 拉取镜像会报错“http: server gave HTTP response to HTTPS client”

cat << EOF > /etc/modules-load.d/containerd.conf
overlay
br_netfilter
EOF
# 生成配置文件
containerd config default > /etc/containerd/config.toml
# 编辑配置文件
vim /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".containerd.runtimes.runc.options]
  SystemdCgroup = true
[plugins."io.containerd.grpc.v1.cri"]  
  sandbox_image = "10.xx.xx.xx:5000/k8s.gcr.io/pause:3.8"
  #sandbox_image = "k8s.gcr.io/pause:3.2"
# 这里的配置需要跟后续本地仓库中存储的沙盒镜像名一致

[plugins."io.containerd.grpc.v1.cri".registry]
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
      endpoint = ["https://docker.mirrors.ustc.edu.cn"]
      #endpoint = ["https://registry-1.docker.io"]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."*"]
      endpoint = ["https://docker.mirrors.ustc.edu.cn"]
    [plugins."io.containerd.grpc.v1.cri".registry.mirrors."192.168.196.110:5000"]
      endpoint = ["http://10.xx.xx.xx:5000"]
  [plugins."io.containerd.grpc.v1.cri".registry.configs]
    [plugins."io.containerd.grpc.v1.cri".registry.configs."192.168.196.110:5000".tls]
      insecure_skip_verify = true
# 标红的是需要修改的地方

systemctl enable containerd
systemctl restart containerd

参考 使用containerd部署k8s集群

4. 准备初始化相关镜像

查看所需镜像列表

# 这一步需要在内网环境进行,因为内外网 kube 套件的版本不一致会导致镜像版本错误
kubeadm config images list --image-repository=registry.aliyuncs.com/google_containers
# --kubernetes-version 参数对某些镜像无效,因此不能指望该参数会找到所需要版本的镜像
# --image-repository 参数可以指定国内镜像源
registry.aliyuncs.com/google_containers/kube-apiserver:v1.25.2
registry.aliyuncs.com/google_containers/kube-controller-manager:v1.25.2
registry.aliyuncs.com/google_containers/kube-scheduler:v1.25.2
registry.aliyuncs.com/google_containers/kube-proxy:v1.25.2
registry.aliyuncs.com/google_containers/pause:3.9
registry.aliyuncs.com/google_containers/etcd:3.5.4-0
registry.aliyuncs.com/google_containers/coredns:v1.9.3

在互联网系统拉取所需镜像

# 试了使用 kubeadm config images pull 的方式拉取,在设置了镜像仓库后确实可以拉取,然而无论用 docker images 还是 ctr image list 查找拉取的镜像,都找不到,后来发现需要用 crictl images来查看拉取的镜像列表,
# crictl 是 CRI 兼容的容器运行时命令行接口。 可以使用它来检查和调试 Kubernetes 节点上的容器运行时和应用程序。https://kubernetes.io/zh-cn/docs/tasks/debug/debug-cluster/crictl
# 可以使用 docker pull 一个一个的拉取镜像例如:
docker pull registry.aliyuncs.com/google_containers/kube-apiserver:v1.25.2
docker save -o kube-apiserver.tar registry.aliyuncs.com/google_containers/kube-apiserver:v1.25.2
#也可以写个 shell 脚本更方便的拉取镜像并保存到本地文件
# cat pull-save-images.sh
#!/bin/bash
images=(
    kube-apiserver:v1.25.2
    kube-controller-manager:v1.25.2
    kube-scheduler:v1.25.2
    kube-proxy:v1.25.2
    pause:3.9
    etcd:3.5.4-0
    coredns:1.9.3
)
for imageName in ${images[@]};
do
    docker pull registry.aliyuncs.com/google_containers/${imageName}
    docker tag registry.aliyuncs.com/google_containers/${imageName} 10.x.x.x:5000/registry.aliyuncs.com/google_containers/${imageName}
    docker rmi registry.aliyuncs.com/google_containers/${imageName}
    docker save -o `echo ${imageName}|awk -F ':' '{print $1}'`.tar 10.x.x.x:5000/registry.aliyuncs.com/google_containers/${imageName}
done
# 10.x.x.x:5000 是内网镜像仓库接口

离线导入镜像到本地&上传本地镜像仓库

# cat load-push-image.sh
#!/bin/bash
ls /xxx/kubeadm-images-1.25.2 > /xx/images-list.txt

cd /xxx/kubeadm-images-1.25.2
for i in $(cat /root/images-list.txt)
do
     docker load -i $i
done
images=(
    kube-apiserver:v1.25.2
    kube-controller-manager:v1.25.2
    kube-scheduler:v1.25.2
    kube-proxy:v1.25.2
    pause:3.9
    etcd:3.5.4-0
    coredns:1.9.3
)
for imageName in ${images[@]};
do
    docker push 10.x.x.x:5000/registry.aliyuncs.com/google_containers/${imageName}
done 
# 这里 push 的镜像标签需要与上面 pull-save-images.sh 中的镜像标签相互呼应

# 查看镜像仓库中的镜像
curl http://10.x.x.x:5000/v2/_catalog |jq
# 发现一个好用的 linux 工具 jq,可以格式化输出 json 格式文本

5. 初始化 【排坑2】

设置DNS,设置后重启网络

查看文件是否存在: ls /etc/resolv.conf

内网本来没有设置DNS,因为意义不大,但CentOS在没有DNS的情况下,默认没有文件 /etc/resolv.conf,这会导致在 kubeadm init 的阶段,报错

Couldn't initialize a kubernetes cluster

调取 kubelet 的日志:

journalctl -xeu kubelet

会出现 "Error getting node" err="node "localhost.localdomain" not found", 日志前面会出现

"Failed to generate sandbox config for pod" err=”open /etc/resolv.conf: no such file or directory"

出现这个错误就是因为,k8s找不到 /etc/resolv.conf 文件,从而无法创建沙盒 pod,这应该是 k8s 内网环境的兼容性问题,希望以后 k8s 可以对内网环境友好

执行初始化

kubeadm init --image-repository=10.x.x.x:5000/registry.k8s.io --pod-network-cidr=192.168.0.0/16 --apiserver-advertise-address=10.x.x.x
# --image-repository 指定本地镜像仓库和路径
# --pod-network-cidr 预先选取 calico 网络插件作为 k8s 集群的 pod 网络插件,calico 默认的容器网络子网为 192.168.0.0/16,与内网环境的子网10.x 段不冲突,所以使用该网段
# --apiserver-advertise-address,除非另有说明,否则 kubeadm 使用与默认网关关联的网络接口来设置此控制平面节点 API server 的广播地址。
# 不要设置--control-plane-endpoint,只有HA集群才配置这个参数,为所有控制平面节点设置共享端点。 端点可以是负载均衡器的 DNS 名称或 IP 地址