Девопсолог | DevOps, GitOps и прочий Ops
272 subscribers
60 photos
5 videos
2 files
91 links
Пишу про docker, k8s, gitops и прочие инфраструктурные штуки

Чат канала: https://t.me/AppliedTryndology
Download Telegram
Упаковываем php приложение в helm chart и деплоим в k8s. Часть 1

Мы базово подготовили кластер к работе и теперь нам не терпится задеплоить туда наш код.
Для этого мы сделаем helm chart в репозитории приложения, настроим там деплой во внутреннее хранилище пакетов gitlab и внесем изменения в инфраструктурный репозиторий кластера, чтобы наш чарт устанавливался и обновлялся в кластере при пуше в гитлаб.
Начнем:

1. Заходим в гитлаб, в репозиторий приложения. Там открываем раздел Settings -> Repository -> Deploy tokens. Создаем три токена: app-example-pull с правом read_registry, helm с правом read_package_registry и helm-push с правом write-package-registry. При создании токенов будут сгенерированы пароли для каждого. Запишите их в надежное хранилище паролей. Далее они нам понадобятся.

2. В репозитории приложения создаем папку .helm. Тут будет лежать наш helm chart. Он состоит из следующих файлов:
2.1. Chart.yaml - здесь лежит описание чарта, его тип, версия чарта и версия приложения. Мы будем в дальнейшем использовать только версию чарта
2.2. values.yaml - здесь хранятся дефолтные настройки чарта. Мы будем переопределять при деплое image, из которого будет деплоится приложение и image tag. Также обратите внимание на параметр ingress.host. По этому адресу будет доступно приложение из браузера.
2.3. .helmignore - думаю понятно для чего этот файл. Взят дефолтный из конструктора чарта (Команда helm create)
2.4. templates/deployment.yaml - здесь описана базовая сущность куба - deployment. В этом файле описывается в скольких репликах запускать приложение, из какого образа, на каком порту контейнер принимает подключения, healthchecks и ограничения по ресурсам, на основе которых куб решает на какую ноду деплоить приложение. Все значения тут - плэйсхолдеры, которые подставляются при установке чарта из values.yaml и переопределенных значений.
2.5. templates/service.yaml - создается также базовая сущность k8s - service. Тут мы говорим кластеру, что данный сервис принимает подключения на 80 порту и перенаправляет трафик на поды (Еще одна базовая сущность куба, по сути стручок с контейнерами; пока у нас в стручке будет один контейнер) приложения на порт 8080. На какие именно поды отправлять трафик задается в секции selector. Тут указываются labels, которые заданы в deployment, чтобы сервис и поды могли друг-друга найти.
2.6. Ну и наконец templates/ingress.yaml - настраиваем ingress так, чтобы трафик приходящий на домен app-example.local перенаправлялся на наш сервис, который в свою очередь зарулит все в нужные контейнеры.

3. Возвращаемся в gitlab и в разделе Settings -> CI/CD -> Variables создаем две переменные HELM_USER со значением helm-push и HELM_PASS с паролем этого Deploy token, его мы создавали на первом шаге. Переменную с паролем помечаем как masked, чтобы в логах pipeline не светилось ее значение.

