search
尋找貓咪~QQ 地點 桃園市桃園區 Taoyuan , Taoyuan

如何在Rancher Catalog中使用VMware Harbor

Harbor Registry是VMware公司的Docker鏡像管理產品。相較於其他鏡像倉庫,Harbor提供身份管理功能,安全性更高,支持單個主機上的多個registry,這些功能正是很多企業用戶需要的。

在Rancher容器管理平台之上,VMware Harbor可以被添加為Rancher應用商店(Catalog)中的一個條目。本文將展示如何將Harbor在線安裝程序docker化,然後rancher化,從而在Docker主機的分散式集群上安裝Harbor。

本文作者MASSIMO是VMware雲原生應用程序事業部的雲架構師。

為了進一步了解Docker容器和它們的生態系統,我在過去幾個月里一直在關注Rancher(開源容器管理平台)。

我最感興趣的是Rancher的可擴展的應用商店(Catalog)和基礎設施服務: Library為官方應用商店目錄(由Rancher維護和構建),還有一個叫做「社區應用商店」(由Rancher維護,但由Rancher社區建立和支持),此外,用戶還可以添加私有應用商店目錄(你可以添加自己的私有目錄條目並且自己進行維護)。

雖然Rancher支持用戶連接Cloud Registry,但是在社區目錄中只有一個 Registry(Convoy Registry)可以進行部署和管理。這會是添加VMware Harbor為私有目錄項選項的好機會,如下圖所示:

你應該考慮所有你了解到的情況,從字面上說,在當前的形態下,能否把一個想法照搬到生產目的中去。

致謝

在我們深入討論這個問題之前,我想要感謝Rancher的Raul Sanchez(耐心地)為我答疑解惑(並幫我修復了一些錯誤的yaml)。如果沒有他的幫助,我想這篇blog會短很多。當然了,因為大家應該都會這樣吧,所以我還要感謝我的妻子和我的狗(雖然我沒有狗)。

困難升級

首先,我需要先完成一定數量的任務,以完成初始目標。一般來說,一個任務都是依賴於另一個任務的。

如果你想要創建Rancher應用商店條目,就要從應用程序定義文件(使用默認的Cattle調度程序時的標準Docker Compose文件)和Rancher Compose文件上實例化你的應用程序。shell腳本或類似的東西並不能成為Rancher應用商店條目的一部分。

你是不是在研究如何(通過文檔化的「在線安裝程序」)在Docker主機上安裝Harbor? 它與Rancher應用商店模型並不真正兼容。你可以參考下面的步驟:

安裝Harbor時,必須先下載Harbor在線tar.gz安裝程序文件,並在harbor.cfg文件中設置你的配置設置,然後運行」準備」腳本。這個腳本會輸入harbor.cfg文件,然後創建配置文件和環境變數文件。最後,運行Docker Compose文件以傳遞配置文件和環境變數文件作為Docker Compose的卷和指令(要注意一些過程是發生在主安裝腳本下的,並且是在屏幕下發生的)。這才是標準的在線安裝程序。實際上,Docker Compose文件抓取了Docker Hub的Docker鏡像,而且根據配置輸入實例化了Harbor。

最後,將開始的簡單」PoC」項目分成了三個」子項目」:

將Harbor在線安裝程序docker化,這樣「準備」過程就能作為Docker Compose的一部分,並將輸入的參數作為變數傳遞到Docker Compose中去(而不是手動編輯harbor.cfg文件,然後執行整個準備circus)。

將已經Docker化Harbor在線安裝程序Rancher化,並且創建一個Rancher私有應用商店以模擬典型的單主機Harbor設置。

作為獎勵:將docker化的Harbor在線安裝程序rancher化,並創建一個Rancher私有應用商店的應用模版,讓我們可以在Docker主機的分散式集群上安裝Harbor。

要注意的是,我需要創建一個docker化的Harbor在線安裝程序來匹配Rancher的目錄模型,而且當你無法採用手動和互動式的方式、只能自動stand up Harbor時,你也可以用這個在線安裝程序(Rancher是這些用戶實例之一)。

在接下來的幾節中,我會詳細介紹為了實施這些子項目我所做的一些工作。

子項目1: 將Harbor 在線安裝程序容器化

在我寫這篇文章的時候,Harbor 0.5.0已經可以使用OVA或通過安裝程序安裝。安裝程序可以在線(鏡像從Docker Hub動態提取)或離線(鏡像是安裝程序的一部分並會在本地載入)。

