Production-ReadyなK8s(RKE2)クラスタを構築する際のあれこれ

この記事は MicroAd Advent Calendar 2022 の4日目の記事です。

qiita.com

本番でUnmanagedなKubernetesクラスタを構築しようとした際にどうやって構築するか悩みますよね。
今回はKubernetesディストリビューションのRKE2を用いて書いていきます。

前提

  • OS:Ubuntu 20.04 (RH系も多分大丈夫)
  • Arch:amd64
  • Kubernetes distribution: RKE2
  • Ranhcer: v2.6
  • CNI: Cilium(L2・VXLAN)
  • 用途: Rancher Serverのinstall先、または、Rancherで管理しないKubernetesクラスタ

ここで触れないこと

CNIやPV、Secretなどは、ボリュームがデカいのでまたの機会に。

RKE2って?

docs.rke2.io

RKE2は、米国連邦政府のセキュリティとコンプライアンスに重点を置き、完全準拠しているKubernetesディストリビューションだそうです(なんか強そう)。

そのため、RKE2では以下を行っているそうです。

また、Rancher Labsの血を引いているのでK3sの使いやすさやシンプルさを兼ね備えています(ただし機能はK3sとはことなり何かを引いているとかはないです)。

アーキテクチャについては以下を参照ください。

docs.rke2.io

RancherのWeb UIからRKE2 Nodeをinstall可能ですが、K3sの様に簡単にinstall出来ます。
Server Node(≒control plane)をセットアップする場合、 /etc/rancher/rke2/config.yaml に設定ファイルを置いた上で、以下を実行したら立ち上がってきます。

# curl -sfL https://get.rke2.io | INSTALL_RKE2_VERSION="v1.XX.X+rke2rX" INSTALL_RKE2_TYPE="server" sh -
# systemctl enable --now rke2-server.service

IaCし易い構成になっていて、以下の様にansibleのリポジトリもあります。

github.com

また、Kubernetesクラスタ構築の際に、インターネット経由でコンテナイメージを各サーバから取得出来ない場合は、Air-Gap向けのinstallが用意されています。

docs.rke2.io

Kubernetesコンポーネント

Kubernetesクラスタを構成する場合、大きく「Control Plane」と「Node」の役割があります。
アプリはNode上でPodを管理し、Control Planeは、クラスタ内のNodeとPodを管理します。

kubernetes.io

RKE2のアーキテクチャ

RKE2のアーキテクチャは以下が参考になります。
基本的には一般的なKubernetesと変わりないです。

docs.rke2.io

RKE2特有の用語として、「Server Node」と「Agent Node」があります。
Kubernetesコンポーネントと照らして考えた場合、
ざっくりと「Server Node」=「Control Plane」、「Agent Node」=「Node」として考えたらOKです。 (正確には「Server Node」にはcontrol planeとetcdが含まれます)

ただ、RKE2をinstallする際に INSTALL_RKE2_TYPE="server" として構築した「Server Node」は、Kubernetesコンポーネントでいうところの「Control Plane」だけでなく「Node」としての役割としても機能出来ます。 (利用者のワークロードを実行したくない場合は、install設定でnode-taintに設定が必要です1

つまり、1台だけでもKubernetesとして機能します。

RKE2の制限事項・必要条件

ハマりそうなのは以下の2つ。

  • firewalldを無効するRKE2と言うよりはCNIの制限)
  • NetworkManagerを使っている場合は、NetworkManager が calico/flannel 関連のネットワークインターフェイスを無視するよう設定が必要
  • ホスト名はユニークにしなければいけない

他にもあるので詳細は以下を参照ください。

docs.rke2.io

docs.rke2.io

次から本番クラスタについて考えていきます。

RKE2 ServerとAgent Nodeの構成をどうするか

ざっくり考えられそうなパターンは以下。

No Server Node Agent Node 備考
1 1 0 可用性0のお試し環境
2 3 0 最小のHA構成。HAなRancher Management Serverの最小構成
Downstream User Clusterとしてユーザ利用する場合はワークロードがI/OヘビーだとKubernetes API(etcd)に影響するのでおすすめ出来ない。
3 3 1以上 安パイなHA構成。
★:No.2と違いServer Nodeにユーザのワークロードを実行しないようにNode Taintを付ける。
4 5 1以上 一番安全な構成。Server Nodeをcontrol plane×2、etcd×3として構成する。
★:No.3と同様にServer NodeにNode Taintを付ける。

