Разворачиваем среду для работы с микросервисами. Часть 1 установка Kubernetes HA на bare metal

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

Данный цикл будет состоять минимум из четырех статей:

  1. В первой из них я расскажу, как на голое железо установить отказоустойчивый кластер kubernetes, как установить стандартный дашборд и настроить доступ к нему, как установить ingress контроллер.
  2. Во второй статье я расскажу, как развернуть отказоустойчивый кластер Ceph и как начать использовать RBD тома в нашем кластере Kubernetes. Также немного затрону остальные виды стораджей (storages) и более подробно рассмотрю local-storage. Дополнительно расскажу, как на базе созданного кластера CEPH организовать отказоустойчивое хранилище S3
  3. В третьей статье я расскажу, как в нашем кластере Kubernetes развернуть отказоустойчивый кластер MySql, а именно — Percona XtraDB Cluster on Kubernetes. И также опишу все проблемы с которыми мы столкнулись, когда решили перенести БД в kubernetes.
  4. В четвертой статье я постараюсь собрать все вместе и рассказать, как задеплоить и запустить приложение, которое будет использовать БД и тома ceph. Расскажу, как настроить ingress контроллер для доступа к нашему приложению извне и сервис автоматического заказа сертификатов от Let’s Encrypt. Еще — как автоматически поддерживать данные сертификаты в актуальном состоянии. Также немного затронем тему RBAC в контексте доступа до панели управления. Расскажу в двух словах про Helm и его установку.
    Если Вам интересна информация данных публикаций, то — добро пожаловать !

Вступление:

Для кого предназначены данные статьи? В первую очередь, для тех, кто только начинает свой путь в изучении Kubernetes. Также данный цикл будет полезен для инженеров, которые думают переходить от монолита к микросервисам. Все описанное — это мой опыт, в том числе полученный и при переводе нескольких проектов из монолита в Kubernetes. Возможно, что какие-то части публикаций будут интересны и опытным инженерам.

Что я не буду подробно рассматривать в данной серии публикаций:

  • подробно объяснять, что такое примитивы kubernetes, такие как: pod, deployment, service, ingress и тд.
  • CNI (Container Networking Interface) я рассмотрю очень поверхностно, мы используем callico поэтому другие решения, я только перечислю.
  • процесс сборки docker образов.
  • процессы CICD. (Возможно отдельной публикацией, но после всего цикла)
  • helm; про него написано уже достаточно много, я затрону лишь процесс его инсталляции в кластер и настройку клиента.

Что я хочу рассмотреть подробно:

  • пошаговый процесс развертывания кластера Kubernetes. Я буду использовать kubeadm. Но при этом я подробно шаг за шагом рассмотрю процесс инсталляции кластера на голое железо, различные виды инсталляции ETCD, составление конфигфайлов для kube admina. Постараюсь разъяснить все варианты балансировки для Ingress контроллера и отличие в разнообразных схемах доступа worknodes до api сервера.
    Я знаю, что сегодня для развертывания kubernetes есть много прекрасных инструментов, например, kubespray или тот же rancher. Возможно, кому-то будет более удобно использовать их. Но, я думаю, найдется немало инженеров которые захотят рассмотреть вопрос более детально.
  • терминологию CEPH и пошаговую инсталляцию кластера CEPH, а также пошаговую инструкцию подключение хранилища ceph к созданному Kubernetes кластеру.
  • local-storages, подключение к кластеру kubernetes, а также отличия от подключений типа hostpath и тд.
  • kubernetes операторы и развертывание Percona XtraDB Cluster с помощью оператора, а также постараюсь рассказать про плюсы и минусы такого решения после полугодового опыта использования в продакшене. А также немного поделюсь планами по доработке оператора от percona.

Оглавление:

  1. Cписок хостов, ресурсы хостов, версии ОС и ПО
  2. Схема HA кластера kubernetes
  3. До начала работы или before you begin
  4. Заполняем файл create-config.sh
  5. Обновление ядра ОС
  6. Подготовка нод Установка Kubelet, Kubectl, Kubeadm и docker
  7. Установка ETCD (различные варианты)
  8. Запуск первого мастера kubernetes
  9. Установка CNI Callico
  10. Запуск второго и третьего мастера kubernetes
  11. Добавляем worker нод в кластер
  12. Устанавливаем haproxy на worker ноды для HA
  13. Установка Ingress контроллера
  14. Установка Web UI (Dashboard)

