Управление конфигурацией Kubernetes в Kustomize

Развертывание приложений в Kubernetes иногда может бывает процессом довольно трудоемким: во-первых, нужно запустить несколько подов, поддерживаемых развертыванием, с определенной в сервисе доступностью. Во-вторых, для правильной работы всем этим ресурсам требуются файлы YAML.

Более того, приложению может понадобиться взаимодействие с базой данных, управление веб-контентом или настройка логирования. И, конечно, эти параметры могут отличаться в зависимости от среды, в которой вы развертываете свое приложение. Это может привести к разрастанию базы определений YAML, каждое из которых содержит изменения в одну или две строки (из-за чего их бывает трудно отследить).

Kustomize – это открытый инструмент управления конфигурацией, разработанный для устранения подобных проблем. Начиная с версии Kubernetes 1.14, kubectl полностью поддерживает файлы Kustomize и kustomization.

В этом руководстве вы научитесь управлять конфигурацией Kubernetes с помощью Kustomize на примере небольшого приложения. Вы развернете свое приложение в средах разработки и производства с разными конфигурациями. Затем мы покажем, как собрать эти переменные конфигурации в слои, используя базовые ресурсы и overlays Kustomize – и тогда ваш код будет легче читать и, следовательно, легче поддерживать.

Требования

1: Развертывание приложения без Kustomize

Прежде всего мы попробуем развернуть приложение более традиционным способом – без Kustomize. В этом мануале мы используем разрабатываемую версию my-app – условного статического веб-приложения, размещенного на Nginx. Хранить веб-контент мы будем в виде данных в ConfigMap, который монтируется в под внутри развертывания. Для каждого из этих компонентов потребуется отдельный файл YAML, который мы сейчас создадим.

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

Итак, в своем домашнем каталоге создайте новую папку и перейдите в нее:

mkdir ~/my-app && cd ~/my-app

Теперь используйте любой текстовый редактор, чтобы создать и открыть файл по имени configmap.yml:

nano configmap.yml

Добавьте в него следующий код:

---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app
namespace: default
data:
body: >
<html>
<style>
body {
background-color: #222;
}
p {
font-family:"Courier New";
font-size:xx-large;
color:#f22;
text-align:center;
}
</style>
<body>
<p>DEVELOPMENT</p>
</body>
</html>

Эта спецификация создаст новый объект ConfigMap. Мы назвали его my-app и сохранили в нем некоторый веб-контент в формате HTML (внутри data).

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

Теперь создайте и откройте файл по имени deployment.yml:

nano deployment.yml

Вставьте в него следующее:

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
labels:
app: my-app
spec:
replicas: 1
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
spec:
containers:
- name: server
image: nginx:1.17
volumeMounts:
- name: my-app
mountPath: /usr/share/nginx/html
ports:
- containerPort: 80
protocol: TCP
resources:
requests:
cpu: 100m
memory: "128M"
limits:
cpu: 100m
memory: "256M"
env:
- name: LOG_LEVEL
value: "DEBUG"
volumes:
- name: my-app
configMap:
name: my-app
items:
- key: body
path: index.html

Эта спецификация создает новый объект развертывания (Deployment). Здесь мы определили имя и метку my-app, установили количество реплик (1) и указали образ контейнера Nginx версии 1.17, который нужно использовать этому объекту. Кроме того, мы установили порт контейнера (80), определили запросы и ограничения для cpu и памяти, а также уровень логирования (DEBUG).

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

Теперь разверните эти два файла в кластере Kubernetes. Чтобы создать несколько объектов из stdin, передайте команду cat в kubectl:

cat configmap.yml deployment.yml | kubectl apply -f -

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

kubectl get pods -l app=my-app

В результате вы увидите один под с запущенным приложением и значением 1/1 в столбце READY (оно указывает, что у вас есть один контейнер, и он запущен):

NAME                      READY   STATUS    RESTARTS   AGE
my-app-56bbd86cc9-chs75   1/1     Running   0          8s

Итак, наш под работает и поддерживается развертыванием, но мы по-прежнему не можем получить доступ к своему приложению. Прежде всего нужно добавить сервис.

Создайте и откройте третий файл YAML, service.yml:

nano service.yml

Добавьте в файл следующие строки:

---
apiVersion: v1
kind: Service
metadata:
name: my-app
labels:
app: my-app
spec:
type: LoadBalancer
ports:
- name: my-app-http
port: 80
protocol: TCP
targetPort: 80
selector:
app: my-app

Это новый объект – сервис по имени my-app. Если вы установите значение LoadBalancer в строке spec.type, большинство облачных провайдеров выполнит оркестровку балансировщика нагрузки, чтобы сделать ваше приложение доступным в Интернете. Параметр spec.ports использует TCP-порт 80 для любого пода с меткой my-app.

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

Теперь разверните сервис в своем кластере Kubernetes:

kubectl apply -f service.yml

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

kubectl get services -w

В итоге публичный IP-адрес сервиса появится в столбце EXTERNAL-IP (вместо your_external_ip будет уникальный IP-адрес):

