Menggunakan gateway keluar Cloud Service Mesh di cluster GKE: Tutorial


Tutorial ini menunjukkan cara menggunakan Cloud Service Mesh gateway keluar dan kontrol Google Cloud lainnya untuk mengamankan traffic keluar (traffic keluar) dari beban kerja yang di-deploy di cluster Google Kubernetes Engine. Tutorial dimaksudkan sebagai pendamping Praktik Terbaik untuk menggunakan gateway keluar Cloud Service Mesh di cluster GKE.

Audiens yang dituju untuk tutorial ini mencakup jaringan, platform, dan engineer keamanan yang mengelola cluster Google Kubernetes Engine yang digunakan oleh satu atau lebih banyak tim pengiriman perangkat lunak. Kontrol yang dijelaskan di sini sangat berguna untuk organisasi yang harus menunjukkan kepatuhan terhadap peraturan—misalnya, GDPR dan PCI.

Tujuan

  • Siapkan infrastruktur untuk menjalankan Cloud Service Mesh:
  • Instal Cloud Service Mesh.
  • Instal proxy gateway keluar yang berjalan di kumpulan node khusus.
  • Konfigurasikan aturan pemilihan rute multi-tenant untuk traffic eksternal melalui gateway keluar:
    • Aplikasi dalam namespace team-x dapat terhubung ke example.com
    • Aplikasi dalam namespace team-y dapat terhubung ke httpbin.org
  • Gunakan resource Sidecar untuk membatasi cakupan proxy file bantuan untuk setiap namespace.
  • Konfigurasikan kebijakan otorisasi untuk menerapkan aturan keluar.
  • Mengonfigurasi gateway keluar untuk mengupgrade permintaan HTTP biasa ke TLS (TLS asal).
  • Konfigurasikan gateway keluar untuk meneruskan traffic TLS.
  • Menyiapkan kebijakan jaringan Kubernetes sebagai kontrol traffic keluar tambahan.
  • Konfigurasikan akses langsung ke Google API menggunakan Pengelolaan Akses dan Identitas Google (IAM) Pribadi izin akses.

Biaya

Dalam dokumen ini, Anda menggunakan komponen Google Cloud yang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga. Pengguna baru Google Cloud mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

Setelah menyelesaikan tutorial ini, Anda dapat menghindari biaya berkelanjutan dengan menghapus resource yang telah dibuat. Untuk informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

  1. Di konsol Google Cloud, pada halaman pemilih project, pilih atau buat project Google Cloud.

    Buka pemilih project

  2. Pastikan penagihan telah diaktifkan untuk project Google Cloud Anda.

  3. Di konsol Google Cloud, aktifkan Cloud Shell.

    Aktifkan Cloud Shell

  4. Buat direktori kerja yang akan digunakan saat mengikuti tutorial:

    mkdir -p ~/WORKING_DIRECTORY
    cd ~/WORKING_DIRECTORY
    
  5. Buat skrip shell untuk melakukan inisialisasi lingkungan untuk tutorial. Ganti dan edit variabel sesuai dengan project dan preferensi Anda. Jalankan skrip ini dengan perintah source untuk menginisialisasi ulang lingkungan Anda jika sesi shell Anda berakhir:

    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
    
  6. Aktifkan compute.googleapis.com:

    gcloud services enable compute.googleapis.com --project=YOUR_PROJECT_ID
    
  7. Jadikan skrip dapat dieksekusi dan jalankan dengan perintah source untuk melakukan inisialisasi lingkungan Anda. Pilih Y jika diminta untuk mengaktifkan compute.googleapis.com:

    chmod +x ./init-egress-tutorial.sh
    source ./init-egress-tutorial.sh
    

Menyiapkan infrastruktur

Membuat subnet dan jaringan VPC

  1. Buat jaringan VPC baru:

    gcloud compute networks create vpc-network \
        --subnet-mode custom
    
  2. Buat subnet untuk cluster yang akan dijalankan dengan subnet sekunder yang telah ditetapkan Rentang alamat IP untuk Pod dan service. Akses Google Pribadi adalah sehingga aplikasi dengan hanya alamat IP internal yang dapat menjangkau Google API dan Layanan 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
    

Mengonfigurasi Cloud NAT

Cloud NAT memungkinkan koneksi ke workload tanpa alamat IP eksternal tujuan di internet dan menerima respons masuk dari tujuan.

  1. Membuat cloud router

    gcloud compute routers create nat-router \
        --network vpc-network
    
  2. Tambahkan konfigurasi NAT ke router:

    gcloud compute routers nats create nat-config \
        --router nat-router \
        --nat-all-subnet-ip-ranges \
        --auto-allocate-nat-external-ips
    

Membuat akun layanan untuk setiap node pool GKE

Membuat dua akun layanan untuk digunakan oleh kedua node GKE Google Cloud. Akun layanan terpisah ditetapkan untuk setiap kumpulan node sehingga Anda dapat menerapkan aturan firewall VPC ke node tertentu.

  1. Buat akun layanan untuk digunakan oleh node di kumpulan node default:

    gcloud iam service-accounts create sa-application-nodes \
        --description="SA for application nodes" \
        --display-name="sa-application-nodes"
    
  2. Buat akun layanan untuk digunakan oleh node dalam kumpulan node gateway:

    gcloud iam service-accounts create sa-gateway-nodes \
        --description="SA for gateway nodes" \
        --display-name="sa-gateway-nodes"
    

Memberikan izin ke akun layanan

