Essa é a versão completa de impressão dessa seção Clique aqui para imprimir.

Retornar à visualização normal.

Acessando Aplicações em um Cluster

Configurar balanceamento de carga, redirecionamento de porta, ou configuração de firewall ou DNS para acessar aplicativos em um cluster.

1 - Acessando clusters

Esse tópico fala sobre diversas maneiras de interagir com clusters.

Acessando pela primeira vez com kubectl

Se estiver acessando o Kubernetes API pela primeira vez, recomendamos usar a CLI do Kubernetes, kubectl.

Para acessar um cluster, você precisa saber a localização do cluster e ter credenciais para acessá-lo. Geralmente, isso é configurado automaticamente quando você trabalha com um Guia de instalação ou outra pessoa configurou o cluster e forneceu a você credenciais e uma localização.

Verifique o local e as credenciais que o kubectl conhece com esse comando:

kubectl config view

Muitos dos exemplos fornecem uma introdução ao uso do kubectl e a documentação completa pode ser encontrada no guia de referência do kubectl.

Acessando diretamente a API REST

O Kubectl lida com a localização e a autenticação no servidor de API. Se você quiser acessar diretamente a API REST com um cliente http como curl ou wget, ou um navegador, há várias maneiras de localizar e autenticar:

  • Executar o kubectl no modo proxy.
    • Método recomendado.
    • Usa a localização previamente armazenada do servidor da API.
    • Verifica a identidade do apiserver usando um certificado autoassinado. Não há possibilidade de ataque MITM (Man-In-The-Middle).
    • Autentica-se no servidor da API.
    • No futuro, poderá fazer balanceamento de carga inteligente no lado do cliente, e transferência em caso de falha.
  • Forneça o local e as credenciais diretamente para o cliente http.
    • Método alternativo.
    • Funciona com alguns tipos de código de cliente que são confundidos pelo uso de um proxy.
    • É necessário importar um certificado raiz em seu navegador para se proteger contra ataque MITM (Man-In-The-Middle).

Usando o kubectl proxy

O comando a seguir executa o kubectl em um modo em que ele atua como um proxy reverso. Ele lida com localização do apiserver e da autenticação. Execute-o desta forma:

kubectl proxy --port=8080

Consulte kubectl proxy para obter mais detalhes.

Em seguida, você pode explorar a API com curl, wget ou um navegador, substituindo localhost por [::1] para IPv6, da seguinte forma:

curl http://localhost:8080/api/

O resultado é semelhante a este:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

Sem kubectl proxy

Use kubectl apply e kubectl describe secret... para criar um token para a conta de serviço padrão com grep/cut:

Primeiro, crie o Secret, solicitando um token para a ServiceAccount padrão:

kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
  name: default-token
  annotations:
    kubernetes.io/service-account.name: default
type: kubernetes.io/service-account-token
EOF

Em seguida, aguarde até que o controlador de token preencha o Secret com um token:

while ! kubectl describe secret default-token | grep -E '^token' >/dev/null; do
  echo "waiting for token..." >&2
  sleep 1
done

Recupere e use o token gerado:

APISERVER=$(kubectl config view --minify | grep server | cut -f 2- -d ":" | tr -d " ")
TOKEN=$(kubectl describe secret default-token | grep -E '^token' | cut -f2 -d':' | tr -d " ")

curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

O resultado é semelhante a este:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

Usando jsonpath:

APISERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}')
TOKEN=$(kubectl get secret default-token -o jsonpath='{.data.token}' | base64 --decode)

curl $APISERVER/api --header "Authorization: Bearer $TOKEN" --insecure

O resultado é semelhante a este:

{
  "kind": "APIVersions",
  "versions": [
    "v1"
  ],
  "serverAddressByClientCIDRs": [
    {
      "clientCIDR": "0.0.0.0/0",
      "serverAddress": "10.0.1.149:443"
    }
  ]
}

Os exemplos acima usam a opção --insecure. Isso deixa o cluster sujeito a ataques MITM. Quando o kubectl acessa o cluster, ele usa um certificado raiz guardado e certificados de cliente para acessar o servidor. (Esses certificados são instalados no diretório ~/.kube). Como os certificados do cluster normalmente são autoassinados, pode ser necessária uma configuração especial para que seu cliente http use o certificado raiz.

Em alguns clusters, o servidor da API não requer autenticação; ele pode servir no localhost ou estar protegido por um firewall. Não há um padrão para isso. A página Controlando Acesso à API do Kubernetes
descreve como um administrador de cluster pode configurar isso.

Acesso programático à API

O Kubernetes suporta oficialmente as bibliotecas de clientes Go e Python.

Cliente Go

  • Para obter a biblioteca, execute o seguinte comando: go get k8s.io/client-go@kubernetes-<kubernetes-version-number>, consulte INSTALL.md para obter instruções detalhadas de instalação. Consulte https://github.com/kubernetes/client-go para ver quais versões são compatíveis.
  • Escreva um aplicativo utilizando o cliente Go. Observe que ela define seus próprios objetos de API, portanto, se necessário, importe as definições de API do cliente Go em vez de importá-las do repositório principal. Por exemplo, import "k8s.io/client-go/kubernetes" está correto.

O cliente Go pode usar o mesmo arquivo kubeconfig como a CLI do kubectl faz, para localizar e autenticar ao apiserver. Veja esse exemplo.

