• Русский
  • Понимание команд запуска

    Содержание

    Overview

    Команды запуска в Kubernetes определяют основной исполняемый файл, который запускается при старте контейнера. Они соответствуют полю command в спецификациях Pod Kubernetes и переопределяют стандартную инструкцию ENTRYPOINT, заданную в образах контейнеров. Команды запуска обеспечивают полный контроль над тем, какой процесс выполняется внутри ваших контейнеров.

    Core Concepts

    Что такое команды запуска?

    Команды запуска — это:

    • Основной исполняемый файл, который запускается при старте контейнера
    • Переопределяют инструкцию ENTRYPOINT в Docker-образах
    • Определяют главный процесс (PID 1) внутри контейнера
    • Работают совместно с параметрами (args), формируя полную командную строку

    Взаимосвязь с Docker и параметрами

    Понимание взаимосвязи между инструкциями Docker и полями Kubernetes:

    DockerKubernetesНазначение
    ENTRYPOINTcommandОпределяет исполняемый файл
    CMDargsЗадает аргументы по умолчанию
    # Пример Dockerfile
    FROM ubuntu:20.04
    ENTRYPOINT ["/usr/bin/myapp"]
    CMD ["--config=/etc/default.conf"]
    # Переопределение в Kubernetes
    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: myapp
        image: myapp:latest
        command: ["/usr/bin/myapp"]
        args: ["--config=/etc/custom.conf", "--debug"]

    Взаимодействие command и args

    СценарийDocker ImageСпецификация KubernetesИтоговая команда
    По умолчаниюENTRYPOINT + CMD(отсутствует)ENTRYPOINT + CMD
    Переопределение argsENTRYPOINT + CMDargs: ["new-args"]ENTRYPOINT + new-args
    Переопределение commandENTRYPOINT + CMDcommand: ["new-cmd"]new-cmd
    Переопределение обоихENTRYPOINT + CMDcommand: ["new-cmd"]
    args: ["new-args"]
    new-cmd + new-args

    Сценарии использования

    1. Пользовательский запуск приложения

    Запуск разных приложений с использованием одного базового образа:

    apiVersion: v1
    kind: Pod
    metadata:
      name: web-server
    spec:
      containers:
      - name: nginx
        image: ubuntu:20.04
        command: ["/usr/sbin/nginx"]
        args: ["-g", "daemon off;", "-c", "/etc/nginx/nginx.conf"]

    2. Отладка и устранение неполадок

    Переопределение стандартной команды для запуска оболочки с целью отладки:

    apiVersion: v1
    kind: Pod
    metadata:
      name: debug-pod
    spec:
      containers:
      - name: debug
        image: myapp:latest
        command: ["/bin/bash"]
        args: ["-c", "sleep 3600"]

    3. Скрипты инициализации

    Запуск пользовательских скриптов инициализации перед стартом основного приложения:

    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: app
        image: myapp:latest
        command: ["/bin/sh"]
        args:
        - "-c"
        - |
          echo "Инициализация приложения..."
          /scripts/init.sh
          echo "Запуск основного приложения..."
          exec /usr/bin/myapp --config=/etc/app.conf

    4. Многоцелевые образы

    Использование одного образа для разных целей:

    # Веб-сервер
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: web
    spec:
      template:
        spec:
          containers:
          - name: web
            image: myapp:latest
            command: ["/usr/bin/myapp"]
            args: ["server", "--port=8080"]
    
    ---
    # Фоновый воркер
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: worker
    spec:
      template:
        spec:
          containers:
          - name: worker
            image: myapp:latest
            command: ["/usr/bin/myapp"]
            args: ["worker", "--queue=tasks"]
    
    ---
    # Миграция базы данных
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: migrate
    spec:
      template:
        spec:
          containers:
          - name: migrate
            image: myapp:latest
            command: ["/usr/bin/myapp"]
            args: ["migrate", "--up"]
          restartPolicy: Never

    Примеры CLI и практическое использование

    Использование kubectl run

    # Полное переопределение команды
    kubectl run debug --image=nginx:alpine --command -- /bin/sh -c "sleep 3600"
    
    # Запуск интерактивной оболочки
    kubectl run -it debug --image=ubuntu:20.04 --restart=Never --command -- /bin/bash
    
    # Пользовательский запуск приложения
    kubectl run myapp --image=myapp:latest --command -- /usr/local/bin/start.sh --config=/etc/app.conf
    
    # Одноразовая задача
    kubectl run task --image=busybox --restart=Never --command -- /bin/sh -c "echo 'Task completed'"

    Использование kubectl create job

    # Создание job с пользовательской командой
    kubectl create job backup --image=postgres:13 --dry-run=client -o yaml -- pg_dump -h db.example.com mydb > backup.yaml
    
    # Применение job
    kubectl apply -f backup.yaml

    Сложные примеры команд запуска

    Многошаговая инициализация

    apiVersion: v1
    kind: Pod
    metadata:
      name: complex-init
    spec:
      containers:
      - name: app
        image: myapp:latest
        command: ["/bin/bash"]
        args:
        - "-c"
        - |
          set -e
          echo "Шаг 1: Проверка зависимостей..."
          /scripts/check-deps.sh
    
          echo "Шаг 2: Настройка конфигурации..."
          /scripts/setup-config.sh
    
          echo "Шаг 3: Выполнение миграций базы данных..."
          /scripts/migrate.sh
    
          echo "Шаг 4: Запуск приложения..."
          exec /usr/bin/myapp --config=/etc/app/config.yaml
        volumeMounts:
        - name: scripts
          mountPath: /scripts
        - name: config
          mountPath: /etc/app
      volumes:
      - name: scripts
        configMap:
          name: init-scripts
          defaultMode: 0755
      - name: config
        configMap:
          name: app-config

    Условная логика запуска

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: conditional-app
    spec:
      template:
        spec:
          containers:
          - name: app
            image: myapp:latest
            command: ["/bin/sh"]
            args:
            - "-c"
            - |
              if [ "$APP_MODE" = "worker" ]; then
                exec /usr/bin/myapp worker --queue=$QUEUE_NAME
              elif [ "$APP_MODE" = "scheduler" ]; then
                exec /usr/bin/myapp scheduler --interval=60
              else
                exec /usr/bin/myapp server --port=8080
              fi
            env:
            - name: APP_MODE
              value: "server"
            - name: QUEUE_NAME
              value: "default"

    Лучшие практики

    1. Обработка сигналов и корректное завершение

    # ✅ Корректная обработка сигналов
    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: app
        image: myapp:latest
        command: ["/bin/bash"]
        args:
        - "-c"
        - |
          # Перехват SIGTERM для корректного завершения
          trap 'echo "Получен SIGTERM, завершаемся корректно..."; kill -TERM $PID; wait $PID' TERM
    
          # Запуск основного приложения в фоне
          /usr/bin/myapp --config=/etc/app.conf &
          PID=$!
    
          # Ожидание завершения процесса
          wait $PID

    2. Обработка ошибок и логирование

    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: app
        image: myapp:latest
        command: ["/bin/bash"]
        args:
        - "-c"
        - |
          set -euo pipefail  # Выход при ошибках, неинициализированных переменных и ошибках в пайпах
    
          log() {
            echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*" >&2
          }
    
          log "Начинается инициализация приложения..."
    
          if ! /scripts/health-check.sh; then
            log "ОШИБКА: Проверка состояния не пройдена"
            exit 1
          fi
    
          log "Запуск основного приложения..."
          exec /usr/bin/myapp --config=/etc/app.conf

    3. Вопросы безопасности

    # ✅ Запуск от имени непривилегированного пользователя
    apiVersion: v1
    kind: Pod
    spec:
      securityContext:
        runAsNonRoot: true
        runAsUser: 1000
        runAsGroup: 1000
      containers:
      - name: app
        image: myapp:latest
        command: ["/usr/bin/myapp"]
        args: ["--config=/etc/app.conf"]
        securityContext:
          allowPrivilegeEscalation: false
          readOnlyRootFilesystem: true
          capabilities:
            drop:
            - ALL

    4. Управление ресурсами

    apiVersion: v1
    kind: Pod
    spec:
      containers:
      - name: app
        image: myapp:latest
        command: ["/usr/bin/myapp"]
        args: ["--config=/etc/app.conf"]
        resources:
          requests:
            memory: "64Mi"
            cpu: "250m"
          limits:
            memory: "128Mi"
            cpu: "500m"

    Расширенные шаблоны использования

    1. Init-контейнеры с пользовательскими командами

    apiVersion: v1
    kind: Pod
    spec:
      initContainers:
      - name: setup
        image: busybox
        command: ["/bin/sh"]
        args:
        - "-c"
        - |
          echo "Настройка общих данных..."
          mkdir -p /shared/data
          echo "Настройка завершена" > /shared/data/status
        volumeMounts:
        - name: shared-data
          mountPath: /shared
      containers:
      - name: app
        image: myapp:latest
        command: ["/bin/sh"]
        args:
        - "-c"
        - |
          while [ ! -f /shared/data/status ]; do
            echo "Ожидание завершения настройки..."
            sleep 1
          done
          echo "Запуск приложения..."
          exec /usr/bin/myapp
        volumeMounts:
        - name: shared-data
          mountPath: /shared
      volumes:
      - name: shared-data
        emptyDir: {}

    2. Sidecar-контейнеры с разными командами

    apiVersion: v1
    kind: Pod
    spec:
      containers:
      # Основное приложение
      - name: app
        image: myapp:latest
        command: ["/usr/bin/myapp"]
        args: ["--config=/etc/app.conf"]
    
      # Sidecar для отправки логов
      - name: log-shipper
        image: fluent/fluent-bit:latest
        command: ["/fluent-bit/bin/fluent-bit"]
        args: ["--config=/fluent-bit/etc/fluent-bit.conf"]
    
      # Sidecar для экспорта метрик
      - name: metrics
        image: prom/node-exporter:latest
        command: ["/bin/node_exporter"]
        args: ["--path.rootfs=/host"]

    3. Шаблоны Job с пользовательскими командами

    # Job для резервного копирования
    apiVersion: batch/v1
    kind: Job
    metadata:
      name: database-backup
    spec:
      template:
        spec:
          containers:
          - name: backup
            image: postgres:13
            command: ["/bin/bash"]
            args:
            - "-c"
            - |
              set -e
              echo "Начало резервного копирования в $(date)"
              pg_dump -h $DB_HOST -U $DB_USER $DB_NAME > /backup/dump-$(date +%Y%m%d-%H%M%S).sql
              echo "Резервное копирование завершено в $(date)"
            env:
            - name: DB_HOST
              value: "postgres.example.com"
            - name: DB_USER
              value: "backup_user"
            - name: DB_NAME
              value: "myapp"
            volumeMounts:
            - name: backup-storage
              mountPath: /backup
          restartPolicy: Never
          volumes:
          - name: backup-storage
            persistentVolumeClaim:
              claimName: backup-pvc

    Команды запуска обеспечивают полный контроль над выполнением контейнеров в Kubernetes. Понимая, как правильно настраивать и использовать команды запуска, вы можете создавать гибкие, поддерживаемые и надежные контейнеризированные приложения, соответствующие вашим конкретным требованиям.