Дополнительные сценарии администрирования DropApp#

Сценарии репликации#

Репликация pods в DropApp является одной из ключевых концепций, обеспечивающих отказоустойчивость, масштабируемость и высокую доступность приложений. В разделе представлены основные сценарии использования репликации pods и инструменты DropApp, которые их поддерживают.

Гарантия минимального количества работающих pods#

DropApp гарантирует, что указанное количество экземпляров pods будет запущено и поддерживаться в рабочем состоянии. Если один из pods падает или удаляется, система автоматически создает новый pod для восстановления желаемого состояния.

Инструменты репликации:

  • ReplicaSet - управляет набором pods, гарантируя, что заданное количество реплик всегда работает;

  • Deployment - абстракция более высокого уровня, которая управляет ReplicaSet и предоставляет дополнительные возможности, такие как обновления и откаты.

Пример настройки:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx:latest

При описании ReplicaSet стоит указать, сколько экземпляров pods должно работать одновременно, установив параметр .spec.replicas. По умолчанию значение .spec.replicas равно единице.

Масштабирование приложений#

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

Инструменты масштабирования:

  • Horizontal Pod Autoscaler (HPA) - автоматически увеличивает или уменьшает количество реплик pods на основе метрик, таких как использование CPU или памяти;

  • kubectl scale - команда для ручного масштабирования.

Пример HPA:

apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: app-autoscaler
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: app-deployment
  minReplicas: 2
  maxReplicas: 10
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50

Команда для ручного масштабирования:

kubectl scale deployment app-deployment --replicas=5

Обновление приложений без простоя#

При обновлении приложения важно минимизировать простои. Kubernetes поддерживает стратегии развертывания, такие как "Rolling Update", которые позволяют постепенно обновлять pods, не останавливая работу приложения.

Инструменты обновления:

  • Deployment - поддерживает стратегии развертывания, такие как RollingUpdate и Recreate.

  • Rollback - поддерживает возможность отката к предыдущей версии приложения в случае ошибок.

Пример:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: app-deployment
spec:
  replicas: 3
  strategy:
    type: RollingUpdate
    rollingUpdate:
      maxUnavailable: 1
      maxSurge: 1
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
      - name: my-container
        image: nginx:1.21

Команда для отката:

kubectl rollout undo deployment/app-deployment

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

Для выполнения одноразовых задач, таких как миграции баз данных или выполнение скриптов, используются объекты Job и CronJob. Эти объекты создают pods, которые завершаются после выполнения задачи.

Инструменты запуска одноразовых задач:

  • Job - создает один или несколько pods для выполнения задачи до завершения;

  • CronJob - позволяет выполнять задачи по расписанию.

Пример Job:

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  template:
    spec:
      containers:
      - name: job-container
        image: busybox
        command: ["sh", "-c", "echo 'Task completed' && sleep 5"]
      restartPolicy: Never
  backoffLimit: 4

Пример CronJob:

apiVersion: batch/v1
kind: CronJob
metadata:
  name: example-cronjob
spec:
  schedule: "*/5 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: cron-container
            image: busybox
            command: ["sh", "-c", "echo 'Cron task executed'"]
          restartPolicy: OnFailure

Запуск демонов на всех nodes#

Для запуска pods на каждом node кластера, например, для сбора логов или мониторинга, используется объект DaemonSet.

Инструмент запуска демонов, DaemonSet - гарантирует, что один экземпляр pod будет запущен на каждом node.

Пример:

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: monitoring-agent
spec:
  selector:
    matchLabels:
      app: monitoring
  template:
    metadata:
      labels:
        app: monitoring
    spec:
      containers:
      - name: monitoring-container
        image: monitoring-agent:latest

Отказоустойчивость и самовосстановление#

Если pod падает или удаляется, DropApp автоматически создает новый pod для замены. Это обеспечивает отказоустойчивость приложений.

Инструменты отказоустойчивости и самовосстановления:

  • ReplicaSet или Deployment - управляют pods и восстанавливают их при необходимости;

  • Liveness и Readiness Probes - проверяют работоспособность pods и перезапускают их при необходимости.

Пример Liveness Probe:

apiVersion: v1
kind: Pod
metadata:
  name: liveness-pod
spec:
  containers:
  - name: liveness-container
    image: nginx
    livenessProbe:
      httpGet:
        path: /healthz
        port: 80
      initialDelaySeconds: 3
      periodSeconds: 3

Рекомендации#