Se o aplicativo for disponibilizado como um pod no cluster, consulte a próxima seção.

Cliente Python

Para usar o cliente Python, execute o seguinte comando: pip install kubernetes. Consulte a página Python Client Library para obter mais opções de instalação.

O cliente Python pode usar o mesmo arquivo kubeconfig que a ferramenta kubectl utiliza para localizar e autenticar ao servidor da API. Veja esse exemplo.

Outras bibliotecas

Existem bibliotecas de clientes para acessar a API utilizando outras linguagens. Consulte a documentação de outras bibliotecas para saber como elas se autenticam.

Acessando a API a partir de um pod

Ao acessar a API a partir de um pod, a localização e a autenticação para o servidor de API são um pouco diferentes.

Consulte Acessando a API a partir de um pod para obter mais detalhes.

Acessando serviços em execução no cluster

A seção anterior descreve como se conectar ao servidor da API do Kubernetes. Para obter informações sobre como se conectar a outros serviços em execução em um cluster do Kubernetes, consulte Acessando serviços em execução em clusters.

Solicitação de redirecionamentos

Os recursos de redirecionamento foram descontinuados e removidos. Em vez disso, use um proxy (veja abaixo).

Tantos proxies

Há vários proxies diferentes que você pode encontrar ao usar o Kubernetes:

  1. O kubectl proxy:

    • é executado no computador de um usuário ou em um pod
    • cria um proxy de um endereço localhost para o servidor da API do Kubernetes
    • a conexão do cliente para o proxy usa HTTP
    • a conexão do proxy para o servidor da API usa HTTPS
    • localiza o apiserver
    • adiciona cabeçalhos de autenticação
  2. O proxy do servidor da API:

    • é um bastião incorporado ao apiserver
    • conecta um usuário fora do cluster aos IPs do cluster que, de outra forma, poderiam não ser acessíveis
    • é executado no processo do servidor da API
    • cliente para proxy usa HTTPS (ou http se o servidor da API estiver configurado dessa forma)
    • a conexão do proxy para o destino pode usar HTTP ou HTTPS, conforme escolhido pelo proxy usando as informações disponíveis
    • pode ser usado para acessar um Nó, Pod ou Serviço
    • faz o balanceamento de carga quando usado para acessar um serviço
  3. O kube proxy:

    • é executado em cada nó
    • proxy de UDP e TCP
    • não entende HTTP
    • fornece balanceamento de carga
    • é usado apenas para acessar serviços
  4. Um Proxy/balanceador de carga na frente do(s) servidor(es) da API:

    • a existência e a implementação variam de cluster para cluster (por exemplo, nginx)
    • fica entre todos os clientes e um ou mais servidores da API
    • atua como um balanceador de carga se houver vários servidores da API.
  5. Balanceadores de carga de provedor de nuvem em serviços externos:

    • são fornecidos por alguns provedores de nuvem computacional (por exemplo, AWS ELB, Google Cloud Load Balancer)
    • são criados automaticamente quando o serviço Kubernetes tem o tipo LoadBalancer
    • usam somente UDP/TCP
    • a implementação varia de acordo com o provedor de nuvem.

Normalmente, os usuários do Kubernetes não precisam se preocupar com nada além dos dois primeiros tipos. O administrador do cluster normalmente garantirá que os últimos tipos sejam configurados corretamente.

2 - Configurar o acesso a múltiplos clusters

Esta página mostra como configurar o acesso a vários clusters usando arquivos de configuração. Depois que os clusters, os usuários e os contextos forem definidos em um ou mais arquivos de configuração, você pode alternar rapidamente entre os clusters usando o comando kubectl config use-context.

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 se kubectl está instalado, execute kubectl version --client. A versão do kubectl deve ter no máximo uma versão menor de diferença da versão do servidor de API do seu cluster.

Defina clusters, usuários e contextos

Suponha que você tenha dois clusters, um para o trabalho de desenvolvimento, chamado development, e outro para o trabalho de teste, chamado test. No cluster development, seus desenvolvedores de front-end trabalham em um namespace chamado frontend, e os desenvolvedores de armazenamento trabalham em um namespace chamado storage. Em seu cluster test, os desenvolvedores trabalham no namespace padrão ou criam namespaces auxiliares conforme acharem adequado. O acesso ao cluster de desenvolvimento requer autenticação por certificado. O acesso ao cluster de teste requer autenticação por nome de usuário e senha.

Crie um diretório chamado config-exercise. Em seu diretório config-exercise, crie um arquivo chamado config-demo com este conteúdo:

apiVersion: v1
kind: Config
preferences: {}

clusters:
- cluster:
  name: development
- cluster:
  name: test

users:
- name: developer
- name: experimenter

contexts:
- context:
  name: dev-frontend
- context:
  name: dev-storage
- context:
  name: exp-test

Um arquivo de configuração descreve clusters, usuários e contextos. Seu arquivo config-demo tem a estrutura para descrever dois clusters, dois usuários e três contextos.

Vá para o diretório config-exercise. Digite estes comandos para adicionar detalhes do cluster ao seu arquivo de configuração:

kubectl config --kubeconfig=config-demo set-cluster development --server=https://1.2.3.4 --certificate-authority=fake-ca-file
kubectl config --kubeconfig=config-demo set-cluster test --server=https://5.6.7.8 --insecure-skip-tls-verify

