はじめに
Kind (Kubernetes in Docker) は、ローカル環境でKubernetesクラスタを簡単に構築できるツールです。そう、「簡単に」と言いましたが、「簡単」の定義は人によって大きく異なりますから。ある人にとっては「簡単」でも、他の人には「アラート対応を猫に教えるくらい難しい」かもしれません。
さあ、気軽に「簡単な」Kubernetes体験の世界へ飛び込みましょう。途中で迷子になっても、パニックにならないでください。結局のところ、私たちプログラマーは迷子になることが仕事なのですから。
サンプルコード
動いているものをおいておくと記事の安心感と信頼性に繋がるので置いておきます。
Kind公式ドキュメント
環境情報
環境としてはLimaを利用しております。
参考リンク
Kindのセットアップと基本的な使用方法
Kindのインストール
KindはHomebrewやバイナリのダウンロード、Go言語を使用したインストールなど複数の方法でインストールすることができます。
私はbrew で入れているので一応、コマンド記載しときます。
brew install kind
基本的なクラスタの作成
最も基本的なKindクラスタを作成するには、以下のコマンドを使用します。
kind create cluster
これにより、単一ノードのKubernetesクラスタが作成されます。
カスタム設定でのクラスタ作成
より詳細な設定を行う場合は、YAML設定ファイルを使用します。
# kind-config.yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane - role: worker - role: worker
このファイルを使用してクラスタを作成するには
kind create cluster --config kind-config.yaml
クラスタの管理
クラスタの一覧を表示:
kind get clusters
特定のクラスタを削除:
kind delete cluster --name cluster-name
特定のクラスタのkubeconfig
を取得:
kind get kubeconfig --name cluster-name
1. Skaffoldとの統合による高速な開発サイクルの実現
ホットリロード可能なローカル開発環境は、DockerとAirの組み合わせで構築できますが、SkaffoldとKindを用いることで、Kubernetes環境で同等の機能を持つ開発環境を実現することも可能です。
サービスのソースコード
変更が分かりやすければ正直なんでも良いのでこちらです。
// main.go package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World from Go!") }) http.ListenAndServe(":8080", nil) }
Dockerfileの作成
go.mod のバージョンとベースイメージがズレているとエラーが出るので修正しなきゃいけないですわねー
# Dockerfile FROM golang:1.22 as builder WORKDIR /app # Copy go mod and sum files COPY go.mod ./ # Download all dependencies. Dependencies will be cached if the go.mod and go.sum files are not changed RUN go mod tidy # Copy the source from the current directory to the Working Directory inside the container COPY . . # Build the Go app RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o go-app . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/go-app . CMD ["./go-app"]
Kubernetes設定ファイルの作成
deployment.yaml にServiceも入れてます。
# k8s-deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: go-app spec: replicas: 1 selector: matchLabels: app: go-app template: metadata: labels: app: go-app spec: containers: - name: go-app image: go-app ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: go-app spec: type: NodePort ports: - port: 8080 targetPort: 8080 selector: app: go-app
Skaffold設定ファイルの作成
Skaffold設定ファイルの作成します。プロジェクトのルートディレクトリに skaffold.yaml
ファイルを作成します。Dockerfileのビルドとkubectl でのデプロイの両方をやってくれます。
# skaffold.yaml # Skaffoldの設定ファイル # このファイルはDockerイメージのビルドとKubernetesへのデプロイを自動化します apiVersion: skaffold/v2beta26 kind: Config # ビルド設定 build: artifacts: - image: go-app # ビルドされるイメージの名前 context: . # ビルドコンテキストのパス(通常はプロジェクトのルートディレクトリ) docker: dockerfile: Dockerfile # 使用するDockerfileの名前 # デプロイ設定 deploy: kubectl: manifests: - k8s-*.yaml # デプロイに使用するKubernetesマニフェストファイルのパターン # 注意点: # 1. `go-app`はあなたのアプリケーション名に合わせて変更してください。 # 2. Dockerfileがルートディレクトリにない場合は、パスを適切に調整してください。 # 3. `k8s-*.yaml`は実際のマニフェストファイル名のパターンに合わせて変更してください。 # 4. 必要に応じて、プロファイルやテスト設定を追加することができます。
アプリケーションの実行とテスト
Kindクラスタを作成し、Skaffoldを起動してます。
kind create cluster
skaffold dev --port-forward
この後、main.go
やDockerfile
を編集してください。ファイルを保存すると、Skaffoldが自動的に以下の処理を行います。
- 変更を検知
- 新しいDockerイメージをビルド
- ビルドしたイメージをKindクラスタにロード
- アプリケーションを再デプロイ
変更の確認
ブラウザやcurl
コマンドを使用して、アプリケーションにアクセスし、変更が反映されていることを確認します。
curl http://localhost:8080
2. マイクロサービスアーキテクチャのシミュレーション
Skaffoldを使用して、2つのGoマイクロサービスを含む環境をKindでシミュレートします。
Kindクラスタの作成
# kind-multi-node.yaml kind: Cluster apiVersion: kind.x-k8s.io/v1alpha4 nodes: - role: control-plane extraPortMappings: - containerPort: 30000 hostPort: 8080 - containerPort: 30001 hostPort: 8081 - role: worker - role: worker
デプロイじゃい
kind create cluster --config kind-multi-node.yaml
サービスのソースコード その1
// service-a/main.go package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from Service A!") }) http.ListenAndServe(":8080", nil) }
サービスのソースコード その2
// service-b/main.go package main import ( "fmt" "net/http" ) func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello from Service B!") }) http.ListenAndServe(":8081", nil) }
Dockerfileの作成
各サービスのディレクトリに以下のDockerfileを作成します。
# service-a/Dockerfile と service-b/Dockerfile FROM golang:1.22 as builder WORKDIR /app COPY go.mod . COPY main.go . RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o main . FROM alpine:latest RUN apk --no-cache add ca-certificates WORKDIR /root/ COPY --from=builder /app/main . CMD ["./main"]
Kubernetes設定ファイルの作成
service-aとservice-bのファイルを適切なディレクトリに設置します。
# k8s-manifests.yaml apiVersion: apps/v1 kind: Deployment metadata: name: service-a spec: replicas: 1 selector: matchLabels: app: service-a template: metadata: labels: app: service-a spec: containers: - name: service-a image: service-a ports: - containerPort: 8080 --- apiVersion: v1 kind: Service metadata: name: service-a spec: type: NodePort ports: - port: 8080 targetPort: 8080 nodePort: 30000 selector: app: service-a --- apiVersion: apps/v1 kind: Deployment metadata: name: service-b spec: replicas: 1 selector: matchLabels: app: service-b template: metadata: labels: app: service-b spec: containers: - name: service-b image: service-b ports: - containerPort: 8081 --- apiVersion: v1 kind: Service metadata: name: service-b spec: type: NodePort ports: - port: 8081 targetPort: 8081 nodePort: 30001 selector: app: service-b
Skaffold設定ファイルの作成
プロジェクトのルートディレクトリに skaffold.yaml
ファイルを作成します。
# skaffold.yaml apiVersion: skaffold/v2beta29 kind: Config build: artifacts: - image: service-a context: service-a docker: dockerfile: Dockerfile - image: service-b context: service-b docker: dockerfile: Dockerfile deploy: kubectl: manifests: - k8s-manifests.yaml
アプリケーションの実行とテスト
Skaffoldを使用してアプリケーションをビルド、デプロイ、そして監視します。
skaffold dev --port-forward
このコマンドは以下の動作を行います。 - サービスAとサービスBのDockerイメージをビルド - ビルドしたイメージをKindクラスタにロード - Kubernetes マニフェストを適用してサービスをデプロイ - ポートフォワーディングを設定 - ファイルの変更を監視し、変更があれば上記のプロセスを再実行
確認
別のターミナルウィンドウで以下のコマンドを実行して、サービスにアクセスできることを確認します。
curl http://localhost:8080 # Service A curl http://localhost:8081 # Service B
これで、2つのマイクロサービスがKindクラスタ上で実行され、Skaffoldによって自動的に管理されます。ソースコードを変更すると、Skaffoldが自動的に再ビルドとデプロイを行います。
おわりに
本記事では、Kind(Kubernetes in Docker)を使用したGoアプリケーションの開発について詳しく解説しました。Kindの基本的なセットアップから、Skaffoldとの統合による高速な開発サイクルの実現、そしてマイクロサービスアーキテクチャのシミュレーションまで、実践的なアプローチで解説しました。
ここで学んだtipsとセットアップ方法を活用することで、アプリケーション開発者は以下の利点を得ることができます
効率的な開発サイクル: Skaffoldとの統合により、コード変更から再デプロイまでのプロセスが自動化され、開発速度が大幅に向上します。
本番環境に近いテスト環境: Kindの柔軟性により、マイクロサービスアーキテクチャや複雑なネットワーク構成を、ローカル環境で簡単にシミュレートできます。
Kindの強力な機能を利用することで、本番環境に近い状態でアプリケーションをテストし、開発サイクルを迅速化できます。これは、特にクラウドネイティブな開発において非常に重要です。
今後のステップとして、以下のような発展的なトピックにチャレンジすることをおすすめします。まぁ一番は俺が書けって話ですけどね。
- 本番環境に近いテスト環境の構築
- 設定管理の簡素化
- データの永続化
- セキュリティの強化
- Kindを使用したCI/CDパイプラインの構築
- サービスメッシュ(例:Istio)のKind環境への導入
- Kindを使用したカオスエンジニアリングの実践
- マルチクラスタ環境のシミュレーションとフェデレーション
最後に、Kindはあくまでもローカル開発とテストのためのツールであることを忘れないでください。本番環境への移行時には、クラウドプロバイダーやマネージドKubernetesサービスの特性を考慮し、適切な調整を行う必要があります。