Kubernetesに入門してみる
背景
実務でKubernetesに触れる機会があったので、入門がてらに自分用にメモしながらざっくり概要調べつつ、少し動かしてみる。
15分程度で読めるような内容にする。
Kubernetesとは
詳細は公式ドキュメントやネットの情報を読めば分かるが、コンテナのオーケストレーションツール。
リソースと呼ばれるKubernetesオブジェクトでクラスター(ざっくり言うとコンテナ群)の状態を定義しておくことで、その定義通りに動くようにKubernetesが管理してくれる。
構成要素
Kubernetesの構成要素はこんなかんじ
ざっくりいうと、図左のコントロールプレーンと図右のワーカーノードで構成されている。
コントロールプレーンもワーカーノードも可用性向上のために冗長化するのが一般的らしい。
ワーカーノードの中でコンテナが動くみたい。
コントロールプレーン
コントールプレーンはその名の通りでワーカーノードを制御する部品で構成されている。
各部品にそれぞれ役割があるようだが、入門時点ではそれほどここは意識せずに進める。
ワーカーノード
コンテナが動く場所。
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