Как я могу позволить контейнеру (sidecar) завершиться в развертывании Kubernetes без его перезапуска?

Мое развертывание состоит из:

  • контейнер инициализации
  • длительный сервис
  • сопроводительный файл, который необходимо настроить для связанной службы.

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

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

Есть ли способ разрешить завершение работы контейнера без его перезапуска при развертывании? В качестве альтернативы, есть ли способ, чтобы контейнер инициализации работал вместе с обычными контейнерами?

Некоторые детали для решения проблем XY:

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

Пример:

#my-service.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-service
spec:
  replicas: 1
  template:
    spec:
      initContainers:
        - name: my-service-init
          image: my-service
          imagePullPolicy: IfNotPresent
          env:
          - name: DATABASE_URL
            value: postgres://postgres:postgres_password@$db_host:5432/database
          args: ['init_script.py']
      containers:
        - name: my-service
          env:
          - name: DATABASE_URL
            value: postgres://db_role:db_password@$db_host:5432/database
          image: my-service
          imagePullPolicy: IfNotPresent
          args: ['main.py']
        - name: related-service-configure
          env:
          - name: RELATED_API_SERVICE_ADMIN_ENDPOINT
            value: http://related_api_service/api/
          image: my-service
          imagePullPolicy: IfNotPresent
          args: ['manage_related_service.py']
#related-api-service.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: related-api-service  
spec:
  replicas: 1
  template:
    spec:
      containers:
        - name: related-api-service
          env:
          - name: DATABASE_URL
            value: postgres://db_role:db_password@$db_host:5432/database
          image: related-api-image
          imagePullPolicy: IfNotPresent
          ports:
          - containerPort: 8080
            name: http
            protocol: TCP
#manage_related_service.py
import time
import requests
import json


def upgrade_metadata(query_url, metadata_file):
    with open(metadata_file) as fp:
        metadata = json.load(fp)

    print(f"Querying {query_url}...")
    rsp = requests.post(query_url, json=metadata)
    response = rsp.json()
    print(f"Response to request was:\n{response}")
    if response.get('success') != 'True':
        raise ValueError("Metadata upgrade was not successful")


if __name__ == '__main__':
    from environs import Env
    env = Env()
    env.read_env()

    RELATED_API_SERVICE_ADMIN_ENDPOINT = env("RELATED_API_SERVICE_ADMIN_ENDPOINT")
    METADATA_FILE = env("METADATA_FILE", "metadata.json")

    upgrade_metadata(RELATED_API_SERVICE_ADMIN_ENDPOINT, METADATA_FILE)

    # Once metadata has been uploaded, sleep forever
    while True:
        time.sleep(3600)

person Nan Lin    schedule 16.01.2020    source источник
comment
Интересный вопрос. Не уверен, есть ли какой-нибудь чистый способ, кроме взлома livenessProbe, установив для него очень высокое значение.   -  person Shashank V    schedule 17.01.2020
comment
Этот вопрос особенно выиграет от MCVE, поскольку очень сложно говорить абстрактно; при этом, если у вас есть контроль над command: модуля, то command: ["bash", "-c", "long-running &\nexec the-main-service"] может быть тем, что вы ищете   -  person mdaniel    schedule 17.01.2020
comment
Это не ответ на точный вопрос, так как вы хотите использовать контейнер sidecar, но вы также можете попробовать посмотреть, можете ли вы использовать Post-start хуки для вашего варианта использования.   -  person Shashank V    schedule 17.01.2020
comment
Я посмотрю, что я могу сделать с точки зрения MCVE - это больше о конфигурации Kubernetes или базовых службах? Между прочим, у @mdaniel, выполняющего несколько процессов, есть обратная сторона: если long-running выйдет из строя, он не будет перезапущен кубернетами, но это все равно может быть приемлемым компромиссом.   -  person Nan Lin    schedule 17.01.2020


Ответы (1)


Я думаю, вам следует создавать рабочие места Kubernestes вместо Развертывания. Затем вы должны завершить работу с сайдкаром. После этого конкретный контейнер также будет автоматически завершен.

Вы можете имитировать определенное поведение коляски. Вот пример сценария, который поможет вам в этом:

containers:
  - name: example
    image: gcr.io/some/image:latest
    command: ["/bin/bash", "-c"]
    args:
      - |
        trap "touch /tmp/pod/main-terminated" EXIT
        /my-batch-job/bin/main --config=/config/my-job-config.yaml
    volumeMounts:
      - mountPath: /tmp/pod
        name: tmp-pod
  - name: envoy-container
    image: gcr.io/our-envoy-plus-bash-image:latest
    command: ["/bin/bash", "-c"]
    args:
      - |
        /usr/local/bin/envoy --config-path=/my-batch-job/etc/envoy.json &
        CHILD_PID=$!
        (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; fi; sleep 1; done) &
        wait $CHILD_PID
        if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; fi
    volumeMounts:
      - mountPath: /tmp/pod
        name: tmp-pod
        readOnly: true
volumes:
  - name: tmp-pod
    emptyDir: {}

Дополнительную информацию можно найти здесь: остановка коляски, поведение коляски.

person Malgorzata    schedule 30.01.2020
comment
@Nan Lin Это ответ на ваш вопрос. Вы пробовали создать работу? - person matt_j; 17.03.2021