Acessar objetos da API Kubernetes usando um conector

Um cluster do Google Kubernetes Engine (GKE) consiste em um plano de controle e máquinas de worker chamadas nós. É possível executar as cargas de trabalho conteinerizadas do Kubernetes em um cluster do GKE. Os nós são as máquinas de worker que executam seus aplicativos conteinerizados e outras cargas de trabalho, e o plano de controle é o endpoint unificado do seu cluster. Para mais informações, consulte Arquitetura de clusters do GKE.

O servidor da API Kubernetes é executado no plano de controle, permitindo que você interaja com os objetos do Kubernetes no cluster por meio de chamadas da API Kubernetes. Os objetos são entidades persistentes no sistema Kubernetes e representam o estado do cluster. Para mais informações, na documentação do Kubernetes, consulte Objetos no Kubernetes e a Visão geral da API, que está vinculada às páginas de "Referência da API Kubernetes".

Neste documento, mostramos como usar o conector da API Kubernetes em um fluxo de trabalho para fazer solicitações ao endpoint de serviço do Kubernetes hospedado no plano de controle de um cluster do GKE. Por exemplo, é possível usar o conector para criar implantações do Kubernetes, executar jobs, gerenciar pods ou acessar aplicativos implantados por meio de um proxy. Para mais informações, consulte a Visão geral do conector da API Kubernetes.

Antes de começar

Antes de prosseguir com as tarefas neste documento, verifique se você concluiu determinados pré-requisitos.

Ativar APIs

Antes de acessar os objetos da API Kubernetes usando o conector da API Kubernetes, é necessário ativar as seguintes APIs:

  • API Google Kubernetes Engine: para criar e gerenciar aplicativos baseados em contêineres usando o GKE
  • APIs Workflows: para gerenciar definições e execuções de fluxo de trabalho. Ativar a API Workflows ativa automaticamente a API Workflow Executions.

Console

Ative as APIs:

Ativar as APIs

gcloud

  1. No Console do Google Cloud, ative o Cloud Shell.

    Ativar o Cloud Shell

    Na parte inferior do Console do Google Cloud, uma sessão do Cloud Shell é iniciada e exibe um prompt de linha de comando. O Cloud Shell é um ambiente shell com a CLI do Google Cloud já instalada e com valores já definidos para o projeto atual. A inicialização da sessão pode levar alguns segundos.

  2. Ative as APIs:

    gcloud services enable container.googleapis.com workflows.googleapis.com

Crie uma conta de serviço

Crie uma conta de serviço gerenciada pelo usuário que aja como a identidade do seu fluxo de trabalho e conceda a ela o papel Desenvolvedor do Kubernetes Engine (roles/container.developer) para que o fluxo de trabalho possa acessar objetos da API Kubernetes dentro de clusters.

Console

  1. No console do Google Cloud, acesse a página Contas de serviço.

    Acesse as Contas de serviço

  2. Selecione um projeto e clique em Criar conta de serviço.

  3. No campo Nome da conta de serviço, insira um nome. O console do Google Cloud preenche o campo ID da conta de serviço com base nesse nome.

    No campo Descrição da conta de serviço, insira uma descrição. Por exemplo, Service account for Kubernetes API.

  4. Clique em Criar e continuar.

  5. Na lista Selecionar um papel, filtre e selecione o papel Desenvolvedor do Kubernetes Engine.

  6. Clique em Continuar.

  7. Para concluir a criação da conta, clique em Concluído.

gcloud

  1. Crie a conta de serviço:

    gcloud iam service-accounts create SERVICE_ACCOUNT_NAME
    

    Substitua SERVICE_ACCOUNT_NAME pelo nome da conta de serviço.

  2. Atribua o papel container.developer à conta de usuário:

    gcloud projects add-iam-policy-binding PROJECT_ID \
        --member=serviceAccount:SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com \
        --role=roles/container.developer

    Substitua o PROJECT_ID pelo ID do projeto do Google Cloud.

