Kubernetes 1.18 runs on CentOS 8

Kubernetes 1.18 を CentOS 8.1にインストールして動かしてみました。

KuberenetesクラスタはKVMゲストを使用した3台構成にしました。
・Master node(1 台):CentOS 8.1
・Worker node(2 台):CentOS 8.1

リソースは、仮想CPU:2個、メモリ:4GBを割り当てました。
なお、Kubernetes のドキュメントでは最小システム要件は「CPUコア:2 個、メモリ:2GB」となっています。
     参考 URL: https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm...

使用したソフトウェアとバージョン:

・Kubernetes:1.18.0
      注) CentOS 8 の nftables との整合性の関係で、Kubernetesは1.17.0か、それ以降のバージョンが必要です。
・Docker-CE(Docker Community Edition):19.03.8
・Containerd(コンテナランタイム):1.2.6
・weave(Pod ネットワーク用 add-on):2.6.2
     注) CentOS 8 の nftables との整合性の関係で、weave は 2.6.1 か、それ以降のバージョンが必要です。
・metallb(L2 ロードバランサ):0.8.3
・nginx(アプリケーション):1.14.2

Kubernetes と CentOS 8のiptables/nftablesの整合性について:

コンテナにインストールされたiptablesがiptables-legacyだと、コンテナはホストOSのカーネルを共有するので、CentOS 8の場合はiptables-nft(iptables v1.8.2)を使用しているため、カーネル内にiptables-legacyのテーブルとnftablesのテーブルの2種類が出来て、不整合が生じてしまいます。
この場合、ホストOSであるCentOS 8のiptables v1.8.2 (nf_tables)により「iptables -L」や「iptables -t nat -L」を実行するとカーネル内にテーブルが2種類出来ていることを検知して、以下のようなWarningを出します。

     # Warning: iptables-legacy tables present, use iptables-legacy to see them
     (CentOS 8にiptables-legacyはないので、ホストOS(ノード)側では確認できません。。)

Kubernetes 1.17以降ではこの問題は以下のようにして解決しています。
また、Podネットワーク用のadd-onもiptablesを使用しています。(weave、calico、flannelなどの実装については以下のURLを参照)
     参考 URL : https://kubernetes.io/ja/docs/concepts/cluster-administration/networking...
今回は weave を使いましたが、weaveも2.6.1以降では以下のように、Kubernetesと同様の方法で問題を解決しています。

Kubernetes の kube-proxy コンテナおよびweave コンテナには iptables-legacy と iptables-nft の両方がインストールされています。
これらのコンテナは iptables か nftables のどちらのテーブルをホストOSが利用しているかを判定して、対応している iptables の方を実行します。
ホスト OS(ノード)が CentOS 8 の場合は iptables-nft を実行します。
(iptables-legacy-saveとiptables-nft-saveを実行し、iptables と nftablesのそれぞれテーブル内のエントリの個数により判定します)

注)
以下のKubernetes v1.18の日本語ドキュメントは現時点(2020年4月1日)ではまだ以前の日本語訳のまま、以下のように記載されています。
「この nftables バックエンドは現在の kubeadm パッケージと互換性がありません。(ファイアウォールルールが重複し、kube-proxy を破壊するためです。)」
「RHEL 8 はレガシーモードへの切り替えをサポートしていないため、現在の kubeadm パッケージと互換性がありません。」
https://kubernetes.io/ja/docs/setup/production-environment/tools/kubeadm...

しかし、以下のv1.18の英語の原文では上記の記述は削除されています。
https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/in...

日本語訳の原文は昨年2019年9月13日に書かれたもののようで、この時点ではKubernetes(kube-proxy)はiptables-legacyを使用していたと思われます。
https://github.com/kubernetes/website/pull/16271#issuecomment-529795614

Kubernetes のリリース履歴:
Kubernetes のリリース履歴と nftables への対応はつぎのようになっています。

・Kubernetes 1.18.0

