Кластер kubernetes HA с containerd. Или есть ли жизнь без docker?

в 5:36, , рубрики: containerd, devops, k8s, kubernetes HA, системное администрирование

Развертываение kubernetes HA с containerd

Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 1
Добрый день уважаемые читатели ! 24.05.2018 г. в официальном блоге Kubernetes была опубликована статья под названием Kubernetes Containerd Integration Goes GA, в которой говорится, что интеграция containerd с Kubernetes готова к production. Также ребята из компании Флант в своем блоге разместили перевод статьи на русский язык, добавив немного уточнений от себя. Почитав документацию проекта на github, я решил попробовать containerd на "собственной шкуре".

У нас в компании есть несколько проектов в стадии "до продакшена еще очень далеко". Вот они и станут нашими подопытными; для них мы решили попробовать развернуть отказоустойчивый кластер Kubernetes с использованием containerd и посмотреть, есть ли жизнь без docker.

Если Вам интересно посмотреть, как мы это делали и что из этого получилось, — добро пожаловать под кат.

Cхема и описание развертывания
Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 2

При разворачивании кластера, как и обычно, ( об этом я писал в предыдущей статье мы используем

keepalived — реализации протокола VRRP (Virtual Router Redundancy Protocol) для Linux

Keepalived создает виртуальный IP (VIRTIP) который "указывает" (создает subinterface) на IP одного из трех мастеров. Демон keepalived следит за работоспособностью машин и в случае обнаружения сбоя — исключает сбойный сервер из списка активных серверов, переключая VIRTIP yна IP другого сервера, согласно "весу", указанному при настройке keepalived на каждом сервере.

Демоны keepalived общаются по протоколу VRRP, посылая друг другу сообщения на адрес 224.0.0.18.

Если сосед не прислал свое сообщение, то по истечению периода он считается умершим. Как только упавший сервер начинает слать свои сообщения в сеть, все возвращается на свои места

Работу с API сервером на нодах kubernetes мы настраиваем следующим образом.

После установки кластера настраиваем kube-proxy, меняем порт с 6443 на 16443 (подробности ниже). На каждом из мастеров развернут nginx, который работает как loadbalancer, слушает порт 16443 и делает upstream по всем трем мастерам на порт 6443 (подробности ниже).

Данной схемой достигнута повышенная отказоустойчивость c помощью keepalived, а так же с помощью nginx достигнута балансировка между API серверами на мастерах.

В прошлой статье я описывал развертывание nginx и etcd в docker. Но в данном случае docker у нас отсутствует, поэтому nginx и etcd будут работать локально на мастернодах.

Теоретически можно было бы развернуть nginx и etcd с помощью containerd, но в случае каких либо проблем данный подход усложнил бы диагностику, поэтому все же решили не экспериментировать и запускать из локально.

Описание серверов для развертывания:

Name IP Службы
VIRTIP 172.26.133.160 ------
kube-master01 172.26.133.161 kubeadm, kubelet, kubectl, etcd, containerd, nginx, keepalived
kube-master02 172.26.133.162 kubeadm, kubelet, kubectl, etcd, containerd, nginx, keepalived
kube-master03 172.26.133.163 kubeadm, kubelet, kubectl, etcd, containerd, nginx, keepalived
kube-node01 172.26.133.164 kubeadm, kubelet, kubectl, containerd
kube-node02 172.26.133.165 kubeadm, kubelet, kubectl, containerd
kube-node03 172.26.133.166 kubeadm, kubelet, kubectl, containerd

Установка kubeadm, kubelet, kubectl и сопутствующие пакеты

Все комманды выполнять из под root

sudo -i

apt-get update && apt-get install -y apt-transport-https curl
curl -s https://packages.cloud.google.com/apt/doc/apt-key.gpg | apt-key add -
cat <<EOF >/etc/apt/sources.list.d/kubernetes.list
deb http://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl unzip tar apt-transport-https btrfs-tools libseccomp2 socat util-linux mc vim keepalived

Установка conteinerd
Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 3

cd /
wget https://storage.googleapis.com/cri-containerd-release/cri-containerd-1.1.0-rc.0.linux-amd64.tar.gz
tar -xvf cri-containerd-1.1.0-rc.0.linux-amd64.tar.gz

Настраиваем конфиги containerd

mkdir -p /etc/containerd
nano /etc/containerd/config.toml

Добавляем в файл:

[plugins.cri]
  enable_tls_streaming = true

Cтартуем conteinerd проверяем, что все ОК

systemctl enable containerd
systemctl start containerd
systemctl status containerd
● containerd.service - containerd container runtime
   Loaded: loaded (/etc/systemd/system/containerd.service; disabled; vendor preset: enabled)
   Active: active (running) since Mon 2018-06-25 12:32:01 MSK; 7s ago
     Docs: https://containerd.io
  Process: 10725 ExecStartPre=/sbin/modprobe overlay (code=exited, status=0/SUCCESS)
 Main PID: 10730 (containerd)
    Tasks: 15 (limit: 4915)
   Memory: 14.9M
      CPU: 375ms
  CGroup: /system.slice/containerd.service
           └─10730 /usr/local/bin/containerd

Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="Get image filesystem path "/var/lib/containerd/io.containerd.snapshotter.v1.overlayfs""
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=error msg="Failed to load cni during init, please check CRI plugin status before setting up network for pods" error="cni con
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="loading plugin "io.containerd.grpc.v1.introspection"..." type=io.containerd.grpc.v1
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="Start subscribing containerd event"
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="Start recovering state"
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg=serving... address="/run/containerd/containerd.sock"
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="containerd successfully booted in 0.308755s"
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="Start event monitor"
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="Start snapshots syncer"
Jun 25 12:32:01 hb-master02 containerd[10730]: time="2018-06-25T12:32:01+03:00" level=info msg="Start streaming server"

Установка и запуск etcd

Важное замечание, я проводил установку кластера kubernetes версии 1.10. Буквально через пару дней, во время написания статьи вышла версия 1.11 Если вы устанавливаете версию 1.1 то установите переменную ETCD_VERSION="v3.1.17", если 1.10 то ETCD_VERSION="v3.1.12".

export ETCD_VERSION="v3.1.12"
curl -sSL https://github.com/coreos/etcd/releases/download/${ETCD_VERSION}/etcd-${ETCD_VERSION}-linux-amd64.tar.gz | tar -xzv --strip-components=1 -C /usr/local/bin/

Копируем конфиги с гитахаба.

git clone https://github.com/rjeka/k8s-containerd.git
cd k8s-containerd

Настраиваем переменные в конфиг файле.

vim create-config.sh

Описание переменных файла create-config.sh

#!/bin/bash

# local machine ip address
export K8SHA_IPLOCAL=172.26.133.161

# local machine etcd name, options: etcd1, etcd2, etcd3
export K8SHA_ETCDNAME=kube-master01

# local machine keepalived state config, options: MASTER, BACKUP. One keepalived cluster only one MASTER, other's are BACKUP
export K8SHA_KA_STATE=MASTER

# local machine keepalived priority config, options: 102, 101,100 MASTER must 102
export K8SHA_KA_PRIO=102

# local machine keepalived network interface name config, for example: eth0
export K8SHA_KA_INTF=ens18

#######################################
# all masters settings below must be same
#######################################

# master keepalived virtual ip address
export K8SHA_IPVIRTUAL=172.26.133.160

# master01 ip address
export K8SHA_IP1=172.26.133.161

# master02 ip address
export K8SHA_IP2=172.26.133.162

# master03 ip address
export K8SHA_IP3=172.26.133.163

# master01 hostname
export K8SHA_HOSTNAME1=kube-master01

# master02 hostname
export K8SHA_HOSTNAME2=kube-master02

# master03 hostname
export K8SHA_HOSTNAME3=kube-master03

# keepalived auth_pass config, all masters must be same
export K8SHA_KA_AUTH=56cf8dd754c90194d1600c483e10abfr

#etcd tocken:
export ETCD_TOKEN=9489bf67bdfe1b3ae077d6fd9e7efefd

# kubernetes cluster token, you can use 'kubeadm token generate' to get a new one
export K8SHA_TOKEN=535tdi.utzk5hf75b04ht8l

# kubernetes CIDR pod subnet, if CIDR pod subnet is "10.244.0.0/16" please set to "10.244.0.0\/16"
export K8SHA_CIDR=10.244.0.0\/16

настройки на локальной машине каждой из нод (на каждой ноде свои)
K8SHA_IPLOCAL — IP адрес ноды на которой настраивается скрипт
K8SHA_ETCDNAME — имя локальной машины в кластере ETCD
K8SHA_KA_STATE — роль в keepalived. Одна нода MASTER, все остальные BACKUP.
K8SHA_KA_PRIO — приоритет keepalived, у мастера 102 у остальных 101, 100 При падении мастера с номером 102, его место занимает нода с номером 101 и так далее.
K8SHA_KA_INTF — keepalived network interface. Имя интерфейса который будет слушать keepalived.

Общие настройки для всех мастернод одинаковые:

K8SHA_IPVIRTUAL=172.26.133.160 — виртуальный IP кластера.
K8SHA_IP1...K8SHA_IP3 — IP адреса мастеров
K8SHA_HOSTNAME1 ...K8SHA_HOSTNAME3 — имена хостов для мастернод. Важный пункт, по этим именам kubeadm будет генерировать сертификаты.
K8SHA_KA_AUTH — пароль для keepalived. Можно задать произвольный
K8SHA_TOKEN — токен кластера. Можно сгенерировать командой kubeadm token generate
K8SHA_CIDR — адрес подсети для подов. Я использую flannel поэтому CIDR 0.244.0.0/16. Обязательно экранировать — в конфиге должно быть K8SHA_CIDR=10.244.0.0/16

Запускаем скрипт, который сконфигурирует nginx, keepalived, etcd и kubeadmin

./create-config.sh

Запускаем etcd.

etcd я поднимал без tls. Если Вам нужен tls, то в официальной документации kubernetes подробно написано, как генерировать сертификаты для etcd.

systemctl daemon-reload && systemctl start etcd && systemctl enable etcd

Проверка статуса

etcdctl cluster-health
member ad059013ec46f37 is healthy: got healthy result from http://192.168.5.49:2379
member 4d63136c9a3226a1 is healthy: got healthy result from http://192.168.4.169:2379
member d61978cb3555071e is healthy: got healthy result from http://192.168.4.170:2379
cluster is healthy

etcdctl member list
ad059013ec46f37: name=hb-master03 peerURLs=http://192.168.5.48:2380 clientURLs=http://192.168.5.49:2379,http://192.168.5.49:4001 isLeader=false
4d63136c9a3226a1: name=hb-master01 peerURLs=http://192.168.4.169:2380 clientURLs=http://192.168.4.169:2379,http://192.168.4.169:4001 isLeader=true
d61978cb3555071e: name=hb-master02 peerURLs=http://192.168.4.170:2380 clientURLs=http://192.168.4.170:2379,http://192.168.4.170:4001 isLeader=false

Если все хорошо, приступаем к следующему шагу.

Настраиваем kubeadmin

Для того, чтобы kybernetes начал работать не с docker, а с containerd, настроим конфиг kubeadmin

vim /etc/systemd/system/kubelet.service.d/10-kubeadm.conf

После [Service] добавляем строчку в блок

Environment="KUBELET_EXTRA_ARGS=--runtime-cgroups=/system.slice/containerd.service --container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"

Весь конфиг должен выглядеть так:

[Service]
Environment="KUBELET_EXTRA_ARGS=--runtime-cgroups=/system.slice/containerd.service --container-runtime=remote --runtime-request-timeout=15m --container-runtime-endpoint=unix:///run/containerd/containerd.sock"
Environment="KUBELET_KUBECONFIG_ARGS=--bootstrap-kubeconfig=/etc/kubernetes/bootstrap-kubelet.conf --kubeconfig=/etc/kubernetes/kubelet.conf"
Environment="KUBELET_SYSTEM_PODS_ARGS=--pod-manifest-path=/etc/kubernetes/manifests --allow-privileged=true"
Environment="KUBELET_NETWORK_ARGS=--network-plugin=cni --cni-conf-dir=/etc/cni/net.d --cni-bin-dir=/opt/cni/bin"
Environment="KUBELET_DNS_ARGS=--cluster-dns=10.96.0.10 --cluster-domain=cluster.local"
Environment="KUBELET_AUTHZ_ARGS=--authorization-mode=Webhook --client-ca-file=/etc/kubernetes/pki/ca.crt"
Environment="KUBELET_CADVISOR_ARGS=--cadvisor-port=0"
Environment="KUBELET_CERTIFICATE_ARGS=--rotate-certificates=true --cert-dir=/var/lib/kubelet/pki"
ExecStart=
ExecStart=/usr/bin/kubelet $KUBELET_KUBECONFIG_ARGS $KUBELET_SYSTEM_PODS_ARGS $KUBELET_NETWORK_ARGS $KUBELET_DNS_ARGS $KUBELET_AUTHZ_ARGS $KUBELET_CADVISOR_ARGS $KUBELET_CERTIFICATE_ARGS $KUBELET_EXTRA_ARGS

Если вы ставите версию 1.11 и хотите поэкспериментировать с CoreDNS вместо kube-dns и потестить динамическую конфигурацию, раскоментируйте в файле настройки kubeadm-init.yaml следующий блок:

feature-gates:
  DynamicKubeletConfig: true
  CoreDNS: true

Рестартуем kubelet

systemctl daemon-reload && systemctl restart kubelet

Инициализация первого мастера

Перед тем, как запустить kubeadm, нужно рестартануть keepalived и проверить его статус

systemctl restart keepalived.service

systemctl status keepalived.service
● keepalived.service - Keepalive Daemon (LVS and VRRP)
   Loaded: loaded (/lib/systemd/system/keepalived.service; enabled; vendor preset: enabled)
   Active: active (running) since Wed 2018-06-27 10:40:03 MSK; 1min 44s ago
  Process: 4589 ExecStart=/usr/sbin/keepalived $DAEMON_ARGS (code=exited, status=0/SUCCESS)
 Main PID: 4590 (keepalived)
    Tasks: 7 (limit: 4915)
   Memory: 15.3M
      CPU: 968ms
   CGroup: /system.slice/keepalived.service
           ├─4590 /usr/sbin/keepalived
           ├─4591 /usr/sbin/keepalived
           ├─4593 /usr/sbin/keepalived
           ├─5222 /usr/sbin/keepalived
           ├─5223 sh -c /etc/keepalived/check_apiserver.sh
           ├─5224 /bin/bash /etc/keepalived/check_apiserver.sh
           └─5231 sleep 5

проверить, пингуется ли VIRTIP

ping -c 4 172.26.133.160
PING 172.26.133.160 (172.26.133.160) 56(84) bytes of data.
64 bytes from 172.26.133.160: icmp_seq=1 ttl=64 time=0.030 ms
64 bytes from 172.26.133.160: icmp_seq=2 ttl=64 time=0.050 ms
64 bytes from 172.26.133.160: icmp_seq=3 ttl=64 time=0.050 ms
64 bytes from 172.26.133.160: icmp_seq=4 ttl=64 time=0.056 ms

--- 172.26.133.160 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3069ms
rtt min/avg/max/mdev = 0.030/0.046/0.056/0.012 ms

После этого запускаем kubeadmin. Обязательно указать строчку --skip-preflight-checks. Kubeadmin по умолчанию ищет docker и без пропуска проверок вывалится с ошибкой.

kubeadm init --config=kubeadm-init.yaml  --skip-preflight-checks

После того, как kubeadm отработал, сохраняем cгенерированную строку. Она понадобится для ввода в кластер рабочих нод.

kubeadm join 172.26.133.160:6443 --token XXXXXXXXXXXXXXXXXXXXXXXXX --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

Далее указываем, где хранится файл admin.conf
Если работаем под root то:

vim ~/.bashrc
export KUBECONFIG=/etc/kubernetes/admin.conf
source ~/.bashrc

Для простого пользователя следуем инструкциям на экране.

mkdir -p $HOME/.kube
sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config
sudo chown $(id -u):$(id -g) $HOME/.kube/config

Добавляем в кластер еще 2 мастера. Для этого нужно скопировать сертификаты из kube-master01 на kube-master02 и kube-master03 в каталог /etc/kubernetes/. Я для этого настраивал доступ по ssh для root, а после копирования файлов возвращал настройки обратно.

scp -r /etc/kubernetes/pki 172.26.133.162:/etc/kubernetes/
scp -r /etc/kubernetes/pki 172.26.133.163:/etc/kubernetes/

После копирования на kube-master02 и kube-master03 запускаем.

kubeadm init --config=kubeadm-init.yaml  --skip-preflight-checks

Установка CIDR flannel

на kube-master01 выполнить

kubectl apply -f https://raw.githubusercontent.com/coreos/flannel/v0.10.0/Documentation/kube-flannel.yml

Акутальную версию flanel можно посмотреть в документации kubernetes.

Дожидаемся пока создадутся все контейнеры

watch -n1 kubectl get pods --all-namespaces -o wide

NAMESPACE     NAME                                    READY     STATUS    RESTARTS   AGE       IP               NODE
kube-system   kube-apiserver-kube-master01            1/1       Running   0          17m       172.26.133.161   kube-master01
kube-system   kube-apiserver-kube-master02            1/1       Running   0          6m        172.26.133.162   kube-master02
kube-system   kube-apiserver-kube-master03            1/1       Running   0          6m        172.26.133.163   kube-master03
kube-system   kube-controller-manager-kube-master01   1/1       Running   0          17m       172.26.133.161   kube-master01
kube-system   kube-controller-manager-kube-master02   1/1       Running   0          6m        172.26.133.162   kube-master02
kube-system   kube-controller-manager-kube-master03   1/1       Running   0          6m        172.26.133.163   kube-master03
kube-system   kube-dns-86f4d74b45-8c24s               3/3       Running   0          17m       10.244.2.2       kube-master03
kube-system   kube-flannel-ds-4h4w7                   1/1       Running   0          2m        172.26.133.163   kube-master03
kube-system   kube-flannel-ds-kf5mj                   1/1       Running   0          2m        172.26.133.162   kube-master02
kube-system   kube-flannel-ds-q6k4z                   1/1       Running   0          2m        172.26.133.161   kube-master01
kube-system   kube-proxy-9cjtp                        1/1       Running   0          6m        172.26.133.163   kube-master03
kube-system   kube-proxy-9sqk2                        1/1       Running   0          17m       172.26.133.161   kube-master01
kube-system   kube-proxy-jg2pt                        1/1       Running   0          6m        172.26.133.162   kube-master02
kube-system   kube-scheduler-kube-master01            1/1       Running   0          18m       172.26.133.161   kube-master01
kube-system   kube-scheduler-kube-master02            1/1       Running   0          6m        172.26.133.162   kube-master02
kube-system   kube-scheduler-kube-master03            1/1       Running   0          6m        172.26.133.163   kube-master03

Делаем репликацию kube-dns на все три мастера

На kube-master01 выполнить

kubectl scale --replicas=3 -n kube-system deployment/kube-dns

Установка и настройка nginx

На каждой мастер ноде устанавливаем nginx в качестве балансировщика для API Kubernetes
У меня все машины кластера на debian. Из пакетов nginx не поддерживает модуль stream, по этому добавим репозитории nginx и установим его из репозиториев nginx`a. Если у вас другая ОС, то смотрите документацию nginx.

curl -s https://nginx.ru/keys/nginx_signing.key | apt-key add -
echo -e "n#nginxn
deb http://nginx.org/packages/debian/ stretch nginxn
deb-src http://nginx.org/packages/debian/ stretch nginx"  >> /etc/apt/sources.list

apt-get update && apt-get install nginx -y

Создадим конфиг nginx (если еще не создан)

./create-config.sh

nginx.conf

user nginx;
worker_processes auto;

error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}

http {
include /etc/nginx/mime.types;
default_type application/octet-stream;

log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                  '$status $body_bytes_sent "$http_referer" '
                  '"$http_user_agent" "$http_x_forwarded_for"';

access_log  /var/log/nginx/access.log  main;

sendfile        on;
#tcp_nopush     on;

keepalive_timeout  65;

#gzip  on;

include /etc/nginx/conf.d/*.conf;

}

stream {
upstream apiserver {
server 172.26.133.161:6443 weight=5 max_fails=3 fail_timeout=30s;
server 172.26.133.162:6443 weight=5 max_fails=3 fail_timeout=30s;
server 172.26.133.163:6443 weight=5 max_fails=3 fail_timeout=30s;

}

server {
    listen 16443;
    proxy_connect_timeout 1s;
    proxy_timeout 3s;
    proxy_pass apiserver;
}

}

Проверяем, что все ОК и применяем конфигурацию

nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

systemctl restart nginx
systemctl status nginx
● nginx.service - nginx - high performance web server
   Loaded: loaded (/lib/systemd/system/nginx.service; enabled; vendor preset: enabled)
   Active: active (running) since Thu 2018-06-28 08:48:09 MSK; 22s ago
     Docs: http://nginx.org/en/docs/
  Process: 22132 ExecStart=/usr/sbin/nginx -c /etc/nginx/nginx.conf (code=exited, status=0/SUCCESS)
 Main PID: 22133 (nginx)
    Tasks: 2 (limit: 4915)
   Memory: 1.6M
      CPU: 7ms
   CGroup: /system.slice/nginx.service
           ├─22133 nginx: master process /usr/sbin/nginx -c /etc/nginx/nginx.conf
           └─22134 nginx: worker process

Протестируем работу балансировщика

curl -k https://172.26.133.161:16443 | wc -l
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   233  100   233    0     0  12348      0 --:--:-- --:--:-- --:--:-- 12944

Конфигурируем kube-proxy для работы с балансировщиком

После того, как настроен балансировщик, редактируем порт в настройках kubernetes.

kubectl edit -n kube-system configmap/kube-proxy

Меняем настройки server на https://172.26.133.160:16443
Далее нужно настроить kube-proxy на работу c новым портом

kubectl get pods --all-namespaces -o wide | grep proxy
kube-system   kube-proxy-9cjtp                        1/1       Running   1          22h       172.26.133.163   kube-master03
kube-system   kube-proxy-9sqk2                        1/1       Running   1          22h       172.26.133.161   kube-master01
kube-system   kube-proxy-jg2pt                        1/1       Running   4          22h       172.26.133.162   kube-

Удаляем все поды, после удаления они автоматом пересоздаются с новыми настройками

kubectl delete pod -n kube-system kube-proxy-XXX
```bash
Проверяем что все рестартанули. Время жизни должно быть небольшое
```bash
kubectl get pods --all-namespaces -o wide | grep proxy
kube-system   kube-proxy-hqrsw                        1/1       Running   0          33s       172.26.133.161   kube-master01
kube-system   kube-proxy-kzvw5                        1/1       Running   0          47s       172.26.133.163   kube-master03
kube-system   kube-proxy-zzkz5                        1/1       Running   0          7s        172.26.133.162   kube-master02

Добавление рабочих нод в кластер

На каждой ноде из-под рута выполнить команду, которую сгенерировал kubeadm

kubeadm join 172.26.133.160:6443 --token XXXXXXXXXXXXXXXXXXXXXXXXX --discovery-token-ca-cert-hash sha256:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX --cri-socket  /run/containerd/containerd.sock  --skip-preflight-checks

Если строчку "потеряли", то нужно сгенерировать новую

kubeadm token generate
kubeadm token create <generated-token> --print-join-command --ttl=0

Установка dashboard

kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/master/src/deploy/recommended/kubernetes-dashboard.yaml

Создаем пользователя с админскими полномочиями:

kubectl apply -f kube-dashboard/dashboard-adminUser.yaml

Получаем токен для входа:

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

Настраиваем доступ dashboard через NodePort на VIRTIP

kubectl -n kube-system edit service kubernetes-dashboard

Заменяем значение type: ClusterIP на type: NodePort и в секцию port: добавляем значение nodePort: 30000 (или порт в диапазоне 30000 до 32000 на котором вы хотите что бы была доступна панель):

Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 4

Теперь панель доступна по адресу https://VIRTIP:30000

Heapster

Далее установим Heapster — это инструмент для получения метрик составляющих кластера.

Установка:

git clone https://github.com/kubernetes/heapster.git
cd heapster
kubectl create -f deploy/kube-config/influxdb/
kubectl create -f deploy/kube-config/rbac/heapster-rbac.yaml

Выводы

Особых проблем при работе с containerd я не заметил. Один раз был непонятный глюк с подом после удаления деплоя. Kubernetes считал, что под удален, но под стал таким своеобразным "зомби. Он остался существовать на ноде, но в статусе extended.

Я считаю, что Containerd более ориентирована в качестве среды выполнения контейнеров для kubernetes. Скорее всего в перспективе в качестве среды для запуска микросервисов в Kubernetes можно и нужно будет использовать разные среды, которые будут ориентированны для разных задач, проектов и т.д.

Проект очень быстро развивается. Alibaba Cloud начал активно использовать conatinerd и подчеркивает, что это идеальная среда для выполнения контейнеров.

Как уверяют разработчики, интеграция containerd в облачной платформе Google Kubernetes теперь эквивалентна интеграции Docker.

Хороший пример работы консольной утилиты crictl . Также приведу немного примеров из созданного кластера:

kubectl describe nodes | grep "Container Runtime Version:" 

Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 5

В Docker CLI отсутствуют основные концепции Kubernetes, например, pod и namespace, а crictl поддерживает данные концепции

crictl pods

Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 6

А если нужно, то можем посмотреть и контейнеры в привычном формате, как у docker

crictl ps

Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 7

Можем посмотреть образы, которые есть на ноде

crictl images

Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 8

Как оказалось, жизнь без docker` есть :)

