Основы Kubernetes

В этой публикации я хотел рассказать об интересной, но незаслуженно мало описанной на Хабре, системе управления контейнерами Kubernetes.

image

Что такое Kubernetes?


Kubernetes является проектом с открытым исходным кодом, предназначенным для управления кластером контейнеров Linux как единой системой. Kubernetes управляет и запускает контейнеры Docker на большом количестве хостов, а так же обеспечивает совместное размещение и репликацию большого количества контейнеров. Проект был начат Google и теперь поддерживается многими компаниями, среди которых Microsoft, RedHat, IBM и Docker.

Компания Google пользуется контейнерной технологией уже более десяти лет. Она начинала с запуска более 2 млрд контейнеров в течение одной недели. С помощью проекта Kubernetes компания делится своим опытом создания открытой платформы, предназначенной для масштабируемого запуска контейнеров.

Проект преследует две цели. Если вы пользуетесь контейнерами Docker, возникает следующий вопрос о том, как масштабировать и запускать контейнеры сразу на большом количестве хостов Docker, а также как выполнять их балансировку. В проекте предлагается высокоуровневый API, определяющее логическое группирование контейнеров, позволяющее определять пулы контейнеров, балансировать нагрузку, а также задавать их размещение.

Концепции Kubernetes


Nodes (node.md): Нода это машина в кластере Kubernetes.
Pods (pods.md): Pod это группа контейнеров с общими разделами, запускаемых как единое целое.
Replication Controllers (replication-controller.md): replication controller гарантирует, что определенное количество «реплик» pod'ы будут запущены в любой момент времени.
Services (services.md): Сервис в Kubernetes это абстракция которая определяет логический объединённый набор pod и политику доступа к ним.
Volumes (volumes.md): Volume(раздел) это директория, возможно, с данными в ней, которая доступна в контейнере.
Labels (labels.md): Label'ы это пары ключ/значение которые прикрепляются к объектам, например pod'ам. Label'ы могут быть использованы для создания и выбора наборов объектов.
Kubectl Command Line Interface (kubectl.md): kubectl интерфейс командной строки для управления Kubernetes.

Архитектура Kubernetes


Работающий кластер Kubernetes включает в себя агента, запущенного на нодах (kubelet) и компоненты мастера (APIs, scheduler, etc), поверх решения с распределённым хранилищем. Приведённая схема показывает желаемое, в конечном итоге, состояние, хотя все ещё ведётся работа над некоторыми вещами, например: как сделать так, чтобы kubelet (все компоненты, на самом деле) самостоятельно запускался в контейнере, что сделает планировщик на 100% подключаемым.
image

Нода Kubernetes

При взгляде на архитектуру системы мы можем разбить его на сервисы, которые работают на каждой ноде и сервисы уровня управления кластера. На каждой ноде Kubernetes запускаются сервисы, необходимые для управления нодой со стороны мастера и для запуска приложений. Конечно, на каждой ноде запускается Docker. Docker обеспечивает загрузку образов и запуск контейнеров.

Kubelet

Kubelet управляет pod'ами их контейнерами, образами, разделами, etc.

Kube-Proxy

Также на каждой ноде запускается простой proxy-балансировщик. Этот сервис запускается на каждой ноде и настраивается в Kubernetes API. Kube-Proxy может выполнять простейшее перенаправление потоков TCP и UDP (round robin) между набором бэкендов.

Компоненты управления Kubernetes

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

etcd

Состояние мастера хранится в экземпляре etcd. Это обеспечивает надёжное хранение конфигурационных данных и своевременное оповещение прочих компонентов об изменении состояния.

Kubernetes API Server

Kubernetes API обеспечивает работу api-сервера. Он предназначен для того, чтобы быть CRUD сервером со встроенной бизнес-логикой, реализованной в отдельных компонентах или в плагинах. Он, в основном, обрабатывает REST операции, проверяя их и обновляя соответствующие объекты в etcd (и событийно в других хранилищах).

Scheduler

Scheduler привязывает незапущенные pod'ы к нодам через вызов /binding API. Scheduler подключаем; планируется поддержка множественных scheduler'ов и пользовательских scheduler'ов.

Kubernetes Controller Manager Server

Все остальные функции уровня кластера представлены в Controller Manager. Например, ноды обнаруживаются, управляются и контролируются средствами node controller. Эта сущность в итоге может быть разделена на отдельные компоненты, чтобы сделать их независимо подключаемыми.

ReplicationController — это механизм, основывающийся на pod API. В конечном счете планируется перевести её на общий механизм plug-in, когда он будет реализован.

Пример настройки кластера


В качестве платформы для примера настройки была выбрана Ubuntu-server 14.10 как наиболее простая для примера и, в то же время, позволяющая продемонстрировать основные параметры настройки кластера.

Для создания тестового кластера будут использованы три машины для создания нод и отдельная машина для проведения удалённой установки. Можно не выделять отдельную машину и производить установку с одной из нод.

Список используемых машин:
  • Conf
  • Node1: 192.168.0.10 — master, minion
  • Node2: 192.168.0.11 — minion
  • Node3: 192.168.0.12 — minion

Подготовка нод

Требования для запуска:

  1. На всех нодах установлен docker версии 1.2+ и bridge-utils
  2. Все машины связаны друг с другом, необходимости в доступе к интернету нет (в этом случае необходимо использовать локальный docker registry)
  3. На все ноды можно войти без ввода логина/пароля, с использованием ssh-ключей

Установка ПО на ноды

Установку Docker можно произвести по статье в официальных источниках:

node% sudo apt-get update $ sudo apt-get install wget
node% wget -qO- https://get.docker.com/ | sh

Дополнительная настройка Docker после установки не нужна, т.к. будет произведена скриптом установки Kubernetes.
Установка bridge-utils:

node% sudo apt-get install bridge-utils

Добавление ssh-ключей

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

conf% ssh-keygen 

Копируем ключи на удалённые машины, предварительно убедившись в наличии на них необходимого пользователя, в нашем случае core.

conf% ssh-copy-id core@192.168.0.10
conf% ssh-copy-id core@192.168.0.11
conf% ssh-copy-id core@192.168.0.12

Установка Kubernetes

Далее мы займёмся установкой непосредственно Kubernetes. Для этого в первую очередь скачаем и распакуем последний доступный релиз с GitHub:

conf% wget https://github.com/GoogleCloudPlatform/kubernetes/releases/download/v0.17.0/kubernetes.tar.gz
conf% tar xzf ./kubernetes.tar.gz
conf% cd ./kubernetes

Настройка