Tambahkan sekumpulan peran IAM minimal ke aplikasi dan gateway akun layanan. Peran-peran ini diperlukan untuk pencatatan log, pemantauan, dan mengambil image container pribadi dari 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}." \
            --role="$role"
        gcloud projects add-iam-policy-binding ${PROJECT_ID} \
            --member="serviceAccount:sa-gateway-nodes@${PROJECT_ID}." \
            --role="$role"
    done

Membuat aturan firewall

Pada langkah berikut, Anda menerapkan aturan firewall ke jaringan VPC, sehingga secara default, semua traffic keluar akan ditolak. Konektivitas khusus diperlukan untuk cluster agar dapat berfungsi dan agar node gateway dapat mencapai tujuan di luar VPC. Sekumpulan minimal aturan {i>firewall<i} tertentu akan menggantikan aturan 'tolak semua' secara default untuk mengizinkan konektivitas yang diperlukan.

  1. Membuat aturan firewall default (prioritas rendah) untuk menolak semua traffic keluar dari Jaringan 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."
    
  2. Buat aturan untuk hanya mengizinkan node yang memiliki layanan gateway akun untuk terhubung ke 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}. \
        --network vpc-network \
        --priority 1000 \
        --description "Allow the nodes running the egress gateways to connect to the web"
    
  3. Izinkan node mencapai bidang kontrol Kubernetes:

    gcloud compute firewall-rules create allow-egress-to-api-server \
        --action ALLOW \
        --direction EGRESS \
        --rules tcp:443,tcp:10250 \
        --target-service-accounts sa-application-nodes@${PROJECT_ID}.,sa-gateway-nodes@${PROJECT_ID}. \
        --destination-ranges 10.5.0.0/28 \
        --network vpc-network \
        --priority 1000 \
        --description "Allow nodes to reach the Kubernetes API server."
    
  4. Opsional: Aturan firewall ini tidak diperlukan jika Anda menggunakan Managed Cloud Service Mesh.

    Cloud Service Mesh menggunakan webhook saat menginjeksikan proxy file bantuan ke sebagian besar workload standar dan berbasis cloud. Mengizinkan server GKE API memanggil webhook diekspos oleh bidang kontrol mesh layanan yang berjalan di node:

    gcloud compute firewall-rules create allow-ingress-api-server-to-webhook \
        --action ALLOW \
        --direction INGRESS \
        --rules tcp:15017 \
        --target-service-accounts sa-application-nodes@${PROJECT_ID}.,sa-gateway-nodes@${PROJECT_ID}. \
        --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"
    
  5. Izinkan konektivitas keluar antara Node dan Pod yang berjalan di . GKE secara otomatis membuat aturan traffic masuk yang sesuai. Tidak ada aturan yang diperlukan untuk Konektivitas layanan karena rantai {i>routing<i} iptables selalu mengonversi alamat IP Layanan menjadi Alamat IP pod.

    gcloud compute firewall-rules create allow-egress-nodes-and-pods \
        --action ALLOW \
        --direction EGRESS \
        --rules all \
        --target-service-accounts sa-application-nodes@${PROJECT_ID}.,sa-gateway-nodes@${PROJECT_ID}. \
        --destination-ranges 10.0.0.0/24,10.1.0.0/16 \
        --network vpc-network \
        --priority 1000 \
        --description "Allow egress to other Nodes and Pods"
    
  6. Izinkan akses ke kumpulan alamat IP yang dicadangkan yang digunakan oleh Akses Google Pribadi untuk menyalurkan Google API, Container Registry, dan layanan lainnya:

    gcloud compute firewall-rules create allow-egress-gcp-apis \
        --action ALLOW \
        --direction EGRESS \
        --rules tcp \
        --target-service-accounts sa-application-nodes@${PROJECT_ID}.,sa-gateway-nodes@${PROJECT_ID}. \
        --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)"
    
  7. Mengizinkan layanan health checker Google Cloud mengakses pod yang berjalan di cluster. Lihat health check: untuk informasi selengkapnya.

    gcloud compute firewall-rules create allow-ingress-gcp-health-checker \
        --action ALLOW \
        --direction INGRESS \
        --rules tcp:80,tcp:443 \
        --target-service-accounts sa-application-nodes@${PROJECT_ID}.,sa-gateway-nodes@${PROJECT_ID}. \
        --source-ranges 35.191.0.0/16,130.211.0.0/22,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"
    

Mengonfigurasi akses pribadi ke Google Cloud API

Akses Google Pribadi mengaktifkan VM dan Pod yang hanya memiliki IP internal untuk mengakses Google API dan layanan Google. Meskipun Google API dan layanan dari IP eksternal, traffic dari node tidak pernah keluar dari jaringan saat menggunakan Akses Google Pribadi.

Aktifkan Cloud DNS API:

gcloud services enable dns.googleapis.com

Buat zona DNS pribadi, kumpulan data CNAME, dan A sehingga node dan workload dapat terhubung ke Google API dan layanan Google menggunakan Akses Google Pribadi dan nama 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

Mengonfigurasi akses pribadi ke Container Registry

Buat zona DNS pribadi, data CNAME, dan A agar node dapat untuk terhubung ke Container Registry menggunakan Akses Google Pribadi Nama 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

