Основы работы с Kubernetes

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

В этом мануале вы узнаете, как развернуть под на Kubernetes, настроить его как сервис и масштабировать через контроллер репликации.

Требования

Чтобы выполнить этот мануал, сначала нужно выполнить предыдущее руководство в этой серии Начало работы с Kubernetes.

1: Основные объекты Kubernetes

Kubernetes предоставляет API, который клиенты используют для создания, масштабирования и завершения работы приложений. Каждая операция нацелена на один из объектов, которыми управляет Kubernetes. Эти объекты образуют основные блоки Kubernetes, с помощью которых вы можете управлять контейнерными приложениями.

Ниже приведен краткий обзор ключевых объектов API Kubernetes:

  • Кластеры: пул для вычислений, хранения и сетевых ресурсов.
  • Ноды: хост-машины, работающие в кластере.
  • Пространства имен: логические разделы кластера.
  • Поды: единицы развертывания.
  • Метки и селекторы: пары «ключ-значение» для идентификации и обнаружения сервисов.
  • Сервисы: коллекция подов, принадлежащих одному и тому же приложению.
  • Набор реплик: обеспечивает доступность и масштабируемость.
  • Развертывание: управляет жизненным циклом приложения.

Ноды, которые запускают кластер Kubernetes, также рассматриваются как объекты. Ими можно управлять, как и любыми другими объектами API Kubernetes. Чтобы разрешить логическое разделение приложений, Kubernetes поддерживает пространства имен. Например, организация может логически разбить кластер Kubernetes для запуска разработки, тестирования, промежуточной и производственной среды. Каждая среда может быть помещена в выделенное пространство имен, которое управляется независимо. Kubernetes предоставляет свой API через мастер-ноду.

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

Основной элемент упаковки и развертывания в Kubernetes называется под. Каждый под может содержать один или несколько контейнеров, которыми необходимо управлять вместе. Например, контейнер веб-сервера (Nginx) и контейнер кэша (Redis) могут быть упакованы вместе как под. Kubernetes рассматривает все контейнеры, которые принадлежат тому или иному поду, как логическую единицу. Каждый раз, когда создается новый Pod, вместе с ним создаются все контейнеры, объявленные в его определении. Все контейнеры в Pod имеют одинаковый контекст (IP-адрес, имя хоста и хранилище). Они работают друг с другом посредством межпроцессного взаимодействия (IPC), а не от удаленных вызовов или API REST.

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

Поды в Kubernetes открываются через сервисы. Каждый сервис объявляется внутренней или внешней конечной точкой вместе с информацией о порте и протоколе. Внутренние и внешние потребители (такие как другие поды и клиенты API) используют сервисы Kubernetes для базового взаимодействия. Сервисы поддерживают протоколы TCP и UDP.

Каждый объект в Kubernetes, такой как под или сервис, связан с дополнительными метаданными меток и селекторов. Метки представляют собой пары ключ-значение, прикрепленные к объекту Kubernetes. Эти метки однозначно идентифицируют один или несколько объектов API. Селекторы связывают один объект Kubernetes с другим. Например, селектор, определенный в сервисе, помогает Kubernetes найти все поды с меткой, которая соответствует значению селектора. Такое взаимодействие позволяет динамически открывать объекты. Новые объекты с теми же метками будут мгновенно обнаружены и связаны с соответствующими селекторами. Этот механизм обнаружения сервисов обеспечивает эффективную динамическую конфигурацию.

Одним из преимуществ переключения на контейнеры является быстрое масштабирование. Поскольку контейнеры гораздо легче виртуальных машин, их можно очень быстро масштабировать. Для высокодоступной и масштабируемой настройки вам потребуется развернуть несколько экземпляров приложений и обеспечить работу минимального количества экземпляров этого приложения. Чтобы поддерживать эту конфигурацию контейнеризованных приложений, Kubernetes представил наборы реплик, которые предназначены для запуска одного или нескольких подов. Когда в кластере нужно запустить несколько экземпляров подов, они упаковываются в набор реплик. Kubernetes гарантирует, что количество подов, определенное в наборе реплик, всегда находится в рабочем режиме. Если под прекратит работу из-за проблем с оборудованием или конфигурацией, Kubernetes немедленно запустит другой под.

