こんにちは。CyberAgentの川部です。
Cluster API の概要
Cluster APIはKubernetesのCluster Lifecycle SIGsで開発されているOSSです。
端的にいってしまうとKubernetes上で別のKubernetesクラスタの構築や更新、削除といった一連の操作を実現するためのソフトウェアとなっています。
なぜ、わざわざKubernetesクラスタでKubernetesクラスタを管理するのでしょうか? 筆者の考えるメリットとしては、クラスタの構成をマニフェストとして定義することでKubernetesクラスタの構築や更新、削除の自動化が可能という点です。
Cluster APIの実態は複数のCRDやカスタムコントローラから構成されます。
Cluster APIはClusterやControlPlane、MachineDeployment、Machineといったカスタムリソースを提供しています。これらのリソースを管理Kubernetesクラスタに作成することで、別のKubernetesの作成を行います。
また、利用するインフラストラクチャに応じてプロバイダを個別に実装するアーキテクチャになっています。既存のプロバイダを利用すればAWSやGCP、OpenStackなど様々なインフラストラクチャ上にKubernetesクラスタを構築できます。
InfrastructureClusterやInfrastructureMachineといったリソースはプロバイダごとに定義されることを想定したリソースです。AWSのプロバイダを例に挙げると、AWSClusterとAWSMachineがそのリソースにあたります。
AWSClusterリソースではSecurityGroupやVPC、Gatewayに関する設定ができ、作成するとKubernetesクラスタが動作するネットワーク構成の構築が自動的に行われます。
Kubernetesノードが動作するVMや物理マシンを抽象化したMachineリソースのプロバイダ実装であるAWSMachineでは、作成するとKubernetesのコンポーネントがインストールされた状態のEC2のVMが立ち上がります。
今回紹介するCluster API BYOHにおいても、独自のリソースとCluster APIが提供するリソースの関係が重要となってくるので後ほど紹介します。
Cluster APIではプロバイダ実装をサポートするために、公式ドキュメントで実装すべき項目や想定する実装内容が説明されています。詳しくはそちらをご覧ください。
今回紹介するCluster API BYOHはCluster APIプロバイダ実装の一種で、既存のLinuxマシンを物理、VM問わずKubernetesノードとして利用できます。
Cluster API Bring Your Own Hostとは?
先ほども述べた通り、Cluster API BYOH
BYOHはCluster APIプロバイダの中でも異色なプロバイダです。
BYOHではMachineリソースを作成しても、新規にLinuxマシンを作成したりLinuxマシンが動作するネットワーク構成を新規作成、更新することはありません。
他のプロバイダでは基本的にMachineリソースを定義し、それに応じてインフラストラクチャが提供するAPIなどを操作してVMの作成やネットワークの構成管理を行う形でした。しかしBYOHでは既存のLinuxマシンをKubernetesノードに組み込むという仕様上、これらのアプローチとは異なる形でプロバイダが実装されています。
BYOHの面白い点はこのプロバイダの実装にあるのですが、使う側は特にその内容を意識することなく、他のプロバイダと同様にKubernetesクラスタの構築やバージョンアップを自動化できます。つまり、既存のLinuxマシンの資源を再利用できるというメリットに変わりはありません。
BYOHによるKubernetesクラスタの構築
それでは実際にBYOHでのKubernetesクラスタの構築について説明します。
なお、ここからはKubernetesクラスタが複数出てきてややこしいので、Linuxマシンを利用して作成したいKubernetesクラスタをWorkloadクラスタ、それを管理するクラスタをManegementクラスタと呼ぶことにします。
まずCluster APIの多くのプロバイダでは、プロバイダが提供するコントローラがManagementクラスタ上でのみ動作し、MachineやClusterといったリソースに応じてインフラストラクチャのリソースを操作します。
しかし、BYOHはこのパターンに当てはまらない実装となっており、agentと呼ばれるカスタムコントローラとManagementクラスタで動作するカスタムコントローラの二つが必要となります。またagentは既存のLinuxマシン上で動作しますので、利用したいLinuxマシンの数だけインストールする必要があります。
図4はBYOHにおけるagentとカスタムコントローラの関係を表したものです。
agentはLinuxマシンのIPアドレスやMACアドレスといったホスト固有の情報を、ManagementクラスタにByoHostというカスタムリソースとして登録することが第一の役割です。
その後はClusterAPIがAWSのEC2インスタンスを作成するのと同じように、BYO Hostの情報を参照し、BYOHMachineを作りながらcloud-initスクリプトで実際にノードの初期化を行います。
他のプロバイダではBYO Hostのようなリソースは登場しませんが、BYOHではBYO HostでLinuxマシンの情報を抽象化することによって、別のKubernetesクラスタのノードとして再利用できます。
初期化処理の実態はcloud-initのスクリプトです。
* Applying /etc/sysctl.conf ...
net.ipv4.tcp_max_tw_buckets = 65536
net.core.somaxconn = 16384
net.core.netdev_max_backlog = 2048
net.ipv4.tcp_max_syn_backlog = 2048
net.ipv4.tcp_tw_reuse = 1
(中略)
+ for pkg in cri-tools kubernetes-cni kubectl kubelet kubeadm
+ dpkg --install /var/lib/byoh/bundles/projects.registry.vmware.com/cluster_api_provider_bringyourownhost/byoh-bundle-ubuntu_20.04.1_x86-64_k8s:v1.23.5/kubelet.deb
Selecting previously unselected package kubelet.
(Reading database ... 64597 files and directories currently installed.)
Preparing to unpack .../kubelet.deb ...
Unpacking kubelet (1.23.5-00) ...
Setting up kubelet (1.23.5-00) ...
Created symlink /etc/systemd/system/multi-user.target.wants/kubelet.service → /lib/systemd/system/kubelet.service.
+ apt-mark hold kubelet
kubelet set on hold.
+ for pkg in cri-tools kubernetes-cni kubectl kubelet kubeadm
+ dpkg --install /var/lib/byoh/bundles/projects.registry.vmware.com/cluster_api_provider_bringyourownhost/byoh-bundle-ubuntu_20.04.1_x86-64_k8s:v1.23.5/kubeadm.deb
上記のように必要なKubernetesのコンポーネントのインストールやカーネルパラメータチューニングなどを行っています。
コントロールプレーンとワーカーの分離
さて、ここまで読まれて
その前に、Cluster APIとCluster API BYOHのカスタムリソースとその関係性を改めて整理してみましょう。
図5における語句の説明は次のとおりです。
- KubeadmControlPlane:コントロールプレーン専用のMachineSetを管理します。Deployment的な立ち位置です。
- MachineDeployment:ワーカーノード用のMachineSetを管理します。こちらも同様にDeploymentと似たような振る舞いをします。
- KubeadmConfigTemplate:Machine作成時に起動するcloud-initスクリプトの定義を行います。MachineDeploymentとKubeadmControlPlaneから参照されます。
- MachineSet:ReplicaSetと似たようにMachineの台数を管理します。
- Machine:Kubernetesの1ノードに対応します。InfrastructureMachineへの参照を持っています。
- Cluster:Kubernetesのクラスタが使用するバージョンやKubeadmControlPlane、InfrastructureClusterへの参照を持ちます。
- ByoHost:LinuxマシンのIPアドレスやMACアドレスを保持します。
- ByoMachineTemplate:どのLinuxマシンを選択するかのSelectorを持ちます。
- ByoMachine:ByoHostへの参照と初期化スクリプトを定義します。
- ByoCluster:コントロールプレーンのエンドポイントとKubernetesのバージョンを指定します。
つまりコントロールプレーンとそうでないものを分離するためには、KubeadmControlPlaneとMachineDeploymentを利用すればいいということになります。
余談ですが、MachineDeploymentやKubeadmControlPlaneではローリングアップデートの機能がサポートされており、ノードのKubernetesのバージョンを更新する際の影響を調整することも可能です。
多くのプロバイダでは、KubeadmControlPlaneとMachineDeploymentそれぞれのリソースを作成すればそれに応じたVMの作成や初期化処理が行われるため、何か特別な手順を踏む必要はありません。
しかし、BYOHでは既にLinuxマシンが存在する前提であり、それぞれにコントロールプレーン用、ワーカー用という区別はありません。
そこでBYOHではBYOHostリソースに手動でラベルを付与し、BYOMachineTemplateのSelectorによって、KubeadmControlPlaneで利用するLinuxマシンなのか、MachineDeploymentで利用するLinuxマシンなのかを制御します。
コントロールプレーンの冗長化
kubeadmを用いて手動でKubernetesクラスタを構築する際、コントロールプレーンを冗長化させるのは少々手間が必要ですが、Cluster API BYOHではkube-vipを用いることで比較的簡単に冗長化させることができます。
kube-vipはKubeadmControlPlaneにstatic-podのマニフェストを定義します。そしてControlPlaneとなるLinuxマシン上で動作させます。
apiVersion: controlplane.cluster.x-k8s.io/v1beta1
kind: KubeadmControlPlane
metadata:
labels:
nodepool: pool0
name: byoh-cluster-control-plane
namespace: default
spec:
kubeadmConfigSpec:
clusterConfiguration:
apiServer:
certSANs:
- localhost
- 127.0.0.1
- 0.0.0.0
- host.docker.internal
controllerManager:
extraArgs:
enable-hostpath-provisioner: "true"
files:
- content: |
apiVersion: v1
kind: Pod
metadata:
creationTimestamp: null
name: kube-vip
namespace: kube-system
spec:
containers:
- args:
- manager
env:
- name: cp_enable
value: "true"
- name: vip_arp
value: "true"
- name: vip_leaderelection
value: "true"
- name: vip_address
value: 172.18.0.10
- name: vip_interface
value:
- name: vip_leaseduration
value: "15"
- name: vip_renewdeadline
value: "10"
- name: vip_retryperiod
value: "2"
image: ghcr.io/kube-vip/kube-vip:v0.4.1
imagePullPolicy: IfNotPresent
name: kube-vip
resources: {}
securityContext:
capabilities:
add:
- NET_ADMIN
- NET_RAW
volumeMounts:
- mountPath: /etc/kubernetes/admin.conf
name: kubeconfig
hostNetwork: true
hostAliases:
- hostnames:
- kubernetes
ip: 127.0.0.1
volumes:
- hostPath:
path: /etc/kubernetes/admin.conf
type: FileOrCreate
name: kubeconfig
status: {}
owner: root:root
path: /etc/kubernetes/manifests/kube-vip.yaml
(以下略)
kube-vipでは複数のLinuxホストのうちいずれかのホストがarpを用いて該当のVIP宛の通信を受け付けます。今回の例では172.
もちろん、kube-vip を用いずに個別に作成したロードバランサと仮想IPを使用することもできます。
その場合はBYOClusterリソースの.spec.
この際、ロードバランサにプールメンバーとしてLinuxホストを登録するのを忘れないようにしましょう。また、Machineリソースを削除した際にプールメンバーから外すといった処理も自分で実行する必要があります。
CNIやServiceTypeLB、Ingressの導入
BYOHはインフラストラクチャを問わずに既存のLinuxマシンを用いてKubernetesクラスタを構築します。故にCNIやLoadBalancer Service、Ingressといったよく使うであろう機能は自前で導入する必要があります。
とはいってもBYOHで構築されたクラスタはkubeadmで構築されたものなので、よく見るOSSをそのまま導入することが可能です。
- CNI: Calico, Cilium
- ServiceTypeLB: MetalLB
- Ingress: ingress-nginx
これらのソフトウェアスタックを、構築したクラスタ環境に合わせて使うことになります。
まとめ
今回はCluster API BYOHについて紹介しました。
- Cluster APIのメリットはKubernetesクラスタの管理をKubernetesのライフサイクルや自動回復、ローリングアップデートといった機能を利用して行える。
- Cluster API BYOHは既存のLinuxマシンをCluster APIのリソースとして登録できる。
- BYOHの実装は他のプロバイダと違い、エージェントを用いた特殊な構成である。
- コントロールプレーンはkube-vipによって冗長化できる。
- CNIやServiceTypeLB、Ingressなどは自前でOSSを活用する必要がある。
Cluster APIは本体やクラウドごとのプロバイダの開発が盛んに行われていて個人的に注目しているプロジェクトです。
現在はCluster API自体はv1beta1というapiVersionになっており、v1に至るまでリソース構造の変化や新しいリソースなどがこれからも追加される可能性があります。
AWSやGCP、そして今回紹介したBYOHのようなプロバイダ側の実装も場合によってはその変更に追従しなくてはならないので、そういった動きにも注目していると面白いかもしれません。