🎖️

Go言語で学ぶ Webアプリケーション開発5:[Kubernetesを活用したデプロイ & 負荷テスト実用編]

2025/03/05に公開

はじめに

前回の記事では、Herokuへの簡単なデプロイ方法と 負荷対策(データベース最適化、キャッシュ、非同期処理、ページネーション)を解説しました。
今回は、より高度な運用手法としてKubernetes(K8s)を活用したデプロイ方法とより具体的な負荷テストの実施方法について解説します。

対象読者

  • Goで開発したWebアプリをKubernetes上にデプロイしたい方
  • 負荷テストを実施し、パフォーマンスを計測 & 最適化したい方

目次

  1. Kubernetesを活用したデプロイ
    • Kubernetesの基本概念
    • Kubernetesクラスターの構築(Minikubeを使用)
    • KubernetesへのGoアプリのデプロイ
  2. 負荷テストの実施
    • 負荷テストの目的
    • k6を使った負荷テスト
    • 負荷テストの結果分析と最適化

1. Kubernetesを活用したデプロイ

1.1 Kubernetesの基本概念

Kubernetes(K8s) は、コンテナ化されたアプリケーションを管理・運用するためのオーケストレーションツールです。

  • 自動スケーリング:負荷に応じてコンテナを増減
  • サービスディスカバリ & ロードバランシング:複数のコンテナにトラフィックを分散
  • 自己回復機能:クラッシュしたコンテナを自動で再起動

1.2 Kubernetesクラスターの構築(Minikubeを使用)

まずは、ローカル環境でKubernetesクラスターを構築するためにMinikubeを使用します。

Minikubeのインストール

# Minikubeをインストール
brew install minikube

# Minikubeを起動
minikube start

1.3 KubernetesへのGoアプリのデプロイ

Dockerイメージの作成 & Minikubeにプッシュ

docker build -t my-go-app .
minikube image load my-go-app

Kubernetesのデプロイメント定義

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: go-app
spec:
  replicas: 3
  selector:
    matchLabels:
      app: go-app
  template:
    metadata:
      labels:
        app: go-app
    spec:
      containers:
      - name: go-app
        image: my-go-app
        ports:
        - containerPort: 8080

サービスの定義(Service.yaml)

apiVersion: v1
kind: Service
metadata:
  name: go-app-service
spec:
  type: NodePort
  selector:
    app: go-app
  ports:
  - protocol: TCP
    port: 8080
    targetPort: 8080

Kubernetesにデプロイ

kubectl apply -f deployment.yaml
kubectl apply -f service.yaml

サービスの確認 & アクセス

minikube service go-app-service --url

2. 負荷テストの実施

2.1 負荷テストの目的

負荷テストを行うことで、アプリケーションの限界性能を確認し、適切なスケーリングのための指標を得ることができます。

負荷テストの目的:

  • 最大リクエスト数の測定
  • レスポンス時間の分析
  • スケールアップの必要性の判断

2.2 k6を使った負荷テスト

k6のインストール

brew install k6

負荷テストのスクリプト作成(load-test.js)

import http from 'k6/http';
import { check, sleep } from 'k6';

export let options = {
  vus: 50, // 仮想ユーザー数
  duration: '30s', // テスト時間
};

export default function () {
  let res = http.get('http://localhost:8080/api/todos');
  check(res, {
    'status was 200': (r) => r.status == 200,
    'response time < 200ms': (r) => r.timings.duration < 200,
  });
  sleep(1);
}

負荷テストの実行

k6 run load-test.js

2.3 負荷テストの結果分析と最適化

k6の出力例

checks..................: 100.00% ✓ 1500 ✗ 0
http_req_duration......: avg=120.56ms min=90ms max=250ms
http_reqs..............: 50 requests per second

このデータを元に、以下の最適化を検討します。

課題 改善策
レスポンスが遅い キャッシュ(Redis)を導入
CPU 負荷が高い Kubernetesのオートスケールを設定
リクエストが増えすぎる レートリミットを適用

Kubernetesのオートスケール設定

kubectl autoscale deployment go-app --cpu-percent=50 --min=2 --max=5

レートリミットの設定(Gin Middleware)

import "golang.org/x/time/rate"

var limiter = rate.NewLimiter(1, 5)

func rateLimitMiddleware(c *gin.Context) {
    if !limiter.Allow() {
        c.JSON(http.StatusTooManyRequests, gin.H{"error": "Too many requests"})
        c.Abort()
        return
    }
    c.Next()
}

まとめ

項目 説明
Kubernetes アプリケーションをスケーラブルにデプロイするためのオーケストレーションツール
Minikube ローカル環境でKubernetesをテストするためのツール
負荷テスト(k6) Webアプリケーションのパフォーマンスを測定するためのツール
スケーリング & 最適化 キャッシュ、オートスケール、レートリミットを活用して負荷を軽減

本記事では、Kubernetes を活用したデプロイ方法と負荷テストの具体的な実施方法について解説しました。
もう少しクラウド環境(AWS, GCP, Azure)でのデプロイとかKubernetesのCI/CDパイプライン構築もやっていこうかな

Discussion