DevOps 综合实战从 Git 提交到 K8s 部署的全链路这是本系列的最后一篇咱们把前面学的 Docker、K8s、Jenkins 这些散件串成一条完整的交付链路。一、问题引入技术都会就是不会发版你有没有遇到过这种情况团队里小王会写 Dockerfile小李会搭 Jenkins老张会玩 Kubernetes。但一到发版那天群里还是炸锅“我代码提交了谁去服务器上打包”“这个镜像 tag 是啥latest还是v1.2.3”“K8s 上怎么还没更新是不是 YAML 写错了”“完了线上出问题了回滚回哪个版本”说白了单点技术大家都会但没人能把它们串成一条自动化流水线。结果就是发版靠手工、沟通靠吼、回滚靠猜。我当年也在这个坑里摸爬滚打过。那时候我们团队刚转型 DevOps学了 Docker 觉得真香学了 K8s 觉得高大上结果真正发版的时候我还是得半夜 SSH 上服务器手动docker build、docker push再kubectl apply。一套操作下来手心全是汗。那么问题来了怎么把 Git 提交、自动构建、镜像推送、K8s 部署这四件事连成一条自动化的链路这就是今天要聊的主题。二、方案分析先画一张大图在动手之前咱们先把整条链路想清楚。我一开始想的是能不能让 Jenkins 定时去拉代码可以但不够优雅。后来改成了Git Webhook 触发代码一推就自动干活这才对味。最终的架构大图是这样的┌─────────────┐ push ┌─────────────┐ │ 开发者本地 │ ──────────── │ GitLab/GitHub│ │ (git push) │ │ 代码仓库 │ └─────────────┘ └──────┬──────┘ │ webhook ▼ ┌─────────────┐ │ Jenkins │ │ CI/CD 引擎 │ └──────┬──────┘ │ 触发 Pipeline ▼ ┌────────────────┼────────────────┐ │ │ │ ▼ ▼ ▼ ┌─────────┐ ┌─────────┐ ┌─────────┐ │ 拉代码 │ │ 跑测试 │ │ 构建镜像 │ │ (git) │ │ (mvn) │ │(docker) │ └────┬────┘ └────┬────┘ └────┬────┘ │ │ │ └───────────────┼───────────────┘ ▼ ┌─────────────┐ │ 推送镜像 │ │ Harbor/ │ │ Docker Hub │ └──────┬──────┘ │ ▼ ┌─────────────┐ │ K8s 集群 │ │ 更新部署 │ │(kubectl/helm)│ └──────┬──────┘ │ ▼ ┌─────────────┐ │ 应用对外 │ │ 提供服务 │ └─────────────┘这张图就是咱们今天的作战地图。核心链路只有四步Git 提交触发 WebhookJenkins 自动构建 测试Docker 镜像推送到私有仓库K8s 更新 Deployment接下来咱们一步一步拆解。三、实现过程Step by StepStep 1Git Webhook 触发 Jenkins这一步的目标很简单代码一提交Jenkins 就知道该干活了。在 GitLab 里配置 Webhook 地址http://your-jenkins-server:8080/project/my-springboot-app然后在 Jenkins 里创建一个 Pipeline 项目勾选 “Build when a change is pushed to GitLab”。Jenkinsfile 的开头长这样pipeline{agent any// 关键定义环境变量后面到处都要用environment{IMAGE_NAMEharbor.company.com/app/my-service// 坑1预警千万别用 latest后面细说IMAGE_TAG${BUILD_NUMBER}-${GIT_COMMIT.take(7)}}stages{stage(Checkout){steps{// 拉取最新代码git branch:main,url:https://gitlab.company.com/app/my-service.git}}// ... 后面继续}}关键点IMAGE_TAG我用的是构建号 Git 短哈希比如42-a3f8d2e。这样每个镜像都有唯一身份出了问题一眼就能定位到代码版本。Step 2Jenkins 里构建和测试代码拉下来了先跑测试。别嫌麻烦这一步是救命用的。我吃过亏有次为了赶时间跳过测试结果把一个有 NPE 的代码推到了线上半夜被老板打电话骂醒。stage(Build Test){steps{sh # Maven 打包跳过测试不咱们要跑测试 mvn clean package -DskipTestsfalse }}测试通过后开始构建 Docker 镜像。Dockerfile 不用写得多复杂核心就这几层# 第一阶段用 Maven 镜像编译 FROM maven:3.9-eclipse-temurin-17-alpine AS builder WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests # 第二阶段用 JRE 镜像运行体积更小 FROM eclipse-temurin:17-jre-alpine WORKDIR /app # 关键只复制构建产物不复制源码 COPY --frombuilder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]关键点多阶段构建能大幅减少最终镜像体积。第一阶段用 Maven 镜像几百 MB第二阶段只用 JRE 镜像几十 MB生产环境只跑第二阶段。Step 3推送镜像到 Harbor镜像构建好了得放到私有仓库里。咱们用的是 Harbor企业级首选。stage(Push Image){steps{sh # 登录 Harbor凭据提前在 Jenkins 里配好 docker login harbor.company.com -u \${HARBOR_USER} -p \${HARBOR_PASS} # 打标签并推送 docker build -t \${IMAGE_NAME}:\${IMAGE_TAG} . docker push \${IMAGE_NAME}:\${IMAGE_TAG} # 顺手也推一个 latest不后面告诉你为什么最好别这么干 }}Step 4更新 K8s Deployment到了最激动人心的一步让 K8s 用上咱们的新镜像。这里有两种做法做法 A直接 kubectl set image简单直接stage(Deploy to K8s){steps{sh # 关键更新 Deployment 的镜像版本 kubectl set image deployment/my-service \ my-service\${IMAGE_NAME}:\${IMAGE_TAG} \ -n production # 等待滚动更新完成 kubectl rollout status deployment/my-service -n production }}做法 B用 Helm 升级更规范stage(Helm Upgrade){steps{sh helm upgrade --install my-service ./helm-chart \ --set image.tag\${IMAGE_TAG} \ --namespace production }}我推荐做法 B。因为 Helm 可以把 K8s 的所有配置Deployment、Service、Ingress、ConfigMap打包管理升级和回滚都特别方便。四、基础设施即代码IaC是啥什么时候用链路跑通了但还有一个问题Jenkins、Harbor、K8s 集群本身是怎么搭起来的总不能每次新建环境都手动点鼠标吧这时候就要请出IaCInfrastructure as Code基础设施即代码了。Ansible配置管理的利器Ansible 更像一个远程执行脚本的工具。你写一份 playbook它能帮你批量安装 Java、配置 Nginx、启动服务。# 伪代码用 Ansible 安装并启动 Docker-hosts:k8s_nodestasks:-name:安装 Dockeryum:name:docker-cestate:present-name:启动 Docker 服务service:name:dockerstate:startedenabled:yes什么时候用 Ansible服务器已经有了需要批量配置软件环境部署应用、改配置文件、重启服务Terraform云资源的建筑师Terraform 专注的是从无到有。你想在阿里云上创建 10 台 ECS、一个 VPC、一个 SLBTerraform 一行命令搞定。# 伪代码用 Terraform 创建阿里云 ECS resource alicloud_instance k8s_node { count 3 image_id centos_7_9_x64_20G_alibase_20231231.vhd instance_type ecs.c7.xlarge tags { Name k8s-node-${count.index} } }什么时候用 Terraform需要创建云资源虚拟机、数据库、负载均衡多环境开发/测试/生产保持一致简单总结Terraform 负责造房子Ansible 负责装修房子。两者可以搭配使用。五、DevOps 文化与 SRE 实践技术链路搭好了但 DevOps 不只是工具链更是一种文化。这里分享几个我们在实践中坚持的 SRE 理念。1. Secrets 安全管理K8s 的 Secret 千万别硬编码在 YAML 里我见过有团队把数据库密码直接写在 Git 仓库的deployment.yaml里结果代码一开源密码全网裸奔。正确做法是# 错误示范 ❌env:-name:DB_PASSWORDvalue:123456# 千万别这么干# 正确做法 ✅env:-name:DB_PASSWORDvalueFrom:secretKeyRef:name:db-secret# 提前用 kubectl create secret 创建key:password更进一步可以用Vault或External Secrets Operator把密钥存在专门的密钥管理系统里K8s 只存引用。2. SLA / SLO / SLI这些词听着高大上其实很好理解SLA对外承诺的服务等级比如全年可用性 99.9%SLO内部目标比如接口 P99 延迟 200msSLI具体指标比如错误率 0.1%说白了就是先定义清楚什么叫好再用监控数据验证是不是真的好了。3. 故障演练Chaos Engineering咱们团队每个月会搞一次故障演练随机杀掉一个 Pod看看服务能不能自动恢复或者把某个依赖服务搞挂看看熔断降级有没有生效。工具推荐Chaos Mesh在 K8s 上搞破坏特别方便# 伪代码随机杀掉一个 Pod测试服务恢复能力apiVersion:chaos-mesh.org/v1alpha1kind:PodChaosmetadata:name:pod-kill-examplespec:action:pod-killmode:oneselector:namespaces:-productionlabelSelectors:app:my-service4. 容量规划别等到线上卡死了才想着扩容。平时就要关注CPU / 内存使用率趋势QPS 和响应延迟数据库连接池是否吃紧Prometheus Grafana 这套组合基本成了标配提前设好告警阈值防患于未然。六、踩坑记录那些年我流过的泪坑 1镜像版本管理混乱回滚找不到北场景早期我们图省事所有镜像都打成latest标签。有一天线上出了问题我想回滚结果发现latest已经被新构建覆盖掉了根本不知道上一个稳定版本是哪个。教训永远不要用latest作为生产环境的镜像标签每个镜像标签必须唯一推荐构建号-Git短哈希或语义化版本v1.2.3Harbor 里开启镜像保留策略定期清理过期镜像坑 2K8s Secrets 硬编码在 YAML 里密码泄露场景有同事为了方便直接把数据库密码写在了 Git 仓库的 YAML 文件里。后来仓库权限调整被实习生误操作公开了密码直接暴露。教训敏感信息绝不进 Git用kubectl create secret或 Vault 管理密钥Git 仓库里只放配置的骨架不放血肉坑 3Jenkins 和 K8s 网络不通部署失败场景Jenkins 跑在公司的内网服务器上K8s 集群在阿里云上。Pipeline 最后一步kubectl apply死活连不上报错Unable to connect to the server。排查过程先检查 Jenkins 服务器能不能curl到 K8s API Server —— 不通发现是安全组规则没开 Jenkins IP 的白名单更深层的问题是Jenkins 直接操作 K8s耦合太紧最终方案在 K8s 集群里部署 Jenkins Agent用 K8s Plugin让构建和部署都在集群内部完成或者改用 GitOps 方案比如 ArgoCDJenkins 只负责构建镜像部署由 ArgoCD 监听 Git 变更自动完成七、验证与总结咱们来回顾一下今天这条链路打通之后发版变成了什么样以前本地手动打包SSH 上服务器上传 jar 包手动改配置重启服务祈祷别出问题现在git push去喝杯咖啡收到 Jenkins 通知部署成功这就是 CI/CD 流水线的魅力。不是让你更忙而是让你更闲。核心知识点回顾环节技术/工具核心作用代码管理Git GitLab/GitHub版本控制 Webhook 触发持续集成Jenkins / GitLab CI自动构建、测试、打包容器化Docker环境一致性一次构建到处运行镜像仓库Harbor安全存储和分发镜像容器编排Kubernetes自动化部署、扩缩容、故障恢复包管理HelmK8s 应用的标准化打包和发布基础设施Terraform / Ansible环境创建和配置的自动化可观测性Prometheus Grafana监控、告警、容量规划GitOpsArgoCD声明式持续部署学习路径建议如果你也想系统学习 DevOps我建议按这个顺序来先学 Git 工作流Git Flow / Trunk-Based再学 Docker镜像、容器、Dockerfile、网络接着上 K8sPod、Deployment、Service、Ingress然后搭 Jenkins Pipeline把构建和部署串起来最后补监控和 GitOpsPrometheus、ArgoCD别想着一口吃成胖子一步一步来每打通一个环节都是实实在在的进步。八、写在最后到这里咱们的 DevOps 系列就正式收官了。从 Nginx、Git到 Docker、Jenkins、Prometheus、K8s最后到今天的 DevOps 全链路一路走来不容易。如果你也跟着读到了这里恭喜你已经具备了从开发到运维的完整视野。当然技术这条路没有终点。今天的方案也不是银弹可能你团队用的是 GitLab CI 而不是 Jenkins用的是 AWS 而不是阿里云用的是 ArgoCD 而不是 Helm —— 都没关系核心思路是相通的。最后想问问你你们团队的发版流程是怎样的有没有遇到过比我更离谱的踩坑经历对于 CI/CD 流水线你有什么更好的实践想分享欢迎在评论区交流咱们一起进步