Список и назначение хостов

Все ноды моего кластера будут располагаться на виртуальных машинах с предустановленной системой Debian 9 stretch c ядром 4.19.0-0.bpo.5-amd64. Для виртуализации я использую Proxmox VE.

Таблица ВМ и их ТТХ:

NameIP адресCommentCPUMEMDISK1DISK2
master0110.73.71.25master node4vcpu4GbHDD
master0210.73.71.26master node4vcpu4GbHDD
master0310.73.71.27master node4vcpu4GbHDD
worknode0110.73.75.241work node4vcpu4GbHDDSSD
worknode0210.73.75.242work node4vcpu4GbHDDSSD
worknode0310.73.75.243work node4vcpu4GbHDDSSD

Не обязательно, что у Вас должна быть именно такая конфигурация машин, но все таки я советую придерживаться рекомендациям официальной документации, а для мастеров увеличить количество оперативной памяти минимум до 4Гб. Забегая вперед скажу, что при более маленьком количестве, я ловил глюки в работе CNI Callico
Ceph тоже достаточно прожорлив к памяти и производительности дисков.
Наши продакшн инсталляции работают без виртуализации на голом железе, но я знаю много примеров, где хватало и виртуальных машин с достаточно скромными ресурсами. Все зависит от ваших потребностей и нагрузок.

Список и версии ПО

NameVersion
Kubernetes1.15.1
Docker19.3.1

Kubeadm, начиная с версии 1.14, перестал поддерживать API версии v1alpha3 и полностью перешел на API версии v1beta1, которую будет поддерживать в ближайшем будущем, поэтому в статье я буду рассказывать только про v1beta1.
Итак, мы считаем, что у Вы подготовили машины для kubernetes кластера. Они все доступны друг другу по сети, имеют «выход» в интернет и на них установлена «чистая» операционная система.
Для каждого шага установки я буду уточнять, на каких именно машинах выполняется команда или блок команд. Все команды выполнять из-под пользователя root, если не указано иного.
Все файлы конфигурации, а также скрипт для их подготовки доступны для скачивания на github.
Итак, начнем.


Схема HA кластера kubernetes

Примерная схема HA кластера. Художник из меня так себе, если честно, но постараюсь объяснить в двух словах и достаточно упрощенно, особо не углубляясь в теорию.
Итак, наш кластер будет состоять из трех master нод и трех worker нод. На каждой master ноде kubernetes у нас будет работать etcd (на схеме зеленые стрелочки) и служебные части kubernetes; назовем их обобщенно — kubeapi.
Через кластер etcd master ноды обмениваются состоянием кластера kubernetes. Эти же адреса я укажу как точки входа ingress контроллера для внешнего трафика (на схеме красные стрелочки)
На worker нодах у нас работает kubelet, который связывается с api сервером kubernetes через haproxy установленным локально на каждой worker ноде. В качестве адреса api сервера для kubelet я буду использовать локалхост 127.0.0.1:6443, а haproxy по roundrobin будет раскидывать запросы по трем master нодам, также он будет проверять доступность master нод. Данная схема позволит нам создать HA, и в случае выхода из строя одной из master нод, worker ноды будут спокойно посылать запросы на две оставшихся в живых master ноды.


Перед началом работы

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

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

apt-get update && apt-get install -y curl apt-transport-https git

На master ноды скопируем репозиторий с шаблонами конфигов

sudo -i
git clone https://github.com/rjeka/kubernetes-ceph-percona.git

Проверим, что ip адрес хостов на мастерах соответствует тому, на котором будет слушать API сервер kubernetes

hostname && hostname -i
master01
10.73.71.25

и так для всех master нод.

Обязательно отключите SWAP, иначе kubeadm будет выдавать ошибку

[ERROR Swap]: running with swap on is not supported. Please disable swap

Отключить можно командой

swapoff -a

Не забудьте закомментировать в файле /etc/fstab


Заполняем файл create-config.sh

Для автоматического заполнения конфигов, нужных для установки кластера kubernetes, я накидал небольшой скриптик create-config.sh. Вам нужно заполнить в нем буквально 8 строчек. Указать IP адреса и hostname своих мастеров. А также указать etcd tocken, можете его не менять. Я приведу ниже ту часть скрипта в которой нужно сделать изменения.

