1. 項目概述與痛點分析為什麼 Harbor 也需要高可用1.1 單節點 Harbor 的隱患鏡像倉庫掛了會發生什麼先講一個我親身經歷的案例。某公司在內部推行容器化改造開發環境、測試環境、預生產環境的鏡像全都推到一台 Harbor 伺服器上。前期一切正常直到某天上午那台伺服器的磁碟因為鏡像堆積被寫滿Harbor 直接拒絕服務。開發那邊 deploy 流程全部卡住測試環境沒法更新版本運維這邊也因為沒法拉取基礎鏡像連故障排查的容器都起不來。整個研發節奏被打斷了將近半天最後還是臨時騰了一台機器手動恢復數據才勉強把服務拉起來。鏡像倉庫這個東西平時存在感很低但它實際上是整個容器化體系裡的核心樞紐。CI/CD 流水線、Kubernetes 集群拉取鏡像、開發人員本地調試全都依賴它。一旦它掛了影響的不是某一個服務而是整條交付鏈路。單節點 Harbor 的問題歸納起來主要是三類沒有故障轉移能力硬體故障、系統崩潰、內存洩漏任何一種情況都可能讓服務直接中斷。沒有備用節點就只能等人工介入。升級維護必須停機Harbor 版本升級、配置變更、證書輪換都需要重啟服務。單節點架構下這些操作只能選在深夜低峰期做或者直接冒著影響業務的風險硬上。性能瓶頸無法橫向擴展並發拉取量大、鏡像體積大單節點的 CPU、內存、帶寬都會成為瓶頸尤其在高併發 CI 場景下特別明顯。當時我們團隊內部的結論很直接鏡像倉庫必須做高可用。至少要保證一台節點掛了服務還能繼續轉。這就是這篇文章的出發點——用 HAProxy 做入口調度配合 Harbor 多節點部署構建一套可靠的高可用架構。1.2 方案選型為什麼入口層選 HAProxy 而不是 Nginx 或 F5在做入口選型的時候市面上常見的無外乎三類軟體負載均衡HAProxy、Nginx、雲廠商 LB、硬體負載均衡F5 那類。從成本和运维靈活度來考慮我們當時直接排除了硬體設備雲廠商 LB 在自建機房的場景下也壓根不適用剩下就是 HAProxy 和 Nginx 之間的抉擇。HAProxy 在負載均衡領域是專精選手它的設計目標就是做高併發代理。跟 Nginx 相比它有幾個很關鍵的優勢一是連接調度能力更強。HAProxy 對 TCP 層的代理支持非常成熟可以做到連接級別的負載和健康檢查而且支持基於 Cookie 的 session 保持。Harbor 的客戶端既有 Docker CLI 也有 HTTP API連接模型複雜HAProxy 處理起來更穩。二是健康檢查手段豐富。除了基礎的端口探測HAProxy 支持 HTTP 層的http-check可以直接請求 Harbor 的/api/v2.0/ping接口來判斷節點是否真的健康。Nginx 被動式的健康檢查需要商業版才支持開源版只能靠上游服務器返回的錯誤來間接判斷靈活性差很多。三是性能開銷極低。HAProxy 是事件驅動的單進程模型在同樣的硬體條件下能支撐的併發連接數遠高於 Nginx。作為流量入口不希望它本身成為瓶頸HAProxy 在這方面非常值得信賴。另外HAProxy 的配置語法非常直白frontend、backend、listen三個段搞定所有的代理邏輯沒有 Nginx 那麼多模塊化的規則。後期維護成本也低。注意如果你對 Nginx 特別熟悉硬要用它來做也並非不行。但 Harbor 這種多協議、多端口HTTP 443、Harbor 內部組件通信的場景HAProxy 的 TCP 代理能力和健康檢查機制明顯更合適。別在入口層複雜化問題。2. Harbor 高可用的架構設計思路2.1 整體架構與流量路徑一張圖講清楚各組件關係HAProxy 實現 Harbor 高可用的核心思路就是「前面加調度後面做冗餘」。整個架構可以分為四層客戶端層包含 Docker CLI、Kubernetes 節點、CI/CD 工具。它們訪問的是統一的虛擬地址VIP 或域名而不是具體的 Harbor 節點。入口調度層也就是 HAProxy。它負責接收所有請求按策略轉發到後端 Harbor 節點同時通過健康檢查來剔除異常節點。Harbor 節點層兩個或以上的 Harbor 實例部署在不同的物理機或虛擬機上互為主備或雙活。每個節點上都運行著完整的 Harbor 服務棧包括核心服務、註冊表、入口控制器等。共享數據層這是整個架構能否成立的關鍵。Harbor 的運行狀態分為兩大塊——存儲在 PostgreSQL 和 Redis 中的元數據以及存放在對象存儲或文件系統中的鏡像層數據。高可用架構下這兩個部分必須由所有 Harbor 節點共享。流量路徑是這樣的客戶端請求到 HAProxy → HAProxy 通過負載均衡算法選中一個 Harbor 節點 → Harbor 節點處理請求讀寫共享的 PostgreSQL/Redis/存儲 → 返回結果給客戶端。關鍵點在於任何一個 Harbor 節點收到請求後讀寫的都是同一份底層數據所以無論請求被轉發到哪個節點最終結果都是一致的。這就是「共享一切」架構的含義。2.2 兩種高可用模式雙活模式和主備模式該怎麼選Harbor 高可用有兩種常見的部署模式區別在於 Harbor 配置文件中harbor.yml的external_url和資料庫連線設置。雙活模式Active-Active兩個節點同時工作都對外提供服務。HAProxy 把流量均勻分散到兩個節點上。這種模式的優勢是資源利用率高整個系統的吞吐能力是兩台節點的疊加。但前提是底層的共享層必須支持併發讀寫PostgreSQL 和 Redis 都必須配置成集群或主從模式存儲層則需要支持多節點同時掛載。主備模式Active-Standby只有主節點在提供服務備用節點處於空閒狀態但保持數據同步。HAProxy 通過健康檢查監控主節點狀態一旦主節點掛了流量自動切到備用節點。這種模式的好處是配置簡單對共享層的併發壓力小但也意味着有一台機器長期閒置存在資源浪費。我們的建議是如果你的 Harbor 承載的是核心生產業務雙活是值得投入成本的因為它能同時解決高可用和性能擴展兩個問題。如果鏡像倉庫只是輔助角色流量不大主備模式就夠用了後期也能平滑切換到雙活。2.3 共享層的關鍵角色存儲、資料庫、Redis 一個都不能少為什麼說共享層是整個方案的成敗關鍵我拆開來講。鏡像存儲Harbor 底層本質上是 Docker Distribution鏡像的 blob 數據存儲在文件系統或對象存儲中。高可用架構下如果兩個 Harbor 節點各存各的就會出現「節點 A 能拉到的鏡像節點 B 上根本不存在」的情況。所以必須讓所有節點訪問同一份存儲通常是 NFS、CephFS、GlusterFS、MinIO 這類方案。PostgreSQLHarbor 的用戶、項目、鏡像清單、審計日誌、權限策略全都存在 PostgreSQL 裡。單節點 PostgreSQL 在高可用架構下就是一個新的單點。你可以給它做主從複製也可以用 Patroni 這類工具做自動故障轉移在雲環境下直接用託管的 PostgreSQL 服務也是一種思路。RedisHarbor 用 Redis 做緩存和會話管理。Redis 掛了Harbor 雖然不一定立刻崩潰但會出現會話丟失、掃描任務異常等問題。同樣需要考慮高可用Redis Sentinel 或 Redis Cluster 都可以。我當時踩過一個很典型的坑Harbor 兩個節點都配好了HAProxy 也轉發正常但鏡像推送偶爾會出問題。排查了半天發現問題出在兩個 Harbor 共享了同一個 PostgreSQL但是 Redis 是各自獨立的。用戶的 session 信息沒有共享導致請求被轉發到不同節點時登入狀態會丟失。後來把 Redis 改成共享模式問題立刻消失。忠告架構容易畫但共享層往往決定成敗。動手之前先把存儲、資料庫、緩存這三層的高可用方案確定下來否則整個方案就是空中樓閣。3. 實戰部署從環境準備到 HAProxy 配置3.1 環境規劃與前置準備我們用一台 HAProxy 節點加兩台 Harbor 節點來演示具體規劃如下。實際項目中為了避免 HAProxy 自身成為單點建議再部署一台備用 HAProxy 節點搭配 Keepalived 做 VIP 漂移。角色規劃說明HAProxy 節點10.10.1.10入口調度層對外提供服務Harbor Node110.10.1.21第一台 Harbor 節點雙活模式Harbor Node210.10.1.22第二台 Harbor 節點雙活模式NFS 共享存儲10.10.1.30提供 /data/nfs/harbor 目錄作為鏡像存儲PostgreSQL10.10.1.31主從複製對應 Harbor 元數據庫Redis10.10.1.32Sentinel 模式供 Harbor 做會話和緩存在動手之前有幾個前置條件必須確認所有節點的時間要同步建議配置 NTP。時間不一致會導致 token 校驗失敗這是個很隱蔽的問題。所有節點的主機名要解析正常公私鑰認證不是必須但 Harbor 節點之間如果要互相調用 API配一下會方便不少。Harbor 的harbor.yml配置中external_url要設定成對外的虛擬地址例如https://harbor.example.local兩個節點上的配置保持一致。千萬別把external_url寫成節點自己的 IP。3.2 共享存儲和共享資料庫的部署細節NFS 是最容易上手的共享存儲方案。服務端在 10.10.1.30 上安裝nfs-kernel-server編輯/etc/exports/data/nfs/harbor 10.10.1.21(rw,sync,no_root_squash,no_subtree_check) 10.10.1.22(rw,sync,no_root_squash,no_subtree_check)Harbor 節點上掛載mount -t nfs 10.10.1.30:/data/nfs/harbor /data/harbor需要特別注意掛載參數的選擇直接影響性能和數據一致性。no_root_squash是必須的否則 Harbor 容器內 root 使用者寫入的文件會因為權限被壓縮而報錯。sync是為了保證數據即時落盤防止宕機時丟失資料。實測下來NFS 在最壞情況下吞吐會有一定衰減如果你的場景是高併發大量鏡像推送建議直接上 CephFS 或 MinIO 這種更大規模的存儲方案架構上更穩後期也好擴展。PostgreSQL 的配置相對獨立這裡說幾個要點。Harbor 需要的是「專用的資料庫實例」官方支援 PostgreSQL 9.6 及以上版本。如果資料庫和 Harbor 在同一台機器上配置基本上不用改直接裝好就行。分離部署的話需要修改harbor.yml中database部分的連線信息database: type: external external: host: 10.10.1.31 port: 5432 username: harbor password: harbor_password db_name: harbor max_idle_conns: 50 max_open_conns: 100主從複製的配置不在本文的範圍內網上文章很多基本的思路就是pg_basebackup做基礎備份再配置primary_conninfo做流式複製。Redis 也是同理建議用 Sentinel 模式兩個 Harbor 節點連的是同一個 Sentinel 集群而不是各自連一個 Redis。3.3 兩台 Harbor 節點的部署harbor.yml 的關鍵配置Harbor 的離線安裝包解壓後會有一個harbor.yml.tmpl範本複製成harbor.yml然後逐項修改。兩個節點的配置要一致除了hostname不同但需要指向同一個對外域名。核心配置大概長這樣hostname: harbor.example.local http: port: 80 https: port: 443 certificate: /data/certs/harbor.crt private_key: /data/certs/harbor.key external_url: https://harbor.example.local harbor_admin_password: Harbor12345 database: type: external external: host: 10.10.1.31 port: 5432 username: harbor password: harbor_password db_name: harbor data_volume: /data/harbor storage_service: ca_bundle: /data/certs/harbor_ca.crt filesystem: maxkeys: 100000 maxsize: 1000000 redis: type: external external: addr: 10.10.1.32:6379 sentinel_master_set: mymaster sentinel_addrs: 10.10.1.32:26379 db: 0 password: redis_password幾個關鍵點data_volume必須指向共享存儲也就是 NFS 掛載的那個目錄。Harbor 的所有持久化數據包括鏡像層、資料庫備份、證書等都會寫到這個目錄。storage_service裡的filesystem可以配置但如果你用的是 S3 兼容的對象存儲Harbor 也支援直接對接。實測中對象存儲的並發讀寫能力比 NFS 強很多是更推薦的生產方案。證書的配置要特別小心。所有節點的證書必須是同一套不然客戶端在切換節點時會看到證書不匹配的警告。用內部 CA 簽發即可但docker login的客戶端需要信任這個 CA。配置完成後執行./install.sh。Harbor 會以 docker-compose 的方式啟動一堆容器包括harbor-core、harbor-registry、harbor-portal、registryctl等。可以先用docker ps確認容器是否都在運行。3.4 HAProxy 的安裝與配置HAProxy 安裝很簡單用發行版自帶的包管理器即可apt install haproxy主要是要做好配置。先看一下我們最終的完整配置再逐段解釋。# /etc/haproxy/haproxy.cfg global log /dev/log local0 maxconn 4096 chroot /var/lib/haproxy user haproxy group haproxy daemon defaults log global mode http option httplog option dontlognull option forwardfor option http-server-close timeout connect 5s timeout client 30s timeout server 30s frontend harbor_https bind *:443 mode tcp default_backend harbor_nodes backend harbor_nodes mode tcp balance roundrobin option tcp-check stick-table type ip size 1m expire 30m stick on src server harbor1 10.10.1.21:443 check inter 5s fall 3 rise 2 server harbor2 10.10.1.22:443 check inter 5s fall 3 rise 2等等為啥用mode tcp而不是mode http這個問題很多人問過。Harbor 的 443 端口上跑的是 HTTPS如果 HAProxy 用mode http就得承擔 SSL 終結和重新加密的任務要麼你告訴它後端服務用的是 HTTP 還是 HTTPSSSL 證書的管理也會變複雜。用mode tcp是最省事的方式HAProxy 只做四層轉發把 TLS 加密的裸流量直接透傳到後端證書的驗證完全由 Harbor 自己處理。這樣一來HAProxy 不需要管證書後端節點換證書也不需要動 HAProxy 配置。balance roundrobin是預設的負載均衡算法兩個節點輪流接收請求。stick-table的作用是讓同一個來源 IP 的請求在存在健康節點的情況下盡量定向到同一個後端節點。這個特性對 Harbor 是加分的——有些客戶端比如 Kubernetes 的 containerd會持有多個連接如果這些連接被分散到不同節點雖然底層數據一致但連接建立的成本會更高。最重要的一段是健康檢查option tcp-check server harbor1 10.10.1.21:443 check inter 5s fall 3 rise 2inter 5s表示每 5 秒探測一次fall 3表示連續失敗 3 次才判定節點不可用rise 2表示連續成功 2 次才恢復可用。這個參數組合比較保守能有效避免短暫抖動造成的誤判。如果你希望健康檢查更貼近業務層可以改用 HTTP 檢查。把後端節點的檢查切換成backend harbor_nodes mode http option httpchk GET /api/v2.0/ping http-check expect status 200 server harbor1 10.10.1.21:443 ssl verify none check inter 5s fall 3 rise 2 server harbor2 10.10.1.22:443 ssl verify none check inter 5s fall 3 rise 2ssl verify none的意思是檢查時不驗證後端證書這樣可以避免內部 CA 證書未被信任的問題。expect status 200確保後端真的能回應請求而不只是端口通。3.5 Keepalived 做 HAProxy 高可用HAProxy 自己掛了怎麼辦這個問題得提前考慮。我們的做法是在 HAProxy 前面再架一層 Keepalived用 VIP 提供虛擬位址。配置非常簡單。兩台 HAProxy 節點上安裝 Keepalived/etc/keepalived/keepalived.conf寫成下面這樣vrrp_script chk_haproxy { script /usr/bin/kill -0 $(cat /var/run/haproxy.pid) interval 2 weight -20 } vrrp_instance VI_1 { state MASTER interface eth0 virtual_router_id 51 priority 100 advert_int 1 authentication { auth_type PASS auth_pass 123456 } virtual_ipaddress { 10.10.1.10/24 } track_script { chk_haproxy } }解釋一下Keepalived 的vrrp_script會去檢查 HAProxy 進程是否還活著如果掛了自身的優先級會降低 20心跳間隔後另一個節點就搶佔 VIP。服務對外始終是 10.10.1.10對客戶端來說HAPROXY 節點的故障是無感知的。注意兩台 HAProxy 節點的state可以都寫成MASTER配合不同的priority也可以一台MASTER一台BACKUP後者比較直觀但前者的 failover 速度更快。我個人傾向於都寫MASTER讓 priority 決定誰優先。3.6 客戶端側的配置docker 如何信任自簽證書這是整個方案落地時最容易出現問題但往往被忽略的一步。Docker 默認只信任系統 CA 機構頒發的證書你內部 CA 簽發的 Harbor 證書如果不做配置docker login必然失敗。如果客戶端是和 Harbor 在同一網段內的伺服器最簡單的方案是把 CA 證書放到 Docker 的信任目錄cp harbor_ca.crt /etc/docker/certs.d/harbor.example.local/ca.crt如果 Harbor 監聽的是非標準端口比如harbor.example.local:8443目錄名要寫成harbor.example.local:8443格式對應 IP 和端口。配置完重啟 Docker 即可systemctl restart docker如果客戶端是開發筆記型電腦要確保使用正確的解析——域名要解析到 VIP10.10.1.10而不是某個 Harbor 節點的 IP。在/etc/hosts或者 DNS 伺服器裡配置好就行否則流量根本不會走到 HAProxy。4. 驗證與測試如何確認高可用架構真的可用4.1 基本功能驗證推送、拉取、登入配置完成後第一個要驗證的是基本功能。兩台 Harbor 節點都正常運行時執行以下操作# 登入 Harbor docker login harbor.example.local -u admin -p Harbor12345 # 打標籤並推送 docker tag nginx:latest harbor.example.local/library/nginx:latest docker push harbor.example.local/library/nginx:latest # 拉取 docker pull harbor.example.local/library/nginx:latest如果這三步都通了說明整個鏈路是通的。接下來可以進一步觀察請求是否被輪流分發到了兩個節點。登入 Harbor 的 Web 管理介面查看「審計日誌」會看到來自同一客戶端的推拉操作時而落在節點 A時而落在節點 B。在雙活模式下這種現象是正常的也是預期的。4.2 故障注入測試停掉一台 Harbor 節點這一步是整個高可用驗證的核心。模擬一台 Harbor 節點宕機看看整個系統是否還能正常提供服務。這裡的操作順序很關鍵。先不要直接停服務建議先觀察 HAProxy 的狀態頁面或日誌確認它對後端每個節點的監控狀態都是綠色的。然後在 Node2 上執行docker-compose stop # 在 Node2 的 Harbor 安裝目錄下執行或者乾脆模擬硬體故障直接把 VM 關機。然後觀察 HAProxy 節點上的日誌tail -f /var/log/haproxy.log正常情況下幾秒內就能看到健康檢查開始失敗fall 3之後Node2 的狀態會變成紅色HAProxy 自動停止向它轉發請求。此時立刻執行之前的三步驗證流程登入、推送、拉取。全部應該正常完成沒有任何報錯。推送的鏡像會落到 Node1 上但通過共享存儲Node2 恢復後也能讀到同一份數據。這就驗證了「業務無感知的故障轉移」。客戶端的請求被 HAProxy 自動切換到了健康的節點上。4.3 恢復測試與資料最終一致性讓 Node2 恢復服務。重啟 VM 後執行cd /home/harbor/harbor docker-compose up -d等待所有容器啟動完成大概 30 秒到 1 分鐘。HAProxy 的健康檢查通過後Node2 自動回到負載池中。關鍵驗證點剛才在 Node2 宕機期間我們向 Node1 推送了一個新的鏡像現在要在 Node2 上確認這個鏡像是否存在。執行# 從 Node2 本機上拉取 docker pull harbor.example.local/library/nginx:latest如果拉取失敗或報找不到鏡像說明共享存儲配置有問題鏡像數據沒有被真正的共享。正常的結果是立即成功——因為鏡像數據存在共享存儲上Node2 的 registry 服務只是作為一個讀入口它本身不保存數據。同樣的原理也適用於資料庫。在 Node2 恢復後到 Harbor 的 Web 頁面上看一下用戶、項目、權限設置都應該和宕機前保持一致因為這些數據存在共享的 PostgreSQL 中。4.4 性能與穩定性測試高可用不光是「掛了能切」還要驗證正常運行的性能。我建議做兩組測試RAID 隊列測試用腳本並發推送幾十個鏡像觀察兩個節點的 CPU、內存、網路吞吐曲線確認負載是否被有效分散。極端場景測試找一台配置最低的客戶端持續做大批量拉取觀察整體吞吐是否有明顯下降。這能幫你發現 HAProxy 的連接數瓶頸。5. 遇到的坑與排查經驗5.1 健康檢查節點全部判定為 down但 Harbor 本身是好的這個問題出現的機率非常高。排查思路從以下幾步入手先用curl -k https://10.10.1.21/api/v2.0/ping在 HAProxy 節點上直接測試確認 Harbor 介面是真的通。如果 curl 結果正常說明問題在於 HAProxy 的檢查方式。常見原因一HAProxy 配置文件裡檢查的是 HTTP GET/api/v2.0/ping但 Harbor 返回的不是純 200而是帶了 JSON。確認expect status 200是否匹配實際回應碼。常見原因二證書問題。如果ssl verify參數不是noneHAProxy 在檢查時會去驗證後端證書如果 CA 沒被信任檢查就會失敗節點被誤判為 down。常見原因三timeout 太短導致握手失敗。如果你的 Harbor 節點負載較高SSL 握手可能會超過 HAProxy 配置的timeout connect值健康檢查就會頻繁失敗。把timeout connect增到 10 秒左右。5.2 docker login 成功但 docker push 報 unauthorized這個問題的本質是 Harbor 的 token 機制。Harbor 的 registry 元件在收到 push 請求時會把 token 送回 core 元件驗證如果 core 元件的資料庫連線的是不同的 PostgreSQLtoken 驗證就會失敗。這個問題在網上被討論過很多次很多時候是因為配置的 PostgreSQL 不是同一個實例。你的兩個 Harbor 節點必須連到同一個 PostgreSQL 和同一個 Redis否則就會出現「A 節點登入成功但請求到了 B 節點B 節點驗證 token 時用的是自己的資料庫查不到這個 token」的情況。所以排查順序是先確認 Redis 是否共享再確認 PostgreSQL 是否共享最後看兩個節點的時間是否同步。token 是有時效性的時間不同步也可能導致驗證失敗。5.3 切換節點後Kubernetes 拉取鏡像偶爾失敗Kubernetes 節點上的 kubelet 在拉取鏡像時會並發建立多個連接。如果你的 HAProxy 沒有做 stick-table 配置這些連接會被分散到兩個 Harbor 節點。理論上雙活架構下這完全沒問題但實測中偶爾會出現 5xx 錯誤。原因其實不在 Harbor而在底層存儲的競爭。當兩個請求同時讀取同一個未緩存的 blob 層時NFS 在高併發下可能出現短暫的延遲超限。解決方案有兩個方向一是給 HAProxy 加上 stick-table讓同一個來源 IP 的請求盡量落在同一個節點降低跨節點的存儲競爭。二是把共享存儲從 NFS 換到對象存儲比如 MinIO 或 Ceph RGW對象存儲的併發讀寫能力遠超 NFS。5.4 證書輪換後docker 客戶端報 x509 驗證錯誤Harbor 的證書快到期了你重新簽發了一張新證書更新到了 Harbor 節點上。然後客戶端報x509: certificate signed by unknown authority。原因是 Docker 客戶端緩存了舊的 CA 證書。如果你使用的是內部 CA 或者自簽證書CA 本身沒變只是 Harbor 的服務端證書換了客戶端理論上不需要任何操作。但如果 CA 也換了就需要更新客戶端的/etc/docker/certs.d/harbor.example.local/ca.crt。這裡要提醒的是千萬只更新了 Harbor 節點上的證書忽略了客戶端。這類問題通常不是 Harbor 的配置錯誤而是證書鏈沒有傳遞完整。排查方法很簡單在客戶端執行openssl s_client -connect harbor.example.local:443 -showcerts看輸出的證書鏈和你更新後的證書是否一致。5.5 升級 Harbor 版本時要注意什麼高可用架構下Harbor 的升級流程可以做滾動升級不用全量停機。我們的做法是先把其中一個節點從 HAProxy 的負載池中摘除。在 HAProxy 的後端配置中把對應的節點注釋掉# server harbor2 10.10.1.22:443 check inter 5s fall 3 rise 2重載 HAProxy確認流量全部落在 Node1。然後對 Node2 執行升級操作停止 Harbor、備份數據目錄、替換二進制包、執行遷移腳本、重啟。等 Node2 起來並通過健康檢查後把它加回負載池。接著重複同樣的流程升級 Node1。整個過程中業務不會中斷而且兩個節點的版本不會長時間不一致。升級前一定要備份共享的 PostgreSQL 和存儲目錄即使用了滾動升級也要做全量備份以防遷移腳本出問題。5.6 高可用架構下的監控與告警配置HAProxy 本身提供了一個統計頁面通過 Web 介面可以看到每個後端節點的實時狀態。在配置中添加一個監聽段即可listen stats bind *:8404 mode http stats enable stats uri /stats stats auth admin:admin_password這樣就可以在瀏覽器訪問HTTP://10.10.1.10:8404/stats輸入用戶名密碼後看到後端節點的運行狀態。建議對以下三個指標做監控告警後端節點是否全部 down。如果兩個 Harbor 節點都不可用說明整個服務已經中斷需要緊急介入。健康檢查失敗的次數。如果某個節點頻繁出現檢查失敗又恢復說明該節點可能存在隱患比如磁碟快滿了或記憶體洩漏。HAProxy 的連接數和會話數。這個數據能提前預警流量是否在快速增長是否需要擴容節點或調整存儲。6. 最終架構總結與運維建議到這裡整個 HAProxy 實現 Harbor 高可用的架構已經完整落地了。流量入口是 Keepalived 提供的 VIP底下掛著兩台 HAProxy 節點HAProxy 把請求分發到兩台 Harbor 節點上Harbor 底層共享同一套 PostgreSQL、Redis 和鏡像存儲。任何一個 Harbor 節點掛了HAProxy 自動切走流量HAProxy 本身掛了Keepalived 自動切換 VIP單台 Harbor 節點的升級維護也完全不影響業務。這個方案我實際跑了將近一年穩定性非常好。但有些經驗值得拿出來強調一下監控比架構本身更重要。高可用方案不是部署完就一勞永逸的你需要知道節點的健康狀態才能在故障發生前提前干預。磁碟空間尤其值得盯緊鏡像倉庫的磁碟增長速度往往超出預期存儲寫滿的時候再好的高可用架構都白搭。別把 HAProxy 本身搞成單點。很多團隊做完 Harbor 高可用就覺得萬事大吉忘了 HAProxy 也是唯一的入口。配上 Keepalived 是必須的這個成本很低帶來的收益卻很大。升級操作要走流程。高可用架構下很多運維操作可以滾動進行但前提是要有清晰的流程和預案。先摘除節點再執行操作最後加回節點。每一步之前都要想清楚「如果這一步失敗了我該怎麼回滾」。回顧整個過程最有感觸的是高可用架構的本質是讓「故障」這件事從「事故」變成「演練」。鏡像倉庫掛掉的時長從數小時縮短到幾十秒甚至業務層面完全無感知這對研發團隊的交付效率提升是質變級的。如果你還沒做這套方案趁早動手別等鏡像倉庫真的掛了再後悔。