OS:Ubuntu 20.04.2 LTS / Ubuntu 22
Kubernetes:1.25.10 (1.24+已经弃用了docker,初始化时会有超时异常)

官方文档:
Creating a cluster with kubeadm

参考博客:
使用Kubeadm(1.13+)快速搭建Kubernetes集群 - 雨夜朦胧
Ubuntu 22.10 安装 k8s 1.25.3

一、准备

两台虚拟机(CPU最少2核)

禁用swap

Kubernetes 1.8开始要求必须禁用Swap(内存交换),如果不关闭,默认配置下kubelet将无法启动

sudo vim /etc/fstab
"""
# 注释下面这行
#/swap.img      none    swap    sw      0       0 
"""
sudo swapoff -a
# 确认swap已经关闭:若swap行都显示 0 则表示关闭成功 
free -m

hosts配置

sudo vim /etc/hosts

"""
# 自己本地ip
192.168.10.110 k8s-master
192.168.10.111 k8s-node-1
"""
reboot # 重启

安装docker

Kubernetes从1.6开始使用CRI(Container Runtime Interface)容器运行时接口。默认的容器运行时仍然是Docker,是使用kubelet中内置dockershim CRI来实现的

docker详细安装教程
查看CHANGELOG-x.xx.md选择Kubernetes对应的docker版本

sudo apt-get remove docker docker-engine docker.io containerd runc
sudo apt-get update

# 更新apt包索引并安装包以允许apt通过 HTTPS 使用存储库:
sudo apt-get install -y ca-certificates curl gnupg lsb-release

# 添加 Docker 的官方 GPG 密钥
sudo mkdir -p /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg

# 设置稳定存储库
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable" | sudo tee  /etc/apt/sources.list.d/docker.list > /dev/null
sudo chmod a+r /etc/apt/keyrings/docker.gpg
sudo apt-get update

sudo apt-get install -y docker-ce=5:20.10.17~3-0~ubuntu-jammy docker-ce-cli=5:20.10.17~3-0~ubuntu-jammy containerd.io docker-buildx-plugin docker-compose-plugin

sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
sudo containerd config default > $HOME/config.toml
sudo cp $HOME/config.toml /etc/containerd/config.toml

sudo systemctl stop containerd.service
sudo systemctl stop docker.service
# 修改 /etc/containerd/config.toml 文件后,要将 docker、containerd 停止后,再启动
sudo sed -i "s#registry.k8s.io/pause#registry.cn-hangzhou.aliyuncs.com/google_containers/pause#g" /etc/containerd/config.toml
# https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#containerd-systemd
# 确保 /etc/containerd/config.toml 中的 disabled_plugins 内不存在 cri
##### Ubuntu 22+的版本一定要执行下面命令
sudo sed -i "s#SystemdCgroup = false#SystemdCgroup = true#g" /etc/containerd/config.toml
sudo systemctl enable --now containerd.service

sudo systemctl restart docker.service
sudo systemctl enable docker.service
systemctl list-unit-files | grep docker

设置docker权限

如果使用docker images提醒没有权限,可用下面命令设置

sudo chown root:docker /var/run/docker.sock # 修改docker.sock权限为root:docker
sudo groupadd docker          # 添加docker用户组 
sudo gpasswd -a $USER docker  # 将当前用户添加至docker用户组
newgrp docker                 # 更新docker用户组

配置docker

sudo vim /etc/docker/daemon.json

"""
{
	"registry-mirrors": [
		"https://docker.mirror.ustc.edu.cn",
		"https://registry.docker-cn.com"
	],
	"exec-opts": ["native.cgroupdriver=systemd"], # 最重要的是这行配置cgroups
	"log-driver": "json-file",
	"log-opts": {
		"max-size": "100m"
	},
	"storage-driver": "overlay2"
}
"""
sudo systemctl daemon-reload
sudo systemctl restart docker.service 
sudo docker info  # 查看是否设置成功

为什么要修改为使用systemd
Kubernetes 推荐使用 systemd 来代替 cgroupfs,因为systemd是Kubernetes自带的cgroup管理器,负责为每个进程分配cgroups,但docker的cgroup driver默认是cgroupfs,这样就同时运行有两个cgroup控制管理器,当资源有压力的情况时,有可能出现不稳定的情况

安装 kubeadm, kubelet, kubectl

  • kubeadm: 引导启动k8s集群的命令行工具。
  • kubelet: 在群集中所有节点上运行的核心组件, 用来执行如启动pods和containers等操作。
  • kubectl: 操作集群的命令行工具。
