Introdução aos contêineres


Se você não tem familiaridade com cargas de trabalho conteinerizadas, este tutorial é para você. Ele apresenta contêineres e orquestração de contêineres ao mostrar como configurar um aplicativo simples do código-fonte para um contêiner em execução no GKE.

Este tutorial não exige experiência com contêineres ou Kubernetes. No entanto, se você quiser ler uma visão geral da terminologia principal do Kubernetes antes de começar este tutorial, consulte Começar a aprender sobre o Kubernetes ou, se preferir aprender sobre o Kubernetes em formato de quadrinhos, consulte nossa história em quadrinhos do Kubernetes. Você vai encontrar recursos mais detalhados na seção Próximas etapas no final do tutorial.

Se você já conhece contêineres e o Kubernetes, pule este tutorial e comece a aprender sobre o GKE.

Objetivos

  1. Explorar um aplicativo "hello world" de vários serviços
  2. Execute o aplicativo a partir da origem.
  3. Colocar o aplicativo em um contêiner
  4. Criar um cluster do Kubernetes
  5. Implantar os contêineres no cluster

Antes de começar

Siga estas etapas para ativar a API do Kubernetes Engine:
  1. Acesse a página do Kubernetes Engine no console do Trusted Cloud .
  2. Crie ou selecione um projeto.
  3. Aguarde a ativação da API e dos serviços relacionados. Isso pode levar alguns minutos.
  4. Verify that billing is enabled for your Trusted Cloud project.

Preparar o Cloud Shell

Neste tutorial, usamos o Cloud Shell, que provisiona uma máquina virtual (VM) g1-small do Compute Engine executando um sistema operacional Linux baseado em Debian.

