Установка HA Master Kubernetes кластера с помощью Kubespray

  • Tutorial


Kubespray (ранее Kargo) — это набор Ansible ролей для установки и конфигурации системы оркестрации контейнерами Kubernetes. В качестве IaaS в этом случае могут выступать AWS, GCE, Azure, OpenStack или обычные виртуальные машины. Проект раньше назывался Kargo. Это проект с открытым исходным кодом и открытой моделью разработки, поэтому по желанию каждый может повлиять на его жизненный цикл.

На Хабре уже писали об установке Kubernetes с помощью Kubeadm, но в этом способе есть значительные недостатки: он до сих пор не поддерживает мультимастер конфигураций и, порой, не очень гибкий. Kubespray, хоть и использует Kubeadm под капотом, уже имеет функционал обеспечения высокой доступности как для мастера, так и для etcd на этапе инсталляции. О его сравнении с другими актуальными методами установки Kubernetes можно почитать по ссылке https://github.com/kubernetes-incubator/kubespray/blob/master/docs/comparisons.md

В этой статье мы создадим 5 серверов на ОС Ubuntu 16.04. В моем случае их перечень будет следующим:

192.168.20.10 k8s-m1.me
192.168.20.11 k8s-m2.me
192.168.20.12 k8s-m3.me
192.168.20.13 k8s-s1.me
192.168.20.14 k8s-s2.me

Добавляем их к /etc/hosts всех этих серверов, в том числе локальной системы, или же к dns-серверу. Фаервол и другие ограничения в сети этих хостов должны быть деактивированы. Кроме этого, необходимо разрешить IPv4 forwarding и каждый из хостов должен иметь свободный доступ к сети Интернет для загрузки docker-образов.

Копируем публичный rsa-ключ к каждому серверу из списка:

$ ssh-copy-id ubuntu@server.me

Указываем необходимого пользователя и ключ для подключения с локальной машины:

$ vim ~/.ssh/config
...
Host *.me
    User ubuntu
    ServerAliveInterval 60
    IdentityFile ~/.ssh/id_rsa

Где ubuntu — пользователь, от имени которого будет происходить подключение к серверу, a id_rsa — приватный ключ. Более того, этот пользователь нуждается в возможности выполнения команд sudo без пароля.

Клонируем репозиторий Kubespray:

$ git clone https://github.com/kubernetes-incubator/kubespray.git

После копируем директорию inventory для редактирования ее содержимого:

$ cp -r inventory my_inventory
$ cd my_inventory

В качестве примера используем inventory.example:

$ mv inventory.example inventory

$ vim inventory

k8s-m1.me ip=192.168.20.10
k8s-m2.me ip=192.168.20.11
k8s-m3.me ip=192.168.20.12
k8s-s1.me ip=192.168.20.13
k8s-s2.me ip=192.168.20.14

[kube-master]
k8s-m1.me
k8s-m2.me
k8s-m3.me

[etcd]
k8s-m1.me
k8s-m2.me
k8s-m3.me

[kube-node]
k8s-s1.me
k8s-s2.me

[k8s-cluster:children]
kube-node
kube-master

Исходя из представленного выше, мы выполним установку HA инсталляции Kubernetes: etcd, хранилище параметров конфигурации кластера, будет состоять из 3-х узлов для присутствия кворума, а сервисы Kubernetes Master (kube-apiserver, controller-manager, scheduler и т.д.) будут продублированы трижды. Конечно, ничего не мешает вынести сервис etcd полностью отдельно.

На этом этапе хотелось бы немного подробнее рассказать о том, как реализован режим HA для мастеров. На каждом воркере Kubernetes (в нашем случае это k8s-s*.me) будет установлен Nginx в режиме балансировки, в upstream которого будут описаны все мастера Kubernetes:

stream {
        upstream kube_apiserver {
            least_conn;
            server kube-master_ip1:6443;
            server kube-master_ip2:6443;
            server kube-master_ip3:6443;
                    }

        server {
            listen        127.0.0.1:6443;
            proxy_pass    kube_apiserver;
            proxy_timeout 10m;
            proxy_connect_timeout 1s;

        }

Соответственно в случае падения одного из мастеров, Nginx исключит его из upstream и прекратит пересылать запросы на такой сервер.



Такая схема позволяет исключить единую точку отказа: в случае падения мастера его работу примет на себя другой мастер, а ответственный за переадресацию запросов Nginx работает на каждом воркере.

На этапе установки кластера есть возможность отключить этот внутренний балансировщик и уже заботиться обо всем самостоятельно. Это может быть, например, какой-то сторонний Nginx или HAProxy. Однако не стоит забывать, что для обеспечения высокой доступности они должны работать в паре, между членами которой при необходимости должен мигрировать Virtual IP. VIP может быть реализован с помощью различных технологий таких, как Keepalived, Heartbeat, Pacemaker и т.п.

На мастере kube-apiserver работает одновременно на 2-х портах: локальном 8080 без шифрования (для служб, работающих на одном сервере) и внешнем HTTPS 6443. Последний, как я уже упомянул, используется для связи с воркерами и может пригодиться, если сервисы одного мастера (kubelet, kube-proxy и др) необходимо вынести на другие хосты.

Продолжим работу по созданию тестового кластера. Отредактируем group_vars/all.yml:

$ vim group_vars/all.yml
...
bootstrap_os: ubuntu
...
kubelet_load_modules: true

Кроме Ubuntu 16.04 Kubespray также поддерживает инсталляцию на узлы с CoreOS, Debian Jessie, CentOS/RHEL 7, то есть на все основные актуальные дистрибутивы.

При необходимости следует также заглянуть в group_vars/k8s-cluster.yml, где можно указать необходимую версию Kubernetes, которая будет проинсталлирована, выбрать плагин для оверлейной сети (по-умолчанию это calico, но доступны и другие варианты), установить efk (elasticsearch/fluentd/kibana), helm, istio, netchecker и т.п.

Также рекомендую посмотреть roles/kubernetes/preinstall/tasks/verify-settings.yml. Здесь находятся базовые проверки, которые будут выполнены перед началом установки Kubernetes. Например, проверки наличия достаточного количества оперативной памяти (на данный момент, это не менее 1500MB для мастеров и 1000MB для нод), количества etcd серверов (для обеспечения кворума их должно быть нечетное количество) и прочее. В последних релизах Kubespray появилась дополнительное требование по swap-у: он должен быть выключен на всех узлах кластера.

Если Ansible еще отсутствует в локальной системе, установим его вместе с модулем netaddr:

# pip install ansible
# pip install netaddr

Важно обратить внимание на то, что модуль netaddr и ansible должны работать с той же версией Python.

После этого можем приступать к установке кластера Kubernetes:

$ ansible-playbook -i my_inventory/inventory cluster.yml -b -v

Как вариант, rsa-ключ и пользователя для подключения можно передать аргументами, например:

$ ansible-playbook -u ubuntu -i my_inventory/inventory cluster.yml -b -v --private-key=~/.ssh/id_rsa

Обычно установка кластера занимает около 15-20 мин, но все зависит также от вашего железа. После мы можем проверить корректно ли все работает, для чего необходимо подключиться к любому хосту кластера и выполнить следующее:

root@k8s-m1:~# kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
k8s-m1    Ready     master    28m       v1.8.4+coreos.0
k8s-m2    Ready     master    28m       v1.8.4+coreos.0
k8s-m3    Ready     master    28m       v1.8.4+coreos.0
k8s-s1    Ready     node      28m       v1.8.4+coreos.0
k8s-s2    Ready     node      28m       v1.8.4+coreos.0

root@k8s-m1:~# kubectl get pods --all-namespaces
NAMESPACE     NAME                                    READY     STATUS    RESTARTS   AGE
kube-system   calico-node-2z6jz                       1/1       Running   0          27m
kube-system   calico-node-6d6q6                       1/1       Running   0          27m
kube-system   calico-node-96rgg                       1/1       Running   0          27m
kube-system   calico-node-nld9z                       1/1       Running   0          27m
kube-system   calico-node-pjcjs                       1/1       Running   0          27m
kube-system   kube-apiserver-k8s-m1                   1/1       Running   0          27m
...
kube-system   kube-proxy-k8s-s1                       1/1       Running   0          26m
kube-system   kube-proxy-k8s-s2                       1/1       Running   0          27m
kube-system   kube-scheduler-k8s-m1                   1/1       Running   0          28m
kube-system   kube-scheduler-k8s-m2                   1/1       Running   0          28m
kube-system   kube-scheduler-k8s-m3                   1/1       Running   0          28m
kube-system   kubedns-autoscaler-86c47697df-4p7b8     1/1       Running   0          26m
kube-system   kubernetes-dashboard-85d88b455f-f5dm4   1/1       Running   0          26m
kube-system   nginx-proxy-k8s-s1                      1/1       Running   0          28m
kube-system   nginx-proxy-k8s-s2                      1/1       Running   0          28m

Как видим, по-умолчанию, сразу была установлена ​​и веб-панель kubernetes-dashboard. Детали относительно ее работы можно найти по следующей ссылке https://github.com/kubernetes/dashboard

Исключительно для базовой проверки выльем под с двумя контейнерами:

$ vim first-pod.yaml

apiVersion: v1
kind: Pod
metadata:
  name: first-pod
spec:
  containers:
  - name: sise
    image: mhausenblas/simpleservice:0.5.0
    ports:
    - containerPort: 9876
    resources:
      limits:
        memory: "64Mi"
        cpu: "500m"
  - name: shell
    image: centos:7
    command:
      - "bin/bash"
      - "-c"
      - "sleep 10000"

$ kubectl apply -f first-pod.yaml
pod "first-pod" created

$ kubectl get pods
NAME              READY     STATUS    RESTARTS   AGE
first-pod        2/2       Running   0          16s

$ kubectl exec first-pod -c sise -i -t -- bash
[root@first-pod /]# curl localhost:9876/info
{"host": "localhost:9876", "version": "0.5.0", "from": "127.0.0.1"}

Это было тестовое приложение на языке Python с ресурса http://kubernetesbyexample.com/.

Довольно странно, но в качестве системы контейнеризации был установлен Docker 17.03.1-ce, хотя в официальной документации упоминается, что лучше всего использовать именно версию 1.13. Версия Docker, которая будет установлена, описанная в roles/docker/defaults/main.yml и, теоретически, ее можно перезаписать в файлах конфигурации выше или передать значение аргументом.

Ansible скрипты Kubespray также поддерживают масштабирование к-ва узлов кластера. Для этого обновим inventory, в котором добавим новую ноду (worker):

$ vim my_inventory/inventory

k8s-m1.me ip=192.168.20.10
k8s-m2.me ip=192.168.20.11
k8s-m3.me ip=192.168.20.12
k8s-s1.me ip=192.168.20.13
k8s-s2.me ip=192.168.20.14
k8s-s3.me ip=192.168.20.15

[kube-master]
k8s-m1.me
k8s-m2.me
k8s-m3.me

[etcd]
k8s-m1.me
k8s-m2.me
k8s-m3.me

[kube-node]
k8s-s1.me
k8s-s2.me
k8s-s3.me

[k8s-cluster:children]
kube-node
kube-master

Конечно, узел k8s-s3.me также должен быть соответствующим образом настроен, как и предыдущие ноды. Теперь можем запускать масштабирование кластера:

$ ansible-playbook -i my_inventory/inventory scale.yml -b -v

Согласно документации Kubespray, для этого можно использовать и предварительную процедуру с cluster.yml, однако с scale.yml это займет значительно меньше времени. В результате сейчас можем наблюдать новый узел через kubectl:

$ kubectl get nodes
NAME      STATUS    ROLES     AGE       VERSION
k8s-m1    Ready     master    6h        v1.8.4+coreos.0
k8s-m2    Ready     master    6h        v1.8.4+coreos.0
k8s-m3    Ready     master    6h        v1.8.4+coreos.0
k8s-s1    Ready     node      6h        v1.8.4+coreos.0
k8s-s2    Ready     node      6h        v1.8.4+coreos.0
k8s-s3    Ready     node      19m       v1.8.4+coreos.0

Вот и все. Так же эту статью можно прочитать на украинском языке по адресу http://blog.ipeacocks.info/2017/12/kubernetes-part-iv-setup-ha-cluster.html

PS. Обо всех ошибках лучше сразу писать в приват — оперативно исправим.

  • +15
  • 3,4k
  • 2
Поделиться публикацией
Похожие публикации
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама
Комментарии 2
  • +1

    Спасибо за статью!

    • +1

      Спасибо. Надо пробовать!

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