Репликация pods в DropApp решает множество задач, от обеспечения отказоустойчивости до масштабирования и управления жизненным циклом приложений. Выбор подходящего инструмента зависит от конкретных требований:

  • используйте Deployment для долгоживущих приложений;

  • используйте Job и CronJob для одноразовых задач;

  • используйте DaemonSet для запуска pods на всех nodes;

  • используйте HPA для автоматического масштабирования.

Примеры дополнительных сценариев администрирования DropApp#

Примечание

Все описанные примеры управляются пользователем с ролью – Администратор.

Пользователи получают доступ к API DropApp, используя kubectl клиентские библиотеки или отправляя запросы REST. Для доступа к API могут быть авторизованы как обычные пользователи, так и учетные записи служб DropApp.

Безопасность на Transport#

По умолчанию сервер API DropApp прослушивает порт 6443 на первом сетевом интерфейсе нелокального хоста, защищенного TLS 1.2. В типичном производственном кластере DropApp API обслуживает порт 443. Порт можно изменить с помощью флага --secure-port, а IP-адрес прослушивания с помощью --bind-address флага.

Сервер API предоставляет сертификат. Этот сертификат может быть подписан с использованием клиентского центра сертификации (CA) или на основе инфраструктуры открытых ключей, связанной с CA. Сертификат и соответствующий закрытый ключ могут быть установлены с помощью флагов --TLS-cert-file и --TLS-private-key-file.

Если кластер DropApp использует клиентский центр сертификации, потребуется копия этого сертификата CA, настроенного в пользовательском ~/.kube/config на клиенте, чтобы можно было доверять соединению и быть уверенными, что оно не было перехвачено.

На этом этапе клиент может предоставить сертификат клиента TLS 1.2.

Аутентификация#

Как только TLS 1.2 установлен, HTTP-запрос переходит к этапу аутентификации.

При создании кластера DropApp администратор кластера DropApp настраивает сервер API для запуска одного или нескольких pods аутентификации.

Входными данными для этапа аутентификации является весь HTTP-запрос; однако обычно этот запрос проверяет заголовки и/или сертификат клиента.

Pods аутентификации (Policy) включают клиентские сертификаты, пароль и простые токены, токены начальной загрузки и веб-токены JSON (используются для учетных записей служб).

Можно указать несколько pods аутентификации, в этом случае каждый из pods проверяется последовательно, пока проверка одного из pods не завершится успешно.

Если запрос не может быть аутентифицирован, он отклоняется с кодом состояния HTTP 401. В противном случае пользователь аутентифицируется как определенный username, и имя пользователя доступно для использования.

Хотя DropApp использует имена пользователей для принятия решений по управлению доступом и регистрации запросов, у него нет пользовательского хранилища и он не хранит имена пользователей или другую информацию о пользователях в своем API.

Авторизация#

После проверки подлинности запроса, как исходящего от определенного пользователя, запрос должен быть авторизован.

Запрос должен включать:

  • имя пользователя, запрашивающего авторизацию;

  • само запрашиваемое действие (авторизацию);

  • объект, на который влияет действие (сама авторизация).

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

Например, если у пользователя maria есть политика, приведенная ниже, то он может читать pods только в namespace projectCaribou:

{
"apiVersion": "abac.authorization.kubernetes.io/v1beta1",
"kind": "Policy",
"spec": {
"user": "maria",
"namespace": "projectCaribou",
"resource": "pods",
"readonly": true
}
}

Если пользователь maria выполняет следующий запрос, запрос будет авторизован, поскольку пользователю maria разрешено читать объекты в namespace projectCaribou:

{
"apiVersion": "authorization.k8s.io/v1beta1",
"kind": "SubjectAccessReview",
"spec": {
"resourceAttributes": {
"namespace": "projectCaribou",
"verb": "get",
"group": "unicorn.example.org",
"resource": "pods"
}
}
}

Если пользователь maria отправляет запрос на запись (create или update) в объекты в namespace projectCaribou, то авторизация пользователя maria отклоняется. Если maria делает запрос на чтение (get) объектов в другом namespace, например, projectFish, то авторизация пользователя maria отклоняется.

Авторизация в DropApp требует, чтобы использовались общие атрибуты REST для взаимодействия с существующими системами контроля доступа в масштабах организации или облачного провайдера. Важно использовать форматирование REST, поскольку эти системы управления могут взаимодействовать с другими API, помимо API DropApp.

