生产环境 DevOps 实战 | 第 16 天:Harbor 安装与配置——HTTPS、自签名证书、密码学组件

第 16/60 天

引言

在上一篇文章中,我们用 kaniko 在 Tekton 里构建出了容器镜像。但镜像构建出来之后放哪里?这就轮到我们的制品仓库 Harbor 登场了。作为三件套里的”存储中枢”,Harbor 承上启下——上游接收 Tekton 推送的镜像,下游被 Argo CD 拉取部署。

很多团队部署 Harbor 时图省事直接用 HTTP,结果在接入 Tekton 和 Argo CD 时反复踩坑:Docker/containerd 拒绝非 HTTPS 仓库、凭证明文传输、自签名证书没被信任导致 x509: certificate signed by unknown authority 报错满天飞。本文带你从零完成一个生产级、HTTPS、含密码学组件正确配置的 Harbor 部署,为后续第 29、30 天的三件套集成扫清障碍。

本文覆盖范围:Harbor 的组件架构、自签名 CA 与证书签发、harbor.yml 完整配置、在线/离线安装、HTTPS 验证与 Docker 信任配置、以及密码学相关的密钥与凭证管理。

核心概念

1. Harbor 的组件架构

Harbor 不是单体,而是一组容器服务的集合。理解它的组件,才知道 harbor.yml 里每一项配置对应什么:

组件 作用 说明
nginx 反向代理/入口 统一对外提供 HTTPS,转发到各组件
core 核心 API 服务 处理镜像/制品元数据、RBAC、复制任务
portal Web 管理界面 提供给运维/开发的可视化控制台
registry 镜像存储 底层就是开源的 Docker Distribution
registryctl 注册表控制器 配合垃圾回收、配额管理
jobservice 异步任务服务 复制、扫描、GC 等后台任务的执行器
database 元数据数据库 存储项目、用户、权限等(默认 PostgreSQL)
redis 缓存/队列 会话、job 队列、扫描缓存
trivy-adapter 漏洞扫描 对接 Trivy 做镜像安全扫描

密码学组件:Harbor 内部依赖一组密钥——secretkey(用于加密复制任务的推送密钥)、_secret 主密钥(用于加密数据库中的敏感字段)、HTTPS 证书密钥。这些在安装时需要正确落盘,否则重启后会出现”凭证解密失败”或”复制到远端仓库时凭据错误”的诡异问题。

2. 为什么必须用 HTTPS

  • Docker/containerd 默认拒绝 HTTP 仓库(除非显式配置 insecure-registries,这会关闭 TLS 校验,不安全)。
  • 凭证安全:robot account、push 密码在 HTTP 下明文传输,生产环境不可接受。
  • Kubernetes/containerd 拉取:Kubelet 拉取镜像时会对 registry 做 TLS 校验,未配置好证书会直接 x509 报错。
  • 合规:金融/医疗等行业的审计要求传输加密。

3. 自签名证书的三层信任模型

层级 说明
CA 根证书 自建私有 CA 的根证书,是信任链的起点
服务器证书 harbor.stellardata.top 签发的证书,由 CA 签发
客户端信任 Docker daemon、containerd、浏览器都需要导入 CA 根证书才信任服务器证书

生产环境如果有内网 PKI 或公共 CA,直接用即可;没有的话,自建私有 CA 是最常见做法。自签名 ≠ 自建 CA:直接用 openssl req -x509 生成一个”自签名”证书虽快,但每个客户端都要单独信任,且不便签发多张证书;自建 CA 只需信任一次根证书,后续签发任意域名证书都有效。

实战步骤

步骤 1:准备环境与依赖

# 检查 Docker Compose(Harbor 官方安装器依赖 docker-compose)
docker compose version
# 或旧版:docker-compose --version

# 下载 Harbor 离线安装包(以 v2.11 为例,实际以官方最新为准)
cd /opt
wget https://github.com/goharbor/harbor/releases/download/v2.11.1/harbor-offline-installer-v2.11.1.tgz
tar xzvf harbor-offline-installer-v2.11.1.tgz
cd harbor
# 生成默认配置模板
cp harbor.yml.tmpl harbor.yml

步骤 2:自建私有 CA 并签发服务器证书

这一步是密码学组件的基础。先创建 CA 根证书,再用它签发 Harbor 服务器证书:

# 1) 创建私有 CA 根证书
mkdir -p /opt/harbor/certs && cd /opt/harbor/certs