我們接下來要關注的是在線安裝程序。

正如我們已經提到的,一旦你下載了在線安裝程序,就要調整在安裝包模板中附帶的harbor.cfg文件的參數以「準備」你的Harbor安裝。

然後將生成的配置集輸入到Docker Compose文件中(通過映射為「卷」的本地目錄和通過「env_file」指令)。

如果不通過「準備」過程,直接將Harbor設置參數傳遞給Docker Compose文件,這樣做是不是會更容易或更好?

進入Harbor-setupwrapper。

Harbor-setupwrapper是一個包含新docker鏡像的Harbor安裝包,並(或多或少)在docker容器中實現「準備」進程。而Harbor配置參數作為環境變數輸入到容器中。最後,在容器中運行一個腳本,啟動準備常式(這是所有容器本身就包含的),當然這一步也是很重要的。

這個鏡像的Dockerfile和啟動準備常式的腳本都是值得研究的問題。

其實,什麼是harbor-setupwrapper.sh和什麼是以install.sh為標準的Harbor在線安裝程序,這兩個問題是非常相似的。

我們現在有一個新的Docker Compose文件,這個文件很大程度上是建立在原始Docker Compose文件的基礎上的。此外,這個原始Docker Compose文件是官方在線安裝程序附帶的。現在,你可以通過」組合」這個新的Docker Compose文件傳遞你在harbor.cfg文件中調整過的參數了。

如下圖所示:

一定要注意這只是一個PoC!

我只測試了HARBORHOSTNAME和HARBOR ADMIN_PASSWORD變數。其他變數應該是可以運行的,但我並沒有進行測試

肯定會有特殊情況發生。例如,如果你選擇使用安全連接(https),而我還沒有找到創建證書的方法。這個時候就需要實現harbor-setupwrapper.sh中的附加邏輯(提示:啟用https可能會發生一些奇怪的事情)

採用原始的在線安裝程序就意味著要在單個Docker主機上運行。我會在同樣的模型和相同的前提條件下,實現這個新的安裝機制

由於以上原因,我沒有試過在分散式Swarm集群上部署這個compose文件。另外,雖然說「legacy Swarm」已轉換成了「Swarm模式」,但Docker Compose和後者似乎並不兼容,而我又不想花太多的時間在前者上,於是我選擇不在Swarm環境中測試它

也許會有更多的警告,只是我沒有想過(但肯定是可能存在的!)

將wrapper(由harbor-setupwrapper.sh腳本生成)中的配置文件提供給應用程序容器並不難。我已經實現了「volumes_from」指令,所以應用程序容器可以直接從wrapper容器中獲得相關的配置文件。

找出將ENVIRONMENT變數(在wrapper容器上的各種文件)傳遞到應用程序容器上的方法具有一定的難度。而且我無法在compose中運行」env_file」指令,因為指令指向的是運行compose的系統中可見的文件(在我使用時,這些文件在wrapper容器中)。長話短說,我改變了應用程序容器的入口,指向了一個腳本,首先要載入這些環境變數,然後啟動原始腳本或原始入口的命令。如果你願意的話,你可以檢查harbor-setupwrapper GitHub repo中所有的entrypoint * .sh文件。

如果你打算按照這個方法做,並且用這個新的機制設置Harbor的話,那你就需要克隆harbor-setupwrapper?repo和」up」你在harbor-setupwrapper目錄中發現的Docker Compose文件。但是,在啟動它之前,先要導出HARBORHOSTNAM和HARBOR_ADMIN_PASSWORD變數。這相當於在原始安裝程序中調整harbor.cfg文件。如果你忘記導出這些變數,Docker Compose會顯示:

至少要對HARBORHOSTNAME變數進行設置,把HARBORHOSTNAME變數設置為將要安裝它的主機的IP地址或FQDN(否則設置將不起作用,我會在後面解釋原因)。如果你沒有對HARBOR_ADMIN_PASSWORD變數進行設置的話,那你就需要用默認的Harbor密碼(Harbor12345)。

你要做的是:

注:如果你打算在同一個主機上反覆實施Harbor實例,並打算從頭開始的話,那麼一定要刪除主機上的/ data目錄(因為它會保存實例狀態,如果新實例找到了這個目錄,那麼它將接收之前的實例狀態)。

子項目2: 創建單主機部署的Rancher 應用商店條目

