BGPを使用したCalicoの導入①

## 環境
- ubuntu：22.0.4.1 LTS
- kubernetes：1.28.2
- calico 3.26


## 要件確認
公式ドキュメントより確認

https://docs.tigera.io/calico/latest/getting-started/kubernetes/requirements

以下、抜粋。

> - x86-64, arm64, ppc64le, or s390x processor
> - Calico must be able to manage cali* interfaces on the host. When IPIP is enabled (the default), Calico also needs to be able to manage tunl* interfaces. When VXLAN is enabled, Calico also needs to be able to manage thevxlan.calico interface.
> - Linux kernel 3.10 or later with required dependencies. The following distributions have the required kernel, its dependencies, and are known to work well with Calico and Kubernetes.
> 　- RedHat Linux 7
> 　- CentOS 7
> 　- Flatcar Container Linux
> 　- Fedora CoreOS
> 　- Ubuntu 18.04
> 　- Debian 8
> - If your Linux distribution comes with installed Firewalld or another iptables manager it should be disabled. These may interfere with rules added by Calico and result in unexpected behavior.
> - Many Linux distributions, such as most of the above, include NetworkManager. By default, NetworkManager does not allow Calico to manage interfaces. If your nodes have NetworkManager, complete the steps in Preventing NetworkManager from controlling Calico interfaces before installing Calico.

### 確認 - アーキテクチャ
以下コマンドでアーキテクチャの確認をします。

```cmd
# uname -m
x86_64
```

### 確認 - カーネルバージョン
以下コマンドでカーネルバージョンの確認をします。
```cmd
# uname -r
5.15.0-88-generic
```

### UFWの無効化
コントロールプレーンノードおよび、ワーカーノードでUFWを無効にします。

```cmd
# sudo systemctl disable ufw
Synchronizing state of ufw.service with SysV service script with /lib/systemd/systemd-sysv-install.
Executing: /lib/systemd/systemd-sysv-install disable ufw
Removed /etc/systemd/system/multi-user.target.wants/ufw.service.
# sudo systemctl stop ufw
# sudo systemctl status ufw
● ufw.service - Uncomplicated firewall
     Loaded: loaded (/lib/systemd/system/ufw.service; disabled; vendor preset: enabled)
     Active: inactive (dead)
       Docs: man:ufw(8)

Nov 04 01:21:30 kube-controlplane-001 systemd[1]: Starting Uncomplicated firewall...
Nov 04 01:21:31 kube-controlplane-001 systemd[1]: Finished Uncomplicated firewall.
Nov 08 14:17:49 kube-controlplane-001 systemd[1]: Stopping Uncomplicated firewall...
Nov 08 14:17:49 kube-controlplane-001 ufw-init[1550797]: Skip stopping firewall: ufw (not enabled)
Nov 08 14:17:49 kube-controlplane-001 systemd[1]: ufw.service: Deactivated successfully.
Nov 08 14:17:49 kube-controlplane-001 systemd[1]: Stopped Uncomplicated firewall.
```

### NetworkManagerの設定
NetworkManager がインターフェイスに干渉する可能性があるらしいので、以下の設定ファイルを作成をします。control-plane-nodeおよびworker-nodeで実施してください。
```cmd
# sudo mkdir /etc/NetworkManager/conf.d/
# sudo touch /etc/NetworkManager/conf.d/calico.conf
# sudo vi /etc/NetworkManager/conf.d/calico.conf

---
[keyfile]
unmanaged-devices=interface-name:cali*;interface-name:tunl*;interface-name:vxlan.calico;interface-name:vxlan-v6.calico;interface-name:wireguard.cali;interface-name:wg-v6.cali
```
これを実施しないと「csi-node-driver」が'ContainerCreating'でstuckしました。結果としてNodeのSTATUSは'NotReady'でstauckします。

これで準備が完了しました。
それでは、Calico（BGP）を導入していきます。

## Calicoの導入
### 導入手順

オンプレのkubernetesへの導入は、以下の公式ドキュメントが対応しています。

https://docs.tigera.io/calico/latest/getting-started/kubernetes/self-managed-onprem/onpremises

> 1. Install the operator on your cluster.
> 2. Download the custom resources necessary to configure Calico
> 3. Create the manifest in order to install Calico.
> 4. Verify Calico installation in your cluster.

### Calicoオペレーターの導入
まず、tigera-operator.yamlをダウンロードします。

```cdm:control-plane-node
# wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/tigera-operator.yaml


--2023-11-08 14:32:45--  https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/tigera-operator.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 2606:50c0:8000::154, 2606:50c0:8001::154, 2606:50c0:8002::154, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|2606:50c0:8000::154|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 1475581 (1.4M) [text/plain]
Saving to: 'tigera-operator.yaml'

tigera-operator.yam 100%[===================>]   1.41M  --.-KB/s    in 0.04s

2023-11-08 14:32:51 (34.3 MB/s) - 'tigera-operator.yaml' saved [1475581/1475581]
```

ダウンロードしたら、kubectlを使用してCalicoオペレーターを導入します。
この時'apply'を使用すると'Too long: must have at most'といったエラーが出ます。