#!/bin/bash

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

# master01 ip address
export K8SHA_IP1=10.73.71.25 

# master02 ip address
export K8SHA_IP2=10.73.71.26

# master03 ip address
export K8SHA_IP3=10.73.71.27

# master01 hostname
export K8SHA_HOSTNAME1=master01

# master02 hostname
export K8SHA_HOSTNAME2=master02

# master03 hostname
export K8SHA_HOSTNAME3=master03

#etcd tocken:
export ETCD_TOKEN=9489bf67bdfe1b3ae077d6fd9e7efefd

#etcd version
export ETCD_VERSION="v3.3.10"

Обновление ядра ОС

Данный шаг является необязательным, так как ядро нужно будем обновлять из back портов, и делаете Вы это на свой страх и риск. Возможно, Вы никогда столкнетесь с данной проблемой, а если и столкнетесь, то обновить ядро можно и после разворачивания kubernetes. В общем, решать Вам.
Обновление ядра требуется для устранения старого бага docker, который исправили только в ядре linux версии 4.18. Более подробно про этот баг можно почитать вот здесь. Выражался баг в периодическом зависании сетевого интерфейса на нодах kubernetes c ошибкой:

waiting for eth0 to become free. Usage count = 1

У меня после установки ОС было ядро версии 4.9

uname -a
Linux master01 4.9.0-7-amd64 #1 SMP Debian 4.9.110-3+deb9u2 (2018-08-13) x86_64 GNU/Linux

На каждой машине для kubernetes выполняем
Шаг №1
Добавляем back ports в source list

echo deb http://ftp.debian.org/debian stretch-backports main > /etc/apt/sources.list
apt-get update
apt-cache policy linux-compiler-gcc-6-x86

Шаг №2
Установка пакетов

apt install -y -t stretch-backports linux-image-amd64 linux-headers-amd64

Шаг №3
Перезагрузка

reboot

Проверяем что все ОК

uname -a
Linux master01 4.19.0-0.bpo.5-amd64 #1 SMP Debian 4.19.37-4~bpo9+1 (2019-06-19) x86_64 GNU/Linux

Подготовка нод Установка Kubelet, Kubectl, Kubeadm и docker

Установка Kubelet, Kubectl, Kubeadm

Ставим на все ноды кластера, согласно документации kubernetes

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 https://apt.kubernetes.io/ kubernetes-xenial main
EOF
apt-get update
apt-get install -y kubelet kubeadm kubectl
apt-mark hold kubelet kubeadm kubectl

Установка Docker

Устанавливаем docker по инструкции из документации

apt-get remove docker docker-engine docker.io containerd runc
apt-get install apt-transport-https ca-certificates curl gnupg2 software-properties-common
curl -fsSL https://download.docker.com/linux/debian/gpg | apt-key add -
apt-key fingerprint 0EBFCD88
add-apt-repository 
   "deb [arch=amd64] https://download.docker.com/linux/debian 
   $(lsb_release -cs) 
   stable"
apt-get update
apt-get install docker-ce docker-ce-cli containerd.io

Установка Установка Kubelet, Kubectl, Kubeadm и docker c помощью ansible

Если Вы по каким либо причинам не хотите использовать docker, есть возможность использовать любые CRI. Почитать об этом можно, например тут, но эта тема выходит за рамки данной статьи.


Установка ETCD

Не буду сильно углубляться в теорию, в двух словах: etcd — это распределенное хранилище типа «ключ-значение» c открытым исходным кодом. etcd написан на GO и используется в kubernetes фактически, как база данных для хранения состояния кластера. Для более подробного ознакомления можно почитать в документации kubernetes.
etcd можно устанавливать многими способами. Можно устанавливать локально и запускать, как демона, можно запускать в docker контейнерах, можно устанавливать даже как поды кубернетеса. Можно устанавливать руками, а можно установить с помощью kubeadm (я данный способ не пробовал). Можно устанавливать на машины кластера или отдельные сервера.
Я буду устанавливать etcd локально на master ноды и запускать, как демон, через systemd, а также рассмотрю установку в докере. Я использую etcd без TLS, если вам нужен TLS обратитесь к документации самого etcd или kubernetes 
Также в моем github будет выложен ansible-playbook для установки etcd с запуском через systemd.

