Kubernetes 初心者の超簡単まとめ

Dec 18, 2017 23:29 · 3438 words · 7 minutes read #kubernetes

kubernetes.png

はじめに

Docker が Kubernetes と統合すると発表したり、最近なにかとバズってたりしていて、ホットな感じがしたので、社内外の勉強会に参加してなんとなく覚えたことを書き殴っておこうと思います。

Kubernetes ってなに?

コンテナオーケストレーションツール。

コンテナで稼働するアプリケーションを良い感じに管理してくれるもので DockerSwarm とか AmazonECS と雰囲気は同じ。Google が開発を始めて、現在は CNCF(Cloud Native Computing Foundation)が主導で開発を行っている。インターネット上だと Kubernetes だと長くて打つのだるいから k8s と表記してる人が多い。

とりあえず kubernetes.io に詳しいことは書かれているので一読したほうが良いかも。

Kubernetes is an open-source system for automating deployment, scaling, and management of containerized applications.

先日 Publickey で公開されていた記事(Dockerコンテナ時代の第一章の終わり、そして第二章の展望など)も歴史がまとまってて結構わかりやすかった。

とりあえず覚えた用語

関係がわかるように画像にまとめた方が良いんだけど面倒なのでとりあえず列挙してく

k8s Objects

  • k8s の機能の構成要素
  • k8s Control Plane から後に紹介するものは全て k8s Objects

k8s Control Plane

  • k8s Objects を実現するためにマシン上で稼働するプロセス群
  • k8s cluster のネットワークを構成している

Node

  • k8s cluster を構成するマシン
  • クラスタの管理を行うのがマスターノード
  • アプリを稼働させるのがメンバーノード

Pod

  • Node内で稼働するコンテナのグループ
  • アプリケーションを動かすための最小単位(1つ以上のコンテナで構成される)
  • Pod内のコンテナは同一ホスト上で稼働
  • 1つのPodに1つのクラスター内IPが割り当てられる

Service

  • Pod へのルーティングとロードバランシングを行う
  • クラスター内外の通信を行うために複数のタイプがある

Label

  • k8s objects(Podとか)に key/value で付与されるメタデータ的なやつ

Label Selector

  • Label の条件を指定してグルーピングすることが出来る
  • Service がルーティングするためにも使われる

Deployment

  • 言葉そのままでデプロイに使うオブジェクト
  • Pod を制御することが出来る
  • Pod を起動したりスケールさせたり破棄したり

ReplicaSet

  • Pod を指定された数に調整する仕組み
  • Pod がレプリカ数より足りない場合には追加、多い場合は削除
  • Deployment の際にコンテナイメージのバージョンアップがあったら新しい ReplicaSet が生成されて新旧のPod数が調整されながらローリングアップグレードがなされる(めっちゃお利口)

DaemonSet

  • 全てのメンバーノードに共通の Pod を稼働させる仕組み
  • Node が追加されると追加されたノードで自動起動
  • Node で共通な機能を提供したいときに利用(fluentd とか)

ここからは実際にコマンドを実行して k8s cluster を制御してみる

kubectl による k8s cluster の操作

k8s cluster の操作は kubectl という CLI で行う。内部的にはコマンドを k8s の REST API を呼び出しているだけみたい。直接 REST API も叩けるらしい。

ちなみに「キューブコントロール」と発音する → Tim Hockin pronounces kubectl

$ kubectl version

クライアントとサーバーのバージョンが確認できる
コマンドの結果から v1.7.10 で稼働していることがわかる。
ちなみに 2017年12月19日時点 での最新バージョンは v1.9.0 。
https://github.com/kubernetes/kubernetes/releases

$ kubectl version
Client Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.10", GitCommit:"bebdeb749f1fa3da9e1312c4b08e439c404b3136", GitTreeState:"clean", BuildDate:"2017-11-03T17:13:44Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"7", GitVersion:"v1.7.10", GitCommit:"bebdeb749f1fa3da9e1312c4b08e439c404b3136", GitTreeState:"clean", BuildDate:"2017-11-03T16:31:49Z", GoVersion:"go1.8.3", Compiler:"gc", Platform:"linux/amd64"}

