【K8s从零到实战】一个真实项目带你理解:K8s是什么?和Docker什么关系?YAML文件怎么配?

📅 2026/7/23 10:13:14 👁️ 阅读次数 📝 编程学习
【K8s从零到实战】一个真实项目带你理解:K8s是什么?和Docker什么关系?YAML文件怎么配?

【K8s从零到实战】一个真实项目带你理解:K8s是什么?和Docker什么关系?YAML文件怎么配?

别再死记概念了,我带你从一份真实的k8s/目录配置读懂Kubernetes


一、引言:从一段真实的开发经历说起

小张是个后端开发,他花了一周时间用Python FastAPI写了一个资产管理平台,Docker打包后在本地跑得很欢。

老板说:“上线吧。”

小张把Docker镜像推到服务器,docker run -d ...,搞定。

第二天,服务挂了,同事重启了一下。

第三天,服务又挂了,这次是内存爆了。

第四天,并发量上来了,一台机器扛不住,小张手动启动了第二台,然后发现两个容器访问的是不同的本地数据库,数据不一致……

小张崩溃了。

这些问题的根源是什么?

  • 没有自愈能力——挂了没人自动重启

  • 没有资源限制——内存爆了就OOM

  • 没有负载均衡——多实例需要手动管理

  • 没有服务发现——实例之间不知道怎么找到对方

  • 没有滚动更新——升级=停服

而这些问题,正是Kubernetes要解决的。

今天,我们就通过一个真实的开源项目——CAMP云资产管理平台k8s/配置文件,来彻底搞懂Kubernetes是怎么解决这些问题的。


二、Docker vs Kubernetes:它们到底是什么关系?

在开始解析YAML之前,我必须先帮你理清楚这两个“出镜率最高”的概念。很多人学了很久还是模糊的,这里用一个“盖房子”的比喻让你一辈子忘不掉:

概念类比职责
Docker标准化的砖块生产厂把应用打包成镜像(Image),让同一个应用在任何机器上都能跑
Kubernetes智慧建筑工地总指挥管理容器(Container)在哪里跑、跑几个、挂了怎么办、怎么对外提供服务

一句话总结Docker负责“打包”,Kubernetes负责“调度”

在你要学习的这个项目中,这个关系体现得非常清晰:

text

┌─────────────────────────────────────────────────────────────────┐ │ 开发者写代码 (Python / JavaScript) │ │ ↓ │ │ Dockerfile (定义如何打包) │ │ ↓ │ │ docker build → camp-backend:latest (镜像) │ │ ↓ │ │ docker push → GHCR (镜像仓库) │ │ ↓ │ │ Kubernetes拉取镜像 + 按YAML配置运行 → Pod、Service、Ingress │ └─────────────────────────────────────────────────────────────────┘

Docker解决了“环境不一致”的问题——开发环境能跑,生产环境就能跑。

Kubernetes解决了“容器规模化运维”的问题——当你需要管理几十上百个容器时,手动操作已经不现实了。


三、这个项目中的K8s配置长什么样?

一个项目的k8s/目录下有这些核心文件:

text

k8s/ ├── namespace.yaml # 命名空间(把资源隔离开) ├── configmap.yaml # 非敏感配置 ├── secret.yaml # 敏感配置(密码、密钥等) ├── backend-deployment.yaml # 后端服务的Pod编排 ├── web-frontend-deployment.yaml # 主前端 ├── auth-frontend-deployment.yaml # 认证前端 ├── service.yaml # 服务发现与负载均衡 ├── ingress.yaml # 外部访问入口 ├── persistent-volumes.yaml # 持久化存储 ├── horizontal-pod-autoscaler.yaml # 自动伸缩 ├── network-policy.yaml # 网络隔离规则 ├── resource-quota.yaml # 资源配额限制 ├── monitoring.yaml # 监控组件 ├── deploy.sh # 一键部署脚本 └── cleanup.sh # 一键清理脚本

这些文件之间是什么关系?用一张图就能看清:

核心逻辑

  1. Namespace是“容器”,所有资源都装在里面。

  2. Deployment管Pod的“生老病死”(副本数、镜像版本、探针等)。

  3. Service给Pod一个“固定门牌号”(不管Pod怎么重启,通过Service总能找到)。

  4. Ingress是“大门”(外部流量从这里进来,再分发给各个Service)。

  5. ConfigMap/Secret是“配置中心”(把配置从镜像里抽出来,便于修改)。

  6. PVC是“硬盘”(容器重启数据不丢)。

  7. HPA是“自动升降机”(流量大了自动加Pod,小了自动减Pod)。


四、逐文件深度解析:每个YAML到底在说什么?

1.namespace.yaml—— 资源的“文件夹”

yaml

apiVersion: v1 kind: Namespace metadata: name: camp labels: app: cloud-asset-management-platform environment: production

作用:创建一个叫camp的命名空间。

为什么要用Namespace?

场景不用Namespace用Namespace
查看所有资源kubectl get pods→ 全部混在一起kubectl get pods -n camp→ 只看camp的
资源隔离开发环境可能误删生产环境的Pod不同环境用不同Namespace,互不影响
权限控制无法精细控制可以给不同用户授予不同Namespace的权限

大白话:Namespace就像你电脑里的“文件夹”,把项目A和项目B的文件分开存放,免得乱七八糟。


2.configmap.yaml—— 配置的“公开文件夹”

yaml

apiVersion: v1 kind: ConfigMap metadata: name: camp-config namespace: camp data: DATABASE_URL: "sqlite:///./camp.db" DEBUG: "false" LOG_LEVEL: "info" CORS_ORIGINS: "http://localhost:3004,http://localhost:3000" MAX_FILE_SIZE: "52428800"

作用:存储应用的非敏感配置。

为什么要用ConfigMap?

  • 分离配置和代码:改配置不用重新构建镜像

  • 同一套代码,不同环境用不同配置DEBUG: "true"(开发)vsDEBUG: "false"(生产)

大白话:ConfigMap就是给容器注入环境变量的“说明书”,想让程序怎么跑,改这里就行,不用重新打包镜像。


3.secret.yaml—— 配置的“加密保险柜”

yaml

apiVersion: v1 kind: Secret metadata: name: camp-secrets namespace: camp type: Opaque data: SECRET_KEY: "ZGV2LXNlY3JldC1rZXk=" # Base64编码 JWT_SECRET: "ZGV2LWp3dC1zZWNyZXQ=" DEFAULT_PASSWORD: "YWRtaW4xMjM="

注意:Secret里的值必须是Base64编码的,不是明文!

为什么要用Secret?

问题解决方案
密码明文写在YAML里 → 安全隐患用Secret存储,且值用Base64编码
任何人能看到YAML文件 → 泄露密码配合RBAC权限控制,只有特定角色能读取Secret

大白话:Secret和ConfigMap功能一样,都是存配置。区别是Secret存的是密码、密钥、Token这些见不得光的东西。


4.backend-deployment.yaml—— 最核心的“Pod说明书”

这是整个项目里最重要、最核心的一个YAML文件。理解了它,Kubernetes你就懂了一半。

yaml

apiVersion: apps/v1 kind: Deployment metadata: name: camp-backend namespace: camp labels: app: camp component: backend spec: replicas: 2 selector: matchLabels: app: camp component: backend template: metadata: labels: app: camp component: backend spec: containers: - name: camp-backend image: ghcr.io/elishatheodore/camp-backend:latest imagePullPolicy: Always ports: - containerPort: 8000 # ... 以下是重点
replicas: 2—— 我要2个“分身”

这告诉Kubernetes:“我要2个一模一样的Pod同时运行。”

  • 一个挂了,另一个还能顶上去 →高可用

  • 流量大了,2个一起分担 →负载均衡

解决小张的问题:一台机器不够就多开几台,Kubernetes自动管理。


② 探针(Probe)—— Kubernetes的“体检系统”

yaml

livenessProbe: httpGet: path: /test port: 8000 initialDelaySeconds: 30 # 等30秒再开始检查 periodSeconds: 10 # 每10秒查一次 failureThreshold: 3 # 连续失败3次就判定为“死了” readinessProbe: httpGet: path: /health port: 8000 initialDelaySeconds: 5 periodSeconds: 5 failureThreshold: 3