Вариант №1
Установка локально, запуск через systemd

На всех мастерах: (на рабочих нодах кластера этот шаг выполнять не нужно)
Шаг №1
Скачиваем и распаковываем архив с etcd:

mkdir archives
cd archives
export etcdVersion=v3.3.10
wget https://github.com/coreos/etcd/releases/download/$etcdVersion/etcd-$etcdVersion-linux-amd64.tar.gz
tar -xvf etcd-$etcdVersion-linux-amd64.tar.gz -C /usr/local/bin/ --strip-components=1

Шаг №2
Создаем конфиг файл для ETCD

cd ..
./create-config.sh etcd

Скрипт принимает на вход значение etcd, и формирует конфиг файл в каталоге etcd. После работы скрипта готовый конфиг файл будет находится в каталоге etcd.
Для всех других конфигов, скрипт работает по тому же принципу. Принимает на вход какое-то значение и создает конфиг в определенном каталоге.

Шаг №3
Запускаем etcd кластер и проверяем его работоспособность

systemctl start etcd

Проверяем работоспособность демона

systemctl status etcd
● etcd.service - etcd
   Loaded: loaded (/etc/systemd/system/etcd.service; disabled; vendor preset: enabled)
   Active: active (running) since Sun 2019-07-07 02:34:28 MSK; 4min 46s ago
     Docs: https://github.com/coreos/etcd
 Main PID: 7471 (etcd)
    Tasks: 14 (limit: 4915)
   CGroup: /system.slice/etcd.service
           └─7471 /usr/local/bin/etcd --name master01 --data-dir /var/lib/etcd --listen-client-urls http://0.0.0.0:2379,http://0.0.0.0:4001 --advertise-client-urls http://10.73.71.25:2379,http://10.73.71.