Настройка Kubernetes через стандартные скрипты примеров полностью производится перед установкой производится через конфигурационные файлы. При установке мы будем использовать скрипты папке ./cluster/ubuntu/.

В первую очередь изменим скрипт ./cluster/ubuntu/build.sh который скачивает и подготавливает необходимые для установки бинарники Kubernetes, etcd и flannel:

conf% vim ./cluster/ubuntu/build.sh

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

# k8s
echo "Download kubernetes release ..."
K8S_VERSION="v0.15.0"

На:

# k8s
echo "Download kubernetes release ..."
K8S_VERSION="v0.17.0"

И запустим:

conf% cd ./cluster/ubuntu/ 
conf% ./build.sh      #Данный скрипт важно запускать именно из той папки, где он лежит.

Далее указываем параметры будущего кластера, для чего редактируем файл ./config-default.sh:

## Contains configuration values for the Ubuntu cluster
# В данном пункте необходимо указать все ноды будущего кластера, MASTER-нода указывается первой
# Ноды указываются в формате <user_1@ip_1> <user_2@ip_2> <user_3@ip_3> разделитель - пробел
# В качестве пользователя указывается тот пользователь для которого по нодам разложены ssh-ключи
export nodes="core@192.168.0.10 core@192.168.0.10 core@192.168.0.10"
# Определяем роли нод : a(master) или i(minion) или ai(master и minion), указывается в том же порядке, что и ноды в списке выше.
export roles=("ai" "i" "i")
# Определяем количество миньонов
export NUM_MINIONS=${NUM_MINIONS:-3}
# Определяем IP-подсеть из которой, в последствии будут выделяться адреса для сервисов.
# Выделять необходимо серую подсеть, которая не будет пересекаться с имеющимися, т.к. эти адреса будут существовать только в пределах каждой ноды.
#Перенаправление на IP-адреса сервисов производится локальным iptables каждой ноды.
export PORTAL_NET=192.168.3.0/24
#Определяем подсеть из которой будут выделяться подсети для создания внутренней сети flannel.
#flannel по умолчанию выделяет подсеть с маской 24 на каждую ноду, из этих подсетей будут выделяться адреса для Docker-контейнеров.
#Подсеть не должна пересекаться с PORTAL_NET
export FLANNEL_NET=172.16.0.0/16
# Admission Controllers определяет политику доступа к объектам кластера.
ADMISSION_CONTROL=NamespaceLifecycle,NamespaceAutoProvision,LimitRanger,ResourceQuota
# Дополнительные параметры запуска Docker.  Могут быть полезны для дополнительных настроек
# например установка --insecure-registry для локальных репозиториев.
DOCKER_OPTS=""

На этом настройка заканчивается и можно переходить к установке.

Установка

Первым делом необходимо сообщить системе про наш ssh-agent и используемый ssh-ключ для этого выполняем:

eval `ssh-agent -s`
ssh-add /путь/до/ключа

Далее переходим непосредственно к установке. Для этого используется скрипт ./kubernetes/cluster/kube-up.sh которому необходимо указать, что мы используем ubuntu.

conf% cd ../
conf% KUBERNETES_PROVIDER=ubuntu ./kube-up.sh

В процессе установки скрипт потребует пароль sudo для каждой ноды. По окончанию установки проверит состояние кластера и выведет список нод и адреса Kubernetes api.

Пример вывода скрипта
Starting cluster using provider: ubuntu
... calling verify-prereqs
... calling kube-up
Deploying master and minion on machine 192.168.0.10
<Список копируемых файлов>
[sudo] password to copy files and start node: 
etcd start/running, process 16384
Connection to 192.168.0.10 closed.
Deploying minion on machine 192.168.0.11
<Список копируемых файлов>
[sudo] password to copy files and start minion: 
etcd start/running, process 12325
Connection to 192.168.0.11 closed.
Deploying minion on machine 192.168.0.12
<Список копируемых файлов>
[sudo] password to copy files and start minion: 
etcd start/running, process 10217
Connection to 192.168.0.12 closed.
Validating master
Validating core@192.168.0.10
Validating core@192.168.0.11
Validating core@192.168.0.12
Kubernetes cluster is running.  The master is running at:
  http://192.168.0.10
... calling validate-cluster
Found 3 nodes.
     1  NAME           LABELS    STATUS
     2  192.168.0.10   <none>    Ready
     3  192.168.0.11   <none>    Ready
     4  192.168.0.12   <none>    Ready
Validate output:
NAME                 STATUS    MESSAGE   ERROR
etcd-0               Healthy   {"action":"get","node":{"dir":true,"nodes":[{"key":"/coreos.com","dir":true,"modifiedIndex":11,"createdIndex":11},{"key":"/registry","dir":true,"modifiedIndex":5,"createdIndex":5}],"modifiedIndex":5,"createdIndex":5}}
                     nil
controller-manager   Healthy   ok        nil
scheduler            Healthy   ok        nil
Cluster validation succeeded
Done, listing cluster services:
Kubernetes master is running at http://192.168.0.10:8080


Посмотрим, какие ноды и сервисы присутствуют в новом кластере:
conf% cp ../kubernetes/platforms/linux/amd64/kubectl /opt/bin/
conf% /opt/bin/kubectl get services,minions -s "http://192.168.0.10:8080"
NAME            LABELS                                    SELECTOR     IP           PORT(S)
kubernetes      component=apiserver,provider=kubernetes   <none>       192.168.3.2     443/TCP
kubernetes-ro   component=apiserver,provider=kubernetes   <none>       192.168.3.1     80/TCP
NAME           LABELS    STATUS
192.168.0.10   <none>    Ready
192.168.0.11   <none>    Ready
192.168.0.12   <none>    Ready

Видим список из установленных нод в состоянии Ready и два предустановленных сервиса kubernetes и kubernetes-ro — это прокси для непосредственного доступа к Kubernetes API. Как и к любому сервису Kubernetes к kubernetes и kubernetes-ro можно обратиться непосредственно по IP адресу с любой из нод.

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


Для запуска сервиса необходимо подготовить docker контейнер, на основе которого будет создан сервис. Дабы не усложнять, в примере будет использован общедоступный контейнер nginx. Обязательными составляющими сервиса являются Replication Controller, обеспечивающий запущенность необходимого набора контейнеров (точнее pod) и service, который определяет, на каких IP адресе и портах будет слушать сервис и правила распределения запросов между pod'ами.

Любой сервис можно запустить 2-я способами: вручную и с помощью конфиг-файла. Рассмотрим оба.

Запуск сервиса вручную

Начнём с создания Replication Controller'а:

conf% /opt/bin/kubectl run-container nginx --port=80 --port=443 --image=nginx --replicas=6 -s "http://192.168.0.10:8080"

