Kubernetes: Лучшая поддержка контейнеров с коляской в ​​пакетных заданиях

Созданный на 19 мая 2016  ·  116Комментарии  ·  Источник: kubernetes/kubernetes

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

Какие существуют варианты для этого? Какие варианты должны существовать?

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

Некоторое время назад этот вопрос был задан в Stack Overflow, и нет лучшего ответа, чем изменить второй контейнер, чтобы он больше ориентировался на Kubernetes, что не идеально. Другой клиент недавно сказал мне об этом как о болевой точке.

@ kubernetes / goog-control-plane @erictune

arebatch areworkload-apjob kinfeature lifecyclfrozen prioritimportant-longterm siapps sinode

Самый полезный комментарий

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

containers:
  - name: main
    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
    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: {}

Все 116 Комментарий

/ sub

Также использование проблемы живучести, как предложено здесь http://stackoverflow.com/questions/36208211/sidecar-containers-in-kubernetes-jobs , не работает, поскольку модуль будет считаться неудачным, а общее задание не будет считаться успешным.

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

Может ли зонд работать с контейнером, который уже вышел, или будет там
быть гонкой, в которой ее сносят?

Другой вариант - обозначить определенные коды выхода как имеющие особое значение.

И «Успех для всего модуля», и «Неудачный для всего модуля» являются
полезный.

Это должно быть в объекте Pod, так что это большое изменение API.

22 сентября 2016 г. в 13:41 Мин Фанг [email protected] написал:

Как насчет того, чтобы мы объявили проверку успешности работы, чтобы Иов мог ее проверить?
обнаруживать успех вместо того, чтобы ждать, пока модуль вернет 0.

Как только зонд вернет успешный результат, модуль может быть прекращен.

-
Вы получаете это, потому что вас упомянули.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -249021627,
или отключить поток
https://github.com/notifications/unsubscribe-auth/AHuudjrpVtef6U35RWRlZr3mDKcCRo7oks5qsugRgaJpZM4IiqQH
.

@erictune Хорошее замечание; мы не можем исследовать вышедший контейнер.

Можно ли обозначить конкретный контейнер в модуле как контейнер «завершения», чтобы при выходе из этого контейнера мы могли сказать, что работа завершена?

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

Можно ли обозначить конкретный контейнер в модуле как контейнер «завершения», чтобы при выходе из этого контейнера мы могли сказать, что работа завершена?

Вы изучили этот пункт 3 документа, подробно описанный здесь, где вы в основном не устанавливаете .spec.completions и как только первый контейнер заканчивается с кодом выхода 0, задания выполняются.

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

Лично мне они больше похожи на RS, чем на работу, но это мое личное мнение и, самое главное, я не знаю всех деталей вашей настройки.

Как правило, следующие обсуждения https://github.com/kubernetes/kubernetes/issues/17244 и https://github.com/kubernetes/kubernetes/issues/30243 также затрагивают эту тему.

@soltysh ссылка, которую вы отправили выше, точка 3 ссылается на завершение пода, а не на завершение контейнера.

Два контейнера могут совместно использовать emptyDir и первый контейнер и писать сообщение «Я выхожу сейчас» в файл, а другой может выйти, когда увидит это сообщение.

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

Я использую библиотеку client-go, чтобы закодировать все, что ниже:

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

Мне удалось сохранить этот файл результатов, если я использовал HostPath в качестве VolumeSource, и, поскольку я запускаю minikube локально, файл результатов сохраняется на моей рабочей станции.

Но я понимаю, что это не рекомендуется и идеально подходит для производственных контейнеров. Итак, я использовал EmptyDir как было предложено выше. Но, опять же, если я это сделаю, я не смогу захватить его, потому что он будет удален вместе с самим модулем.

Итак, должен ли я решать свою проблему, используя также шаблон контейнера с коляской?

В принципе, делайте то, что вы предложили выше. При запуске задания запускайте 2 контейнера в модуле. 1 контейнер запускает задание и, как только задание будет выполнено, отбрасывает сообщение, которое получает другой контейнер, который затем захватывает файл результатов и сохраняет его где-нибудь?

Я не понимаю, зачем нам вообще нужны 2 контейнера. Почему контейнер заданий не может сделать все это самостоятельно? То есть завершить работу, сохранить где-нибудь файл результатов, получить к нему доступ / прочитать и где-нибудь сохранить.

@anshumanbh Я бы посоветовал вам:

  1. использовать постоянное хранилище, вы сохраняете файл результатов
  2. используйте hostPath mount, что почти то же самое, что и 1, и вы уже пробовали это
  3. загрузить файл результатов в известное удаленное место (s3, google drive, dropbox), как правило, на любой общий диск

@soltysh Я не хочу, чтобы файл хранился постоянно. При каждом запуске я просто хочу сравнивать этот результат с последним результатом. Итак, я думал сделать это при каждом запуске фиксации в репозитории github, а затем выполнять сравнение, чтобы увидеть, что изменилось. Итак, для этого мне просто нужно временно где-то сохранить результат, чтобы я мог получить к нему доступ и отправить его в Github. Есть смысл?

@anshumanbh совершенно ясно, и все же он не попадает в категорию контейнеров с

@soltysh, поэтому, учитывая, что я хочу выбрать вариант 3 из списка, который вы предложили выше, как мне его реализовать?

Проблема, с которой я столкнулся, заключается в том, что как только работа завершается, контейнер закрывается, и я теряю файл. Если у меня нет файла, как мне загрузить его на общий диск, например S3 / Google Drive / Dropbox? Я не могу изменить код задания, чтобы он автоматически загружался куда-нибудь до того, как он завершится, поэтому, к сожалению, мне пришлось бы сначала запустить задание, а затем где-нибудь сохранить файл ..

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

@soltysh да, в этом есть смысл. Я могу сделать это. Однако следующий у меня вопрос: предположим, мне нужно запустить несколько заданий (подумайте об этом как о запуске разных инструментов), и ни один из этих инструментов не имеет встроенной части загрузки. Итак, теперь мне нужно было создать эту оболочку и расширить каждый из этих инструментов с помощью части загрузки. Есть ли способ просто написать оболочку / расширение один раз и использовать ее для всех инструментов?

