# Тестовое задание SimbirSoft DevOps
>[!NOTE]
>Соловьев Руслан
>
>Резюме - [HH](https://krasnodar.hh.ru/resume/b105319cff0f77ed050039ed1f5a4a4a733148)
>
>Узнать поднобнее - https://ruslansoloviev.ru
## Почему хочу девопсить
Мне нравится DevOps за сочетание разработки и системного администрирования. Мне интересно не только написать приложение, но и разобраться, как оно будет развёрнуто, как автоматизировать этот процесс, обеспечить его стабильную работу и понять, что происходит с сервисом после его запуска.
Именно поэтому со временем я стал больше заниматься инфраструктурной частью своих проектов: Docker, CI/CD, Kubernetes, мониторингом, сетями и автоматизацией. Особенно нравится автоматизировать повторяющиеся процессы и превращать ручную настройку в воспроизводимую конфигурацию.
В дальнейшем я хочу развиваться именно как DevOps-инженер, работать с более крупной инфраструктурой и задачами, где требования к надёжности, автоматизации и наблюдаемости значительно выше, чем в моих текущих проектах.
## Теоретическая часть
1) Нужно обеспечить высокую доступность сервиса, как бы ее реализовал?
- Так как у нас технически в данном задании nginx раздает только статику я бы вообще убрал сервер как точку отказа и вынес статическую страницу в объектное хранилище S3 и подключил CDN, таким образом высокая доступность будет обеспечена силами облачного провайдера, а CDN ускорит доставку контента до пользователей и сократит затраты на GET операции в хранилище.
- Если же необходимо реализовать высокую доступность именно посредством серверов, то я бы поднял как минимум 2 экземпляра на разных ВМ в разных зонах доступности и повесил на них балансировщик с хелс чеками доступности каждой из ВМ что бы не слать трафик на заведомо мертвую ВМ, 2 AZ поскольку этого будет достаточно в большинстве случаем да и самому nginx не нужен кворум для работы
2) Тебе надо создать и настроить 5 таких серверов, как бы это реализовал?
- Так как я описал необходимое состояние ВМ в ansible плейбук то для настройки будет достаточно указать все ВМ в инвентаре плейбука, а для заказа смотря как управляется текущая инфраструктура - если там терраформ или что то похожее то в конфигурации описал бы необходимые 5 экземпляров, если ручками то заказываю в гипервизоре или панели клауд провайдера
## Практическая часть
В данном тестовом задании я использовал Ansible и для его воспроизводимости понадобятся сам Ansible и некоторые его коллекции, установить которые можно следующими командами:
**Debian/Ubuntu**
```sh
sudo apt update && sudo apt install -y ansible
```
**macOS**
```sh
brew install ansible
```
**Через pip**
```sh
python3 -m pip install ansible
```
```sh
ansible-galaxy collection install community.general
ansible-galaxy collection install community.crypto
ansible-galaxy collection install community.docker
ansible-galaxy collection install ansible.posix
```
В файле *hosts.yaml* необходимо указать адрес ВМ и пользователя, например
```yaml
all:
hosts:
nginx:
ansible_host: 192.168.20.217
ansible_user: rouxinol
```
Далее в файле *secrets.yaml* необходимо указать пароль для указаного ранее пользователя, а так же пароль для *sudo* для указаного пользователя, например:
```yaml
ansible_password: "superpass123"
ansible_become_password: "superpass123"
```
Далее можно зашифровать этот файл:
```sh
ansible-vault encrypt secrets.yaml
```
После всех действий можно запустить плейбук:
```sh
ansible-playbook -i hosts.yaml playbook.yaml
```
> [!WARNING]
> Если был зашифрован secrets.yaml то необходимо так же добавить флаг ```--ask-vault-pass```
---
Скриншоты работы сервиса:
**HTTP**

**HTTPS**

---
В качестве лабораторной работы я заказал ВМ с Ubuntu Server 24.04 с пользователем *rouxinol* в Proxmox VE, IP ВМ в локальной сети - 192.168.20.217
Логи выполнения плейбука можно посмотреть в [логе выполнения Ansible](./ansible-playbook.log)
Логи повторного выполнения плейбука можно посмотреть в [логе повторного выполнения Ansible](./ansible-playbook-repeat.log)
## Ремарки к практическим заданиям
3) Продемонстрировать блокировку портов
**Конечная конфирукция ufw с ВМ**
```log
rouxinol@rouxinol-testserver:/opt/nginx$ sudo ufw status verbose
Status: active
Logging: on (low)
Default: deny (incoming), allow (outgoing), deny (routed)
New profiles: skip
To Action From
-- ------ ----
22/tcp (OpenSSH) ALLOW IN Anywhere
80/tcp ALLOW IN Anywhere
443/tcp ALLOW IN Anywhere
22/tcp (OpenSSH (v6)) ALLOW IN Anywhere (v6)
80/tcp (v6) ALLOW IN Anywhere (v6)
443/tcp (v6) ALLOW IN Anywhere (v6)
```
**Nmap по привелигированным портам**
```log
❯ nmap 192.168.20.217
Starting Nmap 7.98 ( https://nmap.org ) at 2026-08-17 01:54 +0300
Nmap scan report for 192.168.20.217
Host is up (0.0029s latency).
Not shown: 997 filtered tcp ports (no-response)
PORT STATE SERVICE
22/tcp open ssh
80/tcp open http
443/tcp open https
Nmap done: 1 IP address (1 host up) scanned in 43.31 seconds
```
6) Бекап каждый понедельник
```log
root@rouxinol-testserver:/opt/nginx# crontab -l
CRON_TZ="UTC"
#Ansible: nginx configuration backup
0 1 * * 1 /opt/nginx/backup.sh
root@rouxinol-testserver:/opt/nginx# ./backup.sh
Successfully copied 25.1kB to /tmp/tmp.9hPGthi4R2/nginx
root@rouxinol-testserver:/opt/nginx# ls backups/
nginx_2026-08-16_23-01-36.tar.gz nginx_2026-08-16_23-02-10.tar.gz
```
7) В Dockerfile указано запускать master-процесс от пользователя nginx, а так же в nginx,conf указано запускать worker-процессы так же от nginx, однако для этого были выбраны непривелигированные порты 8080 и 8443, однако можно было использовать образ nginxinc/nginx-unprivileged и не указывать ничего из этого и в Dockerfile есть закомментированный FROM этого образа - однако он не был выбран так как в Docker Hub нет нужной 1.29.6 версии - я подобрал ближайшую
8) При запуске плейбука в его корне автоматически создается ssh ed25519 ключ без фразы пароля, для подключения к ВМ будет достаточно именно для моего тестового окружения следующей команды:
```sh
ssh -i ./id_ed25519_simbirkey rouxinol@192.168.20.217
```
9) [Dockerfile тут](./roles/nginx/files/Dockerfile)