kubeadmでkubernetes v1.14.1のインストール

# 背景
kubernetesのインストール手順は沢山の人が書いてるし、公式ドキュメントも日本語対応していて、とっても今更感がありますが、Matzさんの講演会で、アウトプットが大切だよ。と言われてたので、手順をアウトプットします！
講演会については、別の方がまとめてくれています。
https://qiita.com/motoki4917/items/40386dd7fbd70987cc1d

初投稿なので、優しい目で見ていただければと思います。

# 構成

- CentOS7 4台(minimalインストール)
  - master 1台
  - worker 2台
  - kubectl実行サーバ 1台　← masterからkubectlを実行する場合は不要
- kubernetes v1.14.1
- CNI: canal


# 概要
- dockerインストール (対象:全台)※ kubectl実行するサーバは、docker buildとかを自分は使う機会があるため、対象にしています。
- 事前準備 (対象:全台)
- kubernetesパッケージインストール (対象:全台)
- master作業 (対象:master) 一部kubectl実行サーバで行う部分があります。
- worker作業 (対象:worker) 一部kubectl実行サーバで行う部分があります。
- kubectl実行サーバ作業 (対象:kubectl実行サーバ)

# 手順
## dockerインストール
- 事前パッケージインストール

~~~
yum install yum-utils device-mapper-persistent-data lvm2 -y
~~~

- dockerリポジトリの登録

~~~
yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
~~~

- docker-ceのインストール

~~~
yum install docker-ce -y
~~~

- docker設定ファイル作成

~~~
mkdir -m 644 /etc/docker
~~~

作成したディレクトリに以下ファイルを配置する

~~~json:/etc/docker/daemon.json
{
  "exec-opts": ["native.cgroupdriver=systemd"],
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "100m"
  },
  "storage-driver": "overlay2",
  "storage-opts": [
    "overlay2.override_kernel_check=true"
  ]
}
~~~

- dockerの自動起動設定と起動

~~~
systemctl enable docker && systemctl start docker
~~~

## 事前準備

- 時刻同期設定

~~~
yum install chrony -y
systemctl start chronyd && systemctl enable chronyd
~~~

- hostsファイル設定

今回利用するノードを名前解決できるように設定

~~~
vi /etc/hosts
~~~

- swap無効化

fstabのswap行をコメントアウトすることで、再起動後に無効になる。

~~~
vi /etc/fstab
-------------
/dev/mapper/cl-swap     swap    defaults0 0
# /dev/mapper/cl-swap     swap    defaults0 0
~~~

- SELinux無効化

うまく書き換えできていないと、OSが起動できず面倒になるため、慎重に。(一回スペルミスで事故ったので...)

~~~
vi /etc/selinux/config
---------
SELINUX=enforcing
SELINUX=disabled
~~~


- FireWalld無効化

実運用を考えると、必要なポートのみ開ける運用が正しいが、面倒だから今回は無効化。

~~~
systemctl disable firewalld
~~~

- 再起動

~~~
shutdown -r now
~~~

- 状態確認

SELinux

~~~
getenforce
-----
Disabled
~~~

swap  
何も表示されないこと

~~~
swapon -s
~~~

firewall

~~~
systemctl status firewalld
-----
● firewalld.service - firewalld - dynamic firewall daemon
   Loaded: loaded (/usr/lib/systemd/system/firewalld.service; disabled; vendor preset: enabled)
   Active: inactive (dead)
     Docs: man:firewalld(1)
~~~

- NW構成の変更

~~~
echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
~~~


## kubernetesパッケージインストール

kubernetesリポジトリ登録

~~~
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=https://packages.cloud.google.com/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=1
repo_gpgcheck=1
gpgkey=https://packages.cloud.google.com/yum/doc/yum-key.gpg https://packages.cloud.google.com/yum/doc/rpm-package-key.gpg
exclude=kube*
EOF
~~~

- kubeletインストール

v1.13など古いバージョンをkubelet、kubeadmを同時にインストールしようとすると、依存パッケージ(kubernetes-cni)のバージョンの問題でエラーになったため、タイミングを分けています。

~~~
yum install kubelet-v1.14.1 --disableexcludes=kubernetes -y
~~~


- kubeadm,kubectlインストール

