VMware Harbor:基於 Docker Distribution 的企業級 Registry 服務

前言

對於 Harbor 這樣一個優秀的 Docker Registry 管理開源項目,如下內容基本上來自前人已有的研究,我只是將其在實踐中進行了測試,並整理聚集了相關資料供你們參考,同時針對 Harbor 與 Rancher產品的整合作了一些實驗性的工做,以更好更全面的理解 Harbor 這個工具,也更加了解 Rancher 在快速一鍵部署、彈性伸縮高可用等方面的優點。python

Harbor 簡介

Harbor 是一個企業級 Registry 服務。它對開源的 Docker Registry 服務進行了擴展,添加了更多企業用戶須要的功能。Harbor 被設計用於部署一套組織內部使用的私有環境,這個私有 Registry 服務對於很是關心安全的組織來講是十分重要的。另外,私有 Registry 服務能夠經過避免從公域網下載鏡 像而提升企業生產力。這對於沒有良好的 Internet 鏈接狀態,使用 Docker Container 的用戶是一個福音。mysql

  • 基於角色的訪問控制:用戶與 Docker 鏡像倉庫經過「項目」進行組織管理,一個用戶能夠對多個鏡像倉庫在同一命名空間(project)裏有不一樣的權限。linux

  • 圖形化用戶界面:用戶能夠經過瀏覽器來瀏覽,檢索當前 Docker 鏡像倉庫,管理項目和命名空間。nginx

  • 審計管理:全部針對鏡像倉庫的操做均可以被記錄追溯,用於審計管理。git

  • 國際化:基於英文與中文語言進行了本地化。能夠增長更多的語言支持。github

  • RESTful API - RESTful API:提供給管理員對於 Harbor 更多的操控, 使得與其它管理軟件集成變得更容易。web

Harbor 架構介紹

(1)主要組件

圖片描述

Harbor 在架構上主要由五個組件構成:sql

  • Proxy:Harbor 的 registry, UI, token 等服務,經過一個前置的反向代理統一接收瀏覽器、Docker 客戶端的請求,並將請求轉發給後端不一樣的服務。docker

  • Registry:負責儲存 Docker 鏡像,並處理 docker push/pull 命令。因爲咱們要對用戶進行訪問控制,即不一樣用戶對 Docker image 有不一樣的讀寫權限,Registry 會指向一個 token 服務,強制用戶的每次 docker pull/push 請求都要攜帶一個合法的 token, Registry 會經過公鑰對 token 進行解密驗證。數據庫

  • Core services:這是 Harbor 的核心功能,主要提供如下服務:

UI:提供圖形化界面,幫助用戶管理 registry 上的鏡像(image),並對用戶進行受權;
webhook:爲了及時獲取 registry 上 image 狀態變化的狀況, 在 Registry 上配置 webhook,把狀態變化傳遞給 UI 模塊;
token 服務:負責根據用戶權限給每一個 docker push/pull 命令簽發 token。Docker 客戶端向Registry 服務發起的請求,若是不包含token,會被重定向到這裏,得到 token 後再從新向 Registry進行請求;

  • Database:爲 core services 提供數據庫服務,負責儲存用戶權限、審計日誌、Docker image 分組信息等數據。

  • Log collector:爲了幫助監控 Harbor 運行,負責收集其餘組件的 log,供往後進行分析。各個組件之間的關係以下圖所示:

圖片描述

(2)實現

Harbor 的每一個組件都是以 Docker 容器的形式構建的,所以很天然地,咱們使用 Docker Compose 來對它進行部署。在源代碼中(https://github.com/vmware/har...,用於部署 Harbor 的 Docker Compose 模板位於 /Deployer/docker-compose.yml. 打開這個模板文件,會發現 Harbor 由 5 個容器組成:

  • proxy:由 Nginx 服務器構成的反向代理。

  • registry:由 Docker 官方的開源 registry 鏡像構成的容器實例。

  • ui:即架構中的 core services, 構成此容器的代碼是 Harbor 項目的主體。

  • mysql:由官方 MySql 鏡像構成的數據庫容器。

  • log: 運行着 rsyslogd 的容器,經過 log-driver 的形式收集其餘容器的日誌。

這幾個容器經過 Docker link 的形式鏈接在一塊兒,這樣,在容器之間能夠經過容器名字互相訪問。對終端用戶而言,只須要暴露 proxy (即 Nginx)的服務端口。

(3)工做原理

下面以兩個 Docker 命令爲例,講解主要組件之間如何協同工做。

1) docker login

