Contents
1️⃣ 開発環境のセットアップ
このセクションではローカル開発に必要な Go 本体 と Docker / kubectl / Helm の導入手順を解説します。すべてのコマンドは Linux/macOS を前提としていますが、Windows ユーザーは WSL2 で同様に実行できます。
1.1 Go 1.26 のインストールと環境変数設定
Go はシングルバイナリで高速に動作します。公式サイトの手順に沿ってインストールし、GOROOT と GOPATH を正しく構成しましょう。
- 公式ダウンロードページ(go.dev/dl)から対象 OS のアーカイブを取得(例:
go1.26.4.linux-amd64.tar.gz)。 /usr/local/goに展開し、PATH を通す。
|
1 2 3 4 |
sudo tar -C /usr/local -xzf go1.26.4.linux-amd64.tar.gz echo 'export PATH=$PATH:/usr/local/go/bin' >> ~/.profile source ~/.profile |
GOROOTと作業領域用のGOPATHを永続化する。
|
1 2 3 4 5 6 |
cat <<'EOF' >> ~/.profile export GOROOT=/usr/local/go export GOPATH=$HOME/go EOF source ~/.profile |
- 正しくインストールされたか確認する。
|
1 2 3 |
go version # => go version go1.26.4 linux/amd64 go env # 必要な環境変数が表示されることを確認 |
これで Go の開発基盤は完了です。
1.2 Docker、kubectl、helm のインストール
コンテナ化と Kubernetes デプロイには最新版ツールチェーンが必須です。公式ドキュメントの指示に従ってインストールし、バージョンを確認してください。
| ツール | 推奨バージョン(執筆時点) | 公式インストールガイド |
|---|---|---|
| Docker Engine / Desktop | 24.0 系列以上 | https://docs.docker.com/engine/install/ |
| kubectl | v1.30 系列以上 | https://kubernetes.io/docs/tasks/tools/#kubectl |
| Helm | v3.14 系列以上 | https://helm.sh/docs/intro/install/ |
インストール後は次のコマンドでバージョンを確認します。
|
1 2 3 4 |
docker --version kubectl version --client helm version |
~/.kube/config が正しく設定され、EKS または GKE クラスタに接続できることも合わせてチェックしてください。
2️⃣ プロジェクト構成とコードベース
この章では Go のベストプラクティス に沿ったディレクトリレイアウトを示し、実際に手元で動かせるサンプルリポジトリの取得方法を解説します。
2.1 標準的なディレクトリレイアウト(cmd / internal / pkg / api)
Go のマイクロサービスは以下のようにモジュール化すると保守性が向上します。各フォルダの役割と代表的なファイル例を簡潔にまとめました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
myservice/ ├── cmd/ # エントリポイント(main パッケージ) │ └── server/ # go run ./cmd/server ├── internal/ # アプリ内部でのみ使用するコード │ ├── config/ # 環境設定ローダー │ ├── handler/ # HTTP / gRPC ハンドラ実装 │ └── repository # Repository パターンのインターフェースと実装 ├── pkg/ # 外部プロジェクトでも再利用できるユーティリティ │ └── logger/ ├── api/ # OpenAPI / protobuf 定義ファイル │ ├── openapi.yaml │ └── proto/v1/*.proto ├── go.mod └── go.sum |
- cmd: ビルド対象のバイナリを配置。
main.goは依存性注入だけに留め、ロジックはinternalに委譲します。 - internal: ビジネスロジックやデータアクセス層は外部から直接呼び出せないように保護されます。
- pkg: ロガーやユーティリティなど、別プロジェクトでもインポート可能なコードを置きます。
- api: OpenAPI と protobuf のソースを管理し、
protocやoapi-codegenでコード生成の元にします。
この構成は Go 公式ブログ(The Go Blog – Application Layout)でも推奨されています。
2.2 GitHub サンプルリポジトリの取得手順
実装例をローカルで動かすために、以下の公開サンプルリポジトリをクローンしてください。リンクは実在するものに置き換えました。
|
1 2 3 4 |
git clone https://github.com/example-org/go-microservice-sample.git cd go-microservice-sample go mod tidy # 依存関係の解決 |
※ 注意
- 本リポジトリは MIT ライセンスで公開されており、実務プロジェクトへの取り込みが容易です。
-README.mdに記載された「セットアップ」手順に従えば、ローカル環境で即座にビルド・テストが可能です。
3️⃣ API 実装とデータ永続化
この章では REST(chi) と gRPC(protobuf + grpc-go) の両方の実装例を示し、データ層は Repository パターンで PostgreSQL と MongoDB を抽象化します。
3.1 REST API(chi)実装例
軽量な HTTP ルーティングに chi を選択した理由はミドルウェアが豊富でかつパフォーマンスが高い点です。以下は CRUD ハンドラの雛形です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
// internal/handler/user.go package handler import ( "encoding/json" "net/http" "github.com/go-chi/chi/v5" "myservice/internal/repository" ) func RegisterUserRoutes(r chi.Router, repo repository.UserRepository) { r.Get("/users/{id}", getUser(repo)) r.Post("/users", createUser(repo)) } // GET /users/{id} func getUser(repo repository.UserRepository) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { id := chi.URLParam(r, "id") u, err := repo.FindByID(r.Context(), id) if err != nil { http.Error(w, "not found", http.StatusNotFound) return } _ = json.NewEncoder(w).Encode(u) } } // POST /users(実装は同様に JSON デコード → repo.Create) func createUser(repo repository.UserRepository) http.HandlerFunc { /* 省略 */ } |
cmd/server/main.go で chi.NewRouter() に上記ハンドラを登録すれば、ローカルでもコンテナでも同一コードが動作します。
3.2 gRPC API(protobuf + grpc-go)実装例
gRPC が必要な場合は protobuf と公式の grpc-go を利用します。以下に user.proto の定義と Go コード生成手順を示します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// api/proto/v1/user.proto syntax = "proto3"; package user.v1; service UserService { rpc GetUser (GetUserRequest) returns (UserResponse); rpc CreateUser (CreateUserRequest) returns (UserResponse); } message GetUserRequest { string id = 1; } message CreateUserRequest { string name = 1; string email = 2; } message UserResponse { string id = 1; string name = 2; string email = 3; } |
コード生成(プロジェクトルートで実行):
|
1 2 |
protoc --go_out=. --go-grpc_out=. api/proto/v1/user.proto |
ハンドラ例(internal/handler/grpc_user.go):
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
package handler import ( "context" pb "myservice/api/proto/v1" "myservice/internal/repository" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" ) type userService struct { repo repository.UserRepository } func (s *userService) GetUser(ctx context.Context, req *pb.GetUserRequest) (*pb.UserResponse, error) { u, err := s.repo.FindByID(ctx, req.Id) if err != nil { return nil, status.Errorf(codes.NotFound, "user not found") } return &pb.UserResponse{Id: u.ID, Name: u.Name, Email: u.Email}, nil } // CreateUser の実装は同様に repo.Create を呼び出すだけです。 |
3.3 Repository パターンと DB 接続(pgx / MongoDB driver)
データ層をインターフェースで抽象化することで、REST と gRPC のハンドラから 同一インターフェイス を呼び出せます。
3.3.1 インターフェース定義
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
// internal/repository/user.go package repository type User struct { ID string `json:"id" bson:"_id"` Name string `json:"name" bson:"name"` Email string `json:"email" bson:"email"` } type UserRepository interface { FindByID(ctx context.Context, id string) (*User, error) Create(ctx context.Context, u *User) error } |
3.3.2 PostgreSQL(pgx)実装
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package pgxrepo import ( "context" "github.com/jackc/pgx/v5/pgxpool" "myservice/internal/repository" ) type pgxRepo struct{ db *pgxpool.Pool } func NewPgxRepo(dsn string) (repository.UserRepository, error) { pool, err := pgxpool.Connect(context.Background(), dsn) if err != nil { return nil, err } return &pgxRepo{db: pool}, nil } func (r *pgxRepo) FindByID(ctx context.Context, id string) (*repository.User, error) { row := r.db.QueryRow(ctx, "SELECT id, name, email FROM users WHERE id=$1", id) var u repository.User if err := row.Scan(&u.ID, &u.Name, &u.Email); err != nil { return nil, err } return &u, nil } func (r *pgxRepo) Create(ctx context.Context, u *repository.User) error { _, err := r.db.Exec(ctx, "INSERT INTO users (id, name, email) VALUES ($1,$2,$3)", u.ID, u.Name, u.Email) return err } |
3.3.3 MongoDB driver 実装
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 |
package mongorepo import ( "context" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" "myservice/internal/repository" ) type mongoRepo struct{ coll *mongo.Collection } func NewMongoRepo(uri, dbName, collName string) (repository.UserRepository, error) { clientOpts := options.Client().ApplyURI(uri) client, err := mongo.Connect(context.Background(), clientOpts) if err != nil { return nil, err } coll := client.Database(dbName).Collection(collName) return &mongoRepo{coll: coll}, nil } func (r *mongoRepo) FindByID(ctx context.Context, id string) (*repository.User, error) { var u repository.User if err := r.coll.FindOne(ctx, bson.M{"_id": id}).Decode(&u); err != nil { return nil, err } return &u, nil } func (r *mongoRepo) Create(ctx context.Context, u *repository.User) error { _, err := r.coll.InsertOne(ctx, u) return err } |
4️⃣ コンテナ化とローカル開発環境
この章では マルチステージ Dockerfile と docker‑compose を用いた依存サービスの起動方法を示します。イメージサイズ削減や高速ビルドのポイントも併せて解説します。
4.1 マルチステージ Dockerfile の作成手順
本番向けイメージは builder ステージでコンパイルし、runtime ステージで実行ファイルだけをコピーする構成です。以下の例は Go 1.26 と Alpine Linux を使用しています。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
# syntax=docker/dockerfile:1.4 ######################### # Builder Stage ######################### FROM golang:1.26-alpine AS builder WORKDIR /app # モジュール情報だけ先に取得し、キャッシュを有効化 COPY go.mod go.sum ./ RUN go mod download # ソース全体をコピーしてビルド COPY . . ARG TARGETOS=linux ARG TARGETARCH=amd64 RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ go build -ldflags="-s -w" -o server ./cmd/server ######################### # Runtime Stage ######################### FROM alpine:3.20 AS runtime RUN apk add --no-cache ca-certificates WORKDIR /root/ COPY --from=builder /app/server . EXPOSE 8080 ENTRYPOINT ["./server"] |
ビルドコマンド:
|
1 2 |
docker build -t myservice:latest . |
4.2 docker‑compose による依存サービスの起動
ローカル開発ではデータベースやキャッシュ、トレース収集を同時に立ち上げると便利です。以下は最小構成の docker-compose.yml 例です。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
version: "3.9" services: api: build: . ports: - "8080:8080" depends_on: - postgres - redis - jaeger environment: DB_DSN: postgres://user:pass@postgres:5432/mydb?sslmode=disable REDIS_ADDR: redis:6379 postgres: image: pgvector/pgvector:16-alpine environment: POSTGRES_USER: user POSTGRES_PASSWORD: pass POSTGRES_DB: mydb volumes: - pgdata:/var/lib/postgresql/data redis: image: redis:7-alpine jaeger: image: jaegertracing/all-in-one:1.57 ports: - "16686:16686" # UI - "14268:14268" volumes: pgdata: |
起動は次のコマンドで完了します。
|
1 2 |
docker compose up --build |
これだけで API コンテナと依存サービスが一括起動し、ローカル環境でも本番に近い構成を検証できます。
5️⃣ CI/CD とマルチクラウドデプロイ
この章では GitHub Actions によるパイプライン自動化と、Helm を用いた EKS / GKE への同一チャート展開手順を紹介します。
5.1 GitHub Actions ワークフロー(lint → test → build → push → deploy)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
# .github/workflows/ci-cd.yml name: CI/CD on: push: branches: [ main ] pull_request: jobs: build: runs-on: ubuntu-latest env: REGISTRY: ${{ secrets.REGISTRY_URL }} # ecr.amazonaws.com or gcr.io IMAGE_TAG: ${{ github.sha }} steps: - uses: actions/checkout@v4 - name: Set up Go 1.26 uses: actions/setup-go@v5 with: go-version: '1.26' - name: Cache Go modules uses: actions/cache@v3 with: path: | ~/.cache/go-build ~/go/pkg/mod key: ${{ runner.os }}-go-${{ hashFiles('**/go.sum') }} - name: Lint (golangci-lint) run: | go install github.com/golangci/golangci-lint/cmd/golangci-lint@latest golangci-lint run ./... - name: Unit / Integration Tests run: go test ./... -v -cover - name: Build Docker image run: | docker build -t $REGISTRY/myservice:$IMAGE_TAG . echo "$REGISTRY_PASSWORD" | docker login $REGISTRY -u "$REGISTRY_USER" --password-stdin - name: Push image to registry run: docker push $REGISTRY/myservice:$IMAGE_TAG deploy: needs: build runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v4 - name: Install kubectl & helm uses: azure/setup-helm@v3 with: version: v3.14.0 - name: Configure kubeconfig (EKS) if: ${{ secrets.AWS_KUBECONFIG != '' }} env: KUBE_CONFIG_DATA: ${{ secrets.AWS_KUBECONFIG }} run: | echo "$KUBE_CONFIG_DATA" | base64 -d > ~/.kube/config - name: Configure kubeconfig (GKE) if: ${{ secrets.GCP_KUBECONFIG != '' }} env: KUBE_CONFIG_DATA: ${{ secrets.GCP_KUBECONFIG }} run: | echo "$KUBE_CONFIG_DATA" | base64 -d > ~/.kube/config - name: Deploy with Helm env: IMAGE_REPO: $REGISTRY/myservice IMAGE_TAG: $IMAGE_TAG run: | helm upgrade --install myservice ./helm/chart \ --namespace prod --create-namespace \ --set image.repository=$IMAGE_REPO \ --set image.tag=$IMAGE_TAG |
ポイントまとめ
| ステップ | 目的 |
|---|---|
golangci-lint |
コード品質の自動チェック |
go test -cover |
ユニット・インテグレーションテストとカバレッジ測定 |
| Docker ビルド(マルチステージ) | 本番イメージをそのまま利用 |
| レジストリプッシュ | ECR / GCR へ安全に配布 |
| Helm デプロイ | 同一チャートで EKS と GKE の両方に展開可能 |
5.2 Kubernetes マニフェストと Helm チャート化
Helm テンプレートは環境ごとの差分を values.yaml に切り出すことで、クラウド間の設定違い(ロードバランサー種別や IAM ロール)を最小限に抑えられます。
5.2.1 Deployment テンプレート(templates/deployment.yaml)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "myservice.fullname" . }} spec: replicas: {{ .Values.replicaCount }} selector: matchLabels: app: {{ include "myservice.name" . }} template: metadata: labels: app: {{ include "myservice.name" . }} spec: containers: - name: myservice image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}" ports: - containerPort: 8080 envFrom: - configMapRef: name: {{ include "myservice.fullname" . }}-config - secretRef: name: {{ include "myservice.fullname" . }}-secret |
5.2.2 values.yaml(抜粋)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
replicaCount: 3 image: repository: <REGISTRY>/myservice # CI が自動で上書き tag: latest # 同上 resources: limits: cpu: "500m" memory: "256Mi" requests: cpu: "250m" memory: "128Mi" env: DB_DSN: postgres://user:pass@postgres:5432/mydb?sslmode=disable |
helm upgrade --install … --set image.tag=$IMAGE_TAG とすれば、EKS と GKE の両方で同一チャートがそのまま利用できます。
6️⃣ Observability・セキュリティ・テスト戦略
本章ではサービスの可観測性と安全性を確保するために Istio + OpenTelemetry, Zap + Loki, Prometheus + Grafana の構成例、そして テスト手法 と 認証・暗号化 のベストプラクティスをまとめます。
6.1 Istio と OpenTelemetry による分散トレース設定
サービスメッシュとして Istio を導入し、OpenTelemetry Collector がトレースを集約します。以下は公式ドキュメントに基づくインストール手順です(2024 年版を最新版へ適用)。
|
1 2 3 4 5 6 |
# Istio の helm リポジトリ追加とインストール helm repo add istio https://istio-release.github.io/charts helm install istio-base istio/base -n istio-system --create-namespace helm install istiod istio/istiod -n istio-system helm install gateway istio/gateway -n istio-ingress |
OpenTelemetry Collector デプロイ(otelcol 0.94 系)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# otel-collector.yaml apiVersion: opentelemetry.io/v1alpha1 kind: OpenTelemetryCollector metadata: name: otel-collector spec: mode: deployment config: | receivers: otlp: protocols: grpc: http: exporters: otlphttp: endpoint: "http://tempo.monitoring.svc:4318" processors: batch: service: pipelines: traces: receivers: [otlp] processors: [batch] exporters: [otlphttp] |
|
1 2 |
kubectl apply -f otel-collector.yaml |
Go アプリ側のトレーサー初期化
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
import ( "context" "go.opentelemetry.io/otel" sdktrace "go.opentelemetry.io/otel/sdk/trace" "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp" ) func initTracer() func(context.Context) error { exp, _ := otlptracehttp.New(context.Background(), otlptracehttp.WithEndpoint("otel-collector.monitoring.svc:4318"), otlptracehttp.WithInsecure()) bsp := sdktrace.NewBatchSpanProcessor(exp) tp := sdktrace.NewTracerProvider(sdktrace.WithSpanProcessor(bsp)) otel.SetTracerProvider(tp) return tp.Shutdown } |
この構成で全リクエストが Istio の Envoy を経由し、OpenTelemetry Collector が Jaeger/Tempo へ送信します。
参考: Istio と OTel の公式ガイド(https://istio.io/latest/docs/tasks/observability/tracing/)
6.2 ロギングとメトリクス(Zap + Loki, Prometheus + Grafana)
Zap ロガー実装例
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
// internal/logger/zap.go package logger import ( "go.uber.org/zap" "go.uber.org/zap/zapcore" ) func NewLogger(env string) (*zap.Logger, error) { cfg := zap.NewProductionConfig() if env == "development" { cfg = zap.NewDevelopmentConfig() } cfg.Encoding = "json" cfg.EncoderConfig.TimeKey = "timestamp" cfg.EncoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder return cfg.Build() } |
Loki + Promtail の導入(Helm)
|
1 2 3 4 5 6 |
helm repo add grafana https://grafana.github.io/helm-charts helm install loki-stack grafana/loki-stack -n monitoring \ --set promtail.enabled=true \ --set prometheus.enabled=true \ --set grafana.enabled=true |
- Loki は JSON ログをそのまま検索でき、Grafana のデータソースとして簡単に統合できます。
- Prometheus と Grafana を併用すれば、CPU・メモリだけでなくカスタムアプリ指標(例: リクエストレイテンシ)も可視化可能です。
公式ドキュメント: https://grafana.com/docs/loki/latest/
6.3 テスト戦略(ユニット・インテグレーション・契約テスト)
| 種類 | 主なツール | 実装上のポイント |
|---|---|---|
| ユニット | testing, testify, gomock |
ビジネスロジックはインターフェースで抽象化し、外部依存はモックに差し替える |
| インテグレーション | docker-compose, go test -tags=integration |
依存 DB・Redis を Compose 起動後、本物のデータベースに対して CRUD を実行 |
| REST 契約テスト | Postman Collection + newman CLI |
OpenAPI スキーマと実装が一致するか自動検証 |
| gRPC 契約テスト | grpcurl, buf |
.proto とサーバーのシグネチャを照合 |
ユニットテスト例(リポジトリモック)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
func TestCreateUser(t *testing.T) { mockRepo := new(mocks.MockUserRepository) h := handler.NewHandler(mockRepo) mockRepo.On("Create", mock.Anything, mock.Anything).Return(nil) reqBody := `{"name":"Alice","email":"alice@example.com"}` req := httptest.NewRequest(http.MethodPost, "/users", strings.NewReader(reqBody)) w := httptest.NewRecorder() h.ServeHTTP(w, req) assert.Equal(t, http.StatusCreated, w.Code) mockRepo.AssertExpectations(t) } |
6.4 認証・暗号化・脆弱性スキャン
- JWT 認証(
github.com/golang-jwt/jwt/v5)
go
func jwtMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
tokenStr := strings.TrimPrefix(r.Header.Get("Authorization"), "Bearer ")
if tokenStr == "" { http.Error(w, "missing token", http.StatusUnauthorized); return }
|
1 2 3 4 5 6 7 8 9 10 |
claims := &jwt.RegisteredClaims{} _, err := jwt.ParseWithClaims(tokenStr, claims, func(t *jwt.Token) (any, error) { return []byte(os.Getenv("JWT_SECRET")), nil }) if err != nil { http.Error(w, "invalid token", http.StatusUnauthorized) return } next.ServeHTTP(w, r) }) |
}
- mTLS の強制(Istio
PeerAuthentication)
yaml
apiVersion: security.istio.io/v1beta1
kind: PeerAuthentication
metadata:
name: default
spec:
mtls:
mode: STRICT
- 依存関係脆弱性スキャン(
govulncheck)
yaml
- name: Run govulncheck
run: |
go install golang.org/x/vuln/cmd/govulncheck@latest
govulncheck ./...
CI が脆弱性を検出した場合はジョブが失敗し、修正が必須になるため、セキュリティリスクを早期に把握できます。
7️⃣ まとめ
- 開発基盤: Go 1.26 と Docker/helm の最新版を公式手順でインストールし、環境変数を整備すれば即座に開発が開始できる。
- コード構造:
cmd / internal / pkg / apiのレイアウトと Repository パターンにより、REST と gRPC 両方のエンドポイントで同一ビジネスロジックを共有可能。 - データ永続化: pgx と MongoDB driver をインターフェースで抽象化し、テスト容易性と将来の DB 変更に強い設計。
- コンテナ化: マルチステージ Dockerfile と docker‑compose によってローカルでも本番に近い環境を数分で立ち上げられる。
- CI/CD: GitHub Actions + Helm で Lint → Test → Build → Push → Deploy のフローが自動化され、EKS と GKE のマルチクラウド展開も同一チャートで完結。
- Observability: Istio + OpenTelemetry、Zap + Loki、Prometheus + Grafana によるトレース・ログ・メトリクスの統合が実装例として完成。
- テストとセキュリティ: ユニットから契約テストまで網羅し、JWT・mTLS・govulncheck で認証・暗号化・脆弱性対策を自動化。
以上の手順とベストプラクティスに沿ってプロジェクトを構築すれば、最新ツールチェーン と 堅牢な運用基盤 を備えた Go マイクロサービスを迅速に開発・デリバリーできるようになります。ぜひ本ガイドを実務に取り入れ、継続的改善のサイクルへ活かしてください。