Разве в этом случае не подошел бы рисунок боковой машины?

Да, может. Хотя я бы попробовал использовать несколько контейнеров внутри одного модуля, pattern. Айау. ваш модуль запускает контейнер заданий и еще один, ожидающий вывода и загружающий его. Не уверен, насколько это возможно, но вы уже можете попробовать.

Мягкий ping-sidecar сделает управление прокси-серверами микросервисов, такими как Envoy, намного более приятным. Есть ли прогресс, которым можно поделиться?

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

Ранее предлагалось обозначить некоторые контейнеры как контейнер «завершения». Я предлагаю обратное - возможность обозначать некоторые контейнеры как «коляски». Когда последний контейнер, не являющийся дополнительным элементом, в модуле завершается, модуль должен отправить TERM вспомогательным машинам. Это было бы аналогично концепции «фонового потока», присутствующей во многих библиотеках потоковой передачи, например, в Python Thread.daemon .

Пример конфигурации, когда контейнер main завершается, кубелет убивает envoy :

containers:
  - name: main
    image: gcr.io/some/image:latest
    command: ["/my-batch-job/bin/main", "--config=/config/my-job-config.yaml"]
  - name: envoy
    image: lyft/envoy:latest
    sidecar: true
    command: ["/usr/local/bin/envoy", "--config-path=/my-batch-job/etc/envoy.json"]

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

containers:
  - name: main
    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
    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: {}

Я предлагаю обратное - возможность обозначать некоторые контейнеры как «коляски». Когда последний контейнер, не являющийся дополнительным элементом, в Pod завершается, Pod должен отправить TERM в боковые вагоны.

@ jmillikin-stripe Мне нравится эта идея, хотя я не уверен, следует ли она принципу, согласно которому некоторые контейнеры обрабатываются по-разному в Pod'е или вводятся зависимости между ними. Я полагаюсь на

Хотя вы проверили # 17244, подойдет ли этот тип решения вашему варианту использования? Это то, что @erictune упомянул несколькими комментариями ранее:

Другой вариант - обозначить определенные коды выхода как имеющие особое значение.

@ jmillikin-stripe Мне нравится эта идея, хотя я не уверен, следует ли она принципу, согласно которому некоторые контейнеры обрабатываются по-разному в Pod'е или вводятся зависимости между ними. Я полагаюсь на

Я думаю, что Kubernetes, возможно, должен проявить гибкость в отношении принципа не обращаться с контейнерами по-разному. Мы (Stripe) не хотим модифицировать сторонний код, такой как Envoy, чтобы иметь хуки жизненного цикла в стиле Lamprey, и попытка принять инверсию exec в стиле Envelope будет намного сложнее, чем позволить Kubelet завершать определенные сайдкары.

Хотя вы проверили # 17244, подойдет ли этот тип решения вашему варианту использования? Это то, что @erictune упомянул несколькими комментариями ранее:

Другой вариант - обозначить определенные коды выхода как имеющие особое значение.

Я категорически против того, чтобы Kubernetes или Kubelet интерпретировали коды ошибок с более высокой степенью детализации, чем «ноль или ненулевой». Использование Борглетом магических чисел кода выхода было неприятной ошибкой, и было бы намного хуже в Kubernetes, где конкретный образ контейнера мог быть либо «основным», либо «вспомогательным» в разных подах.

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

Может быть:

  • PostStop: со средством запуска событий жизненного цикла для других контейнеров в модуле (т.е. остановка триггера)
  • PeerStopped: сигнализирует о том, что «одноранговый» контейнер в модуле умер - возможно, с кодом выхода в качестве аргумента.

Это также может определять средства для определения настраиваемых политик для перезапуска контейнера - или даже запуска контейнеров, которые не запускаются по умолчанию, чтобы разрешить некоторую последовательную цепочку контейнеров (когда контейнер a завершается, запускайте контейнер b)

Также отсутствует это. Каждые 30 минут мы запускаем задание, которому нужен VPN-клиент для подключения, но, похоже, есть много случаев использования, когда это может быть очень полезно (например, для чего нужен прокси kubectl). В настоящее время я использую jobSpec.concurrencyPolicy: Replace в качестве обходного пути, но, конечно, это работает только в том случае, если а.) Вы можете жить без параллельных запусков заданий и б.) Время выполнения задания короче, чем интервал планирования.

РЕДАКТИРОВАТЬ: в моем случае использования было бы вполне достаточно иметь какое-то свойство в спецификации задания, чтобы пометить контейнер как завершающий и иметь монитор задания для статуса выхода и убить оставшиеся.

Мне тоже это нужно. В нашем случае это работа, которая использует контейнер cloudql-proxy в качестве дополнительной службы.

Как насчет возможного добавления аннотации, которая соответствует имени «основного» контейнера в модуле? Таким образом, ни в коем случае не нужно изменять спецификацию модуля.

По характеру того, как устроены модули, это очень распространенный вариант использования. @soltysh @erictune есть планы поработать над этим в ближайшее время? Рад помочь где возможно :)

Также нужна эта функция. Для нашего случая использования :
pod A должен быть в контейнерах

  • контейнер A1 :
  • контейнер A2 : контейнер sidecar, который просто передает логи из файла в стандартный вывод

Что я хочу : когда контейнер A1 завершится успешно, модуль A завершится успешно. Можем ли мы просто пометить контейнер A1 как основной контейнер , когда основной контейнер выходит, контейнер выходит? @erictune (эту идею также описывает @mingfang )

Привет, ребята, я вижу, что этот вопрос открыт уже месяц. Что нового по этому поводу? У нас есть вариант использования, когда мы хотим запустить задание. Задание запускает контейнер main с несколькими боковыми вагонами containers . Мы хотим, чтобы задание завершалось при выходе из контейнера main . Является ли современный уровень техники совместным использованием file для отправки signal между контейнерами?