$ kubectl get nodes

k8s cluster を構成する Node が確認できる
今回は検証用にマスターノード1台・メンバーノード2台の計3台構成にしてみた。
↓ を git clone して vagrant up したら同じ構成ですぐに k8s cluster を構築できるのでオススメです。
https://github.com/pires/kubernetes-vagrant-coreos-cluster

$ kubectl get nodes
NAME           STATUS                     AGE       VERSION
172.17.8.101   Ready,SchedulingDisabled   5h        v1.7.10
172.17.8.102   Ready                      5h        v1.7.10
172.17.8.103   Ready                      5h        v1.7.10

$ kubectl cluster-info

k8s cluster に関する情報を確認できる
コマンドの結果からマスターノードが 172.17.8.101 で KubeDNS がどの endpoint を提供しているのか把握することができます。

$ kubectl cluster-info
Kubernetes master is running at https://172.17.8.101
KubeDNS is running at https://172.17.8.101/api/v1/namespaces/kube-system/services/kube-dns/proxy

To further debug and diagnose cluster problems, use 'kubectl cluster-info dump'.

$ kubectl run

アプリケーションをデプロイできる
Pod を制御するための Deployment が作成され Pod が生成される
今回は DockeHub で公開されている kubernetes-bootcamp というイメージを利用しています。

$ kubectl run kubernetes-bootcamp --image=docker.io/jocatalin/kubernetes-bootcamp:v1 --port=8080
deployment "kubernetes-bootcamp" created

$ kubectl get deployments

Deployment Objects が確認できる

$ kkubectl get deployment
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   1         1         1            0           4s

$ kubectl get pods

Pod を確認できる

$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-2457653786-3b77j   1/1       Running   0          1m

$ kubectl describe

k8s Objects の詳細を確認することができる
Deployment Object とか Service Object とか k8s Objects ならなんでも。
/ で区切らないと関連する全ての k8s Objects が出力されます。

$ kubectl describe deployments/kubernetes-bootcamp
Name:			kubernetes-bootcamp
Namespace:		default
CreationTimestamp:	Tue, 19 Dec 2017 00:43:45 +0900
Labels:			run=kubernetes-bootcamp
Annotations:		deployment.kubernetes.io/revision=1
Selector:		run=kubernetes-bootcamp
Replicas:		1 desired | 1 updated | 1 total | 1 available | 0 unavailable
StrategyType:		RollingUpdate
MinReadySeconds:	0
RollingUpdateStrategy:	1 max unavailable, 1 max surge
Pod Template:
  Labels:	run=kubernetes-bootcamp
  Containers:
   kubernetes-bootcamp:
    Image:		docker.io/jocatalin/kubernetes-bootcamp:v1
    Port:		8080/TCP
    Environment:	<none>
    Mounts:		<none>
  Volumes:		<none>
Conditions:
  Type		Status	Reason
  ----		------	------
  Available 	True	MinimumReplicasAvailable
OldReplicaSets:	<none>
NewReplicaSet:	kubernetes-bootcamp-2457653786 (1/1 replicas created)
Events:
  FirstSeen	LastSeen	Count	From			SubObjectPath	Type		Reason			Message
  ---------	--------	-----	----			-------------	--------	------			-------
  3m		3m		1	deployment-controller			Normal		ScalingReplicaSet	Scaled up replica set kubernetes-bootcamp-2457653786 to 1

$ kubectl proxy

Pod(コンテナ)を公開するためのプロキシを起動できる
内部的には kubectl が認証なしのAPIエンドポイントとして生成してリクエストを受けたら Pod(コンテナ)にプロキシする感じ。 さくっと動作を確認するのには良いかも。プロキシを起動したことで Pod(コンテナ)へのリクエストを投げることが出来た

# 127.0.0.1:8001 でアクセスできることがわかる
$ kubectl proxy
Starting to serve on 127.0.0.1:8001

# 様々なエンドポイントが提供されている
$ curl http://localhost:8001/version
{
  "major": "1",
  "minor": "7",
  "gitVersion": "v1.7.10",
  "gitCommit": "bebdeb749f1fa3da9e1312c4b08e439c404b3136",
  "gitTreeState": "clean",
  "buildDate": "2017-11-03T16:31:49Z",
  "goVersion": "go1.8.3",
  "compiler": "gc",
  "platform": "linux/amd64"
}

