36
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

TRIAL&RetailAIAdvent Calendar 2024

Day 20

Helmを「完全に理解した」

Last updated at Posted at 2024-12-19

はじめに

TRIAL&RetailAI Advent Calendar 2024  の 20日目の記事です。

昨日の記事は @kyojinnaapyon さんの『Google Vision AIでレシートスキャンに挑戦!Kotlin × Quarkusでアプリを作ってみた』という記事でした。

Google Cloudにレシート情報を取り込んだ後は、自分がどの商品をどのくらいの間隔で買うのか、必要なもの不要なものはどれかなどをAIで分析できるようにしても面白そうですね🧐

自己紹介

はじめまして。新卒2年目の伊藤と申します。

インフラ・クラウド関係の部署に配属され、約9ヶ月。
SREという重い肩書きを背負いながら、日々学習に明け暮れています。

最近は12/23のGoogle Cloud Architectの試験に向けて、怯えながら過去問を解いている毎日です。

本題

業務でTerraformとHelmに触れる機会があり、「コンテナ?Kubernetes?Helm?IaC?…何だそれ?」と概念から理解することのできなかった日から、脳が焼き切れるくらい考え、Helmを「完全に理解」することができたので、この機会にHelmをちょっとだけ紹介(アウトプット)したいと思います。

ちなみに、Kubernetesは本当にまだ理解できていません。

※こちらの記事は、個人的な見解であり、所属する会社、組織とは全く関係ありません。

Helmとは

Helm is the best way to find, share, and use software built for Kubernetes.
(Helm は、 Kubernetes 用に構築されたソフトウェアを検索、共有、使用するための最良の方法です。)

