cover

團隊超過 3 個服務,映像檔管理就會開始混亂:不知道哪個 tag 對應哪個 commit、staging 和 prod 用了不同來源的 image、安全漏洞無法追蹤、磁碟被舊 image 撐爆。Harbor 不只是「放 image 的地方」,它是映像檔的治理中心。

先講結論

Registry 的治理重點就四個:Project 做權限邊界、Immutable tag 防覆蓋、安全掃描當 deploy gate、Retention policy 控成本。做到這四個,你的映像檔就從「一堆檔案」變成「可治理的資產」。

Project 是權限邊界

以專案切分:infra/ec/data/。每個 Project 有獨立的 RBAC。CI bot 只能 push 到自己的 project,開發人員只能 pull。不要讓所有人都有 admin 權限——這跟 DB 的最小權限原則一樣。

Immutable Tag:prod 的版本不能被覆蓋

你有沒有遇過 CI 不小心 push 了一個同名的 tag,結果 prod 拉到的 image 跟 registry 裡的不一致?

Harbor 可以針對 tag pattern 設 Immutable:v* 不可覆蓋、dev-* 可以。prod 只允許 pull v* 或 commit SHA 的 image。

安全掃描是 Release Gate,不是報表

掃描出 Critical CVE 的 image 還是被 deploy 到 prod?那掃描只是在浪費 CPU。

正確做法:Critical CVE 禁止 pull、High CVE 必須有例外流程(有人 review 並記錄原因和期限)。Harbor 可以設定 policy 讓有漏洞的 image 無法被拉取。

部署和推送

# 下載 Harbor
wget https://github.com/goharbor/harbor/releases/download/v2.10.0/harbor-offline-installer-v2.10.0.tgz
tar xvf harbor-offline-installer-v2.10.0.tgz
cd harbor
cp harbor.yml.tmpl harbor.yml
# harbor.yml 重點設定
hostname: harbor.example.com
https:
  port: 443
  certificate: /etc/harbor/certs/fullchain.pem
  private_key: /etc/harbor/certs/privkey.pem
 
harbor_admin_password: ChangeMeToStrongPassword
data_volume: /data/harbor
 
trivy:
  ignore_unfixed: false
  security_check: vuln
  severity: CRITICAL,HIGH,MEDIUM
./install.sh --with-trivy

CI 推送用 robot account,不要用人的帳號。Robot account 可以限制只能 push、只能操作某個 project、有 token 到期時間。

# .gitlab-ci.yml
build:
  stage: build
  before_script:
    - docker login -u $HARBOR_ROBOT -p $HARBOR_TOKEN $HARBOR_HOST
  script:
    - docker build -t $HARBOR_HOST/$HARBOR_PROJECT/api:$CI_COMMIT_SHA .
    - docker push $HARBOR_HOST/$HARBOR_PROJECT/api:$CI_COMMIT_SHA

Retention Policy:不清理就會爆

我見過 Harbor 磁碟用到 95% 然後 CI 無法 push 的情況。那天是大 release 的前一天。

設定 Retention Policy:保留最近 10 個版本、清除 30 天未被 pull 的 tag、刪除 untagged manifest。然後監控磁碟使用率,80% 就告警。

命名規則

tag 至少要有 commit SHA(ec/api:3b7e1c2),正式版本加 SemVer(ec/api:v1.8.0)。Feature branch 用 feature-*,但這些 tag 不需要進 prod,Retention 會自動清掉。


Registry 就像倉庫管理。你可以把東西都丟進去不管,但等到要找某個特定版本的時候,你會發現自己在一堆沒標籤的箱子裡翻找——而且倉庫已經爆滿了。