kubernetes

Kubernetes覚え書き

More than 1 year has passed since last update.


概要

Kubernetesが難しいので調べたことを順次覚え書き的に書いていきます。

役割
IPアドレス

master
10.136.3.183

node1
10.136.3.184

node2
10.136.3.185


  • 名前解決は利用せず、IPアドレスのみ使う

  • masterはmaster nodeと呼ばれることもある

  • nodeはworker nodeと呼ばれる


    • 昔はminionとも呼ばれていた(今も?)




インストールの流れ



  • 順番


    • etcd (masterのみ)


      • masterとは別のetcdサーバでも問題ないが、masterに入れられる事がほとんど

      • nodeはetcdサーバから情報を取得するだけなのでnode自体にetcdは入って無くても良い



    • flanneld

    • docker

    • kubernetes




  • etcd (masterのみ)


    • /etc/etcd/etcd.conf

    • ETCD_LISTEN_CLIENT_URLS="http://10.136.3.183:2379,http://localhost:2379"

    • ETCD_ADVERTISE_CLIENT_URLS="http://localhost:2379"




  • flanneld


    • /etc/sysconfig/flanneld (master,node共通)


      • FLANNEL_ETCD_ENDPOINTS="http://10.136.3.183:2379"

      • FLANNEL_ETCD_PREFIX="/flannel/network"






etcdについて


  • 分散Key-Valuesストアを使い各種設定をノード間で共有するメカニズム


    • Key-Valuesストアデータは、ディレクトリ構造(=パス)で管理されている

    • Linuxの実際のディレクトリは別物。あくまでディレクトリ構造で管理されているということ



  • Kubernetesでの用途


    • flannelやSkyDNS、その他関連コンポーネントのデータストア




コマンドで確認

インストールとmaster,nodeの構築が終わっている状態で確認。ネットワーク以外にコンテナの情報もetcdで管理されているようだが簡単のためにここでは書かない。

### インストール時、以下のコマンドでconfigを作成済み

$ sudo /usr/bin/etcdctl mk /flannel/network/config {"Network":"172.17.0.0/16"}

[10.136.3.183(master)]

### 状態の確認
$ etcdctl cluster-health
================================================
member 8e9e05c52164694d is healthy: got healthy result from http://localhost:2379
cluster is healthy
================================================
-> memberはmasterのみ

### ディレクトリ構造の確認
$ etcdctl ls
================================================
/flannel
================================================

$ etcdctl ls /flannel --recursive -p
================================================
/flannel/network/
/flannel/network/config
/flannel/network/subnets/
/flannel/network/subnets/172.17.3.0-24
/flannel/network/subnets/172.17.67.0-24
/flannel/network/subnets/172.17.98.0-24
================================================
--recursive : 再帰的に表示
-p : ディレクトリの場合は後ろに「/」が付く

### キーバリューの確認
$ etcdctl get /flannel/network/config
================================================
{"Network":"172.17.0.0/16"}
================================================
-> このレンジのアドレスが各ホストにアサインされる

$ etcdctl get /flannel/network/subnets/172.17.3.0-24
================================================
{"PublicIP":"10.136.3.184"}
================================================
-> 10.136.3.184のホストはこのIPレンジがアサインされる

$ etcdctl get /flannel/network/subnets/172.17.67.0-24
================================================
{"PublicIP":"10.136.3.185"}
================================================

$ etcdctl get /flannel/network/subnets/172.17.98.0-24
================================================
{"PublicIP":"10.136.3.183"}
================================================

### nodeで値を取得
[10.136.3.184(node1)]
$ curl http://10.136.3.183:2379/v2/keys
================================================
{"action":"get","node":{"dir":true,"nodes":[{"key":"/flannel","dir":true,"modifiedIndex":4,"createdIndex":4}]}}
================================================

$ curl http://10.136.3.183:2379/v2/keys/flannel/network/subnets/172.17.3.0-24 | jq
================================================
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 214 100 214 0 0 199k 0 --:--:-- --:--:-- --:--:-- 208k
{
"action": "get",
"node": {
"key": "/flannel/network/subnets/172.17.3.0-24",
"value": "{\"PublicIP\":\"10.136.3.184\"}",
"expiration": "2017-04-22T09:47:54.099017257Z",
"ttl": 21188,
"modifiedIndex": 2425,
"createdIndex": 2425
}
}
================================================