公式(https://helm.sh/)より

Kubernetesを作成した方なら経験があると思いますが、yamlファイルを地獄のように書き続けなければならないです。
Helmはその手間を省き、helm install というコマンド一発で環境を構築することができます。

Helmを理解する近道は、実際に使ってみることです!

▼ 私が以前Kubernets作成で参考にさせていただいた手順書(鬼ムズ)

▼ Helmが利用できるか確認するサイトもあります

やってみる

コードとかダラダラ書いてるので読み飛ばしていいです。

作業内容

GKE (Google Kubernetes Engine) のクラスタ内に、Helmでリソースのデプロイします。
アプリケーションだと、Deployment、Service、Ingressが最小構成になると思います。
今回は外部公開をしないので、ロードバランサーの役割を担う、Ingressは作成しません。

イメージ図

Helm.png

Helm 構成

helm create <chart-name> というコマンドを実行すると、以下のようなファイルが自動生成されます。

<chart-name>/
├── Chart.yaml                # チャートのメタ情報
├── values.yaml               # ユーザーが設定を上書きするためのデフォルト値ファイル
├── charts/                   # 他のチャートの依存関係を格納するディレクトリ(helm dependencyで管理)
├── templates/                # Kubernetesマニフェストのテンプレートファイルを格納
│   ├── _helpers.tpl          # テンプレート内で使用されるヘルパーファイル(繰り返し利用する関数)
│   ├── deployment.yaml       # Deploymentリソースのテンプレート
│   ├── service.yaml          # Serviceリソースのテンプレート
│   ├── ingress.yaml          # Ingressリソースのテンプレート
│   ├── hpa.yaml              # Horizontal Pod Autoscalerのテンプレート
│   ├── NOTES.txt             # インストール時に表示されるメッセージ
│   └── tests/                # テスト用のマニフェストを格納(helm testで使用)
│       └── test-connection.yaml  # Pod間接続テスト用テンプレート
└── .helmignore               # 無視するファイルやディレクトリを定義 (.gitignoreに類似)

上記のものがHelmの雛形になりますが、少し分かりにくいので、不要なものを削除します。

service/
├── Chart.yaml
├── values.yaml
├── charts/
├── templates/
│   ├── deployment.yaml
│   ├── service.yaml
│   └── ingress.yaml
└── .helmignore

あら、綺麗。

簡単な説明

chart.yaml

  • apiのversionや名前を保存する

values.yaml

  • values-dev.yamlや、values-stg.yaml、values.yamlなどで、環境ごとにデフォルト値を設定できる
  • イメージ情報やレプリカ数などを保存する

charts/

  • 別のチャートを追加できる
  • 無くても動くため、特に気にする必要はない

templates/

  • Kubernetesマニュフェスト(deployment.yamlやconfigmap.yamlなど)のテンプレを保存する
  • この中身から判断して、KubernetesのYAMLファイルを作成する

作業

1. クラスタを準備

GKEでクラスタを準備します。(コンソールから簡単に作成できます)
本題では無いので省略。

test-cluster.png

2. コードを書く

values.yamlに値を、templateフォルダ内に変数を入れます。

deployment

# service/values.yaml
deployment:
  enabled: true
  replicas: 1
  labels:
    app: my-test-app

  containers:
    - name: app-container
      image:
        repository: nginx
        tag: latest
        pullPolicy: IfNotPresent
      ports:
        containerPort: 80
      resources:
        limits:
          cpu: "500m"
          memory: "512Mi"
        requests:
          cpu: "250m"
          memory: "256Mi"
      livenessProbe:
        enabled: true
        httpGet:
          path: /
          port: 80
        initialDelaySeconds: 5
        periodSeconds: 10
      readinessProbe:
        enabled: true
        httpGet:
          path: /
          port: 80
        initialDelaySeconds: 5
        periodSeconds: 10
# service/template/deployment.yaml
{{- if .Values.deployment.enabled }}
apiVersion: apps/v1
kind: Deployment
metadata:
  name: {{ .Release.Name }}-deployment
  labels:
    app: {{ .Values.deployment.labels.app }}
spec:
  replicas: {{ .Values.deployment.replicas }}
  selector:
    matchLabels:
      app: {{ .Values.deployment.labels.app }}
  template:
    metadata:
      labels:
        app: {{ .Values.deployment.labels.app }}
    spec:
      containers:
        {{- range .Values.deployment.containers }}
        - name: {{ .name }}
          image: "{{ .image.repository }}:{{ .image.tag }}"
          imagePullPolicy: {{ .image.pullPolicy }}
          ports:
            - containerPort: {{ .ports.containerPort }}
          resources:
            limits:
              cpu: {{ .resources.limits.cpu }}
              memory: {{ .resources.limits.memory }}
            requests:
              cpu: {{ .resources.requests.cpu }}
              memory: {{ .resources.requests.memory }}
          {{- if .livenessProbe.enabled }}
          livenessProbe:
            httpGet:
              path: {{ .livenessProbe.httpGet.path }}
              port: {{ .livenessProbe.httpGet.port }}
            initialDelaySeconds: {{ .livenessProbe.initialDelaySeconds }}
            periodSeconds: {{ .livenessProbe.periodSeconds }}
          {{- end }}
          {{- if .readinessProbe.enabled }}
          readinessProbe:
            httpGet:
              path: {{ .readinessProbe.httpGet.path }}
              port: {{ .readinessProbe.httpGet.port }}
            initialDelaySeconds: {{ .readinessProbe.initialDelaySeconds }}
            periodSeconds: {{ .readinessProbe.periodSeconds }}
          {{- end }}
        {{- end }}
{{- end }}

service

# service/values.yaml
service:
  type: ClusterIP
  port: 80
  labels:
    app: my-test-app
# service/template/service.yaml
apiVersion: v1
kind: Service
metadata:
  name: {{ .Release.Name }}-service
  labels:
    app: {{ .Values.deployment.labels.app }}
spec:
  type: {{ .Values.service.type }}
  ports:
    - port: {{ .Values.service.port }}
      targetPort: 80
      protocol: TCP
  selector:
    app: {{ .Values.deployment.labels.app }}

ingress

# service/values.yaml
ingress:
  enabled: false     # 無効
  className: "nginx"
  host: example.com
  path: /
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
# service/template/ingress.yaml
{{- if .Values.ingress.enabled }}
apiVersion: networking.k8s.io/v1
kind: Ingress
# ~ 省略 ~
{{- end }}

▼ 全容はこちら

簡単な説明

{{ .Values.xxx.xxxxx }}

values.yamlを参照。
valuesのxxxのxxxxxの値のように、細かく分けることができる。

例)

# chart/template/deployment.yaml
labels:
  app: {{ .Values.deployment.labels.app }}
# chart/values.yaml
deployment:
  labels:
    app: my-test-app

{{- if .Values.xxx.xxxxx }}