NAME         TYPE           CLUSTER-IP       EXTERNAL-IP        PORT(S)       AGE
kubernetes   ClusterIP      10.245.0.1       <none>       443/TCP        7h26m
my-app       LoadBalancer   10.245.186.235   <pending>    80:30303/TCP   65s
my-app      LoadBalancer   10.245.186.235   your_external_ip   80:30303/TCP   2m29s

Скопируйте появившийся IP-адрес, введите его в браузер, и вы увидите версию DEVELOPMENT вашего приложения.

В терминале нажмите CTRL+C, чтобы остановить просмотр сервисов.

На этом этапе мы развернули разрабатываемую версию простого приложения my-app в Kubernetes. В разделах 2 и 3 мы попробуем повторно развернуть эту версию my-app с помощью Kustomize, а затем развернем производственную версию с немного другими конфигурациями. Новый рабочий процесс продемонстрирует, насколько хорошо Kustomize может управлять изменениями конфигурации и насколько сильно он способен упростить разработку.

2: Развертывание приложения с помощью Kustomize

Итак, сейчас мы развернем то же самое приложение, но через Kustomize, а не в стандартной манере Kubernetes.

В настоящее время файловая система проекта выглядит так:

my-app/
├── configmap.yml
├── deployment.yml
└── service.yml

Чтобы сделать это приложение доступным для развертывания с помощью Kustomize, необходимо добавить один файл, kustomization.yml. Давайте создадим его:

nano kustomization.yml

Как минимум, этот файл должен указывать, какими ресурсами следует управлять при запуске команды kubectl с параметром –k (который и направит kubectl на обработку файла kustomization).

Добавьте в файл следующий блок конфигураций:

---
resources:
- configmap.yml
- deployment.yml
- service.yml

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

Перед повторным развертыванием, удалите существующие ресурсы Kubernetes, которые вы создали в разделе 1:

kubectl delete deployment/my-app service/my-app configmap/my-app

А затем разверните их снова, но на этот раз с помощью Kustomize:

kubectl apply -k .

Вместо опции –f, которая позволяет Kubernetes создать ресурсы из файла, мы включаем в команду kubectl опцию –k и каталог (символ точки обозначает текущий каталог). Такая команда обращается к Kustomize и проверяет файл kustomization.yml указанного каталога.

В результате команда создает все три ресурса: ConfigMap, развертывание и сервис. Используйте команду get pods, чтобы проверить свое развертывание:

kubectl get pods -l app=my-app

Вы снова увидите один под с запущенным приложением и 1/1 в столбце READY (что значит, что ваш единственный контейнер успешно запущен).

Снова запустите команду get services. Вы опять увидите свой сервис и его публичный IP-адрес:

kubectl get services -l app=my-app

Итак, вы использовали Kustomize для управления конфигурациями Kubernetes, и все прошло успешно. На следующем этапе мы развернем тестовое приложение в производственной среде с немного другой конфигурацией. Затем мы попробуем использовать Kustomize для управления разными версиями конфигураций.

3: Управление конфигурациями приложения для разных сред с помощью Kustomize

Конфигурационные файлы ресурсов Kubernetes могут начать разрастаться, как только вы станете работать с несколькими типами ресурсов (особенно когда между средами разработки и производства есть небольшие различия). К примеру, вместо одного файла deployment.yml у вас могут появиться файлы deployment-development.yml и deployment-production.yml. Это может коснуться и всех других ресурсов.

Представьте, что может случиться, когда выйдет новая версия Docker-образа Nginx и вы захотите использовать е в своем проекте. Допустим, вы протестировали новую версию в файле deployment-development.yml и хотите внедрить ее – но забываете обновить файл deployment-production.yml. И тогда в среде разработки и в среде производства используются две разные версии Nginx. Подобные недочеты и небольшие ошибки в конфигурации могут быстро сломать приложение.

Kustomize может значительно упростить вашу работу. Давайте вспомним, как теперь выглядит файловая система с конфигурационными файлами Kubernetes и kustomization.yml:

my-app/
├── configmap.yml
├── deployment.yml
├── kustomization.yml
└── service.yml

Предположим, теперь вы готовы развернуть my-app в производственной среде, причем рабочая версия приложения будет отличаться от версии разработки следующим образом:

  • Число реплик в параметре replicas увеличится с 1 до 3.
  • Запросы (requests) ресурсов контейнера увеличатся со 100m ЦП и 128М памяти до 250m и 256М соответственно.
  • ограничения ресурсов контейнера (limits) увеличатся со 100m ЦП и 256М памяти до 1 и 1 ГБ соответственно.
  • переменная среды LOG_LEVEL будет иметь значение не DEBUG, а INFO.
  • Данные ConfigMap изменятся, чтобы показывать немного другой контент.

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

mkdir base

Этот каталог будет содержать вашу «базовую» конфигурацию, или base. В данном примере это будет разрабатываемая версия my-app.

Теперь переместите текущую конфигурацию из my-app/ в этот каталог:

mv configmap.yml deployment.yml service.yml kustomization.yml base/