Объект развертывания представляет собой комбинацию подов и наборов реплик. Этот объект привносит PaaS-подобные возможности в приложения Kubernetes. Он позволяет выполнять скользящее обновление существующего развертывания с минимальным временем простоя. Это также позволяет выполнять канареечное развертывание и развертывание blue/green. Объекты развертывания управляют жизненным циклом (ALM) контейнерных приложений.

2: Ноды и пространства имен Kubernetes

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

kubectl get nodes
NAME                  STATUS    ROLES     AGE       VERSION
spc3c97hei-master-1   Ready     master    10m       v1.8.7
spc3c97hei-worker-1   Ready     <none>    4m        v1.8.7
spc3c97hei-worker-2   Ready     <none>    4m        v1.8.7
kubectl get namespaces
NAME                STATUS    AGE
default             Active    11m
kube-public         Active    11m
kube-system         Active    11m
stackpoint-system   Active    4m

Если пространство имен не указано, kubectl выбирает пространство имен по умолчанию.

Теперь нужно запустить приложение.

3: Создание и развертывание пода

Объекты Kubernetes объявляются в файлах YAML и передаются в Kubernetes через CLI kubectl. Давайте определим под и развернем его.

Создайте новый файл YAML:

nano Simple-Pod.yaml

Добавьте следующий код, который определяет под с одним контейнером на основе веб-сервера Nginx. Он отображается на порту 80 по протоколу TCP. Обратите внимание, что определение содержит метки name и env. Эти метки нужны для идентификации и настройки определенных подов.

apiVersion: "v1"
kind: Pod
metadata:
name: web-pod
labels:
name: web
env: dev
spec:
containers:
- name: myweb
image: nginx
ports:
- containerPort: 80
name: http
protocol: TCP

Запустите следующую команду, чтобы создать под.

kubectl create -f Simple-Pod.yml
pod "web-pod" created

Убедитесь, что под создан:

kubectl get pods
NAME      READY     STATUS    RESTARTS   AGE
web-pod   1/1       Running   0          2m

На следующем этапе нужно сделать этот Pod доступным в интернете.

4: Открытие пода через сервис

Сервисы позволяют открывать внешний или внутренний доступ к подам. Попробуйте определить сервис, который откроет публичный доступ к поду Nginx. Открыть Nginx нужно через NodePort, схему, которая делает под доступным по произвольному порту, открытому на каждой ноде кластера.

Создайте файл Simple-Service.yaml и добавьте в него такой код для определения сервиса Nginx.

apiVersion: v1
kind: Service
metadata:
name: web-svc
labels:
name: web
env: dev
spec:
selector:
name: web
type: NodePort
ports:
- port: 80
name: http
targetPort: 80
protocol: TCP

Сервис обнаруживает все поды в одном пространстве имен, которые соответствуют метке name: web. Селектор файла YAML явно определяет эту ассоциацию.

Этот файл также определяет, что сервис относится к типу NodePort.

Затем используйте kubectl, чтобы отправить его в кластер.

kubectl create -f Simple-Service.yml

Вы увидите такой вывод:

service "web-svc" created

Давайте получим порт, на котором доступен под.

kubectl get services
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)        AGE
kubernetes   ClusterIP   10.3.0.1     <none>        443/TCP        28m
web-svc      NodePort    10.3.0.143   <none>        80:32097/TCP   38s

В этом выходе можно увидеть, что сервис доступен по порту 32097. Попробуйте подключиться к одной из рабочих нод.

Используйте консоль для получения IP-адреса ноды.

Используйте команду curl, чтобы отправить HTTP-запрос одной из нод по порту 31930.

curl http://your_worker_1_ip_address:32097

В результате вы увидите домашнюю страницу Nginx по умолчанию:

<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
...
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>
<p><em>Thank you for using nginx.</em></p>
</body>
</html>

Вы определили под и сервис. Теперь попробуйте выполнить масштабирование с помощью наборов реплик.

5: Масштабирование подов через набор реплик

Набор реплик гарантирует, что в кластере будет работать хотя бы минимальное количество подов. Удалите текущий под и создайте три пода через набор реплик.

Сначала удалите существующий под.

kubectl delete pod web-pod
pod "web-pod" deleted

Теперь создайте новый набор реплик. Определение набора реплик идентично определению пода. Ключевое отличие состоит в том, что набор реплик содержит элемент replica, который определяет количество подов, которые нужно запустить. Как и под, он также содержит метки, которые помогают в обнаружении сервисов.

Создайте файл Simple-RS.yml и добавьте этот код:

apiVersion: apps/v1beta2
kind: ReplicaSet
metadata:
name: web-rs
labels:
name: web
env: dev
spec:
replicas: 3
selector:
matchLabels:
name: web
template:
metadata:
labels:
name: web
env: dev
spec:
containers:
- name: myweb
image: nginx
ports:
- containerPort: 80
name: http
protocol: TCP

Сохраните и закройте файл.

Затем создайте набор реплик:

kubectl create -f Simple-RS.yml
replicaset "web-rs" created

Проверьте количество подов.

kubectl get pods
NAME           READY     STATUS    RESTARTS   AGE
web-rs-htb58   1/1       Running   0          38s
web-rs-khtld   1/1       Running   0          38s
web-rs-p5lzg   1/1       Running   0          38s

При обращении к сервису через NodePort запрос будет отправлен на один из подов, управляемых набором реплик.

Давайте проверим функциональность набора реплик, удалив один из подов, и посмотрим, что произойдет:

kubectl delete pod web-rs-p5lzg
pod "web-rs-p5lzg" deleted

Снова посмотрите на поды:

NAME           READY     STATUS              RESTARTS   AGE
web-rs-htb58   1/1       Running             0          2m
web-rs-khtld   1/1       Running             0          2m
web-rs-fqh2f   0/1       ContainerCreating   0          2s
web-rs-p5lzg   1/1       Running             0          2m
web-rs-p5lzg   0/1       Terminating         0          2m

Как только вы удалили один под, Kubernetes сразу создал другой под на его замену.

6: Развертывание

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

Удалите существующий набор реплик, прежде чем создать развертывание (это удалит и связанный с ним под):

kubectl delete rs web-rs
replicaset "web-rs" deleted

Теперь определите новое развертывание. Создайте файл Simple-Deployment.yaml и добавьте следующий код:

apiVersion: apps/v1beta2
kind: Deployment
metadata:
name: web-dep
labels:
name: web
env: dev
spec:
replicas: 3
selector:
matchLabels:
name: web
template:
metadata:
labels:
name: web
spec:
containers:
- name: myweb
image: nginx
ports:
- containerPort: 80

Создайте развертывание и проверьте его:

kubectl create -f Simple-Deployment.yml
deployment "web-dep" created

Просмотрите развертывание:

kubectl get deployments
NAME      DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
web-dep   3         3         3            3           1m

Поскольку в результате развертывания создаются поды, три пода будут выполняться в соответствии с объявлением реплики в файле YAML.

kubectl get pods
NAME                       READY     STATUS    RESTARTS   AGE
web-dep-8594f5c765-5wmrb   1/1       Running   0          2m
web-dep-8594f5c765-6cbsr   1/1       Running   0          2m
web-dep-8594f5c765-sczf8   1/1       Running   0          2m

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

Очистите ресурсы, удалив развертывание и сервис.

kubectl delete deployment web-dep
deployment "web-dep" deleted
kubectl delete service web-svc
service "web-svc" deleted

Больше информации о развертывании вы найдете в документации Kubernetes.

Заключение

В этом мануале вы ознакомились с основными объектами Kubernetes при развертывании веб-сервера Nginx с использованием подов, сервиса, набора реплик и развертывания.

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

Tags: