[Oracle Cloud] Oracle CloudでKubernetes the Hard Wayする (その②)

# はじめに

[[Oracle Cloud] Oracle CloudでKubernetes the Hard Wayする (その①)](https://qiita.com/NSO-KC/items/9b827603d186c10e9b37)からの続きです。

# Kubenets the Hard Way in OCI (前回の続きから最後まで)

## ワーカー・ノードの構成

ワーカー・ノードに配置される各コンポーネントを構成します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/f6909e39-8254-8013-e655-07bd192bb0bd.png)

★ **WORKERノード設定：worker01/worker02/worker03で繰り返す** 
**------------------------------------- < ここから > -------------------------------------**
### rpmパッケージのインストール
socat、conntrack、ipsetをインストールします

```CONSOLE
## worker01にログイン
(client)$ ssh worker01.private
※worker02・worker03作業時は、各ノードにログインして作業します。読み替えてください

(worker)$ sudo yum install -y socat conntrack ipset
________________< 出力は省略 >________________
```

### swapの無効化

デフォルトでは、swapが有効化されているとkubeletがfailするそうなので、swapを無効化します
> By default the kubelet will fail to start if swap is enabled. It is recommended that swap be disabled to ensure Kubernetes can provide proper resource allocation and quality of service.

```CONSOLE
## swapの状態を確認する
(worker):$ sudo swapon --show
________________< コマンド実行後 出力 >________________
NAME      TYPE      SIZE USED PRIO
/dev/sda2 partition   8G   0B   -2
⇒ デフォルトでは有効化されている

## swapを無効化する
(worker):$ sudo swapoff -a
(worker):$ sudo cp -pi /etc/fstab /etc/fstab.$(date '+%Y%m%d')
(worker):$ sudo vi /etc/fstab
//swapのエントリをコメントアウトする//
#UUID=2ed28945-ff72-47d4-a34f-dedaed22eaec swap                    swap    defaults,_netdev,x-initrd.mount 0 0

## 再度swapの状態を確認し、何も出力されないことを確認する
(worker):$ sudo swapon --show
```
### ワーカー用バイナリのインストール

```CONSOLE
## ディレクトリを作成
(worker):$ sudo mkdir -p \
  /etc/cni/net.d \
  /opt/cni/bin \
  /var/lib/kubelet \
  /var/lib/kube-proxy \
  /var/lib/kubernetes \
  /var/run/kubernetes

## ファイルの展開
(worker):$ {
  mkdir containerd
  tar -xf crictl-v1.18.0-linux-amd64.tar.gz
  tar -xf containerd-1.3.6-linux-amd64.tar.gz -C containerd
  sudo tar -xf cni-plugins-linux-amd64-v0.8.6.tgz -C /opt/cni/bin/
  sudo mv runc.amd64 runc
  chmod +x crictl kubectl kube-proxy kubelet runc 
  sudo mv crictl kubectl kube-proxy kubelet runc /usr/local/bin/
  sudo mv containerd/bin/* /bin/
}

## 確認
(worker):$ cd /usr/local/bin/
(worker):$ ll crictl kubectl kube-proxy kubelet runc
________________< コマンド実行後 出力 >________________
-rwxr-xr-x. 1 opc opc  28447123 Apr  1  2020 crictl
-rwxrwxr-x. 1 opc opc  44036096 Jul 15  2020 kubectl
-rwxrwxr-x. 1 opc opc 113292024 Jul 15  2020 kubelet
-rwxrwxr-x. 1 opc opc  38383616 Jul 15  2020 kube-proxy
-rwxrwxr-x. 1 opc opc  12642864 Jul 30 10:33 runc
⇒ 上記ファイルが存在することを確認

(worker):$ cd -

(worker):$ ll /opt/cni/bin
________________< コマンド実行後 出力 >________________
total 70496
-rwxr-xr-x. 1 root root  4159518 May 13  2020 bandwidth
-rwxr-xr-x. 1 root root  4671647 May 13  2020 bridge
-rwxr-xr-x. 1 root root 12124326 May 13  2020 dhcp
-rwxr-xr-x. 1 root root  5945760 May 13  2020 firewall
-rwxr-xr-x. 1 root root  3069556 May 13  2020 flannel
-rwxr-xr-x. 1 root root  4174394 May 13  2020 host-device
-rwxr-xr-x. 1 root root  3614480 May 13  2020 host-local
-rwxr-xr-x. 1 root root  4314598 May 13  2020 ipvlan
-rwxr-xr-x. 1 root root  3209463 May 13  2020 loopback
-rwxr-xr-x. 1 root root  4389622 May 13  2020 macvlan
-rwxr-xr-x. 1 root root  3939867 May 13  2020 portmap
-rwxr-xr-x. 1 root root  4590277 May 13  2020 ptp
-rwxr-xr-x. 1 root root  3392826 May 13  2020 sbr
-rwxr-xr-x. 1 root root  2885430 May 13  2020 static
-rwxr-xr-x. 1 root root  3356587 May 13  2020 tuning
-rwxr-xr-x. 1 root root  4314446 May 13  2020 vlan
⇒ 上記ファイルが存在することを確認

(worker):$ ll /bin/containerd* /bin/ctr
________________< コマンド実行後 出力 >________________
-rwxr-xr-x. 1 opc opc 53283200 Jun 30  2020 /bin/containerd
-rwxr-xr-x. 1 opc opc  7180288 Jun 30  2020 /bin/containerd-shim
-rwxr-xr-x. 1 opc opc  8802304 Jun 30  2020 /bin/containerd-shim-runc-v1
-rwxr-xr-x. 1 opc opc  8806400 Jun 30  2020 /bin/containerd-shim-runc-v2
-rwxr-xr-x. 1 opc opc 25063104 Jun 30  2020 /bin/containerd-stress
-rwxr-xr-x. 1 opc opc 26991648 Jun 30  2020 /bin/ctr
⇒ 上記ファイルが存在することを確認
```

