Kubernetes完全ガイドを読みながらKubernetesに入門する

 以前特定ミドルウェアやトレンド技術に対応できるエビデンスを作っていきたいという話をしました。ということでKubernetesに入門してみることにしました。上で動かすアプリケーションが無いのにKubernetesだけを学ぶのはiPhoneのマニュアルだけ読んでアプリをインストールしないのに似ています。それだとつまらないので最終的に何かしらサービスを作っていくことを目標にします1

Kubernetesとは

 たくさんのマシン上でたくさんコンテナを実行するためのミドルウェアです。デプロイ・スケーリングなどの管理が自動化できます。Dockerだと単体のマシンでコンテナを動かすことはできても複数台で協調させることは難しいです。ロードバランシングやサービスディスカバリを設定したりできるらしいです。AWSならECS、Route53、ELB等がありますが、同等のことをオンプレで実現できるのが嬉しさなのかなと思います。自前のデータセンターを持っている場合はこれを使うことになるんだと思います。あとはGoogleが原型を作っていたけれども今はオープンソースなのでベンダーロックインが少ないあたりが嬉しさになってくるんでしょうか。マネージドの場合でもKubernetesのレイヤーが噛んでいるのでAWSからGCP、GCPからAzureなどの移行が比較的簡単にできたりするんですかね。

 リソースの定義はマニフェストというyamlを書いて行います。マニフェストは以下みたいなものです。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: sample-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: sample-app
  template:
    metadata:
      labels:
        app: sample-app
    spec:
      containers:
      - name: nginx-container
        image: nginx:1.16

マニフェストにあるべき姿を書いて、現状にズレがあったらKubernetesが戻そうとするとのことです。ここらへんはCloudFormationとECSのタスク数設定をあわせたような動きになりそうです。更に、ノードの障害があっても、Kubernetesが死活監視しているので別ノードでコンテナを実行するよう復旧するなどの賢い動きができるそうです。

 コンテナはどこのノードで実行されるのかユーザーは考えなくてよく、Kubernetesによって賢くスケジューリングされます。スケジューリングではコンテナのディスクIOの量を加味してSSDを持つノードで実行するなどができます。特に指定がなければ現在使用中のリソース状況に応じてスケジューリングされます2

Kubernetes環境

 Kubernetesを動かす環境はローカル・Kubernetes構築ツール・マネージドKubernetesサービスがあります。個人で勉強するためには費用的にローカルしか選択肢がないですが、ローカルの選択肢としてはMinikubeとkindがあります。前者ではマルチノードを再現することができないため、kindを使うべきです。kindはローカルマシンにDockerをインストールしておき、Docker上のコンテナをノードに見立ててKubernetesを実行します。

 WSL2での実行方法としては、Dockerをインストールし、以下を実行してください。

curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.17.0/kind-linux-amd64
chmod +x ./kind
sudo mv ./kind /usr/local/bin/kind

次に以下kind.yamlを作成し、

apiVersion: kind.x-k8s.io/v1alpha4
kind: Cluster
nodes:
- role: control-plane
  image: kindest/node:v1.18.2
- role: control-plane
  image: kindest/node:v1.18.2
- role: control-plane
  image: kindest/node:v1.18.2
- role: worker
  image: kindest/node:v1.18.2
- role: worker
  image: kindest/node:v1.18.2
- role: worker
  image: nginx:1.17
kind create cluster --config kind.yml --name kindcluster

することでクラスタを作れます。

 あれ、ノードの中でpodが複数動くはずだから、kindの場合Dockerコンテナの中で複数のコンテナが動くdocker in docker状態になるということでしょうか?

apiVersion: v1
kind: Pod
metadata:
  name: sample-pod
spec:
  containers:
  - name: nginx-container
    image: nginx:1.16

上のようなymlを作成し、

kubectl apply -f sample-pod.yml
docker ps

すると

