🤖

Kubernetesに入門してみる

2023/04/02に公開

背景

実務でKubernetesに触れる機会があったので、入門がてらに自分用にメモしながらざっくり概要調べつつ、少し動かしてみる。
15分程度で読めるような内容にする。

Kubernetesとは

詳細は公式ドキュメントやネットの情報を読めば分かるが、コンテナのオーケストレーションツール。
リソースと呼ばれるKubernetesオブジェクトでクラスター(ざっくり言うとコンテナ群)の状態を定義しておくことで、その定義通りに動くようにKubernetesが管理してくれる。

構成要素

Kubernetesの構成要素はこんなかんじ

https://kubernetes.io/ja/docs/concepts/overview/components/

ざっくりいうと、図左のコントロールプレーンと図右のワーカーノードで構成されている。
コントロールプレーンもワーカーノードも可用性向上のために冗長化するのが一般的らしい。

ワーカーノードの中でコンテナが動くみたい。

コントロールプレーン

コントールプレーンはその名の通りでワーカーノードを制御する部品で構成されている。
各部品にそれぞれ役割があるようだが、入門時点ではそれほどここは意識せずに進める。

ワーカーノード

コンテナが動く場所。
yamlでリソースを記述した通りにワーカーノード上でコンテナを動かしてくれる。

リソース

コンテナを稼働させる条件、状態などを定義するもの。
Kubernetesではリソースというオブジェクト群でコンテナやコンテナの実行環境を抽象化して、コンテナ周りを扱いやすくしているよう。
リソースにはいくつか種類があり、それらを使ってコンテナをどのように動かしたいかを記述する。

リソースの種類

とりあえず、有名そうなリソースについて書いておく。
リソースのイメージはこのようなかんじ。

Pod

Podはコンテナやストレージを格納しているリソース。
基本的には1つのPodには1つのコンテナが格納される。
(複数のコンテナが格納される場合もある)

ReplicaSet

Podのレプリカを複製して、指定した数のPodが動くように維持するリソース。

Depoloyment

Podのデプロイ方法を管理するリソース。

Service

ネットワークを管理するリソース。
これがないとPod(コンテナ)と通信できない。

実際に動かしてみる

環境

M1 Mac
docker desktop 4.17.0
※docker desktopでKubernetesを有効にしておく(けっこう時間かかる)

各種ソース

今回はとりあえず、goの簡単なプログラムを実装して、コンテナ化する。

  • main.go
package main

import (
	"net/http"

	"github.com/labstack/echo/v4"
	"github.com/labstack/echo/v4/middleware"
)

func main() {
	// echoのインスタンスを生成
	e := echo.New()

	// ミドルウェアを設定
	e.Use(middleware.Logger())
	e.Use(middleware.Recover())
	e.GET("/", func(c echo.Context) error {
		return c.String(http.StatusOK, `ok`)
	})
	e.GET("/test", func(c echo.Context) error {
		return c.String(http.StatusOK, `testOK`)
	})
	// サーバーをポート番号指定で起動
	e.Logger.Fatal(e.Start(":80"))
}
  • Dockerfile
FROM golang:1.19-alpine as dev

ENV ROOT=/go/src/app
ENV CGO_ENABLED 0
WORKDIR ${ROOT}
# alpineは最低限しか入ってないので、アップデートとgitのインストール
RUN apk update && apk add git && apk add bash
COPY go.mod go.sum ./
RUN go mod download

COPY *.go ./

EXPOSE 8080

CMD ["go", "run", "main.go"]

FROM golang:1.19-alpine as builder

ENV ROOT=/go/src/app
WORKDIR ${ROOT}
# alpineは最低限しか入ってないので、アップデートとgitのインストール
RUN apk update && apk add git
COPY go.mod go.sum ./
RUN go mod download

COPY . ${ROOT}
RUN CGO_ENABLED=0 GOOS=linux go build -o $ROOT/binary

#コンテナ内でコマンド実行したいので、alpine入れとく
FROM alpine:3.14 as prod
#FROM scratch as prod

ENV ROOT=/go/src/app
WORKDIR ${ROOT}
#コンテナ内でコマンド実行したいので、bash入れとく
RUN apk add bash && apk add curl
COPY --from=builder ${ROOT}/binary ${ROOT}

EXPOSE 8080
CMD ["/go/src/app/binary"]
  • deployment.yml
    ポイントはspec.selector.matchLabels.appとspec.template.metadata.labels.appの名前を合わせるところ。
    ローカルのイメージ使用するので、imagePullPolicyはIfNotPresentにするところ。
    あとは大体、ネットとかの情報からコピペでいける。
apiVersion: apps/v1
kind: Deployment
metadata:
  name: k8stest
spec:
  replicas: 1
  selector:
    matchLabels:
      app: k8stest
  template:
    metadata:
      labels:
        app: k8stest
    spec:
      containers:
        - name: k8stestapp
          image: k8stest/gosample:v1
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 80

  • service.yml
    ポイントは8080でうけたものを80に流してるところ。
apiVersion: v1
kind: Service
metadata:
  name: k8stest
spec:
  type: LoadBalancer
  selector:
    app: k8stest
  ports:
  - port: 8080
    targetPort: 80

実行してみる

まずはデプロイ

kubectl apply -f deployment.yml

コンテナとネットワーク繋がるようにServiceを適用

kubectl apply -f service.yml

実行結果

コンテナがRunningになってる

http://localhost:8080にアクセスするとレスポンスもくる。

pod内でコマンド打つ

pod名確認

kubectl get pods
NAME                      READY   STATUS    RESTARTS   AGE
k8stest-c5f54fcdf-l97jm   1/1     Running   0          71s

以下のようにするとpod内でコマンド打てる

kubectl exec -it 【pod名】 -c 【コンテナ名】 -- コマンド
kubectl exec -it k8stest-c5f54fcdf-l97jm -c k8stestapp -- bash

感想

とりあえず、お試しレベルで動かせた。
EKSとかGKEも試しに動かしてみたい。

Discussion