Я был бы не против начать некоторую работу над этим, хотел бы знать, сможет ли кто-нибудь просмотреть предстоящие PR, если я это сделаю (возможно, после kubecon).

коп @erictune @ a-robinson @soltysh

@andrewsykim какой подход вы бы main не должен запускаться, пока боковые тележки не инициализированы

Как будто основной контейнер не должен запускаться, пока боковые тележки не инициализированы

Я думаю, что этот случай не является проблемой, поскольку main должен иметь возможность проверять, когда инициализируется вспомогательный элемент (или использовать проверку готовности). Это не относится к этой проблеме, потому что main вышел бы :)

Я закончил тем, что написал простой скрипт, который следит за kubernetes API и завершает задания с помощью соответствующей аннотации и чей основной контейнер завершился. Это не идеально, но удовлетворяет основные потребности. Могу поделиться, если людям интересно.

@ajbouh Я был бы лично признателен, если бы вы поделились этим как суть. Я собирался написать что-то подобное

@nrmitchi Вот суть написанного мною ямла. Это очень сценарий оболочки, но, возможно, это хорошая отправная точка для вас с точки зрения того, какие API использовать и как получить что-то, что работает. Я могу ответить на вопросы о том, что он делает, если у вас возникнут вопросы.

https://gist.github.com/ajbouh/79b3eb4833aa7b068de640c19060d126

У меня такой же вариант использования прокси-сервера Cloud SQL, как и у @mrbobbytables. Для безопасного подключения к облачному SQL рекомендуется использовать прокси, но этот прокси не завершается после завершения работы, что приводит к сумасшедшим взломам или мониторингу, которые выглядят следующим образом. Есть ли в этом какой-то путь вперед?

image

@ amaxwell01 Что касается https://issuetracker.google.com/issues/70746902 (изменить: и я сожалею о некоторых фразах, которые я использовал там сгоряча; к сожалению редактировать не могу)

Спасибо @abevoelker Я слежу за вашим постом там. Плюс твои комментарии рассмешили меня 👍

Мы тоже сталкиваемся с этой проблемой.
У нас есть несколько команд управления django в наших микросервисах, которые могут работать на k8s cronjobs, но не могут быть успешными из-за сопутствующего файла cloudqlproxy, который не останавливается при завершении задания.
Есть новости о том, когда у нас может быть решение?
Шаблон контейнера sidecar используется все больше и больше, и многие из нас не смогут использовать cronjobs и задания k8s, пока эта проблема не будет решена.

Просто хотел добавить за это свой +1. У меня такая же проблема с прокси-сервером GCE Cloud SQL, как и у всех остальных. Это меня убивает ... сбой развертывания руля, что, в свою очередь, не позволяет применить мою терраформу.

Очень хотелось бы увидеть какое-то решение по этому поводу ... jist от

Для кого-то еще, требующего cloudsql-proxy , подойдет ли вашему варианту использования запуск cloudsql-proxy как DaemonSet? В моем случае у меня было как постоянное развертывание, так и CronJob, требующий прокси, поэтому имело смысл отсоединить его от отдельных подов и вместо этого прикрепить по одному экземпляру к каждому узлу.

Да,

Мы решили удалить побочные прокси-серверы cloudql и создали пул
Cloudql прокси в своем центральном пространстве имен, он отлично работает и позволяет
масштабируемость и упрощение развертывания.
Теперь мы можем без проблем запускать задания и cronjobs.

В среду, 7 февраля 2018 г., в 9:37, Роб Джексон [email protected]
написал:

Для кого-то еще, кому требуется cloudql-proxy, подойдет ли он для вашего варианта использования
запустить cloudql-proxy как DaemonSet? В моем случае у меня были как постоянные
Развертывание и CronJob, требующие прокси, поэтому имело смысл отсоединить
это из отдельных модулей и вместо этого прикрепите по одному экземпляру к каждому узлу.

-
Вы получили это, потому что прокомментировали.
Ответьте на это письмо напрямую, просмотрите его на GitHub
https://github.com/kubernetes/kubernetes/issues/25908#issuecomment-363710890 ,
или отключить поток
https://github.com/notifications/unsubscribe-auth/ACAWMwetx6gA_SrHL_RRbTMJVOhW1FKLks5tSW7JgaJpZM4IiqQH
.

Интересно, что использование деамонсета кажется хорошим вариантом. @ RJacksonm1 & @devlounge - как работает обнаружение облачного прокси-сервера sql при использовании наборов демонов?

Нашел это, похоже, это поможет ...
https://buoyant.io/2016/10/14/a-service-mesh-for-kubernetes-part-ii-pods-are-great-until-theyre-not/

В основном включает в себя использование чего-то вроде этого для получения IP-адреса хоста:

env:
- name: NODE_NAME
  valueFrom:
    fieldRef:
      fieldPath: spec.nodeName

@ RJacksonm1 - Вы сделали что-нибудь особенное, чтобы hostPort ? Я постоянно получаю connection refused при использовании в сочетании с подходом fieldPath: spec.nodeName 🤔

Изменить: я убедился, что spec.nodeName проходит правильно, и я нахожусь на GKE v1.9.2-gke.1

@cvallance У меня есть служба, настроенная для предоставления DaemonSet, к которой мое приложение может получить доступ через DNS. Это не гарантирует, что приложение будет взаимодействовать с экземпляром cloudsql-proxy запущенным на том же хосте, что и он сам, но это гарантирует, что cloudsql-proxy будет масштабироваться вместе с кластером в целом (изначально у меня был прокси в качестве Deployment и HorizontalPodAutoscaler, но обнаружил, что он слишком сильно масштабируется вверх / вниз, вызывая ошибки MySQL has gone away в приложении). Думаю, это не в духе DaemonSet ... 🤔

@ RJacksonm1 - заработал с hostPort и spec.nodeName ... теперь они будут подключаться напрямую к DaemonSet на своем узле 😄