-> valueのホストにkeyのレンジがアサインされる


参考


flanneldについて


  • flanneldが無い場合


    • あるホストで稼働するコンテナに、別のホストで稼働しているコンテナからブリッジネットワーク経由でアクセスできない


      • docker network lsでbridgeと表示されるネットワーク

      • docker0(よくある172.17.〜)のネットワーク





  • flanneldは各ホストで起動しているデーモンプロセス


    • flanneldにより各コンテナで一意なアドレスを持つようにできる

    • ホスト間のコーディネーションのような仕組みではない


      • 同じデータストアでルーティングテーブルを共有しているだけ

      • データストアはetcdが使われることが多い





  • flanneldのネットワークはプライベートなアドレス


    • Kubernetesの外側からは叩け無い

    • Kubernetesのサービスのネットワークも別物


      • これもKubernetesの外側からは叩けない(そもそもifocnfigやipで確認できない)






コマンドで確認

etcdで確認したものと同じネットワークがそれぞれのホストに割り当てられている

[10.136.3.183(master)]

$ cat /run/flannel/docker
================================================
DOCKER_OPT_BIP="--bip=172.17.98.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_MTU="--mtu=1472"
DOCKER_NETWORK_OPTIONS=" --bip=172.17.98.1/24 --ip-masq=true --mtu=1472"
================================================

$ cat /run/flannel/subnet.env
================================================
FLANNEL_NETWORK=172.17.0.0/16
FLANNEL_SUBNET=172.17.98.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
================================================

$ ip a
================================================
...
3: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN qlen 500
link/none
inet 172.17.98.0/16 scope global flannel0
valid_lft forever preferred_lft forever
4: docker0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN
link/ether 02:42:d6:c1:17:ba brd ff:ff:ff:ff:ff:ff
inet 172.17.98.1/24 scope global docker0
valid_lft forever preferred_lft forever
================================================

$ netstat -rn
================================================
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.136.2.3 0.0.0.0 UG 0 0 0 eno16780032
10.136.0.0 0.0.0.0 255.255.128.0 U 0 0 0 eno16780032
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel0
172.17.98.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
================================================

[10.136.3.184(node1)]
$ cat /run/flannel/docker
================================================
DOCKER_OPT_BIP="--bip=172.17.3.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_MTU="--mtu=1472"
DOCKER_NETWORK_OPTIONS=" --bip=172.17.3.1/24 --ip-masq=true --mtu=1472"
================================================

$ cat /run/flannel/subnet.env
================================================
FLANNEL_NETWORK=172.17.0.0/16
FLANNEL_SUBNET=172.17.3.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
================================================

$ ip a
================================================
3: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN qlen 500
link/none
inet 172.17.3.0/16 scope global flannel0
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1472 qdisc noqueue state UP
link/ether 02:42:b3:f5:03:12 brd ff:ff:ff:ff:ff:ff
inet 172.17.3.1/24 scope global docker0
valid_lft forever preferred_lft forever
================================================

$ netstat -rn
================================================
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.136.2.3 0.0.0.0 UG 0 0 0 eno16780032
10.136.0.0 0.0.0.0 255.255.128.0 U 0 0 0 eno16780032
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel0
172.17.3.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
================================================

[10.136.3.185(node2)]
$ cat /run/flannel/docker
================================================
DOCKER_OPT_BIP="--bip=172.17.67.1/24"
DOCKER_OPT_IPMASQ="--ip-masq=true"
DOCKER_OPT_MTU="--mtu=1472"
DOCKER_NETWORK_OPTIONS=" --bip=172.17.67.1/24 --ip-masq=true --mtu=1472"
================================================

$ cat /run/flannel/subnet.env
================================================
FLANNEL_NETWORK=172.17.0.0/16
FLANNEL_SUBNET=172.17.67.1/24
FLANNEL_MTU=1472
FLANNEL_IPMASQ=false
================================================

$ ip a
================================================
3: flannel0: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1472 qdisc pfifo_fast state UNKNOWN qlen 500
link/none
inet 172.17.67.0/16 scope global flannel0
valid_lft forever preferred_lft forever
4: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1472 qdisc noqueue state UP
link/ether 02:42:2c:d9:cf:88 brd ff:ff:ff:ff:ff:ff
inet 172.17.67.1/24 scope global docker0
valid_lft forever preferred_lft forever
================================================