我們可以通過「compose up」來docker化Harbor安裝程序。現在我們可以把注意力放在第二個子項目了。換句話說就是,創建Rancher應用商店條目的結構。

我覺得這應該是比較容易的。畢竟,我們之前討論過關於重新使用新docker-compose.yml文件的問題。

我了解到比較困難的都是細節的問題,特別是在容器的文章里,為了「修復」一個特定問題而進行的調整通常意味著在其他地方打開一些worms。

我以後會儘可能寫一些你們需要的或是你們想要了解的東西,以便於詳細了解這個安裝包,我把我的經歷分享給你們,是希望可以在其他情況下幫到你們(我會把我的發現記錄下來,不然我恐怕會在2周后忘記)。

首先,在Rancher中,在sidekick中你只能做到「volume_from」。最開始的時候,我是將「io.rancher.sidekicks:harbour-setupwrapper」添加到compose中的每個容器去。然而,我突然發現,這會為每個容器創建一個harbor-setupwrapper以輔助容器,這是一個sidekick。 雖然看起來都已經準備就緒,但我最後發現在一個單一的Harbor部署下運行多個腳本的實例可能會導致各種配置不一致(例如用不可信的密鑰簽名的令牌等)。

我需要改變策略,變成只有一個harbor-setupwrapper容器的實例(在一個過程中將會一致地生成所有的配置文件),我已經在主容器與所有其他應用程序容器中實現了它。實際上,我只是添加了「io.rancher.sidekicks:registry,ui,jobservice,mysql,proxy」作為harbor-setupwrapper容器的標籤。 (警告:我並沒有告訴Raul這件事,因為這可能會嚇到他或任何其他Rancher專家。 但是這成功了,所以請原諒我。)

我們通過開放一個問題來解決另一個問題。sidekick容器的名稱解析並不會真的像你預想的那樣運作,所以我只能找出其它解決方法(如果你感興趣的話,你可以在這裡了解問題並且修復它:https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876)。

在創建Rancher應用商店條目的過程中,還有兩個問題需要解決:

「harborhostname」變數需要設置為確切值,這樣用戶就可以通過它連接到該Harbor實例。

所有的Harbor容器都只能部署在單個主機上,這個主機可能是許多主機(Cattle)集群中的一個。

我可能會讓Rancher專家再一次感到害怕,為了給主機上的所有容器貼上「harbor-host = true」的標籤,我已經配置Docker Compose文件。

這樣我就能確保所有容器都部署在同一台主機上(更重要的是,對某一個主機有一定程度的控制權)。 而且,因為我知道我的容器將要到達哪個主機,所以我可以明智地選擇變數「harborhostname」。 它可以是主機IP地址或主機FQDN。

最後,Docker Compose文件將會發布主機上代理容器的埠80和443(顯然在在該主機上這些埠是免費的,不然部署會失效)。也許這不是一個最佳實踐,但可以解決一些基本的或是較為容易的問題。

注意:因為狀態會保存在主機的/ data目錄中,所以如果你是為了測試而啟動和關閉Harbor實例,那你要將狀態保存在多個部署中。這和你運行一個真正的雲本地應用程序還是有很大差距的,但它能說明Harbor(0.5.0)是怎麼構建的,我只是忠於單個主機上的Rancherization方案的原本的操作模式。

下圖說明了單個主機部署中各個組件間的詳細信息和關係:

下圖是我運行過程中的實際部署:

用於單主機部署的Rancher的Harbor私有應用商店應用模版的當前狀態如下:

它只適用於Cattle調度程序

構建Swarm和K8s的Harbor目錄的版本和Cattle的版本之間應該是沒什麼關係的

這個應用模版有上述docker化在線安裝程序的所有限制(例如,它不支持https等)

在Docker主機上推送或拉取鏡像時,要在Docker守護進程上設置「-insecure-registry」標誌(因為我們只能通過http訪問啟動Harbor)

有一個主機必須要有docker-compose的「harbour-host = true」標籤,這樣才能夠正常工作和調度容器

具有「harbour-host = true」標籤的主機上必須要有可用的埠80和443

你可以在我的Rancher 應用商店的擴展庫中找到這個子項目的可交付項:https://github.com/mreferre/rancher-catalog-extension。

子項目3: 分散式部署的Rancher 應用商店條目創建

這是操作分散式應用程序中非常有挑戰性的部分,也是很有趣有用的部分。