Jul 07 02:34:28 master01 etcd[7471]: b11e73358a31b109 [logterm: 1, index: 3, vote: 0] cast MsgVote for f67dd9aaa8a44ab9 [logterm: 2, index: 5] at term 554
Jul 07 02:34:28 master01 etcd[7471]: raft.node: b11e73358a31b109 elected leader f67dd9aaa8a44ab9 at term 554
Jul 07 02:34:28 master01 etcd[7471]: published {Name:master01 ClientURLs:[http://10.73.71.25:2379 http://10.73.71.25:4001]} to cluster d0979b2e7159c1e6
Jul 07 02:34:28 master01 etcd[7471]: ready to serve client requests
Jul 07 02:34:28 master01 etcd[7471]: serving insecure client requests on [::]:4001, this is strongly discouraged!
Jul 07 02:34:28 master01 systemd[1]: Started etcd.
Jul 07 02:34:28 master01 etcd[7471]: ready to serve client requests
Jul 07 02:34:28 master01 etcd[7471]: serving insecure client requests on [::]:2379, this is strongly discouraged!
Jul 07 02:34:28 master01 etcd[7471]: set the initial cluster version to 3.3
Jul 07 02:34:28 master01 etcd[7471]: enabled capabilities for version 3.3
lines 1-19

И работоспособность самого кластера:

etcdctl cluster-health
member 61db137992290fc is healthy: got healthy result from http://10.73.71.27:2379
member b11e73358a31b109 is healthy: got healthy result from http://10.73.71.25:2379
member f67dd9aaa8a44ab9 is healthy: got healthy result from http://10.73.71.26:2379
cluster is healthy

etcdctl member list
61db137992290fc: name=master03 peerURLs=http://10.73.71.27:2380 clientURLs=http://10.73.71.27:2379,http://10.73.71.27:4001 isLeader=false
b11e73358a31b109: name=master01 peerURLs=http://10.73.71.25:2380 clientURLs=http://10.73.71.25:2379,http://10.73.71.25:4001 isLeader=false
f67dd9aaa8a44ab9: name=master02 peerURLs=http://10.73.71.26:2380 clientURLs=http://10.73.71.26:2379,http://10.73.71.26:4001 isLeader=true

Установка etcd локально c помощью ansible, запуск через systemd

Если вы хотите запустить etcd в докере, то под спойлером инструкция.
Установка etcd c помощью docker-compose, запуск в докер


Запуск первого мастера kubernetes

Первым делом нам нужно сгенерировать конфиг для kubeadmin

./create-config.sh kubeadm

Разбираем конфиг для kubeadm

Инициируем первый мастер

kubeadm init  --config=kubeadmin/kubeadm-init.yaml

Если kubeadm отработает без ошибок, то на выходе мы получим примерно следующий вывод:

You can now join any number of control-plane nodes by copying certificate authorities
and service account keys on each node and then running the following as root:

  kubeadm join 10.73.71.25:6443 --token ivwoap.259retezqf34amx8 
    --discovery-token-ca-cert-hash sha256:b5c93e32457c8e6478782ff62e8ef77acf72738dda59cd603cdf4821abe12ca3 
    --control-plane

Then you can join any number of worker nodes by running the following on each as root:

kubeadm join 10.73.71.25:6443 --token ivwoap.259retezqf34amx8 
    --discovery-token-ca-cert-hash sha256:b5c93e32457c8e6478782ff62e8ef77acf72738dda59cd603cdf4821abe12ca3

Установка CNI Calico

Пришло время установить сеть, в которой будут работать наши поды. Я использую calico, ее и будем ставить.
А для начала настроим доступ для kubelet. Все команды выполняем на master01
Если вы работаете из-под root

export KUBECONFIG=/etc/kubernetes/admin.conf

Если из-под простого пользователя

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

Также Вы можете управлять кластером со своего ноутбука или любой локальной машины. Для этого скопируйте файл /etc/kubernetes/admin.conf на свой ноутбук или любую другую машину в $HOME/.kube/config

Ставим CNI согласно документации kubernetes

kubectl apply -f https://docs.projectcalico.org/v3.8/manifests/calico.yaml

Ждем, пока все поды поднимутся

watch -n1 kubectl get pods -A
NAMESPACE     NAME                                       READY   STATUS    RESTARTS   AGE
kube-system   calico-kube-controllers-59f54d6bbc-psr2z   1/1     Running   0          96s
kube-system   calico-node-hm49z                          1/1     Running   0          96s
kube-system   coredns-5c98db65d4-svcx9                   1/1     Running   0          77m
kube-system   coredns-5c98db65d4-zdlb8                   1/1     Running   0          77m
kube-system   kube-apiserver-master01                    1/1     Running   0          76m
kube-system   kube-controller-manager-master01           1/1     Running   0          77m
kube-system   kube-proxy-nkdqn                           1/1     Running   0          77m
kube-system   kube-scheduler-master01                    1/1     Running   0          77m

Запуск второго и третьего мастера kubernetes

Перед тем, как запустить master02 и master03, нужно с master01 скопировать сертификаты, которые сгенерировал kubeadm при создании кластера. Я буду копировать через scp
На master01

export master02=10.73.71.26
export master03=10.73.71.27
scp -r /etc/kubernetes/pki $master02:/etc/kubernetes/ 
scp -r /etc/kubernetes/pki $master03:/etc/kubernetes/

На master02 и master03
Создаем конфиг для kubeadm

./create-config.sh kubeadm

И добавляем в кластер master02 и master03

kubeadm init  --config=kubeadmin/kubeadm-init.yaml

Глюки при нескольких сетевых интерфейсах !!!!


Добавляем worker ноды в кластер

На данный момент у нас работает кластер, в котором запущены три master ноды. Но master ноды — это машины, на которых работает api, scheduler и прочие сервисы кластера kubernetes. Для того, чтобы мы могли запускать свои поды, нам нужны так называемые worker ноды.
Если Вы ограничены в ресурсах, то можно запускать поды и на master нодах.Но я лично не советую так делать.
Запуск подов на мастернодах

Устанавливаем на worker ноды kubelet, kubeadm, kubectl и докер как на master нодах
Установка kubelet, kubeadm, kubectl и докер

Теперь пора время вернуться к той строчке, которую нам сгенерировал kubeadm при установке мастер ноды.
У меня она выглядит так.

kubeadm join 10.73.71.25:6443 --token ivwoap.259retezqf34amx8 
    --discovery-token-ca-cert-hash sha256:b5c93e32457c8e6478782ff62e8ef77acf72738dda59cd603cdf4821abe12ca3

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

kubeadm token create --print-join-command --ttl=0

После того, как kubeadm отработает, Ваша новая нода введена в кластер и готова для работы

This node has joined the cluster:
* Certificate signing request was sent to apiserver and a response was received.
* The Kubelet was informed of the new secure connection details.

Run 'kubectl get nodes' on the control-plane to see this node join the cluster.

Теперь посмотрим на результат

root@master01:~# kubectl get nodes
NAME         STATUS   ROLES    AGE     VERSION
master01     Ready    master   10d     v1.15.1
master02     Ready    master   10d     v1.15.1
master03     Ready    master   10d     v1.15.1
worknode01   Ready    <none>   5m44s   v1.15.1
worknode02   Ready    <none>   59s     v1.15.1
worknode03   Ready    <none>   51s     v1.15.1

Устанавливаем haproxy на worknodes

Теперь мы имеем рабочий кластер с тремя master нодами и тремя worker нодами.
Проблема в том, что сейчас наши worker ноды не имеют HA режима.
Если посмотреть на конфиг файл kubelet, то мы увидим, что наши worker ноды обращаются только к одной master ноде из трех.

root@worknode01:~# cat /etc/kubernetes/kubelet.conf | grep server:
    server: https://10.73.71.27:6443

В моем случае это master03. При данной конфигурации, в случае падения master03, worker нода потеряет связь с API сервером кластера. Чтобы наш кластер стал полностью HA, мы установим на каждый из воркеров Load Balancer (Haproxy), который по round robin будет раскидывать запросы на три master ноды, а в конфигах kubelet на worker нодах мы поменяем адрес сервера на 127.0.0.1:6443
Для начала установим HAProxy на каждую worker ноду.
Есть неплохая шпаргалка по установке

curl https://haproxy.debian.net/bernat.debian.org.gpg | 
      apt-key add -
echo deb http://haproxy.debian.net stretch-backports-2.0 main | 
      tee /etc/apt/sources.list.d/haproxy.list
apt-get update
apt-get install haproxy=2.0.*

После того, как HAproxy, установлен нам нужно создать для него конфиг.
Если на worker нодах нет каталога с конфиг файлами, то клонируем его

git clone https://github.com/rjeka/kubernetes-ceph-percona.git
cd kubernetes-ceph-percona/

И запускаем скрипт конфига с флагом haproxy

./create-config.sh haproxy

Скрипт сконфигурирует и перезапустит haproxy.
Проверим, что haproxy стал слушать порт 6443.

root@worknode01:~/kubernetes-ceph-percona# netstat -alpn | grep 6443
tcp        0      0 127.0.0.1:6443          0.0.0.0:*               LISTEN      30675/haproxy
tcp        0      0 10.73.75.241:6443       0.0.0.0:*               LISTEN      30675/haproxy

Теперь нам нужно сказать kubelet, чтобы он обращался на localhost вместо master ноды. Для этого нужно отредактировать значение server в файлах /etc/kubernetes/kubelet.conf и /etc/kubernetes/bootstrap-kubelet.conf на всех worker нодах.

vim  /etc/kubernetes/kubelet.conf
vim nano /etc/kubernetes/bootstrap-kubelet.conf

Значение server должно принять вот такой вид:

server: https://127.0.0.1.6443

После внесения изменений нужно перезапустить службы kubelet и docker

systemctl restart kubelet && systemctl restart docker

Проверим, что все ноды работают исправно

kubectl get nodes
NAME         STATUS   ROLES    AGE     VERSION
master01     Ready    master   29m     v1.15.1
master02     Ready    master   27m     v1.15.1
master03     Ready    master   26m     v1.15.1
worknode01   Ready    <none>   25m     v1.15.1
worknode02   Ready    <none>   3m15s   v1.15.1
worknode03   Ready    <none>   3m16s   v1.15.1

Пока что у нас нет приложений в кластере, чтобы проверить работу HA. Но мы можем остановить работу kubelet на первой master ноде и убедится, что наш кластер остался дееспособным.

systemctl stop kubelet && systemctl stop docker

Проверяем со второй master ноды

root@master02:~# kubectl get nodes
NAME         STATUS     ROLES    AGE   VERSION
master01     NotReady   master   15h   v1.15.1
master02     Ready      master   15h   v1.15.1
master03     Ready      master   15h   v1.15.1
worknode01   Ready      <none>   15h   v1.15.1
worknode02   Ready      <none>   15h   v1.15.1
worknode03   Ready      <none>   15h   v1.15.1

Все ноды функционируют нормально, кроме той, на которой мы остановили службы.
Не забываем включить обратно службы kubernetes на первой master ноде

systemctl start kubelet && systemctl start docker

Установка Ingress контроллера

Ingress контроллер — это дополнение Kubernetes, c помощью которого мы можем получить доступ до наших приложений снаружи. Подробное описание есть в документации Kuberbnetes. Ingress контролеров существует достаточное большое количество, я пользуюсь контроллером от Nginx. Про его установку я и буду рассказывать. Документацию по работе, настройке и установке Ingress контроллера от Nginx можно почитать на официальном сайте

Приступим к установке, все команды можно выполнять с master01.
Устанавливаем сам контроллер

kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/static/mandatory.yaml

А теперь — сервис, через который будет доступен ингресс
Для этого подготовим конфиг

./create-config.sh ingress

И отправим его в наш кластер

kubectl apply -f ingress/service-nodeport.yaml

Проверим, что наш Ingress работает на нужных адресах и слушает нужные порты

# kubectl get svc -n ingress-nginx
NAME            TYPE       CLUSTER-IP    EXTERNAL-IP                           PORT(S)                      AGE
ingress-nginx   NodePort   10.99.35.95   10.73.71.25,10.73.71.26,10.73.71.27   80:31669/TCP,443:31604/TCP   10m
 kubectl describe svc -n ingress-nginx ingress-nginx
Name:                     ingress-nginx
Namespace:                ingress-nginx
Labels:                   app.kubernetes.io/name=ingress-nginx
                          app.kubernetes.io/part-of=ingress-nginx
Annotations:              kubectl.kubernetes.io/last-applied-configuration:
                            {"apiVersion":"v1","kind":"Service","metadata":{"annotations":{},"labels":{"app.kubernetes.io/name":"ingress-nginx","app.kubernetes.io/par...
Selector:                 app.kubernetes.io/name=ingress-nginx,app.kubernetes.io/part-of=ingress-nginx
Type:                     NodePort
IP:                       10.99.35.95
External IPs:             10.73.71.25,10.73.71.26,10.73.71.27
Port:                     http  80/TCP
TargetPort:               80/TCP
NodePort:                 http  31669/TCP
Endpoints:                192.168.142.129:80
Port:                     https  443/TCP
TargetPort:               443/TCP
NodePort:                 https  31604/TCP
Endpoints:                192.168.142.129:443
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

Установка Web UI (Dashboard)

У Kubernetes есть стандартный Web UI, через который иногда удобно быстро глянуть состояние кластера или отдельных его частей. Я в своей работе часто использую daschboard для первичной диагностики деплоя или состояния частей кластера.
Ссылка на документацию находится на сайте kubernetes
Установка. Я использую стабильную версию, 2.0 пока что не пробовал.

#Стабильная версия
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v1.10.1/src/deploy/recommended/kubernetes-dashboard.yaml
#Версия 2.0
kubectl apply -f https://raw.githubusercontent.com/kubernetes/dashboard/v2.0.0-beta1/aio/deploy/recommended.yaml

После того, как мы установили панель в наш кластер, панель стала доступна по адресу

http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.

Но для того, чтобы на нее попасть, нам нужно с локальной машины пробросить порты с помощью kubectl proxy. Для меня эта схема очень не удобная. Поэтому я изменю service панели управления, для того чтобы dashboard стал доступен на адресе любой ноды кластера на порту 30443. Есть еще другие способы получить доступ до дашборда, например, через ingress. Возможно, я рассмотрю этот способ в следующих публикациях.
Для изменения сервиса запустим деплой измененного сервиса

kubectl apply -f dashboard/service-nodeport.yaml

Осталось создать admin пользователя и token для доступа к кластеру через дашборд

kubectl apply -f dashboard/rbac.yaml
kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep admin-user | awk '{print $1}')

После этого можно залогинится в панеле управления по адресу https://10.73.71.25:30443

Главный экран dashboard

Поздравляю! Если Вы дошли до этого шага, то у Вас есть работающий HA кластер kubernetes, который готов для деплоя Ваших приложений.
Kubernetes является костяком микросервисной инфраструктуру, на который требуется устанавливать различные дополнения. Про некоторые из них я планирую рассказать в следующих публикациях.
На все вопросы постараюсь ответить в комментариях, на GitHub, или в любых соцсетях, указанных в моем профиле.

C уважением, Евгений Родионов.