RKE2にてcontrol planeとetcdを分けて構築するには

以下のようにして、etcd・control planeロールのみになる設定するとOK。

www.suse.com

RancherからCreateしたクラスタと構築済みのクラスタを登録する場合の違い

「(Web UIやCLI使って)Rancherからで作成する場合」と「構築済みのクラスタをRancherに登録(Import)する場合」では出来る操作が変わります。基本的には登録したクラスタについてはRancherを使わずに管理することになります。詳細は以下のドキュメントあたりが参考になります。

出来ることが増えるので、Rancherを使ってクラスタを管理するなら特別な理由が無い限り、Downstream User ClusterとしてRKE2を使う場合には、基本的にはRancherからクラスタを作成した方が良いです。

RKE2の設定ポイント

RKE2の設定は以下にまとまってます

docs.rke2.io

設定ポイント:RKE2で利用するデータ領域を別Diskに指定する

オンプレ利用時の特有な考慮事項。
OSと同じDiskをRKE2でも使った場合、RKE2関連の利用によるH/W障害がOSに影響しないようにするためにDisk分けるという選択もありです。

--data-dir (default: "/var/lib/rancher/rke2") を使って、別Diskを指定することも出来ます。

設定ポイント: tokenは指定する方が楽 ※超重要※

tokenは設定しないと /var/lib/rancher/rke2/server/node-token に自動生成してしまいます。
事前に任意のランダム文字列を決めておいてそれを利用する方がIaCするときには非常に楽です(文字列なら何でもOK)。

設定ポイント:RKE2 Server Node

ドキュメントが古いのでCLIのヘルプを確認する

RKE2 Serverの設定は以下の通り。

Server Configuration Reference | RKE 2

ただし、このドキュメントは古くて必要なパラメータがすべて入っていません。
RKE2 CLIのバージョンによっても変わるので、以下のようにして実際にコマンドのhelpを確認した方が良いです。

# rke2 help server
NAME:
   rke2 server - Run management server

USAGE:
   rke2 server [OPTIONS]