雖然Harbor是一個容器化應用程序,但因為某些原因,它並不是應用雲本地應用程序操作最佳實踐的理想選擇。它不遵守「十二因子應用(The Twelve-Factor App)」的方法論。

首先,在6個容器都在「眾所周知的」單個主機上運行的前提下,Harbor安裝程序已經建立了。這裡有一些例子強調了部分挑戰。我們可能已經提到了其中一些:

Harbor軟體包附帶了一個嵌入式的syslog伺服器,Docker守護進程會和這個伺服器進行會話/日誌。如果你查看了原始的Docker Compose文件,你會發現假定syslog在所有其他容器的同一主機上運行,那麼所有應用程序容器都會記錄到127.0.0.1

您必須輸入(作為設置參數)確切的Harbor主機名,以便於用戶連接註冊表伺服器。理想情況下,在雲原生的環境中,應用程序應該能夠使用與其關聯的任何給定的IP / FQDN。最後,應該有一個選項來設置(後設置)應用程序將使用的正確的IP / FQDN端點。對於Harbor 0.5.0,你要知道(預先)在啟動設置之前的IP / FQDN是什麼(使得一些事在動態,自服務和分散式環境中更加難以操作)。也就是說,如果你的harbor服務以「service123.mycompany.com」這個形式暴露在用戶面前,你就必須在部署時輸入該字元串作為FQDN(甚至可能不知道容器的哪些主機去部署)

Harbour在已知的單個主機上運行是假設的一部分,產品將自己的狀態保存在其部署到的主機的本地目錄上。這是通過容器配置中不同的目錄映射完成的

這個子項目的目標是讓Harbor在一個Cattle集群上運行,而不是在一個已知的主機上運行。

為此,日誌圖像在集群的每個節點上需要實例化(要求:每個節點必須具有標籤「harbor-log = true」)。一個更好的解決方案是有一個單獨的syslog伺服器指向(從而完全擺脫Docker Compose中的日誌服務)。

此外,由於我們不知道代理伺服器將要到達哪個主機(在這種情況下,我們希望在服務發現方面實現低接觸體驗),我們通過利用Traefik實現了Harbour分散式模型。如果你熟悉Docker的話,就會發現Traefik做的(有點)類似於Docker通過Swarm模式提供的「HTTP Routing Mesh」開箱即用體驗。要注意代理容器埠(80和443)不會暴露在主機上,Traefik是將服務暴露給外界的唯一方法(在這個特定的分散式實現中)。

總體想法是,你的DNS可以解析運行Traefik的IP,然後Traefik會「自動」將你在Harbor設置中輸入的主機名添加到其配置。

存儲管理也是一個有趣的部分。在分散式環境中,你不能讓容器將數據存儲在任何給定時間點都能及時運行的伺服器上。

如果容器在另一台主機上重新啟動(由於失敗或升級),它需要訪問同一組數據。更不用說其他容器(可能在不同的主機上運行)需要訪問同一組數據。

為了解決這個問題,我選擇用Rancher提供的通用NFS服務,它靈活而方便,並且是有用的。因為它允許你預先配置所需的所有卷(在這種情況下,它們通過Harbor目錄條目重新實例化),或者你可以讓Docker Compose在實例化時自動創建(在這種情況下,當Harbor實例關閉時,它們會被刪除)。要注意的是,所有卷都映射到應用程序容器(除了不需要卷的日誌和代理容器之外)。這裡有很大的優化空間(因為不是所有的卷都需要映射到容器),但我暫時不會考慮這個問題。

因為在Docker Compose中沒有卷目錄映射(所有卷都命名為NFS共享上的卷),所以這會使得所有主機無狀態。

下圖顯示了分散式部署中各個組件間的詳細信息和關係:

此圖片顯示了實際操作中的部署:

Rancher用於分散式部署的Harbor私有應用商店條目的當前狀態如下:

它只適用於Cattle調度程序

構建Swarm和K8s的Harbor應用商店的版本和Cattle的版本之間應該是沒什麼關係的

這個應用商店條目有上述docker化在線安裝程序的所有限制(例如,它不支持https等)

在Docker主機上拉/推圖像時,要在Docker守護進程上設置「-insecure-registry」標誌(因為我們只能通過http訪問啟動Harbor)

集群上的所有主機必須要有docker-compose的「harbour-host = true」標籤,這樣才能夠正常工作和調度容器

Traefik服務(位於社區目錄中)需要啟動並運行才能從外部訪問Harbor。這已經暴露埠80(要注意Traefik默認值是8080)

