AnsibleでHelm version3を操作する。
使用モジュール
Helm version3 を使うには、community.kubernetes collectionのhelmモジュールを使用する。
このモジュールはHelm関連のPythonパッケージは必要とせず、CLIのhelm
コマンドを内部から実行する仕様になっている。
よってAnsibleの実行環境・権限でhelm
コマンドも使用できるようにKUBECONFIG
関連も設定しておく。
旧helmモジュール
community.general collectionにも同名のhelmモジュールがあるが、こちらはHelm version2向け。
また、Ansible 2.9以前のhelmモジュールや、2.10でもFQCN表記しない場合はこちらのcommunity.general.helm
が使われるので注意。
検証環境
(venv) [zaki@cloud-dev helm-sample]$ ansible --version ansible 2.10.2 config file = /home/zaki/src/ansible-sample/tmp/helm-sample/ansible.cfg configured module search path = ['/home/zaki/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /home/zaki/src/ansible-sample/venv/lib64/python3.6/site-packages/ansible executable location = /home/zaki/src/ansible-sample/venv/bin/ansible python version = 3.6.8 (default, Apr 2 2020, 13:34:55) [GCC 4.8.5 20150623 (Red Hat 4.8.5-39)]
community.kubernetes collectionバージョンは1.1.1 (pip install ansible
でインストールしている)
(venv) [zaki@cloud-dev helm-sample]$ grep version $VIRTUAL_ENV/lib/python3.6/site-packages/ansible_collections/community/kubernetes/MANIFEST.json "version": "1.1.1",
対象クラスタはkindで構築したKubernetes 1.19環境。
(venv) [zaki@cloud-dev helm-sample]$ kubectl version --short Client Version: v1.19.2 Server Version: v1.19.1 (venv) [zaki@cloud-dev helm-sample]$ helm version --short v3.3.4+ga61ce56
(venv) [zaki@cloud-dev helm-sample]$ kubectl get pod -A NAMESPACE NAME READY STATUS RESTARTS AGE kube-system coredns-f9fd979d6-6qtq6 1/1 Running 0 40m kube-system coredns-f9fd979d6-t6w67 1/1 Running 0 40m kube-system etcd-kind-1.19-control-plane 1/1 Running 0 40m kube-system kindnet-flqmf 1/1 Running 0 40m kube-system kindnet-jvk54 1/1 Running 0 40m kube-system kindnet-l74r8 1/1 Running 0 40m kube-system kube-apiserver-kind-1.19-control-plane 1/1 Running 0 40m kube-system kube-controller-manager-kind-1.19-control-plane 1/1 Running 3 40m kube-system kube-proxy-4585c 1/1 Running 0 40m kube-system kube-proxy-kqfdk 1/1 Running 0 40m kube-system kube-proxy-kzkvd 1/1 Running 0 40m kube-system kube-scheduler-kind-1.19-control-plane 1/1 Running 3 40m local-path-storage local-path-provisioner-78776bfc44-7q7fk 1/1 Running 2 40m
まだアプリケーションpodは何もない状態。
playbook例
Helmリポジトリを設定し、MySQLのチャートをインストールする例。
repository設定
helmモジュールでなくhelm_repositoryモジュールを使用する。
- name: Add default repository community.kubernetes.helm_repository: name: stable repo_url: https://kubernetes-charts.storage.googleapis.com
この内容でansible-playbook
を実行すれば、実行ユーザの~/.config/helm/repositories.yaml
が設定される。
helm repo update
CLIだとリポジトリ設定後によく実行するけど、この処理単体を実現するplaybookの記述は無い。
後述のchartインストールのplaybookに以下のパラメタを追加すれば良い。
update_repo_cache: true
Helm chartのインストール
helmモジュールを使用する。
基本的にはExampleを見れば使い方はすぐにわかると思う。
- name: helm community.kubernetes.helm: name: mysql-sample update_repo_cache: true chart_ref: stable/mysql release_namespace: db create_namespace: true
(venv) [zaki@cloud-dev helm-sample]$ kubectl get pod -n db NAME READY STATUS RESTARTS AGE mysql-sample-56859879c4-mckq8 1/1 Running 0 38s (venv) [zaki@cloud-dev helm-sample]$ helm ls -n db NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION mysql-sample db 1 2020-11-01 11:00:31.421374967 +0900 JST deployed mysql-1.6.7 5.7.30
この通りデプロイされた。
また、上記のplaybookは再実行しても冪等性が保たれてok
となる。
カスタマイズYAML
現バージョンでは2通りの設定が可能。
ただしvalues_files
は制限がある。
release_values (valuesもaliasで使用可能)
チャートに対するカスタマイズYAMLをrelease_values
以下に直接記載する。
以下はServiceのtypeのカスタマイズ例
- name: helm community.kubernetes.helm: name: mysql-sample update_repo_cache: true chart_ref: stable/mysql release_namespace: db create_namespace: true release_values: service: type: NodePort port: 3306
これをデプロイすれば、type:NodePortのServiceとなる。
(venv) [zaki@cloud-dev helm-sample]$ kc get svc -n db NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE mysql-sample NodePort 10.96.86.245 <none> 3306:31456/TCP 26m
values_files (注意点有り)
もう一つがカスタマイズYAMLファイルを別途作成し、そのパスを指定するもの。
- name: helm community.kubernetes.helm: name: mysql-sample update_repo_cache: true chart_ref: stable/mysql release_namespace: db create_namespace: true values_files: - ./mysql-conf/values-service.yaml
## Configure the service ## ref: http://kubernetes.io/docs/user-guide/services/ service: annotations: {} ## Specify a service type ## ref: https://kubernetes.io/docs/concepts/services-networking/service/#publishing-services---service-types type: NodePort port: 3306 # nodePort: 32000 # loadBalancerIP:
こういうこと。
ただしこのvalues_files
を指定する場合は現バージョンでは注意が必要で、「カスタマイズYAML指定無しでreleaseがデプロイされている状態で、values_files
の指定のみで変更を行うとする」と、機能しない。(変更が適用されない)
具体的には、CLIでhelm get values <release-name>
がnull
になる状態からの変更が行われない。
ソースを見る限り、デプロイが行われる条件が「release_values
の値とデプロイ済みreleaseのカスタマイズYAMLの値が不一致の場合」に処理されるため、values_files
の設定が参照されていない。
この設定を反映させるには、追加でforce: true
の付与も必要だが、helm
の引数に--force
が付与されてチャート全体が再デプロイされる動作になるため、注意が必要。
例えばこのmysqlチャートのようにpvを使ってる場合など。
TASK [helm] ******************************************************************* fatal: [localhost]: FAILED! => changed=false command: /usr/local/bin/helm --namespace=db upgrade -i --reset-values --force --create-namespace --values=./mysql-conf/values-service.yaml mysql-sample stable/mysql msg: |- Failure when executing Helm command. Exited 1. stdout: stderr: Error: UPGRADE FAILED: failed to replace object: PersistentVolumeClaim "mysql-sample" is invalid: spec: Forbidden: spec is immutable after creation except resources.requests for bound claims core.PersistentVolumeClaimSpec{ AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOnce"}, Selector: nil, Resources: core.ResourceRequirements{Requests: core.ResourceList{s"storage": {i: resource.int64Amount{value: 8589934592}, Format: "BinarySI"}}}, - VolumeName: "", + VolumeName: "pvc-c32003b0-ac97-4fc9-8d06-022e4e8162a2", - StorageClassName: nil, + StorageClassName: &"standard", VolumeMode: &"Filesystem", DataSource: nil, } && failed to replace object: Service "mysql-sample" is invalid: spec.clusterIP: Invalid value: "": field is immutable stderr: |- Error: UPGRADE FAILED: failed to replace object: PersistentVolumeClaim "mysql-sample" is invalid: spec: Forbidden: spec is immutable after creation except resources.requests for bound claims core.PersistentVolumeClaimSpec{ AccessModes: []core.PersistentVolumeAccessMode{"ReadWriteOnce"}, Selector: nil, Resources: core.ResourceRequirements{Requests: core.ResourceList{s"storage": {i: resource.int64Amount{value: 8589934592}, Format: "BinarySI"}}}, - VolumeName: "", + VolumeName: "pvc-c32003b0-ac97-4fc9-8d06-022e4e8162a2", - StorageClassName: nil, + StorageClassName: &"standard", VolumeMode: &"Filesystem", DataSource: nil, } && failed to replace object: Service "mysql-sample" is invalid: spec.clusterIP: Invalid value: "": field is immutable stderr_lines: <omitted> stdout: '' stdout_lines: <omitted>
ちなみに、カスタマイズYAML設定済みのreleaseが動いている状態での再実行であれば、force
設定無しでvalues_files
の内容は適用される。
(むしろ冪等性が保たれず常に実行される)
ドキュメントを見るとvalues_files
は1.1.0で追加された新しい設定なので、実装側の処理漏れっぽいかな。。
サンプルコード(playbook全体)
(11/5追記) コレクションのFQCNの変更について
11/4のこのブログ記事で、AnsibleからHelmを使うサンプル付きの記事が公開されてました。
重要なのは以下。
Please note that prior to the release of kubernetes.core 1.1, its contents were released as community.kubernetes. With this content becoming Red Hat support and certified content, a name change was in order. We are in the process of making that transition.
community.kubernetes
からkubernetes.core
にコレクション名が変更されることになったらしい。
Galaxy Pageにもすでに作成されているので、そのうち入れ替わる模様。