harbor鏡像倉庫遠程複製問題

簡要說明


最近在基於jenkins+docker+harbor做持續集成,開發環境與測試環境在公司內網,可以相通,因此鏡像倉庫之間的主從複製無問題。而生產環境是客戶的雲環境上,因此需要遠程複製,將測試環境與生產環境的鏡像倉庫做遠程複製。我將遠程複製遇到的填坑經驗分享一下。

harbor應用不能添加uri_prefix


首先在生產環境的一臺機器(192.168.2.58)上搭建docker+harbor環境,也比較麻煩,因爲生產環境的內部機器不能直接聯網,所以只能離線安裝docker,docker-compose和harbor(harbor也是docker鏡像安裝的)。harbor的nginx配置如下(配置太長,刪減了部分):

  server {
    listen 80;
    server_tokens off;  
    client_max_body_size 0;
    include /etc/nginx/conf.d/harbor.http.*.conf;

    location / {
      proxy_pass http://portal/;
      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_set_header X-Forwarded-Proto $scheme;      
      proxy_buffering off;
      proxy_request_buffering off;
    }

    location /c/ {
       ...
    }

    location /api/ {
      ...
    }

    location /chartrepo/ {
      ...
    }

    location /v1/ {
      return 404;
    }

    location /v2/ {
      ...
    }

    location /service/ {
      ...
    }

    location /service/notifications {
      return 404;
    }
  }
}

其次在生產的入口nginx,添加一個location指向harbor機器上。

upstream harbor_server{
  server 192.168.2.58   #harbor應用
}

server{
  #...

  location /harbor{
    proxy_pass http://harbor_server;
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $Remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

問題來了。

問題描述


在本地通過***可以正常訪問及操作遠端的192.168.2.58的harbor應用。然後通過生產環境的http://www.xxx.com/harbor正常打開harbor登錄頁面,但是怎麼都登錄不了。

打開google的Network查看一下,發現登錄的login請求url有問題。

Request URL:
http://www.xxx.cn/c/login
Request Method:
POST
Status Code:
404 Not Found

我去。。這個地址能登進去才神奇。入口的nginx哪有配置/c或者/c/login的路徑映射。在內部的harbor機器的nginx纔有相關配置。入口的nginx已經攔截下來,你後續能訪問纔怪。

一般類似web應用,請求的路徑一般是通過context_path加上相對路徑。例如: 部署的應用名稱爲/app,那麼訪問c/login,請求的路徑應該是http://ip:port/app/c/login。ngnix可以配置成location app{proxy_pass http://ip:port/app},就可以正常訪問。

但是harbor並不能直接設置uri_prefix,他提供的訪問路徑是http://ip:port/直接訪問。並未提供應用名稱,能否設置uri_prefix,很遺憾,暫時未找到哪個地方設置,直接網上搜索,果然在github上有人提出類似的問題。

https://github.com/goharbor/harbor/issues/6772

問題描述:

To deploy harbor and notary using the same hostname, I need to be able to use custom paths.
Unfortunately, it's impossible yet mainly because the Angular app cannot be configured at runtime before it's first api call.
This issue is related to the following Pull Request : goharbor/harbor-helm#143
Ideally, I wish to able to set or query param, a cookie or an environment variable to make Angular application to use an URI prefix for all of its API calls.
It seems that the first problem is that, in src/app/app-config.service.ts, systemInfoEndpoint, the API endpoint used to get Harbor configuration is hardcoded.
Also I have now easy way to transmit params to the Angular application at runtime (eg. systemInfoEndpoint URL).
Even if I was able to transmit a parameter to customize this URL, there is no way to easily set uri_prefix globally. We have to redefine all endpoints URLs.
In a try to fix this issue rfom the outside, without touching to the Angular app, Iadd additional annotations to the ingress configuration:
nginx.ingress.kubernetes.io/rewrite-target: /
nginx.ingress.kubernetes.io/add-base-url: "true"
It works properly for the HTML part of the app but unfortunately not for API calls.
Maybe it is more a feature request than an issue.
Thank you for your help.

作者回答:

@max-k With initial thinking, I believe it's possible to allow user to set prefix, but we need to balance the complexity in configuration, we don't want to add to many settings that may confuse users until we have to.
Could you let us know the motivation of this requirement?
Do you want same or different prefix for registry and notary and Harbor API? I believe docker client will only communicate with /v2/ api, not /prefix/v2.
In addition, I recall there used to be a bug in notary to support prefix in its service and I submitted a patch. We'll also need to double check whether it's included in the latest build of notary.

---“我相信允許用戶設置前綴是可能的,但是我們需要平衡配置的複雜性,我們不想添加到許多設置中,這些設置可能會混淆用戶,直到我們不得不這樣做。”

我去,擺明是不想解決這個issue,這個解決問題的想法不可取啊。

好吧,只能自己來解決。

解決辦法


解決思路也很簡單:在入口nginx配置location /harbor{}指向Harbor應用,後續的請求則通過referer來判斷,如果是來源於/harbor,則直接在轉向harbor應用即可。

修改入口的nginx配置

location / {
   root   html;
   index  index.html index.htm;

   proxy_set_header    Host $http_host;
   proxy_set_header    X-Real-IP $remote_addr;
   proxy_set_header    X-Forwarded-For $proxy_add_x_forwarded_for;

  
   if ($http_referer ~* "/harbor"){
     proxy_pass http://harbor_server;
   }
}

使用nginx -s reload重新加載配置,然後再次登錄,就OK了。

當然,除了這個解決方法之外,也有其他的解決辦法:

  • 一個是用另外一個外網入口(二級域名也行),直接指向harbor,但是需要用域名。一般來說,涉及到域名的基本上都不考慮這種解決辦法。

  • 一個是修改harbor應用本身,給他添加應用前綴,但這種耗時費力,不討好的事情咱不幹。

  • 當然如果你不想用harbor也可以,用其他的鏡像倉庫,如:Nexus、Docker Repository、Dragonfly、Portus。會不會也出現這種問題,我也不知道,沒實際使用經驗


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章