Команда CloudSql Proxy не работает:
-instances={{ .Values.sqlConnectionName }}=tcp:{{ .Values.internalPort }}
Работающий:
-instances={{ .Values.sqlConnectionName }}=tcp:0.0.0.0:{{ .Values.internalPort }}

🤦‍♂️

Что мы можем сделать, чтобы решить эту проблему?
Он был открыт уже почти 2 года, и до сих пор у нас есть только обходные пути

Я подозреваю, что даже если я добровольно предложу реализовать это, я не смогу это сделать, поскольку для этого требуется некоторое одобрение от внутренних ребят относительно того, какое решение реализовать, изменения API и т. Д.

Что я могу сделать, чтобы это сделать?

Для справки я создал версию обходного пути @ jmillikin-stripe для облака-sql-proxy, где файл на общем томе передает состояние сопроводительной машине.

Он работает нормально, но это, безусловно, самый неприятный прием в моей конфигурации K8s :(

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  template:
    spec:
      containers:
      - name: example-job
        image: eu.gcr.io/example/example-job:latest
        command: ["/bin/sh", "-c"]
        args:
          - |
            trap "touch /tmp/pod/main-terminated" EXIT
            run-job.sh
        volumeMounts:
          - mountPath: /tmp/pod
            name: tmp-pod
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.11
        command: ["/bin/sh", "-c"]
        args:
          - |
            /cloud_sql_proxy --dir=/cloudsql -instances=example:europe-west3:example=tcp:3306 -credential_file=/secrets/cloudsql/credentials.json &
            CHILD_PID=$!
            (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; echo "Killed $CHILD_PID as the main container terminated."; fi; sleep 1; done) &
            wait $CHILD_PID
            if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; echo "Job completed. Exiting..."; fi
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: cloudsql
            mountPath: /cloudsql
          - mountPath: /tmp/pod
            name: tmp-pod
            readOnly: true
      restartPolicy: Never
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
        - name: cloudsql
          emptyDir:
        - name: tmp-pod
          emptyDir: {}
  backoffLimit: 1

Может ли кто-нибудь из сотрудников проекта прокомментировать, как продвигается эта проблема?

Такая же проблема здесь

cc @ kubernetes / sig-apps-feature-requests @ kubernetes / sig-node-feature-requests

Имеет ли смысл разрешить пользователям указывать (по имени) контейнеры в задании, которые они хотят видеть успешно завершенными, чтобы пометить модуль заданий как выполненный (с остановленными другими контейнерами), например:

apiVersion: batch/v2beta1
kind: Job
metadata:
  name: my-job
  namespace: app
spec:
  template:
    spec:
      containers:
        - name: my-container
          image: my-job-image
          ...
        - name: cloudsql-proxy
          image: gcr.io/cloudsql-docker/gce-proxy:1.11
          ...
  backoffLimit: 2
  jobCompletedWith:
    - my-container

Т.е. модуль будет работать, ждать, пока my-container успешно завершится, а затем просто завершит работу cloudsql-proxy .

РЕДАКТИРОВАТЬ: прокручивая эту тему, теперь я вижу, что это было предложено ранее. Может ли @erictune или кто-то еще уточнить, почему это не сработает?

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

Да, это было бы идеально.

Мне нравится эта идея @jpalomaki

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

Вы можете заставить контроллер заданий удалить Pod, когда контроллер решит, что это сделано, но это также будет отличаться от текущего поведения, когда запись Terminated Pod остается на сервере API (без использования ресурсов узла).

По этим причинам мне кажется более понятным решить эту проблему на уровне Pod API, если вообще. Узел - это единственное, что должно достигать и уничтожать отдельные контейнеры, потому что «завершающие» контейнеры, о которых вы заботитесь, уже завершены. Это может быть либо API-интерфейс уровня Pod, который позволяет вам указать, какие контейнеры следует ожидать, либо API-интерфейс уровня Pod, позволяющий внешним агентам (например, контроллеру заданий) принудительно завершать работу Pod-модуля без фактического удаления. стручок.

Я также ищу решение для загрузки файлов, созданных контейнером, если контейнер процессора успешно завершился.

Я не уверен, что понимаю аргумент @mingfang против того, чтобы контейнер sidecar следил за состоянием контейнера через API k8s, чтобы знать, когда и когда начинать загрузку или выход. Когда контейнер с коляской покидает капсулу, работа должна быть успешно завершена.

Еще одна мысль, которая действительно кажется взломом, но я хотел бы знать, насколько плохо было бы превратить контейнер, производящий данные, в контейнер инициализации и иметь контейнер для загрузки данных (который больше не должен быть контейнером sidecar ) автоматически запускается только после успешного выхода из контейнера процессора. В моем случае мне также понадобится контейнер загрузчика данных в качестве первого контейнера инициализации, чтобы предоставить данные в контейнер обработки. Если это особенно плохая идея, я хотел бы узнать, почему.

Разве продвижение коляски к первоклассной концепции k8s не решило бы эту проблему? Kubelet сможет завершить работу модуля, если все запущенные в нем контейнеры отмечены как вспомогательные.

FWIW, я работал над этим, просто развернув прокси Cloud SQL как обычное развертывание ( replicas: 1 ) и заставил мои Job и CronJob использовать его через type: ClusterIP услуга. Работа сейчас в полном порядке.

Я хотел бы получить официальную позицию по этому поводу.

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

Я не уверен, к кому пинговать или как привлечь к этому внимание ...

Было бы действительно неплохо решить эту проблему. В дополнение к тому, что задание никогда не исчезнет, ​​общий статус модуля явно неверен:

Init Containers:
  initializer:
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 21 Mar 2018 17:52:57 -0500
      Finished:     Wed, 21 Mar 2018 17:52:57 -0500
    Ready:          True
Containers:
  sideCar:
    State:          Running
      Started:      Wed, 21 Mar 2018 17:53:40 -0500
    Ready:          True
  mainContainer:
    State:          Terminated
      Reason:       Completed
      Exit Code:    0
      Started:      Wed, 21 Mar 2018 17:53:41 -0500
      Finished:     Wed, 21 Mar 2018 17:55:12 -0500
    Ready:          False
Conditions:
  Type           Status
  Initialized    True 
  Ready          False 
  PodScheduled   True 

Что интересно, обратите внимание на состояние и готовность для initContainer (Завершено, Завершено, Готово = Истина) и основного контейнера приложения (Завершено, Завершено, Готово = Ложь). Похоже, это приводит к тому, что состояние «Готовность стручка» имеет значение «Ложь» - на мой взгляд, неправильно. Это приводит к тому, что этот модуль помечается как имеющий проблему на наших информационных панелях.

У меня есть еще один клиент, столкнувшийся с этой проблемой именно с прокси Cloud SQL. Они не хотели бы запускать его как постоянную службу, чтобы задания cron могли получать доступ к Cloud SQL.

@yuriatgoogle Самым простым решением остается "магия" bash и emptyDir, например: https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -365924958

Это хакер, но с ним нужно работать. Не оскорбляю @phidah.

Определенно кажется, что многие люди хотят этого по разным причинам. Было бы хорошо получить официальную поддержку. У меня была такая же проблема с нашей собственной коляской и заданиями, поэтому я попросил ее использовать kube api для наблюдения за статусом другого контейнера в модуле, если он завершается с помощью completed боковая машина выйдет из 0, если это приводило к ошибке, и коляска выходила 1. Возможно, это не самое элегантное решение, но оно помогло, и наши разработчики не потребовали значительных изменений. код здесь, если кому-то интересно: https://github.com/uswitch/vault-creds/blob/master/cmd/main.go#L132.

Это напоминает мне песню Gorillaz M1 A1 ...

Привет? Приветоооооо? Кто-то там?

Да, давайте, пожалуйста, наберитесь сил +1

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

  1. sidecar: true от @ jmillikin-stripe
  2. Дополнительные хуки жизненного цикла от @msperl
  3. jobCompletedWith от @jpalomaki

Временное решение для коляски, хакерское (но работает):

  1. За cloudsql-proxy sidecar от @phidah

Мне бы очень хотелось увидеть ответ разработчика Kubernetes относительно предлагаемых решений и дать нам рекомендации, как решить этот вариант использования с использованием существующей версии Kubernetes. Спасибо!

Только что обнаружил этот поток, потратив день на попытки написать агент журнала, который загружал бы stdout / stderr моей задачи рендеринга в базу данных, только чтобы обнаружить, что присутствие агента в модуле будет означать, что задание никогда не будет завершено.

Из приведенных выше предложений мне больше всего нравится «sidecar: true», поскольку оно простое и по существу - очень понятное для такого разработчика, как я. Я бы, вероятно, назвал это чем-то немного другим, поскольку «sidecar» на самом деле является шаблоном проектирования модуля, который применяется не только к заданиям, но и подразумевает другие вещи, помимо требований к завершению. Если вы извините за мой отказ от велосипеда, я бы, вероятно, назвал это чем-то вроде «ambient: true», чтобы указать, что задание можно считать выполненным, даже если оно все еще выполняется. Другими словами могут быть «вспомогательные» или «вспомогательные».

Я также столкнулся с этой проблемой для того же рабочего процесса, который описывали многие другие (контейнер sidecar, который используется для проксирования соединений или сбора метрик и не имеет цели после успешного завершения другого контейнера в модуле).

Ранее предлагалось обозначить некоторые контейнеры как контейнер «завершения». Я предлагаю обратное - возможность обозначать некоторые контейнеры как «коляски». Когда последний контейнер, не являющийся дополнительным элементом, в Pod завершается, Pod должен отправить TERM в боковые вагоны.

Это мое идеальное решение. Я мог бы предложить SIGHUP вместо SIGTERM - похоже, это точный вариант использования, для которого актуальна семантика SIGHUP! - но я был бы доволен любым из них.

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

Я хотел бы сделать патч для этого, но хотел бы получить некоторые рекомендации от @ kubernetes / sig-apps-feature-requests, прежде чем копаться в любом коде. Мы согласны с добавлением поля sidecar в спецификацию модуля, чтобы эта работа работала? Я не решаюсь вносить какие-либо изменения в спецификации модуля, не будучи уверенным, что мы этого хотим. Может, пока воспользуемся аннотациями?

@andrewsykim Я

Я рассуждаю так:

  • Эта проблема существует уже почти 2 года и не особо привлекла внимание ядра kubernetes. Следовательно, если мы дождемся внесения изменений в спецификацию модуля или прямого ввода, мы, вероятно, будем ждать очень долго.
  • Работоспособный PR намного легче привлечь внимание, чем старый вопрос.
  • Каждый должен быть хорош, чтобы переключить подход к аннотации для использования атрибута pod в будущем.

Мысли?

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

Я создал PR для предложения по усовершенствованию, чтобы решить эту проблему, поэтому я надеюсь, что это вызовет некоторое обсуждение https://github.com/kubernetes/community/pull/2148.

Спасибо за то, что собрал это, @ Joseph-Irving! Похоже, есть еще кое-что, что нужно решить для этого, поэтому я воздержусь от работы до тех пор :)

