Como se conectar pelo Google Kubernetes Engine

Nesta página, descrevemos como configurar uma conexão de um aplicativo em execução no Google Kubernetes Engine com uma instância do Cloud SQL.

Introdução

Para acessar uma instância do Cloud SQL a partir de um aplicativo em execução no Google Kubernetes Engine, use o Cloud SQL Proxy (com IP público ou privado) ou conecte-se diretamente usando um endereço IP privado.

O Cloud SQL Proxy é a maneira recomendada de se conectar ao Cloud SQL, mesmo ao usar o IP privado. Isso ocorre porque o proxy fornece criptografia e autenticação fortes usando o IAM, o que pode ajudar a manter seu banco de dados seguro.

As conexões do banco de dados consomem recursos no servidor e no aplicativo conectado. Sempre use boas práticas de gerenciamento de conexão para minimizar o espaço ocupado pelo seu aplicativo e reduzir a probabilidade de exceder os limites de conexão do Cloud SQL. Para mais informações, consulte Como gerenciar conexões de banco de dados.

Antes de começar

Para se conectar ao Cloud SQL, é preciso ter:

  • Um cluster do GKE, com a ferramenta de linha de comando kubectl instalada e configurada para se comunicar com o cluster.

    Para ajuda com o GKE, consulte o Início rápido.

    Para se conectar usando um IP privado, o cluster do GKE precisa ser nativo de VPC e estar na mesma rede VPC que a instância do Cloud SQL.

  • Uma instância criada.

    Para ajuda na criação de uma instância do Cloud SQL, consulte Como criar instâncias.

  • Uma conta de usuário do MySQL configurada na instância.

    Seu aplicativo usará essa conta para se conectar ao banco de dados. Para ajuda na criação de uma conta de usuário, consulte Como criar um usuário.

Sobre secrets

No Kubernetes, os Secrets são uma maneira segura de transmitir detalhes de configuração para seu aplicativo. É possível criar um Secret com detalhes como o nome do banco de dados, o usuário e a senha que podem ser injetados no aplicativo como variáveis de ambiente.

Há muitas maneiras diferentes de usar Secrets, dependendo do tipo de conexão:

  • Um Secret de credenciais de banco de dados inclui o nome do usuário do banco de dados a que você está se conectando e a senha do banco de dados do usuário.
  • Se você se conectar ao proxy, um Secret poderá ser usado para manter o arquivo de credenciais da sua conta de serviço.
  • Se você se conectar a um IP particular, um Secret poderá ser usado para especificar o endereço IP particular da instância do Cloud SQL.

Para exemplos completos de como usar secrets, consulte os repositórios do GitHub mencionados posteriormente nesta página.

Como criar um objeto Secret

  1. Crie os objetos Secret usando o comando kubectl create secret.

    Para criar um Secret de credenciais de banco de dados:

    kubectl create secret generic <YOUR-DB-SECRET> \
      --from-literal=username=<YOUR-DATABASE-USER> \
      --from-literal=password=<YOUR-DATABASE-PASSWORD> \
      --from-literal=database=<YOUR-DATABASE-NAME>
    
  2. Após a criação, é possível visualizar os objetos na seção Configuração da página do Google Kubernetes Engine no Console do Cloud.

Conexão pelo Cloud SQL Proxy

Quando você se conecta usando o Cloud SQL Proxy, o Cloud SQL Proxy é adicionado ao pod usando o padrão de contêiner sidecar. O contêiner de proxy está no mesmo pod que seu aplicativo, o que permite que o aplicativo se conecte ao proxy usando localhost, o que aumenta a segurança e o desempenho. Saiba mais.

Para saber mais, consulte Sobre o Cloud SQL Proxy. Para mais informações sobre como trabalhar com pods, consulte Visão geral de pods na documentação do Kubernetes.

