O Guia Definitivo para Pods e Serviços no Kubernetes

O Kubernetes é uma poderosa plataforma de orquestração de contêineres, mas para aproveitar todo o seu potencial, é importante entender seus principais componentes, com pods e serviços desempenhando papéis fundamentais. Neste artigo, vamos explorar o que são e como trabalham juntos para expor e gerenciar o acesso a aplicativos em execução dentro de um cluster do Kubernetes.

O Que É um Pod?

Pods são as menores unidades de computação que você pode criar e gerenciar no Kubernetes.

Antes de criarmos um pod, vamos verificar os recursos da API disponíveis no seu cluster do Kubernetes; você pode usar o comando kubectl api-resources. Esse comando lista os recursos da API suportados pelo servidor de API do Kubernetes, incluindo seus nomes abreviados, grupos de API e se são ou não namespaced. Isso é útil para entender as capacidades do seu cluster, especialmente ao trabalhar com recursos personalizados ou explorar novos recursos do Kubernetes. O comando kubectl explain complementa isso fornecendo informações detalhadas sobre recursos individuais.

Vamos criar um arquivo de configuração básico para um pod executando um contêiner Nginx simples.

Crie um arquivo chamado nginx-pod.yaml:

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

Aqui está uma breve explicação dos termos utilizados:

  • apiVersion: v1: Especifica a versão da API.
  • kind: Pod: Indica que esta configuração é para um pod.
  • metadata:name: O nome do pod.
  • metadados: rótulos: Pares de chave-valor que podem ser usados para organizar e selecionar o pod.
  • spec:containers: Uma lista de contêineres que serão executados no pod.
  • spec:containers:nome: O nome do contêiner.
  • spec:containers:imagem: A imagem do contêiner a ser usada (neste caso, a última imagem do Nginx).
  • spec:containers:portas: As portas a serem expostas pelo contêiner.

Use kubectl para aplicar o arquivo de configuração e criar o pod:

  • kubectl apply -f nginx-pod.yaml

Verifique o status do pod para garantir que tenha sido criado e esteja em execução:

  • kubectl get pods

Você deverá ver uma saída semelhante a esta:

Shell

 

NAME         READY   STATUS    RESTARTS    AGE
nginx-pod    1/1     Running   0           10s

Em seguida, exclua o pod:

  • kubectl delete pod nginx-pod

A saída deve ser semelhante ao seguinte:

Shell

 

kubectl get pod
No resources found in default namespace.

O que é um Serviço?

A criação de um serviço para um pod Nginx no Kubernetes permite expor a aplicação Nginx e torná-la acessível dentro ou fora do cluster. Aqui está um guia passo a passo para criar um Serviço para um pod Nginx.

Para garantir que você tenha um pod Nginx em execução, se ainda não tiver, crie um arquivo YAML chamado nginx-pod.yaml:

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
  labels:
    app: nginx
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80

Aplicar a configuração do Pod:

  • kubectl apply -f nginx-pod.yaml

Crie um arquivo YAML chamado nginx-service.yaml para definir o Serviço:

YAML

 

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
       targetPort: 80
  type: ClusterIP

Aqui estão algumas coisas a serem observadas:

  • selector: Um seletor de rótulo para corresponder ao pod Nginx.
  • app: nginx: Isso deve corresponder ao rótulo no pod Nginx.
  • type: ClusterIP: O tipo do Serviço. ClusterIP torna o Serviço acessível apenas dentro do cluster. Você também pode usar NodePort ou LoadBalancer para expor o Serviço externamente.

Aplicar a configuração do Serviço usando kubectl:

  • kubectl apply -f nginx-service.yaml
  • kubectl get services
Shell

 

NAME             TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
nginx-service    ClusterIP   10.96.0.1        <none>        80/TCP    10s

Como o Serviço é do tipo ClusterIP, ele só é acessível dentro do cluster. Para acessá-lo de fora do cluster, você pode alterar o tipo de Serviço para NodePort ou LoadBalancer.

Para expor o Serviço externamente usando NodePort, modifique o arquivo nginx-service.yaml:

YAML

 

apiVersion: v1
kind: Service
metadata:
  name: nginx-service
spec:
  selector:
    app: nginx
  ports:
    - protocol: TCP
      port: 80
       targetPort: 80
      nodePort: 30007  # Specify a node port in the range 30000-32767 (optional)
  type: NodePort

