
現代のソフトウェア開発は、スピード、スケーラビリティ、可観測性が求められる時代へと突入しています。これを支えるのがクラウドネイティブなアプローチであり、その中核を担うのがGoとKubernetesの組み合わせです。
この投稿では、Goで開発したWeb APIアプリケーションを、Dockerを使ってコンテナ化し、Kubernetes上にデプロイするまでの流れを、実践的な手順で詳しく解説していきます。
さらに、Helmによるデプロイの自動化、PrometheusとGrafanaを活用した可観測性の確保、そして最終的にはGKE・EKS・AKSといったパブリッククラウドへの展開までを網羅します。
開発者、SRE、DevOpsエンジニアの皆さんにとって、クラウドネイティブ時代の基盤を築く一助となれば幸いです。
📑 目次
- なぜGoとKubernetesなのか?クラウドネイティブ時代の選択
- Goアプリケーションの準備
- DockerによるGoアプリのコンテナ化
- KubernetesのYAMLマニフェストを理解する
- MinikubeまたはKindでのローカルデプロイ
- Helmを使ったデプロイの自動化
- 可観測性の確保:Prometheus・Grafana・Loki
- GKE・EKS・AKSへのクラウド展開
- 持続可能なクラウドネイティブアーキテクチャとは
1. なぜGoとKubernetesなのか?クラウドネイティブ時代の選択
モノリシックなアーキテクチャでは、拡張性や柔軟性に限界があります。そうした背景から、マイクロサービス化とクラウドネイティブな設計へのシフトが進んでいます。
Goはシンプルで高速、コンパイル後は単一バイナリで実行できるため、コンテナとの相性が非常に良い言語です。一方、Kubernetesは、複数のコンテナを自動的に管理・スケーリング・監視できるコンテナオーケストレーションプラットフォームです。
この強力な組み合わせは、Google、Dropbox、Uberといった大規模サービスの基盤でも採用されており、今後のインフラのスタンダードになるといっても過言ではありません。
このシリーズでは、Goアプリケーションをコンテナ化し、Kubernetesにデプロイし、クラウド環境にまでスケールさせていく実践的なアプローチを段階的に解説します。