### CNIネットワークの構成

```CONSOLE
## POD用ネットワークアドレスを変数に設定
(worker):$ POD_CIDR=<★作業しているworkerノードに応じて、以下のネットワークレンジを指定します★>
* worker01の場合：10.200.0.0/24
* worker02の場合：10.200.1.0/24
* worker03の場合：10.200.2.0/24

## bridgeネットワーク用の設定ファイルを生成
(worker):$ cat <<EOF | sudo tee /etc/cni/net.d/10-bridge.conf
{
    "cniVersion": "0.3.1",
    "name": "bridge",
    "type": "bridge",
    "bridge": "cnio0",
    "isGateway": true,
    "ipMasq": true,
    "ipam": {
        "type": "host-local",
        "ranges": [
          [{"subnet": "${POD_CIDR}"}]
        ],
        "routes": [{"dst": "0.0.0.0/0"}]
    }
}
EOF
________________< 出力は省略 >________________

## 確認
(worker):$ cat /etc/cni/net.d/10-bridge.conf
________________< 出力は省略 >________________
⇒ 変数部分が意図した値に設定されていること

## loopback用ネットワーク設定ファイルを生成
(worker):$ cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf
{
    "cniVersion": "0.3.1",
    "name": "lo",
    "type": "loopback"
}
EOF
________________< 出力は省略 >________________

(worker):$ cat /etc/cni/net.d/99-loopback.conf
________________< 出力は省略 >________________
⇒ 設定が書き込まれていること

```

### Containerdの設定

