Thank you for reading this post, don't forget to subscribe!
1: Развертывание приложения без Kustomize
2: Развертывание приложения с помощью Kustomize
3: Управление конфигурациями приложения для разных сред с помощью Kustomize
Kustomize – это открытый инструмент управления конфигурацией, разработанный для устранения подобных проблем. Начиная с версии Kubernetes 1.14, kubectl полностью поддерживает файлы Kustomize и kustomization.
1: Развертывание приложения без Kustomize
Прежде всего мы попробуем развернуть приложение более традиционным способом – без Kustomize. В этом мануале мы используем разрабатываемую версию my-app – условного статического веб-приложения, размещенного на Nginx. Хранить веб-контент мы будем в виде данных в ConfigMap, который монтируется в под внутри развертывания. Для каждого из этих компонентов потребуется отдельный файл YAML, который мы сейчас создадим.
Сначала создайте новый каталог для своего приложения и всех его конфигурационных файлов. Здесь мы будем запускать все команды этого руководства.
Итак, в своем домашнем каталоге создайте новую папку и перейдите в нее:
mkdir ~/my-app && cd ~/my-app
Теперь используйте любой текстовый редактор, чтобы создать и открыть файл по имени configmap.yml:
nano configmap.yml
Добавьте в него следующий код:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
--- 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
Вставьте в него следующее:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
--- 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 (оно указывает, что у вас есть один контейнер, и он запущен):
1 2 |
NAME READY STATUS RESTARTS AGE my-app-56bbd86cc9-chs75 1/1 Running 0 8s |
Итак, наш под работает и поддерживается развертыванием, но мы по-прежнему не можем получить доступ к своему приложению. Прежде всего нужно добавить сервис.
Создайте и откройте третий файл YAML, service.yml:
nano service.yml
Добавьте в файл следующие строки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
--- 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-адрес):
1 2 3 4 |
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.
В настоящее время файловая система проекта выглядит так:
1 2 3 4 |
my-app/ ├── configmap.yml ├── deployment.yml └── service.yml |
Чтобы сделать это приложение доступным для развертывания с помощью Kustomize, необходимо добавить один файл, kustomization.yml. Давайте создадим его:
nano kustomization.yml
Как минимум, этот файл должен указывать, какими ресурсами следует управлять при запуске команды kubectl с параметром –k (который и направит kubectl на обработку файла kustomization).
Добавьте в файл следующий блок конфигураций:
1 2 3 4 5 |
--- 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:
1 2 3 4 5 |
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
Добавьте следующие конфигурации в файл:
1 2 3 4 5 6 |
--- bases: - ../../base patchesStrategicMerge: - configmap.yml - deployment.yml |
В этом файле будет указана база для нашего будущего оверлея и стратегия, которую Kubernetes будет использовать для изменения ресурсов. В этом примере для обновления ресурсов ConfigMap и Deployment мы используем патч типа StrategicMerge.
Сохраните и закройте файл.
А теперь добавьте новые файлы deployment.yml и configmap.yml в каталог overlays/production/.
Сначала создайте новый файл deployment.yml:
nano overlays/production/deployment.yml
Добавьте в свой файл следующее. Выделенные разделы определяют изменения в конфигурации разработки:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
--- 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
Добавьте в файл следующий контент:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
--- 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.
Итак, теперь структура каталогов выглядит так:
1 2 3 4 5 6 7 8 9 10 11 |
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 сервиса):
1 2 3 4 |
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 сервиса:
1 2 3 4 5 6 |
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. Это значительно упрощает процесс разработки, улучшает читаемость конфигураций и снижает вероятность возникновения ошибок.