This is the multi-page printable view of this section. Click here to print.

Return to the regular view of this page.

Solução de Problemas em Aplicações

Depuração de problemas comuns em aplicações conteinerizadas.

Este documento contém um conjunto de recursos para solucionar problemas em aplicações conteinerizadas. Ele aborda questões comuns relacionadas a recursos do Kubernetes (como Pods, Services e StatefulSets), orientações para interpretar mensagens de término de contêineres e métodos para depurar contêineres em execução.

1 - Depuração de Pods

Este guia foi criado para ajudar os usuários a depurar aplicações implantadas no Kubernetes que não estão se comportando corretamente. Este não é um guia para quem deseja depurar seu cluster. Para isso, você deve conferir este guia.

Diagnosticando o problema

O primeiro passo na solução de problemas é a triagem. Qual é o problema? São seus Pods, seu Replication Controller ou seu Service?

Depurando Pods

O primeiro passo para depurar um Pod é examiná-lo. Verifique o estado atual do Pod e eventos recentes com o seguinte comando:

kubectl describe pods ${POD_NAME}

Observe o estado dos containers no pod. Todos estão em Running? Houve reinicializações recentes?

Continue a depuração dependendo do estado dos pods.

Meu pod fica em estado pending

Se um Pod estiver preso em Pending, significa que ele não pode ser alocado em um nó. Geralmente, isso ocorre porque há recursos insuficientes de algum tipo, impedindo a alocação. Verifique a saída do comando kubectl describe ... mencionado acima. Deve haver mensagens do escalonador explicando por que o Pod não pode ser alocado. As razões incluem:

  • Você não tem recursos suficientes: Pode ser que você tenha esgotado a capacidade de CPU ou Memória no seu cluster. Nesse caso, você precisa excluir Pods, ajustar as solicitações de recursos ou adicionar novos nós ao cluster. Consulte o documento Recursos de Computação para mais informações.

  • Você está usando hostPort: Quando você vincula um Pod a um hostPort, há um número limitado de locais onde esse Pod pode ser alocado. Na maioria dos casos, hostPort é desnecessário, tente usar um objeto Service para expor seu Pod. Se você realmente precisar de hostPort, então só poderá alocar tantos Pods quanto o número de nós no seu cluster Kubernetes.

Meu pod fica em estado waiting

Se um Pod estiver preso no estado Waiting, significa que ele foi alocado para um nó de trabalho, mas não pode ser executado nessa máquina. Novamente, as informações do comando kubectl describe ... devem fornecer detalhes úteis.

A causa mais comum para Pods em estado Waiting é a falha ao baixar a imagem. Há três coisas que você deve verificar:

  • Certifique-se de que o nome da imagem está correto.
  • Você enviou a imagem para o registro?
  • Tente baixar a imagem manualmente para verificar se ela pode ser baixada. Por exemplo, se você usa Docker no seu PC, execute docker pull .

Meu pod fica em estado terminating

Se um Pod estiver preso no estado Terminating, significa que uma solicitação de exclusão foi emitida, mas a camada de gerenciamento não conseguiu remover o objeto do Pod.

Isso geralmente ocorre se o Pod possui um finalizer e há um admission webhook instalado no cluster que impede a camada de gerenciamento de remover o finalizer.

Para identificar esse cenário, verifique se seu cluster possui algum ValidatingWebhookConfiguration ou MutatingWebhookConfiguration que tenha como alvo operações UPDATE para recursos pods.

Se o webhook for fornecido por um terceiro:

  • Certifique-se de estar usando a versão mais recente.
  • Desative o webhook para operações UPDATE.
  • Relate um problema ao provedor correspondente.

Se você for o autor do webhook:

  • Para um webhook de mutação, certifique-se de que ele nunca altere campos imutáveis em operações UPDATE. Por exemplo, mudanças em contêineres geralmente não são permitidas.
  • Para um webhook de validação, garanta que suas regras de validação se apliquem apenas a novas alterações. Em outras palavras, você deve permitir que Pods com violações existentes passem pela validação. Isso permite que Pods criados antes da instalação do webhook continuem em execução.

Meu pod está falhando ou não está íntegro

Depois que seu Pod for alocado, você pode usar os métodos descritos em Depurando Pods em Execução para depuração.

Meu pod está em execução, mas não faz o que eu defini