Membuat cluster GKE pribadi

  1. Temukan alamat IP eksternal Cloud Shell agar Anda dapat menambahkannya ke daftar jaringan yang diizinkan untuk mengakses server API cluster:

    SHELL_IP=$(dig TXT -4 +short @ns1.google.com o-o.myaddr.l.google.com)
    

    Setelah tidak aktif selama beberapa waktu, alamat IP eksternal VM Cloud Shell dapat berubah. Jika hal itu terjadi, Anda harus memperbarui daftar cluster jaringan yang diizinkan. Tambahkan perintah berikut ke skrip inisialisasi:

    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
    
  2. Mengaktifkan Google Kubernetes Engine API:

    gcloud services enable container.googleapis.com
    
  3. Buat cluster GKE pribadi:

    gcloud container clusters create cluster1 \
        --enable-ip-alias \
        --enable-private-nodes \
        --release-channel "regular" \
        --enable-master-authorized-networks \
        --master-authorized-networks ${SHELL_IP//\"}/32 \
        --master-ipv4-cidr 10.5.0.0/28 \
        --enable-dataplane-v2 \
        --service-account "sa-application-nodes@${PROJECT_ID}." \
        --machine-type "e2-standard-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}
    

    Pembuatan cluster memerlukan waktu beberapa menit. Cluster ini memiliki node pribadi dengan alamat IP internal. Pod dan service ditetapkan IP dari rentang sekunder bernama yang Anda tetapkan saat membuat VPC di subnet yang berbeda.

    Cloud Service Mesh dengan bidang kontrol dalam cluster memerlukan cluster node untuk menggunakan jenis mesin yang memiliki setidaknya 4 vCPU.

    Google merekomendasikan agar cluster berlangganan ke "reguler" merilis untuk memastikan bahwa node menjalankan versi Kubernetes yang didukung oleh Cloud Service Mesh.

    Untuk mengetahui informasi selengkapnya tentang prasyarat untuk menjalankan Cloud Service Mesh dengan bidang kontrol dalam cluster, lihat prasyarat dalam cluster.

    Untuk informasi selengkapnya tentang persyaratan dan batasan untuk menjalankan Cloud Service Mesh terkelola fitur yang didukung Cloud Service Mesh terkelola.

    Workload Identity Federation untuk GKE adalah yang sudah diaktifkan di cluster. Cloud Service Mesh memerlukan Workload Identity Federation untuk GKE dan adalah cara yang direkomendasikan untuk mengakses Google API dari GKE sebagian besar workload standar dan berbasis cloud.

  4. Buat kumpulan node bernama gateway. Kumpulan node ini adalah tempat traffic keluar di-deploy. taint dedicated=gateway:NoSchedule ditambahkan ke setiap {i>node<i} pada kumpulan node 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}." \
        --num-nodes "1"
    

    taint dan toleransi Kubernetes membantu memastikan bahwa hanya Pod gateway keluar yang berjalan pada node di node gateway kolam renang.

  5. Download kredensial agar Anda dapat terhubung ke cluster dengan kubectl:

    gcloud container clusters get-credentials cluster1
    
  6. Pastikan node gateway memiliki taint yang benar:

    kubectl get nodes -l cloud.google.com/gke-nodepool=gateway -o yaml \
    -o=custom-columns='name:metadata.name,taints:spec.taints[?(@.key=="dedicated")]'
    

    Outputnya mirip dengan hal berikut ini:

    name                                 taints
    gke-cluster1-gateway-9d65b410-cffs   map[effect:NoSchedule key:dedicated value:gateway]
    

Menginstal dan menyiapkan Cloud Service Mesh

Ikuti salah satu panduan penginstalan untuk Cloud Service Mesh:

Setelah Anda menginstal Cloud Service Mesh, berhenti dan kembali ke tutorial ini tanpa menginstal gateway masuk atau keluar.

