第一部分:镜像版本控制与自动更新流程图

第二部分:制品管理
1. 基于 Harbor 的 Docker Hub 代理缓存
1.1 任务目标
配置 Harbor 作为 Docker Hub 的代理缓存,实现:
首次拉取从 Docker Hub 同步
后续拉取从 Harbor 本地缓存提供
避免频繁访问外网,加速镜像拉取
1.2 操作步骤
完整流量路径(拉取镜像时)
1. Harbor(192.168.1xx.100) 请求 alpine 镜像
│
2. 发现本地无缓存,需要访问 Docker Hub
│
3. 读取 http_proxy=http://172.16.11.1:7890
│
4. 请求 → 代理服务器(172.16.11.1:7890)
│
5. 代理服务器 → FW2(172.16.11.211) → FW1(172.16.11.254) → 互联网 → Docker Hub(两层防火墙架构)
│
6. 镜像数据原路返回:Docker Hub → FW1 → FW2 → 代理服务器 → Harbor
│
7. Harbor 缓存镜像并返回给客户端Harbor 服务端启动
编辑 harbor.yml,添加上面的代理配置
sudo nano harbor.yml找到proxy模块,配置参考如下:

proxy:
http_proxy: http://172.16.11.1:7890
https_proxy: http://172.16.11.1:7890
no_proxy: localhost,192.168.106.102,127.0.0.1,172.16.11.211,core,jobservice,registry,harbor-db,redis,trivy,trivy-adapter
components:
- core
- jobservice
- trivy重新生成 docker-compose.yml 并启用 Trivy,重启harbor
sudo ./prepare --with-trivy && sudo docker compose down && sudo docker compose up -d启动成功后,进入harbor网页

为什么代理写在 harbor.yml 而非 docker-compose.yml?
Harbor 采用配置源与运行时分离的设计模式:
harbor.yml:管理员手动维护的唯一配置源
docker-compose.yml:由 ./prepare 脚本根据 harbor.yml 自动生成的运行时配置文件,禁止手动修改
每次执行 ./prepare 时,脚本会读取 harbor.yml,然后将代理配置转换为各容器的环境变量,写入 docker-compose.yml。
若手动修改 docker-compose.yml,下次执行 ./prepare 时修改将被完全覆盖。
此外,Harbor 包含 core、jobservice、registry、trivy 等多个组件,在 harbor.yml 中统一声明代理地址,./prepare 会自动将代理环境变量注入到所有需要访问外网的组件中,实现一处配置、多处生效,避免遗漏或配置不一致。
如果直接在 docker-compose.yml 中手动配置,不仅工作量大,而且极易在 Harbor 升级或重新配置时引发配置漂移问题。
为什么 no_proxy 要包含 172.16.11.211?
FW2 是同一网络架构内的防火墙管理地址,Harbor 访问它不需要经过代理服务器,写在 no_proxy 中可以:
避免请求环路
降低延迟
防止代理服务器无法正确处理内部管理地址的请求
Harbor(192.168.1xx.100) → 访问 172.16.11.211(FW2)
│
├── 如果走代理:请求 → 172.16.11.1 → FW2 环路/超时
│
└── 如果不走代理(no_proxy):直连 FW2 正常Harbor 服务端配置
创建代理项目
进入 Harbor UI → 项目 → 新建项目
配置参考如下:

点击“确定”完成创建
创建 Docker Hub 代理目标
进入 Harbor UI → 系统管理 → 复制管理 → 新建目标
配置参考如下:

提供者:Docker Hub
目标名:docker-proxy
目标 URL:https://hub.docker.com
访问 ID:Docker Hub 用户名
访问密码:Personal Access Token
在Docker Hub上创建Personal Access Token

点击“测试连接”,提示“测试连接成功”后保存
验证代理缓存功能
客户端拉取镜像

进入 Harbor UI → 项目 docker-proxy → 镜像仓库,应看到:

2. Harbor Trivy 扫描器离线部署与配置
2.1 任务目标
在内网离线环境下,手动导入 Trivy 漏洞数据库,并配置 Harbor 中的 Trivy 扫描器以离线模式运行,使其在不依赖外网访问的情况下,能够对 Harbor 中的容器镜像进行完整的漏洞扫描,确保镜像安全合规。
2.2 操作步骤
安装 oras 工具
oras 是一个 OCI 注册表客户端工具,用于从 GitHub Container Registry 拉取 Trivy 数据库构件。
# 下载 oras 二进制文件
curl -LO "https://github.com/oras-project/oras/releases/download/v1.2.0/oras_1.2.0_linux_amd64.tar.gz"
# 解压文件
tar -xvf oras_1.2.0_linux_amd64.tar.gz
# 移动到系统路径,便于全局调用
sudo mv oras /usr/local/bin/
# 验证安装
oras versionoras 工具在这里的作用是从 OCI 仓库拉取 Trivy 数据库构件。虽然也可以使用 docker pull,但 oras 更适合拉取非容器镜像的 OCI 构件(如数据库压缩包),且失败率更低。
拉取 Trivy 数据库
# 拉取 Trivy V2 数据库镜像(OCI 构件)
oras pull ghcr.io/aquasecurity/trivy-db:2该命令会下载一个名为 db.tar.gz 的文件,这是 Trivy 的核心漏洞数据库,包含 CVE 漏洞信息、受影响组件及修复版本等数据。下载过程可能需要 20-30 分钟,取决于网络状况。
创建目录、解压并授权
# 创建目录 → 解压数据库 → 授权(UID 10000 为 Trivy 容器内用户)
sudo mkdir -p /data/trivy-adapter/trivy/db && \
sudo tar -zxvf db.tar.gz -C /data/trivy-adapter/trivy/db/ && \
sudo chown -R 10000:10000 /data/trivy-adapter/trivy/db//data 是 Harbor 默认数据目录;chown 10000 确保容器有读取权限,否则扫描失败。
修改 harbor.yml 配置并生效
trivy:
skip_update: true # 跳过在线更新
offline_scan: true # 强制离线扫描两个参数必须同时开启。skip_update 禁止下载数据库,offline_scan 禁止所有网络请求,实现完全离线。
sudo ./prepare --with-trivy && sudo docker compose down && sudo docker compose up -d #重启后新配置生效查看日志
# 查看日志,确认无下载报错
sudo docker logs -f trivy-adapter
为什么会出现 "No such file or directory"?
Harbor 支持自定义 TLS 证书:如果用户需要验证私有镜像仓库的证书,可以将 CA 证书放在 /etc/harbor/ssl 目录下
你没有配置自定义证书:所以该目录不存在,find 命令找不到它是预期行为
脚本的设计逻辑:Trivy 启动脚本会尝试查找该目录,找不到就跳过,继续执行后续操作
2.3 验证
审查服务可以对所有镜像进行扫描

在项目内部可以指定镜像进行扫描

查看镜像漏洞

双击漏洞名,查看漏洞详细信息

3. Harbor自动清理
3.1 任务目标
在 Harbor 中配置自动垃圾回收机制,定期清理无用的镜像层和未打 tag 的 artifacts,释放存储空间;同时配置不可变 Tag 规则,防止重要镜像被意外覆盖或删除,保障生产环境镜像的稳定性和可追溯性。
3.2 操作步骤
配置定时垃圾回收
操作路径:Harbor UI → 系统管理 → 清理服务 → 垃圾清理

什么是垃圾回收
Harbor 的垃圾回收功能用于清理不再被任何镜像引用的 Blob 层。当镜像被删除或覆盖时,底层的存储层可能仍然占用磁盘空间,垃圾回收可以释放这些空间。
不可变 Tag 规则配置
不可变 Tag 规则用于禁止对特定名称的镜像进行覆盖或删除操作,防止生产环境中正在使用的镜像被意外修改。
操作路径:项目 → 选择项目 → 策略 → 不可变 Tag


配置不可变 Tag 规则后,主要实现以下三个效果:
禁止覆盖:任何人都无法向已被保护的 Tag 推送新镜像,防止生产版本被意外替换。
禁止删除:无法删除带有不可变 Tag 的镜像,确保重要版本永久可追溯。
无需额外权限控制:规则生效后自动拦截违规操作,不依赖用户权限设置,即使项目管理员也无法绕过。
第三部分:版本策略
1. 镜像更新器
1.1 任务目标
在 Kubernetes 集群中部署 ArgoCD Image Updater,使其能够自动检测 Harbor 私有仓库中的镜像更新,并自动同步到 ArgoCD 管理的应用中,实现镜像版本的自动化更新。
1.2 工作流程
Harbor 新镜像推送 → Image Updater 检测到变化 → 更新 ArgoCD 应用的参数 → ArgoCD 自动同步 → Pod 滚动更新
1.3 部署步骤
安装 ArgoCD Image Updater
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj-labs/argocd-image-updater/stable/config/install.yaml
执行结果:会创建 CRD、ServiceAccount、RBAC 权限、ConfigMap、Deployment 等一系列资源。
最后 Pod 正常运行:
kubectl get pod -n argocd -l app.kubernetes.io/name=argocd-image-updater
# 状态应为 Running
创建 Harbor 仓库访问凭据
Image Updater 需要登录 Harbor 才能检查镜像。创建一个 Secret 存储用户名和密码:
kubectl create secret generic harbor-http-creds \
--from-literal=creds=harbor用户名:密码 \
-n argocd
#验证
kubectl get secret harbor-http-creds -n argocd
创建 Git 仓库访问凭据
Image Updater 更新应用配置后需要将变更提交回 Git 仓库,因此需要 Git 仓库的访问凭据:
# 创建 Secret 存储 Git 仓库信息
k3s kubectl create secret generic the-first-repo-credss \
-n argocd \
--from-literal=url="http://192.168.106.103:3000/momo/demo.git" \
--from-literal=username="momo" \
--from-literal=password="gitea token"
# 打上标签,标记为 ArgoCD 仓库类型的 Secret
k3s kubectl label secret the-first-repo-credss \
-n argocd \
"argocd.argoproj.io/secret-type=repository"
#验证标签
kubectl get secret -n argocd -l argocd.argoproj.io/secret-type=repositoryImage Updater 会将检测到的新镜像版本写入 Git 仓库中的 YAML 文件,然后 ArgoCD 从 Git 拉取变更并同步到集群。

如何获取gitea的token?