Se o seu pod não está se comportando como esperado, pode haver um erro na descrição do pod (por exemplo, no arquivo mypod.yaml em sua máquina local) que foi ignorado silenciosamente ao criar o pod. Muitas vezes, uma seção da descrição do pod pode estar aninhada incorretamente ou um nome de chave pode ter sido digitado incorretamente, fazendo com que a chave seja ignorada. Por exemplo, se você digitou commnd em vez de command, o pod será criado, mas não usará o comando que você pretendia.

A primeira coisa a fazer é excluir seu pod e tentar criá-lo novamente usando a opção --validate. Por exemplo, execute kubectl apply --validate -f mypod.yaml. Se você digitou command incorretamente como commnd, verá um erro como este:

I0805 10:43:25.129850   46757 schema.go:126] unknown field: commnd
I0805 10:43:25.129973   46757 schema.go:129] this may be a false alarm, see https://github.com/kubernetes/kubernetes/issues/6842
pods/mypod

A próxima coisa a verificar é se o pod no servidor da API corresponde ao pod que você pretendia criar (por exemplo, no arquivo yaml em sua máquina local). Por exemplo, execute kubectl get pods/mypod -o yaml > mypod-on-apiserver.yaml em seguida, compare manualmente a descrição original do pod, mypod.yaml com a versão obtida do servidor da API, mypod-on-apiserver.yaml.
Normalmente, a versão do "servidor da API" terá algumas linhas extras que não estão na versão original, o que é esperado. No entanto, se houver linhas na versão original que não aparecem na versão do servidor da API, isso pode indicar um problema na especificação do seu pod.

Depurando Replication Controllers

Replication Controllers são bastante diretos. Eles podem criar pods ou não. Se não conseguirem criar pods, consulte as instruções acima para depurar seus pods.

Você também pode usar kubectl describe rc ${CONTROLLER_NAME} para examinar eventos relacionados ao replication controller.

Depurando Services

Os Services fornecem balanceamento de carga entre um conjunto de pods. Existem vários problemas comuns que podem fazer com que os Services não funcionem corretamente. As instruções a seguir devem ajudar na depuração de problemas com Services.

Primeiro, verifique se há endpoints para o Service. Para cada objeto Service, o servidor da API disponibiliza um recurso endpoints.

Você pode visualizar esse recurso com o seguinte comando:

kubectl get endpoints ${SERVICE_NAME}

Certifique-se de que os endpoints correspondem ao número de pods que você espera que sejam membros do seu service. Por exemplo, se seu Service estiver associado a um container Nginx com 3 réplicas, você deve esperar ver três endereços IP diferentes nos endpoints do Service.

Meu Service não possui endpoints

Se os endpoints estiverem ausentes, tente listar os pods usando os rótulos que o Service utiliza. Por exemplo, imagine que você tenha um Service com os seguintes rótulos:

...
spec:
  - selector:
     name: nginx
     type: frontend

Você pode usar:

kubectl get pods --selector=name=nginx,type=frontend

para listar os pods que correspondem a esse seletor. Verifique se a lista corresponde aos pods que você espera que forneçam seu Service.
Além disso, certifique-se de que o containerPort do pod corresponde ao targetPort do service.

O tráfego de rede não está sendo encaminhado

Consulte Depurando Services para mais informações.

Próximos passos

Se nenhuma das soluções acima resolver seu problema, siga as instruções no documento de Depuração de Services para garantir que seu Service está em execução, possui Endpoints e que seus Pods estão realmente respondendo; além disso, verifique se o DNS está funcionando, as regras do iptables estão configuradas corretamente e se o kube-proxy não está com problemas.

Você também pode consultar o documento de solução de problemas para mais informações.

2 - Depuração de Services

Um problema que surge com bastante frequência em novas instalações do Kubernetes é que um Service não está funcionando corretamente. Você implantou seus Pods através de um Deployment (ou outro controlador de carga de trabalho) e criou um Service, mas não recebe nenhuma resposta ao tentar acessá-lo. Este documento, esperançosamente, ajudará você a descobrir o que está errado.

Executando comandos em um Pod

Para muitas etapas aqui, você desejará ver o que um Pod em execução no cluster está enxergando. A maneira mais simples de fazer isso é executar um Pod interativo com busybox:

kubectl run -it --rm --restart=Never busybox --image=gcr.io/google-containers/busybox sh

Se você já tem um Pod em execução que prefere usar, você pode executar um comando nele usando:

kubectl exec <POD-NAME> -c <CONTAINER-NAME> -- <COMMAND>

Configuração

Para os propósitos deste passo a passo, vamos executar alguns Pods. Como você provavelmente está depurando seu próprio Service, pode substituir os detalhes pelos seus próprios ou seguir junto para obter um segundo ponto de referência.

kubectl create deployment hostnames --image=registry.k8s.io/serve_hostname
deployment.apps/hostnames created

Os comandos kubectl exibirão o tipo e o nome do recurso criado ou modificado, que podem então ser usados em comandos subsequentes.

Vamos escalar o deployment para 3 réplicas.

kubectl scale deployment hostnames --replicas=3
deployment.apps/hostnames scaled

Observe que isso é o mesmo que se você tivesse iniciado o Deployment com o seguinte YAML:

apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: hostnames
  name: hostnames
spec:
  selector:
    matchLabels:
      app: hostnames
  replicas: 3
  template:
    metadata:
      labels:
        app: hostnames
    spec:
      containers:
      - name: hostnames
        image: registry.k8s.io/serve_hostname

O rótulo "app" é definido automaticamente pelo kubectl create deployment como o nome do Deployment.

Você pode confirmar que seus Pods estão em execução:

kubectl get pods -l app=hostnames
NAME                        READY     STATUS    RESTARTS   AGE
hostnames-632524106-bbpiw   1/1       Running   0          2m
hostnames-632524106-ly40y   1/1       Running   0          2m
hostnames-632524106-tlaok   1/1       Running   0          2m

Você também pode confirmar que seus Pods estão respondendo. Você pode obter a lista de endereços IP dos Pods e testá-los diretamente.

kubectl get pods -l app=hostnames \
    -o go-template='{{range .items}}{{.status.podIP}}{{"\n"}}{{end}}'
10.244.0.5
10.244.0.6
10.244.0.7

O contêiner de exemplo usado neste passo a passo serve seu próprio hostname via HTTP na porta 9376, mas se você estiver depurando sua própria aplicação, deverá usar o número da porta na qual seus Pods estão escutando.

De dentro de um Pod:

for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do
    wget -qO- $ep
done

Isso deve produzir algo como:

hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok

Se você não estiver recebendo as respostas esperadas neste ponto, seus Pods podem não estar íntegro ou podem não estar ouvindo na porta que você pensa que estão. Você pode achar útil usar kubectl logs para ver o que está acontecendo ou, talvez, seja necessário executar kubectl exec diretamente em seus Pods e depurar a partir daí.

Supondo que tudo tenha ocorrido conforme o esperado até agora, você pode começar a investigar por que seu Service não está funcionando.

O Service existe?

O leitor atento terá notado que você ainda não criou um Service – isso é intencional. Esse é um passo que às vezes é esquecido e é a primeira coisa a verificar.

O que aconteceria se você tentasse acessar um Service inexistente? Se você tiver outro Pod que consome esse Service pelo nome, obteria algo como:

wget -O- hostnames
Resolving hostnames (hostnames)... failed: Name or service not known.
wget: unable to resolve host address 'hostnames'

A primeira coisa a verificar é se esse Service realmente existe:

kubectl get svc hostnames
No resources found.
Error from server (NotFound): services "hostnames" not found

Vamos criar o Service. Como antes, isso faz parte do passo a passo – você pode usar os detalhes do seu próprio Service aqui.

kubectl expose deployment hostnames --port=80 --target-port=9376
service/hostnames exposed

E ler de volta:

kubectl get svc hostnames
NAME        TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
hostnames   ClusterIP   10.0.1.175   <none>        80/TCP    5s

Agora você sabe que o Service existe.

Como antes, isso é o mesmo que se você tivesse iniciado o Service com YAML:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: hostnames
  name: hostnames
spec:
  selector:
    app: hostnames
  ports:
  - name: default
    protocol: TCP
    port: 80
    targetPort: 9376

Para destacar toda a gama de configurações, o Service que você criou aqui usa um número de porta diferente dos Pods. Para muitos Services do mundo real, esses valores podem ser os mesmos.

Alguma regra de Network Policy Ingress está afetando os Pods de destino?

Se você implantou alguma regra de Network Policy Ingress que possa afetar o tráfego de entrada para os Pods hostnames-*, elas precisam ser revisadas.

Consulte a documentação sobre Network Policies para mais detalhes.

O Service funciona pelo nome DNS?

