CodeRoadMap
首页路线题库资源库文章社区
CodeRoadMap

程序员的学习成长路线图。内容免费开放,登录后可同步路线图与课时进度。

由 程序员柏风 独立维护 · 关于作者

学习

  • 路线图
  • 课程
  • 面试题
  • 文章
  • 我

更多

  • 资源
  • 社区
  • 关于作者
  • 内容说明

© 2026 CodeRoadMap

津ICP备2026012044号-1·津公网安备12011002026155号·coderoadmap@126.com
Kubernetes 入门/课时/综合练习:部署 backend
RawBlame
课时目录12 节

Kubernetes 入门

  1. 01Kubernetes 是什么
  2. 02核心概念与架构
  3. 03本地集群与 kubectl
  4. 04Pod
  5. 05Deployment 与滚动更新
  6. 06Service 与网络
  7. 07ConfigMap 与 Secret
  8. 08存储卷
  9. 09Ingress 入口
  10. 10资源配额与 HPA
  11. 11RBAC 与安全基础
  12. 12综合练习:部署 backend

综合练习:部署 backend

Deployment + Service + ConfigMap;Helm/GitOps 下一步。

45 分钟

综合练习:部署 backend

这一课你将能做到

  1. 提交一套完整可 apply 的清单:Namespace + ConfigMap + Secret + Deployment(探针/资源齐全)+ Service(可选 Ingress)
  2. 用 port-forward(或 Ingress)打通本站风格的 API 冒烟,并解释每一步「通/不通」的判定依据
  3. 完成一次改镜像滚动更新与 rollout undo,写下它与 docker compose up 发布的差异

为什么要学

前面 11 课是零件,本课把它们装配成整车:把 docker-essentials 里构建的 backend 镜像(Spring Boot + MySQL/Redis 配置外置)接进 K8s 主路径对象。这一课做完,你就具备了「把一个无状态服务放上 K8s」的完整能力——这也是大多数公司 K8s 岗位的实际日常工作内容。

目标不是一次上生产,而是形成「声明期望 → 观察状态 → 排障定位 → 回滚止损」的肌肉记忆。做完本课,把清单文件存进仓库,它就是你的第一份可复用的部署模板,也是通往 Helm/GitOps 的原材料。

先建立图像

ConfigMap(backend-config) ──envFrom──┐
Secret(db-secret) ──env──┐           │
                         ▼           ▼
              Deployment(backend) × 2 副本
                │ probes: /actuator/health
                │ resources: requests/limits
                ▼
              Service backend(ClusterIP 80→8080)
                │
     ┌──────────┴───────────┐
 port-forward(本机调试)   Ingress(可选,/api 分流)
                │
             你的 curl

MySQL / Redis:集群外(Compose/托管),DB_HOST 指向可达地址
资源本课最低要求
Deployment2 副本、标签 app=backend、readiness+liveness、requests/limits
ServiceClusterIP,selector 匹配,80→8080(占位镜像为 80)
ConfigMapSPRING_PROFILES_ACTIVE、DB_HOST、REDIS_HOST
SecretDB_PASSWORD(演示值即可)
Ingress可选;host/path 复刻现网 Nginx

跟着做

步骤 1:命名空间与镜像准备

kubectl create namespace coderoadmap --dry-run=client -o yaml | kubectl apply -f -
kubectl config set-context --current --namespace=coderoadmap

镜像二选一:

  • 真镜像:把 docker-essentials 构建的 backend 导入本地集群(不推仓库的本地镜像必须 load):
minikube image load your-backend:1.0.0
  • 占位镜像:没有现成镜像就用 nginx:1.27-alpine 走通全部对象,之后再换真 tag。

步骤 2:先 apply 配置与密钥(顺序很重要)

:

backend-config.yaml
apiVersion: v1
kind: ConfigMap
metadata:
  name: backend-config
data:
  SPRING_PROFILES_ACTIVE: "prod"
  DB_HOST: "192.168.49.1"        # minikube 里宿主机的固定网关地址(Compose 的 MySQL 在宿主机)
  REDIS_HOST: "192.168.49.1"

backend-secret.yaml:

apiVersion: v1
kind: Secret
metadata:
  name: db-secret
type: Opaque
stringData:
  DB_PASSWORD: "change-me-demo"
kubectl apply -f backend-config.yaml -f backend-secret.yaml
kubectl get cm,secret

真实口令不要进 Git;本课用演示值,键名结构照搬即可。apply 顺序:配置/密钥 → 工作负载,否则 Pod 卡 CreateContainerConfigError。