Adicione detalhes do usuário ao seu arquivo de configuração:

kubectl config --kubeconfig=config-demo set-credentials developer --client-certificate=fake-cert-file --client-key=fake-key-seefile
kubectl config --kubeconfig=config-demo set-credentials experimenter --username=exp --password=some-password

Adicione detalhes de contexto ao seu arquivo de configuração:

kubectl config --kubeconfig=config-demo set-context dev-frontend --cluster=development --namespace=frontend --user=developer
kubectl config --kubeconfig=config-demo set-context dev-storage --cluster=development --namespace=storage --user=developer
kubectl config --kubeconfig=config-demo set-context exp-test --cluster=test --namespace=default --user=experimenter

Abra seu arquivo config-demo para ver os detalhes adicionados. Como alternativa para abrir o arquivo config-demo, você pode usar o comando config view

kubectl config --kubeconfig=config-demo view

O resultado mostra os dois clusters, dois usuários e três contextos:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: fake-ca-file
    server: https://1.2.3.4
  name: development
- cluster:
    insecure-skip-tls-verify: true
    server: https://5.6.7.8
  name: test
contexts:
- context:
    cluster: development
    namespace: frontend
    user: developer
  name: dev-frontend
- context:
    cluster: development
    namespace: storage
    user: developer
  name: dev-storage
- context:
    cluster: test
    namespace: default
    user: experimenter
  name: exp-test
current-context: ""
kind: Config
preferences: {}
users:
- name: developer
  user:
    client-certificate: fake-cert-file
    client-key: fake-key-file
- name: experimenter
  user:
    # Nota de documentação (este comentário NÃO faz parte da saída do comando).
    # Armazenar senhas na configuração do cliente Kubernetes é arriscado.
    # Uma alternativa melhor seria usar um plugin de credenciais
    # e armazenar as credenciais separadamente.
    # Veja https://kubernetes.io/pt-br/docs/reference/access-authn-authz/authentication/#plugins-de-credenciais-client-go
    password: some-password
    username: exp

O fake-ca-file, o fake-cert-file e o fake-key-file acima são os espaços reservados para a localização dos arquivos de certificado. Você precisa alterá-los para a localização real dos arquivos de certificado em seu ambiente.

Às vezes, você pode querer usar dados codificados em Base64 incorporados aqui, em vez de arquivos de certificado separados. Nesse caso, é necessário adicionar o sufixo data às chaves, por exemplo, certificate-authority-data, client-certificate-data, client-key-data.

Cada contexto é uma tripla (cluster, usuário, namespace). Por exemplo, o contexto dev-frontend diz: "Use as credenciais do usuário developer para acessar o namespace frontend do cluster development".

Define o contexto atual:

kubectl config --kubeconfig=config-demo use-context dev-frontend

Agora, sempre que você use um comando kubectl, a ação será aplicada ao cluster, e ao namespace listados no contexto dev-frontend. E o comando usará as credenciais do usuário listado no contexto dev-frontend.

Para ver apenas as informações de configuração associadas ao o contexto atual, use a opção --minify.

kubectl config --kubeconfig=config-demo view --minify

O resultado mostra as informações de configuração associadas ao contexto dev-frontend:

apiVersion: v1
clusters:
- cluster:
    certificate-authority: fake-ca-file
    server: https://1.2.3.4
  name: development
contexts:
- context:
    cluster: development
    namespace: frontend
    user: developer
  name: dev-frontend
current-context: dev-frontend
kind: Config
preferences: {}
users:
- name: developer
  user:
    client-certificate: fake-cert-file
    client-key: fake-key-file

Agora, suponha que você queira trabalhar por um tempo no cluster de teste.

Altere o contexto atual para exp-test:

kubectl config --kubeconfig=config-demo use-context exp-test

Agora, qualquer comando kubectl que você usar, será aplicado ao namespace padrão do cluster test. E o comando usará as credenciais do usuário listado no contexto exp-test.

Ver a configuração associada ao novo contexto atual, exp-test.

kubectl config --kubeconfig=config-demo view --minify

Por fim, suponha que você queira trabalhar por um tempo no namespace storage do cluster development.

Altere o contexto atual para dev-storage:

kubectl config --kubeconfig=config-demo use-context dev-storage

Ver a configuração associada ao novo contexto atual, dev-storage.

kubectl config --kubeconfig=config-demo view --minify

Crie um segundo arquivo de configuração

Em seu diretório config-exercise, crie um arquivo chamado config-demo-2 com este conteúdo:

apiVersion: v1
kind: Config
preferences: {}

contexts:
- context:
    cluster: development
    namespace: ramp
    user: developer
  name: dev-ramp-up

O arquivo de configuração anterior define um novo contexto chamado dev-ramp-up.

Defina a variável de ambiente KUBECONFIG

Verifique se você tem uma variável de ambiente chamada KUBECONFIG. Em caso afirmativo, salve o valor atual da variável de ambiente KUBECONFIG para que você possa restaurá-lo posteriormente. Por exemplo:

Linux

export KUBECONFIG_SAVED="$KUBECONFIG"

Windows PowerShell

$Env:KUBECONFIG_SAVED=$ENV:KUBECONFIG