Uma das formas mais comuns de os clientes consumirem um Service é através de um nome DNS.

A partir de um Pod no mesmo Namespace:

nslookup hostnames
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      hostnames
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local

Se isso falhar, talvez seu Pod e Service estejam em Namespaces diferentes. Tente um nome qualificado pelo namespace (novamente, de dentro de um Pod):

nslookup hostnames.default
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      hostnames.default
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local

Se isso funcionar, você precisará ajustar sua aplicação para usar um nome qualificado pelo namespace ou executar sua aplicação e o Service no mesmo Namespace. Se isso ainda falhar, tente um nome totalmente qualificado:

nslookup hostnames.default.svc.cluster.local
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      hostnames.default.svc.cluster.local
Address 1: 10.0.1.175 hostnames.default.svc.cluster.local

Observe o sufixo aqui: "default.svc.cluster.local". O "default" é o Namespace no qual você está operando. O "svc" indica que este é um Service. O "cluster.local" é o domínio do seu cluster, que PODE ser diferente no seu próprio cluster.

Você também pode tentar isso a partir de um Node no cluster:

nslookup hostnames.default.svc.cluster.local 10.0.0.10
Server:         10.0.0.10
Address:        10.0.0.10#53

Name:   hostnames.default.svc.cluster.local
Address: 10.0.1.175

Se você conseguir fazer uma consulta de nome totalmente qualificado, mas não uma relativa, precisará verificar se o arquivo /etc/resolv.conf no seu Pod está correto. De dentro de um Pod:

cat /etc/resolv.conf

Você deve ver algo como:

nameserver 10.0.0.10
search default.svc.cluster.local svc.cluster.local cluster.local example.com
options ndots:5

A linha nameserver deve indicar o Service DNS do seu cluster. Isso é passado para o kubelet com a flag --cluster-dns.

A linha search deve incluir um sufixo apropriado para que o nome do Service seja encontrado. Neste caso, ele está procurando Services no Namespace local ("default.svc.cluster.local"), Services em todos os Namespaces ("svc.cluster.local"), e, por último, nomes no cluster ("cluster.local"). Dependendo da sua instalação, você pode ter registros adicionais depois disso (até um total de 6). O sufixo do cluster é passado para o kubelet com a flag --cluster-domain. Ao longo deste documento, assumimos que o sufixo do cluster é "cluster.local". Seu cluster pode estar configurado de forma diferente, e, nesse caso, você deve ajustar isso em todos os comandos anteriores.

A linha options deve definir ndots com um valor alto o suficiente para que sua biblioteca cliente de DNS considere os caminhos de pesquisa. O Kubernetes define isso como 5 por padrão, o que é suficiente para cobrir todos os nomes DNS que ele gera.

Algum Service funciona pelo nome DNS?

Se as etapas anteriores ainda falharem, as consultas DNS não estão funcionando para seu Service. Você pode dar um passo atrás e verificar o que mais não está funcionando. O Service principal do Kubernetes deve sempre funcionar. De dentro de um Pod:

nslookup kubernetes.default
Server:    10.0.0.10
Address 1: 10.0.0.10 kube-dns.kube-system.svc.cluster.local

Name:      kubernetes.default
Address 1: 10.0.0.1 kubernetes.default.svc.cluster.local

Se isso falhar, consulte a seção kube-proxy deste documento ou até volte ao início e comece novamente, mas, em vez de depurar seu próprio Service, depure o Service de DNS.

O Service funciona pelo IP?

Supondo que você tenha confirmado que o DNS está funcionando, o próximo passo é testar se o seu Service funciona pelo endereço IP. A partir de um Pod no seu cluster, acesse o IP do Service (obtido com kubectl get acima).

for i in $(seq 1 3); do 
    wget -qO- 10.0.1.175:80
done

Isso deve produzir algo como:

hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok

Se o seu Service estiver funcionando, você deverá obter respostas corretas. Caso contrário, há várias possíveis causas para o problema. Continue lendo.

O Service está definido corretamente?

Pode parecer óbvio, mas você deve realmente verificar duas ou três vezes se seu Service está correto e corresponde à porta do seu Pod. Leia novamente seu Service e verifique:

kubectl get service hostnames -o json
{
    "kind": "Service",
    "apiVersion": "v1",
    "metadata": {
        "name": "hostnames",
        "namespace": "default",
        "uid": "428c8b6c-24bc-11e5-936d-42010af0a9bc",
        "resourceVersion": "347189",
        "creationTimestamp": "2015-07-07T15:24:29Z",
        "labels": {
            "app": "hostnames"
        }
    },
    "spec": {
        "ports": [
            {
                "name": "default",
                "protocol": "TCP",
                "port": 80,
                "targetPort": 9376,
                "nodePort": 0
            }
        ],
        "selector": {
            "app": "hostnames"
        },
        "clusterIP": "10.0.1.175",
        "type": "ClusterIP",
        "sessionAffinity": "None"
    },
    "status": {
        "loadBalancer": {}
    }
}
  • A porta do Service que você está tentando acessar está listada em spec.ports[]?
  • O targetPort está correto para seus Pods (alguns Pods usam uma porta diferente da do Service)?
  • Se você pretende usar uma porta numérica, ela está especificada como um número (9376) ou como uma string ("9376")?
  • Se você pretende usar uma porta nomeada, seus Pods expõem uma porta com o mesmo nome?
  • O protocol da porta está correto para seus Pods?

O Service tem algum Endpoint?

Se você chegou até aqui, já confirmou que seu Service está corretamente definido e resolvido pelo DNS. Agora, vamos verificar se os Pods que você executou estão realmente sendo selecionados pelo Service.

Anteriormente, você viu que os Pods estavam em execução. Você pode verificar novamente:

kubectl get pods -l app=hostnames
NAME                        READY     STATUS    RESTARTS   AGE
hostnames-632524106-bbpiw   1/1       Running   0          1h
hostnames-632524106-ly40y   1/1       Running   0          1h
hostnames-632524106-tlaok   1/1       Running   0          1h

O argumento -l app=hostnames é um seletor de rótulo configurado no Service.

A coluna "AGE" indica que esses Pods têm cerca de uma hora de idade, o que implica que estão funcionando corretamente e não estão falhando.

A coluna "RESTARTS" indica que esses Pods não estão falhando frequentemente ou sendo reiniciados. Reinicializações frequentes podem causar problemas intermitentes de conectividade. Se a contagem de reinicializações for alta, leia mais sobre como depurar pods.

Dentro do sistema Kubernetes, existe um loop de controle que avalia o seletor de cada Service e salva os resultados em um objeto Endpoints correspondente.

kubectl get endpoints hostnames

NAME        ENDPOINTS
hostnames   10.244.0.5:9376,10.244.0.6:9376,10.244.0.7:9376

Isso confirma que o controlador de endpoints encontrou os Pods corretos para seu Service. Se a coluna ENDPOINTS estiver com <none>, você deve verificar se o campo spec.selector do seu Service realmente seleciona os valores de metadata.labels nos seus Pods. Um erro comum é ter um erro de digitação ou outra inconsistência, como o Service selecionando app=hostnames, mas o Deployment especificando run=hostnames, como em versões anteriores à 1.18, onde o comando kubectl run também poderia ser usado para criar um Deployment.

Os Pods estão funcionando?

Neste ponto, você já sabe que seu Service existe e selecionou seus Pods. No início deste passo a passo, você verificou os próprios Pods. Vamos verificar novamente se os Pods estão realmente funcionando – você pode ignorar o mecanismo do Service e ir diretamente para os Pods, conforme listado nos Endpoints acima.

De dentro de um Pod:

for ep in 10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376; do
    wget -qO- $ep
done

Isso deve produzir algo como:

hostnames-632524106-bbpiw
hostnames-632524106-ly40y
hostnames-632524106-tlaok

Você espera que cada Pod na lista de Endpoints retorne seu próprio hostname. Se isso não acontecer (ou se o comportamento correto for diferente para seus próprios Pods), você deve investigar o que está acontecendo.

O kube-proxy está funcionando?

Se você chegou até aqui, seu Service está em execução, possui Endpoints e seus Pods estão realmente respondendo. Neste ponto, todo o mecanismo de proxy do Service pode ser o problema. Vamos confirmá-lo, parte por parte.

A implementação padrão dos Services, e a mais usada na maioria dos clusters, é o kube-proxy. Esse é um programa que roda em cada nó e configura um dos mecanismos disponíveis para fornecer a abstração de Service. Se seu cluster não usa kube-proxy, as próximas seções não se aplicarão, e você precisará investigar qual implementação de Services está em uso.

O kube-proxy está em execução?