```CONSOLE
## ディレクトリ作成
(worker):$ sudo mkdir -p /etc/containerd/

## containerdの設定ファイル作成
(worker):$ cat << EOF | sudo tee /etc/containerd/config.toml
[plugins]
  [plugins.cri.containerd]
    snapshotter = "overlayfs"
    [plugins.cri.containerd.default_runtime]
      runtime_type = "io.containerd.runtime.v1.linux"
      runtime_engine = "/usr/local/bin/runc"
      runtime_root = ""
EOF
________________< 出力は省略 >________________

## 確認
(worker):$ cat /etc/containerd/config.toml
________________< 出力は省略 >________________
⇒ 設定が書き込まれていること

## containerdのsystemdサービス設定ファイルを作成
(worker):$ cat <<EOF | sudo tee /etc/systemd/system/containerd.service
[Unit]
Description=containerd container runtime
Documentation=https://containerd.io
After=network.target

[Service]
ExecStartPre=/sbin/modprobe overlay
ExecStart=/bin/containerd
Restart=always
RestartSec=5
Delegate=yes
KillMode=process
OOMScoreAdjust=-999
LimitNOFILE=1048576
LimitNPROC=infinity
LimitCORE=infinity

[Install]
WantedBy=multi-user.target
EOF
________________< 出力は省略 >________________

(worker):$ cat /etc/systemd/system/containerd.service
________________< 出力は省略 >________________
⇒ 設定が書き込まれていること
```

### kubeletの設定

```CONSOLE
## 証明書およびkubeconfigの配賦
(worker):$ {
  sudo mv ${HOSTNAME}-key.pem ${HOSTNAME}.pem /var/lib/kubelet/
  sudo mv ${HOSTNAME}.kubeconfig /var/lib/kubelet/kubeconfig
  sudo mv ca.pem /var/lib/kubernetes/
}

## kubelet設定ファイルの作成
## オリジナルのkubernetes the hard wayには、以下のエントリがあります。
## resolvConf: "/run/systemd/resolve/resolv.conf"
## ただ、OCIで提供されているOELのイメージにはsystemd-resolvedがデフォルトでインストールされておらず、
## このエントリがあると、pod起動時にエラーになったため削除しています
(worker):$ cat <<EOF | sudo tee /var/lib/kubelet/kubelet-config.yaml
kind: KubeletConfiguration
apiVersion: kubelet.config.k8s.io/v1beta1
authentication:
  anonymous:
    enabled: false
  webhook:
    enabled: true
  x509:
    clientCAFile: "/var/lib/kubernetes/ca.pem"
authorization:
  mode: Webhook
clusterDomain: "cluster.local"
clusterDNS:
  - "10.32.0.10"
podCIDR: "${POD_CIDR}"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/${HOSTNAME}.pem"
tlsPrivateKeyFile: "/var/lib/kubelet/${HOSTNAME}-key.pem"
EOF
________________< 出力は省略 >________________

## 確認
(worker):$ cat /var/lib/kubelet/kubelet-config.yaml
________________< 出力は省略 >________________
⇒ 設定が書き込まれていること

## kubelet用systemdサービス設定ファイルの作成
(worker):$ cat <<EOF | sudo tee /etc/systemd/system/kubelet.service
[Unit]
Description=Kubernetes Kubelet
Documentation=https://github.com/kubernetes/kubernetes
After=containerd.service
Requires=containerd.service

[Service]
ExecStart=/usr/local/bin/kubelet \\
  --config=/var/lib/kubelet/kubelet-config.yaml \\
  --container-runtime=remote \\
  --container-runtime-endpoint=unix:///var/run/containerd/containerd.sock \\
  --image-pull-progress-deadline=2m \\
  --kubeconfig=/var/lib/kubelet/kubeconfig \\
  --network-plugin=cni \\
  --register-node=true \\
  --v=2
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
________________< 出力は省略 >________________

## 確認
(worker):$ cat /etc/systemd/system/kubelet.service
________________< 出力は省略 >________________
⇒ 設定が書き込まれていること

```

### Kubertenes Proxyの設定
```CONSOLE
## kubeconfigの配賦
(worker):$ sudo mv kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig

## kubernetes proxy設定ファイルの作成
(worker):$ cat <<EOF | sudo tee /var/lib/kube-proxy/kube-proxy-config.yaml
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
  kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "10.200.0.0/16"
EOF
________________< 出力は省略 >________________

## 確認
(worker):$ cat /var/lib/kube-proxy/kube-proxy-config.yaml
________________< 出力は省略 >________________
⇒ 設定が書き込まれていること

## kubernetes proxy用systemdサービス設定ファイルの作成
(worker):$ cat <<EOF | sudo tee /etc/systemd/system/kube-proxy.service
[Unit]
Description=Kubernetes Kube Proxy
Documentation=https://github.com/kubernetes/kubernetes

[Service]
ExecStart=/usr/local/bin/kube-proxy \\
  --config=/var/lib/kube-proxy/kube-proxy-config.yaml
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
________________< 出力は省略 >________________

## 確認
(worker):$ cat /etc/systemd/system/kube-proxy.service
________________< 出力は省略 >________________
⇒ 設定が書き込まれていること

```