Para se conectar usando o Cloud SQL Proxy, você precisa do seguinte:

  1. O nome da conexão da instância do Cloud SQL.

    O nome da conexão da instância está disponível na página Detalhes da instância do Cloud SQL do Console do Cloud ou pelo comando gcloud sql instances describe.

  2. O local do arquivo de chaves associado a uma conta de serviço com os privilégios adequados para sua instância do Cloud SQL.

    Para mais informações, consulte Como criar uma conta de serviço.

  3. A API Cloud SQL Admin está ativada.

    Ative a API

Como fornecer a conta de serviço ao proxy

A primeira etapa para executar o Cloud SQL Proxy no Google Kubernetes Engine é criar uma conta de serviço para representar seu aplicativo. É recomendável criar uma conta de serviço exclusiva para cada aplicativo, em vez de usar a mesma em todos os lugares. Este modelo é mais seguro, porque permite limitar as permissões por aplicativo.

A conta de serviço do seu aplicativo precisa atender aos seguintes critérios:

  • Pertencer a um projeto com a API Cloud SQL Admin ativada;
  • Ter o papel do IAM de cliente do Cloud SQL (ou equivalente) no projeto que contém a instância à qual você quer se conectar;
  • Ao se conectar usando IP privado, é preciso usar um cluster do GKE nativo de VPC na mesma VPC da sua instância do Cloud SQL.

Você precisa configurar o GKE para fornecer a conta de serviço ao Cloud SQL Proxy. Há duas maneiras recomendadas de fazer isso: identidade da carga de trabalho ou um arquivo de chave da conta de serviço.

Identidade da carga de trabalho

Se você estiver usando o Google Kubernetes Engine, o método preferencial é usar o recurso Identidade da carga de trabalho do GKE. Esse método permite vincular uma conta de serviço do Kubernetes (KSA) a uma conta de serviço do Google (GSA). A GSA poderá ser acessada por aplicativos que usam a KSA correspondente.

Uma conta de serviço do Google (GSA) é uma identidade do IAM que representa o aplicativo no Google Cloud. De modo similar, uma conta de serviço do Kubernetes (KSA) é uma identidade que representa o aplicativo em um cluster do Google Kubernetes Engine.

A Identidade da carga de trabalho vincula uma KSA a uma GSA, fazendo com que qualquer implantação com essa KSA seja autenticada como a GSA nas interações com o Google Cloud.

  1. Ativar a identidade da carga de trabalho para o cluster
  2. Em geral, cada aplicativo tem a própria identidade, representada por um par de KSA e GSA. Crie uma KSA para seu aplicativo executando kubectl apply -f service-account.yaml:

    apiVersion: v1
    kind: ServiceAccount
    metadata:
      name: <YOUR-KSA-NAME> # TODO(developer): replace these values
  3. Ative a vinculação do IAM entre YOUR-GSA-NAME e YOUR-KSA-NAME:

    gcloud iam service-accounts add-iam-policy-binding \
      --role roles/iam.workloadIdentityUser \
      --member "serviceAccount:<YOUR-GCP-PROJECT>.svc.id.goog[<YOUR-K8S-NAMESPACE>/<YOUR-KSA-NAME>]" \
      <YOUR-GSA-NAME>@<YOUR-GCP-PROJECT>.iam.gserviceaccount.com
    
  4. Adicione uma anotação a YOUR-KSA-NAME para concluir a vinculação:

    kubectl annotate serviceaccount \
       <YOUR-KSA-NAME> \
       iam.gke.io/gcp-service-account=<YOUR-GSA-NAME>@<YOUR-GCP-PROJECT>.iam.gserviceaccount.com
    
  5. Por fim, especifique a conta de serviço do objeto k8s.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: <YOUR-DEPLOYMENT-NAME>
    spec:
      selector:
        matchLabels:
          app: <YOUR-APPLICATION-NAME>
      template:
        metadata:
          labels:
            app: <YOUR-APPLICATION-NAME>
        spec:
          serviceAccountName: <YOUR-KSA-NAME>