假設咱們將 Harbor 部署在主機名爲 registry.yourdomainname.com 的虛機上。用戶經過 docker login 命令向這個 Harbor 服務發起登陸請求:docker login registry.yourdomainname.com當用戶輸入所需信息並點擊回車後,Docker 客戶端會向地址「registry.yourdomainname.com/v2/」 發出 HTTP GET 請求。 Harbor 的各個容器會經過如下步驟處理:

(a) 首先,這個請求會由監聽 80 端口的 proxy 容器接收到。根據預先設置的匹配規則,容器中的 Nginx會將請求轉發給後端的 registry 容器;

(b) 在 registry 容器一方,因爲配置了基於 token 的認證,registry 會返回錯誤代碼 401,提示 Docker客戶端訪問 token 服務綁定的 URL。在 Harbor 中,這個 URL 指向 Core Services;

(c) Docker 客戶端在接到這個錯誤代碼後,會向token服務的URL發出請求,並根據HTTP協議的BasicAuthentication 規範,將用戶名密碼組合並編碼,放在請求頭部(header);

(d)相似地,這個請求經過 80 端口發到 proxy 容器後,Nginx 會根據規則把請求轉發給 ui 容器,ui 容器監聽 token 服務網址的處理程序接收到請求後,會將請求頭解碼,獲得用戶名、密碼;

(e) 在獲得用戶名、密碼後,ui 容器中的代碼會查詢數據庫,將用戶名、密碼與 mysql 容器中的數據進行比對(注:ui 容器還支持 LDAP 的認證方式,在那種狀況下 ui 會試圖和外部 LDAP 服務進行通訊並校驗用戶名/密碼)。比對成功,ui 容器會返回表示成功的狀態碼, 並用密鑰生成 token,放在響應體中返回給 Docker 客戶端。這個過程當中組件間的交互過程以下圖所示:

圖片描述

至此,一次 docker login 成功地完成了,Docker 客戶端會把步驟(c)中編碼後的用戶名密碼保存在本地的隱藏文件中。

2) docker push

用戶登陸成功後用 docker push 命令向 Harbor 推送一個 Docker 鏡像:docker push registry.youdomainname.com/library/hello-world

(a) 首先,docker 客戶端會重複 login 的過程,首先發送請求到 registry,以後獲得 token 服務的地址;

(b) 以後,Docker 客戶端在訪問ui容器上的token服務時會提供額外信息,指明它要申請一個對imagelibrary/hello-world 進行 push 操做的 token;

(c) token 服務在通過 Nginx 轉發獲得這個請求後,會訪問數據庫覈實當前用戶是否有權限對該 image進行 push。若是有權限,它會把 image 的信息以及 push 動做進行編碼,並用私鑰簽名,生成 token返回給 Docker 客戶端;

(d) 獲得 token 以後 Docker 客戶端會把 token 放在請求頭部,向 registry 發出請求,試圖開始推送image。 Registry 收到請求後會用公鑰解碼 token 並進行覈對,一切成功後,image 的傳輸就開始了。咱們省去 proxy 轉發的步驟,下圖描述了這個過程當中各組件的通訊過程 :

圖片描述

Harbor 單機安裝調試步驟

這次示範以 CentOS 7.2.1511 x86_64 爲例:

[root@registry ~]# yum install https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-selinux-1.11.2-
    
    1.el7.centos.noarch.rpm
    [root@registry ~]# yum install https://yum.dockerproject.org/repo/main/centos/7/Packages/docker-engine-1.11.2-
    
    1.el7.centos.x86_64.rpm
    [root@registry ~]# systemctl enable docker
    [root@registry ~]# systemctl start docker
    [root@registry ~]# yum install git
    [root@registry ~]# git clone https://github.com/vmware/harbor
    [root@registry ~]# cd harbor/
    [root@registry harbor]# cd Deploy/
    [root@registry Deploy]# vi harbor.cfg

修改的重點內容以下:

