梗概
产物管理(Artifact Management)是对软件研发、部署、运行过程中产生的各类”产物”(也叫”制品”)进行全生命周期管理的实践,核心目标是确保产物的一致性、可追溯性和安全性。
核心价值
产物管理就像给软件的”中间成果”和”最终成果”建立一个规范的”仓库+档案系统”,让每个产物都有迹可循、可控可用,是保障运维和部署稳定性的重要环节。
详细说明
产物类型
1. 构建产物
child::
构建产物
梗概
Artifact(工件/构建产物) 是软件开发过程中编译、构建或打包后生成的可部署文件,是CD流程的核心输出物。
定义
构建产物是指经过编译、构建、测试等步骤后生成的,可以直接用于部署或分发的文件或包。
详细说明
常见类型
1. 二进制文件
- 编译好的可执行文件
- 动态链接库(.dll、.so)
- 静态库文件
2. 容器镜像
- Docker镜像:最常见的现代构建产物
- 包含应用代码、运行时环境、依赖库
- 可在任何支持容器的环境中运行
3. 包文件
- 前端项目:打包后的静态文件(dist目录)
- Java项目:JAR、WAR文件
- Node.js项目:npm包
- Python项目:wheel包、egg包
4. 安装包
- Windows安装程序(.msi、.exe)
- macOS安装包(.dmg、.pkg)
- Linux软件包(.deb、.rpm)
在CI/CD流程中的作用
1. CI阶段产出
- CI系统构建完成后的标准化输出
- 经过测试验证的可靠版本
- 版本化管理,便于回滚
2. CD阶段输入
- 部署阶段的标准输入
- 确保开发、测试、生产环境的一致性
- 支持蓝绿部署、金丝雀发布等策略
存储与管理
1. 制品仓库
- Docker Registry:存储容器镜像
- Maven Repository:Java构建产物
- npm Registry:Node.js包
- PyPI:Python包
2. 版本管理
- 语义化版本控制
- 标签和元数据管理
- 生命周期管理(保留策略)
3. 安全考虑
- 构建产物签名验证
- 漏洞扫描
- 访问权限控制
最佳实践
1. 构建一致性
- 使用相同的构建环境
- 固定依赖版本
- 可重现的构建过程
2. 产物优化
- 最小化产物大小
- 移除不必要的依赖
- 压缩和优化
3. 质量保证
- 自动化测试覆盖
- 静态代码分析
- 安全扫描
与其他概念的关系
- Provisioning:基础设施准备,为构建产物提供运行环境
- 监控系统:监控构建产物在生产环境的运行状态
- 审计日志:记录构建产物的部署和使用历史
child::CI_CD
指向原始笔记的链接
2. 配置产物
配置文件:
- 应用配置(application.yml、config.json)
- 环境变量配置
- 数据库连接配置
- 第三方服务配置
基础设施配置:
- kubernetes部署清单(YAML文件)
- Terraform配置文件
- Ansible剧本
3. 部署产物
脚本文件:
- 部署脚本(deploy.sh)
- 启停脚本(start.sh、stop.sh)
- 数据库迁移脚本
- 健康检查脚本
文档产物:
- API文档
- 部署说明文档
- 变更日志
4. 依赖产物
第三方库:
- Maven依赖(JAR包)
- NPM包
- Python包(Wheel、Egg)
- 系统级依赖包
产物管理的核心环节
1. 产物存储
专用仓库选择
| 产物类型 | 推荐仓库 | 特点 |
|---|---|---|
| Java包 | Nexus Repository, Artifactory | 支持Maven、Gradle |
| 容器镜像 | Harbor, AWS ECR, Docker Hub | OCI标准,安全扫描 |
| 通用制品 | Artifactory, Azure Artifacts | 多格式支持 |
| NPM包 | npm registry, Verdaccio | JavaScript生态 |
Harbor容器镜像仓库示例
# harbor部署配置
version: '2.3'
services:
registry:
image: goharbor/registry-photon:v2.5.2
container_name: registry
restart: always
cap_drop:
- ALL
cap_add:
- CHOWN
- SETGID
- SETUID
volumes:
- /data/registry:/storage:z
- ./common/config/registry/:/etc/registry/:z
networks:
- harbor
depends_on:
- log
logging:
driver: "syslog"
options:
syslog-address: "tcp://localhost:1514"
tag: "registry"2. 版本控制
语义化版本控制
# 版本号格式:MAJOR.MINOR.PATCH
# 示例:1.2.3
# 主版本号:不兼容的API修改
# 次版本号:向下兼容的功能性新增
# 修订号:向下兼容的问题修正
# Git标签管理
git tag -a v1.2.3 -m "Release version 1.2.3"
git push origin v1.2.3产物元数据管理
{
"artifact": {
"name": "user-service",
"version": "1.2.3",
"type": "docker-image",
"repository": "harbor.company.com/prod/user-service",
"build": {
"number": "456",
"timestamp": "2024-01-15T10:30:00Z",
"commit": "abc123def456",
"branch": "main",
"builder": "jenkins-agent-01"
},
"dependencies": [
{
"name": "openjdk",
"version": "11-jre-slim",
"type": "base-image"
}
],
"security": {
"scanned": true,
"vulnerabilities": 0,
"scan_date": "2024-01-15T10:35:00Z"
}
}
}3. 权限控制
RBAC权限模型
# Harbor项目权限配置
apiVersion: v1
kind: ConfigMap
metadata:
name: harbor-rbac
data:
policy.csv: |
# 项目管理员
p, project-admin, /api/v2.0/projects/myproject/**, *
# 开发者:可推送镜像
p, developer, /api/v2.0/projects/myproject/repositories/**, POST
p, developer, /api/v2.0/projects/myproject/repositories/**, GET
# 部署者:只能拉取镜像
p, deployer, /api/v2.0/projects/myproject/repositories/**, GET
# 用户角色绑定
g, alice, project-admin
g, bob, developer
g, charlie, deployer访问控制实践
# Maven仓库访问控制
# settings.xml配置
<servers>
<server>
<id>nexus-releases</id>
<username>${env.NEXUS_USERNAME}</username>
<password>${env.NEXUS_PASSWORD}</password>
</server>
<server>
<id>nexus-snapshots</id>
<username>${env.NEXUS_USERNAME}</username>
<password>${env.NEXUS_PASSWORD}</password>
</server>
</servers>
# Docker镜像访问控制
docker login harbor.company.com -u ${HARBOR_USERNAME} -p ${HARBOR_PASSWORD}4. 生命周期管理
保留策略配置
# Harbor镜像保留策略
apiVersion: goharbor.io/v1beta1
kind: RetentionPolicy
metadata:
name: production-retention
spec:
rules:
- disabled: false
priority: 1
template: "latestPushedK"
params:
latestPushedK: 10 # 保留最新的10个版本
tag_selectors:
- kind: "doublestar"
decoration: "matches"
pattern: "v*" # 匹配v开头的标签
- disabled: false
priority: 2
template: "nDaysAfter"
params:
nDaysAfter: 30 # 30天后清理
tag_selectors:
- kind: "doublestar"
decoration: "matches"
pattern: "dev-*" # 开发版本自动清理脚本
#!/bin/bash
# 清理过期产物脚本
NEXUS_URL="http://nexus.company.com"
REPOSITORY="maven-snapshots"
DAYS_TO_KEEP=7
# 获取过期产物列表
curl -u admin:admin123 \
"$NEXUS_URL/service/rest/v1/search?repository=$REPOSITORY" \
| jq -r ".items[] | select(.lastModified < \"$(date -d \"$DAYS_TO_KEEP days ago\" -Iseconds)\") | .id" \
> expired_artifacts.txt
# 删除过期产物
while read -r artifact_id; do
echo "Deleting artifact: $artifact_id"
curl -X DELETE -u admin:admin123 \
"$NEXUS_URL/service/rest/v1/components/$artifact_id"
done < expired_artifacts.txt
echo "Cleanup completed"5. 与CI/CD流程联动
Jenkins Pipeline集成
pipeline {
agent any
environment {
HARBOR_REGISTRY = 'harbor.company.com'
HARBOR_PROJECT = 'production'
IMAGE_NAME = 'user-service'
NEXUS_URL = 'http://nexus.company.com'
}
stages {
stage('构建') {
steps {
script {
// 构建应用
sh 'mvn clean package -DskipTests'
// 上传JAR到Nexus
sh '''
mvn deploy:deploy-file \
-DgroupId=com.company \
-DartifactId=user-service \
-Dversion=${BUILD_NUMBER} \
-Dpackaging=jar \
-Dfile=target/user-service.jar \
-Durl=${NEXUS_URL}/repository/maven-releases/ \
-DrepositoryId=nexus-releases
'''
}
}
}
stage('构建镜像') {
steps {
script {
def imageTag = "${HARBOR_REGISTRY}/${HARBOR_PROJECT}/${IMAGE_NAME}:${BUILD_NUMBER}"
// 构建Docker镜像
sh "docker build -t ${imageTag} ."
// 推送到Harbor
withCredentials([usernamePassword(
credentialsId: 'harbor-credentials',
usernameVariable: 'HARBOR_USER',
passwordVariable: 'HARBOR_PASS'
)]) {
sh "docker login ${HARBOR_REGISTRY} -u ${HARBOR_USER} -p ${HARBOR_PASS}"
sh "docker push ${imageTag}"
}
// 记录产物信息
writeFile file: 'artifact-metadata.json', text: """
{
"image": "${imageTag}",
"build_number": "${BUILD_NUMBER}",
"git_commit": "${GIT_COMMIT}",
"build_date": "${new Date().format('yyyy-MM-dd HH:mm:ss')}"
}
"""
// 归档元数据
archiveArtifacts artifacts: 'artifact-metadata.json'
}
}
}
stage('部署到测试环境') {
steps {
script {
def imageTag = "${HARBOR_REGISTRY}/${HARBOR_PROJECT}/${IMAGE_NAME}:${BUILD_NUMBER}"
// 更新Kubernetes部署
sh """
kubectl set image deployment/user-service \
user-service=${imageTag} \
-n testing
"""
// 等待部署完成
sh "kubectl rollout status deployment/user-service -n testing"
}
}
}
}
post {
success {
// 通知部署成功
slackSend channel: '#deployments',
color: 'good',
message: "✅ ${IMAGE_NAME}:${BUILD_NUMBER} 部署成功"
}
failure {
// 通知部署失败
slackSend channel: '#deployments',
color: 'danger',
message: "❌ ${IMAGE_NAME}:${BUILD_NUMBER} 部署失败"
}
}
}GitOps工作流集成
# ArgoCD Application配置
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: user-service
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/company/k8s-manifests
targetRevision: HEAD
path: user-service
helm:
parameters:
- name: image.repository
value: harbor.company.com/production/user-service
- name: image.tag
value: "123" # 由CI流水线更新
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true
selfHeal: true产物安全管理
1. 漏洞扫描
# Harbor自动扫描配置
apiVersion: goharbor.io/v1beta1
kind: Project
metadata:
name: production
spec:
projectName: production
metadata:
autoScan: "true"
severity: "critical"
reuseSysCveAllowlist: "true"
cveAllowlist:
items:
- cveId: "CVE-2019-12345" # 已知可接受的漏洞2. 镜像签名
# 使用Cosign签名镜像
export COSIGN_EXPERIMENTAL=1
# 生成密钥对
cosign generate-key-pair
# 签名镜像
cosign sign --key cosign.key harbor.company.com/prod/user-service:1.2.3
# 验证签名
cosign verify --key cosign.pub harbor.company.com/prod/user-service:1.2.33. 准入控制
# OPA Gatekeeper策略:只允许来自可信仓库的镜像
apiVersion: templates.gatekeeper.sh/v1beta1
kind: ConstraintTemplate
metadata:
name: allowedrepos
spec:
crd:
spec:
names:
kind: AllowedRepos
validation:
properties:
repos:
type: array
items:
type: string
targets:
- target: admission.k8s.gatekeeper.sh
rego: |
package allowedrepos
violation[{"msg": msg}] {
container := input.review.object.spec.containers[_]
not starts_with(container.image, input.parameters.repos[_])
msg := sprintf("Container image %v is not from allowed registry", [container.image])
}
---
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: AllowedRepos
metadata:
name: must-come-from-harbor
spec:
match:
kinds:
- apiGroups: ["apps"]
kinds: ["Deployment"]
parameters:
repos:
- "harbor.company.com/"监控与观测
1. 产物使用追踪
# Prometheus监控配置
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-config
data:
prometheus.yml: |
global:
scrape_interval: 15s
scrape_configs:
- job_name: 'harbor-exporter'
static_configs:
- targets: ['harbor-exporter:8080']
metrics_path: /metrics
- job_name: 'nexus-exporter'
static_configs:
- targets: ['nexus-exporter:8080']2. 产物依赖分析
#!/bin/bash
# 产物依赖关系分析脚本
HARBOR_API="https://harbor.company.com/api/v2.0"
PROJECT="production"
# 获取所有镜像
curl -s -u admin:Harbor12345 \
"$HARBOR_API/projects/$PROJECT/repositories" \
| jq -r '.[].name' > images.txt
# 分析每个镜像的依赖
while read -r image; do
echo "分析镜像: $image"
# 获取镜像清单
curl -s -u admin:Harbor12345 \
"$HARBOR_API/projects/$PROJECT/repositories/$image/artifacts" \
| jq -r '.[0].digest' > digest.txt
# 分析镜像层
docker pull "harbor.company.com/$PROJECT/$image@$(cat digest.txt)"
docker history --no-trunc "harbor.company.com/$PROJECT/$image@$(cat digest.txt)" \
| grep -v "missing" | head -10
done < images.txt产物管理是现代DevOps实践的重要组成部分,它与CI_CD流水线、容器编排、微服务架构等技术紧密结合,形成了完整的软件交付体系。通过建立完善的产物管理体系,可以显著提高软件交付的质量、效率和安全性。