Cloud Intelligence™Cloud Intelligence™

Cloud Intelligence™

Modernizando o acesso a aplicações internas no GKE: da VPN ao Gateway externo com IAP

By Nir ForerJan 13, 20256 min read

Esta página também está disponível em English, Deutsch, Español, Français, Italiano e 日本語.

Aposente a VPN e adote uma solução Zero Trust moderna para aplicações HTTPS internas

Você ainda gerencia conexões VPN para que seu time remoto acesse aplicações internas no GKE (Google Kubernetes Engine)? Existe um caminho melhor. Neste post, vamos mostrar como trocar o acesso tradicional via VPN pelo Identity-Aware Proxy (IAP) do Google Cloud usando o GKE External Gateway. Essa abordagem moderna reduz o esforço operacional e ainda oferece um controle de acesso muito mais granular, com autenticação e autorização via IAM.

Por que fazer a troca?

O acesso tradicional via VPN a aplicações internas traz uma série de desafios:

  • Alto esforço operacional para gerenciar túneis VPN
  • Custos extras com infraestrutura de VPN
  • Configurações de roteamento de rede complexas
  • Controle de acesso pouco granular

Ao implementar um External Gateway com IAP habilitado, você consegue:

  • Consolidar várias aplicações atrás de um único load balancer HTTPS
  • Gerenciar o acesso entre diferentes namespaces do GKE com eficiência
  • Aproveitar o robusto sistema de autenticação do Google Cloud
  • Reduzir custos e complexidade da infraestrutura

GKE Ingress vs. Gateway: comparativo na implementação do IAP

Ao implementar o IAP com o GKE, você tem duas abordagens principais: usar o GKE Ingress ou o GKE Gateway. Entender as diferenças entre eles é fundamental para escolher a solução certa para o seu ambiente.

Limitações do GKE Ingress

  • Restrições de namespace: o GKE Ingress só consegue referenciar Services dentro do mesmo namespace em que o recurso Ingress está implantado:

Um GKE Ingress no namespace Fu não consegue referenciar um Service no namespace Bar

  • Recursos de load balancer: pode ser necessário usar vários load balancers se as aplicações estiverem em namespaces diferentes:

É preciso usar 2 load balancers HTTPS diferentes quando os Services estão em namespaces distintos — e ainda recorrer ao roteamento por domínio, o que adiciona mais uma camada de complexidade

Vantagens do GKE Gateway

  • Suporte entre namespaces: roteia tráfego para Services em diferentes namespaces a partir de um único recurso Gateway
  • Arquitetura simplificada: um único load balancer atende várias aplicações, independentemente do namespace
  • Roteamento mais flexível: facilita a implementação de padrões de roteamento complexos entre namespaces

Um GKE Gateway em um namespace consegue enviar tráfego para Services em outros namespaces usando um único load balancer HTTPS

Guia de implementação

Pré-requisitos

  • GKE Standard v1.24+ ou GKE Autopilot v1.26+
  • Cluster configurado como VPC-native
  • Add-on HttpLoadBalancing habilitado

Passo 1: criar o cluster GKE

gcloud container clusters create test-gateway \
 --region=us-central1 \
 --release-channel=regular \
 --enable-ip-alias \
 --num-nodes=1 \
 --addons HttpLoadBalancing \
 --gateway-api=standard

gcloud container clusters get-credentials test-gateway --region us-central1

Passo 2: configurar o certificado SSL

cat <<EOF | kubectl apply -f -
apiVersion: networking.gke.io/v1
kind: ManagedCertificate
metadata:
 name: gateway-nir-dns-tests-google-com
 namespace: default
spec:
 domains:
 - gateway.nir-dns-tests-google-com
EOF

Passo 3: configurar o IP externo e apontar um registro DNS A para esse IP

Para que o ManagedCertificate seja provisionado, você precisa ter um registro DNS A apontando para o load balancer HTTPS e o certificado anexado a esse load balancer (o que será feito no próximo passo)

gcloud compute addresses create gateway --project=nir-playground --global
RESERVED_IP=$(gcloud compute addresses describe gateway --global | grep address: | awk '{print $2}')

gcloud dns --project=nir-playground record-sets create gateway.nir-dns-tests-google-com. \
  --zone="nir-dns-tests-google-com" --type="A" --ttl="60" --rrdatas=$RESERVED_IP

Passo 4: implantar o recurso Gateway

Repare que o gatewayClassName representa um load balancer HTTPS Global External e que o array de listeners libera HTTPRoutes vindos de qualquer namespace. Note também que estamos definindo o IP reservado com addresses[0].type como NamedAddresses e o valor sendo o nome usado ao reservar o IP estático ("gateway" neste exemplo):

CERT_NAME=$(kubectl get managedcertificate gateway-nir-dns-tests-google-com -o=jsonpath="{.status.certificateName}")

cat <<EOF | kubectl apply -f -
kind: Gateway
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
 name: external-http
spec:
 gatewayClassName: gke-l7-global-external-managed
 listeners:
 - name: https
   protocol: HTTPS
   port: 443
   allowedRoutes:
     namespaces:
       from: All
   tls:
     mode: Terminate
     options:
       networking.gke.io/pre-shared-certs: $CERT_NAME
 addresses:
 - type: NamedAddress
   value: gateway
EOF

# Verifica a atribuição do IP do Gateway
while true; do
 GATEWAY_IP=$(kubectl get gateway external-http -o=jsonpath="{.status.addresses[0].value}")
 if [ "$GATEWAY_IP" != "" ]; then
   break
 fi
 sleep 3