hostname = registry.yourdomainname.comui_url_protocol = https
    
    email_server = smtp.yourmailserver.comemail_server_port = 25
    email_username = registry_admin@yourdomainname.comemail_password = yourpassword
    email_from = registry_admin@yourdomainname.comemail_ssl = false
    
    harbor_admin_password = myharborpasswordauth_mode = db_auth
    db_password = yoursqlpasswordself_registration = off
    customize_crt = off

修改完成

假設已經準備好站點的數字證書文件 registry.yourdomainname.com.crt 和registry.yourdomainname.com.key,則能夠配置 https 的訪問模式:

[root@registry Deploy]# cd config/nginx/
[root@registry nginx]# ls cert/
registry.yourdomainname.com.crt registry.yourdomainname.com.key
[root@registry nginx]# mv nginx.conf nginx.conf.bak
[root@registry nginx]# cp nginx.https.conf nginx.conf
[root@registry nginx]# vi nginx.conf

修改內容以下:

圖片描述
圖片描述

修改內容結束

安裝 docker-compose 命令:

圖片描述
圖片描述

添加 harbor 的啓停腳本:

圖片描述

添加 harbor 爲 systemd 服務:

圖片描述

管理 Harbor 的生命週期:

圖片描述

關於數字證書,上面的描述適用於向第三方根證書頒發機構申請獲得的數字證書文件,若是是自簽名數字證書,可參考 Harbor 官方文檔:https://github.com/vmware/har...

訪問 Harbor:

  1. 網頁訪問方式 https://registry.yourdomainna...

  2. Linux Docker 客戶端如須要訪問這個倉庫服務器,若是數字證書的根證書頒發機構不在系統列表裏,則須要手動添加信任關係(須要將證書文件 registry.yourdomainname.com.crt 拷貝至指定目錄),而後更新證書緩存:

cp registry.yourdomainname.com.crt /usr/local/share/ca-certificates/update-ca-certificates

以上兩條命令適用於 Ubuntu 系列

cp registry.yourdomainname.com.crt/etc/pki/ca-trust/source/anchors/update-ca-trust

以上兩條命令適用於 RHEL 或 CentOS 系列

登錄及 push image 過程:

[root@RancherHost01 ~]# docker login
registry.yourdomainname.com
Username: admin
Password:
Login Succeeded
[root@RancherHost01 ~]#

圖片描述

登錄 Web 端便可看見已經上傳的 image 了:

圖片描述

新增用戶界面:

圖片描述

Harbor 做爲 Mirror Registry

Mirror 是 Docker Registry 的一種特殊類型,它起到了相似代理服務器的緩存角色,在用戶和Docker Hub 之間作 Image 的緩存。

其基本工做原理是,當用戶 pull 一個鏡像時,若鏡像在 mirror 服務器存在,則直接從 mirror 服務器拉取,不然若不存在該鏡像,則由 mirror server 自動代理往 dockerhub(可配置)中拉取鏡像,並緩存到 mirror 服務器中,當客戶再次拉取這個鏡像時,直接從 mirror server 中拉取,不須要再次從docker hub 中拉取。

Harbor 目前不支持 pull cache 功能,已提交 Github issue #120。 https://github.com/vmware/har...

不過咱們只須要手動修改下配置便可完成,具體配置可查看官方 Registry as a pull through cache.
https://github.com/vmware/har...

咱們在運行./prepare 以前修改 config/registry/config.yml 文件,追加如下配置

:proxy:remoteurl: https://registry-1.docker.io

若是須要訪問私有倉庫,須要填寫 Docker Hub 的用戶名和密碼

:proxy:
remoteurl: https://registry-1.docker.io
username: [username]
password: [password]

而後從新啓動 Harbor 服務:(注意不要執行./prepare)

docker-compose stop 
docker-compose rm -f 
docker-compose up -d

除了設置 Harbor(或者 registry),還須要配置本地 docker 服務,指定--registry-mirror 參數,修改docker 配置文件

Ubuntu:/etc/default/docker

DOCKER_OPTS="$DOCKER_OPTS --registry-mirror=https://registry.yourdomainname.com

DOCKER_OPTS="$DOCKER_OPTS --registry-mirror=https://registry.yourdomainname.com --insecure-registry 

registry.yourdomainname.com"

或者