$ netstat -rn
================================================
Kernel IP routing table
Destination Gateway Genmask Flags MSS Window irtt Iface
0.0.0.0 10.136.2.3 0.0.0.0 UG 0 0 0 eno16780032
10.136.0.0 0.0.0.0 255.255.128.0 U 0 0 0 eno16780032
172.17.0.0 0.0.0.0 255.255.0.0 U 0 0 0 flannel0
172.17.67.0 0.0.0.0 255.255.255.0 U 0 0 0 docker0
================================================

### master(10.136.3.183)からnode2(10.136.3.185)のコンテナ(172.17.67.2)に疎通確認
[10.136.3.183]
$ ping 172.17.67.2
================================================
PING 172.17.67.2 (172.17.67.2) 56(84) bytes of data.
64 bytes from 172.17.67.2: icmp_seq=1 ttl=61 time=0.574 ms
64 bytes from 172.17.67.2: icmp_seq=2 ttl=61 time=0.422 ms
64 bytes from 172.17.67.2: icmp_seq=3 ttl=61 time=0.256 ms
================================================

## 参考


Kubernetesについて

コンテナ型仮想化のDockerを管理するフレームワーク


  • Kubernetesがやること


    • 複数のコンテナをデプロイ


      • どのホストにどのコンテナを配備するかを隠蔽



    • コンテナ間のネットワーク管理(名前空間含む)


      • サービスディスカバリ相当



    • コンテナの死活管理


      • コンテナが死んだら自動で起動



    • コンテナの負荷分散


      • 同一機能の複数コンテナへのアクセスをバランシング



    • コンテナのリソースアロケーション


      • コンテナ毎にCPUやメモリのわりあて





  • ひとつのプロセスで動くプロセスの数を最小限にして、代わりにコンテナ群を管理する


    • 理屈で言えばコンテナは1つのOS相当なので複数のサービスを動かす事ができる

    • 簡易化のためにここでは1コンテナ1プロセス




用語


  • Pod


    • 1つ以上のコンテナの集まり

    • 複数のコンテナがある場合は共有されたボリュームも管理する

    • Pod内のコンテナは必ず同じホスト

    • Label


      • Podにつけるラベル

      • 例) Production、Development、Staging、Frontend、Backendなど

      • 複数ラベルが付けられる





  • ReplicaSet


    • Podを生成、管理する


      • PodTemplateから指定された数のレプリカを作成して維持する

      • 起動中のPodの監視をしていて何らかの原因でPodが減ったり増えたりしたら、元の数に戻す



    • Replication Controllerの後継



  • Deployment


    • ReplicaSetを生成、管理

    • デプロイ管理


      • ローリングアップデート


        • 古いバージョンのコンテナから新しいバージョンのコンテナに徐々に置き換えていくなど

        • 新旧のPod共に共通するラベルを持っており、Serviceを通して新旧混ざった状態でサービスを提供できる



      • ロールバック


        • ローリングアップデート後もアップデート前のReplicaSetは一定数保持される





    • Kubernetes: Deployment の仕組み



  • Service


    • L3のプロキシみたいな役割

    • 設定したPodにラウンドロビンでアクセスを分配する




コンポーネント


  • master


    • kube-apiserver


      • Kubernetesのリソースを管理するAPIサーバー



    • etcd

    • kube-controller-manager


      • 各種コントローラーを起動し管理するマネージャー

      • Node Controller: ノードが落ちたときにアラートを出したら何か処理をする

      • Replication Controller: Podがちゃんと定められた数稼働しているかなどを管理する

      • Endpoints Controller: エンドポイントを移したりする

      • Service Account & Token Controllers: デフォルトアカウントを作ったり新しいnamespaceにアクセストークンを作ったりする



    • cloud-controller-manager


      • クラウドプロバイダとやりとりするマネージャー

      • Kubernetes 1.6から



    • kube-scheduler


      • Podのノードへの割り当てを行うスケジューラー



    • DNS



  • node


    • kubelet


      • Podを起動し管理するエージェント(Nodeのメイン処理)



    • kube-proxy


      • KubernetesのServiceが持つ仮想的なIPアドレス(cluster IP)へのアクセスをルーティングする





  • client


    • kubectl


      • KubernetesのCLIクライアント






コマンド


Deployment関連

レプリカセット
デプロイリビジョン
nginxのバージョン

rs/deployment-example-2748039730
1
1.10

rs/deployment-example-2829304371
2
1.11

