kubefedでマルチクラスタを構築

こちらの記事で、複数のKubernetesクラスタをFederateするkubefedを知ったので、ローカル環境で試してみる

https://amsy810.hateblo.jp/entry/2020/06/17/090000

READMEのQuickstartを参考に進める

https://github.com/kubernetes-sigs/kubefed#quickstart


## 環境

* macOS Monterey 12.1
* go 1.17.5
* kind v0.11.1
* kubefed v0.9.0

## 親クラスタの構築

セットアップ

```sh
$ kind create cluster
$ git clone https://github.com/kubernetes-sigs/kubefed.git && cd kubefed
```

これもしておかないと、後の`make deploy.kind`でこけた

```sh
$ brew install gnu-sed

$ ./scripts/download-binaries.sh
$ export PATH=$(pwd)/bin:${PATH}
```

etcdのバージョンが古くて動作しない問題もあったので解消しておく([issue](https://github.com/kubernetes-sigs/kubefed/issues/1483))

```sh
$ curl -OL https://github.com/etcd-io/etcd/releases/download/v3.5.1/etcd-v3.5.1-darwin-amd64.zip
$ unzip etcd-v3.5.1-darwin-amd64.zip
$ mv etcd-v3.5.1-darwin-amd64/etcd bin
$ vi scripts/sync-up-helm-chart.sh
$ git diff -U0 scripts/sync-up-helm-chart.sh
-${ROOT_DIR}/bin/etcd --data-dir ${WORKDIR} --log-output stdout > ${WORKDIR}/etcd.log 2>&1 &
+${ROOT_DIR}/bin/etcd --data-dir ${WORKDIR} --log-outputs stdout > ${WORKDIR}/etcd.log 2>&1 &
```

デプロイ

```sh
$ make deploy.kind
...
I0113 15:31:34.864712    1309 join.go:299] Created federated cluster resource
```

リソースの確認

```sh
$ kubectl get po -n kube-federation-system
NAME                                          READY   STATUS    RESTARTS   AGE
kubefed-admission-webhook-694bcd856-bx2p7     1/1     Running   0          15m
kubefed-controller-manager-6997b76d77-7gv9b   1/1     Running   0          15m
kubefed-controller-manager-6997b76d77-8kbql   1/1     Running   0          15m

$ kubectl -n kube-federation-system get kubefedcluster
NAME        AGE   READY
kind-kind   15m
```

macOSだとReadyにするためにはこの手順も必要（スクリプトが動かなかったので修正いれた）

```sh
$ vi ./scripts/fix-joined-kind-clusters.sh
$ git diff -U0 scripts/fix-joined-kind-clusters.sh
-    IP_ADDR="$(docker inspect -f "${INSPECT_PATH}" "${cluster}-control-plane")"
+    IP_ADDR="$(docker inspect -f "${INSPECT_PATH}" "kind-control-plane")"

$ ./scripts/fix-joined-kind-clusters.sh
kubefedcluster.core.kubefed.io/kind-kind patched

$ kubectl get kubefedclusters -n kube-federation-system
NAME        AGE   READY
kind-kind   19m   True
```

## 子クラスタの構築
こちらの記事が参考なった

https://www.ntt-tx.co.jp/column/tec/kubernetes/200110/

```sh
$ kind create cluster --name child1
$ kind create cluster --name child2

$ kubectl config current-context
kind-kind
$ kubefedctl join child1 --cluster-context kind-child1 --host-cluster-context kind-kind
$ kubefedctl join child2 --cluster-context kind-child2 --host-cluster-context kind-kind
```

親クラスタと同様にReadyにするためにスクリプトを実行

```sh
$ git restore scripts/fix-joined-kind-clusters.sh
$ ./scripts/fix-joined-kind-clusters.sh
$ kubectl get kubefedclusters -n kube-federation-system
NAME        AGE     READY
child1      102s    True
child2      172s    True
kind-kind   101m    True
```

## リソースを子クラスタに反映
`FederetadXXX`を親クラスタに登録することで、リソースを子クラスタに反映させる
参考：https://github.com/kubernetes-sigs/kubefed/tree/master/example/sample1

```federated-namespace.yaml
apiVersion: types.kubefed.io/v1beta1
kind: FederatedNamespace
metadata:
  name: test-namespace
  namespace: test-namespace
spec:
  placement:
    clusters:
    - name: child1
    - name: child2
```

```sh
$ kubectl create ns test-namespace
$ kubectl apply -f federated-namespace.yaml
$ kubectl get federatednamespace -n test-namespace
NAME             AGE
test-namespace   10s

$ kubectl get ns --context kind-child1 | grep test-namespace
test-namespace           Active   2s
$ kubectl get ns --context kind-child2 | grep test-namespace
test-namespace           Active   9s
```

できてる！
Podも立ててみる

```federated-deployment.yaml
apiVersion: types.kubefed.io/v1beta1
kind: FederatedDeployment
metadata:
  name: test-deployment
  namespace: test-namespace
spec:
  template:
    metadata:
      labels:
        app: nginx
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: nginx
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - image: nginx
            name: nginx
  placement:
    clusters:
    - name: child1
    - name: child2
  overrides:
  - clusterName: child2
    clusterOverrides:
    - path: "/spec/replicas"
      value: 2
```

```sh
$ kubectl apply -f federated-deployment.yaml
$ kubectl get federateddeployment -n test-namespace
NAME              AGE
test-deployment   39s

$ kubectl get po --context kind-child1 -n test-namespace
NAME                               READY   STATUS    RESTARTS   AGE
test-deployment-6799fc88d8-ptrhl   1/1     Running   0          86s
$ kubectl get po --context kind-child2 -n test-namespace
NAME                               READY   STATUS    RESTARTS   AGE
test-deployment-6799fc88d8-ch78x   1/1     Running   0          93s
test-deployment-6799fc88d8-x6dqm   1/1     Running   0          93s
```

いい感じ！

## カスタムリソースをFederate
以下の設定をしておけば`Federated<Kind>`で反映できるようになる
参考：https://github.com/kubernetes-sigs/kubefed/blob/master/docs/userguide.md#federated-api-types

```sh
$ kubefedctl enable customresourcedefinitions
$ kubefedctl federate crd mytype.mygroup.mydomain.io
$ kubefedctl enable mytype.mygroup.mydomain.io --federated-group mytype.mygroup.mydomain.io
```