### サービスの起動

```CONSOLE
## サービス起動
(worker):$ {
  sudo systemctl daemon-reload
  sudo systemctl enable containerd kubelet kube-proxy
  sudo systemctl start containerd kubelet kube-proxy
}
________________< 出力は省略 >________________

## 確認
(worker):$ systemctl status containerd kubelet kube-proxy
________________< コマンド実行後 出力 >________________
● containerd.service - containerd container runtime
   Loaded: loaded (/etc/systemd/system/containerd.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2021-01-23 03:17:04 GMT; 28s ago
     Docs: https://containerd.io
  Process: 13075 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
//出力省略：running状態であること//

● kubelet.service - Kubernetes Kubelet
   Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2021-01-23 03:17:04 GMT; 28s ago
     Docs: https://github.com/kubernetes/kubernetes
 Main PID: 13085 (kubelet)
//出力省略：running状態であること//

● kube-proxy.service - Kubernetes Kube Proxy
   Loaded: loaded (/etc/systemd/system/kube-proxy.service; enabled; vendor preset: disabled)
   Active: active (running) since Sat 2021-01-23 03:17:04 GMT; 28s ago
     Docs: https://github.com/kubernetes/kubernetes
 Main PID: 13084 (kube-proxy)
//出力省略：running状態であること//

## workerノードからログアウトし、clientノードに戻る
(worker):$ exit
```
### 動作確認

```CONSOLE
(client):$ ssh controller01.private kubectl get nodes --kubeconfig admin.kubeconfig
________________< コマンド実行後 出力 >________________
<worker01のみ完了時>
NAME       STATUS   ROLES    AGE     VERSION
worker01   Ready    <none>   4m43s   v1.18.6

<worker02まで完了時>
NAME       STATUS   ROLES    AGE     VERSION
worker01   Ready    <none>   9m46s   v1.18.6
worker02   Ready    <none>   14s     v1.18.6

<worker03まで完了時>
NAME       STATUS   ROLES    AGE     VERSION
worker01   Ready    <none>   25m     v1.18.6
worker02   Ready    <none>   16m     v1.18.6
worker03   Ready    <none>   3m28s   v1.18.6
```
**------------------------------------- < ここまで > -------------------------------------**

上記作業をworker02・worker03まで繰り返す

## リモートからkubectlコマンドを実行するための設定
クライアント・ノードから、adminユーザ権限でkubectlコマンドを実行できるように設定します
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/23c97334-0554-74d6-2a8a-e594f11ec06e.png)


