Kubernetes Up and Running 2nd Edition

**`2019/12/30` -  `7`章 あたり。読み進むごとに、この記事を更新していきます。だいたい休みの日にビール飲みながら書いている🍺**

# Kubernetes Up and Running

[Kubernetes: Up and Running, 2nd Edition](http://shop.oreilly.com/product/0636920223788.do) 

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/e9ad79a9-2511-befb-ea40-5a462357e78a.png)

- 「なにこれ、わかりやすっ」てなったので、これを教科書にしてハンズオンしながら理解していくことに
- 作者はマイクロソフトのブランドン・バーンズさん [Github](https://github.com/brendandburns)に、この本でのサンプルコードがある。




# Kubernetesの設計思想

いいこと書いてありますが、まず触りたいので、ここの部分はのちほど戻って更新していきます。

- Declarative configuration vs. Imperative configuration 

# Kubernetesハンズオンの選択肢
- Google Cloud Platform | Google Kubernetes Engine（今回はこれで）
- Amazon Web Service | Elastic Kubernetes Service
- Microsoft Azure | Azure Kubernetes Service
- Minikube


# 事前準備

[Google Cloud SDK](https://cloud.google.com/sdk/docs/quickstart-macos?hl=ja) をインストール

Mac なので `brew` します。 `cask` っていうのが新鮮

```
brew cask install google-cloud-sdk
```

いろんなメッセージが流れるが、その中で、ここが重要らしい

```
==> Source [/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.bash.inc] in your profile to enable shell command completion for gcloud.
==> Source [/usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.bash.inc] in your profile to add the Google Cloud SDK command line tools to your $PATH.
```

これに従い、`.bash_profile` に以下を追加して、読み込む `. ~/.bash_profile`

```shell:.bash_profile
source /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/completion.bash.inc
source /usr/local/Caskroom/google-cloud-sdk/latest/google-cloud-sdk/path.bash.inc
```

## いちおうバージョンを確認

```
$ gcloud version
Google Cloud SDK 273.0.0
bq 2.0.50
core 2019.12.06
gsutil 4.46
```

## 初期化する

```
$ gcloud init
```
ずらずらっとメッセージが出力される。途中でGoogleアカウントとプロジェクトを聞かれるので、作る/選ぶする

デフォルトのゾーンはUS `us-west1-a` にしておいた （最初、東京 `asia-northeast1` にしたら、なんかのバージョンが古いとかでうまく動かなかった）

```
$ gcloud config set compute/zone us-west1-a

$ gcloud config list
[compute]
zone = us-west1-a
[core]
account = ****@gmail.com
disable_usage_reporting = True
project = ****-*******-******
```

# Cluster

## いざ、クラスタをつくる！

```
$ gcloud container clusters create kuar-cluster 
WARNING: Accessing a Kubernetes Engine cluster requires the kubernetes commandline
client [kubectl]. To install, run
  $ gcloud components install kubectl
```
... 怒られた。`kubectl`のコンポーネントを入れないといけない

```
gcloud components install kubectl
```

これで、いけた感じ。以下のような、「昔別の入れ方しただろ？」的なメッセージがでてるが、一旦スルーする

```
There are older versions of Google Cloud Platform tools on your system PATH.
```

## いざ、クラスタをつくる！（二回目）

```
$ gcloud container clusters create c1

Creating cluster c1 in us-west1-a... Cluster is being health-checked (master is healthy)...done.                        
Created [https://container.googleapis.com/v1/projects/*-*-*/zones/us-west1-a/clusters/c1].
To inspect the contents of your cluster, go to: https://console.cloud.google.com/kubernetes/workload_/gcloud/us-west1-a/c1?project=--**
kubeconfig entry generated for c1.
NAME LOCATION  MASTER_VERSION MASTER_IP    MACHINE_TYPE  NODE_VERSION  NUM_NODES STATUS
c1  us-west1-a 1.13.11-gke.14 *.*.*.* n1-standard-1 1.13.11-gke.14 3     RUNNING
```

できた！ここまでくると `kubectl` コマンドが使えるようになってた。なるほどこうなるのか。

確認してみる

```
gcloud container clusters describe c1
```


#### TIPS - `kubectl` のコマンド補完を効くようにしとくとよい
```
brew install bash-completion
echo "source <(kubectl completion bash)" >> ~/.bashrc
```

# Component

## コンポーネントをみてみる

```
$ kubectl get componentstatus

NAME         STATUS  MESSAGE       ERROR
controller-manager  Healthy  ok          
etcd-1        Healthy  {"health": "true"}  
etcd-0        Healthy  {"health": "true"}  
scheduler      Healthy  ok    
```


# Node

## ノードをみてみる

```
$ kubectl get nodes

NAME                STATUS  ROLES  AGE   VERSION
gke-c1-default-pool-748a7c69-2l7j  Ready  <none>  9m29s  v1.13.11-gke.14
gke-c1-default-pool-748a7c69-jbtb  Ready  <none>  9m29s  v1.13.11-gke.14
gke-c1-default-pool-748a7c69-nrtt  Ready  <none>  9m29s  v1.13.11-gke.14
```

`-o` 使うと、`json` や `yaml`フォーマットでより詳細な情報が取れる。長すぎるので出力は割愛する

```
kubectl get nodes -o [ json | yaml ]
```

#### TIPS - `$HOME/.kube/config` にいろいろなコンフィグがあるので覗いてみると良いかも

ちなみにこの段階だと、`Pod` はまだない

```
$ kubectl get pods
No resources found.
```

# Pod

## Pod とは
>A Pod represents a collection of application containers and volumes running in the same execution environment. Pods, not containers, are the smallest deployable artifact in a Kubernetes cluster. This means all of the containers in a Pod always land on the same machine. 

- `Pod` は同一の実行環境で動く複数のアプリケーションコンテナとボリュームを集めたもの
- `Pod` は `k8s` クラスタへデプロイできる最小単位（コンテナが最小単位ではない）
- つまり、ある `Pod` の中の全てのコンテナは同じマシンにデプロイされる
- `Pod` の中のアプリケーションは `Pod` のIPアドレスやポート（ネットワークネームスペース）やホストネームを共有する。アプリケーション間はIPCで通信可能

`k8s` はコンテナを直に扱うのではなく、`Pod` という単位で扱うようだ


## Pod にアプリケーションをどういれるべきか

- 例えば、`Wordpress`と`DB`を同じ`Pod`に入れたりすると、このペアでスケールアウトすることになるから、うまくない
- 同一のマシンでないと動かないようなアプリケーション群を（の場合だけ）同じ `Pod` にいれるとよい

## Pod のリソースと構成
- マニフェストファイルで定義する（宣言的コンフィグ）
- マニフェストファイルが処理されて `etcd` へ構成が保存される
 
## Pod ハンズオン

### まずはコマンドで作る

```shell:create-kuard-pod

$ kubectl run kuard --generator=run-pod/v1 --image=gcr.io/kuar-demo/kuard-amd64:blue 
pod/kuard created
```

```
$ kubectl get pods
NAME                     READY   STATUS             RESTARTS   AGE
kuard                    1/1     Running            0          41m
kuard-78d7989464-bgc58   0/1     CrashLoopBackOff   5          4m1s
```

作成時にタイプミスしたやつが `CrashLoopBackOff` で残ってるが気にしない

### Podを消す

```
$ kubectl delete pods/kuard
pod "kuard" deleted
```

### マニフェストファイルから作る

さっきのコマンドライン `create-kuard-pod` と等価なマニュフェストファイルがこれ

```yaml:kuard-pod.yaml
apiVersion : v1
kind : Pod
metadata :
  name : kuard
spec :
  containers :
  - image : gcr.io/kuar-demo/kuard-amd64:blue
    name : kuard
    ports :
      - containerPort : 8080
        name : http
        protocol: TCP 
```

### 読み込む

```
$ kubectl apply -f kuard-pod.yaml 
pod/kuard created
```

### Podの詳細

```
$ kubectl describe pods kuard
```
長い出力がでるので割愛

### Pod の中へ

ポートフォワードを設定

```
$ kubectl port-forward kuard 8080:8080
Forwarding from 127.0.0.1:8080 -> 8080
Forwarding from [::1]:8080 -> 8080
```


`https://localhost:8080` へ接続
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/68b0d2eb-c6ac-b64e-eb2c-ac3c02e9ad8c.png)

### Pod のログ

```
$ kubectl logs kuard
2019/12/15 05:39:28 Starting kuard version: v0.10.0-blue
2019/12/15 05:39:28 **********************************************************************
2019/12/15 05:39:28 * WARNING: This server may expose sensitive
2019/12/15 05:39:28 * and secret information. Be careful.
2019/12/15 05:39:28 **********************************************************************
2019/12/15 05:39:28 Config: 
{
  "address": ":8080",
  "debug": false,
  "debug-sitedata-dir": "./sitedata",
  "keygen": {
    "enable": false,
    "exit-code": 0,
    "exit-on-complete": false,
    "memq-queue": "",
    "memq-server": "",
    "num-to-gen": 0,
    "time-to-run": 0
  },
  "liveness": {
    "fail-next": 0
  },
  "readiness": {
    "fail-next": 0
  },
  "tls-address": ":8443",
  "tls-dir": "/tls"
}
2019/12/15 05:39:28 Could not find certificates to serve TLS
2019/12/15 05:39:28 Serving on HTTP on :8080
2019/12/15 05:41:06 127.0.0.1:55558 GET /
2019/12/15 05:41:06 Loading template for index.html
2019/12/15 05:41:06 127.0.0.1:55558 GET /static/css/bootstrap.min.css
2019/12/15 05:41:07 127.0.0.1:55560 GET /static/css/styles.css
2019/12/15 05:41:07 127.0.0.1:55562 GET /built/bundle.js
2019/12/15 05:41:07 127.0.0.1:55562 GET /favicon.ico
```

`-f` をつけることで、`tail -f` みたいなことができる

### Pod 内でコマンド実行

```
$ kubectl exec kuard date
Sun Dec 15 05:49:02 UTC 2019
```

`docker exec` みたいな感じ

```
$ kubectl exec -it kuard ash
~ $ uname -a
Linux kuard 4.14.138+ #1 SMP Tue Sep 3 02:58:08 PDT 2019 x86_64 Linux

$ cd /tmp
$ touch file.txt
$ echo 'file.txt in kurd /tmp' > file.txt
```

### Pod からファイルをコピー

```
$ kubectl cp kuard:tmp/file.txt ./file.txt
$ more file.txt 
file.txt in kurd /tmp
```

`-it` でインタラクティブシェルを動かすところも `docker` と同じ感じ

#### TIPS - `Pod` というの名前の由来だが、Dockerコンテナが くじら をテーマにしているので、くじら（コンテナ）の群れを表す `Pod` という名前になったのか？

>(The name goes with the whale theme of Docker containers, since a Pod is also a group of whales.) 

# ヘルスチェック

そもそも、アプリケーションが落ちていたらk8sが再起動してくれるが、生死の確認だけでは足りないだろうから、以下のチェックがある

- **Liveness Probe** - あるポートへの HTTP Get などアプリ固有のチェック。チェックにFailするとデフォルトの動作はPodをリスタート
- **Readiness Probe** - アプリケーションが正常に応答できるかをチェック。Failするとロードバラスの対象から外される

`HTTP` だけじゃなく `tcpSocket` もみるし、 `exec` でコマンド結果をチェックすることもできる

##### TIPS - Liveness Probe vs. Readiness Probe
この二つの違いは微妙な感じのようだ... [KubernetesのLiveness ProbeとReadiness Probeの使い分けを考えたけど結局思いつかなかったや](https://bufferings.hatenablog.com/entry/2018/02/17/181946)

#### ヘルスチェックを適用する - [5-2-kuard-pod-health.yaml](https://github.com/kubernetes-up-and-running/examples/blob/master/5-2-kuard-pod-health.yaml) 

```
kubectl apply -f 5-2-kuard-pod-health.yaml
```
# リソース管理

CPUやメモリの使用量をコンテナごとに定義する（Pod毎ではない）

- 最小のリソース `resource` > `requests`
- リソースの上限 `resource` > `limits`

## 最小リソースと上限リソースを設定する - [5-4-kaurd-pod-reslim.yaml](https://github.com/kubernetes-up-and-running/examples/blob/master/5-4-kaurd-pod-reslim.yaml)

```yaml:5-4-kaurd-pod-reslim.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kuard
spec:
  containers:
    - image: gcr.io/kuar-demo/kuard-amd64:1
      name: kuard
      resources:
        requests:
          cpu: "500m"
          memory: "128Mi"
        limits:
          cpu: "1000m"
          memory: "256Mi"
      ports:
        - containerPort: 8080
          name: http
          protocol: TCP
```

# ボリューム

- Cache
- Persistent data
- Mounting the host filesystem
- Persistent data using remote disk - NFS, etc.

## ホストのファイルシステムをマウント - [5-5-kuard-pod-vol.yaml](https://github.com/kubernetes-up-and-running/examples/blob/master/5-5-kuard-pod-vol.yaml)
## NFS マウント - [5-6-kuard-pod-full.yaml](https://github.com/kubernetes-up-and-running/examples/blob/master/5-6-kuard-pod-full.yaml)

# ラベルとアノテーション

- ラベル - Kubernetes オブジェクト(Podなど)につけることのできる `key/value` ペア。グルーピングしたり、見たり、操作するための基礎になる
- アノテーション - Kubernetesオブジェクトに対する追加のメタデータ

Pod が増えてくるとラベルでも付けないと大変。ラベルに対して操作（例：ネットワークポリシをあてるなど）することで管理を楽に

## ラベルつける `--lebels`

```shell:label
# alpaca-prod
kubectl run alpaca-prod \
--image=gcr.io/kuar-demo/kuard-amd64:blue \
--replicas=2 \
--labels="ver=1,app=alpaca,env=prod" 

# alpaca-test
kubectl run alpaca-test \
--image=gcr.io/kuar-demo/kuard-amd64:green \
--replicas=1 \
--labels="ver=2,app=alpaca,env=test" 

# bandicoot-prod 
kubectl run bandicoot-prod \
--image=gcr.io/kuar-demo/kuard-amd64:green \
--replicas=2 \
--labels="ver=2,app=bandicoot,env=prod" 

# bandicoot-staging 
kubectl run bandicoot-staging \
--image=gcr.io/kuar-demo/kuard-amd64:green \
--replicas=1 \
--labels="ver=2,app=bandicoot,env=staging" 
```

## ラベルをみる

```shell
$ kubectl get deployment --show-labels
NAME                READY   UP-TO-DATE   AVAILABLE   AGE    LABELS
alpaca-prod         2/2     2            2           30m    app=alpaca,env=prod,ver=1
alpaca-test         1/1     1            1           28m    app=alpaca,canary=true,env=test,ver=2
bandicoot-prod      2/2     2            2           28m    app=bandicoot,env=prod,ver=2
bandicoot-staging   1/1     1            1           28m    app=bandicoot,env=staging,ver=2
kuard               0/1     1            0           6d2h   run=kuard
```


## `-L` でフィルタして見やすく

```shell
$ kubectl get deployment -L ver,canary,env,app
NAME                READY   UP-TO-DATE   AVAILABLE   AGE    VER   CANARY   ENV       APP
alpaca-prod         2/2     2            2           33m    1              prod      alpaca
alpaca-test         1/1     1            1           31m    2     true     test      alpaca
bandicoot-prod      2/2     2            2           31m    2              prod      bandicoot
bandicoot-staging   1/1     1            1           31m    2              staging   bandicoot
kuard               0/1     1            0           6d2h    
```

## ラベルを変える

```
$ kubectl label deployments bandicoot-staging "canary=true"
deployment.extensions/bandicoot-staging labeled

$ kubectl get deployment -L canary
NAME                READY   UP-TO-DATE   AVAILABLE   AGE    CANARY
alpaca-prod         2/2     2            2           36m    
alpaca-test         1/1     1            1           34m    true
bandicoot-prod      2/2     2            2           34m    
bandicoot-staging   1/1     1            1           34m    true
kuard               0/1     1            0           6d2h  
```
## ラベルを消す

ラベル名の後ろに `-` をつけると消える

```
$ kubectl label deployments alpaca-test "canary-"
deployment.extensions/alpaca-test labeled

$ kubectl get deployment -L canary
NAME                READY   UP-TO-DATE   AVAILABLE   AGE    CANARY
alpaca-prod         2/2     2            2           44m    
alpaca-test         1/1     1            1           42m    
bandicoot-prod      2/2     2            2           42m    
bandicoot-staging   1/1     1            1           42m    true
kuard               0/1     1            0           6d2h 
```

## ラベルセレクタ `--selector="xxx=yyy"`

ここまできたら、あとはいろんなコマンドの出力をラベルでフィルタできる

```
$ kubectl get pods --selector="ver=2" -L ver
NAME                                READY   STATUS    RESTARTS   AGE    VER
alpaca-test-68cc9fdf9d-vthvc        1/1     Running   0          111m   2
bandicoot-prod-585ffc884b-27xnk     1/1     Running   0          111m   2
bandicoot-prod-585ffc884b-vcx6z     1/1     Running   0          111m   2
bandicoot-staging-74dc6b658-mz7fx   1/1     Running   0          111m   2
```

`in` もつかえる

```
$ kubectl get pods --selector="app in (alpaca, bandicoot)" -L app
NAME                                READY   STATUS    RESTARTS   AGE    APP
alpaca-prod-67474dc478-kxfzq        1/1     Running   0          117m   alpaca
alpaca-prod-67474dc478-x5s6m        1/1     Running   0          117m   alpaca
alpaca-test-68cc9fdf9d-vthvc        1/1     Running   0          115m   alpaca
bandicoot-prod-585ffc884b-27xnk     1/1     Running   0          115m   bandicoot
bandicoot-prod-585ffc884b-vcx6z     1/1     Running   0          115m   bandicoot
bandicoot-staging-74dc6b658-mz7fx   1/1     Running   0          115m   bandicoot
```

## アノテーション

ここは、マイナーそうなので、一回飛ばして、あとで戻ってくる

# サービスディスカバリ

Kubernetes はダイナミックすぎて... サービスディスカバリが必要。DNSなど、歴史的に良いサービスディスカバリの仕組みがあるが、キャッシュにより間違ったIPへ接続にいくなど、問題がある。本当のサービスディスカバリが必要。

## サービスを作ってみる

```
kubectl run alpaca-prod \
--image=gcr.io/kuar-demo/kuard-amd64:blue \
--replicas=3 \
--port=8080 \
--labels="ver=1,app=alpaca,env=prod" 

kubectl expose deployment alpaca-prod 

kubectl run bandicoot-prod \
--image=gcr.io/kuar-demo/kuard-amd64:green \
--replicas=2 \
--port=8080 \
--labels="ver=2,app=bandicoot,env=prod" 

kubectl expose deployment bandicoot-prod

$ kubectl get services -o wide
NAME             TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE   SELECTOR
alpaca-prod      ClusterIP   10.35.244.41    <none>        8080/TCP   28m   app=alpaca,env=prod,ver=1
bandicoot-prod   ClusterIP   10.35.249.225   <none>        8080/TCP   28m   app=bandicoot,env=prod,ver=2
kubernetes       ClusterIP   10.35.240.1     <none>        443/TCP    12h   <none>

## サービスとしてCLUSTER-IPを公開（expose）

$ kubectl get pods
NAME                              READY   STATUS    RESTARTS   AGE
alpaca-prod-685dd59c7-84sqs       1/1     Running   0          30m
alpaca-prod-685dd59c7-b6ccd       1/1     Running   0          30m
alpaca-prod-685dd59c7-n9tw7       1/1     Running   0          30m
bandicoot-prod-6db7c4fc7c-p47ft   1/1     Running   0          30m
bandicoot-prod-6db7c4fc7c-vf95q   1/1     Running   0          30m

## CLUSTER-IPの背後には複数のPodがあり、ロードバランスされる
```

>that service is assigned a new type of virtual IP called a cluster IP . This is a special IP address the system will load-balance across all of the Pods that are identified by the selector. 

クラスタIPという特別なバーチャルIPをつかって、複数のPods間でロードバランスされる

## 全部消すコマンド

```
$ kubectl delete deployment,service --all
```

## Service DNS

やっぱりホスト名の方が便利なので、クラスタ内部のIPをホスト名で解決しよう:
`alpaca-prod.default.svc.cluster.local.	30 IN A 10.115.245.13`

## 監視の内容を変更する

おお、`edit` で直接YAMLを書き換えることができるのか。

```
$ kubectl edit deployment/alpaca-prod
```

`readinessProbe` を足す

```yaml
    spec:

        :

        readinessProbe:
          failureThreshold: 3
          httpGet:
            path: /ready
            port: 8080
            scheme: HTTP
          initialDelaySeconds: 2
          periodSeconds: 2
          successThreshold: 1
          timeoutSeconds: 1
```

## エンドポイントの変更をウォッチ

```
$ kubectl get endpoints alpaca-prod --watch
```

`ClusterIP` はクラスタ内部からしかアクセスできないみたいだ。~~ここからはクラスタ外部からのアクセスを考える~~ `ClusterIP` と `NodePorts` は共にクラスタ内部からのアクセス用

https://cloud.google.com/kubernetes-engine/docs/concepts/service?hl=ja

## `NodePorts`を設定する

```
# service の spec.type を ClusterIP から NodePorts へ書き換え

$ kubectl edit service alpaca-prod 
service/alpaca-prod edited

$ kubectl describe service alpaca-prod 
Name:                     alpaca-prod
Namespace:                default
Labels:                   app=alpaca
                          env=prod
                          ver=1
Annotations:              <none>
Selector:                 app=alpaca,env=prod,ver=1
Type:                     NodePort　＃ClusterIPからNodePortに変わっている
IP:                       10.35.248.62
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  30485/TCP
Endpoints:                10.32.1.14:8080,10.32.2.22:8080,10.32.2.23:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>
```

※ `Nodeport`にsshトンネルを張るところでうまくいかない... 一旦飛ばしてあとで帰ってくるか。

## `LoadBalancer` を設定する

```
# service の spec.type を NodePorts から LoadBalancer へ書き換え

$ kubectl edit service alpaca-prod
service/alpaca-prod edited

$ kubectl describe service alpaca-prod 
Name:                     alpaca-prod
Namespace:                default
Labels:                   app=alpaca
                          env=prod
                          ver=1
Annotations:              <none>
Selector:                 app=alpaca,env=prod,ver=1
Type:                     LoadBalancer ＃NodePortからLoadBalancerに変わっている
IP:                       10.35.248.62
Port:                     <unset>  8080/TCP
TargetPort:               8080/TCP
NodePort:                 <unset>  30485/TCP
Endpoints:                10.32.1.14:8080,10.32.2.22:8080,10.32.2.23:8080
Session Affinity:         None
External Traffic Policy:  Cluster
Events:
  Type    Reason                Age   From                Message
  ----    ------                ----  ----                -------
  Normal  Type                  11s   service-controller  NodePort -> LoadBalancer
  Normal  EnsuringLoadBalancer  11s   service-controller  Ensuring load balancer
```

お、こんどは普通に外部公開されている。`http://<LoadBalancer Ingress>:<Port>` で例の画面が見れる

```
$ kubectl describe endpoints alpaca-prod 
Name:         alpaca-prod
Namespace:    default
Labels:       app=alpaca
              env=prod
              ver=1
Annotations:  <none>
Subsets:
  Addresses:          10.32.1.14,10.32.2.22,10.32.2.23
  NotReadyAddresses:  <none>
  Ports:
    Name     Port  Protocol
    ----     ----  --------
    <unset>  8080  TCP

Events:  <none>

```

## エンドポイントの確認

```
$ kubectl describe endpoints alpaca-prod 

or

$ kubectl get endpoints alpaca-prod
```

Endpoint IP は deployment を 消したり再作成したりすると変わるのでアプリケーションが参照する場合は注意

#### TODO - このあたりでServiceというかネットワーク周りを図解した方がいいかもしれない。 `ClusterIP`, `ExternalIP`, `PodIP`, `NodeIP` など

## 手動でのサービスディスカバリ

ラベルを使って目的のものにたどり着くことを手動でのサービスディスカバリと紹介しているようだ

```
$ kubectl get pods -o wide --show-labels
NAME                              READY   STATUS    RESTARTS   AGE   IP           NODE                                NOMINATED NODE   READINESS GATES   LABELS
alpaca-prod-685dd59c7-99t54       1/1     Running   0          22m   10.32.1.16   gke-c1-default-pool-748a7c69-2l7j   <none>           <none>            app=alpaca,env=prod,pod-template-hash=685dd59c7,ver=1
alpaca-prod-685dd59c7-dbfph       1/1     Running   0          22m   10.32.2.24   gke-c1-default-pool-748a7c69-nrtt   <none>           <none>            app=alpaca,env=prod,pod-template-hash=685dd59c7,ver=1
alpaca-prod-685dd59c7-dgvxf       1/1     Running   0          22m   10.32.2.25   gke-c1-default-pool-748a7c69-nrtt   <none>           <none>            app=alpaca,env=prod,pod-template-hash=685dd59c7,ver=1
bandicoot-prod-6db7c4fc7c-rwt6d   1/1     Running   0          22m   10.32.1.17   gke-c1-default-pool-748a7c69-2l7j   <none>           <none>            app=bandicoot,env=prod,pod-template-hash=6db7c4fc7c,ver=2
bandicoot-prod-6db7c4fc7c-z5cxs   1/1     Running   0          22m   10.32.0.15   gke-c1-default-pool-748a7c69-jbtb   <none>           <none>            app=bandicoot,env=prod,pod-template-hash=6db7c4fc7c,ver=2
```

絞り込む

```
$ kubectl get pods -o wide --selector=app=alpaca,env=prod -L app,env
NAME                          READY   STATUS    RESTARTS   AGE   IP           NODE                                NOMINATED NODE   READINESS GATES   APP      ENV
alpaca-prod-685dd59c7-99t54   1/1     Running   0          25m   10.32.1.16   gke-c1-default-pool-748a7c69-2l7j   <none>           <none>            alpaca   prod
alpaca-prod-685dd59c7-dbfph   1/1     Running   0          25m   10.32.2.24   gke-c1-default-pool-748a7c69-nrtt   <none>           <none>            alpaca   prod
alpaca-prod-685dd59c7-dgvxf   1/1     Running   0          25m   10.32.2.25   gke-c1-default-pool-748a7c69-nrtt   <none>           <none>            alpaca   prod
```

## kube-proxy

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/bcbadc7f-a0e9-58ff-91d2-7555d680d5ea.png)

- Cluster IP はサービス内の Endpoints へトラフィックをロードバランスしている
- その正体は `kube-proxy` 。 `kube-proxy` はクラスタの全てのノードで動いている
- `kube-proxy` は apiserverを通して、クラスタ内の新しい service をウォッチしている
- `kube-proxy` は カーネルの `iptable` ルールを書き換えることでエンドポイントの一つにパケットを送れるようにする
- エンドポイントが（落ちたりして）変わったら、 `iptable` を書き換える
- Cluster IP 自体はサービスが作られるときに apiserver によってアサインされる。ユーザが Cluster IP をしていすることもできる。Cluster IPは変更ができないので削除して再作成となる





#### TIPS - GUI（ダッシュボード）の説明をあとで確認する
https://kubernetes.io/docs/tasks/access-application-cluster/web-ui-dashboard/

# 参考
https://speakerdeck.com/nwiizo/introduction-to-containers-and-beyond?slide=81