Arquivo de chave da conta de serviço

Como alternativa, se não for possível usar a identidade da carga de trabalho, o padrão recomendado é ativar um arquivo de chave da conta de serviço no pod do Cloud SQL Proxy e usar a sinalização -credential_file.

  1. Crie um arquivo de credencial para a chave da sua conta de serviço:

    gcloud iam service-accounts keys create ~/key.json \
      --iam-account <YOUR-SA-NAME>@project-id.iam.gserviceaccount.com
    
  2. Transforme a chave da sua conta de serviço em um Secret do k8s:

    kubectl create secret generic <YOUR-SA-SECRET> \
    --from-file=service_account.json=~/key.json
    
  3. Ative o secret como um volume no spec: do objeto k8s:

    volumes:
    - name: <YOUR-SA-SECRET-VOLUME>
      secret:
        secretName: <YOUR-SA-SECRET>
    
  4. Siga as instruções na próxima seção para acessar o volume do pod do proxy.

Como executar o proxy como um arquivo secundário

Recomendamos executar o proxy em um padrão sidecar (como um outro contêiner que compartilha um pod com seu aplicativo). Recomendamos isso em vez de ser executado como um serviço separado por vários motivos:

  • Seu tráfego SQL não será exposto localmente porque o proxy fornece criptografia em conexões de saída, mas você terá que limitar a exposição para conexões de entrada
  • Impede um único ponto de falha. O acesso de cada aplicativo ao seu banco de dados é independente dos outros, tornando-o mais resiliente.
  • Limita o acesso ao proxy, o que permite que você use permissões do IAM por aplicativo em vez de expor o banco de dados a todo o cluster
  • Permite que você faça o escopo das solicitações de recursos com mais precisão. Como o proxy consome recursos linearmente ao uso, esse padrão permite que você defina o escopo com mais precisão e solicite recursos para corresponder aos seus aplicativos à medida que eles são escalonados.
  1. Adicione o Cloud SQL Proxy à configuração do pod em containers::

    - name: cloud-sql-proxy
      # It is recommended to use the latest version of the Cloud SQL proxy
      # Make sure to update on a regular schedule!
      image: gcr.io/cloudsql-docker/gce-proxy:1.17
      command:
        - "/cloud_sql_proxy"
    
        # If connecting from a VPC-native GKE cluster, you can use the
        # following flag to have the proxy connect over private IP
        # - "-ip_address_types=PRIVATE"
    
        # Replace DB_PORT with the port the proxy should listen on
        # Defaults: MySQL: 3306, Postgres: 5432, SQLServer: 1433
        - "-instances=<INSTANCE_CONNECTION_NAME>=tcp:<DB_PORT>"
      securityContext:
        # The default Cloud SQL proxy image runs as the
        # "nonroot" user and group (uid: 65532) by default.
        runAsNonRoot: true

    Se você estiver usando uma chave de conta de serviço, especifique o volume do secret e adicione a sinalização -credential_file ao comando:

      # This flag specifies where the service account key can be found
      - "-credential_file=/secrets/service_account.json"
    securityContext:
      # The default Cloud SQL proxy image runs as the
      # "nonroot" user and group (uid: 65532) by default.
      runAsNonRoot: true
    volumeMounts:
    - name: <YOUR-SA-SECRET-VOLUME>
      mountPath: /secrets/
      readOnly: true
  2. Por fim, configure seu aplicativo para se conectar usando 127.0.0.1 no DB_PORT especificado na seção de comando.

Conclua os arquivos de configuração de exemplo:

Proxy com a identidade da carga de trabalho

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      serviceAccountName: <YOUR-KSA-NAME>
      containers:
      - name: <YOUR-APPLICATION-NAME>
        # ... other container configuration
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: database
      - name: cloud-sql-proxy
        # It is recommended to use the latest version of the Cloud SQL proxy
        # Make sure to update on a regular schedule!
        image: gcr.io/cloudsql-docker/gce-proxy:1.17
        command:
          - "/cloud_sql_proxy"

          # If connecting from a VPC-native GKE cluster, you can use the
          # following flag to have the proxy connect over private IP
          # - "-ip_address_types=PRIVATE"

          # Replace DB_PORT with the port the proxy should listen on
          # Defaults: MySQL: 3306, Postgres: 5432, SQLServer: 1433
          - "-instances=<INSTANCE_CONNECTION_NAME>=tcp:<DB_PORT>"
        securityContext:
          # The default Cloud SQL proxy image runs as the
          # "nonroot" user and group (uid: 65532) by default.
          runAsNonRoot: true

Proxy com a chave da conta de serviço

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      containers:
      - name: <YOUR-APPLICATION-NAME>
        # ... other container configuration
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: database
      - name: cloud-sql-proxy
        # It is recommended to use the latest version of the Cloud SQL proxy
        # Make sure to update on a regular schedule!
        image: gcr.io/cloudsql-docker/gce-proxy:1.17
        command:
          - "/cloud_sql_proxy"

          # If connecting from a VPC-native GKE cluster, you can use the
          # following flag to have the proxy connect over private IP
          # - "-ip_address_types=PRIVATE"

          # Replace DB_PORT with the port the proxy should listen on
          # Defaults: MySQL: 3306, Postgres: 5432, SQLServer: 1433
          - "-instances=<INSTANCE_CONNECTION_NAME>=tcp:<DB_PORT>"

          # This flag specifies where the service account key can be found
          - "-credential_file=/secrets/service_account.json"
        securityContext:
          # The default Cloud SQL proxy image runs as the
          # "nonroot" user and group (uid: 65532) by default.
          runAsNonRoot: true
        volumeMounts:
        - name: <YOUR-SA-SECRET-VOLUME>
          mountPath: /secrets/
          readOnly: true
      volumes:
      - name: <YOUR-SA-SECRET-VOLUME>
        secret:
          secretName: <YOUR-SA-SECRET>

Como se conectar sem o proxy do Cloud SQL

Embora não seja tão seguro, é possível se conectar de um cluster do GKE nativo de VPC a uma instância do Cloud SQL na mesma VPC usando um IP privado sem o proxy.

  1. Crie um secret com o endereço IP privado da instância:

    kubectl create secret generic <YOUR-PRIVATE-IP-SECRET> \
        --from-literal=db_host=<YOUR-PRIVATE-IP-ADDRESS>
    
  2. Em seguida, adicione o secret ao contêiner do aplicativo:

    - name: DB_HOST
      valueFrom:
        secretKeyRef:
          name: <YOUR-PRIVATE-IP-SECRET>
          key: db_host
  3. Por fim, configure seu aplicativo para se conectar usando o endereço IP a partir da variável de ambiente DB_HOST. Você precisará usar a porta correta para o MySQL: 3306

Conclua o arquivo de configuração de exemplo:

Sem proxy: IP privado

apiVersion: apps/v1
kind: Deployment
metadata:
  name: <YOUR-DEPLOYMENT-NAME>
spec:
  selector:
    matchLabels:
      app: <YOUR-APPLICATION-NAME>
  template:
    metadata:
      labels:
        app: <YOUR-APPLICATION-NAME>
    spec:
      containers:
      - name: <YOUR-APPLICATION-NAME>
        # ... other container configuration
        env:
        - name: DB_USER
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: username
        - name: DB_PASS
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: password
        - name: DB_NAME
          valueFrom:
            secretKeyRef:
              name: <YOUR-DB-SECRET>
              key: database
        - name: DB_HOST
          valueFrom:
            secretKeyRef:
              name: <YOUR-PRIVATE-IP-SECRET>
              key: db_host

Precisa de ajuda? Para ajuda na solução de problemas com o proxy, consulte Como solucionar problemas nas conexões do Cloud SQL Proxy ou veja a página de suporte do Cloud SQL.

A seguir