デプロイ

### --record : kubectlのコマンドをアノテーションに保存

$ kubectl create -f deployment-example.yaml --record
================================================
deployment "deployment-example" created
================================================

### 設定したラベルを指定して関連リソース
### --selector : ラベルを指定するオプション
### app=<lavel>
$ kubectl get deployments,replicasets,pods --selector app=deployment-example
================================================
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/deployment-example 2 2 2 0 33s

NAME DESIRED CURRENT READY AGE
rs/deployment-example-2748039730 2 2 0 33s

NAME READY STATUS RESTARTS AGE
po/deployment-example-2748039730-2q8vr 0/1 ContainerCreating 0 33s
po/deployment-example-2748039730-sm7z3 0/1 ContainerCreating 0 33s
================================================

ローリングアップデート

### deployment-exampleの中身をさっきと変更して実行

$ kubectl apply -f deployment-example.yaml --record
================================================
deployment "deployment-example" configured
================================================

### ローリングアップデートされている様子を表示
$ kubectl get deployments,replicasets,pods --selector app=deployment-example
================================================
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/deployment-example 2 3 2 1 11m

NAME DESIRED CURRENT READY AGE
rs/deployment-example-2748039730 1 1 1 11m
rs/deployment-example-2829304371 2 2 0 20s

NAME READY STATUS RESTARTS AGE
po/deployment-example-2748039730-2q8vr 1/1 Running 0 11m
po/deployment-example-2829304371-gnrf2 0/1 ContainerCreating 0 20s
po/deployment-example-2829304371-wmds5 0/1 ContainerCreating 0 20s
================================================

### ローリングアップデート完了後
$ kubectl get deployments,replicasets,pods --selector app=deployment-example
================================================
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/deployment-example 2 2 2 2 16m

NAME DESIRED CURRENT READY AGE
rs/deployment-example-2748039730 0 0 0 16m
rs/deployment-example-2829304371 2 2 2 5m

NAME READY STATUS RESTARTS AGE
po/deployment-example-2829304371-gnrf2 1/1 Running 0 5m
po/deployment-example-2829304371-wmds5 1/1 Running 0 5m
================================================

ロールバック

### デプロイの履歴を表示

$ kubectl rollout history deployment deployment-example
================================================
REVISION CHANGE-CAUSE
1 kubectl create -f deployment-example.yaml --record
2 kubectl apply -f deployment-example.yaml --record
================================================

### リビジョンの詳細確認
$ kubectl rollout history deployment deployment-example --revision=1
================================================
deployments "deployment-example" with revision #1
Labels: app=deployment-example
pod-template-hash=2748039730
Annotations: kubernetes.io/change-cause=kubectl create -f deployment-example.yaml --record
Containers:
nginx:
Image: nginx:1.10
Port: 80/TCP
Volume Mounts: <none>
Environment Variables: <none>
No volumes.
================================================

### リビジョンを指定してロールバックを実行
### 指定しない場合は一つ前のリビジョンになる
$ kubectl rollout undo deployment deployment-example --to-revision=1
================================================
deployment "deployment-example" rolled back
================================================

### 前のバージョンに戻ったことを確認
$ kubectl get deployments,replicasets,pods --selector app=deployment-example
================================================
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
deploy/deployment-example 2 2 2 2 34m

NAME DESIRED CURRENT READY AGE
rs/deployment-example-2748039730 2 2 2 34m
rs/deployment-example-2829304371 0 0 0 23m

NAME READY STATUS RESTARTS AGE
po/deployment-example-2748039730-0rcn0 1/1 Running 0 1m
po/deployment-example-2748039730-44h4v 1/1 Running 0 1m
================================================


Pod関連

### 全てのネームスペースのポッドの情報を表示

$ kubectl get pods --all-namespaces
================================================
NAMESPACE NAME READY STATUS RESTARTS AGE
default deployment-example-2829304371-gnrf2 1/1 Running 0 10m
default deployment-example-2829304371-wmds5 1/1 Running 0 10m
joruri joruri-ldap-centos7 1/1 Running 0 1d
kube-system kubernetes-dashboard-4108885099-mc042 1/1 Running 0 2d
================================================

