企业实战:Go/Node 构建、扫描、审批与 EKS 发布

验证:未记录
适用版本
未记录
验证范围
尚未登记验证记录。

把已有订单服务的 Go 或 Node.js 仓库接入 Jenkins:测试 → 构建镜像 → 漏洞扫描 → 推送 ECR → 预生产业务验证 → 审批 → 生产发布 → 验证/回退。ECR 是 Amazon Elastic Container Registry(镜像仓库),EKS 是 Amazon Elastic Kubernetes Service(托管 Kubernetes)。

本实验使用真实业务服务和两个隔离环境,不用 Hello World 代替业务验证;应用开发与集群创建沿用已有文档。首次运行只接预生产,失败演练通过后再开放生产审批。

1. 前置条件与验收目标#

  • 已完成 Controller 部署、Agent 和 权限隔离。只读验证 Controller 与可信发布 Controller 分离。
  • 两套可访问的 EKS 集群,各有 orders 命名空间及 orders-api Deployment,容器名 api,当前镜像固定 digest。就绪探针、优雅退出、滚动升级容量与数据库兼容参考 企业基线。
  • 真实应用仓库提供 Dockerfile、锁定依赖、业务测试;Go 运行 go test -race ./... 与 go vet ./...,Node 运行 npm ci、npm run lint、npm test。Go 的 race 检查需要相应平台及 C 编译工具链。
  • 三台独立 EC2 Agent,每台 1 个执行器:trusted-build、staging-release、production-release。分别附加专属 instance profile;不能共用管理员实例角色。
  • 构建 Agent 安装固定版本 Java、Git、Go/Node、rootless Podman、Trivy、AWS CLI;发布 Agent 只需 Java、Python 3、AWS CLI、兼容集群的 kubectl。

验收:生产镜像摘要与预生产完全相同;测试/扫描失败禁止推送;预生产失败禁止审批;错误生产版本会触发受保护的回退;任何身份均不能读取无关秘密。

2. 准备仓库及身份#

由平台管理员设置实际区域、角色和集群变量。下面初始化仅执行一次;资源已存在时先检查,不覆盖既有策略:

export AWS_REGION='ap-east-1'
export ECR_REPOSITORY='ci/orders-api'
export STAGING_CLUSTER='REPLACE_STAGING_CLUSTER'
export PRODUCTION_CLUSTER='REPLACE_PRODUCTION_CLUSTER'
export BUILD_ROLE_NAME='REPLACE_BUILD_INSTANCE_ROLE'
export STAGING_ROLE_NAME='REPLACE_STAGING_INSTANCE_ROLE'
export PRODUCTION_ROLE_NAME='REPLACE_PRODUCTION_INSTANCE_ROLE'
export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text)
aws ecr create-repository --region "$AWS_REGION" --repository-name "$ECR_REPOSITORY" --image-tag-mutability IMMUTABLE

三个角色由企业已有 EC2 provisioning 流程建立并附到对应实例;信任主体为 EC2 服务,发布节点不要给构建任务使用。使用以下脚本生成最小权限文件,不手抄账户号:

python3 - <<'PY'
import json, os
from pathlib import Path
r,a=os.environ['AWS_REGION'],os.environ['AWS_ACCOUNT_ID']
def write(name, statements):
    Path(name).write_text(json.dumps({'Version':'2012-10-17','Statement':statements},indent=2))
write('build-policy.json',[
 {'Effect':'Allow','Action':['ecr:GetAuthorizationToken'],'Resource':'*'},
 {'Effect':'Allow','Action':['ecr:DescribeRepositories','ecr:DescribeImages',
 'ecr:BatchCheckLayerAvailability','ecr:InitiateLayerUpload','ecr:UploadLayerPart',
 'ecr:CompleteLayerUpload','ecr:PutImage'],
 'Resource':f"arn:aws:ecr:{r}:{a}:repository/{os.environ['ECR_REPOSITORY']}"}])