```CONSOLE
## admin.kubeconfigファイルが存在するディレクトリに移動
(client):$ cd $HOME/kubectl/kubeconfig
(client):$ ll admin.kubeconfig
________________< コマンド実行後 出力 >________________
-rw-------. 1 opc opc 6261 Jan 22 04:44 admin.kubeconfig
⇒ 上記ファイルが存在すること

## LBのIPを変数に設定
(client):$ LB_IP=★LBのPrivate IP★

(client):$ {
  kubectl config set-cluster kubernetes-the-hard-way \
    --certificate-authority=$HOME/cfssl/cert/ca.pem \
    --embed-certs=true \
    --server=https://${LB_IP}:6443

  kubectl config set-credentials admin \
    --client-certificate=$HOME/cfssl/cert/admin.pem \
    --client-key=$HOME/cfssl/cert/admin-key.pem

  kubectl config set-context kubernetes-the-hard-way \
    --cluster=kubernetes-the-hard-way \
    --user=admin

  kubectl config use-context kubernetes-the-hard-way
}
________________< コマンド実行後 出力 >________________
Cluster "kubernetes-the-hard-way" set.
User "admin" set.
Context "kubernetes-the-hard-way" modified.
Switched to context "kubernetes-the-hard-way".

## 動作確認
(client):$ kubectl get componentstatuses
________________< コマンド実行後 出力 >________________
NAME                 STATUS    MESSAGE             ERROR
controller-manager   Healthy   ok
scheduler            Healthy   ok
etcd-2               Healthy   {"health":"true"}
etcd-1               Healthy   {"health":"true"}
etcd-0               Healthy   {"health":"true"}
⇒ 上記のように出力されること

(client):$ kubectl get nodes
________________< コマンド実行後 出力 >________________
NAME       STATUS   ROLES    AGE   VERSION
worker01   Ready    <none>   37m   v1.18.6
worker02   Ready    <none>   28m   v1.18.6
worker03   Ready    <none>   15m   v1.18.6
⇒ 上記のように出力されること
```

## ルート表の修正
Pod用ネットワークの通信が各ワーカー・ノードにルーティングされるように設定します

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/cad63b32-34fd-4e1e-1eec-4680e96b17f2.png)

**Cloud Shellから**以下のコマンドを実行します