openssl genrsa -out ca.key 4096
openssl req -x509 -new -nodes -key ca.key -sha256 -days 3650 
  -subj "/CN=Harbor Private CA/O=StellarTop/C=CN" 
  -out ca.crt

# 2) 生成 Harbor 服务器的私钥
openssl genrsa -out harbor.key 2048

# 3) 创建证书签名请求(CSR)配置文件——这里指定 SAN 域名
cat > harbor.csr.cnf << 'EOF'
[req]
distinguished_name = req_distinguished_name
req_extensions = v3_req
prompt = no

[req_distinguished_name]
CN = harbor.stellardata.top
O = StellarTop
C = CN

[v3_req]
subjectAltName = @alt_names

[alt_names]
DNS.1 = harbor.stellardata.top
DNS.2 = registry.stellardata.top
IP.1 = 192.168.10.10
EOF

# 4) 生成 CSR
openssl req -new -key harbor.key -out harbor.csr -config harbor.csr.cnf

# 5) 用 CA 签发服务器证书(含 SAN,有效期 1 年)
openssl x509 -req -in harbor.csr -CA ca.crt -CAkey ca.key -CAcreateserial 
  -out harbor.crt -days 365 -sha256 -extensions v3_req -extfile harbor.csr.cnf

# 6) 校验证书
openssl x509 -in harbor.crt -noout -text | grep -A1 "Subject Alternative Name"

关键点harbor.crt 是给 Harbor nginx 用的服务器证书,ca.crt 是分发给所有客户端的信任锚。二者不能混淆。

步骤 3:编写 harbor.yml 配置

# /opt/harbor/harbor.yml
hostname: harbor.stellardata.top

# HTTPS 配置——生产环境必开
http:
  port: 80

https:
  port: 443
  certificate: /opt/harbor/certs/harbor.crt   # 服务器证书
  private_key: /opt/harbor/certs/harbor.key   # 服务器私钥

# 密码学组件:Harbor 用于加密敏感字段的密钥(持久化在文件系统)
# secretkey 默认在 data/secretkey,_secret 在环境变量 HARBOR_ADMIN_PASSWORD
# 生产建议外部化,见下文"密码学组件"小节

# 管理员初始密码(首次登录后请立即修改)
harbor_admin_password: "ChangeMe_Strong_2026!"

database:
  password: "DB_Strong_Password_2026!"   # PostgreSQL 的 postgres 用户密码
  max_idle_conns: 100
  max_open_conns: 900

data_volume: /data/harbor

trivy:
  ignore_unfixed: true
  skip_update: false
  offline_scan: false
  severity: "HIGH,CRITICAL"

# 核心 API 与 Portal 的鉴权密钥(密码学组件核心)
# _secret:用于加密 robot account 密码、复制任务远端凭据等
# 首次安装时由 prepare 脚本自动生成到 /data/harbor/secret
secretkey_path: /data/harbor/secret

log:
  level: info
  local:
    rotate_count: 50
    rotate_size: 200M

步骤 4:运行 prepare 与安装

# 生成 Docker Compose 配置并初始化密码学密钥
sudo ./prepare

# 安装并启动 Harbor(离线包自带镜像)
sudo ./install.sh --with-trivy

# 验证所有组件健康
docker ps | grep harbor
# 期望看到:nginx、core、portal、registry、registryctl、jobservice、database、redis、trivy-adapter

步骤 5:验证 HTTPS 并让 Docker 信任 CA

# 1) 检查 HTTPS 端口与证书链
curl -k https://harbor.stellardata.top/api/v2.0/health
# {"status":"healthy",...}

# 2) 用完整 CA 校验服务器证书(不加 -k,验证信任链)
curl --cacert /opt/harbor/certs/ca.crt https://harbor.stellardata.top/api/v2.0/health

# 3) 让本机 Docker daemon 信任私有 CA
mkdir -p /etc/docker/certs.d/harbor.stellardata.top
cp /opt/harbor/certs/ca.crt /etc/docker/certs.d/harbor.stellardata.top/ca.crt
systemctl restart docker

# 4) 验证 docker 可登录(不报 x509)
echo "AdminPass123" | docker login harbor.stellardata.top -u admin --password-stdin
# Login Succeeded

步骤 6:让 Kubernetes 节点信任 CA(为 Argo CD/containerd 准备)

Kubelet 用 containerd 拉取镜像,需要把 CA 放到每个节点:

# 在每个 K8s 节点执行
for node in node01 node02 node03; do
  ssh $node "mkdir -p /etc/containerd/certs.d/harbor.stellardata.top && 
    scp /opt/harbor/certs/ca.crt $node:/etc/containerd/certs.d/harbor.stellardata.top/ca.crt"