постоянная долгосрочная проблема :(

cc @ kow3ns @janetkuo

Не желая еще больше усложнять ситуацию, было бы также полезно иметь возможность запускать контейнер в стиле «sidecar» вместе с initContainers .

Мой вариант использования похож на людей здесь: мне нужно запустить облачный прокси-сервер sql одновременно с initContainer, который выполняет миграцию базы данных. Поскольку initContainers запускаются по одному, я не вижу способа сделать это, кроме как запустить прокси как службу развертывания +, но я ожидаю, что есть другие варианты использования (управление журналами и т. Д.), Где это не будет подходящей работой вокруг.

@mcfedr Есть достаточно активное предложение по усовершенствованию, которое может оценить это наблюдение, касающееся поведения контейнера инициализации. Мне неясно, входит ли это в объем данного предложения или связанное с ним улучшение, но я думаю, что это достаточно связано, и имеет смысл вынести его на рассмотрение.

Несмотря на потенциальные проблемы с реализацией / совместимостью, ваша идеальная модель, по-видимому, должна была бы состоять в том, чтобы контейнеры инициализации sidecar запускались одновременно с контейнерами инициализации non-sidecar, которые продолжают работать последовательно, как сейчас, и чтобы вспомогательные машины завершали работу до запуска контейнеров основной последовательности?

как бы то ни было, я также хотел бы выразить необходимость игнорировать боковые машины, все еще работающие как CloudSQL Proxy et.al.

Мне удалось убить контейнер cloudsql через 30 секунд, так как я знаю, что мой сценарий не займет так много времени. Вот мой подход:

apiVersion: batch/v1beta1
kind: CronJob
metadata:
  name: schedule
spec:
  concurrencyPolicy: Forbid
  schedule: "*/10 * * * *"
  startingDeadlineSeconds: 40
  jobTemplate:
    spec:
      completions: 1
      template:
        spec:
          containers:
          - image: someimage
            name: imagename
            args:
            - php
            - /var/www/html/artisan
            - schedule:run
          - command: ["sh", "-c"]
            args:
            - /cloud_sql_proxy -instances=cloudsql_instance=tcp:3306 -credential_file=some_secret_file.json & pid=$! && (sleep 30 && kill -9 $pid 2>/dev/null)
            image: gcr.io/cloudsql-docker/gce-proxy:1.11
            imagePullPolicy: IfNotPresent
            name: cloudsql
            resources: {}
            volumeMounts:
            - mountPath: /secrets/cloudsql
              name: secretname
              readOnly: true
          restartPolicy: OnFailure
          volumes:
          - name: secretname
            secret:
              defaultMode: 420
              secretName: secretname

И это работает для меня.
Вы, ребята, не видите недостатков в этом подходе?

Поскольку я думаю, что они связаны и легко адаптируются для CronJobs, это мое решение: https://github.com/GoogleCloudPlatform/cloudsql-proxy/issues/128#issuecomment -413444029

Он основан на одном из описанных здесь обходных путей, но использует preStop потому что он предназначен для развертываний. Но запереть коляску было бы замечательно.

Следуя этой проблеме. Также используется контейнер cloud_sql_proxy в качестве дополнительной машины в cronjob
Я использовал реализацию тайм-аута @stiko

Просто добавив к разговору решение, предложенное @xygen0211 по использованию Replace, на данный момент является достойным обходным путем, обязательно проверьте его, если вы

https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -327396198

У нас есть этот KEP, предварительно одобренный https://github.com/kubernetes/community/pull/2148 , у нас все еще есть несколько вещей, которые нам нужно согласовать, но, надеюсь, он дойдет до того места, где работа над ним может начаться относительно скоро . Обратите внимание, что KEP будут перемещены на https://github.com/kubernetes/enhancements 30-го числа, поэтому, если вы хотите продолжить, он будет там.

Пока не прибудет поддержка sidecar, вы можете использовать решение на уровне докеров, которое можно легко удалить позже: https://gist.github.com/janosroden/78725e3f846763aa3a660a6b2116c7da

Он использует привилегированный контейнер с установленным докер-сокетом и стандартными ярлыками kubernetes для управления контейнерами в задании.

У нас была такая же проблема с Istio и его сайд-каром, и мы решили удалить модуль с помощью хука curl + preStop, как это

дайте вашей работе минимальное правило RBAC, подобное этому

apiVersion: v1
kind: ServiceAccount
metadata:
  name: myservice-job
---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: myservice-role
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["delete"]
---
kind: RoleBinding
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: myservice-job-rolebinding
subjects:
  - kind: ServiceAccount
    name: myservice-job
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: myservice-role

и POD_NAME и POD_NAMESPACE в ваш ENV вот так

   env:
        - name: POD_NAME
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace

и, наконец, добавьте хук preStop, например

 lifecycle:
      preStop:
        exec:
          command: 
            - "/bin/bash" 
            - "-c"
            - "curl -X DELETE -H "Authorization: Bearer $(cat /var/run/secrets/kubernetes.io/serviceaccount/token)" --cacert /var/run/secrets/kubernetes.io/serviceaccount/ca.crt https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/$POD_NAMESPACE/pods/$POD_NAME?gracePeriodSeconds=1"

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

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

https://github.com/nrmitchi/k8s-controller-sidecars

Спасибо @jpalomaki на https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -371469801 за предложение запустить cloud_sql_proxy в качестве развертывания с сервисом ClusterIP и @ cvallance на https://github.com/kubernetes/kubernetes/issues/25908#issuecomment -364255363 за совет по установке tcp:0.0.0.0 в параметре cloud_sql_proxy instances чтобы разрешить не -локальные подключения к процессу. Вместе они позволили безболезненно разрешить заданиям cron использовать прокси.

долгосрочная проблема (примечание для себя)

Та же проблема. Ищете способ или официальную документацию о том, как использовать GKE cron job с Cloud SQL

Примечание:
Google обновил свой Cloud SQL -> Подключение из документации Google Kubernetes Engine , теперь в дополнение к Connecting using the Cloud SQL Proxy Docker image вы можете Connecting using a private IP address
Итак, если вы здесь по той же причине, что и я (из-за cloud_sql_proxy), вы можете использовать новую функцию Private IP.

Примечание:
Google обновил свой Cloud SQL -> Подключение из документации Google Kubernetes Engine , теперь в дополнение к Connecting using the Cloud SQL Proxy Docker image вы можете Connecting using a private IP address
Итак, если вы здесь по той же причине, что и я (из-за cloud_sql_proxy), вы можете использовать новую функцию Private IP.

Похоже, что для функции частного IP-адреса необходимо удалить весь кластер и воссоздать один ........?

@cropse Это необходимо только в том случае, если ваш кластер не поддерживает VPC.

Я сделал обходной путь для этой проблемы, не отличное решение, но сработало, надеюсь, это поможет до добавления функции, и VPC - это один из способов решить эту проблему, но удаление всего кластера по-прежнему болезненно.

Просто чтобы добавить свои два цента: тесты helm также прерываются, если происходит внедрение istio sidecar, поскольку pod никогда не завершается.

@dansiviter, вы можете проверить мой обходной путь, я уже тестировал в своем проекте с помощью helm.

с нетерпением жду, когда это будет реализовано! :)

