こんにちは。KOUKIです。
とある企業でWebエンジニアをやっています。
前回は、Helmの簡単な使い方やデプロイの方法を学びました。
今回は、Chartの検証方法やテスト方法を学びましょう。
<目次>
検証環境
- helm v3
- mac
- minikube
Kubernetesに関しては、こちらも参考にしてください。
dry-runオプション
Helmを使うと簡単にKubernetesへデプロイすることができることを学びました。
ちょっと復習を兼ねて、Nginxをインストールしてみましょう。
1 2 3 |
$ tree . └── values.yaml |
ローカルには、values.yamlがあります。
1 2 3 |
# values.yaml service: type: NodePort |
このファイルのValueをこれからkubernetesにデプロイするNginxのパラメータとして渡します。
1 2 |
# Install $ helm install nginx01 --values values.yaml --set service.port=8080 bitnami/nginx |
–valuesオプションでファイルの値を、–setオプションで直接値をNginxに渡します。
下記のコマンドで、無事にデプロイできたことを確認します。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ kubectl get all NAME READY STATUS RESTARTS AGE pod/nginx01-7d557d97b5-b4n2l 1/1 Running 0 55s NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 3d5h service/nginx01 NodePort 10.102.82.87 <none> 8080:31087/TCP 55s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx01 1/1 1 1 55s NAME DESIRED CURRENT READY AGE |
前置きが長くなりましたが、「–dry-run」オプションの話に移りましょう。
このコマンドは、デバッキングする時に便利です。
百聞は一見にしかず、ということで「–dry-run」オプション付きでコマンドを実行しましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
$ helm install nginx01 --values values.yaml --set service.port=8080 bitnami/nginx --dry-run NAME: nginx01 LAST DEPLOYED: Tue Nov 23 10:26:30 2021 NAMESPACE: default STATUS: pending-install REVISION: 1 TEST SUITE: None HOOKS: MANIFEST: --- # Source: nginx/templates/server-block-configmap.yaml apiVersion: v1 kind: ConfigMap metadata: name: nginx01-server-block labels: app.kubernetes.io/name: nginx helm.sh/chart: nginx-9.5.13 app.kubernetes.io/instance: nginx01 app.kubernetes.io/managed-by: Helm data: server-blocks-paths.conf: |- include "/opt/bitnami/nginx/conf/server_blocks/ldap/*.conf"; include "/opt/bitnami/nginx/conf/server_blocks/common/*.conf"; --- # Source: nginx/templates/svc.yaml apiVersion: v1 kind: Service metadata: name: nginx01 labels: app.kubernetes.io/name: nginx helm.sh/chart: nginx-9.5.13 app.kubernetes.io/instance: nginx01 app.kubernetes.io/managed-by: Helm spec: type: NodePort externalTrafficPolicy: "Cluster" ports: - name: http port: 8080 targetPort: http selector: app.kubernetes.io/name: nginx app.kubernetes.io/instance: nginx01 --- # Source: nginx/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: nginx01 labels: app.kubernetes.io/name: nginx helm.sh/chart: nginx-9.5.13 app.kubernetes.io/instance: nginx01 app.kubernetes.io/managed-by: Helm spec: replicas: 1 selector: matchLabels: app.kubernetes.io/name: nginx app.kubernetes.io/instance: nginx01 template: metadata: labels: app.kubernetes.io/name: nginx helm.sh/chart: nginx-9.5.13 app.kubernetes.io/instance: nginx01 app.kubernetes.io/managed-by: Helm spec: automountServiceAccountToken: false shareProcessNamespace: false serviceAccountName: default affinity: podAffinity: podAntiAffinity: preferredDuringSchedulingIgnoredDuringExecution: - podAffinityTerm: labelSelector: matchLabels: app.kubernetes.io/name: nginx app.kubernetes.io/instance: nginx01 namespaces: - "default" topologyKey: kubernetes.io/hostname weight: 1 nodeAffinity: containers: - name: nginx image: docker.io/bitnami/nginx:1.21.4-debian-10-r0 imagePullPolicy: "IfNotPresent" env: - name: BITNAMI_DEBUG value: "false" ports: - name: http containerPort: 8080 livenessProbe: tcpSocket: port: http periodSeconds: 10 timeoutSeconds: 5 successThreshold: 1 failureThreshold: 6 readinessProbe: tcpSocket: port: http initialDelaySeconds: 5 periodSeconds: 5 timeoutSeconds: 3 successThreshold: 1 failureThreshold: 3 resources: limits: {} requests: {} volumeMounts: volumes: - name: nginx-server-block-paths configMap: name: nginx01-server-block items: - key: server-blocks-paths.conf path: server-blocks-paths.conf |
結構、ズラーっと出力されましたが、注目してほしい部分は、ここです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
# Source: nginx/templates/svc.yaml apiVersion: v1 kind: Service metadata: name: nginx01 labels: app.kubernetes.io/name: nginx helm.sh/chart: nginx-9.5.13 app.kubernetes.io/instance: nginx01 app.kubernetes.io/managed-by: Helm spec: type: NodePort externalTrafficPolicy: "Cluster" ports: - name: http port: 8080 targetPort: http selector: app.kubernetes.io/name: nginx app.kubernetes.io/instance: nginx01 |
書き換えた値である「NodePort」が確認できます。
つまり何が言いたいかというと、「–dry-run」オプションを使うとアプリをデプロイする前に、どの様なパラメーターでアプリがデプロイされるかわかるということです。
結構便利そうですよね。
helm get
「helm get」コマンドで、色々な情報を取得できます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
# nginx01の情報 $ helm get notes nginx01 NOTES: CHART NAME: nginx CHART VERSION: 9.5.13 APP VERSION: 1.21.4 ** Please be patient while the chart is being deployed ** NGINX can be accessed through the following DNS name from within your cluster: nginx01.default.svc.cluster.local (port 8080) To access NGINX from outside the cluster, follow the steps below: 1. Get the NGINX URL by running these commands: export NODE_PORT=$(kubectl get --namespace default -o jsonpath="{.spec.ports[0].nodePort}" services nginx01) export NODE_IP=$(kubectl get nodes --namespace default -o jsonpath="{.items[0].status.addresses[0].address}") echo "http://${NODE_IP}:${NODE_PORT}" $ helm get values nginx01 USER-SUPPLIED VALUES: service: port: 8080 type: NodePort # 全ての情報 $ helm get values nginx01 --all # nginx01のマニフェスト $ helm get manifest nginx01 |
ロールバック
続いて、ロールバックの方法を見ていきましょう。
まず、現状の状況を確認します。
1 2 3 |
$ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx01 NodePort 10.102.82.87 <none> 8080:31087/TCP 15m |
nginx01のTYPEは、NodePortですね。
このTYPEを誤って下記のように上書きしてしまったとしましょう。
1 2 |
$ helm upgrade nginx01 --set service.type=foo bitnami/nginx Error: UPGRADE FAILED: cannot patch "nginx01" with kind Service: Service "nginx01" is invalid: spec.type: Unsupported value: "foo": supported values: "ClusterIP", "ExternalName", "LoadBalancer", "NodePort" |
エラーが出ましたね。下記のコマンドでもfailedになりました。
1 2 3 |
$ helm list NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION nginx01 default 3 2021-11-23 10:48:12.17782 +0900 JST failed nginx-9.5.13 1.21.4 |
以下のステータスがあるらしいです。
STATUS | DESCRIPTION |
---|---|
pending-install | マニフェストの準備OK、Kubernetes送信前 |
deployed | Kubernetesへマニフェストを送信し、デプロイ済み |
pending-upgrade | アップグレード用のマニフェストの準備OK、Kubernetes送信前 |
superseded | アップグレード成功 |
pending-rollback | ロールバック用のマニフェストの準備OK、Kubernetes送信前 |
uninstalling | 現バージョンがアンインストールしている状態 |
uninstalled | アンインストール済み |
failed | Kubernetseがリクエストされたマニフェストを拒否した状態 |
ちなみに、履歴は下記のコマンドで確認可能です。
1 2 3 4 5 |
$ helm history nginx01 REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 1 Tue Nov 23 10:24:59 2021 deployed nginx-9.5.13 1.21.4 Install complete 2 Tue Nov 23 10:41:31 2021 failed nginx-9.5.13 1.21.4 Upgrade "nginx01" failed: cannot patch "nginx01" with kind Service: Service "nginx01" is invalid: spec.type: Unsupported value: "foo": supported values: "ClusterIP", "ExternalName", "LoadBalancer", "NodePort" 3 Tue Nov 23 10:48:12 2021 failed nginx-9.5.13 1.21.4 Upgrade "nginx01" failed: cannot patch "nginx01" with kind Service: Service "nginx01" is invalid: spec.type: Unsupported value: "foo": supported values: "ClusterIP", "ExternalName", "LoadBalancer", "NodePort" |
helmはrevision管理ができるので、かなり便利ですよね。
上記の「REVISION」を使って、ロールバックをしてみましょう。
1 2 3 4 5 6 7 8 |
$ helm rollback nginx01 1 Rollback was a success! Happy Helming! $ helm history nginx01 REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 1 Tue Nov 23 10:24:59 2021 superseded nginx-9.5.13 1.21.4 Install complete ... 4 Tue Nov 23 11:02:49 2021 deployed nginx-9.5.13 1.21.4 Rollback to 1 |
OKですね。
ちなみに、helm uninstallでアプリを消すと履歴が消えてしまうのですが、「–keep-history」オプションを付けて実行すると消えないです。
1 2 3 4 5 6 7 8 |
$ helm uninstall nginx01 --keep-history release "nginx01" uninstalled $ helm history nginx01 REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION 1 Tue Nov 23 10:24:59 2021 superseded nginx-9.5.13 1.21.4 Install complete ... 4 Tue Nov 23 11:02:49 2021 uninstalled nginx-9.5.13 1.21.4 Uninstallation complete |
履歴が残っていれば、消してしまった状態でもロールバックが可能です。
1 2 3 4 5 6 7 8 9 10 11 12 |
$ helm rollback nginx01 1 Rollback was a success! Happy Helming! $ kubectl get svc NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx01 NodePort 10.110.196.54 <none> 8080:31371/TCP 16s $ helm history nginx01 REVISION UPDATED STATUS CHART APP VERSION DESCRIPTION ... 4 Tue Nov 23 11:02:49 2021 uninstalled nginx-9.5.13 1.21.4 Uninstallation complete 5 Tue Nov 23 11:06:25 2021 deployed nginx-9.5.13 1.21.4 Rollback to 1 |
最高ですね! 実運用でもめちゃくちゃ役に立ちそうです。
Helm Tips
アプリ名の動的変更1
「helm install nginx01」でnginxをKubernetesへデプロイしたわけですが、名前の付け方に注意が必要です。
例えば、現在nginx01がデプロイされています。
1 2 3 4 5 6 7 8 9 10 |
$ kubectl get svc,deployment,pod NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d service/nginx01 NodePort 10.110.196.54 <none> 8080:31371/TCP 18h NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx01 1/1 1 1 18h NAME READY STATUS RESTARTS AGE pod/nginx01-7d557d97b5-2skdr 1/1 Running 1 (18h ago) 18h |
この状態で、「helm install nginx01」を実行してみましょう。
1 2 |
$ helm install nginx01 Error: INSTALLATION FAILED: must either provide a name or specify --generate-name |
上記の通り、重複した名前の場合はErrorで弾かれます。
このような場合は、動的に名前を変更できるようにしましょう。
1 2 3 4 5 6 7 8 9 |
# RANDOMな値を環境変数として登録 $ export RELEASE_SUFFIX=$(LC_CTYPE=C tr -dc a-z0-9 </dev/urandom | head -c 13 ; echo) # 確認 $ echo $RELEASE_SUFFIX wvzgii54w7fb6 # インストール $ helm install nginx-$RELEASE_SUFFIX bitnami/nginx |
こんな具合ですね。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
$ kubectl get svc,deployment,pod NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 4d service/nginx-wvzgii54w7fb6 LoadBalancer 10.111.159.108 <pending> 80:30941/TCP 18s service/nginx01 NodePort 10.110.196.54 <none> 8080:31371/TCP 18h NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/nginx-wvzgii54w7fb6 1/1 1 1 18s deployment.apps/nginx01 1/1 1 1 18h NAME READY STATUS RESTARTS AGE pod/nginx-wvzgii54w7fb6-7f59784d6d-rj2jq 1/1 Running 0 18s pod/nginx01-7d557d97b5-2skdr 1/1 Running 1 (18h ago) 18h |
いい感じですね
アプリ名の動的変更2
いやいや、めんどくさいよという方は、こんな「–generate-name」オプションもおすすめです。
これはリソース名をランダムに生成してくれます。
1 2 3 4 5 6 7 8 |
# nginxをインストール $ helm install bitnami/nginx --generate-name $ helm list NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION nginx-1637699827 default 1 2021-11-24 05:37:11.229348 +0900 JST deployed nginx-9.5.13 1.21.4 nginx-wvzgii54w7fb6 default 1 2021-11-24 05:34:15.628088 +0900 JST deployed nginx-9.5.13 1.21.4 nginx01 default 5 2021-11-23 11:06:25.772102 +0900 JST deployed nginx-9.5.13 1.21.4 |
「nginx-1637699827 」が–generate-nameオプションで生成されたnginxですね。
ネームスペースの自動作成
復習となりますが、Kubernetesではネームスペースを下記のコマンドで作成します。
1 2 |
# Namespaceの作成 kubectl create ns web |
Helmでは「-n」オプションでネームスペースを指定できるのですが、事前に作成されていないとエラーになります。
1 2 |
$ helm install nginx01 -n apps bitnami/nginx Error: INSTALLATION FAILED: create: failed to create: namespaces "apps" not found |
そんな時は、「–create-namespace」オプションが便利です。これは、ネームスペースを自動で作成してくれます。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# --create-namespaceオプションで動的にNamespaceを作成 $ helm install nginx01 -n apps bitnami/nginx --create-namespace # Namespace一覧 $ kubectl get ns NAME STATUS AGE apps Active 41s default Active 4d istio-system Active 4d kube-node-lease Active 4d kube-public Active 4d kube-system Active 4d web Active 3d18h |
apps ネームスペースが作成されましたね!
installオプション(CI/CD デプロイに使える)
アプリをアップグレードしたい場合は、以下のコマンドを実行します。
1 2 3 |
# upgrade $ helm upgrade nginx10 --set service.port=8080 bitnami/nginx Error: UPGRADE FAILED: "nginx10" has no deployed releases |
しかし、上記の様に「nginx10」がデプロイされていない環境下だとErrorが発生します。
こんな時に、「–install」オプションを付けると便利です。
1 2 |
$ helm upgrade --install nginx10 --set service.port=8080 bitnami/nginx Release "nginx10" does not exist. Installing it now. |
「Release “nginx10” does not exist. Installing it now.」とあるように、nginx10がデプロイされていない場合は、デプロイしてくれます。
これは、CI/CDに組み込む時に便利そうなコマンドです。
ちなみに、既にデプロイされている場合は、そのままUpgradeされます。
1 2 |
$ helm upgrade --install nginx10 --set service.port=8080 bitnami/nginx Release "nginx10" has been upgraded. Happy Helming! |
値の検証(CI/CDパイプライン)
少し前に、誤った値を渡した時のHelmのステータスについて触れました。
例えば、registryを適当な値に変更します。
1 2 |
# registryを適当な値に $ helm upgrade nginx10 --set image.registry=foo bitnami/nginx |
この状態で、Podの様子を見てみましょう。
1 2 3 |
$ kubectl get pod NAME READY STATUS RESTARTS AGE nginx10-5548f7cbbf-t57qq 0/1 ImagePullBackOff 0 33s |
「ImagePullBackOff」になってますね。このような状態にならないようにバリデーションチェックをしたいところです。
この様な場合は、「–wait」オプション付きで実行してみましょう。
1 2 |
$ helm upgrade nginx10 --set image.registry=foo bitnami/nginx --wait --timeout 10s Error: UPGRADE FAILED: timed out waiting for the condition |
–waitのデフォルトの待機時間は300sなので、–timeoutオプションで10sに変更してます。
ご覧の通り、エラーになってくれましたね!
これは、CI/CDパイプラインに組み込むとき、大変便利です。
Clean Up
最後に、環境を綺麗にしておきましょう。
1 2 3 4 5 6 7 8 9 10 11 |
AME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION nginx-1637699827 default 1 2021-11-24 05:37:11.229348 +0900 JST deployed nginx-9.5.13 1.21.4 nginx-wvzgii54w7fb6 default 1 2021-11-24 05:34:15.628088 +0900 JST deployed nginx-9.5.13 1.21.4 nginx01 default 5 2021-11-23 11:06:25.772102 +0900 JST deployed nginx-9.5.13 1.21.4 nginx10 default 5 2021-11-24 06:07:49.318392 +0900 JST failed nginx-9.5.13 1.21.4 $ helm uninstall nginx-1637699827 nginx-wvzgii54w7fb6 nginx01 nginx10 release "nginx-1637699827" uninstalled release "nginx-wvzgii54w7fb6" uninstalled release "nginx01" uninstalled release "nginx10" uninstalled |
次回
次回は、Helm ChartのTemplateについて深く学びましょう。
コメントを残す
コメントを投稿するにはログインしてください。