OPTIONS:
   --config FILE, -c FILE                        (config) Load configuration from FILE (default: "/etc/rancher/rke2/config.yaml") [$RKE2_CONFIG_FILE]
   --debug                                       (logging) Turn on debug logs [$RKE2_DEBUG]
   --bind-address value                          (listener) rke2 bind address (default: 0.0.0.0)
   --advertise-address value                     (listener) IPv4 address that apiserver uses to advertise to members of the cluster (default: node-external-ip/node-ip)
   --tls-san value                               (listener) Add additional hostnames or IPv4/IPv6 addresses as Subject Alternative Names on the server TLS cert
   --data-dir value, -d value                    (data) Folder to hold state (default: "/var/lib/rancher/rke2")
   --cluster-cidr value                          (networking) IPv4/IPv6 network CIDRs to use for pod IPs (default: 10.42.0.0/16)
   --service-cidr value                          (networking) IPv4/IPv6 network CIDRs to use for service IPs (default: 10.43.0.0/16)
   --service-node-port-range value               (networking) Port range to reserve for services with NodePort visibility (default: "30000-32767")
   --cluster-dns value                           (networking) IPv4 Cluster IP for coredns service. Should be in your service-cidr range (default: 10.43.0.10)
   --cluster-domain value                        (networking) Cluster Domain (default: "cluster.local")
   --egress-selector-mode value                  (networking) One of 'agent', cluster', 'pod', 'disabled' (default: "agent")
   --servicelb-namespace value                   (networking) Namespace of the pods for the servicelb component (default: "kube-system")
   --token value, -t value                       (cluster) Shared secret used to join a server or agent to a cluster [$RKE2_TOKEN]
   --token-file value                            (cluster) File containing the cluster-secret/token [$RKE2_TOKEN_FILE]
   --write-kubeconfig value, -o value            (client) Write kubeconfig for admin client to this file [$RKE2_KUBECONFIG_OUTPUT]
   --write-kubeconfig-mode value                 (client) Write kubeconfig with this mode [$RKE2_KUBECONFIG_MODE]
   --enable-pprof                                (experimental) Enable pprof endpoint on supervisor port
   --kube-apiserver-arg value                    (flags) Customized flag for kube-apiserver process
   --etcd-arg value                              (flags) Customized flag for etcd process
   --kube-controller-manager-arg value           (flags) Customized flag for kube-controller-manager process
   --kube-scheduler-arg value                    (flags) Customized flag for kube-scheduler process
   --etcd-expose-metrics                         (db) Expose etcd metrics to client interface. (Default false)
   --etcd-disable-snapshots                      (db) Disable automatic etcd snapshots
   --etcd-snapshot-name value                    (db) Set the base name of etcd snapshots. Default: etcd-snapshot-<unix-timestamp> (default: "etcd-snapshot")
   --etcd-snapshot-schedule-cron value           (db) Snapshot interval time in cron spec. eg. every 5 hours '* */5 * * *' (default: "0 */12 * * *")
   --etcd-snapshot-retention value               (db) Number of snapshots to retain (default: 5)
   --etcd-snapshot-dir value                     (db) Directory to save db snapshots. (Default location: ${data-dir}/db/snapshots)
   --etcd-snapshot-compress                      (db) Compress etcd snapshot
   --etcd-s3                                     (db) Enable backup to S3
   --etcd-s3-endpoint value                      (db) S3 endpoint url (default: "s3.amazonaws.com")
   --etcd-s3-endpoint-ca value                   (db) S3 custom CA cert to connect to S3 endpoint
   --etcd-s3-skip-ssl-verify                     (db) Disables S3 SSL certificate validation
   --etcd-s3-access-key value                    (db) S3 access key [$AWS_ACCESS_KEY_ID]
   --etcd-s3-secret-key value                    (db) S3 secret key [$AWS_SECRET_ACCESS_KEY]
   --etcd-s3-bucket value                        (db) S3 bucket name
   --etcd-s3-region value                        (db) S3 region / bucket location (optional) (default: "us-east-1")
   --etcd-s3-folder value                        (db) S3 folder
   --etcd-s3-insecure                            (db) Disables S3 over HTTPS
   --etcd-s3-timeout value                       (db) S3 timeout (default: 5m0s)
   --disable value                               (components) Do not deploy packaged components and delete any deployed components (valid items: rke2-coredns, rke2-ingress-nginx, rke2-metrics-server)
   --disable-scheduler                           (components) Disable Kubernetes default scheduler
   --disable-cloud-controller                    (components) Disable rke2 default cloud controller manager
   --disable-kube-proxy                          (components) Disable running kube-proxy
   --node-name value                             (agent/node) Node name [$RKE2_NODE_NAME]
   --node-label value                            (agent/node) Registering and starting kubelet with set of labels
   --node-taint value                            (agent/node) Registering kubelet with set of taints
   --image-credential-provider-bin-dir value     (agent/node) The path to the directory where credential provider plugin binaries are located (default: "/var/lib/rancher/credentialprovider/bin")
   --image-credential-provider-config value      (agent/node) The path to the credential provider plugin config file (default: "/var/lib/rancher/credentialprovider/config.yaml")
   --container-runtime-endpoint value            (agent/runtime) Disable embedded containerd and use alternative CRI implementation
   --snapshotter value                           (agent/runtime) Override default containerd snapshotter (default: "overlayfs")
   --private-registry value                      (agent/runtime) Private registry configuration file (default: "/etc/rancher/rke2/registries.yaml")
   --node-ip value, -i value                     (agent/networking) IPv4/IPv6 addresses to advertise for node
   --node-external-ip value                      (agent/networking) IPv4/IPv6 external IP addresses to advertise for node
   --resolv-conf value                           (agent/networking) Kubelet resolv.conf file [$RKE2_RESOLV_CONF]
   --kubelet-arg value                           (agent/flags) Customized flag for kubelet process
   --kube-proxy-arg value                        (agent/flags) Customized flag for kube-proxy process
   --protect-kernel-defaults                     (agent/node) Kernel tuning behavior. If set, error if kernel tunables are different than kubelet defaults.
   --agent-token value                           (cluster) Shared secret used to join agents to the cluster, but not servers [$RKE2_AGENT_TOKEN]
   --agent-token-file value                      (cluster) File containing the agent secret [$RKE2_AGENT_TOKEN_FILE]
   --server value, -s value                      (cluster) Server to connect to, used to join a cluster [$RKE2_URL]
   --cluster-reset                               (cluster) Forget all peers and become sole member of a new cluster [$RKE2_CLUSTER_RESET]
   --cluster-reset-restore-path value            (db) Path to snapshot file to be restored
   --system-default-registry value               (image) Private registry to be used for all system images [$RKE2_SYSTEM_DEFAULT_REGISTRY]
   --selinux                                     (agent/node) Enable SELinux in containerd [$RKE2_SELINUX]
   --lb-server-port value                        (agent/node) Local port for supervisor client load-balancer. If the supervisor and apiserver are not colocated an additional port 1 less than this port will also be used for the apiserver client load-balancer. (default: 6444) [$RKE2_LB_SERVER_PORT]
   --cni value                                   (networking) CNI Plugins to deploy, one of none, calico, canal, cilium; optionally with multus as the first value to enable the multus meta-plugin (default: canal) [$RKE2_CNI]
   --enable-servicelb                            (components) Enable rke2 default cloud controller manager's service controller [$RKE2_ENABLE_SERVICELB]
   --kube-apiserver-image value                  (image) Override image to use for kube-apiserver [$RKE2_KUBE_APISERVER_IMAGE]
   --kube-controller-manager-image value         (image) Override image to use for kube-controller-manager [$RKE2_KUBE_CONTROLLER_MANAGER_IMAGE]
   --cloud-controller-manager-image value        (image) Override image to use for cloud-controller-manager [$RKE2_CLOUD_CONTROLLER_MANAGER_IMAGE]
   --kube-proxy-image value                      (image) Override image to use for kube-proxy [$RKE2_KUBE_PROXY_IMAGE]
   --kube-scheduler-image value                  (image) Override image to use for kube-scheduler [$RKE2_KUBE_SCHEDULER_IMAGE]
   --pause-image value                           (image) Override image to use for pause [$RKE2_PAUSE_IMAGE]
   --runtime-image value                         (image) Override image to use for runtime binaries (containerd, kubectl, crictl, etc) [$RKE2_RUNTIME_IMAGE]
   --etcd-image value                            (image) Override image to use for etcd [$RKE2_ETCD_IMAGE]
   --kubelet-path value                          (experimental/agent) Override kubelet binary path [$RKE2_KUBELET_PATH]
   --cloud-provider-name value                   (cloud provider) Cloud provider name [$RKE2_CLOUD_PROVIDER_NAME]
   --cloud-provider-config value                 (cloud provider) Cloud provider configuration file path [$RKE2_CLOUD_PROVIDER_CONFIG]
   --profile value                               (security) Validate system configuration against the selected benchmark (valid items: cis-1.5, cis-1.6 ) [$RKE2_CIS_PROFILE]
   --audit-policy-file value                     (security) Path to the file that defines the audit policy configuration [$RKE2_AUDIT_POLICY_FILE]
   --control-plane-resource-requests value       (components) Control Plane resource requests [$RKE2_CONTROL_PLANE_RESOURCE_REQUESTS]
   --control-plane-resource-limits value         (components) Control Plane resource limits [$RKE2_CONTROL_PLANE_RESOURCE_LIMITS]
   --kube-apiserver-extra-mount value            (components) kube-apiserver extra volume mounts [$RKE2_KUBE_APISERVER_EXTRA_MOUNT]
   --kube-scheduler-extra-mount value            (components) kube-scheduler extra volume mounts [$RKE2_KUBE_SCHEDULER_EXTRA_MOUNT]
   --kube-controller-manager-extra-mount value   (components) kube-controller-manager extra volume mounts [$RKE2_KUBE_CONTROLLER_MANAGER_EXTRA_MOUNT]
   --kube-proxy-extra-mount value                (components) kube-proxy extra volume mounts [$RKE2_KUBE_PROXY_EXTRA_MOUNT]
   --etcd-extra-mount value                      (components) etcd extra volume mounts [$RKE2_ETCD_EXTRA_MOUNT]
   --cloud-controller-manager-extra-mount value  (components) cloud-controller-manager extra volume mounts [$RKE2_CLOUD_CONTROLLER_MANAGER_EXTRA_MOUNT]
   --kube-apiserver-extra-env value              (components) kube-apiserver extra environment variables [$RKE2_KUBE_APISERVER_EXTRA_ENV]
   --kube-scheduler-extra-env value              (components) kube-scheduler extra environment variables [$RKE2_KUBE_SCHEDULER_EXTRA_ENV]
   --kube-controller-manager-extra-env value     (components) kube-controller-manager extra environment variables [$RKE2_KUBE_CONTROLLER_MANAGER_EXTRA_ENV]
   --kube-proxy-extra-env value                  (components) kube-proxy extra environment variables [$RKE2_KUBE_PROXY_EXTRA_ENV]
   --etcd-extra-env value                        (components) etcd extra environment variables [$RKE2_ETCD_EXTRA_ENV]
   --cloud-controller-manager-extra-env value    (components) cloud-controller-manager extra environment variables [$RKE2_CLOUD_CONTROLLER_MANAGER_EXTRA_ENV]

クラスタ内部から外へ通信が発生する場合は--tls-sanへの追加を忘れない

クラスタ内部で外部と通信が必要な場合(クラスタ外のHashicorp VaultサーバからSecretをもらいたいとか)、tls-sanFQDNまたはIPアドレスを追加する必要がります。

例えば、tls-sanに外部Vaultのエンドポイントを追加しておかないとPodとVault間の認証に使う VaultのKubernetes Auth Methodにて、403 permission denied になってしまうので要注意。
また、後から追加したい場合は、Serever Nodeに1台ずつ追加してrke2-serverを再起動し全台適用が済んだら利用可能になる

ネットワーク設定について

ネットワーク関連の設定は以下が参考になります。

docs.rke2.io

また、CNIについては、Network Options | RKE 2 にある通り、RKE2から利用できるCNIは限定されています(とは言えメジャーどころは抑えてます)。

標準で用意されているオプションは以下の通り。

docs.rke2.io

CNIが、Rancher Servcerとして利用可能か または Rancher Servcerの管理下のクラスタとして利用できるか については、 Rancherのサポートマトリクス を確認ください。

サポート外でも良いので、RKE2が用意していないCNI使う場合は、以前作成した以下の記事を参考にしてください。

qiita.com

※ただし、クラスタのアップデートなどは慎重に確認が必要です。

