Featured image of post K8s 生产二进制集群前置:节点规划与 Linux 系统调优

K8s 生产二进制集群前置:节点规划与 Linux 系统调优

3 master + N worker 节点网络规划、端口段、Ubuntu 系统基础优化、内核参数与 IPVS 配置

写在前面

在 Kubernetes 1.6(2017 年)之前,社区主流的"高可用生产集群"基本是 3 master + N worker 手工二进制部署路线——比起 kubeadmin/kubeadm,手工二进制能完全掌控每个组件的 flag、证书路径和 systemd 单元,是国内大厂 2018-2022 年生产环境的标配方案。

本文是整个 K8s 二进制部署系列的前置篇,只讲集群起步:网络规划、服务器角色划分、Ubuntu 22.04 系统基础优化、IPVS/iptables 内核参数准备。不涉及任何 K8s 组件安装

适用版本:Kubernetes 1.28.5 / etcd 3.5.11 / Ubuntu 22.04 server 集群规模:3 master(etcd + controlplane + nginx/keepalived)+ 10 worker


1. 集群网络与节点规划

1.1 角色划分

角色数量部署组件
master3etcd、kube-apiserver、kube-controller-manager、kube-scheduler、kubelet、kube-proxy、nginx、keepalived
workerNkubelet、kube-proxy、容器运行时
VIP2一个内网用,一个公网用,keepalived 漂移

1.2 IP 与 VIP 段(示例拓扑)

网段用途说明
<node-network>节点操作系统网段物理网络,所有节点 IP 都在此
10.96.0.0/12Service 网段kube-apiserver 默认 --service-cluster-ip-range
10.96.0.10CoreDNS Service IPkube-dns 固定 IP
172.218.0.0/12Pod 网络kube-controller-manager 的 --cluster-cidr
<vip-internal>内网 VIP漂移在 master1 / master2
<vip-public>公网映射 VIP漂移在 master1 / master2

Service 段、Pod 段在生产中可以按需调整,前提是所有节点路由可达

1.3 NodePort 端口范围

K8s 默认 Service NodePort 范围是 30000-32767,如果需要在前面用 Nginx 4 层反代 NodePort,必须在 kube-apiserver 启动参数里显式声明:

1
--service-node-port-range=30000-32767

修改 /etc/systemd/system/kube-apiserver.service 后:

1
2
systemctl daemon-reload
systemctl restart kube-apiserver.service

1.4 主机名与 hosts

1
2
3
4
# 三个 master 设置 hostname
hostnamectl set-hostname master1   # 内网示例:<node-ip> 节点
hostnamectl set-hostname master2
hostnamectl set-hostname master3

所有节点配置 /etc/hosts(内网 IP 替换为实际值):

1
2
3
4
5
6
7
cat << "EOF" >> /etc/hosts
<node-ip> master1
<node-ip> master2
<node-ip> master3
<node-ip> worker1
<node-ip> worker2
EOF

注意:内网 IP 已用占位符 <node-ip> 替代;实际操作时换成你集群的真实 IP。


2. 安装文件清单

在 master1 上准备好所有需要分发的二进制包(典型命名):

