Como criar clusters privados do GKE com proxies de rede para acesso mestre

Ao criar um cluster privado do GKE com um endpoint mestre, não é possível acessar o nó mestre do cluster pela Internet pública. No entanto, é necessário que ele possa ser acessado para fins de administração.

Por padrão, os clusters podem acessar o mestre por meio do respectivo endpoint particular, e é possível definir redes autorizadas na VPC.

No entanto, para acessar o mestre a partir de uma rede local ou de outra rede VPC, é necessário realizar mais etapas. Isso ocorre porque a rede VPC que hospeda o mestre é de propriedade do Google e não pode ser acessada de recursos conectados por meio de outra conexão de peering de rede VPC, Cloud VPN ou Cloud Interconnect.

Para acessar o mestre a partir de uma rede local ou de outra rede VPC conectada pelo Cloud VPN ou pelo Cloud Interconnect, ative a exportação de rota (Beta) da rede VPC de propriedade do Google para sua rede VPC.

Para ativar o acesso ao mestre a partir de outra rede VPC ou de uma rede local conectada por outro peering de rede VPC, como projetos com hub e spoke, crie um proxy hospedado no espaço de endereços IP autorizado, já que o peering de rede VPC não é transitivo.

Neste tutorial, você aprenderá a configurar esse proxy no cluster privado do GKE.

Objetivos

  • Criar um cluster privado do GKE sem acesso externo.
  • Criar e implantar uma imagem do Docker para executar o proxy.
  • Criar um serviço Kubernetes para acessar o proxy.
  • Testar o acesso ao proxy.

Custos

Neste tutorial, há componentes faturáveis do Google Cloud Platform, incluindo estes:

Use a calculadora de preços para gerar uma estimativa de custo com base no uso previsto.

Ao concluir este tutorial, exclua os recursos criados para evitar o faturamento contínuo. Para mais informações, consulte Como fazer a limpeza.

Antes de começar

  1. Faça login na sua Conta do Google.

    Se você ainda não tiver uma, inscreva-se.

  2. No Console do Cloud, na página de seletor de projetos, selecione ou crie um projeto do Cloud.

    Acessar a página do seletor de projetos

  3. Verifique se a cobrança está ativada para o seu projeto do Google Cloud. Saiba como confirmar se a cobrança está ativada para o seu projeto.

  4. Ative as APIs Compute Engine and Google Kubernetes Engine.

    Ative as APIs

Como configurar o ambiente

Neste tutorial, use o Cloud Shell para inserir comandos. O Cloud Shell fornece acesso à linha de comando no Console do Cloud e inclui o SDK do Cloud e outras ferramentas que precisam ser desenvolvidas no Google Cloud. Ele aparece como uma janela na parte inferior do Console do Cloud. A inicialização leva vários minutos, mas a janela aparece imediatamente.

Siga estes passos para configurar o ambiente usando o Cloud Shell:

  1. No Console do Cloud, abra o Cloud Shell.

    ABRIR Cloud Shell

  2. Verifique se você está trabalhando no projeto criado ou selecionado. Substitua o [YOUR_PROJECT_ID] pelo ID do projeto do Google Cloud.

    gcloud config set project [YOUR_PROJECT_ID]
    export PROJECT_ID=`gcloud config list --format="value(core.project)"`
    
  3. Defina a zona de computação padrão. Para os fins deste tutorial, use us-east1. Se você estiver implantando em um ambiente de produção, faça isso em uma região de sua escolha.

    gcloud config set compute/region us-central1
    gcloud config set compute/zone us-central1-c
    export REGION=us-central1
    export ZONE=us-central1-c
    
    

Como criar uma rede VPC e uma VM cliente

Crie uma rede e uma sub-rede VPC para hospedar os recursos.

  1. Crie uma rede VPC:

    gcloud compute networks create k8s-proxy --subnet-mode=custom
    
  2. Crie uma sub-rede personalizada na rede VPC recém-criada:

    gcloud compute networks subnets create subnet-cluster \
        --network=k8s-proxy --range=10.50.0.0/16
    
  3. Crie uma VM cliente que você usará para implantar recursos no cluster do Kubernetes:

    gcloud compute instances create --subnet=subnet-cluster \
        --scopes cloud-platform proxy-temp
    
  4. Salve o endereço IP interno da instância recém-criada em uma variável de ambiente:

    export CLIENT_IP=`gcloud compute instances describe proxy-temp \
        --format="value(networkInterfaces[0].networkIP)"`
    
  5. Crie uma regra de firewall para permitir o acesso SSH à rede VPC:

    gcloud compute firewall-rules create k8s-proxy-ssh --network k8s-proxy \
        --allow tcp:22
    