A variável de ambiente KUBECONFIG é uma lista de caminhos para arquivos de configuração. A lista é delimitada por dois pontos para Linux e Mac, e delimitada por ponto e vírgula para Windows. Se você tiver uma variável de ambiente KUBECONFIG, familiarize-se com os arquivos de configuração na lista.

Anexe temporariamente duas localizações à sua variável de ambiente KUBECONFIG. Por exemplo:

Linux

export KUBECONFIG="${KUBECONFIG}:config-demo:config-demo-2"

Windows PowerShell

$Env:KUBECONFIG=("config-demo;config-demo-2")

Em seu diretório config-exercise, digite este comando:

kubectl config view

O resultado mostra informações mescladas de todos os arquivos listados em sua variável de ambiente KUBECONFIG. Em particular, observe que as informações mescladas têm o contexto dev-ramp-up do arquivo config-demo-2 e os três contextos do arquivo config-demo:

contexts:
- context:
    cluster: development
    namespace: frontend
    user: developer
  name: dev-frontend
- context:
    cluster: development
    namespace: ramp
    user: developer
  name: dev-ramp-up
- context:
    cluster: development
    namespace: storage
    user: developer
  name: dev-storage
- context:
    cluster: test
    namespace: default
    user: experimenter
  name: exp-test

Para obter mais informações sobre como os arquivos kubeconfig são mesclados, consulte Organizando o acesso ao cluster usando arquivos kubeconfig

Explore o diretório $HOME/.kube

Se você já tiver um cluster e puder usar o kubectl para interagir com o o cluster, então provavelmente você tem um arquivo chamado config no diretório $HOME/.kube.

Vá para $HOME/.kube e veja quais arquivos estão lá. Normalmente, há um arquivo chamado config. Também pode haver outros arquivos de configuração nesse diretório. Em um breve momento familiarize-se com o conteúdo desses arquivos.

Acrescente $HOME/.kube/config à sua variável de ambiente KUBECONFIG

Se você tiver um arquivo $HOME/.kube/config e ele ainda não estiver listado em sua variável de ambiente KUBECONFIG, acrescente-o à sua variável de ambiente KUBECONFIG agora. Por exemplo:

Linux

export KUBECONFIG="${KUBECONFIG}:${HOME}/.kube/config"

Windows Powershell

$Env:KUBECONFIG="$Env:KUBECONFIG;$HOME\.kube\config"

Visualize as informações de configuração mescladas de todos os arquivos que agora estão listados em sua variável de ambiente KUBECONFIG. Em seu diretório config-exercise, digite:

kubectl config view

Limpar

Retorne sua variável de ambiente KUBECONFIG ao seu valor original. Por exemplo:

Linux

export KUBECONFIG="$KUBECONFIG_SAVED"

Windows PowerShell

$Env:KUBECONFIG=$ENV:KUBECONFIG_SAVED

Verificar o sujeito representado pelo kubeconfig

Nem sempre é óbvio quais atributos (nome de usuário, grupos) você obterá após a autenticação no cluster. Isso pode ser ainda mais desafiador se você estiver gerenciando mais de um cluster ao mesmo tempo.

Há um subcomando de kubectl para verificar os atributos do sujeito, como o nome de usuário, para o Kubernetes contexto selecionado: kubectl auth whoami.

Leia Acesso da API às informações de autenticação de um cliente para saber mais sobre isso em detalhes.

Próximos passos

3 - Use o redirecionamento de porta para acessar aplicativos em um cluster.

Esta página mostra como usar o kubectl port-forward para se conectar a um servidor MongoDB em execução em um cluster Kubernetes. Esse tipo de conexão pode ser útil para depuração de bancos de dados.

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:

    O seu servidor Kubernetes deve estar numa versão igual ou superior a v1.10. Para verificar a versão, digite kubectl version.
  • Instale o MongoDB Shell.

Criando a implantação e o serviço do MongoDB

  1. Crie uma Implantação que execute o MongoDB:

    kubectl apply -f https://k8s.io/examples/application/mongodb/mongo-deployment.yaml
    

    A saída de um comando bem-sucedido verifica que a implantação foi criada:

    deployment.apps/mongo criado
    

    Visualize o status do pod para verificar se ele está pronto:

    kubectl get pods
    

    A saída exibe o pod criado:

    NAME                     READY   STATUS    RESTARTS   AGE
    mongo-75f59d57f4-4nd6q   1/1     Em execução   0          2m4s
    

    Visualize o status da implantação:

    kubectl get deployment
    

    A saída exibe que a implantação foi criada:

    NAME    READY   UP-TO-DATE   AVAILABLE   AGE
    mongo   1/1     1            1           2m21s
    

    A implantação gerencia automaticamente um conjunto de réplicas. Visualize o status do conjunto de réplicas usando:

    kubectl get replicaset
    

    Visualize o status do conjunto de réplicas usando:

    NAME               DESIRED   CURRENT   READY   AGE
    mongo-75f59d57f4   1         1         1       3m12s
    
  2. Crie um serviço para expor o MongoDB na rede:

    kubectl apply -f https://k8s.io/examples/application/mongodb/mongo-service.yaml
    

    A saída de um comando bem-sucedido verifica que o serviço foi criado:

    service/mongo criado
    

    Verifique o serviço criado::

    kubectl get service mongo
    

    A saída exibe o serviço criado:

    NAME    TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)     AGE
    mongo   ClusterIP   10.96.41.183   <none>        27017/TCP   11s
    
  3. Verifique se o servidor MongoDB está sendo executado no Pod e ouvindo a porta 27017:

    # Altere mongo-75f59d57f4-4nd6q para o nome do Pod
    kubectl get pod mongo-75f59d57f4-4nd6q --template='{{(index (index .spec.containers 0).ports 0).containerPort}}{{"\n"}}'
    

    A saída exibe a porta para o MongoDB nesse Pod:

    27017
    

    27017 é a porta TCP alocada ao MongoDB na internet.