Где:
  • nginx — имя будущего rc
  • --port — порты на которых будут слушать контейнеры rc
  • --image — образ из которого будут запущены контейнеры
  • --replicas=6 — количество реплик

Посмотрим, что у нас получилось:

/opt/bin/kubectl get pods,rc -s "http://192.168.0.10:8080"

Вывод
POD           IP           CONTAINER(S)   IMAGE(S)   HOST                        LABELS                STATUS    CREATED     MESSAGE
nginx-3gii4   172.16.58.4                             192.168.0.11/192.168.0.11   run-container=nginx   Running   9 seconds   
                           nginx          nginx                                                        Running   9 seconds   
nginx-3xudc   172.16.62.6                             192.168.0.10/192.168.0.10   run-container=nginx   Running   9 seconds   
                           nginx          nginx                                                        Running   8 seconds   
nginx-igpon   172.16.58.6                             192.168.0.11/192.168.0.11   run-container=nginx   Running   9 seconds   
                           nginx          nginx                                                        Running   8 seconds   
nginx-km78j   172.16.58.5                             192.168.0.11/192.168.0.11   run-container=nginx   Running   9 seconds   
                           nginx          nginx                                                        Running   8 seconds   
nginx-sjb39   172.16.83.4                             192.168.0.12/192.168.0.12   run-container=nginx   Running   9 seconds   
                           nginx          nginx                                                        Running   8 seconds 
nginx-zk1wv   172.16.62.7                             192.168.0.10/192.168.0.10   run-container=nginx   Running   9 seconds   
                           nginx          nginx                                                        Running   8 seconds   
CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR              REPLICAS
nginx        nginx          nginx      run-container=nginx   6


Был создан Replication Controller с именем nginx и количеством реплик равным 6. Реплики в произвольном порядке запущены на нодах, местоположения каждой pod'ы указано в столбце HOST.
Вывод может отличаться от приведённого в некоторых случаях, например:
  • Часть pod находится в состоянии pending: это значит, что они ещё не запустились, необходимо немного подождать
  • У pod не определён HOST: это значит, что scheduler ещё не назначил ноду на которой будет запущен pod


Далее создаём service который будет использовать наш Replication Controller как бекенд.
Для http:

conf% /opt/bin/kubectl expose rc nginx --port=80 --target-port=80 --service-name=nginx-http -s "http://192.168.0.10:8080"

И для https:

conf% /opt/bin/kubectl expose rc nginx --port=443 --target-port=443 --service-name=nginx-https -s "http://192.168.0.10:8080"

Где:
  • rc nginx — тип и имя используемого ресурса (rc = Replication Controller)
  • --port — порт на котором будет «слушать» сервис
  • --target-port — порт контейнера на который будет производиться трансляция запросов
  • --service-name — будущее имя сервиса

Проверяем результат:

/opt/bin/kubectl get rc,services -s "http://192.168.0.10:8080"

Вывод
CONTROLLER   CONTAINER(S)   IMAGE(S)   SELECTOR              REPLICAS
nginx        nginx          nginx      run-container=nginx   6
NAME            LABELS                                    SELECTOR              IP           PORT(S)
kubernetes      component=apiserver,provider=kubernetes   <none>                192.168.3.2     443/TCP
kubernetes-ro   component=apiserver,provider=kubernetes   <none>                192.168.3.1     80/TCP
nginx-http      <none>                                    run-container=nginx   192.168.3.66    80/TCP
nginx-https     <none>                                    run-container=nginx   192.168.3.172   443/TCP


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

node% curl http://192.168.3.66

В выводе curl увидим стандартную приветственную страницу nginx. Готово, сервис запущен и доступен.

Запуск сервиса с помощью конфигов

Для этого способа запуска необходимо создать конфиги для Replication Controller'а и service'а. Kubernetes принимает конфиги в форматах yaml и json. Мне ближе yaml поэтому будем использовать его.

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

conf% /opt/bin/kubectl delete services nginx-http nginx-https -s "http://192.168.0.10:8080"
conf% /opt/bin/kubectl stop rc nginx -s "http://192.168.0.10:8080"
Теперь приступим к написанию конфигов.

nginx_rc.yaml
содержимое
apiVersion: v1beta3
kind: ReplicationController
# Указываем имя ReplicationController
metadata:
  name: nginx-controller
spec:
  # Устанавливаем количество реплик
  replicas: 6
  selector:
    name: nginx
  template:
    metadata:
      labels:
        name: nginx
    spec:
      containers:
        #Описываем контейнер
        - name: nginx
          image: nginx
          #Пробрасываем порты
          ports:
            - containerPort: 80
            - containerPort: 443
          livenessProbe:
            # включаем проверку работоспособности
            enabled: true
            type: http
            # Время ожидания после запуска pod'ы до момента начала проверок
            initialDelaySeconds: 30
            TimeoutSeconds: 5
            # http проверка
            httpGet:
              path: /
              port: 80
      portals:
        - destination: nginx


Применяем конфиг:

conf% /opt/bin/kubectl create -f ./nginx_rc.yaml -s "http://192.168.0.10:8080"

Проверяем результат:

conf% /opt/bin/kubectl get pods,rc -s "http://192.168.0.10:8080"

Вывод
POD                      IP           CONTAINER(S)   IMAGE(S)   HOST                        LABELS       STATUS    CREATED          MESSAGE
nginx-controller-0wklg   172.16.58.7                             192.168.0.11/192.168.0.11   name=nginx   Running   About a minute   
                                      nginx          nginx                                               Running   About a minute   
nginx-controller-2jynt   172.16.58.8                             192.168.0.11/192.168.0.11   name=nginx   Running   About a minute   
                                      nginx          nginx                                               Running   About a minute   
nginx-controller-8ra6j   172.16.62.8                             192.168.0.10/192.168.0.10  name=nginx   Running   About a minute   
                                      nginx          nginx                                               Running   About a minute   
nginx-controller-avmu8   172.16.58.9                             192.168.0.11/192.168.0.11   name=nginx   Running   About a minute   
                                      nginx          nginx                                               Running   About a minute   
nginx-controller-ddr4y   172.16.83.7                             192.168.0.12/192.168.0.12   name=nginx   Running   About a minute   
                                      nginx          nginx                                               Running   About a minute   
nginx-controller-qb2wb   172.16.83.5                             192.168.0.12/192.168.0.12  name=nginx   Running   About a minute   
                                      nginx          nginx                                               Running   About a minute   
CONTROLLER         CONTAINER(S)   IMAGE(S)   SELECTOR     REPLICAS
nginx-controller   nginx          nginx      name=nginx   6


