Introdução aos contêineres


Se você não conhece as cargas de trabalho em contêineres, este tutorial é para você. Ele apresenta contêineres e orquestração de contêineres, orientando você na configuração de um aplicativo simples, do código-fonte a um contêiner em execução no GKE.

Este tutorial não exige experiência anterior com contêineres ou Kubernetes. No entanto, se você quiser ler uma visão geral da terminologia principal do Kubernetes antes de iniciar este tutorial, consulte Começar a aprender sobre o Kubernetes. Se você preferir aprender sobre o Kubernetes em forma de histórias em quadrinhos, consulte nosso quadrinho 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 aprenda sobre o GKE em si.

Objetivos

  1. Explorar um aplicativo "hello world" de vários serviços
  2. Execute o aplicativo na 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 Google 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. Make sure that billing is enabled for your Google 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 do 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.
  • Você pode escolher entre os editores de texto integrados:

    • 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 Google Cloud console, activate Cloud Shell.

Activate Cloud Shell

At the bottom of the Google Cloud console, a Cloud Shell session starts and displays a command-line prompt. Cloud Shell is a shell environment with the Google Cloud CLI already installed and with values already set for your current project. It can take a few seconds for the session to initialize.

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. Ela 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 exemplo, 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 server:

    curl http://localhost:8080
    

    A saída de server é a seguinte:

    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 receber mensagens semelhantes a esta:

    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 agora está sendo executado no mesmo host, o que permite usar localhost para enviar solicitações ao server.

  11. Para interromper o loadgen e o server, pressione Ctrl-c em cada janela do 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, é necessário empacotar os componentes do aplicativo de exemplo em contêineres. Um contêiner é um pacote que contém todos os elementos necessários para que o aplicativo seja executado em qualquer ambiente. Este tutorial usa o Docker para criar contêineres do aplicativo.

Para conteinerizar o aplicativo 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 em uma imagem de contêiner. Depois de criar a imagem, faça o upload dela para um registro de contêineres, 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. Confira a seguir o Dockerfile do 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" ]

Neste arquivo, você encontra o seguinte:

  • A instrução FROM python:3-slim as base instrui o Docker a usar a imagem do Python 3 mais recente como a imagem 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 à usada para executar server.py no código-fonte.
  • A instrução EXPOSE especifica que o server detecta a 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, você precisa fazer algumas configurações para as ferramentas e os serviços que vai usar:

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

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

    gcloud config set compute/region us-central1
    

Criar o repositório

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

  1. Verifique se o serviço do Artifact Registry está ativado no seu projetodo Google 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 contêinerizar o aplicativo. Primeiro, faça a contenção do 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 projeto Google Cloud .

    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, contêinerize o serviço do 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 este:

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

Nesse ponto, você pode 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 em caso de falha e também precisa 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 conectando 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 oferece os mecanismos para você interagir com o cluster.

Para executar os contêineres no GKE, primeiro é necessário criar e se conectar 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 do Google Cloud que você definiu 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
    

Examinar 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.

Especifique 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 de um ou mais objetos do Kubernetes.

O exemplo contém um manifesto para 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). Um pod é a menor unidade de computação implantável que você pode criar e gerenciar no Kubernetes e contém um ou mais contêineres.

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

Aplicativo conteinerizado em execução no
GKE

Saiba mais sobre pods, implantações e serviços em Comece a aprender sobre o Kubernetes ou nos recursos no 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 dos pods está o campo image, que é o nome da imagem a ser extraída do Artifact Registry. Na próxima etapa, atualize para a nova imagem que você 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 importante é 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 seu editor de texto preferido).

  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 projeto do Google 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 projeto do Google 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:

  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 do 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 receber 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 do Compute Engine, discos e recursos de rede.

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

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

A seguir