設定ポイント:RKE2 Agent Node

ドキュメントが古いのでCLIのヘルプを確認する

RKE2 Serverの設定は以下の通り。

Agent Configuration Reference | RKE 2

Serverと同じ様に古いのでCLIのヘルプを確認した方が良いです。

# rke2 help agent
NAME:
   rke2 agent - Run node agent

USAGE:
   rke2 agent [OPTIONS]

OPTIONS:
   --config FILE, -c FILE                        (config) Load configuration from FILE (default: "/etc/rancher/rke2/config.yaml") [$RKE2_CONFIG_FILE]
   --debug                                       (logging) Turn on debug logs [$RKE2_DEBUG]
   --token value, -t value                       (cluster) Token to use for authentication [$RKE2_TOKEN]
   --token-file value                            (cluster) Token file to use for authentication [$RKE2_TOKEN_FILE]
   --server value, -s value                      (cluster) Server to connect to [$RKE2_URL]
   --data-dir value, -d value                    (data) Folder to hold state (default: "/var/lib/rancher/rke2")
   --node-name value                             (agent/node) Node name [$RKE2_NODE_NAME]
   --node-label value                            (agent/node) Registering and starting kubelet with set of labels
   --node-taint value                            (agent/node) Registering kubelet with set of taints
   --image-credential-provider-bin-dir value     (agent/node) The path to the directory where credential provider plugin binaries are located (default: "/var/lib/rancher/credentialprovider/bin")
   --image-credential-provider-config value      (agent/node) The path to the credential provider plugin config file (default: "/var/lib/rancher/credentialprovider/config.yaml")
   --container-runtime-endpoint value            (agent/runtime) Disable embedded containerd and use alternative CRI implementation
   --snapshotter value                           (agent/runtime) Override default containerd snapshotter (default: "overlayfs")
   --private-registry value                      (agent/runtime) Private registry configuration file (default: "/etc/rancher/rke2/registries.yaml")
   --node-ip value, -i value                     (agent/networking) IPv4/IPv6 addresses to advertise for node
   --node-external-ip value                      (agent/networking) IPv4/IPv6 external IP addresses to advertise for node
   --resolv-conf value                           (agent/networking) Kubelet resolv.conf file [$RKE2_RESOLV_CONF]
   --kubelet-arg value                           (agent/flags) Customized flag for kubelet process
   --kube-proxy-arg value                        (agent/flags) Customized flag for kube-proxy process
   --protect-kernel-defaults                     (agent/node) Kernel tuning behavior. If set, error if kernel tunables are different than kubelet defaults.
   --selinux                                     (agent/node) Enable SELinux in containerd [$RKE2_SELINUX]
   --lb-server-port value                        (agent/node) Local port for supervisor client load-balancer. If the supervisor and apiserver are not colocated an additional port 1 less than this port will also be used for the apiserver client load-balancer. (default: 6444) [$RKE2_LB_SERVER_PORT]
   --kube-apiserver-image value                  (image) Override image to use for kube-apiserver [$RKE2_KUBE_APISERVER_IMAGE]
   --kube-controller-manager-image value         (image) Override image to use for kube-controller-manager [$RKE2_KUBE_CONTROLLER_MANAGER_IMAGE]
   --cloud-controller-manager-image value        (image) Override image to use for cloud-controller-manager [$RKE2_CLOUD_CONTROLLER_MANAGER_IMAGE]
   --kube-proxy-image value                      (image) Override image to use for kube-proxy [$RKE2_KUBE_PROXY_IMAGE]
   --kube-scheduler-image value                  (image) Override image to use for kube-scheduler [$RKE2_KUBE_SCHEDULER_IMAGE]
   --pause-image value                           (image) Override image to use for pause [$RKE2_PAUSE_IMAGE]
   --runtime-image value                         (image) Override image to use for runtime binaries (containerd, kubectl, crictl, etc) [$RKE2_RUNTIME_IMAGE]
   --etcd-image value                            (image) Override image to use for etcd [$RKE2_ETCD_IMAGE]
   --kubelet-path value                          (experimental/agent) Override kubelet binary path [$RKE2_KUBELET_PATH]
   --cloud-provider-name value                   (cloud provider) Cloud provider name [$RKE2_CLOUD_PROVIDER_NAME]
   --cloud-provider-config value                 (cloud provider) Cloud provider configuration file path [$RKE2_CLOUD_PROVIDER_CONFIG]
   --profile value                               (security) Validate system configuration against the selected benchmark (valid items: cis-1.5, cis-1.6 ) [$RKE2_CIS_PROFILE]
   --audit-policy-file value                     (security) Path to the file that defines the audit policy configuration [$RKE2_AUDIT_POLICY_FILE]
   --control-plane-resource-requests value       (components) Control Plane resource requests [$RKE2_CONTROL_PLANE_RESOURCE_REQUESTS]
   --control-plane-resource-limits value         (components) Control Plane resource limits [$RKE2_CONTROL_PLANE_RESOURCE_LIMITS]
   --kube-apiserver-extra-mount value            (components) kube-apiserver extra volume mounts [$RKE2_KUBE_APISERVER_EXTRA_MOUNT]
   --kube-scheduler-extra-mount value            (components) kube-scheduler extra volume mounts [$RKE2_KUBE_SCHEDULER_EXTRA_MOUNT]
   --kube-controller-manager-extra-mount value   (components) kube-controller-manager extra volume mounts [$RKE2_KUBE_CONTROLLER_MANAGER_EXTRA_MOUNT]
   --kube-proxy-extra-mount value                (components) kube-proxy extra volume mounts [$RKE2_KUBE_PROXY_EXTRA_MOUNT]
   --etcd-extra-mount value                      (components) etcd extra volume mounts [$RKE2_ETCD_EXTRA_MOUNT]
   --cloud-controller-manager-extra-mount value  (components) cloud-controller-manager extra volume mounts [$RKE2_CLOUD_CONTROLLER_MANAGER_EXTRA_MOUNT]
   --kube-apiserver-extra-env value              (components) kube-apiserver extra environment variables [$RKE2_KUBE_APISERVER_EXTRA_ENV]
   --kube-scheduler-extra-env value              (components) kube-scheduler extra environment variables [$RKE2_KUBE_SCHEDULER_EXTRA_ENV]
   --kube-controller-manager-extra-env value     (components) kube-controller-manager extra environment variables [$RKE2_KUBE_CONTROLLER_MANAGER_EXTRA_ENV]
   --kube-proxy-extra-env value                  (components) kube-proxy extra environment variables [$RKE2_KUBE_PROXY_EXTRA_ENV]
   --etcd-extra-env value                        (components) etcd extra environment variables [$RKE2_ETCD_EXTRA_ENV]
   --cloud-controller-manager-extra-env value    (components) cloud-controller-manager extra environment variables [$RKE2_CLOUD_CONTROLLER_MANAGER_EXTRA_ENV]