步骤 3:apply 完整的 Deployment 与 Service

backend-deploy.yaml(占位镜像版,端口 80;真镜像把 image 换掉、探针与端口换成 8080 + /actuator/health):

apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 2
  revisionHistoryLimit: 5
  selector:
    matchLabels:
      app: backend
  template:
    metadata:
      labels:
        app: backend
    spec:
      containers:
        - name: api
          image: nginx:1.27-alpine
          ports:
            - containerPort: 80
          envFrom:
            - configMapRef:
                name: backend-config
          env:
            - name: DB_PASSWORD
              valueFrom:
                secretKeyRef:
                  name: db-secret
                  key: DB_PASSWORD
          readinessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 5
            periodSeconds: 5
          livenessProbe:
            httpGet:
              path: /
              port: 80
            initialDelaySeconds: 15
            periodSeconds: 10
          resources:
            requests:
              cpu: "100m"
              memory: "128Mi"
            limits:
              cpu: "500m"
              memory: "256Mi"
---
apiVersion: v1
kind: Service
metadata:
  name: backend
spec:
  selector:
    app: backend
  ports:
    - name: http
      port: 80
      targetPort: 80
kubectl apply -f backend-deploy.yaml
kubectl get pods -l app=backend -w
kubectl get endpoints backend

验收:Pod 全部 Running 且 READY 1/1,Endpoints 有 2 个 IP。

步骤 4:API 冒烟

kubectl port-forward svc/backend 18080:80
# 另开终端
curl -sS http://127.0.0.1:18080/ | head -3

真 backend 镜像时改用:curl http://127.0.0.1:18080/actuator/health,应返回 {"status":"UP"}。失败按三板斧定位:describe 看 Events → logs 看应用 → get endpoints 看挂载。

步骤 5:发布与回滚演练

kubectl set image deployment/backend api=nginx:1.25-alpine
kubectl rollout status deployment/backend
kubectl rollout history deployment/backend
kubectl rollout undo deployment/backend
kubectl rollout status deployment/backend
kubectl get pods -l app=backend

应完整观察到:新旧 Pod 交替 → revision 记录 → 回到上一版本。对照本站发版:tag 由 CI 产出、集群只消费;回滚不需要重新构建,只回到上一个 revision。

步骤 6:可选 Ingress 与复盘

若第 9 课的 ingress 插件仍启用,把 Ingress 的 namespace 对齐后 apply(参考第 9 课清单),用 curl -H "Host: app.local" http://$(minikube ip)/ 再冒烟一次。

在笔记写下三行复盘:

  1. 与 docker compose up 比,多了哪些对象?(Deployment/Service/CM/Secret/探针/资源声明)
  2. 排错多了哪两步?(describe 事件层、endpoints 健康层)
  3. MySQL 放哪最省心?(集群外/托管,DB_HOST 指外部地址)

保留资源可继续练手;清场:

kubectl delete namespace coderoadmap

讲清楚要点

  1. 标签串联一切:Deployment 的 selector、Service 的 selector、HPA 目标、排障命令全靠 app=backend——命名规范在第一天就定死。
  2. apply 顺序即依赖顺序:Namespace → ConfigMap/Secret → Deployment → Service → Ingress;用「先配置后负载」避免 CreateContainerConfigError。
  3. 验收看 Ready 与 Endpoints,不看 Running:Running 只代表进程活着,Ready + Endpoints 才代表「能接流量」——这是发布验收的硬标准。
  4. 镜像 tag 可追溯是回滚的前提:CI 产出的固定 tag + revisionHistoryLimit 保历史,undo 才有明确落点;:latest 是回滚噩梦。
  5. 探针与依赖耦合是「保护」不是「故障」:MySQL 未就绪时 readiness 失败、摘流、稍后自愈——K8s 不保证启动顺序,但保证最终可用。
  6. 本站全貌 = 本课清单 × 2 + 存储 + 入口:platform 再来一套同样的 Deployment+Service,MySQL/Redis 外置,Ingress 聚合 / 与 /api——你已经能推演出整站的部署图。

