Архитектура сервиса Kubernetes
Kubernetes aaS в Платформе включает:
- Интерфейс управления для создания кластера, его масштабирования и настройки.
- Горизонтальное масштабирование узлов кластера в большую или меньшую сторону, которое выполняется автоматически.
- Возможность остановки и запуска кластера целиком.
- Поддержка создания Node Pools (пулов ВМ разных размеров). Масштабировать группы можно независимо.
- Persistent Volumes интегрированы с системой хранения OpenStack.
- Поддерживается Cluster Policy: Local, которая позволяет получать реальные IP-адреса пользователей внутри кластеров.
- Создание и масштабирование кластеров Kubernetes с помощью UI или API Платформы, управление сущностями через Kubernetes Dashboard и kubectl.
- Плавное обновление (rolling update) без простоя как для минорных, так и для мажорных версий.
Самый нижний слой — типовые физические серверы (compute nodes). Сейчас их несколько тысяч, они используются под вычисления и хранение. Для хранения мы предоставляем файловые и блочные хранилища на базе Ceph и S3-совместимые объектные хранилища. Серверы распределены по дата-центрам, между которыми проложена сеть 40 Gbps.
Поверх уровня серверов работает OpenStack, который обеспечивает виртуализацию для пользовательских окружений. Поверх ВМ, сетей и балансировщиков работают PaaS-решения: Kubernetes, БД, хранилище данных, Hadoop, Spark и другие (см. рисунок 1).
- Операционная система — CentOS.
- Сеть — модуль Neutron.
- Ingress Controller — Nginx.
- Мониторинг — Kubernetes Dashboard.
Kubernetes в Платформе может быть развернут в формате Multi Master, при этом каждая пользовательская группа нод уже находится в конкретной зоне доступности. Геораспределение гарантируется созданием виртуальных машин по принципу Soft Anti Affinity, когда машины по возможности запускаются на разных гипервизорах (см. рисунок 2).
В Multi Master etcd работает в кластерном режиме. Под каждый etcd выделен отдельный SSD-диск, что обеспечивает небольшое время ожидания (latency) и быструю работу API-сервера, так как в etcd находится служебная информация о всех ресурсах кластера Kubernetes.
Для доступа извне используется балансировщик нагрузки API сервера Kubernetes, который имеет внешний IP-адрес. При этом все ноды — и мастера, и миньоны — находятся в приватной сети и не имеют публичных адресов.
Способы доступа к сервисам внутри кластера перечислены в официальной документации Kubernetes. Подробности реализации в Платформе:
NodePortоткрывает публичный порт на узле. В целях безопасности по умолчанию публичные IP-адреса не назначены на мастера и миньоны, кластеры создаются без «белых» IP-адресов. Для назначения внешнего IP-адреса см. раздел Привязка IP-адреса к инстансу.LoadBalancer(см. риcунок рисунок 3). Платформа предоставляет Load Balancer как сервис и может сама создавать балансировщики. На Платформе балансировщики нагрузки поднимаются сразу в отказоустойчивом режимеactive-standby. Когда поднимается основной балансировщик (на HAProxy), у него всегда имеется «спящий балансер» (standby). Между ними настроен VRRP. Если основной балансировщик отказывает, весь трафик переключается на standby, при этом IP-адрес не меняется.
В настройке балансировки для Kubernetes помогает наш Cloud Provider. Нужно создать манифест, в котором пользователь указывает тип манифеста «сервис» и тип сервиса «Load Balancer» (см. рисунок 3). После применения этого манифеста Cloud Provider обращается к OpenStack API, создаёт балансировщик и внешний IP-адрес, если это необходимо. Если внешний адрес не нужен, нужно поставить аннотацию, что требуется внутренний балансировщик, и можно пускать трафик на кластер, не открывая публичный IP-адрес на каждой ноде.
Ingress Controller интегрирован с балансировщиком OpenStack, то есть в декларации сервиса конкретного Ingress Controller указан тип «Load Balancer». Для кластера создаётся один балансировщик, по которому Ingress Controller работает и распределяет трафик по сервисам. Ingress Controller балансирует по DNS-именам.
Схема работы Ingress представлена на рисунке 5.
Для некоторых клиентов важно, чтобы в Pod было видно IP-адреса клиентов, получающих доступ в кластер. При балансировке теряются заголовки IP-пакетов: приложение не получает реальный IP-адрес клиента. Балансировщик OpenStack ещё видит заголовок X-Forwarded-For, но Ingress Controller и Pod его уже не получают. Это не позволяет настроить доступ пользователей по White Lists, не работают сервисы типа GeoIP или anti-DDoS, которым нужно видеть реальные IP-адреса клиентов.
Если разворачивать Kubernetes локально или в облаке просто на виртуальных машинах, то по умолчанию в нем нет нормальной работы с постоянными дисками. Можно использовать Host Path, Local volume (no-provisioner), либо прямо в кластере Kubernetes разворачивать экзотические программно-определяемые системы хранения типа Linstor или OpenEBS.
При самостоятельном подключении блочных устройств к кластеру могут возникнуть проблемы: CSI драйверы не идеальны для многих типов хранилищ, и автоматическое перемонтирование может не произойти. При отключении Pod блочное устройство переподключается к новому Pod автоматически.
В Платформе используется CEPH, который работает через OpenStack. OpenStack предоставляет специальные модули, абстрагирующие Kubernetes (или любые инстансы), на конкретных драйверах — OpenStack Cinder.
Платформа имеет несколько storage-классов, которые работают в Kubernetes: SSD Ceph, HDD Ceph (см. рисунок 6). Существует storage-класс, отвечающий за блочные диски: фактически это дисковые шкафы с SSD, которые подключаются к хост-машинам по iSCSI.
Если приложение не имеет микросервисную архитектуру, рекомендуется использовать хранилища NFS. В Платформе имеется аналог сервиса EFS от Amazon — файловое хранилище с NFS-протоколом, доступное как сервис. Файловое хранилище подойдёт для legacy-приложений, которые переводятся в Kubernetes.
В Платформе имеются локальные SSD. Сложно гарантировать их доступность и переезд данных, так как они доступны только с физических серверов, к которым подключены.
OpenStack Cinder отвечает за работу с файловыми хранилищами. OpenStack Cinder подключается к каждому узлу Kubernetes и обеспечивает возможность переезда хранилища в случае падения узла. Если повышается нагрузка чтения/записи, и Kubernetes решает перевозить неважные Pod на другие узлы, OpenStack Cinder автоматически переводит монтирование этого диска к другим узлам Kubernetes (см. рисунок 7).
Можно использовать storage-класс, написав в манифесте декларацию PersistentVolumeClaim. Например, Cloud Provider выделит новый Persistent Volume размером 30 ГБ в заданной зоне доступности, с типом диска SSD, подключит его к узлу и подключит к Pod (см. рисунок 8). Также он будет следить, чтобы этот диск переезжал между узлами в случае переезда Pod.
В Платформе имеется Cluster Autoscaler, который выполняет горизонтальное масштабирование при возрастании или уменьшении нагрузки. Масштабирование выполняется автоматически — до 100 узлов и обратно в течение нескольких минут.
Cluster Autoscaler лучше настраивать совместно с Horizontal Pod Autoscaler. Различие использования двух вариантов Autoscaler:
- Cluster Autoscaler позволяет расширять выделенные для кластера ресурсы. Он может автоматически арендовать дополнительные ресурсы или сократить их использование через Cloud Provider.
- Horizontal Pod Autoscaler позволяет расширять ресурсы Pod в рамках существующих выделенных ресурсов кластера, чтобы оптимально их использовать.
Возможна интеграция со стандартными инструментами Kubernetes:
- Хранение и обработка serverless-функций в контейнерах: OpenFaaS, OpenWhisk, Kubeless.
- Инструменты Service Mesh: Istio, Consul, Linkerd.
- Мониторинг, аналитика, логирование: Fluentd, Jaeger, OpenTracing.
- CI/CD: Gitlab, CircleCI, Travis CI.
- IaC (описание приложений): Helm.
- Kubernetes использует аутентификацию по сертификатам.
- Систему безопасности кластеров можно интегрировать с LDAP/Active Directory для аутентификации пользователей. При этом ролевую модель безопасности в Kubernetes можно настроить на проверку прав доступа на основе принадлежности пользователя к группам в LDAP-каталоге.
- Для сетевой безопасности можно применять Calico Network Policy.