4、Kubernetes集群部署:K8s架构理解、kubeadm搭建集群、部署Dashboard、Pod与Service管理

好,咱们进入第四章节。说实话,Kubernetes 这块内容,是低代码平台能否真正扛住生产压力的分水岭。很多同学在单机 Docker 上跑得挺欢,一上集群就各种翻车。我当年第一次部署 K8s 集群时,也是踩了不少坑,今天就把这些经验掰开揉碎讲给你听。

4.1 先搞懂 K8s 架构:别急着动手

很多人一上来就敲命令,结果出了问题完全不知道从哪查。我个人习惯是,先花半小时把架构图看明白。

Kubernetes 说白了就两大块:控制平面工作节点

  • 控制平面(Master):集群的大脑。包含 API Server、Scheduler、Controller Manager、etcd。API Server 是唯一入口,你所有操作都得经过它。
  • 工作节点(Node):真正跑容器的地方。每个节点上有 kubelet、kube-proxy、容器运行时(比如 containerd)。

为什么会这样设计?你想想看,如果每个节点都能直接改集群状态,那不乱套了?所以所有变更必须经过 API Server,它负责鉴权、校验,然后写入 etcd。Scheduler 负责把 Pod 分配到合适的节点上。Controller Manager 则像个监工,确保集群状态跟你期望的一致。

核心要点:etcd 是集群的"数据库",存着所有状态。如果 etcd 挂了,整个集群就瞎了。我在生产环境遇到过 etcd 磁盘写满导致集群只读的故障,那叫一个酸爽。

4.2 用 kubeadm 搭建集群:我推荐的方式

搭建 K8s 集群的方式有好几种,kubeadm、二进制部署、minikube 等等。对于生产环境,我强烈推荐 kubeadm。它帮你把很多繁琐的证书生成、组件配置都自动化了,但又不是黑盒,出了问题你能知道去哪查。

下面是我总结的标准化步骤,你照着做基本不会出错:

4.2.1 环境准备

我建议至少准备 3 台机器(1 个 Master + 2 个 Node)。系统用 Ubuntu 20.04 或 CentOS 7.9 都行。每台机器都要做:

# 关闭 swap(K8s 要求必须关)
sudo swapoff -a
sudo sed -i '/ swap / s/^\(.*\)$/#\1/g' /etc/fstab

# 开启内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF

sudo modprobe overlay
sudo modprobe br_netfilter

# 设置 sysctl 参数
cat <<EOF | sudo tee /etc/sysctl.d/k8s.conf
net.bridge.bridge-nf-call-iptables  = 1
net.bridge.bridge-nf-call-ip6tables = 1
net.ipv4.ip_forward                 = 1
EOF

sudo sysctl --system

避坑指南:我曾经因为忘记关 swap,结果 kubelet 启动不起来,日志里报错说"running with swap on is not supported"。嗯,这个坑我替你们踩过了。

4.2.2 安装容器运行时

K8s 从 1.24 版本开始移除了对 Docker 的直接支持,推荐用 containerd。我个人习惯用 containerd,性能更好,也更轻量。

# 安装 containerd
sudo apt-get update
sudo apt-get install -y containerd

# 生成默认配置
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml

# 修改配置,使用 systemd cgroup 驱动
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml

sudo systemctl restart containerd
sudo systemctl enable containerd

4.2.3 安装 kubeadm、kubelet、kubectl

# 添加 K8s 源
sudo apt-get update
sudo apt-get install -y apt-transport-https ca-certificates curl
curl -fsSL https://packages.cloud.google.com/apt/doc/apt-key.gpg | sudo gpg --dearmor -o /etc/apt/keyrings/kubernetes-archive-keyring.gpg
echo "deb [signed-by=/etc/apt/keyrings/kubernetes-archive-keyring.gpg] https://apt.kubernetes.io/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list

# 安装指定版本(我建议用稳定版,比如 1.28)
sudo apt-get update
sudo apt-get install -y kubelet=1.28.0-00 kubeadm=1.28.0-00 kubectl=1.28.0-00
sudo apt-mark hold kubelet kubeadm kubectl

4.2.4 初始化 Master 节点

