Kubernetes The Hard Way とは
Kubernetes の公式ドキュメントで Setup の項目をたどると kubeadm を使う例が記載されている。いくつかの機能はまだ alpha/beta であるものの公式でも kubeadm をクラスタ構築に使う流れを後押ししたいように見える。確かに kubeadm (や各ベンダの構築ツール)を使ったクラスタ構築は楽なのだけれど、ツール内部でやっていることを理解しない限りただツールに使われるだけになってしまうのと、トラブル発生時に原因把握もできなくなってしまう。ここでは従来よりスクラッチからのクラスタ構築として定評のある Kubernetes The Hard Way を AWS で実施していく。なお本家は GCP での構築例であり、AWS のサポートには消極的な様子。ここでは少し古いものの AWS 版の Hard Way を公開している方がいるのでそちらをベースに進めながら、AWS 依存の構成やバージョンのアップデートなどでハマった点を備忘録がてらに残しておく。
本家(GCPでの構築を想定) GitHub - kelseyhightower/kubernetes-the-hard-way: Bootstrap Kubernetes the hard way on Google Cloud Platform. No scripts.
分家(本家をAWSでの構築用に追記+修正したもの。内容はやや古い) GitHub - slawekzachcial/kubernetes-the-hard-way-aws: AWS flavour of https://github.com/kelseyhightower/kubernetes-the-hard-way
実際に Kubernetes The Hardway on AWS を完走するまでにやったことと注意点
- VPC, Subnet, RouteTable, Internet Gateway などは awscli ではなく CloudFormation で実施したほうが便利。何回かやり直すことになると思うので再実行しやすいのと振り返りにも役立つ。
- 各手順もそれぞれシェルスクリプトにまとめておくと再実行しやすいし、あとでプロビジョニングツール用に変換もできる。slawekzachcial さんの AWS 版では内部IP取得のために無駄にだらだら awscli を長く利用していたり、user-data に埋め込んでいるところがあるが、そこは固定で埋め込んでしまったほうが混乱がなくてよい。
- slawekzachcial さんの例では kubelet v1.9.0 だが kubelet v1.9.0 + ubuntu 18.04 だと
couldn't propagate object cache: timed out waiting for the condition
になるので controllers, workres ともに v1.12.7 にアップデートする。 pods "coredns-595db6f9cb-svfj5" is forbidden: User "system:node:ip-10-240-0-20" cannot patch pods/status in the namespace "kube-system"
を解決するために clusterrole も更新する。- slawekzachcial さんの例では kubelet + cri-containerd で構築しているが kubelet + containerd に置き換える。cri-containerd はあくまで過渡期の一時用であり、containerd 1.1 から完全体となっているため。
- 公式ドキュメントでも記載されているが、最低限のマシンスペックとして 2GB RAM, 2 CPUs が必要とされる。最初ケチって t3.nano で構築していたが、これだと workers の構築が完了し kubelet, kube-proxy を動作させると controllers 側が劇的に重くなるので t3.small にした。 https://kubernetes.io/docs/setup/independent/install-kubeadm/
- EC2 の src/dst チェック外しておく。ENI(Elastic Network Interface) で作成した 10.200.0.0/16 のパケットが ENI に届けられず破棄されてしまう。
- Route Table の「Main Table」を変更するのを忘れずに。
- Securigy Group で DNS(udp:53) が塞がれていると、kube-dns service(10.32.0.10) から各 endpoint の coredns pod へ通信できない。いっそ Pod CIDR のネットワーク帯は All traffic を通すのも検証段階ではよいと思う(= All traffic from 10.200.0.0/24, 10.200.0.0/16)。これで node(ec2) からも dig が通るようになる。
- coreDNS は以下が通れば OK。
ubuntu@ip-10-240-0-10:~/80-k8s-hardway$ dig +short @10.200.0.25 www.google.com kubernetes.default.svc.cluster.local kube-dns.kube-system.svc.cluster.local 172.217.164.164 10.32.0.1 10.32.0.10
- 正しく完走できれば最終的には以下のようになるはず。
- Kubernetes のネットワークモデルについては以下のドキュメントがとてもわかりやすい。AWS を元にして書かれているのと、内部で amazon-vpc-cni-k8s という CNI プラグインを紹介しているがこれは Hard Way で ENI と Route Table を利用して POD CIDR への経路を用意したのと同じように思える。
GCP ではなく AWS で Kubernetes The Hard Way を実施するのは、AWS 依存の設定もあり、文字通り以上にハードだったけれど、そのぶん Controll-pane や worker 、そして CNI の概要が理解できたと思う。ただ完全には把握できず、やはり Kubernetes 難しいと改めて感じたのと、バージョンごとに機能や設定がどんどん変わっていくので追随していかないと構築例もあっというまに時代遅れになってしまうと感じた (_o_)