Shinyproxy: Atualização contínua para implantação do shinyproxy causa pods órfãos

Criado em 19 ago. 2019  ·  7Comentários  ·  Fonte: openanalytics/shinyproxy

Oi, quando há uma alteração no application.yaml e a atualização contínua é escolhida (com as réplicas definidas como 0 e depois de volta para 1) - principalmente porque a nova imagem shinyproxy precisa ser baixada do artefato - Todos os pods anteriores que foram gerados pelo shinyproxy anterior são deixados para trás como zumbis

Reproduzir:

  • kubectl obter tudo

NOME PRONTO STATUS REINICIA IDADE
pod/shinyproxy-7f76d48c79-8x9hs 2/2 Em execução 0 41m

NOME TIPO CLUSTER-IP EXTERNO-IP PORTA(S) IDADE
service/shinyproxy NodePort 172.30.85.1918080:32094/TCP 40m

NOME DESEJADO ATUALIZADA IDADE DISPONÍVEL
deployment.apps/shinyproxy 1 1 1 1 41m

NOME IDADE ATUAL DESEJADA PRONTO
replicaset.apps/shinyproxy-7f76d48c79 1 1 1 41m

NOME DO HOST/CAMINHO DO PORTO SERVIÇOS CURINGA DE TERMINAÇÃO DO PORTO
route.route.openshift.io/shinyproxy shinyproxy-aap.apps.cpaas.service.test shinyproxyNenhum

  • Faça logon no aplicativo (no meu caso, estou usando a autenticação LDAP e /app_direct/ para um aplicativo brilhante (novo pod para o aplicativo é ativado) - conforme o esperado

NOME PRONTO STATUS REINICIA IDADE
pod/shinyproxy-7f76d48c79-8x9hs 2/2 Em execução 0 43m
pod/sp-pod-e7603441-03ba-470b-925a-22cfba1716de 1/1 Em execução 0 12s

NOME TIPO CLUSTER-IP EXTERNO-IP PORTA(S) IDADE
service/shinyproxy NodePort 172.30.85.1918080:32094/TCP 43m

NOME DESEJADO ATUALIZADA IDADE DISPONÍVEL
deployment.apps/shinyproxy 1 1 1 1 43m

NOME IDADE ATUAL DESEJADA PRONTO
replicaset.apps/shinyproxy-7f76d48c79 1 1 1 43m

NOME DO HOST/CAMINHO DO PORTO SERVIÇOS CURINGA DE TERMINAÇÃO DO PORTO
route.route.openshift.io/shinyproxy shinyproxy-aap.apps.cpaas.service.test shinyproxyNenhum

  • Após a criação da nova imagem shinyproxy:

kubectl scale --replicas=0 deployment/shinyproxy
deployment.extensions/shinyproxy dimensionado

kubectl scale --replicas=1 deployment/shinyproxy
deployment.extensions/shinyproxy dimensionado

  • A nova imagem foi baixada para o proxy brilhante e o contêiner sendo criado.

NOME PRONTO STATUS REINICIA IDADE
pod/shinyproxy-7f76d48c79-l5fvw 0/2 ContainerCriando 0 4s
pod/sp-pod-e7603441-03ba-470b-925a-22cfba1716de 1/1 Em execução 0 1m

NOME TIPO CLUSTER-IP EXTERNO-IP PORTA(S) IDADE
service/shinyproxy NodePort 172.30.85.1918080:32094/TCP 44m

NOME DESEJADO ATUALIZADA IDADE DISPONÍVEL
deployment.apps/shinyproxy 1 1 1 0 45m

NOME IDADE ATUAL DESEJADA PRONTO
replicaset.apps/shinyproxy-7f76d48c79 1 1 0 45m

NOME DO HOST/CAMINHO DO PORTO SERVIÇOS CURINGA DE TERMINAÇÃO DO PORTO
route.route.openshift.io/shinyproxy shinyproxy-aap.apps.cpaas.service.test shinyproxyNenhum

  • Nesta fase, meu aplicativo da web não responde - a única coisa a fazer é fechar a guia/janela. E o pod (para o aplicativo R) continua permanecendo, a menos que seja excluído manualmente.

  • O pod que está consumindo recursos não está acessível, porque o novo serviço aponta para a implantação e o aplicativo atualizados só podem ser acessados ​​por meio de uma rota pelo serviço

  • Também é muito difícil identificar quais dos pods são os obsoletos e excluir manualmente

Comentários muito úteis

Encontrei uma solução para este problema. Na verdade, isso não é um problema no shinyproxy ou containerproxy, pois o aplicativo Spring Boot é encerrado corretamente e normalmente.

O problema é o contêiner sidecar kubctl proxy . Para o Kubernetes, não está claro se o containerproxy depende do contêiner sidecar para se comunicar com o próprio Kubernetes. Portanto, em uma nova implantação, o Kubernetes enviará SIGTERM para o proxy e o contêiner sidecar em todos os pods antigos. O contêiner sidecar será encerrado imediatamente e o containerproxy não se comunicará com o Kubernetes.

Eu li que o Kubernetes está prestes a resolver essas dependências de inicialização e desligamento na v1.18 conforme documentado aqui:
https://github.com/kubernetes/enhancements/issues/753
https://banzaicloud.com/blog/k8s-sidecars/

Até lá, há uma solução simples para colocar a seguinte anotação de ciclo de vida no contêiner sidecar:

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

Todos 7 comentários

Olá @ramkumarg1

Quando shinyproxy recebe como sinal SIGTERM (quando a implantação é reduzida), ele deve terminar normalmente parando todos os pods de aplicativos primeiro. Talvez seja necessário aumentar o período de carência terminationGracePeriodSeconds na especificação do pod (o padrão é 30s). Se o shinyproxy não puder encerrar dentro desse período, ele receberá um SIGKILL e será encerrado imediatamente, deixando para trás pods órfãos. Mais informações aqui: https://kubernetes.io/docs/concepts/containers/container-lifecycle-hooks/

Obrigado @dseynaev , alterei a especificação de implantação para incluir terminaçãoGracePeriodSeconds - mas não fez diferença. O pod foi morto imediatamente - Talvez, esse problema esteja vinculado a https://github.com/kubernetes/kubernetes/issues/47576 , onde a inicialização por mola precisa lidar com o SIGTERM normalmente?

spec:
  terminationGracePeriodSeconds : 180
  containers:
  - name: shinyproxy

Observamos o mesmo problema com pods de zumbis e, para nós, a configuração do período de carência de encerramento também não resolve isso.

Eu tenho o mesmo problema e é isso que é registrado por shiny/containerproxy após o término:

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'

Encontrei uma solução para este problema. Na verdade, isso não é um problema no shinyproxy ou containerproxy, pois o aplicativo Spring Boot é encerrado corretamente e normalmente.

O problema é o contêiner sidecar kubctl proxy . Para o Kubernetes, não está claro se o containerproxy depende do contêiner sidecar para se comunicar com o próprio Kubernetes. Portanto, em uma nova implantação, o Kubernetes enviará SIGTERM para o proxy e o contêiner sidecar em todos os pods antigos. O contêiner sidecar será encerrado imediatamente e o containerproxy não se comunicará com o Kubernetes.

Eu li que o Kubernetes está prestes a resolver essas dependências de inicialização e desligamento na v1.18 conforme documentado aqui:
https://github.com/kubernetes/enhancements/issues/753
https://banzaicloud.com/blog/k8s-sidecars/

Até lá, há uma solução simples para colocar a seguinte anotação de ciclo de vida no contêiner sidecar:

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

Posso confirmar que a correção do @fmannhardt resolve isso. Muito obrigado!

Olá a todos

Com versões recentes do ShinyProxy (não tenho certeza de qual versão exatamente, mas pelo menos ShinyProxy 2.3.1) não há necessidade de usar um sidecar kube-proxy. O ShinyProxy detecta automaticamente a localização e a autenticação da API do Kubernetes.
Portanto, acho que esse problema é resolvido automaticamente.
No entanto, obrigado pelo seu tempo e investigação!

Esta página foi útil?
0 / 5 - 0 avaliações