一、harbor概述
VMware開源的企業級Registry項目Harbor,以Docker公司開源的registry 為基礎,提供了管理UI, 基於角色的訪問控制(Role Based Access Control),AD/LDAP集成、以及審計日志(Audit logging) 等企業用戶需求的功能,同時還原生支持中文,主要特點:
-
基於角色的訪問控制 - 用戶與 Docker 鏡像倉庫通過“項目”進行組織管理,一個用戶可以對多個鏡像倉庫在同一命名空間(project)里有不同的權限。
-
鏡像復制 - 鏡像可以在多個 Registry 實例中復制(同步)。尤其適合於負載均衡,高可用,混合雲和多雲的場景。
-
圖形化用戶界面 - 用戶可以通過瀏覽器來瀏覽,檢索當前 Docker 鏡像倉庫,管理項目和命名空間。
-
AD/LDAP 支持 - Harbor 可以集成企業內部已有的 AD/LDAP,用於鑒權認證管理。
-
審計管理 - 所有針對鏡像倉庫的操作都可以被記錄追溯,用於審計管理。
-
國際化 - 已擁有英文、中文、德文、日文和俄文的本地化版本。更多的語言將會添加進來。
-
RESTful API - RESTful API 提供給管理員對於 Harbor 更多的操控, 使得與其它管理軟件集成變得更容易。
-
部署簡單 - 提供在線和離線兩種安裝工具, 也可以安裝到 vSphere 平台(OVA 方式)虛擬設備
二、harbor架構介紹
默認情況下,Harbor運行起來后有如下容器:

名稱分別為:nginx、harbor-jobservice、harbor-ui、harbor-db、harbor-adminserver、registry以及harbor-log。

如上圖所描述,Harbor由6個大的模塊所組成:
-
Proxy: Harbor的registry、UI、token services等組件,都處在一個反向代理后邊。該代理將來自瀏覽器、docker clients的請求轉發到后端服務上。
-
Registry: 負責存儲Docker鏡像,以及處理Docker push/pull請求。因為Harbor強制要求對鏡像的訪問做權限控制, 在每一次push/pull請求時,Registry會強制要求客戶端從token service那里獲得一個有效的token。
-
Core services: Harbor的核心功能,主要包括如下3個服務:
1)UI: 作為Registry Webhook, 以圖像用戶界面的方式輔助用戶管理鏡像。
2)WebHook:WebHook是在registry中配置的一種機制, 當registry中鏡像發生改變時,就可以通知到Harbor的webhook endpoint。Harbor使用webhook來更新日志、初始化同步job等。
3) Token 服務:負責根據用戶權限給每個docker push/pull命令簽發token. Docker 客戶端向Regiøstry服務發起的請求,如果不包含token,會被重定向到這里,獲得token后再重新向Registry進行請求。 -
Database:為core services提供數據庫服務,負責儲存用戶權限、審計日志、Docker image分組信息等數據。 -
Job services: 主要用於鏡像復制,本地鏡像可以被同步到遠程Harbor實例上。
-
Log collector: 負責收集其他組件的日志到一個地方
這里我們與上面運行的7個容器對比,對harbor-adminserver感覺有些疑慮。其實這里harbor-adminserver主要是作為一個后端的配置數據管理,並沒有太多的其他功能。harbor-ui所要操作的所有數據都通過harbor-adminserver這樣一個數據配置管理中心來完成。
三、Harbor實現
Harbor的每一個組件都被包裝成一個docker容器。自然,Harbor是通過docker compose來部署的。在Harbor源代碼的make目錄下的docker-compose模板會被用於部署Harbor。打開該模板文件,可以看到Harbor由7個容器組件所組成:
-
proxy: 通過nginx服務器來做反向代理 -
registry: docker官方發布的一個倉庫鏡像組件 -
ui: 整個架構的核心服務。該容器是Harbor工程的主要部分 -
adminserver: 作為Harbor工程的配置數據管理器使用 -
mysql: 通過官方Mysql鏡像創建的數據庫容器 -
job services: 通過狀態機的形式將鏡像復制到遠程Harbor實例。鏡像刪除同樣也可以被同步到遠程Harbor實例中。 -
log: 運行rsyslogd的容器,主要用於收集其他容器的日志
這些容器之間都通過Docker內的DNS服務發現來連接通信。通過這種方式,每一個容器都可以通過相應的容器來進行訪問。對於終端用戶來說,只有反向代理(Nginx)服務的端口需要對外暴露。
四、harbor部署
1、系統版本

2、軟件版本(Docker安裝過程略)