Aplicar a configuração atualizada do Serviço:

  • kubectl apply -f nginx-service.yaml

Agora você pode acessar a aplicação Nginx usando o endereço IP do nó e a porta do nó (por exemplo, http://<node-ip>:30007).

Pods de Múltiplos Contêineres

Usar um único contêiner por pod fornece a máxima granularidade e desacoplamento. No entanto, existem cenários nos quais implantar múltiplos contêineres, às vezes referidos como contêineres compostos, dentro de um único pod é benéfico. Esses contêineres secundários podem desempenhar várias funções: lidar com o registro ou aprimorar o contêiner primário (conceito de sidecar), atuar como um proxy para sistemas externos (conceito de embaixador) ou modificar dados para se ajustar a um formato externo (conceito de adaptador). Esses contêineres secundários complementam o contêiner primário ao realizar tarefas que ele não lida.

Abaixo está um exemplo de uma configuração de Pod do Kubernetes que inclui um contêiner primário executando um servidor Nginx e um contêiner secundário atuando como um sidecar para lidar com o registro. O contêiner sidecar usa um contêiner de registro simples como o BusyBox para demonstrar como ele pode monitorar os logs de acesso do Nginx.

YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: nginx-with-logging-sidecar
spec:
  containers:
  - name: nginx
    image: nginx:latest
    ports:
    - containerPort: 80
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
  - name: log-sidecar
    image: busybox:latest
    command: ["sh", "-c", "tail -f /var/log/nginx/access.log"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/nginx
  volumes:
  - name: shared-logs
    emptyDir: {}

Em seguida, você fará o seguinte:

  • Salve a configuração YAML em um arquivo, por exemplo, nginx-with-logging-sidecar.yaml
  • Aplique a configuração usando kubectl:kubectl apply -f nginx-with-logging-sidecar.yaml
  • Verifique se o Pod está em execução: kubectl get pods
  • Verifique os logs do contêiner sidecar para ver os logs de acesso do Nginx: kubectl logs -f <nome-do-pod> -c log-sidecar.

Seguindo estes passos, você excluirá o Pod existente e aplicará a nova configuração, configurando um Pod com um contêiner Nginx e um contêiner sidecar para logging. Isso garantirá que a nova configuração esteja ativa e em execução em seu cluster Kubernetes.

Os pods de vários contêineres no Kubernetes oferecem várias vantagens, possibilitando implantação e gerenciamento de aplicativos mais flexíveis e eficientes.

Padrões de Pod de Vários Contêineres

Padrão Sidecar

Contêineres sidecar podem aprimorar o aplicativo principal fornecendo funções auxiliares como logging, gerenciamento de configuração ou proxy. Este padrão ajuda a estender a funcionalidade sem modificar o contêiner principal. Um contêiner sidecar pode lidar com logging coletando e encaminhando logs do contêiner do aplicativo principal.

Padrão Embaixador

Contêineres embaixadores atuam como um proxy, gerenciando a comunicação entre o aplicativo principal e os serviços externos. Isso pode simplificar a integração e configuração. Um contêiner embaixador pode lidar com a terminação SSL ou funções de gateway de API.

O padrão Embaixador envolve o uso de um contêiner sidecar para gerenciar a comunicação entre o aplicativo principal e os serviços externos. Este padrão pode lidar com tarefas como proxy, balanceamento de carga ou gerenciamento de conexões seguras, abstraindo assim a complexidade do contêiner do aplicativo principal.

  • Contêiner de Aplicativo Principal: Um servidor web simples que faz requisições HTTP
  • Contêiner Embaixador: Proxy Envoy configurado para gerenciar requisições à API externa
YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: app-with-ambassador
spec:
  containers:
  - name: web-app
    image: python:3.8-slim
    command: ["python", "-m", "http.server", "8000"]
    volumeMounts:
    - name: config-volume
      mountPath: /etc/envoy
  - name: envoy-proxy
    image: envoyproxy/envoy:v1.18.3
    args: ["-c", "/etc/envoy/envoy.yaml"]
    ports:
    - containerPort: 8080
    volumeMounts:
    - name: config-volume
      mountPath: /etc/envoy
  volumes:
  - name: config-volume
    configMap:
      name: envoy-config

---
apiVersion: v1
kind: ConfigMap
metadata:
  name: envoy-config
data:
  envoy.yaml: |
    static_resources:
      listeners:
      - name: listener_0
        address:
          socket_address:
            address: 0.0.0.0
            port_value: 8080
        filter_chains:
        - filters:
          - name: envoy.filters.network.http_connection_manager
            typed_config:
              "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
              stat_prefix: ingress_http
              route_config:
                name: local_route
                virtual_hosts:
                - name: local_service
                  domains: ["*"]
                  routes:
                  - match:
                      prefix: "/"
                    route:
                      cluster: external_service
              http_filters:
              - name: envoy.filters.http.router
      clusters:
      - name: external_service
        connect_timeout: 0.25s
        type: LOGICAL_DNS
        lb_policy: ROUND_ROBIN
        load_assignment:
          cluster_name: external_service
          endpoints:
          - lb_endpoints:
            - endpoint:
                address:
                  socket_address:
                    address: api.example.com
                    port_value: 80

Este exemplo demonstra o padrão Ambassador no Kubernetes, onde um proxy Envoy atua como intermediário para gerenciar a comunicação externa para o contêiner de aplicativo principal. Este padrão ajuda a abstrair as complexidades da comunicação e aprimora a modularidade e a manutenibilidade.

Padrão Adaptador

Contêineres Adaptadores podem modificar ou transformar dados entre a aplicação principal e sistemas externos, garantindo compatibilidade e integração. Por exemplo, um contêiner adaptador pode reformatar dados de log para atender aos requisitos de um serviço de log externo.

O padrão Adaptador no Kubernetes envolve o uso de um contêiner lateral para transformar dados entre o contêiner de aplicativo principal e sistemas externos. Isso pode ser útil quando a aplicação principal requer dados em um formato específico que difere do formato fornecido ou exigido pelos sistemas externos.

Suponha que você tenha um contêiner de aplicativo principal que gera logs em um formato personalizado. Você precisa enviar esses logs para um serviço de log externo que requer logs em um formato padronizado específico. Um contêiner adaptador pode ser usado para transformar os dados de log no formato necessário antes de enviá-los para o serviço externo.

  • Contêiner de Aplicativo Principal: Uma aplicação simples que escreve logs em um formato personalizado.
  • Contêiner Adaptador: Um contêiner que lê os logs personalizados, os transforma em formato JSON e os envia para um serviço de log externo.
YAML

 

apiVersion: v1
kind: Pod
metadata:
  name: app-with-adapter
spec:
  containers:
  - name: log-writer
    image: busybox
    command: ["sh", "-c", "while true; do echo \"$(date) - Custom log entry\" >> /var/log/custom/app.log; sleep 5; done"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/custom
  - name: log-adapter
    image: busybox
    command: ["sh", "-c", "tail -f /var/log/custom/app.log | while read line; do echo \"$(echo $line | sed 's/ - / - {\"timestamp\": \"/;s/$/\"}/')\" >> /var/log/json/app.json; done"]
    volumeMounts:
    - name: shared-logs
      mountPath: /var/log/custom
    - name: json-logs
      mountPath: /var/log/json
  - name: log-sender
    image: busybox
    command: ["sh", "-c", "while true; do cat /var/log/json/app.json | grep -v '^$' | while read line; do echo \"Sending log to external service: $line\"; done; sleep 10; done"]
    volumeMounts:
    - name: json-logs
      mountPath: /var/log/json
  volumes:
  - name: shared-logs
    emptyDir: {}
  - name: json-logs
    emptyDir: {}

Este exemplo demonstra o padrão Adapter no Kubernetes, onde um contêiner adaptador transforma dados do contêiner de aplicativo principal no formato necessário antes de enviá-lo para um sistema externo. Esse padrão ajuda a integrar aplicativos com serviços externos ao lidar com transformações de formato de dados dentro do contêiner sidecar.

Resumo

Em resumo, pods:

  • São as menores unidades implantáveis no Kubernetes.
  • Representam uma única instância de um processo em execução.
  • Podem conter um ou mais contêineres.

Serviços:

  • Fornece um endereço IP estável e nome DNS para acessar pods.
  • Permite o balanceamento de carga em um conjunto de pods.
  • Facilita a descoberta de serviços dentro do cluster.

Source:
https://dzone.com/articles/the-ultimate-guide-to-kubernetes-pods-and-services