はじめに
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 用に構築されたソフトウェアを検索、共有、使用するための最良の方法です。)
Kubernetesを作成した方なら経験があると思いますが、yamlファイルを地獄のように書き続けなければならないです。
Helmはその手間を省き、helm install
というコマンド一発で環境を構築することができます。
Helmを理解する近道は、実際に使ってみることです!
▼ 私が以前Kubernets作成で参考にさせていただいた手順書(鬼ムズ)
▼ Helmが利用できるか確認するサイトもあります
やってみる
コードとかダラダラ書いてるので読み飛ばしていいです。
作業内容
GKE (Google Kubernetes Engine) のクラスタ内に、Helmでリソースのデプロイします。
アプリケーションだと、Deployment、Service、Ingressが最小構成になると思います。
今回は外部公開をしないので、ロードバランサーの役割を担う、Ingressは作成しません。
イメージ図
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でクラスタを準備します。(コンソールから簡単に作成できます)
本題では無いので省略。
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 container clusters list
接続しているプロジェクト内に、作成したtest-clusterがリストにあることが分かります。
③リソースをデプロイしたいクラスタとの認証する
gcloud container clusters get-credentials <CLUSTER_NAME>
イメージ図
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
helm uninstall
不要になったとき実行
helm uninstall <RELEASE_NAME> -n <NAMESPACE>
5. Kubectl で操作する
kubectl
kubectl get xxx -n <NAMESPACE>
kubernetesのコマンドで、K8s内の情報を取得
他にkubectl exec
コマンドでpodの中に入ったり、kubectl logs
でログを見たりできる。
イメージ図
完全に理解した
ちなみに「完全に理解した」と言ってくる人の信用度は低いです。
おそらく全てを学んではいないでしょう。
Linuxの生みの親は、Linuxを「チョットデキル」。
何もわからない
「完全に理解した」と大きく書いていますが、実際は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からチェックしてください。
個人的には、ともにクラウドを極める、クラウドエンジニア が来てくれると嬉しいです!
参考資料