Observe que é possível usar o IAM e o controle de acesso baseado em papéis (RBAC, na sigla em inglês) do Kubernetes para controlar o acesso ao cluster do GKE:

  • O IAM não é específico do Kubernetes. Ele fornece gerenciamento de identidade para vários produtos do Google Cloud e opera principalmente no nível do projeto do Google Cloud.

  • O RBAC do Kubernetes é um componente principal do Kubernetes e permite criar e conceder papéis (conjuntos de permissões) para qualquer objeto ou tipo de objeto dentro do cluster. Se você usa principalmente o GKE e precisa de permissões refinadas para cada objeto e operação no cluster, o RBAC do Kubernetes é a melhor escolha.

Para mais informações, consulte Controle de acesso.

Crie um cluster do GKE

Para usar o conector da API Kubernetes, você já precisa ter criado um cluster público ou particular do GKE. Em um cluster particular, os nós têm apenas endereços IP internos, o que significa que os nós e os pods são isolados da Internet por padrão. Para mais informações, consulte Clusters particulares.

Também é possível especificar o modo de operação que oferece diferentes níveis de flexibilidade, responsabilidade e controle. Por exemplo, é possível criar um cluster do Autopilot, um modo de operação no GKE em que o Google gerencia a configuração do cluster, incluindo nós, escalonamento, segurança e outras configurações predefinidas. Para mais informações, acesse Escolher um modo de operação do GKE.

Se você ainda não criou um cluster do GKE, é possível implantar um aplicativo conteinerizado de servidor da Web em um cluster do GKE. Ou, para testar as instruções deste documento, crie um cluster do Autopilot seguindo estas instruções.

Console

  1. No Console do Google Cloud, acesse a página de clusters do Kubernetes.

    Acessar clusters do Kubernetes

  2. Clique em Criar.

  3. Se for solicitado que você selecione um modo de cluster, escolha Autopilot.

  4. Na seção Princípios básicos do cluster, conclua o seguinte:

    1. Digite o Nome do cluster, como hello-cluster.
    2. Selecione uma região para o cluster, como us-central1.
  5. Clique em Próximo: rede.

  6. Na seção Acesso à rede IPv4, para criar um cluster com um endpoint acessível publicamente, escolha Cluster público.

  7. Para todas as outras configurações, aceite os padrões.

  8. Clique em Criar.

A criação do cluster pode levar vários minutos para ser concluída. Depois que o cluster for criado, uma marca de seleção indicará que ele está em execução.

gcloud

Execute este comando:

gcloud container clusters create-auto CLUSTER_NAME \
    --location=LOCATION \
    --project=PROJECT_ID

Substitua:

  • CLUSTER_NAME: o nome do seu cluster do GKE, como hello-cluster
  • LOCATION: a região do cluster, como us-central1
  • PROJECT_ID: o ID do projeto do Google Cloud

A criação do cluster pode levar vários minutos para ser concluída. Depois que o cluster é criado, a saída fica mais ou menos assim:

Creating cluster hello-cluster...done.
Created [https://container.googleapis.com/v1/projects/MY_PROJECT/zones/us-central1/clusters/hello-cluster].
[...]
STATUS: RUNNING

Usar o conector para enviar uma solicitação HTTP

Use o conector da API Kubernetes para enviar uma solicitação HTTP ao plano de controle de um cluster do GKE. Por exemplo, o fluxo de trabalho a seguir cria uma implantação chamada nginx-deployment no cluster do Kubernetes especificado. A implantação descreve um estado necessário. Neste caso, para executar três pods com a imagem nginx:1.14.2 e expor o serviço na porta 80. Se não especificado, project e location assumem como padrão o fluxo de trabalho.

Para mais informações, consulte a página de referência da função do conector da API Kubernetes, gke.request.

Observações:

Implantar seu fluxo de trabalho

Antes de executar um fluxo de trabalho, você precisa criá-lo e implantá-lo.

Console

  1. No console do Google Cloud, abra a página Workflows.

    Acessar fluxos de trabalho

  2. Clique em Criar.

  3. Insira um nome para o novo fluxo de trabalho, como kubernetes-api-request.

  4. Na lista Região, selecione us-central1.

  5. Selecione a conta de serviço que você criou anteriormente.

  6. Clique em Próxima.

  7. No editor de fluxo de trabalho, insira a seguinte definição para seu fluxo de trabalho:

    YAML

    main:
      steps:
        - create_deployment:
            call: gke.request
            args:
              cluster_id: "CLUSTER_NAME"
              project: "PROJECT_ID"
              location: "LOCATION"
              method: "POST"
              path: "/apis/apps/v1/namespaces/default/deployments"
              body:
                kind: Deployment
                metadata:
                  name: nginx-deployment
                  labels:
                    app: nginx
                spec:
                  replicas: 3
                  selector:
                    matchLabels:
                      app: nginx
                  template:
                    metadata:
                      labels:
                        app: nginx
                    spec:
                      containers:
                        - name: nginx
                          image: nginx:1.14.2
                          ports:
                            - containerPort: 80
            result: result
        - returnResult:
            return: '${result}'

    JSON

    {
      "main": {
        "steps": [
          {
            "create_deployment": {
              "call": "gke.request",
              "args": {
                "cluster_id": "CLUSTER_NAME",
                "project": "PROJECT_ID",
                "location": "LOCATION",
                "method": "POST",
                "path": "/apis/apps/v1/namespaces/default/deployments",
                "body": {
                  "kind": "Deployment",
                  "metadata": {
                    "name": "nginx-deployment",
                    "labels": {
                      "app": "nginx"
                    }
                  },
                  "spec": {
                    "replicas": 3,
                    "selector": {
                      "matchLabels": {
                        "app": "nginx"
                      }
                    },
                    "template": {
                      "metadata": {
                        "labels": {
                          "app": "nginx"
                        }
                      },
                      "spec": {
                        "containers": [
                          {
                            "name": "nginx",
                            "image": "nginx:1.14.2",
                            "ports": [
                              {
                                "containerPort": 80
                              }
                            ]
                          }
                        ]
                      }
                    }
                  }
                }
              },
              "result": "result"
            }
          },
          {
            "returnResult": {
              "return": "${result}"
            }
          }
        ]
      }
    }
    

    Substitua:

    • CLUSTER_NAME: o nome do seu cluster do GKE, como hello-cluster
    • PROJECT_ID: o ID do projeto do Google Cloud
    • LOCATION: a região do cluster, como us-central1
  8. Selecione Implantar.

gcloud

  1. Crie um arquivo de código-fonte para seu fluxo de trabalho:

    touch kubernetes-api-request.JSON_OR_YAML
    

    Substitua JSON_OR_YAML por yaml ou json, dependendo do formato do seu fluxo de trabalho.

  2. Em um editor de texto, copie o fluxo de trabalho a seguir para seu arquivo de código-fonte:

    YAML

    main:
      steps:
        - create_deployment:
            call: gke.request
            args:
              cluster_id: "CLUSTER_NAME"
              project: "PROJECT_ID"
              location: "LOCATION"
              method: "POST"
              path: "/apis/apps/v1/namespaces/default/deployments"
              body:
                kind: Deployment
                metadata:
                  name: nginx-deployment
                  labels:
                    app: nginx
                spec:
                  replicas: 3
                  selector:
                    matchLabels:
                      app: nginx
                  template:
                    metadata:
                      labels:
                        app: nginx
                    spec:
                      containers:
                        - name: nginx
                          image: nginx:1.14.2
                          ports:
                            - containerPort: 80
            result: result
        - returnResult:
            return: '${result}'

    JSON

    {
      "main": {
        "steps": [
          {
            "create_deployment": {
              "call": "gke.request",
              "args": {
                "cluster_id": "CLUSTER_NAME",
                "project": "PROJECT_ID",
                "location": "LOCATION",
                "method": "POST",
                "path": "/apis/apps/v1/namespaces/default/deployments",
                "body": {
                  "kind": "Deployment",
                  "metadata": {
                    "name": "nginx-deployment",
                    "labels": {
                      "app": "nginx"
                    }
                  },
                  "spec": {
                    "replicas": 3,
                    "selector": {
                      "matchLabels": {
                        "app": "nginx"
                      }
                    },
                    "template": {
                      "metadata": {
                        "labels": {
                          "app": "nginx"
                        }
                      },
                      "spec": {
                        "containers": [
                          {
                            "name": "nginx",
                            "image": "nginx:1.14.2",
                            "ports": [
                              {
                                "containerPort": 80
                              }
                            ]
                          }
                        ]
                      }
                    }
                  }
                }
              },
              "result": "result"
            }
          },
          {
            "returnResult": {
              "return": "${result}"
            }
          }
        ]
      }
    }
    

    Substitua:

    • CLUSTER_NAME: o nome do seu cluster do GKE, como hello-cluster
    • LOCATION: a região do cluster, como us-central1
  3. Implante o fluxo de trabalho:

    gcloud workflows deploy kubernetes-api-request \
        --source=kubernetes-api-request.JSON_OR_YAML \
        --location=LOCATION \
        --service-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com
    

Executar o fluxo de trabalho

Depois de implantar seu fluxo de trabalho, é possível executá-lo. A execução de um fluxo de trabalho também executa a definição atual associada a ele.

Console

  1. No console do Google Cloud, abra a página Workflows.

    Acessar fluxos de trabalho

  2. Na página Fluxos de trabalho, selecione seu fluxo de trabalho para acessar a página de detalhes dele.

  3. Na página Detalhes do fluxo de trabalho, clique em Executar.

  4. Clique em Executar novamente.

  5. Veja os resultados do fluxo de trabalho no painel Saída.

    Se bem-sucedido, o estado de execução será Succeeded e o corpo da resposta será retornado.

gcloud

Execute o fluxo de trabalho:

gcloud workflows run kubernetes-api-request \
    --location=LOCATION

Se bem-sucedido, o estado será SUCCEEDED e o corpo da resposta será retornado.

Usar o conector para executar um job do Kubernetes

É possível usar o conector da API Kubernetes para implantar e executar um job do Kubernetes em um cluster do GKE. O fluxo de trabalho a seguir cria um job do Kubernetes que executa um script Bash que itera por meio de uma sequência de números. O fluxo de trabalho aguarda até 90 segundos para que o job do Kubernetes seja concluído. Caso contrário, será gerado um erro. Se o job for concluído, ele será excluído.

Um job é considerado concluído quando o status inclui um tipo de condição Complete. Exemplo:

  "status": {
    "conditions": [
      {
        "type": "Complete",
        "status": "True"
      }
    ]
  }

Se o job falhar, uma tag FailedJobError será retornada. Exemplo:

{
  "tags": ["FailedJobError"]
  "job": {...}
  "message":"Kubernetes job failed"
}

Para mais informações, consulte as páginas de referência das seguintes funções do conector da API Kubernetes:

Implantar seu fluxo de trabalho

Antes de executar um fluxo de trabalho, você precisa criá-lo e implantá-lo.

Console

  1. No console do Google Cloud, abra a página Workflows.

    Acessar fluxos de trabalho

  2. Clique em Criar.

  3. Insira um nome para o novo fluxo de trabalho, como kubernetes-api-job.

  4. Na lista Região, selecione us-central1.

  5. Selecione a conta de serviço que você criou anteriormente.

  6. Clique em Próxima.

  7. No editor de fluxo de trabalho, insira a seguinte definição para seu fluxo de trabalho:

    YAML

    main:
      steps:
        - init:
            assign:
              - project: "PROJECT_ID"
              - location: "LOCATION"
              - cluster_id: "CLUSTER_NAME"
              - job_name: "JOB_NAME"
              - namespace: "default"
        - create_job:
            call: gke.create_job
            args:
              cluster_id: '${cluster_id}'
              location: '${location}'
              project: '${project}'
              namespace: '${namespace}'
              job:
                apiVersion: batch/v1
                kind: Job
                metadata:
                  name: "${job_name}"
                spec:
                  template:
                    spec:
                      containers:
                        - name: counter
                          image: centos:7
                          command:
                            - "bin/bash"
                            - "-c"
                            - "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"
                      restartPolicy: Never
            result: job
        - wait_for_job:  # if job fails, raise error with "FailedJobError" tag and "job" field
            call: gke.await_job
            args:
              cluster_id: '${cluster_id}'
              job_name: '${job_name}'
              location: '${location}'
              project: '${project}'
              timeout: 90  # 90 seconds
            result: completed_job
        - cleanup_job:
            call: gke.delete_job
            args:
              cluster_id: '${cluster_id}'
              job_name: '${job_name}'
              location: '${location}'
              project: '${project}'
              query:
                propagationPolicy: "Foreground"  # delete child Pods
        - return_job:
            return: '${completed_job}'

    JSON

    {
      "main": {
        "steps": [
          {
            "init": {
              "assign": [
                {
                  "project": "PROJECT_ID"
                },
                {
                  "location": "LOCATION"
                },
                {
                  "cluster_id": "CLUSTER_NAME"
                },
                {
                  "job_name": "JOB_NAME"
                },
                {
                  "namespace": "default"
                }
              ]
            }
          },
          {
            "create_job": {
              "call": "gke.create_job",
              "args": {
                "cluster_id": "${cluster_id}",
                "location": "${location}",
                "project": "${project}",
                "namespace": "${namespace}",
                "job": {
                  "apiVersion": "batch/v1",
                  "kind": "Job",
                  "metadata": {
                    "name": "${job_name}"
                  },
                  "spec": {
                    "template": {
                      "spec": {
                        "containers": [
                          {
                            "name": "counter",
                            "image": "centos:7",
                            "command": [
                              "bin/bash",
                              "-c",
                              "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"
                            ]
                          }
                        ],
                        "restartPolicy": "Never"
                      }
                    }
                  }
                }
              },
              "result": "job"
            }
          },
          {
            "wait_for_job": {
              "call": "gke.await_job",
              "args": {
                "cluster_id": "${cluster_id}",
                "job_name": "${job_name}",
                "location": "${location}",
                "project": "${project}",
                "timeout": 90
              },
              "result": "completed_job"
            }
          },
          {
            "cleanup_job": {
              "call": "gke.delete_job",
              "args": {
                "cluster_id": "${cluster_id}",
                "job_name": "${job_name}",
                "location": "${location}",
                "project": "${project}",
                "query": {
                  "propagationPolicy": "Foreground"
                }
              }
            }
          },
          {
            "return_job": {
              "return": "${completed_job}"
            }
          }
        ]
      }
    }
    

    Substitua:

    • LOCATION: a região do cluster, como us-central1
    • CLUSTER_NAME: o nome do seu cluster do GKE, como hello-cluster
    • JOB_NAME: o nome do job do Kubernetes, como hello-job
  8. Selecione Implantar.

gcloud

  1. Crie um arquivo de código-fonte para seu fluxo de trabalho:

    touch kubernetes-api-job.JSON_OR_YAML
    

    Substitua JSON_OR_YAML por yaml ou json, dependendo do formato do seu fluxo de trabalho.

  2. Em um editor de texto, copie o fluxo de trabalho a seguir para seu arquivo de código-fonte:

    YAML

    main:
      steps:
        - init:
            assign:
              - project: "PROJECT_ID"
              - location: "LOCATION"
              - cluster_id: "CLUSTER_NAME"
              - job_name: "JOB_NAME"
              - namespace: "default"
        - create_job:
            call: gke.create_job
            args:
              cluster_id: '${cluster_id}'
              location: '${location}'
              project: '${project}'
              namespace: '${namespace}'
              job:
                apiVersion: batch/v1
                kind: Job
                metadata:
                  name: "${job_name}"
                spec:
                  template:
                    spec:
                      containers:
                        - name: counter
                          image: centos:7
                          command:
                            - "bin/bash"
                            - "-c"
                            - "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"
                      restartPolicy: Never
            result: job
        - wait_for_job:  # if job fails, raise error with "FailedJobError" tag and "job" field
            call: gke.await_job
            args:
              cluster_id: '${cluster_id}'
              job_name: '${job_name}'
              location: '${location}'
              project: '${project}'
              timeout: 90  # 90 seconds
            result: completed_job
        - cleanup_job:
            call: gke.delete_job
            args:
              cluster_id: '${cluster_id}'
              job_name: '${job_name}'
              location: '${location}'
              project: '${project}'
              query:
                propagationPolicy: "Foreground"  # delete child Pods
        - return_job:
            return: '${completed_job}'

    JSON

    {
      "main": {
        "steps": [
          {
            "init": {
              "assign": [
                {
                  "project": "PROJECT_ID"
                },
                {
                  "location": "LOCATION"
                },
                {
                  "cluster_id": "CLUSTER_NAME"
                },
                {
                  "job_name": "JOB_NAME"
                },
                {
                  "namespace": "default"
                }
              ]
            }
          },
          {
            "create_job": {
              "call": "gke.create_job",
              "args": {
                "cluster_id": "${cluster_id}",
                "location": "${location}",
                "project": "${project}",
                "namespace": "${namespace}",
                "job": {
                  "apiVersion": "batch/v1",
                  "kind": "Job",
                  "metadata": {
                    "name": "${job_name}"
                  },
                  "spec": {
                    "template": {
                      "spec": {
                        "containers": [
                          {
                            "name": "counter",
                            "image": "centos:7",
                            "command": [
                              "bin/bash",
                              "-c",
                              "for i in 9 8 7 6 5 4 3 2 1 ; do echo $i ; done"
                            ]
                          }
                        ],
                        "restartPolicy": "Never"
                      }
                    }
                  }
                }
              },
              "result": "job"
            }
          },
          {
            "wait_for_job": {
              "call": "gke.await_job",
              "args": {
                "cluster_id": "${cluster_id}",
                "job_name": "${job_name}",
                "location": "${location}",
                "project": "${project}",
                "timeout": 90
              },
              "result": "completed_job"
            }
          },
          {
            "cleanup_job": {
              "call": "gke.delete_job",
              "args": {
                "cluster_id": "${cluster_id}",
                "job_name": "${job_name}",
                "location": "${location}",
                "project": "${project}",
                "query": {
                  "propagationPolicy": "Foreground"
                }
              }
            }
          },
          {
            "return_job": {
              "return": "${completed_job}"
            }
          }
        ]
      }
    }
    

    Substitua:

    • LOCATION: a região do cluster, como us-central1
    • CLUSTER_NAME: o nome do seu cluster do GKE, como hello-cluster
    • JOB_NAME: o nome do job do Kubernetes, como hello-job
  3. Implante o fluxo de trabalho:

    gcloud workflows deploy kubernetes-api-job \
        --source=kubernetes-api-job.JSON_OR_YAML \
        --location=LOCATION \
        --service-account=SERVICE_ACCOUNT_NAME@PROJECT_ID.iam.gserviceaccount.com
    

Executar o fluxo de trabalho

Depois de implantar seu fluxo de trabalho, é possível executá-lo. A execução de um fluxo de trabalho também executa a definição atual associada a ele.

Console

  1. No console do Google Cloud, abra a página Workflows.

    Acessar fluxos de trabalho

  2. Na página Fluxos de trabalho, selecione seu fluxo de trabalho para acessar a página de detalhes dele.

  3. Na página Detalhes do fluxo de trabalho, clique em Executar.

  4. Clique em Executar novamente.

    A execução do fluxo de trabalho pode levar alguns minutos.

  5. Veja os resultados do fluxo de trabalho no painel Saída.

    Os resultados serão semelhantes aos mostrados a seguir:

    {
    ...
      },
      "status": {
        "completionTime": "2023-10-31T17:04:32Z",
        "conditions": [
          {
            "lastProbeTime": "2023-10-31T17:04:33Z",
            "lastTransitionTime": "2023-10-31T17:04:33Z",
            "status": "True",
            "type": "Complete"
          }
        ],
        "ready": 0,
        "startTime": "2023-10-31T17:04:28Z",
        "succeeded": 1,
        "uncountedTerminatedPods": {}
      }
    }
    

gcloud

Execute o fluxo de trabalho:

gcloud workflows run kubernetes-api-job \
    --location=LOCATION

A execução do fluxo de trabalho pode levar alguns minutos. Os resultados serão semelhantes aos seguintes:

{
...
  },
  "status": {
    "completionTime": "2023-10-31T17:04:32Z",
    "conditions": [
      {
        "lastProbeTime": "2023-10-31T17:04:33Z",
        "lastTransitionTime": "2023-10-31T17:04:33Z",
        "status": "True",
        "type": "Complete"
      }
    ],
    "ready": 0,
    "startTime": "2023-10-31T17:04:28Z",
    "succeeded": 1,
    "uncountedTerminatedPods": {}
  }
}

A seguir