Kubernetes マルチクラスタ管理ツール ～ KubeFed  

# 背景

　エッジクラウドのシナリオで、K8s を各地に分散していくアーキテクチャがよくあります。
　例えば全国の各店舗にエッジを置いて、試着の AR を動かしたり、各地工場にエッジを置いて IoT シスエムを動かしたりするケースが考えられます。
　K8s cluster が複数に分散されますが、それぞれの店舗、工場に IT 人員を配置することはもちろん不可能ですが、たとえすべてリモートで接続できるとして、数百個の Cluster に対して一々 kubectl を打ったりするのも非現実的です。
　もちろんスクリプトやAnsible/Jenkinsを組めば、自動的に回すことができますが、例えばやりたいことはすべてのクラスタに対して同じコマンドを打つのだけではなくて、地域によって、クラスタをグルーピングして、特定のグループに対して特定な操作を一斉にしたい場合ならば、状況が複雑になります。これで、大量の同質な K8s cluster をどう管理運用していけばよいかが課題となります。

# Kubefed
　Kubefed の全称は Kubernetes Cluster Federation であり、マルチクラスタを束ねて（Federation）、一つの K8s CRD resource として定義し、管理運用していく OSS ツールです。
　[Kubefed の Git Page](https://github.com/kubernetes-sigs/kubefed)

### Kubefed の定義
　下図のように、Kubefed は Master Cluster の kube-federation-system Namespace にインストールされます。そして、Master Cluster と Slave Cluster を Federation に Join させることによって Federation が構成できます。
　![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2385161/9f7bc20b-499e-e717-4354-c3656163fe42.png)


```shell
kubefedctl join master --cluster-context cluster-1  --host-cluster-context cluster-1 --v=2
Kubefedctl join slave --cluster-context cluster-2  --host-cluster-context cluster-1 --v=2 

kubectl -n kube-federation-system get kubefedclusters
NAME     READY   AGE
master   True    1m
slave    True    1m
```

これで、Master cluster に KubeFed 用の CRD リソースをデプロイすることで、対応するAPI リソースが Slave cluster にも自動的にデプロイされます。
対応している API リソースは以下の10種類：

```
federatedclusterroles     federatednamespaces
federatedconfigmaps       federatedreplicasets      
federateddeployments      federatedsecrets         
federatedingresses        federatedserviceaccounts  
federatedjobs             federatedservices 
```
各種 CRD を使用する前に、Enable は必要となります。
```yaml
kubefedctl enable <kind.api> --kubefed-namespace <NAMESPACE_INSTALL_KUBEFED> kube-federation-system
```

### リソースのデプロイ
リソースをデプロイする前に、各クラスタ間で共通の Namespace (Federated Namespace)を作ることが必要です。
KubeFed は Federated Namespace のみに対して操作可能です。
手順として、まずは Master Cluster 上で普通の Namespace を作成します。
```shell
kubectl create ns stars
```
そして、この Master Cluster 上で作成した Namespace をもとに、FederatedNamespace を作ります。
```yaml
##On the master##
apiVersion: types.kubefed.io/v1beta1
kind: FederatedNamespace
metadata:
  name: stars #<= must be identical to the kubernetes namespace you created with kubectl
  namespace: stars #<= same
spec:
  placement:
    clusters:
    - name: <REPLACE_ME> #Replace this with the name of your master's context name
    - name: <REPLACE_ME> #Replace this with the name of your slave's context name
    - name: … #If you have more slaves then add more elements
```
これを deploy すると、指定された Slave Cluster 内で Master Cluster と同じ Namespace が Kubefed によって自動的に作成されます。

そして、各種 API リソースに対応する CRD（例：FederatedDeployment）の yaml を定義してデプロイします。
```yaml
##On the master##
apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
  name: federated-xwings
  namespace: stars
spec:
  template:
    metadata:
      name: xwings
    spec:
      ... # Normal deployment spec
  placement:
    clusters:
    - name: master
    - name: slave
  overrides:
    - clusterName: master
      clusterOverrides:
      - path: "/spec/replicas"
        value: 2
```
　spec は通常の deployment yaml に従って書けばよいです。
　面白いのは Placement と overrides のセクションです。Placement は配置先の Cluster を定義します。Overrides は各配置先ごとに spec をカスタマイズ可能とします。なので、単純な同質デプロイだけではなく、スコープをコントロールしたり、カスタマイズが可能です。

　さらにいうと、kubefeded cluster にラベルつけて、ラベルベースでの placement ルールを書くことも可能です。
```shell
kubectl label kubefedclusters -n kube-federation-system cluster1 foo=bar
```
```yaml
spec:
  placement:
    clusterSelector:
      matchLabels:
        foo: bar
```

### その他機能
幾つかのトラブルシューティングの機能も用意されています。
・Federated Cluster 確認
```shell
kubectl -n kube-federation-system get kubefedclusters
```
・Federated リソース 確認
```shell
kubectl describe federateddeployments test-deployment –n test-ns
```
・Kubefed log 確認
```shell
kubectl logs deployment/kubefed-controller-manager -n kube-federation-system
```

さらにより新しめの機能として、マルチクラスタ間で Replica Set を重み付けてリソース分散配置する機能も開発されました。
```yaml
apiVersion: scheduling.kubefed.io/v1alpha1
kind: ReplicaSchedulingPreference
metadata:
  name: test-deployment
  namespace: test-ns
spec:
  targetKind: FederatedDeployment
  totalReplicas: 9
  rebalance: true
  clusters:
    A:
      minReplicas: 4
      maxReplicas: 6
      weight: 1
    B:
      minReplicas: 4
      maxReplicas: 8
      weight: 2
```
これでより柔軟にマルチクラスタ間のワークロード配置が便利に実現できるようになります。
[Replica Scheduling の Git page](https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#replicaschedulingpreference
)

# 最後に
　KubeFed 自体は OSS ツールであり、スケールや安定性などの問題は多々ありますが、冒頭で議論した通リ、マルチクラスタ統合運用のニーズはエッジの普及により段々上がっていきますので、参考の選択肢として KubeFed は非常にいい機能（placement, overrides, replaca scheduling）を実現し、いいヒントをくれています。