文件用途
docker-24.0.7.tgzDocker 静态二进制包
cri-dockerd-0.3.9.amd64.tgzcri-dockerd(K8s 1.24+ 不再内置 dockershim)
nginx-1.24.0.tar.gznginx 源码(编译 --with-stream
keepalived-2.2.8.tar.gzkeepalived 源码
etcd-v3.5.11-linux-amd64.tar.gzetcd 二进制
kubernetes-server-linux-amd64.tar.gzK8s 1.28.5 服务端二进制
cfssl_1.6.4_linux_amd64证书签发工具
cfssljson_1.6.4_linux_amd64证书 JSON 化工具
cfssl-certinfo_1.6.4_linux_amd64证书查看工具
helm-v3.13.3-linux-amd64.tar.gzHelm 包管理
coredns-1.29.0.tgzCoreDNS chart(DNS 插件)

3. 目录约定

每台机器统一下列目录结构,方便后面所有组件统一路径:

 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
# 系统服务目录
mkdir -p /etc/systemd/system

# 二进制目录
mkdir -p /usr/local/bin

# 所有节点安装包路径
mkdir -p /data/softs

# 所有节点 k8s 配置目录
mkdir -p /data/k8scnf

# 所有节点的 k8s 证书目录
mkdir -p /etc/kubernetes/pki

# 所有节点 k8s 运行目录
mkdir -p /etc/kubernetes/manifests/
mkdir -p /etc/systemd/system/kubelet.service.d
mkdir -p /var/lib/kubelet
mkdir -p /var/log/kubernetes

# 所有节点 docker 配置目录
mkdir -p /etc/docker

# 所有 master etcd 证书目录
mkdir -p /etc/etcd/ssl

# master1, master2 的 nginx 目录
mkdir -p /usr/local/nginx/conf/{conf.d,stream}
mkdir -p /usr/local/keepalived/conf

4. 节点免密登录(master1 推送前置)

master1 上一键推送 SSH 公钥到其他节点(密码用占位符):

1
2
3
4
5
6
apt install -y sshpass
ssh-keygen -f /root/.ssh/id_rsa -P ''

for HOST in master2 master3 worker1 worker2 worker3 worker4 worker5 worker6 worker7 worker8 worker9; do \
  sshpass -p "{{SSH_PASSWORD}}" ssh-copy-id -o StrictHostKeyChecking=no $HOST; \
done

非 22 端口的节点:

1
ssh-copy-id -i ~/.ssh/id_rsa.pub "-p 10022 user@server"

文件批量推送到其他 master:

1
for HOST in master2 master3; do scp -r /data/softs $HOST:/data; done

5. Ubuntu 22.04 源切换

为了避免 apt install 卡顿,所有节点切到清华源(或其他国内源):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
mv /etc/apt/sources.list /etc/apt/sources.listbak

cat > /etc/apt/sources.list << "EOF"
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-updates main restricted universe multiverse
deb https://mirrors.tuna.tsinghua.edu.cn/ubuntu/ jammy-backports main restricted universe multiverse
deb http://security.ubuntu.com/ubuntu/ jammy-security main restricted universe multiverse
EOF

apt update

6. 系统基础优化

6.1 禁用 swap

K8s 1.20+ 仍要求关闭 swap(kubelet 默认 failSwapOn: true):

1
2
3
4
free -m
swapoff -a
sed -ri 's/.*swap.*/#&/' /etc/fstab
cat /etc/fstab

6.2 关闭防火墙

1
2
3
sudo systemctl stop ufw
sudo systemctl disable ufw
systemctl status ufw   # 状态应为 inactive (dead)

6.3 关闭 systemd-resolved(关键)

Ubuntu 22.04 默认的 systemd-resolved 占用 53 端口,导致 CoreDNS 装不上

1
2
3
4
5
sudo apt install -y unbound
sudo systemctl stop systemd-resolved
sudo systemctl disable systemd-resolved
sudo rm -rf /etc/resolv.conf
sudo touch /etc/resolv.conf

6.4 时间同步

1
2
3
4
5
6
7
8
9
timedatectl status                  # System clock synchronized 必须是 yes
timedatectl set-timezone Asia/Shanghai
apt install -y ntpdate
ntpdate time1.aliyun.com

# 定时同步
crontab -e
*/5 * * * * ntpdate time1.aliyun.com
crontab -l

常见报错Waiting for cache lock: Could not get lock /var/lib/dpkg/lock-frontend 解决:用 lsof /var/lib/dpkg/lock-frontend 查到占用 PID 后 kill -9 杀掉。

6.5 ulimit 与文件描述符

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
ulimit -SHn 65535

cat >> /etc/security/limits.conf << "EOF"
* soft nofile 655360
* hard nofile 131072
* soft nproc 655350
* hard nproc 655350
* soft memlock unlimited
* hard memlock unlimited
EOF

6.6 内核升级

K8s 1.28 要求内核 ≥ 4.18,Ubuntu 22.04 默认 5.15 满足,无需额外升级。

1
2
uname -r
# 5.15.0-91-generic 满足

7. IPVS 与内核网络参数

K8s kube-proxy 的 IPVS 模式比 iptables 模式在大规模集群下性能更好:

7.1 安装 IPVS

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
apt install -y ipvsadm ipset sysstat conntrack

cat >> /etc/modules-load.d/ipvs.conf << "EOF"
ip_vs
ip_vs_rr
ip_vs_wrr
ip_vs_sh
nf_conntrack
ip_tables
ip_set
xt_set
ipt_set
ipt_rpfilter
ipt_REJECT
ipip
EOF

systemctl restart systemd-modules-load.service
lsmod | grep -e ip_vs -e nf_conntrack

7.2 sysctl 优化

 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
cat << "EOF" > /etc/sysctl.d/k8s.conf
net.ipv4.ip_forward = 1
net.bridge.bridge-nf-call-iptables = 1
fs.may_detach_mounts = 1
vm.overcommit_memory = 1
vm.panic_on_oom = 0
fs.inotify.max_user_watches = 89100
fs.file-max = 52706963
fs.nr_open = 52706963
net.netfilter.nf_conntrack_max = 2310720

net.ipv4.tcp_keepalive_time = 600
net.ipv4.tcp_keepalive_probes = 3
net.ipv4.tcp_keepalive_intvl = 15
net.ipv4.tcp_max_tw_buckets = 36000
net.ipv4.tcp_tw_reuse = 1
net.ipv4.tcp_max_orphans = 327680
net.ipv4.tcp_orphan_retries = 3
net.ipv4.tcp_syncookies = 1
net.ipv4.tcp_max_syn_backlog = 16384
net.ipv4.ip_conntrack_max = 65536
net.ipv4.tcp_timestamps = 0
net.core.somaxconn = 16384
EOF

sysctl --system

8. 排错速查

现象原因解决
aptdpkg lock-frontend后台 unattended-upgrade 占用lsof /var/lib/dpkg/lock-frontendkill -9 PID
CoreDNS Pod 一直 CrashLoopBackOffsystemd-resolved 占用 53关闭 systemd-resolved,见 6.3
kubelet 启动失败 failSwapOnswap 未关swapoff -a + /etc/fstab 注释
NodePort 配 80 端口启动失败不在 30000-32767 范围kube-apiserver 加 --service-node-port-range
节点 NotReady路由转发未开net.ipv4.ip_forward = 1

9. 小结

集群前置看似都是"复制粘贴"的体力活,但每一步都是后面所有组件能起来的前提。最容易踩的坑是

  1. systemd-resolved 没关 → CoreDNS 起不来
  2. swap 没禁 → kubelet 直接 failSwapOn 拒绝启动
  3. 防火墙没关 → 跨节点 Service 不通
  4. 时间不同步 → 证书签名失败、etcd 集群脑裂

下一步:容器运行时:Docker + cri-dockerd 二进制部署实战


前置知识 / 下一步

  • 前置:了解 Linux 基础(systemd、apt、sysctl)
  • 本篇:所有 master/worker 节点一致的系统基线
  • 下一步:在所有节点上部署容器运行时(Docker 24 + cri-dockerd)
使用 Hugo 构建
主题 StackJimmy 设计