O uso do Cloud Shell tem as seguintes vantagens:

  • Um ambiente de desenvolvimento Python 3 (incluindo virtualenv) está totalmente configurado.
  • As ferramentas de linha de comando gcloud, docker, git e kubectl usadas neste tutorial já estão instaladas.
  • É possível escolher os editores de texto integrados:

    • O Editor do Cloud Shell, que você acessa clicando em Abrir editor na parte de cima da janela do Cloud Shell.

    • Emacs, Vim ou Nano, que você acessa na linha de comando do Cloud Shell.

  • In the Trusted Cloud console, activate Cloud Shell.

    Activate Cloud Shell

    Fazer o download do exemplo de código

    1. Faça o download do código-fonte helloserver:

      git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
      
    2. Mude para o diretório do código de amostra:

      cd anthos-service-mesh-samples/docs/helloserver
      

    Explorar o aplicativo multisserviço

    O aplicativo de exemplo é escrito em Python. Ele tem os seguintes componentes que se comunicam usando REST:

    • server: um servidor básico com um endpoint GET, / , que imprime "hello world" na janela do terminal.
    • loadgen: um script que envia tráfego para server, com um número configurável de solicitações por segundo (RPS, na sigla em inglês).

    Exemplo de aplicativo

    Executar o aplicativo a partir do código-fonte

    Para se familiarizar com o aplicativo de amostra, execute-o no Cloud Shell:

    1. No diretório sample-apps/helloserver, execute o server:

      python3 server/server.py
      

      Na inicialização, o server exibe o seguinte:

      INFO:root:Starting server...
      
    2. Abra outra janela de terminal para enviar solicitações ao server. Para fazer isso no Cloud Shell, clique em Abrir uma nova guia para abrir outra sessão.

    3. Na nova janela do terminal, envie uma solicitação para o server:

      curl http://localhost:8080
      

      A saída de server é esta:

      Hello World!
      
    4. Na mesma guia, mude para o diretório que contém o script loadgen:

      cd anthos-service-mesh-samples/docs/helloserver/loadgen
    5. Crie as variáveis de ambiente a seguir:

      export SERVER_ADDR=http://localhost:8080
      export REQUESTS_PER_SECOND=5
      
    6. Inicialize virtualenv:

      virtualenv --python python3 env
      
    7. Ative o ambiente virtual:

      source env/bin/activate
      
    8. Instale os requisitos para loadgen:

      pip3 install -r requirements.txt
      
    9. Execute o aplicativo loadgen para gerar tráfego para o server:

      python3 loadgen.py
      

      Na inicialização, a saída de loadgen é semelhante a esta:

      Starting loadgen: 2024-10-11 09:49:51.798028
      5 request(s) complete to http://localhost:8080
      
    10. Agora abra a janela do terminal que está executando o server. Você vai ver mensagens semelhantes a estas:

      127.0.0.1 - - [11/Oct/2024 09:51:28] "GET / HTTP/1.1" 200 -
      INFO:root:GET request,
      Path: /
      Headers:
      Host: localhost:8080
      User-Agent: python-requests/2.32.3
      Accept-Encoding: gzip, deflate
      Accept: */*
      Connection: keep-alive
      

      Do ponto de vista da rede, todo o aplicativo está em execução no mesmo host, o que permite usar localhost para enviar solicitações ao server.

    11. Para interromper loadgen e server, pressione Ctrl-c em cada janela de terminal.

    12. Na janela de terminal loadgen, desative o ambiente virtual:

      deactivate
      

    Colocar o aplicativo em um contêiner

    Para executar o aplicativo no GKE, você precisa empacotar os dois componentes do aplicativo de amostra em contêineres. Um contêiner é um pacote que contém todos os elementos necessários para que seu aplicativo seja executado em qualquer ambiente. Este tutorial usa o Docker para criar um contêiner do aplicativo.

    Para colocar o aplicativo em um contêiner com o Docker, você precisa de um Dockerfile. Um Dockerfile é um arquivo de texto que define os comandos necessários para juntar o código-fonte do aplicativo e as dependências dele em uma imagem de contêiner. Depois de criar a imagem, faça o upload dela para um registro de contêiner, como o Artifact Registry.

    O código-fonte deste tutorial inclui um Dockerfile para o server e o loadgen com todos os comandos necessários para criar as imagens. Veja a seguir o Dockerfile para server:

    FROM python:3.13-slim as base
    FROM base as builder
    RUN apt-get -qq update \
        && apt-get install -y --no-install-recommends \
            g++ \
        && rm -rf /var/lib/apt/lists/*
    
    # Enable unbuffered logging
    FROM base as final
    ENV PYTHONUNBUFFERED=1
    
    RUN apt-get -qq update \
        && apt-get install -y --no-install-recommends \
            wget
    
    WORKDIR /helloserver
    
    # Grab packages from builder
    COPY --from=builder /usr/local/lib/python3.* /usr/local/lib/
    
    # Add the application
    COPY . .
    
    EXPOSE 8080
    ENTRYPOINT [ "python", "server.py" ]
    

    Nesse arquivo, você pode conferir o seguinte:

    • A instrução FROM python:3-slim as base informa ao Docker para usar a imagem mais recente do Python 3 como a imagem de base.
    • A instrução COPY . . copia os arquivos de origem do diretório de trabalho atual (neste caso, server.py) para o sistema de arquivos do contêiner.
    • O ENTRYPOINT define a instrução usada para executar o contêiner. Neste exemplo, a instrução é semelhante à que você usou para executar server.py do código-fonte.
    • A instrução EXPOSE especifica que o server detecta atividade na porta 8080. Essa instrução não expõe nenhuma porta, mas serve como documentação necessária para abrir a porta 8080 ao executar o contêiner.

    Preparar para colocar o aplicativo em um contêiner

    Antes de contêinerizar o aplicativo, faça algumas configurações para as ferramentas e serviços que você vai usar:

    1. Defina o projeto Trusted Cloud padrão para a Google Cloud CLI.

      gcloud config set project PROJECT_ID
    2. Defina a região padrão da Google Cloud CLI.

      gcloud config set compute/region us-central1
      

    Crie o repositório

    Para criar um repositório para imagens de contêiner do Docker no Artifact Registry, faça o seguinte:

    1. Verifique se o serviço do Artifact Registry está ativado no seu projetoTrusted Cloud .

      gcloud services enable artifactregistry.googleapis.com
      
      
    2. Criar o repositório do Artifact Registry:

      gcloud artifacts repositories create container-intro --repository-format=docker \
          --location=us-central1 \
          --description="My new Docker repository"
      
    3. Configure a autenticação do Docker para o Artifact Registry usando a Google Cloud CLI:

      gcloud auth configure-docker us-central1-docker.pkg.dev
      

    Colocar o server em um contêiner

    Agora é hora de conteinerizar seu aplicativo. Primeiro, crie um contêiner para o server "hello world" e envie a imagem para o Artifact Registry:

    1. Mude para o diretório em que o server de amostra está localizado:

      cd ~/anthos-service-mesh-samples/docs/helloserver/server/
    2. Crie a imagem usando o Dockerfile:

      docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1 .
      
      • Substitua PROJECT_ID pelo ID do seu projeto Trusted Cloud by S3NS .

      A sinalização -t representa a tag do Docker. Esse é o nome da imagem que você usa ao implantar o contêiner.

    3. Envie a imagem para o Artifact Registry:

      docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
      

    Colocar o loadgen em um contêiner

    Em seguida, crie um contêiner para o serviço de gerador de carga da mesma forma:

    1. Mude para o diretório em que o loadgen de amostra está localizado:

      cd ../loadgen
      
    2. Crie a imagem:

      docker build -t us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1 .
      
    3. Envie a imagem para o Artifact Registry:

      docker push us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
      

    Listar as imagens

    Gere uma lista das imagens no repositório para confirmar se as imagens foram enviadas:

    gcloud container images list --repository us-central1-docker.pkg.dev/PROJECT_ID/container-intro
    

    A saída vai listar os nomes das imagens que você enviou, semelhante a isto:

    NAME
    us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver
    us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen
    

    Criar um cluster do GKE

    Neste ponto, é possível executar os contêineres na VM do Cloud Shell usando o comando docker run. No entanto, para executar cargas de trabalho de produção confiáveis, é necessário gerenciar contêineres de maneira mais unificada. Por exemplo, você precisa garantir que os contêineres sejam reiniciados se falharem e de uma maneira de escalonar e iniciar instâncias extras de um contêiner para lidar com aumentos de tráfego.

    O GKE pode ajudar você a atender a essas necessidades. O GKE é uma plataforma de orquestração de contêineres que funciona ao conectar VMs a um cluster. Cada VM é chamada de . Os clusters do GKE são fornecidos pelo sistema de gerenciamento de cluster de código aberto do Kubernetes. O Kubernetes disponibiliza os mecanismos para você interagir com o cluster.

    Para executar os contêineres no GKE, primeiro crie e conecte-se a um cluster:

    1. Crie o cluster:

      gcloud container clusters create-auto container-intro
      

      O comando gcloud cria um cluster no projeto e na região padrão Trusted Cloud definidos anteriormente.

      O comando para criar o cluster leva alguns minutos para ser concluído. Quando o cluster estiver pronto, a saída será semelhante a esta:

       NAME: container-intro
       LOCATION: us-central1
       MASTER_VERSION: 1.30.4-gke.1348000
       MASTER_IP: 34.44.14.166
       MACHINE_TYPE: e2-small
       NODE_VERSION: 1.30.4-gke.1348000
       NUM_NODES: 3
       STATUS: RUNNING
      
    2. Forneça credenciais à ferramenta de linha de comando kubectl para que você possa usá-la para gerenciar o cluster:

      gcloud container clusters get-credentials container-intro
      

    Analisar manifestos do Kubernetes

    Ao executar o aplicativo a partir do código-fonte, você usou um comando imperativo: python3 server.py

    Imperativo significa que ele está orientado por verbos: "faça isso".

    Por outro lado, o Kubernetes opera em um modelo declarativo. Isso significa que, em vez de dizer ao Kubernetes exatamente o que fazer, você informa ao Kubernetes o estado pretendido. Por exemplo, o Kubernetes inicia e encerra os pods conforme necessário para que o estado real do sistema corresponda ao estado desejado.

    Você especifica o estado desejado em um arquivo chamado manifesto. Os manifestos são escritos em linguagens como YAML ou JSON e contêm a especificação para um ou mais objetos do Kubernetes.

    A amostra contém um manifesto para cada server e loadgen. Cada manifesto especifica o estado desejado para o objeto de implantação do Kubernetes (que gerencia a execução do contêiner, empacotado para gerenciamento como um pod do Kubernetes) e o serviço (que fornece um endereço IP para o pod). O pod é a menor unidade de computação implantável que pode ser criada e gerenciada no Kubernetes, e contém um ou mais contêineres.

    O diagrama a seguir descreve o aplicativo em execução no GKE:

    Aplicativo em contêineres executado no
GKE

    Saiba mais sobre pods, implantações e serviços em Começar a aprender sobre o Kubernetes ou nos recursos ao final desta página.

    Servidor

    Primeiro, confira o manifesto do server "hello world":

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: helloserver
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: helloserver
      template:
        metadata:
          labels:
            app: helloserver
        spec:
          containers:
          - image: gcr.io/google-samples/istio/helloserver:v0.0.1
            imagePullPolicy: Always
            name: main
          restartPolicy: Always
          terminationGracePeriodSeconds: 5

    Esse manifesto contém os seguintes campos:

    • kind indica o tipo de objeto.
    • metadata.name especifica o nome da implantação.
    • O primeiro campo spec contém uma descrição do estado desejado.
    • spec.replicas especifica o número de pods desejado.
    • A seção spec.template define um modelo de pod. Incluído na especificação para os pods está no campo image, que é o nome da imagem a ser extraída do Artifact Registry. Na próxima etapa, você vai atualizar isso para a nova imagem que acabou de criar.

    O serviço hellosvc é definido da seguinte maneira:

    apiVersion: v1
    kind: Service
    metadata:
      name: hellosvc
    spec:
      ports:
      - name: http
        port: 80
        targetPort: 8080
      selector:
        app: helloserver
      type: LoadBalancer
    • LoadBalancer: os clientes enviam solicitações para o endereço IP de um balanceador de carga de rede, que tem um endereço IP estável e pode ser acessado fora do cluster.
    • targetPort: lembre-se de que o comando EXPOSE 8080 em Dockerfile não expõe portas. Você expõe a porta 8080 para alcançar o contêiner server fora do cluster. Nesse caso, hellosvc.default.cluster.local:80 (nome abreviado: hellosvc) é mapeado para a porta 8080 do IP do pod helloserver.
    • port: é o número da porta que outros serviços no cluster usam ao enviar solicitações.

    Gerador de carga

    O objeto de implantação em loadgen.yaml é semelhante a server.yaml. Uma diferença significativa é que a especificação do pod para a implantação loadgen tem um campo chamado env. Esta seção define as variáveis de ambiente necessárias para loadgen, que você definiu anteriormente ao executar o aplicativo da origem.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: loadgenerator
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: loadgenerator
      template:
        metadata:
          labels:
            app: loadgenerator
        spec:
          containers:
          - env:
            - name: SERVER_ADDR
              value: http://hellosvc:80/
            - name: REQUESTS_PER_SECOND
              value: '10'
            image: gcr.io/google-samples/istio/loadgen:v0.0.1
            imagePullPolicy: Always
            name: main
            resources:
              limits:
                cpu: 500m
                memory: 512Mi
              requests:
                cpu: 300m
                memory: 256Mi
          restartPolicy: Always
          terminationGracePeriodSeconds: 5

    Como loadgen não aceita solicitações de entrada, o campo type é definido como ClusterIP. Esse tipo de serviço fornece um endereço IP estável que as entidades no cluster podem usar, mas o endereço IP não é exposto a clientes externos.

    apiVersion: v1
    kind: Service
    metadata:
      name: loadgensvc
    spec:
      ports:
      - name: http
        port: 80
        targetPort: 8080
      selector:
        app: loadgenerator
      type: ClusterIP

    Implantar os contêineres no GKE

    Para implantar os contêineres, aplique os manifestos que especificam o estado desejado usando kubectl.

    Implantar o server

    1. Mude para o diretório em que o server de amostra está localizado:

      cd ~/anthos-service-mesh-samples/docs/helloserver/server/
    2. Abra server.yaml no editor do Cloud Shell ou no editor de texto de sua preferência.

    3. Substitua o nome no campo image pelo nome da imagem do Docker.

      image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/helloserver:v0.0.1
      

      Substitua PROJECT_ID pelo ID do seu projeto Trusted Cloud .

      • Se você estiver usando o editor do Cloud Shell, o arquivo será salvo automaticamente. Volte para a janela do terminal clicando em Abrir terminal.
      • Se você estiver usando um editor de texto no Cloud Shell, salve e feche server.yaml.
    4. Implante o manifesto no Kubernetes:

      kubectl apply -f server.yaml
      

      O resultado será assim:

      deployment.apps/helloserver created
      service/hellosvc created
      

    Implantar o loadgen

    1. Mude para o diretório em que loadgen está localizado.

      cd ../loadgen
      
    2. Abra loadgen.yaml em um editor de texto, como antes.

    3. Substitua o nome no campo image pelo nome da imagem do Docker.

      image: us-central1-docker.pkg.dev/PROJECT_ID/container-intro/loadgen:v0.0.1
      

      Substitua PROJECT_ID pelo ID do seu projeto Trusted Cloud .

      • Se você estiver usando o editor do Cloud Shell, o arquivo será salvo automaticamente. Volte para a janela do terminal clicando em Abrir terminal.
      • Se você estiver usando um editor de texto no Cloud Shell, salve e feche loadgen.yaml.
    4. Implante o manifesto no cluster:

      kubectl apply -f loadgen.yaml
      

      Se o procedimento for bem-sucedido, o comando responderá com o seguinte:

      deployment.apps/loadgenerator created
      service/loadgensvc created
      

    verifique sua implantação

    Depois de implantar os manifestos no cluster, verifique se os contêineres foram implantados com sucesso:

    1. Verifique o status dos pods no cluster:

      kubectl get pods
      

      O comando responde com o status semelhante ao seguinte:

      NAME                             READY   STATUS    RESTARTS   AGE
      helloserver-69b9576d96-mwtcj     1/1     Running   0          58s
      loadgenerator-774dbc46fb-gpbrz   1/1     Running   0          57s
      
    2. Encontre os registros do aplicativo do pod loadgen. Substitua POD_ID pelo identificador do pod gerador de carga da saída anterior.

      kubectl logs POD_ID
      
    3. Encontre os endereços IP externos de hellosvc:

      kubectl get service hellosvc
      

      O resultado será assim:

      NAME         TYPE           CLUSTER-IP     EXTERNAL-IP     PORT(S)        AGE
      hellosvc     LoadBalancer   10.81.15.158   192.0.2.1       80:31127/TCP   33m
      
    4. Envie uma solicitação para hellosvc. Substitua EXTERNAL_IP pelo endereço IP externo do hellosvc.

      curl http://EXTERNAL_IP
      

      Você vai ver uma mensagem "Hello World!" do servidor.

    Limpar

    Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.

    Se você não quiser excluir todo o projeto:

    • Exclua o cluster do GKE. A exclusão do cluster exclui todos os recursos que o compõem, como instâncias, discos e recursos de rede do Compute Engine.

       gcloud container clusters delete container-intro
      
    • Exclua o repositório do Artifact Registry:

       gcloud artifacts repositories delete container-intro --location=us-central1
      

    A seguir