4. Правим .gitlab-ci.yml. Тут у нас будет три шага:
4.1. Собираем production образ приложения (На самом деле не совсем production, пока мы не переопределям APP_ENV, будем делать это позже, когда подключим БД)
4.2. Пушим в gitlab registry. Тэг ставим по тэгу текущего коммита в сокращенной форме
4.3. Подменяем адрес image и image tag в values.yaml чарта. К сожалению, сам helm при запаковке в архив подменять значения не умеет. Это возможно только при установке, но мы будем ставить чарт автоматом через flux. Далее добавляем helm repo, запаковываем чарт, при этом подменяя последнюю цифру версии на ID текущей Job`ы гитлаба (Это нужно для того, чтобы flux автоматически обновлял приложение в кластере). Ну и пушим архив в гитлаб. На машине с gitlab-runner должен быть установлен helm и плагин cm-push. Плагин устанавливается след. командой helm plugin install https://github.com/chartmuseum/helm-push под юзером gitlab-runner

5. Закидываем изменения в гитлаб, ждем выполнения pipeline. В секции Deploy -> Package registry проверяем наличие helm chart, в секции Deploy -> Container registry должен лежать образ приложения с нужным тэгом.
Упаковываем php приложение в helm chart и деплоим в k8s. Часть 2

6. Осталось настроить только выкатку этого добра через flux.
Тут все практически аналогично установке metallb и ingress-nginx. Смотрим этот коммит.
Из отличий:
6.1. Файл image-pull-secret.yaml - тут мы создаем secret (сущность куба для хранения чувствительных данных) для скачивания образов приложения из gitlab container registry. Тут необходимо в секцию .dockerconfigjson вставить строку, подготовленную след. образом:
6.1.1. Логинимся в registry с помощью команды docker --config deploy login registry.example.com. Используем токен app-example-pull, созданный на первом шаге
6.1.2. Делаем base64 deploy/config.json, получаем искомую строку
6.1.3. Удаляем папку deploy
6.2. В файле hr-app.yaml тоже есть создание секрета. Но тут мы уже напрямую указываем логин helm и пароль для этого токена.

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

7. Пушим в инфраструктурный репозиторий наши изменения, смотрим статус flux get all -A. Как только везде будет Ready = True - переходим к след. шагу.

8. С помощью команды kubectl get ing -n app-example проверяем настроен ли наш ingress для работы с доменом app-example.local. Видим что-то подобное:
NAME                  CLASS   HOSTS               ADDRESS         PORTS   AGE
app-example-ingress nginx app-example.local 192.168.0.200 80 47h


Если все окей добавляем в локальный DNS или /etc/hosts своей машины соответствующую запись. У меня это 192.168.0.200 app-example.local

Открываем браузер и проверяем, что приложуха отвечает по нужному домену. Должна быть надпись Welcome to example application.

Фуф, мы молодцы. В след. посте прикрутим к этому всему добру SSL сертификат, получаемый через letsencrypt. Домен тоже придется сделать настоящий)
👍4
Опрос в догонку. Сложность постов возрастает, объяснить все в маленьком количестве текста становится сложно. Нужны ли видео на ютубе, где все вышеизложенное будет наглядно показано?
Anonymous Poll
52%
Нужны
35%
И текстом норм
13%
Мне все равно
В декабре буду выступать с докладом на PHP Russia 2024!
Расскажу как подготовить своё PHP приложение к работе в облаке.

Если кто-то планирует быть оффлайн - с радостью пообщаюсь.
🎉7👍5🔥5
Шифрованные секреты в инфраструктурном репозитории

Мне не давала покоя мысль о том, что в нашем инфраструктурном git репозитории не должно быть секретов в открытом виде. Все best practice твердят нам это. Я почитал доку и сейчас мы будем делать шифрованные секреты в репозитории, чтобы затем они расшифровывались в кластере и попадали в нужное место. Я выбрал вариант с использованием gpg и утилиты sops.
Приступим:

1. Заходим на мастер машину нашего кластера и создаем там gpg ключ
export KEY_NAME="cluster.yourdomain.com"
export KEY_COMMENT="flux secrets"

gpg --batch --full-generate-key <<EOF
%no-protection
Key-Type: 1
Key-Length: 4096
Subkey-Type: 1
Subkey-Length: 4096
Expire-Date: 0
Name-Comment: ${KEY_COMMENT}
Name-Real: ${KEY_NAME}
EOF

2. Получаем отпечаток нашего ключа
gpg --list-secret-keys "${KEY_NAME}"
Видим следующее:
pub   rsa4096 2024-09-23 [SCEA]
AD02237C200DCF7465E0FA88AF8CB328D6E19757
uid [ultimate] dev flux (flux secrets)
sub rsa4096 2024-09-23 [SEA]

3. Сохраняем его в env переменную export KEY_FP=AD02237C200DCF7465E0FA88AF8CB328D6E19757
4. Экспортируем ключ в кластер
gpg --export-secret-keys --armor "${KEY_FP}" |
sudo kubectl create secret generic sops-gpg \
--namespace=flux-system \
--from-file=sops.asc=/dev/stdin

5. Экспортируем публичную часть ключа и сохраняем его в репозитории в файл cluster/flux-system/.sops.pub.asc
gpg --export --armor "${KEY_FP}" > /home/user/.sops.pub.asc
6. Удаляем ключи с мастер машины кластера. Они тут нам больше не нужны
gpg --delete-secret-and-public-keys "${KEY_FP}"
rm /home/user/.sops.pub.asc
7. Теперь пришло время зашифровать наши секреты и настроить flux так, чтобы он их расшифровывал и в расшифрованном виде сохранял в кластер. Первым делом добавляем в 03-app.yaml следующие строчки:
decryption:
provider: sops
secretRef:
name: sops-gpg

Здесь мы указываем кластеру имя секрета, где хранится секретный ключ gpg, который будет использоваться для расшифровки файлов из репозитория
8. Из файла hr-app.yaml убираем секрет и кладем его в helm-pull-secret.yaml
9. Импортируем публичную часть ключа уже на нашей рабочей машине
gpg --import cluster/flux-system/.sops.pub.asc
10. Ставим утилиту sops. И шифруем наши секреты
cd components/app-example
sops --encrypt --encrypted-regex '^(data|stringData)$' --pgp 'AD02237C200DCF7465E0FA88AF8CB328D6E19757' --in-place helm-pull-secret.yaml
sops --encrypt --encrypted-regex '^(data|stringData)$' --pgp 'AD02237C200DCF7465E0FA88AF8CB328D6E19757' --in-place image-pull-secret.yaml


Получаем зашифрованные версии наших конфигов секретов. helm-pull-secret.yaml и image-pull-secret.yaml
11. Вот и все. Пушим в репо и проверяем статус командой flux get all -A

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

Stay tuned ;)
🔥6
Видео с конференции по безопасности контейнеров и контейнерных сред (БЕКОН)

Пока что адски перегружен и никак не могу продолжить писать следующий пост. Но без контента вас не оставлю :)
Держите офигенные доклады по безопасности с конференции БЕКОН 2024

https://www.youtube.com/watch?v=V7wOfQeghpQ&list=PL80eyh4Ug9W-bg3wco8e9UNpawrQlnkAk
👍4
Идеальный Dockerfile

В очередной раз переосмыслил для себя каким должен быть Dockerfile.
Вовсе не обязательно делать отдельно под локальную разработку и под prod.
Достаточно использовать мультистадийную сборку и локально собирать с одним target, а для прода с другим.
По сути мы наследуем все что собираем для локалки и добавляем слои, которые нужны для прода.
А CMD можно вынести за скобки в docker-compose.yaml, .gitlab-ci.yml и т.д.
👍12
Healthcheck для php-fpm

Я уже несколько лет везде использую roadrunner. Но не так давно пришлось поработать с php-fpm в докере.

Думал как же проверять его здоровье, но оказалось, что уже все придумано. Есть такой вот скрипт - php-fpm-healthcheck.

Использование предельно просто:

healthcheck:
test: [ "CMD", "php-fpm-healthcheck" ]
interval: 5s
timeout: 5s
retries: 5


Чтобы это работало - в php-fpm должен быть включен status и в докер образе должна стоять библиотечка для работы с fcgi. Для Debian ставим libfcgi-bin
👍5🔥3
Symfony + docker. Когда компилировать DI контейнер?

Недавно созванивались с Валентином Удальцовым и обсуждали этот вопрос.
Сначала я компилировал DI контейнер сразу в Dockerfile, что обеспечивало быстрый запуск docker контейнера с приложением из уже подготовленного образа.
Потом вынес этот момент из Dockerfile в запуск приложения, т.е. сначала делаем cache:clear, а потом запускаем roadrunner. Но это замедляет старт docker контейнера.

Когда же лучше это делать?

Если у вас нет специфичных настроек DI, зависящих от переменной APP_ENV или еще каких-то переменных окружения, которые влияют на сборку DI контейнера - можно и нужно компилировать DI контейнер в Dockerfile.

Если такие настройки есть - то компиляцию DI контейнера лучше вынести вне сборки образа и сделать при запуске приложения.

P.S. Когда я это все тестировал - обнаружил любопытный момент. Linux кэширует ENV переменные для запущенного процесса и если мы поменяем переменную в уже запущенном docker контейнере, то в приложении ничего не изменится, так как значение переменной уже закэшировано для процесса, который запускает php скрипты, будь то roadrunner или php-fpm
👍8🔥2
На канале FartTime сегодня стрим по нашей излюбленной тематике!
Forwarded from PHP Fart Time (Pavel Buchnev)
Давненько у нас не было стримов. Сегодня появилось время и я первым делом запланировал стрим, чтобы увидеть своих маленьких друзей! Почти месяц погружался в devops, поднял несколько кластеров k8s и т.д. Короче пока помню все и есть желание вам показать очередной крутой инструмент - terraform. Те кто незнаком, советую приходить.

Ваша жизнь изменится на до и после! :)

🕘 В 20:00 по МСК

https://youtube.com/live/NVHV-Mp-B5k?feature=share

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

Разберем создание инфраструктуры, настройку домена, подключение сервера и автоматизацию всех этих процессов. А также узнаем чем еще можно управлять с помощью terraform.

Подходит для тех, кто хочет не только расширить свой кругозор, но и упростить жизнь, осваивая Infrastructure as Code (IaC) и делая управление инфраструктурой более удобным.

Готовьте вопросы!
👍21🔥1
PHP Russia 2024

Добиваю оставшиеся моменты по подготовке к конференции. До встречи на PHP Russia 2024, кто будет присутствовать оффлайн!

Ну и маленькое объявление:
Чтобы наверстать упущенное - ориентировочно в середине декабря планирую провести стрим. Закрепим уже вышедшие посты про кубер и посмотрим как это все делается вживую. Думаю так материал будет усвоен лучше. Ну и пообщаемся в чате трансляции.

Stay tuned!
👍14🔥74
Production конфигурация php в докере

Доделываю сегодня последний шаблон приложения как дополнение для моего выступления на конференции. Стал проверять один момент и с удивлением обнаружил, что php работает в конфигурации по умолчанию и никакой базовый php.ini для него не загружен. Я думал, что умолчание - production ready конфигурация. Но нет :)

Чтобы переключить php в prod режим нужно сделать следующее:

RUN mv "$PHP_INI_DIR/php.ini-production" "$PHP_INI_DIR/php.ini"


И об этом написано в документации к официальному php образу на docker hub.

Будьте внимательны, всегда читайте доку!
👍6🔥3
Хозяйке на заметку
Forwarded from linkmeup
Небольшое напоминание, что в этом мире есть команда timeout, чтобы ограничивать выполнение команд по времени. Типа, пишешь timeout 30s ping pelmeni и пинговалка будет убита через 30 секунд, а не будет долбиться в хост до скончания времён.

https://www.cyberciti.biz/faq/linux-run-a-command-with-a-time-limit/
4👍3
Вот и прошла PHP Russia 2024! Это было очень круто! Надеюсь в следующем году тоже будет о чем рассказать.

В воскресенье 15 декабря в 18:00 Мск планирую провести стрим по развертыванию куба и накатыванию всех тех штук, что мы уже успели обсудить на канале.
🔥12👍3🎉2
Выбираю платформу(мы) для стрима. Вы можете повлиять на выбор :)
Anonymous Poll
28%
ВК
33%
Telegram
22%
Twitch
44%
Youtube (Скорее всего только для записи)
Завтра стрим!

Как и договаривались - завтра будем проводить стрим. В 18 Мск.
Покажу на практике развертывание dev кластера k8s, покажу все то, что было уже описано в постах здесь, на канале.
В опросе победили две площадки - youtube и telegram. Поэтому будем стримить на них.
Сегодня будет несколько тестовых трансляций, заходить на них не нужно, это просто мои тесты.

Держите ссылочку на ютуб:
https://www.youtube.com/watch?v=dDfWQp3JRqg
🔥9👍4🎉2