ARTICLE DETAIL

资讯详情

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

DevOps实战:CI/CD、基础设施即代码与网络基础

DevOps实战:CI/CD、基础设施即代码与网络基础 这两年只要聊到软件工程DevOps这三个字母就绕不开。招聘网站上铺天盖地的“DevOps工程师”培训机构的广告恨不得把运维、开发、测试全都塞进这一个词里。但你要是追着任何一个干了五年以上的老运维问一句DevOps是什么他大概率会先叹口气然后跟你说这不是个工具也不是个职位这玩意儿说到底是一种磕磕绊绊中磨出来的工作方式。我入行那会儿还没有DevOps这个说法当时叫“开发运维一体化”听起来比现在朴素得多但做的事儿差不多。后来这个词越来越火火到有点变味了——有人把写Jenkinsfile叫DevOps有人把搭K8s集群叫DevOps还有人把招一个“什么都会一点的全栈运维”叫DevOps。这些说法都对但都不完整。这篇文章我想从根上讲清楚DevOps到底是什么它解决的到底是哪些人的什么痛想往这个方向走的人——尤其是后端开发、传统运维转岗的朋友——需要补哪些计算机网络知识以及我在实际落地过程中踩过的坑。全文不讲虚的尽量让你看完能有个清晰的路线图。1. DevOps到底是什么先从一次凌晨两点的故障说起1.1 一次典型的“开发运维大战”想象一个场景。电商平台要赶在活动日前上线一个新支付模块开发在测试环境里测了三天一切正常。上线当晚运维把代码部署到生产环境结果支付接口直接超时数据库连接数被打满前端页面白屏。开发看了一眼日志说“我们测试环境跑得好好的肯定是你们生产环境配置有问题。”运维看了一眼监控说“这代码一上去CPU直接飙到100%跟我们环境有什么关系”两边都觉得自己没错最后拉了个群吵到凌晨四点活动还是没上成。这不是段子这是DevOps出现之前软件行业的日常。我在早期做运维的时候这种“上线像打仗”的场面见得太多以至于后来哪个项目能平稳上线大家都要发红包庆祝。现在回头看问题的根源根本不是某个人的技术不行而是开发和运维的目标天生就拧着。1.2 开发要变化运维要稳定DevOps就是来解决这对矛盾的开发同学的核心KPI是“功能上线”一个月迭代两个版本都嫌慢最好天天有新功能。运维同学的核心KPI是“系统稳定”恨不得代码一年别动动一次就多一分出事的风险。一个要快一个要稳放到一起自然打架。DevOps的核心思想说到底就是把这两拨人的目标对齐不是让开发迁就稳定也不是让运维无脑求快而是通过一套自动化的流程和工具链让“快速交付”和“稳定运行”同时成立。也就是业内常说的小步快跑频繁发布出了问题能快速回滚。这个概念今天听起来稀松平常但在十年前能做到“每天发布一次”的公司都屈指可数。DevOps真正改变的不是某个工具而是整个软件交付的节奏和团队协作的方式。1.3 拆掉那堵墙DevOps的本质是文化不是岗位我见过很多公司搞DevOps第一步就是成立一个“DevOps团队”招几个什么都会的人然后让其他团队继续按老一套干活。这种做法基本等于换了件马甲继续生病。DevOps的全称是Development和Operations的组合它强调的从来不是“新增一个角色”而是打破开发和运维之间的部门墙。具体拆开有三层文化层开发和运维共同为线上故障负责不再互相甩锅。出了问题不追责到个人而是复盘流程哪里能改进。流程层交付过程被拆成小批次每次变更都走自动化流水线从代码提交到上线全程可追溯。工具层用技术手段把流程固定下来让“手动部署”变成“一键触发”让“环境不一致”变成“代码化描述”。这三层缺一不可。只搞工具不搞文化流水线建得再漂亮开发的代码照样往运维手里一扔就不管了。只搞文化不搞工具团队再同心协力部署还是靠人肉效率上不去。2. DevOps的三大核心实践CI/CD、IaC与可观测性2.1 持续集成与持续交付把上线变成流水线CI/CD是DevOps最出圈的两个缩写也是绝大多数公司落地DevOps的切入点。很多人把CI/CD理解成“用Jenkins/GitLab CI自动打包部署”这个理解没错但不够完整。持续集成Continuous Integration的意思是每个人每天把代码合并到主干分支多次每次合并都自动触发编译和测试尽早发现集成问题。注意关键词是“尽早”——如果每个人各自开发一个月再合并冲突和回归能把人折磨死如果每几小时合并一次问题一冒头就被摁死了修复成本低一个数量级。持续交付Continuous Delivery的意思是代码通过所有自动化测试之后随时可以部署到生产环境部署动作本身是自动化的。再往上一步是持续部署Continuous Deployment连“确认上线”的手动按钮都省了代码合到主干直接自动发布。大部分公司做到持续交付就够用了生产发布前保留一个人工确认环节心里踏实一些。我司的流水线走过这样一个演进过程一开始是半夜定时的shell脚本打包加scp后来换成Jenkins的静态流水线再后来迁到GitLab CI配合Kubernetes做滚动发布。演进的核心驱动力就一个——缩短从“代码提交”到“代码上线”的时间。一条比较标准的流水线大概长这样提交代码 - 静态代码扫描 - 单元测试 - 构建容器镜像 - 推送镜像仓库 - 部署到测试环境 - 自动化接口测试 - 部署到预发环境 - 冒烟测试 - 灰度发布 - 全量发布每一步都有存在的意义。静态扫描和单元测试在最前面是为了最快的失败代码有问题就别往下走了省得浪费构建时间。镜像构建完之后推仓库是为了保证测试环境和生产环境用的是同一个制品杜绝“环境不一致”的借口。灰度发布是为了控制爆炸半径先放5%的流量观察指标没问题再慢慢放大。这里面最容易忽略的是“失败的可恢复性”。很多人设计流水线只考虑一条路走到黑没想过失败之后怎么重跑。我见过一个团队流水线做到一半脚本挂了重新跑的时候发现数据库迁移脚本执行了两次导致数据异常最后花了两天修数据。所以幂等性不是废话流水线里的每个步骤最好都设计成“跑两次和跑一次结果相同”。2.2 基础设施即代码让环境像代码一样可复现传统运维有个著名的痛点叫“雪人服务器”——Snowflake Server意思是每台服务器都像雪花一样独一无二配置文件全靠手工改谁也不知道这台机器上被谁动过什么。今天线上出了问题排查半天最后发现是半年前同事在某台机器上手动装了一个包。基础设施即代码Infrastructure as Code, IaC解决的就是这个问题。思路很简单把服务器、网络、负载均衡这些基础设施的配置写成代码放进Git仓库管理要用的时候通过工具自动创建出来。环境不再是手工作坊而是流水线产物。工具选型上目前主流的分工是Terraform管云上资源比如创建虚拟机、VPC、安全组、负载均衡器偏“资源编排”。Ansible管服务器内部配置比如装软件、改配置文件、启动服务偏“配置管理”。Kubernetes声明式API容器编排描述“我要什么状态”系统自动向这个状态收敛。我个人的建议是别一上来全上先拿一个非核心项目试点。我自己最早是先从Ansible起步的因为公司当时还没容器化一堆物理机和虚拟机要管理。后来上了云才开始用Terraform编排云资源。这两个都熟了之后再去理解K8s的原生声明式能力就顺理成章了。写IaC代码要注意一个关键性质——幂等性。什么叫幂等就是同一个配置应用一百遍结果都是同一个最终状态不会因为重复执行而出错。Terraform和Ansible的设计目标就是幂等的但具体roles、modules能不能做到还得看写的人。比如一个任务是“往配置文件里加一行”如果你用的模块是“存在则跳过不存在则追加”那就是幂等的如果粗暴地用shell命令直接echo追加跑两次就会有两行。这些细节都是实战中才会碰到的。2.3 监控与可观测性没有反馈的DevOps是瞎忙DevOps循环里有一步叫“持续反馈”也就是监控和可观测性。没有这一步流水线再顺也只是在“闭着眼睛发布”。可观测性和监控的区别值得讲一下。监控解决的是“你提前知道你要看什么”的问题比如CPU超过了80%就告警。但很多时候你根本不知道问题会出在哪儿这时候就需要可观测性——也就是通过指标Metrics、日志Logs、链路追踪Traces这三板斧随时能回答“系统现在到底发生了什么”这个问题。一个微服务系统请求从前端打到网关网关调到订单服务订单服务再调库存服务任何一个环节慢了或者挂了用户感知就是“加载不出来”。如果用传统的监控思路每个服务的CPU、内存都看着正常你根本不知道到底哪里慢了。这时候就需要全链路追踪把一次请求串起来的调用链拉出来看一目了然地看到瓶颈在哪一环。我见过很多团队在可观测性上踩的坑有两个。一个是日志打得太随意线上报错连个request_id都不带排查时只能靠猜。另一个是告警配置得有量无质动不动就凌晨三点被短信炸醒但真正业务挂了的告警混在里面反而没注意。后来我们做了一件事把告警收敛到几个核心业务指标上比如支付成功率、下单接口的P99延迟、消息积压量其他的只记录不告警。效果立竿见影告警量少了七成真正的故障一个都没漏。3. DevOps工程师必学的计算机网络知识这是绕不过去的底座3.1 为什么网络对DevOps特别重要把“devops工程师学习的计算机网络”这个关键词放进来看说明很多准备入行的人已经隐约感觉到了DevOps整天打交道的容器、微服务、负载均衡、API网关底层全是计算机网络。如果不懂网络你写出来的部署方案可能根本跑不通出了问题时也只能看着一堆数据发呆。我见过一个工程师容器怎么都连不上数据库他在安全组、防火墙里倒腾了一下午都没搞定最后让我帮忙我随手画了个拓扑——原来是数据库所在的网络ACL里没放行容器所在的子网网段。这种问题懂网络的人看一眼就明白了不懂的人只能在那里瞎试。真实环境下DevOps工程师遇到的大部分问题都可以归结为连通性问题和性能问题而这两类问题都属于计算机网络的范畴。所以计算机网络不是可有可无的加分项而是吃饭的家伙。3.2 必须掌握的八大网络核心知识点第一个就是TCP/IP协议栈。三次握手建立连接四次挥手断开连接这些不是面试题是排查问题的基础。我遇到过线上服务大量TIME_WAIT导致端口耗尽的情况当时就靠这个知识点判断出是短连接没复用后来在连接池配置里加了个keep-alive参数问题就解决了。不懂TCP状态机这种问题根本无从下手。第二个是HTTP和HTTPS。请求方法、状态码、请求头、缓存机制这些都是日常排查的必备。有一次线上接口偶尔超时抓包一看居然是服务端返回的Cache-Control配置不对导致某些代理服务器缓存了不该缓存的响应。很多人一看到HTTP就觉得自己会但真的能把常见状态码、常用请求头、缓存协商逻辑讲清楚的人其实不多。第三个是DNS。域名解析流程、TTL、CNAME、A记录的区别直接影响上线时的故障。我踩过一个典型的坑改了DNS记录但忘了调低TTL结果旧IP的流量在TTL过期之前一直还在新服务已经切走了部分用户还在访问旧地址。如果早点把TTL调低再切就不存在这个问题。第四个是负载均衡。L4和L7区别、健康检查机制、会话保持是做高可用方案必须懂的东西。特别是健康检查很多人配错了检查路径后端服务明明活着负载均衡却判定它不健康把流量全打到了另外一台机器上直接把那台机器打崩。第五个是网络安全组和防火墙。入方向、出方向、协议的端口放行规则看起来简单实际误配率非常高。我自己就干过把生产环境数据库的3306端口开放给全网段的事还好第二天巡检发现了不然数据库裸奔在网上想想都后怕。第六个是容器网络。Docker的bridge模式、host模式、端口映射原理是排查容器内服务“为什么外部访问不到”的必经之路。很多人以为容器里开了80端口就能从宿主机访问其实没做端口映射就是不可以。第七个是Kubernetes网络模型。Pod间通信、Service的ClusterIP和转发规则、Ingress的HTTP路由这是现在做微服务的基石。K8s排障里最大的坑之一就是网络插件的选择不同CNI插件底层实现差异很大出了问题不看底层原理基本无从下手。第八个是网络排查工具的使用。curl、dig、telnet、nc、tcpdump、ss、mtr这些命令不用多精通但一定要熟练。排查问题的时候工具用不用得顺直接决定排障速度是十分钟还是俩小时。为了更直观一些我把这些知识点和对应的典型故障场景整理成了一张表网络知识点典型故障场景排查工具TCP/IP协议族连接超时、端口耗尽、大量TIME_WAITss、netstat、tcpdumpHTTP/HTTPS接口偶发502、缓存过期、重定向循环curl、浏览器DevToolsDNS域名解析到旧IP、解析超时dig、nslookup负载均衡健康检查误判、会话丢失curl探测、查看后端日志安全组/防火墙服务间访问不通、端口误开放telnet、nc、云控制台日志容器网络容器无法对外提供服务、端口映射失效docker network、iptablesK8s网络Service无法访问、跨节点通信异常kubectl describe、coredns日志网络工具排障效率低、定位问题靠猜tcpdump、mtr、ss3.3 怎么学网络一条可落地的路线别一上来就捧着《TCP/IP详解》啃那是大学教材不是实战手册。我建议按下面这个顺序来先跟着业务走哪里出问题就学哪一块。比如你发现在排查容器网络问题那就先把Docker的四种网络模式搞明白再去看iptables的NAT规则。问题驱动的学习效率远高于书本驱动的学习。再就是把抓包当成日常习惯。不管什么问题只要跟网络有关先抓个包看一眼流量长什么样。tcpdump的语法不用记太全会几个常用参数就够用了。抓包能让你看到真实流量是长什么样的比自己脑补的强太多。然后动手搭一个实验环境。不需要买服务器一台电脑用VirtualBox或者Multipass起几台虚拟机就行在上面搭个简单的Web服务配置负载均衡和防火墙规则随便折腾。我当年练手的时候最常干的事就是把安全组的入站规则改成错的一条然后看服务访问超时再反向猜测哪里不对。这个过程看着笨但对理解网络配置的逻辑帮助很大。最后是学会画拓扑图。排查网络问题的时候先在纸上画出客户端到服务端之间经过了多少跳——DNS、负载均衡、网关、防火墙、容器网络都算在内。然后在每个节点上做连通性测试二分法逐步缩小范围。这个方法听着特别朴素但恰恰是排查效率最高的方法。4. 从入门到落地DevOps学习的路线图与常见槽点4.1 新人最容易陷入的三个误区第一个误区是上来就啃Kubernetes。很多人看到招聘要求里写着“熟悉K8s”于是跑去学部署K8s集群结果发现K8s的抽象概念——Pod、Deployment、Service、Ingress——对新手来说一个比一个难懂。K8s固然重要但它是一个面向中大规模容器编排的工具没有一定的容器基础和实践场景学起来纯属囫囵吞枣。我建议先把Docker用熟能自己写Dockerfile懂得镜像分层和容器生命周期管理再上K8s才顺理成章。第二个误区是只学工具不理解原理。这有两层意思一层是工具的底层原理比如Jenkins的Agent节点机制、GitLab CI的Runner机制不懂这些你就没法排查流水线问题另一层是业务系统的运行原理很多人能把流水线搭起来但线上出了故障不知道怎么定位因为他不了解整个系统是怎么串联起来的。DevOps工程师的核心价值是“能定位问题”不是“会点鼠标”。第三个误区是忽略了“人”的因素。DevOps有一半是流程和文化的改造这意味着你不仅要和技术打交道还要和人的惯性较劲。我见过太多人技术能力很好但推行DevOps方案的时候因为没跟开发团队讲清楚“这能给你带来什么好处”直接被各种理由拒绝。工具不复杂人心才复杂。4.2 我亲眼见过三个真实踩坑案例案例一流水线深夜失败原因是权限配置不一致。当时公司刚迁到新的GitLab Runner集群其中一台Runner注册的时候用了不同的Token导致它没办法拉取私有仓库代码。看起来像是流水线偶尔失败实际上是负载均衡把任务随机分配到了那台坏的Runner上。排查了很久才发现不是配置的问题而是集群里混进了一台“问题成员”。这个问题的教训是任何一台机器加入集群都要走标准的初始化流程不能图省事手动改配置。案例二健康检查路径配错滚动更新直接打挂服务。我们的K8s部署配置里livenessProbe检查的是/healthz路径但新版本服务把这个路径改成了/health导致新Pod一直被认为是“不健康的”被K8s不断重启。同时因为新Pod一直没起来流量全压在旧Pod上旧Pod也扛不住压力跟着挂最终整个服务不可用。从那以后我把部署配置的Review加进了合并请求的强制检查清单里每一个探针路径改动都必须有对应说明。案例三安全组配置错误预发环境连不上生产数据库。这是我在云上最常见的坑之一。预发环境在新创建了一个VPC网段但安全组规则里还是用旧的网段段做白名单。结果就是预发环境的应用日志里全是连接超时控制台看安全组又觉得没问题——因为你看到的是“数据库允许了某个网段”但没想到应用所在的网段压根不在里面。这个问题的教训是网络问题排查先画拓扑再一层层验证连通性不要凭印象改配置。4.3 入行建议和继续深挖的方向如果你决心往DevOps方向发展我的建议是分三步走第一步打好基础。操作系统、计算机网络、Linux常用命令和Shell脚本这三样是底座。没有这些就算会操作各种工具也是空中楼阁。第二步深耕一条工具链。先把版本控制Git和CI系统玩透然后选一套容器方案Docker或Podman再选一套编排方案K8s或Nomad最后选一套监控方案Prometheus或Grafana。不要求全但求精通。第三步向云原生扩展。了解了容器编排之后自然会接触到服务网格、Serverless、可观测性平台等更上层的概念。这些不用急着学等实际项目中用到了再深入也不迟。从我个人的体验来看DevOps这个领域最大的特点就是“变化快”。五年前还在讲Jenkins和Puppet今天大家聊的是ArgoCD和OpenTelemetry。但底层的那些知识——操作系统怎么管理进程、网络怎么转发数据包、服务是怎么响应请求的——反而一直没变。把底层的东西学扎实了上层工具怎么变都不慌。最后分享一个我用了很久的笨办法每次排查完一个问题就写一张“问题卡片”记录现象、根因、排查过程、解决方案四栏内容。攒到几十张之后你会发现绝大多数故障都能归到几个固定的模式里。到那时候你心里对这些系统就有了真正的“感觉”这感觉比任何证书都值钱。
返回列表