# Pod name を取得する
$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-2457653786-3b77j   1/1       Running   0          8m

# Pod へのアクセスができた(http://localhost:8001/api/v1/proxy/namespaces/[pod name]/)
$ curl http://localhost:8001/api/v1/proxy/namespaces/default/pods/kubernetes-bootcamp-2457653786-3b77j/
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-2457653786-3b77j | v=1

$ kubectl logs [pod name]

Pod(コンテナ)のログを確認できる

# Pod name を取得する
$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-2457653786-3b77j   1/1       Running   0          10m

# -f を付けると following も可能
$ kubectl logs kubernetes-bootcamp-2457653786-3b77j
Kubernetes Bootcamp App Started At: 2017-12-18T15:44:03.637Z | Running On:  kubernetes-bootcamp-2457653786-3b77j

Running On: kubernetes-bootcamp-2457653786-3b77j | Total Requests: 1 | App Uptime: 518.311 seconds | Log Time: 2017-12-18T15:52:41.948Z

$ kubectl exec [pod name] [command]

Pod(コンテナ)に対してコマンドを実行できる
以下の例は環境変数を出力した結果。

$ kubectl exec kubernetes-bootcamp-2457653786-3b77j env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
HOSTNAME=kubernetes-bootcamp-2457653786-3b77j
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT=tcp://10.100.0.1:443
KUBERNETES_PORT_443_TCP=tcp://10.100.0.1:443
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT_443_TCP_ADDR=10.100.0.1
KUBERNETES_SERVICE_HOST=10.100.0.1
NPM_CONFIG_LOGLEVEL=info
NODE_VERSION=6.3.1
HOME=/root

-it のオプションを付与して /bin/bash を実行すれば Pod(コンテナ)の中に入ることも可能

$ kubectl exec -it kubernetes-bootcamp-2457653786-3b77j /bin/bash

root@kubernetes-bootcamp-2457653786-3b77j:/# cat /etc/os-release
PRETTY_NAME="Debian GNU/Linux 8 (jessie)"
NAME="Debian GNU/Linux"
VERSION_ID="8"
VERSION="8 (jessie)"
ID=debian
HOME_URL="http://www.debian.org/"
SUPPORT_URL="http://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

$ kubectl expose [deployment object]

Pod(コンテナ)へのルーティングとロードバランシングを行うための Service Object が作成できる
–type で色々選択できるみたい。今回は NodePort タイプで各Pod(コンテナ)に 8080 で LISTEN する形にする

$ kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080
service "kubernetes-bootcamp" exposed

$ kubectl get services

Service Object を確認できる
コマンドの結果から各Nodeの 31045 Port からアプリケーションにアクセスできるかがわかる。
内部的には各Nodeが 31045 Port でリクエストを受け取って各Pod(コンテナ)にルーティングしてる感じ。

# Service Object が生成されていることがわかる
$ kubectl get services
NAME                  CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            10.100.0.1      <none>        443/TCP          6h
kubernetes-bootcamp   10.100.117.91   <nodes>       8080:31045/TCP   49s

# 詳細な情報をみたいときは kubectl describe
$ kubectl describe services/kubernetes-bootcamp
Name:			kubernetes-bootcamp
Namespace:		default
Labels:			run=kubernetes-bootcamp
Annotations:		<none>
Selector:		run=kubernetes-bootcamp
Type:			NodePort
IP:			10.100.117.91
Port:			<unset>	8080/TCP
NodePort:		<unset>	31045/TCP <--- 各Nodeがどの Port で LISTEN しているか
Endpoints:		10.244.36.2:8080
Session Affinity:	None
Events:			<none>

# 各Node の IP
$ kubectl get nodes
NAME           STATUS                     AGE       VERSION
172.17.8.101   Ready,SchedulingDisabled   6h        v1.7.10
172.17.8.102   Ready                      6h        v1.7.10
172.17.8.103   Ready                      6h        v1.7.10

