K8S 安装部署 (Ubuntu 22.04)
关于在 Ubuntu 22.04 环境下部署 k8s 的详细记录
环境
在 WireGuard PVE Openwrt 组网 Note 中记录了两台 PVE 之间的网络情况。 现在继续在这个环境下搭建 k8s,准备使用 ubuntu-01
作为 master 节点(部署 control-plane
),其余两个节点作为 worker 即可。
node | ip | resource | role | version |
---|---|---|---|---|
ubuntu-01 | 172.16.1.101 | 4 core 30 GB | master | 22.04 |
ubuntu-02 | 172.16.1.102 | 4 core 30 GB | worker | 22.04 |
ubuntu-03 | 172.16.1.103 | 3 core 12 GB | worker | 22.04 |
真希望哪天公司能淘汰一个戴尔服务器廉价卖给我 😭
准备
接下来的工作,在所有的节点上执行,可以使用 iTerm2 多窗口 broadcast 输入
主机名解析
修改 /etc/hosts
增加主机名解析记录
1
2
3
172.16.1.101 ubuntu-01
172.16.1.102 ubuntu-02
172.16.1.103 ubuntu-03
禁用 swap 空间
修改 /etc/fstab
将 swap 这一行给注释掉
1
2
3
4
5
6
7
8
9
10
11
12
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point> <type> <options> <dump> <pass>
# / was on /dev/sda3 during installation
UUID=8afcc49f-6158-4985-a108-69b2dd7cd55b / ext4 errors=remount-ro 0 1
# /boot/efi was on /dev/sda2 during installation
UUID=0CE6-58A6 /boot/efi vfat umask=0077 0 1
#/swapfile none swap sw 0 0
禁止休眠
1
systemctl mask sleep.target suspend.target hibernate.target hybrid-sleep.target
禁止防火墙
1
2
ufw disable
ufw status
允许 iptables 检查桥接流量
1
2
modprobe overlay
modprobe br_netfilter
修改配置文件 /etc/modules-load.d/k8s.conf
1
2
overlay
br_netfilter
修改配置文件 /etc/sysctl.d/k8s.conf
1
2
3
net.bridge.bridge-nf-call-iptables = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward = 1
使上述配置生效
1
sysctl --system
配置 containerd
先看下系统是否有 containerd 服务
1
systemctl status containerd
没有的话需要先安装并保持开机启动,我是在 DockerHub 按照官方教程安装 Docker 后就会有 containerd 服务。
生成 containerd 的默认配置
1
containerd config default > /etc/containerd/config.toml
将默认配置作出如下修改
- 开启
SystemdCgroup
1
SystemdCgroup = true
- 修改
sandbox_image
镜像为阿里云google_containers
镜像源
1
sandbox_image = "registry.aliyuncs.com/google_containers/pause:3.9"
- 在
[plugins."io.containerd.grpc.v1.cri".registry]
配置项下面增加一行config_path
1
2
[plugins."io.containerd.grpc.v1.cri".registry]
config_path = "/etc/containerd/certs.d"
- 确认下面配置项已经清空
1
2
[plugins."io.containerd.grpc.v1.cri".registry.mirrors]
# <make-sure-here-is-nothing>
配置完毕后可以重启 containerd
服务
1
systemctl restart containerd
安装 kubelet kubeadm kubectl
下述安装流程与 k8s 官方手册保持一致,此次安装的版本是 v1.30.1。
1
2
3
4
5
6
7
8
9
10
11
12
apt-get update
# apt-transport-https 可能是一个虚拟包(dummy package);如果是的话,你可以跳过安装这个包
apt-get install -y apt-transport-https ca-certificates curl gpg
# 如果 `/etc/apt/keyrings` 目录不存在,则应在 curl 命令之前创建它,请阅读下面的注释。
# sudo mkdir -p -m 755 /etc/apt/keyrings
curl -fsSL https://pkgs.k8s.io/core:/stable:/v1.30/deb/Release.key | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg
# 此操作会覆盖 /etc/apt/sources.list.d/kubernetes.list 中现存的所有配置。
echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://pkgs.k8s.io/core:/stable:/v1.30/deb/ /' | sudo tee /etc/apt/sources.list.d/kubernetes.list
apt-get update
apt-get install -y kubelet kubeadm kubectl
# 锁定版本
apt-mark hold kubelet kubeadm kubectl
nginx + keepalived 高可用配置
nginx
创建 nginx 配置文件
1
vim volumes/conf/nginx.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
# 使用默认配置
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
# stream 模块负责创建 TCP 和 UDP 流量代理
stream {
log_format main '$remote_addr $upstream_addr - [$time_local] $status $upstream_bytes_sent';
access_log /var/log/nginx/k8s-access.log main;
error_log /var/log/nginx/k8s-error.log debug;
# upstream 定义了一个上游服务器组, 用于负载均衡
upstream k8s-apiserver {
server 172.16.1.101:6443;
server 172.16.1.102:6443;
server 172.16.1.103:6443;
}
server {
listen 6443;
# proxy_pass 会指定流量转发的目标, 即上游服务器组 k8s-apiserver
proxy_pass k8s-apiserver;
}
}
创建 nginx docker compose 文件
1
2
3
4
5
6
7
8
9
10
11
services:
nginx:
container_name: nginx-1
image: nginx:latest
network_mode: host
volumes:
- /etc/localtime:/etc/localtime:ro
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/conf/nginx.conf:/etc/nginx/nginx.conf
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/html:/usr/share/nginx/html
- ${DOCKER_VOLUME_DIRECTORY:-.}/volumes/logs:/var/log/nginx
restart: always
keepalived
通过 apt 安装
1
apt-get install keepalived
创建配置文件 /etc/keepalived/keepalived.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
global_defs {
router_id keepalived_1 # 用于标识 keepalived 唯一实例, 主从需要区分
vrrp_skip_check_adv_addr # 跳过对 VRRP 广告报文来源地址的检查
# vrrp_strict # 启用严格的 VRRP 检查。确保收到的报文符合严格的 VRRP 协议标准, 单播模式需要注释
vrrp_garp_interval 0.1 # 设置 GARP(Gratuitous ARP)报文的发送间隔,单位为秒。GARP 用于向网络中的其他设备通告 IP 地址的变化。设网络拓扑越复杂设置的越短
vrrp_gna_interval 0.1 # 设置 GNA(Gratuitous NA, 针对 IPv6)报文的发送间隔,单位为秒。类似于 GARP,但用于 IPv6。网络越稳定设置的越长
max_auto_priority # 根据系统资源和配置自动计算 VRRP 实例的最大优先级, 一定程度可以优化性能
}
vrrp_instance VI_1 { # 用于定义一个 VRRP 实例, 每个实例表示一组参与 VRRP 协议的路由器, 共同管理一个或多个虚拟 IP 地址
state MASTER # 定义当前节点的初始状态, 可以是 MASTER 和 BACKUP
interface enp6s18 # 指定 VRRP 运行的网络接口(物理)按需修改
virtual_router_id 11 # 定义虚拟路由器的 ID, 用于标识一个 VRRP 群组, 在同一个广播域中, 参与同一个 VRRP 实例的所有路由器都需要使用相同的 ID
priority 100 # MASTER 设置的高一些
advert_int 1 # 设置 VRRP 广告报文的发送间隔, 单位 s
authentication { # VRRP 的认证信息
auth_type PASS # 认证类型为简单密码(PASS)
auth_pass 1234 # 定义用于认证的密码
}
nopreempt # 当本节点成为 MASTER 时, 如果有更高优先级的节点上限, 本节点将继续保持 MASTER 的角色, 非抢占
unicast_src_ip 172.16.1.101 # 本机IP
unicast_peer {
172.16.1.102
172.16.1.103
}
virtual_ipaddress {
172.16.1.100 #定义虚拟 IP 地址, 要保持和实际IP在同一网段
}
}
配置其它节点上的 keepalived 时, 需要修改 router_id, state 以及 priority. 另外 docker compose 配置文件可以修改 container 名称.
keepalived 应该直接在本地部署, 使用 docker 部署会有一些网络问题
配置 master 节点
只需要在 ubuntu-01 执行即可
配置 master 节点之前,可以在 ubuntu-01 预先下载镜像,k8s 下载的镜像和 docker pull 不是一回事。
1
kubeadm config images pull --image-repository registry.aliyuncs.com/google_containers
使用 kubeadm init 进行 master 节点初始化
1
2
3
4
5
6
7
kubeadm init \
--apiserver-advertise-address=172.16.1.101 \
--control-plane-endpoint=172.16.1.100 \
--image-repository registry.aliyuncs.com/google_containers \
--kubernetes-version v1.30.1 \
--service-cidr=10.96.0.0/16 \
--pod-network-cidr=10.244.0.0/16
其中:
apiserver-advertise-address
指定了 k8s api server 对外广播的 ip 地址,设置为当前 ip 地址,以便别的节点可以通过该地址访问 api serverservice-cidr
指定了 k8s 服务的虚拟 ip 地址范围,不应该与物理网络冲突。pod-network-cidr
是 pod 之间通讯的地址范围。下面要安装的 flannel 文件中就有这个网段。
下面是上述命令的输出结果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
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/
You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:
kubeadm join 172.16.3.100:6443 --token 20n67u.psrogtp3tpeqkhla \
--discovery-token-ca-cert-hash sha256:d7273510fe2ccb40e0f2232df7c418c892e636cf7a75e0676b21cf634be1df83 \
--control-plane
Then you can join any number of worker nodes by running the following on each as root:
kubeadm join 172.16.3.100:6443 --token 20n67u.psrogtp3tpeqkhla \
--discovery-token-ca-cert-hash sha256:d7273510fe2ccb40e0f2232df7c418c892e636cf7a75e0676b21cf634be1df83
根据提示的配置保存集群访问认证的配置文件 这样就可以通过配置文件来访问 k8s 集群了
init 成功之后需要先在 master 节点安装一下 flannel 网络插件,使用默认值即可,不需要更新文件。
1
2
wget https://raw.githubusercontent.com/coreos/flannel/master/Documentation/kube-flannel.yml
kubectl apply -f kube-flannel.yml
如果需要创建多 master 节点支持高可用, 可以在别的 master 节点上执行下述命令加入集群,请注意要包含 --control_plane
和 --certificate-key
两个参数,刚刚在 master-1 执行的 kubeadm init
命令并没有输出 --certificate-key
的值,可以使用下述语句在 master-1 上生成 certificate key
。
1
2
3
4
❯ kubeadm init phase upload-certs --upload-certs
[upload-certs] Storing the certificates in Secret "kubeadm-certs" in the "kube-system" Namespace
[upload-certs] Using certificate key:
c821cc6829e1e402e965f06aa4994fbb59a5f227f021e88daba482538c4b0fcc
然后在 master-2 节点上执行下述命令加入 master 组
1
2
3
kubeadm join 172.16.1.100:6443 --token mrik2v.i6skqyc3zs89zkqd \
--discovery-token-ca-cert-hash sha256:6d51a002a7abdeeaff04ba988ba8271038a256809543713dca28d216c8832d15 \
--certificate-key 58b5069121358f791d0d14f97c391cd16b6337a3953289c7baccd1f0fe23ee41 --control-plane
加入成功后会出现下述提示
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
This node has joined the cluster and a new control plane instance was created:
* Certificate signing request was sent to apiserver and approval was received.
* The Kubelet was informed of the new secure connection details.
* Control plane label and taint were applied to the new node.
* The Kubernetes control plane instances scaled up.
* A new etcd member was added to the local/stacked etcd cluster.
To start administering your cluster from this node, 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
Run 'kubectl get nodes' to see this node join the cluster.
执行下述命令是以 worker 身份加入 worker 加入的时候不能写 –certificate-key,这个参数是给 master 用的
1
2
kubeadm join 172.16.1.100:6443 --token mrik2v.i6skqyc3zs89zkqd \
--discovery-token-ca-cert-hash sha256:6d51a002a7abdeeaff04ba988ba8271038a256809543713dca28d216c8832d15
加入成功后会出现下述提示
1
2
3
4
5
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.
配置 worker 节点
ubuntu-01 配置完之后,应该会输出类似于 kubeadm join <ip>:<port> --token xxx --discovery-token-ca-cert-hash xxx
的命令,如果忘记了,也可以在 ubuntu-01 重新显示:
1
kubeadm token create --print-join-command
将 master 节点的 /etc/kubernetes/admin.conf
配置文件拷贝到每个 worker,保持与 master 一致即可。
将 kubeadm join
输出的命令在 ubuntu-02 和 ubuntu-03 上执行一遍,这样 ubuntu-02 和 ubuntu-03 就会作为 worker 加入 ubuntu-01 集群。
将 ubuntu-02 和 ubuntu-03 作为 worker 加入之后,默认 ROLE 是空的,可以手动给它们加上 ROLE 字段,下面是修改 ROLES
字段的命令:
1
2
kubectl label node ubuntu-02 node-role.kubernetes.io/worker=worker
kubectl label node ubuntu-03 node-role.kubernetes.io/worker=worker
查看当前集群所有的 node:
1
2
3
4
5
❯ kubectl get nodes -o wide -A
NAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME
ubuntu-01 Ready control-plane 22h v1.30.1 172.16.1.101 <none> Ubuntu 22.04.4 LTS 6.5.0-35-generic containerd://1.6.32
ubuntu-02 Ready worker 22h v1.30.1 172.16.1.102 <none> Ubuntu 22.04.4 LTS 6.5.0-35-generic containerd://1.6.32
ubuntu-03 Ready worker 22h v1.30.1 172.16.1.103 <none> Ubuntu 22.04.4 LTS 6.5.0-35-generic containerd://1.6.32
至此 k8s 集群创建完毕,结合之前的组网教程,可以远程在 Mac 上访问家庭内的 k8s 集群了,当然,Mac 上复制该集群的访问配置文件是必不可少的🌵。