WorkerNodeはkubectlは実際不要だと思います。
MasterNodeに関しても、kubectlを実行しないのであれば不要です。
kubectl実行サーバに関しては、kubectlだけあれば問題ないです。
~~手順分けて書くのが面倒だった~~ 汎用的に作業したかったため、全台に導入しました。

~~~
yum install kubeadm-v1.14.1 kubectl-v1.14.1 --disableexcludes=kubernetes -y
~~~

- kubeletの自動起動設定

~~~
systemctl enable kubelet && systemctl start kubelet
~~~

## master作業

- クラスタ作成

***pod-network-cidr***は利用するCNIによって異なる。
自分は、***canal***を利用するため、***10.244.0.0/16***にする。  
詳しくは、公式ドキュメントを確認してください。  
https://kubernetes.io/ja/docs/setup/independent/create-cluster-kubeadm/

~~~
kubeadm init --pod-network-cidr=10.244.0.0/16 --kubernetes-version v1.14.1

-----
kubeadm join 192.168.0.101:6443 --token eo0kz5.7crch5fxhbzbmez6 \
    --discovery-token-ca-cert-hash sha256:08ffe7836f8d8e0ccedf2b5b14f83830faa170c53030a2e601ef25ea774e2f25
~~~

もし、以下のようなエラーが表示された場合、kubelet,kubeadmをv1.13でインストールしてからv1.14.1をインストールしてください。
詳しい手順は一番下の[kubeadm initエラー](#bangai)に書きます。

~~~
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp [::1]:10248: connect: connection refused.
~~~

最後の行に、クラスタに参加するためのコマンドが表示されるため、メモしておく。
この表示されているtokenは、一定時間経過後失効されるため、注意。
以下コマンドでtokenの状態を確認、発行できる。

~~~
kubeadm token list
kubeadm token create
~~~




- kubectlのconfig設定(kubectlサーバで実行)

masterサーバで作成された認証情報をkubectlを実行するサーバに転送。

~~~
mkdir ~/.kube
scp root@masterIP:/etc/kubernetes/admin.conf ~/.kube/config
chown $(id -u):$(id -g) ~/.kube/config

-----masterサーバでkubectlを実行する場合-----
mkdir -p $HOME/.kube
cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
chown $(id -u):$(id -g) $HOME/.kube/config
~~~

普通はrootユーザのsshログインは許可されてないと思うので、うまく転送してやってください。


kubectl実行の確認

~~~
kubectl get nodes
-----
NAME          STATUS     ROLES    AGE     VERSION
k8s-master1   NotReady   master   9m49s   v1.14.1
~~~

masterが表示されているが、CNIの設定をしていないため、まだ ***NotReady*** の状態。


- CNIの適用(kubectlサーバで実行)

~~~
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/canal/rbac.yaml
kubectl apply -f https://docs.projectcalico.org/v3.3/getting-started/kubernetes/installation/hosted/canal/canal.yaml
~~~

今回は、canalを利用。CNIごとに手順が異なるため、公式ドキュメントを確認  
https://kubernetes.io/ja/docs/setup/independent/create-cluster-kubeadm/

- 結果の確認(kubectlサーバで実行)

Podの状態確認(全てRunningになっていること)

~~~
kubectl get pods -n kube-system
-----
NAME                                              READY   STATUS    RESTARTS   AGE
canal-g9l29                                       3/3     Running   0          52s
coredns-fb8b8dccf-grh5c                           1/1     Running   0          13m
coredns-fb8b8dccf-jfthh                           1/1     Running   0          13m
etcd-k8s-worker14p.hmd.local                      1/1     Running   0          12m
kube-apiserver-k8s-worker14p.hmd.local            1/1     Running   0          12m
kube-controller-manager-k8s-worker14p.hmd.local   1/1     Running   0          12m
kube-proxy-m8h52                                  1/1     Running   0          13m
kube-scheduler-k8s-worker14p.hmd.local            1/1     Running   0          12m
~~~

Nodeの状態確認

~~~
kubectl get nodes
-----
kubectl get nodes
NAME            STATUS   ROLES    AGE   VERSION
k8s-master1     Ready    master   15m   v1.14.1
~~~

master nodeの状態が ***Ready*** の状態になっているはず。
もし、なっていなければ、何かをミスっています。
CNIによって制約が異なる部分があるので、公式ガイドで確認してもらえればと思います。
自分は以前、NetworkCIDRのレンジが違っていて、calicoのインストールをミスっていたことがあります。
解決しなければ、他のCNIを使うのも一つの手だと思います。


## worker作業(Worker Node数分行う)

- クラスタへの参加

masterサーバに表示されたコマンドを実行。

~~~
kubeadm join 192.168.0.101:6443 --token eo0kz5.7crch5fxhbzbmez6 --discovery-token-ca-cert-hash sha256:08ffe7836f8d8e0ccedf2b5b14f83830faa170c53030a2e601ef25ea774e2f25
~~~


- 参加状況の確認(kubectlサーバで実行)

~~~
kubectl get nodes
~~~


## kubectl実行サーバ作業

- 予測変換の有効化(これがないと、kubectl実行はしんどい。)

~~~
yum install bash-completion -y
echo "source <(kubectl completion bash)" >> ~/.bashrc
source ~/.bashrc
~~~

面倒になってきたから、ここからは文字だけ。
URL張るので、そっちで確認してください。

- kubectxの設定

cluster,namespaceの切り替えを簡単にしてくれる。
namespaceは、よく切り替えるから入れておいてもいい気がする。

https://github.com/ahmetb/kubectx

- kube-ps1の設定

どのcluster、どのnamespaceで作業しているのかを表示してくれる。
複数クラスタを持つ場合は、結構必要性を感じる。ただ、動作がもっさりする。

https://github.com/jonmosco/kube-ps1

- kubectlをkで実行

すごい便利。慣れるとkubectlを打つのが面倒になってくる。

https://qiita.com/superbrothers/items/cd26ad2d266995ca7021

---

一旦、kubernetesを使える状態になったと思います。楽しいkubernetesライフを！お疲れ様でした。

# kubeadm initエラー
<a name="bangai"></a>

## 原因調査
以下のようにkubeletのヘルスチェックが失敗することがある。ひとまず回避策はあったから深く追及はしていない。

~~~
[kubelet-check] The HTTP call equal to 'curl -sSL http://localhost:10248/healthz' failed with error: Get http://localhost:10248/healthz: dial tcp [::1]:10248: connect: connection refused.
~~~

実際、kubeletを確認してみると、エラーになっている。

~~~
systemctl status kubelet
● kubelet.service - kubelet: The Kubernetes Node Agent
   Loaded: loaded (/usr/lib/systemd/system/kubelet.service; enabled; vendor preset: disabled)
  Drop-In: /usr/lib/systemd/system/kubelet.service.d
           mq10-kubeadm.conf
   Active: activating (auto-restart) (Result: exit-code) since 月 2019-04-29 06:58:11 JST; 2s ago
     Docs: https://kubernetes.io/docs/
  Process: 19104 ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_CONFIG_ARGS $KUBELET_KUBEADM_ARGS $KUBELET_EXTRA_ARGS (code=exited, status=255)
 Main PID: 19104 (code=exited, status=255)

 4月 29 06:58:11 k8s-master01p.hmd.local systemd[1]: kubelet.service: main process exited, code=exited, status=255/n/a
 4月 29 06:58:11 k8s-master01p.hmd.local systemd[1]: Unit kubelet.service entered failed state.
 4月 29 06:58:11 k8s-master01p.hmd.local systemd[1]: kubelet.service failed.
~~~

kubeletの設定ファイルを確認してみると、ファイルが存在していない。。
kubeadm実行中に配られると思ってたけど、違うんだろうか。。原因分からなかったけど、回避策は2つ見つけた。

~~~
ls -l /var/lib/kubelet/config.yaml
~~~

## 手順(回避策)
### 回避策1
最初に思い付いたほうです。回避策2の方がいいですが、一応紹介。
1.13では、問題なくインストールできていたため、v1.13でインストールしてみました。うまくいきました。

~~~
kubeadm reset
yum remove kubelet kubeadm kubectl
yum install kubelet-v1.13.1
yum install kubeadm-v1.13.1 kubectl--v1.13.1
kubeadm init
kubeadm reset
kubeadm install kubelet-v1.14.1 kubeadm-v1.14.1 kubectl-v1.14.1
kubeadm init --pod-network-cidr=10.244.0.0/16 --kubernetes-version v1.14.1
~~~

### 回避策2
多分、こっちが正攻法。アップデートした後に、NW構成が戻っているため、もう一度NW構成の設定。

~~~
yum update -y
echo '1' > /proc/sys/net/bridge/bridge-nf-call-iptables
~~~