ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

基于Kubernetes的DevOps工作流:持续交付与云效流水线实战

基于Kubernetes的DevOps工作流:持续交付与云效流水线实战 简介一份面向DevOps工程师、云原生架构师及Kubernetes实践者的技术分享资料出自郑云龙在云效体系中的演讲围绕构建基于Kubernetes的DevOps工作流展开重点讲解容器化场景下持续集成、持续交付与云平台协同的落地方法。资源包为单个PDF文档大小约3.5MB包内共1个文件便于离线阅读与知识梳理。目前已有97人学习下载。内容基于业界DevOps理念结合云效、Sigma、Pouch等工具链梳理了从代码提交、镜像构建、模板渲染到集群发布的全链路讨论了入口网关、服务控制器、Istio等流量治理组件的作用并涉及多阶段构建优化镜像、无Tiller的模板化部署等实用技巧同时给出应用工程目录结构与CI流程的典型设计。读者可从中获得一套可参考的云原生DevOps工作流搭建思路适合正在规划或优化容器化发布体系的技术团队借鉴无论是初次接触云原生交付还是已有平台建设经验都能找到对应阶段的实践参考。1. 从一次真实分享说起为什么要在Kubernetes上搭DevOps工作流很久之前我就关注过郑云龙在云效技术社区的那次分享讲的正是如何基于Kubernetes构建一套完整的DevOps工作流。说实话当时听完最直接的感受是终于有人把“容器化之后怎么做持续交付”这件事讲得既接地气又不失深度了。毕竟对很多团队来说Kubernetes本身已经是个门槛再往上去设计和落地一个可复用的发布流水线更是容易卡壳。先给还不熟悉这块内容的朋友补个背景。DevOps的核心就四个字持续交付——把代码变成线上可用的功能这个过程中的构建、测试、部署、发布、回滚全部尽量自动化、标准化、可追溯。而Kubernetes下文简称K8s解决的是“应用跑在哪、怎么调度、怎么扩展、怎么自愈”的问题相当于给DevOps提供了一层非常稳定的基础设施底座。这两者结合解决的是很多团队都会遇到的现实困境环境不一致开发环境能跑测试环境崩生产环境更是玄学。发布全靠手工上线窗口长、操作步骤多、人一紧张就容易点错。版本管理混乱镜像Tag乱起部署的到底是哪个版本没人说得清楚。扩容缩容费劲流量一上来手忙脚乱流量走了又舍不得关机器。基于Kubernetes的DevOps工作流正是冲着这些问题去的。它要做的是把“代码提交”到“应用上线”这条路彻底打通让每一次发布都像走流水线一样顺畅可控。这篇文章我结合自己的落地经验把当时分享里最核心的思路、工具选型、实操环节以及踩过的坑完整拆开来讲。2. 整体设计思路拆解两条主线、四个环境、一个核心原则2.1 先想清楚要解决什么问题再选工具很多团队一上来就急着装Jenkins、配GitLab CI、买个云效套餐结果工具买了一大堆流程还是乱的。我当时自己带团队踩过这个坑所以这次设计工作流时特意先问了自己三个问题第一代码提交后多久能知道这次改动是不是好的这决定了CI持续集成要做到什么程度。第二从镜像构建完成到生产环境生效中间需要哪些人工确认这决定了CD持续部署的自动化程度和审批关卡。第三出了事故怎么最快恢复这决定了回滚机制和版本管理策略。这三个问题想明白整个工作流设计就顺了。云效在这套体系里承担的是“调度中枢”的角色负责把代码托管、制品管理、K8s部署这些环节串起来而不是让每个环节各自为政。2.2 工作流的主线设计镜像才是唯一的交付物我认为这套设计里最值得借鉴的一点是——整个工作流围绕镜像来组织而不是围绕机器或服务来组织。换句话说从代码仓库拉下来的代码经过编译、测试、构建镜像、推送镜像仓库最后部署到K8s集群这条链路里每一环节的输入和输出都尽量统一到“镜像”这个载体上。这样做的好处非常明显环境一致性天然成立。同一个镜像在测试环境跑什么样在生产环境跑什么样行为基本一致。回滚变成了“换镜像版本”这么简单的一件事而不是重新部署一套旧代码。团队的关注点从“怎么部署”转移到“怎么把镜像构建好、验证好”上。整个工作流分成两条主线一条是开发侧从代码提交到镜像构建完成一条是运维侧从镜像部署到生产验证完成。云效在中间做的是把这两条线串起来并给每个环节打上状态标记方便追溯和审计。2.3 四套环境的配置策略郑云龙分享里提到的一个思路我特别认同环境治理不要贪多够用就好。当时推荐的配置是四套环境环境用途对应分支自动部署策略开发环境开发者联调自测feature/* 或 dev 分支代码提交后自动部署无需审批测试环境功能验证、接口联调test 分支或release候选分支自动部署保留最近N个版本供回退预发环境生产前的最后验证生产发布候选Tag手动触发需负责人确认生产环境正式对外服务release Tag手动触发必须审批支持灰度发布这套配置的核心思想是越是靠近生产的环境自动化程度越高但人工确认的环节要补上。开发环境本来就不是“稳定”的代名词代码随时提交随时部署没人拦着而生产环境一旦出问题就是事故所以宁可多一道审批也要把风险挡住。关于镜像仓库的版本管理我补充一个教训。早期我们用镜像Tag来标识环境比如order-service:dev、order-service:prod结果环境一多就乱了同一个镜像在好几个环境被反复覆盖想定位线上跑的到底是哪个版本查起来非常痛苦。后来统一改成“代码版本号构建序号”的方式比如order-service:20241105-1423-a9f3e2d这样哪个环境部署哪个镜像一目了然而且不会互相覆盖。这个改动看起来小但对排查线上问题的效率提升是质变级的。3. 核心细节解析云效流水线的关键节点与参数配置3.1 四个核心环节构建、推送、部署、验证云效流水线的设计思路跟主流CI/CD工具是相通的核心环节是这四个构建、推送、部署、验证。下面我把每个环节的要点拆开讲。构建环节Build从代码仓库拉取指定分支代码在云端执行编译和单元测试。这里有两个关键配置——构建环境和构建命令。云效支持自定义构建镜像比如Java服务用Maven 3.8 JDK 17前端项目用Node 18 npm按需选择即可。构建命令建议固定成项目内的标准脚本比如mvn clean package -DskipTestsfalse把质量校验前置到构建阶段。推送环节Push构建产物生成之后云效会自动把镜像推送到制品仓库比如阿里云容器镜像服务ACR。这里有个很多人容易忽略的参数——镜像版本号。不要用默认时间戳我建议格式统一为仓库名:分支名-commit短哈希-构建序号。这样在任何时间点看到镜像Tag就能反推出代码版本和构建来源排查问题不知道能省多少时间。部署环节Deploy云效通过Kubernetes的API与集群交互执行镜像更新操作。这个环节有三个核心参数需要确认集群连接串KubeConfig、命名空间Namespace、工作负载名称Deployment/StatefulSet的名字。我建议为DevOps流程单独建一个Kubernetes的ServiceAccount并只授予相应命名空间的部署权限避免使用集群管理员账号。安全性和可追溯性都要好很多。验证环节Verify部署完成不代表发布成功。云效流水线支持添加健康检查脚本比如调用应用的/health接口或者检查Deployment的Pod副本数是否达到预期。建议在环境变量中配置健康检查地址这一步能挡住不少“部署成功但实际不可用”的问题。3.2 KubeConfig拿不到怎么办两种方案实测实际操作中不少人会卡在“连接Kubernetes集群”这一步——KubeConfig文件获取不到或者不知道放哪合适。我把我试过的两种方案列出来供你参考方案适用场景优点缺点直接用KubeConfig文件大多数K8s集群配置简单通用性强需注意文件过期和权限控制使用云厂商的认证插件阿里云ACK等托管集群动态获取凭证更安全依赖云厂商插件迁移性稍差我的建议是如果是自己搭建的K8s集群直接用KubeConfig文件就行云效一般以Secret的方式存储如果用的是托管的云K8s服务可以看看云效是否有对应的插件直接支持动态凭证少踩很多权限坑。3.3 镜像构建速度优化缓存与分层构建速度是DevOps体验的重要指标。我之前遇到过一个服务每次流水线跑完要20多分钟大家都在等效率极其低下。后来优化了镜像构建方式时间压缩到5分钟左右主要做了三件事第一依赖层缓存。把pom.xml或package-lock.json这些依赖描述文件放在Dockerfile的前面这样依赖不变化时构建系统会直接使用缓存层不用每次重新拉依赖。第二基础镜像固定版本。不要用latest标签比如openjdk:17-slim固定到具体版本避免基础镜像变化导致的不可控差异。第三多阶段构建。构建阶段用包含完整编译工具的镜像运行阶段用精简版运行镜像最终交付的镜像体积能小一大半部署速度自然跟着快。3.4 云效与K8s交互的关键配置云效在部署K8s应用时底层本质上是执行了类似于kubectl set image deployment/xxx xxx镜像地址:版本的操作。所以你在配置部署任务时下面这几项一定要仔细填集群与凭证选择目标集群或上传KubeConfig。命名空间确认目标环境比如dev、test、prod。工作负载选择对应的Deployment名称。镜像更新策略选择“更新镜像版本”指定新的镜像地址和Tag。滚动更新参数比如maxSurge25%、maxUnavailable25%这些参数决定发布时最多允许超出多少个副本、最多允许多少个副本不可用。这里我特别补充一下滚动更新的原理。K8s默认的滚动更新策略不会一次性停掉所有旧Pod然后再起新Pod而是先起一个新的等新的Ready了再停一个旧的过程循环往复直到全部替换完成。这种策略的好处是发布期间不影响服务可用性。但是要注意如果新版本启动很慢比如启动需要两分钟滚动更新的时间也会比较长甚至可能被判定为超时。所以对启动较慢的应用要把Deployment里的progressDeadlineSeconds调大一点否则发布过程中可能会出现“更新卡住”的假象。4. 实操过程从零搭建一套基于云效与K8s的发布流水线4.1 前置准备清单动手之前把这五样东西准备好一个可用Kubernetes集群我之前测试用的是ACK托管版你也可以用kubeadm自建。一个云效企业免费版/标准版都可以标准版的功能更完整。一个可用的容器镜像仓库ACR个人版就够测试用。一个代码仓库云效自带的Codeup或者GitHub都行。一个待发布的应用项目比如一个Spring Boot服务或Node服务。4.2 逐步搭建代码、镜像、环境变量、流水线我按当时配置的流程一步步带你走一遍同时会把关键参数和选择理由说清楚。第一步准备代码仓库与构建文件假设你有一个Spring Boot项目放在云效代码仓库里。项目根目录要有Dockerfile基础镜像固定版本示例FROM maven:3.8-openjdk-17 AS builder WORKDIR /app COPY pom.xml . RUN mvn dependency:go-offline COPY src ./src RUN mvn package -DskipTests FROM openjdk:17-slim WORKDIR /app COPY --frombuilder /app/target/*.jar app.jar EXPOSE 8080 ENTRYPOINT [java, -jar, app.jar]这个Dockerfile用了多阶段构建第一阶段负责编译打包第二阶段只保留运行环境。mvn dependency:go-offline这步是为了让依赖下载走缓存构建速度会快很多。第二步创建云效流水线在云效流水线页面选择“新建流水线”选“Kubernetes部署”模板。模板会自动生成四个阶段的骨架源代码、构建镜像、推送镜像、部署K8s。你只需要填好每一阶段的参数。构建阶段参数参考参数项推荐值说明构建环境Maven 3.8 JDK 17与项目实际依赖匹配构建命令mvn clean package -DskipTestsfalse测试失败则中止后续流程Dockerfile路径./Dockerfile与项目实际情况对齐镜像名称registry.cn-hangzhou.aliyuncs.com/namespace/order-service注意仓库命名空间第三步配置镜像推送与版本号在“构建镜像”阶段配置镜像仓库地址和镜像版本号。我当时用的是云效内置变量版本号模板如下${DATETIME}-${COMMIT_ID:0:7}COMMIT_ID是代码提交的短哈希。这样生成的镜像Tag比如20241105-1423-a9f3e2d既能看出构建时间又能溯源到代码提交。第四步配置部署任务在“Kubernetes部署”阶段选择集群填入命名空间和工作负载名称镜像地址引用上一步的产物变量。云效会自动生成部署单执行滚动更新。这里会有一些高级选项比如发布策略滚动更新、副本数、CPU和内存的资源限制。生产环境建议都填上测试环境可以简化。第五步添加人工确认与健康检查在部署到生产环境之前加一个人工确认的节点。云效支持在流水线中插入“人工卡点”只有指定的负责人点“通过”之后后续的部署任务才会继续。这一步非常重要我把生产环境的人工确认设为必须项之前有一次就是因为少了确认开发把没测好的代码直接推上了生产那种教训一次就够了。健康检查脚本放在部署之后用一段Shell脚本定期探测应用健康接口for i in {1..30}; do HEALTH_CODE$(curl -s -o /dev/null -w %{http_code} http://order-service:8080/health) if [ $HEALTH_CODE 200 ]; then echo health check passed exit 0 fi sleep 5 done echo health check failed exit 1这个脚本30秒内连续探测健康接口成功即退出超过30次仍不通过则判定部署失败流水线自动终止。注意脚本里的服务名要换成你实际的Service名称或Pod地址。4.3 实际执行效果发布一次需要多久配置完成后我实测了一次完整发布流程。开发环境从代码Push到服务更新完成大概耗时6-8分钟含镜像构建和部署生产环境因为多了人工确认和额外验证约15分钟。对比以前手动打包上传开发机再重启的效率完全是两种节奏。5. 常见问题与排查技巧这些坑我替你踩过5.1 Kubernetes Dashboard访问不了先查这三个地方很多人搭建完K8s想用Dashboard可视化看看集群状态结果发现访问不了。我排查过很多次90%是这三个原因端口映射没暴露Dashboard默认是ClusterIP类型的Service集群外部访问不了。解决办法是改成NodePort或者用kubectl proxy转发推荐后者更安全kubectl proxy然后本地浏览器访问http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/。Token权限不够创建Dashboard中的用户时如果用默认ServiceAccount往往没有cluster-admin权限。需要单独创建管理员用户绑定cluster-admin角色否则页面能进但很多操作没权限。证书不受信任自签证书会导致浏览器报警。可以下载Dashboard的证书配置到本地或者跳过校验访问不过生产环境建议还是把证书配置正确。5.2 镜像拉取失败ImagePullBackOff怎么排查K8s最经典的问题之一就是Pod卡在ImagePullBackOff。我总结了一套排查顺序kubectl get pods先看Pod状态。kubectl describe pod xxx查看Events里的具体报错。最常见的错误是ImagePullBackOff: pull access denied说明镜像仓库认证失败需要配置imagePullSecret或者镜像地址写错了。如果是私有镜像仓库记得在Deployment的spec.template.spec.imagePullSecrets中指定有效的Secret。我之前碰到过一次特别玄学的问题镜像地址明明没问题但一直拉取失败。后来发现是镜像仓库和K8s集群不在同一个地域内网访问不了被迫走公网而公网拉取大镜像超时。最后把仓库和集群迁移到同一地域问题才彻底解决。这个点很多人会忽略云服务的“地域”必须对齐否则私网互联就是空谈。5.3 部署成功但服务不可用健康检查的必要性有段时间我们经常遇到“流水线显示发布成功但实际访问报错”的情况。排查到最后发现Deployment里的readinessProbe就绪探针没有配置。没有就绪探针时K8s只要Pod进程起来了就会把它加入Service的负载均衡流量一进来就打到“还没准备好”的Pod上自然报错。我之前踩过这个坑后来总结出个经验配置就绪探针时探针路径一定要选那种能真实反映业务可用性的接口别拿一个空返回的根路径糊弄。比如根路径/只要服务起来就返回200但/health它会顺带检查数据库连接或缓存状态。用前者做探针数据库挂了照样报健康这是自欺欺人。配置参考readinessProbe: httpGet: path: /health port: 8080 initialDelaySeconds: 10 periodSeconds: 55.4 云效流水线构建慢的优化思路这个前面已经提到一部分这里再补充一个常见的原因Docker镜像构建时的上下文过大。如果你在项目根目录执行构建而项目里有node_modules或target这类大目录每次构建时这些文件都会被打包发送给构建服务效率极低。解决办法是在项目根目录放一个.dockerignore文件把这些大目录排除掉node_modules target .env .git *.log5.5 关于Kubernetes面试的一些题外话近期因为K8s热度过高问的人多了我发现不少开发者在面试时会被问到“K8s的Deployment滚动更新策略”和“Pod的调度原理”。其实这些内容在做DevOps工作流时都会接触到。如果能把这里提到的滚动更新参数、健康检查机制讲清楚面试基本是够用的。具体的面试题集锦我不在这里展开但你顺着上面讲的这五大块去梳理胜在体系完整比零散背题要稳得多。6. 运维侧的一些额外动作环境隔离与权限管理6.1 命名空间隔离不要所有环境挤在一起如果你在同一个集群里跑多个环境一定要用命名空间区分比如dev、test、prod各自独立。这样做的理由很简单避免配置混乱导致的相互影响。之前有团队把测试环境和生产环境放在同一个命名空间有一次测试环境发布配置写错直接把生产服务的Deployment给覆盖了差点酿成故障。命名空间隔离之后配合K8s的Role-Based Access Control可以为不同团队创建不同的权限范围做到“谁只能操作谁的环境”。6.2 资源配额防止某个环境把集群资源吃光在K8s里ResourceQuota和LimitRange是环境治理里容易被忽略但又非常关键的工具。比如给生产环境设置最大CPU 20核、内存20Gi超了就拒绝调度这样即使误操作也不会拖垮整个集群。这对测试环境尤其重要因为测试有可能会造大流量搞挂自己。6.3 镜像安全扫描容器镜像里的安全漏洞是很多DevOps团队容易忽视的环节。云效和ACR都支持镜像安全扫描可以在镜像推送后自动触发扫描在高危漏洞未修复时阻断部署到生产环境。我目前的做法是在“生产部署”节点前加一个“镜像扫描”节点一旦发现高危漏洞就中止流水线。这个环节加完之后生产环境的安全事件确实少了很多。7. 最后的几点实操建议与个人体会整套基于Kubernetes的DevOps工作流搭建起来其实没有太高深的技术门槛真正的挑战在于“想清楚边界然后坚持执行”。我回顾自己的落地过程有几条建议给准备动手的团队先从最简单的场景跑通再逐步加功能。我见过不少团队一上来就规划好几个环境、好几条流水线结果一套都没跑好。建议先拿一个非核心应用搭好“开发环境自动部署”这一条最基础的路径团队真正用起来、尝到甜头了再去扩展测试环境、预发环境、灰度发布、镜像扫描这些高阶能力。每个发布版本要做到能说清“代码是谁、镜像是什么、部署到哪”。这是审计和排查事故的基础。流水线中一定要保留这些信息的日志云效在这方面做得比较完善节点日志都有留痕但关键还是团队自己要养成规范使用的习惯。DevOps是一个持续改进的过程不是一次性交付的“项目”。工具搭好之后需要根据团队的发布频率、故障类型、开发反馈不断调整参数。比如滚动更新的超时时间、健康检查的探针路径、灰度发布的流量比例这些没有标准答案只有“最适合你团队”的方案。我在实际使用中一般每隔一两个迭代就会回顾一遍流水线的执行情况看看哪里耗时最长、哪里失败率最高然后针对性优化。如果你正准备在自己的团队里落地这套体系我建议第一步就按我上面说的“最小可行流水线”去搭。搭完之后先跑通、再完善让团队在真实的使用中慢慢沉淀出属于自己的最佳实践。这套路我亲自验证过确实是走得通的。本文还有配套的精品资源点击获取
返回列表