NFS服務(位於庫目錄中)需要啟動,運行並正確配置連接到NFS共享。Docker Compose文件已經參數化,其他驅動程序中我只測試了」rancher-nfs」

你可以在我的Rancher私有應用商店目錄中找到這個子項目的可交付項:https://github.com/mreferre/rancher-catalog-extension 。

總體挑戰和問題

在這個項目中,我遇到了一些挑戰。我會介紹其中一些,把這些記錄下來主要是為了將來可以進行參考。

一些小東西有時會有一些大用處。有時它是一個級聯問題(即做A你需要完成B,但做B又需要完成C)。例如,Rancher sidekick要求能夠執行「volume_from」。這基本上打破了完全名稱解析(請參閱單主機部分了解更多信息,了解問題是什麼)

容器出現「全綠色」並不代表著你的應用程序會啟動和(正常)運行。有時,容器開始確定並沒有錯誤,但我無法登錄到harbor(由於運行安裝wrapper的多個實例生成的證書不匹配)。有時,我可以登錄,但不能push鏡像。有時,我可以push鏡像,但它們不會在UI中顯示出來(因為sidekicks的名稱解析問題,註冊表容器無法解析ui容器名稱)

在分散式環境中調試容器很困難。有時候,我以為遇到了一個隨機問題,後來才發現是因為特定的容器在錯誤配置的主機上(隨機)調度了。如果找到了問題根源,解決這個問題很容易。但往往,事情難就難在找不到問題根源。

將應用程序包裝為在容器中運行(最重要的是編排部署)時,了解應用程序內部是至關重要的。在分散式場景中我將所有命名卷連接到所有容器的原因之一是因為我不能100%確定哪個容器從哪個卷讀取/寫入。此外,不知道應用程序會使其包裝困難(特別是當某些東西不能正常工作需要調試的時候)。總而言之,容器(和編排)更類似於你如何打包和運行應用程序與你如何管理基礎設施

雖然容器編排是關於自動化和可重複,但它也有點像「手工精靈藝術」。有時候(隨機)代理容器只會顯示nginx歡迎頁面(而不是Harbor用戶界面)。最後我通過重新啟動該容器(部署后)解決了這個問題。我認為這是某個啟動序列的原因。我嘗試用「depends_on」指令,使得代理容器開始「朝向結束」的組成,但這沒有成功。現在似乎是通過利用「external_links」指令(理論上應該不需要AFAIK)。總而言之,正確地協調容器的啟動仍然是工作進程中的一部分(從2014年開始)

管理基礎架構(和服務)以運行容器化的應用程序是很困難的。我運用一些簡單的服務,例如基本的Rancher NFS服務時,遇到了一些問題,我必須解決使用不同級別的軟體,不同的部署機制等等。從一個版本的基礎設施到另一個版本的基礎設施的升級也很關鍵

我遇到的另一個NFS問題是,當堆棧關閉時,卷不能在NFS共享上正確清除。在Rancher UI中,卷似乎已經不存在了,但是直接查看NFS共享,其中一些(一個隨機數)似乎以剩餘的目錄的形式留下。我沒有深入研究這是為什麼。

結論

正如我所提到的,這只是一個粗略的整合,毫無疑問,它可以更完善一些。這主要是一次很好的學習經歷,未來可以進一步擴展,比如在Rancher Kubernetes內集成,啟用https協議等等。

在分散式系統中完成應用服務的動態配置也是這次實驗的挑戰之一,當然這不是很複雜,但通過這個過程可以讓你更好地了解如何解決這些問題。

從更高的層次看,將一個應用容器化並部署在分散式系統中,它有兩種方式:一是你的基礎服務就以Paas方式構建,所需要的服務資源(如調度、負載均衡、DNS解析等)向Paas申請,你可能需要深度改造你的應用;二是,選用Rancher這樣的平台,利用它提供的特性,只需要編寫compose編排文件,就可以很輕易的實現需求。實際上Ranche也是更多得幫助你在第二種場景中快速實現你的需求,簡單易用的基礎設施服務助你快速實現應用容器化。

原文來源:VMware Harbor as a Rancher catalog entry

翻譯:劉力,Rancher Labs大中華區架構師。



熱門推薦

本文由 yidianzixun 提供 原文連結

寵物協尋 相信 終究能找到回家的路
寫了7763篇文章,獲得2次喜歡
留言回覆
回覆
精彩推薦