Menginstal gateway keluar

  1. Buat namespace Kubernetes untuk gateway keluar:

    kubectl create namespace istio-egress
    
  2. Saat Anda men-deploy gateway keluar, konfigurasi akan otomatis yang dimasukkan berdasarkan label yang Anda terapkan ke deployment atau namespace. Jika disiapkan. Beri label namespace dengan label injeksi default , jika tidak, Anda akan menggunakan label revisi untuk bidang kontrol yang yang telah Anda instal. Label revisi yang Anda tambahkan juga bergantung pada apakah Anda men-deploy atau tidak Cloud Layanan Cloud terkelola atau menginstal bidang kontrol dalam cluster.

    Pilih tab di bawah ini sesuai dengan jenis penginstalan Anda (baik yang terkelola dalam cluster).

    Terkelola

    Gunakan perintah berikut untuk menemukan revisi bidang kontrol yang tersedia:

    kubectl -n istio-system get controlplanerevision
    

    Outputnya mirip dengan hal berikut ini:

    NAME          RECONCILED   STALLED   AGE
    asm-managed   True         False     112m
    

    Catat nilai di kolom NAME untuk bidang kontrol baru yang ingin Anda gunakan. Biasanya saluran rilis Cloud Service Mesh Anda sesuai dengan saluran rilis cluster Google Kubernetes Engine Anda.

    Dalam cluster

    Untuk bidang kontrol dalam cluster, Layanan dan Deployment istiod biasanya memiliki label revisi yang mirip dengan istio.io/rev=, dengan mengidentifikasi versi Cloud Service Mesh. Tujuan revisi menjadi bagian dari nama Layanan istiod, misalnya: istiod-.istio-system

    Gunakan perintah berikut untuk menemukan label revisi di istiod untuk bidang kontrol dalam cluster:

    kubectl get deploy -n istio-system -l app=istiod \
      -o=jsonpath='{.items[*].metadata.labels.istio\.io\/rev}''{"\n"}'
    
  3. Opsional: Beri label namespace sehingga konfigurasi gateway akan dimasukkan secara otomatis. Anda cukup memberi label namespace atau deployment. Untuk tujuan tutorial ini, Anda melabeli keduanya untuk menghindari peringatan dari alat istioctl analyze.

    kubectl label namespace istio-egress istio.io/rev=REVISION
    
  4. Membuat manifes operator untuk gateway keluar:

    cat << EOF > egressgateway-operator.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: egressgateway-operator
      annotations:
        config.kubernetes.io/local-config: "true"
    spec:
      profile: empty
      revision: REVISION
      components:
        egressGateways:
        - name: istio-egressgateway
          namespace: istio-egress
          enabled: true
      values:
        gateways:
          istio-egressgateway:
            injectionTemplate: gateway
            tolerations:
              - key: "dedicated"
                operator: "Equal"
                value: "gateway"
            nodeSelector:
              cloud.google.com/gke-nodepool: "gateway"
    EOF
    
  5. Download alat istioctl. Anda harus menggunakan versi 1.16.2-asm.2 atau yang lebih baru bahkan jika Anda menggunakan Cloud Service Mesh versi 1.15 atau yang lebih lama. Lihat Mendownload versi istioctl yang benar.

  6. Setelah mengekstrak arsip yang didownload, setel variabel lingkungan untuk menahan jalur ke alat istioctl dan tambahkan ke skrip inisialisasi Anda:

    ISTIOCTL=$(find "$(pwd -P)" -name istioctl)
    echo "ISTIOCTL=\"${ISTIOCTL}\"" >> ./init-egress-tutorial.sh
    
  7. Membuat manifes penginstalan gateway keluar menggunakan operator manifes dan istioctl:

    ${ISTIOCTL} manifest generate \
        --filename egressgateway-operator.yaml \
        --output egressgateway \
        --cluster-specific
    
  8. Instal gateway keluar:

    kubectl apply --recursive --filename egressgateway/
    
  9. Pastikan gateway keluar berjalan pada node di node gateway kolam:

    kubectl get pods -n istio-egress -o wide
    
  10. Pod gateway keluar memiliki affinity untuk node pada kumpulan node gateway dan toleransi yang memungkinkan mereka berjalan di node {i>gateway<i} yang tercemar. Periksa afinitas dan toleransi node untuk pod gateway keluar:

    kubectl -n istio-egress get pod -l istio=egressgateway \
        -o=custom-columns='name:metadata.name,node-affinity:spec.affinity.nodeAffinity.requiredDuringSchedulingIgnoredDuringExecution.nodeSelectorTerms,tolerations:spec.tolerations[?(@.key=="dedicated")]'
    

    Outputnya mirip dengan hal berikut ini:

    name                                   node-affinity                                                                                   tolerations
    istio-egressgateway-754d9684d5-jjkdz   [map[matchExpressions:[map[key:cloud.google.com/gke-nodepool operator:In values:[gateway]]]]]   map[key:dedicated operator:Equal value:gateway]
    

Mengaktifkan logging akses Envoy

Langkah-langkah yang diperlukan untuk mengaktifkan log akses Envoy bergantung pada Cloud Service Mesh Anda jenis file, baik yang terkelola maupun dalam cluster:

Menyiapkan mesh dan aplikasi pengujian

  1. Pastikan bahwa STRICT mutual TLS diaktifkan. Terapkan default Kebijakan PeerAuthentication untuk mesh dalam namespace istio-system:

    cat <<EOF | kubectl apply -f -
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "default"
      namespace: "istio-system"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    Anda dapat mengganti konfigurasi ini dengan membuat PeerAuthentication resource dalam namespace tertentu.

  2. Buat namespace yang akan digunakan untuk men-deploy workload pengujian. Langkah selanjutnya di tutorial ini menjelaskan cara mengonfigurasi aturan perutean keluar yang berbeda untuk setiap namespace.

    kubectl create namespace team-x
    kubectl create namespace team-y
    
  3. Memberi label pada namespace agar dapat dipilih oleh jaringan Kubernetes kebijakan:

    kubectl label namespace team-x team=x
    kubectl label namespace team-y team=y
    
  4. Agar Cloud Service Mesh dapat otomatis memasukkan file bantuan proxy, Anda menetapkan label revisi bidang kontrol pada namespace workload:

    kubectl label ns team-x istio.io/rev=REVISION
    kubectl label ns team-y istio.io/rev=REVISION
    
  5. Buat file YAML yang akan digunakan untuk melakukan deployment pengujian:

    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
    
  6. Deploy aplikasi pengujian ke namespace team-x:

    kubectl -n team-x create -f ./test.yaml
    
  7. Memastikan aplikasi pengujian di-deploy ke node secara default dan bahwa container file bantuan proxy dimasukkan. Ulangi langkah berikut hingga status pod menjadi Running:

    kubectl -n team-x get po -l app=test -o wide
    

    Outputnya mirip dengan hal berikut ini:

    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
    

    2 dari 2 container adalah Running. Satu container adalah tempat pengujian aplikasi dan yang lainnya adalah file bantuan proxy.

    Pod berjalan pada node di kumpulan node default.

  8. Memverifikasi bahwa membuat permintaan HTTP dari pengujian tidak dapat dilakukan penampung ke situs eksternal:

    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
    

    Pesan error dari proxy file bantuan dibuat karena Aturan firewall global-deny-egress-all menolak koneksi upstream.