Был создан Replication Controller с именем nginx и количеством реплик равным 6. Реплики в произвольном порядке запущены на нодах, местоположения каждой pod'ы указано в столбце HOST.

nginx_service.yaml
Содержимое
apiVersion: v1beta3
kind: Service
metadata:
  name: nginx
spec:
  publicIPs: 
    - 12.0.0.5 # IP который будет присвоен сервису помимо автоматически назначенного.
  ports:
    - name: http
      port: 80 #порт на котором будет слушать сервис
      targetPort: 80 порт контейнера на который будет производиться трансляция запросов
      protocol: TCP
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
  selector:
    name: nginx # поле должно совпадать с аналогичным в конфиге ReplicationController


Можно заметить, что при использовании конфига за одним сервисом могут быть закреплены несколько портов.
Применяем конфиг:

conf% /opt/bin/kubectl create -f ./nginx_service.yaml -s "http://192.168.0.10:8080"

Проверяем результат:

/opt/bin/kubectl get rc,services -s "http://192.168.0.10:8080"

Вывод
CONTROLLER         CONTAINER(S)   IMAGE(S)   SELECTOR     REPLICAS
nginx-controller   nginx          nginx      name=nginx   6
NAME            LABELS                                    SELECTOR     IP           PORT(S)
kubernetes      component=apiserver,provider=kubernetes   <none>       192.168.3.2     443/TCP
kubernetes-ro   component=apiserver,provider=kubernetes   <none>       192.168.3.1     80/TCP
nginx           <none>                                    name=nginx   192.168.3.214   80/TCP
                                                                       12.0.0.5     443/TCP



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

node% curl http://192.168.3.214
node% curl http://12.0.0.5

В выводе curl увидим стандартную приветственную страницу nginx.

Заметки на полях


В качестве заключения хочу описать пару важных моментов, о которые уже пришлось запнуться при проектировании системы. Связаны они были с работой kube-proxy, того самого модуля, который позволяет превратить разрозненный набор элементов в сервис.
PORTAL_NET. Сущность сама по себе интересная, предлагаю ознакомиться с тем, как же это реализовано.
Недолгие раскопки привели меня к осознанию простой, но эффективной модели, заглянем в вывод iptables-save:

-A PREROUTING -j KUBE-PORTALS-CONTAINER
-A PREROUTING -m addrtype --dst-type LOCAL -j DOCKER
-A OUTPUT -j KUBE-PORTALS-HOST
-A OUTPUT ! -d 127.0.0.0/8 -m addrtype --dst-type LOCAL -j DOCKER
-A POSTROUTING -s 10.0.42.0/24 ! -o docker0 -j MASQUERADE
-A KUBE-PORTALS-CONTAINER -d 10.0.0.2/32 -p tcp -m comment --comment "default/kubernetes:" -m tcp --dport 443 -j REDIRECT --to-ports 46041
-A KUBE-PORTALS-CONTAINER -d 10.0.0.1/32 -p tcp -m comment --comment "default/kubernetes-ro:" -m tcp --dport 80 -j REDIRECT --to-ports 58340
-A KUBE-PORTALS-HOST -d 10.0.0.2/32 -p tcp -m comment --comment "default/kubernetes:" -m tcp --dport 443 -j DNAT --to-destination 172.16.67.69:46041
-A KUBE-PORTALS-HOST -d 10.0.0.1/32 -p tcp -m comment --comment "default/kubernetes-ro:" -m tcp --dport 80 -j DNAT --to-destination 172.16.67.69:58340

Все запросы к IP-адресу сервиса попавшие в iptables заворачиваются на порт на котором слушает kube-proxy. В связи с этим возникает одна проблема: Kubernetes, сам по себе, не решает проблему связи с пользователем. Поэтому придётся решать этот вопрос внешними средствами, например:
  • gcloud — платная разработка от Google
  • bgp — с помощью анонсирования подсетей
  • IPVS
  • и прочие варианты, которых множество

SOURCE IP Так же. при настройке сервиса nginx мне пришлось столкнуться с интересной проблемой. Она выглядела как строчка в мануале: «Using the kube-proxy obscures the source-IP of a packet accessing a Service». Дословно — при использовании kube-proxy скрывает адрес источника пакета, а это значит, что всю обработку построенную на основе source-IP придётся проводить до использования kube-proxy.

На этом всё, спасибо за внимание
К сожалению, всю информацию, которую хочется передать, не получается уместить в одну статью.

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

