Apresentamos os contentores


Se não estiver familiarizado com cargas de trabalho contentorizadas, este tutorial é para si. Apresenta-lhe os contentores e a orquestração de contentores através da configuração de uma aplicação simples a partir do código fonte para um contentor executado no GKE.

Este tutorial não requer experiência anterior com contentores nem com o Kubernetes. No entanto, se quiser ler uma vista geral da terminologia essencial do Kubernetes antes de começar este tutorial, consulte o artigo Comece a saber mais sobre o Kubernetes (ou, se preferir saber mais sobre o Kubernetes em formato de banda desenhada, consulte a nossa banda desenhada sobre o Kubernetes). Encontra recursos mais detalhados na secção O que fazer a seguir no final do tutorial.

Se já conhecer os contentores e o Kubernetes, pode ignorar este tutorial e começar a saber mais sobre o GKE em si.

Objetivos

  1. Explore uma aplicação "hello world" simples com vários serviços.
  2. Execute a aplicação a partir da origem.
  3. Contentorize a aplicação.
  4. Crie um cluster do Kubernetes.
  5. Implemente os contentores no cluster.

Antes de começar

Siga os passos abaixo para ativar a API Kubernetes Engine:
  1. Visite a página do Kubernetes Engine na Google Cloud consola.
  2. Crie ou selecione um projeto.
  3. Aguarde até que a API e os serviços relacionados sejam ativados. Esta ação pode demorar vários minutos.
  4. Verify that billing is enabled for your Google Cloud project.

Prepare o Cloud Shell

Este tutorial usa o Cloud Shell, que aprovisiona uma máquina virtual (VM) g1-small do Compute Engine com um sistema operativo Linux baseado em Debian.

A utilização do Cloud Shell tem as seguintes vantagens:

  • Um ambiente de programação Python 3 (incluindo o virtualenv) está totalmente configurado.
  • As ferramentas de linhas de comando gcloud, docker, git e kubectl usadas neste tutorial já estão instaladas.
  • Tem à sua escolha editores de texto incorporados:

    • Editor do Cloud Shell, ao qual acede clicando em Abrir editor na parte superior da janela do Cloud Shell.

    • Emacs, Vim ou Nano, aos quais acede a partir da linha de comandos no Cloud Shell.

In the Google Cloud console, activate Cloud Shell.

Activate Cloud Shell

Transfira o exemplo de código

  1. Transfira o código-fonte helloserver:

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

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

Explore a aplicação multiserviços

A aplicação de exemplo está escrita em Python. Tem os seguintes componentes que comunicam através de REST:

  • server: um servidor básico com um ponto final GET, / , que imprime "hello world" na janela do terminal.
  • loadgen: um script que envia tráfego para o server, com um número configurável de pedidos por segundo (RPS).

Aplicação de exemplo

Execute a aplicação a partir da origem

Para se familiarizar com a aplicação de exemplo, execute-a no Cloud Shell:

  1. A partir do diretório sample-apps/helloserver, execute o comando server:

    python3 server/server.py
    

    No arranque, o server apresenta o seguinte:

    INFO:root:Starting server...
    
  2. Abra outra janela de terminal para poder enviar pedidos para server. Para o fazer no Cloud Shell, clique em Abrir um novo separador para abrir outra sessão.

  3. Na nova janela de terminal, envie um pedido para server:

    curl http://localhost:8080
    

    A saída de server é a seguinte:

    Hello World!
    
  4. No mesmo separador, mude para o diretório que contém o script loadgen:

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

    export SERVER_ADDR=http://localhost:8080
    export REQUESTS_PER_SECOND=5
    
  6. Início 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 a aplicação loadgen para gerar tráfego para o server:

    python3 loadgen.py
    

    No arranque, o resultado de loadgen é semelhante ao seguinte:

    Starting loadgen: 2024-10-11 09:49:51.798028
    5 request(s) complete to http://localhost:8080
    
  10. Agora, abra a janela de terminal que está a executar o comando server. Deverá ver mensagens semelhantes às seguintes:

    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, toda a aplicação está agora a ser executada no mesmo anfitrião, o que lhe permite usar localhost para enviar pedidos para o server.

  11. Para parar o loadgen e o server, prima Ctrl-c em cada janela do terminal.

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

    deactivate
    

Contentorize a aplicação

Para executar a aplicação no GKE, tem de empacotar os componentes da aplicação de exemplo em contentores. Um contentor é um pacote que contém todos os elementos necessários para a sua aplicação ser executada em qualquer ambiente. Este tutorial usa o Docker para colocar a aplicação num contentor.

