Kubernetes для начинающих, быстрый старт с нуля

Эта статья предназначена для быстрого старта в Kubernetes. Цель статьи – максимально просто рассказать о среде Kubernetes так, чтобы вы сразу могли начать работать с ней. Я специально опущу такие вещи, как: пространство имен, задачи, расписания, версионность, репликация, авто-масштабирование, авто определение сервисов, супервайзинг и прочие страшные слова. Оставим их, как бонус, на потом. Мы так же не будем углубляться в архитектуру k8s, это тема для отдельной статьи.

Также мы писали про Обзор k9s — продвинутого терминального интерфейса для Kubernetes.

Что такое Kubernetes?

Для простоты будем представлять его, как менеджер контейнеров.

Контейнер – это изолированная среда для работы какого-то приложения. Чаще всего на данный момент таким контейнером служит Docker. Наверняка вам приходилось запускать приложения в Docker-е. А может и несколько приложений, работающий совместно, используя docker-compose.

Pod

В k8s один экземпляр приложения называется pod (от англ. – стручок). Контейнеры в нем – горошины. Дело в том, что kubernetes позволяет запускать несколько контейнеров в одном pod. Все контейнеры внутри pod, как правило, объединены одной логикой. К примеру pod может называться web, а в нем 2 контейнера: php и db.

Запущенный Docker контейнер – это горошина в стручке

Чаще всего внутри pod вы найдете всего один контейнер – само приложение, и это нормально. Вторыми, третьими контейнерами там как правило бывают служебные (типа сбора метрик, адаптера и пр.).

Внутри pod все контейнеры имеют один TCP/IP адрес и могут обращаться друг с другом через localhost !

Deployment и StatefulSet

У приложения (pod), помимо контейнеров существуют: описание, методанные, имя, метки, количество запущенных копий (replicas). Плюс к pod-у мы можем подключать внешние тома (volumes) для хранения данных, init-контейнеры (которые будут настраивать наше приложение до его запуска), и много чего еще.

Такое описание pod-а, с его дополнительными ресурсами называется Deployment. Описание в k8s происходит на языке разметки yaml.

Вот пример описания Deployment-а:

В данном примере image – имя образа Docker, доступного из репозитария (docker hub или личного). Пример: image: osixia/openldap:1.2.5 или image: localhost:5000/openldap:latest. Еще вы можете увидеть описание экспортируемых TCP портов ports и внешних томов volumeMounts.

ЗАМЕТКА: Другой вариант Deployment называется StatefulSet – это тот же Deployment, только со статичными именами хостов и особым способом разделения ресурсов: каждый экземпляр реплики получает доступ только ко своей директории. Тогда как в Deployment все реплики имеют доступ к общим директориям. StatefulSet используется реже, как правило для балансировки нагрузки и репликации внутри приложения. К примеру его можно встретить в СУБД PostgreSQL с master-slave репликацией, где у каждой реплики – свой набор данных.

Service

Итак, у нас уже есть приложение, описанное со всеми ресурсами в Deployment. Нам надо к нему обратиться из-вне, к примеру открыть страницу нашего web. Для этого служит новый тип ресурсов: Service. Он позволяет описать что и на каком порту предоставлять в использование:

В данном примере мы описали новый сервис (Service) с именем web-page. Работать он будет с помощью селектора (selector), выбирая все, что попадает под его правила. В данном случаи: app: web. То есть наш pod, описанный в Deployment как раз имеет такую метку (label) (см. выше).

В k8s выборки делаются через метки (label).

Выше указан тип сервиса: type: NodePort. Существует несколько способов открыть доступ до приложения:

  • NodePort – этот тип вывешивает TCP/IP порт прямо на ноде, на которой запущен kubernetes. То есть вы можете обратиться по внешнему IP адресу сервера k8s и этот порт (у нас nodePort: 9000) будет перенаправлен в соответствующий pod.
  • ClusterIP – вывешивает сервис на выделенный IP адрес внутри кластера. Как правило он серый. Это самый используемый тип сервиса, так как позволяет экспортировать порты внутри кластера для общения приложений между собой.
  • LoadBalancerIP – выделенный внешний (белый) IP адрес для сервиса. Располагается на балансировщике нагрузок, расположенным перед нодами k8s кластера.

