Kubernetes 1.31核心架构与基础概念解析

Kubernetes 到现在已经成了容器编排领域的绝对霸主,换个角度看,现在的后端工程师要是不会点 K8s,出门都不好意思跟人打招呼。咱们这篇文章就基于目前最新的稳定版 Kubernetes 1.31(2024年8月刚发布)来聊,这个版本保持了 K8s 一贯的 4 个月一个迭代周期的节奏,稳定性没得说。

很多新手一上来就被 Master 节点、Worker 节点、API Server 这些词给整懵了。咱们换个思路,把 K8s 集群想象成一个厨房

控制平面(Control Plane):大厨的大脑

控制平面就是厨房的大厨,负责决策。它跑在 Master 节点上,核心组件都在这里:

工作节点(Worker Node):干活的灶台

灶台就是真正干活的地方,也就是我们的服务器。上面跑着两个关键东西:

核心资源对象

在 K8s 里,我们不直接操作容器,而是操作“对象”。

典型场景与趋势

现在很多公司在搞微服务架构,把大单体拆成小服务,用 K8s 管理这些服务的生命周期简直是绝配。另外,AI 训练也是 K8s 的大热门,特别是 2024 年这个节点,K8s 对 GPU 资源的调度越来越强,跑 TensorFlow 或者 PyTorch 的分布式训练任务特别合适。

🔧 实战技巧:

刚入门别去折腾二进制安装,直接上 Minikube 或者 Kind。Minikube 是在本地起一个单节点的 K8s 虚拟机,非常适合开发测试。除非你是做运维的,否则没必要在初期死磕集群搭建,那样只会消磨你的耐心。

从零搭建:kubectl配置与Pod调度实战

既然咱们聊的是实战,那第一步肯定得把环境整起来。虽然最新的 K8s 1.31 刚出,但咱们本地开发用 Kind (Kubernetes in Docker) 是最快的,它不需要你装一堆虚拟机,直接利用 Docker 容器模拟节点,特别轻量。

环境准备与 kubectl 配置

首先你得有个 Docker 环境。然后安装 Kind 和 kubectl。

如果你用的是 Mac,直接用 brew:

`bash

brew install kubectl

`

Windows 用户可以用 Chocolatey 或者去 Kubernetes 官方 GitHub Release 页下载二进制文件。

咱们直接创建一个基于 K8s 1.31 的集群(如果 Kind 的镜像支持的话,或者指定最新的稳定版)。

`bash

# 安装 Kind

brew install kind

# 创建一个集群

kind create cluster --name my-k8s-demo

`

这一步会自动把配置写入你本地的 ~/.kube/config 文件。打个比方,这个文件就是你的通行证,kubectl 读取这个文件就知道该去连哪个集群了。

运行下面的命令,看看能不能拿到节点信息:

`bash

kubectl cluster-info

kubectl get nodes

`

如果看到 my-k8s-demo-control-plane 处于 Ready 状态,恭喜你,环境搞定了。

Pod 调度实战

光有环境不行,咱们得跑点东西。很多人以为直接写个 Pod 文件就完事了,其实在生产环境,我们很少直接裸跑 Pod,因为 Pod 挂了就没了。但为了理解调度,咱们先看看 Pod 是怎么被分配到节点上的。

咱们写一个最简单的 Nginx Pod 定义文件 nginx-pod.yaml

apiVersion: v1 kind: Pod metadata: name: nginx-demo 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 被调度到了 my-k8s-demo-control-plane 这个节点上。

调度策略:亲和性与污点

K8s 的调度器(Scheduler)很聪明,但有时候我们需要手动干预。比如,我想让数据库跑在有 SSD 的机器上,或者不想让普通的 Web 服务跑在 Master 节点上。

这就涉及到了污点(Taints)容忍(Tolerations)。Master 节点默认是有污点的,意思是“我很高贵,一般的 Pod 别来烦我”。

咱们试着给 Pod 加个容忍度,让它也能跑在 Master 上(虽然通常不推荐,但咱们为了演示):