sudo apt-get update && sudo apt-get install -y apt-transport-https
curl -s https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | sudo apt-key add -

sudo vim /etc/apt/sources.list.d/kubernetes.list
""" 
deb https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main 
"""
sudo apt update

# k8s1.23以上版本,已经弃用了docker了,如果安装的kubelet kubeadm kubectl,最好指定版本
# k8s的Calico网络插件最新版本v3.25只支持到k8s 1.25版本,所以这里安装1.25版本
sudo apt-get install -y kubelet=1.25.10-00 kubeadm=1.25.10-00 kubectl=1.25.10-00 
# 阻止自动更新(apt upgrade时忽略)。所以更新的时候先unhold,更新完再hold
sudo apt-mark hold kubelet kubeadm kubectl
# 开机自启
sudo systemctl enable kubelet.service

k8s对应Calico网络版本

apt-mark 使用
功能

apt-mark 可以对软件包进行设置(手动/自动 )安装标记,也可以用来处理软件
包的 dpkg(1) 选中状态,以及列出或过滤拥有某个标记的软件包。

语法

apt-mark [选项] {auto|manual} 软件包1 [软件包2 …]

命令

auto – 标记指定软件包为自动安装
manual – 标记指定软件包为手动安装
minimize-manual – Mark all dependencies of meta packages as automatically installed.
hold – 标记指定软件包为保留(held back),阻止软件自动更新
unhold – 取消指定软件包的保留(held back)标记,解除阻止自动更新
showauto – 列出所有自动安装的软件包
showmanual – 列出所有手动安装的软件包
showhold – 列出设为保留的软件包

二、创建节点(master、node)

1. 初始化 k8s-master

K8s的控制面板组件运行在Master节点上,包括etcd和API server(Kubectl便是通过API server与k8s通信)

sudo kubeadm init \
--kubernetes-version v1.26.5 \
--pod-network-cidr=10.244.0.0/16 \
--apiserver-advertise-address=x.x.x.x \
--image-repository registry.aliyuncs.com/google_containers
–pod-network-cidr

选择一个Pod网络插件,并检查它是否需要在初始化Master时指定一些参数,它的值取决于你在下一步选择的哪个网络网络插件,这里选择Flannel的网络插件参数为 10.244.0.0/16。Calico网络为192.168.0.0/16。参考:Installing a pod network add-on

–apiserver-advertise-address=

kubeadm使用eth0的默认网络接口(通常是内网IP)做为Master节点的advertise address,如果我们想使用不同的网络接口,该参数来设置。
如果适应IPv6,则必须使用IPv6d的地址,如:--apiserver-advertise-address=fd00::101

–image-repository

使用kubeadm config images pull来预先拉取初始化需要用到的镜像,用来检查是否能连接到KubenetesRegistries
Kubenetes默认Registries地址是k8s.gcr.io,很明显,在国内并不能访问gcr.io,因此在kubeadm v1.13之前的版本,安装起来非常麻烦,但是在1.13版本中终于解决了国内的痛点,其增加了一个--image-repository参数,默认值是k8s.gcr.io,我们将其指定为国内镜像地址:registry.aliyuncs.com/google_containers

–kubernetes-version

默认值是stable-1,会导致从https://dl.k8s.io/release/stable-1.txt下载最新的版本号,我们可以将其指定为固定版本来跳过网络请求。

如果我们想使用非root用户操作kubectl,可以使用以下命令,这也是kubeadm init输出的一部分

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

export KUBECONFIG=/etc/kubernetes/admin.conf

2. 添加节点k8s-node

查询token(master)
kubeadm token list

注意:
Token 的过期时间是24小时
如果该命令查无数据,则直接跳转到重新生成Token

查询cert-hash(master)
openssl x509 -pubkey -in /etc/kubernetes/pki/ca.crt | openssl rsa -pubin -outform der 2>/dev/null | openssl dgst -sha256 -hex | sed 's/^.* //'
拼接连接字符串(node)
sudo kubeadm join 192.168.88.123:6443 --token ay9cdc.0n7sjjy21hejhdae --discovery-token-ca-cert-hash sha256:091d0e1adc9cc4e77cd6d25fb5eebc1a594c690827362a594abffa0b193861a2

如果node节点加入到集群时卡住 [preflight] Running pre-flight checks有两种原因

  1. master与node时间不同步,使用date命令查看
  2. master的token过期,重新生成一个
重新生成Token(master)