Para colocar a aplicação num contentor com o Docker, precisa de um Dockerfile. Um Dockerfile é um ficheiro de texto que define os comandos necessários para reunir o código-fonte da aplicação e as respetivas dependências numa imagem do contentor. Depois de criar a imagem, carregue-a para um registo de contentores, 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. Segue-se o Dockerfile para o 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 ficheiro, pode ver o seguinte:

  • A instrução FROM python:3-slim as base indica ao Docker que use a imagem do Python 3 mais recente como imagem de base.
  • A instrução COPY . . copia os ficheiros de origem do diretório de trabalho atual (neste caso, server.py) para o sistema de ficheiros do contentor.
  • O elemento ENTRYPOINT define a instrução que é usada para executar o contentor. Neste exemplo, a instrução é semelhante à que usou para executar o comando server.py a partir do código-fonte.
  • A instrução EXPOSE especifica que o server é responsável pela deteção na porta 8080. Esta instrução não expõe nenhuma porta, mas serve como documentação de que tem de abrir a porta 8080 quando executar o contentor.

Prepare-se para colocar a aplicação em contentores

Antes de colocar a aplicação num contentor, tem de fazer alguma configuração para as ferramentas e os serviços que vai usar:

  1. Defina o projeto Google Cloud predefinido para a CLI do Google Cloud.

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

    gcloud config set compute/region us-central1
    

Crie o repositório

Para criar um novo repositório para imagens de contentores Docker no Artifact Registry, faça o seguinte:

  1. Certifique-se de que o serviço Artifact Registry está ativado no seu Google Cloud projeto.

    gcloud services enable artifactregistry.googleapis.com
    
    
  2. Crie 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 através da CLI do Google Cloud:

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

Coloque o server num contentor

Agora, está na altura de contentorizar a sua aplicação. Primeiro, coloque o "hello world" server num contentor e envie a imagem para o Artifact Registry:

  1. Mude para o diretório onde se encontra o exemplo server:

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

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

    A flag -t representa a etiqueta do Docker. Este é o nome da imagem que usa quando implementa o contentor.

  3. Envie a imagem para o Artifact Registry:

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

Coloque o loadgen num contentor

Em seguida, coloque o serviço do gerador de carga num contentor da mesma forma:

  1. Mude para o diretório onde se encontra o exemplo loadgen:

    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
    

Indica as imagens

Obtenha uma lista das imagens no repositório para confirmar que as imagens foram enviadas:

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

O resultado deve apresentar os nomes das imagens que enviou, semelhantes aos seguintes:

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

Crie um cluster do GKE

Neste ponto, pode simplesmente executar os contentores na VM do Cloud Shell usando o comando docker run. No entanto, para executar cargas de trabalho de produção fiáveis, tem de gerir os contentores de uma forma mais unificada. Por exemplo, tem de se certificar de que os contentores são reiniciados se falharem e precisa de uma forma de aumentar a escala e iniciar instâncias adicionais de um contentor para processar aumentos no tráfego.

O GKE pode ajudar a satisfazer estas necessidades. O GKE é uma plataforma de orquestração de contentores que funciona através da ligação de VMs a um cluster. Cada MV é referida como um . Os clusters do GKE são baseados no sistema de gestão de clusters de código aberto do Kubernetes. O Kubernetes fornece os mecanismos através dos quais interage com o seu cluster.

Para executar os contentores no GKE, primeiro tem de criar e, em seguida, estabelecer ligação a um cluster:

  1. Crie o cluster:

    gcloud container clusters create-auto container-intro
    

    O comando gcloud cria um cluster no projeto Google Cloud e na região predefinidos que definiu anteriormente.

    O comando para criar o cluster demora alguns minutos a ser concluído. Quando o cluster estiver pronto, o resultado é semelhante ao seguinte:

     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 comandos kubectl para que a possa usar para gerir o cluster:

    gcloud container clusters get-credentials container-intro
    

Examine manifestos do Kubernetes

Quando executou a aplicação a partir do código-fonte, usou um comando imperativo: python3 server.py

Imperativo significa orientado por verbos: "faz isto".

Por outro lado, o Kubernetes opera num modelo declarativo. Isto significa que, em vez de dizer exatamente ao Kubernetes o que fazer, fornece ao Kubernetes um estado desejado. Por exemplo, o Kubernetes inicia e termina os pods conforme necessário para que o estado real do sistema corresponda ao estado desejado.

Especifica o estado pretendido num ficheiro denominado manifesto. Os manifestos são escritos em linguagens como YAML ou JSON e contêm a especificação de um ou mais objetos Kubernetes.