true or false の条件式。
enabledは有効にするか無効にするか。

例)

# chart/template/deployment.yaml
{{ if .Values.deployment.enabled }}

{{ end }}
# chart/values.yaml
deployment:
  enabled: true

{{- range .Values.xxx.xxxxx }}
リストやマップを繰り返し処理する。
.Valuesを省略できるため、使い勝手がいい。

例)

# chart/template/deployment.yaml
{{- range .Values.deployment.containers }}
  - name: {{ .name }}
    image: "{{ .image.repository }}:{{ .image.tag }}"
    imagePullPolicy: {{ .image.pullPolicy }}
{{ end }}
# chart/values.yaml
deployment:
  containers:
    - name: app-container-1
      image:
        repository: nginx
        tag: latest
        pullPolicy: IfNotPresent
    - name: app-container-2
      image:
        repository: redis
        tag: latest
        pullPolicy: IfNotPresent

3. 認証

①ローカルPCにgoogle cloudの認証情報をセット
gcloud auth login
gcloud config set project <PROJECT_ID>
gcloud config set account <ACCOUNT_ADDRESS>

gcloud config list コマンドでPCにどの認証情報があるか確認します。

gcloud_config_list_2.png

②プロジェクトで、どのクラスタがあるのか確認する

gcloud container clusters list
接続しているプロジェクト内に、作成したtest-clusterがリストにあることが分かります。

gcloud_container_cluster_list.png

③リソースをデプロイしたいクラスタとの認証する
gcloud container clusters get-credentials <CLUSTER_NAME>

gcloud_credentials.png

イメージ図

gke_1.png

4. Helm install

helm install
kube create ns <NAMESPACE>
helm install -n <NAMESPACE> <RELEASE_NAME> -f <VALUE_FILE> <CHART_NAME>

テストコマンド
helm install -n <NAMESPACE> <RELEASE_NAME> -f <VALUE_FILE> <CHART_NAME> --dry-run --debug

kube_create_ns.png

helm_install_service1.png

コマンド成功後、GKEにも反映されました!
gke.png

helm uninstall
不要になったとき実行
helm uninstall <RELEASE_NAME> -n <NAMESPACE>

5. Kubectl で操作する

kubectl
kubectl get xxx -n <NAMESPACE>
kubernetesのコマンドで、K8s内の情報を取得

kube_get_services.png

kube_get_deployment.png

kube_get_pods.png

他にkubectl execコマンドでpodの中に入ったり、kubectl logsでログを見たりできる。

イメージ図

gke_2.png

完全に理解した

ちなみに「完全に理解した」と言ってくる人の信用度は低いです。
おそらく全てを学んではいないでしょう。

ダニング・クルーガー効果.png

Linuxの生みの親は、Linuxを「チョットデキル」。

チョットデキル.jpg

何もわからない

「完全に理解した」と大きく書いていますが、実際はHelmで一部のKubenetesのオブジェクトをつくれるようなるチュートリアルが終わっただけであって、本当に理解しているという意味ではありません...

Kubernetsには、ReplicaSetやDaemonSet、StatefulSetなどのControllerや、SecretやConfigMapなどなどたくさんのオブジェクトがあり、PrometheusやElasticsearch、Grafanaなどのソフトウェアやサービスのさまざまなチャートで、どの構成がベストプラクティスなのかも考える必要があると思います。

Kubernetes含む、Helmを全てを理解するには、まだ道のりが長そうです…
「Kubernetes?Helm?IaC? チョットデキルよ。」と言えるように、学習を続けていきます。

長々と書いていますが、この記事で「Helmというものがあるんだなぁ」程度に覚えていただければ、全てOKです!

さいごに

明日のTRIAL&RetailAI Advent Calendar 2024 の 21日目の記事は、
@k-yoshigai さんの『インテグレーションテストをもっと楽に!Testcontainers はじめました』という記事です。

一時期テスターしてたので、テスト作業の辛さが分かりますが、テストが楽になるのはテスターにとって最高のことですね。
次回もお楽しみに!

TRIALとRetailAIではエンジニアを募集しています。
興味ある方は以下のURLからチェックしてください。
個人的には、ともにクラウドを極める、クラウドエンジニア が来てくれると嬉しいです!

参考資料

36
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
36
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?