CNIの設定は不要

Agentの設定にcniの指定は不要です。
RKE2 Server NodeがAgent Nodeをクラスタに追加する際に、Server Node側からCNIの指定をするのでAgent Nodeで指定する必要は無いです。

なので、特別な設定が何も必要ないなら設定は以下だけ。

server: https://${LBのFQDN}:9345
token: ${SERVER_TOKEN}

HAクラスタの構築の流れ

Rancherを使わずにRKE2にてHAクラスタを構築する場合の流れは、基本的には以下のドキュメントの通りです。

docs.rke2.io

大まかな流れは以下の通り。

  1. LBを構築して起動
    • ただし、ProxyするのはRKE2 Serverの1台目だけ
  2. RKE2 Server Nodeの1台目を起動
  3. RKE2 Server Nodeの2台目以降を起動
  4. RKE2 Server Nodeが正常に起動後、1台目の設定のserverコメントアウトしてrke2-serverサービスを再起動
  5. LBでProxyする対象を2台目以降のRKE2 Server Nodeも含めるようにする
  6. RKE2 Agent Nodeを追加
  7. kubectl get nodekubectl get po -A -o wide してPodが正常に稼働しているか最終確認

また、RKE2のロールのetcd、control plane、workerを分けて構築する場合は以下を参考にしてください。

