Kubernetes v1.31核心概念与架构解析(Elli版本更新)
简单来说,Kubernetes(咱们常叫它K8s)现在已经是容器编排界的绝对霸主了。如果你还没上手,那真的有点落后于时代了。就在2024年8月13日,K8s刚发布了最新的稳定版 v1.31,代号 "Elli"。作为一个跟了K8s好几年的老鸟,我得告诉你,这个版本虽然看起来只是数字上的迭代,但它依然保持了每4个月一个大版本的节奏(通常在奇数月发布),这说明社区活跃度极高,技术栈更新非常快。
咱们先聊聊它的核心架构。很多新手一上来就被Master节点、Worker节点搞晕,其实你把它想象成一个公司就很好理解了。
控制平面(Control Plane) 就是公司的董事会,负责发号施令:
- API Server:这是唯一的入口,所有操作都得经过它,就像公司的前台接待,所有的指令都得先递交给它。
- etcd:这是个分布式存储数据库,存着集群的所有配置和状态。打个比方,它就是公司的账本,记录着谁在哪个工位,谁在干什么。
- Scheduler:调度器。当你说“我要跑一个应用”,Scheduler就负责找个最合适的“工位”(Node)给这个应用。
- Controller Manager:控制器管理器。它负责维护集群的期望状态,比如你说要跑3个副本,它就会盯着,少了就补,多了就杀。
数据平面(Data Plane) 就是干活儿的员工(Worker节点):
- Kubelet:每个节点上的“监工”,负责按照API Server的指令,指挥本地的容器干活。
- Kube-proxy:负责网络转发,让流量能进能出。
在v1.31这个版本里,虽然移除Dockershim已经是过去式了(现在大家都用Containerd或CRI-O),但社区现在的热点在于平台工程和AI工作负载。现在的K8s不仅仅是跑跑Web应用,越来越多的AI训练任务(比如TensorFlow/PyTorch)都在往K8s上搬,因为它对GPU的调度已经做得非常丝滑了。
核心功能特性速览
K8s之所以火,是因为它解决了几个痛点:
- 自我修复:如果你的容器崩了,K8s会自动重启它。如果节点挂了,它会把上面的应用调度到其他健康的节点上。这就像有了自动替补队员,不用你半夜爬起来重启服务器。
- 服务发现与负载均衡:K8s给每个Pod分配一个IP,并通过Service提供稳定的访问入口。配合Ingress,你就能轻松实现七层流量分发。
- 自动化滚动更新与回滚:想更新应用?K8s可以做到一个一个替换旧版本,用户完全无感知。要是新版本有Bug,一键回滚,简直不要太爽。
- 存储编排:不管是云盘的AWS EBS,还是网络存储NFS,K8s都能自动挂载,不用你手动去服务器上挂载磁盘。
常见面试考点:Deployment 与 StatefulSet
这里划个重点,也是面试必问的:Deployment 和 StatefulSet 有啥区别?
- Deployment:适合无状态应用。比如你的Web后端,随便杀掉一个Pod,再启动一个新的,不带任何历史数据,照样干活。Pod名字是随机的(比如
web-7c9d8c4f5-abcde)。
- StatefulSet:适合有状态应用。比如数据库MySQL、Redis集群。它要求Pod有固定的网络标识和持久化存储。Pod名字是有序的(比如
mysql-0, mysql-1)。
# 这是一个最基础的 Pod 定义示例,感受一下结构
apiVersion: v1
kind: Pod
metadata:
name: nginx-demo
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25
ports:
- containerPort: 80
🔧 实战技巧:刚开始学,别纠结那些复杂的概念。先把 Pod 当成K8s里最小的“豌豆”(运行容器的基本单位),把 Deployment 当成管理这些豌豆的“豌豆荚”。 只要理解了“期望状态”这个词——你告诉K8s你想要什么(比如3个Nginx),K8s就拼命去实现它——你就理解了一半。
从零搭建K8s集群:Containerd运行时与kubeadm实战
既然要实战,咱们就得动真格的。现在都2024年了,千万别再去折腾Docker作为运行时了,Dockershim早就被移除了。现在的绝对主流是 Containerd。咱们就用 Kubernetes v1.31 配合 Containerd,手把手带你用 kubeadm 搭一个集群。
环境准备,我假设你有两台干净的 Ubuntu 22.04 或者 CentOS 8+ 的机器(一台Master,一台Worker,内存建议2G以上,CPU 2核)。
第一步:系统环境配置
先在所有节点上关闭防火墙和swap。K8s很讨厌swap,它希望完全控制内存,不希望系统把内存交换到磁盘去,那样性能不可控。
# 临时关闭 swap
sudo swapoff -a
# 永久关闭,编辑 /etc/fstab,把swap那一行注释掉(如果需要)
# 加载内核模块
cat <<EOF | sudo tee /etc/modules-load.d/k8s.conf
overlay
br_netfilter
EOF
sudo modprobe overlay
sudo modprobe br_netfilter
# 设置网络参数
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
第二步:安装 Containerd
这是最关键的一步。咱们安装 Containerd 并生成默认配置。
# 安装依赖
sudo apt-get update && sudo apt-get install -y ca-certificates curl gnupg
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 安装 containerd
sudo apt-get update && sudo apt-get install -y containerd.io
# 生成默认配置
sudo mkdir -p /etc/containerd
containerd config default | sudo tee /etc/containerd/config.toml
# 必须开启 SystemdCgroup,否则 kubeadm 初始化会报错
sudo sed -i 's/SystemdCgroup = false/SystemdCgroup = true/' /etc/containerd/config.toml
# 重启 containerd
sudo systemctl restart containerd
sudo systemctl enable containerd
第三步:安装 kubeadm, kubelet, kubectl
咱们指定安装 v1.31 版本。
# 添加阿里云镜像源(国内速度快,不用翻墙)
sudo apt-get update && sudo apt-get install -y apt-transport-https curl
curl -fsSL https://mirrors.aliyun.com/kubernetes/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://mirrors.aliyun.com/kubernetes/apt/ kubernetes-xenial main" | sudo tee /etc/apt/sources.list.d/kubernetes.list
# 安装指定版本
sudo apt-get update
sudo apt-get install -y kubelet=1.31.0-1.1 kubeadm=1.31.0-1.1 kubectl=1.31.0-1.1
sudo apt-mark hold kubelet kubeadm kubectl
第四步:初始化 Master 节点
在 Master 节点上执行。这里咱们指定了 Kubernetes 版本 1.31.0,并且设置了 Pod 网段(这里用 Calico 默认的 192.168.0.0/16)。
sudo kubeadm init \
--kubernetes-version=1.31.0 \
--pod-network-cidr=192.168.0.0/16 \
--apiserver-advertise-address=<你的Master节点IP>
初始化成功后,终端会输出一大段东西,包括 kubeadm join 的命令,一定要复制保存下来,那是Worker节点加入集群的凭证。
然后配置 kubectl 命令工具:
mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config
第五步:安装网络插件(CNI)
K8s必须配合网络插件才能通信。这里推荐 Calico。
kubectl apply -f https://docs.projectcalico.org/manifests/calico.yaml
等几分钟,看到 Master 节点的状态变成 Ready,就说明搞定了。
kubectl get nodes
# 输出应该类似:
# NAME STATUS ROLES AGE VERSION
# master-1 Ready control-plane 5m v1.31.0
🔧 实战技巧:很多新手在 kubeadm init 的时候会卡住,报错 crictl 找不到或者 CRI 超时。99%的原因都是 Containerd 的 SystemdCgroup 没改成 true。如果你避雷经验了,先去检查 /etc/containerd/config.toml 里的配置,改完记得重启 containerd。
实战:使用Deployment与Service部署你的第一个Web应用
集群搭好了,总得跑点东西吧?咱们不搞那些虚的,直接部署一个真实的 Nginx Web 应用。这里会涉及到两个核心资源:Deployment(负责管应用)和 Service(负责管访问)。
换个角度看,Deployment 就是你的“发布说明书”。你告诉它你要什么镜像,要几个副本,它就去帮你把 Pod 搞起来。
编写 Deployment 配置
创建一个文件叫 nginx-deployment.yaml。
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
# 关键点:副本数,这里设置2个,K8s会保证一直有2个Pod在跑
replicas: 2
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.25-alpine
ports:
- containerPort: 80
# 核心要点:健康检查配置,这是生产环境必须的
# Liveness Probe: 存活性探针,挂了就重启
livenessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 10
periodSeconds: 5
# Readiness Probe: 就绪性探针,通过了才能接流量
readinessProbe:
httpGet:
path: /
port: 80
initialDelaySeconds: 5
periodSeconds: 5
这里解释一下两个探针(面试中常被问到):
- Liveness Probe:其实,“你还活着吗?”。如果探测失败,K8s就认为你这个容器废了,会杀了重启。
- Readiness Probe:“你准备好了吗?”。比如你的应用启动需要加载10秒数据,这10秒内你不想接用户请求吧?那就靠这个探针,没通过之前,流量不会打进来。
编写 Service 配置
Pod 是有生命周期的,IP会变。你总不能让用户直接访问Pod IP吧?这时候就需要 Service。Service 提供一个稳定的虚拟IP(ClusterIP)和DNS名字。
创建 nginx-service.yaml。
apiVersion: v1
kind: Service
metadata:
name: nginx-service
spec:
# ClusterIP 是默认类型,只能在集群内部访问
type: ClusterIP
selector:
# 这里是关键!Selector 会去匹配 Pod 的 labels
app: nginx
ports:
- protocol: TCP
port: 80 # Service 暴露的端口
targetPort: 80 # 容器也就是 Pod 的端口
部署与验证
把这两个文件应用到集群里:
kubectl apply -f nginx-deployment.yaml
kubectl apply -f nginx-service.yaml
查看状态:
# 查看 Pod,应该看到 2/2 Running
kubectl get pods -l app=nginx -o wide
# 查看 Service,会看到一个 CLUSTER-IP
kubectl get svc nginx-service
想验证能不能访问?咱们可以在集群里临时起一个工具Pod去curl:
# 运行一个 busybox 或者 curl 镜像去测试
kubectl run curl-test --image=radial/busyboxplus:curl -i --tty --rm
# 进入容器后执行:
curl http://nginx-service
# 如果看到 nginx 的欢迎页 HTML,说明 Service 到 Pod 的链路通了!
滚动更新实战
咱们试试更新。把 nginx-deployment.yaml 里的镜像改成 nginx:1.26-alpine,然后重新 apply。
kubectl apply -f nginx-deployment.yaml
# 观察滚动更新过程
kubectl rollout status deployment/nginx-deployment
你会发现它是先起一个新的,再杀一个旧的,这就是滚动更新,用户完全无感知。
💡 经验总结:在写 YAML 的时候,千万别忘了写 selector 和 labels 的匹配关系。很多新手Deployment创建成功了,但Pod起不来,或者Service找不到Pod,99%是因为 selector 没匹配对 labels。这就像你快递填错了地址,东西肯定送不到。
流量管理进阶:Ingress与Gateway API配置及区别详解
咱们刚才部署了Service,但那是ClusterIP,只能在集群内部访问。如果你想让外网的用户访问你的网站,怎么办?
这时候有两个选择:一个是传统的 Ingress,另一个是现在社区超级火的 Gateway API。
传统方案:Ingress
Ingress 是K8s早期的七层路由标准。它相当于一个智能的路由器,根据域名或者路径把流量转发到不同的Service。
咱们先装一个 Ingress Controller。这里用最流行的 Nginx Ingress Controller。
# 安装 Nginx Ingress Controller (这里用官方镜像,国内可能需要镜像加速)
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
等它跑起来后,咱们创建一个 Ingress 规则。注意,Ingress 需要配合 Service 使用。
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: nginx-ingress
annotations:
# 这里指定用 nginx,虽然看起来多余,但在多Ingress Controller环境很重要
kubernetes.io/ingress.class: "nginx"
spec:
rules:
# 这里配置域名,本地测试的话改下 hosts 文件指向 Node IP 即可
- host: "k8s.demo.local"
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: nginx-service
port:
number: 80
部署后,你就能通过 http://k8s.demo.local 访问到你的应用了。
进阶方案:Gateway API
其实,Ingress 有个很大的问题:配置太死板,而且把流量管理(基础设施层)和业务路由(应用层)混在了一起。现在社区的大趋势是 Gateway API。
Gateway API 把角色分得很清楚,符合现在的平台工程理念:
- GatewayClass:类似于“模板”,由基础设施提供商定义(比如 Nginx 官方)。
- Gateway:由集群管理员配置,定义监听的端口、TLS等。
- HTTPRoute:由开发者配置,定义具体的路由规则。
目前 Gateway API 还在推广阶段,但它是未来的标准。咱们看个简单的 Gateway 配置(假设你已经安装了支持 Gateway API 的控制器,比如 Nginx Gateway Fabric 或者 Istio)。
# 1. 定义 Gateway (管理员视角)
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: nginx-gateway
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
---
# 2. 定义 HTTPRoute (开发者视角)
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: nginx-route
spec:
parentRefs:
- name: nginx-gateway
hostnames:
- "k8s-gw.demo.local"
rules:
- matches:
- path:
type: PathPrefix
value: /
backendRefs:
- name: nginx-service
port: 80
Ingress vs Gateway API 到底选哪个?
- Ingress:成熟、生态完善、文档多。如果你只是想快速把服务暴露出去,用 Ingress 没毛病。
- Gateway API:更强大、更灵活、面向角色。它支持像“流量分割”(比如 90% 流量给 v1,10% 给 v2)这种高级功能,而且配置更清晰。
作为资深开发,我的建议是:新项目可以考虑直接上 Gateway API,老项目如果跑得好,没必要折腾。
监控与排错
不管用哪个,排错思路都一样。如果访问不通,按这个顺序查:
- Pod 活着吗?
kubectl get pods
- Service 有 Endpoints 吗?
kubectl get endpoints nginx-service (如果没有IP列表,说明标签没匹配上)。
- Ingress/Gateway 配置对吗?
kubectl describe ingress ... 看 Events。
- 日志!日志!日志! 看 Ingress Controller 的日志,通常能直接看到报错。
# 查看 Nginx Ingress Controller 的日志
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
📖 学习建议:很多人在配置 Ingress 的时候,域名解析容易搞错。Ingress 只是一个规则,它本身不提供外部IP。 你需要把域名解析到 Ingress Controller 所在的 Node 的 IP 地址上(如果是云环境,通常是 LoadBalancer 的 IP)。在本地测试,直接改你电脑的 /etc/hosts 文件,把域名指向任意一台 Node 的 IP 就行了。
5. 云原生CI/CD与GitOps:基于ArgoCD的自动化部署实践
搞微服务和K8s,最头疼的往往不是写代码,而是怎么把代码顺滑地推到集群里。传统的CI/CD流水线,比如Jenkins,虽然也能用,但在K8s这种动态环境里,配置起来真的挺繁琐,而且经常遇到权限管理混乱的问题。现在圈子里最火的概念叫 GitOps,可以这么理解,就是把你的Git仓库当成“真理之源”(Single Source of Truth)。你想让集群变成什么样,就直接在Git里改配置文件,剩下的交给工具去同步。
在2024年的社区讨论里,ArgoCD 绝对是GitOps领域的顶流,和 Flux 并驾齐驱。ArgoCD 的核心逻辑特别清晰:它像个勤劳的小蜜蜂,一直在盯着你的Git仓库(或者Helm Chart仓库),一旦发现仓库里的配置和当前集群里的状态不一样,它就自动把集群拉回到Git定义的状态。这就叫“拉取式”部署,比传统的“推送式”安全多了,因为你不需要在CI环境里暴露集群的Kubeconfig。
咱们来实操一下,怎么在 Kubernetes v1.31(代号 "Elli",2024年8月刚发布的稳定版)上把 ArgoCD 跑起来。
安装 ArgoCD
先在你的终端里敲下面的命令,咱们用官方的 manifests 来装,简单粗暴:
# 1. 创建一个专门的命名空间
kubectl create namespace argocd
# 2. 应用 ArgoCD 的安装清单(这里用的是最新稳定版)
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# 3. 等待所有 Pod 启动,这可能需要一两分钟
kubectl get pods -n argocd
装好之后,ArgoCD 有个Web UI,咱们得把它的服务暴露出来。为了省事,咱们直接改个 LoadBalancer 或者 NodePort,或者像我一样用端口转发(Port Forward)来访问:
# 把 argocd-server 映射到本地 8080 端口
kubectl port-forward svc/argocd-server -n argocd 8080:443
配置应用并部署
ArgoCD 装好了,接下来得告诉它去哪儿找代码。假设你在 GitHub 上有个仓库,里面放着你的 K8s YAML 文件。咱们得先获取 ArgoCD 的默认密码,然后登录进去配置应用。
# 获取初始管理员密码
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d; echo
拿到密码后,咱们不用Web UI,直接用命令行 argocd 客户端或者写个 Application 的 CRD(自定义资源)来定义部署。这才是云原生的玩法。
创建一个 app-of-apps.yaml 文件:
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-guestbook
namespace: argocd
spec:
project: default
source:
# 关键点:这里填你自己的 Git 仓库地址
repoURL: https://github.com/your-username/your-repo.git
targetRevision: HEAD
# 如果你的yaml文件在仓库的子目录里,这里要指定
path: k8s-manifests
destination:
# 要部署到哪个集群(in-cluster表示当前集群)
server: https://kubernetes.default.svc
# 部署到哪个命名空间
namespace: default
syncPolicy:
automated:
# 开启自动同步,Git一变,集群就变
prune: true
selfHeal: true
把这个文件 kubectl apply -f app-of-apps.yaml 之后,ArgoCD 就开始干活了。
🔧 实战技巧:刚开始玩 GitOps 的时候,千万别一上来就开 automated: prune: true。prune 的意思是如果你在 Git 里删除了某个资源,ArgoCD 也会在集群里删掉它。新手很容易因为手滑删错文件,导致线上服务被干掉。建议先手动 Sync,或者只开 selfHeal(自愈),等玩熟了再全自动化。
现在的趋势是,ArgoCD 已经不仅仅是个部署工具了,它正在成为 平台工程 (Platform Engineering) 的核心组件。大厂都在搞内部开发者平台(IDP),用 ArgoCD 加上 Backstage 这种工具,让开发同学点点鼠标就能发布服务,完全不用管底层 K8s 的复杂配置。而且,现在的 ArgoCD 对 Gateway API 的支持也越来越好,以后替代传统的 Ingress 也是大势所趋。
6. K8s面试中常被问到:Deployment与StatefulSet区别及调度流程
面试K8s岗位,要是面试官不问你 Deployment 和 StatefulSet 的区别,那这面试大概率是不专业的。这俩货虽然都是用来管 Pod 的,但适用的场景简直是天壤之别。打个比方,如果你跑的是无状态服务(比如Web后端、API网关),用 Deployment;如果你跑的是有状态服务(比如MySQL、Redis、MongoDB),那必须得用 StatefulSet。
Deployment vs StatefulSet:核心差异
咱们来细扒一下。Deployment 管理的 Pod,名字是随机的,比如 nginx-deployment-7c8b45d4f9-abcde,重启或者更新后,名字就变了,IP也变了。这在K8s眼里,这些 Pod 都是“牲口”,挂了就换新的,不在乎你是谁。
但 StatefulSet 不一样,它管理的 Pod 名字是固定的,比如 mysql-0, mysql-1。哪怕你把 mysql-0 删了,重启后它还是叫 mysql-0。而且,它会配合 Headless Service,给每个 Pod 提供一个固定的DNS域名,像 mysql-0.mysql-service.default.svc.cluster.local。这对于需要主从复制、集群选举的数据库来说,简直是救命稻草。
还有一个大坑就是存储。Deployment 通常用共享存储或者不需要持久化,而 StatefulSet 会配合 volumeClaimTemplates,给每个 Pod 创建独立的 PVC(持久化卷)。mysql-0 挂了再起来,还是能挂载回原来那块盘,数据不丢。
调度流程:从 YAML 到 Running
面试官还特别喜欢问:“一个 Pod 从被创建到运行,到底经历了啥?” 咱们结合 K8s v1.31 的架构来捋一捋。
- 你敲下
kubectl apply:这时候,你的 YAML 被转换成 JSON,通过 HTTPS 发给 API Server。
- API Server 认证与写入:API Server 做鉴权(RBAC),然后把 Pod 的信息存到 etcd 里。这时候 Pod 只是个“死”记录,还没开始跑。
- Scheduler 介入(调度):调度器(Scheduler)这时候在旁边盯着呢,它发现有个 Pod 还没绑定节点(Node)。它就开始算账:这个 Pod 要多少 CPU?要多少内存?有没有亲和性(Affinity)要求?比如“我想跟 Redis 跑在一起”或者“我不想跟 GPU 节点混着”。算好了,Scheduler 就把“这个 Pod 应该去 Node A”这个信息写回 API Server(更新 etcd)。
- Kubelet 接手(运行):Node A 上的 Kubelet 组件发现:“嘿,有个 Pod 分给我了”。它就开始干活,调用容器运行时(记住,现在 K8s 早就移除了 Dockershim,主流都是用 containerd 或者 CRI-O 了)去拉镜像、启动容器。
- 健康检查:容器跑起来后,Kubelet 就开始盯着你定义的 Liveness Probe(存活探针) 和 Readiness Probe(就绪探针)。如果 Liveness 挂了,Kubelet 就重启容器;如果 Readiness 没通过,就不把流量导进来。
代码示例:对比两者的 YAML
咱们看个实际的例子,感受一下 StatefulSet 的“固执”。
Deployment 示例 (nginx-deploy.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
StatefulSet 示例 (mysql-ss.yaml):
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
ports:
- port: 3306
clusterIP: None # 值得留意的是,这是 Headless Service,不给 ClusterIP
selector:
app: mysql
---
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: mysql
spec:
serviceName: "mysql-headless" # 必须关联上面的 Headless Service
replicas: 3
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0
ports:
- containerPort: 3306
name: mysql
env:
- name: MYSQL_ROOT_PASSWORD
value: "password123"
volumeMounts:
- name: data
mountPath: /var/lib/mysql
# 核心要点:这里是动态存储模板,每个Pod会生成一个独立的PVC
volumeClaimTemplates:
- metadata:
name: data
spec:
accessModes: [ "ReadWriteOnce" ]
resources:
requests:
storage: 10Gi
📖 学习建议:面试的时候,如果聊到调度流程,别忘了提一嘴 亲和性(Affinity) 和 污点(Taints/Tolerations)。这是生产环境里控制 Pod 跑在哪些机器上的核心手段。比如你有一批 GPU 机器,就给它们打个 gpu=true 的污点,然后只有配置了对应容忍度的 Pod(比如你的 TensorFlow 训练任务)才能跑上去,这样能避免普通Web服务把宝贵的GPU资源给占了。
7. 总结与展望:平台工程与AI工作负载下的K8s未来
咱们聊了这么多,从怎么部署一个应用,到怎么用 ArgoCD 搞自动化,再到面试怎么吹牛逼。现在咱们把视角拉高一点,看看 Kubernetes 这艘大船未来要往哪儿开。毕竟,K8s 现在已经不是什么新鲜玩意儿了,它正在从“新兴技术”变成“基础设施的水电煤”。
根据最新的社区动态和 2024-2026 年的趋势,有两个方向特别火:平台工程 (Platform Engineering) 和 AI/ML 工作负载。
平台工程:别让开发同学直接写 YAML
其实,K8s 太复杂了。你让一个业务开发同学去手写 Deployment、Service、Ingress、ConfigMap,他大概率会崩溃。现在的趋势是,大厂都在搞 内部开发者平台 (IDP)。K8s 退居幕后,变成一个底层的“能力提供者”。
大家开始用 Backstage 这样的工具,配合 K8s 的 Operator 模式,把复杂的部署逻辑封装起来。开发同学只需要填个表单,或者改个简单的 values.yaml,剩下的什么服务发现、负载均衡、日志采集,平台都帮你搞定了。这就是所谓的“开发者体验(DX)”优化。未来的 K8s 使用者,可能根本不需要懂什么是 kubectl,他们只需要懂怎么在平台上点“发布”按钮。
AI 工作负载:K8s 成了 AI 的底座
另一个大趋势就是 AI。现在的 AI 训练和推理,尤其是大模型,对资源调度要求极高。K8s 凭借其强大的调度能力,正在成为 AI 基础设施的标准。
你想跑个 PyTorch 或者 TensorFlow 的训练任务?现在都是直接扔给 K8s。特别是 GPU 调度,K8s v1.31 在这方面已经做得非常成熟了。而且,像 KServe 这样的项目,专门用来做模型推理服务的部署,能让你像部署普通 Web 服务一样部署 AI 模型,还能根据请求量自动扩缩容 GPU 实例。这可比以前手动去机器上装 CUDA 驱动、配环境要爽多了。
安全性与 Serverless
除了上面两个,还有两个值得关注的点。一个是 安全性左移。现在大家都在谈软件供应链安全(Supply Chain Security),K8s 社区也在加强 SBOM(软件物料清单)和镜像签名验证。以后你往集群里推一个没签名的镜像,可能直接就被拦截了。
另一个是 Serverless。虽然 Serverless 喊了很久,但结合 Knative 和 K8s,现在的体验已经好很多了。你写个函数,不用管服务器,流量来了自动扩容,没流量了缩容到零。这对于那些流量波动巨大的业务来说,简直是省钱神器。
给新手的建议
写了这么多,最后给正在入门的你一个实在的建议:别光看文档,多动手。
现在的 K8s 生态虽然庞大,但核心概念就那么几个。找个云厂商的免费试用,或者本地用 Minikube/Kind 搭个环境,把咱们前面说的 Deployment、StatefulSet、ArgoCD 都跑一遍。踩实战经验,比如 Pod 一直 Pending 是什么原因?Ingress 访问不通怎么排查?这些经验比背八股文有用得多。
K8s 每4个月发一个大版本(通常是奇数月),虽然咱们不用追着最新版跑,但关注一下像 v1.31 "Elli" 这种稳定版的新特性,能让你保持技术敏感度。未来的 K8s 会更智能、更自动化,作为工程师,咱们要做的就是驾驭它,而不是被它复杂的配置淹没。加油,未来的云原生大佬!