こんにちは。Tomoyuki(@tomoyuki65)です。
Go言語(Golang)はマイクロサービスでよく使われたりしますが、そんなマイクロサービスを大規模なサービスで開発している場合、インフラにはKubernetes(略してk8s)を使っていることが多いのではないでしょうか。
k8sを実務で使える機会はなかなか無いと思いますが、Go言語を極めていくなら触れておいた方がいい技術ではあるので、今回はkind(Kubernetes in Docker)というツールを使ったk8sの使い方についてご紹介します。
kindでKubernetes(k8s)のローカル開発環境を作ってGo言語(Golang)のAPIをデプロイする方法
今回はkind(Kubernetes in Docker)というツールを使いますが、これを使うには事前にDockerを使える必要もあるので、もしまだDocker環境が無い方は事前にDocker Desktopなどをインストールして使えるようにして下さい。
そしてMacOSならお馴染みのHomebrewを前提に話を進めますが、以下のコマンドを実行し、必要なツールをインストールして下さい。
$ brew install kubectl
$ brew install kind
※kubectlはk8s用のコマンドラインツールです
次に以下のコマンドを実行し、コマンドが使えることを確認して下さい。
$ kubectl version --client
$ kind --version
事前に簡単なGo言語(Golang)のAPIを作成する
事前に簡単なGo言語(Golang)のAPIを作るため、以下のコマンドを実行して各種ファイルを作成して下さい。
$ mkdir k8s-go && cd k8s-go
$ mkdir src && cd src
$ touch main.go
$ cd ..
$ mkdir -p docker/local && cd docker/local
$ touch Dockerfile
$ cd ../..
$ touch compose.yml
次に作成したファイルをそれぞれ以下のように記述します。
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World !!")
})
e.GET("/k8s-go", func(c echo.Context) error {
return c.String(http.StatusOK, "Go API on k8s !!")
})
e.Logger.Fatal(e.Start(":8080"))
}
※Go言語のフレームワークにはEchoを使ってます。
FROM golang:1.24-alpine
WORKDIR /go/src
COPY ./src .
# モジュールの依存関係をインストール
RUN if [ -f ./go.mod ]; then \
go install; \
fi
# air をインストール
RUN go install github.com/air-verse/air@latest
EXPOSE 8080
services:
api:
container_name: k8s-go-api
build:
context: .
dockerfile: ./docker/local/Dockerfile
command: air -c .air.toml
volumes:
- ./src:/go/src
tty: true
stdin_open: true
ports:
- 8080:8080
次に以下のコマンドを実行し、コンテナのビルドから開発サーバーの起動まで行います。
$ docker compose build --no-cache
$ docker compose run --rm api go mod init k8s-go
$ docker compose run --rm api air init
$ docker compose run --rm api go mod tidy
$ docker compose up -d
次にブラウザで「http://localhost:8080」や「http://localhost:8080/k8s-go」を開き、画面にそれぞれテキストが表示されればOKです。
次に以下のコマンドを実行し、コンテナを停止して下さい。
$ docker compose down
k8sにデプロイするためのDockerコンテナを作成する
次に以下のコマンドを実行し、k8sにデプロイするためのDockerコンテナ用のDockerfileを作成します。
$ mkdir -p docker/prod && cd docker/prod
$ touch Dockerfile
$ cd ../..
次に作成したDockerfileを以下のように記述します。
####################
# ビルドステージ
####################
FROM golang:1.24-alpine AS builder
WORKDIR /go/src
COPY ./src .
# 依存関係を反映
RUN go install
# ビルド
RUN go build -o main .
####################
# 実行ステージ
####################
FROM alpine:3.21
WORKDIR /go/src
# コンテナ用ユーザー作成
RUN addgroup --system --gid 1001 appuser && \
adduser --system --uid 1001 appuser
# ビルドステージで作成したバイナリをコピー
COPY --from=builder --chown=appuser:appuser ./go/src/main .
# ポートを設定
EXPOSE 8080
# コンテナ起動ユーザー
USER appuser
# APIサーバー起動コマンド
CMD ["./main"]
次に以下のコマンドを実行し、k8sにデプロイするためのコンテナをビルドします。
$ docker build --no-cache -f ./docker/prod/Dockerfile -t k8s-go-api:latest .
次に以下のコマンドを実行し、コンテナを起動します。
$ docker run -p 80:8080 k8s-go-api
次にブラウザで「http://localhost」や「http://localhost/k8s-go」を開き、画面にそれぞれテキストが表示されればOKです。
次にMacOSの場合はターミナルをアクティブにして以下のショートカットキーを実行し、コンテナを停止して下さい。
control + c
kind(Kubernetes in Docker)でk8sのローカル開発環境を構築する
次に以下のコマンドを実行し、kind(Kubernetes in Docker)でk8sのローカル開発環境を構築するための各種ファイルを作成します。
$ mkdir k8s && cd k8s
$ touch kind-cluster.yaml
$ touch kind-deployment.yaml
$ touch kind-service.yaml
$ cd ..
次に作成した各種ファイルはそれぞれ以下のように記述します。
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
nodes:
# マスターノード1
- role: control-plane
extraPortMappings:
- containerPort: 30010
hostPort: 80
# ワーカーノード2
- role: worker
- role: worker
apiVersion: apps/v1
kind: Deployment
metadata:
name: kind-go-deployment
# Podと関連付けるラベル
labels:
app: go-api
spec:
# Podの数の定義
replicas: 3
# Deploymentが管理するPodの定義
selector:
matchLabels:
app: go-api
# 新しいPodを作成する際のテンプレート定義
template:
metadata:
labels:
app: go-api
spec:
containers:
- name: go-api
image: k8s-go-api:latest
# ローカルのDockerイメージを使う設定
imagePullPolicy: Never
ports:
- containerPort: 8080
apiVersion: v1
kind: Service
metadata:
name: kind-go-service
spec:
selector:
app: go-api
# 接続方法
type: NodePort
ports:
- port: 8080
nodePort: 30010
次に以下のコマンドを実行し、クラスターおよびノードを作成します。
$ kind create cluster --config k8s/kind-cluster.yaml
※クラスター(Cluster)は、k8sが管理する複数のノードの集合体です。そしてノード(Node)は、クラスタを構成する個々のコンピューターで、ポッドを実行するためのものです。
コマンド実行後、ターミナルでは以下のようになります。
次に以下のコマンドを実行し、ノードが作成されていることを確認します。
$ kubectl get nodes -o wide
※オプション「-o wide」は詳細を表示させるもの
コマンド実行後、ターミナルでは以下のようになります。
次に以下のコマンドを実行し、ローカル環境で事前にビルドしたDockerコンテナのイメージをkindにロードします。
$ kind load docker-image k8s-go-api:latest
次に以下のコマンドを実行し、ポッドをデプロイします。
$ kubectl create -f k8s/kind-deployment.yaml
※ポッド(Pod)は、k8sにおけるアプリケーションの最小単位で、一つ以上のコンテナとそれらコンテナの動作に必要な情報をまとめています。
次に以下のコマンドを実行し、ポッドが作成されていることを確認します。
$ kubectl get pods -o wide
コマンド実行後、ターミナルでは以下のようになります。
※「STATUS」がRunnningであること。また対象のPodがどのノードに属しているかは「NODE」の部分を確認する。
次に以下のコマンドを実行し、サービスを作成してブラウザからアクセスできるようにします。
$ kubectl create -f k8s/kind-service.yaml
※サービス(Service)は、ポッドへアクセスするための仕組みです。ポッドはノード上で動的に作成・削除され、そのIPアドレスは常に変わる可能性がありますが、サービスはこれら動的に変化するポッドへのアクセスを安定的に提供します。
次に以下のコマンドを実行し、サービスが作成されていることを確認します。
$ kubectl get services -o wide
コマンド実行後、ターミナルでは以下のようになります。
次にブラウザで「http://localhost」や「http://localhost/k8s-go」を開き、画面にそれぞれテキストが表示されればOKです。
GoのAPIを修正してPodを更新する
次にGoのAPIを以下のように修正します。
package main
import (
"net/http"
"github.com/labstack/echo/v4"
)
func main() {
e := echo.New()
e.GET("/", func(c echo.Context) error {
return c.String(http.StatusOK, "Hello, World !!")
})
e.GET("/k8s-go", func(c echo.Context) error {
return c.String(http.StatusOK, "Go API on k8s with kind !!")
})
e.Logger.Fatal(e.Start(":8080"))
}
※API「/k8s-go」の出力を修正
次に以下のコマンドを実行し、Dokcerコンテナを再ビルドします。
$ docker build --no-cache -f ./docker/prod/Dockerfile -t k8s-go-api:latest .
次に以下のコマンドを実行し、ローカル環境で事前にビルドしたDockerコンテナのイメージをkindにロードします。
$ kind load docker-image k8s-go-api:latest
次のコマンドを実行し、デプロイメントの全てのレプリカを再起動(ポッドを削除して新しいポッドをデプロイ)します。
$ kubectl rollout restart deployment kind-go-deployment
次にブラウザで「http://localhost/k8s-go」を開き、画面に変更したテキストが表示されればOKです。
クラスターを削除して終了する
次に以下のコマンドを実行し、クラスターを削除して終了します。
$ kind delete cluster
最後
今回はkind(Kubernetes in Docker)というツールを使ったk8sの使い方についてご紹介しました。
インフラにk8sを使うことでアプリケーションを分散処理することができ、自動スケーリング(自動的にポッドの数を増減)や自己修復(ノードやポッドに障害が発生しても、自動的に再起動や再配置する)も可能になるため、可用性と障害耐性を高めることが可能です。
k8sは大手企業などの大規模サービス以外ではあまり使われず、実務で使える機会はなかなか無いと思いますが、これからk8sを試してみたいという方は、ぜひ参考にしてみて下さい!
コメント