Confirme que o kube-proxy está rodando nos seus Nodes. Executando diretamente em um Node, você deve obter algo como o seguinte:

ps auxw | grep kube-proxy
root  4194  0.4  0.1 101864 17696 ?    Sl Jul04  25:43 /usr/local/bin/kube-proxy --master=https://kubernetes-master --kubeconfig=/var/lib/kube-proxy/kubeconfig --v=2

Em seguida, confirme que ele não está falhando em algo óbvio, como contatar o master. Para isso, você precisará verificar os logs. O acesso aos logs depende do sistema operacional do Node. Em alguns sistemas, é um arquivo, como /var/log/kube-proxy.log, enquanto em outros, os logs podem ser acessados com journalctl. Você deve ver algo como:

I1027 22:14:53.995134    5063 server.go:200] Running in resource-only container "/kube-proxy"
I1027 22:14:53.998163    5063 server.go:247] Using iptables Proxier.
I1027 22:14:54.038140    5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns-tcp" to [10.244.1.3:53]
I1027 22:14:54.038164    5063 proxier.go:352] Setting endpoints for "kube-system/kube-dns:dns" to [10.244.1.3:53]
I1027 22:14:54.038209    5063 proxier.go:352] Setting endpoints for "default/kubernetes:https" to [10.240.0.2:443]
I1027 22:14:54.038238    5063 proxier.go:429] Not syncing iptables until Services and Endpoints have been received from master
I1027 22:14:54.040048    5063 proxier.go:294] Adding new service "default/kubernetes:https" at 10.0.0.1:443/TCP
I1027 22:14:54.040154    5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns" at 10.0.0.10:53/UDP
I1027 22:14:54.040223    5063 proxier.go:294] Adding new service "kube-system/kube-dns:dns-tcp" at 10.0.0.10:53/TCP

Se você vir mensagens de erro sobre a impossibilidade de contatar o master, deve verificar novamente a configuração do seu Node e as etapas de instalação.

O kube-proxy pode rodar em diferentes modos. No log listado acima, a linha Using iptables Proxier indica que o kube-proxy está rodando no modo "iptables". O outro modo mais comum é o "ipvs".

Modo Iptables

No modo "iptables", você deve ver algo como o seguinte em um Node:

iptables-save | grep hostnames
-A KUBE-SEP-57KPRZ3JQVENLNBR -s 10.244.3.6/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-57KPRZ3JQVENLNBR -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.3.6:9376
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -s 10.244.1.7/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-WNBA2IHDGP2BOBGZ -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.1.7:9376
-A KUBE-SEP-X3P2623AGDH6CDF3 -s 10.244.2.3/32 -m comment --comment "default/hostnames:" -j MARK --set-xmark 0x00004000/0x00004000
-A KUBE-SEP-X3P2623AGDH6CDF3 -p tcp -m comment --comment "default/hostnames:" -m tcp -j DNAT --to-destination 10.244.2.3:9376
-A KUBE-SERVICES -d 10.0.1.175/32 -p tcp -m comment --comment "default/hostnames: cluster IP" -m tcp --dport 80 -j KUBE-SVC-NWV5X2332I4OT4T3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.33332999982 -j KUBE-SEP-WNBA2IHDGP2BOBGZ
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -m statistic --mode random --probability 0.50000000000 -j KUBE-SEP-X3P2623AGDH6CDF3
-A KUBE-SVC-NWV5X2332I4OT4T3 -m comment --comment "default/hostnames:" -j KUBE-SEP-57KPRZ3JQVENLNBR

Para cada porta de cada Service, deve haver uma regra em KUBE-SERVICES e uma cadeia KUBE-SVC-<hash>. Para cada endpoint do Pod, deve haver um pequeno número de regras nessa cadeia KUBE-SVC-<hash> e uma cadeia KUBE-SEP-<hash> com algumas regras dentro dela. As regras exatas podem variar dependendo da sua configuração específica (incluindo node-ports e load-balancers).

Modo IPVS

No modo "ipvs", você deve ver algo como o seguinte em um Node:

ipvsadm -ln
Prot LocalAddress:Port Scheduler Flags
  -> RemoteAddress:Port           Forward Weight ActiveConn InActConn
...
TCP  10.0.1.175:80 rr
  -> 10.244.0.5:9376               Masq    1      0          0
  -> 10.244.0.6:9376               Masq    1      0          0
  -> 10.244.0.7:9376               Masq    1      0          0