3、安裝docker-compose(Harbor是通過docker compose來部署的)
1)配置阿里的epel源
# wget -O /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo
2)安裝並升級Python-pip
# yum install python-pip -y
# pip install --upgrade pip
3)安裝docker-compose
# pip install docker-compose
4)查看docker-compose版本
# docker-compose -v docker-compose version 1.26.2, build unknow
4、下載harbor安裝包
1)可以在網站上下載離線安裝包
地址:https://github.com/goharbor/harbor/releases

此處我們下載的是最新版:2.0.1版本:
https://github.com/goharbor/harbor/releases/download/v2.0.1/harbor-offline-installer-v2.0.1.tgz
2)國內harbor離線版鏡像(版本可能不是最新,下載速度較快)
5、解壓harbor離線版安裝包
# tar xf harbor-offline-installer-v2.0.1.tgz # cd harbor # ll 總用量 522300 -rw-r--r-- 1 root root 3361 6月 29 09:58 common.sh -rw-r--r-- 1 root root 534799479 6月 29 09:58 harbor.v2.0.1.tar.gz -rw-r--r-- 1 root root 7816 6月 29 09:58 harbor.yml.tmpl -rwxr-xr-x 1 root root 2523 6月 29 09:58 install.sh -rw-r--r-- 1 root root 11347 6月 29 09:58 LICENSE -rwxr-xr-x 1 root root 1856 6月 29 09:58 prepare
6、修改harbor安裝的配置文件
# cp harbor.yml.tmpl harbor.yml # mkdir -p /opt/application/harbor //用於存放harbor的持久化數據 harbor.yml配置文件主要修改參數如下: hostname: 192.168.0.8:9999 //設置訪問地址,可以使用ip、域名,不可以設置為127.0.0.1或localhost。默認情況下,harbor使用的端口是80,若使用自定義的端口,除了要改docker-compose.yml文件中的配置外,這里的hostname也要加上自定義的端口,否則在docker login、push時會報錯 #http配置 http: # port for http, default is 80. If https enabled, this port will redirect to https port port: 9999 #https配置(如不需要可不配置,注釋掉) # https related config #https: # https port for harbor, default is 443 #port: 443 # The path of cert and key files for nginx #certificate: /your/certificate/path #private_key: /your/private/key/path #external_url: https://reg.mydomain.com:8433 //如果要啟用外部代理,比如外層的NGINX、LB等,請取消注釋external_url,當它啟用時,hostname將不再使用。 harbor_admin_password: Harbor12345 //admin密碼 #數據庫配置 database: # The password for the root user of Harbor DB. Change this before any production use. password: root123 # The maximum number of connections in the idle connection pool. If it <=0, no idle connections are retained. max_idle_conns: 50 # The maximum number of open connections to the database. If it <= 0, then there is no limit on the number of open connections. # Note: the default number of connections is 100 for postgres. max_open_conns: 100 #持久化數據目錄 data_volume: /opt/application/harbor ……
7、安裝並啟動Harbor
安裝之前需要啟動docker,然后執行安裝腳本:

安裝完成后查看下正在運行的docker容器:
8、訪問harbor WEB界面
http://192.168.0.8:9999 admin Harbor12345


五、Harbor的使用(上傳下載鏡像)
1、登錄harbor
# docker login 192.18.0.8:9999 Username: admin Password: Error response from daemon: Get https://192.18.0.8:9999/v2/: net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)
報錯原因:Docker自從1.3.X之后docker registry交互默認使用的是HTTPS,但是我們搭建私有鏡像默認使用的是HTTP服務,所以與私有鏡像交時出現以上錯誤。
報錯解決:
修改Docker的配置文件/etc/docker/daemon.json :
# vim /etc/docker/daemon.json
{
"registry-mirrors": ["https://k728i8z5.mirror.aliyuncs.com"],
"insecure-registries":["192.168.0.8:5000"],
"insecure-registries":["192.168.0.8:9999"]
}
然后重新啟動Docker:
# systemctl restart docker
2、在Harbor上創建新項目供上傳使用

3、給構建好的鏡像打標簽並上傳到harbor
# docker tag xoa_all_production:v1 192.168.0.8:9999/xoa_all_production/2020.06.01.1:v1
# docker push 192.168.0.8:9999/xoa_all_production/2020.06.01.1:v1
The push refers to repository [192.168.0.8:9999/xoa_all_production/2020.06.01.1]
9d4aefde8c76: Pushed
22e5c751af2a: Pushed
8143d5ce48e6: Pushed
39f6023f8742: Pushed
5a4d6e35085c: Pushed
56057dc217a6: Pushed
452b3c93db6e: Pushed
aaefb8d976d1: Pushed
f1de55fab847: Pushed
72223f98927f: Pushed
edf3aa290fb3: Pushed
v1: digest: sha256:81de8ab261ecfdb0bfd66ed1b1db8c13222b288fcd732c1dcdd09446f250b185 size: 2637
注意:xoa_all_production:這個是項目名稱,非鏡像名。如果tag的鏡像名是:192.168.0.8:9999/xoa_all_production:v1,在推送過程中會報錯,會不知道把鏡像上傳到哪去,最終會報錯。為此耗費了不少時間去排錯。

