Это продолжение первой части, которое надеюсь, служит логичным ее продолжением - мы имеем кластер Kubernetes, работаем в отдельном Namespace, умеем запускать небольшое stateless приложение на PHP и знаем, как получить к нему доступ. Что дальше можно сделать? Вероятнее всего, нужно упрощать обновление приложения - так как тяжело каждый раз вручную копировать Deployment в консоль с лишь одной обновленной строкой (в нашем случае это ID коммита), пример из первой части:
image: g3rhard/php-sample-app:467794
Небольшая часть с лайфхаками
Для удобного просмотра состояния объектов в кластере можно использовать k9s:
minikube kubectl -- config view --flatten --minify > cluster-config.txt # kubectl config view --flatten --minify > cluster-config.txt k9s --kubeconfig cluster-config.txt
Проверить, как будет выглядеть наш общий шаблон helm chart (об этом будет чуть ниже):
helm template ./helm-php-sample-app
Итак, приступим.
Часть 2. Упрощаем deploy приложения
Выбор инструмента по упрощению deploy пал на helm, как на достаточно подробно описанный инструмент.
Создаем пустой репо на GitHub, клонируем его себе и создаем пустой шаблон пакета helm:
git clone git@github.com:g3rhard/helm-php-sample-app.git helm create helm-php-sample-app cd helm-php-sample-app
Структура каталога выглядит так:
❯ tree -L 3 -a -I ".git" helm-php-sample-app helm-php-sample-app ├── .helmignore ├── Chart.yaml ├── README.md ├── charts ├── templates │ ├── NOTES.txt │ ├── _helpers.tpl │ ├── deployment.yaml │ ├── hpa.yaml │ ├── ingress.yaml │ ├── service.yaml │ ├── serviceaccount.yaml │ └── tests │ └── test-connection.yaml └── values.yaml 3 directories, 12 files
И отправляем изменения в репо:
git add . git commit -a -m 'first commit' git push origin main
Теперь займемся последовательным переносом тех конфигураций, что описаны в первой части этой заметки:
Для отладки клонируем helm chart на машину с minikube:
git clone https://github.com/g3rhard/helm-php-sample-app
На этой же машине проверить шаблон helm chart можно так:
helm install --dry-run --debug ./helm-php-sample-app --set service.type=NodePort --generate-name
Пробежавшись по конфигурациям, можно заметить, что helm сгенерировал совсем не то, что нам бы хотелось, поэтому обновляем файл values.yaml и правим в нем переменные:
replicaCount: 1 -> replicaCount: 3
repository: nginx -> repository: "g3rhard/php-sample-app"
tag: "" -> tag: "ad2dfb"
serviceAccount::create: false
type: ClusterIP -> type: NodePort
После этого можно проверить, как будет выглядеть наш общий шаблон helm chart:
helm template ./helm-php-sample-app
На вид все ок, а значит отправляем изменения в репо и загружаем данные на наш сервер и пробуем применить:
helm install -n developer php-sample-app ./helm-php-sample-app
Error: rendered manifests contain a resource that already exists. Unable to continue with install: Service "php-sample-app" in namespace "developer" exists and cannot be imported into the current release: invalid ownership metadata; label validation error: missing key "app.kubernetes.io/managed-by": must be set to "Helm"; annotation validation error: missing key "meta.helm.sh/release-name": must be set to "php-sample-app"; annotation validation error: missing key "meta.helm.sh/release-namespace": must be set to "developer"
К сожалению, в шаблоне было много новых и непонятных (пока что) label, поэтому сходу применить изменения не получилось. Но так как это и не было нашей целью, то мы просто удаляем старые отдельные ресурсы, созданные в первой части:
kubectl -n developer delete service php-sample-app
kubectl -n developer delete deployment php-sample-app
kubectl -n developer delete ingress php-sample-app-ingress
И снова попробуем установить наш helm chart:
helm install -n developer php-sample-app ./helm-php-sample-app
В результате видим сообщение:
NAME: php-sample-app
LAST DEPLOYED: Wed Jul 7 19:05:44 2021
NAMESPACE: developer
STATUS: deployed
REVISION: 1
NOTES:
1. Get the application URL by running these commands:
export NODE_PORT=$(kubectl get --namespace developer -o jsonpath="{.spec.ports[0].nodePort}" services php-sample-app)
export NODE_IP=$(kubectl get nodes --namespace developer -o jsonpath="{.items[0].status.addresses[0].address}")
echo http://$NODE_IP:$NODE_PORT
Проверяем установку:
Helm:
helm ls --all -n developer NAME NAMESPACE REVISION UPDATED STATUS CHART APP VERSION php-sample-app developer 1 2021-07-07 19:05:44.009257183 +0000 UTC deployed php-sample-app-0.1.0 1.16.0
Pods:
kubectl -n developer get pods NAME READY STATUS RESTARTS AGE php-sample-app-6555dd88f5-6ttkq 1/1 Running 0 16m php-sample-app-6555dd88f5-6zkx8 1/1 Running 0 16m php-sample-app-6555dd88f5-xjlk4 1/1 Running 0 16m
Deployments:
kubectl -n developer get deployments NAME READY UP-TO-DATE AVAILABLE AGE php-sample-app 3/3 3 3 16m
Service:
kubectl -n developer get service NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE php-sample-app NodePort 10.103.150.105 <none> 80:32200/TCP 16m
И напоследок попробуем обновить наше приложение, все еще вручную, но уже более автоматизированно: Добавляем некоторые изменения в index.php, собираем новый образ и тэг нового образа сохраняем в helm chart, а после обновляем на сервере:
cd helm-php-sample-app
git pull
cd ..
helm upgrade -n developer php-sample-app ./helm-php-sample-app
И видим вывод:
Release "php-sample-app" has been upgraded. Happy Helming!
NAME: php-sample-app
LAST DEPLOYED: Wed Jul 7 19:31:09 2021
NAMESPACE: developer
STATUS: deployed
REVISION: 2
Действительно, есть с чем поздравить. На этом с этой частью можно заканчивать.
После завершения, еще можно было проверить две операции - rollback и delete:
Rollback:
- Возвращаемся на первую версию нашего приложения (helm chart), где 1 - это номер из параметра “REVISION: 1”, который можно найти в листингах выше.
helm rollback -n developer php-sample-app 1
- И возвращаемся на вторую версию нашего приложения (REVISION: 2)
helm rollback -n developer php-sample-app 2
И простой момент - удаление:
helm delete -n developer php-sample-app
release "php-sample-app" uninstalled
That’s all.