Menggunakan resource File bantuan untuk membatasi cakupan konfigurasi proxy file bantuan

Anda dapat menggunakan Resource file bantuan untuk membatasi cakupan pemroses keluar yang dikonfigurasi untuk file bantuan menggunakan {i>proxy<i}. Untuk mengurangi penggelembungan konfigurasi dan penggunaan memori, sebaiknya menerapkan resource Sidecar default untuk setiap namespace.

Proxy yang dijalankan Cloud Service Mesh di file bantuan adalah Envoy. Di beberapa Terminologi Envoy, cluster adalah grup endpoint upstream yang mirip secara logis yang digunakan sebagai tujuan load balancing.

  1. Periksa cluster keluar yang dikonfigurasi di proxy file bantuan Envoy untuk pod pengujian dengan menjalankan perintah istioctl proxy-config:

    ${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \
        -o jsonpath={.items..metadata.name}).team-x --direction outbound
    

    Ada sekitar 11 klaster Envoy dalam daftar tersebut, termasuk beberapa di antaranya untuk gateway keluar.

  2. Membatasi konfigurasi {i>proxy<i} ke rute keluar yang telah ditentukan secara eksplisit dengan entri layanan di namespace team-x dan traffic keluar. Terapkan resource Sidecar ke Namespace team-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
    

    Menetapkan mode kebijakan traffic keluar ke REGISTRY_ONLY akan membatasi konfigurasi {i>proxy<i} untuk hanya menyertakan {i> host<i} eksternal yang telah secara eksplisit ditambahkan ke registry layanan mesh dengan menentukan entri layanan.

    Menyetel egress.hosts akan menentukan bahwa proxy file bantuan hanya memilih dari namespace keluar yang tersedia menggunakan atribut exportTo. 'team-x/*' mencakup setiap rute yang telah dikonfigurasi secara lokal di namespace team-x.

  3. Melihat cluster keluar yang dikonfigurasikan di proxy file bantuan Envoy, dan membandingkannya dengan daftar klaster yang dikonfigurasi sebelum diterapkan resource Sidecar:

    ${ISTIOCTL} pc c $(kubectl -n team-x get pod -l app=test \
        -o jsonpath={.items..metadata.name}).team-x --direction outbound
    

    Anda akan melihat cluster untuk gateway keluar dan satu lagi untuk pod pengujian.