apiVersion: v1 kind: Pod metadata: name: nginx-tolerate-master spec: tolerations: - key: "node-role.kubernetes.io/control-plane" operator: "Exists" effect: "NoSchedule" containers: - name: nginx image: nginx:1.25

⚡ 效率提示:

在本地用 Kind 或者 Minikube 的时候,经常遇到镜像拉取失败的问题(ImagePullBackOff)。核心要点:如果你用的是私有镜像或者网络不好,记得先 docker pull 把镜像拉下来,然后 Kind 支持直接把本地镜像加载进去:kind load docker-image nginx:1.25 --name my-k8s-demo,这样部署速度飞快,还能避开网络限制的坑。

手把手实战:Deployment微服务部署与Service暴露

上一章咱们跑了裸 Pod,但在真实项目里,那简直是自杀行为。想象一下,你的服务挂了,你得手动去重启;你想更新代码,得手动删掉旧的再建新的。这谁受得了?所以,咱们必须请出 Deployment

为什么要用 Deployment?

Deployment 是 K8s 里管理无状态应用的核心。它不仅能帮你维持指定数量的 Pod 副本(比如你定义 3 个,它哪怕死了一个也会给你拉起一个新的),还支持滚动更新

换个角度看,Deployment 就是个“监护人”。它下面管着 ReplicaSet(副本集),ReplicaSet 再管着具体的 Pod。这种层级结构保证了应用的高可用性。

实战:部署一个 Go 微服务

假设我们有一个简单的 Go 微服务,镜像名叫 my-go-app:v1。咱们写一个 deployment.yaml

apiVersion: apps/v1 kind: Deployment metadata: name: go-microservice labels: app: go-microservice spec: # 副本数,也就是要跑几个实例 replicas: 3 selector: matchLabels: app: go-microservice template: metadata: labels: app: go-microservice spec: containers: - name: app image: my-go-app:v1 ports: - containerPort: 8080 # 健康检查很重要,K8s 靠这个判断容器是否存活 livenessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 10 periodSeconds: 5 resources: requests: memory: "64Mi" cpu: "250m" limits: memory: "128Mi" cpu: "500m"

运行部署:

kubectl apply -f deployment.yaml kubectl get deployments kubectl get pods

你会看到 3 个 Pod 在启动。

暴露服务:Service 的几种类型

Pod 有了,但是它们的 IP 是集群内部的,外网访问不到,Pod 之间互相访问也不方便。这时候就需要 Service 了。

K8s 的 Service 有几种类型,咱们得根据场景选:

咱们这里为了演示,用 NodePort 暴露服务,创建一个 service.yaml

apiVersion: v1 kind: Service metadata: name: go-service spec: # 注意这里没有缩进问题,是顶格的 selector: app: go-microservice ports: - protocol: TCP port: 80 targetPort: 8080 type: NodePort

部署并查看:

kubectl apply -f service.yaml kubectl get svc go-service

你会看到一个 PORT(S) 列,显示类似 80:31234/TCP。这时候你可以通过 localhost:31234(如果是本地 Kind 集群,可能需要额外端口映射,或者直接用 kubectl port-forward)来访问服务。

滚动更新与回滚

咱们把镜像升级到 v2:

kubectl set image deployment/go-microservice app=my-go-app:v2

这时候 K8s 会滚动更新,先起一个新的,再杀一个旧的,保证服务不中断。

如果 v2 有 Bug,想回滚?一行命令搞定:

kubectl rollout undo deployment/go-microservice

⚡ 效率提示:

写 YAML 文件的时候,千万别手写。强烈建议使用 Kustomize 或者 Helm。Kustomize 已经内置在 kubectl 里了,可以帮你管理不同环境(开发、测试、生产)的配置差异。另外,记得给容器加上 resources(资源限制),不限制 CPU 和内存的话,一个 Pod 跑飞了可能会把整个节点搞崩,这就是 K8s 的 QoS 机制在起作用,资源限制越明确,Pod 越不容易被驱逐。

进阶技巧:HPA自动扩缩容与Ingress流量路由