リリース日:2020年3月25日
参考 URL: https://kubernetes.io/blog/2020/03/25/kubernetes-1-18-release-announceme...

・Kubernetes 1.17.0

リリース日:2019年12月9日
参考 URL: https://kubernetes.io/blog/2019/12/09/kubernetes-1-17-release-announceme...
https://kubernetes.io/docs/setup/release/notes/
The official kube-proxy image (used by kubeadm, among other things) is now compatible with systems running iptables 1.8 in “nft” mode, and will autodetect which mode it should use. (#82966, @danwinship)」

・Kubernetes 1.16.0

リリース日:2019年9月18日
参考 URL: https://kubernetes.io/blog/2019/09/18/kubernetes-1-16-release-announceme...

Weave のリリース履歴:
Weave のリリース履歴と nftables への対応はつぎのようになっています。

・Weave 2.6.2

リリース日:2020年3月18日
参考 URL: https://github.com/weaveworks/weave/releases/tag/v2.6.2

・Weave 2.6.1

リリース日:2019年3月7日
参考 URL: https://github.com/weaveworks/weave/releases/tag/v2.6.1
support for iptables 1.8 and a bug-fix」

・Weave 2.6.0

リリース日:2019年11月6日
参考 URL: https://github.com/weaveworks/weave/releases/tag/v2.6.0

インストール手順の概要:

インストール手順の概要は以下となります。
     参考 URL: https://kubernetes.io/docs/setup/production-environment/tools/kubeadm/in...

1. CentOS 8.1 をインストールした KVM ゲスト(ノード)を 3 台作成する。
2. 各ノードで Kubernetes 用の基本設定を行う。

- ホスト名の設定
- SELinux ⇒ disabledに設定
- swap 領域は使用しない(使用すると Kubernetes のインストール時にエラーとなる)
- firewalld を停止する

コンテナにインストールされたiptables-nft は firewalld がカーネル内に作成する firewalld テーブルを参照しません(参照できません)。
今回のインストールではこれに合わせてホスト OS 側でも firewalld を停止しました。
filter テーブル、nat テーブルともにインストール時のデフォルトポリシーは ACCEPT(許可)となります。
しがたって、ホスト OS 側でパケットフィルタの設定を行う場合は nftコマンドではなく iptables(nft)コマンドを使うのがわかりやすいと思います。

- /etc/hosts に 3 台のノードを登録する。(必須)
- 以上の設定が終わったら、システムを再起動

3. Containerd をインストールする
4. Docker-CE をインストールする
5. kubeadm をインストールする

※ 以上の 1.~5.の手順は各ノードで共通です。
1 台作成して、残りの2 台をクローンとして作成し、ホスト名と/etc/hosts を編集すると効率良くできます。

6. (Masterノード上で実行) 「kubeadm init」コマンドを実行し、kubernetes コントロールプレーンをセットアップする。

「kubeadm init」実行時に表示されるメッセージの最後の方に、以降、以下のステップ9までに実行するコマンドが表示されます。

7. (Masterノード上で実行) weave(Pod ネットワーク用の add-on)をインストールする

参考 URL: https://www.weave.works/docs/net/latest/kubernetes/kube-addon/

8. (1 台目のWorker ノード上で実行) Kubernetes クラスタに参加(join)させる
9. (2 台目のWorker ノード上で実行) Kubernetes クラスタに参加(join)させる
10. (Masterノード上で実行) metallb(ロードバランサー)をインストールする

MetalLB は BGP ルータとして使用する方法と Layer2 モードのロードバランサーとして使用方法があります。
今回は Layer2 モードのロードバランサーとして使用します。
参考 URL: https://v0-7-3--metallb.netlify.com/tutorial/layer2/

11. (Masterノード上で実行) nginx をインストールする

参考 URL:
https://raw.githubusercontent.com/google/metallb/v0.8.2/manifests/tutori...
https://raw.githubusercontent.com/kubernetes/website/master/content/en/e...

インストール:

1. CentOS 8.1 をインストールした KVM ゲスト(ノード)を 3 台作成する。

2. 各ノードで Kubernetes 用の基本設定を行う。
# vi /etc/hostname(以下、例です) c8-k8s-1.localdomain # vi /etc/selinux/config(以下、抜粋) #SELINUX=enforcing ←行頭に#を付ける SELINUX=disabled ←追加 # vi /etc/fstab(以下、抜粋) #/dev/mapper/cl-swap swap swap defaults 0 0 ←行頭に#を付ける # systemctl disable firewalld # systemctl reboot
参考:/etc/hostsの例(以下の3行を追記)      192.168.101.173 c8-k8s-1.localdomain c8-k8s-1      192.168.101.80 c8-k8s-2.localdomain c8-k8s-2      192.168.101.54 c8-k8s-3.localdomain c8-k8s-3
3. Containerd をインストールする
# dnf install https://download.docker.com/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.6-3.3.el7.x86_64.rpm
4. Docker-CE をインストールする
(podman がインストールされている場合は Docker-CE パッケージとコンフリクトするため、事前に削除) # rpm -e podman-manpages podman cockpit-podman # dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo # dnf install docker-ce # systemctl enable docker # systemctl start docker
5. kubeadm をインストールする
# vi /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 # dnf install kubeadm # systemctl enable kubelet
※ 以上の 1.~5.の手順は各ノードで共通です。 1 台作成して、残りの2 台をクローンとして作成し、ホスト名と/etc/hosts を編集すると効率良くできます。 6. (Masterノード上で実行) 「kubeadm init」コマンドを実行し、kubernetes コントロールプレーンをセットアップする。
[root@c8-k8s-1 ~]# kubeadm init ...(途中省略)... Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f [podnetwork].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.101.173:6443 --token t2l4d2.fsjwsyww86jn2wek \ --discovery-token-ca-cert-hash sha256:86d8b0c082463487661cb9dac3f695c3664076964cebdccb13180d5723ed297e [root@c8-k8s-1 ~]# mkdir -p $HOME/.kube [root@c8-k8s-1 ~]# cp -i /etc/kubernetes/admin.conf $HOME/.kube/config [root@c8-k8s-1 ~]# chown $(id -u):$(id -g) $HOME/.kube/config
7. (Masterノード上で実行) weave(Pod ネットワーク用の add-on)をインストールする
参考: 事前に、ダウンロードされるweaveのバージョンを確認してみます。 Kubernetesのバージョン情報を指定した場合は、対応するバージョンのweaveがダウンロードされるようです。 [root@c8-k8s-1 ~]# export kubever=$(kubectl version | base64 | tr -d '\n') [root@c8-k8s-1 ~]# wget -O - -q https://cloud.weave.works/k8s/net?k8s-version=$kubever |grep image image: 'docker.io/weaveworks/weave-kube:2.6.2' image: 'docker.io/weaveworks/weave-npc:2.6.2' Kubernetesのバージョン情報を指定しない場合は、最新バージョンのweaveがダウンロードされるようです。 [root@c8-k8s-1 ~]# wget -O - -q https://cloud.weave.works/k8s/net |grep image image: 'docker.io/weaveworks/weave-kube:2.6.2' image: 'docker.io/weaveworks/weave-npc:2.6.2' 今回はどちらの場合でも、バージョンは2.6.2となります。
[root@c8-k8s-1 ~]# export kubever=$(kubectl version | base64 | tr -d '\n') [root@c8-k8s-1 ~]# kubectl apply -f "https://cloud.weave.works/k8s/net?k8s-version=$kubever"
8. (1台目のWorkerノード上で実行) Kubernetes クラスタに参加(join)させる
[root@c8-k8s-2 ~]# kubeadm join 192.168.101.173:6443 --token t2l4d2.fsjwsyww86jn2wek \ > --discovery-token-ca-cert-hash sha256:86d8b0c082463487661cb9dac3f695c3664076964cebdccb13180d5723ed297e
9. (2台目のWorkerノード上で実行) Kubernetes クラスタに参加(join)させる
[root@c8-k8s-3 ~]# kubeadm join 192.168.101.173:6443 --token t2l4d2.fsjwsyww86jn2wek \ > --discovery-token-ca-cert-hash sha256:86d8b0c082463487661cb9dac3f695c3664076964cebdccb13180d5723ed297e
10. (Masterノード上で実行) metallb(L2 ロードバランサー)をインストールする
[root@c8-k8s-1 ~]# kubectl apply -f https://raw.githubusercontent.com/google/metallb/v0.8.3/manifests/metallb.yaml [root@c8-k8s-1 ~]# vi config.yaml apiVersion: v1 kind: ConfigMap metadata: namespace: metallb-system name: config data: config: | ←このまま。この「 | 」を入れておかないとエラーとなる address-pools: - name: default protocol: layer2 addresses: - 192.168.101.240-192.168.101.242 ← 外部公開アドレスの範囲を指定(今回の例です) [root@c8-k8s-1 ~]# kubectl apply -f config.yaml
11. (Masterノード上で実行) nginx をインストールする
[root@c8-k8s-1 ~]# vi nginx.yaml apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2 ← Kubernetes のバージョンは 1.18.0 なので v1 を指定 kind: Deployment metadata: name: nginx spec: selector: matchLabels: app: nginx replicas: 5 # tells deployment to run 5 pods matching the template ← podを5個作成(例です) template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.14.2 ← nginxのバージョンを1.14.2に指定(例です) ports: - name: http containerPort: 80 --- apiVersion: v1 kind: Service metadata: name: nginx spec: ports: - name: http port: 80 protocol: TCP targetPort: 80 selector: app: nginx type: LoadBalancer ← タイプを LoadBalancerに指定 [root@c8-k8s-1 ~]# kubectl apply -f nginx.yaml

動作確認:

(/etc/hostsの内容を表示)
[root@c8-k8s-1 ~]# cat /etc/hosts
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

192.168.101.173	c8-k8s-1.localdomain c8-k8s-1
192.168.101.80	c8-k8s-2.localdomain c8-k8s-2
192.168.101.54	c8-k8s-3.localdomain c8-k8s-3

(3台のノードのSTATUSがReadyになっていることを確認)
[root@c8-k8s-1 ~]# kubectl get nodes
NAME                   STATUS   ROLES    AGE     VERSION
c8-k8s-1.localdomain   Ready    master   15m     v1.18.0
c8-k8s-2.localdomain   Ready    <none>   4m26s   v1.18.0
c8-k8s-3.localdomain   Ready    <none>   52s     v1.18.0

(kube-proxyのpodが各ノードで稼動していることを確認)
[root@c8-k8s-1 ~]# kubectl get pod -n kube-system -o wide |grep kube-proxy
kube-proxy-b4vsf         1/1     Running   2      6d17h   192.168.101.173   c8-k8s-1.localdomain   ...(以降省略)
kube-proxy-gcnwf         1/1     Running   0      6d17h   192.168.101.80    c8-k8s-2.localdomain   ...(以降省略)
kube-proxy-wjz49         1/1     Running   0      6d17h   192.168.101.54    c8-k8s-3.localdomain   ...(以降省略)

(weaveのpodが各ノードで稼動していることを確認)
[root@c8-k8s-1 ~]# kubectl get pod -n kube-system -o wide |grep weave
weave-net-ch6b9          2/2     Running   0      12m   192.168.101.80    c8-k8s-2.localdomain   ...(以降省略)
weave-net-k7wjm          2/2     Running   1      8m34s 192.168.101.54    c8-k8s-3.localdomain   ...(以降省略)
weave-net-v64qs          2/2     Running   3      18m   192.168.101.173   c8-k8s-1.localdomain   ...(以降省略)

(weaveによるpodネットワークのアドレスを各ノードで確認。以下はMasterノードでの例)
[root@c8-k8s-1 ~]# ip a(抜粋表示)
...
8: weave:  mtu 1376 qdisc noqueue state UP group default qlen 1000
    link/ether 6e:54:55:ec:0c:48 brd ff:ff:ff:ff:ff:ff
    inet 10.32.0.1/12 brd 10.47.255.255 scope global weave
…
[root@c8-k8s-1 ~]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.101.1   0.0.0.0         UG    100    0        0 ens3
10.32.0.0       0.0.0.0         255.240.0.0     U     0      0        0 weave

[root@c8-k8s-1 ~]# kubectl exec weave-net-v64qs -n kube-system -c weave -- /home/weave/weave --local report

podネットワークは10.32.0.0/12に設定されています。
vxlan を使用し、ノードネットワーク192.168.101.0/24 のオーバーレイネットワークとなっているようです。
以下の通り、このネットワークに各ノードで稼動するアプリケーションpod(及び一部のシステムpod)が接続されています。
(kube-proxyとweaveは192.168.101.0/24に接続)

(nginxのyamlファイルでレプリカの個数を5個に指定したので、5個のpodがどのノードで稼動しているか確認)
[root@c8-k8s-1 ~]# kubectl get pods -o wide
NAME                     READY   STATUS    RESTARTS   AGE    IP          NODE                   ...(以降省略)
nginx-589d667786-2f8k2   1/1     Running   0          105s   10.47.0.3   c8-k8s-3.localdomain   ...(以降省略)
nginx-589d667786-5c8rx   1/1     Running   0          106s   10.47.0.2   c8-k8s-3.localdomain   ...(以降省略)
nginx-589d667786-bjd76   1/1     Running   0          105s   10.44.0.3   c8-k8s-2.localdomain   ...(以降省略)
nginx-589d667786-fw448   1/1     Running   0          106s   10.44.0.2   c8-k8s-2.localdomain   ...(以降省略)
nginx-589d667786-tbvk9   1/1     Running   0          106s   10.47.0.1   c8-k8s-3.localdomain   ...(以降省略)

(nginx service に EXTERNAL-IP が割り当てられたことを確認)
[root@c8-k8s-1 ~]# kubectl get service nginx
NAME    TYPE           CLUSTER-IP     EXTERNAL-IP       PORT(S)        AGE
nginx   LoadBalancer   10.96.132.49   192.168.101.240   80:31994/TCP   61s

(外部公開アドレス(EXTERNAL-IP)にアクセスして、nginxのサービスを受けられることを確認)
[root@c8-k8s-1 ~]# curl http://192.168.101.240
...
<h1>Welcome to nginx!</h1>
...

(iptablesのバージョンを確認)
[root@c8-k8s-1 ~]# iptables --version
iptables v1.8.2 (nf_tables)

[root@c8-k8s-1 ~]# kubectl exec kube-proxy-wjz49 -n kube-system -c kube-proxy -- cat /etc/issue
Debian GNU/Linux 10 \n \l   ← kube-proxyコンテナのベースOSは「Debian GNU/Linux 10」
[root@c8-k8s-1 ~]# kubectl exec kube-proxy-wjz49 -n kube-system -c kube-proxy -- iptables --version
iptables v1.8.3 (nf_tables)

[root@c8-k8s-1 ~]# kubectl exec weave-net-v64qs -n kube-system -c weave -- /home/weave/weave --local version 
weave 2.6.2
[root@c8-k8s-1 ~]# kubectl exec weave-net-v64qs -n kube-system -c weave -- cat /etc/issue
Welcome to Alpine Linux 3.10  ← weave-netコンテナのベースOSは「Alpine Linux 3.10」
Kernel \r on an \m (\l)
[root@c8-k8s-1 ~]# kubectl exec weave-net-v64qs -n kube-system -c weave -- iptables --version
iptables v1.8.3 (nf_tables)

以上