Docker & Kubernetes完全攻略 第10編:HelmとCI/CDパイプライン
Docker & Kubernetes Complete Guide Part 10: Helm and CI/CD Pipeline
序論:効率的なKubernetesアプリケーションデプロイ
これまでKubernetesのさまざまなリソースと設定方法を学んできました。しかし、実際のプロダクション環境では、数十、数百のYAMLファイルを管理しなければならず、環境ごとに異なる設定を適用する必要があります。このような複雑さを解決するためにHelmというパッケージマネージャーが登場しました。
また、現代のソフトウェア開発では、コード変更からプロダクションデプロイまでのプロセスを自動化するCI/CDパイプラインが必須です。この編では、Helmの活用法とGitOpsベースのCI/CDパイプライン構築方法を詳しく見ていきます。
1. Helmとは?
1.1 Helmの概要
HelmはKubernetesのパッケージマネージャーです。Linuxのapt、yumやmacOSのHomebrewのように、HelmはKubernetesアプリケーションを簡単にインストール、アップグレード、管理できるようにしてくれます。
Helmのコア概念:
- Chart:Kubernetesアプリケーションを定義するファイルの集まり
- Release:クラスターにインストールされたChartのインスタンス
- Repository:Chartを保存し共有するリポジトリ
- Values:Chartのデフォルト設定をカスタマイズする値
1.2 Helmを使用する理由
| 問題点 | Helmの解決策 |
|---|---|
| 多数のYAMLファイル管理 | 単一のChartにパッケージング |
| 環境別設定の違い | values.yamlでオーバーライド |
| デプロイ履歴管理 | リリースバージョン管理とロールバック |
| 複雑な依存関係 | Chart依存関係管理 |
| 再利用性の欠如 | テンプレートと共有可能なChart |
2. Helmのインストールと基本的な使い方
2.1 Helmのインストール
# macOS
brew install helm
# Linux(スクリプト)
curl https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3 | bash
# Windows(Chocolatey)
choco install kubernetes-helm
# インストール確認
helm version
2.2 リポジトリ管理
# 公式Helm Chartリポジトリの追加
helm repo add stable https://charts.helm.sh/stable
helm repo add bitnami https://charts.bitnami.com/bitnami
# リポジトリリストの確認
helm repo list
# リポジトリの更新
helm repo update
# Chartの検索
helm search repo nginx
helm search repo mysql
# Hubで検索
helm search hub prometheus
2.3 基本コマンド
# Chartのインストール
helm install my-release bitnami/nginx
# 特定のネームスペースにインストール
helm install my-release bitnami/nginx -n my-namespace --create-namespace
# valuesファイルでインストール
helm install my-release bitnami/nginx -f custom-values.yaml
# コマンドラインで値を指定
helm install my-release bitnami/nginx --set replicaCount=3
# リリースリストの確認
helm list
helm list -A # すべてのネームスペース
# リリース状態の確認
helm status my-release
# リリースのアップグレード
helm upgrade my-release bitnami/nginx --set replicaCount=5
# リリースのロールバック
helm rollback my-release 1 # リビジョン1にロールバック
# リリース履歴の確認
helm history my-release
# リリースの削除
helm uninstall my-release
3. Chart構造の理解
3.1 Chartディレクトリ構造
my-chart/
├── Chart.yaml # Chartメタデータ
├── values.yaml # デフォルト設定値
├── charts/ # 依存関係Chart
├── templates/ # Kubernetesマニフェストテンプレート
│ ├── deployment.yaml
│ ├── service.yaml
│ ├── ingress.yaml
│ ├── configmap.yaml
│ ├── secret.yaml
│ ├── _helpers.tpl # テンプレートヘルパー関数
│ ├── NOTES.txt # インストール後に表示されるメッセージ
│ └── tests/ # テストファイル
│ └── test-connection.yaml
├── .helmignore # パッケージング時に除外するファイル
└── README.md # ドキュメント
3.2 Chart.yaml
# Chart.yaml
apiVersion: v2
name: my-app
description: A Helm chart for my application
type: application
version: 1.0.0 # Chartバージョン
appVersion: "2.0.0" # アプリケーションバージョン
# 依存関係の定義
dependencies:
- name: mysql
version: "9.x.x"
repository: https://charts.bitnami.com/bitnami
condition: mysql.enabled
- name: redis
version: "17.x.x"
repository: https://charts.bitnami.com/bitnami
condition: redis.enabled
# キーワードとメタデータ
keywords:
- web
- application
home: https://example.com
sources:
- https://github.com/example/my-app
maintainers:
- name: DevOps Team
email: devops@example.com
3.3 values.yaml
# values.yaml
# デフォルト設定値の定義
# アプリケーション設定
replicaCount: 2
image:
repository: myregistry/my-app
tag: "latest"
pullPolicy: IfNotPresent
imagePullSecrets: []
nameOverride: ""
fullnameOverride: ""
# サービス設定
service:
type: ClusterIP
port: 80
targetPort: 8080
# Ingress設定
ingress:
enabled: true
className: nginx
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
hosts:
- host: myapp.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: myapp-tls
hosts:
- myapp.example.com
# リソース制限
resources:
limits:
cpu: 500m
memory: 512Mi
requests:
cpu: 100m
memory: 128Mi
# オートスケーリング
autoscaling:
enabled: true
minReplicas: 2
maxReplicas: 10
targetCPUUtilizationPercentage: 80
# 環境変数
env:
- name: APP_ENV
value: production
- name: LOG_LEVEL
value: info
# 依存関係の有効化
mysql:
enabled: true
auth:
database: myapp
username: appuser
redis:
enabled: false
3.4 テンプレート作成
templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "my-app.fullname" . }}
labels:
{{- include "my-app.labels" . | nindent 4 }}
spec:
{{- if not .Values.autoscaling.enabled }}
replicas: {{ .Values.replicaCount }}
{{- end }}
selector:
matchLabels:
{{- include "my-app.selectorLabels" . | nindent 6 }}
template:
metadata:
labels:
{{- include "my-app.selectorLabels" . | nindent 8 }}
spec:
{{- with .Values.imagePullSecrets }}
imagePullSecrets:
{{- toYaml . | nindent 8 }}
{{- end }}
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
{{- if .Values.env }}
env:
{{- toYaml .Values.env | nindent 12 }}
{{- end }}
resources:
{{- toYaml .Values.resources | nindent 12 }}
livenessProbe:
httpGet:
path: /health
port: http
initialDelaySeconds: 30
periodSeconds: 10
readinessProbe:
httpGet:
path: /ready
port: http
initialDelaySeconds: 5
periodSeconds: 5
4. values.yamlのカスタマイズ
4.1 環境別valuesファイル
# 環境別valuesファイルの構成
values/
├── values.yaml # デフォルト値
├── values-dev.yaml # 開発環境
├── values-staging.yaml # ステージング環境
└── values-prod.yaml # プロダクション環境
values-prod.yaml
# values-prod.yaml - プロダクション環境設定
replicaCount: 5
image:
tag: "1.2.3" # 特定のバージョンを固定
resources:
limits:
cpu: 1000m
memory: 1Gi
requests:
cpu: 500m
memory: 512Mi
autoscaling:
enabled: true
minReplicas: 5
maxReplicas: 20
targetCPUUtilizationPercentage: 70
ingress:
hosts:
- host: api.example.com
paths:
- path: /
pathType: Prefix
tls:
- secretName: api-prod-tls
hosts:
- api.example.com
env:
- name: APP_ENV
value: production
- name: LOG_LEVEL
value: warn
- name: DB_HOST
valueFrom:
secretKeyRef:
name: db-credentials
key: host
# 複数のvaluesファイルを組み合わせ
helm install my-app ./my-chart \
-f values.yaml \
-f values-prod.yaml \
--set image.tag=1.2.4
4.2 テンプレートレンダリングの確認
# レンダリングされたテンプレートを確認(実際のデプロイなし)
helm template my-release ./my-chart -f values-prod.yaml
# 特定のテンプレートのみ確認
helm template my-release ./my-chart -s templates/deployment.yaml
# デバッグモード
helm install my-release ./my-chart --dry-run --debug
5. 便利なHelm Charts
5.1 Prometheusスタックのインストール
# prometheus-communityリポジトリの追加
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm repo update
# kube-prometheus-stackのインストール(Prometheus + Grafana + AlertManager)
helm install prometheus prometheus-community/kube-prometheus-stack \
--namespace monitoring \
--create-namespace \
--set grafana.adminPassword=admin123
5.2 その他の便利なCharts
# Nginx Ingress Controller
helm install nginx-ingress ingress-nginx/ingress-nginx \
--namespace ingress-nginx --create-namespace
# cert-manager(TLS証明書自動化)
helm install cert-manager jetstack/cert-manager \
--namespace cert-manager --create-namespace \
--set installCRDs=true
# Redis
helm install redis bitnami/redis \
--set auth.password=mypassword
# PostgreSQL
helm install postgresql bitnami/postgresql \
--set auth.postgresPassword=mypassword
6. CI/CD概念の復習
6.1 CI/CDとは?
- CI(Continuous Integration):コード変更を頻繁に統合し、自動化されたビルドとテストを実行
- CD(Continuous Delivery):プロダクションにデプロイする準備ができた状態を常に維持
- CD(Continuous Deployment):すべての変更が自動的にプロダクションにデプロイ
6.2 従来のCI/CD vs GitOps
| 特性 | 従来のCI/CD | GitOps |
|---|---|---|
| デプロイトリガー | CIパイプラインがpush | Git変更をpull |
| 信頼の源泉 | CIサーバーの状態 | Gitリポジトリ |
| ロールバック | 再デプロイが必要 | Git revert |
| 監査追跡 | CIログ | Git履歴 |
| セキュリティ | CIにクラスターアクセス権限が必要 | クラスター内部でのみ動作 |
7. GitOps入門
7.1 GitOpsの原則
- 宣言的設定:すべてのインフラとアプリケーション状態を宣言的に定義
- バージョン管理:Gitを唯一の信頼の源泉として使用
- 自動同期:承認された変更は自動的にクラスターに適用
- 継続的調整:実際の状態と望ましい状態の差異を継続的に検知し修正
7.2 ArgoCD
ArgoCDは最も広く使われているGitOpsツールです。
# ArgoCDのインストール
kubectl create namespace argocd
kubectl apply -n argocd -f https://raw.githubusercontent.com/argoproj/argo-cd/stable/manifests/install.yaml
# ArgoCD CLIのインストール(macOS)
brew install argocd
# 初期adminパスワードの確認
kubectl -n argocd get secret argocd-initial-admin-secret -o jsonpath="{.data.password}" | base64 -d
# ポートフォワーディングで接続
kubectl port-forward svc/argocd-server -n argocd 8080:443
ArgoCD Applicationの定義
# argocd-application.yaml
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: my-app
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/myorg/my-app-config.git
targetRevision: main
path: kubernetes/overlays/production
destination:
server: https://kubernetes.default.svc
namespace: production
syncPolicy:
automated:
prune: true # 削除されたリソースの自動クリーンアップ
selfHeal: true # 手動変更の自動復旧
syncOptions:
- CreateNamespace=true
8. GitHub ActionsでK8sデプロイ自動化
8.1 GitHub Actionsワークフロー基本構造
# .github/workflows/ci-cd.yaml
name: CI/CD Pipeline
on:
push:
branches: [main, develop]
pull_request:
branches: [main]
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
# 1. テストとビルド
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: '20'
cache: 'npm'
- name: Install dependencies
run: npm ci
- name: Run tests
run: npm test
- name: Run linting
run: npm run lint
# 2. Dockerイメージビルドとプッシュ
build:
needs: test
runs-on: ubuntu-latest
outputs:
image-tag: ${{ steps.meta.outputs.tags }}
steps:
- uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=sha,prefix=
type=ref,event=branch
type=semver,pattern={{version}}
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
# 3. Kubernetesデプロイ
deploy:
needs: build
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
environment: production
steps:
- uses: actions/checkout@v4
- name: Set up kubectl
uses: azure/setup-kubectl@v3
with:
version: 'latest'
- name: Configure kubeconfig
run: |
mkdir -p $HOME/.kube
echo "${{ secrets.KUBECONFIG }}" | base64 -d > $HOME/.kube/config
chmod 600 $HOME/.kube/config
- name: Set up Helm
uses: azure/setup-helm@v3
with:
version: 'latest'
- name: Deploy with Helm
run: |
helm upgrade --install my-app ./charts/my-app \
--namespace production \
--create-namespace \
--set image.tag=${{ github.sha }} \
--set image.repository=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} \
--wait \
--timeout 5m
- name: Verify deployment
run: |
kubectl rollout status deployment/my-app -n production
kubectl get pods -n production -l app.kubernetes.io/name=my-app
9. 結論とシリーズのまとめ
この第10編では、Kubernetesアプリケーションデプロイを効率化するHelmと、自動化されたCI/CDパイプラインについて学びました:
- Helm:Kubernetesパッケージマネージャーとして、複雑なアプリケーションデプロイを簡素化
- Chart構造:テンプレート、values、ヘルパー関数を活用した再利用可能なパッケージ
- GitOps:Gitを信頼の源泉とする現代的なデプロイ方式
- ArgoCD/Flux:代表的なGitOpsツール
- GitHub Actions:完全なCI/CDパイプラインの構築
Docker & Kubernetes完全攻略シリーズのまとめ
これまで10編にわたって、DockerとKubernetesのコア概念と実践的な活用法を扱ってきました:
- 第1編:Docker基礎とコンテナの概念
- 第2編:DockerイメージとDockerfile
- 第3編:Docker Composeでマルチコンテナ管理
- 第4編:Kubernetes基礎とアーキテクチャ
- 第5編:Pod、Deployment、Service
- 第6編:Volumeと永続性
- 第7編:リソース管理とスケーリング
- 第8編:ネットワーキングとService Mesh
- 第9編:ConfigMap、Secret、Ingress
- 第10編:HelmとCI/CDパイプライン
このシリーズを通じて、コンテナ技術の基礎からプロダクションレベルのKubernetes運用まで、全般的な知識を習得していただけたことを願っています。コンテナとオーケストレーション技術は継続的に発展していますので、公式ドキュメントとコミュニティを通じて最新の動向を把握し続けてください。
実践と経験が最良の先生です。学んだ内容を実際のプロジェクトに適用してみてください!