2. Goアプリケーションの準備
Goは、静的型付け・コンパイル型の言語であり、依存関係を含んだ自己完結型の単一バイナリを生成できるため、Dockerコンテナとの親和性が非常に高いという特徴を持っています。
Kubernetes上での運用を前提としたアプリケーション開発では、コードの構造をモジュール化し、設定を外部化することが重要です。ここでは、簡単なRESTful API(/ping
エンドポイント)を題材に、Goアプリの構成を解説します。
📁 推奨ディレクトリ構成
以下は、マイクロサービスとしてGoアプリケーションを構築する際の一例となるプロジェクト構成です:
go-k8s-app/
├── go.mod
├── go.sum
├── main.go
├── handler/
│ └── ping.go
├── config/
│ └── config.go
└── Dockerfile
go.mod
はGoモジュールの依存関係を管理するファイルであり、handler
ディレクトリには各エンドポイントの処理ロジックをまとめることで、コードの可読性と保守性が向上します。
📌 REST APIの最小サンプル
以下は、/ping
へのGETリクエストに対して”pong”と応答する最小構成のAPIサーバーコードです:
package main
import (
"log"
"net/http"
"yourapp/handler"
)
func main() {
http.HandleFunc("/ping", handler.Ping)
log.Println("Listening on port 8080...")
log.Fatal(http.ListenAndServe(":8080", nil))
}
次に、実際のハンドラ関数は以下のようになります(handler/ping.go
):
package handler
import (
"encoding/json"
"net/http"
)
func Ping(w http.ResponseWriter, r *http.Request) {
response := map[string]string{"message": "pong"}
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(response)
}
このようなヘルスチェック用のエンドポイントは、後述するKubernetesのlivenessProbe
やreadinessProbe
にも活用されます。
🛠️ 依存関係のインストールと起動
Goモジュールとアプリケーションを起動するためのコマンドは以下の通りです:
go mod tidy
go run main.go
ローカルホストで起動したアプリにアクセスするには、http://localhost:8080/ping
にブラウザまたはcurlでリクエストを送ってください。
{
"message": "pong"
}
これで、Kubernetes環境で動作させるためのGoアプリケーションの準備が整いました。次はこのアプリをDockerコンテナに変換するステップに進みましょう。
3. DockerによるGoアプリのコンテナ化
Goアプリケーションのローカル実行が確認できたら、次は本番環境を見据えてDockerコンテナとしてパッケージングしましょう。コンテナ化することで、どの環境でも同一の実行環境を再現でき、Kubernetesへのデプロイも可能になります。
Goの大きな特徴のひとつは、コンパイル後に単一のバイナリファイルを生成できることです。これにより、非常に軽量なコンテナイメージを構築することができます。ここでは、マルチステージビルドを活用したDockerfileを紹介します。
🧱 マルチステージDockerfileの例
以下は、Goアプリケーションの最適化されたDockerfileの例です。
# ビルドステージ
FROM golang:1.20-alpine AS builder
WORKDIR /app
COPY go.mod ./
COPY go.sum ./
RUN go mod download
COPY . ./
RUN go build -o app .
# 実行ステージ
FROM alpine:latest
WORKDIR /root/
COPY --from=builder /app/app .
EXPOSE 8080
CMD ["./app"]
ポイント:
- 最初のステージではAlpineベースのGoイメージを使用してバイナリをビルドします。
- 最終ステージでは、ビルドしたバイナリのみを含むAlpineイメージを使用し、10MB未満の軽量なイメージを実現します。
- マルチステージにより、セキュリティリスクのある不要な依存パッケージを含めずに済みます。
🐳 Dockerビルドと実行
以下のコマンドでDockerイメージをビルドし、コンテナを起動できます。
docker build -t go-k8s-app .
docker run -p 8080:8080 go-k8s-app
コンテナが起動したら、http://localhost:8080/ping
にアクセスして応答を確認できます。
{
"message": "pong"
}
🔎 なぜマルチステージビルドが重要か
シンプルなDockerfileでも動作しますが、開発環境と本番環境のビルドアーティファクトを分離することで、次のようなメリットがあります:
- 最小限の依存性によるセキュリティ向上
- ビルドキャッシュの活用による高速化
- より軽量なデプロイと起動の高速化
このように、コンテナ化はKubernetesへのステップとしてだけでなく、運用・保守の観点からも重要な意味を持ちます。
次は、このコンテナ化したアプリケーションをKubernetes上にデプロイするためのYAMLファイルについて解説していきます。
4. KubernetesのYAMLマニフェストを理解する
GoアプリケーションをDockerでコンテナ化したら、いよいよKubernetes上にデプロイする準備に入ります。Kubernetesでは、リソースの状態を「宣言的」に定義するために、YAMLマニフェストを使用します。
ここでは、基本的な構成要素である Deployment、Service、ConfigMap を例に、どのようにYAMLで定義するかを見ていきましょう。

📦 主なKubernetesリソース
リソース | 概要 |
---|---|
Deployment | Podのレプリカ数、更新戦略などを管理 |
Service | Podへのアクセスを提供(クラスタ内外から) |
ConfigMap | アプリ設定などの環境変数を外部化 |
📄 Deploymentの例
以下は、2つのレプリカでGoアプリを稼働させるDeploymentの例です:
apiVersion: apps/v1
kind: Deployment
metadata:
name: go-k8s-app
spec:
replicas: 2
selector:
matchLabels:
app: go-k8s-app
template:
metadata:
labels:
app: go-k8s-app
spec:
containers:
- name: go-app
image: go-k8s-app:latest
ports:
- containerPort: 8080
resources:
limits:
memory: "128Mi"
cpu: "500m"
requests:
memory: "64Mi"
cpu: "250m"
livenessProbe:
httpGet:
path: /ping
port: 8080
initialDelaySeconds: 5
periodSeconds: 10
補足:
replicas
でPodの数(=冗長性)を設定resources
でCPU・メモリのリソース制限を定義livenessProbe
でヘルスチェックを自動化
🔌 Serviceの例
次に、外部からアクセスできるようにするService定義です:
apiVersion: v1
kind: Service
metadata:
name: go-k8s-service
spec:
selector:
app: go-k8s-app
ports:
- protocol: TCP
port: 80
targetPort: 8080
type: NodePort
NodePort
タイプを使用すると、クラスタ外からも指定されたポートでアクセス可能になります。クラウド環境ではLoadBalancer
を使うことが多いです。
🧾 ConfigMapの例
アプリの設定情報をConfigMapで外部化する例です:
apiVersion: v1
kind: ConfigMap
metadata:
name: app-config
data:
APP_MODE: "production"
LOG_LEVEL: "info"
このConfigMapはDeploymentのenv
セクションで参照することで、設定のコード分離が可能になります。
これらのYAMLファイルを使って、次章ではMinikubeやKindを使ったローカルクラスタへのデプロイを行います。
5. MinikubeまたはKindでのローカルデプロイ
KubernetesのYAMLマニフェストが準備できたら、まずはローカル環境でのデプロイを試してみましょう。これにより、本番クラスタに反映する前に動作確認が可能になります。
ローカル環境でよく使われるKubernetesツールには、MinikubeとKind(Kubernetes IN Docker)があります。ここではMinikubeを使った流れを中心に説明しますが、Kindでもほぼ同じ手順で対応可能です。
🔧 Minikubeのインストールと起動
macOS環境の場合、以下のコマンドでMinikubeをインストールして起動できます:
brew install minikube
minikube start --driver=docker
起動が完了すると、ローカル上にKubernetesクラスタが構築され、kubectl
コマンドで制御できるようになります。
📂 YAMLファイルの適用
準備したYAMLファイルを以下のように適用します:
kubectl apply -f configmap.yaml
kubectl apply -f deployment.yaml
kubectl apply -f service.yaml
すべてのリソースが正しく作成されたかどうかは、次のコマンドで確認できます:
kubectl get all
🌐 サービスへのアクセス
NodePort
タイプのサービスは、以下のコマンドで自動的にアクセスURLを取得できます:
minikube service go-k8s-service --url
出力されたURL(例:http://127.0.0.1:30080
)にアクセスし、/ping
エンドポイントが動作しているか確認してみましょう。
📋 Podの状態確認とログ出力
実行中のPodのログをリアルタイムで確認するには:
kubectl logs -f deployment/go-k8s-app
複数のPodがある場合は、以下のコマンドで名前を確認した上で個別にログを見ることもできます:
kubectl get pods
📁 複数YAMLの一括適用
YAMLファイルを一つのフォルダにまとめておけば、次のように一括で適用できます:
kubectl apply -f ./k8s/
これで、GoアプリケーションがローカルのKubernetesクラスタで正常に稼働している状態が確認できました。
次章では、Helmを使ってこのデプロイ作業をさらに効率的に自動化する方法を学びましょう。
6. Helmを使ったデプロイの自動化
KubernetesではYAMLファイルでリソースを定義できますが、サービスが複雑になるにつれて管理が煩雑になります。Helmを使えば、テンプレート化とパラメータ管理を行うことで、再利用可能でメンテナンスしやすいデプロイメントが可能になります。

Helmは「Kubernetesのパッケージマネージャー」とも呼ばれ、Helm Chartを使ってアプリケーションを定義・管理・バージョン管理できます。
📦 Helm Chartとは?
Helm Chartは、複数のKubernetesリソース(Deployment, Service, ConfigMapなど)を一つの単位にまとめたテンプレートパッケージです。一般的な構成は以下の通りです:
go-k8s-chart/
├── Chart.yaml # チャートのメタデータ
├── values.yaml # 設定値(環境別に差し替え可能)
├── templates/ # YAMLテンプレート(Goテンプレート構文)
│ ├── deployment.yaml
│ ├── service.yaml
│ └── _helpers.tpl
🛠️ Helmのインストールとチャート作成
macOSではHomebrewを使ってインストールできます:
brew install helm
helm create go-k8s-chart
helm create
を実行すると、サンプルテンプレートが含まれたチャートが自動生成されます。
📄 values.yamlの設定例
以下は、Goアプリケーション用の基本的な設定例です:
replicaCount: 2
image:
repository: go-k8s-app
tag: latest
pullPolicy: IfNotPresent
service:
type: NodePort
port: 80
resources:
limits:
cpu: 500m
memory: 128Mi
requests:
cpu: 250m
memory: 64Mi
これらの値はテンプレート内で{{ .Values.image.repository }}
のように動的に参照され、環境ごとに柔軟な構成が可能です。
🚀 Helmによるデプロイとアップグレード
以下のコマンドでアプリケーションをデプロイします:
helm install go-app ./go-k8s-chart
values.yaml
を変更後に設定を反映させるには、次のようにアップグレードします:
helm upgrade go-app ./go-k8s-chart
不要になった場合はアンインストールも可能です:
helm uninstall go-app
🌍 Helm活用のメリット
- 再利用性: テンプレート化により複数環境での再利用が容易
- 管理性: バージョン管理やロールバックが可能
- GitOps対応: ArgoCDやFluxなどのCI/CDツールと統合しやすい
Helmを使うことで、手動のYAML管理から解放され、スピードと品質を両立した運用が実現できます。
次章では、クラスタ内でのアプリの動作を継続的に監視するための「可観測性」について詳しく解説します。
7. 可観測性の確保:Prometheus・Grafana・Loki
本番環境で安定した運用を行うには、「可観測性(Observability)」が不可欠です。これは、システムがどのように動いているのかを外部から理解し、問題を迅速に発見・対応するための仕組みです。
Kubernetesでは、プローブによるヘルスチェック機能に加え、PrometheusとGrafanaによるメトリクス監視、Lokiによるログ収集が代表的な可観測性スタックとして広く使われています。
🩺 Liveness / Readiness プローブ
プローブはPodの状態を監視し、必要に応じて再起動やトラフィック制御を行うための設定です:
- Liveness Probe: アプリが「生きているか」を確認し、失敗時には自動再起動
- Readiness Probe: アプリが「リクエストを受け付けられる状態か」を確認
以下はReadiness Probeの追加例です(Deployment内):
readinessProbe:
httpGet:
path: /ping
port: 8080
initialDelaySeconds: 2
periodSeconds: 5
📊 PrometheusとGrafanaによるメトリクス監視
PrometheusはKubernetesクラスタの状態やリソース使用量を収集・蓄積するツールで、Grafanaはそのデータを視覚化するダッシュボードツールです。
Helmを使ってPrometheusとGrafanaを一括導入するには:
helm repo add prometheus-community https://prometheus-community.github.io/helm-charts
helm install k8s-monitor prometheus-community/kube-prometheus-stack
GrafanaのUIにアクセスするにはポートフォワードを利用します:
kubectl port-forward svc/k8s-monitor-grafana 3000:80
ブラウザでhttp://localhost:3000
にアクセス(初期ユーザー名・パスワードはadmin/admin)すると、ダッシュボードでリソース状況を確認できます。
📝 Lokiを使ったログ収集
LokiはGrafanaと統合できるログ集約システムで、Podごとのログを一元管理し、構造化クエリで検索できます。
Lokiのインストール手順は以下の通りです:
helm repo add grafana https://grafana.github.io/helm-charts
helm install loki grafana/loki-stack
Grafanaの「データソース」からLokiを追加すれば、{app="go-k8s-app"}
のようなラベルでログ検索が可能になります。
📈 可観測性の構築がもたらす効果
- CPUやメモリの使用量を時系列で把握
- Pod単位でのレスポンスタイムやエラー率の追跡
- アラートの設定による障害の即時検知
- ログとメトリクスの相関分析による根本原因の特定
可観測性は、単なる「モニタリング」ではなく、運用の意思決定を支える情報基盤です。
次章では、これまで構築したアプリケーションをGKE・EKS・AKSといったクラウド環境へとスケールさせる方法を見ていきましょう。
8. GKE・EKS・AKSへのクラウド展開
ローカルでの動作確認が完了したら、いよいよ本番環境への展開です。Google Cloud, AWS, Azureが提供するマネージドKubernetesサービスである GKE、EKS、AKS を使うことで、高可用性・スケーラビリティ・セキュリティを確保しながら運用することが可能になります。
☁️ なぜマネージドKubernetesなのか?
各クラウドプラットフォームは、以下のような恩恵を提供します:
- コントロールプレーンの自動管理とアップグレード
- オートスケーリングと負荷分散の統合
- クラウドネイティブなモニタリング/セキュリティ
🌐 GKE(Google Kubernetes Engine)
Google Cloud CLIを使ってGKEクラスタを作成する例:
gcloud container clusters create go-app-cluster \
--zone=asia-northeast1-a \
--num-nodes=3 \
--enable-ip-alias
Workload Identityを使えば、KubernetesサービスアカウントとGoogle IAMの連携が可能になります。LoadBalancer
タイプのServiceを使用すれば、外部IPが自動的に付与されます。
🛡️ EKS(Elastic Kubernetes Service / AWS)
eksctl
コマンドを使って簡単にEKSクラスタを立ち上げることができます:
eksctl create cluster \
--name go-app-cluster \
--region ap-northeast-1 \
--nodes 3
EKSでは、aws-auth
ConfigMapによってIAMユーザー/ロールとRBACのマッピングが必要です。ALB Ingress ControllerやExternal DNSの設定もよく使われます。
📘 AKS(Azure Kubernetes Service)
Azure CLIを使用したAKSの作成例:
az aks create \
--resource-group myResourceGroup \
--name go-app-cluster \
--node-count 3 \
--enable-addons monitoring \
--generate-ssh-keys
AKSはAzure ADと連携したRBACが可能で、Azure MonitorやLog Analyticsと自動統合されます。
📌 クラウド展開時の主な注意点
項目 | 考慮点 |
---|---|
認証・認可 | IAMやRBAC、OIDC連携などクラウドごとのセキュリティ設定 |
ノード構成 | オートスケーリング、スポットインスタンスの活用 |
ネットワーク | VPC設計、ロードバランサー、Ingress Controller |
モニタリング | プラットフォーム統合の可観測性ツールとの連携 |
クラウド環境でKubernetesを使う際には、単なるYAMLの適用にとどまらず、インフラ設計・セキュリティ・運用戦略を包括的に考える必要があります。
次章では、本シリーズのまとめとして、拡張性と持続可能性を備えたクラウドネイティブアーキテクチャの考え方を整理していきます。
9. 持続可能なクラウドネイティブアーキテクチャとは
クラウドネイティブの実践は、単にKubernetesを導入し、Goでマイクロサービスを書くことにとどまりません。それは、変化に強く、スケーラブルで、メンテナンスしやすいシステムを設計・運用するという思想に根ざしています。
本シリーズでは、以下のステップに沿って、Goアプリケーションをクラウドネイティブな形で構築してきました:
- GoによるREST APIの開発
- Dockerを使ったコンテナ化
- KubernetesへのデプロイとHelmによる自動化
- Prometheus・Grafana・Lokiによる可観測性の構築
- GKE・EKS・AKSなどクラウド環境への拡張
🧭 技術を超えた学び
- 小さく始めて、着実にスケールする: 単純なユースケースから始めて、段階的にサービスを分離・拡張していく
- Infrastructure as Code(IaC): 手動作業を減らし、すべてをコード化することで品質と再現性を高める
- 見える化=信頼: メトリクス・ログ・アラートは運用の信頼性を支える柱
- 疎結合: コンフィグ・サービス・リソースを疎結合に保ち、環境変更に強い設計を目指す
これらの原則は、どのような技術スタックでも通用する持続可能なアーキテクチャの本質です。
道具は進化し続けます。Goの後継言語が出てくるかもしれませんし、Kubernetesの上に新しい抽象化レイヤーが加わるかもしれません。しかし、「スピードと信頼性の両立」という目標は変わりません。
今、あなたのアプリケーションは、ただの機能提供を超えて、「運用文化」の一部となる準備ができています。