```cmd
# kubectl apply -f tigera-operator.yaml
The CustomResourceDefinition "installations.operator.tigera.io" is invalid: metadata.annotations: Too long: must have at most 262144 bytes
```

なので、必ずドキュメントの通り、'create'を使用してインストールします。

```cmd
kubectl create -f tigera-operator.yaml
```

### 確認 - Pod
tigera-operator podが正しく作成されていることを確認してください。

```cmd
# kubectl get pods -n tigera-operator
NAME                               READY   STATUS    RESTARTS   AGE
tigera-operator-597bf4ddf6-smlmn   1/1     Running   0          29s
```

### calico用カスタムリソースの作成
次にcalico用のカスタムリソースをダウンロードします。

```cmd
# wget https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/custom-resources.yaml
--2023-11-08 14:43:50--  https://raw.githubusercontent.com/projectcalico/calico/v3.26.3/manifests/custom-resources.yaml
Resolving raw.githubusercontent.com (raw.githubusercontent.com)... 2606:50c0:8001::154, 2606:50c0:8003::154, 2606:50c0:8000::154, ...
Connecting to raw.githubusercontent.com (raw.githubusercontent.com)|2606:50c0:8001::154|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 824 [text/plain]
Saving to: 'custom-resources.yaml'

custom-resources.ya 100%[===================>]     824  --.-KB/s    in 0s

2023-11-08 14:43:52 (4.61 MB/s) - 'custom-resources.yaml' saved [824/824]
```

上記のファイルを基に、カスタムリソースを修正していきます。
今回の導入要件は以下の通りとします。

- PodネットワークでBGPを使用
- kubeadm init実行時に、ClusterConfigurationでnetorking.podSubnetを設定している
192.168.0.0/16

修正したカスタムリソースは以下の通りです。

```custom-resources.yaml
# This section includes base Calico installation configuration.
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.Installation
apiVersion: operator.tigera.io/v1
kind: Installation
metadata:
  name: default
spec:
  # Configures Calico networking.
  calicoNetwork:
    # Note: The ipPools section cannot be modified post-install.
    bgp: Enabled
    ipPools:
    - cidr: 192.168.0.0/16
      encapsulation: None
      natOutgoing: Disabled
      nodeSelector: all()
      blockSize: 24
    nodeAddressAutodetectionV4:
      firstFound: false
      kubernetes: NodeInternalIP

---

# This section configures the Calico API server.
# For more information, see: https://projectcalico.docs.tigera.io/master/reference/installation/api#operator.tigera.io/v1.APIServer
apiVersion: operator.tigera.io/v1
kind: APIServer
metadata:
  name: default
spec: {}

```

物理インフラでBGPを利用する場合は、「spec.calicoNetwork.ipPools.natOutgoing」を「Disabled」にする必要があります。

https://docs.tigera.io/calico/latest/networking/configuring/workloads-outside-cluster#disable-nat-for-on-premises-deployments-using-physical-infrastructure

### calico構成用カスタムリソースの導入
それではカスタムリソースを導入します。
```cmd
# kubectl create -f custom-resources.yaml
installation.operator.tigera.io/default created
apiserver.operator.tigera.io/default created
```

### 確認 - カスタムリソース
```cmd
# kubectl get Installation
NAME      AGE
default   2m50s
# kubectl get APIServer
NAME      AGE
default   2m55s
```

### 確認 - Pod
```cmd
# kubectl get pods -A -owide
NAMESPACE          NAME                                            READY   STATUS    RESTARTS       AGE     IP              NODE                    NOMINATED NODE   READINESS GATES
calico-apiserver   calico-apiserver-677cc474fc-56fbw               1/1     Running   0              3m11s   192.168.181.2   kube-worker-001         <none>           <none>
calico-apiserver   calico-apiserver-677cc474fc-njhjh               1/1     Running   0              3m11s   192.168.181.4   kube-worker-001         <none>           <none>
calico-system      calico-kube-controllers-7b49bd7c6f-6swpt        1/1     Running   0              3m17s   192.168.181.3   kube-worker-001         <none>           <none>
calico-system      calico-node-975x9                               1/1     Running   0              3m18s   172.21.0.8      kube-controlplane-001   <none>           <none>
calico-system      calico-node-m9nc9                               1/1     Running   0              3m18s   172.21.0.18     kube-worker-001         <none>           <none>
calico-system      calico-typha-97ddcffd7-j9t6d                    1/1     Running   0              3m19s   172.21.0.18     kube-worker-001         <none>           <none>
calico-system      csi-node-driver-b7bp8                           2/2     Running   0              3m18s   192.168.170.3   kube-controlplane-001   <none>           <none>
calico-system      csi-node-driver-clm6k                           2/2     Running   0              3m17s   192.168.181.5   kube-worker-001         <none>           <none>
kube-system        coredns-5dd5756b68-7v6jr                        1/1     Running   0              26h     192.168.45.65   kube-worker-001         <none>           <none>
kube-system        coredns-5dd5756b68-rmnk2                        1/1     Running   0              26h     192.168.45.66   kube-worker-001         <none>           <none>
kube-system        etcd-kube-controlplane-001                      1/1     Running   8              26h     172.21.0.8      kube-controlplane-001   <none>           <none>
kube-system        kube-apiserver-kube-controlplane-001            1/1     Running   8              26h     172.21.0.8      kube-controlplane-001   <none>           <none>
kube-system        kube-controller-manager-kube-controlplane-001   1/1     Running   8              26h     172.21.0.8      kube-controlplane-001   <none>           <none>
kube-system        kube-proxy-ps64z                                1/1     Running   1              26h     172.21.0.18     kube-worker-001         <none>           <none>
kube-system        kube-proxy-smd86                                1/1     Running   0              26h     172.21.0.8      kube-controlplane-001   <none>           <none>
kube-system        kube-scheduler-kube-controlplane-001            1/1     Running   9              26h     172.21.0.8      kube-controlplane-001   <none>           <none>
tigera-operator    tigera-operator-597bf4ddf6-ndr6p                1/1     Running   14 (78m ago)   3h5m    172.21.0.18     kube-worker-001         <none>           <none>
```