RHEL/CentOS:/usr/lib/systemd/system/docker.service):
[Service]
ExecStart=
ExecStart=/usr/bin/docker daemon -H fd:// --registry-mirror=https://registry.yourdomainname.com

注意:修改了 docker 配置文件,必須重啓 docker 服務才能生效。

Harbor 因爲引進了認證功能,所以 push 操做時,必須保證 project 存在,好比 push
krystism/ffmpeg,必須保證 Harbor 建立了 krystism project,不然會失敗。爲了可以正常 push/pulldockerhub 的官方鏡像,務必建立 library project,如圖:

圖片描述

(1)假設本地不存在 python 鏡像:

咱們第一次 pull python 後,Harbor 發現不存在該鏡像,因而本身做爲代理往 Docker Hub 里拉取,拉取後保存到本地,能夠經過 Web UI 查看。客戶端再次拉取 python 鏡像時,因爲 Harbor 已經存在該鏡像,所以不須要再往 Docker Hub 拉取,速度大幅度提升!

注意,對於 Mirror Registry 模式,雖然能夠 pull cache 了,可是 push 功能卻不被支持了:https://github.com/vmware/har...

(2)與 Rancher 的整合:

1)Add Harbor deploy stack and 5 services in Rancher:(在 Rancher 系統裏添加包含 5 個 services 的stack)

圖片描述

2)Add Registry server in Rancher:(在 Rancher 系統裏添加 Registry 服務器,供 Rancher Agent Hosts調用)

圖片描述

3)Build a Catalog entry in Rancher:(爲 Harbor 建立一個 Rancher 專有的應用模板項,實現一鍵部署,使安裝調試複雜的 Harbor 產品簡單化、並實現彈性伸縮及高可用等特性)

圖片描述

(3)對接 LDAP 認證:

Harbor 支持兩種認證方式,默認爲本地存儲,即帳號信息存儲在 mysql 下,上文已經具體介紹。接下來介紹另一種認證方式 LDAP,只須要修改配置文件便可。須要提供 ldap url 以及 ldap basedn 參數,而且設置 auth_mode 爲 ldap_auth。

快速部署 LDAP 服務:

爲了測試方便,咱們使用 Docker 啓動一個 LDAP 服務器,啓動腳本以下:

!/bin/bash
NAME=ldap_server
docker rm -f $NAME 2>/dev/null
docker run --env LDAP_ORGANISATION="Unitedstack Inc." \--env LDAP_DOMAIN="ustack.com" \
--env LDAP_ADMIN_PASSWORD="admin_password" \
-v pwd/containers/openldap/data:/var/lib/ldap \
-v pwd/containers/openldap/slapd.d:/etc/ldap/slapd.d \--detach --name $NAME osixia/openldap:1.1.2

建立新用戶,首先須要定義 ldif 文件,

new_user.ldif:dn: uid=test,dc=ustack,dc=com
uid: test
cn: test
sn: 3
objectClass: topobjectClass: posixAccountobjectClass: inetOrgPersonloginShell: /bin/bashhomeDirectory: 

/home/testuidNumber: 1001gidNumber: 1001userPassword: 1q2w3e4rmail: test@example.comgecos: test

經過如下腳本建立新用戶,其中 ldap_server 爲 LDAP 服務容器名稱。

docker cp new_user.ldif ldap_server:/
docker exec ldap_server ldapadd -x \
-D "cn=admin,dc=ustack,dc=com" \
-w admin_password \-f /new_user.ldif -ZZ

查看用戶是否建立成功:

docker exec ldap_server ldapsearch -x -h localhost \
-b dc=ustack,dc=com -D "cn=admin,dc=ustack,dc=com" \
-w admin_password

檢查 test 用戶是否存在,若存在,則說明建立成功,不然須要使用 docker logs 查看日誌。

配置 Harbor 使用 LDAP 認證
修改 harbor.cfg 文件關於 LDAP 配置項,以下

:auth_mode = ldap_auth
ldap_url = ldap://42.62.x.x
ldap_basedn = uid=%s,dc=ustack,dc=com

而後從新部署 Harbor:

./prepare 
docker-compose stop 
docker-compose rm -f 
docker-compose up -d

測試是否可以使用 test 用戶登陸:

docker login -u test -p 1q2w3e4r \
-e test@example.com 42.62.x.x
相關文章
相關標籤/搜索