у нас действительно есть такая же проблема с обычными заданиями, когда к нему внедряется прокси-сервер Istio, выше, мы также хотим этого, потому что мы хотим запускать задания CI с Prow.
например, контейнер приложения Rails + контейнер базы данных sidecar для тестирования.

@cropse Спасибо. Я не пробовал, так как нам нужно будет настроить это для всех тестов. Мы просто позволяем Pod (тесты Helm, к сожалению, не позволяют Job) выйти из строя и полагаемся на ручную проверку журнала, пока эта проблема не будет исправлена ​​в долгосрочной перспективе. Однако это также становится проблемой и для других рабочих мест, поэтому мы, возможно, пересмотрели эту позицию.

К вашему сведению, проблема с отслеживанием для этой функции находится здесь https://github.com/kubernetes/enhancements/issues/753, если люди хотят следить за ними, у нас есть KEP, выполнено некоторое прототипирование (есть ветка POC / видео ), все еще необходимо уточнить некоторые детали реализации, прежде чем она станет реализуемой.

Примечание:
Google обновил свой Cloud SQL -> Подключение из документации Google Kubernetes Engine , теперь в дополнение к Connecting using the Cloud SQL Proxy Docker image вы можете Connecting using a private IP address
Итак, если вы здесь по той же причине, что и я (из-за cloud_sql_proxy), вы можете использовать новую функцию Private IP.