执行了查询Token的命令,没有返回数据时,需要重新生成Token

kubeadm token create --ttl 0 --print-join-command

查看kubelet日志

journalctl -xefu kubelet

三、遇到的异常

[ERROR Port-10250]: Port 10250 is in use

端口被启动失败或者成功的kubeadm占用

sudo netstat -ntlup|grep 10250
"""
tcp6       0      0 :::10250                :::*                    LISTEN      27560/kubelet
"""

sudo kill -9 27560
sudo kubeadm reset

[ERROR FileAvailable–etc-kubernetes-manifests-kube-apiserver.yaml]: /etc/kubernetes/manifests/kube-apiserver.yaml already exists

yaml文件已存在

sudo kubeadm reset

[kubelet-check] The HTTP call equal to ‘curl -sSL http://localhost:10248/healthz’ failed with error: Get http://localhost:10248/healthz: dial tcp 127.0.0.1:10248: connect: connection refused.

使用tcp协议连接到127.0.0.1:10248的连接被拒绝。这是cgroup驱动问题。默认情况下Kubernetes cgroup驱动程序设置为system,但docker设置为systemd。我们需要更改Docker cgroup驱动。

sudo vim /etc/docker/daemon.json
"""
# 如果配置了daemon.json加上{}内的参数即可
{
	"exec-opts": ["native.cgroupdriver=systemd"]
}
"""

sudo systemctl daemon-reload
sudo systemctl restart docker
sudo systemctl restart kubelet
sudo kubeadm reset
sudo kubeadm init

# 还有个可能是没有关闭交换分区

[ERROR CRI]: container runtime is not running: output: E1021 15:03:22.662135

参考github大佬们的讨论

rm -rf /etc/containerd/config.toml
systemctl restart containerd

[ERROR CRI]: container runtime is not running: output: time=“2023-03-24T19:16:15+08:00” level=fatal msg=“validate service connection: CRI v1 runtime API is not implemented for endpoint “unix:///var/run/containerd/containerd.sock” : rpc error: code = Unimplemented desc = unknown service runtime.v1.RuntimeService”

参考CSDN解决方案

sudo vim /etc/containerd/config.toml
"""
# 更改如下配置
# disabled_plugins : ["cri"] 
disabled_plugins : []
"""
# 重启容器
sudo systemctl restart containerd 

Unable to connect to the server: x509: certificate signed by unknown authority

参考kubernetes 坑人的错误
kubeadm resetrm -rf $HOME/.kube 然后执行 kubeadm init ...

couldn’t get current server API group list: Get “https://xxx.xxx.xxx.xxx:6443/api?timeout=32s”: dial tcp xxx.xxx.xxx.xxx:6443: connect: connection refused

配置文件 使用

sudo systemctl stop containerd.service

sudo cp /etc/containerd/config.toml /etc/containerd/config.toml.bak
sudo containerd config default > $HOME/config.toml
sudo cp $HOME/config.toml /etc/containerd/config.toml

# 修改 /etc/containerd/config.toml 文件后,要将 docker、containerd 停止后,再启动
sudo sed -i "s#registry.k8s.io/pause#registry.cn-hangzhou.aliyuncs.com/google_containers/pause#g" /etc/containerd/config.toml
# https://kubernetes.io/zh-cn/docs/setup/production-environment/container-runtimes/#containerd-systemd
# 确保 /etc/containerd/config.toml 中的 disabled_plugins 内不存在 cri
sudo sed -i "s#SystemdCgroup = false#SystemdCgroup = true#g" /etc/containerd/config.toml

kubelet.service: Failed with result ‘exit-code’

原因:重启后交换分区又被开启了或者直接init初始化

Warning: apt-key is deprecated. Manage keyring files in trusted.gpg.d instead (see apt-key(8)).

sudo cp /etc/apt/trusted.gpg /etc/apt/trusted.gpg.d/

四、安装网络插件

为了让Pods间可以相互通信,我们必须安装一个网络插件,并且必须在部署任何应用之前安装,CoreDNS也是在网络插件安装之后才会启动的。
网络的插件完整列表,请参考 Networking and Network Polic

在安装之前,我们先查看一下当前Pods的状态:

kubectl get pods --all-namespaces -o wide
"""
NAMESPACE     NAME                                 READY   STATUS    RESTARTS       AGE
kube-system   coredns-6d8c4cb4d-9kqvq              0/1     Pending   0             2d17h
kube-system   coredns-6d8c4cb4d-ql7g9              0/1     Pending   0             2d17h
kube-system   etcd-k8s-master                      1/1     Running   4             2d17h
kube-system   kube-apiserver-k8s-master            1/1     Running   6 (24m ago)   2d17h
kube-system   kube-controller-manager-k8s-master   1/1     Running   4             2d17h
kube-system   kube-proxy-lv8td                     1/1     Running   4             2d17h
kube-system   kube-scheduler-k8s-master            1/1     Running   5             2d17h
"""

可以看到CoreDND状态是Pending,这是因为我们还没有安装网络插件。
如果使用kubectl get pods --all-namespaces报如下错误The connection to the server localhost:8080 was refused是由于没有执行mkdir -p $HOME/.kube ... 这三行命令

安装 Flannel 网络插件(选择1)

K8s网络组件Flannel的介绍和部署

Flannel是用于解决容器跨节点通信问题的解决方案,兼容CNI插件API。它使用“虚拟网桥和veth设备”的方式为Pod创建虚拟网络接口,通过可配置的“后端”定义Pod间的通信网络,支持基于VXLAN和UDP的Overlay网络,以及基于三层路由的Underlay网络。

默认情况下,Flannel网络插件使用的的网段是10.244.0.0/16,在init的时候,通过--pod-network-cidr=10.244.0.0/16来适配Flannel,当然你也可以修改kube-flannel.yml文件来指定不同的网段。命令如下

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

稍等片刻,再使用kubectl get pods --all-namespaces -o wide命令来查看网络插件的安装情况:

NAMESPACE      NAME                                 READY   STATUS    RESTARTS       AGE
kube-flannel   kube-flannel-ds-q8htw                1/1     Running   0              3m
kube-system    coredns-6d8c4cb4d-9kqvq              1/1     Running   0              2d22h
kube-system    coredns-6d8c4cb4d-ql7g9              1/1     Running   0              2d22h
kube-system    etcd-k8s-master                      1/1     Running   4              2d22h
kube-system    kube-apiserver-k8s-master            1/1     Running   6 (5h6m ago)   2d22h
kube-system    kube-controller-manager-k8s-master   1/1     Running   4              2d22h
kube-system    kube-proxy-lv8td                     1/1     Running   4              2d22h
kube-system    kube-scheduler-k8s-master            1/1     Running   5              2d22h

安装 Calico 网络插件(选择2) 亲测有效

Calico是一个纯三层的虚拟网络方案,Calico 为每个容器分配一个 IP,每个 host 都是 router,把不同 host 的容器连接起来。与 VxLAN 不同的是,Calico 不对数据包做额外封装,不需要 NAT 和端口映射,扩展性和性能都很好。

默认情况下,Calico网络插件使用的的网段是192.168.0.0/16,在init的时候,通过--pod-network-cidr=192.168.0.0/16来适配Calico,当然你也可以修改calico.yml文件来指定不同的网段。命令如下:

curl https://raw.githubusercontent.com/projectcalico/calico/v3.25.1/manifests/calico.yaml -O
kubectl apply -f calico.yaml

# 上面的calico.yaml会去quay.io拉取镜像,如果无法拉取,可使用下面的国内镜像
kubectl apply -f http://mirror.faasx.com/k8s/calico/v3.3.2/rbac-kdd.yaml
kubectl apply -f http://mirror.faasx.com/k8s/calico/v3.3.2/calico.yaml

关于更多Canal的信息可以查看Calico官方文档:kubeadm quickstart

稍等片刻,再使用kubectl get pods --all-namespaces命令来查看网络插件的安装情况。

修改 cidr 地址范围

kubectl -n kube-system edit cm kubeadm-config
vim /etc/kubernetes/manifests/kube-scheduler.yaml
kubectl cluster-info dump | grep -m 1 cluster-cidr  # 检查配置是否生效

五、卸载

sudo rm -rvf $HOME/.kube
sudo kubeadm reset -f
sudo apt-get -y auroremove kubelet kubeadm kubectl
sudo rm -rvf /etc/kubernetes/
sudo rm -rvf /etc/systemd/system/kubelet.service.d
sudo rm -rvf /etc/systemd/system/kubelet.service
sudo rm -rvf /usr/bin/kube*
sudo rm -rvf /etc/cni
sudo rm -rvf /opt/cni
sudo rm -rvf /var/lib/etcd
sudo rm -rvf /var/etcd

kubernetes 单机与集群的使用

Logo

开源、云原生的融合云平台

更多推荐