节点规划

一个最小可用的 K8s 集群至少需要 1 个 master + 1 个 worker,生产环境推荐至少 3 master + 2 worker。

角色        主机名             IP                内存 / CPU 最低
master     k8s-master01     192.168.66.10     2C / 2G
worker     k8s-node01       192.168.66.20     1C / 1G
worker     k8s-node02       192.168.66.21     1C / 1G

所有节点:

  • Linux 内核 ≥ 5.4(Ubuntu 22.04 / Debian 12 / RHEL 9 任选)
  • 关闭 swap(K8s 要求)
  • 关闭防火墙(或者放通 6443、10250、8472 等关键端口)
  • 关闭 SELinux(RHEL 系)或设 permissive

系统调优(所有节点)

主机名解析:

hostnamectl set-hostname k8s-master01   # 每台机器不同

cat >> /etc/hosts <<EOF
192.168.66.10 k8s-master01
192.168.66.20 k8s-node01
192.168.66.21 k8s-node02
EOF

关 swap:

swapoff -a
sed -i '/ swap / s/^/#/' /etc/fstab

内核参数:

cat > /etc/modules-load.d/k8s.conf <<EOF
br_netfilter
EOF
modprobe br_netfilter

cat > /etc/sysctl.d/k8s.conf <<EOF
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF
sysctl --system
原 Memo 中的 tcp_tw_recycle 在新内核已废弃,移除掉。同理,K8s 1.24+ 已经移除 dockershim,下面用 containerd。

容器运行时:containerd

安装 containerd(K8s 1.27 推荐):

apt update
apt install -y containerd

mkdir -p /etc/containerd
containerd config default > /etc/containerd/config.toml

# 改 cgroup driver 与 systemd 一致
sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

systemctl restart containerd
systemctl enable containerd

安装 kubeadm / kubelet / kubectl

用阿里云镜像源(国内可达):

apt update && apt install -y apt-transport-https ca-certificates curl

curl -fsSL https://mirrors.aliyun.com/kubernetes/apt/doc/apt-key.gpg | gpg --dearmor -o /etc/apt/keyrings/kubernetes-apt-keyring.gpg

echo 'deb [signed-by=/etc/apt/keyrings/kubernetes-apt-keyring.gpg] https://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main' \
  > /etc/apt/sources.list.d/kubernetes.list

apt update
apt install -y kubelet=1.27.10-1.1 kubeadm=1.27.10-1.1 kubectl=1.27.10-1.1
apt-mark hold kubelet kubeadm kubectl

systemctl enable kubelet

master 节点初始化

kubeadm init \
  --kubernetes-version=1.27.10 \
  --apiserver-advertise-address=192.168.66.10 \
  --image-repository registry.aliyuncs.com/google_containers \
  --service-cidr=10.96.0.0/12 \
  --pod-network-cidr=10.244.0.0/16 \
  --cri-socket=unix:///run/containerd/containerd.sock

几个参数含义:

  • apiserver-advertise-address:master 自己的 IP
  • image-repository:拉镜像的源(国内改阿里云避免 GFW)
  • service-cidr:Service IP 段
  • pod-network-cidr:Pod IP 段,要与下面 Flannel 的网段一致

初始化完成后按提示配置 kubectl:

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

worker 加入集群

master 上生成 join 命令(24 小时内有效):

kubeadm token create --print-join-command

worker 节点上运行打印出的命令,类似:

kubeadm join 192.168.66.10:6443 --token <TOKEN> \
  --discovery-token-ca-cert-hash sha256:<HASH>

网络插件:Flannel

Flannel 简单稳定,适合学习环境。Calico 功能更强(NetworkPolicy),生产推荐。

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

检查:

kubectl get pods -n kube-flannel
# NAME                    READY   STATUS    RESTARTS   AGE
# kube-flannel-ds-xxx     1/1     Running   0          30s
# kube-flannel-ds-yyy     1/1     Running   0          30s
# kube-flannel-ds-zzz     1/1     Running   0          30s

验证

kubectl get nodes
# NAME            STATUS   ROLES           AGE   VERSION
# k8s-master01    Ready    control-plane   5m    v1.27.10
# k8s-node01      Ready    <none>          2m    v1.27.10
# k8s-node02      Ready    <none>          2m    v1.27.10

# 起一个 nginx 测试
kubectl create deploy nginx --image=nginx:1.25 --replicas=3
kubectl expose deploy nginx --port=80 --target-port=80 --type=NodePort
kubectl get pods -o wide
kubectl get svc nginx

如果 Pod 都 Running,集群就绪。

kubectl 速记

kubectl get pods -A                           # 所有命名空间
kubectl describe pod <name> -n <ns>            # 排错
kubectl logs <pod> -f                         # 看日志
kubectl exec -it <pod> -- bash                # 进容器
kubectl scale deploy <name> --replicas=5     # 扩缩
kubectl set image deploy/<name> <ctr>=<img>  # 滚动更新
kubectl rollout undo deploy/<name>            # 回滚
kubectl delete all -l app=<label>             # 按 label 删除

使用准则

  1. 生产环境 kubeadm init 时给 --control-plane-endpoint,便于 master HA。
  2. 不要跳过 --cri-socket,kubeadm 1.27 默认会试 dockershim。
  3. 镜像源国内一定要换阿里云,否则 kubeadm init 卡住。
  4. worker 加入前先在 master 端确认 token 没过期。
  5. 升级前看 Kubernetes 升级偏差策略。
参考资料