Линукс и DevOps Дни
2.22K subscribers
108 photos
8 videos
194 links
Самобытно про разработку, devops, linux, скрипты, тестирование, сисадминство, техдирство, пиэмство и за айтишную жизу.
Download Telegram
Сегодня за девопс, gitlab и как сделать комфортный pipeline с выпадающими списками Variables + Бонусы.

Из коробки, когда ты жмешь кнопку Run Pipeline, тебе нужно руками вбивать нужные Variables, например, чтобы указать окружение, в которое будет раскатан релиз.

Каждый раз вбивать руками Variable ENVIRONMENT=stage / production ну пиздец тяжко и неудобно. А если таких переменных овердохуя, то всё желание пропадает что-то делать.

Хочется чтобы был выпадающий список со всеми параметрами. Накликал мышкой и в продакшен.

Выпадающие списки можно делать не только с окружениями, но и добавить банальные вопросы YES/NO и прочее. А затем в секции rules уже все это разруливать и обрабатывать.

✔️Ниже базовая болванка

Создаем файл .gitlab-ci.yml в корне проекта и добавляем в него:

variables:
ENVIRONMENT:
value: "N/A"
options:
- "N/A"
- "STAGE"
- "PRODUCTION"
description: "Deployment environment"

.stage_server:
&stage_server
WEB_NODE: "xx.xx.xx.xx"
DB_NODE: "xx.xx.xx.xx"

.production_server:
&production_server
WEB_NODE: "xx.xx.xx.xx"
DB_NODE: "xx.xx.xx.xx"

deploy:
tags:
- common-runner
script:
- echo $ENVIRONMENT
- echo "build & deploy here"
rules:
- if: '$ENVIRONMENT == "STAGE"'
variables:
<<: *stage_server
- if: '$ENVIRONMENT == "PRODUCTION"'
variables:
<<: *production_server


В первой секции variables, описываем выпадающий список. Из него будем выбирать мышкой, куда деплоить.

N/A (выбран по умолчанию) добавлено для дураков, которые ничего не выбирают и сразу тыкают Run Pipeline. В таком случае пайплайн зафейлится и ничего не пострадает.

Дальше идут две секции, которые описывают окружения stage и production, там указываем айпишинки и вообще всё, что захотим для каждого окружения. Можно флагов навтыкать и прочего говна.

Ну и основная секция deploy, у меня указан раннер с тэгом common-runner, а потом полезная нагрузка которая будет выполнена.

В секции rules зашита логика. В зависимости от того, какое окружение было выбрано из выпадающего списка, применяются настройки либо от stage, либо от production. Короче инклудится нужное.

Собственно всё. Если нужно добавить еще каких-то выпадающих списков, добавляем в первую секцию всё необходимое, аналогично ENVIRONMENT. Ну и потом в rules все это обрабатываем. Например, так:

- if: '$JOB == "YES" && $ENVIRONMENT == "STAGE"'


В общем всё элементарно. По итогу получаем незамысловатый пайплайн, всё в одном месте и ничего не раскидано по самому gitlab.

Бонусы. Да, если нужен общий пайплайн для нескольких проектов, делаем так:

Создаем репу dev/pipelines, кидаем туда файл .gitlab-ci.yml, настраиваем в нем всё под свои реалии.

Дальше в нужных проектах добавляем файл .gitlab-ci.yml с таким содержимым:

include:
- project: "dev/pipelines"
file: ".gitlab-ci.yml"


Всё, теперь не надо плодить кучу .gitlab-ci.yml с одинаковым содержимым, все инклудится из одного места. Ну и если нужно что-то поменять, меняем один раз и все проекты автоматически это подхватывают.

Максимально попытался упростить и сделать наглядно, а дальше уже включай фантазию и твори.

Хорошего тебе дня, увидимся!

tags: #devops

@ВАSНDАYS | BАSHDАYS.CОM
Со шрамами приходит сила

И снова здрасти. Хуй знает очевидная эта штука для тебя или нет, но я все равно ее подсвечу.

Предположим у тебя есть какой-то проект описанный в docker-compose.yml. Вся эта чача раскатывается через пайплайны gitlab на продакшен.

Из того что я постоянно вижу — После сборки проекта, все собранные файлы копируются на продакшен с помощью rsync, scp или подобных утилит, ну и ранится все это дело через ssh.

Например:

script 
- билд хуилд
- rsync -avz --delete ./ user@$prod:/var/www`
- ssh user@$prod "docker compose up -d"


1. Что-то там собралось
2. Файлы синканулись с продом
3. Запустилось если смогло

Хуита! Всё делается изящнее. Ща покажу.

stage: deploy
image:
name: docker/compose
script:
    - docker-compose -H "ssh://root@$prod" down --remove-orphans
    - docker-compose -H "ssh://root@$prod" pull
    - docker-compose -H "ssh://root@$prod" up -d


Используем мощности docker-compose, не привлекаем никакие rsync, scp и т.п. А сразу нативно запускаем на проде наш docker-compose.yml файл.

Никаких лишних файлов не копируется, никаких утилит, минималистичное. Я примеры сократил, но суть ты поймешь. Не обязательно тащить на прод какие-то ямеэльки.

В штыки не воспринимай, способ с rsync и т.п. вполне годный. Но делюсь, тем, чем пользуюсь сам. У меня телеграм боты так деплоятся.

Изучай. Не отвлекаю! Если хоть одному из вас пригодится, это уже хорошо!

tags: #devops

🔔
Про интересный факап и траблшутинг.

Обратился клиент — у нас mysql реплика не работает. Вернее работает, но отстала всего лишь на 3 месяца.

На вопрос — а хули вы 3 месяца сидели, у вас же мониторинг есть?

Очевидный ответ — да, есть, но оно молчит.

Ладно, полез разбираться. SHOW SLAVE STATUS\G;

А там ошибки брынчат, как хуи в бидоне.

Error 'Cannot delete or update a parent row: a foreign key constraint fails'


Ну это ладно, ошибка и ошибка, тут понятно что делать — НИЧЕГО.

Так как реплика используется чисто аналитиками на потыкать, игнорим эту ошибку через my.cfg. Быстрофикс.

Для продуктовой реплики такое делать - НЕЛЬЗЯ!

Самый важный вопрос — какого хера мониторинг 3 месяца молчал?

Тут уже интереснее. Реплика заведена в prometheus, экспортеры есть, все дела.

Но из графаны сервер пропал, хотя год назад я ее точно там видел.

Думаем… Думаем… Смотрю графану, мониторится поле: replica_seconds_behind

Хм, лезу обратно на реплику, а там сроду нет mysql_exporter. Что же это тогда такое?

Копаем вглубь и видим, что node_exporter мониторит папку /tmp на наличие файликов .prom.

Ага… То есть метрики с mysql реплики собирает какой-то bash скрипт по крону, генерит текстовичок и отдает в prometheus.

Типа такого:

replica_slave_io_running{host="replica"} 1
replica_seconds_behind{host="replica"} 1234567


Да, оно прекрасно работало, до момента пока не вылезла ошибка: Cannot delete or update a parent row

Соответственно текстовый файл replica.prom получился в таком формате:

replica_slave_io_running{host="replica"} 1
replica_seconds_behind{host="replica"} Null


Ну а дальше prometheus такое распарсить не смог (он хочет циферки, а не буковки) и тихонечко вывел эту ноду из графаны и вообще отовсюду. Ну и аллерты в придачу. На что им тригериться если ноды нет нигде?

Прикол в том, что во время возникновения ошибки, поле Seconds_Behind_Master в mysql принимает значение Null, а не продолжает дальше считать на сколько отстала реплика.

А вот и bash скрипт, который собирал метрики:

#!/bin/bash

MAINDIR=/tmp
METRICS=rstatus.prom
HOST="replica"

SLAVE_IO_RUNNING=$(mysql -e 'SHOW SLAVE STATUS \G' | grep 'Slave_IO_Running'| awk '{print $2}')
SLAVE_SECONDS_BEHIND=$(mysql -e 'SHOW SLAVE STATUS \G' | grep 'Seconds_Behind_Master'| awk '{print $2}')

if [[ "$SLAVE_IO_RUNNING" == "Yes" ]]; then
J=1
echo 'replica_slave_io_running{host="'$HOST'"}' $J > $MAINDIR/$METRICS
else
J=0
echo 'replica_slave_io_running{host="'$HOST'"}' $J > $MAINDIR/$METRICS
fi

echo 'replica_seconds_behind{host="'$HOST'"}' $SLAVE_SECONDS_BEHIND >> $MAINDIR/$METRICS


Работа над ошибками проведена, инцидент разобран. Ни одна жопа на ретроспективе пока не пострадала, но возможно дело времени.

Как писать подобные экспортеры я накидывал в этом посте.


И всегда помни — если изобретаешь велосипед, всегда обрабатывай эксепшены!

tags: #devops #debug #bash #monitoring

🔔
Здрасти приехали, пятница!

Частый вопрос который задают ребята с проекта Linux Factory:

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


В gitlab есть встроенная херня, которая находится в Settings → Packages & Registries → Container Registry. Заранее не забудь выбрать нужный проект.

Там есть раздел: Cleanup Policies, в нём нажимаешь кнопку Set cleanup rules иии видишь еще кучу какого-то гавна.

Короче:

Run cleanup — выбираешь как часто запускать зачистку

Keep these tags — теги которые не нужно зачищать

Remove these tags — теги которые будем удалять

Remove tags older than — ну тут ежу понятно

В этих штуках работают регулярные выражения, примеры этих регулярок можешь глянуть тут.

Еще момент, если заполнить Keep these tags, то это даст протекцию тегам и даже если их прописать в Remove these tags имейджы не будут удалены.

Заполняешь, сохраняешь и оно автоматически будет тебе все подчищать.

Дополнительные варианты зачистки:

- удаляешь мышкой в UI самого гитлаба
- удаляешь через API самого гитлаба (например баш скриптом)
- используешь утилиты типа regclient или docker-gc

Такие дела, надеюсь было полезно. Давай, хороших тебе предстоящих выходных и береги себя!

tags: #devops

🔔 ➡️
Еще раз привет. В последнее время многие столкнулись с проблемой при запуске пайплайнов в гитлабе.

Требуется какая-то ебучая Verify my account, квест который не так просто пройти. Но есть способ это обойти, спасибо за наводку Akhmed Gvashev.

Пиздуем в Settings → CI/CD → Runners → Instance runners и отключаем Enable instance runners for this project.

Всё, дело в шляпе. А дальше регистрируешь свои локальные раннеры и запускаешь пайплайны хоть до посинения.

Пользуйтесь!

tags: #devops

🔔 ➡️
Здрасти. Еще один частый вопрос с проекта Linux Factory:

Я собрал докер имейдж, а контейнер вечно в ребуте либо вообще не запускается, чо делать и как отлаживать?


Давай симулируем ситуацию и попробуем что-то с этим сделать.

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

Создаем на хостовой машине пару файлов:

Dockerfile:

FROM nginx:latest
WORKDIR /etc/nginx
COPY ./nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]


nginx.conf

user  nginx;
worker_processes 1;

events {
worker_connections 1024;
}

http {
server {
listen 80;
server_name localhost;

location / {
return 200 'Hello, Docker!'
add_header Content-Type text/plain;
}
}
}


Собираем имейдж:

docker build -t my-nginx .


Ждем, на экране бежит куча всякого непотребства. Это нормально. Ждем…

Проверяем:

docker images


Ага, все ок, выплюнуло что-то вроде:

REPOSITORY   TAG       IMAGE ID       CREATED          SIZE
my-nginx latest b844ef77daa3 33 seconds ago 188MB


Запускаем:

docker run -d -p 80:80 my-nginx


Проверяем:

docker ps


Хуй там плавал. Ничо не стартануло… ошибок нет, куда смотреть?

Если контейнер вообще не запускается, то для начала смотрим логи:

1. Узнаем состояние контейнера:

docker ps -a


Видим хуй с маслом: Exited (1) 4 minutes ago

2. Смотрим логи:

docker logs --follow <id or name>


В <id or name> подставляем айдишник либо имя контейнера:

В логах видим ошибку:

 invalid number of arguments in "return" directive in /etc/nginx/nginx.conf:15


Вот! С ней уже можно работать. Получается мы посмотрели логи, даже для незапущенного контейнера. Пиздуем в nginx конфиг и видим, что в 14й строке проебали точку с запятой.

Дополнительно можно посмотреть коды выхода:

docker inspect <id or name>


Например, если код выхода ExitCode = 137, значит не хватило ресурсов, подкинь памяти и все взлетит. Наверное…

Это основные моменты отладки.

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

docker exec -it <id or name> bash/sh


Подставляешь id/name контейнера и выбираешь шелл, частенько bash и коробки не установлен, поэтому как вариант запускаешь sh.

А для визуализации слоев используем утилиту dive

Установка dive:

DIVE_VERSION=$(curl -sL "https://api.github.com/repos/wagoodman/dive/releases/latest" | grep '"tag_name":' | sed -E 's/.*"v([^"]+)".*/\1/')
curl -OL https://github.com/wagoodman/dive/releases/download/v${DIVE_VERSION}/dive_${DIVE_VERSION}_linux_amd64.deb
sudo apt install ./dive_${DIVE_VERSION}_linux_amd64.deb


Открываем имейдж на анализ:

dive <id or imagename>


Подставляем id или имя — ИМЕЙДЖА (не контейнера)

Смотрим, охуеваем, закрываем.

Еще можно глянуть конкретный файл в контейнере:

docker exec -it <id or name> cat /etc/nginx/nginx.conf


Либо скопировать его себе на локальную машину:

docker cp <id or name>:/etc/nginx/nginx.conf /tmp


Поправить и скопировать обратно в контейнер:

docker cp /tmp/nginx.conf <id or name>:/etc/nginx/nginx.conf


Перезапускаем контейнер с новым конфигом:

Прикол в том, что тебе не нужно билдить новый имейдж, ты делаешь правки прям в контейнере.


docker exec <id or name> nginx -s reload


Такие дела! Если знаешь еще хаки и способы отладки контейнеров/имеджей, пиши в комменты, будет полезно!

tags: #devops #debug #docker

Оказывается не все знают как в гитлабе сделать приватную репу публичной.

➡️ На примере облачного гитлаба:


Пиздуем в ПроектSettingsGeneralVisibility, project features, permissionsProject visibility

Выбираем из выпадающего списка: private, public, internal

Если у тебя облачный гитлаб с группами, читай дальше.

➡️ На примере Self-Hosted:

В отличии от облачного гитлаба, здесь недоступны варианты public, internal. Это многих смущает и вводит в ступор. Если коротко — сгорают жопы!

Открываем проект c репозиторием, вверху слева будет название группы, у меня оно linuxfactory и следом название проекта. Тыкаем на название группы, попадаем примерно на такой урл: https://git.bashdays.ru/linuxfactor

Нажимает три точки справа сверху появляется всплывашка, выбираем → Group Settings.

Находим: Visibility level и выставляем видимость группы public.

Пиздуем опять на страницу проекта с репозиторием → SettingsGeneralVisibility, project features, permissionsProject visibility

И о чудо! Активируются пункты public и internal.

Если чо-то забыл, добавляй в комменты, тема реально муторная и многие на эти грабли частенько наступают. Да чо греха таить я сам прихуел от таких пиздостраданий.

Пользуйтесь!

tags: #devops

🔔 ➡️
Хелоу мая диа френдз! Я повидал дохуя bash скриптов по зачистки старых бекапов, какие-то работают заебись, какие-то создают лишь видимость.

Заебись когда бекапы у тебя лежат на той же машине где ты их делаешь.

Запускаешь по крону команду rm и паре с find и зачищаешь ненужное гавно которое старше определенного времени.

А чо делать когда бекапы «правильно» заливаются в облако s3 по протоколу swift?

Там find с rm уже не прокатит. Можно конечно изгаляться, но я в рот ебал изобретать очередной велосипед.

Для этих целей отлично подходит rclone, кто бы блядь мог подумать.

Работает так:

/usr/bin/rclone --config ~/.config/rclone/rclone.conf \
--log-file /var/log/rclone-trasher.log \
-v delete selectel:backups/1c/ --min-age 3d --rmdirs


Показываем где лежит конфиг, конфиг представляет нечто такое:

[selectel]
type = swift
env_auth = false
user = bashdays
key = fuckyou
auth = https://auth.selcdn.ru/
endpoint_type = internal


Пишем непотребства в лог файл, чтобы потом посмотреть что там в кроне навыполнялось.

Указываем где чистим бекапы, задаем сколько бекапов нам оставить, в примере я оставляю за 3 последних дня. Бекапы у меня в каталогах по датам, добавляю ключик rmdirs.

Вешаем на крон и идем дальше работать пинать хуи.

По моему отличное решение, и даже думать не пришлось.

Пользуйтесь на здоровье!

tags: #devops

🔔 ➡️