你的服务跑起来了,但这才刚开始。如果流量突然暴涨怎么办?人工盯着扩容肯定来不及。K8s 提供了 HPA(Horizontal Pod Autoscaler) 来解决这个问题。

HPA:让应用自动呼吸

HPA 个自动伸缩器。它会监控你的 Pod 指标(比如 CPU 使用率),如果超过了阈值,它就自动增加 replica(副本数);如果降下来了,它就自动缩容。

注意:HPA 依赖 Metrics Server 来收集指标。在 Kind 集群里,你可能需要手动安装它。

`bash

kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml

`

如果因为证书问题起不来,可能需要给 deployment 加个 --kubelet-insecure-tls 参数,这是本地测试常用的“实战经验”解决方案。

咱们给刚才的 go-microservice 配置一个 HPA,目标是 CPU 使用率超过 50% 就扩容,最多扩到 10 个副本。

创建一个 hpa.yaml

`yaml

apiVersion: autoscaling/v2

kind: HorizontalPodAutoscaler

metadata:

name: go-hpa

spec:

scaleTargetRef:

apiVersion: apps/v1

kind: Deployment

name: go-microservice

minReplicas: 1

maxReplicas: 10

metrics:

- type: Resource

resource:

name: cpu

target:

type: Utilization

averageUtilization: 50

`

应用它:

`bash

kubectl apply -f hpa.yaml

kubectl get hpa

`

现在你可以用压测工具(比如 abhey)去打你的服务,观察 Pod 数量的变化:

`bash

kubectl get pods -w

`

Ingress:统一的流量入口

虽然我们之前用了 NodePort,但在生产环境,你不可能给每个微服务都开一个 NodePort。我们需要一个统一的入口,这就是 Ingress

Ingress 是 K8s 的七层负载均衡(HTTP/HTTPS)。它根据域名和路径把流量转发到不同的 Service。

最新趋势:现在社区里 Gateway API 很火,被认为是下一代的 Ingress 标准,功能更强大。但 Ingress 目前依然是主流,咱们先搞定它。

要用 Ingress,你得先有个 Ingress Controller。Kind 里可以用 Nginx Ingress Controller。

`bash

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/kind/deploy.yaml

`

假设我们想通过 demo.local 这个域名访问我们的服务。

创建 ingress.yaml

`yaml

apiVersion: networking.k8s.io/v1

kind: Ingress

metadata:

name: demo-ingress

annotations:

nginx.ingress.kubernetes.io/rewrite-target: /

spec:

ingressClassName: nginx

rules:

- host: demo.local

http:

paths:

- path: /

pathType: Prefix

backend:

service:

name: go-service

port:

number: 80

`

部署后,修改你本地的 /etc/hosts 文件,把 demo.local 指向你的集群节点 IP(如果是 Kind,通常指向 127.0.0.1 或者配合 port-forward 使用)。

然后访问:

`bash

curl http://demo.local

`

进阶视野:eBPF 与 Cilium

在 2024 年的 K8s 生态里,传统的网络方案(像 Flannel)正在被基于 eBPF 的技术取代,比如 Cilium。Cilium 利用 Linux 内核的新特性,让网络性能更好,安全性更高。如果你在搭建新集群,可以关注一下 Cilium 作为 CNI 插件的方案,这绝对是未来的主流方向。

💡 经验总结:

调试 HPA 和 Ingress 的时候,最头疼的是不知道为什么没生效。

5. CI/CD集成:Jenkins与GitOps声明式交付实践

可以这么理解,咱们写代码的最终目的还是为了上线跑起来。在 Kubernetes 这么一个复杂的集群环境里,你要是还靠手动敲 kubectl apply,那迟早得累死或者背锅背死。现在的主流玩法就是 CI/CD,而且最近社区里吵得火热的 GitOps 已经是事实上的标准了。

咱们先聊聊老牌劲旅 Jenkins。虽然现在都说 Jenkins 有点"老"了,但在很多公司里它依然是主力。结合 Kubernetes 1.31 这种新版本,我们通常会用 Jenkins 的 Kubernetes Plugin 来动态生成 Slave Pod。这意味着你跑构建任务的时候,K8s 才会临时起一个 Pod,跑完就销毁,资源利用率杠杠的。