К примеру реверсивный proxy-сервер в вашем кластере может иметь тип LoadBalancerIP и висеть на выделенном IP адресе, обращаясь к другим сервисам, которые имеют тип ClusterIP. Такой proxy-сервер в k8s называется Ingress, о нем будет ниже.

Все! Deployment + Service – нам этого достаточно, чтобы запустить наше приложение в kubernetes!

Принцип работы Kubernetes

Вот упрощенно как будет выглядеть работа приложения в k8s:

Kubernetes для начинающих, быстрый старт с нуля
Kubernetes для начинающих, быстрый старт с нуля

Тут app: web – наше приложение, запущенное в единственном экземпляре. И какое-то другое (app: other) – масштабируемое. У них разные сервисы и разные метки. По этому прокси сервер при обращении к определенному порту (или имени, в случаи если мы используем Ingress) – будет переправлять нас на соответствующее приложение внутри k8s.

Ingress

Ingress – это http прокси сервер k8s, позволяющий обращаться к ресурсам по именам. Вот пример описания ingress-сервиса:

По указанным правилам (имя хоста и путь) – прокси сервер выберет соответствующий сервис: serviceName: web-page, который был описан нами ранее.

ЗАМЕТКА: Тип нашему сервису (Service) web-page, в данном случаи, лучше поставить ClusterIP, убрав директиву nodePort, чтобы не вывешивать его прямо на ноде.

Helm

Все это конечно хорошо, но когда же мы приступим к практике? С чего начать? Я предлагаю сразу в бой! Но для этого нам понадобится шлем (Helm).

Helm
Helm

Чтобы не составлять все эти yaml – файлы с описанием вручную, не искать их по интернету – мы будем использовать готовые шаблоны (templates).

Дело в том, что работать напрямую с yaml-файлами kubernetes не очень удобно. Во-первых их надо много (чтобы описать все возможные ресурсы). Во-вторых, чтобы что-то изменить – надо искать и править эти файлы. Такой подход не приемлем для множественных установок одного и того же приложения, но с разными параметрами (именами, настройками, логинами, паролями и пр.).

Одним из самых популярных инструментов шаблонизации yaml-файлов для k8s на сегодня является Helm.

Вышеприведенный yaml-файл на нем выглядел бы как-то так:

Тут вы видите, что изменяемые данные заменены на переменные:

  • .Values.hostname – переменная из специального values.yaml – файла. Записывается в файле так:
После чего становится доступна, как .Values.hostname. То есть мы вынесли уже статичные данные из yaml-файла и сделали его шаблоном, пригодным для применения с другими данными. Ничего не надо править – только values.yaml .

  • $fullName – какая-то дополнительная переменная. В данном случаи обозначает имя нашего приложения. Для таких вспомогательных переменных служит специальный файл: _helpers.tpl.

Все файлы шаблонов находятся в директории templates. Посмотрите любой удобный для вас пример от сюда: https://github.com/helm/charts/tree/master/stable

Найдите в выбранном вами примере шаблоны описания Deployment (или StatefulSet), Service, Ingress. Как правило они располагаются в соответствующих файлах директории templates: deployment.yamlservices.yaml и т.п.

Установка приложения с Helm сводится к правке values.yaml-файла, или созданию нового my-values.yaml – файла, с нужными вам значениями переменных, а затем использованию клиента helm для установки данного набора шаблонов в k8s:

Данная команда возьмет переменные из вашего my-values.yaml – файла, совместит их с другими переменными values.yaml – файла, идущего в поставке. После чего на их основе сгенерирует конечные yaml-файлы и применит их в k8s.

Полезные команды

  • kubectl get pods – получить все запущенные pod
  • kubectl describe pod <name> – получить детальные описания pod
  • kubectl get services – получить все сервисы
  • kubectl get deployments – получить все Deployment
  • helm list – получить все установленные пакеты приложений (релизы)

Minikube

Для старта работы с k8s вы можете использовать minikube, который позволяет получить окружение kubernetes у вас на компьютере или в виртуальной машине: https://github.com/kubernetes/minikube

источник