# 各Node の 31045 Port にアクセスすることで Pod(コンテナ)にルーティングされていることがわかる
$ curl http://172.17.8.101:31045
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-2457653786-3b77j | v=1
$ curl http://172.17.8.102:31045
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-2457653786-3b77j | v=1
$ curl http://172.17.8.103:31045
Hello Kubernetes bootcamp! | Running on: kubernetes-bootcamp-2457653786-3b77j | v=1

$ kubectl scale [deployment object]

Pod(コンテナ)をスケールさせることができる

# スケール前
$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-2457653786-3b77j   1/1       Running   0          37m

# Pod を 4つ にスケールアウト
$ kubectl scale deployments/kubernetes-bootcamp --replicas=4
deployment "kubernetes-bootcamp" scaled

# スケールアウトされて Pod が 4つ になった
$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-2457653786-3b77j   1/1       Running   0          38m
kubernetes-bootcamp-2457653786-lms34   1/1       Running   0          24s
kubernetes-bootcamp-2457653786-mmxbc   1/1       Running   0          24s
kubernetes-bootcamp-2457653786-pvhcp   1/1       Running   0          24s

# Pod を 2つ にスケールイン
$ kubectl scale deployments/kubernetes-bootcamp --replicas=2
deployment "kubernetes-bootcamp" scaled

# 余計な 2つ の Pod が停止している様子
$ kubectl get pods
NAME                                   READY     STATUS        RESTARTS   AGE
kubernetes-bootcamp-2457653786-3b77j   1/1       Running       0          38m
kubernetes-bootcamp-2457653786-lms34   1/1       Running       0          58s
kubernetes-bootcamp-2457653786-mmxbc   0/1       Terminating   0          58s
kubernetes-bootcamp-2457653786-pvhcp   0/1       Terminating   0          58s

# スケールインされて Pod が 2つ になった
$ kubectl get pods
NAME                                   READY     STATUS    RESTARTS   AGE
kubernetes-bootcamp-2457653786-3b77j   1/1       Running   0          39m
kubernetes-bootcamp-2457653786-lms34   1/1       Running   0          1m

$ kubectl delete [service|deployment|pod] [name]

k8s Object を削除する
以下のように k8s Object を削除することが可能です。ちなみに Deployment を削除せずに Pod を削除しようとすると、延々と Pod が復活する様子を眺められるので試してみると面白いです。ReplicaSet が機能して自動でレプリカ数が調整されてとてもお利口な感じです。

# Service の削除
$ kubectl get service
NAME                  CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
kubernetes            10.100.0.1      <none>        443/TCP          7h
kubernetes-bootcamp   10.100.117.91   <nodes>       8080:31045/TCP   48m

$ kubectl delete service kubernetes-bootcamp
service "kubernetes-bootcamp" deleted

$ kubectl get service
NAME         CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   10.100.0.1   <none>        443/TCP   7h

# Deployment の削除
$ kubectl get deployment
NAME                  DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
kubernetes-bootcamp   2         2         2            2           1h

$ kubectl delete deployment kubernetes-bootcamp
deployment "kubernetes-bootcamp" deleted

$ kubectl get deployment
No resources found.

# Deployment を削除すると Pod も自動で削除される
$ kubectl get pod
NAME                                   READY     STATUS        RESTARTS   AGE
kubernetes-bootcamp-2457653786-j1czw   0/1       Terminating   0          2m

$ kubectl get pod
No resources found.

所感

ここまで一通り用語を覚えて、手を動かしたらなんとなく k8s の操作を理解できた気がする。
Production で使うならもっと覚えないといけないこと・気をつけないといけないとこあるんだろうけど(小声)

まあ普段業務で Docker を使っているし、Docker Swarm も少しだけかじってたから意外とすんなり入門できた印象もありました。より内部の仕組みを知っていくためにも更に踏み込んで学んでいかないとなあと思ったので、引き続き k8s で遊んでいきたいと思います!次はローカルじゃなくてクラウド上に k8s cluster を構築したりして遊ぶのもいいかも \(^o^)/

今後コンテナオーケストレーションツールとして標準となっていくみたいなので、波に乗り遅れない程度にはアンテナを張っておきます!!!