Я был здесь по той же причине, однако наш Cloud SQL был подготовлен до того, как эта функция была готова. Я объединил предыдущие предложения и получил это (вероятно, не идеально, но оно работает) для моей диаграммы управления мигратора dbmate.

      containers:
      - name: migrator
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        imagePullPolicy: {{ .Values.image.pullPolicy }}
        command: ["/bin/bash", "-c"]
        args:
          - |
            /cloud_sql_proxy -instances={{ .Values.gcp.project }}:{{ .Values.gcp.region }}:{{ .Values.gcp.cloudsql_database }}=tcp:5432 -credential_file=/secrets/cloudsql/credentials.json &
            ensure_proxy_is_up.sh dbmate up
        env:
        - name: DATABASE_URL
          valueFrom:
            secretKeyRef:
              name: mysecret
              key: DATABASE_URL
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials

ensure_proxy_is_up.sh

#!/bin/bash

until pg_isready -d $(echo $DATABASE_URL); do
    sleep 1
done

# run the command that was passed in
exec "$@"

Может быть, сейчас подходящее время для представления о контейнерах с коляской в ​​Kubernetes и разрешения очистки контейнера в зависимости от того, закончены ли контейнеры без коляски?

@Willux Я использую

@krancour спасибо за обновление. Должно быть, я упустил эту деталь. В последнее время здесь не было большой активности, поэтому просто хотел убедиться, что что-то происходит :)

Для справки я создал версию обходного пути @ jmillikin-stripe для облака-sql-proxy, где файл на общем томе передает состояние сопроводительной машине.