4、下載鏡像
# docker rmi 192.168.0.8:9999/xoa_all_production/2020.06.01.1:v1 //先刪除本地鏡像 # docker pull 192.168.0.8:9999/xoa_all_production/2020.06.01.1:v1 //拉取鏡像 v1: Pulling from xoa_all_production/2020.06.01.1 Digest: sha256:81de8ab261ecfdb0bfd66ed1b1db8c13222b288fcd732c1dcdd09446f250b185 Status: Downloaded newer image for 192.168.0.8:9999/xoa_all_production/2020.06.01.1:v1
六、Harbor如何停止與啟動
# cd soft/harbor //切換到harbor安裝包目錄 # docker-compose stop //停止Harbor # docker-compose start //啟動Harbor
七、Harbor使用外部代理
harbor默認只能使用harbor.yml中hostname指定的ip或主機名作為web訪問地址,但在實際使用過程中,一般不允許ip地址或者主機名直接暴露在外訪問,故需要配置nginx代理,通過代理后指定的地址進行訪問。
配置方式:
修改harbor.yml,把https相關的注釋(如果沒有注釋,http會自動重定向到https,導致多次重定向),然后添加external_url配置:
# Configuration file of Harbor # The IP address or hostname to access admin UI and registry service. # DO NOT use localhost or 127.0.0.1, because Harbor needs to be accessed by external clients. hostname: 192.168.0.8:9999 # http related config http: # port for http, default is 80. If https enabled, this port will redirect to https port port: 9999 # https related config #https: # https port for harbor, default is 443 #port: 443 # The path of cert and key files for nginx #certificate: /your/certificate/path #private_key: /your/private/key/path # # Uncomment following will enable tls communication between all harbor components # internal_tls: # # set enabled to true means internal tls is enabled # enabled: true # # put your cert and key files on dir # dir: /etc/harbor/tls/internal # Uncomment external_url if you want to enable external proxy # And when it enabled the hostname will no longer used external_url: https://harbor.xxx.cn #如果這里是https,nginx代理就需要配置ssl
……
修改配置后docker-compose down停止所有服務,刪除當前配置目錄:rm -rf ./common/config下配置清單,重新執行install.sh生成配置
NGINX外部代理配置文件:
server { listen 80; server_name harbor.xxx.cn; #client_max_body_size 1000M; access_log /data/wwwlogs/harbor.xxx.cn_access.log combined; rewrite ^(.*) https://$server_name$1 permanent; location / { #proxy_redirect off; #proxy_set_header Host $host; #proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:9999; } } ##########################ssl####################### server { listen 443 ssl; server_name harbor.xxx.cn; ssl_certificate sslkey/harbor.xxx.cn_chain.crt; ssl_certificate_key sslkey/harbor.xxx.cn_key.key; ssl_session_cache shared:SSL:1m; ssl_session_timeout 5m; ssl_ciphers HIGH:!aNULL:!MD5; ssl_prefer_server_ciphers on; access_log /data/wwwlogs/harbor.xxx.cn_access.log combined; location / { #proxy_redirect off; #proxy_set_header Host $host; #proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://127.0.0.1:9999; } }
注意:這幾項配置都不要,注釋掉,否則在pull和push鏡像的時候會報錯。
#proxy_redirect off; #proxy_set_header Host $host; #proxy_set_header X-Real-IP $remote_addr; #proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
具體報錯如下:
# docker push harbor.xxx.cn/xxx/ubuntu
The push refers to repository [harbor.xxx.cn/xxx/ubuntu]
7555a8182c42: Pushing [==================================================>] 72.78MB/72.78MB
unknown blob
# docker push harbor.xxx.cn/xxx/ubuntu
The push refers to repository [harbor.xxx.cn/xxx/ubuntu]
7555a8182c42: Pushing [==================================================>] 72.78MB/72.78MB
dial tcp 127.0.0.1:9999: connect: connection refused
另外一個報錯:push的鏡像文件比較大的時候
error parsing HTTP 413 response body: invalid character '<' looking for beginning of value: "<html>\r\n<head><title>413 Request Entity Too Large</title></head>\r\n<body>\r\n<center><h1>413 Request Entity Too Large</h1></center>\r\n<hr><center>nginx</center>\r\n</body>\r\n</html>\r\n"
解決方式:
修改外部代理nginx配置文件:nginx.conf
client_max_body_size默認為0, 修改0為特定的大小即可。如 client_max_body_size 102400M