你可能会懵的地方

  • ImagePullBackOff(用了自己的镜像时)? 本地构建的镜像不在 minikube 里:minikube image load 镜像:tag,或推送到可访问仓库并配 imagePullSecrets(私有仓库)。

  • 连不上 MySQL? 集群内 Pod 访问宿主机 Compose 的 MySQL,minikube(docker 驱动) 用网关地址 192.168.49.1(即 Docker 网桥的宿主 IP);云集群用内网地址或 ExternalName。MySQL 还要放行该网段并确认账号 host。

  • 要不要一上来就 Helm? 先手写清楚每个对象(本课价值所在),Helm 只是把这套清单模板化、参数化——下一个 track 的事。不理解对象直接上 Helm,排错会退化成「改 chart 碰运气」。

  • platform 和 backend 谁先上? 先 API 后前端:backend 冒烟通过后再部署 platform 并配 Ingress 分流,问题域一次只有一个。

  • 内存里的 Compose 还要保留吗? 保留。本地开发 Compose 最顺手,K8s 清单用于「准生产验证」——两套配置共享同一套键名约定(第 7 课),迁移成本已降到最低。

错法对照

错法问题正解
清单散落在终端历史里环境不可复现全部文件化、进仓库
Service 端口与容器端口不一致Endpoints 有 IP 但连不通核对 port/targetPort/containerPort
用 :latest 且缓存旧镜像「更新了却没变」钉 tag,必要时 --image-pull-policy=Always
验收只看 Running流量打到未 Ready 实例看 READY 与 get endpoints
只发布不演练回滚真故障时手忙脚乱每次发布练习必做一次 undo

卡点急救

  1. Pod 卡 CreateContainerConfigError:引用的 ConfigMap/Secret 名或 key 缺失——describe 点名缺谁,按「先配置后负载」补 apply。
  2. Endpoints 为空 / curl 拒绝连接:selector 与标签对账 → Pod READY 是否 1/1 → Service 端口与容器端口是否一致;逐层收窄。
  3. undo 之后服务仍异常:回滚到的 revision 本身就有问题,或配置对象(CM/Secret)已被改而未随版本回退——回滚范围要包含「镜像 + 配置」整体,这正是「清单进 Git」的意义。

面试常问

  • 描述你把一个 Spring Boot 服务部署上 K8s 的完整流程。 ① CI 构建镜像推仓库(固定 tag);② 编写清单:ConfigMap(配置外置)+ Secret(口令)+ Deployment(2 副本、readiness/liveness 指向 /actuator/health、requests/limits、envFrom/env 注入)+ Service(ClusterIP);③ apply 顺序:配置 → 负载 → Service;④ 验收:Pod Ready、Endpoints 就绪、port-forward/Ingress 冒烟;⑤ 发布:set image 或改清单触发滚动更新,rollout status 观察;⑥ 异常则 rollout undo 回滚。数据库采用托管或集群外,通过 Service 名/ExternalName 连接。

  • K8s 里服务连不上,你的排查套路是什么? 自底向上四层:① Pod 层——get pods 看状态,异常类型对号(ImagePullBackOff 查镜像、CrashLoopBackOff 查 logs --previous、Pending 查资源/调度);② 事件层——describe 看 Events 的关键报错;③ 网络层——get endpoints 是否有健康后端(标签、readiness);④ 入口层——Service 端口映射、Ingress 规则与 Controller。配合 kubectl run curl 在集群内复现,把「网络问题」和「应用问题」分开。

  • 为什么生产更倾向「无状态服务上 K8s、数据库托管」? K8s 的核心优势(副本弹性、滚动发布、自愈调度)天然匹配无状态服务;数据库的核心诉求(稳定 IO、备份恢复、主从切换)在云托管上更成熟省心。混合架构用稳定网络标识打通,兼顾弹性与数据安全,也是多数团队的性价比最优解——强行把一切塞进集群只会同时承担两种复杂度。

自测三问

  1. 写出本课最低资源集合及其 apply 依赖顺序。
  2. Endpoints 为空时,你的三层排查动作分别是什么?
  3. 若只把 backend 上 K8s、MySQL 留在宿主机 Compose,DB_HOST 应填什么?凭什么?

小结一句话

用 Namespace+ConfigMap+Secret+Deployment+Service 在本地集群跑通 backend 的部署、冒烟、滚动与回滚,即完成本 track 的主路径闭环——下一步把这套清单模板化进 Helm 与 GitOps 流水线。

延伸

  • Deploying an application(官方教程)
  • Helm(下一步方向:把本课清单模板化、参数化,管理多环境发布)
  • 下一课预告:本 track 到此收官。建议的下一步:① 把本课清单提交进你的仓库并跑通一次真实 CI 发布;② 进入 Helm/GitOps 进阶,把「手写 apply」升级为「声明式流水线」;③ 备考 CKA 巩固集群层知识。
加载本节练习…
← 上一课RBAC 与安全基础