www.suse.com

この場合、大まかな流れは以下の通り。

  1. LBを構築して起動
    • ただし、Proxyするのはcontrol planeロールのNodeは1台目だけ
  2. etcdロールの設定をして起動(etcdとして起動したいNode分だけ実行)
  3. control planeロールの設定をして起動
    • ただし、1台目の設定に LBを指定したserverは必要だが、もう1台には不要
  4. control planeロールのNodeが2台とも正常に起動後、1台目の設定のserverコメントアウトしてrke2-serverサービスを再起動
  5. LBでProxyする対象を2台目のcontrol planeロールのNodeも含めるようにする
  6. RKE2 Agent Nodeを追加
  7. kubectl get nodekubectl get po -A -o wide してPodが正常に稼働しているか最終確認

rke2-serverサービスの状況は sudo journalctl -u rke2-server -f でログを確認すると分かります。
どちらの方法についても、kubectl get nodeでNodeのSTATUSはReadyとなっていても、以下の様なエラーが出て正常にクラスタ参加が出来ていない状態ですが、1台目のcontrol planeロールのNodeが正常に起動するとエラーログは消えます。

Nov 30 05:27:17 rke2-server01 rke2[1190]: time="2022-11-30T05:27:17+09:00" level=info msg="Connecting to proxy" url="wss://172.30.40.26:9345/v1-rke2/connect"
Nov 30 05:27:19 rke2-server01 rke2[1190]: time="2022-11-30T05:27:19+09:00" level=error msg="Remotedialer proxy error" error="connect not allowed"

Tips1:LBの構築ポイント

クラスタ管理用のエンドポイントとして利用するLBの構築ポイントについて。

以下のポートをcontrol planeのいるNodeにProxyしたらOK。

  • 6443 → RKE2 Server Nodeの6443(Kubernetes API Server用ポート)
  • 9345 → RKE2 Server Nodeの9345 (RKE2向けの新しいNodeの登録用ポート)

例えば、HAProxyの場合ならこんな感じ。

frontend apiservers
    bind *:6443
    mode tcp
    option  tcplog
    default_backend k8s_apiservers

backend k8s_apiservers
    mode tcp
    balance roundrobin
    option log-health-checks
    default-server inter 10s fall 2
    server rke2-server01 198.51.100.2:6443 check
    server rke2-server02 198.51.100.3:6443 check
    server rke2-server03 198.51.100.4:6443 check

frontend new_node_regist
    bind 198.51.100.1:9345 # LBのIP
    option tcplog
    mode tcp
    default_backend rke2_new_node_regist

backend rke2_new_node_regist
    mode tcp
    option ssl-hello-chk
    option log-health-checks
    default-server inter 10s fall 2
    server rke2-server01 198.51.100.2:9345 check
    server rke2-server02 198.51.100.3:9345 check
    server rke2-server03 198.51.100.4:9345 check

HAProxyで無くても以下の条件を満たせばOK。例えばLVSとか。

  • A layer 4 (TCP) load balancer
  • Round-robin DNS
  • Virtual or Elastic IP addresses

docs.rke2.io

また、LB自体の可用性も必要になるので、Keepalivedなどの利用も合わせて検討ください。

そのあたりについては、以下のKubeadmのドキュメントが参考になります。

github.com

