- Authors
- Name
- 1. Helmとは?
- 2. Chartディレクトリ構造
- 3. values.yaml設計パターン
- 4. テンプレートの作成
- 5. Helm Hooks
- 6. CI/CDパイプライン連携
- 7. Chartテスト
- 8. クイズ

1. Helmとは?
Helmは、Kubernetesのパッケージマネージャーです。複雑なKubernetesリソースを一つのChartとしてパッケージングし、インストール、アップグレード、ロールバックを簡単に管理できます。
なぜHelmなのか?
- 繰り返しのYAML記述を排除
- 環境別の設定分離(dev/staging/production)
- バージョン管理とロールバック
- 依存関係の管理
2. Chartディレクトリ構造
mychart/
├── Chart.yaml # Chartメタデータ
├── Chart.lock # 依存関係ロックファイル
├── values.yaml # デフォルト設定値
├── values-prod.yaml # プロダクションオーバーライド
├── templates/ # Kubernetesマニフェストテンプレート
│ ├── _helpers.tpl # 共通ヘルパー関数
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── hpa.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── serviceaccount.yaml
│ ├── NOTES.txt # インストール後の案内メッセージ
│ └── tests/
│ └── test-connection.yaml
├── charts/ # 依存Chart
└── .helmignore # パッケージング除外ファイル
Chart.yamlの作成
apiVersion: v2
name: my-web-app
description: A production-ready web application
type: application
version: 1.2.0 # Chartバージョン(SemVer)
appVersion: '3.1.0' # アプリバージョン
maintainers:
- name: youngjukim
email: fjvbn2003@gmail.com
dependencies:
- name: postgresql
version: '12.x.x'
repository: 'https://charts.bitnami.com/bitnami'
condition: postgresql.enabled
- name: redis
version: '17.x.x'
repository: 'https://charts.bitnami.com/bitnami'
condition: redis.enabled
3. values.yaml設計パターン
# values.yaml - デフォルト設定
replicaCount: 2
image:
repository: myregistry.io/my-web-app
tag: '' # Chart appVersionを使用
pullPolicy: IfNotPresent
service:
type: ClusterIP
port: 80
targetPort: 8080
ingress:
enabled: true
className: nginx
annotations:
cert-manager.io/cluster-issuer: letsencrypt-prod
hosts:
- host: app.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: app-tls
hosts:
- app.example.com
resources:
limits:
cpu: 500m
memory: 256Mi
requests:
cpu: 100m
memory: 128Mi
autoscaling:
enabled: false
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
postgresql:
enabled: true
auth:
database: myapp
username: appuser
redis:
enabled: false
4. テンプレートの作成
_helpers.tpl - 共通ヘルパー
{{- define "mychart.name" -}}
{{- default .Chart.Name .Values.nameOverride | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- define "mychart.fullname" -}}
{{- if .Values.fullnameOverride }}
{{- .Values.fullnameOverride | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- $name := default .Chart.Name .Values.nameOverride }}
{{- if contains $name .Release.Name }}
{{- .Release.Name | trunc 63 | trimSuffix "-" }}
{{- else }}
{{- printf "%s-%s" .Release.Name $name | trunc 63 | trimSuffix "-" }}
{{- end }}
{{- end }}
{{- end }}
{{- define "mychart.labels" -}}
helm.sh/chart: {{ include "mychart.chart" . }}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
app.kubernetes.io/version: {{ .Chart.AppVersion | quote }}
app.kubernetes.io/managed-by: {{ .Release.Service }}
{{- end }}
{{- define "mychart.selectorLabels" -}}
app.kubernetes.io/name: {{ include "mychart.name" . }}
app.kubernetes.io/instance: {{ .Release.Name }}
{{- end }}
deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "mychart.fullname" . }}
labels:
{{- include "mychart.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "mychart.selectorLabels" . | nindent 6 }}
template:
metadata:
annotations:
checksum/config: {{ include (print $.Template.BasePath "/configmap.yaml") . | sha256sum }}
labels:
{{- include "mychart.selectorLabels" . | nindent 8 }}
spec:
containers:
- name: {{ .Chart.Name }}
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
imagePullPolicy: {{ .Values.image.pullPolicy }}
ports:
- name: http
containerPort: {{ .Values.service.targetPort }}
protocol: TCP
livenessProbe:
httpGet:
path: /healthz
port: http
initialDelaySeconds: 15
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
resources:
{{- toYaml .Values.resources | nindent 12 }}
envFrom:
- configMapRef:
name: {{ include "mychart.fullname" . }}-config
5. Helm Hooks
Hookを使用すると、リリースライフサイクルの特定の時点でタスクを実行できます:
# templates/pre-install-job.yaml
apiVersion: batch/v1
kind: Job
metadata:
name: {{ include "mychart.fullname" . }}-db-migrate
annotations:
"helm.sh/hook": pre-install,pre-upgrade
"helm.sh/hook-weight": "-5"
"helm.sh/hook-delete-policy": before-hook-creation
spec:
template:
spec:
restartPolicy: Never
containers:
- name: migrate
image: "{{ .Values.image.repository }}:{{ .Values.image.tag | default .Chart.AppVersion }}"
command: ["python", "manage.py", "migrate"]
envFrom:
- secretRef:
name: {{ include "mychart.fullname" . }}-db-secret
backoffLimit: 3
Hookの種類
| Hook | 実行タイミング |
|---|---|
| pre-install | インストール前 |
| post-install | インストール後 |
| pre-upgrade | アップグレード前 |
| post-upgrade | アップグレード後 |
| pre-rollback | ロールバック前 |
| pre-delete | 削除前 |
| test | helm test実行時 |
6. CI/CDパイプライン連携
GitHub Actions + Helm
# .github/workflows/deploy.yml
name: Deploy Helm Chart
on:
push:
branches: [main]
jobs:
deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v4
with:
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
aws-region: ap-northeast-2
- name: Update kubeconfig
run: aws eks update-kubeconfig --name my-cluster
- name: Install Helm
uses: azure/setup-helm@v3
with:
version: v3.14.0
- name: Helm lint
run: helm lint ./charts/my-web-app
- name: Helm upgrade
run: |
helm upgrade --install my-app ./charts/my-web-app \
--namespace production \
--create-namespace \
-f ./charts/my-web-app/values-prod.yaml \
--set image.tag=${{ github.sha }} \
--wait --timeout 5m
helm templateでのローカル検証
# レンダリングされたマニフェストを確認
helm template my-release ./mychart -f values-prod.yaml
# 特定の値をオーバーライド
helm template my-release ./mychart --set replicaCount=3
# kubevalで有効性を検証
helm template my-release ./mychart | kubeval --strict
7. Chartテスト
# templates/tests/test-connection.yaml
apiVersion: v1
kind: Pod
metadata:
name: "{{ include "mychart.fullname" . }}-test"
annotations:
"helm.sh/hook": test
spec:
containers:
- name: curl
image: curlimages/curl:8.5.0
command: ['curl']
args: ['{{ include "mychart.fullname" . }}:{{ .Values.service.port }}/healthz']
restartPolicy: Never
# テスト実行
helm test my-release -n production
8. クイズ
Q1: Chart.yamlのversionとappVersionの違いは?
- version: Chart自体のバージョンです。Chartの構造、テンプレート、valuesが変更されたときに上げます。SemVerに従います。
- appVersion: Chartがデプロイするアプリケーションのバージョンです。アプリコードが変更されたときに上げます。
例:Chart version 1.2.0がappVersion 3.1.0をデプロイすることがあります。
Q2: Helm Hookのhook-weightはどのような役割を果たしますか?
hook-weightは、同じタイプのhookが複数ある場合に実行順序を決定します。低い数字が先に実行されます。
例:weight -5のDBマイグレーションがweight 0のキャッシュ初期化よりも先に実行されます。
Q3: deployment.yamlのchecksum/configアノテーションの用途は?
ConfigMapが変更されるとsha256sumが変わり、Podのアノテーションが変更されます。これにより、Deploymentがローリングアップデートをトリガーします。
ConfigMapのみ変更した場合、デフォルトではPodが再起動されない問題を解決するパターンです。