```CONSOLE
## ワーカー・ノードのIPを設定
(CShell):$ WORKER01_IP=★worker01のIP★
(CShell):$ WORKER02_IP=★worker02のIP★
(CShell):$ WORKER03_IP=★worker03のIP★

## 各ワーカーノードのNIC OCIDを取得
(CShell):$ WORKER01_VNIC_OCID=$(oci --profile k8s compute instance list-vnics --raw-output --query 'data[?"hostname-label"==`worker01` && "lifecycle-state"==`AVAILABLE`].id |[0]')
(CShell):$ echo ${WORKER01_VNIC_OCID}
________________< コマンド実行後 出力 >________________
ocid1.vnic.oc1.ap-tokyo-1.abxhiljrlc4vueta5b26dpvn3crji7nvlgvitfdrvvcadmuc4hrxsnouwj4q
⇒ ocid1.vnicから始まるIDが出力されること

(CShell):$ WORKER02_VNIC_OCID=$(oci --profile k8s compute instance list-vnics --raw-output --query 'data[?"hostname-label"==`worker02` && "lifecycle-state"==`AVAILABLE`].id |[0]')
(CShell):$ echo ${WORKER02_VNIC_OCID}
________________< コマンド実行後 出力 >________________
ocid1.vnic.oc1.ap-tokyo-1.abxhiljrg56hd3cqq5luef7e2oikwaxqsulxbturobk32fzeog5j7uhhc3oa
⇒ ocid1.vnicから始まるIDが出力されること

(CShell):$ WORKER03_VNIC_OCID=$(oci --profile k8s compute instance list-vnics --raw-output --query 'data[?"hostname-label"==`worker03` && "lifecycle-state"==`AVAILABLE`].id |[0]')
(CShell):$ echo ${WORKER03_VNIC_OCID}
________________< コマンド実行後 出力 >________________
ocid1.vnic.oc1.ap-tokyo-1.abxhiljrnlvv2zeie7wzlln2shp23gl2hjrhddxxd4zejwz222uuqjatgxha
⇒ ocid1.vnicから始まるIDが出力されること

## 各VNICで、ソース・宛先チェック処理をスキップするように設定する
(CShell):$ for vnic_ocid in ${WORKER01_VNIC_OCID} ${WORKER02_VNIC_OCID} ${WORKER03_VNIC_OCID}
do
  oci --profile k8s network vnic update \
    --force \
    --vnic-id ${vnic_ocid} --skip-source-dest-check true
done
________________< 出力は省略 >________________

## PrivateサブネットのルートテーブルのOCIDを取得
(CShell):$ ROUTE_OCID=$(oci --profile k8s network route-table list --raw-output --query 'data[?"display-name"==`route-table-private` && "lifecycle-state"==`AVAILABLE`].id |[0]')
(CShell)$ echo ${ROUTE_OCID}
________________< コマンド実行後 出力 >________________
ocid1.routetable.oc1.ap-tokyo-1.aaaaaaaaowoavnonhkmy5356rkefyy5ofrqtebxuqcxiz7tzprv7y3weg2mq
⇒ ocid1.routetableから始まるIDが出力されること

## NAT GWのOCIDを取得
(CShell):$ NAT_GW_OCID=$(oci --profile k8s network nat-gateway list --raw-output --query 'data[].id |[0]')
(CShell):$ echo ${NAT_GW_OCID}
________________< コマンド実行後 出力 >________________
ocid1.natgateway.oc1.ap-tokyo-1.aaaaaaaa6i65puwgi23reds2pacxlt3zhfjn6rjnro7cdw4dysjz2vqjlaqq
⇒ ocid1.natgatewayから始まるIDが出力されること

## 各ワーカーノードのPrivate IP OCIDを取得
(CShell):$ WORKER01_IP_OCID=$(oci --profile k8s network private-ip list --ip-address ${WORKER01_IP} --raw-output --query 'data[].id |[0]')
(CShell):$ echo ${WORKER01_IP_OCID}
________________< コマンド実行後 出力 >________________
ocid1.privateip.oc1.ap-tokyo-1.abxhiljr2vtr2tjqbl6y2ewfnw6b25xbwjevxixwyjlwfbeweels362eiuxq
⇒ ocid1.privateipから始まるIDが出力されること

(CShell):$ WORKER02_IP_OCID=$(oci --profile k8s network private-ip list --ip-address ${WORKER02_IP} --raw-output --query 'data[].id |[0]')
(CShell):$ echo ${WORKER02_IP_OCID}
________________< コマンド実行後 出力 >________________
ocid1.privateip.oc1.ap-tokyo-1.abxhiljr2tkmyt6nmdogjlkic7hcqcnsi5ubs4xs64j57i5vppuoodp2uzza
⇒ ocid1.privateipから始まるIDが出力されること

(CShell):$ WORKER03_IP_OCID=$(oci --profile k8s network private-ip list --ip-address ${WORKER03_IP} --raw-output --query 'data[].id |[0]')
(CShell):$ echo ${WORKER03_IP_OCID}
________________< コマンド実行後 出力 >________________
ocid1.privateip.oc1.ap-tokyo-1.abxhiljrs6lzm5zzi243pis6kjurzpn2o54nsswopzcszrju2xo4s5whng5q
⇒ ocid1.privateipから始まるIDが出力されること

## Privateサブネットのルート表をアップデートする
(CShell):$ oci --profile k8s network route-table update --force \
  --rt-id ${ROUTE_OCID} \
  --route-rules '[{"destination":"0.0.0.0/0",   "networkEntityId":"'${NAT_GW_OCID}'"}
               ,{"destination":"10.200.0.0/24", "networkEntityId":"'${WORKER01_IP_OCID}'"}
               ,{"destination":"10.200.1.0/24", "networkEntityId":"'${WORKER02_IP_OCID}'"}
               ,{"destination":"10.200.2.0/24", "networkEntityId":"'${WORKER03_IP_OCID}'"}]'
________________< 出力は省略 >________________
```

更新後、Privateサブネットのルート・ルールが以下のように変更されていること
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/25f94133-3f6c-4401-7b6e-0fcf78218c38.png)

## DNSクラスター・アドオンのインストール

### CoreDNSをインストールする

サービス・ディスカバリに利用する、Kubernetes内部の名前解決用のPodをデプロイします

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/456818/5b53a95c-9d18-67ae-7569-d69374a1d183.png)

**クライアント・ノードから**以下のコマンドを実行します

