序論:効率的な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の原則

  1. 宣言的設定:すべてのインフラとアプリケーション状態を宣言的に定義
  2. バージョン管理:Gitを唯一の信頼の源泉として使用
  3. 自動同期:承認された変更は自動的にクラスターに適用
  4. 継続的調整:実際の状態と望ましい状態の差異を継続的に検知し修正

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. 第1編:Docker基礎とコンテナの概念
  2. 第2編:DockerイメージとDockerfile
  3. 第3編:Docker Composeでマルチコンテナ管理
  4. 第4編:Kubernetes基礎とアーキテクチャ
  5. 第5編:Pod、Deployment、Service
  6. 第6編:Volumeと永続性
  7. 第7編:リソース管理とスケーリング
  8. 第8編:ネットワーキングとService Mesh
  9. 第9編:ConfigMap、Secret、Ingress
  10. 第10編:HelmとCI/CDパイプライン

このシリーズを通じて、コンテナ技術の基礎からプロダクションレベルのKubernetes運用まで、全般的な知識を習得していただけたことを願っています。コンテナとオーケストレーション技術は継続的に発展していますので、公式ドキュメントとコミュニティを通じて最新の動向を把握し続けてください。

実践と経験が最良の先生です。学んだ内容を実際のプロジェクトに適用してみてください!