Kubernetes CI/CD:GitHub Actions 构建并发布镜像
用 GitHub Actions 搭发布流水线:OIDC 短期凭据、不可变镜像、环境审批与 rollout 验证。
CI/CD 流水线最容易出问题的地方不在「构建镜像」,而在「部署凭据怎么给」和「发布后怎么确认」。这篇文章写一条我实际在用的发布流水线:测试 → 构建 → 扫描 → 推送 → 部署 → 验证,每一步都说清楚为什么。
#凭据:用 OIDC,别把 kubeconfig 塞进仓库
最不安全的做法是把 KUBECONFIG、长期 Token 直接写进 GitHub Secrets 甚至仓库文件。正确姿势是用 OIDC 短期令牌:GitHub Actions 向云厂商/集群换取几分钟有效的凭据,用完即失效,没有长期泄露面。
permissions:
id-token: write # 允许换取 OIDC token
contents: read
packages: write配置一个 federation 之后,凭据通过 configure-kubeconfig 之类的 action 注入,流水线里不需要任何明文密钥。这一步把「凭据泄露」这个 CI/CD 最大的风险直接消掉,值得花半天时间配好。
#流水线:测试、构建、扫描、发布
name: release
on:
push:
branches: [main]
jobs:
build-and-deploy:
runs-on: ubuntu-latest
permissions:
id-token: write
contents: read
packages: write
steps:
- uses: actions/checkout@v4
- name: Run tests
run: go test ./...
- name: Build and push
run: |
docker build -t ghcr.io/acme/demo-api:${{ github.sha }} .
docker push ghcr.io/acme/demo-api:${{ github.sha }}
- name: Configure kubeconfig
uses: azure/k8s-set-context@v4
with:
method: oidc
cluster: ${{ vars.CLUSTER_NAME }}
- name: Deploy
run: |
kubectl set image deployment/demo-api api=ghcr.io/acme/demo-api:${{ github.sha }}
- name: Verify rollout
run: kubectl rollout status deployment/demo-api --timeout=180s几个细节值得展开:
- 镜像 tag 用 commit SHA(
${{ github.sha }}),不可变、可追溯。别用latest——latest 是可变的,出问题你根本不知道线上跑的是哪一版。配合digest更严谨,但 SHA tag 已能满足绝大多数场景。 - 构建和部署分步,构建失败不会触发部署,部署失败会有明确的 step 标红。
kubectl rollout status必须作为流水线最后一步。很多人部署完就结束,发布失败全靠人工发现。rollout 超时会返回非零退出码,让 CI 直接失败,这才是「发布失败能被及时发现」的机制。
#环境隔离:dev / prod 分开,别一套脚本打天下
on: push: branches: [main] 直接发布生产是最危险的做法。至少做到:
- 生产环境用 GitHub Environments(
environment: production),开启「需要审批」——代码合并自动发测试,生产发布必须点一下确认。 - 不同环境用不同的
vars(镜像仓库、namespace、values 文件),配置不写死在流水线里。
deploy-prod:
needs: [build-and-deploy]
environment: production # 审批 + 保护规则
runs-on: ubuntu-latest
steps:
- run: |
kubectl -n production set image deployment/demo-api api=ghcr.io/acme/demo-api:${{ github.sha }}
kubectl -n production rollout status deployment/demo-api --timeout=180s#排障:发布失败后怎么查
CI 报错只是开始,接下来按顺序查:
kubectl -n production get events --sort-by=.lastTimestamp | tail -30
kubectl -n production get pods -l app=demo-api
kubectl -n production describe pod <pod-name>
kubectl -n production logs <pod-name> --previous先看 Events(调度失败、镜像拉取失败、探针失败都会出现在这里),再 describe 看具体状态,最后看日志。镜像 tag 拼错是最常见的坑:构建用 SHA、部署也用 SHA,一旦两边对不上就是 ImagePullBackOff,Events 里一眼就能看到。
#经验
一条稳的发布流水线 = 短期凭据 + 不可变镜像 + 环境审批 + rollout 验证。发布不是终点,验证才是。另外补一句:CI 里跑 go test 之类的单测当然好,但更值钱的是加一条「冒烟」——部署完打一个真实请求确认服务可用,这一步能拦住一半的「测试过了但线上挂」事故。
写于 2026 年 7 月 5 日
- 栏目
- 技术文章
- 约
- 3 分钟
- 字数
- 2.3K
- 阅读
- 247
本文为原创记录,转载请注明出处。如果这篇替你省了时间,欢迎留言说说你踩到的坑。
同题 · related
- 把博客从 docker-compose 搬到 k3s:单机迁移与上线全过程在 4C3.6G 的云主机上把博客从 docker-compose 迁到单机 k3s。附完整 YAML 清单(Deployment、Service、PVC、Ingress、Certificate 等)与全部配置命令,记录部署、数据迁移与切换上线的踩坑过程。
- DevOps 运维中 AI 那些事把 AI 放进运维的真实分工:从服务器硬件、网络、GPU、内存,到虚拟化、Kubernetes、应用构建、CI/CD、可观测性、资源分配,再到 AI 自身的部署与算力调度。讲清楚哪些活它能接、边界划在哪、以及我踩过的那些坑。
- ArgoCD 实战:用 GitOps 把 CI/CD 部署搬进 Kubernetes从安装、Application 声明到 App of Apps 与 CI 配合,把 GitOps 部署体系在 Kubernetes 上落地,并复盘真实事故。
留言 · remarks
00 条还没有留言,来说点什么吧。