Перейти к основному контенту
Tech Path Finder
КурсыИнтервьюКод-ревьюБлог
Tech Path Finder

Персонализированный путеводитель в IT. Квизы, мок-интервью, код ревью и аналитика прогресса.

@potapov_me

Платформа

  • Курсы
  • Прогресс
  • Мок-интервью
  • Код ревью
  • Живое ревью с ИИ
  • Тренажёр переговоров
  • Закладки

Контент

  • Блог
  • Главная
  • Обратная связь

Компания

  • О проекте
  • Тарифы
  • Условия использования
  • Конфиденциальность
  • Согласие на обработку данных
  • Cookie
  • Реквизиты

Аккаунт

  • Войти
  • Зарегистрироваться
  • Профиль

© 2026 Tech Path Finder. Все права защищены.

·ИП Потапов К.С.·Политика конфиденциальности·
Сделано с ❤️ в России
  1. Admin Processes — админ-процессы
admin_processes

Admin Processes — админ-процессы

Административные задачи как одноразовые процессы

Admin Processes: Административные процессы

Запускайте административные задачи как одноразовые процессы

#Суть принципа

Admin Processes — двенадцатый фактор 12-Factor App. Принцип гласит:

Административные задачи (миграции БД, консольные команды, скрипты) должны запускаться как одноразовые процессы в том же окружении, что и приложение.**

┌─────────────────────────────────────────────────────────────────┐
│              Административные процессы                          │
│                                                                  │
│  ┌─────────────────┐                                           │
│  │  Долгосрочные   │  Веб-процессы, воркеры                    │
│  │  процессы       │  (работают постоянно)                     │
│  └─────────────────┘                                           │
│                                                                  │
│  ┌─────────────────┐                                           │
│  │  Одноразовые    │  Миграции, консоль, скрипты               │
│  │  процессы       │  (запускаются по необходимости)           │
│  └─────────────────┘                                           │
│                                                                  │
│  Оба типа используют одинаковое окружение и код                │
└─────────────────────────────────────────────────────────────────┘

#Типы административных задач

#Миграции базы данных

# Применение миграций python manage.py migrate alembic upgrade head rails db:migrate

#Консольные команды

# Django shell python manage.py shell # Создание суперпользователя python manage.py createsuperuser # Сборка статики python manage.py collectstatic

#Одноразовые скрипты

# Импорт данных python scripts/import_data.py # Очистка кэша python scripts/clear_cache.py # Отчёт за период python scripts/generate_report.py --from 2024-01-01 --to 2024-01-31

#Обслуживание данных

# Бэкап базы данных pg_dump $DATABASE_URL > backup.sql # Восстановление из бэкапа psql $DATABASE_URL < backup.sql # Очистка старых данных python scripts/cleanup_old_data.py --days 365

#Запуск в разных средах

#Локальная разработка

# Миграции локально docker-compose exec web python manage.py migrate # Консоль Django docker-compose exec web python manage.py shell # Скрипт docker-compose exec web python scripts/import_data.py

#Production (Kubernetes)

# Миграции в Kubernetes kubectl exec -it deployment/myapp -- python manage.py migrate # Консоль в поде kubectl exec -it deployment/myapp -- python manage.py shell # Запуск скрипта kubectl exec -it deployment/myapp -- python scripts/cleanup.py

#Production (Docker)

# Миграции docker run --rm \ --env-file .env.prod \ --network app-network \ myapp:latest \ python manage.py migrate # Консоль docker run -it --rm \ --env-file .env.prod \ --network app-network \ myapp:latest \ python manage.py shell # Скрипт docker run --rm \ --env-file .env.prod \ myapp:latest \ python scripts/generate_report.py

#CI/CD для миграций

#GitLab CI

# .gitlab-ci.yml stages: - test - build - migrate - deploy migrate: stage: migrate image: registry/myapp:$CI_COMMIT_SHA script: - python manage.py migrate environment: name: production when: manual # Ручное подтверждение перед деплоем only: - main deploy: stage: deploy image: bitnami/kubectl script: - kubectl set image deployment/myapp myapp=registry/myapp:$CI_COMMIT_SHA environment: name: production needs: - migrate

#GitHub Actions

