第469回ではKubernetesの環境を構築しました。今回はそのKubernetes上にソフトウェアスタックを構築する上で便利なパッケージ管理ツール「Helm」について紹介します。
Kubernetesでパッケージ管理ツールを使う理由
「Helm」はKubernetes用のパッケージ管理ツールです[1]。パッケージそのものは「Chart」と呼ばれるYAMLファイルの集合体で、独自のパッケージリポジトリとして「Kubernetes Charts」を提供しています。
UbuntuのAPTシステムでいうところのDebパッケージファイルがChartで、Kubernetes Chartsは公式パッケージリポジトリ、そのリポジトリやローカルシステムからDebパッケージファイルをダウンロード・インストールするコマンドがhelm
だとイメージすれば良いでしょう。
Kubernetesにはその役割に応じてさまざまなリソースの概念が存在します。たとえば「Pods」はひとつないし複数のDockerコンテナを細分化不可なひとつのリソースとしてまとめたものですし、「Services」はレプリケーションされた複数のPodsが提供するサービスを抽象化するリソースです。「Deployments」はレプリケーションコントローラーとして、Podsの生死を監視し必要に応じてPodsの再起動を行います。また永続的なデータは「Volumes」で管理します。サービスやコンテナの実体を分離することで、サービスを維持したままPodsのアップデートやスケールを実現できるのです。
kubectl
コマンドはこれら個々のリソースを区別することなく、「kubectl create -f YAML
」で一括して作成します。リソースごとにYAMLファイルを作成する場合もありますし、前回使用したGuestbookのall-in-oneのようにひとつのYAMLファイルにまとめることもできます。
ただし、実際にKubernetesのサンプルを使ってみるとわかるのですが、ソフトウェアスタックが提供するYAMLファイルをそのまま使えることはまれです。大抵の場合は、秘密鍵をどうするのか、ストレージはどのように準備するのか、ロードバランサーは何を使うのかなど、デプロイするサイト固有の環境に応じてYAMLファイルをカスタマイズする必要があります。
そこで出てくるのが今回紹介するHelmです。Helmでは、kubectl
コマンドが使うYAMLファイルから設定可能な部分を別YAMLファイルとして分離できます。テンプレートエンジンを使って、インストール時にサイト固有の設定をkubectl
コマンドに提供するYAMLファイルに反映するのです。また、Hook機能によってパッケージのライフサイクルや定義済みのイベントの途中に、別の処理を行うことも可能ですし、他のパッケージ(Chart)との依存関係も構築できます。
パッケージそのものはひとつのアーカイブファイルとして構築します。アクセス可能な箇所であればネットワーク越しにダウンロードしてインストールすることも可能ですし、git clone
したディレクトリをインストール対象としても指定できます。またローカルパッケージリポジトリをKubernetes上に構築可能です。
いずれにせよKubernetesを使うのであれば、Helmの使い方もセットで覚えておくと、さまざまなソフトウェアスタックの作成・構築・削除が簡単になることでしょう。
Helmのインストールと初期設定
HelmそのものはGo言語で構築されたひとつのバイナリファイルとして提供されています。よってそのインストール方法は、最新のバイナリファイルをダウンロードしてbin
ディレクトリに展開するだけです。
Helmを使う前に、リポジトリなどのメタデータセットをホームディレクトリ以下に作成し(helm init
)、Kubernetes Chartsのリポジトリデータをダウンロードします(helm repo update
)。
この時点でのリポジトリのパッケージリストは、~/.helm/repository/cache/stable-index.yaml
です。
helm init
によってローカルリポジトリサーバーにインスタンス(Tiller)が自動的にKubernetes上に構築されます[2]。
Jenkinsパッケージのインストール
実際の使用例として、公式リポジトリにあるJenkins Chartをインストールしてみましょう。
まずリポジトリの検索はhelm search
を、パッケージ情報の表示はhelm inspect
を使います。
helm inspect
はパッケージのメタデータに加えて、パッケージインストール時に変更できる設定値一覧も表示します。もしくは「helm inspect values Chart名
」で設定値のみを表示できます。この設定値はサイト固有のデプロイ時に変更できる値であり、その一部は変更が必要な値でもあります。インストールする前に一読する癖をつけておきましょう。
設定値は「--set
」オプションで個別に指定したり、「--values
」オプションで設定値を記述したYAMLファイルを指定できます。たとえばKubernetes外部へのアクセス手段を設定するServiceTypeとしてClusterIPを使用し、永続的なストレージを用意しない(Jenkins
Podが終了や再起動するとデータが失われる)場合、次のようにインストールします (
※3)。
インストール後の作業も表示してくれる親切設計です。これはChartのNOTES.txtをテンプレートによって書き換えた上で表示しています。
ちなみにHelmではインストールしたパッケージのインスタンスを「リリース(Release)」と呼びます。「--name chtholly
」はインストール後のリリースの名前(ReleaseName)を指定しています。APTとは異なり、あるパッケージをインストールしたらそのリリースはパッケージ名とは異なる固有の名前を持ちます。これにより、同じパッケージを別名・別設定で何度でもインストールできるのです。
「--name
」オプションを指定しない場合は、いくつかの単語のランダムな組み合わせで名前がつけられます。覚えるのが大変であるため、普段から「--name
」オプションをつけるようにしたほうが良いでしょう。
インストール済みのパッケージは「helm list
」コマンドで確認できます。
またkubectl
コマンドを使えば、Jenkinsのサービスが立ち上がっていることがわかります。
Jenkinsは外部へのウェブインターフェースとして8080番ポートを、MasterとSlave間の通信用に50000番ポートを使用しています。インストール時のメッセージではkubectl port-forward
で設定する方法がアナウンスされていますが、これはローカルでしか使えません。よってNginx Ingress Controllerで外部からのアクセスを許可するために、8080番ポートだけをルーティングしましょう。そこで次のような内容で、jenkins-ingress.yaml
ファイルを作成します。
これをkubectl
コマンドに渡します。
あとは「jenkins.example.org
」にアクセスするだけです。インストール時のメッセージにあるように、管理者のアカウント名は「admin」で、パスワードについては次のコマンドで取得できます。
無事にフロントページにアクセスできれば、インストール完了です。
パッケージの削除
Helmでインストールしたパッケージを削除するには、helm delete
コマンドにリリースの名前を渡すだけです。リリース名(ReleaseName)であってパッケージ名ではありません。
なおパッケージを削除したとしてもリリース名は予約されたままとなります。もし同じ名前で再インストールしたい場合は、「--purge
」オプションを付けて削除してください。
削除したけれども名前は残っているリリースも含むすべてのリリースの一覧は「helm list --all
」で確認できます。その他の使い方は、Helmのコマンドリファレンスが参考になるでしょう。