kubernetes the hard way on PC (１１．Worker Nodes)

#初めに
「[kubernetes the hard way](https://github.com/kelseyhightower/kubernetes-the-hard-way) を PC でやってみる」の１１回目、「Worker Node」についてです。だいぶ進んできましたね。（ [目次](https://qiita.com/shimauma_Zzzzz/items/84ecf5c748ceafd05380#%E8%AA%AC%E6%98%8E%E8%A8%98%E4%BA%8B%E7%9B%AE%E6%AC%A1) ）

kubernetes の実働部分のセットアップです。
worker node に関しては、 前提条件が地味にいろいろありますので注意しましょう。

やることは以下の通りです。
**※ 3台の worker node それぞれで実施します**

- 前提条件の確認
- Worker 用バイナリの入手・導入
- CNI Network の設定
- containerd の設定
- kubelet の設定
- kubernetes proxy の設定
- worker サービスの起動
- 検証



図で言うと赤枠の部分です。

![47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/b9578a57-c760-1a43-9c03-d7fdb7ce6f19.png)



また、例によって 末尾につまづいたエラーとその調査・対応方法も記載しておきます。

---
# 前提条件の確認

kubernetes の前提条件としては、以下のようなものがあります。
詳しくは、kubernetes のドキュメントの [kubeadmのインストール](https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm/install-kubeadm/) あたりが参考になると思います。

まず、 OS のコンポーネントをインストールしていきます。

```shell-session
# apt update
Hit:1 http://jp.archive.ubuntu.com/ubuntu focal InRelease
Get:2 http://jp.archive.ubuntu.com/ubuntu focal-updates InRelease [107 kB]
Get:3 http://jp.archive.ubuntu.com/ubuntu focal-backports InRelease [98.3 kB]
...(略)

# apt -y install socat conntrack ipset
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following additional packages will be installed:
...(略)
```

次に、kubernetes the hard way では記載がありませんが、CPU が2個あることも確認しておきましょう

```shell-session
# lscpu
Architecture:                    x86_64
CPU op-mode(s):                  32-bit, 64-bit
Byte Order:                      Little Endian
Address sizes:                   36 bits physical, 48 bits virtual
CPU(s):                          2
On-line CPU(s) list:             0,1
Thread(s) per core:              1
...(略)
```

swap を disable します。

```shell-session
# swapon --show
NAME      TYPE SIZE USED PRIO
/swap.img file   2G   0B   -2

# swapoff -a
# swapon --show
#
```

また、OS 再起動時に swap が有効になるのを回避するため、 fstab も修正しておきます。
（※ swap.img 行をコメントアウトします)

```shell-session
# vi /etc/fstab
# /etc/fstab: static file system information.
#
# Use 'blkid' to print the universally unique identifier for a
# device; this may be used with UUID= as a more robust way to name devices
# that works even if disks are added and removed. See fstab(5).
#
# <file system> <mount point>   <type>  <options>       <dump>  <pass>
# / was on /dev/vda2 during curtin installation
/dev/disk/by-uuid/d25ad5fe-d5c9-4c91-bc90-7d6360b5c266 / ext4 defaults 0 0
#/swap.img      none    swap    sw      0       0

```


#worker 用バイナリの入手・導入

入手元は以下の通りです。 github の物は、 リンク先の releases から最新版がたどれます。

|バイナリ|入手元|
|:--|:--|
|cri-tools|https://github.com/kubernetes-sigs/cri-tools|
|runc|https://github.com/opencontainers/runc|
|CNI plugin|https://github.com/containernetworking/plugins|
|containerd|https://github.com/containerd/containerd/|

