基于Git修订版本的K8s部署方案及Ansible转K8s部署疑问
刚好这两个问题都是K8s部署场景里的高频需求,我来给你详细捋一捋:
当然可以!K8s本身基于容器运行,但我们可以通过把Git修订版本和容器镜像绑定,或者借助工具来实现指定Git版本部署,主要有这几个常用选项:
容器镜像标签绑定Git修订版:这是最直接的方式。你可以在CI/CD流程(比如GitHub Actions、GitLab CI)里构建镜像时,把Git的commit短哈希、tag或者分支名作为镜像标签,比如
my-app:abc123(abc123就是commit短哈希)。然后在Deployment的yaml文件中,把spec.template.spec.containers[0].image字段设置为这个带标签的镜像。每次要部署特定Git版本,只要确保对应镜像已构建并推送到镜像仓库,更新Deployment里的镜像标签即可。用Kustomize动态替换镜像:如果你的K8s配置用Kustomize管理,可以在base配置里给镜像留占位符,然后在overlay层指定对应Git修订版的镜像标签;或者直接用命令行动态替换:
kustomize edit set image my-app=my-registry/my-app:$(git rev-parse HEAD),生成最终配置后再用kubectl apply部署。这种方式适合多环境管理,不用手动修改yaml文件。GitOps工具自动同步:像Argo CD、Flux CD这类GitOps工具,本身就以Git作为单一数据源。你可以让工具监听Git仓库的配置变化,或者直接配置工具追踪某个特定的Git commit/tag/分支。比如在Argo CD里创建应用时,指定Git仓库的某个commit作为源,工具会自动把对应版本的应用配置和镜像部署到集群;如果要切换版本,只要更新Git仓库的配置或调整工具的源设置就行,全程自动化,还能审计所有变更。
从Ansible迁移到K8s,确实要适配容器化和K8s的运维思路,这里给你几个可行的方案:
GitOps工作流(首推):这完全契合你提到的不可变部署最佳实践。把所有K8s资源配置(Deployment、Service、Ingress等)都存在Git仓库里,用Argo CD或Flux CD这类工具自动同步到集群。每次部署就是更新Git里的配置(比如把Deployment的镜像标签改成对应Git修订版的标签),工具会自动触发滚动更新,创建新Pod替换旧Pod,全程可追溯,回滚也只要恢复Git里的旧版本就行,非常安全。
CI/CD流水线直接部署:如果不想引入额外的GitOps工具,可以用你熟悉的CI/CD工具(比如Jenkins、GitHub Actions)直接操作K8s。流程大概是:代码提交到Git后,CI先构建对应版本的镜像(打上commit哈希标签),然后用
kubectl set image deployment/my-app my-app=my-registry/my-app:abc123或者kubectl apply -f deployment.yaml来更新集群里的Deployment。这种方式上手快,适合小型项目或快速迭代的场景。Ansible过渡方案:如果暂时不想完全放弃Ansible,可以用Ansible的
k8s模块来管理K8s资源。你可以把Git修订版作为变量传入Ansible playbook,让Ansible去更新Deployment里的镜像标签,或者生成对应的yaml文件后应用到集群。不过长期来看,GitOps更符合K8s的原生设计,建议逐步过渡过去。
关于你提到的不可变部署疑问:完全正确! 在K8s里,不可变部署就是最佳实践——绝对不要在运行的Pod里修改代码,那样既不好追踪,也不符合K8s的声明式管理思路。你说的“在.yaml文件中更新Git修订版本号”,本质是更新镜像标签(因为镜像标签和Git修订版是绑定的)。只要你把对应Git版本的代码构建成了带对应标签的镜像,并且更新了Deployment里的image字段,K8s就会自动启动新的Pod(拉取对应版本的镜像),逐步替换旧Pod,完成滚动更新。整个过程不需要碰运行中的实例,完全符合不可变部署的要求。
内容的提问来源于stack exchange,提问作者cool breeze