O exemplo contém um manifesto para o server e o loadgen. Cada manifesto especifica o estado pretendido para o objeto de implementação do Kubernetes (que gere a execução do seu contentor, organizado para gestão 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 implementável que pode criar e gerir no Kubernetes, e contém um ou mais contentores.

O diagrama seguinte representa a aplicação em execução no GKE:

Aplicação contentorizada em execução no GKE

Pode saber mais sobre Pods, implementações e serviços em Comece a aprender sobre o Kubernetes ou nos recursos no final desta página.

Servidor

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

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

Este manifesto contém os seguintes campos:

  • kind indica o tipo de objeto.
  • metadata.name especifica o nome da implementação.
  • O primeiro campo spec contém uma descrição do estado pretendido.
  • spec.replicas especifica o número de pods desejados.
  • A secção spec.template define um modelo de agrupamento. A especificação dos pods inclui o campo image, que é o nome da imagem a extrair do Artifact Registry. No passo seguinte, vai atualizar esta imagem para a nova imagem que acabou de criar.

O Serviço hellosvc é definido da seguinte forma:

apiVersion: v1
kind: Service
metadata:
  name: hellosvc
spec:
  ports:
  - name: http
    port: 80
    targetPort: 8080
  selector:
    app: helloserver
  type: LoadBalancer
  • LoadBalancer: os clientes enviam pedidos para o endereço IP de um balanceador de carga de rede, que tem um endereço IP estável e é acessível fora do cluster.
  • targetPort: lembre-se de que o comando EXPOSE 8080 em Dockerfile não expõe realmente nenhuma porta. Expõe a porta 8080 para poder aceder ao contentor server fora do cluster. Neste caso, hellosvc.default.cluster.local:80 (nome abreviado: hellosvc) é mapeado para a porta 8080 do IP do agrupamento helloserver.
  • port: este é o número da porta que outros serviços no cluster usam quando enviam pedidos.

Gerador de carga

O objeto de implementação em loadgen.yaml é semelhante a server.yaml. Uma diferença notável é que a especificação do pod para a implementação loadgen tem um campo denominado env. Esta secção define as variáveis de ambiente necessárias para loadgen, que definiu anteriormente quando executou a aplicação a partir 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

Uma vez que o loadgen não aceita pedidos recebidos, o campo type está definido como ClusterIP. Este 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

Implemente os contentores no GKE

Para implementar os contentores, aplica os manifestos que especificam o estado pretendido através do kubectl.

Implemente o server

  1. Mude para o diretório onde se encontra o exemplo server:

    cd ~/anthos-service-mesh-samples/docs/helloserver/server/
  2. Abra server.yaml no editor do Cloud Shell (ou no seu editor de texto preferido).

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

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

    Substitua PROJECT_ID pelo ID do seu Google Cloud projeto.

    • Se estiver a usar o editor do Cloud Shell, o ficheiro é guardado automaticamente. Regresse à janela de terminal clicando em Abrir terminal.
    • Se estiver a usar um editor de texto no Cloud Shell, guarde e feche server.yaml.
  4. Implemente o manifesto no Kubernetes:

    kubectl apply -f server.yaml
    

    O resultado é semelhante ao seguinte:

    deployment.apps/helloserver created
    service/hellosvc created
    

Implemente o loadgen

  1. Altere para o diretório onde se encontra loadgen.

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

  3. Mais uma vez, substitua o nome no campo image pelo nome da sua imagem do Docker.

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

    Substitua PROJECT_ID pelo ID do seu Google Cloud projeto.

    • Se estiver a usar o editor do Cloud Shell, o ficheiro é guardado automaticamente. Regresse à janela de terminal clicando em Abrir terminal.
    • Se estiver a usar um editor de texto no Cloud Shell, guarde e feche loadgen.yaml.
  4. Implemente o manifesto no seu cluster:

    kubectl apply -f loadgen.yaml
    

    Em caso de êxito, o comando responde com o seguinte:

    deployment.apps/loadgenerator created
    service/loadgensvc created
    

Valide a implementação

Depois de implementar os manifestos no cluster, verifique se os contentores foram implementados com êxito:

  1. Verifique o estado dos pods no seu cluster:

    kubectl get pods
    

    O comando responde com um estado 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. Obtenha os registos da aplicação do loadgen Pod. Substitua POD_ID pelo identificador do pod do gerador de carga da saída anterior.

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

    kubectl get service hellosvc
    

    O resultado é semelhante ao seguinte:

    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 um pedido para hellosvc. Substitua EXTERNAL_IP pelo endereço IP externo do seu hellosvc.

    curl http://EXTERNAL_IP
    

    Deverá ver a mensagem "Hello World!" do servidor.

Limpar

Para evitar incorrer em custos na sua conta do Google Cloud pelos recursos usados neste tutorial, elimine o projeto que contém os recursos ou mantenha o projeto e elimine os recursos individuais.

Se não quiser eliminar todo o projeto:

  • Elimine o cluster do GKE. A eliminação do cluster elimina todos os recursos que compõem o cluster, como as instâncias, os discos e os recursos de rede do Compute Engine.

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

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

O que se segue?