...

Para cada porta de cada Service, além de qualquer NodePort, IP externo e IP de load-balancer, o kube-proxy criará um servidor virtual. Para cada endpoint de Pod, ele criará servidores reais correspondentes. Neste exemplo, o Service hostnames (10.0.1.175:80) tem 3 endpoints (10.244.0.5:9376, 10.244.0.6:9376, 10.244.0.7:9376).

O kube-proxy está realizando o proxy?

Supondo que você tenha identificado um dos casos acima, tente novamente acessar seu Service pelo IP a partir de um dos seus Nodes:

curl 10.0.1.175:80
hostnames-632524106-bbpiw

Se isso ainda falhar, verifique os logs do kube-proxy em busca de linhas específicas como:

Setting endpoints for default/hostnames:default to [10.244.0.5:9376 10.244.0.6:9376 10.244.0.7:9376]

Se você não encontrar essas mensagens nos logs, tente reiniciar o kube-proxy com a flag -v definida como 4 e, em seguida, verifique os logs novamente.

Caso extremo: Um Pod não consegue acessar a si mesmo pelo IP do Service

Isso pode parecer improvável, mas acontece e deveria funcionar corretamente.

Esse problema pode ocorrer quando a rede não está configurada corretamente para tráfego "hairpin", geralmente quando o kube-proxy está rodando no modo iptables e os Pods estão conectados por meio de uma rede bridge. O Kubelet expõe um parâmetro hairpin-mode na linha de comando que permite que os endpoints de um Service realizem balanceamento de carga para si mesmos ao tentar acessar seu próprio VIP do Service. O parâmetro hairpin-mode deve estar configurado como hairpin-veth ou promiscuous-bridge.

As etapas comuns para solucionar esse problema são as seguintes:

  • Confirme se o hairpin-mode está configurado como hairpin-veth ou promiscuous-bridge. Você deve ver algo semelhante ao seguinte. No exemplo abaixo, hairpin-mode está definido como promiscuous-bridge:
ps auxw | grep kubelet
root      3392  1.1  0.8 186804 65208 ?        Sl   00:51  11:11 /usr/local/bin/kubelet --enable-debugging-handlers=true --config=/etc/kubernetes/manifests --allow-privileged=True --v=4 --cluster-dns=10.0.0.10 --cluster-domain=cluster.local --configure-cbr0=true --cgroup-root=/ --system-cgroups=/system --hairpin-mode=promiscuous-bridge --runtime-cgroups=/docker-daemon --kubelet-cgroups=/kubelet --babysit-daemons=true --max-pods=110 --serialize-image-pulls=false --outofdisk-transition-frequency=0
  • Confirme o hairpin-mode efetivo. Para isso, será necessário verificar o log do kubelet. O acesso aos logs depende do sistema operacional do Node. Em alguns sistemas, ele está em um arquivo como /var/log/kubelet.log, enquanto em outros, os logs podem ser acessados com journalctl. Observe que o modo hairpin efetivo pode não corresponder à flag --hairpin-mode devido a questões de compatibilidade. Verifique se há linhas de log contendo a palavra-chave hairpin no kubelet.log. Deve haver linhas indicando o modo hairpin efetivo, como algo semelhante ao seguinte:
I0629 00:51:43.648698    3252 kubelet.go:380] Hairpin mode set to "promiscuous-bridge"
  • Se o modo hairpin efetivo for hairpin-veth, certifique-se de que o Kubelet tem permissão para operar em /sys no Node. Se tudo estiver funcionando corretamente, você deve ver algo como:
for intf in /sys/devices/virtual/net/cbr0/brif/*; do cat $intf/hairpin_mode; done
1
1
1
1
  • Se o modo hairpin efetivo for promiscuous-bridge, certifique-se de que o Kubelet tem permissão para manipular a bridge Linux no Node. Se a bridge cbr0 for usada e configurada corretamente, você deve ver:
ifconfig cbr0 |grep PROMISC
UP BROADCAST RUNNING PROMISC MULTICAST  MTU:1460  Metric:1
  • Procure ajuda se nenhuma das opções acima funcionar.

Procure ajuda

Se você chegou até aqui, algo muito estranho está acontecendo. Seu Service está rodando, tem Endpoints e seus Pods estão realmente respondendo. O DNS está funcionando e o kube-proxy não parece estar com problemas. E, mesmo assim, seu Service não está funcionando. Informe-nos o que está acontecendo, para que possamos ajudar a investigar!

Entre em contato conosco pelo Slack, Fórum ou GitHub.

Próximos passos

Visite o documento de visão geral de solução de problemas para mais informações.

3 - Depuração de um StatefulSet

Esta tarefa mostra como depurar um StatefulSet.

Antes de você começar

  • Você precisa ter um cluster Kubernetes e a ferramenta de linha de comando kubectl configurada para se comunicar com seu cluster.
  • Você deve ter um StatefulSet em execução que deseja investigar.

Depuração de um StatefulSet

Para listar todos os Pods que pertencem a um StatefulSet e possuem o rótulo app.kubernetes.io/name=MyApp definido, você pode usar o seguinte comando:

kubectl get pods -l app.kubernetes.io/name=MyApp

Se você notar que algum dos Pods listados está no estado Unknown ou Terminating por um longo período, consulte a tarefa Excluindo Pods de um StatefulSet para obter instruções sobre como lidar com esses casos. Você pode depurar Pods individuais em um StatefulSet utilizando o guia Depuração de Pods.

Próximos passos

Saiba mais sobre depuração de um Init Container.

4 - Depurando Contêineres de Inicialização

Esta página mostra como investigar problemas relacionados à execução de contêineres de inicialização. As linhas de comando de exemplo abaixo referem-se ao pod como <pod-name> e aos contêineres de inicialização como <init-container-1> e <init-container-2>.

Antes de você começar

Você precisa ter um cluster do Kubernetes e a ferramenta de linha de comando kubectl deve estar configurada para se comunicar com seu cluster. É recomendado executar esse tutorial em um cluster com pelo menos dois nós que não estejam atuando como hosts de camada de gerenciamento. Se você ainda não possui um cluster, pode criar um usando o minikube ou pode usar um dos seguintes ambientes:

Para verificar a versão, digite kubectl version.

Verificando o status dos contêineres de inicialização

Exiba o status do seu pod:

kubectl get pod <pod-name>

Por exemplo, um status de Init:1/2 indica que uma das duas inicializações de contêineres concluíram com sucesso:

NAME         READY     STATUS     RESTARTS   AGE
<pod-name>   0/1       Init:1/2   0          7s

Consulte Entendendo sobre o status do pod para obter mais exemplos de valores de status e seus significados.

Obtendo detalhes sobre os contêineres de inicialização

Veja informações mais detalhadas sobre a execução de contêineres de inicialização:

kubectl describe pod <pod-name>

Por exemplo, um pod com dois contêineres de inicialização pode mostrar o seguinte:

Init Containers:
  <init-container-1>:
    Container ID:    ...
    ...
    State:           Terminated
      Reason:        Completed
      Exit Code:     0
      Started:       ...
      Finished:      ...
    Ready:           True
    Restart Count:   0
    ...
  <init-container-2>:
    Container ID:    ...
    ...
    State:           Waiting
      Reason:        CrashLoopBackOff
    Last State:      Terminated
      Reason:        Error
      Exit Code:     1
      Started:       ...
      Finished:      ...
    Ready:           False
    Restart Count:   3
    ...

Você também pode acessar programaticamente os status dos contêineres de inicialização, lendo o campo status.initContainerStatuses nas especificações do pod:

kubectl get pod nginx --template '{{.status.initContainerStatuses}}'

Este comando retornará as mesmas informações acima em JSON bruto.

Acessando logs de contêineres de inicialização

Passe o nome do contêiner de inicialização junto com o nome do Pod para acessar seus logs.

kubectl logs <pod-name> -c <init-container-2>

Contêineres de inicialização que executam comandos de script de shell imprimem à medida que são executados. Por exemplo, você pode fazer isso no Bash executando set -x no início do script.

Entendendo sobre o status do pod

Um status do Pod começando com Init: resume o status da execução de contêineres de inicialização. A tabela abaixo descreve alguns valores de status de exemplo que você pode ver durante a depuração de contêineres de inicialização.

Status Significado
Init:N/M O pod tem contêineres de inicialização M e N que foram concluídas até agora.
Init:Error Um contêiner de inicialização falhou ao executar.
Init:CrashLoopBackOff Um contêiner de inicialização falhou repetidamente.
Pending O pod ainda não começou a executar o contêiner de inicialização.
PodInitializing ou Running O pod já concluiu a execução dos contêineres de inicialização.