16.9.6 镜像与制品管理规范

镜像与制品管理规范

在生产环境中,镜像与制品是交付的核心载体,应建立统一的命名、构建、存储、分发与审计体系。镜像应采用分层构建与最小化原则,选择官方基础镜像或经组织审批的标准基镜像,移除不必要工具与调试组件,降低攻击面与体积。统一命名规范包含项目、组件、环境、版本与构建号,严格区分不可变版本与可变标签(如 latest),禁止在生产环境依赖可变标签。

原理草图(镜像与制品流转):

文章图片

一、命名与标签规范示例
推荐格式:<org>/<app>-<component>:<env>-<version>-<build>

# 合规示例
harbor.example.com/ops/web-api:prod-1.4.2-20240318.1
harbor.example.com/ops/web-api:staging-1.4.2-20240318.1

# 不合规示例(生产禁止 latest)
harbor.example.com/ops/web-api:latest

二、镜像构建与多阶段示例(含解释)

# 文件路径:/build/web-api/Dockerfile
# 第一阶段:构建
FROM golang:1.21-alpine AS builder
WORKDIR /src
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o /out/web-api ./cmd/api

# 第二阶段:运行(最小化)
FROM alpine:3.19
RUN adduser -D -u 10001 app
USER app
COPY --from=builder /out/web-api /usr/local/bin/web-api
EXPOSE 8080
ENTRYPOINT ["/usr/local/bin/web-api"]

构建与推送(包含关键参数与预期效果):

# 1) 构建镜像(-t 标签)
docker build -t harbor.example.com/ops/web-api:prod-1.4.2-20240318.1 .

# 2) 登录仓库(保存凭据)
docker login harbor.example.com

# 3) 推送镜像(进入制品库)
docker push harbor.example.com/ops/web-api:prod-1.4.2-20240318.1
# 预期:仓库出现该版本,并可被K8s拉取

三、镜像扫描与签名示例(示例工具:Trivy + Cosign)

# 安装 trivy(以 Debian/Ubuntu 为例)
sudo apt-get update && sudo apt-get install -y trivy

# 扫描镜像(高危漏洞阻断)
trivy image --severity HIGH,CRITICAL harbor.example.com/ops/web-api:prod-1.4.2-20240318.1

# 安装 cosign(签名)
curl -LO https://github.com/sigstore/cosign/releases/latest/download/cosign-linux-amd64
sudo install cosign-linux-amd64 /usr/local/bin/cosign

# 生成签名密钥
cosign generate-key-pair

# 对镜像签名
cosign sign --key cosign.key harbor.example.com/ops/web-api:prod-1.4.2-20240318.1

# 验证签名
cosign verify --key cosign.pub harbor.example.com/ops/web-api:prod-1.4.2-20240318.1

四、Kubernetes 拉取与准入策略示例
1)镜像拉取策略与密钥

# 文件路径:/k8s/web-api/deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-api
  namespace: prod
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web-api
  template:
    metadata:
      labels:
        app: web-api
    spec:
      imagePullSecrets:
        - name: harbor-cred
      containers:
        - name: web-api
          image: harbor.example.com/ops/web-api:prod-1.4.2-20240318.1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080

创建仓库拉取密钥:

kubectl create secret docker-registry harbor-cred \
  --docker-server=harbor.example.com \
  --docker-username=ops \
  --docker-password='***' \
  --docker-email=ops@example.com \
  -n prod

2)限制非标准仓库(示例:OPA Gatekeeper 约束)

# 文件路径:/policy/allowed-registries.yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sAllowedRepos
metadata:
  name: allow-harbor-only
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    repos:
      - "harbor.example.com/"

五、制品管理(Helm Chart/YAML)示例

# Helm Chart 打包与上传(示例仓库为 chartmuseum)
helm package /charts/web-api -d /tmp
curl --data-binary "@/tmp/web-api-1.4.2.tgz" http://chart.example.com/api/charts

# YAML 清单发布到 Git(GitOps)
git add /k8s/web-api/deploy.yaml
git commit -m "release web-api 1.4.2"
git push origin main

六、故障排查(常见问题与命令)
1)镜像拉取失败

kubectl describe pod web-api-xxxxx -n prod
# 关注事件:Failed to pull image / ImagePullBackOff

# 测试节点到仓库的连通性与DNS
kubectl run -n prod -it nettest --image=alpine:3.19 -- sh
apk add --no-cache curl bind-tools
nslookup harbor.example.com
curl -v https://harbor.example.com/v2/

2)签名校验失败

# 检查签名公钥是否一致
cosign verify --key cosign.pub harbor.example.com/ops/web-api:prod-1.4.2-20240318.1
# 若失败:核对镜像标签是否被覆盖、签名密钥是否过期

3)镜像体积过大

# 查看镜像分层与大小
docker history harbor.example.com/ops/web-api:prod-1.4.2-20240318.1
# 优化:使用多阶段构建、删除构建依赖

七、安装与搭建(示例:快速部署私有仓库 Harbor)

# 下载离线安装包
wget https://github.com/goharbor/harbor/releases/download/v2.9.4/harbor-offline-installer-v2.9.4.tgz
tar xf harbor-offline-installer-v2.9.4.tgz
cd harbor

# 配置文件(设置域名、密码)
cp harbor.yml.tmpl harbor.yml
sed -i 's/hostname: .*/hostname: harbor.example.com/' harbor.yml
sed -i 's/harbor_admin_password: .*/harbor_admin_password: StrongPass!/' harbor.yml

# 安装并启动
sudo ./install.sh
# 预期:访问 https://harbor.example.com 可登录

八、练习
1)按命名规范为任意应用构建镜像,推送到私有仓库,并在 K8s 中成功拉取。
2)使用 Trivy 扫描一个存在高危漏洞的镜像,记录并修复(升级基础镜像),对比扫描结果。
3)为镜像签名并配置准入策略,验证未签名镜像无法部署。
4)通过 Helm 打包并上传 Chart,使用 GitOps 流程进行发布与回滚。