Encaminhe uma porta local para uma porta no Pod

  1. kubectl port-forward permite usar o nome do recurso, como o nome do pod, para selecionar um pod correspondente para encaminhar a porta.

    # Altere mongo-75f59d57f4-4nd6q para o nome do Pod
    kubectl port-forward mongo-75f59d57f4-4nd6q 28015:27017
    

    que é o mesmo que

    kubectl port-forward pods/mongo-75f59d57f4-4nd6q 28015:27017
    

    ou

    kubectl port-forward deployment/mongo 28015:27017
    

    ou

    kubectl port-forward replicaset/mongo-75f59d57f4 28015:27017
    

    ou

    kubectl port-forward service/mongo 28015:27017
    

    Qualquer um dos comandos acima funciona. A saída é semelhante a esta:

    Encaminhamento de 127.0.0.1:28015 -> 27017
    Encaminhamento de [::1]:28015 -> 27017
    
  2. Inicie a interface de linha de comando do MongoDB:

    mongosh --port 28015
    
  3. No prompt de comando do MongoDB, digite o comando ping:

    db.runCommand( { ping: 1 } )
    

    Uma solicitação de ping bem-sucedida retorna:

    { ok: 1 }
    

Opcionalmente, deixe kubectl escolher a porta local

Se você não precisa de uma porta local específica, pode permitir que o kubectl escolha e reserve a porta local e, assim, evitar ter que gerenciar conflitos de porta local, com a sintaxe ligeiramente mais simples:

kubectl port-forward deployment/mongo :27017

A ferramenta kubectl encontra um número de porta local que não está em uso (evitando números de porta baixos, porque esses podem ser usados por outras aplicações). A saída é semelhante a:

Encaminhamento de 127.0.0.1:63753 -> 27017
Encaminhamento de [::1]:63753 -> 27017

Discussão

As conexões feitas à porta local 28015 são encaminhadas para a porta 27017 do Pod que está executando o servidor MongoDB. Com esta conexão em vigor, você pode usar seu local de trabalho para depurar o banco de dados que está sendo executado no Pod.

Próximos passos

Saiba mais sobre kubectl port-forward.

4 - Conectando um Frontend a um Backend usando Serviços

Esta tarefa mostra como criar um microserviço frontend e um microserviço backend. O microserviço backend é um serviço que envia uma mensagem de saudação. O frontend expõe o backend usando o nginx e um objeto Service do Kubernetes.

Objetivos

  • Crie e execute um microserviço de backend de amostra chamado hello usando um objeto Deployment.
  • Use um objeto de serviço (Service) para enviar tráfego para as várias réplicas do microserviço de backend.
  • Crie e execute um microserviço de frontend chamado nginx, também usando um objeto Deployment.
  • Configure o microserviço de frontend para enviar tráfego para o microserviço de backend.
  • Use um objeto Service do tipo LoadBalancer para expor o microserviço de frontend fora do cluster.

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.

Esta tarefa utiliza Serviços com balanceadores de carga externos, que necessitam de um ambiente suportado. Se o seu ambiente não suportar isso, você pode substituir por um serviço do tipo NodePort.

Criando o backend usando um Deployment.

O backend é um microserviço simples de saudação. Aqui está o arquivo de configuração para o Deployment do backend:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  selector:
    matchLabels:
      app: hello
      tier: backend
      track: stable
  replicas: 3
  template:
    metadata:
      labels:
        app: hello
        tier: backend
        track: stable
    spec:
      containers:
        - name: hello
          image: "gcr.io/google-samples/hello-go-gke:1.0"
          ports:
            - name: http
              containerPort: 80
...

Crie o Deployment do backend:

kubectl apply -f https://k8s.io/examples/service/access/backend-deployment.yaml

Veja informações sobre o Deployment do backend:

kubectl describe deployment backend

A saída é semelhante a esta:

Name:                           backend
Namespace:                      default
CreationTimestamp:              Mon, 24 Oct 2016 14:21:02 -0700
Labels:                         app=hello
                                tier=backend
                                track=stable
Annotations:                    deployment.kubernetes.io/revision=1
Selector:                       app=hello,tier=backend,track=stable
Replicas:                       3 desired | 3 updated | 3 total | 3 available | 0 unavailable
StrategyType:                   RollingUpdate
MinReadySeconds:                0
RollingUpdateStrategy:          1 max unavailable, 1 max surge
Pod Template:
  Labels:       app=hello
                tier=backend
                track=stable
  Containers:
   hello:
    Image:              "gcr.io/google-samples/hello-go-gke:1.0"
    Port:               80/TCP
    Environment:        <none>
    Mounts:             <none>
  Volumes:              <none>
