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 流程进行发布与回滚。