Управление конфигурацией Kubernetes в Kustomize
Development | Комментировать запись
Развертывание приложений в Kubernetes иногда может бывает процессом довольно трудоемким: во-первых, нужно запустить несколько подов, поддерживаемых развертыванием, с определенной в сервисе доступностью. Во-вторых, для правильной работы всем этим ресурсам требуются файлы YAML.
Более того, приложению может понадобиться взаимодействие с базой данных, управление веб-контентом или настройка логирования. И, конечно, эти параметры могут отличаться в зависимости от среды, в которой вы развертываете свое приложение. Это может привести к разрастанию базы определений YAML, каждое из которых содержит изменения в одну или две строки (из-за чего их бывает трудно отследить).
Kustomize – это открытый инструмент управления конфигурацией, разработанный для устранения подобных проблем. Начиная с версии Kubernetes 1.14, kubectl полностью поддерживает файлы Kustomize и kustomization.
В этом руководстве вы научитесь управлять конфигурацией Kubernetes с помощью Kustomize на примере небольшого приложения. Вы развернете свое приложение в средах разработки и производства с разными конфигурациями. Затем мы покажем, как собрать эти переменные конфигурации в слои, используя базовые ресурсы и overlays Kustomize – и тогда ваш код будет легче читать и, следовательно, легче поддерживать.
Требования
- Кластер Kubernetes 1.14+ с подключением kubectl по умолчанию.
- Установка kubectl на вашем локальном компьютере. Следуйте руководству по началу работы с Kubernetes.
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: Kubernetes, Kustomize