# .github/workflows/deploy.yml name: Deploy on: push: branches: [main] jobs: migrate: runs-on: ubuntu-latest environment: production steps: - uses: actions/checkout@v3 - name: Run migrations run: | docker run --rm \ -e DATABASE_URL=${{ secrets.DATABASE_URL }} \ registry/myapp:${{ github.sha }} \ python manage.py migrate deploy: runs-on: ubuntu-latest environment: production needs: migrate steps: - name: Deploy to Kubernetes run: | kubectl set image deployment/myapp myapp=registry/myapp:${{ github.sha }}

#Job-процессы в Kubernetes

#Job для миграций

# migration-job.yaml apiVersion: batch/v1 kind: Job metadata: name: db-migration spec: template: spec: containers: - name: migration image: registry/myapp:latest command: ["python", "manage.py", "migrate"] env: - name: DATABASE_URL valueFrom: secretKeyRef: name: app-secrets key: database-url restartPolicy: OnFailure backoffLimit: 3 # Количество повторных попыток
# Обновление deployment после миграции apiVersion: apps/v1 kind: Deployment metadata: name: myapp spec: template: spec: initContainers: - name: wait-for-migration image: busybox command: ['sh', '-c', 'until [ -f /migration-done ]; do sleep 1; done'] volumeMounts: - name: migration-status mountPath: /migration-status containers: - name: web image: registry/myapp:latest

#CronJob для периодических задач

# cleanup-cronjob.yaml apiVersion: batch/v1 kind: CronJob metadata: name: data-cleanup spec: schedule: "0 2 * * *" # Каждый день в 2:00 jobTemplate: spec: template: spec: containers: - name: cleanup image: registry/myapp:latest command: ["python", "scripts/cleanup_old_data.py", "--days", "365"] env: - name: DATABASE_URL valueFrom: secretKeyRef: name: app-secrets key: database-url restartPolicy: OnFailure

#Django management commands

#Создание кастомных команд

# management/commands/create_admin.py from django.core.management.base import BaseCommand from django.contrib.auth import get_user_model User = get_user_model() class Command(BaseCommand): help = 'Создаёт администратора' def add_arguments(self, parser): parser.add_argument('--email', type=str, required=True) parser.add_argument('--password', type=str, required=True) def handle(self, *args, **options): email = options['email'] password = options['password'] if User.objects.filter(email=email).exists(): self.stdout.write( self.style.WARNING(f'User {email} already exists') ) return User.objects.create_superuser(email=email, password=password) self.stdout.write( self.style.SUCCESS(f'Successfully created user {email}') )
# Использование python manage.py create_admin --email admin@example.com --password secret123

#Команда для импорта данных

# management/commands/import_data.py import csv from django.core.management.base import BaseCommand from myapp.models import Product class Command(BaseCommand): help = 'Импортирует продукты из CSV' def add_arguments(self, parser): parser.add_argument('csv_file', type=str) parser.add_argument('--dry-run', action='store_true') def handle(self, *args, **options): csv_file = options['csv_file'] dry_run = options['dry_run'] with open(csv_file, 'r') as f: reader = csv.DictReader(f) for row in reader: if dry_run: self.stdout.write(f"Would create: {row['name']}") else: Product.objects.create( name=row['name'], price=row['price'], sku=row['sku'] ) self.stdout.write( self.style.SUCCESS(f"Created: {row['name']}") )
# Сухой запуск python manage.py import_data products.csv --dry-run # Реальный импорт python manage.py import_data products.csv

#Безопасность административных задач

#Ограничение доступа

# management/commands/delete_user.py from django.core.management.base import BaseCommand, CommandError from django.contrib.auth import get_user_model import os User = get_user_model() class Command(BaseCommand): help = 'Удаляет пользователя (требует подтверждения)' def add_arguments(self, parser): parser.add_argument('user_id', type=int) parser.add_argument('--force', action='store_true') def handle(self, *args, **options): # Проверка переменной окружения для production if os.environ.get('ENV') == 'production' and not options['force']: raise CommandError( 'Production delete requires --force flag. ' 'Are you sure?' ) user_id = options['user_id'] try: user = User.objects.get(id=user_id) except User.DoesNotExist: raise CommandError(f'User {user_id} does not exist') self.stdout.write(f'Deleting user: {user.email}') user.delete() self.stdout.write( self.style.SUCCESS('User deleted successfully') )