done

Passo 5: verificar o status do ManagedCertificate

# Verifica o status do certificado
while true; do
 STATUS=$(kubectl get managedcertificate gateway-nir-dns-tests-google-com -o=jsonpath="{.status.certificateStatus}")
 if [ "$STATUS" = "Active" ]; then
   break
 fi
 echo "Certificate is in $STATUS status, will check again if it became active in 3 seconds"
 sleep 3
done

Passo 6: implantar aplicações de exemplo

kubectl create namespace first-namespace
kubectl create namespace second-namespace

# Implanta o App A no first-namespace
cat <<EOF | kubectl apply -n first-namespace -f -
apiVersion: apps/v1
kind: Deployment
metadata:
 name: app-a
spec:
 replicas: 2
 selector:
   matchLabels:
     app: app-a
 template:
   metadata:
     labels:
       app: app-a
   spec:
     containers:
     - name: app-a
       image: hashicorp/http-echo
       args: ["-text=Hello from App A"]
       ports:
       - containerPort: 5678
EOF

# Cria o Service do App A
cat <<EOF | kubectl apply -n first-namespace -f -
apiVersion: v1
kind: Service
metadata:
 name: service-a
spec:
 selector:
   app: app-a
 ports:
 - protocol: TCP
   port: 80
   targetPort: 5678
EOF

# Implanta o App B no second-namespace
cat <<EOF | kubectl apply -n second-namespace -f -
apiVersion: apps/v1
kind: Deployment
metadata:
 name: app-b
spec:
 replicas: 2
 selector:
   matchLabels:
     app: app-b
 template:
   metadata:
     labels:
       app: app-b
   spec:
     containers:
     - name: app-b
       image: hashicorp/http-echo
       args: ["-text=Hello from App B"]
       ports:
       - containerPort: 5678
EOF

# Cria o Service do App B
cat <<EOF | kubectl apply -n second-namespace -f -
apiVersion: v1
kind: Service
metadata:
 name: service-b
spec:
 selector:
   app: app-b
 ports:
 - protocol: TCP
   port: 80
   targetPort: 5678
EOF

Passo 7: habilitar o IAP e criar um Secret no k8s para as credenciais do IAP

echo -n CLIENT_SECRET_REDACTED > iap-secret.txt
kubectl create secret generic iap --from-file=key=iap-secret.txt

Passo 8: criar uma GCPBackendPolicy que aplique o IAP

# Habilita o IAP para o App A
cat <<EOF | kubectl apply -n first-namespace -f -
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
 name: backend-policy
spec:
 default:
   iap:
     enabled: true
     oauth2ClientSecret:
       name: iap
     clientID: REPLACE_WITH_YOUR_IAP_OAUTH_CLIENT_ID
 targetRef:
   group: ""
   kind: Service
   name: service-a
EOF

# Habilita o IAP para o App B
cat <<EOF | kubectl apply -n second-namespace -f -
apiVersion: networking.gke.io/v1
kind: GCPBackendPolicy
metadata:
 name: backend-policy
spec:
 default:
   iap:
     enabled: true
     oauth2ClientSecret:
       name: iap
     clientID: REPLACE_WITH_YOUR_IAP_OAUTH_CLIENT_ID
 targetRef:
   group: ""
   kind: Service
   name: service-b
EOF

Passo 9: criar a HTTPRoute

# Cria a rota para o App A
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
 name: route-a
 namespace: first-namespace
spec:
 parentRefs:
 - name: external-http
   kind: Gateway
   namespace: default
 rules:
 - matches:
   - path:
       value: /first
   backendRefs:
   - name: service-a
     port: 80
EOF

# Cria a rota para o App B
cat <<EOF | kubectl apply -f -
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
 name: route-b
 namespace: second-namespace
spec:
 parentRefs:
 - name: external-http
   kind: Gateway
   namespace: default
 rules:
 - matches:
   - path:
       value: /second
   backendRefs:
   - name: service-b
     port: 80
EOF

Passo 10: acessar as aplicações protegidas pelo IAP

Acesse a URL protegida pelo IAP. A página de login do Google será exibida. Qualquer usuário que pertença à mesma organização do Google Cloud em que a aplicação está implantada e que tenha a permissão IAM IAP-Secured Web App User conseguirá acessar a aplicação:

[email protected] é um usuário da organização GCP doit.com e tem as permissões IAM necessárias para acessar a aplicação. Já [email protected] não pertence a essa organização e, portanto, não conseguirá acessar a aplicação

Quando um usuário fora da organização ou alguém sem as permissões necessárias tenta fazer login e acessar a aplicação, ele se depara com uma página de permissão negada:

Página de permissão negada exibida para principals não autorizados

Modernizar os padrões de acesso ao GKE, saindo da VPN para um External Gateway com IAP, é só uma das muitas formas de elevar a segurança e a eficiência operacional da sua infraestrutura no Google Cloud. Essa abordagem fortalece a postura de segurança e, ao mesmo tempo, reduz o esforço operacional e os custos.

Embora este guia foque na modernização do acesso ao GKE, oportunidades parecidas de transformação existem em toda a sua infraestrutura na nuvem. Da otimização de custos à automação de infraestrutura, do reforço da segurança ao design de arquitetura na nuvem, a DoiT International reúne expertise abrangente em diversos domínios de cloud. Para descobrir como a DoiT pode ajudar a modernizar outros aspectos da sua infraestrutura na nuvem ou conhecer nossas demais soluções de engenharia em cloud, acesse doit.com/expertise/.