Neste tutorial, mostramos como usar os gateways de saída do Anthos Service Mesh e outros controles do Google Cloud para proteger o tráfego de saída das cargas de trabalho implantadas em um cluster do Google Kubernetes Engine. O tutorial serve como complemento ao guia de práticas recomendadas.
O público-alvo deste tutorial inclui engenheiros de rede, plataforma e segurança que administram os clusters do Google Kubernetes Engine usados por uma ou mais equipes de entrega de software. Os controles descritos aqui são especialmente úteis para organizações que precisam demonstrar conformidade com regulamentações, por exemplo, GDPR e PCI.
Objetivos
- Configure a infraestrutura para executar o Anthos Service Mesh:
- Rede VPC personalizada e sub-rede privada.
- Cloud NAT para acesso à Internet
- Cluster do GKE privado com um pool de nós extra para pods de gateway de saída
- Regras de firewall VPC de saída restritiva. Somente nós de gateway podem alcançar hosts externos
- Acesso privado do Google para conexão com Container Registry e APIs do Google
- Instalar o Anthos Service Mesh com gateways de saída em execução em um pool de nós dedicado.
- Configure regras de roteamento de vários locatários para o tráfego externo por meio do
gateway de saída:
- Os aplicativos no namespace "team-x" podem se conectar a example.com
- Os aplicativos no namespace "team-y" podem se conectar a httpbin.org
- Use o recurso
Sidecar
para restringir o escopo da configuração de saída do proxy sidecar para cada namespace. - Configure políticas de autorização para aplicar regras de saída.
- Configure o gateway de saída para fazer upgrade de solicitações HTTP simples para a TLS (origem de TLS).
- Configure o gateway de saída para transmitir o tráfego TLS de passagem.
- Configure as políticas de rede do Kubernetes como um controle de saída adicional.
- Configure o acesso direto às APIs do Google usando permissões de Acesso privado do Google e de Gerenciamento de identidade e acesso (IAM).
Custos
Neste documento, você usará os seguintes componentes faturáveis do Google Cloud:
- Compute Engine
- Google Kubernetes Engine (GKE)
- Container Registry
- Anthos Service Mesh
- Cloud Load Balancing
- Cloud NAT
- Rede
- Cloud Storage
Para gerar uma estimativa de custo baseada na projeção de uso deste tutorial, use a calculadora de preços.
Ao concluir este tutorial, exclua os recursos criados para evitar custos contínuos. Para mais informações, consulte Como fazer a limpeza.
Antes de começar
-
In the Google Cloud console, on the project selector page, select or create a Google Cloud project.
-
Verifique se a cobrança está ativada para o seu projeto do Google Cloud.
-
In the Google Cloud console, activate Cloud Shell.
Crie um diretório de trabalho para usar e siga este tutorial:
mkdir -p ~/WORKING_DIRECTORY cd ~/WORKING_DIRECTORY
Crie um script de shell para inicializar seu ambiente para o tutorial. Substitua e edite as variáveis de acordo com o projeto e as preferências. Execute este script com o comando
source
para reinicializar o ambiente se a sessão de shell expirar.cat << 'EOF' > ./init-egress-tutorial.sh #! /usr/bin/env bash PROJECT_ID=YOUR_PROJECT_ID REGION=REGION ZONE=ZONE gcloud config set project ${PROJECT_ID} gcloud config set compute/region ${REGION} gcloud config set compute/zone ${ZONE} EOF
Torne o script executável e o execute com o comando
source
para inicializar seu ambiente:chmod +x ./init-egress-tutorial.sh source ./init-egress-tutorial.sh
Defina os papéis necessários de gerenciamento de identidade e acesso (IAM, na sigla em inglês). Se você for um proprietário do projeto, terá todas as permissões necessárias para concluir a instalação. Se você não for um proprietário do projeto, peça ao administrador que conceda a você os papéis do IAM a seguir. No comando a seguir, altere PROJECT_EMAIL_ADDRESS para a conta que você usa para fazer login no Google Cloud.
gcloud projects add-iam-policy-binding ${PROJECT_ID} \ --member user:PROJECT_EMAIL_ADDRESS \ --role=roles/editor \ --role=roles/compute.admin \ --role=roles/container.admin \ --role=roles/resourcemanager.projectIamAdmin \ --role=roles/iam.serviceAccountAdmin \ --role=roles/iam.serviceAccountKeyAdmin \ --role=roles/gkehub.admin \ --role=roles/serviceusage.serviceUsageAdmin
Ative as APIs necessárias para o tutorial:
gcloud services enable \ dns.googleapis.com \ container.googleapis.com \ compute.googleapis.com \ monitoring.googleapis.com \ logging.googleapis.com \ cloudtrace.googleapis.com \ meshca.googleapis.com \ meshtelemetry.googleapis.com \ meshconfig.googleapis.com \ iamcredentials.googleapis.com \ gkeconnect.googleapis.com \ gkehub.googleapis.com \ cloudresourcemanager.googleapis.com \ stackdriver.googleapis.com
A ativação das APIs pode levar um minuto ou mais para ser concluída. Quando as APIs estão ativadas, você vê uma saída semelhante a esta:
Operation "operations/acf.601db672-88e6-4f98-8ceb-aa3b5725533c" finished successfully.
Como configurar a infraestrutura
Crie uma rede e uma sub-rede VPC
Crie uma nova rede VPC:
gcloud compute networks create vpc-network \ --subnet-mode custom
Crie uma sub-rede para o cluster executar em intervalos com endereços IP secundários pré-atribuídos para pods e serviços. O Acesso privado do Google é ativado para que os aplicativos apenas com endereços IP internos possam acessar as APIs e os serviços do Google:
gcloud compute networks subnets create subnet-gke \ --network vpc-network \ --range 10.0.0.0/24 \ --secondary-range pods=10.1.0.0/16,services=10.2.0.0/20 \ --enable-private-ip-google-access
Configurar o Cloud NAT
O Cloud NAT permite que cargas de trabalho sem endereços IP externos se conectem a destinos na Internet e recebam respostas de entrada desses destinos.
Criar um Cloud Router
gcloud compute routers create nat-router \ --network vpc-network
Adicionar uma configuração NAT ao roteador
gcloud compute routers nats create nat-config \ --router nat-router \ --nat-all-subnet-ip-ranges \ --auto-allocate-nat-external-ips
Criar contas de serviço para cada pool de nós do GKE
Crie duas contas de serviço para uso pelos dois pools de nós do GKE. Uma conta de serviço separada é atribuída a cada pool de nós para que você possa aplicar regras de firewall VPC a nós específicos.
Crie uma conta de serviço para ser usada pelos nós no pool de nós padrão:
gcloud iam service-accounts create sa-application-nodes \ --description="SA for application nodes" \ --display-name="sa-application-nodes"
Crie uma conta de serviço para ser usada pelos nós no pool de nós de gateway:
gcloud iam service-accounts create sa-gateway-nodes \ --description="SA for gateway nodes" \ --display-name="sa-gateway-nodes"
Conceder permissões às contas de serviço
Adicione um conjunto mínimo de papéis do IAM às contas de serviço do aplicativo e do gateway. Esses papéis são necessários para registrar, monitorar e extrair imagens de contêiner particular do Container Registry.
project_roles=(
roles/logging.logWriter
roles/monitoring.metricWriter
roles/monitoring.viewer
roles/storage.objectViewer
)
for role in "${project_roles[@]}"
do
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:sa-application-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="$role"
gcloud projects add-iam-policy-binding ${PROJECT_ID} \
--member="serviceAccount:sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \
--role="$role"
done
Como criar as regras de firewall
Nas etapas a seguir, você aplica uma regra de firewall à rede VPC para que, por padrão, todo o tráfego de saída seja negado. É necessária uma conectividade específica para que o cluster funcione e os nós de gateway possam alcançar destinos fora da VPC. Um conjunto mínimo de regras de firewall específicas substitui a regra padrão de negação de tudo para permitir a conectividade necessária.
Crie uma regra de firewall padrão (de baixa prioridade) para negar todas as saídas da rede VPC:
gcloud compute firewall-rules create global-deny-egress-all \ --action DENY \ --direction EGRESS \ --rules all \ --destination-ranges 0.0.0.0/0 \ --network vpc-network \ --priority 65535 \ --description "Default rule to deny all egress from the network."
Crie uma regra para permitir que apenas os nós com a conta de serviço de gateway cheguem à Internet:
gcloud compute firewall-rules create gateway-allow-egress-web \ --action ALLOW \ --direction EGRESS \ --rules tcp:80,tcp:443 \ --target-service-accounts sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com \ --network vpc-network \ --priority 1000 \ --description "Allow the nodes running the egress gateways to connect to the web"
Permita que os nós cheguem ao plano de controle do Kubernetes:
gcloud compute firewall-rules create allow-egress-to-api-server \ --action ALLOW \ --direction EGRESS \ --rules tcp:443,tcp:10250 \ --destination-ranges 10.5.0.0/28 \ --network vpc-network \ --priority 1000 \ --description "Allow nodes to reach the Kubernetes API server."
O Anthos Service Mesh usa webhooks ao injetar proxies sidecar em cargas de trabalho. Permita que o servidor da API GKE chame os webhooks expostos pelo plano de controle da malha de serviço em execução nos nós:
gcloud compute firewall-rules create allow-ingress-api-server-to-webhook \ --action ALLOW \ --direction INGRESS \ --rules tcp:15017 \ --source-ranges 10.5.0.0/28 \ --network vpc-network \ --priority 1000 \ --description "Allow the API server to call the webhooks exposed by istiod discovery"
Permita a conectividade de saída entre pods e serviços em execução no cluster. O GKE cria automaticamente uma regra de entrada correspondente.
gcloud compute firewall-rules create allow-egress-pods-and-services \ --action ALLOW \ --direction EGRESS \ --rules all \ --destination-ranges 10.1.0.0/16,10.2.0.0/20 \ --network vpc-network \ --priority 1000 \ --description "Allow pods and services on nodes to reach each other"
Um serviço chamado Calico fornece a funcionalidade de API
NetworkPolicy
para o GKE. Permita a conectividade para Calico na sub-rede:gcloud compute firewall-rules create allow-egress-calico \ --action ALLOW \ --direction EGRESS \ --rules tcp:5473 \ --destination-ranges 10.0.0.0/24 \ --network vpc-network \ --priority 1000 \ --description "Allow Calico Typha within the subnet"
A porta somente leitura do kubelet é necessária para que o GKE leia as métricas do nó. Permitir o acesso dentro da sub-rede:
gcloud compute firewall-rules create allow-egress-kubelet-readonly \ --action ALLOW \ --direction EGRESS \ --rules tcp:10255 \ --destination-ranges 10.0.0.0/24 \ --network vpc-network \ --priority 1000 \ --description "Allow access to the kubelet read-only port within the subnet"
Permita o acesso aos conjuntos de endereços IP usados pelo Acesso privado do Google para disponibilizar APIs do Google, o Container Registry e outros serviços:
gcloud compute firewall-rules create allow-egress-gcp-apis \ --action ALLOW \ --direction EGRESS \ --rules tcp \ --destination-ranges 199.36.153.8/30 \ --network vpc-network \ --priority 1000 \ --description "Allow access to the VIPs used by Google Cloud APIs (Private Google Access)"
Permita que o serviço do verificador de integridade do Google Cloud acesse os pods em execução no cluster:
gcloud compute firewall-rules create allow-ingress-gcp-health-checker \ --action ALLOW \ --direction INGRESS \ --rules tcp:80,tcp:443 \ --source-ranges 130.211.0.0/22,35.191.0.0/16,35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \ --network vpc-network \ --priority 1000 \ --description "Allow workloads to respond to Google Cloud health checks"
Como configurar o acesso particular às APIs do Google Cloud
O Acesso privado do Google permite que VMs e pods que tenham apenas endereços IP internos acessem APIs e serviços do Google. As APIs e os serviços do Google são exibidos do IPs externos, mas o tráfego dos nós nunca sai da rede do Google quando o Acesso privado do Google é usado.
OCrie uma zona de DNS privada, além de um registro "CNAME" e "A", para que os nós e as cargas de trabalho possam se conectar a serviços e APIs do Google usando o Acesso privado do Google e o nome do host "private.googleapis.com":
gcloud dns managed-zones create private-google-apis \
--description "Private DNS zone for Google APIs" \
--dns-name googleapis.com \
--visibility private \
--networks vpc-network
gcloud dns record-sets transaction start --zone private-google-apis
gcloud dns record-sets transaction add private.googleapis.com. \
--name *.googleapis.com \
--ttl 300 \
--type CNAME \
--zone private-google-apis
gcloud dns record-sets transaction add "199.36.153.8" \
"199.36.153.9" "199.36.153.10" "199.36.153.11" \
--name private.googleapis.com \
--ttl 300 \
--type A \
--zone private-google-apis
gcloud dns record-sets transaction execute --zone private-google-apis
Como configurar o acesso particular ao Container Registry
Crie uma zona de DNS particular, além de um registro "CNAME" e um registro "A", para que os nós possam se conectar ao Container Registry usando o Acesso privado do Google e o nome do host "gcr.io":
gcloud dns managed-zones create private-gcr-io \
--description "private zone for Container Registry" \
--dns-name gcr.io \
--visibility private \
--networks vpc-network
gcloud dns record-sets transaction start --zone private-gcr-io
gcloud dns record-sets transaction add gcr.io. \
--name *.gcr.io \
--ttl 300 \
--type CNAME \
--zone private-gcr-io
gcloud dns record-sets transaction add "199.36.153.8" "199.36.153.9" "199.36.153.10" "199.36.153.11" \
--name gcr.io \
--ttl 300 \
--type A \
--zone private-gcr-io
gcloud dns record-sets transaction execute --zone private-gcr-io
Criar um cluster do GKE particular
Encontre o endereço IP externo do seu Cloud Shell para que você possa adicioná-lo à lista de redes que podem acessar o servidor da API do cluster:
SHELL_IP=$(dig TXT -4 +short @ns1.google.com o-o.myaddr.l.google.com)
Após um período de inatividade, o endereço IP externo da VM do Cloud Shell pode mudar. Se isso acontecer, você precisará atualizar a lista de redes autorizadas do cluster. Adicione o seguinte comando ao seu script de inicialização:
cat << 'EOF' >> ./init-egress-tutorial.sh SHELL_IP=$(dig TXT -4 +short @ns1.google.com o-o.myaddr.l.google.com) gcloud container clusters update cluster1 \ --enable-master-authorized-networks \ --master-authorized-networks ${SHELL_IP//\"}/32 EOF
Criar um cluster do GKE particular
gcloud container clusters create cluster1 \ --enable-ip-alias \ --enable-private-nodes \ --release-channel "regular" \ --no-enable-basic-auth \ --no-issue-client-certificate \ --enable-master-authorized-networks \ --master-authorized-networks ${SHELL_IP//\"}/32 \ --master-ipv4-cidr 10.5.0.0/28 \ --enable-network-policy \ --service-account "sa-application-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \ --machine-type "e2-standard-4" \ --num-nodes "4" \ --network "vpc-network" \ --subnetwork "subnet-gke" \ --cluster-secondary-range-name "pods" \ --services-secondary-range-name "services" \ --workload-pool "${PROJECT_ID}.svc.id.goog" \ --zone ${ZONE}
O cluster leva alguns minutos para ser criado. O cluster tem nós particulares com endereços IP internos. Os pods e serviços recebem os IPs dos intervalos secundários nomeados que você definiu ao criar a sub-rede VPC.
O Anthos Service Mesh requer que os nós do cluster usem um tipo de máquina que tenha pelo menos quatro vCPUs. O Google recomenda que o cluster seja inscrito no canal de lançamento "regular" para ajudar a garantir que os nós estejam executando uma versão do Kubernetes compatível com o Anthos Service Mesh. Para mais informações, consulte os guias de instalação do Anthos Service Mesh.
A Identidade da carga de trabalho está ativada no cluster. O Anthos Service Mesh requer a identidade da carga de trabalho e é o modo recomendado para acessar as APIs do Google a partir das cargas de trabalho do GKE.
Crie um pool de nós chamado gateway. Esse pool de nós é onde o gateway de saída é implantado. O taint
dedicated=gateway:NoSchedule
é adicionado a cada nó no pool de nós de gateway.gcloud container node-pools create "gateway" \ --cluster "cluster1" \ --machine-type "e2-standard-4" \ --node-taints dedicated=gateway:NoSchedule \ --service-account "sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \ --num-nodes "1"
Os taints e as tolerâncias do Kubernetes ajudam a garantir que somente os pods do gateway de saída sejam executados nos nós do pool.
Faça o download de credenciais para se conectar ao cluster com a kubectl:
gcloud container clusters get-credentials cluster1
Verifique se os nós de gateway têm o taint correto:
kubectl get nodes -l cloud.google.com/gke-nodepool=gateway -o yaml \ -o=custom-columns='name:metadata.name,taints:spec.taints[?(@.key=="dedicated")]'
O resultado será assim:
name taints gke-cluster1-gateway-9d65b410-cffs map[effect:NoSchedule key:dedicated value:gateway]
Como instalar e configurar o Anthos Service Mesh
Neste tutorial, são usados os recursos opcionais do Anthos Service Mesh. Para saber como instalar o Anthos Service Mesh com um script, leia o guia de instalação na documentação.
Crie namespaces para o plano de controle da malha de serviço e os gateways de saída a serem implantados em:
kubectl create ns istio-system kubectl create ns istio-egress
Rotule os namespaces istio-egress, istio-system e kube-system:
kubectl label ns istio-egress istio=egress istio-injection=disabled kubectl label ns istio-system istio=system kubectl label ns kube-system kube-system=true
Esses rótulos são usados posteriormente para aplicar a Kubernetes NetworkPolicy. O rótulo
istio-injection=disabled
evita avisos errados ao executar a análise deistioctl
.Crie um arquivo de manifesto para personalizar a instalação do Anthos Service Mesh usando a API Istio Operator:
cat << 'EOF' > ./asm-custom-install.yaml apiVersion: install.istio.io/v1alpha1 kind: IstioOperator metadata: name: "egress-gateway" spec: meshConfig: accessLogFile: "/dev/stdout" components: egressGateways: - name: "istio-egressgateway" enabled: true namespace: "istio-egress" label: istio: "egress" k8s: tolerations: - key: "dedicated" operator: "Equal" value: "gateway" nodeSelector: cloud.google.com/gke-nodepool: "gateway" EOF
Esse arquivo é fornecido como um argumento para o script de instalação e especifica a seguinte configuração:
- Uma implantação de gateway de saída em execução no namespace
istio-egress
com uma tolerância e nodeSelector para que seja executada apenas em nósgateway
. - Registro de acesso a "stdout" para todos os proxies secundários.
- Uma implantação de gateway de saída em execução no namespace
Faça o download do script de instalação:
curl -O https://storage.googleapis.com/csm-artifacts/asm/install_asm
Torne o script executável:
chmod +x install_asm
Instale o Anthos Service Mesh executando o script a seguir:
./install_asm \ --mode install \ --project_id ${PROJECT_ID} \ --cluster_name cluster1 \ --cluster_location ${ZONE} \ --custom_overlay ./asm-custom-install.yaml \ --output_dir ./ \ --enable_all
Quando o script for concluído, defina uma variável de ambiente para manter o caminho para a ferramenta
istioctl
e adicione-o ao script de inicialização:ISTIOCTL=$(find "$(pwd -P)" -name istioctl) echo "ISTIOCTL=\"${ISTIOCTL}\"" >> ./init-egress-tutorial.sh
Como verificar a instalação do Anthos Service Mesh
Verifique se os componentes do plano de controle do Anthos Service Mesh estão em execução no namespace
istio-system
:kubectl get pod -n istio-system
Você verá
istio-ingressgateway
eistiod-asm
pods em execução.Verifique se os pods do gateway de saída estão em execução no namespace
istio-egress
e nos nós no pool de nósgateway
:kubectl get pods -n istio-egress -o wide
Os pods do gateway de saída têm um
nodeSelector
para selecionar nós no pool de nósgateway
e uma tolerância que permite que eles sejam executados nos nós de gateway com taint. Examine o nodeSelector e as tolerâncias para os pods do gateway de saída:kubectl -n istio-egress get pod -l app=istio-egressgateway \ -o=custom-columns='name:metadata.name,nodeSelector:spec.nodeSelector,\ tolerations:spec.tolerations[?(@.key=="dedicated")]'
O resultado será assim:
name nodeSelector tolerations istio-egressgateway-74687946f5-dg9mp map[cloud.google.com/gke-nodepool:gateway] map[key:dedicated operator:Equal value:gateway]
Como preparar a malha e um aplicativo de teste
Verifique se a TLS mútuo do STRICT está ativada. Aplique uma política de
PeerAuthentication
padrão para a malha no namespaceistio-system
:cat <<EOF | kubectl apply -f - apiVersion: "security.istio.io/v1beta1" kind: "PeerAuthentication" metadata: name: "default" namespace: "istio-system" spec: mtls: mode: STRICT EOF
É possível modificar essa configuração criando recursos
PeerAuthentication
em namespaces específicos.Crie namespaces a serem usados para implantar cargas de trabalho de teste. As etapas posteriores neste tutorial explicam como configurar diferentes regras de roteamento de saída para cada namespace.
kubectl create namespace team-x kubectl create namespace team-y
Rotule os namespaces para que eles possam ser selecionados pelas políticas de rede do Kubernetes:
kubectl label namespace team-x team=x kubectl label namespace team-y team=y
Para que o Anthos Service Mesh injete automaticamente proxies sidecar, você precisa definir um rótulo de revisão nos namespaces da carga de trabalho. O rótulo de revisão precisa corresponder à revisão do plano de controle do Anthos Service Mesh implantado no cluster. Procure o rótulo de revisão no pod
istiod
e armazene-o em uma variável de ambiente:REVISION_LABEL=$(kubectl get pod -n istio-system -l app=istiod \ -o jsonpath='{.items[0].metadata.labels.istio\.io/rev}')
Defina o rótulo de revisão nos namespaces
team-x
eteam-y
:kubectl label ns team-x istio.io/rev=${REVISION_LABEL} kubectl label ns team-y istio.io/rev=${REVISION_LABEL}
Crie um arquivo YAML a ser usado para fazer implantações de teste:
cat << 'EOF' > ./test.yaml apiVersion: v1 kind: ServiceAccount metadata: name: test --- apiVersion: v1 kind: Service metadata: name: test labels: app: test spec: ports: - port: 80 name: http selector: app: test --- apiVersion: apps/v1 kind: Deployment metadata: name: test spec: replicas: 1 selector: matchLabels: app: test template: metadata: labels: app: test spec: serviceAccountName: test containers: - name: test image: gcr.io/google.com/cloudsdktool/cloud-sdk:slim command: ["/bin/sleep", "infinity"] imagePullPolicy: IfNotPresent EOF
Implante o aplicativo de teste no namespace
team-x
:kubectl -n team-x create -f ./test.yaml
Verifique se o aplicativo de teste está implantado em um nó no pool padrão e se um contêiner de arquivo secundário de proxy está injetado. Repita o comando a seguir até o status do pod ser
Running
:kubectl -n team-x get po -l app=test -o wide
O resultado será assim:
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES test-d5bdf6f4f-9nxfv 2/2 Running 0 19h 10.1.1.25 gke-cluster1-default-pool-f6c7a51f-wbzj
Dois de dois contêineres são
Running
. Um contêiner é o aplicativo de teste, e o outro é o arquivo secundário do proxy.O pod está sendo executado em um nó no pool de nós padrão.
Verifique se não é possível fazer uma solicitação HTTP do contêiner de teste para um site externo:
kubectl -n team-x exec -it \ $(kubectl -n team-x get pod -l app=test -o jsonpath={.items..metadata.name}) \ -c test -- curl -v http://example.com
Uma mensagem de erro do proxy sidecar é gerada porque a regra de firewall "global-deny-egress-all" nega a conexão upstream.
Como usar o recurso do arquivo secundário para restringir o escopo da configuração de proxy sidcar
Use o
recurso do arquivo secundário
para restringir o escopo do listener de saída configurado
para proxies sidecar. Para reduzir a ocupação excessiva da configuração e do uso da memória, é recomendável aplicar um
recurso Sidecar
padrão para cada namespace.
O proxy executado pelo Anthos Service Mesh no arquivo secundário é o Envoy. Na
terminologia Envoy,
um cluster
é um grupo logicamente similar de endpoints upstream usados como
destinos para balanceamento de carga.
Inspecione os clusters de saída configurados no proxy sidecar do Envoy para o pod de teste executando o comando
istioctl proxy-config
:${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}).team-x --direction outbound
Há aproximadamente 20 clusters Envoy na lista, incluindo vários para o gateway de saída.
Restrinja a configuração do proxy às rotas de saída que foram definidas explicitamente com as entradas de serviço nos namespaces
istio-egress
eteam-x
. Aplique um recursoSidecar
ao namespaceteam-x
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Sidecar metadata: name: default namespace: team-x spec: outboundTrafficPolicy: mode: REGISTRY_ONLY egress: - hosts: - 'istio-egress/*' - 'team-x/*' EOF
Definir o modo de política de tráfego de saída como
REGISTRY_ONLY
restringe a configuração de proxy para incluir somente os hosts externos que foram explicitamente adicionados ao registro de serviço da malha definindo entradas de serviço.A parte "
istio-egress/*
" especifica que o proxy sidecar seleciona rotas do namespaceistio-egress
que estão disponíveis usando o atributoexportTo
. A parte "team-x/*
" inclui todas as rotas que foram configuradas localmente no namespaceteam-x
.Visualize os clusters de saída configurados no proxy sidecar do Envoy e compare-os com a lista de clusters que foram configurados antes da aplicação do recurso
Sidecar
:${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}).team-x --direction outbound
A saída inclui apenas alguns clusters para o gateway de saída e um para o próprio pod de teste.
Como configurar o Anthos Service Mesh para rotear o tráfego por meio do gateway de saída
Configure um
Gateway
para tráfego HTTP na porta 80. OGateway
seleciona o proxyistio-egressgateway
que o instalador implantou no namespaceistio-egress
. A configuraçãoGateway
é aplicada ao namespaceistio-egress
e processa o tráfego para qualquer host.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: egress-gateway namespace: istio-egress spec: selector: istio: egress servers: - port: number: 80 name: https protocol: HTTPS hosts: - '*' tls: mode: ISTIO_MUTUAL EOF
Criar um
DestinationRule
para o gateway de saída com TLS mútua para autenticação e criptografia. Usar uma única regra de destino compartilhada para todos os hosts externos.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: target-egress-gateway namespace: istio-egress spec: host: istio-egressgateway.istio-egress.svc.cluster.local subsets: - name: target-egress-gateway-mTLS trafficPolicy: loadBalancer: simple: ROUND_ROBIN tls: mode: ISTIO_MUTUAL EOF
Crie um
ServiceEntry
no namespaceistio-egress
para registrar explicitamente example.com no registro de serviço da malha para o namespaceteam-x
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: example-com-ext namespace: istio-egress spec: hosts: - example.com ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'team-x' - 'istio-egress' EOF
Crie um
VirtualService
para rotear o tráfego para example.com por meio do gateway de saída. Há duas condições de correspondência: a primeira condição direciona o tráfego para o gateway de saída, e a segunda direciona o tráfego do gateway de saída para o host de destino. A propriedadeexportTo
controla quais namespaces podem usar o serviço virtual.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: example-com-through-egress-gateway namespace: istio-egress spec: hosts: - example.com gateways: - istio-egress/egress-gateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 weight: 100 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: example.com port: number: 80 weight: 100 exportTo: - 'istio-egress' - 'team-x' EOF
Execute
istioctl analyze
para verificar se há erros de configuração:${ISTIOCTL} analyze -n istio-egress
O resultado será assim:
✔ No validation issues found when analyzing namespace: istio-egress.
Envie várias solicitações pelo gateway de saída ao site externo:
for i in {1..4} do kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- \ curl -s -o /dev/null -w "%{http_code}\n" http://example.com done
Você verá
200
códigos de status para as quatro respostas.Verifique se as solicitações foram direcionadas por meio do gateway de saída. Para isso, confira os registros de acesso do proxy. Primeiro, verifique o registro de acesso para o proxy sidecar implantado com o aplicativo de teste:
kubectl -n team-x logs -f $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) istio-proxy
Para cada solicitação enviada, você vê uma entrada de registro semelhante a esta:
[2020-09-14T17:37:08.045Z] "HEAD / HTTP/1.1" 200 - "-" "-" 0 0 5 4 "-" "curl/7.67.0" "d57ea5ad-90e9-46d9-8b55-8e6e404a8f9b" "example.com" "10.1.4.12:8080" outbound|80||istio-egressgateway.istio-egress.svc.cluster.local 10.1.0.17:42140 93.184.216.34:80 10.1.0.17:60326 - -
Verifique também o registro de acesso do gateway de saída:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egress \ -o jsonpath="{.items[0].metadata.name}") istio-proxy
Para cada solicitação enviada, você vê uma entrada de registro de acesso ao gateway de saída semelhante a esta:
[2020-09-14T17:37:08.045Z] "HEAD / HTTP/2" 200 - "-" "-" 0 0 4 3 "10.1.0.17" "curl/7.67.0" "095711e6-64ef-4de0-983e-59158e3c55e7" "example.com" "93.184.216.34:80" outbound|80||example.com 10.1.4.12:37636 10.1.4.12:8080 10.1.0.17:44404 outbound_.80_.target-egress-gateway-mTLS_.istio-egressgateway.istio-egress.svc.cluster.local -
Configurar um roteamento diferente para um segundo namespace
Configure o roteamento para um segundo host externo e saiba como diferentes conectividades diferentes podem ser configuradas para equipes diferentes.
Crie um recurso
Sidecar
para o namespaceteam-y
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Sidecar metadata: name: default namespace: team-y spec: outboundTrafficPolicy: mode: REGISTRY_ONLY egress: - hosts: - 'istio-egress/*' - 'team-y/*' EOF
Implante o aplicativo de teste no namespace
team-y
:kubectl -n team-y create -f ./test.yaml
Registre um segundo host externo e exporte para o
team-x
e o namespaceteam-y
:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: httpbin-org-ext namespace: istio-egress spec: hosts: - httpbin.org ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'istio-egress' - 'team-x' - 'team-y' EOF
Crie um serviço virtual para rotear o tráfego para httpbin.org por meio do gateway de saída:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin-org-through-egress-gateway namespace: istio-egress spec: hosts: - httpbin.org gateways: - istio-egress/egress-gateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 weight: 100 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: httpbin.org port: number: 80 weight: 100 exportTo: - 'istio-egress' - 'team-x' - 'team-y' EOF
Execute
istioctl analyze
para verificar se há erros de configuração:${ISTIOCTL} analyze -n istio-egress
Você verá:
✔ No validation issues found when analyzing namespace: istio-egress.
Faça uma solicitação para httpbin.org pelo app de teste
team-y
:kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test -o \ jsonpath={.items..metadata.name}) -c test -- curl -I http://httpbin.org
Você verá uma resposta
200 OK
.Faça também uma solicitação para httpbin.org do app de teste
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://httpbin.org
Você verá uma resposta
200 OK
.Tente fazer uma solicitação para example.com pelo namespace
team-y
:kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
A solicitação falha porque não há uma rota de saída configurada para o host
example.com
.
Como usar a política de autorização para fornecer mais controle sobre o tráfego
Neste tutorial, as políticas de autorização para o gateway de saída são criadas no
namespace istio-egress
. É possível configurar o RBAC do Kubernetes para que apenas
administradores de rede possam acessar o namespace istio-egress
.
Crie um
AuthorizationPolicy
para que os aplicativos no namespaceteam-x
possam se conectar a example.com, mas não a outros hosts externos ao enviar solicitações usando a porta 80. OtargetPort
correspondente nos pods do gateway de saída é 8080.cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: egress-team-x-to-example-com namespace: istio-egress spec: rules: - from: - source: namespaces: - 'team-x' to: - operation: hosts: - 'example.com' when: - key: destination.port values: ["8080"] EOF
Verifique se é possível fazer uma solicitação para example.com pelo aplicativo de teste no namespace
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
Você verá uma resposta
200 OK
.Tente fazer uma solicitação para httpbin.org pelo aplicativo de teste no namespace
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -s -w " %{http_code}\n" \ http://httpbin.org
A solicitação falha com uma mensagem
RBAC: access denied
e um código de status "403 Forbidden". Aguarde alguns segundos, porque às vezes ocorre um pequeno atraso antes que a política de autorização entre em vigor.As políticas de autorização fornecem controle avançado sobre qual tráfego é permitido ou negado. Aplique a seguinte política de autorização para permitir que o app de teste no namespace
team-y
faça solicitações a httpbin.org usando um caminho de URL específico ao enviar solicitações usando a porta 80. OtargetPort
correspondente nos pods do gateway de saída é 8080.cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: egress-team-y-to-httpbin-teapot namespace: istio-egress spec: rules: - from: - source: namespaces: - 'team-y' to: - operation: hosts: - httpbin.org paths: ['/status/418'] when: - key: destination.port values: ["8080"] EOF
Tente se conectar a httpbin.org pelo app de teste no namespace
team-y
:kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -s -w " %{http_code}\n" \ http://httpbin.org
A solicitação falha com uma mensagem de RBAC: acesso negado e um código de status "403 Forbidden".
Agora, faça uma solicitação para httpbin.org/status/418 no mesmo app:
kubectl -n team-y exec -it $(kubectl -n team-y get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl http://httpbin.org/status/418
A solicitação é bem-sucedida porque o caminho corresponde ao padrão na política de autorização. A resposta será semelhante a:
-=[ teapot ]=- _...._ .' _ _ `. | ."` ^ `". _, \_;`"---"`|// | ;/ \_ _/ `"""`
Origem da TLS no gateway de saída
É possível configurar gateways de saída para fazer upgrades de solicitações HTTP simples para a TLS (origem de TLS). Permitir que os aplicativos façam solicitações HTTP simples tem muitas vantagens quando usados com a TLS mútua do Istio e do TLS. Para mais informações, consulte o guia de práticas recomendadas.
Criar um
DestinationRule. The DestinationRule
especifica que o gateway originou uma conexão TLS com example.com.cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: DestinationRule metadata: name: example-com-originate-tls namespace: istio-egress spec: host: example.com subsets: - name: example-com-originate-TLS trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 443 tls: mode: SIMPLE sni: example.com EOF
Atualize o serviço virtual de example.com para que as solicitações para a porta 80 no gateway sejam "atualizadas" para TLS na porta 443 quando forem enviadas ao host de destino:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: example-com-through-egress-gateway namespace: istio-egress spec: hosts: - example.com gateways: - mesh - istio-egress/egress-gateway http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: example.com port: number: 443 subset: example-com-originate-TLS weight: 100 EOF
Faça várias solicitações para example.com pelo app de teste no namespace
team-x
:for i in {1..4} do kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com done
Como antes, as solicitações são bem-sucedidas com respostas
200 OK
.Verifique o registro do gateway de saída para verificar se o gateway roteou as solicitações para o host de destino originando conexões TLS:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egress \ -o jsonpath=" {.items[0].metadata.name}") istio-proxy
O resultado será assim:
[2020-09-24T17:58:02.548Z] "HEAD / HTTP/2" 200 - "-" "-" 0 0 6 5 "10.1.1.15" "curl/7.67.0" "83a77acb-d994-424d-83da-dd8eac902dc8" "example.com" "93.184.216.34:443" outbound|443|example-com-originate-TLS|example.com 10.1.4.31:49866 10.1.4.31:8080 10.1.1.15:37334 outbound_.80_.target-egress-gateway-mTLS_.istio-egressgateway.istio-egress.svc.cluster.local -
O proxy sidecar enviou a solicitação para o gateway usando a porta 80 e a TLS originada na porta 443 para enviar a solicitação ao host de destino.
Passagem de conexões HTTPS/TLS
Talvez seus aplicativos atuais já estejam usando conexões TLS ao se comunicar com serviços externos. É possível configurar o gateway de saída para transmitir conexões TLS sem descriptografá-lo.
Modifique sua configuração para que o gateway de saída use a passagem TLS para conexões com a porta 443:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: Gateway metadata: name: egress-gateway namespace: istio-egress spec: selector: istio: egress servers: - port: number: 80 name: https protocol: HTTPS hosts: - '*' tls: mode: ISTIO_MUTUAL - port: number: 443 name: tls protocol: TLS hosts: - '*' tls: mode: PASSTHROUGH EOF
Atualize o
DestinationRule
que aponta para o gateway de saída e adicione um segundo subconjunto para a porta 443 no gateway. Esse novo subconjunto não usa TLS mútuo. O TLS mútuo do Istio não é compatível com a passagem de conexões TLS. As conexões na porta 80 ainda usam mTLS:cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: DestinationRule metadata: name: target-egress-gateway namespace: istio-egress spec: host: istio-egressgateway.istio-egress.svc.cluster.local subsets: - name: target-egress-gateway-mTLS trafficPolicy: loadBalancer: simple: ROUND_ROBIN portLevelSettings: - port: number: 80 tls: mode: ISTIO_MUTUAL - name: target-egress-gateway-TLS-passthrough EOF
Atualize o serviço virtual para example.com para que o tráfego TLS na porta 443 seja transmitido por meio do gateway:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1alpha3 kind: VirtualService metadata: name: example-com-through-egress-gateway namespace: istio-egress spec: hosts: - example.com gateways: - mesh - istio-egress/egress-gateway http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: example.com port: number: 443 subset: example-com-originate-TLS weight: 100 tls: - match: - gateways: - mesh port: 443 sniHosts: - example.com route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-TLS-passthrough port: number: 443 - match: - gateways: - istio-egress/egress-gateway port: 443 sniHosts: - example.com route: - destination: host: example.com port: number: 443 weight: 100 exportTo: - 'istio-egress' - 'team-x' EOF
Atualize o serviço virtual para httpbin.org para que o tráfego TLS na porta 443 seja transmitido por meio do gateway:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: VirtualService metadata: name: httpbin-org-through-egress-gateway namespace: istio-egress spec: hosts: - httpbin.org gateways: - istio-egress/egress-gateway - mesh http: - match: - gateways: - mesh port: 80 route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-mTLS port: number: 80 weight: 100 - match: - gateways: - istio-egress/egress-gateway port: 80 route: - destination: host: httpbin.org port: number: 80 weight: 100 tls: - match: - gateways: - mesh port: 443 sniHosts: - httpbin.org route: - destination: host: istio-egressgateway.istio-egress.svc.cluster.local subset: target-egress-gateway-TLS-passthrough port: number: 443 - match: - gateways: - istio-egress/egress-gateway port: 443 sniHosts: - httpbin.org route: - destination: host: httpbin.org port: number: 443 weight: 100 exportTo: - 'istio-egress' - 'team-x' - 'team-y' EOF
Adicione uma política de autorização que aceite qualquer tipo de tráfego enviado para a porta 443 do serviço de gateway de saída. O
targetPort
correspondente nos pods de gateway é 8443.cat <<EOF | kubectl apply -f - apiVersion: security.istio.io/v1beta1 kind: AuthorizationPolicy metadata: name: egress-all-443 namespace: istio-egress spec: rules: - when: - key: destination.port values: ["8443"] EOF
Execute
istioctl analyze
para verificar se há erros de configuração:${ISTIOCTL} analyze -n istio-egress
Você verá:
✔ No validation issues found when analyzing namespace: istio-egress.
Faça uma solicitação HTTP simples para example.com do aplicativo de teste no namespace
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
A solicitação é bem-sucedida com uma resposta
200 OK
.Agora, faça várias solicitações TLS (HTTPS) do aplicativo de teste no namespace
team-x
:for i in {1..4} do kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -s -o /dev/null \ -w "%{http_code}\n" \ https://example.com done
Você vê 200 respostas.
Verifique o registro do gateway de saída novamente:
kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egress \ -o jsonpath="{.items[0].metadata.name}") istio-proxy
Você verá entradas de registro semelhantes a estas:
[2020-09-24T18:04:38.608Z] "- - -" 0 - "-" "-" 1363 5539 10 - "-" "-" "-" "-" "93.184.216.34:443" outbound|443||example.com 10.1.4.31:51098 10.1.4.31:8443 10.1.1.15:57030 example.com -
A solicitação HTTPS foi tratada como tráfego TCP e passada pelo gateway para o host de destino. Portanto, nenhuma informação HTTP está incluída no registro.
Como usar o Kubernetes NetworkPolicy como controle adicional
Há muitas situações em que um aplicativo pode ignorar um proxy sidecar.
Use o Kubernetes NetworkPolicy
para especificar ainda mais quais conexões
podem ser feitas. Depois que uma única política de rede é aplicada,
todas as conexões que não são especificamente permitidas são negadas.
Neste tutorial, são consideradas somente conexões de saída e seletores de saída para
políticas de rede. Se você controlar a entrada com políticas de rede nos seus próprios
clusters, precisará criar políticas de entrada para corresponder às suas políticas
de saída. Por exemplo, se você permitir a saída de cargas de trabalho no namespace team-x
para o namespace team-y
, também precisará permitir a
entrada para o namespace team-y
do namespace team-x
.
Permita que cargas de trabalho e proxies implantados no namespace
team-x
se conectem aistiod
e o gateway de saída:cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-control-plane namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: istio: system podSelector: matchLabels: istio: istiod - namespaceSelector: matchLabels: istio: egress podSelector: matchLabels: istio: egress EOF
Permitir que cargas de trabalho e proxies consultem DNS:
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-dns namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: kube-system: "true" ports: - port: 53 protocol: UDP - port: 53 protocol: TCP EOF
Permita que cargas de trabalho e os proxies se conectem aos IPs que disponibilizam APIs e serviços do Google, incluindo o Mesh CA:
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-google-apis namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - ipBlock: cidr: 199.36.153.4/30 - ipBlock: cidr: 199.36.153.8/30 EOF
Permita que cargas de trabalho e proxies se conectem ao servidor de metadados do GKE:
cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-metadata-server namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: # For GKE data plane v2 - ipBlock: cidr: 169.254.169.254/32 - to: # For GKE data plane v1 - ipBlock: cidr: 127.0.0.1/32 ports: - protocol: TCP port: 988 EOF
Opcional: permita que cargas de trabalho e proxies no namespace
team-x
se conectem umas às outras:cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-same-namespace namespace: team-x spec: podSelector: {} ingress: - from: - podSelector: {} egress: - to: - podSelector: {} EOF
Opcional: permita que cargas de trabalho e proxies no namespace
team-x
se conectem a cargas de trabalho implantadas por outra equipe:cat <<EOF | kubectl apply -f - apiVersion: networking.k8s.io/v1 kind: NetworkPolicy metadata: name: allow-egress-to-team-y namespace: team-x spec: podSelector: {} policyTypes: - Egress egress: - to: - namespaceSelector: matchLabels: team: 'y' EOF
As conexões entre proxies sidecar permanecem. As conexões atuais não são encerradas quando você aplica uma nova política de rede. Reinicie as cargas de trabalho no namespace team-x para garantir que as conexões atuais sejam fechadas:
kubectl -n team-x rollout restart deployment
Verifique se ainda é possível fazer uma solicitação HTTP para example.com pelo aplicativo de teste no namespace
team-x
:kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- curl -I http://example.com
A solicitação é bem-sucedida com uma resposta
200 OK
.
Como acessar diretamente as APIs do Google usando o Acesso privado do Google e as permissões do IAM
As APIs e os serviços do Google são expostos usando endereços IP externos. Quando os pods com endereços IP de alias nativos de VPC fazem conexões com as APIs do Google usando o Acesso privado do Google, o tráfego nunca sai da rede do Google.
Ao configurar a infraestrutura para este tutorial, você ativou o Acesso privado do Google para a sub-rede usada pelos pods do GKE. Para permitir o acesso aos endereços IP usados pelo Acesso privado do Google, você criou uma rota, uma regra de firewall VPC e uma zona de DNS particular. Essa configuração permite que os pods alcancem as APIs do Google diretamente sem enviar tráfego por meio do gateway de saída. É possível controlar quais APIs estão disponíveis para contas de serviço específicas do Kubernetes e, portanto, namespaces, usando a Identidade da carga de trabalho e o IAM. A autorização do Istio não tem efeito porque o gateway de saída não processa conexões com as APIs do Google.
Antes que os pods chamem APIs do Google, você precisa usar o IAM para conceder permissões. O cluster que você está usando para este tutorial está configurado para usar a Identidade da carga de trabalho, o que permite que uma conta de serviço do Kubernetes atue como uma conta de serviço do Google.
Crie uma conta de serviço do Google para o aplicativo usar:
gcloud iam service-accounts create sa-test-app-team-x
Permita que a conta de serviço do Kubernetes personifique a conta de serviço do Google:
gcloud iam service-accounts add-iam-policy-binding \ --role roles/iam.workloadIdentityUser \ --member "serviceAccount:${PROJECT_ID}.svc.id.goog[team-x/test]" \ sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com
Anote a conta de serviço do Kubernetes para app de teste no namespace
team-x
com o endereço de e-mail da conta de serviço do Google:cat <<EOF | kubectl apply -f - apiVersion: v1 kind: ServiceAccount metadata: annotations: iam.gke.io/gcp-service-account: sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com name: test namespace: team-x EOF
O pod do aplicativo de teste precisa acessar o servidor de metadados do Google, executado como um DaemonSet, para receber credenciais temporárias de chamada de APIs do Google. Crie uma entrada de serviço para o servidor de metadados do GKE:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: metadata-google-internal namespace: istio-egress spec: hosts: - metadata.google.internal ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'istio-egress' - 'team-x' EOF
Crie também uma entrada de serviço para private.googleapis.com e storage.googleapis.com:
cat <<EOF | kubectl apply -f - apiVersion: networking.istio.io/v1beta1 kind: ServiceEntry metadata: name: private-googleapis-com namespace: istio-egress spec: hosts: - private.googleapis.com - storage.googleapis.com ports: - number: 80 name: http protocol: HTTP - number: 443 name: tls protocol: TLS resolution: DNS location: MESH_EXTERNAL exportTo: - 'istio-egress' - 'team-x' EOF
Verifique se a conta de serviço do Kubernetes está configurada corretamente para atuar como a conta de serviço do Google:
kubectl -n team-x exec -it $(kubectl -n team-x get pod -l app=test \ -o jsonpath={.items..metadata.name}) -c test -- gcloud auth list
Você verá a conta de serviço do Google listada como a identidade ativa e única.
Crie um arquivo de teste em um bucket do Cloud Storage:
echo "Hello, World!" > /tmp/hello gsutil mb gs://${PROJECT_ID}-bucket gsutil cp /tmp/hello gs://${PROJECT_ID}-bucket/
Conceda permissão à conta de serviço para listar e visualizar arquivos no bucket:
gsutil iam ch \ serviceAccount:sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com:objectViewer \ gs://${PROJECT_ID}-bucket/
Verifique se o aplicativo de teste pode acessar o bucket de teste:
kubectl -n team-x exec -it \ $(kubectl -n team-x get pod -l app=test -o jsonpath={.items..metadata.name}) \ -c test \ -- gsutil cat gs://${PROJECT_ID}-bucket/hello
Você verá:
Hello, World!
Limpeza
Para evitar cobranças na sua conta do Google Cloud pelos recursos usados no tutorial, exclua o projeto que os contém ou mantenha o projeto e exclua os recursos individuais.
Para evitar cobranças sobre os recursos usados neste tutorial na conta do Google Cloud, conclua as etapas nas seções a seguir:
Excluir o projeto
A maneira mais fácil de evitar o faturamento é excluir o projeto criado para
o tutorial.
- In the Google Cloud console, go to the Manage resources page.
- In the project list, select the project that you want to delete, and then click Delete.
- In the dialog, type the project ID, and then click Shut down to delete the project.
A seguir
- Leia o guia de práticas recomendadas para campanhas complementares.
- Consulte o guia de aumento da proteção do GKE.
- Aprenda a gerenciar configurações e políticas em toda a infraestrutura com o Gerenciamento de configurações do GKE Enterprise.
- Para mais arquiteturas de referência, diagramas e práticas recomendadas, confira a Central de arquitetura do Cloud.