#Логирование административных действий

# management/commands/update_config.py import logging from django.core.management.base import BaseCommand logger = logging.getLogger('audit') class Command(BaseCommand): help = 'Обновляет конфигурацию' def handle(self, *args, **options): logger.info( "Config update started", extra={ 'event_type': 'config_update', 'user': os.environ.get('USER', 'unknown'), } ) # Логика обновления update_config() logger.info( "Config update completed", extra={ 'event_type': 'config_update', 'status': 'success', } )

#Антипаттерны

#❌ Административный код в веб-приложении

# ❌ Неправильно: админ-эндпоинты в веб-приложении @app.route('/admin/migrate') def run_migrations(): # Миграции через HTTP! subprocess.run(['python', 'manage.py', 'migrate']) return 'Migrations complete' @app.route('/admin/shell') def web_shell(): # Веб-консоль! code = request.args.get('code') return eval(code) # 😱

Проблемы:

  • Безопасность — любой может вызвать миграции
  • Таймауты — миграции могут выполняться долго
  • Нет аудита — кто запустил команду?

#❌ Ручные шаги в production

# ❌ Неправильно: ручные команды в production # 1. SSH на сервер ssh admin@prod-server # 2. Переход в директорию cd /var/www/myapp # 3. Активация виртуального окружения source venv/bin/activate # 4. Запуск миграций python manage.py migrate # 5. Перезапуск приложения sudo systemctl restart myapp

Решение: Автоматизировать через CI/CD.

#❌ Разное окружение для админ-задач

# ❌ Неправильно: разные переменные окружения # Development DATABASE_URL=sqlite:///dev.db python manage.py migrate # Production DATABASE_URL=postgresql://prod-db/app python manage.py migrate # Может не работать из-за различий

Решение: Использовать одинаковое окружение.

#Проверка соответствия принципу

Задайте себе вопросы:

  • Запускаются ли миграции как отдельные процессы?
  • Используют ли админ-процессы тот же образ, что и приложение?
  • Автоматизирован ли запуск миграций в CI/CD?
  • Есть ли аудит логирование для административных действий?
  • Защищены ли опасные команды (удаление данных)?
  • Используются ли Job/CronJob в Kubernetes?

#Связь с другими факторами

  • Codebase — админ-код в том же репозитории
  • Dependencies — те же зависимости для админ-процессов
  • Config — те же переменные окружения
  • Processes — админ-процессы тоже stateless

#Пример из практики

#До: ручные административные задачи

# Ручное развёртывание # 1. SSH на сервер ssh admin@prod-server # 2. Остановка приложения sudo systemctl stop myapp # 3. Бэкап БД pg_dump myapp > backup_$(date +%Y%m%d).sql # 4. Применение миграций python manage.py migrate # 5. Запуск приложения sudo systemctl start myapp # 6. Проверка curl https://myapp.example.com/health

Проблемы:

  • Человеческие ошибки
  • Нет аудита кто и когда запускал
  • Длительный простой

#После: автоматизированные админ-процессы

# .gitlab-ci.yml stages: - test - build - migrate - deploy migrate: stage: migrate image: registry/myapp:$CI_COMMIT_SHA script: - python manage.py migrate environment: name: production when: manual deploy: stage: deploy image: bitnami/kubectl script: - kubectl rollout restart deployment/myapp - kubectl rollout status deployment/myapp environment: name: production needs: - migrate
# cleanup-cronjob.yaml apiVersion: batch/v1 kind: CronJob metadata: name: daily-cleanup spec: schedule: "0 3 * * *" jobTemplate: spec: template: spec: containers: - name: cleanup image: registry/myapp:latest command: ["python", "scripts/cleanup.py"] restartPolicy: OnFailure

Результат:

  • ✅ Автоматизированные миграции в CI/CD
  • ✅ Периодические задачи через CronJob
  • ✅ Аудит всех административных действий
  • ✅ Одинаковое окружение для всех задач

Ключевой вывод: Административные задачи (миграции, консоль, скрипты) должны запускаться как одноразовые процессы в том же окружении, что и основное приложение. Это обеспечивает переносимость, аудируемость и автоматизацию через CI/CD.

Далее: Telemetry — телеметрия