for env in ['STAGING','PRODUCTION']:
    write(env.lower()+'-policy.json',[{'Effect':'Allow','Action':['eks:DescribeCluster'],
      'Resource':f"arn:aws:eks:{r}:{a}:cluster/{os.environ[env+'_CLUSTER']}"}])
PY
aws iam put-role-policy --role-name "$BUILD_ROLE_NAME" --policy-name JenkinsBuild --policy-document file://build-policy.json
aws iam put-role-policy --role-name "$STAGING_ROLE_NAME" --policy-name JenkinsRelease --policy-document file://staging-policy.json
aws iam put-role-policy --role-name "$PRODUCTION_ROLE_NAME" --policy-name JenkinsRelease --policy-document file://production-policy.json

这些策略是附加权限,不能抵消已有宽权限,必须同时审查角色其他策略与权限边界。实例应强制 IMDSv2(Instance Metadata Service v2,实例元数据服务第二版),阻止其他信任域访问元数据。使用官方非中国区、同账户 ECR;跨账户或其他分区要修改仓库地址、策略和拉取授权。

集群管理员为两个角色建立 Access Entry(访问身份映射),并按 发布权限 分别应用 Role/RoleBinding:

# 前提:集群 authenticationMode 已为 API 或 API_AND_CONFIG_MAP。
# 从 CONFIG_MAP 迁移需单独评审,不能在流水线临时切换认证模式。
for ENV_NAME in STAGING PRODUCTION; do
  CLUSTER_VAR="${ENV_NAME}_CLUSTER"
  ROLE_VAR="${ENV_NAME}_ROLE_NAME"
  ROLE_ARN=$(aws iam get-role --role-name "${!ROLE_VAR}" --query Role.Arn --output text)
  aws eks create-access-entry --region "$AWS_REGION" --cluster-name "${!CLUSTER_VAR}" --principal-arn "$ROLE_ARN" --type STANDARD --kubernetes-groups orders-release
done

以上循环用 Bash 执行。不要额外关联集群管理员访问策略。集群工作节点需有 ECR 拉取权限及网络,发布角色不需要推镜像权限。EKS Access Entry 说明

在三台 Agent 上执行 aws sts get-caller-identity,核对分别是预期角色;发布节点生成临时 kubeconfig 后执行 权限正反检查。禁止保存 AWS access key。

3. 安装项目文件#

下载到应用仓库:

本地位置 下载
Jenkinsfile 流水线
ci/build-image.sh 构建与扫描
ci/deploy.py 部署与回退
ci/verify-business.sh 真实 API 验证

应用 Dockerfile 使用固定基础镜像、非 root 运行用户;.dockerignore 排除 .git、环境文件和密钥,构建秘密不得通过 ARG/COPY 固化到层。应用容器基础示例见 Go 与 Node.js,本项目必须换成实际业务服务。私有基础镜像另授予其仓库的最小拉取权限。

修改 Jenkinsfile 的 APP_KIND(go/node)、区域、仓库名及两个集群名;这些是受审查常量,不向任意构建者开放生产目标参数。保留镜像摘要与审计文件的传递方式,不重新构建生产镜像。

扫描使用 Trivy 的 HIGH/CRITICAL 阈值,数据库下载失败也会失败;接受风险时通过有负责人和到期时间的审查修改规则,不直接忽略全部漏洞。构建节点预留镜像磁盘空间,缓存仅在同一信任域内使用。

4. 接入真实业务门禁#

脚本定义的接口契约:POST /orders 支持 Idempotency-Key 并返回 id;GET /orders/{id} 返回 id、tenant、status,状态为 created 或 accepted。若你的实际接口不同,按其契约修改脚本并审查;不要改成只检查 HTTP 200。

在两个发布 Agent 的节点配置 → Node Properties → Environment variables 分别设置:

变量 值
VERIFY_ENVIRONMENT staging 或 production,与节点一致
VERIFY_BASE_URL 该环境真实 HTTPS 业务入口,不带末尾 /
VERIFY_TENANT 已授权的合成测试租户,例如 release-verification
VERIFY_TOKEN_FILE Agent 本地受控文件路径,内容为该租户 API token
VERIFY_PAYLOAD_FILE 已评审业务请求 JSON 文件路径

秘密由企业秘密系统投递,文件仅 Agent 用户可读;不将 token 写入节点环境变量、仓库或归档。业务 token 定期轮换,范围只限测试租户。请求文件示意如下,字段需满足你的服务契约:

{"tenant":"release-verification","synthetic":true,"sku":"REPLACE_APPROVED_TEST_SKU","quantity":1}

synthetic 字段本身不提供隔离:先确认服务端把该租户路由到测试库存、支付沙箱及消息消费者,不触发真实扣款/发货,并设置测试数据留存与清理。禁止在未实现这种隔离的生产系统执行创建订单测试。

手工在预生产发布节点运行 bash ci/verify-business.sh staging:必须完成创建、同键重复创建不产生新订单、持久化读回。生产节点先由业务负责人确认隔离机制,再执行对应测试。

5. 建任务并完整运行#

  1. 仓库保护 main,Jenkinsfile、ci、Dockerfile、依赖锁文件修改必须经过指定维护者审查。部署任务只读取该仓库受保护的 main。
  2. 在可信 Controller 新建 Pipeline → Pipeline script from SCM → Git,填写固定仓库、只读凭据、分支 */main、路径 Jenkinsfile。不允许开发者 Configure/Replay 该发布任务。
  3. 三个节点分别设对应标签和专用执行模式;身份组中建立真实 release-managers。先禁用自动触发,人工发起首轮。
  4. Build once 成功后下载 audit/image.txt;确认内容是 仓库@sha256:...,不是可变标签。
  5. 预生产通过后审阅 staging.json、扫描结果、监控与数据库兼容性,再由发布经理批准;首次可直接拒绝审批验证阻断路径。
  6. 开放生产后核对两个环境镜像摘要、production.json、业务指标和变更记录。错误率、延迟、队列积压等指标的评估窗口与阈值写入变更单;本脚本的少量业务调用不代替负载测试或持续观测。

同一 ECR 仓库由这一个发布任务写入,标签使用提交号加 BUILD_NUMBER;迁移任务时保留构建号或调整受审查的命名规则,避免不可变标签碰撞。不要直接重跑已经发布的摘要;脚本会拒绝制造“新发布”。

6. 故障演练与退出#

演练(先在预生产) 必须观察到的结果
提交失败测试 不构建、不推送、不部署
扫描命中阈值或扫描器不可用 不推送;保留扫描/失败记录
候选版本业务验证失败 恢复旧摘要并重新验证;流水线失败
验证期间由管理员更改镜像 回退条件检查失败,不覆盖他人版本
审批超时/非发布经理操作 不触发生产部署
Agent 在部署后掉线 人工按归档与实际状态恢复,不能宣称自动回退成功

演练结束停用测试触发器,删除临时 Access Entry/RoleBinding 及专用实例身份授权,按留存策略清理测试镜像和订单。不要删除共享仓库、生产工作负载或仍用于恢复的旧镜像。后续镜像签名与准入验证参考 软件供应链。

可直接运行的配套工程#

完整配套业务见 企业订单参考工程。复制其源码和 ci/test.sh 到应用仓库,再复制本文 Jenkins 资产;APP_KIND=python,构建节点配置 CONTAINER_ENGINE=podman、批准的 BASE_IMAGE/POSTGRES_IMAGE 摘要并安装 podman compose provider。测试用固定回环端口 8088,可信构建 Agent 限单执行器;该工程与 Go/Node 路径二选一。设置 VERIFY_ASYNC=true,测试正文使用 {“tenant”:“release-verification”,“synthetic”:true,“amount_cents”:1200},门禁会等待账本及投影完成。

搜索文档

输入关键词,搜索所有文档。

↑ ↓ 选择 · Enter 打开 · Esc 关闭