Shinyproxy: Непрерывное обновление для развертывания блестящего прокси-сервера приводит к появлению потерянных модулей

Созданный на 19 авг. 2019  ·  7Комментарии  ·  Источник: openanalytics/shinyproxy

Привет, когда есть изменение в application.yaml и выбрано скользящее обновление (с репликами, установленными на 0, а затем обратно на 1) - в основном потому, что новый образ блестящего прокси-сервера необходимо загрузить из артефакта - все более ранние модули, которые были раскручены предыдущим блестящим прокси, остаются позади как зомби

Чтобы воспроизвести:

  • кубектл получить все

ИМЯ ГОТОВ СТАТУС ПЕРЕЗАПУСКА ВОЗРАСТ
pod/shinyproxy-7f76d48c79-8x9hs 2/2 Бег 0 41м

НАЗВАНИЕ ТИП КЛАСТЕР-IP ВНЕШНИЙ-IP ПОРТ(Ы) ВОЗРАСТ
сервис/shinyproxy NodePort 172.30.85.1918080:32094/TCP 40 м

ИМЯ ЖЕЛАЕМЫЙ НАСТОЯЩИЙ ДОСТУПНЫЙ ВОЗРАСТ
Deployment.apps/shinyproxy 1 1 1 1 41 м

ИМЯ ЖЕЛАЕМЫЙ НАСТОЯЩИЙ ВОЗРАСТ ГОТОВНОСТИ
replicaset.apps/shinyproxy-7f76d48c79 1 1 1 41 м

