Initial commit: interview prep repo (resume, legend, stack cases, Kubernetes course)
This commit is contained in:
95
stack/ci-cd/CASE.md
Normal file
95
stack/ci-cd/CASE.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# Кейс: CI/CD (Git, Gitea, GitLab, TeamCity)
|
||||
|
||||
Связь с легендой: [../../legend/LEGEND.md](../../legend/LEGEND.md) — GitLab (ОКБ СУХОЙ, хранение тестовых скриптов), Gitea + TeamCity (АО ТНИИС, хранение Ansible-ролей и CI-конвейер с Molecule).
|
||||
|
||||
## Что нужно реально сделать (домашний стенд)
|
||||
|
||||
Поднять Gitea локально, запушить туда роль Ansible из [../ansible/CASE.md](../ansible/CASE.md), и настроить пайплайн через GitHub Actions (доступная бесплатная альтернатива TeamCity для домашней практики — принцип pipeline/stage/job идентичен, конкретный синтаксис отличается; на собеседовании это стоит явно проговаривать как «дома тренировался на GitHub Actions, на текущей работе — TeamCity, принцип тот же»).
|
||||
|
||||
### 1. Gitea в Docker Compose
|
||||
|
||||
```yaml
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
gitea:
|
||||
image: gitea/gitea:1.22
|
||||
container_name: gitea
|
||||
environment:
|
||||
- GITEA__database__DB_TYPE=sqlite3
|
||||
- GITEA__server__ROOT_URL=http://localhost:3001/
|
||||
ports:
|
||||
- "3001:3000"
|
||||
- "2222:22"
|
||||
volumes:
|
||||
- gitea_data:/data
|
||||
|
||||
volumes:
|
||||
gitea_data:
|
||||
```
|
||||
|
||||
```bash
|
||||
docker compose up -d
|
||||
# зайти на localhost:3001, создать администратора, создать репозиторий "ansible-nginx-role"
|
||||
git remote add gitea http://localhost:3001/<user>/ansible-nginx-role.git
|
||||
git push gitea main
|
||||
```
|
||||
|
||||
### 2. Пайплайн, прогоняющий molecule test на каждый push
|
||||
|
||||
```yaml
|
||||
# .github/workflows/molecule.yml (для GitHub как доступной альтернативы; на реальном месте — эквивалент в TeamCity)
|
||||
name: Molecule Test
|
||||
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: "3.11"
|
||||
- name: Install dependencies
|
||||
run: pip install ansible molecule molecule-plugins[docker] docker
|
||||
- name: Run molecule test
|
||||
run: molecule test
|
||||
```
|
||||
|
||||
Смысл именно в том, чтобы это был реальный прогон уже готовой роли из [../ansible/CASE.md](../ansible/CASE.md): пайплайн скачивает код, ставит зависимости и выполняет тот же `molecule test`, который до этого прогонялся вручную — то есть проверка идемпотентности и корректности роли теперь происходит автоматически при каждом push, без ручного запуска.
|
||||
|
||||
### 3. Модель веток
|
||||
|
||||
```bash
|
||||
git checkout -b feature/add-ssl-support
|
||||
# правки роли
|
||||
git push gitea feature/add-ssl-support
|
||||
# создать Pull Request в Gitea UI: feature/add-ssl-support -> main
|
||||
```
|
||||
|
||||
Protected branch (`main`) в настройках репозитория Gitea — запрет прямого push, обязательное прохождение пайплайна (CI status check) и минимум одного ревью перед merge. Смысл: код не может попасть в основную ветку, минуя автоматическую проверку и код-ревью.
|
||||
|
||||
### 4. Базовые операции Git на практике
|
||||
|
||||
```bash
|
||||
git rebase main # переносит коммиты ветки поверх актуального main, история линейная
|
||||
git merge main # создаёт merge-коммит, сохраняет реальную историю параллельной разработки
|
||||
git cherry-pick <commit-hash> # переносит один конкретный коммит в текущую ветку
|
||||
git bisect start
|
||||
git bisect bad # текущий коммит содержит баг
|
||||
git bisect good <старый-коммит> # этот коммит был рабочим
|
||||
# git автоматически предлагает коммиты между ними для бинарного поиска, где баг появился
|
||||
```
|
||||
|
||||
## Что это даёт в разговоре с интервьюером
|
||||
|
||||
- Реально запушенный в Gitea код и реально прогнанный через CI пайплайн, проверяющий Ansible-роль — а не абстрактное «умею писать YAML».
|
||||
- Понимание разницы rebase/merge не как определения, а с пониманием, когда какой подход уместен (rebase — для чистки локальной истории перед PR, merge — для сохранения факта параллельной разработки).
|
||||
- Практическое понимание protected branches как механизма, а не просто слов.
|
||||
- Умение нарисовать и объяснить типовой pipeline: lint → test/molecule → deploy — то, что реально спрашивали на нескольких собеседованиях (см. [../../interview/real-interviews.md](../../interview/real-interviews.md)).
|
||||
|
||||
## Как это ложится в легенду
|
||||
|
||||
Git-хостинги и CI — сквозная инфраструктура вокруг уже проработанного Ansible-кейса. Здесь не отдельный «продукт» для тестирования — кейс встраивает существующую роль в реальный пайплайн, замыкая рассказ «написал роль → протестировал локально через Molecule → теперь это же автоматически проверяется в CI на каждый push».
|
||||
31
stack/ci-cd/QUESTIONS.md
Normal file
31
stack/ci-cd/QUESTIONS.md
Normal file
@@ -0,0 +1,31 @@
|
||||
# Вопросы: CI/CD
|
||||
|
||||
Опираются на кейс: [CASE.md](CASE.md). Источники — [Реалист банк.md](../../interview/Реалист%20банк.md), [Bi.Zone.md](../../interview/Bi.Zone.md), [Alfa-Bank.md](../../interview/Alfa-Bank.md).
|
||||
|
||||
### В чём разница между CI и CD?
|
||||
|
||||
CI (Continuous Integration) — автоматическая проверка кода при каждом изменении: сборка, линтинг, тесты — цель поймать проблему как можно раньше, до слияния с основной веткой. CD (Continuous Delivery/Deployment) — автоматизация доставки уже проверенного кода до среды исполнения (staging/production) — сборка артефакта/образа, публикация в registry, применение на целевой инфраструктуре. Граница на практике: CI заканчивается там, где код признан «годным» (все тесты прошли, собран артефакт), CD начинается с того, что этот артефакт доставляется дальше.
|
||||
|
||||
### Нарисуй CI/CD и как проливается код через GitLab CI — что будет в процессе CI и что в CD (с этапа, когда код уже запушен в GitHub, а образы в Nexus)?
|
||||
|
||||
От push в GitHub: (1) webhook/триггер запускает pipeline в GitLab CI; (2) CI-часть — стадии `lint` (статический анализ) → `test` (юнит/интеграционные тесты, в моей практике — `molecule test` для Ansible-ролей) → `build` (сборка Docker-образа); (3) стадия публикации — образ пушится в Nexus как container registry с тегом (обычно commit SHA или семантическая версия); (4) CD-часть начинается с деплоя — pipeline берёт собранный образ именно из Nexus (не пересобирает заново) и применяет его на целевом окружении (`kubectl apply`/`helm upgrade` при K8s, или через Ansible-плейбук деплоя при классической инфраструктуре) — сначала обычно на staging, дальше по ручному approve или автоматически на production. Ключевой принцип: то, что задеплоено в prod — это тот же самый бинарный артефакт (образ), что прошёл все проверки CI, без пересборки на каждом этапе.
|
||||
|
||||
### Что такое pipeline/stage/job?
|
||||
|
||||
Pipeline — весь процесс целиком, от триггера (push/MR) до конечного результата (успешный деплой или явный fail). Stage — логическая фаза внутри pipeline (например, `build`, `test`, `deploy`) — stages выполняются последовательно. Job — конкретная выполняемая задача внутри stage (например, в stage `test` могут быть параллельно запущены job `unit-tests` и job `molecule-test`) — job'ы внутри одного stage обычно выполняются параллельно, если нет явных зависимостей.
|
||||
|
||||
### Зачем нужны protected branches?
|
||||
|
||||
Защита основной ветки (обычно `main`/`master`) от прямых push и слияний без прохождения обязательных проверок — требует, чтобы изменения проходили через Merge/Pull Request с обязательным прохождением CI (status checks) и, как правило, минимум одного ревью. Смысл — предотвратить попадание непроверенного или сломанного кода прямо в ветку, с которой разворачивается прод.
|
||||
|
||||
### Как откатить плохой деплой?
|
||||
|
||||
Зависит от инфраструктуры: при K8s — `kubectl rollout undo deployment/<name>` (возврат к предыдущей ревизии Deployment) или `helm rollback <release> <revision>` при Helm-релизах. При классическом деплое через Ansible/образы — передеплоить предыдущий проверенный тег образа (тот самый принцип «в prod идёт конкретный собранный артефакт из registry» из вопроса про GitLab CI выше — откат это просто повторный деплой более старого тега). Важно, чтобы откат был таким же автоматизированным процессом через тот же pipeline, а не ручными правками на проде.
|
||||
|
||||
### Чем отличается git merge --no-ff от fast-forward merge?
|
||||
|
||||
Fast-forward merge происходит, когда в целевой ветке не было новых коммитов после создания feature-ветки — Git просто «продвигает» указатель ветки вперёд, без создания отдельного merge-коммита, история выглядит линейной, как будто feature-ветки не было вовсе. `git merge --no-ff` принудительно создаёт merge-коммит, даже если fast-forward был бы возможен — это сохраняет в истории явный факт, что была отдельная ветка разработки, что удобно для читаемости истории и для возможности откатить весь набор изменений одним `revert` merge-коммита.
|
||||
|
||||
### Как выглядит типичный pipeline для инфраструктурного репозитория?
|
||||
|
||||
`lint` (например, `ansible-lint` для проверки стиля и распространённых ошибок в ролях) → `test` (`molecule test` — идемпотентность и корректность роли в изолированном окружении, см. [../ansible/CASE.md](../ansible/CASE.md)) → `deploy` (применение роли/плейбука на целевую инфраструктуру, обычно с разделением на staging и production stage с ручным approve перед production). Именно эту цепочку я воспроизвёл в [CASE.md](CASE.md) — начиная с `push` в Gitea и заканчивая автоматическим прогоном `molecule test` в пайплайне.
|
||||
Reference in New Issue
Block a user