CONTAINER ID   IMAGE                                COMMAND                  CREATED        STATUS       PORTS                                                                                            NAMES
4117db094f2c   kindest/node:v1.18.2                 "/usr/local/bin/entr…"   5 hours ago    Up 5 hours   127.0.0.1:37973->6443/tcp                                                                        kindcluster-control-plane2
798151edb29a   kindest/node:v1.18.2                 "/usr/local/bin/entr…"   5 hours ago    Up 5 hours   127.0.0.1:37639->6443/tcp                                                                        kindcluster-control-plane3
c2b7dc9b10de   kindest/node:v1.18.2                 "/usr/local/bin/entr…"   5 hours ago    Up 5 hours                                                                                                    kindcluster-worker
16df365d3d35   kindest/node:v1.18.2                 "/usr/local/bin/entr…"   5 hours ago    Up 5 hours                                                                                                    kindcluster-worker3
311ce81d8d9b   kindest/node:v1.18.2                 "/usr/local/bin/entr…"   5 hours ago    Up 5 hours                                                                                                    kindcluster-worker2
6e79ead44109   kindest/haproxy:v20220207-ca68f7d4   "haproxy -sf 7 -W -d…"   5 hours ago    Up 5 hours   127.0.0.1:41061->6443/tcp                                                                        kindcluster-external-load-balancer
74f5e62640ed   kindest/node:v1.18.2                 "/usr/local/bin/entr…"   5 hours ago    Up 5 hours   127.0.0.1:43043->6443/tcp                                                                        kindcluster-control-plane

と出てきてどこにもnginxの姿が無いので多分コンテナ内でコンテナが動いているんでしょう。

リソース

 Kubernetesでは配置するオブジェクトのことをリソースと言っています。リソースにはWorkloads APIs、Service APIs、Config & Storage APIs、Cluster APIs、Metadata APIsがあります。

kubectl

 Kubernetesをインタラクティブにいじる際はkubectlというコマンドラインツールを使います。Kubernetes Masterが提供しているAPIをkubectlは叩いているだけなので、クライアントプログラムからもkubectlと同じ事ができます。kubectlは接続先の認証情報を~/.kube/configに保存しています。kindでクラスタを作ると自動で認証情報も書き出されます。

 リソースの作成・変更・削除ではcreate/apply/deleteというコマンドを使います。例えば、

kubectl apply -f hoge.yml

のような形です。ただし、kubectl createでリソースを作成するのはベストプラクティスではなく、常にkubectl applyでリソースを作るべきとのことです。なぜなら、–save-configをつけずにkubectl createすると初回のマニフェストを忘れ、次回apply時に正しく差分検出できないからです。また、applyとcreateを使い分けるのも面倒です。

マニフェストの設計

 マニフェストは個別にkubectl apply -f ファイル名 すればクラスタに反映されます。また、”—“で区切れば同じymlに複数のリソースを書くことができたり、kubectl apply -f ./ すれば、同一ディレクトリのマニフェストをいっぺんに適用する事もできます。では、どういうファイル分割・管理が適切かという疑問が生じますが、

  • 全システムを1ディレクトリで管理
  • サブシステムごとにディレクトリを分けて管理
  • マイクロサービスごとに分けて管理

などのパターンがあります。ベストプラクティスやアンチパターンはこの本では紹介されていないようです。

アノテーション・ラベル

 リソースにはアノテーションとラベルというものを付与できます。前者はシステムコンポーネントが使用し、後者はユーザーが検索しやすくするなどリソース管理で利用するものです。アノテーションはGKE等固有の機能を利用したい場合に付与したり、Kubernetesの実験的機能を使う時付与します。

所感

やっぱり単なる教科書の抜粋になっていてエビデンスになっていないので、この活動のやり方も考えなきゃならないですね…この本を読み進める前にもうnostrのなにかを作ってその記録をここに書くか…

  1. 最近Nostrが話題になっているので、そっち系でなにか作ろうかな?
  2. 逆に言うとアプリケーションはどのノードで動いているかに依存しないように作る必要があるということですね

コメント

タイトルとURLをコピーしました