ИМЯ ПУТЬ ХОСТА/ПОРТА СЛУЖБЫ ПОРТ ТЕРМИНАЦИЯ ПОДСТАВНОЙ КАРТА
route.route.openshift.io/shinyproxyshinyproxy-aap.apps.cpaas.service.testshinyproxyНикто

  • Войдите в приложение (в моем случае я использую аутентификацию LDAP и /app_direct/ для блестящего приложения (новый модуль для приложения развернут) - как и ожидалось.

ИМЯ ГОТОВ СТАТУС ПЕРЕЗАПУСКА ВОЗРАСТ
pod/shinyproxy-7f76d48c79-8x9hs 2/2 Бег 0 43м
pod/sp-pod-e7603441-03ba-470b-925a-22cfba1716de 1/1 Работает 0 12 с

НАЗВАНИЕ ТИП КЛАСТЕР-IP ВНЕШНИЙ-IP ПОРТ(Ы) ВОЗРАСТ
сервис/shinyproxy NodePort 172.30.85.1918080:32094/TCP 43 м

ИМЯ ЖЕЛАЕМЫЙ НАСТОЯЩИЙ ДОСТУПНЫЙ ВОЗРАСТ
Deployment.apps/shinyproxy 1 1 1 1 43 м

ИМЯ ЖЕЛАЕМЫЙ НАСТОЯЩИЙ ВОЗРАСТ ГОТОВНОСТИ
replicaset.apps/shinyproxy-7f76d48c79 1 1 1 43 м

ИМЯ ПУТЬ ХОСТА/ПОРТА СЛУЖБЫ ПОРТ ТЕРМИНАЦИЯ ПОДСТАВНОЙ КАРТА
route.route.openshift.io/shinyproxyshinyproxy-aap.apps.cpaas.service.testshinyproxyНикто

  • После сборки нового образаshininproxy:

масштаб kubectl --replicas=0 развертывание/shinyproxy
развертывание.extensions/shinyproxy масштабируется

масштаб kubectl --replicas=1 развертывание/shinyproxy
развертывание.extensions/shinyproxy масштабируется

  • Был загружен новый образ для блестящего прокси и создаваемого контейнера.

ИМЯ ГОТОВ СТАТУС ПЕРЕЗАПУСКА ВОЗРАСТ
pod/shinyproxy-7f76d48c79-l5fvw 0/2 ContainerCreating 0 4s
pod/sp-pod-e7603441-03ba-470b-925a-22cfba1716de 1/1 Бег 0 1м

НАЗВАНИЕ ТИП КЛАСТЕР-IP ВНЕШНИЙ-IP ПОРТ(Ы) ВОЗРАСТ
сервис/shinyproxy NodePort 172.30.85.1918080:32094/TCP 44 м

ИМЯ ЖЕЛАЕМЫЙ НАСТОЯЩИЙ ДОСТУПНЫЙ ВОЗРАСТ
Deployment.apps/shinyproxy 1 1 1 0 45 м

ИМЯ ЖЕЛАЕМЫЙ НАСТОЯЩИЙ ВОЗРАСТ ГОТОВНОСТИ
replicaset.apps/shinyproxy-7f76d48c79 1 1 0 45 м

ИМЯ ПУТЬ ХОСТА/ПОРТА СЛУЖБЫ ПОРТ ТЕРМИНАЦИЯ ПОДСТАВНОЙ КАРТА
route.route.openshift.io/shinyproxyshinyproxy-aap.apps.cpaas.service.testshinyproxyНикто

  • На данном этапе мое веб-приложение не отвечает - единственное, что нужно сделать, это закрыть вкладку/окно. И модуль (для приложения R) продолжает оставаться, пока не будет удален вручную.

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

  • Также очень сложно определить, какие из модулей являются устаревшими, и удалить их вручную.

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

Я нашел решение этой проблемы. На самом деле это не проблема в блестящем прокси-сервере или контейнерном прокси-сервере, поскольку приложение Spring Boot корректно и изящно закрывается.

Проблема заключается в контейнере коляски kubctl proxy . Для Kubernetes неясно, использует ли containerproxy контейнер sidecar для связи с самим Kubernetes. Таким образом, при новом развертывании Kubernetes будет отправлять SIGTERM как на прокси, так и на дополнительный контейнер во всех старых модулях. Sidecar-контейнер немедленно прекратит работу, и containerproxy не сможет связаться с Kubernetes.

Я читал, что Kubernetes собирается решить эти зависимости запуска и завершения работы в версии 1.18, как описано здесь:
https://github.com/kubernetes/enhancements/issues/753
https://banzaicloud.com/blog/k8s-sidecars/

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

          lifecycle:
            preStop:
              exec:
                command: ["sh", "-c", "sleep 5"] # wait 5 seconds to let shinyproxy remove the pods on graceful shutdown

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

Привет @ramkumarg1

Когда shiningproxy получает сигнал SIGTERM (при масштабировании развертывания), он должен корректно завершаться, сначала останавливая все модули приложений. Возможно, вам придется увеличить льготный период terminationGracePeriodSeconds в спецификации модуля (по умолчанию — 30 секунд). Если shiningproxy не может завершиться в течение этого периода, он получит SIGKILL и будет немедленно завершен, оставив потерянные модули. Подробнее здесь: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/

Спасибо @dseynaev. Я изменил спецификацию развертывания, включив в нее терминированиеGracePeriodSeconds, но это не изменило ситуацию. Модуль был немедленно убит. Возможно, эта проблема связана с https://github.com/kubernetes/kubernetes/issues/47576 , где весенняя загрузка должна изящно обрабатывать SIGTERM?

spec:
  terminationGracePeriodSeconds : 180
  containers:
  - name: shinyproxy

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

У меня та же проблема, и это то, что записывается блестящим/контейнерным прокси после завершения:

2020-01-30 10:56:56.785  INFO 1 --- [           main] e.o.c.ContainerProxyApplication          : Started ContainerProxyApplication in 39.115 seconds (JVM running for 43.619)
2020-01-30 10:57:01.374  INFO 1 --- [  XNIO-2 task-1] io.undertow.servlet                      : Initializing Spring FrameworkServlet 'dispatcherServlet'
2020-01-30 10:57:01.375  INFO 1 --- [  XNIO-2 task-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization started
2020-01-30 10:57:01.507  INFO 1 --- [  XNIO-2 task-1] o.s.web.servlet.DispatcherServlet        : FrameworkServlet 'dispatcherServlet': initialization completed in 131 ms
2020-01-30 10:57:26.275  INFO 1 --- [ XNIO-2 task-16] e.o.containerproxy.service.UserService   : User logged in [user: **]
2020-01-30 10:57:35.802  INFO 1 --- [  XNIO-2 task-3] e.o.containerproxy.service.ProxyService  : Proxy activated [user: ***] [spec: insight] [id: 9274ad33-665a-4d47-bab5-6c4b39a618b8]
2020-01-30 10:59:02.376  INFO 1 --- [       Thread-2] ConfigServletWebServerApplicationContext : Closing org.springframework.boot.web.servlet.context.AnnotationConfigServletWebServerApplicationContext<strong i="6">@2b2948e2</strong>: startup date [Thu Jan 30 10:56:24 GMT 2020]; root of context hierarchy
2020-01-30 10:59:02.377 ERROR 1 --- [pool-4-thread-1] java.io.InputStreamReader                : Error while pumping stream.
java.io.EOFException: null
    at okio.RealBufferedSource.require(RealBufferedSource.java:61) ~[okio-1.15.0.jar!/:na]
    at okio.RealBufferedSource.readHexadecimalUnsignedLong(RealBufferedSource.java:303) ~[okio-1.15.0.jar!/:na]
    at okhttp3.internal.http1.Http1Codec$ChunkedSource.readChunkSize(Http1Codec.java:469) ~[okhttp-3.12.0.jar!/:na]
    at okhttp3.internal.http1.Http1Codec$ChunkedSource.read(Http1Codec.java:449) ~[okhttp-3.12.0.jar!/:na]
    at okio.RealBufferedSource$1.read(RealBufferedSource.java:439) ~[okio-1.15.0.jar!/:na]
    at java.io.InputStream.read(InputStream.java:101) ~[na:1.8.0_171]
    at io.fabric8.kubernetes.client.utils.BlockingInputStreamPumper.run(BlockingInputStreamPumper.java:49) ~[kubernetes-client-4.2.2.jar!/:na]
    at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [na:1.8.0_171]
    at java.util.concurrent.FutureTask.run(FutureTask.java:266) [na:1.8.0_171]
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [na:1.8.0_171]
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [na:1.8.0_171]
    at java.lang.Thread.run(Thread.java:748) [na:1.8.0_171]
2020-01-30 10:59:02.394  INFO 1 --- [       Thread-2] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans on shutdown
2020-01-30 10:59:02.403  INFO 1 --- [       Thread-2] o.s.j.e.a.AnnotationMBeanExporter        : Unregistering JMX-exposed beans
2020-01-30 10:59:02.514  WARN 1 --- [       Thread-2] .s.c.a.CommonAnnotationBeanPostProcessor : Invocation of destroy method failed on bean with name 'proxyService': eu.openanalytics.containerproxy.ContainerProxyException: Failed to stop container
2020-01-30 10:59:02.525  INFO 1 --- [       Thread-2] io.undertow.servlet                      : Destroying Spring FrameworkServlet 'dispatcherServlet'

Я нашел решение этой проблемы. На самом деле это не проблема в блестящем прокси-сервере или контейнерном прокси-сервере, поскольку приложение Spring Boot корректно и изящно закрывается.

Проблема заключается в контейнере коляски kubctl proxy . Для Kubernetes неясно, использует ли containerproxy контейнер sidecar для связи с самим Kubernetes. Таким образом, при новом развертывании Kubernetes будет отправлять SIGTERM как на прокси, так и на дополнительный контейнер во всех старых модулях. Sidecar-контейнер немедленно прекратит работу, и containerproxy не сможет связаться с Kubernetes.

Я читал, что Kubernetes собирается решить эти зависимости запуска и завершения работы в версии 1.18, как описано здесь:
https://github.com/kubernetes/enhancements/issues/753
https://banzaicloud.com/blog/k8s-sidecars/

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

          lifecycle:
            preStop:
              exec:
                command: ["sh", "-c", "sleep 5"] # wait 5 seconds to let shinyproxy remove the pods on graceful shutdown

Я могу подтвердить, что исправление @fmannhardt решает эту проблему. Большое спасибо!

всем привет

С последними версиями ShinyProxy (я не уверен, какая именно версия, но по крайней мере ShinyProxy 2.3.1) нет необходимости использовать сайдкар kube-proxy. ShinyProxy автоматически определяет местоположение и аутентификацию Kubernetes API.
Поэтому я думаю, что эта проблема автоматически решается.
Тем не менее, спасибо за ваше время и расследование!

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