不过,作为混迹圈内 5 年的开发者,我更推荐你关注 GitOps。这玩玩意儿的核心思想就是:Git 仓库里的状态就是真理。你不需要在 Jenkins 里写一堆复杂的脚本去调 K8s API,而是让一个控制器(Controller)去盯着你的 Git 仓库。目前社区里最火的两个工具就是 Argo CDFlux CD。根据 2024 年的社区讨论热度,Argo CD 的 UI 界面更友好,上手更快,而 Flux CD 更偏向于云原生底层一些。

咱们直接上实战,看看怎么用 Argo CD 实现声明式交付。

假设你已经有一个K8s集群(1.31版本也没问题,向下兼容很好),先装 Argo CD:

kubectl create namespace argocd kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml

装完后,咱们得有个应用配置。这里我写一个简单的 Application 资源定义。这就相当于告诉 Argo CD:嘿,去那个 Git 仓库把那个文件夹里的配置给我同步过来。

# application.yaml apiVersion: argoproj.io/v1alpha1 kind: Application metadata: name: guestbook namespace: argocd spec: project: default source: repoURL: https://github.com/argoproj/argocd-example-apps.git targetRevision: HEAD path: guestbook destination: server: https://kubernetes.default.svc namespace: default syncPolicy: automated: prune: true selfHeal: true

💡 经验总结:这里值得留意的是,,selfHeal: true 这个配置非常关键。简单来说,就是防止有人手贱去集群里手动改配置。只要 Git 里没改,Argo CD 发现集群状态和 Git 不一致,就会自动把它改回来,这叫"自我修复",跟 K8s 本身的机制异曲同工。

对比一下 Jenkins 的传统流水线(Pipeline)和 GitOps:

现在大家都在搞 平台工程(Platform Engineering),很多团队基于 K8s 构建内部开发者平台(IDP),GitOps 就是这块的基石。你只需要把 YAML 丢进 Git,剩下的交给平台,这才是极致的开发体验。

另外,实际案例经验之谈:如果你用的是 Jenkins 且集成了 Docker 构建,记得现在 K8s 早就弃用 Dockershim 了。别再折腾 Docker in Docker (DinD) 了,直接上 kaniko 或者 buildah 在 Pod 里构建镜像,这才是正道。

---

6. :Pod驱逐机制与CNI插件选型对比

做运维或者开发,最怕半夜报警说服务挂了。很多时候不是你代码崩了,而是 K8s 在"清理门户"。这一章节咱们聊聊两个容易让人懵圈的话题:Pod 驱逐和 CNI 选型。

先说 Pod 驱逐(Eviction)。可以这么理解,这事儿是 kubelet 干的。当你的节点(Node)资源不够用了,比如磁盘快满了(DiskPressure)或者内存爆了(MemoryPressure),kubelet 为了保证节点不宕机,就会开始杀 Pod。

这里有个 QoS(服务质量)的等级问题,这也是常见面试问题。K8s 会优先杀掉那些"不重要"的 Pod。优先级大概是:

来个实际的配置例子,教你怎么保命。如果你有个核心应用,千万别像下面这样写:

# 反面教材:BestEffort 级别,随时可能被杀 apiVersion: v1 kind: Pod metadata: name: hungry-app spec: containers: - name: app image: nginx:latest # 故意不写 resources

你应该这样写,保证它是 Guaranteed

# 正面教材:Guaranteed 级别 apiVersion: v1 kind: Pod metadata: name: stable-app spec: containers: - name: app image: nginx:1.25 resources: requests: memory: "512Mi" cpu: "500m" limits: memory: "512Mi" cpu: "500m"

📌 要点提醒:一定要给关键的 Deployment 加上 resources 限制。别觉得设了 limits 就亏了,这其实是在保护你的 Pod,防止它因为节点资源不足被无情驱逐。