Mengonfigurasi Cloud Service Mesh untuk mengarahkan traffic melalui gateway keluar

  1. Konfigurasi Gateway untuk traffic HTTP di port 80. Gateway memilih proxy gateway keluar yang Anda deploy ke namespace keluar. Konfigurasi Gateway diterapkan ke traffic keluar namespace dan menangani lalu lintas untuk setiap {i>host<i}.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: egress-gateway
      namespace: istio-egress
    spec:
      selector:
        istio: egressgateway
      servers:
      - port:
          number: 80
          name: https
          protocol: HTTPS
        hosts:
          - '*'
        tls:
          mode: ISTIO_MUTUAL
    EOF
    
  2. Membuat DestinationRule untuk gateway keluar dengan TLS bersama untuk otentikasi dan enkripsi. Gunakan satu aturan tujuan bersama untuk semua untuk host eksternal.

    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:
          tls:
            mode: ISTIO_MUTUAL
    EOF
    
  3. Buat ServiceEntry di namespace keluar untuk secara eksplisit mendaftarkan example.com di registry layanan mesh untuk team-x ruang nama:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1beta1
    kind: ServiceEntry
    metadata:
      name: example-com-ext
      namespace: istio-egress
      labels:
        # Show this service and its telemetry in the Cloud Service Mesh page of the Google Cloud console
        service.istio.io/canonical-name: example.com
    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
    
  4. Buat VirtualService untuk mengarahkan traffic ke example.com melalui gateway keluar. Ada dua kondisi pencocokan: kondisi pertama mengarahkan traffic ke gateway keluar, dan yang kedua mengarahkan traffic dari gateway keluar ke host tujuan. Kontrol properti exportTo namespace mana yang dapat menggunakan layanan 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
    
  5. Jalankan istioctl analyze untuk memeriksa error konfigurasi:

    ${ISTIOCTL} analyze -n istio-egress --revision REVISION
    

    Outputnya mirip dengan hal berikut ini:

    ✔ No validation issues found when analyzing namespace: istio-egress.
    
  6. Kirim beberapa permintaan melalui gateway keluar ke situs eksternal:

    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
    

    Anda akan melihat kode status 200 untuk keempat respons.

  7. Pastikan bahwa permintaan diarahkan melalui gateway keluar dengan memeriksa log akses {i>proxy<i}. Pertama, periksa log akses untuk proxy file bantuan yang di-deploy dengan aplikasi pengujian:

    kubectl -n team-x logs -f $(kubectl -n team-x get pod -l app=test \
        -o jsonpath={.items..metadata.name}) istio-proxy
    

    Untuk setiap permintaan yang dikirim, Anda akan melihat entri log yang mirip dengan berikut ini:

    [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 - -
    
  8. Periksa juga log akses gateway keluar:

    kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egressgateway \
        -o jsonpath="{.items[0].metadata.name}") istio-proxy
    

    Untuk setiap permintaan yang dikirim, Anda akan melihat entri log akses gateway keluar mirip dengan contoh berikut ini:

    [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 -
    

Mengonfigurasi pemilihan rute yang berbeda untuk namespace kedua

Konfigurasikan perutean untuk host eksternal kedua guna mempelajari bagaimana perbedaan konektivitas dapat dikonfigurasi untuk tim yang berbeda.

  1. Buat resource Sidecar untuk namespace team-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
    
  2. Deploy aplikasi pengujian ke namespace team-y:

    kubectl -n team-y create -f ./test.yaml
    
  3. Daftarkan host eksternal kedua, lalu ekspor ke team-x dan namespace team-y:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1beta1
    kind: ServiceEntry
    metadata:
      name: httpbin-org-ext
      namespace: istio-egress
      labels:
        # Show this service and its telemetry in the Cloud Service Mesh page of the Google Cloud console
        service.istio.io/canonical-name: httpbin.org
    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
    
  4. Buat layanan virtual untuk mengarahkan lalu lintas data ke httpbin.org melalui gateway keluar:

    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
    
  5. Jalankan istioctl analyze untuk memeriksa error konfigurasi:

    ${ISTIOCTL} analyze -n istio-egress --revision REVISION
    

    Anda akan melihat:

    ✔ No validation issues found when analyzing namespace: istio-egress.
    
  6. Buat permintaan ke httpbin.org dari aplikasi pengujian 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
    

    Anda melihat respons 200 OK.

  7. Buat juga permintaan ke httpbin.org dari aplikasi pengujian 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
    

    Anda melihat respons 200 OK.

  8. Coba buat permintaan ke example.com dari 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
    

    Permintaan gagal karena tidak ada rute keluar yang dikonfigurasi untuk Host example.com.

Menggunakan Kebijakan Otorisasi untuk memberikan kontrol tambahan atas traffic

Dalam tutorial ini, kebijakan otorisasi untuk gateway keluar dibuat di namespace istio-egress. Anda dapat mengonfigurasi RBAC Kubernetes agar hanya administrator jaringan dapat mengakses namespace istio-egress.

  1. Buat AuthorizationPolicy agar aplikasi di team-x namespace dapat terhubung ke {i>example.com<i} tetapi tidak ke {i>host<i} eksternal lain ketika mengirimkan permintaan menggunakan porta 80. targetPort yang sesuai di pod gateway keluar adalah 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:
      action: ALLOW
      rules:
        - from:
          - source:
              namespaces:
              - 'team-x'
          to:
          - operation:
              hosts:
                - 'example.com'
          when:
          - key: destination.port
            values: ["8080"]
    EOF
    
  2. Memastikan bahwa Anda dapat membuat permintaan ke example.com dari pengujian aplikasi dalam 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
    

    Anda melihat respons 200 OK.

  3. Coba buat permintaan ke httpbin.org dari aplikasi uji coba di 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
    

    Permintaan gagal dengan pesan RBAC: access denied dan 403 Kode status dilarang. Anda mungkin perlu menunggu beberapa detik karena ada sering terjadi penundaan singkat sebelum kebijakan otorisasi berlaku.

  4. Kebijakan otorisasi memberikan kontrol yang kaya terhadap lalu lintas mana yang diizinkan atau ditolak. Terapkan kebijakan otorisasi berikut untuk mengizinkan aplikasi uji coba di namespace team-y untuk membuat permintaan ke httpbin.org menggunakan satu jalur URL tertentu saat mengirim permintaan menggunakan porta 80. Tujuan targetPort yang sesuai pada pod gateway keluar adalah 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:
      action: ALLOW
      rules:
        - from:
          - source:
              namespaces:
              - 'team-y'
          to:
          - operation:
              hosts:
              - httpbin.org
              paths: ['/status/418']
          when:
          - key: destination.port
            values: ["8080"]
    EOF
    
  5. Mencoba menghubungkan ke httpbin.org dari aplikasi pengujian di team-y ruang nama:

    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
    

    Permintaan gagal dengan pesan RBAC: access denied dan 403 Kode status dilarang.

  6. Sekarang buat permintaan ke httpbin.org/status/418 dari aplikasi yang sama:

    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
    

    Permintaan berhasil karena jalur sesuai dengan pola dalam kebijakan otorisasi. Outputnya mirip dengan hal berikut ini:

       -=[ teapot ]=-
          _...._
        .'  _ _ `.
       | ."` ^ `". _,
       \_;`"---"`|//
         |       ;/
         \_     _/
           `"""`
    

Asal TLS di gateway keluar

Anda dapat mengonfigurasi gateway keluar ke HTTP biasa upgrade (asal) ke TLS atau TLS bersama. Mengizinkan aplikasi membuat permintaan HTTP biasa memiliki beberapa keuntungan saat digunakan dengan asal TLS dan TLS bersama Istio. Sebagai informasi selengkapnya, lihat panduan praktik terbaik.

Asal TLS di gateway keluar

  1. Membuat DestinationRule. The DestinationRule menentukan bahwa memulai koneksi TLS ke {i>example.com<i}.

    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:
            portLevelSettings:
            - port:
                number: 443
              tls:
                mode: SIMPLE
                sni: example.com
    EOF
    
  2. Update layanan virtual untuk example.com agar meminta port 80 di gateway adalah upgraded ke TLS pada porta 443 ketika dikirim ke host tujuan:

    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
    
  3. Buat beberapa permintaan ke example.com dari aplikasi pengujian di team-x ruang nama:

    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
    

    Seperti sebelumnya, permintaan berhasil dengan 200 OK respons.

  4. Periksa log gateway keluar untuk memastikan bahwa gateway tersebut mengarahkan rute ke permintaan ke host tujuan dengan koneksi TLS asal:

    kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egressgateway \
        -o jsonpath="    {.items[0].metadata.name}") istio-proxy
    

    Outputnya mirip dengan hal berikut ini:

    [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 -
    

    File bantuan proxy mengirim permintaan ke gateway menggunakan port 80 dan TLS berasal dari porta 443 untuk mengirim permintaan ke {i>host<i} tujuan.

Lewati koneksi HTTPS/TLS

Aplikasi Anda yang ada mungkin sudah menggunakan koneksi TLS saat berkomunikasi dengan layanan eksternal. Anda dapat mengonfigurasi gateway keluar untuk melewati koneksi TLS tanpa membongkar enkripsinya.

{i>tls pass through<i}

  1. Ubah konfigurasi Anda agar gateway keluar menggunakan TLS {i>pass-through<i} untuk koneksi ke porta 443:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: egress-gateway
      namespace: istio-egress
    spec:
      selector:
        istio: egressgateway
      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
    
  2. Perbarui DestinationRule yang mengarah ke gateway keluar untuk menambahkan {i>subset<i} kedua untuk porta 443 di {i>gateway<i}. {i>Subset<i} baru ini tidak menggunakan TLS bersama. TLS mutual Istio tidak didukung untuk pass-through TLS koneksi jarak jauh. Koneksi pada porta 80 masih menggunakan 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:
          portLevelSettings:
          - port:
              number: 80
            tls:
              mode: ISTIO_MUTUAL
      - name: target-egress-gateway-TLS-passthrough
    EOF
    
  3. Mengupdate layanan virtual untuk example.com agar traffic TLS pada port 443 diteruskan melalui 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
    
  4. Mengupdate layanan virtual untuk httpbin.org agar traffic TLS pada port 443 diteruskan melalui 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
    
  5. Tambahkan kebijakan otorisasi yang menerima semua jenis traffic yang dikirim ke port 443 dari layanan gateway keluar. targetPort yang sesuai aktif pod gateway-nya adalah 8443.

    cat <<EOF | kubectl apply -f -
    apiVersion: security.istio.io/v1beta1
    kind: AuthorizationPolicy
    metadata:
      name: egress-all-443
      namespace: istio-egress
    spec:
      action: ALLOW
      rules:
        - when:
          - key: destination.port
            values: ["8443"]
    EOF
    
  6. Jalankan istioctl analyze untuk memeriksa error konfigurasi:

    ${ISTIOCTL} analyze -n istio-egress --revision REVISION
    

    Anda akan melihat:

    ✔ No validation issues found when analyzing namespace: istio-egress.
    
  7. Membuat permintaan HTTP biasa ke example.com dari aplikasi pengujian di 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
    

    Permintaan berhasil dengan respons 200 OK.

  8. Sekarang buat beberapa permintaan TLS (HTTPS) dari aplikasi pengujian di 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
    

    Anda melihat 200 tanggapan.

  9. Lihat kembali log gateway keluar:

    kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egressgateway \
        -o jsonpath="{.items[0].metadata.name}") istio-proxy
    

    Anda akan melihat entri log yang mirip dengan berikut ini:

    [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 -
    

    Permintaan HTTPS diperlakukan sebagai traffic TCP dan diteruskan melalui ke host tujuan, sehingga tidak ada informasi HTTP yang disertakan dalam log.

Menggunakan NetworkPolicy Kubernetes sebagai kontrol tambahan

Ada banyak skenario ketika aplikasi dapat mengabaikan proxy file bantuan. Anda dapat menggunakan NetworkPolicy Kubernetes untuk menentukan juga koneksi mana yang diizinkan untuk dilakukan. Setelah satu kebijakan jaringan diterapkan, semua koneksi yang tidak secara spesifik diizinkan akan ditolak.

Tutorial ini hanya mempertimbangkan koneksi keluar dan pemilih traffic keluar untuk kebijakan jaringan. Jika Anda mengontrol traffic masuk dengan kebijakan jaringan sendiri Anda, maka Anda harus membuat kebijakan traffic masuk agar sesuai dengan traffic keluar kebijakan izin yang relevan. Misalnya, jika Anda mengizinkan traffic keluar dari workload di team-x namespace ke namespace team-y, Anda juga harus mengizinkan traffic masuk ke team-y dari namespace team-x.

  1. Izinkan workload dan proxy yang di-deploy di namespace team-x untuk hubungkan ke istiod dan gateway keluar:

    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:
              "kubernetes.io/metadata.name": istio-system
          podSelector:
            matchLabels:
              istio: istiod
        - namespaceSelector:
            matchLabels:
              "kubernetes.io/metadata.name": istio-egress
          podSelector:
            matchLabels:
              istio: egressgateway
    EOF
    
  2. Izinkan workload dan proxy untuk mengkueri 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:
              "kubernetes.io/metadata.name": kube-system
        ports:
        - port: 53
          protocol: UDP
        - port: 53
          protocol: TCP
    EOF
    
  3. Izinkan workload dan proxy terhubung ke IP yang melayani Google API dan layanan, termasuk certificate authority Cloud Service Mesh:

    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
    
  4. Izinkan workload dan proxy terhubung ke GKE server metadata:

    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 # Prior to 1.21.0-gke.1000
        - ipBlock:
            cidr: 169.254.169.252/32 # 1.21.0-gke.1000 and later
        ports:
        - protocol: TCP
          port: 987
        - protocol: TCP
          port: 988
    EOF
    
  5. Opsional: Izinkan beban kerja dan proxy di namespace team-x untuk melakukan koneksi antara satu sama lain:

    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
    
  6. Opsional: Izinkan beban kerja dan proxy di namespace team-x untuk melakukan koneksi ke beban kerja yang di-deploy oleh tim yang berbeda:

    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:
              "kubernetes.io/metadata.name": team-y
    EOF
    
  7. Koneksi antara proxy file bantuan akan tetap ada. Koneksi yang ada adalah tidak ditutup saat Anda menerapkan kebijakan jaringan baru. Mulai ulang workload dalam namespace tim-x untuk memastikan koneksi yang ada ditutup:

    kubectl -n team-x rollout restart deployment
    
  8. Verifikasi bahwa Anda masih dapat membuat permintaan HTTP ke example.com dari aplikasi pengujian di 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
    

    Permintaan berhasil dengan respons 200 OK.

Mengakses Google API secara langsung menggunakan Akses Google Pribadi dan izin IAM

API dan layanan Google diekspos menggunakan alamat IP eksternal. Kapan pod dengan alamat IP alias native VPC membuat koneksi ke Google API Akses Google Pribadi, lalu lintas data tidak pernah keluar dari jaringan Google.

Saat menyiapkan infrastruktur untuk tutorial ini, Anda mengaktifkan Akses Google Pribadi untuk subnet yang digunakan oleh GKE pod. Untuk mengizinkan akses ke alamat IP yang digunakan oleh Akses Google Pribadi, Anda telah membuat rute, aturan firewall VPC, dan zona DNS pribadi. Ini memungkinkan pod menjangkau Google API secara langsung tanpa mengirim traffic melalui gateway keluar. Anda dapat mengontrol API mana yang tersedia untuk Akun layanan Kubernetes (dan juga namespace) dengan menggunakan Workload Identity Federation untuk GKE dan IAM. Otorisasi Istio tidak berlaku karena traffic keluar tidak menangani koneksi ke Google API.

Sebelum pod dapat memanggil Google API, Anda harus menggunakan IAM untuk memberikan izin akses. Cluster yang Anda gunakan untuk tutorial ini dikonfigurasi untuk digunakan Workload Identity Federation untuk GKE, yang memungkinkan akun layanan Kubernetes bertindak sebagai Akun layanan Google.

  1. Buat akun layanan Google untuk aplikasi Anda yang akan digunakan:

    gcloud iam service-accounts create sa-test-app-team-x
    
  2. Izinkan akun layanan Kubernetes meniru layanan Google akun:

    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}.
    
  3. Menganotasi akun layanan Kubernetes untuk aplikasi pengujian di Namespace team-x dengan alamat email akun layanan 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}.
      name: test
      namespace: team-x
    EOF
    
  4. Pod aplikasi pengujian harus dapat mengakses metadata Google server (berjalan sebagai DaemonSet) untuk mendapatkan kredensial sementara untuk memanggil Google API. Membuat entri layanan untuk GKE server metadata:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1beta1
    kind: ServiceEntry
    metadata:
      name: metadata-google-internal
      namespace: istio-egress
      labels:
        # Show this service and its telemetry in the Cloud Service Mesh page of the Google Cloud console
        service.istio.io/canonical-name: metadata.google.internal
    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
    
  5. Buat juga entri layanan untuk private.googleapis.com dan storage.googleapis.com:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1beta1
    kind: ServiceEntry
    metadata:
      name: private-googleapis-com
      namespace: istio-egress
      labels:
        # Show this service and its telemetry in the Cloud Service Mesh page of the Google Cloud console
        service.istio.io/canonical-name: googleapis.com
    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
    
  6. Memastikan akun layanan Kubernetes dikonfigurasi dengan benar untuk bertindak sebagai akun layanan 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
    

    Anda akan melihat akun layanan Google tercantum sebagai identitas yang aktif dan satu-satunya.

  7. Buat file pengujian di bucket Cloud Storage:

    echo "Hello, World!" > /tmp/hello
    gcloud storage buckets create gs://${PROJECT_ID}-bucket
    gcloud storage cp /tmp/hello gs://${PROJECT_ID}-bucket/
    
  8. Beri akun layanan izin untuk menampilkan dan melihat file di bucket:

    gcloud storage buckets add-iam-policy-binding gs://${PROJECT_ID}-bucket/ \
        --member=serviceAccount:sa-test-app-team-x@${PROJECT_ID}. \
        --role=roles/storage.objectViewer
    
  9. Pastikan bahwa aplikasi pengujian dapat mengakses bucket pengujian:

    kubectl -n team-x exec -it \
    $(kubectl -n team-x get pod -l app=test -o jsonpath={.items..metadata.name}) \
    -c test \
    -- gcloud storage cat gs://${PROJECT_ID}-bucket/hello
    

    Anda akan melihat:

    Hello, World!
    

Pembersihan

Agar tidak perlu membayar biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, hapus project yang berisi resource tersebut, atau simpan project dan hapus setiap resource.

Agar tidak menimbulkan biaya ke akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, selesaikan langkah-langkah di bagian berikut:

Menghapus project

Cara termudah untuk menghilangkan penagihan adalah dengan menghapus project yang Anda buat tutorial.

  1. Di konsol Google Cloud, buka halaman Manage resource.

    Buka Manage resource

  2. Pada daftar project, pilih project yang ingin Anda hapus, lalu klik Delete.
  3. Pada dialog, ketik project ID, lalu klik Shut down untuk menghapus project.

Langkah selanjutnya