配置镜像仓库(ConfigMap)
创建一个 ConfigMap,告诉 Image Updater 如何连接到 Harbor:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ConfigMap
metadata:
name: argocd-image-updater-config
namespace: argocd
data:
argocd.insecure: "true"
registries.conf: |
registries:
- name: Internal Harbor
prefix: 192.168.106.102
api_url: http://192.168.106.102
insecure: true
credentials: secret:argocd/harbor-http-creds#creds
EOF
#出现这个说明更改成功
configmap/argocd-image-updater-config configured
#查看配置
kubectl get cm argocd-image-updater-config -n argocd -o yaml
对应的redis.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: redis-deployment
spec:
replicas: 2
selector:
matchLabels:
app: redis
template:
metadata:
labels:
app: redis
spec:
containers:
- name: redis
image: 192.168.106.102/nginx/redis:7.0
ports:
- containerPort: 30081创建 Kustomization 配置文件
为了让 Image Updater 能够自动更新 Kustomize 管理的应用,需要在 Git 仓库中创建 kustomization.yaml 文件,并配置 Image Updater 与之协同工作。
进入 Git 仓库对应的应用目录,创建 kustomization.yaml:
apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- redis.yamlKustomization 文件告诉 ArgoCD 这是一个 Kustomize 应用,resources 中列出的 YAML 文件会被组合渲染后部署到集群。
创建 ImageUpdater 资源
基于 Image Updater v1.1.1 版本,官方已废弃旧版的注解配置方式,强制采用 CRD 进行配置。
在创建 ImageUpdater 自定义资源之前,需要先在 ArgoCD 中有一个已存在的应用。以下是创建应用的关键注意事项:
不能使用 library 默认项目
Harbor 的 library 项目比较特殊,Image Updater 在处理时可能会默认剪断映射关系,导致更新失败
仓库中必须有对应的 YAML 文件
Git 仓库中需要包含部署应用所需的 Kubernetes 资源文件(如 redis.yaml、deployment.yaml)
镜像路径必须一致
应用 YAML 中的镜像地址必须与后续 ImageUpdater 中配置的 imageName 完全对齐
在内网环境中,由于可能存在未知的 API 解析 bug,Image Updater 在直接解析内网 IP 镜像路径时,可能会报以下错误:
could not find an image-name in application解决方案:通过 CRD 显式映射别名(alias)和镜像路径(imageName),强制告诉 Image Updater 镜像的实际位置,绕过自动解析逻辑
创建 ImageUpdater 资源,定义镜像自动更新的规则:
cat <<EOF | kubectl apply -f -
apiVersion: argocd-image-updater.argoproj.io/v1alpha1
kind: ImageUpdater
metadata:
name: redis-repo-updater
namespace: argocd
spec:
applicationRefs:
- namePattern: "my-redis-app" # 匹配 ArgoCD 应用名称
images:
- alias: "my-redis" # 定义别名,规避内网 IP 路径的转义歧义
imageName: "192.168.106.102/nginx/redis" # 必须与 redis.yaml 镜像路径完全对齐
commonUpdateSettings:
updateStrategy: "semver" # 开启 SemVer 语义化版本演进算法
writeBackConfig:
method: "git" # 激活 Git Write-back 自动回写机制
gitConfig: {} # 自动索引关联的仓库凭证,简化配置
EOF
配置流程图:
┌─────────────────────────────────────────────────────────────────┐
│ ImageUpdater CRD 配置流程 │
├─────────────────────────────────────────────────────────────────┤
│ │
│ ① 在 ArgoCD 中创建应用(不能使用 library 项目) │
│ │ │
│ ▼ │
│ ② 确保 Git 仓库中有对应的 YAML 文件(如 redis.yaml) │
│ │ │
│ ▼ │
│ ③ 创建 ImageUpdater CRD 资源 │
│ - 设置 alias 别名 │
│ - 显式指定 imageName │
│ - 配置 updateStrategy │
│ │ │
│ ▼ │
│ ④ 验证 ImageUpdater 正常运行,无报错 │
│ │
└─────────────────────────────────────────────────────────────────┘验证 ImageUpdater 资源
# 查看 argocd 命名空间下的 ImageUpdater 资源
kubectl get imageupdater -n argocd
# 查看指定 ImageUpdater 资源的详细 YAML 配置
kubectl get imageupdater redis-repo-updater -n argocd -o yaml
切换渲染引擎
Argo CD 的默认逻辑是 “只读”。即便 Image Updater 发现了新镜像并尝试更新,如果应用处于普通的 YAML 模式,Argo CD 不会去理会那些需要动态生成的参数变更。
核心问题:
纯 YAML 模式下,Argo CD 只能静态读取 Git 仓库中的文件
Image Updater 检测到新镜像后,需要修改应用配置并写回 Git
切换为 Kustomize 引擎后,Argo CD 才能正确识别和处理这些动态更新
如果 ArgoCD 应用原本不是 Kustomize 类型,需要执行 patch 命令进行转换:
kubectl patch app my-first-gitops -n argocd --type merge -p '{"spec":{"source":{"path":".", "kustomize":{}}}}'该命令将 ArgoCD 应用的源类型设置为 Kustomize,指定仓库根目录(.)为 Kustomization 文件所在路径。
重启 ArgoCD 核心组件
为了清理陈旧缓存并重新初始化渲染逻辑,需要重启以下组件:
# 重启 repo-server:负责拉取 Git 源码并进行模板渲染
kubectl rollout restart deployment argocd-repo-server -n argocd
# 重启控制器:负责重新计算应用状态并执行同步
kubectl rollout restart statefulset argocd-application-controller -n argocd重启 Image Updater 控制器
# 强制删除旧 Pod,Kubernetes 会自动重建
kubectl delete pod -l app.kubernetes.io/name=argocd-image-updater -n argocd删除 Pod 后,Deployment 控制器会立即创建新的 Pod,新 Pod 会加载最新的 ConfigMap 配置(如 Harbor 仓库凭据和镜像规则)。
1.4 验证
手动推送新版本号的镜像


等待一段时间,查看argo里的APP状态和gitea里的.argocd-source-my-redis-app.yaml