livenessProbe(存活探针):检查容器是否“活着”。

  • 访问/test接口,返回200说明活着

  • 连续失败3次 → Kubernetes认为容器“死亡”,自动重启

  • 这是Kubernetes的自愈能力,无需人工干预

readinessProbe(就绪探针):检查容器是否“准备好接客”。

  • 访问/health接口,返回200说明准备好了

  • 如果失败 → Kubernetes不会把流量转发给这个Pod,直到它恢复

  • 这确保了用户不会访问到“正在启动中”或“有故障”的服务

解决小张的问题:服务挂了不用手工重启,Kubernetes会自动处理。


③ 资源限制(Resources)—— 防止“一个坏邻居拖垮整栋楼”

yaml

resources: requests: memory: "256Mi" cpu: "250m" limits: memory: "512Mi" cpu: "500m"
概念含义比喻
requests最低保障申请“我要至少256MB内存”,调度器才会把你安排到有这个资源的机器上
limits最高上限“最多给你512MB,超过就杀掉”,防止某个程序吃光所有资源

解决小张的问题:内存爆了不会把整个服务器搞死,只会杀掉这个Pod,然后Kubernetes自动重建。


④ 环境变量注入——连接ConfigMap和Secret

yaml

env: - name: DATABASE_URL valueFrom: configMapKeyRef: name: camp-config key: DATABASE_URL - name: SECRET_KEY valueFrom: secretKeyRef: name: camp-secrets key: SECRET_KEY

这些环境变量注入到容器后,Python代码直接os.getenv("DATABASE_URL")就能读到。

这就是配置与镜像分离的精髓:镜像不变,换个ConfigMap/Secret就能在不同环境跑。


⑤ 存储挂载(Volumes)—— 数据不丢失的秘密

yaml

volumeMounts: - name: uploads-storage mountPath: /app/uploads - name: database-storage mountPath: /app/camp.db subPath: camp.db volumes: - name: uploads-storage persistentVolumeClaim: claimName: camp-uploads-pvc - name: database-storage persistentVolumeClaim: claimName: camp-database-pvc

原理

  • PVC(PersistentVolumeClaim)相当于“申请单”,向Kubernetes申请一块“硬盘”

  • volumeMounts把这块“硬盘”挂载到容器里的某个目录

  • 容器重启了,数据还在“硬盘”上

解决小张的问题:SQLite数据库文件存在PVC里,Pod重启了数据也不会丢。


5.service.yaml—— 给Pod一个“永不改变的门牌号”

yaml

apiVersion: v1 kind: Service metadata: name: camp-backend-service namespace: camp spec: type: ClusterIP ports: - port: 8000 targetPort: 8000 selector: app: camp component: backend

问题:Pod的IP是动态的,每次重启都可能变化。前端怎么知道后端的IP?

答案:Service提供一个固定的虚拟IP和DNS名称。

  • 前端访问camp-backend-service.camp.svc.cluster.local就能找到后端

  • Service自动把请求负载均衡到所有匹配selector的Pod上

大白话:Pod就像不断换住址的租客,Service就是那个“永不改变的门牌号”,找Service就能找到所有租客。


6.ingress.yaml—— 互联网的“大门”

yaml

apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: camp-ingress namespace: camp spec: rules: - host: camp.example.com http: paths: - path: /api pathType: Prefix backend: service: name: camp-backend-service port: number: 8000 - path: / pathType: Prefix backend: service: name: camp-web-frontend-service port: number: 80

作用:外部用户通过域名访问时,Ingress根据路径把请求路由到不同的Service:

路径目标
camp.example.com/api/*→ 后端Service (FastAPI)
camp.example.com/auth/*→ 认证前端Service
camp.example.com/*→ 主前端Service

大白话:Ingress就是大楼的“门厅接待处”——有人来了,根据他要去几楼,指引他到对应的电梯。


五、如何部署这些YAML文件?

方式一:直接用kubectl(传统方式)

bash

# 部署整个k8s目录下的所有资源 kubectl apply -f k8s/ # 或者先切到k8s目录再部署 cd k8s kubectl apply -f .

方式二:使用Kustomize(推荐方式)

这个项目的k8s/目录使用了Kustomize——Kubernetes原生的配置管理工具。

bash

# 在项目根目录执行 kubectl apply -k k8s/

-k参数告诉kubectl:“这个目录里有一个kustomization.yaml,请按它描述的构建方式部署。”

常用管理命令

bash

# 查看部署状态 kubectl get pods -n camp kubectl get svc -n camp kubectl get ingress -n camp # 查看日志 kubectl logs -f deployment/camp-backend -n camp # 扩容/缩容 kubectl scale deployment camp-backend --replicas=3 -n camp # 更新镜像 kubectl set image deployment/camp-backend camp-backend=ghcr.io/xxx/camp-backend:v2.0.0 -n camp # 滚动重启(不改变镜像,用于刷新配置) kubectl rollout restart deployment/camp-backend -n camp # 查看滚动更新状态 kubectl rollout status deployment/camp-backend -n camp # 回滚到上一个版本 kubectl rollout undo deployment/camp-backend -n camp # 删除所有资源 kubectl delete -k k8s/ # 或 kubectl delete -f k8s/

六、Kubernetes应用场景总结

通过这个项目,你可以看到Kubernetes解决了以下几个核心场景的问题:

场景痛点K8s解决方案项目中的体现
服务高可用容器挂了要人手工重启自愈能力(livenessProbe)探针自动检测+重启
流量分发多个实例需要手动负载均衡Service负载均衡Service自动分发流量
滚动更新升级需要停服滚动更新策略kubectl set image+rollout
配置管理改配置要重新打镜像ConfigMap/Secret配置独立于镜像
数据持久化容器重启数据丢失PersistentVolumeClaimPVC独立于Pod生命周期
自动伸缩流量高峰需要手动加机器HorizontalPodAutoscaler根据指标自动扩缩容
网络隔离服务之间没有访问控制NetworkPolicy精细控制Pod间通信
资源管理单个服务吃光所有资源ResourceQuota + LimitRange资源限制防“吵闹邻居”

七、一张图总结:这个项目中Docker和K8s如何协作

核心一句话:Docker负责“造砖”,Kubernetes负责“盖楼、修楼、扩容、防塌”。


八、写在最后

通过这个真实项目的k8s/目录,我们完整地看到了:

  1. Docker和K8s的分工:Docker打包,K8s调度

  2. K8s的核心资源:Namespace、Deployment、Service、Ingress、ConfigMap、Secret、PVC

  3. K8s如何解决实际问题:自愈、负载均衡、滚动更新、配置分离、数据持久化

  4. 一个微服务应用在K8s上完整运行的全貌

如果你正在学习Kubernetes,不要只背概念,去跑一个真实项目。把项目里的YAML文件一个个看过去,跑起来,改一改,看看效果。这才是最快的学习方式。

九、当Kubernetes遇见AI:智能运维时代已经到来

如果说Kubernetes是云原生时代的“操作系统”,那么AI就是给这个操作系统装上“大脑”。

前面我们详细解析了Kubernetes的各个组件和工作原理。但你可能不知道的是,AI正在深刻改变Kubernetes的运维方式和应用场景。在这一章,我们从三个层面来看K8s与AI的结合。


9.1 AI + K8s = 智能运维(AIOps)

传统的Kubernetes运维依赖人工配置、人工排查、人工决策。但当集群规模达到成百上千个节点时,人已经跟不上节奏了。AI的介入,让K8s从“自动化”走向“智能化”。

🤖 AI辅助:YAML智能生成与校验

还记得你刚学K8s时被YAML折磨的日子吗?现在AI可以帮你做了。

yaml

# 你只需要用自然语言描述需求,AI帮你生成YAML “我要部署一个Python FastAPI服务,副本数3,内存限制512Mi,暴露端口8000” ↓ # AI自动生成的Deployment YAML apiVersion: apps/v1 kind: Deployment metadata: name: fastapi-app spec: replicas: 3 selector: matchLabels: app: fastapi template: spec: containers: - name: app image: python:3.11 command: ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000"] ports: - containerPort: 8000 resources: limits: memory: "512Mi"

实操工具

  • GitHub Copilot:在IDE里写YAML时自动补全

  • ChatGPT/Claude:用自然语言描述需求,生成完整的K8s YAML

  • k8sgpt:开源工具,用AI扫描集群并给出修复建议

bash

# 安装k8sgpt brew install k8sgpt # 扫描集群问题 k8sgpt analyze --explain # 输出:AI分析Pod为什么一直CrashLoopBackOff,并给出具体修复建议
🔮 AI预测:智能自动伸缩(KEDA + AI)

传统的HPA基于当前的CPU/内存指标做伸缩决策,是被动的——流量来了才开始扩容,已经有点晚了。

AI驱动的预测性伸缩会分析历史流量模式,提前预测高峰,主动扩容。

yaml

# 使用KEDA (Kubernetes Event-driven Autoscaling) + AI预测 apiVersion: keda.sh/v1alpha1 kind: ScaledObject metadata: name: camp-backend-ai-scaler spec: scaleTargetRef: name: camp-backend triggers: - type: prometheus metricName: http_requests_total threshold: 100 # AI模型会分析历史数据,预测未来5分钟的流量 # 提前扩容而不是被动响应

实际效果

  • 传统HPA:流量高峰到来 → 指标上升 → 扩容(有延迟,用户可能已经感受到卡顿)

  • AI预测伸缩:AI识别出“每天下午3点流量会翻倍” → 2:55提前扩容 → 用户无感知

🧠 AI诊断:故障根因分析

当一个Pod出问题时,传统方式是你去看日志、看事件、看监控,凭经验猜测原因。

AI可以通过分析海量日志和指标,直接告诉你:

text

❌ Pod camp-backend-7d8f9-abc12 处于 CrashLoopBackOff 状态 🤖 AI诊断结果: - 根因:内存限制(512Mi)不足以处理当前请求量 - 证据:过去1小时内OOMKilled事件出现 7 次 - 建议:将 memory.limits 从 512Mi 提升到 1Gi - 同时建议:检查代码中是否有内存泄漏,重点关注 /api/upload 接口

实操工具

  • k8sgpt:开源的K8s AI诊断工具

  • Robusta:结合Prometheus和AI的自动化运维平台

bash

# 使用k8sgpt分析特定Pod k8sgpt analyze --namespace camp --pod camp-backend-7d8f9-abc12 --explain # 输出AI分析结果,直接告诉你问题和修复建议

9.2 AI应用跑在K8s上:在K8s中部署AI工作负载

除了“AI帮我们管K8s”,还有另一个方向——“在K8s上跑AI应用”。现代AI/ML工作负载正大规模迁移到Kubernetes。

🧪 AI推理服务部署

假设你的CAMP平台想增加一个“智能资产标签”功能——用户上传图片,AI自动识别设备类型并打标签。

在K8s上部署AI推理服务就像部署普通微服务一样,只需多关注GPU资源:

yaml

apiVersion: apps/v1 kind: Deployment metadata: name: ai-inference-service namespace: camp spec: replicas: 2 selector: matchLabels: app: ai-inference template: metadata: labels: app: ai-inference spec: containers: - name: inference image: ghcr.io/camp/ai-classifier:v1.0 ports: - containerPort: 8080 resources: requests: nvidia.com/gpu: 1 # 请求1张GPU limits: nvidia.com/gpu: 1 env: - name: MODEL_PATH value: "/models/resnet50.onnx" - name: BATCH_SIZE value: "32" volumeMounts: - name: model-storage mountPath: /models volumes: - name: model-storage persistentVolumeClaim: claimName: ai-models-pvc --- # Service暴露AI服务 apiVersion: v1 kind: Service metadata: name: ai-inference-service namespace: camp spec: type: ClusterIP ports: - port: 8080 targetPort: 8080 selector: app: ai-inference

关键变化

  • resources里指定了nvidia.com/gpu:告诉Kubernetes这个Pod需要GPU

  • 需要提前安装NVIDIA GPU Operator,让K8s能识别和管理GPU资源

🚀 使用Kubeflow:K8s上的ML平台

如果AI服务变得复杂(需要模型训练、超参数调优、多版本管理),可以使用Kubeflow——专门在K8s上运行AI/ML工作负载的平台。

yaml

# Kubeflow Pipeline定义:自动化AI模型训练→评估→部署 apiVersion: pipelines.kubeflow.org/v1beta1 kind: Pipeline metadata: name: model-training-pipeline spec: tasks: - name: data-preprocessing component: data-prep - name: model-training component: train dependencies: [data-preprocessing] parameters: epochs: 50 learning_rate: 0.001 - name: model-evaluation component: evaluate dependencies: [model-training] - name: model-deployment component: deploy-k8s dependencies: [model-evaluation]

Kubeflow让数据科学家也能用K8s,他们不需要懂复杂的K8s概念,只需定义Pipeline就能完成模型训练和部署。


9.3 这个项目如何与AI结合?

回到我们的CAMP云资产管理平台,可以在多个环节引入AI:

💡 场景一:AI驱动的智能告警

用AI分析Prometheus监控数据,当检测到异常趋势时主动告警,而不是等阈值触发。

bash

# 部署AI告警引擎 ./scripts/deploy.sh -c aks-dev -e dev -t ai-alerting-v1

效果

  • 传统告警:CPU超过80%才报警 → 可能已经出问题了

  • AI告警:AI识别出“CPU增长曲线异常,预测10分钟后超限” → 提前预警

💡 场景二:智能日志分析

把Pod日志接入AI模型,自动识别异常日志模式,无需人工翻日志。

yaml

# 在monitoring.yaml中增加AI日志分析组件 - name: ai-log-analyzer image: ghcr.io/camp/log-analyzer:v1 env: - name: OPENAI_API_KEY valueFrom: secretKeyRef: name: ai-secrets key: openai-key - name: LOG_SOURCE value: "camp-backend"
💡 场景三:自然语言查询K8s状态

用自然语言查询集群状态,AI自动转换成kubectl命令:

text

你:“帮我看看camp命名空间下有哪些Pod在跑” AI → 自动执行:kubectl get pods -n camp 你:“后端服务最近有报错吗?” AI → 自动执行:kubectl logs -f deployment/camp-backend -n camp --tail=50 | grep ERROR 你:“帮我把后端的副本数从2扩到5” AI → 自动执行:kubectl scale deployment camp-backend --replicas=5 -n camp

实操工具

  • KubeAI:Kubernetes的AI助手

  • K8sGPT:自然语言查询K8s状态


9.4 AI + K8s:技术栈总览

层级AI相关技术作用
集群资源层NVIDIA GPU Operator让K8s能调度GPU资源
工作负载层Kubeflow, Ray, MLflow在K8s上运行AI训练和推理
可观测性层k8sgpt, RobustaAI自动诊断集群问题
弹性伸缩层KEDA + AI预测模型智能预测性伸缩
交互层KubeAI, 自然语言接口用自然语言操作K8s
应用层CAMP + AI推理服务在资产管理平台中嵌入AI功能

9.5 技术展望:K8s + AI 的未来

阶段特征典型能力
阶段一(当前)AI辅助运维YAML智能生成、问题诊断建议、日志智能分析
阶段二(近未来)AI驱动自动化预测性伸缩、自动修复、自动优化资源配置
阶段三(远期)AI原生K8s集群自我优化、零人工干预、意图驱动运维

一句话展望:未来的Kubernetes集群不再是“你告诉它怎么做”,而是“你告诉它你想要什么结果,AI帮你实现”。


十、写在最后

通过这个真实项目的k8s/目录,我们完整地看到了:

  1. Docker和K8s的分工:Docker打包,K8s调度

  2. K8s的核心资源:Namespace、Deployment、Service、Ingress、ConfigMap、Secret、PVC

  3. K8s如何解决实际问题:自愈、负载均衡、滚动更新、配置分离、数据持久化

  4. AI如何赋能K8s:智能诊断、预测伸缩、自然语言操作、AI工作负载调度

  5. 一个微服务应用在K8s上完整运行的全貌

如果你正在学习Kubernetes,不要只背概念,去跑一个真实项目。把项目里的YAML文件一个个看过去,跑起来,改一改,看看效果。这才是最快的学习方式。


相关文章推荐

  • 《别再手动写K8s YAML了!Helm保姆级入门指南》

  • 《从零理解Kubernetes核心概念:Pod、Service、Ingress》

  • 《Kubernetes + AI:智能运维落地实践》


本文基于开源项目 kubernetes-microservices 的k8s/目录分析整理。欢迎Star和Fork学习