DropApp поддерживает несколько pods авторизации, таких как режим RBAC. Когда администратор создает кластер DropApp, он настраивает pods авторизации, которые должны использоваться на сервере API. Если настроено более одного pod авторизации, DropApp проверяет каждый pod, и если какой-либо pod разрешает запрос, то запрос может быть продолжен. Если все pods отклоняют запрос, то запрос отклоняется (код состояния HTTP 403).

Управление доступом#

Pods управления доступом – это программные pods, которые могут изменять или отклонять запросы. В дополнение к атрибутам, доступным pods авторизации, pods управления доступом могут получать доступ к содержимому создаваемого или изменяемого объекта.

Контроллеры доступа действуют на запросы, которые создают, изменяют, удаляют или подключаются к объекту (прокси). Контроллеры доступа не реагируют на запросы, которые просто считывают объекты. Когда настроено несколько контроллеров доступа, они вызываются по порядку.

В отличие от pods аутентификации и авторизации, если какой-либо pod контроллера допуска отклоняет запрос, то этот запрос немедленно отклоняется.

В дополнение к отклонению объектов контроллеры допуска также могут устанавливать сложные значения по умолчанию для полей.

Как только запрос проходит все контроллеры допуска, он проверяется с использованием процедур проверки для соответствующего объекта API, а затем записывается в хранилище объектов.

Аудит#

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

Обеспечение безопасности кластера DropApp#

  1. Сгенерируйте сертификаты при использовании проверки подлинности клиентского сертификата вручную с помощью easyrsa, openssl или cfssl.

  2. Опишите среду для управляемых контейнеров Kubelet на узле DropApp. Список всех служб, которые были запущены при создании контейнера, доступен для этого контейнера в качестве переменных среды. Этот список ограничен службами в том же namespace, что и pod нового контейнера, а также службы плоскости управления DropApp.

    Например, для службы с именем foo, которая сопоставляется контейнеру с именем bar, определены следующие переменные:

    FOO_SERVICE_HOST=<the host the service is running on>
    FOO_SERVICE_PORT=<the port the service is running on>
    
  3. Получите доступ к API DropApp, используя kubectl клиентские библиотеки или отправляя запросы REST.

  4. Во всех кластерах DropApp есть две категории пользователей: учетные записи служб, управляемые DropApp, и обычные пользователи.

    Предполагается, что независимая от кластера DropApp служба управляет обычными пользователями через администратора, распространяющего закрытые ключи. В связи с этим в DropApp нет объектов, которые представляют обычные учетные записи пользователей. Обычных пользователей нельзя добавить в кластер DropApp с помощью вызова API.

  5. Авторизация отделена от аутентификации и контролирует обработку HTTP-вызовов. Пройдите проверку подлинности, прежде чем запрос может быть авторизован (и предоставлено разрешение на доступ).

  6. Используйте контроллеры допуска explains plug-ins which intercepts requests to the DropApp API server after authentication and authorization.

Процесс контроля допуска выполняется в два этапа. На первом этапе выполняются изменяющие контроллеры допуска. На втором этапе выполняется проверка контроллеров допуска. Еще раз обратите внимание, что некоторые контроллеры выполняются обоими этапами.

Если какой-либо из контроллеров на любом этапе отклоняет запрос, весь запрос немедленно отклоняется, и конечному пользователю возвращается ошибка.

Контроллеры допуска иногда могут иметь побочные эффекты, то есть изменять связанные ресурсы как часть обработки запроса. Любой побочный эффект требует соответствующего процесса исправления или согласования, поскольку данный контроллер допуска не знает наверняка, что данный запрос пройдет все другие контроллеры допуска.

  1. Используйте функцию ядра SLO Sysctls в кластере DropApp, который описывает администратору, как использовать sysctl - интерфейс командной строки для установки параметров ядра.

  2. Используйте аудит, чтобы взаимодействовать с журналами аудита DropApp. Каждый запрос может быть записан с соответствующим этапом. Определенные этапы являются:

    • RequestReceived - этап для событий, генерируемых, как только обработчик аудита получает запрос, и до того, как он будет делегирован вниз по цепочке обработчиков.

    • ResponseStarted - этап после отправки заголовков ответа, но до отправки тела ответа. Этот этап генерируется только для длительных запросов (например, watch).

    • ResponseComplete - этап, когда ответ завершен, и байты отправляться не будут.

    • Panic - события, генерируемые при возникновении kernel panic.

