Для начала следует разобраться с тем, что нового произошло с тех времен, как я рассказывал о поднятии кластера с Windows узлами:
Мы не будем его использовать в контексте Kubernetes. Нас теперь интересует только ContainerD. Тем не менее удалять Docker рано, т.к. он всё еще нужен для создания образов.
Я расскажу как настроить Kubernetes кластер с узлами на базе Windows Server 2022 и CRI-ContainerD. В качетсве CNI для кластера будет Calico.
Здесь ничего принциписльно не изменилось. Берем чистую Ubuntu 20.04 LTS и качаем пакеты для ContainerD, kubeadm, kubelet и kubectl. Затем с помощью kubeadm разворачиваем кластер. Т.к. Docker мы не устанавливали, то, ожидаему, что в качестве CRI на мастер узле будет ContainerD, который мы установили.
Calico умеет работать в 2 режимах:
Качаем calico.yaml
...
curl https://docs.projectcalico.org/manifests/calico.yaml -O
... и приступаем к модификации:
меняем местами значения переменных 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"
заменяем calico_backend: "bird"
на calico_backend: "vxlan"
kind: ConfigMap
apiVersion: v1
metadata:
name: calico-config
namespace: kube-system
data:
calico_backend: "vxlan"
отключем bird проверки в readiness/liveness пробах.
livenessProbe:
exec:
command:
- /bin/calico-node
- -felix-live
# - -bird-live
readinessProbe:
exec:
command:
- /bin/calico-node
# - -bird-ready
- -felix-ready
в итоге мы должны получить что-то вот такое. Применяем yaml
kubectl apply -f calico.yaml
Тут можно сделать небольшое отступление, качающееся количества IP адресов на 1 ноду. По умолчанию это всего 64 адреса. Это можно поменять, но об этом потом.
Нам не хватает 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
. Если ее нет (а может не быть), то надо добавить.
Качаем 2 файла:
На момент написания этой статейки, рабочей версией 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>