Как настроить ContainerD в качестве CRI для Windows узлов в Kubernetes кластере?

Windows Server Kubernetes Calico HostProcess

В предыдущих сериях...

Для начала следует разобраться с тем, что нового произошло с тех времен, как я рассказывал о поднятии кластера с Windows узлами:

  1. актуальной версией кубернетеса является 1.22;
  2. в качестве CNI кроме Flannel можно использовать еще и Calico;
  3. вышел Windows Server 2022;
  4. появилась возможность использовать CRI-containerD в том числе и в режиме HostProcess.

Немного слов про Docker

Мы не будем его использовать в контексте Kubernetes. Нас теперь интересует только ContainerD. Тем не менее удалять Docker рано, т.к. он всё еще нужен для создания образов.

Теперь перейдем к самому вкусному

Я расскажу как настроить Kubernetes кластер с узлами на базе Windows Server 2022 и CRI-ContainerD. В качетсве CNI для кластера будет Calico.

Этап первый: установка нового кластера

Здесь ничего принциписльно не изменилось. Берем чистую Ubuntu 20.04 LTS и качаем пакеты для ContainerD, kubeadm, kubelet и kubectl. Затем с помощью kubeadm разворачиваем кластер. Т.к. Docker мы не устанавливали, то, ожидаему, что в качестве CRI на мастер узле будет ContainerD, который мы установили.

Этап второй: установка CNI - Calico

Calico умеет работать в 2 режимах:

  • BGP - используется по умолчанию, но нам не подходит
  • VXLAN - мы будем использовать этот режим

Качаем calico.yaml ...

curl https://docs.projectcalico.org/manifests/calico.yaml -O

... и приступаем к модификации:

  1. меняем местами значения переменных CALICO_IPV4POOL_IPIP и CALICO_IPV4POOL_VXLAN

    env:
     # Enable IPIP
     - name: CALICO_IPV4POOL_IPIP
       value: "Never"
     # Enable or Disable VXLAN on the default IP pool.
     - name: CALICO_IPV4POOL_VXLAN
       value: "Always"
    
  2. заменяем calico_backend: "bird" на calico_backend: "vxlan"

    kind: ConfigMap
    apiVersion: v1
    metadata:
      name: calico-config
      namespace: kube-system
    data:
      calico_backend: "vxlan"
    
  3. отключем bird проверки в readiness/liveness пробах.

    livenessProbe:
      exec:
        command:
        - /bin/calico-node
        - -felix-live
        # - -bird-live
    readinessProbe:
      exec:
        command:
        - /bin/calico-node
        # - -bird-ready
        - -felix-ready
    
  4. в итоге мы должны получить что-то вот такое. Применяем yaml

    kubectl apply -f calico.yaml
    

Тут можно сделать небольшое отступление, качающееся количества IP адресов на 1 ноду. По умолчанию это всего 64 адреса. Это можно поменять, но об этом потом.

Этап третий: готовим кластер к Windows узлам

Нам не хватает DaemonSet'ов для Windows узлов. Берем их здесь: https://raw.githubusercontent.com/kubernetes-sigs/sig-windows-tools/master/hostprocess/calico/calico.yml https://raw.githubusercontent.com/kubernetes-sigs/sig-windows-tools/master/hostprocess/calico/kube-proxy/kube-proxy.yml