Conditions:
  Type          Status  Reason
  ----          ------  ------
  Available     True    MinimumReplicasAvailable
  Progressing   True    NewReplicaSetAvailable
OldReplicaSets:                 <none>
NewReplicaSet:                  hello-3621623197 (3/3 replicas created)
Events:
...

Criando o objeto Service hello

A chave para enviar solicitações do frontend para o backend é o Service do backend. Um Service cria um endereço IP persistente e uma entrada de nome DNS, para que o microserviço do backend possa ser sempre acessado. Um Service usa seletores para encontrar os Pods para os quais ele roteia o tráfego.

Primeiro, explore o arquivo de configuração do Service:

---
apiVersion: v1
kind: Service
metadata:
  name: hello
spec:
  selector:
    app: hello
    tier: backend
  ports:
  - protocol: TCP
    port: 80
    targetPort: http
...

No arquivo de configuração, você pode ver que o Service, chamado de hello, roteia o tráfego para Pods que possuem as labels app: hello e tier: backend.

Crie o Service para o backend:

kubectl apply -f https://k8s.io/examples/service/access/backend-service.yaml

Neste ponto, você possui um Deployment chamado backend executando três réplicas do seu aplicativo hello e possui um Service que pode rotear o tráfego para eles. No entanto, esse serviço ainda não pode ser acessado ou resolvido fora do cluster.

Criando o frontend

Agora que o seu backend está em execução, você pode criar um frontend que seja acessível fora do cluster e se conecte ao backend por meio de solicitações de proxy.

O frontend envia solicitações para os worker Pods do backend usando o nome DNS fornecido ao Serviço do backend. O nome DNS é hello, que é o valor do campo name no arquivo de configuração examples/service/access/backend-service.yaml.

Os Pods no Deployment do frontend executam uma imagem nginx que é configurada para fazer proxy de solicitações para o Serviço de backend hello. Aqui está o arquivo de configuração nginx:

# The identifier Backend is internal to nginx, and used to name this specific upstream
upstream Backend {
    # hello is the internal DNS name used by the backend Service inside Kubernetes
    server hello;
}

server { listen 80;

location / {
    # The following statement will proxy traffic to the upstream named Backend
    proxy_pass http://Backend;
}

}

Similarmente ao backend, o frontend possui um Deployment e um Service. Uma diferença importante a ser notada entre os serviços de backend e frontend é que a configuração do serviço de frontend tem o parâmetro type: LoadBalancer, o que significa que o serviço usa um balanceador de carga fornecido pelo provedor de nuvem e será acessível de fora do cluster.

---
apiVersion: v1
kind: Service
metadata:
  name: frontend
spec:
  selector:
    app: hello
    tier: frontend
  ports:
  - protocol: "TCP"
    port: 80
    targetPort: 80
  type: LoadBalancer
...
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: frontend
spec:
  selector:
    matchLabels:
      app: hello
      tier: frontend
      track: stable
  replicas: 1
  template:
    metadata:
      labels:
        app: hello
        tier: frontend
        track: stable
    spec:
      containers:
        - name: nginx
          image: "gcr.io/google-samples/hello-frontend:1.0"
          lifecycle:
            preStop:
              exec:
                command: ["/usr/sbin/nginx","-s","quit"]
...

Crie o Deployment e o Service para o frontend:

kubectl apply -f https://k8s.io/examples/service/access/frontend-deployment.yaml
kubectl apply -f https://k8s.io/examples/service/access/frontend-service.yaml

A saída mostra que ambos os recursos foram criados:

deployment.apps/frontend created
service/frontend created

Interagindo com o Service frontend

Depois de criar um Service do tipo LoadBalancer, você pode usar este comando para encontrar o IP externo:

kubectl get service frontend --watch

Isso exibe a configuração do Service frontend e fica monitorando por mudanças. Inicialmente, o IP externo é exibido como <pending>:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)  AGE
frontend   LoadBalancer   10.51.252.116   <pending>     80/TCP   10s

Assim que um IP externo é provisionado, a configuração é atualizada para incluir o novo IP na seção EXTERNAL-IP:

NAME       TYPE           CLUSTER-IP      EXTERNAL-IP        PORT(S)  AGE
frontend   LoadBalancer   10.51.252.116   XXX.XXX.XXX.XXX    80/TCP   1m

Esse IP agora pode ser usado para interagir com o serviço frontend de fora do cluster.

Enviando tráfego por meio do frontend

Agora que o frontend e o backend estão conectados, você pode acessar o endpoint usando o comando curl no IP externo do seu serviço frontend:

curl http://${EXTERNAL_IP} # substitua isto pelo `EXTERNAL-IP` que você viu antes

A saída mostra a mensagem gerada pelo backend:

{"message":"Hello"}

Limpando

Para excluir os Services, digite este comando:

kubectl delete services frontend backend