Он работает нормально, но это, безусловно, самый неприятный прием в моей конфигурации K8s :(

apiVersion: batch/v1
kind: Job
metadata:
  name: example-job
spec:
  template:
    spec:
      containers:
      - name: example-job
        image: eu.gcr.io/example/example-job:latest
        command: ["/bin/sh", "-c"]
        args:
          - |
            trap "touch /tmp/pod/main-terminated" EXIT
            run-job.sh
        volumeMounts:
          - mountPath: /tmp/pod
            name: tmp-pod
      - name: cloudsql-proxy
        image: gcr.io/cloudsql-docker/gce-proxy:1.11
        command: ["/bin/sh", "-c"]
        args:
          - |
            /cloud_sql_proxy --dir=/cloudsql -instances=example:europe-west3:example=tcp:3306 -credential_file=/secrets/cloudsql/credentials.json &
            CHILD_PID=$!
            (while true; do if [[ -f "/tmp/pod/main-terminated" ]]; then kill $CHILD_PID; echo "Killed $CHILD_PID as the main container terminated."; fi; sleep 1; done) &
            wait $CHILD_PID
            if [[ -f "/tmp/pod/main-terminated" ]]; then exit 0; echo "Job completed. Exiting..."; fi
        volumeMounts:
          - name: cloudsql-instance-credentials
            mountPath: /secrets/cloudsql
            readOnly: true
          - name: cloudsql
            mountPath: /cloudsql
          - mountPath: /tmp/pod
            name: tmp-pod
            readOnly: true
      restartPolicy: Never
      volumes:
        - name: cloudsql-instance-credentials
          secret:
            secretName: cloudsql-instance-credentials
        - name: cloudsql
          emptyDir:
        - name: tmp-pod
          emptyDir: {}
  backoffLimit: 1

Может ли кто-нибудь из сотрудников проекта прокомментировать, как продвигается эта проблема?

Справедливо ли предположить, что это лучший вариант для тех из нас, кто работает над стабильным выпуском канала GKE, который, вероятно, не догонит Kubernetes 1.18 по крайней мере в течение нескольких месяцев?

@Datamance на данный момент KEP для решения этой проблемы выглядит так, как будто он приостановлен на неопределенный срок .

Некоторое время назад я опубликовал этот комментарий , который был моим старым решением. Я не пытаюсь протолкнуть сюда свои собственные вещи, просто этот комментарий был потерян в «100 дополнительных комментариях ...» на github, и решил, что его обновление может снова пригодиться.

@nrmitchi, спасибо за репост. Я один из тех, кто упустил это из виду в море комментариев, и это выглядит как фантастическое краткосрочное решение.

Мы найдем другой подход, если вы добавите следующее в свои контейнеры Pod:

    securityContext:
            capabilities:
                   add:
                    - SYS_PTRACE

тогда вы сможете использовать grep для Pid в других контейнерах, мы выполним следующее в конце нашего основного контейнера:
sql_proxy_pid=$(pgrep cloud_sql_proxy) && kill -INT $sql_proxy_pid

@krancour рад, что это помогло. Если вы посмотрите на сеть в этом репозитории, есть пара форков, которые почти наверняка находятся в лучшем месте, чем мой исходный, и, возможно, лучше построить / использовать.

IIRC вилка лимонад-hq имела несколько полезных дополнений.

@nrmitchi , я

Не могли бы вы вкратце прокомментировать существующие предварительные условия, не упомянутые в README?

Например, требуют ли изображения, на которых основаны ваши коляски, особой осведомленности об этом обходном пути? например, нужно ли им прослушивать определенный порт для сигнала от контроллера? Или, возможно, они должны включать определенную оболочку (bash?)

@krancour Я

В то время он был разработан таким образом, что рассматриваемым контейнерам не нужно было знать об обходном пути. Мы использовали в основном сторонние приложения в sidecar (например, я считаю, что stripe / veneur был одним из них) и не хотели разветвлять / изменять.

Единственное требование к коляске - это то, что они должным образом прослушивают сигнал SIGTERM, а затем отключаются. Я помню, что у меня были некоторые проблемы со сторонним кодом, работающим в боковых машинах, которые ожидали другого сигнала и должны были быть исправлены, но на самом деле контроллер должен был просто разрешить указание отправленного сигнала (то есть SIGINT вместо SIGTERM).

Им не нужно прослушивать какие-либо порты в поисках сигнала, поскольку контроллер использует exec для прямого сигнала главному процессу сопроводительного файла. IIRC в то время, когда эта функциональность была скопирована из кода kubernetes, потому что ее не было в клиенте. Я считаю, что сейчас это есть в официальном клиенте и, вероятно, его следует обновить.

Мы найдем другой подход, если вы добавите следующее в свои контейнеры Pod:

    securityContext:
            capabilities:
                   add:
                    - SYS_PTRACE

тогда вы сможете использовать grep для Pid в других контейнерах, мы выполним следующее в конце нашего основного контейнера:
sql_proxy_pid=$(pgrep cloud_sql_proxy) && kill -INT $sql_proxy_pid

@ ruiyang2015 спасибо за этот взлом.
Если кто-то реализует это, убедитесь, что понимают последствия совместного использования процесса ns между контейнерами.

@nrmitchi

использует exec, чтобы напрямую сигнализировать об основном процессе сопроводительного файла

Это одна из причин, почему я спросил ... Я думаю, в частности, мне интересно, не работает ли это для контейнеров, основанных на изображениях, которые созданы FROM scratch .

@krancour Справедливое замечание, я никогда не ходил и не тестировал его с контейнерами, которые не были scratch . Глядя на код (или мою исходную версию; это могло быть изменено в разветвлении), похоже, что он будет зависеть от bash , но его можно будет изменить.

он будет зависеть от bash, но его можно будет изменить

Конечно, но пока он выполняется, он всегда будет зависеть от какого-то двоичного файла, который присутствует в контейнере, а для временного контейнера там нет ничего, кроме того, что вы явно поместили туда. 🤷‍♂

Учитывая это ограничение, я не могу использовать это для случая использования, когда запущенные контейнеры могут быть совершенно произвольными и указываться третьей стороной. О, а еще у меня есть контейнеры Windows.

Я скажу, на чем я остановлюсь вместо этого. Вероятно, это слишком тяжеловесно для большинства случаев использования, но я упоминаю об этом на тот случай, если чей-то другой вариант использования достаточно похож на мой, чтобы сойти с рук ...

Я могу позволить себе роскошь простого _удаления_ модуля, чей «основной» контейнер вышел, если я сначала записываю статус выхода. Итак, я собираюсь написать контроллер, который будет контролировать некоторый назначенный (через аннотацию) контейнер на предмет завершения, записывать его успех или неудачу в хранилище данных, которое уже отслеживает статус «задания», а затем полностью удалять модуль.

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

Тяжелый, но для некоторых может сработать.

@krancour Совершенно верно. Как есть, контроллер не будет работать с произвольными базами использования. Честно говоря, я никогда не возвращался и не пытался абстрагироваться от некоторых реализаций для поддержки других случаев, потому что я действительно думал, что ранее упомянутый KEP был бы объединен, и поэтому необходимость в этой функциональности была спорной.

Учитывая, что этой проблеме уже около 4 лет, KEP еще никуда не делся, а современное состояние - это хакерский встроенный сценарий оболочки, заменяющий каждую точку входа, я решил кодифицировать «стандартный» хак (надгробия в общем томе ) в двоичный файл Go, который можно легко встроить в образы контейнеров с помощью многоступенчатой ​​сборки.

https://github.com/karlkfi/kubexit

Есть несколько способов его использования:

  1. Запеките это в свои изображения
  2. Загрузите его сбоку, используя контейнер инициализации и временный том.
  3. Подготовьте его на каждом узле и загрузите сбоку в контейнеры с помощью привязки хоста.

Изменить: v0.2.0 теперь поддерживает «зависимости от рождения» (отложенный старт) и «зависимости от смерти» (самозавершение).

Комментарий по дороге: это выглядит точно так же, как https://github.com/kubernetes/enhancements/issues/753

@vanzin, как было отмечено ранее , KEP приостановлен на неопределенный срок.

В моем случае это то, что Vault предоставляет учетные данные для запуска CronJob. После того, как задача выполнена, сопроводительный файл Vault все еще работает с заданием в состоянии ожидания, и это заставляет систему мониторинга думать, что что-то не так. Очень жаль, что случилось с KEP.

Была ли эта страница полезной?
0 / 5 - 0 рейтинги