```CONSOLE
(client):$ kubectl apply -f https://storage.googleapis.com/kubernetes-the-hard-way/coredns-1.7.0.yaml
________________< コマンド実行後 出力 >________________
clusterrole.rbac.authorization.k8s.io/system:coredns created
clusterrolebinding.rbac.authorization.k8s.io/system:coredns created
configmap/coredns created
deployment.apps/coredns created
service/kube-dns created

## 状態確認
(client):$ kubectl get pods -l k8s-app=kube-dns -n kube-system
________________< コマンド実行後 出力 >________________
NAME                       READY   STATUS              RESTARTS   AGE
coredns-5677dc4cdb-n9xhf   0/1     ContainerCreating   0          36s
coredns-5677dc4cdb-tng6q   0/1     ContainerCreating   0          36s
⇒ 上記のように出力されること
```

### CoreDNSの動作確認

```
## busybox PODの作成
(client):$ kubectl run busybox --image=busybox:1.28 --command -- sleep 3600
________________< コマンド実行後 出力 >________________
pod/busybox created

## 状態確認
(client):$ kubectl get pods -l run=busybox
________________< コマンド実行後 出力 >________________
NAME      READY   STATUS    RESTARTS   AGE
busybox   1/1     Running   0          14m
⇒ 一定期間経過後、Running状態になること

(client):$ POD_NAME=$(kubectl get pods -l run=busybox -o jsonpath="{.items[0].metadata.name}")
(client):$ kubectl exec -ti $POD_NAME -- nslookup kubernetes
________________< コマンド実行後 出力 >________________
Server:    10.32.0.10
Address 1: 10.32.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes
Address 1: 10.32.0.1 kubernetes.default.svc.cluster.local
⇒ 上記のように出力されること
```