ここで注意点ですが、kubeadmの実行時にsandboxイメージを推奨バージョンにしないと、csi-node-driver-*が立ち上がらなかったです。Warningは早めに対処しておきましょう。

```cmd
# kubectl describe pods -n calico-system csi-node-driver-9nh7j
Events:
  Type     Reason           Age                    From               Message
  ----     ------           ----                   ----               -------
  Normal   Scheduled        5m14s                  default-scheduler  Successfully assigned calico-system/csi-node-driver-9nh7j to kube-worker-001
  Warning  NetworkNotReady  14s (x151 over 5m14s)  kubelet            network is not ready: container runtime network not ready: NetworkReady=false reason:NetworkPluginNotReady message:Network plugin returns error: cni plugin not initialized
```

sandboxイメージの変更はこちらの記事に記載しました。

https://qiita.com/ktog/items/a63b6307c0ac32f0df4f#config%E3%81%AE%E4%BD%9C%E6%88%90%E4%BF%AE%E6%AD%A3

最後にノードのステータスについても確認してみます。

```cmd
# kubectl get nodes -owide
NAME                    STATUS   ROLES           AGE     VERSION   INTERNAL-IP   EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION      CONTAINER-RUNTIME
kube-controlplane-001   Ready    control-plane   3h21m   v1.28.2   172.21.0.8    <none>        Ubuntu 22.04.1 LTS   5.15.0-88-generic   containerd://1.6.24
kube-worker-001         Ready    <none>          3h17m   v1.28.2   172.21.0.18   <none>        Ubuntu 22.04.1 LTS   5.15.0-88-generic   containerd://1.6.24
```

これで晴れてクラスターの準備ができました！！！！

## calicoctlのインストール
最後にCalicoリソースを管理するコマンドラインツールをインストールしていきます。

インストール方法はいくつかあります。

> - Install calicoctl as a binary on a single host
> - Install calicoctl as a kubectl plugin on a single host
> - Install calicoctl as a container on a single host
> - Install calicoctl as a Kubernetes pod

簡単そうなので、kubectlプラグインとしてインストールしてみます。
以下をコントロールプレーンノードおよびワーカーノードで実施します。また、コントロールプレーンノードの~/.kube/configをワーカーノードにも作成しておいてください。

### バイナリーファイルのダウンロード
以下のコマンドででバイナリーファイルをダウンロードします。

```cmd
# curl -L https://github.com/projectcalico/calico/releases/download/v3.26.3/calicoctl-linux-amd64 -o kubectl-calico
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
  0     0    0     0    0     0      0      0 --:--:-- --:--:-- --:--:--     0
100 62.0M  100 62.0M    0     0  34.2M      0  0:00:01  0:00:01 --:--:-- 47.4M
```

### 実行権限の変更
以下のコマンドで実行権限を変更します。

```cmd
chmod +x kubectl-calico
```

### /usr/local/bin/へコピー
以下のコマンドで、上記のファイルを/usr/local/binへコピーします。

```cmd
sudo cp kubectl-calico /usr/local/bin/
```

### 動作確認
以下のコマンドで、正しくインストールされているかを確認します。

```cmd
# kubectl calico version
Client Version:    v3.26.3
Git commit:        bdb7878af
Cluster Version:   v3.26.3
Cluster Type:      typha,kdd,k8s,operator,bgp,kubeadm
```
### calicoctlの注意点
デフォルトで、calicoctlは$(HOME)/.kube/configが使用されるようです。もし、異なる場所にkubeconfigがある場合は、/etc/calico/calicoctl.cfgを作成し、kubeconfigoptionを変更する必要があるようです。

```cmd:/etc/calico/calicoctl.cfg
apiVersion: projectcalico.org/v3
kind: CalicoAPIConfig
metadata:
spec:
  datastoreType: "kubernetes"
  kubeconfig: "/path/to/kube/config"
```

今回は以上です。

次回は、外部スイッチとのBGP接続してみます。

https://qiita.com/ktog/items/c8092b02f978b43577c0