Поделиться публикацией
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама
Комментарии 85
  • +1
    Я нырнул в мир Docker буквально пару месяцев назад и это просто потрясающе! Кроме того, что я построил проект, который благодаря Docker стал модульным, безопасным и прекрасным, я наконец смог переехать на Arch Linux благодаря тому, что теперь я и у себя на ноуте могу с минимальными накладными расходами (виртуалка с Linux на Linux мне не нравилась совсем, а с chroot много мороки) иметь окружение идентичное с боевыми серверами.

    Тема управления кластеров с Docker контейнерами сейчас особенно популярна, лично я остановился на Docker Swarm. Преимущества:
    • официально поддерживается Docker
    • прост в настройке и использовании

    К недостаткам Docker Swarm я бы отнёс:
    • возможно, слишком прост для построения изолированных инфраструктур
    • возможно, команде Docker лучше было бы фокусироваться на самом Docker, а не распылять усилия и заходить на территорию kerbernetes/fleet/mesos/...

    Лично мне Docker Swarm нравится и пока что я им доволен как никогда. А какие у вас мысли по этому поводу? Стоит ли морочиться с Kubernetes для кластера из 10 машин?
    • 0
      Я рассматривал Docker Swarm когда выбирал систему управления контейнерами. Выбор между Kubernetes и Docker Swarm сводится к необходимому функционалу. Это связано с тем, что изначальные задачи у них различаются.
      Docker Swarm — способ использовать несколько машин как единую виртуальную среду для запуска контейнеров.
      Kubernetes же позволяет не только запустить несколько машин, но и занимается балансировкой нагрузки, контролем запущенности и обновлением контейнеров (есть функция rolling-update позволяющая без простоя обновить pod'ы внутри RC).

      Морочиться стоит в случае если:
      • Есть необходимость регулярного безпростойного деплоя
      • Необходимо обеспечить высокую отказоустойчивость
      • Необходимо обеспечить горизонтальную масштабируемость и балансировку не прибегая к «зоопарку» ПО
      • Вы не боитесь использовать в продакшне ПО находящееся в стадии альфа стадии разработки

      Возможно я ошибаюсь на счёт Swarm, буду благодарен за дополнительную информацию по опыту работы с ним.
      • +1
        Мой опыт подтверждает ваши слова относительно того, что Swarm — это просто абстракция, которая, на сколько это возможно, стирает границы между разными машинами. Пока что у меня на нём работает тестовый кластер, который изначально был запланирован только для внутрикорпоративнх экспериментов, так что высоких требований по uptime у него нет, так что Swarm отлично подошёл как простой способ управления всем хозяйством с одной машины.
        Вообще, Docker + Swarm вытеснили весь головняк с CFEngine, который хоть и решал проблемы, но всегда происходили какие-то накладки в конфигах, вылавливание которых порой занимало больше времени чем хотелось, так что в этом смысле мне нравится эта связка для текущих задач.
        • +2
          Mesos/Kubernetes/swarm/fleet это немного разные животные.

          IMO Mesos+Kubernetes всех победят, но пока все еще в глубокой альфе. Как и Swarm.
          Fleet хороший, но он более сложен в управлении.

          Из приятных вещей могу предложить tutum.co
          A la Kubernetes уже сегодня. Для среднего бизнеса.
          Очень хороший.
          • 0
            Если я правильно понял, что tutum.co — это вообще другое животное, это SaaS, который к тому же требует использования облачных провайдеров.

            На счёт глубокой альфы Swarm ничего сказать не могу — у меня больше месяца аптайм с ним и ничего не падало ещё.
            • 0
              Нет. Вы поняли не правильно.
      • 0
        Кто-нибудь пробовал использовать ОС заточенные под Docker (RancherOS, CoreOS, Atomic, Snappy Ubuntu, ...)? Меня интересует личный опыт, так как статей я поначитался уже много; больше всего привлекает RancherOS, но они как-то сбавили темпы и это меня расстраивает.
        • 0
          У меня есть небольшой опыт использования CoreOS совместно с Docker. Выбор пал на эту ОС как на активно развивающуюся, настраиваемую конфигом и имеющую возможность кластеризоваться «by design».
          К сожалению опыт прошёл в формате «продакшн тест» и, пока что, далее не продвинулся.
          • 0
            Были ли моменты, когда хотелось что-то сделать вопреки CoreOS? :)

            На самом деле, моя проблема с выбором ОС сейчас связана с одной небольшой деталью — в ядрах до 4.0 есть утечка памяти в ядре (в одном специфическом случае, в который нормальные люди не попадают обычно), так что я хожу по всем проектам и пинаю людей на апдейт ядра.
            • 0
              Честно говоря, вопреки CoreOS сделать ничего не хотелось, хотя и пришлось несколько изменить подход к организации сервисов согласно логике CoreOS.

              А бага интересна, читал про неё, но лично не сталкивался. Надеюсь, что её всё-же устранят.
              • 0
                Её устранили в 4.0 ядре, поэтому и хожу пинаю чтоб обновляли. boot2docker быстро откликнулись и обновили (я думал, что мне на первое время хватит, но оказалось, что я не угадал с направлением), а RancherOS уже две недели не отзываются, а они мне нравятся минимализмом и web-интерфейс у них интересный, хочу попробовать, а ещё они автоматически поднимают ipsec между контейнерами, что позволяет поднимать связанные контейнеры через интернет (интересно, но пока не придумал применения особо).
                • 0
                  Кстати про ipsec.
                  Flannel входящая в состав Kubernetes создаёт единое адресное пространство для всех контейнеров в пределах кластера, что позволяет свободно разносить ноды кластера по разным ЦОДам.

                  Как только они добавят механизм резервирования в систему управления можно будет проводить «учения» на целом ЦОДе.

                  Но и сейчас, потеря мастер-ноды не нарушает работу сервиса.
                  • +1
                    Flannel пока не поддерживает шифрование.
                    • –1
                      Но имеет возможность работать, например, внутри VPN-тоннеля.
                      • 0
                        Внимание всем «виртуализациям сети». Weave/flannel тормознутые.
                        Это не всегда важно, но иногда может быть.
                        • 0
                          Между тем, в той же статье написано, что Flannel с инкапсуляцией VXLan работает вполне корректно.
                          • 0
                            Да. Для этого линк. Знание = сила.
                      • 0
                        Flannel входит не в Kubernetes, а в CoreOS.
                        Вообще у них очень тесные взаимоотношения, команда CoreOS использует fleet чтобы стартануть kubernetes и дальше работают в последнем. Существует вероятность что fleet просто заменят в один прекрасный момент,
              • +1
                CoreOS и все прекрасно.

                Rancher не взлетит. Они ставят на «админку» но конкуренты их задавят.

                Kubernetes/Swarm в очень глубокой бете. Багов словил тонны.
                Fleet стабильно, но на порядок «сложней».
                • 0
                  Попробовал я, значит, CoreOS… Мне кажется, что я скоро сделаю N+1 OS. Когда я только познакомился с Docker, мне казалось, что мне подойдёт любая OS, которая удовлетворяет вот этому условию:
                  • Linux Kernel 3.10+

                  Как сильно я ошибался…
                  • Так получилось, что я использую фичи Docker 1.6.0+ (на момент написания проекта приходилось ночные релизы использовать)
                  • Всё шло гладко до нагрузочного тестирования, которое показало, что течёт память, да не просто память, а память ядра. В ходе раскопок узнал много нужного и не очень, но радости моей не было предела, когда я узнал, что в 4.0 уже это исправлено! Итак: Linux Kernel 4.0+
                  • Собирать своё ядро на Ubuntu мне не хотелось ну совсем, да и на данный момент все эксперименты ведутся в виртуальных машинах, так что можно пойти по пути экзотических ОС, в частности, «оптимизированных» для Docker (так как меинстрим дистрибутивы нереально пнуть на обновление ядра). Ок, RancherOS не прошёл по версии ядра, поставил CoreOS, а тут у нас overlay+extfs и ладно бы оно не лагало, так нет, упало на первом же запуске pip install… Итог: нужен AUFS, как уже проверенное решение

                  Продолжаю поиски…
                  • +1
                    Из годового опыта с докером и ядрами, поделюсь болью:)
                    На 2.6.х заводить докер себе дороже, хотя и работает, но бывают сюрпризы.
                    На 3.10+, на убунте живем вполне неплохо, довольно долго время. Про утечки памяти первый раз слышу.
                    Стандартный DeviceMapper — глючная хрень, мое имхо. Где-то уже пол года выдали докеру раздел с btrfs, тьфу, тьфу — полет нормальный.
                    • +1
                      Утечки памяти не связаны с Docker, а с Cgroups, когда пытаешься включить ограничение памяти ядра (использую как временный костыль против fork-бомб). Ирония в том, что ядро течёт при мониторинги потребления памяти ядра (исправлено в 4.0).
                      • +1
                        ага, вижу, в чем дело. Мы до сих пор на exec-driver=lxc
                      • 0
                        На centos7 словили багу с уничтожением netns и паникой по этому поводу (https://bugzilla.kernel.org/show_bug.cgi?id=65191). Благо на патченном руками ядре пришлось жить меньше месяца, потом фикс доехал в ванильном rhel'овском.

                        Сейчас на centos6 (с 2.6.32-504.16.2.el6) словили багу в cpuacct (в cgroups), пока ковыряю её, чтобы было что отправить в рассылки/багзиллу.

                        Я с devicemapper'а уехал на btrfs (только для /var/lib/docker), пока живёт и работает. Непривычно, правда, смотреть на состояние fs (df показывает погоду на Марсе). Но у меня все volumes — bind-mount на нормальную fs (xfs/ext4).

                        В общем, по 8 месяцам в production, namespaces, cgroups и докер сыроваты на centos6 и centos7.
                        • 0
                          Мы больше года живем в докере на CI, потом сделали стейджинг. Но, это единственная машинка с убунту, исключительно из-за вот этих багов с докером и центосом. В продакшн пока точно не собираемся, но мы и не любители облаков и подобного:)
                          btw, для Btrfs еще делаем крон с /sbin/btrfs scrub start /docker
                • +1
                  Кстати говоря, вот тут есть playbook для ansible (умеет RHEL, Fedora) для авторазвертывания кластера kubernetes. Уверен, что для chef/puppet и других дистров тоже есть.
                  Вообще было удобно конечно. При наличии этого плейбука и машин — все развертывание кластера занимает полчаса времени (у меня было 5 тестовых машин).
                  • +2
                    Да, подобные playbook довольно легко написать для любой системы управления серверами, благо, даже запуск «вручную» у Kubernetes довольно прост. Соответственно и playbook написать не сложно, необходимо описать запуск нескольких исполняемых файлов с определёнными параметрами.

                    Другой вопрос, что эти параметры стоит изучить и написать свой рецепт, а не брать готовый, можно напороться на неприятные последствия.
                    • 0
                      Абсолютно верно, главный «профит» в Ansible/Puppet/Chef в разрезе Kubernetes — то, что можно достаточно легко, без лишних телодвижений добавлять миньоны.
                      • –1
                        К сожалению, пока, добавить миньона «на лету» довольно проблематично. Данный функционал будет реализован чуть позже.
                        • +1
                          Ansible не нужен minion, на сколько мне известно. В остальном, согласен.
                    • +1
                      Смотрю на результаты голосования(лидирует рассказ о запуске стандартного LAMP стека) и удивляюсь — о чем там рассказывать?
                      «In the wild», mysql будет отдельным кластером(percona cluster). Остальное — обычные докер контейнеры и управление конфигами на основе какого-нибудь confd. Бери да запускай.

                      Или я ошибаюсь?
                      • 0
                        У меня несколько другой план:
                        • nginx — вне Kubernetes, дабы корректно обрабатывать source IP
                        • php в контейнерах в нескольких экземплярах, для отказоустойчивости и масштабируемости
                        • memcache в виде двух отдельных сервисов внутри кластера, репликация и отказоустойчивость
                        • galera — внутри кластера в виде 3-4 отдельных сервисов с подключением внешнего хранилища по iscsi

                        Как-то так.
                        Почему именно такой выбор — напишу в статье.
                        • 0
                          А что не так с nginx в ноде?
                          • 0
                            В ноде — нормально, но не в Kubernetes
                            • 0
                              А что не так с nginx в Kubernetes?
                              • 0
                                В статье выше, в разделе «заметки на полях» есть замечательная фраза «Using the kube-proxy obscures the source-IP of a packet accessing a Service» А для меня важно, чтобы приложение знало этот самый source-IP.
                        • 0
                          MySQL в контейнере, да ещё и через iscsi? ИМХО, лишний и ненужный оверхэд. Если хочется нанотехнологий, в CoreOS можно развернуть кластер в systemd-nspawn/docker через systemd/fleet на машинах с подключенной дисковой полкой.
                      • 0
                        А можно как-то вкратце, каким образом происходит синхронизация конкретно данных (баз данных, статики ...) между нодами? Нету хорошей статьи чтобы почитать?
                        • +3
                          Очень просто. Ее нет.
                          • 0
                            Можно прикрутить Flocker github.com/ClusterHQ/flocker, но интеграция с kubernetes там в зародыше.

                            Ну или шарить папку между нодами, а уже локальную папку монтировать в поды.
                            • 0
                              Зачем если есть нативные Data volume containers?
                              • 0
                                Пожалуйста подробнее что вы имеете ввиду. И где это они есть?
                                • 0
                                  Вы пробовали пользоваться поисковыми системами? «Data volume containers».
                                  #1url
                                  • 0
                                    Да я знаю про volume в docker, но они не работают. Они годятся только когда у вас 2-3 контейнера на одной машине, а не когда сотни на нескольких физических серверах.
                                    • 0
                                      Так же гугл вам бы мог помочь узнать что в kebernetes своя реализация для этого.
                                      • 0
                                        Ок. Мы друг друга поняли.
                          • +1
                            К сожалению, исключительно вручную, Kubernetes это система управления контейнерами и работает она только с ними.
                            В последних релизах добавили возможность отдавать через kube-proxy статику, но, как я понял, её нужно раскладывать по серверам так же — вручную.
                            • 0
                              А каким образом, хоть приблизительно, это происходит? Где вся эта парадигма контейнеров предусматривает хранение файлов?
                              Допустим, я запускаю 3 контейнера mysql сервера, данные хранятся в контейнере, реплика — это моя забота штатными средствами, но, как я понимаю логику работы контейнеров, одновременно работает 1 инстанс, как тогда происходит синхронизация?
                              С nginx еще непонятнее, если сервера раскиданы по разным физическим серверам, как синхронизировать статику, скрипты, сессии…
                              Прошу просить за глупые вопросы, но глубоко разбираться нет пока возможности, а понять, как оно работает хочется.
                              • +1
                                > Где вся эта парадигма контейнеров предусматривает хранение файлов?

                                В контейнерах.

                                Если вам одного инстанса мало, то вам нужна распределенная БД. А это уже совсем другой зверь и как правило не mysql.
                                • +1
                                  Парадигма контейнеров предусматривает хранение только статичной информации.
                                  Динамика, пользовательский данные и логи хранить внутри контейнеров вообще не стоит, разве что, при условии монтирования в контейнер внешнего хранилища, например по iscsi.
                                  • 0
                                    Спасибо, в общем становится немного яснее. Так понимаю, в том примере что в статье (без каких-то дополнительных телодвижений), будет 3 варианта статики для nginx, 3 разных лога…, каждый в своем контейнере.
                                    Было бы конечно очень интересно почитать про то, как практически это хозяйство организовать хотя бы на примере простого LAMP.
                                    Получается, если выносить данные за пределы контейнера, получаем одну точку отказа, теряется весь смысл затеянного.
                                    • 0
                                      Ну так используйте кластерную/распределенную ФС.

                                      Раскрою свою мысль.
                                      Есть несколько вариантов деплоя:

                                      * Плавный перезапуск контейнеров, в которых лежит вся статика;
                                      * В контейнере весит демон, который принимает перехватывает kill сигналы. И по kill -HUP(например), делает git pull -u
                                      * Использовать распределенную ФС. Например, gluster
                                      * Использовать что-нибудь типа mysql для хранения статики
                                      • 0
                                        Больше вариантов не успел написать — закончилось время редактиврования. Однако это первое, что пришло на ум. Остальное можете дописать сами.

                                        Лично я использую в своем pet-проекте перезапуск контейнеров с новой статикой.
                                        Для важных данных использую CephRBD.
                                      • 0
                                        Сбор логов — это отдельная задача. Надо настроить nginx (и все другие контейнеры) писать логи на stderr, потом их нужно чем-то собирать со всего кластера и уметь по ним поиск делать. Говорят, Fluentd + Elasticsearch хорошо работают.
                                        • 0
                                          Есть ещё вариант научить всё ПО в контейнерах писать в rsyslog и собирать это на отдельной логовнице.
                                          • 0
                                            Логовница может 1. сдохнуть и потерять часть логов, 2. не справляться с потоком логов от многих машин и, опять же, терять их. Лучше логи писать локально на диск, а потом неторопливо их высасывать в хранилище.
                                    • +1
                                      Предполагается делать это так. Вы ставите на все машины кластера GlusterFS, который поддерживает нужный уровень избыточности данных. Затем, когда контейнер запускается, у него создаётся volume, «смонтированный» в один из каталогов GlusterFS. В результате, все инстансы вашего приложения имеют доступ к одной и той же файловой системе без лишних телодвижений.
                                      • 0
                                        Надо будет попробовать запустить, нашел хорошую статью по GlusterFS — habrahabr.ru/post/251931

                                      • 0
                                        Оригинальный ответ от команды docker — используйте volumes.
                                        Это такие контейнеры которые не запускают сервисов но хранят данные и могут шарить эти данные с другими контейнерами.

                                        К сожалению идея работает очень убого ибо отключить и подключить volume к контейнеру можно только перезапуском самого контейнера.

                                        Ну а базы данных так либо на Gluster либо не в контейнере.
                                        • +2
                                          Это уровня «поиграться». Я не знаю никого в здравом уме, кто будет держать базы на Gluster и подобных сетевых хранилках. Я уже просто молчу, о том, что для баз c маломальской нагрузкой — это смерть.
                                          • 0
                                            +1, даже где-то в FAQ'е Ceph был жирным текстом выделен текст в подзаголовке «Ceph как бэкэнд для mysql», что не надо так делать.

                                            volume — это не контейнеры, это docker -v /path/in/host:/path/in/container.
                                            А взаимодействия конейнеров между собой — это уже другой вопрос.

                                            P.S. Расшарить из докера в хост машину volume оказалось очень не тривиальной задачей, когда я баловался.
                                            • 0
                                              Бывают volumes между хостом и контейнером, а бывают между ондинм контейнером и другим.
                                              Оригинальное использование volumes именно между контейнерами — команда докера так делает бекапы и логи в вообщем все.
                                              Volumes между хостом и контейнером считаются плохим тоном, хотя зря наверное, я люблю всякие сокеты с хоста прокидывать.
                                            • 0
                                              Базы да, а что по поводу статики? Допустим какой-то среднестатистический дефолтный интернет магазин с кучей картинок, превьющек и т.д.
                                              К примеру хотим сделать некое отказоустойчивое решение, имеем 3 сервера. Настройка стандартная nginx + php + mysql.
                                              насколько я понимаю, подход такой, собираем 3 ноды по мануалу из статьи. Внутри каждого контейнера собираем GlusterFS серверную ноду в режиме replicated volume, монтируем на /var/www.
                                              Mysql настраиваем для реплики…
                                              Правда вот сейчас думаю, зачем мне контейнеры )))) если это можно сделать и без них.
                                              Никак не могу понять как правильно в реальной жизни все это можно использовать.
                                              • +2
                                                Я бы ложил на S3 и кешировал локально nginx'ом при запросах:)

                                                С GlusteFS у меня исключительно негативные приключения. Но, если у вас там немного той статики в кол-ве файлов, то вполне себе решение. Хотя, я бы так не делал.
                                                Контейнеры у вас тут только под php подойдут, для остального(nginx, mysql) можно, но без смысла, как по мне.
                                                • 0
                                                  Контейнеры позволяют изолировать окружение. Вы можете упаковать ваши отдельные сервисы в образы и запускать их «вручную» с указанием локальной папки на конкретном сервере. Контейнеры не сделают вам автоматический S3/HDFS/GlusterFS/WeedFS/NFS/… это уровень приложений.

                                                  Кстати, я как-то изучал тему распределённых файловых систем и о GlusterFS всегда были отзывы и конкретные бенчмарки, показывающие, что нужно сторониться этой FS. NFS (не распределённая, но может показаться, что она подойдёт) — не вздумайте полагаться на NFS в проектах (личный опыт). Вы можете даже rsync по расписанию делать из контейнеров, кстати. Я в своё время пришёл к SeaweedFS (WeedFS), но нужно учитывать, что она никогда не будет POSIX-совместимой, но для статики она подходит отлично.
                                                  • +1
                                                    Смысл контейнеров заключается в бинарных апдейтах. В вашем случае это удобно для выкатывания обновлений php. В норме у вас app сервер, помимо php, будет содержать всякие утилиты типа imagemagic и прочие зависимости системы которые, могут уходить глубоко в libc.
                                                    Каждый раз когда вы выкатываете обновление обновление на конфигурацию app сервера вы рискуете получить отличающееся состояние. Докер гарантирует, что обновления будут идентичными.

                                                    Но статья-то про кубернетис, а это следующий шаг после контейнров — scheduled deployments. Тут две радости — во первых удобно следовать infrastructure as code, во вторых масштабировать систему очень приятно — говоришь я хочу еще 10 этих контецнеров и через 5 секунд они работают.
                                                    • 0
                                                      Ага. А ещё удобно тестовую версию системы поднимать. Говоришь — хочу вот точно такую базу данных, в неё, пожалуйста, вчерашний бэкап с продакшна, ещё нужны такие же сервисы, как в продакшне, только с новой версией. И всё само поднимается, связывается друг с другом, и готово к тестированию. Потом прибить всё одной командой, чтобы ресурсы не ело.
                                        • 0
                                          Kubernetes, сам по себе, не решает проблему связи с пользователем.
                                          Очень даже решает. Вы можете запустить Pod с опцией hostNetwork: true. В результате порты будут доступны не на виртуальном динамическом IP, а снаружи. Конфиг выглядит примерно так:

                                          spec:
                                            nodeSelector:
                                              frontend: "true"
                                            hostNetwork: true
                                            containers:
                                              - name: frontend
                                                image: your/packaged/nginx:latest
                                                ports:
                                                  - name: http
                                                    containerPort: 80
                                                    hostPort: 80
                                                    protocol: TCP
                                                  - name: https
                                                    containerPort: 443
                                                    hostPort: 443
                                                    protocol: TCP
                                          

                                          Тут важны два момента. Во-первых, мы ограничиваем, на каких нодах запускать nginx (только на тех, которые мы пометили как frontend=true), а во-вторых, порты 80 и 443 будут доступны снаружи (hostNetwork: true).

                                          Потом можно снаружи какой-нибудь Cloudflare прицепить, чтобы внешний трафик проксировал на эти машины, и получится нормальный отказоустойчивый фронтенд.
                                          • 0
                                            Да, это возможно, но я, пока, не исследовал как себя поведут pod при попытке запуститься на уже занятом порту.
                                            К тому же, проблему связи с пользователем, в данном решении, решает всё-же Cloudflare, а не Kubernetes.
                                            • 0
                                              1. Это решается на этапе scheduling'а. Kubernetes не отправит два пода, которым нужен один и тот же внешний порт, на одну машину. Если на машине порт занят чем-то другим (не подом), то под будет висеть в статусе Pending, пока порт не освободится и он не сможет стартовать.

                                              2. Вы можете запустить одну единственную ноду с nginx, и настроить ваш домен, чтобы он указывал на её IP-адрес. Тогда Cloudflare не нужен. Всё просто работает. Cloudflare — это полезное дополнение, чтобы фронтенд не был единой точкой отказа. Это собственно и не только к Kubernetes относится, а вообще к любой системе, которая претендует на отказоустойчивость.
                                          • 0
                                            Интересует вопрос миграции подов. Допустим система управления приняла решение разгрузить одну из нод, и должна выселить с ноды 30% подов. Как это возможно реализовать? Пока расматриваю 2 варианта:

                                            1. Переводим ноду в статус unschedulable и запускаем rolling-update для репликейшен контроллеров которые имеют поды на необходимой ноде. Таким образом RC заменит поды по очереди, и стартанет их уже в новом месте
                                            2. Настроить жеский контроль по лейблам, и так же ролинг апдейтом перемещать поды с ноды на ноду

                                            • 0
                                              Мне решение #1 кажется наиболее подходящим к философии Kubernetes. Единственное, если вы хотите ограничить нагрузку на машину, чтобы она потребляла на 30% меньше ресурсов, а не отключить её совсем, то вместо unschedulable лучше уменьшить лимит CPU и RAM (поле Capacity).
                                              • 0
                                                Мы хотим оверселить ресурсы, и поймать момент когда пора скейлить инфраструктуру и переносить клиентов на новые ноды. Сразу предвидеть нагрузку нет возможности, так как все зависит от частного случая каждого клиента. А держать сервера в простое тоже не хочется.
                                                • 0
                                                  Я правильно понимаю, что вы хотите делать utilization based scheduling? Т.е. если нагрузка на конкретную ноду стала неприемлемо большой, то вы хотите раскидывать контейнеры на другие ноды?
                                                  • 0
                                                    Именно, так и хотим )
                                                    • 0
                                                      Тогда всё гораздо проще делается. Когда ваша логика решает разгрузить машину, она просто отстреливает «лишние» поды на ней. Replication controller у вас должен быть настроен с политикой LeastRequestedPriority, чтобы новые поды направлялись на наименее загруженные машины.
                                                      • 0
                                                        А где можно прочесть про этот LeastRequestedPriority? Просто отстрелить их не получится, так как нужно без даунтайма это делать. Но если я правильно понял то и ролинг-апдейт тут подойдет.
                                                        • 0
                                                          Если нужен graceful restart, то вместо отстрела, просто снимаете все лейблы с пода. Он ещё запущен, принимает запросы от пользователей, но для kube-proxy и для kube-scheduler он уже не видим. Первый снимет с него трафик, а второй запустит новый под где-нибудь. Через несколько секунд нагрузка на под упадёт до нуля, и его можно уже прибить. Собственно, rolling restart ровно это и делает. Только он делает это со всеми подами, которые у вас есть в кластере, а вы можете сделать это только с теми, которые вам нужно перенести на другие машины.

                                                          Про LeastRequestedPriority тут — github.com/GoogleCloudPlatform/kubernetes/blob/master/plugin/pkg/scheduler/algorithmprovider/defaults/defaults.go#L65
                                                          Документацию человеческую, насколько я знаю, не написали ещё.
                                                          • 0
                                                            У нас поды без трафика, это демоны которые крутятся все время. Но идея с лейблами годится, тогда контроллер поднимет новые, а уже потом можно из вне прибить старые.

                                                            Да исходники я уже тоже нашел и полез изучать ) Похоже все же надо будет ставить себе Го

                                                            Спасибо за наводку!
                                                            • 0
                                                              Если я правильно понял по коду, то он отталкивается от статических данных, а не от текущей нагрузке на ноду. Это не спасает когда у нас 10 подов на одной ноде жрет ресурсов больше чем 20 на другой. При равной конфигурации. Но в теории можно дописать туда своих алгоритмов ))
                                                              • 0
                                                                Ага. Должно быть легко. Интерфейсы там очень простые :)
                                              • 0
                                                Так же насколько мне известно не решен вопрос изоляции групы контейнеров (неймспейсов).

                                                Все поды живут в одной сети.
                                                • 0
                                                  Это в планах. Предполагается, что можно будет задать ACL, какой под может с каким связываться по сети. Это решит много проблем с безопасностью прямо на уровне сети.
                                                  • 0
                                                    Да в планах там много чего, но мне нужно уже сейчас ))

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