kubectl apply の挙動を確認する

[Kubernetes完全ガイド impress top gearシリーズ](https://www.amazon.co.jp/dp/B07HFS7TDT/ref=dp-kindle-redirect?_encoding=UTF8&btkr=1)を読みながら手元で確認した時のメモ。

公式ドキュメントは以下。

[kubectl apply](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply)

# 環境

```bash
$kubectl version
Client Version: version.Info{Major:"1", Minor:"10", GitVersion:"v1.10.3", GitCommit:"2bba0127d85d5a46ab4b778548be28623b32d0b0", GitTreeState:"clean", BuildDate:"2018-05-28T20:03:09Z", GoVersion:"go1.9.3", Compiler:"gc", Platform:"darwin/amd64"}
Server Version: version.Info{Major:"1", Minor:"11+", GitVersion:"v1.11.5-eks-6bad6d", GitCommit:"6bad6d9c768dc0864dab48a11653aa53b5a47043", GitTreeState:"clean", BuildDate:"2018-12-06T23:13:14Z", GoVersion:"go1.10.3", Compiler:"gc", Platform:"linux/amd64"}
```


# ディレクトリ配下のマニュフェストファイル群を適用したい

[Bulk operations in kubectl](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#bulk-operations-in-kubectl)

`-f`オプションでディレクトリを指定し、`-R`オプションも指定することで再帰的にマニュフェストファイルを適用する事ができる。

```bash
# フォルダ配下にマニフェストファイルを2つ配置
$tree k8stest
k8stest
├── 1-sample-pod.yaml
└── 2-sample-pod.yaml

0 directories, 2 files

# マニフェストファイルはほぼ同じ
$cat k8stest/1-sample-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: 1-sample-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
      
$ cat k8stest/2-sample-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: 2-sample-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12

```

上記状況で`kubectl apply`コマンドでまとめて実行します。

```bash
# -R を指定してディレクトリ配下のマニュフェストファイルを適用。ファイル名の順番で実行される
$kubectl apply -f k8stest -R
pod "1-sample-pod" created
pod "2-sample-pod" created

# pod の作成を確認
$kubectl get pods |grep sample-pod
1-sample-pod         1/1       Running   0          36s
2-sample-pod         1/1       Running   0          36s
```

確認できたので掃除。

```bash
$kubectl delete -f k8stest -R
pod "1-sample-pod" deleted
pod "2-sample-pod" deleted
```

# 一つのマニュフェストファイルに複数のリソースを書きたい

[Organizing resource configurations](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#organizing-resource-configurations)

>Many applications require multiple resources to be created, such as a Deployment and a Service. Management of multiple resources can be simplified by grouping them together in the same file (separated by --- in YAML)

とのことで YAML であれば --- で分ければ良い。

```merged-sample-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: 1-sample-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
---
apiVersion: v1
kind: Pod
metadata:
  name: 2-sample-pod
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
```

```bash
$ kubectl apply -f k8stest/merged-sample-pod.yaml
pod "1-sample-pod" created
pod "2-sample-pod" created
```

# kubect apply でリソースを削除する

マニフェストファイルからリソースが削除された場合に`kubectl apply `で`--prune`オプションを指定することでリソースの削除が出来る。
CI/CD を行う場合、`kubectl delete`ではなく、`kubectl apply`を使う事ができれば常に `kubect apply`を実行することでマニュフェストファイルとと実際の環境を同じにするという方針が出来る。

まず、何も指定しない場合を試す。

```bash
$tree prune-test
prune-test
├── 1-sample-pod.yaml
└── 2-sample-pod.yaml

0 directories, 2 files

# apply する
$kubectl apply -f prune-test -R
pod "1-sample-pod" created
pod "2-sample-pod" created

# ファイルを一つ削除
$rm prune-test/2-sample-pod.yaml

# 検知せず、2-sample-pod は削除されない
$kubectl apply -f prune-test -R
pod "1-sample-pod" unchanged
```

次に `--prune`を指定する

```bash
$ kubectl apply -f prune-test -R --prune
error: all resources selected for prune without explicitly passing --all. To prune all resources, pass the --all flag. If you did not mean to prune all resources, specify a label selector.
```

エラー。
理由は[ドキュメント](https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands#apply)に書いてあった。

>Automatically delete resource objects, including the uninitialized ones, that do not appear in the configs and are created by either apply or create --save-config. Should be used with either -l or --all. 


今回のマニュフェストファイルはラベルを付けてなかったので一度削除してラベルを付与して再度やってみる。

まずは Pod を削除。

```bash
# kubectl delete で削除
$kubectl delete -f prune-test
pod "1-sample-pod" deleted
```

次にファイルを編集。
lables を追加。

```bash
$cat prune-test/1-sample-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: 1-sample-pod
  labels:
    system:a
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12


cat prune-test/2-sample-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: 2-sample-pod
  labels:
    system:a
spec:
  containers:
    - name: nginx-container
      image: nginx:1.12
  
```

OK.
これで試す。

```bash
# 2つの Pod を作成 
$kubectl apply -f prune-test -R
pod "1-sample-pod" created
pod "2-sample-pod" configured

# ラベルが付与された Pod が起動する
$kubectl get pod -l system=a
NAME           READY     STATUS    RESTARTS   AGE
1-sample-pod   1/1       Running   0          1m
2-sample-pod   1/1       Running   0          13m

# ファイルを削除
$rm prune-test/2-sample-pod.yaml

# ラベルを指定して --prune を実行.2-sample-pod が prune された
$kubectl apply -f prune-test -R --prune -l system=a
pod "1-sample-pod" unchanged
pod "2-sample-pod" pruned

# 確認しても 2-sample-pod がない
$kubectl get pod -l system=a
NAME           READY     STATUS    RESTARTS   AGE
1-sample-pod   1/1       Running   0          4m

```

無事削除された。
実際の運用経験は無いがどのようにマニュフェストファイルを分けるのか、どのようにラベルを指定するのか予め決めておく必要がありそう。