再聊聊 CNI 插件选型。CNI 就是负责给 Pod 分配 IP、打通网络的。现在市面上的插件太多了,新手直接看晕。根据 2024 年的趋势,eBPF 技术是个大热门,像 Cilium 这种基于 eBPF 的插件性能吊打传统插件。

咱们对比一下常见的几个:

这里有个简单的 Cilium 安装后查看状态的命令:

# 安装 Cilium CLI curl -L --remote-name-all https://github.com/cilium/cilium-cli/releases/latest/download/cilium-linux-amd64.tar.gz tar xzvf cilium-linux-amd64.tar.gz sudo mv cilium /usr/local/bin/ # 安装 Cilium 到 K8s 集群 cilium install # 检查状态 cilium status --wait

避雷经验预警:如果你是从 Docker 时代迁移过来的,记得 K8s 1.31 早就不支持 Dockershim 了。你得用 containerd 或者 CRI-O 作为运行时。有些 CNI(比如老版本的 Calico)跟 containerd 的适配如果不注意,会导致 Pod 一直 ContainerCreating,这时候去查 kubectl describe pod 里的事件,通常能看到是网络插件没起来。

另外,最近社区里还在吵 Gateway API 要替代传统的 Ingress。如果你在选型网络方案,选那些支持 Gateway API 的(比如 Cilium 或者 Istio),这样以后不用改代码就能平滑升级。

---

7. 总结与展望:AI融合与平台工程趋势

不知不觉咱们聊了这么多,从怎么部署一个应用,到怎么用 GitOps 自动化,再到怎么避坑。作为一个写了 5 年代码、踩了无数坑的全栈工程师,我想最后跟大家唠唠 Kubernetes 接下来的路怎么走。毕竟咱们学技术不能只盯着眼前的 YAML,得看看远方。

现在的 K8s 早已不是那个只能跑跑 Web 服务的工具了。根据目前的路线图,Kubernetes 1.31 之后的版本(发布周期大概是每 4 个月一个稳定版),正在往更深、更广的领域渗透。

首当其冲的就是 AI 与 K8s 的深度融合。以前跑 AI 训练任务,大家都是用裸机或者专门的调度系统。现在?全在往 K8s 上搬。为什么?因为 K8s 对 GPU、TPU 等异构资源的调度能力越来越强了。你现在可以用 K8s 很方便地管理 TensorFlow 或者 PyTorch 的分布式训练任务。比如,通过 Device Plugin 机制,你可以把特定的 GPU 卡分配给特定的 Pod,这在 2024-2026 年绝对是主流趋势。

# 在 K8s 中申请 GPU 资源的示例 apiVersion: v1 kind: Pod metadata: name: cuda-vector-add spec: restartPolicy: OnFailure containers: - name: cuda-vector-add image: registry.k8s.io/cuda-vector-add:v0.1 resources: limits: nvidia.com/gpu: 1 # 请求 1 个 GPU

💡 经验总结:如果你在做 AI 相关的平台,别再自己造轮子管 GPU 了,直接基于 K8s 的调度框架来。现在的调度器(如 Volcano)对批量任务的支持已经非常完善了。

第二个大趋势是 平台工程(Platform Engineering)。简单来说,就是不要让业务开发同学去直接面对复杂的 K8s YAML。我们这些搞基础架构的,要基于 K8s 构建一个 内部开发者平台(IDP)。就像咱们之前提到的 GitOps,开发只需要提交代码,平台自动帮你构建、部署、监控。K8s 作为底层的基石,提供了强大的编排能力,但上层的体验一定要做得像 Vercel 或者 Netlify 那样傻瓜化。

还有两个值得关注的点:

最后,咱们说回技术细节。现在 Serverless 也在往 K8s 上靠,Knative 这类框架越来越成熟。这意味着你以后写代码可能都不需要关心 Pod 了,只需要关心函数和流量,而 K8s 在底层帮你实现更细粒度的按需计费。

总之,K8s 已经成为了云原生的操作系统。不管你是做微服务、做 AI,还是做边缘计算,绕不开它。咱们作为开发者,与其焦虑,不如深入进去,把它的核心原理(比如调度、网络、存储)吃透,这才是应对变化最稳的姿势。