昨今Kubernetesが便利で流行っているということで今更ながら触ってみることにしました。
こちらに自分用のメモを兼ねて書きます。
ネットの記事は、AWSやGCPで利用することが前提になっているものが多く、
初見なのもありローカルの開発環境を作り、色々遊びながら理解を深めていきます。
Kubernetesとは
Kubernetesの公式ドキュメントによると
Kubernetesは「コンテナを管理する基盤ツール」です。
使うと何が嬉しいかと言いますと、アプリケーションの開発・管理が楽で安全になります。
例えば、Kubernetesの基本機能として、デプロイ、拡張、負荷分散、ログ記録、監視などがあります。
また、アプリケーションの運用で頭を悩ませる問題として、高負荷などで異常が起きた時、スケールアウトしたり、フェールオーバーする必要があります。
VMを使う構成では、結局のところ管理はそのVM単位になってしまい、スケールアウト・フェールオーバーの設定もVM単位でしか行なえません。
Kubernetesを使うと、コンテナ単位つまりアプリケーション単位で管理することができ(実際にはVMを使っていて、アプリケーション単位で管理しているように扱える感じらしい)、スケールアウト・フェールオーバーもアプリケーション単位で設定することができます。
これは便利ですね。
ゴール
今回の目指すゴールは2つ
・kubernetesの理解を深める
・ローカルの開発環境を作る
です。
公式ドキュメントには、ブラウザ上でコマンドを叩いて動かすチュートリアルがあります。
ただ、今回はローカルのマシンに実際にKubernetes環境を作るところを目標にやっていきたいと思います。
0.アーキテクチャの理解
公式サイトにわかりやすい図がなかったので、図だけwikipediaからお借りしました。
引用:Kubernetes Kubernetesのアーキテクチャ図 https://ja.wikipedia.org/wiki/Kubernetes
Kubernetesをデプロイするとクラスターが展開されます。
このKubernetesクラスターは、コンテナ化されたアプリケーションを実行するノード(Node)と呼ばれるワーカーマシンの集合です。アプリケーションのコンポーネントはPodと呼ばれ、図のように、このPodがノードに1つ以上の含まれ、展開されています。ノードの制御は、kubeletと呼ばれるエージェントで行われ、ノードへのアクセスはkube-proxyと呼ばれるプロキシを介して行われます。
コントロールプレーンと呼ばれるコンポーネントは、クラスターを制御する機能を持ちます。
以下は公式ドキュメントに書かれた詳細な説明です。
コントロールプレーンコンポーネント
kube-apiserver
・Kubernetes APIを外部に提供する
・Kubernetesコントロールプレーンのフロントエンド
etcd
・一貫性、高可用性を持ったキーバリューストアで、Kubernetesの全てのクラスター情報の保存場所
kube-scheduler
・Podにノードが割り当てられているか確認し、割り当てを行う
kube-controller-manager
・通知やPodの数を監視する複数のコントローラープロセスを実行する
cloud-controller-manager
・基盤であるクラウドプロバイダーと対話するコントローラーを実行する
ノードコンポーネント
kubelet
・クラスター内の各ノードで実行されるエージェント。各コンテナがPodで実行されていることを保証
kube-proxy
・クラスター内の各nodeで動作しているネットワークプロキシ
コンテナランタイム
・コンテナの実行を担当する
1.ローカルの開発環境を作る、アプリを動かす
今回は、WebアプリのコンテナをローカルのKubernetes上に立てることを目指します。
こちらを参考に進めます。
Minikubeのインストール
今回、Minikubeと呼ばれるローカル環境でKubernetesを簡単に実行するためのツールを使います。このツールではシングルノードのKubernetesクラスターを作ることができます。
Minikubeの使い方はこちら
※私のローカル開発環境はUbuntu18.04です。
kubectlのインストール
まず、kubectlのインストールですが、こちらはドキュメント通りにさらっとインストールできました。
ハイパーバイザーのインストール
私は以前VirtualBoxをインストールしていたので、こちらは特に作業なしでした。
必要な方はこちらから
Minikubeのインストール
今回はバイナリをダウンロードして、指定の場所に置きインストールしました。
$ curl -Lo minikube https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64 \
&& chmod +x minikube
$ sudo mkdir -p /usr/local/bin/
$ sudo install minikube /usr/local/bin/
インストール確認
インストールが成功したかを下記のKubernetesクラスターを起動するコマンドで確認します。
$ minikube start --kubernetes-version {起動するバージョン}
※指定なしの場合は最新のバージョンが起動されます。
$ minikube start
kubernetes起動後
ステータス確認
$ minikube status
停止
$ minikube stop
削除
$ minikube delete
また、この時点でdockerイメージとdockerボリューム見てみますと、
dockerイメージ
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
gcr.io/k8s-minikube/kicbase v0.0.12-snapshot3 25ac91b9c8d7 5 weeks ago 952MB
dockerボリューム
$ docker volume ls
DRIVER VOLUME NAME
local minikube
Minikubeのイメージとボリュームができていました。
Webサーバをkubernetesで立てる
Minikubeのインストールができたので、kubernetes環境を作り、コンテナの稼働をさせます。
WebサーバはMinikubeに対応している単純な応答だけを返すecho-serverを使います。
次に、Minikubeを起動して、クラスターを作成します。
$ minikube start
この時、dockerコンテナの稼働状況は
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f144c151a63 gcr.io/k8s-minikube/kicbase:v0.0.12-snapshot3 "/usr/local/bin/entr…" 20 hours ago Up 22 minutes 127.0.0.1:32779->22/tcp, 127.0.0.1:32778->2376/tcp, 127.0.0.1:32777->5000/tcp, 127.0.0.1:32776->8443/tcp minikube
minikubeのコンテナが動いています。
次にkubectlでKubernetes Deploymentというものを作ります。このKubernetes Deploymentオブジェクトを作成することでアプリケーションを実行できるようになるようです。こちらはYAMLファイルで記述ができます。これ自体はサービスというより、Podを作るためのDeploymentのアプリのようです。
$ kubectl create deployment hello-minikube --image=k8s.gcr.io/echoserver:1.10
deployment.apps/hello-minikube created
できたhello-minikube Deploymentを使い、サービスとして公開します。こちらが実際のアプリとほぼ等価のようです。
$ kubectl expose deployment hello-minikube --type=NodePort --port=8080
service/hello-minikube exposed
この時点でdockerコンテナの稼働状況は
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
7f144c151a63 gcr.io/k8s-minikube/kicbase:v0.0.12-snapshot3 "/usr/local/bin/entr…" 20 hours ago Up 40 minutes 127.0.0.1:32779->22/tcp, 127.0.0.1:32778->2376/tcp, 127.0.0.1:32777->5000/tcp, 127.0.0.1:32776->8443/tcp minikube
どうやらhello-minikubeというコンテナは別に動いておらず、minikubeのコンテナ上で動いているものと思われます。おそらく、このminikubeコンテナ自体にkubernetesのシングルノードやPod、Deploymentが作られていると思われます。
Podができているかを確認します。
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
hello-minikube-5d9b964bfb-vcznp 1/1 Running 0 24m
statusがRunningになっており、稼働していることが確認できました。また1/1ということからPodの数は1つだとわかります。
ServiceのURLは
$ minikube service hello-minikube --url
http://172.17.0.2:31199
アプリが立ち上がっていることが確認できました。
通常より設定する分が少なくさっとできました。
ただ、本来は色々と設定が必要であると思われ、現時点では試せた程度のものと思われます。
以下は削除の手順です。
Serviceの削除は
$ kubectl delete services hello-minikube
service "hello-minikube" deleted
hello-minikube Deploymentの削除は
$ kubectl delete deployment hello-minikube
deployment.extensions "hello-minikube" deleted
2.コンテナを覗く
公式ドキュメントにあったローカル開発環境を作るチュートリアルはこのくらいで終わりですが、
せっかくなので、コンテナ内を覗こうかと思います。
$ docker exec -itu 0 minikube /bin/bash
上のコマンドでminikube内に入ります。コンテナに入るとrootディレクトリに入ったので、少し探索します。
rootディレクトリでll
root@minikube:/# ll
total 64
drwxr-xr-x 81 root root 4096 Oct 3 15:55 ./
drwxr-xr-x 81 root root 4096 Oct 3 15:55 ../
-rwxr-xr-x 1 root root 0 Oct 3 15:54 .dockerenv*
-rw-r--r-- 1 root root 1094 Aug 25 22:55 Release.key
-rw-r--r-- 1 root root 2543 Aug 25 22:55 afbjorklund-public.key.asc
lrwxrwxrwx 1 root root 7 Apr 23 11:06 bin -> usr/bin/
drwxr-xr-x 2 root root 4096 Apr 15 11:09 boot/
drwxr-xr-x 2 root root 4096 Oct 3 15:54 data/
drwxr-xr-x 17 root root 4260 Oct 4 11:11 dev/
drwxr-xr-x 97 root root 4096 Oct 4 11:11 etc/
drwxr-xr-x 5 root root 4096 Oct 3 15:54 home/
-rw-r--r-- 1 root root 0 Aug 25 22:55 kic.txt
drwxr-xr-x 2 root root 4096 Oct 3 15:54 kind/
lrwxrwxrwx 1 root root 7 Apr 23 11:06 lib -> usr/lib/
lrwxrwxrwx 1 root root 9 Apr 23 11:06 lib32 -> usr/lib32/
lrwxrwxrwx 1 root root 9 Apr 23 11:06 lib64 -> usr/lib64/
lrwxrwxrwx 1 root root 10 Apr 23 11:06 libx32 -> usr/libx32/
drwxr-xr-x 2 root root 4096 Apr 23 11:06 media/
drwxr-xr-x 2 root root 4096 Apr 23 11:06 mnt/
drwxr-xr-x 5 root root 4096 Oct 3 15:54 opt/
dr-xr-xr-x 385 root root 0 Oct 4 11:11 proc/
drwx------ 3 root root 4096 Oct 3 15:55 root/
drwxr-xr-x 10 root root 300 Oct 4 11:11 run/
lrwxrwxrwx 1 root root 8 Apr 23 11:06 sbin -> usr/sbin/
drwxr-xr-x 2 root root 4096 Apr 23 11:06 srv/
dr-xr-xr-x 13 root root 0 Oct 4 11:11 sys/
drwxrwxrwt 5 root root 180 Oct 4 11:11 tmp/
drwxr-xr-x 45 root root 4096 Oct 3 15:55 usr/
drwxr-xr-x 14 root root 4096 Oct 3 15:54 var/
topでプロセスを見る
$ top
PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
789 root 20 0 2144664 112188 63072 S 10.7 0.7 4:18.88 kubelet
1946 root 20 0 1096140 334648 67804 S 8.0 2.0 4:42.40 kube-apiserver
1971 root 20 0 10.1g 59396 20936 S 3.3 0.4 1:34.37 etcd
155 root 20 0 2484692 112980 48532 S 3.0 0.7 1:32.43 dockerd
1926 root 20 0 812076 102952 58672 S 2.7 0.6 1:42.38 kube-controller
144 root 20 0 1414636 52844 24364 S 0.7 0.3 0:11.42 containerd
1940 root 20 0 747680 51316 32688 S 0.7 0.3 0:18.26 kube-scheduler
2692 root 20 0 748940 43908 31260 S 0.7 0.3 0:18.71 coredns
178 root 20 0 2742836 63612 24592 S 0.3 0.4 0:13.66 containerd
1 root 20 0 21768 11356 8332 S 0.0 0.1 0:00.75 systemd
131 root 19 -1 29056 11408 10068 S 0.0 0.1 0:00.66 systemd-journal
149 root 20 0 12164 7276 6352 S 0.0 0.0 0:00.01 sshd
1445 root 20 0 110356 7744 3988 S 0.0 0.0 0:00.22 containerd-shim
見ると、kubeletやkube-apiserverのプロセスが立ち上がっています。
kube-apiserverで開発者からの操作を受け付けるAPIを提供しており、kubeletはエージェントとして各ノード(今回はシングルノード)にあり、Podの実行を保証します。containered*と書かれたプロセスが多数あり、いくつかのコンテナが立ち上がっていることがわかります。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
416c4ef429b6 k8s.gcr.io/echoserver "/usr/local/bin/run.…" About an hour ago Up About an hour k8s_echoserver_hello-minikube-5d9b964bfb-vcznp_default_bed83287-6790-4b31-bfa7-73ca575f44c8_0
164da53f6764 k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_hello-minikube-5d9b964bfb-vcznp_default_bed83287-6790-4b31-bfa7-73ca575f44c8_0
e9c6dc7cd409 bad58561c4be "/storage-provisioner" About an hour ago Up About an hour k8s_storage-provisioner_storage-provisioner_kube-system_69b7aff7-ed52-450b-8886-7662e5166c22_2
4129a33df546 bfe3a36ebd25 "/coredns -conf /etc…" About an hour ago Up About an hour k8s_coredns_coredns-f9fd979d6-7hm4z_kube-system_d7f88807-7a1b-4a83-867b-6cc8d9d4557b_2
0754ca7dafae k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_storage-provisioner_kube-system_69b7aff7-ed52-450b-8886-7662e5166c22_2
9c1a1303176f k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_coredns-f9fd979d6-7hm4z_kube-system_d7f88807-7a1b-4a83-867b-6cc8d9d4557b_2
913319017cfc d373dd5a8593 "/usr/local/bin/kube…" About an hour ago Up About an hour k8s_kube-proxy_kube-proxy-b7pnl_kube-system_f1dbeedd-0267-4d28-8d91-3a64ccad1f46_2
ae3deb3fc9c9 k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_kube-proxy-b7pnl_kube-system_f1dbeedd-0267-4d28-8d91-3a64ccad1f46_2
655d493156ee 0369cf4303ff "etcd --advertise-cl…" About an hour ago Up About an hour k8s_etcd_etcd-minikube_kube-system_5bf47183fef419a3373296d9f180a0b9_2
d1e86d25a77f 2f32d66b884f "kube-scheduler --au…" About an hour ago Up About an hour k8s_kube-scheduler_kube-scheduler-minikube_kube-system_ff7d12f9e4f14e202a85a7c5534a3129_2
72e006e2b202 607331163122 "kube-apiserver --ad…" About an hour ago Up About an hour k8s_kube-apiserver_kube-apiserver-minikube_kube-system_4d8688f08be9c141bacb3bd9e87b9ae5_2
0ec70066cfe6 8603821e1a7a "kube-controller-man…" About an hour ago Up About an hour k8s_kube-controller-manager_kube-controller-manager-minikube_kube-system_dcc127c185c80a61d90d8e659e768641_2
2d9e3f653304 k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_kube-controller-manager-minikube_kube-system_dcc127c185c80a61d90d8e659e768641_2
aec1dd9a5f44 k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_kube-scheduler-minikube_kube-system_ff7d12f9e4f14e202a85a7c5534a3129_2
29837fb95080 k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_kube-apiserver-minikube_kube-system_4d8688f08be9c141bacb3bd9e87b9ae5_2
8be268ad2daa k8s.gcr.io/pause:3.2 "/pause" About an hour ago Up About an hour k8s_POD_etcd-minikube_kube-system_5bf47183fef419a3373296d9f180a0b9_2
コンテナ内でのコンテナの稼働を初めて見ましたが、これを見ると、
echoserverのイメージを使ったコンテナが動いていることがわかりました。仮説はあっていたようです。
よく見るとPODという文字が書かれているコンテナがあり、Podをコンテナで表現しているのかな?と思いました。
kube-proxyのコンテナもあるようで、こいつがServiceのプロキシとして動いているものと思われます。
今回はここまでにしますが、
次回はもう少しKubernetesのアーキテクチャ周りの勉強と、設定を変えてどんな挙動をするのか見たいと思います。
参考
独学Kubernetes コンテナ開発の基本を最速で理解する
・すごくわかりやすかったです。