Сервис развивается: тестируем формат, собираем идеи, улучшаем сервис. Есть идеи?

Написать
Войти
Дайджесты
Таймлайн практики Junior DevOps от Linux до Kubernetes

Как стать DevOps-инженером без коммерческого опыта: план практики

Пошаговый маршрут построения сквозного учебного проекта помогает инженерам получить реальный практический опыт. Последовательное соединение Linux, SSH-доступа, systemd-сервисов, Docker-контейнеров, автоматизации CI/CD, Nginx, мониторинга и Kubernetes в единый рабочий стенд служит отличной демонстрацией навыков.

Как стать DevOps-инженером без коммерческого опыта: план практики

Введение: почему важен сквозной проект

Изучение инструментов DevOps изолированно — частая ошибка начинающих инженеров. Умение писать отдельные Dockerfile или манифесты не дает понимания того, как связать компоненты в единый конвейер доставки ПО. Работодателям нужны специалисты, видящие жизненный цикл приложения целиком.

Наилучший способ продемонстрировать свои навыки — построить собственный сквозной проект (пет-проект), развернув его в реальном облаке с нуля. Этот маршрут шаг за шагом проводит разработчика через все этапы построения современной инфраструктуры: от настройки операционной системы до автоматического деплоя в кластер Kubernetes.

Шаг 1: Аренда сервера и базовая защита Linux

Основой любого проекта является вычислительная инфраструктура. Для старта подойдет виртуальный приватный сервер (VPS) минимальной конфигурации с Ubuntu или Debian. После создания машины первоочередной задачей является ее защита.

  1. Генерация SSH-ключей. На локальном компьютере создайте пару ключей:
    ssh-keygen -t ed25519 -C "[email protected]"
    
  2. Копирование ключа на сервер. Передайте публичный ключ на арендованную виртуальную машину:
    ssh-copy-id -i ~/.ssh/id_ed25519.pub root@<VPS_IP>
    
  3. Отключение авторизации по паролю. Подключитесь к серверу и откройте конфигурационный файл /etc/ssh/sshd_config. Найдите и измените следующие параметры:
    PasswordAuthentication no
    PermitRootLogin prohibit-password
    
  4. Перезапуск службы SSH. Примените изменения командой:
    systemctl restart ssh
    

Это заблокирует попытки подбора паролей злоумышленниками и заставит использовать только безопасные ключи.

Шаг 2: Создание и запуск приложения как systemd-сервиса

Для тестирования инфраструктуры потребуется веб-приложение (например, на Go, Node.js или Python FastAPI), которое слушает порт 8080 и отдает простую текстовую заглушку или JSON-ответ.

Чтобы приложение работало стабильно, запускалось при старте системы и перезапускалось при сбоях, оформите его в виде службы systemd. Создайте конфигурационный файл /etc/systemd/system/myapp.service:

[Unit]
Description=My Web Application
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/var/www/myapp
ExecStart=/var/www/myapp/myapp-binary
Restart=always
RestartSec=5
Environment=PORT=8080

[Install]
WantedBy=multi-user.target

После сохранения файла выполните команды для запуска службы:

systemctl daemon-reload
systemctl enable --now myapp

Проверьте статус запущенного процесса с помощью systemctl status myapp.

Шаг 3: Контейнеризация приложения с помощью Docker

Запуск приложения в виде бинарного файла на хост-системе неудобен при обновлении зависимостей. Современный стандарт разработки требует упаковки кода в изолированные контейнеры Docker.

Для оптимизации размера результирующего образа используйте многоэтапную сборку (multi-stage build). Пример Dockerfile для Go-приложения:

# Этап сборки бинарного файла
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o main .

# Этап финального минималистичного образа
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

Соберите образ и запустите контейнер на порту 8080:

docker build -t myapp:latest .
docker run -d --name myapp-container -p 8080:8080 --restart unless-stopped myapp:latest

Шаг 4: Настройка веб-сервера Nginx и шифрования SSL/TLS

Запускать приложение напрямую на портах 80 или 443 — плохая практика с точки зрения безопасности. Для обработки входящего интернет-трафика используется веб-сервер Nginx, выступающий в роли обратного прокси (reverse proxy).

Установите веб-сервер и настройте конфигурационный файл виртуального хоста /etc/nginx/sites-available/myapp:

server {
    listen 80;
    server_name domain.com;

    location / {
        proxy_pass http://localhost:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

Активируйте конфигурацию и перезапустите Nginx:

ln -s /etc/nginx/sites-available/myapp /etc/nginx/sites-enabled/
nginx -t
systemctl restart nginx

Для настройки HTTPS-соединения воспользуйтесь бесплатными сертификатами Let's Encrypt и утилитой Certbot. Установите Certbot и запустите процесс генерации:

apt install certbot python3-certbot-nginx
certbot --nginx -d domain.com

Утилита сама изменит конфигурационный файл Nginx, настроит перенаправление с HTTP на HTTPS и автоматическое продление сертификатов.

Шаг 5: Автоматизация развертывания через CI/CD

Ручной деплой через терминал отнимает время и ведет к ошибкам. Для автоматизации этого процесса настройте конвейер CI/CD (например, с использованием GitHub Actions). Напишите сценарий в файле .github/workflows/deploy.yml:

name: Deploy Application

on:
  push:
    branches: [main]

jobs:
  build-and-deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Build Docker Image
        run: docker build -t myapp:${{ github.sha }} .

      - name: Push to Registry
        run: |
          echo "${{ secrets.DOCKER_PASSWORD }}" | docker login -u "${{ secrets.DOCKER_USERNAME }}" --password-stdin
          docker tag myapp:${{ github.sha }} ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}
          docker push ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}

      - name: Deploy to VPS via SSH
        uses: appleboy/[email protected]
        with:
          host: ${{ secrets.VPS_HOST }}
          username: root
          key: ${{ secrets.SSH_PRIVATE_KEY }}
          script: |
            docker stop myapp-container || true
            docker rm myapp-container || true
            docker pull ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}
            docker run -d --name myapp-container -p 8080:8080 --restart unless-stopped ${{ secrets.DOCKER_USERNAME }}/myapp:${{ github.sha }}

Этот скрипт запускается при коммите в ветку main, собирает Docker-образ, публикует его, подключается по SSH к серверу и перезапускает контейнер.

Шаг 6: Развертывание мониторинга с Prometheus и Grafana

Необходимо также отслеживать состояние ресурсов сервера и метрики приложения.

  1. Установка Node Exporter. Запустите Node Exporter на сервере для сбора системных метрик (загрузка процессора, оперативная память, свободное место на дисках):
    docker run -d -p 9100:9100 --name node-exporter prom/node-exporter
    
  2. Настройка Prometheus. Создайте файл конфигурации prometheus.yml:
    global:
      scrape_interval: 15s
    
    scrape_configs:
      - job_name: 'vps-node'
        static_configs:
          - targets: ['localhost:9100']
    
    Запустите сервер сбора метрик:
    docker run -d -p 9090:9090 -v $(pwd)/prometheus.yml:/etc/prometheus/prometheus.yml --name prometheus prom/prometheus
    
  3. Визуализация в Grafana. Запустите Grafana:
    docker run -d -p 3000:3000 --name grafana grafana/grafana
    

Откройте интерфейс Grafana (порт 3000), добавьте Prometheus в качестве DataSource и импортируйте стандартный дашборд для Node Exporter.

Шаг 7: Миграция инфраструктуры в Kubernetes

Финальным этапом развития инфраструктуры является переход от запуска одиночных контейнеров к оркестрации с помощью Kubernetes. Это обеспечивает автоматическое масштабирование и отказоустойчивость приложения.

Для миграции подготовьте файлы конфигурации (манифесты).

  1. Создание Deployment (deployment.yaml). Описывает состояние реплик приложения:
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: myapp-deployment
    spec:
      replicas: 2
      selector:
        matchLabels:
          app: myapp
      template:
        metadata:
          labels:
            app: myapp
        spec:
          containers:
          - name: myapp
            image: yourusername/myapp:latest
            ports:
            - containerPort: 8080
    
  2. Создание Service (service.yaml). Описывает сетевой доступ к подам внутри кластера:
    apiVersion: v1
    kind: Service
    metadata:
      name: myapp-service
    spec:
      selector:
        app: myapp
      ports:
        - protocol: TCP
          port: 80
          targetPort: 8080
      type: ClusterIP
    
  3. Создание Ingress (ingress.yaml). Настраивает внешний доступ по доменному имени:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: myapp-ingress
      annotations:
        nginx.ingress.kubernetes.io/ssl-redirect: "true"
    spec:
      rules:
      - host: domain.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: myapp-service
                port:
                  number: 80
    

Для локального тестирования примените манифесты в minikube или Kind с помощью kubectl apply -f deployment.yaml и т.д.

Заключение: демонстрация проекта работодателю

Построив и объединив все указанные компоненты, вы получите рабочий, задокументированный проект. Опишите процесс развертывания в файле README.md вашего репозитория, приложив схему архитектуры и ссылки на приложение, панель Grafana и конфигурации. Такой сквозной проект наглядно покажет работодателям вашу практическую зрелость и понимание современных инженерных подходов.