这一步是关键。在 Master 机器上执行:

sudo kubeadm init \
  --apiserver-advertise-address=192.168.1.100 \
  --pod-network-cidr=10.244.0.0/16 \
  --kubernetes-version=1.28.0

初始化成功后,会输出一段 kubeadm join 命令,记得保存好,那是 Worker 节点加入集群的凭证。

注意:--pod-network-cidr 必须跟你后面要安装的网络插件一致。我用 Flannel 时用的 10.244.0.0/16,如果你用 Calico,可能是 192.168.0.0/16。这个搞错了,Pod 之间通信会出问题。

4.2.5 配置 kubectl

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

# 验证
kubectl get nodes

4.2.6 安装网络插件

我推荐 Flannel,简单稳定:

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

4.2.7 Worker 节点加入

在每台 Worker 节点上执行刚才保存的 join 命令:

sudo kubeadm join 192.168.1.100:6443 --token xxxxx --discovery-token-ca-cert-hash sha256:xxxxx

等几分钟,在 Master 上执行 kubectl get nodes,应该能看到所有节点状态为 Ready。

4.3 部署 Dashboard:可视化运维

命令行虽然强大,但可视化界面在某些场景下更直观。我一般会给团队部署一个 Dashboard,方便非运维人员查看资源状态。

# 部署 Dashboard
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.7.0/aio/deploy/recommended.yaml

# 创建管理员用户
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: admin-user
  namespace: kubernetes-dashboard
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: admin-user
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: cluster-admin
subjects:
- kind: ServiceAccount
  name: admin-user
  namespace: kubernetes-dashboard
EOF

# 获取登录 token
kubectl -n kubernetes-dashboard create token admin-user

然后通过 kubectl proxy 访问:http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/

小技巧:我习惯用 NodePort 方式暴露 Dashboard,这样不用每次开 proxy。但生产环境记得加认证,别裸奔。

4.4 Pod 与 Service 管理:核心实操

集群搭好了,总得跑点东西吧?Pod 是 K8s 最小的调度单元,Service 则是稳定的网络入口。

4.4.1 创建第一个 Pod

我一般不用命令行直接创建 Pod,而是写 YAML 文件,方便版本管理。

# nginx-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:1.25
    ports:
    - containerPort: 80
kubectl apply -f nginx-pod.yaml
kubectl get pods -o wide

经验之谈:Pod 是"临时"的,如果节点挂了,Pod 不会自动恢复。所以生产环境我从来不用裸 Pod,而是用 Deployment 或 StatefulSet 来管理。

4.4.2 用 Deployment 管理 Pod

Deployment 能保证你期望的 Pod 数量始终满足。比如我要跑 3 个 Nginx:

# nginx-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.25
        ports:
        - containerPort: 80
kubectl apply -f nginx-deployment.yaml
kubectl get deployment
kubectl get pods

你会发现 Pod 名字后面带了一串随机字符,那是 Deployment 自动生成的。如果你删掉一个 Pod,Deployment 会立刻再起一个。

4.4.3 Service:让 Pod 可以被访问

Pod 的 IP 是动态的,重启就变了。Service 提供了一个固定的入口。我常用的有三种类型:

类型 说明 适用场景
ClusterIP 集群内部可访问 内部服务调用
NodePort 通过节点 IP + 端口访问 测试环境、简单暴露
LoadBalancer 云厂商提供负载均衡器 生产环境对外暴露
# nginx-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80
  type: NodePort
kubectl apply -f nginx-service.yaml
kubectl get service

然后你就可以通过任意节点的 IP + NodePort 访问 Nginx 了。比如 http://192.168.1.101:30080

注意:NodePort 的端口范围是 30000-32767。我曾经在生产环境不小心用了 80 端口,结果 Service 创建失败,报错说"port out of range"。嗯,这个限制是硬性的。

4.5 本章小结

这一章内容不少,但都是实打实的干货。从架构理解到集群搭建,再到 Dashboard 和核心资源管理,每一步我都尽量把踩过的坑告诉你。你想想看,如果当初有人告诉我这些,我至少能少熬三个通宵。

下一章我们会深入讲存储和配置管理,到时候再聊。