投稿:毛十三
技術校對:星空下的文仔(才雲)、bot(才雲)
*注:萬字長文,建議耐心閱讀!
在 Kubernetes 上部署應用程式可能需要許多相關的部署元件或規範檔案:Deployment、Service、PVC、ConfigMap、ServiceAccount……
管理這些資源并将它們與已部署的應用程式關聯起來是一項挑戰,尤其是跟蹤已部署的應用程式(實際狀态)及其原始來源(授權或期望狀态)的更改和更新時。該應用程式的版本被鎖定在 Kubernetes 平台中,使它們完全脫離了規範本身的版本(通常會在外部源代碼管理庫中進行跟蹤)。
此外,靜态規範通常不能在給定域、環境或雲提供商之外重複使用,但需要花費大量時間進行創作和調試。工具可用于基于正規表達式提供的字元串進行替換,但這種自動化還需要編寫或自定義以執行我們需要的任務,有些時候,這種方式會出現錯誤。
Helm 通過将相關的 Kubernetes 規範打包成一個簡單的部署元件(稱為 chart)來解決這些問題,這些元件可以參數化以獲得最大的靈活性。同時,Helm 也能使使用者在運作時中自定義應用程式包。如果你熟悉 apt 包或 yum 等 OS 包管理器以及 deb 或 rpm 等軟體包,那麼 Helm 以及 Helm chart 的概念你應該很熟悉。
先決條件
首先,你需要一個正在運作的 Kubernetes 叢集,一個本地 Docker 用戶端,以及一個預配置的 kubectl 用戶端和 Kubernetes 叢集配置。Helm 将使用 kubectl 在已配置的叢集上部署 Kubernetes 資源。
* 注:Helm 的預設安裝是不安全的!
安裝 Helm
Helm 有兩個部分:Helm 用戶端(Helm)和 Helm 伺服器(Tiller)。首先,你需要通過 Helm 用戶端在 Kubernetes 叢集上安裝 Tiller。這裡需要注意,用 Helm 用戶端來部署 Tiller 伺服器不是必須的,但現在這樣做很友善。
Helm 用戶端可以從源代碼或預建構的二進制版本安裝,通過 Linux 上的 Snap、macOS 上的 Homebrew 或 Windows 上的 Chocolatey 安裝。但 Helm GitHub repo 還擁有一個安裝程式 shell 腳本,該腳本将自動擷取最新版本的 Helm 用戶端并在本地安裝。
下面是 Ubuntu 16.04 的示範示例,其中 Kubernetes 使用 kubeadm 在本地安裝。
使腳本可執行并運作它,下載下傳、安裝最新版本的 Helm,此步驟需要 sudo 權限。
我們可以使用
version
帶有 client only flag(
-c
)的指令來確定用戶端可用:
此指令将挂起,并将使用我們的 kubeconfig 查找 Tiller ,但現在我們還沒有 Tiller。
預設情況下,Helm 用戶端使用 socat 設定端口轉發到 Tiller 視窗。但在我們的例子中,由于 socat 已經安裝為使用 kubeadm 進行 Kubernetes 叢集初步設定的一部分,是以你并不需要執行這一步。
下面是安裝時的一個例子:
如果你需要安裝 socat,你可以從 apt:
sudo apt-get install socat
。
此時我們應該在叢集上部署 Tiller。
Tiller
Tiller 通常在你部署的 Kubernetes 叢集上運作。
對于開發,它也可以在本地運作并配置為與遠端 Kubernetes 叢集通信的方式(這很友善)!
将 Tiller 安裝到叢集中的最簡單方法就是運作
helm init
。然後 Helm 将驗證 Helm 本地環境是否已正确設定(或在必要時進行設定),使用 kubeconfig 的 current-context 連接配接到與 kubectl 相同的叢集并安裝 Tiller Pod。
init
有一堆選項來影響它的行為:
-
:安裝 Tiller 的 canary 版本(測試最新功能);--canary-image
-
:本地配置,但不安裝 Tiller;--client-only
-
:使用命名 context 來替代--kube-context
檔案中的 current-context;~/.kube/config
-
:指定安排 Tiller Pod 所需的節點标簽;--node-selectors
-
:操縱最終 Tiller 清單的指定屬性;--override
- 接受 Tiller 部署清單中任何有效屬性的有效值
-
:跳過 Tiller 部署清單的安裝,隻需将部署清單以 JSON 或 YAML 格式輸出到 stdout 中;--output
-
:使用除最新版本之外的特定 Tiller 版本;--tiller-image
-
:将 Tiller 更新到最新版本。--upgrade
你也可以通過這個文檔了解更多:https://docs.helm.sh/helm/#helm-init
讓我們
init
通過使用
--output
标志來看一下将要部署的内容并通知它 output yaml(或者如果你願意,可以使用 json):
在這裡,我們看到了 Tiller 部署及其服務;我們可以簡單地儲存這些檔案并使用 kubectl 進行部署,但這會有什麼好處呢?
請注意兩個環境變量:
TILLER_NAMESPACE
和
TILLER_HISTORY_MAX
。
--tiller-namespace
會影響的命名空間;
TILLER_HISTORY_MAX
用于限制每個版本儲存的最大修訂數(0 表示沒有限制),具有無限數量的修訂會對性能産生影響,是以你需要在實踐中使用
--history-max
标志将其設定為合理值。
Tiller 和 RBAC
限制 Tiller 将資源安裝到某些命名空間是個好主意。使用 RBAC 時,我們可以通過為 Kubernetes API 提供身份(Kubernetes 服務帳戶)并使用 Kubernetes 角色和綁定為其配置設定範圍權限來限制任何應用程式對 Kubernetes API 進行通路。
這次逾時我們可以将配置保持在最低限度,為 Tiller 配置設定叢集管理叢集角色,以便它可以部署到任何命名空間。
如果你的叢集不是本地叢集或測試叢集,請不要在家中執行此操作!首先,建立服務帳戶:
現在建立叢集角色綁定,将叢集管理者角色配置設定給 Tiller 服務帳戶:
部署 Tiller
現在我們可以部署 Tiller。首先使用
--service-account
标志來使用 Tiller 服務帳戶:
Helm 會自動将其配置的檔案放入
~/.helm
中。将 Helm 用戶端檔案放在除
~/.helm
之外的其他位置,
$HELM_HOME
在運作之前設定環境變量 helm init,然後使用重要說明部署 Tiller。
請注意,預設情況下,Tiller 會使用不安全的 “允許未經身份驗證的使用者” 政策進行部署。為了防止這種情況,請 helm init 使用-tiller-tls-verify 标志運作。有關保護安裝的更多資訊,請參閱:https://docs.helm.sh/using_helm/#securing-your-helm-installation
* 注:預設的 Tiller 是不安全的!我們可以像在任何其他 Kubernetes 資源上一樣在我們的叢集上找到 Tiller:
在沒有
-c
的情況下運作
version
指令應該同時顯示 Helm 和 Tiller 版本,并確定 Helm 可以找到并與 Tiller 對話。
是時候開始 Helming 了!
探索 chart
衆所周知,
chart 是一組 spec 檔案,它們定義了一組 Kubernetes 資源(如服務、部署等),通常包含将應用程式部署為模闆所需的所有資源。chart 資源模闆使使用者能夠通過為模闆中定義的某些(或所有)變量提供值來自定義,在安裝時部署呈現資源的方式。
chart 還包括所有已定義變量的預設值,隻需要很少(或不需要)自定義就能輕松部署 chart。與其他軟體包管理器一樣,我們希望使用 update 指令從我們配置的 repos 中擷取 chart 的最新清單和更新:
請注意,Helm 跳過了“本地 chart 存儲庫”,但從我們唯一的“穩定”存儲庫中獲得了更新。當你第一次安裝 Helm 時,它預先配置為與本地存儲庫和官方 Kubernetes chart 存儲庫通信。官方存儲庫(名為 “stable”)包含一些精心策劃和維護的常用軟體 chart,如 elasticsearch、Influxdb、mariadb、nginx、prometheus、redis 等等。
列出你的 Helm repos 以顯示已配置的内容:
你可以随時使用
helm repo add
指令添加其他的 repo。下面我們将使用穩定的 repo。
該
helm search
指令将向我們顯示官方存儲庫中的所有可用 chart(因為它是唯一配置和更新的 repo):
請注意使用stable/
前置所有可用 chart 。在 helm/charts 項目中,stable 檔案夾包含經過嚴格更新并滿足某些技術要求的所有 chart。孵化器 chart 也可用,但在滿足這些标準之前還需要不斷改進。你可以使用該
helm repo add
指令添加孵化器存儲庫(與任何其他存儲庫一樣)并将其指向正确的 URL。
另外,請注意 CHART VERSION 和 APP VERSION 列。前者是 Helm chart 版本,必須按照 Helm 項目的規則,遵循 SemVer 2 格式。後者是實際軟體的版本,在 Helm 中以自由形式存在,但與軟體的釋出規則相關。
helm search
可以顯示所有可用的 chart。你可以通過使用過濾器進行搜尋來縮小搜尋結果範圍:
為什麼 traefik 在名單中?因為它的包描述與入口有關。我們可以
helm inspect chart
看看發生了什麼:
traefik chart 的關鍵字部分包含關鍵字“ingress”,是以它會顯示在我們的搜尋中。
部署 chart
稍後我們将探索 chart 的結構,但為了說明部署 chart 是多麼容易,我們可以使用 repo 中的 chart。要安裝 chart ,請使用
helm install
指令,該指令僅需要一個參數:chart 的名稱。你可以使用官方 helm repo 提供的容器化 Docker 系統資料庫。
部署系統資料庫:
剛剛發生了什麼?
Helm 通過為所有變量注入預設值來呈現 Kubernetes 資源模闆,然後通過将它們作為靜态規範檔案送出到 Kubernetes API 來部署 Kubernetes 叢集上的資源。安裝 chart 後會建立一個新的 Helm 釋出對象,上面的這個版本被命名為“kissable-clownfish”(如果你想使用你自己的版本名稱,隻需使用帶有 install 指令标志的
--name
)。
Helm Release 是一組基于 chart 的已部署資源。每次安裝 chart 時,它都會使用自己的版本名稱部署一整套 Kubernetes 資源。
獨特的命名有助于我們跟蹤 Kubernetes 資源的相關性,并允許我們使用不同的自定義方式多次部署 chart。
在安裝過程中,Helm 将列印有關建立資源的有用資訊,在我們的示例中,就是 ConfigMap、Deployment、Secret 和 Service。要再次檢視它,你可以使用 helm status 版本名稱。我們需要使用我們新的系統資料庫伺服器,NOTES 輸出的部分提供了一些使用它的線索:
此時,你的終端應該被劫持以進行端口轉發。啟動一個新終端并使用 Docker 與系統資料庫進行互動。從 Kubernetes 主機上的 Docker 用戶端,拉出一個像 alpine 這樣的輕量級鏡像:
現在重新标記它,在鏡像倉庫名稱前加上 IP 端口并嘗試推送它:
查詢系統資料庫 API ,确認系統資料庫擁有我們的鏡像:
成功!
這很簡單,但我們隻使用此 chart 的預設配置選項。你可能希望在部署之前自定義 chart。要檢視給定 chart 可配置的選項,請使用
helm inspect values
。
使用 Ctrl + C(
^C
)殺死你的程序端口,然後檢查 chart 值:
我們可以進行許多配置更改。
最值得注意的是,我們可以為系統資料庫部署入口記錄(如果我們部署了入口控制器,則非常有用)。我們還可以配置許多不同的存儲後端,比如 S3 bucket 和存儲 AWS 通路密鑰的相關 Secret。
但這些值來自哪裡?
chart 剖析chart 是以 chart 命名目錄中的檔案集合。到目前為止,我們隻從遠端倉庫部署了一個 chart ,你可以通過檢視 GitHub 上 docker-registry chart 的連結看到這些檔案。
安裝 chart 時,Helm 将目錄的内容作為存檔下載下傳,并将其本地緩存在 Helm 用戶端的工作空間目錄中。預設位置是
~/.helm
:
緩存目錄包含歸檔格式的遠端 chart 存儲庫的本地克隆:
如果我們想要浏覽 chart,我們可以自己擴充存檔,或者使用 Helm 指令!
使用
fetch
指令和
--untar
會在我們的本地系統上生成一個 unpacked chart:
關于其中大部分内容的解釋,請參考 Helm 文檔。現在我們将專注于 .yaml 值。之前我們用 helm inspect values 指令檢查了這些值,現在,我們來看看使用 values.yaml 所展示的内容:
值檔案是 chart 的作者為所有 chart 變量設定預設值的地方。你隻需鍵入 helm install,chart 就會起作用。有些 chart 具有先決條件,通常會記錄這些 chart,是以你可以提前知道它們。例如,WordPress chart 聲明了以下先決條件:
- 先決條件:啟用 Beta API 的 Kubernetes 1.4+ —— 底層基礎架構中的 PV 配置器支援。
更新釋出
如果要更改發行版的配置,你可以使用
helm upgrade
指令。Helm 會更新自上次釋出以來發生過變化的内容。Upgrade 與 install 使用相同的覆寫标志,是以你可以在初始安裝或稍後的某個時候自定義 chart 。
我們最初的 Docker Registry Service 是 ClusterIP 類型,這就是我們需要端口轉發的原因:
要确認它是以這種方式部署的,我們需要列出 Kubernetes 服務:
讓我們更新服務以使用 NodePort,以便我們可以将系統資料庫公開給外部世界。在更新期間或初始安裝期間,有兩種方法可以傳遞配置資料:
-
(或--values
):指定帶有覆寫的 YAML 檔案-f
-
:在指令行上指定覆寫--set
- 基本:
==--set name=value
name: value
- 鍵值對以逗号分隔
- 集支援多個複雜值
-
變為:--set servers.port=80
-
- 基本:
我們知道這個
type
是一個服務,是以我們可以設定它的值為
--set service.type=
:
根據上面的輸出,Kubernetes 已更新我們的服務配置。該 NOTES 部分甚至已經更改,表明我們現在可以通過 http:// NODE_IP:NODE_PORT 通路我們的 docker-registry 服務。
我們可以用
helm get values
來檢視新設定是否生效。
沒有這裡提供的資訊。Helm 隻關注 yaml 鍵/值對的變化。讓我們看看它是否有效:
成功!讓我們通過推動鏡像來測試它。
預設情況下,Docker 隻信任 localhost 上的安全遠端系統資料庫或不安全系統資料庫。
由于 Kubernetes 在容器中運作我們的系統資料庫,即使 Docker 守護程式和 docker-registry 在同一主機上運作,系統資料庫也被視為“遠端”。我們的 port-forward 使用了 localhost,是以 Docker 允許我們推送,但這次不會讓我們這樣通過:
有兩種方法可以解決這種情況。一種方法是配置系統資料庫伺服器以支援 TLS。我們可以告訴 Docker 信任我們的非安全系統資料庫(僅在非生産環境中執行此操作),而不是保護 docker-registry。這允許我們在不使用 SSL 證書的情況下使用系統資料庫。
在 Kubernetes 主機上執行下一步很可能會破壞部署 kubeadm 的叢集,因為它需要重新啟動 Docker 并且所有 Kubernetes 服務都在容器中運作。是以,請使用 Kubernetes 主機外部的 Docker 安裝 。
通過在下面建立一個配置檔案來配置我們的 Docker 守護程式
/etc/docker
(将示例 IP 替換為你之前存儲在 NODE_IP 中的節點的 IP):
要使這些更改生效,你需要重新啟動 Docker:
現在,你的 Docker 守護程式是否應該信任我們的系統資料庫:
看它是否有效:
現在你已經擁有了一個團隊可以共享的系統資料庫!但其他人也可以使用它,記得對此加以限制哦!