Затем создайте новый каталог для конфигурации среды производства. Kustomize называет эти конфигурации overlay. Воспринимать overlay следует как слой поверх базовой конфигурации – для функционирования overlay всегда требуется база.

mkdir -p overlays/production

Создайте еще один файл kustomization.yml для определения оверлея среды производства:

nano overlays/production/kustomization.yml

Добавьте следующие конфигурации в файл:

---
bases:
- ../../base
patchesStrategicMerge:
- configmap.yml
- deployment.yml

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

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

А теперь добавьте новые файлы deployment.yml и configmap.yml в каталог overlays/production/.

Сначала создайте новый файл deployment.yml:

nano overlays/production/deployment.yml

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

---
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: default
spec:
replicas: 3
template:
spec:
containers:
- name: server
resources:
requests:
cpu: 250m
memory: "256M"
limits:
cpu: 1
memory: "1G"
env:
- name: LOG_LEVEL
value: "INFO"

Обратите внимание на содержимое этого нового файла deployment.yml. Он включает только поля TypeMeta ресурса, который изменился (в данном случае это развертывание), и еще несколько полей, чтобы перейти во вложенную структуру и указать новое значение (например, для запроса ресурсов контейнера и лимитов).

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

Теперь создайте новый файл configmap.yml для вашего оверлея среды производства:

nano /overlays/production/configmap.yml

Добавьте в файл следующий контент:

---
apiVersion: v1
kind: ConfigMap
metadata:
name: my-app
namespace: default
data:
body: >
<html>
<style>
body {
background-color: #222;
}
p {
font-family:"Courier New";
font-size:xx-large;
color:#22f;
text-align:center;
}
</style>
<body>
<p>PRODUCTION</p>
</body>
</html>

Здесь мы отражаем среду PRODUCTION (а не DEVELOPMENT, как было раньше). Обратите внимание, мы также изменили цвет текста с красного #f22 на синий #22f. Представьте, насколько сложно было бы найти и отследить такие незначительные изменения, если бы мы не использовали инструмент управления конфигурацией Kustomize.

Итак, теперь структура каталогов выглядит так:

my-app/
├── base
│   ├── configmap.yml
│   ├── deployment.yml
│   ├── kustomization.yml
│   └── service.yml
└── overlays
└── production
├── configmap.yml
├── deployment.yml
└── kustomization.yml

Все готово к развертыванию базовой конфигурации. Сначала удалите существующие ресурсы:

kubectl delete deployment/my-app service/my-app configmap/my-app

Разверните базовую конфигурацию в Kubernetes:

kubectl apply -k base/

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

kubectl get pods,services -l app=my-app

Вы увидите свою базовую конфигурацию с версией для разработки (как видно по EXTERNAL-IP сервиса):

NAME                          READY   STATUS    RESTARTS   AGE
pod/my-app-5668b6dc75-rwbtq   1/1     Running   0          21s
NAME             TYPE           CLUSTER-IP       EXTERNAL-IP            PORT(S)        AGE
service/my-app   LoadBalancer   10.245.110.172   your_external_ip   80:31764/TCP   7m43s

Теперь разверните конфигурацию производства:

kubectl apply -k overlays/production/

Проверьте и это развертывание:

kubectl get pods,services -l app=my-app

Вы увидите вашу конфигурацию производства с соответствующей версией, как видно по EXTERNAL-IP сервиса:

NAME                          READY   STATUS    RESTARTS   AGE
pod/my-app-86759677b4-h5ndw   1/1     Running   0          15s
pod/my-app-86759677b4-t2dml   1/1     Running   0          17s
pod/my-app-86759677b4-z56f8   1/1     Running   0          13s
NAME             TYPE           CLUSTER-IP       EXTERNAL-IP            PORT(S)        AGE
service/my-app   LoadBalancer   10.245.110.172   your_external_ip   80:31764/TCP   8m59s

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

kubectl get deployments -l app=my-app -o yaml

Посетите your_external_ip в браузере, чтобы просмотреть рабочую версию сайта.

Теперь вы знаете, как использовать Kustomize для управления конфигурациями приложений. Вернемся к примеру с новым образом Nginx: если вы захотите изменить версию Nginx в проекте, теперь вам нужно будет изменить только deployment.yml в базовой конфигурации – и оверлеи, использующие эту базу, подтянут это изменение через Kustomize. Это значительно упрощает процесс разработки, улучшает читаемость конфигураций и снижает вероятность возникновения ошибок.

Заключение

В этом руководстве мы создали небольшое приложение и развернули его в Kubernetes. После этого мы использовали Kustomize, чтобы упростить управление конфигурацией этого приложения в различных средах. Мы реорганизовали набор почти повторяющих друг друга файлов YAML в многоуровневую модель. Такой подход уменьшит количество ошибок и сделает вашу конфигурацию более читабельной, а значит, и более удобной в поддержке.

За подробной информацией о Kustomize обращайтесь к официальной документации. А на этой странице вы найдете множество примеров.

Tags: ,

Добавить комментарий