弊社Opsチームではアプリケーションの管理にHelmを使います。かんたんDevOpsでもHelmを使うことがありますが、導入して終わりというわけにもいかないので、簡単な使い方や、そもそもHelmって何ってなんなの?っという情報をここにまとめておきます。
そもそもHelmって?
HelmはKubernetesアプリケーションを管理するためのツールで、公式ページでは「Kubernetes用 パッケージマネージャー」を謳っています。チャートと呼ばれるKubernetesマニフェストのテンプレートを元にアプリケーションを管理することができます。パブリックに公開されているHelmチャートはArtifact HUBというWEBサイトや、コマンドラインから検索できます。使いたいチャートがあればHelmリポジトリとして登録することで、HelmからKubernetesにアプリケーションのインストールやアップグレード、アンインストールなどを簡単に行えるようになります。もちろん、公開されていなくても、ローカルや自分だけがアクセスできる場所にチャートを置けば、それを元に操作することが可能です。
Helmを使うと何がいいの?
メリットをいくつかまとめます。
- Helmは動的にパラメータを埋め込むことができる
apiVersion: apps/v1 kind: Deployment spec: replicas: {{ .Values.replicaCount }}
これはdeploymentを作るマニフェストの一部なんですが、replicasを見てください。{{ .Values.replicaCount }}
という変数のようなものが定義されています。これはvalues.yaml
というファイル内で定義されているreplicaCount
に指定した値で置き換えられます。もしくはコマンドライン引数で--set replicaCount=3
などとしても変更することが可能です。このようにマニフェストの値を変更することができるので、複数環境を1つのチャートで管理することが可能になります。
- バージョン管理ができる
HelmチャートにはCHART VERSIONとAPP VERSIONがあります。CHART VERSIONはHelmチャート自体のバージョンです。Helmチャートに変更を加えた時にカウントアップします。APP VERSIONはアプリケーションのバージョンです。インストールやアップグレードの時にCHART VERSIONを指定することで、そのCHART VERSIONに紐づくアプリケーションをインストールすることが可能です。今どのバージョンで動いているのか、過去にどのバージョンが動いていたのか、いつアップグレードされたのかなどが簡単に確認できるので、障害が発生した時や、アップグレード計画を立てるときなどに役立つと思います。
- Artifact HUBの存在
Helmを使っていない場合、公式のリポジトリからマニフェストをダウンロードし、自分の環境に必要な箇所を検索、修正してからデプロイするっということをしていました。しかし、Helmを使うと、チャートはArtifact HUBで公開されていて、各オプションの説明があり、外部から値の埋め込みができるので、前述した苦労から解放されます。
Helmええやん
いいことばかりではありません。デメリットもあります。
- 学習コストがかかる
Helmチャートの実態はKubernetesマニフェストのテンプレートです。Kubernetesマニフェストを知っている必要もありますし、Helmチャートの書き方も学習する必要があります。
- テンプレートが読みづらくなりがち
Helmを使っていると様々な値を外部から変更したくなるでしょう。しかし、やりすぎるとテンプレート内で何をしてるのかがわかりづらくなります。黒魔術にならないよう、あまり複雑なことはしないのがいいのかなっと思います。
- 宣言的ではない
動的に値を埋め込めるので、まぁ、そうですよね。--set
オプションで色々設定してしまうと、シェルのHistoryが消えると終わります。複数環境で1つのチャートを使う場合は、各環境用にvalues.yamlを用意しておいて--values /path/to/file
でオーバーライドしてあげるのでいいように思います。helmfileというツールを使うのもいいかもしれません。
実際に使ってみる
それではいよいよHelmを使っていきたいと思います。まずはKubernetes環境が必要になりますので、以下の過去記事を参考に導入を進めてみてください。ちなみに私は過去記事にはないのですがminikubeを使用しました。
この記事のためにサンプルプロジェクトとコンテナイメージを公開しました。お使いください。
まずはリポジトリの登録です。helm-hello
という名前でリポジトリを登録していきます。
helm repo add helm-hello https://virtualtech-devops.github.io/helm-hello
登録ができたら確認します。
helm repo list
以下のように出力されていれば成功です。
NAME URL ... helm-hello https://virtualtech-devops.github.io/helm-hello
リポジトリに登録されているアプリケーションを確認してみます。
helm search repo
NAME CHART VERSION APP VERSION DESCRIPTION ... helm-hello/hello 1.1.0 v1.1.0 A Helm chart for Kubernetes ...
リポジトリを複数登録してる人は、全てのリポジトリが表示されて少し見づらいかもしれません。出力を絞り込んでみます。絞り込む時はhelm search repo [keyword]
のように入力します。[keyword]
はあいまい検索ができるので、単語やフレーズの一部を入力することでヒットしたものを表示することができます。
helm search repo helm-hello
NAME CHART VERSION APP VERSION DESCRIPTION helm-hello/hello 1.1.0 1.0.0 A Helm chart for Kubernetes
helm-hello
はリポジトリ名、hello
はリポジトリに含まれているアプリケーション名です。今回使っているリポジトリでいうとココから確認できます。
--versions
オプションをつけることで、リポジトリに登録されている全てのバージョンが確認できます。
helm search repo helm-hello --versions
NAME CHART VERSION APP VERSION DESCRIPTION helm-hello/hello 1.1.0 v1.1.0 A Helm chart for Kubernetes helm-hello/hello 1.0.0 v1.0.0 A Helm chart for Kubernetes
CHART VERSIONとAPP VERSIONはズレることがよくあります。これはチャートとアプリのライフサイクルが違うのに起因します。アプリがアップデートされればチャートも変更されるのですが、チャートを変更してもアプリのバージョンは上がりません。もしくは、元々アプリがリリースされていて、後からチャートが追加された、最初なので0.1.0
にしょう、などです。インストールしたいアプリのバージョンは必ずAPP VERSIONを確認しましょう。
もし思ったようなバージョンが出てこなかった場合は以下のコマンドでリポジトリをアップデートしてみてください。
helm repo update
今まで使っていたhelm search
ですが、Artifact HUBから検索することも可能です。
helm search hub
Artifact HUBにある全てのパッケージが出てきますので、適当にKeywordで絞り込んで使ってみてください。
それでは実際にデプロイしてみます。
helm install helm-hello helm-hello/hello --namespace helm-hello --create-namespace
今回はhelm install
を使いましたが、helm upgrade --install
としてもインストールできます。後者の場合、インストールされていなければインストールを、インストール済みであればアップグレードをという動きをします。ちなみに私はupgradeをよく使います。
インストール後、以下のように出力されたと思います。
NAME: helm-hello LAST DEPLOYED: Mon Aug 29 16:50:34 2022 NAMESPACE: helm-hello STATUS: deployed REVISION: 1 NOTES: 1. Get the application URL by running these commands: export POD_NAME=$(kubectl get pods --namespace helm-hello -l "app.kubernetes.io/name=hello,app.kubernetes.io/instance=helm-hello" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace helm-hello $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") echo "Visit http://127.0.0.1:8080 to use your application" kubectl --namespace helm-hello port-forward $POD_NAME 8080:$CONTAINER_PORT
NOTESの欄に色々書いてあります。これはアプリケーション固有の情報で、全てのチャートでこの出力があるわけではありません。しかし、有用な情報が書いてあることがありますので、一応目を通しておくことをおすすめします。
後から取得することも可能です。
helm get notes --namespace helm-hello helm-hello
今回はNOTESにアクセス方法が記載されています。以下の手順を行うことでブラウザからアプリにアクセスできるようになります。
export POD_NAME=$(kubectl get pods --namespace helm-hello -l "app.kubernetes.io/name=hello,app.kubernetes.io/instance=helm-hello" -o jsonpath="{.items[0].metadata.name}") export CONTAINER_PORT=$(kubectl get pod --namespace helm-hello $POD_NAME -o jsonpath="{.spec.containers[0].ports[0].containerPort}") kubectl --namespace helm-hello port-forward $POD_NAME 8080:$CONTAINER_PORT
以下のように待ち受け状態になったら、ブラウザからhttp://127.0.0.1:8080
にアクセスしてみてください。hello helm word
が表示されたと思います。
Forwarding from 127.0.0.1:8080 -> 80 Forwarding from [::1]:8080 -> 80
続いて何がインストールされたのかを見てみましょう。
helm list --namespace helm-hello
NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION helm-hello helm-hello 1 2022-08-29 17:03:59.478781 +0900 JST deployed hello-1.1.0 v1.1.0
いつインストールされて、CHARTとAPPがどのバージョンがデプロイされたかが確認できます。
インストールされたマニフェストは以下で確認できます。
helm get manifest --namespace helm-hello helm-hello
helm install
した時にバージョンを指定しなかったのでlatestがインストールされました。次はバージョンを指定してインストールしてみましょう。今回はすでにアプリがインストール済みなのでupgrade
を使います。
helm upgrade helm-hello helm-hello/hello --namespace helm-hello --create-namespace --version 1.0.0
もう一度 helm listを実行してみてください、REVISIONが進み、CHARTとAPP VERSIONがダウングレードされたと思います。NOTESの通り再度ポートフォワードを設定し、ブラウザからアクセスしてみましょう。hello world
に表示が変わったと思います。
次に操作履歴を見てみます。
helm history --namespace helm-hello helm-hello
REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 1 Tue Aug 30 09:12:56 2022 superseded hello-1.1.0 v1.1.0 Install complete 2 Tue Aug 30 09:13:20 2022 deployed hello-1.0.0 v1.0.0 Upgrade complete
いつインストールやアップグレードがされたか、その時のバージョン情報などを確認することができます。STATUSがdeployedになっているものが現在デプロイされているアプリケーションで、helm listで確認したときのリビジョンと一致していると思います。
それでは最後にアンインストールをして終わります。
helm uninstall --namespace helm-hello helm-hello
まとめ
Helmについて簡単にまとめました。今回紹介したサブコマンドは、私が運用中によく使うものです。紹介したもの以外にも、静的解析やロールバックなど、様々なサブコマンドが用意されています。どれも運用に役立つコマンドなので、色々触ってみてください。