(´-`).。oO(kube-vipがGAしたら良いなぁ)

Tips2:1台目の設定のserverコメントアウトしてrke2-serverサービスを再起動する理由

これを実施しないと1台目のNodeのrke2-serverサービスを再起動した際に、稼働中の2台目のServer Node(control plane)に参加出来ない為です。

RKE2(Kubernetes)のアップグレード

Rancher UIの ☰ > Cluster Management から対象のクラスタを選択して> Edit Configにアップグレード可能なバージョンがあるのでそれを選んでアップグレードする方法もあります。詳細は、 Upgrading and Rolling Back Kubernetes | Rancher Manager を参照ください。

他にもRKE2の場合は、 手動でアップグレードする方法 もあります。
ただ、system-upgrade-controller を使ったKubernetesネイティブな自動アップグレード方法があり、柔軟にアップグレード設定出来るのでとても便利。オススメ。

docs.rke2.io

自動といってもCRDを使って設定する際に、versionv1.23.1+rke2r2のようにして設定したらバージョンを固定に出来るので勝手にアップグレードされることはないです。
ただ、CRDのversionの代わりに、channelを使ってhttps://update.rke2.io/v1-release/channels/stableなどのように指定するとリリースされた時点で自動でアップデート可能なようです。設定可能なチャンネルは https://update.rke2.io/v1-release/channels を見ると分かります。

さいごに

いかがだったでしょうか。
RKE2を使ったKubernetesクラスタを構築する際の考慮事項についてまとめてみました。

これをきっかけに挑戦してみた方がいたら是非以下のRancherJPのMeetupでの登壇お待ちしています!

rancherjp.connpass.com

また、Slackもあるのでよかったら参加ください!

以上、MicroAd Advent Calendar 2022 の4日目の記事でした。

おまけ

Tips: Rancher CLI

RancherというとWeb UIからポチポチのイメージあるかもしれませんが、CLIもちゃんとあります。

クラスタの作成のコマンドも以下の通りあるので必要に応じて利用してください。

docs.ranchermanager.rancher.io

例えば、クラスタの作成は以下の通り。

❯ ./rancher cluster create --help
Usage: 
  rancher clusters create [OPTIONS] [NEWCLUSTERNAME...]

Options:
   --description value         Description to apply to the cluster
   --disable-docker-version    Allow unsupported versions of docker on the nodes, [default=true]
   --import                    Mark the cluster for import, this is required if the cluster is going to be used to import an existing k8s cluster
   --k8s-version value         Kubernetes version to use for the cluster, pass in 'list' to see available versions
   --network-provider value    Network provider for the cluster (flannel, canal, calico) (default: "canal")
   --psp-default-policy value  Default pod security policy to apply
   --rke-config value          Location of an rke config file to import. Can be JSON or YAML format

他にも以下のようなコマンドがあります。

❯ ./rancher --help
Rancher CLI, managing containers one UTF-8 character at a time

Usage: rancher [OPTIONS] COMMAND [arg...]

Version: v2.6.0

Options:
  --debug                   Debug logging
  --config value, -c value  Path to rancher config (default: "/home/nagatomi/.rancher") [$RANCHER_CONFIG_DIR]
  --help, -h                show help
  --version, -v             print the version
  
Commands:
  apps, [app]                                       Operations with apps. Uses helm. Flags prepended with "helm" can also be accurately described by helm documentation.
  catalog                                           Operations with catalogs
  clusters, [cluster]                               Operations on clusters
  context                                           Operations for the context
  globaldns                                         Operations on global DNS providers and entries
  inspect                                           View details of resources
  kubectl                                           Run kubectl commands
  login, [l]                                        Login to a Rancher server
  machines, [machine]                               Operations on machines
  multiclusterapps, [multiclusterapp mcapps mcapp]  Operations with multi-cluster apps
  namespaces, [namespace]                           Operations on namespaces
  nodes, [node]                                     Operations on nodes
  projects, [project]                               Operations on projects
  ps                                                Show workloads in a project
  server                                            Operations for the server
  settings, [setting]                               Show settings for the current server
  ssh                                               SSH into a node
  up                                                apply compose config
  wait                                              Wait for resources cluster, app, project, multiClusterApp
  token                                             Authenticate and generate new kubeconfig token
  help, [h]                                         Shows a list of commands or help for one command

Tips2: TerraformのRancher2 Provider

使ったことないのですが、Terraformのプロバイダの用意もあるのでこちらもどうぞ。

registry.terraform.io