Настройка кластера DropApp#

  1. При определении конфигураций укажите последнюю стабильную версию API.

  2. Файлы конфигурации храните в системе управления версиями перед отправкой в кластер DropApp. Это позволяет быстро откатить изменение конфигурации при необходимости. Это также помогает в повторном создании и восстановлении кластера.

  3. Запишите файлы конфигурации, используя YAML, а не JSON. Хотя эти форматы могут использоваться взаимозаменяемо почти во всех сценариях, YAML, как правило, более удобен для пользователя.

  4. Группируйте связанные объекты в один файл всякий раз, когда это имеет смысл. Часто одним файлом управлять проще, чем несколькими. Посмотрите файл guestbook-all-in-one.yaml в качестве примера этого синтаксиса.

    Обратите также внимание, что многие kubectl команды могут вызываться в каталоге. Например, можно вызвать каталог конфигурационных файлов kubectl apply.

  5. Не указывайте значения по умолчанию без необходимости: простая, минимальная конфигурация сделает ошибки менее вероятными.

  6. Поместите описания объектов в аннотации, чтобы обеспечить лучший самоанализ.

Naked pods в сравнении с наборами копий, развертываниями и заданиями#

Не используйте открытые pods (то есть pods, не привязанные к набору реплик или развертыванию), если можно этого избежать. Открытые pods не будут перенесены в случае сбоя узла.

Развертывание, которое одновременно создает набор копий, чтобы гарантировать, что желаемое количество pods всегда доступно, и определяет стратегию замены pods (например, RollingUpdate), почти всегда предпочтительнее, чем прямое создание pods.

Услуги#

Создайте службу перед соответствующими рабочими нагрузками ее серверной части (развертываниями или наборами реплик) и перед любыми рабочими нагрузками, которым требуется доступ к ней. Когда DropApp запускает контейнер, он предоставляет переменные среды, указывающие на все службы, которые были запущены при запуске контейнера. Например, если служба с именем foo существует, все контейнеры получат следующие переменные в своей исходной среде:

FOO_SERVICE_HOST=<the host the Service is running on>
FOO_SERVICE_PORT=<the port the Service is running on>

Это подразумевает требование к порядку – все, к чему pod может получить доступ, должно быть создано перед pod, иначе переменные среды не будут заполнены. DNS не имеет этого ограничения. Необязательным (хотя и настоятельно рекомендуемым) кластерным дополнением является DNS-сервер. DNS-сервер проверяет API DropApp на наличие новых services и создает набор записей DNS для каждой. Если DNS был включен во всем кластере DropApp, то все pods должны иметь возможность автоматически разрешать имена services.

Не указывайте hostPort для pod, если это не является абсолютно необходимым. Когда pod привязан к hostPort, это ограничивает количество мест, которые pod может запланировать, потому что каждая комбинация hostIP, hostPort, protocol должна быть уникальной. Если не указать hostIP и protocol явно, DropApp будет использовать 0.0.0.0 по умолчанию hostIP и TCP по умолчанию protocol.

Если нужен доступ к порту только для целей отладки, возможно использование прокси-сервера api-server или kubectl port-forward.

Если необходимо предоставить доступ к порту pod на узле, рассмотрите возможность использования службы NodePort, прежде чем прибегать к hostPort.

Использование меток#

Определите и используйте метки, которые идентифицируют семантические атрибуты приложения или развертывания, такие как { app.kubernetes.io/name: MyApp, tier: frontend, phase: test, deployment: v3 }. Можно использовать метки для выбора подходящих pods для других ресурсов; например, службы, которая выбирает все tier: frontend pods или все phase: test компоненты app.dropapp.io/name: MyApp.

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

Желаемое состояние объекта описывается deployment, и если применяются изменения к этой спецификации, контроллер развертывания изменяет фактическое состояние на желаемое состояние с контролируемой скоростью.

Используйте общие метки DropApp для распространенных вариантов использования. Эти стандартизированные метки обогащают метаданные таким образом, что позволяют инструментам, включая kubectl и панель управления, работать совместимым образом.

Можно манипулировать метками для отладки. Поскольку контроллеры DropApp (такие, как - ReplicaSet) и службы соответствуют pods с использованием меток выбора, удаление соответствующих меток из pod остановит его рассмотрение контроллером или передачу трафика службой. Если удалить метки существующего pod, его контроллер создаст новый pod, который займет его место. Для интерактивного удаления или добавления меток используйте kubectl label.