Como criar um cluster particular

Agora, crie um cluster particular para usar neste tutorial.

Se você já tiver um cluster de sua preferência, poderá ignorar a etapa de criação, mas terá que configurar alguma maneira inicial de acesso na máquina cliente.

  • No Cloud Shell, crie um cluster:

    gcloud container clusters create frobnitz  \
        --master-ipv4-cidr=172.16.0.64/28 \
        --network k8s-proxy \
        --subnetwork=subnet-cluster \
        --enable-ip-alias \
        --enable-private-nodes \
        --enable-private-endpoint \
        --master-authorized-networks $CLIENT_IP/32 \
        --enable-master-authorized-networks
    

    O comando cria um cluster privado do GKE denominado frobnitz. Ele tem redes autorizadas pelo mestre e configuradas para permitir que apenas a máquina cliente tenha acesso.

Como criar a imagem do Docker

Use os passos a seguir para criar uma imagem de proxy chamada k8s-api-proxy, da API do Kubernetes. A imagem atua como um proxy de encaminhamento para o servidor dessa API.

  1. No Cloud Shell, crie um diretório e mude para ele:

    mkdir k8s-api-proxy && cd k8s-api-proxy
  2. Crie o Dockerfile. A configuração a seguir cria um contêiner do Alpine (em inglês), que é uma distribuição de contêineres leve com um proxy Privoxy. O Dockerfile também instala curl e jq para a inicialização do contêiner, adiciona os arquivos de configuração necessários, expõe a porta 8118 para o GKE internamente e acrescenta um script de inicialização.

    FROM alpine
    RUN apk add -U curl privoxy jq && \ mv /etc/privoxy/templates /etc/privoxy-templates && \ rm -rf /var/cache/apk/* /etc/privoxy/* && \ mv /etc/privoxy-templates /etc/privoxy/templates ADD --chown=privoxy:privoxy config \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-only.action \ /etc/privoxy/ ADD --chown=privoxy:privoxy k8s-rewrite-internal.filter \ /etc/privoxy/ ADD k8s-api-proxy.sh /
    EXPOSE 8118/tcp
    ENTRYPOINT ["./k8s-api-proxy.sh"]
  3. No diretório k8s-api-proxy, crie o arquivo config e adicione o seguinte conteúdo a ele:

    #config directory
    confdir /etc/privoxy
    # Allow Kubernetes API access only
    actionsfile /etc/privoxy/k8s-only.action
    # Rewrite https://CLUSTER_IP to https://kubernetes.default
    filterfile /etc/privoxy/k8s-rewrite-internal.filter
    # Don't show the pod name in errors
    hostname k8s-privoxy
    # Bind to all interfaces, port :8118
    listen-address  :8118
    # User cannot click-through a block
    enforce-blocks 1
    # Allow more than one outbound connection
    tolerate-pipelining 1
    
  4. No mesmo diretório, crie o arquivo k8s-only.action e adicione o seguinte conteúdo a ele. Observe que CLUSTER_IP será substituído quando k8s-api-proxy.sh for executado.

    # Block everything...
    {+block{Not Kubernetes}}
    /
    # ... except the internal k8s endpoint, which you rewrite (see # k8s-rewrite-internal.filter). {+client-header-filter{k8s-rewrite-internal} -block{Kubernetes}} CLUSTER_IP/
  5. Crie o arquivo k8s-rewrite-internal.filter e adicione o seguinte conteúdo a ele. Observe que CLUSTER_IP será substituído quando k8s-api-proxy.sh for executado.

    CLIENT-HEADER-FILTER: k8s-rewrite-internal\
     Rewrite https://CLUSTER_IP/ to https://kubernetes.default/
    s@(CONNECT) CLUSTER_IP:443\
     (HTTP/\d\.\d)@$1 kubernetes.default:443 $2@ig
    
  6. Crie o arquivo k8s-api-proxy.sh e adicione o seguinte conteúdo a ele.

    #!/bin/sh
    
    set -o errexit
    set -o pipefail
    set -o nounset
    
    # Get the internal cluster IP
    export TOKEN=$(cat /run/secrets/kubernetes.io/serviceaccount/token)
    INTERNAL_IP=$(curl -H "Authorization: Bearer $TOKEN" -k -SsL https://kubernetes.default/api |
    jq -r '.serverAddressByClientCIDRs[0].serverAddress')
    
    # Replace CLUSTER_IP in the rewrite filter and action file
    sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\
     /etc/privoxy/k8s-rewrite-internal.filter
    sed -i "s/CLUSTER_IP/${INTERNAL_IP}/g"\
     /etc/privoxy/k8s-only.action
    
    # Start Privoxy un-daemonized
    privoxy --no-daemon /etc/privoxy/config
    
  7. Torne o k8s-api-proxy.sh executável:

    chmod +x k8s-api-proxy.sh
  8. Crie e envie o contêiner para o projeto.

    docker build -t gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 .
    docker push gcr.io/$PROJECT_ID/k8s-api-proxy:0.1
    

Como implantar a imagem e o serviço

  1. No Cloud Shell, faça login na VM cliente criada anteriormente:

    gcloud compute ssh proxy-temp
    
  2. Instale a ferramenta kubectl:

    sudo apt-get install kubectl
    
  3. Salve o ID do projeto como uma variável de ambiente:

    export PROJECT_ID=`gcloud config list --format="value(core.project)"`
    
  4. Consiga as credenciais do cluster:

    gcloud container clusters get-credentials frobnitz \
    --zone us-central1-c --internal-ip
    
  5. Crie uma implantação do Kubernetes que exponha o contêiner recém-criado:

    kubectl run k8s-api-proxy \
        --image=gcr.io/$PROJECT_ID/k8s-api-proxy:0.1 \
        --port=8118
    
  6. Crie o arquivo ilb.yaml para o balanceador de carga interno e copie o seguinte nele:

    apiVersion: v1
    kind: Service
    metadata:
      labels:
        run: k8s-api-proxy
      name: k8s-api-proxy
      namespace: default
      annotations:
        cloud.google.com/load-balancer-type: "Internal"
    spec:
      ports:
      - port: 8118
        protocol: TCP
        targetPort: 8118
      selector:
        run: k8s-api-proxy
      type: LoadBalancer
    
  7. Implante o balanceador de carga interno:

    kubectl create -f ilb.yaml
  8. Verifique o serviço e aguarde um endereço IP:

    kubectl get service/k8s-api-proxy

    A saída será semelhante à exibida a seguir. Quando você vê um IP externo, o proxy está pronto.

    NAME            TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)          AGE
    k8s-api-proxy   LoadBalancer   10.24.13.129   10.24.24.3    8118:30282/TCP   2m
    

    O endereço IP externo desta etapa é o endereço do proxy.

  9. Salve o endereço IP do ILB como uma variável de ambiente:

    export LB_IP=`kubectl get  service/k8s-api-proxy \
    -o jsonpath='{.status.loadBalancer.ingress[].ip}'`
    
  10. Salve o endereço IP mestre do cluster em uma variável de ambiente:

    export MASTER_IP=`gcloud container clusters describe frobnitz \
    --zone=us-central1-c \
    --format="get(privateClusterConfig.privateEndpoint)"`
    
  11. Acesse a API do Kubernetes por meio proxy vara verificar se ele é utilizável:

    curl -k -x $LB_IP:8118 https://$MASTER_IP/api
    
    O resultado será semelhante ao exibido a seguir:
    {
      "kind": "APIVersions",
      "versions": [
        "v1"
      ],
      "serverAddressByClientCIDRs": [
        {
          "clientCIDR": "0.0.0.0/0",
          "serverAddress": "172.16.0.66:443"
        }
      ]
    }
    
  12. Defina a variável de ambiente https_proxy como o proxy HTTP(S) para que o comando kubectl possa alcançar o balanceador de carga interno a partir de qualquer lugar:

    export https_proxy=$LB_IP:8118
  13. Para testar o proxy e a variável https_proxy, execute o comando kubectl:

    kubectl get pods

    Você terá um resultado parecido com o seguinte, o que significa que você se conectou com êxito à API do Kubernetes por meio do proxy:

    NAME                             READY   STATUS    RESTARTS   AGE
    k8s-api-proxy-766c69dd45-mfqf4   1/1     Running   0          6m15s
    
  14. Saia da VM cliente:

    exit

Como fazer a limpeza

Para evitar que os recursos usados neste tutorial sejam cobrados na conta do Google Cloud Platform, faça o seguinte:

Excluir o projeto

  1. No Console do Cloud, acesse a página Gerenciar recursos:

    Acessar a página Gerenciar recursos

  2. Na lista de projetos, selecione o projeto que você quer excluir e clique em Excluir .
  3. Na caixa de diálogo, digite o ID do projeto e clique em Encerrar para excluí-lo.

A seguir