## Smoke Test
これですべての設定が終わったので、Kubernetesクラスタが適切に動作するかのテストを行います。Smoke testは、[簡易テスト](https://www.itmedia.co.jp/im/articles/1111/07/news166.html)って意味だそうです。知りませんでした

### Data Encryptionテスト
etcdのデータが暗号化されているかどうかをテストします。

```CONSOLE
## シークレットを作成
(client):$ kubectl create secret generic kubernetes-the-hard-way \
  --from-literal="mykey=mydata"
________________< コマンド実行後 出力 >________________
secret/kubernetes-the-hard-way created

## controller01にログイン
(client):$ ssh controller01.private

## 確認
(controller01):$ sudo su -
(controller01):# etcdctl get \
  --endpoints=https://127.0.0.1:2379 \
  --cacert=/etc/etcd/ca.pem \
  --cert=/etc/etcd/kubernetes.pem \
  --key=/etc/etcd/kubernetes-key.pem\
  /registry/secrets/default/kubernetes-the-hard-way | hexdump -C
________________< コマンド実行後 出力 >________________
00000000  2f 72 65 67 69 73 74 72  79 2f 73 65 63 72 65 74  |/registry/secret|
00000010  73 2f 64 65 66 61 75 6c  74 2f 6b 75 62 65 72 6e  |s/default/kubern|
00000020  65 74 65 73 2d 74 68 65  2d 68 61 72 64 2d 77 61  |etes-the-hard-wa|
00000030  79 0a 6b 38 73 3a 65 6e  63 3a 61 65 73 63 62 63  |y.k8s:enc:aescbc|★
00000040  3a 76 31 3a 6b 65 79 31  3a 45 44 cf ea fa fa b6  |:v1:key1:ED.....|★
00000050  33 b0 bd 7d 0b 1b 7b 77  9b 8e 2a 05 58 c1 aa 87  |3..}..{w..*.X...|
00000060  21 9e ee 9f f4 29 71 fd  9f 55 e2 11 b6 2c 59 31  |!....)q..U...,Y1|
00000070  f4 6b c8 cd 96 e0 a0 5b  8f 86 40 bf 83 25 97 84  |.k.....[..@..%..|
//以降の出力省略//
k8s:enc:aescbc:v1:key1という文字列が出力されれればよいみたいです。

## controller01からログアウトして、クライアント・ノードに戻ります
(controller01):# exit
(controller01):$ exit
```

### デプロイメント
nginxのコンテナをデプロイします

```
## Podを作成
(client):$ kubectl create deployment nginx --image=nginx
________________< コマンド実行後 出力 >________________
deployment.apps/nginx created

## 確認
(client):$ kubectl get pods -l app=nginx
________________< コマンド実行後 出力 >________________
NAME                    READY   STATUS    RESTARTS   AGE
nginx-f89759699-kfj9q   1/1     Running   0          31s
⇒ Running状態になることを確認します
```

### ポート・フォワーディング

ポートフォワードが行えることを確認します

```CONSOLE
## POD名を取得します
(client):$ POD_NAME=$(kubectl get pods -l app=nginx -o jsonpath="{.items[0].metadata.name}")
(client):$ kubectl port-forward $POD_NAME 8080:80
________________< コマンド実行後 出力 >________________
Forwarding from 127.0.0.1:8080 -> 80
⇒ この状態で待機状態になります

## もう一つターミナルを起動して、クライアント・ノードにログインします
(client):$ netstat -ntpl
________________< コマンド実行後 出力 >________________
//省略//
tcp        0      0 127.0.0.1:8080          0.0.0.0:*               LISTEN      10204/kubectl
//省略//
⇒ kubectlコマンドがローカル・ホストの8080をリッスンしていることを確認します

## nginxにアクセスできるか確認します
(client):$ curl --head http://127.0.0.1:8080
________________< コマンド実行後 出力 >________________
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Sat, 23 Jan 2021 23:56:56 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 15 Dec 2020 13:59:38 GMT
Connection: keep-alive
ETag: "5fd8c14a-264"
Accept-Ranges: bytes

## アクセスすると、kubectl実行側のプロンプトに、以下のようなログが出力されます
________________< kubectl側 出力 >________________
Handling connection for 8080

## Ctrl+Cキーを押下してkubectlの実行を停止します
```

### ログ
POD(nginx)が出力するログを参照できることを確認します

```CONSOLE
(client):$ kubectl logs $POD_NAME
________________< コマンド実行後 出力 >________________
/docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
/docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
/docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
/docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
/docker-entrypoint.sh: Configuration complete; ready for start up
127.0.0.1 - - [23/Jan/2021:23:56:56 +0000] "HEAD / HTTP/1.1" 200 0 "-" "curl/7.29.0" "-"
```

### コマンド実行
POD(nginx)内で任意コマンドが実行できることを確認します

```CONSOLE
(client):$ kubectl exec -ti $POD_NAME -- nginx -v
________________< コマンド実行後 出力 >________________
nginx version: nginx/1.19.6
⇒ nginxのバージョンが出力されることを確認します
```


### サービス
サービスを利用したアクセスができることを確認します

```CONSOLE
## サービスの作成
(client):$ kubectl expose deployment nginx --port 80 --type NodePort
________________< コマンド実行後 出力 >________________
service/nginx exposed

## 確認
(client):$ kubectl get svc nginx
________________< コマンド実行後 出力 >________________
NAME    TYPE       CLUSTER-IP    EXTERNAL-IP   PORT(S)        AGE
nginx   NodePort   10.32.0.246   <none>        80:30663/TCP   80s
⇒ 上記のように出力されます

## ポート番号を取得して変数に格納
(client):$ NODE_PORT=$(kubectl get svc nginx \
  --output=jsonpath='{range .spec.ports[0]}{.nodePort}')

(client):$ WORKER01_IP=★Worker01のIPを入力★

## worker01(POD実行ノード)のサービス用ポートにアクセス
(client):$ curl -I http://${WORKER01_IP}:${NODE_PORT}
________________< コマンド実行後 出力 >________________
HTTP/1.1 200 OK
Server: nginx/1.19.6
Date: Sun, 24 Jan 2021 00:19:54 GMT
Content-Type: text/html
Content-Length: 612
Last-Modified: Tue, 15 Dec 2020 13:59:38 GMT
Connection: keep-alive
ETag: "5fd8c14a-264"
Accept-Ranges: bytes
⇒ nginxからのレスポンスがあることを確認します
```

## 後片付け
・Computeインスタンスとネットワーク(LB含む)を削除します
ComputeインスタンスとLBは従量課金対象になるため、いらなくなったら削除します
```