Para excluir os Deployments, ReplicaSets e `Pods que estão executando as aplicações frontend e backend, digite este comando:

kubectl delete deployment frontend backend

Próximos passos

5 - Comunicação entre contêineres no mesmo pod usando um volume compartilhado

Esta página mostra como usar um Volume para realizar a comunicação entre dois contêineres rodando no mesmo Pod. Veja também como permitir que processos se comuniquem por compartilhamento de namespace do processo entre os contêineres.

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.

Criando um pod que executa dois contêineres

Neste exercício, você cria um Pod que executa dois contêineres. Os dois contêineres compartilham um volume que eles podem usar para se comunicar. Aqui está o arquivo de configuração para o Pod:

apiVersion: v1
kind: Pod
metadata:
  name: two-containers
spec:

  restartPolicy: Never

  volumes:
  - name: shared-data
    emptyDir: {}

  containers:

  - name: nginx-container
    image: nginx
    volumeMounts:
    - name: shared-data
      mountPath: /usr/share/nginx/html

  - name: debian-container
    image: debian
    volumeMounts:
    - name: shared-data
      mountPath: /pod-data
    command: ["/bin/sh"]
    args: ["-c", "echo Hello from the debian container > /pod-data/index.html"]

No arquivo de configuração, você pode ver que o Pod tem um shared-data chamado shared-data.

O primeiro contêiner listado no arquivo de configuração executa um servidor nginx. O caminho de montagem para o volume compartilhado é /usr/share/nginx/html. O segundo contêiner é baseado na imagem debian e tem um caminho de montagem /pod-data. O segundo contêiner executa o seguinte comando e é encerrado.

echo Hello from the debian container > /pod-data/index.html

Observe que o segundo contêiner grava o arquivo index.html no diretório raiz do servidor nginx.

Crie o Pod e os dois contêineres:

kubectl apply -f https://k8s.io/examples/pods/two-container-pod.yaml

Veja as informações sobre o Pod e os contêineres:

kubectl get pod two-containers --output=yaml

Aqui está uma parte da saída:

apiVersion: v1
kind: Pod
metadata:
  ...
  name: two-containers
  namespace: default
  ...
spec:
  ...
  containerStatuses:

  - containerID: docker://c1d8abd1 ...
    image: debian
    ...
    lastState:
      terminated:
        ...
    name: debian-container
    ...

  - containerID: docker://96c1ff2c5bb ...
    image: nginx
    ...
    name: nginx-container
    ...
    state:
      running:
    ...

Você pode ver que o contêiner debian foi encerrado e o contêiner nginx ainda está em execução.

Obtenha um shell para o contêiner nginx:

kubectl exec -it two-containers -c nginx-container -- /bin/bash

Em seu shell, verifique que o nginx está em execução:

root@two-containers:/# apt-get update
root@two-containers:/# apt-get install curl procps
root@two-containers:/# ps aux

A saída é semelhante a esta:

USER       PID  ...  STAT START   TIME COMMAND
root         1  ...  Ss   21:12   0:00 nginx: master process nginx -g daemon off;

Lembre-se de que o contêiner debian criou o arquivo index.html no diretório raiz do nginx. Use curl para enviar uma solicitação GET para o servidor nginx:

root@two-containers:/# curl localhost

A saída mostra que o nginx responde com uma página da web escrita pelo contêiner debian:

Hello from the debian container

Discussão

O principal motivo pelo qual os pods podem ter vários contêineres é oferecer suporte a aplicações extras que apoiam uma aplicação principal. Exemplos típicos de aplicativos auxiliares são extratores de dados, aplicações para envio de dados e proxies. Aplicativos auxiliares e primários geralmente precisam se comunicar uns com os outros. Normalmente, isso é feito por meio de um sistema de arquivos compartilhado, conforme mostrado neste exercício, ou por meio da interface de rede de loopback, localhost. Um exemplo desse padrão é um servidor web junto com um programa auxiliar que consulta um repositório Git para novas atualizações.

O volume neste exercício fornece uma maneira dos contêineres se comunicarem durante a vida útil do Pod. Se o Pod for excluído e recriado, todos os dados armazenados no volume compartilhado serão perdidos.

Próximos passos

6 - Configurar DNS em um cluster

O Kubernetes oferece um complemento de DNS para os clusters, que a maioria dos ambientes suportados habilitam por padrão. Na versão do Kubernetes 1.11 e posterior, o CoreDNS é recomendado e instalado por padrão com o kubeadm.

Para mais informações sobre como configurar o CoreDNS para um cluster Kubernetes, veja Personalização do Serviço de DNS. Para ver um exemplo que demonstra como usar o DNS do Kubernetes com o kube-dns, consulte Plugin de exemplo para DNS.

7 - Acessando serviços em execução em clusters

Esta página mostra como se conectar aos serviços em execução no cluster Kubernetes.

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.

Acessando serviços em execução no cluster

No Kubernetes, todos nós, Pods e serviços têm seus próprios IPs. Em muitos casos, os IPs dos nós, dos Pods e alguns dos IPs de serviço em um cluster não serão roteáveis, portanto, não estarão acessíveis a partir de uma máquina fora do cluster, como seu computador.

Maneiras de se conectar

Você tem várias opções para se conectar a nós, Pods e serviços de fora do cluster:

  • Acesse serviços através de IPs públicos.
    • Use um serviço com tipo NodePort ou LoadBalancer para tornar o serviço acessível fora do cluster. Consulte a documentação de serviços e kubectl expose.
    • Dependendo do ambiente do cluster, isso pode expor o serviço apenas para a rede corporativa, ou pode expô-lo para a Internet. Pense se o serviço que está sendo exposto é seguro. Ele faz sua própria autenticação?
    • Coloque Pods atrás de serviços. Para acessar um Pod específico de um conjunto de réplicas, como para depurar, coloque uma label exclusiva no Pod e crie um novo serviço que selecione esta label.
    • Na maioria dos casos, não deve ser necessário para o desenvolvedor de aplicativos acessar diretamente nós através de seus endereços IP.
  • Acesse serviços, nós ou Pods usando o Verbo Proxy.
    • Faz autenticação e autorização do servidor de API antes de acessar o serviço remoto. Use isto se os serviços não forem seguros o suficiente para expor à Internet, ou para obter acesso a portas no IP do nó, ou para depuração.
    • Proxies podem causar problemas para algumas aplicações web.
    • Só funciona para HTTP/HTTPS.
    • Descrito aqui.
  • Acesse a partir de um nó ou Pod no cluster.
    • Execute um Pod e, em seguida, conecte-se a um shell nele usando kubectl exec. Conecte-se a outros nós, Pods e serviços a partir desse shell.
    • Alguns clusters podem permitir que você faça ssh para um nó no cluster. De lá, você pode conseguir acessar os serviços do cluster. Este é um método que não é padrão e funcionará em alguns clusters, mas não em outros. Navegadores e outras ferramentas podem ou não estar instalados. O DNS do cluster pode não funcionar.

Descobrindo serviços integrados

Normalmente, existem vários serviços que são iniciados em um cluster pelo kube-system. Obtenha uma lista desses serviços com o comando kubectl cluster-info:

kubectl cluster-info

A saída é semelhante a esta:

Kubernetes master is running at https://192.0.2.1
elasticsearch-logging is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy
kibana-logging is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/kibana-logging/proxy
kube-dns is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/kube-dns/proxy
grafana is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/monitoring-grafana/proxy
heapster is running at https://192.0.2.1/api/v1/namespaces/kube-system/services/monitoring-heapster/proxy

Isso mostra a URL referente ao verbo proxy para acessar cada serviço. Por exemplo, este cluster tem os logs a nível de cluster habilitados (usando o Elasticsearch), que pode ser acessado em https://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/ se as credenciais adequadas forem passadas ou através do comando kubectl proxy, como por exemplo: http://localhost:8080/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/.

Construindo manualmente URLs de proxy do servidor da API

Como mencionado acima, você usa o comando kubectl cluster-info para recuperar a URL do proxy do serviço. Para criar URLs de proxy que incluem endpoints, sufixos e parâmetros de serviço, você adiciona à URL do proxy do serviço: http://endereço_do_mestre_do_kubernetes/api/v1/namespaces/nome_do_namespace/services/[https:]nome_do_serviço[:nome_da_porta]/proxy

Se você não especificou um nome para a porta, não é necessário especificar nome_da_porta na URL. Você também pode usar o número da porta no lugar do nome_da_porta para portas nomeadas e não nomeadas.

Por padrão, o servidor da API usa um proxy para o seu serviço através de HTTP. Para usar HTTPS, adicione o prefixo https: ao nome do serviço: http://<endereço_do_mestre_do_kubernetes>/api/v1/namespaces/<nome_do_namespace>/services/<nome_do_serviço>/proxy

Os formatos suportados para o segmento <nome_do_serviço> da URL são:

  • <nome_do_serviço> - usa um proxy para a porta padrão ou não nomeada usando http
  • <nome_do_serviço>:<nome_da_porta> - usa um proxy para a porta nomeada ou número da porta especificado usando http
  • https:<nome_do_serviço>: - usa um proxy para a porta padrão ou não nomeada usando https (observe o dois-pontos no final)
  • https:<nome_do_serviço>:<nome_da_porta> - usa um proxy para a porta nomeada ou número da porta especificado usando https
Exemplos
  • Para acessar o endpoint de serviço Elasticsearch _search?q=user:kimchy, você usaria:

    http://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_search?q=user:kimchy
    
  • Para acessar as informações de integridade do cluster Elasticsearch _cluster/health?pretty=true, você usaria:

    https://192.0.2.1/api/v1/namespaces/kube-system/services/elasticsearch-logging/proxy/_cluster/health?pretty=true
    

    As informações de integridade são semelhantes a estas:

      {
        "cluster_name" : "kubernetes_logging",
        "status" : "yellow",
        "timed_out" : false,
        "number_of_nodes" : 1,
        "number_of_data_nodes" : 1,
        "active_primary_shards" : 5,
        "active_shards" : 5,
        "relocating_shards" : 0,
        "initializing_shards" : 0,
        "unassigned_shards" : 5
      }
    
  • Para acessar as informações de integridade do serviço Elasticsearch _cluster/health?pretty=true, você usaria:

    https://192.0.2.1/api/v1/namespaces/kube-system/services/https:elasticsearch-logging:/proxy/_cluster/health?pretty=true
    

Usando navegadores da web para acessar serviços em execução no cluster

Você pode conseguir de colocar um URL de proxy do servidor da API na barra de endereço de um navegador. No entanto:

  • Os navegadores da web geralmente não podem passar tokens, portanto, você pode precisar usar autenticação básica (senha). O servidor da API pode ser configurado para aceitar autenticação básica, mas o seu cluster pode não estar configurado para aceitar autenticação básica.
  • Algumas aplicações da web podem não funcionar, principalmente aqueles com javascript do lado do cliente que constroem URLs com um mecanismo que não está ciente do prefixo do caminho do proxy.