Про баги и глюки пока говорить рано, кластер у нас работает где-то неделю. В ближайшее время на него будет перенесен test, а в случае успеха скорее всего и dev стенд одного из проектов. Об этом есть идея написать цикл статей охватывающих процессы DevOps, такие как: создание кластера, настройка ingress контроллера и вынос его на отдельные ноды кластера, автоматизация сборки образов, проверка образов на уязвимости, деплой и т.д. А пока будем смотреть на стабильность работы, искать баги и осваивать новые продукты.

Также данный мануал подойдет для развертывания отказоустойчивого кластера c docker, нужно только поставить docker по инструкции из официальной документации Kubernetes и пропустить шаги по установке containerd и настройки конфига kubeadm.

Или можно поставить containerd и docker одновременно на один хост, и, как уверяют разработчики, они прекрасно будут работать вместе. Containerd, как среда запуска контенеров для kubernetes, а docker — просто как docker )))

Кластер kubernetes HA с containerd. Или есть ли жизнь без docker? - 9

В репозитории containerd есть ansible playbook для установки кластера с одним мастером. Но мне было интереснее "поднять" систему руками, чтобы более детально разобраться в настройке каждого компонента и понять, как это работает на практике.

Возможно, когда нибудь дойдут руки, и я напишу свой playbook для разворачивания кластера c HA, так как за последние пол года я развернул их уже больше десятка и пора бы, наверно, автоматизировать процесс.

Также во время написания статьи вышла версия kubernetes 1.11. Об основных изменениях можно почитать в блоге Флант или в официальном блоге kubernetes. Мы обновили тестовые кластеры до версии 1.11 и заменили kube-dns на CoreDNS. Дополнительно включили функцию DynamicKubeletConfig для тестирования возможностей динамического обновления конфигов.

Используемые материалы:

Спасибо, что дочитали до конца.

Так как информации по kubernetes, особенно по кластерам работающим в реальных условиях, в рунете очень мало, то указания на неточности приветствуются, как и замечания по общей схеме развертывания кластера. Постараюсь их учесть и сделать соответствующие исправления. И я всегда готов ответить на вопросы в комментариях, на githab и в любых соцсетях указанных в моем профиле.

С уважением Евгений.

Автор: rjeka

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js