Service kubernetes что это
Kubernetes как сервис — изучение рынка
Привет, Хабр! Как и многие другие, в прошлом году мне пришлось внезапно мигрировать из тесного привычного офиса к себе домой. Я и раньше работал из дома, когда была такая нужда. Но чтобы несколько месяцев подряд — такое со мной случилось впервые. Появилось свободное время, которое я сначала не знал, куда девать. Но потом приспособился, начав изучать вещи, до которых раньше не доходили руки.
Я поковырялся в инвестиционных играх на бирже, познакомился с облачным геймингом, а ещё успел почитать о том, что за зверь такой появился, про который из каждого умного утюга говорят — Kubernetes. Начав с блога Фланта, я убедился, что конкретно мне и конкретно сейчас эта штука не нужна, но выглядит она интересно.
Почитал, одобрил и забыл, да вот только буржуйский Facebook про меня забывать не хотел. И где-то с неделю показывал мне рекламу с самыми наивыгодными предложениями этого самого кубернетиса. В результате я в очередной раз продемонстрировал моральную слабость и решил лично познакомиться с этим зверем.
Главное, что я понял, так это что если вы не слышали про Kubernetes и не понимаете, как его использовать в вашей работе, то в 99% случаев он вам и не нужен. Но сама идея сокращения цикла разработки за счёт быстрой доставки пользователю и возможности тестировать версии приложений на узких сегментах аудитории прекрасна. Посмотрел, что получилось, после чего можно распространить версию приложения на всех пользователей или немедленно её откатить.
Но продолжу тему знакомства с этой модной платформой управления контейнерами. Я решил не ограничивать себя одной компанией, наиболее часто мозолившей глаз в Facebook. А выбрать несколько более-менее крупных фирм, у которых есть толковое предложение.
Как выбирал
Вы удивитесь, но поиском. Погуглил «Kubernetes в облаке», пролистал пару страниц. Так и нашёл семь компаний, которые наиболее активно продвигают эту услугу: Mail.ru Cloud Solutions, Cloud4Y, CloudMTS, Yandex.Cloud, КРОК, DataLine, Selectel.
Было бы круто воспользоваться сервисом подбора провайдеров, где можно указать фильтры по ценам, возможностям и прочему. Но увы, я такого сервиса не нашёл, так что делал всё ручками. И если кого шибко важного и крупного не указал, так это не по причине моей зловредности, а потому что реклама у них слабенькая. Ну, и или страницы в поиске глубоко находятся. В общем, кого нет в списке, того я не нашёл. Прошу понять, простить и не гнобить.
Про субъективность
Это абсолютно необъективная статья. Было просто интересно, что это за зверь, какой сервис выглядит удобнее и надёжнее остальных, какой проще и понятнее именно для меня. Так что учитывайте, что мой опыт — это всего лишь мой опыт. У вас могут быть другие предпочтения и знания. Рассматривайте данный текст просто как информацию, абстрактное общее сравнение, а не прямое руководство к действию.
Ещё момент: я собирал информацию, которая есть в открытом доступе, стараясь не задалбывать менеджеров глупыми частыми вопросами по почте и телефону. Мне было неловко звонить и расспрашивать, если покупать всё равно не планирую. Тратить чужое время из-за неуёмного моего любопытства было как-то стыдно. Ну захотелось мне проверить, будет ли работать их сервис, нравится ли он мне как пользователю. Были некоторые моменты, которые я узнавал по телефону и почте, но в основном все данные брал из документации и маркетинговых материалов.
Здесь возникли первые сложности. Я старался звонить по-минимуму, но тот же Яндекс без звонка хоть что-то сообщать отказывался. Остальные без проблем написали о том, что они предлагают и как всё это работает. Ну и ладно, подумал я. Информации в свободном доступе тоже хватает. Вернусь позднее и пообщаюсь, раз они такие буки. Или не пообщаюсь, если к тому времени уже натестируюсь по самый докер. Это была зима 2020, и у меня было много свободного времени.
Знакомство
Звонить и писать сразу всем компаниям — гиблое дело, особенно если не готов покупать, а хочешь лишь проверить, как оно работает. Поэтому я потихоньку запрашивал тестовый доступ у каждой компании по очереди. Быстрее всех ответили Selectel, Cloud4Y и MCS, а вот Крок и DataLine оказались не столь быстрыми. Мне даже пришлось несколько раз ментально их пнуть напоминать о себе, чтобы получить какой-то ответ.
И уже на этом этапе круг подопытных кроликов провайдеров сузился. DataLine вообще никак не захотел со мной общаться. Письма ушли в молоко. «Ну и ладно», — подумал я. «И нечего нас дёргать со всякими глупостями», — подумал неизвестный мне менеджер DataLine. КРОК вежливо извинился и сообщил, что мелочь вроде меня им не интересна. Неприятно, но честно. Спасибо за это. Лучше честный отказ, чем игнор или затягивание времени.
Отмечу, что прямо-таки агрессивных продаж не наблюдалось. Понятно, что я не самая крупная рыбка, которая водится в облачном море. Но всё же. Порадовало, что мне не впаривают, а предлагают. Убеждают. Правда, почти все компании сочли своим долгом сделать меня подписчиком полезных корпоративных рассылок. Но к этому я был готов.
Чуть забегая вперёд скажу, что поскольку компаний стало меньше, а я вошёл во вкус, то в процессе тестирования сервисов Kubernetes вспомнил и про Яндекс. «А не позвонить ли мне им?», подумалось мне. Как оказалось, не зря — у этих ребят оказалось не самое плохое решение из тех, что мне удалось посмотреть.
Тестирование
Теперь давайте посмотрим, чего я натестировал.
Понимание сети Kubernetes: сервисы
В первом посте этой серии я рассмотрел, как Kubernetes использует комбинацию виртуальных сетевых устройств и правил маршрутизации. Если отправитель знает IP-адрес пода, комбинация разрешает обмен информацией между подами, запускающимися на разных кластерах. Если вы не знаете, как поды обмениваются информацией, стоит прочитать об этом, перед тем как продолжить чтение статьи.
Сеть подов в кластере – аккуратный материал, но сам по себе он недостаточен для создания долгосрочных систем, поскольку поды в Kubernetes эфемерны. В качестве конечной точки можно использовать IP-адрес пода, но нет гарантии, что при следующем воссоздании пода адрес останется прежним. Его смена может произойти по любой причине.
Вероятно, вы знаете, что это старая проблема, и у нее есть стандартное решение: направить трафик через обратный прокси-сервер/балансировщик нагрузки. Клиенты подключаются к прокси, а прокси отвечает за ведение списка здоровых серверов для пересылки запросов.
Существует несколько требований к прокси-серверу:
Сервисы
В первом посте я показал гипотетический кластер с двумя серверными подами и описал, как они могут общаться через узлы. Я хочу привести пример, чтобы описать, как сервис Kubernetes позволяет балансировать нагрузку на множестве серверных подов, позволяя клиентским модулям работать независимо и долговременно. Чтобы создать серверные поды, можно использовать такой deployment :
Этот deployment создает два очень простых HTTP-сервера, отвечающих на порт 8080 с именем хоста, с которым они работают. После создания развертывания с использованием приложения kubectl мы можем видеть, что поды запущены в кластере, и узнать их сетевые адреса:
Мы можем продемонстрировать, что сеть пода работает, создавая простой клиентский под для выполнения запроса, а затем просматривая вывод.
После того как под будет создан, будет запущена команда до завершения, под войдет в «завершенное» состояние, и результат можно будет получить с помощью kubectl logs :
В этом примере не видно, на каком узле был создан клиентский под. Но независимо от размещения в кластере он сможет достичь серверного пода и получить ответ через сеть пода. Однако, если серверный под должен был умереть и перезапуститься или он перенесен на другой узел, его IP-адрес почти наверняка изменится, и клиент сломается. Мы избегаем этого, создавая сервис.
Сервис – тип ресурса Kubernetes, который заставляет прокси настраиваться для пересылки запросов на набор контейнеров. Набор контейнеров, которые будут получать трафик, определяется селектором соответствующим присвоенным при создании контейнеров меткам. После создания сервиса мы видим, что ему был присвоен IP-адрес, и он будет принимать запросы на порт 80.
Запросы могут быть отправлены непосредственно на IP-адрес сервиса, но было бы лучше использовать имя хоста, которое разрешает IP-адрес. К счастью, Kubernetes предоставляет внутренний DNS-кластер, который разрешает имя сервиса. Мы можем использовать его с небольшим изменением на клиентский под:
После того как этот под завершится, вывод покажет, что сервис перенаправил запрос на один из серверных подов.
Вы можете продолжить запуск клиентского пода и увидите ответы от обоих серверных подов, каждый из которых получит примерно 50% запросов. Если ваша цель – понять принцип работы сервиса, хорошее место для старта – IP-адрес, который был назначен нашей службе.
Сеть сервисов
IP-адрес, который был назначен сервисом тестирования, представляет адрес в сети. Обратите внимание: сеть не совпадает с той, на которой установлены контейнеры.
Это не то же самое, что и частная сеть с узлами. В первом посте я отметил, что диапазон сетевых адресов пода через kubectl не предоставляется, поэтому для получения этого свойства кластера нужно использовать команду поставщика. То же относится и к диапазону сетевых адресов сервиса. Если вы работаете с Google Container Engine, можете сделать это:
Сеть, заданная адресным пространством, называется сервисной. Каждому сервису, который имеет тип ClusterIP”в этой сети будет назначен IP-адрес. Есть и другие типы сервисов, о которых я расскажу в следующем посте про ingress. ClusterIP используется по умолчанию, и это означает, что «сервису будет назначен IP-адрес, доступный из любого пода в кластере». Тип сервиса можно узнать, запустив kubectl describe services с именем сервиса.
Представьте, что команды, выполненные выше, создали следующие поды в тестовом кластере:
Три года назад, когда я начинал работать с Kubernetes, то, что изображено на диаграмме, казалось волшебством. Каким-то образом мои клиенты смогли подключиться к адресу без связанного с ним интерфейса, и эти пакеты выскочили в нужном месте в кластере. Позже я узнал ответ – это часть программного обеспечения под названием kube-proxy.
kube-proxy
В Kubernetes служба – просто ресурс, запись в центральной базе данных, которая показывает, как настроить программное обеспечение. Служба влияет на конфигурацию и поведение нескольких компонентов в кластере, но важно здесь то, что совершает магические действия, – kube-proxy. Многие из вас будут иметь общее представление о том, что этот компонент делает на основе имени. Но есть некоторые особенности kube-proxy, которые делают его отличным от обычного обратного прокси-сервера, такого как haproxy или linkerd.
Общее поведение прокси-сервера заключается в передаче трафика между клиентами и серверами через два открытых соединения. Поскольку все прокси-серверы такого типа работают в пользовательском пространстве, это означает, что пакеты маршрутизируются в пространство пользователя и обратно в пространство ядра при каждом проходе через прокси. Первоначально kube-proxy реализовывался как прокси-сервер пространства пользователя. Прокси-серверу нужен интерфейс как для прослушивания клиентских подключений, так и для подключения к бэкенд-серверам. Единственные доступные на узле интерфейсы – интерфейс ethernet хоста или виртуальные интерфейсы ethernet в сети пода.
Почему бы не использовать адрес в одной из этих сетей? У меня нет глубоких познаний, но в начале работы проекта стало ясно, что это осложнит правила маршрутизации для сетей, предназначенных для удовлетворения потребностей подов и узлов, которые являются эфемерными объектами в кластере. Сервисам явно необходимо собственное, стабильное, не конфликтующее сетевое адресное пространство, и применение системы виртуальных IP-адресов здесь наиболее логично. Однако, как мы уже отмечали, в этой сети нет реальных устройств. Вы можете использовать сеть в правилах маршрутизации, фильтры брандмауэра и т.д., но не сможете прослушивать порт или открывать соединение через интерфейс, который не существует.
Kubernetes обошел это, используя функцию ядра linux, называемую netfilter, и интерфейс пользовательского пространства для него, называемый iptables. В этом посте недостаточно места, чтобы понять, как это работает. Если вы хотите узнать больше, страница netfilter – хорошее место для старта.
tl;dr;: netfilter – механизм обработки пакетов на основе правил. Он работает в пространстве ядра и просматривает каждый пакет в разных точках жизненного цикла. Он сопоставляет пакеты с правилами, и когда находит правило, которое соответствует ему, применяет указанное действие. Среди многих действий, которые он может предпринять, перенаправление пакета в другой пункт назначения. netfilter – это прокси-сервер ядра. Ниже проиллюстрирована роль netfilter, когда kube-proxy работает как прокси-сервер пользователя.
В статье есть еще один поворот. Выше я упомянул, что проксирование на уровне пользовательского пространства является дорогостоящим. Это связано с маршалингом пакетов. В kubernetes 1.2 kube-proxy получил возможность работать в режиме iptables. В этом режиме kube-proxy в большинстве случаев перестает быть прокси-сервером для межкластерных соединений и вместо этого делегирует netfilter работу по обнаружению пакетов, привязанных к IP-адресам сервиса, и перенаправлению их на поды. Теперь все действия происходят в пространстве ядра. В этом режиме задача kube-proxy – поддерживать правила netfilter в актуальном состоянии.
В заключение сравним все вышеописанное с требованиями к надежному прокси, изложенным в начале поста. Является ли прокси-система сервиса долговечной? По умолчанию kube-proxy работает как unitd, поэтому он будет перезагружен, если он не сработает. В Google Container Engine он работает как блок управления, контролируемый daemonset. Это будет значением по умолчанию, возможно, с версией 1.9. В качестве прокси-сервера пользователя kube-proxy по-прежнему представляет собой единственную точку отказа подключения. При запуске в режиме itables система очень долговечна с точки зрения локальных подов, пытающихся соединиться.
Осведомлены ли прокси-сервисы о полезных серверных подах, которые могут обрабатывать запросы? Как упоминалось выше, kube-proxy прослушивает мастер-сервер api для изменений в кластере, который включает в себя изменения в сервисах и конечных точках. Когда он получает обновления, использует iptables для сохранения правил netfilter. Когда создается новый сервис и заполняются его конечные точки, kube-proxy получает уведомление и создает необходимые правила. Аналогично он удаляет правила при удалении сервисов. Проверки работоспособности с конечными точками выполняются с помощью kubelet. Это еще один компонент, который выполняется на каждом узле. Когда найдены нездоровые конечные точки, kubelet уведомляет kube-proxy через сервер api, а правила netfilter редактируются, чтобы удалить эту конечную точку, пока она не станет здоровой снова.
Все это добавляется к высокодоступному кластерному средству для проксирования запросов между контейнерами, позволяя самим контейнерам приходить и уходить, как только меняются потребности кластера. Однако система не лишена своих недостатков. Основной заключается в том, что kube-proxy работает только так, как описано для запросов внутри кластера, т. е. запросов от одного пода к другому. Другой недостаток – следствие того, как работают правила netfilter: для запросов, поступающих извне кластера, правила сбивают исходный IP-адрес. Это стало источником дискуссий, и решения находятся на активном рассмотрении. Более пристально мы рассмотрим оба этих вопроса, когда обсудим ingress в заключительном посте серии.
Основы Kubernetes
В этой публикации я хотел рассказать об интересной, но незаслуженно мало описанной на Хабре, системе управления контейнерами Kubernetes.
Что такое 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% подключаемым.
Нода Kubernetes
При взгляде на архитектуру системы мы можем разбить его на сервисы, которые работают на каждой ноде и сервисы уровня управления кластера. На каждой ноде Kubernetes запускаются сервисы, необходимые для управления нодой со стороны мастера и для запуска приложений. Конечно, на каждой ноде запускается Docker. Docker обеспечивает загрузку образов и запуск контейнеров.
Kubelet
Kubelet управляет pod’ами их контейнерами, образами, разделами, etc.
Kube-Proxy
Также на каждой ноде запускается простой proxy-балансировщик. Этот сервис запускается на каждой ноде и настраивается в Kubernetes API. Kube-Proxy может выполнять простейшее перенаправление потоков TCP и UDP (round robin) между набором бэкендов.
Компоненты управления Kubernetes
Система управления Kubernetes разделена на несколько компонентов. В данный момент все они запускаются на мастер-ноде, но в скором времени это будет изменено для возможности создания отказоустойчивого кластера. Эти компоненты работают вместе, чтобы обеспечить единое представление кластера.
Состояние мастера хранится в экземпляре 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 как наиболее простая для примера и, в то же время, позволяющая продемонстрировать основные параметры настройки кластера.
Для создания тестового кластера будут использованы три машины для создания нод и отдельная машина для проведения удалённой установки. Можно не выделять отдельную машину и производить установку с одной из нод.
Подготовка нод
Требования для запуска:
Установка ПО на ноды
Установку Docker можно произвести по статье в официальных источниках:
Дополнительная настройка Docker после установки не нужна, т.к. будет произведена скриптом установки Kubernetes.
Установка bridge-utils:
Добавление ssh-ключей
Выполняем на машине, с которой будет запущен скрипт установки.
Если ключи ещё не созданы, создаём их:
Копируем ключи на удалённые машины, предварительно убедившись в наличии на них необходимого пользователя, в нашем случае core.
Установка Kubernetes
Далее мы займёмся установкой непосредственно Kubernetes. Для этого в первую очередь скачаем и распакуем последний доступный релиз с GitHub:
Настройка
Для того, чтобы использовать последний, на момент написания статьи, релиз 0.17.0 необходимо заменить:
На этом настройка заканчивается и можно переходить к установке.
Установка
Первым делом необходимо сообщить системе про наш ssh-agent и используемый ssh-ключ для этого выполняем:
В процессе установки скрипт потребует пароль sudo для каждой ноды. По окончанию установки проверит состояние кластера и выведет список нод и адреса Kubernetes api.
Посмотрим, какие ноды и сервисы присутствуют в новом кластере:
Видим список из установленных нод в состоянии Ready и два предустановленных сервиса kubernetes и kubernetes-ro — это прокси для непосредственного доступа к Kubernetes API. Как и к любому сервису Kubernetes к kubernetes и kubernetes-ro можно обратиться непосредственно по IP адресу с любой из нод.
Запуск тестового сервиса
Для запуска сервиса необходимо подготовить docker контейнер, на основе которого будет создан сервис. Дабы не усложнять, в примере будет использован общедоступный контейнер nginx. Обязательными составляющими сервиса являются Replication Controller, обеспечивающий запущенность необходимого набора контейнеров (точнее pod) и service, который определяет, на каких IP адресе и портах будет слушать сервис и правила распределения запросов между pod’ами.
Любой сервис можно запустить 2-я способами: вручную и с помощью конфиг-файла. Рассмотрим оба.
Запуск сервиса вручную
Начнём с создания Replication Controller’а:
Далее создаём service который будет использовать наш Replication Controller как бекенд.
Для http:
Для проверки запущенности можно зайти на любую из нод и выполнить в консоли:
В выводе curl увидим стандартную приветственную страницу nginx. Готово, сервис запущен и доступен.
Запуск сервиса с помощью конфигов
Для этого способа запуска необходимо создать конфиги для Replication Controller’а и service’а. Kubernetes принимает конфиги в форматах yaml и json. Мне ближе yaml поэтому будем использовать его.
Предварительно очистим наш кластер от предыдущего эксперимента:
Был создан Replication Controller с именем nginx и количеством реплик равным 6. Реплики в произвольном порядке запущены на нодах, местоположения каждой pod’ы указано в столбце HOST.
Можно заметить, что при использовании конфига за одним сервисом могут быть закреплены несколько портов.
Применяем конфиг:
Для проверки запущенности можно зайти на любую из нод и выполнить в консоли:
В выводе curl увидим стандартную приветственную страницу nginx.
Заметки на полях
В качестве заключения хочу описать пару важных моментов, о которые уже пришлось запнуться при проектировании системы. Связаны они были с работой kube-proxy, того самого модуля, который позволяет превратить разрозненный набор элементов в сервис.
PORTAL_NET. Сущность сама по себе интересная, предлагаю ознакомиться с тем, как же это реализовано.
Недолгие раскопки привели меня к осознанию простой, но эффективной модели, заглянем в вывод iptables-save:
На этом всё, спасибо за внимание
К сожалению, всю информацию, которую хочется передать, не получается уместить в одну статью.