Como resolver problemas de inicialização de cargas de trabalho no Cloud Service Mesh
Este documento explica problemas comuns do Cloud Service Mesh e como resolvê-los. Se você precisar de mais ajuda, consulte Como receber suporte.
O gateway não é iniciado com o proxy sem distribuição quando uma porta privilegiada é exposta.
Por padrão, o proxy sem distro começa com permissões que não são raiz, o que, em alguns casos, pode causar falhas de vinculação em portas privilegiadas. Se você encontrar erros semelhantes a estes durante a inicialização do proxy, será necessário aplicar mais securityContext para uma implantação de gateway.
Error adding/updating listener(s) 0.0.0.0_80: cannot bind '0.0.0.0:80': Permission denied
O exemplo a seguir é o yaml para uma implantação de gateway de saída:
apiVersion: apps/v1
kind: Deployment
metadata:
name: istio-egressgateway
spec:
selector:
matchLabels:
app: istio-egressgateway
istio: egressgateway
template:
metadata:
annotations:
# This is required to tell Anthos Service Mesh to inject the gateway with the
# required configuration.
inject.istio.io/templates: gateway
labels:
app: istio-egressgateway
istio: egressgateway
spec:
containers:
- name: istio-proxy
image: auto # The image will automatically update each time the pod starts.
resources:
limits:
cpu: 2000m
memory: 1024Mi
requests:
cpu: 100m
memory: 128Mi
# Allow binding to all ports (such as 80 and 443)
securityContext:
sysctls:
- name: net.ipv4.ip_unprivileged_port_start
value: "0"
serviceAccountName: istio-egressgateway
Conexão recusada ao alcançar um endpoint do Cloud Service Mesh
Podem ocorrer, de modo intermitente, erros de conexão recusada (ECONNREFUSED
)
na comunicação dos clusters com os endpoints, como Memorystore Redis, Cloud SQL ou qualquer serviço externo que a carga de trabalho do aplicativo precise alcançar.
Isso pode ocorrer quando a carga de trabalho do aplicativo é iniciada mais rapidamente que o
contêiner istio-proxy (Envoy
) e tenta alcançar um endpoint externo. Como
o istio-init (initContainer
) já foi executado
nesta etapa, por isso, há
regras em vigor que redirecionam todo o tráfego de saída para Envoy
. Como
o istio-proxy ainda não está pronto, as regras do iptables redirecionam o tráfego para um
proxy secundário que ainda não foi iniciado e, portanto, o aplicativo recebe o
erro ECONNREFUSED
.
As etapas a seguir detalham como verificar se esse é o erro que você está enfrentando:
Verifique os registros do Stackdriver com o seguinte filtro para identificar quais pods tiveram o problema.
O exemplo a seguir mostra uma mensagem de erro típica:
Error: failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused [ioredis] Unhandled error event: Error: connect ECONNREFUSED
Pesquise uma ocorrência do problema. Se você estiver usando o Stackdriver legado, use
resource.type="container"
.resource.type="k8s_container" textPayload:"$ERROR_MESSAGE$"
Expanda a ocorrência mais recente para ver o nome do pod e anote
pod_name
emresource.labels
.Encontre a primeira ocorrência do problema para esse pod:
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"
Exemplo de saída:
E 2020-03-31T10:41:15.552128897Z post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect: connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
Anote o carimbo de data/hora do primeiro erro desse pod.
Use o filtro a seguir para ver os eventos de inicialização do pod.
resource.type="k8s_container" resource.labels.pod_name="$POD_NAME$"
Exemplo de saída:
I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Container image "docker.io/istio/proxyv2:1.3.3" already present on machine spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Created container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{istio-proxy} Started container spec.containers{istio-proxy} I 2020-03-31T10:41:15Z spec.containers{APP-CONTAINER-NAME} Created container spec.containers{APP-CONTAINER-NAME} W 2020-03-31T10:41:17Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:26Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:28Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:31Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy} W 2020-03-31T10:41:58Z spec.containers{istio-proxy} Readiness probe failed: HTTP probe failed with statuscode: 503 spec.containers{istio-proxy}
Use os carimbos de data/hora dos erros e eventos de inicialização do istio-proxy para confirmar se os erros estão acontecendo quando o
Envoy
não está pronto.Se os erros ocorrem enquanto o contêiner istio-proxy ainda não está pronto, é normal receber erros de conexão recusada. No exemplo anterior, o pod tentava se conectar ao Redis assim que
2020-03-31T10:41:15.552128897Z
, mas por2020-03-31T10:41:58Z
o istio-proxy ainda falhava nas sondagens de prontidão.Mesmo que o contêiner istio-proxy tenha sido iniciado primeiro, é possível que ele não tenha ficado pronto rápido o suficiente antes de o app já estar tentando se conectar ao endpoint externo.
Se esse for o problema que você está enfrentando, continue com as seguintes etapas de solução de problemas.
Anote a configuração no nível do pod. Isso está disponível apenas no nível do pod e não em nível global.
annotations: proxy.istio.io/config: '{ "holdApplicationUntilProxyStarts": true }'
Modifique o código do aplicativo para que ele verifique se o
Envoy
está pronto antes de tentar fazer outras solicitações para serviços externos. Por exemplo, na inicialização do aplicativo, inicie um loop que faça solicitações para o endpoint de integridade do istio-proxy e só continue depois que um número 200 for recebido. O endpoint de integridade do istio-proxy é este:http://localhost:15020/healthz/ready
Disputa durante a injeção de sidecar entre o Vault e o Cloud Service Mesh
Ao usar vault
para gerenciamento de secrets, às vezes vault
injeta o arquivo secundário antes de istio
, fazendo com que os pods fiquem travados no status Init
. Quando isso acontece, os pods criados ficam travados no status Init depois de reiniciar qualquer implantação ou implantar uma nova. Exemplo:
E 2020-03-31T10:41:15.552128897Z
post-feature-service post-feature-service-v1-67d56cdd-g7fvb failed to create
connection to feature-store redis, err=dial tcp 192.168.9.16:19209: connect:
connection refused post-feature-service post-feature-service-v1-67d56cdd-g7fvb
Esse problema é causado por uma disputa. Tanto o Istio quanto vault
injetam o
arquivo secundário, e o Istio precisa ser o último a fazer isso. O proxy istio
não está em execução
durante os contêineres init. O contêiner init istio
configura as regras do AndroidManifest para redirecionar todo o tráfego para o proxy. Como ela ainda não está em execução, essas regras
redirecionam para nada, bloqueando todo o tráfego. É por isso que o contêiner init precisa
ser o último, para que o proxy entre em execução imediatamente após as regras do Dockerfile serem
configuradas. Infelizmente, a ordem não é determinista. Portanto, se o Istio for injetado
primeiro, ele falhará.
Para resolver essa condição, permita o endereço IP de vault
para que o tráfego
que vai para o IP do Vault não seja redirecionado para o proxy Envoy, que ainda não está pronto
e, portanto, bloqueando a comunicação. Para isso, uma nova anotação
chamada excludeOutboundIPRanges
precisa ser adicionada.
Para o Cloud Service Mesh gerenciado, isso só é possível no nível da implantação ou do pod
em spec.template.metadata.annotations
. Por exemplo:
apiVersion: apps/v1
kind: Deployment
...
...
...
spec:
template:
metadata:
annotations:
traffic.sidecar.istio.io/excludeOutboundIPRanges:
Para o Cloud Service Mesh no cluster, há uma opção para defini-lo como global
com um IstioOperator em spec.values.global.proxy.excludeIPRanges
. Por
exemplo:
apiVersion: install.istio.io/v1alpha1
kind: IstioOperator
spec:
values:
global:
proxy:
excludeIPRanges: ""
Depois de adicionar a anotação, reinicie suas cargas de trabalho.