kubernetes
kubernetes
コンテナを管理,スケールさせるためのツール(コンテナオーケストレーションツール) https://kubernetes.io/docs/concepts/overview/#why-you-need-kubernetes-and-what-can-it-do
kubernetes では負荷分散やストレージオーケストレーション,セキュリティなどが機能としてある. 基本的に kubectl で kubernetes クラスタを操作する.
Contorol Plane は Node(Pod が実行されるマシンで,コンテナをまとめた単位)を制御する
Control Panel
- API server: kubernetes クラスタを操作するための REST interface を提供する.Pod やサービスに対する操作はエンドポイントでプログラムされている
- Scheduler: リソース容量を監視して,Node のパフォーマンスが最適になるように管理する
- Controller manager: Node がダウンしたなどのイベントに対して宣言との差異を確認する
- kubelet: コンテナが実行されていることを確認するために pod の状態を追跡する
- kube proxy: サービスから Node に流入するトラフィックを管理する
- etcd: クラスタの状態を保存する
Component
- Pod: コンテナをまとめるグループで,kubernetes の最小単位.Pod には IP アドレスが割り当てられていて,同じコンテナの Pod は同じリソース(メモリなど)を共有する.
- Deployment: Node 上で動く Pod の管理をする.希望する数の Pod を常に動かしておくなど
- Servise: 個々の Pod において,IP アドレスなど多くのものが生え変わりのたびに変化するので,このアドレスのルーティングなどを行う.Pods はユニークな存在ではないので,ダウンタイムを少なくする工夫が必要
- Ingress: 負荷分散.クラスタ外から来る通信をロードバランサによって制御する.制御されたトラフィックを service にルーティングする.
やってみる
とりあえず windwos に minikube をインストールする. 今回は virtualbox を使う
C:\k8s_play>kubectl get nodes
NAME STATUS ROLES AGE VERSION
minikube Ready control-plane 7d22h v1.27.3
よさそう. 次に pod を作成する manifest ファイルを作る
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx
C:\k8s_play>kubectl create -f pod-nginx.yaml
pod/nginx created
C:\k8s_play>kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx 1/1 Running 0 7s
C:\k8s_play>kubectl delete pod/nginx
pod "nginx" deleted
C:\k8s_play>kubectl get pod
No resources found in default namespace.
pod が変化しているのでよさそう.
manifest component
- spec: オブジェクトに期待する状態を決める.name は名前だし image は使うイメージ
- container onject
- command: コンテナで起動させたいプロセスを指定する.
- args: 特に引数を指定する(と思う)
- env: 環境変数を指定する
- image: コンテナイメージ
- name: コンテナ名
- ports: コンテナが開くポート
- workingDir: ワーキングディレクトリ
apiVersion: v1
kind: Pod
metadata:
name: nginx
spec:
containers:
- name: nginx
image: nginx:alpine
imagePullPolicy: Always
command: []
args: ["nginx", "-g", "daemon off;"]
args:
env:
- name: woot
value: wai
ports:
- containerPort: 80
protocol: TCP
workingDir: /tmp
C:\k8s_play>kubectl create -f pod-nginx.yaml
pod/nginx created
C:\k8s_play>kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx 0/1 ContainerCreating 0 3s
C:\k8s_play>kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx 1/1 Running 0 7s
C:\k8s_play>kubectl exec -- nginx ps
PID USER TIME COMMAND
1 root 0:00 nginx: master process nginx -g daemon off;
30 nginx 0:00 nginx: worker process
31 nginx 0:00 nginx: worker process
32 root 0:00 ps
C:\k8s_play>kubectl exec nginx -- env
...
woot=wai
...
Volume
コンテナはコンテナが削除されたり,再起動した場合に中身が消えてしまう. Volume はデータの永続化のために使う. また,コンテナ間のデータ共有にも使うことができる. クラウドみたいなものだろうか…
永続化に使う volume タイプにはいくつかある
- emptyDir: データの永続化には使えないが,コンテナ間のデータ共有に使う
- hostDir: データの永続化にも使える
volumes:
- name: log-volume
emptyDir:
emptyDir を使った volume を作って,これにコンテナを対応させる
volumeMounts:
- name: log-volume
mountPath: /var/log/date-tail
これで両方のコンテナから deta-tail が参照できるようになる. 全然関係ないけど大文字小文字分かりづらくて泣く,なんで語頭は小文字なんだ
init Container
pods の contaieners で指定したコンテナが起動する前に初期化する. 例えばあるコンテナ A でファイルが必要だが,もう一つのコンテナ B がその作成を担っているとき, A が先に起動してしまうとファイルが無くて失敗してしまうが,これを init Container で防ぐ.
Resource Requirements
pod は CPU や GPU リソースなど pod 内のコンテナに対してリソースの要求や制限を指定することができる 例えば以下
resources:
requests:
cpu: 4
memory: 128M
limits:
cpu: 0.5
memory: 64M
- 要求:コンテナで使いたいリソース量で,確保されていてほしい量
- 制限:コンテナで超えてほしくないリソース量
security context
pod やコンテナに対してアクセス制御やユーザの制限などを行うことができる. 例えば以下は volume のオーナーやパーミッションを指定することができる.
securityContext:
fsGroup: 1000
C:\k8s_play>kubectl apply -f nginx.yaml
pod/fsgroup-test created
C:\k8s_play>kubectl exec -it fsgroup-test -- ls -l /
/:
total 60
drwxr-xr-x 2 root root 4096 Aug 7 13:09 bin
drwxrwsrwx 2 root 1000 4096 Sep 3 10:15 data <--
drwxr-xr-x 5 root root 360 Sep 3 10:15 dev
drwxr-xr-x 1 root root 4096 Sep 3 10:15 etc
drwxr-xr-x 2 root root 4096 Aug 7 13:09 home
drwxr-xr-x 7 root root 4096 Aug 7 13:09 lib
drwxr-xr-x 5 root root 4096 Aug 7 13:09 media
drwxr-xr-x 2 root root 4096 Aug 7 13:09 mnt
drwxr-xr-x 2 root root 4096 Aug 7 13:09 opt
dr-xr-xr-x 257 root root 0 Sep 3 10:15 proc
drwx------ 2 root root 4096 Aug 7 13:09 root
drwxr-xr-x 1 root root 4096 Sep 3 10:15 run
drwxr-xr-x 2 root root 4096 Aug 7 13:09 sbin
drwxr-xr-x 2 root root 4096 Aug 7 13:09 srv
dr-xr-xr-x 12 root root 0 Sep 3 10:15 sys
drwxrwxrwt 2 root root 4096 Aug 7 13:09 tmp
drwxr-xr-x 7 root root 4096 Aug 7 13:09 usr
drwxr-xr-x 12 root root 4096 Aug 7 13:09 var
Deployment
Pod の rolling update や rollback などを行う. ReplicaSet を管理することで,Pod を指定された数(Replica 数)調整する. 足りない場合は追加し,多い場合は削除する. この仕組みで Node の障害やクラッシュで pod が足りなくなった場合も自動的に Pod が追加される.
Deployment はコンテナイメージのアップデートがあった場合に 新しい仕様の ReplicaSet を作成し,全体の Pod を調整しながら新しい仕様の Pod に置き換える (ローリングアップデート). Recreate の場合は全ての Pod を削除してから新しい Pod Template をもとに Pod を作成する.
selector:
matchLabels:
app: nginx
strategy:
rollingUpdate:
maxSurge: 50% # 複製数を超えていい許容量
maxUnavailable: 0%
template:
metadata:
labels:
app: nginx
C:\k8s_play>kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 1s
C:\k8s_play>kubectl get rs # ReplicaSet
NAME DESIRED CURRENT READY AGE
nginx-77b4fdf86c 2 2 2 9s
C:\k8s_play>kubectl get po # Pod
NAME READY STATUS RESTARTS AGE
nginx-77b4fdf86c-qkmz2 1/1 Running 0 15s
nginx-77b4fdf86c-rdfv5 1/1 Running 0 15s
manifest の内容を変えて更新してみる
C:k8s_play>kubectl apply -f nginx.yaml
deployment.apps/nginx configured
C:k8s_play>kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 0 2 2m9s
C:k8s_play>kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-77b4fdf86c 2 2 2 2m22s
C:k8s_play>kubectl get po # pause で止めているので特に変化はない
NAME READY STATUS RESTARTS AGE
nginx-77b4fdf86c-qkmz2 1/1 Running 0 2m35s
nginx-77b4fdf86c-rdfv5 1/1 Running 0 2m35s
C:k8s_play>kubectl rollout resume deploy nginx
deployment.apps/nginx resumed
C:k8s_play>kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 3m45s
C:k8s_play>kubectl get rs # 77b4fdf86c -> 7544d696d4
NAME DESIRED CURRENT READY AGE
nginx-7544d696d4 2 2 2 28s
nginx-77b4fdf86c 0 0 0 3m51s
C:k8s_play>kubectl get po # 完全に置き換わっている
NAME READY STATUS RESTARTS AGE
nginx-7544d696d4-6s2tb 1/1 Running 0 25s
nginx-7544d696d4-bqblr 1/1 Running 0 29s
C:k8s_play>kubectl rollout history deploy nginx
deployment.apps/nginx
REVISION CHANGE-CAUSE
1 <none>
2 <none>
下記は rollout しているときのログ 旧:qkmz2 旧:rdfv5 新:6s2tb 新:bqblr
C:\k8s_play> kubectl get po -w
NAME READY STATUS RESTARTS AGE
nginx-77b4fdf86c-qkmz2 1/1 Running 0 3m8s
nginx-77b4fdf86c-rdfv5 1/1 Running 0 3m8s # <- 旧が動いている
nginx-7544d696d4-bqblr 0/1 Pending 0 0s # <- 新が用意される
nginx-7544d696d4-bqblr 0/1 Pending 0 0s
nginx-7544d696d4-bqblr 0/1 ContainerCreating 0 0s
nginx-7544d696d4-bqblr 1/1 Running 0 3s # <- maxSurge が 50% なので新しいものが一つ追加される
nginx-77b4fdf86c-qkmz2 1/1 Terminating 0 3m26s # <- 旧が一つ止まる
nginx-7544d696d4-6s2tb 0/1 Pending 0 0s # <- 新が用意される
nginx-7544d696d4-6s2tb 0/1 Pending 0 0s
nginx-7544d696d4-6s2tb 0/1 ContainerCreating 0 0s
nginx-77b4fdf86c-qkmz2 0/1 Terminating 0 3m27s
nginx-77b4fdf86c-qkmz2 0/1 Terminating 0 3m28s
nginx-77b4fdf86c-qkmz2 0/1 Terminating 0 3m28s
nginx-77b4fdf86c-qkmz2 0/1 Terminating 0 3m28s
nginx-7544d696d4-6s2tb 1/1 Running 0 3s
nginx-77b4fdf86c-rdfv5 1/1 Terminating 0 3m30s
nginx-77b4fdf86c-rdfv5 0/1 Terminating 0 3m30s
nginx-77b4fdf86c-rdfv5 0/1 Terminating 0 3m31s
nginx-77b4fdf86c-rdfv5 0/1 Terminating 0 3m31s
nginx-77b4fdf86c-rdfv5 0/1 Terminating 0 3m31s
rollback する
C:\k8s_play>kubectl rollout undo deploy nginx --to-revision 1
deployment.apps/nginx rolled back
C:\k8s_play>kubectl get deploy
NAME READY UP-TO-DATE AVAILABLE AGE
nginx 2/2 2 2 9m55s
C:\k8s_play>kubectl get rs
NAME DESIRED CURRENT READY AGE
nginx-7544d696d4 0 0 0 6m33s
nginx-77b4fdf86c 2 2 2 9m56s
C:\k8s_play>kubectl get po
NAME READY STATUS RESTARTS AGE
nginx-77b4fdf86c-6b7sm 1/1 Running 0 14s
nginx-77b4fdf86c-fbwgf 1/1 Running 0 10s
ちゃんと古い ReplicaSet を使っている
nginx-77b4fdf86c-6b7sm 0/1 Pending 0 0s
nginx-77b4fdf86c-6b7sm 0/1 Pending 0 0s
nginx-77b4fdf86c-6b7sm 0/1 ContainerCreating 0 1s
nginx-77b4fdf86c-6b7sm 1/1 Running 0 4s
nginx-7544d696d4-bqblr 1/1 Terminating 0 6m24s
nginx-77b4fdf86c-fbwgf 0/1 Pending 0 0s
nginx-77b4fdf86c-fbwgf 0/1 Pending 0 0s
nginx-77b4fdf86c-fbwgf 0/1 ContainerCreating 0 0s
nginx-7544d696d4-bqblr 0/1 Terminating 0 6m25s
nginx-7544d696d4-bqblr 0/1 Terminating 0 6m25s
nginx-7544d696d4-bqblr 0/1 Terminating 0 6m25s
nginx-7544d696d4-bqblr 0/1 Terminating 0 6m25s
nginx-77b4fdf86c-fbwgf 1/1 Running 0 3s
nginx-7544d696d4-6s2tb 1/1 Terminating 0 6m23s
nginx-7544d696d4-6s2tb 0/1 Terminating 0 6m24s
nginx-7544d696d4-6s2tb 0/1 Terminating 0 6m24s
nginx-7544d696d4-6s2tb 0/1 Terminating 0 6m24s
nginx-7544d696d4-6s2tb 0/1 Terminating 0 6m24s
Service
Pod への接続に関して負荷分散などをするオブジェクト.
- clusterIP: kubernetes 内の通信で利用することができ,クラスタ内で IP アドレスが払い出され,それを利用して Pod 間の通信を行う.
- NodePort: Node のランダムなポートを使って外部サーバとの通信を行う
- LoadBalancer: NodePort の service を作成し,外部の LoadBalancer で転送をしてもらう
- ExternalName: 外部のサービスに対してエイリアスを作成する
下記はserviceの例で,適当な Pod と 適当な Pod で通信する.
spec:
selector:
app: nginx
ports:
- port: 80
selector:
app: nginx
ports:
- port: 80
type: NodePort
C:\k8s_play> kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx-55f598f8d-8r8cv 1/1 Running 0 2m20s
pod/nginx-55f598f8d-jp76l 1/1 Running 0 2m20s
pod/nginx-55f598f8d-q5v7r 1/1 Running 0 2m20s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 2m27s
service/nginx ClusterIP 10.101.95.207 <none> 80/TCP 74s
service/nginx-np NodePort 10.111.133.95 <none> 80:30626/TCP 14s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/nginx 3/3 3 3 2m20s
NAME DESIRED CURRENT READY AGE
replicaset.apps/nginx-55f598f8d 3 3 3 2m20s
C:\k8s_play> kubectl run alpine -it --rm --image alpine -- ash
If you don't see a command prompt, try pressing enter.
/ # env
...
NGINX_NP_SERVICE_HOST=10.111.133.95 <- 一緒
...
NGINX_SERVICE_HOST=10.101.95.207 <- 一緒
...
/ # wget -O - $NGINX_SERVICE_HOST
Connecting to 10.101.95.207 (10.101.95.207:80)
writing to stdout
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the ng
ヘルスチェック
-
LivenessProbe: コンテナの生存チェックをする.これが通らない場合は再生成される.
-
ReadinessProbe: コンテナの Ready 状態をチェックする.init や 処理中でリクエストが返せない場合に対応する.
-
exec: コンテナ内でコマンドを実行できる.この終了ステータスが 0 なら healthy ということになる.
-
httpGet: HTTP の GET リクエストを発行する.レスポンスステータスで判断する
-
topSocket: TCP コネクションが開けるかチェックする.
livenessProbe:
httpGet:
port: 80
path: /
Liveness: http-get http://:80/ delay=0s timeout=1s period=5s #success=1 #failure=5
index.html を消した場合
Warning Unhealthy 1s (x6 over 26s) kubelet Liveness probe failed: HTTP probe failed with statuscode: 403 <- http ステータスコード