А чтобы они (DaemonSet'ы) работали необходимо убедиться что в конфигурации кластера есть вся необходимая информация:

#> kubectl -n kube-system get configmap/kubeadm-config -oyaml
apiVersion: v1
data:
  ClusterConfiguration: |
    apiServer:
      extraArgs:
        authorization-mode: Node,RBAC
      timeoutForControlPlane: 4m0s
    apiVersion: kubeadm.k8s.io/v1beta3
    certificatesDir: /etc/kubernetes/pki
    clusterName: kubernetes
    controllerManager: {}
    controlPlaneEndpoint: 192.168.99.150:6443
    dns: {}
    etcd:
      local:
        dataDir: /var/lib/etcd
    imageRepository: k8s.gcr.io
    kind: ClusterConfiguration
    kubernetesVersion: v1.22.2
    networking:
      dnsDomain: cluster.local
      podSubnet: 10.244.0.0/16
      serviceSubnet: 10.96.0.0/12
    scheduler: {}
kind: ConfigMap
metadata:
  creationTimestamp: "2021-10-24T08:02:20Z"
  name: kubeadm-config
  namespace: kube-system
  resourceVersion: "1168673"
  uid: 396b0bb8-e6ad-4a7a-9611-42538084e1ef

Здесь важно наличие строки controlPlaneEndpoint: 192.168.99.150:6443. Если ее нет (а может не быть), то надо добавить.

Этап четвертый: добавление Windows узла с CRI - ContainerD

Качаем 2 файла:

  1. Install-Containerd.ps1
  2. PrepareNode.ps1

На момент написания этой статейки, рабочей версией CRI-ContainerD был 1.6.0-beta.1. Запускаем его установку:

Install-Containerd.ps1 -ContainerDVersion 1.6.0-beta.1

Устанавливаем весь необходимый софт (kubelet, kubeadm, ...)

PrepareNode.ps1 -ContainerRuntime containerD -KubernetesVersion 1.22.2

Подлючаемся по SSH к мастеру и получаем токен для добавления узлов в кластер:

sudo kubeadm token create --print-join-command

Получаем что-то похожее на вот это:

kubeadm join 192.168.99.150:6443 --token thmvc8.s7tfy38ej3dcawjt --discovery-token-ca-cert-hash sha256:0c6a4b9bc9f03b32dc133b79c491c6820bbb73f09b4edbeb77e6b55407a774eb

Вспоминаем что при установке ContainerD нас просили добавить --cri-socket "npipe:////./pipe/containerd-containerd" к комманде kubeadm join. Получаем итоговую команду:

kubeadm join 192.168.99.150:6443 --token thmvc8.s7tfy38ej3dcawjt --discovery-token-ca-cert-hash sha256:0c6a4b9bc9f03b32dc133b79c491c6820bbb73f09b4edbeb77e6b55407a774eb --cri-socket "npipe:////./pipe/containerd-containerd"

Выполняем ее и радуемся результату. Все готово.

Результат должен быть примерно таким:

PS C:\Users\v.leschenko> kubectl get nodes -owide
NAME             STATUS   ROLES                  AGE    VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE                       KERNEL-VERSION     CONTAINER-RUNTIME
k8s-linux-1      Ready    control-plane,master   14d    v1.22.2   192.168.99.150   <none>        Ubuntu 20.04.3 LTS             5.4.0-89-generic   containerd://1.4.11
k8s-windows-1    Ready    <none>                 5d1h   v1.22.2   192.168.99.151   <none>        Windows Server 2022 Standard   10.0.20348.320     containerd://1.6.0-beta.1
k8s-windows-2    Ready    <none>                 2d2h   v1.22.2   192.168.99.152   <none>        Windows Server 2022 Standard   10.0.20348.320     containerd://1.6.0-beta.1

PS C:\Users\v.leschenko> kubectl -n kube-system get pods -owide
NAME                                       READY   STATUS    RESTARTS   AGE    IP               NODE             NOMINATED NODE   READINESS GATES
calico-kube-controllers-75f8f6cc59-6krlt   1/1     Running   0          162m   10.244.175.2     k8s-linux-1      <none>           <none>
calico-node-tggf4                          1/1     Running   0          162m   192.168.99.150   k8s-linux-1      <none>           <none>
calico-node-windows-6b8rc                  2/2     Running   0          158m   192.168.99.152   k8s-windows-2    <none>           <none>
calico-node-windows-ptx7m                  2/2     Running   0          136m   192.168.99.151   k8s-windows-1    <none>           <none>
coredns-78fcd69978-qsb9v                   1/1     Running   0          162m   10.244.175.3     k8s-linux-1      <none>           <none>
coredns-78fcd69978-wc5gd                   1/1     Running   0          162m   10.244.175.1     k8s-linux-1      <none>           <none>
etcd-k8s-linux-1                           1/1     Running   0          162m   192.168.99.150   k8s-linux-1      <none>           <none>
kube-apiserver-k8s-linux-1                 1/1     Running   0          162m   192.168.99.150   k8s-linux-1      <none>           <none>
kube-controller-manager-k8s-linux-1        1/1     Running   0          162m   192.168.99.150   k8s-linux-1      <none>           <none>
kube-proxy-windows-9p7xm                   1/1     Running   0          162m   192.168.99.151   k8s-windows-1    <none>           <none>
kube-proxy-windows-rnwtm                   1/1     Running   0          158m   192.168.99.152   k8s-windows-2    <none>           <none>
kube-proxy-x6h4q                           1/1     Running   0          162m   192.168.99.150   k8s-linux-1      <none>           <none>
kube-scheduler-k8s-linux-1                 1/1     Running   0          162m   192.168.99.150   k8s-linux-1      <none>           <none>
metrics-server-559f9dc594-c7vgv            1/1     Running   0          162m   10.244.175.4     k8s-linux-1      <none>           <none>