### Podの詳細情報を表示
$ kubectl describe pods --selector=app=deployment-example
================================================
Name: deployment-example-2829304371-gnrf2
Namespace: default
Node: 10.136.3.185/10.136.3.185
Start Time: Sun, 23 Apr 2017 20:12:10 +0900
Labels: app=deployment-example
pod-template-hash=2829304371
Status: Running
IP: 172.17.67.3
Controllers: ReplicaSet/deployment-example-2829304371
Containers:
nginx:
Container ID: docker://c4c539fb48f5a15b45f375eee0cfef4bd00039dc2fb2a75c9188e5e26d1db047
Image: nginx:1.11
Image ID: docker-pullable://docker.io/nginx@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582
Port: 80/TCP
State: Running
Started: Sun, 23 Apr 2017 20:12:48 +0900
Ready: True
Restart Count: 0
Volume Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-wpzd6 (ro)
Environment Variables: <none>
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-wpzd6:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-wpzd6
QoS Class: BestEffort
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
17m 17m 1 {default-scheduler } Normal Scheduled Successfully assigned deployment-example-2829304371-gnrf2 to 10.136.3.185
17m 17m 1 {kubelet 10.136.3.185} spec.containers{nginx} Normal Pulling pulling image "nginx:1.11"
16m 16m 1 {kubelet 10.136.3.185} spec.containers{nginx} Normal Pulled Successfully pulled image "nginx:1.11"
16m 16m 1 {kubelet 10.136.3.185} spec.containers{nginx} Normal Created Created container with docker id c4c539fb48f5; Security:[seccomp=unconfined]
16m 16m 1 {kubelet 10.136.3.185} spec.containers{nginx} Normal Started Started container with docker id c4c539fb48f5

Name: deployment-example-2829304371-wmds5
Namespace: default
Node: 10.136.3.184/10.136.3.184
Start Time: Sun, 23 Apr 2017 20:12:10 +0900
Labels: app=deployment-example
pod-template-hash=2829304371
Status: Running
IP: 172.17.3.4
Controllers: ReplicaSet/deployment-example-2829304371
Containers:
nginx:
Container ID: docker://f9c7a7f709aa846993f4ac6c2da5ac3ad78ad09f012b8902c9a3d37668254068
Image: nginx:1.11
Image ID: docker-pullable://docker.io/nginx@sha256:e6693c20186f837fc393390135d8a598a96a833917917789d63766cab6c59582
Port: 80/TCP
State: Running
Started: Sun, 23 Apr 2017 20:12:45 +0900
Ready: True
Restart Count: 0
Volume Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-wpzd6 (ro)
Environment Variables: <none>
Conditions:
Type Status
Initialized True
Ready True
PodScheduled True
Volumes:
default-token-wpzd6:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-wpzd6
QoS Class: BestEffort
Tolerations: <none>
Events:
FirstSeen LastSeen Count From SubObjectPath Type Reason Message
--------- -------- ----- ---- ------------- -------- ------ -------
17m 17m 1 {default-scheduler } Normal Scheduled Successfully assigned deployment-example-2829304371-wmds5 to 10.136.3.184
17m 17m 1 {kubelet 10.136.3.184} spec.containers{nginx} Normal Pulling pulling image "nginx:1.11"
16m 16m 1 {kubelet 10.136.3.184} spec.containers{nginx} Normal Pulled Successfully pulled image "nginx:1.11"
16m 16m 1 {kubelet 10.136.3.184} spec.containers{nginx} Normal Created Created container with docker id f9c7a7f709aa; Security:[seccomp=unconfined]
16m 16m 1 {kubelet 10.136.3.184} spec.containers{nginx} Normal Started Started container with docker id f9c7a7f709aa
================================================


定義例


Deployment

apiVersion: extensions/v1beta1   ### ※1 Kubernetes APIのバージョンで変わる

kind: Deployment ### オブジェクトの種類を指定
metadata:
name: nginx-deployment ### Deploymentの名前。Namespace内ではユニークである必要がある
spec:
replicas: 2 ### レプリカ数の指定
template: ### Podのテンプレート(PodTemplate)
metadata:
labels:
app: nginx-deployment ### ラベル指定は必須
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80 ### コンテナ側の待ち受けport


  • ※1 Kubernetes API Overview を参照


    • Kubernetes API 1.5 は apiVersion: extensions/v1beta1

    • Kubernetes API 1.6 は apiVersion: apps/v1beta1


    • kubectl --version でKubernetesのバージョンを確認できる


      • この環境の実行結果は Kubernetes v1.5.2 なので apiVersion: extensions/v1beta1






Namespace


参考