また、 kubelet、kube-proxy に関しては 
「[第10回の kubernetes バイナリの入手](https://qiita.com/shimauma_Zzzzz/items/5822813313a7aae049a0#kubernetes-%E3%83%90%E3%82%A4%E3%83%8A%E3%83%AA%E3%81%AE%E5%85%A5%E6%89%8B)」の際に合わせてダウンロードできていますので
それを用いればよいです。

```shell-session
# wget -q --show-progress --https-only --timestamping https://github.com/kubernetes-sigs/cri-tools/releases/download/v1.18.0/crictl-v1.18.0-linux-amd64.tar.gz
crictl-v1.18.0-linux-amd64.tar.gz                        100%[================================================================================================================================>]  12.01M  5.55MB/s    in 2.2s

# wget -q --show-progress --https-only --timestamping https://github.com/opencontainers/runc/releases/download/v1.0.0-rc10/runc.amd64
runc.amd64                                               100%[================================================================================================================================>]  10.77M  4.54MB/s    in 2.4s

# wget -q --show-progress --https-only --timestamping https://github.com/containernetworking/plugins/releases/download/v0.8.5/cni-plugins-linux-amd64-v0.8.5.tgz
cni-plugins-linux-amd64-v0.8.5.tgz                       100%[================================================================================================================================>]  35.15M   663KB/s    in 64s

# wget -q --show-progress --https-only --timestamping https://github.com/containerd/containerd/releases/download/v1.3.4/containerd-1.3.4.linux-amd64.tar.gz
containerd-1.3.4.linux-amd64.tar.gz                      100%[================================================================================================================================>]  38.09M   739KB/s    in 92s
```

tar.gz ファイルがダウンロードされていますので、展開します。
-C で展開先ディレクトリを指定しているものとそうでないものがありますのでご注意ください。

```shell-session
# tar zxf crictl-v1.18.0-linux-amd64.tar.gz

# ls
cni-plugins-linux-amd64-v0.8.5.tgz  containerd-1.3.4.linux-amd64.tar.gz  crictl  crictl-v1.18.0-linux-amd64.tar.gz  runc.amd64

# mkdir containerd
# tar zxf containerd-1.3.4.linux-amd64.tar.gz -C containerd

# mkdir cni
# tar -zxf cni-plugins-linux-amd64-v0.8.5.tgz -C cni

# cp runc.amd64 runc
# chmod 755 runc

# ls
cni  cni-plugins-linux-amd64-v0.8.5.tgz  containerd  containerd-1.3.4.linux-amd64.tar.gz  crictl  crictl-v1.18.0-linux-amd64.tar.gz  runc  runc.amd64
```


次は各種ディレクトリの作成です。

```shell-session
# mkdir -p \
>   /etc/cni/net.d \
>   /opt/cni/bin \
>   /var/lib/kubelet \
>   /var/lib/kube-proxy \
>   /var/lib/kubernetes \
>   /var/run/kubernetes
```

各種ファイルは所定の場所にコピーします。（手順割愛）

|ファイル|場所|
|:--|:--|
|cni/*|/opt/cni/bin|
|crictl|/usr/local/bin|
|runc|/usr/local/bin|
|containerd/bin/*|/bin|
|kubectl|/usr/local/bin|
|kube-proxy|/usr/local/bin|
|kubelet|/usr/local/bin|


#CNI Network の設定

Network の設定を行います。　
kubernetes the hard way では Google Cloud のコマンドを使い POD_CIDER 変数にNW アドレスを格納しています。
ただし、実際に何の NW アドレスが指定されているかは表示されていないため、
オンプレ環境で実施する場合、NW 構成を認識したうえで POD_CIDR を指定しないと
間違った NW アドレスを指定することになります。
(※個人的には、間違えて POD_CIDR 部分に CLUSTER_CIDR を指定してしまい、
後で Pod の IP がノード間でバッティングする、という事件を起こしました。。。
まぁ自分がわかっていないだけ、という話ではありますが…)


※第1回目の表の再掲

|ネットワーク|アドレス|用途|上の図では|kubernetes the hard way では。。|
|:--|:--|:--|:--|:--:|
|LAN|192.168.199.0/24|物理LAN|LAN|10.240.0.0/24|
|cluster-ip-range|10.32.0.0/24|kubernetes の ClusterIP 等で利用される|Service用NW|同じ|
|cluster-cidr|10.200.0.0/16|Pod のIPアドレスで利用される|Pod用NW|同じ|
|pod-cidr (k8sworker0)|10.200.0.0/24|worker ノード#0 Pod用NW|Pod用NW|同じ|
|pod-cidr (k8sworker1)|10.200.1.0/24|worker ノード#1 Pod用NW|Pod用NW|同じ|
|pod-cidr (k8sworker2)|10.200.2.0/24|worker ノード#2 Pod用NW|Pod用NW|同じ|

CNI の設定は3台の worker node で行いますが、
kubernetes the hard way では例によって tmux で3台同時に実行しています。
そのため、ノードごとに異なる設定値は変数に格納して対応しています。
ここでは1台分のみの記載になるため、変数に入れなくてもよいのですが、
作業の流れは合わせて実施します。

```shell-session
# export POD_CIDR=10.200.0.0/24
# echo ${POD_CIDR}
10.200.0.0/24
```
(※2台目は 10.200.1.0/24、3台目は 10.200.2.0/24 です）

次に、CNI のブリッジ設定ファイルを作成します。　（ cnio0 インターフェースです ）

```shell-session
root@k8sworker0:/# 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
{
    "cniVersion": "0.3.1",
    "name": "bridge",
    "type": "bridge",
    "bridge": "cnio0",
    "isGateway": true,
    "ipMasq": true,
    "ipam": {
        "type": "host-local",
        "ranges": [
          [{"subnet": "10.200.0.0/24"}]
        ],
        "routes": [{"dst": "0.0.0.0/0"}]
    }
}
```

同様に loopback インターフェース設定も実施します。

```shell-session
root@k8sworker0:/# cat <<EOF | sudo tee /etc/cni/net.d/99-loopback.conf
> {
>     "cniVersion": "0.3.1",
>     "name": "lo",
>     "type": "loopback"
> }
> EOF
{
    "cniVersion": "0.3.1",
    "name": "lo",
    "type": "loopback"
}
```

これらの NW 設定は Pod が作られた際に有効になります。
詳しくは 第１３回 Pod Network で少しふれます。

#containerd の設定

containerd の設定ファイルを作成します。
runtime_engine に runc が指定されていますね。
kubernetes the hard way では、コンテナランタイムとして 
(docker ではなく) containerd + runc が構成されています。

```shell-session
# mkdir -p /etc/containerd/

# 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
[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 = ""
```

containerd 自体は systemd 配下のサービスで稼働させるため、
ユニット・ファイルを作成します。

```shell-session
# 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
[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
#
```

※ ユニット・ファイル作成後は、 `systemctl daemon-reload` と `systemctl list-unit-files` による確認がいりますが
この後、 kubelet、kube-proxy でもユニット・ファイルを作成しますので、後でまとめて実施します。

#kubelet の設定

ノード上で直接 pod を管理する kubelet ですが、関連する作業は以下の通りです。

- 必要な証明書等の配置
- kubelet-config.yaml 設定ファイルの作成
- systemd のユニット・ファイルの作成


まず、証明書等ですが
第6回目の最後に、各ノードの root ユーザーのホームに各種証明書を配置しましたので、
それを必要な場所にコピーします。 (一部コピー時にリネームしています)
なお、3台で実施するため、例によって hostname コマンド結果を HOSTNAME 変数に格納しています。

|秘密鍵・証明書|場所|
|:--|:--|
|ホスト名-key.pem|/var/lib/kubelet|
|ホスト名.kubeconfig|/var/lib/kubelet/kubeconfig|
|ca.pem|/var/lib/kubelet|


```shell-session
# HOSTNAME=$(hostname)
# cp ${HOSTNAME}-key.pem ${HOSTNAME}.pem /var/lib/kubelet/
# cp ${HOSTNAME}.kubeconfig /var/lib/kubelet/kubeconfig
# cp ca.pem /var/lib/kubernetes/
```

POD_CIDR と HOSTNAME 変数が設定されていることを確認し、
kubelet-config.yaml ファイルを作成します。

```shell-session
# echo ${POD_CIDR}
10.200.0.0/24

# echo ${HOSTNAME}
k8sworker0

# 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}"
> resolvConf: "/run/systemd/resolve/resolv.conf"
> runtimeRequestTimeout: "15m"
> tlsCertFile: "/var/lib/kubelet/${HOSTNAME}.pem"
> tlsPrivateKeyFile: "/var/lib/kubelet/${HOSTNAME}-key.pem"
> EOF
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: "10.200.0.0/24"
resolvConf: "/run/systemd/resolve/resolv.conf"
runtimeRequestTimeout: "15m"
tlsCertFile: "/var/lib/kubelet/k8sworker0.pem"
tlsPrivateKeyFile: "/var/lib/kubelet/k8sworker0-key.pem"
```

さて、ここで唐突に `10.32.0.10` という IP アドレスが出てきていますね。 (clusterDNS部分)
これは何か？なんで 10番なのか？　という話を少しだけ補足しておきます。

CoreDNS の回でも触れる予定ですが、
kubernetes the hard way では、 CoreDNS のデプロイの際に、 kubenetes the hard way 用の CoreDNS の yaml ファイルを利用します。　( https://storage.googleapis.com/kubernetes-the-hard-way/coredns.yaml )

その内容についての説明はなく、最終的な DNS の確認の際に `server: 10.32.0.10` と表示されているだけです。
そのため、疑問に思わなければそのままスルーされる部分だと思います。

この、 CoreDNS 用の yaml ファイルの中の `kind: Service` 部分に `clusterIP: 10.32.0.10` と記載されています。
つまり、 kubernetes the hard way では CoreDNS 向けの Service 用 ClusterIP は 10.32.0.10 と決められている、ということになります。　
それを kubelet 内にも指定していることになります。
ここは (個人的には)  DNS 連携設定上非常に重要と思うのですが、 kubernetes the hard way では触れられていません。
不思議です。。。

以下、CoreDNS 用の yaml ファイルの抜粋です。

```yaml
apiVersion: v1
kind: Service
metadata:
  name: kube-dns
  namespace: kube-system
  annotations:
    prometheus.io/port: "9153"
    prometheus.io/scrape: "true"
  labels:
    k8s-app: kube-dns
    kubernetes.io/cluster-service: "true"
    kubernetes.io/name: "CoreDNS"
spec:
  selector:
    k8s-app: kube-dns
  clusterIP: 10.32.0.10

```

----

次に systemd の ユニット・ファイルを作成します。
containerd と依存関係を持たせていたり、 各種設定ファイルや証明書等を指定していますね。

```shell-session
# 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
[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
```

#kubernetes proxy の設定

実際の通信をコントロールする kube-proxy の設定は、　kubelet 同様以下を実施します。

- 必要なファイルの配置
- kube-proxy-config.yaml 設定ファイルの作成
- systemd のユニット・ファイルの作成

必要な証明書類は kubelet の作業で配置しているため、
ここでは、 kube-proxy のファイル配置を行います。　（リネームします）

|ファイル|場所|
|:--|:--|
|kube-proxy.kubeconfig|/var/lib/kube-proxy/kubeconfig|


```shell-session
# cp kube-proxy.kubeconfig /var/lib/kube-proxy/kubeconfig
```

次に、 kube-proxy-config.yaml ファイルを作成します。
kube-proxy 設定では、 POD_CIDR ではなく  CLUSTER_CIDR ( 10.200.0.0/16 ) なので注意が必要です。


```shell-session
# 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
kind: KubeProxyConfiguration
apiVersion: kubeproxy.config.k8s.io/v1alpha1
clientConnection:
  kubeconfig: "/var/lib/kube-proxy/kubeconfig"
mode: "iptables"
clusterCIDR: "10.200.0.0/16"
#
```

最後に、　systemd のユニット・ファイルを作成します。

```shell-session
# 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
[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
```

ここまでで準備完了です！

#worker サービスの起動

##ユニット・ファイル確認・自動起動有効化

各種 systemd サービスの確認、自動起動有効化します。

```shell-session
# systemctl daemon-reload

# systemctl list-unit-files | grep kube
kube-proxy.service                     disabled        enabled
kubelet.service                        disabled        enabled

# systemctl list-unit-files | grep containerd
containerd.service                     disabled        enabled
```

list-unit-files で "bad" が出たらユニット・ファイル見直しです。

自動起動の有効化します。

```shell-session
# systemctl enable kube-proxy kubelet containerd
Created symlink /etc/systemd/system/multi-user.target.wants/kube-proxy.service → /etc/systemd/system/kube-proxy.service.
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /etc/systemd/system/kubelet.service.
Created symlink /etc/systemd/system/multi-user.target.wants/containerd.service → /etc/systemd/system/containerd.service.

# systemctl list-unit-files | grep kube
kube-proxy.service                     enabled         enabled
kubelet.service                        enabled         enabled

# systemctl list-unit-files | grep containerd
containerd.service                     enabled         enabled
```

## containerd 起動

```shell-session
# systemctl start containerd
# echo $?
0

# systemctl status containerd
● containerd.service - containerd container runtime
     Loaded: loaded (/etc/systemd/system/containerd.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2020-05-09 07:18:03 UTC; 6s ago
       Docs: https://containerd.io
    Process: 1295 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
   Main PID: 1305 (containerd)
      Tasks: 11 (limit: 2282)
     Memory: 21.5M
     CGroup: /system.slice/containerd.service
             mq1305 /bin/containerd

May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.504835949Z" level=info msg="Get image filesystem path \"/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs\""
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.507668961Z" level=info msg="loading plugin \"io.containerd.grpc.v1.introspection\"..." type=io.containerd.grpc.v1
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.507759340Z" level=info msg="Start subscribing containerd event"
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.508229060Z" level=info msg="Start recovering state"
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.508635058Z" level=info msg="Start event monitor"
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.508727639Z" level=info msg="Start snapshots syncer"
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.508798460Z" level=info msg="Start streaming server"
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.510575042Z" level=info msg=serving... address=/run/containerd/containerd.sock.ttrpc
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.511057522Z" level=info msg=serving... address=/run/containerd/containerd.sock
May 09 07:18:03 k8sworker0 containerd[1305]: time="2020-05-09T07:18:03.511146719Z" level=info msg="containerd successfully booted in 0.150605s"
```

無事に loaded, active になっているようです。ログ上でも問題なさそうですね。
必要に応じて `jornalctl -u containerd` などで詳細を確認しておいてください。


##kubelet 起動

```shell-session
# systemctl start kubelet
# echo $?
0

# systemctl status kubelet
● kubelet.service - Kubernetes Kubelet
     Loaded: loaded (/etc/systemd/system/kubelet.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2020-05-09 07:19:38 UTC; 8s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 1326 (kubelet)
      Tasks: 10 (limit: 2282)
     Memory: 12.6M
     CGroup: /system.slice/kubelet.service
             mq1326 /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 --k>

May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.018640    1326 passthrough.go:48] ccResolverWrapper: sending update to cc: {[{/var/run/containerd/containerd.sock 0  <nil>}] <nil>}
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.018658    1326 clientconn.go:577] ClientConn switching balancer to "pick_first"
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.018699    1326 remote_image.go:50] parsed scheme: ""
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.018714    1326 remote_image.go:50] scheme "" not registered, fallback to default scheme
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.018730    1326 passthrough.go:48] ccResolverWrapper: sending update to cc: {[{/var/run/containerd/containerd.sock 0  <nil>}] <nil>}
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.018743    1326 clientconn.go:577] ClientConn switching balancer to "pick_first"
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.019251    1326 balancer_conn_wrappers.go:127] pickfirstBalancer: HandleSubConnStateChange: 0xc00005ba40, CONNECTING
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.019476    1326 balancer_conn_wrappers.go:127] pickfirstBalancer: HandleSubConnStateChange: 0xc00005bb30, CONNECTING
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.020265    1326 balancer_conn_wrappers.go:127] pickfirstBalancer: HandleSubConnStateChange: 0xc00005ba40, READY
May 09 07:19:39 k8sworker0 kubelet[1326]: I0509 07:19:39.020301    1326 balancer_conn_wrappers.go:127] pickfirstBalancer: HandleSubConnStateChange: 0xc00005bb30, READY
```

kubelet のログを見ると、各種デフォルト設定などが見られます。
一度ぐらいは見ておいてもよいかもしれません。

##kube-proxy 起動

```shell-session
# systemctl start kube-proxy
# echo $?
0

# systemctl status kube-proxy
● kube-proxy.service - Kubernetes Kube Proxy
     Loaded: loaded (/etc/systemd/system/kube-proxy.service; enabled; vendor preset: enabled)
     Active: active (running) since Sat 2020-05-09 07:24:50 UTC; 7s ago
       Docs: https://github.com/kubernetes/kubernetes
   Main PID: 1454 (kube-proxy)
      Tasks: 8 (limit: 2282)
     Memory: 9.4M
     CGroup: /system.slice/kube-proxy.service
             mq1454 /usr/local/bin/kube-proxy --config=/var/lib/kube-proxy/kube-proxy-config.yaml

May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.323605    1454 conntrack.go:52] Setting nf_conntrack_max to 131072
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.352721    1454 conntrack.go:83] Setting conntrack hashsize to 32768
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.367783    1454 conntrack.go:100] Set sysctl 'net/netfilter/nf_conntrack_tcp_timeout_established' to 86400
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.368261    1454 conntrack.go:100] Set sysctl 'net/netfilter/nf_conntrack_tcp_timeout_close_wait' to 3600
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.368818    1454 config.go:313] Starting service config controller
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.369019    1454 shared_informer.go:197] Waiting for caches to sync for service config
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.372361    1454 config.go:131] Starting endpoints config controller
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.373901    1454 shared_informer.go:197] Waiting for caches to sync for endpoints config
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.471215    1454 shared_informer.go:204] Caches are synced for service config
May 09 07:24:50 k8sworker0 kube-proxy[1454]: I0509 07:24:50.475077    1454 shared_informer.go:204] Caches are synced for endpoints config

```

#検証

kubelet がきちんと稼働していれば Control plane ノードから確認ができます。
ステータスが Ready であることを確認します。
また、 ログは取れていませんが、 -o wide を指定すればノードの IP 等も確認できます。
※ admin.kubeconfig ファイルがある場所で実行してください。

```shell-session
# kubectl --kubeconfig admin.kubeconfig get nodes
NAME         STATUS   ROLES    AGE   VERSION
k8sworker0   Ready    <none>   10m   v1.16.9
k8sworker1   Ready    <none>   10m   v1.16.9
k8sworker2   Ready    <none>   10m   v1.16.9
```





#エラー並びに調査・対応方法

さて、恒例となった（？）エラー対応です。
黒歴史を書くようで気が進みませんが…


##Pod の IP が重複した

本文中でも触れましたが、 kubernetes the hard way は NW 構成が頭に入っていないと分かりづらいと(個人的に)思います。

今回、 kubelet 設定の中の POD_CIDR 部分に、間違えて CLUSTER_CIDR を指定してしまいました。

![48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310495/10c17c03-c2c1-7784-941e-19be7882b482.png)


Deployment 等を作成し、各ノード上に Pod が展開される際、
Pod の IP アドレスは指定した POD_CIDR 内からふられていくため、
Pod の IP アドレスが重複しました。

具体的には、　後々 CoreDNS の POD を作成した際に、こんな感じになりました。。。

```shell-session
# kubectl get pods --namespace kube-system -o wide
NAME                       READY   STATUS    RESTARTS   AGE   IP           NODE         NOMINATED NODE   READINESS GATES
coredns-68567cdb47-8s42p   1/1     Running   0          46s   10.200.0.2   k8sworker2   <none>           <none>
coredns-68567cdb47-wnh6c   1/1     Running   0          46s   10.200.0.2   k8sworker0   <none>           <none>
```

k8sworker0、k8sworker2 上の coredns Pod の IP が  10.200.0.2 で重複していますね。。。
異なるノード間で IP が重複する場合、 POD_CIDR の指定が間違っているということです。

正解は
CLUSTER_CIDR : 10.200.0.0/16  をノードで分割していく感じですね。
POD_CIDR : 10.200.0.0/24,   10.200.1.0/24 ,  10.200.2.0/24, ....  という感じです。


---
今回はここまでとして、次回は Configuring kubectl for Remote Access の部分を実施します。


← [１０．Control Plane](https://qiita.com/shimauma_Zzzzz/items/5822813313a7aae049a0)
↑ [目次](https://qiita.com/shimauma_Zzzzz/items/84ecf5c748ceafd05380#%E8%AA%AC%E6%98%8E%E8%A8%98%E4%BA%8B%E7%9B%AE%E6%AC%A1)
→ [１２．kubectl](https://qiita.com/shimauma_Zzzzz/items/a45b0221710f0ee89e94)

----