done

# 或配置 containerd 全局信任
# /etc/containerd/config.toml
# [plugins."io.containerd.grpc.v1.cri".registry.configs."harbor.stellardata.top".tls]
#   ca_file = "/etc/containerd/certs.d/harbor.stellardata.top/ca.crt"
systemctl restart containerd

密码学组件:密钥管理与外部化

Harbor 的密码学体系依赖三个持久化密钥,务必理解并做好备份:

#!/usr/bin/env python3
"""检查 Harbor 密码学组件落盘状态(生产巡检脚本片段)"""
import os, json

data_volume = "/data/harbor"
required = {
    "secret":        "主密钥 _secret(加密 robot 与复制凭据)",
    "secretkey":     "复制任务密钥 secretkey",
    "database":      "数据库数据目录",
}
for name, desc in required.items():
    path = os.path.join(data_volume, name)
    exists = os.path.exists(path)
    size = os.path.getsize(path) if os.path.isfile(path) else None
    print(f"[{'OK' if exists else 'MISSING'}] {name:10s} {desc:30s} {size}")

# 生产建议:
# 1. data_volume 使用外部存储(NFS/云盘)并定期备份
# 2. 使用外部 PostgreSQL / Redis 提升可用性(见第 35 天高可用篇)
# 3. 密钥文件权限收紧为 600,仅 harbor 用户可读
# 4. 变更 _secret 后需重新 prepare,否则旧 robot account 凭据解密失败

常见问题

Q1:为什么 docker loginx509: certificate signed by unknown authority
A:Docker daemon 没有信任你的 CA 根证书。把 ca.crt 放到 /etc/docker/certs.d/<hostname>/ca.crt 并重启 docker,或把 CA 加入系统信任库(cp ca.crt /usr/local/share/ca-certificates/ && update-ca-certificates)。

Q2:安装后用 HTTP 也能访问,能不能就先用 HTTP?
A:能,但不推荐。Docker/containerd/Kubernetes 默认都要求 TLS。走 insecure-registries 会关闭校验,且 robot account 凭据明文传输。生产环境请务必配置 HTTPS。

Q3:修改了 harbor.yml 的证书路径,重启后报证书加载失败?
A:改 harbor.yml 后必须重新运行 sudo ./preparedocker compose down && docker compose up -d。prepare 会重新生成 nginx 配置和密码学密钥初始化,只重启容器不会生效。

Q4:重启 Harbor 后 robot account 推送镜像报”凭据无效”?
A:多半是 _secret 主密钥丢失或被覆盖。Harbor 用它加密数据库中的 robot 密码。务必确保 /data/harbor/secret 持久化;若 data_volume 是临时目录或重建了容器卷,旧 robot 凭据将无法解密,需要重建 robot account。

Q5:./install.sh 时报数据库连接失败?
A:检查 database.password 与已存在的数据卷是否一致。若 data_volume 已初始化过,harbor.yml 里的数据库密码必须与初次安装时一致,否则 PostgreSQL 起不来。首次就应把密码记入密码管理器。

总结

本文完成了生产级 Harbor 部署的关键一步,核心要点:

  1. Harbor 是多组件容器栈:nginx / core / registry / jobservice / database / redis / trivy,harbor.yml 的每一项配置都对应具体组件。
  2. HTTPS 是生产底线:自建私有 CA → 签发带 SAN 的服务器证书 → 分发 CA 根证书给 Docker、containerd、浏览器,构建完整信任链。
  3. 密码学组件要持久化_secretsecretkey、数据库密码是 Harbor 的安全根基,data_volume 必须持久化并定期备份。
  4. 改配置必须重跑 prepareharbor.yml./prepare → 重启容器,顺序不能错。
  5. 为下游铺路:让 K8s 节点 containerd 信任 CA,是第 30 天 Argo CD 从 Harbor 拉取镜像的前置条件。

下一篇文章我们将深入 Harbor 的项目隔离与权限管理,把项目类型、访问级别、成员角色吃透,为多团队协作打基础。

📖 系列目录

下期预告: 第 17 天我们将讲解 Harbor 的项目隔离与权限管理,覆盖项目类型、访问级别、成员角色,帮助你在多团队场景下安全地共享镜像仓库。

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享
评论 抢沙发
头像
欢迎您留下宝贵的见解!
提交
头像

昵称

取消
昵称表情代码图片快捷回复

    暂无评论内容