Menggunakan gateway keluar Cloud Service Mesh di cluster GKE: Tutorial


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

Audiens yang dituju untuk tutorial ini meliputi engineer jaringan, platform, dan keamanan yang mengelola cluster Google Kubernetes Engine yang digunakan oleh satu atau beberapa tim pengiriman software. Kontrol yang dijelaskan di sini sangat berguna bagi 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 node pool khusus.
  • Konfigurasi aturan pemilihan rute multi-tenant untuk traffic eksternal melalui gateway keluar:
    • Aplikasi di namespace team-x dapat terhubung ke example.com
    • Aplikasi di namespace team-y dapat terhubung ke httpbin.org
  • Gunakan resource Sidecar untuk membatasi cakupan konfigurasi keluar proxy sidecar untuk setiap namespace.
  • Konfigurasi kebijakan otorisasi untuk menerapkan aturan keluar.
  • Konfigurasi gateway keluar untuk mengupgrade permintaan HTTP biasa ke TLS (TLS origination).
  • Konfigurasikan gateway keluar untuk meneruskan traffic TLS.
  • Siapkan kebijakan jaringan Kubernetes sebagai kontrol egress tambahan.
  • Konfigurasi akses langsung ke Google API menggunakan izin Private Google Access dan Identity and Access Management (IAM).

Biaya

Dalam dokumen ini, Anda akan menggunakan komponen Google Cloudyang dapat ditagih berikut:

Untuk membuat perkiraan biaya berdasarkan proyeksi penggunaan Anda, gunakan kalkulator harga.

Pengguna Google Cloud baru mungkin memenuhi syarat untuk mendapatkan uji coba gratis.

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

Sebelum memulai

  1. In the Google Cloud console, on the project selector page, select or create a Google Cloud project.

    Go to project selector

  2. Verify that billing is enabled for your Google Cloud project.

  3. In the Google Cloud console, activate Cloud Shell.

    Activate Cloud Shell

  4. Buat direktori kerja untuk digunakan saat mengikuti tutorial:

    mkdir -p ~/WORKING_DIRECTORY
    cd ~/WORKING_DIRECTORY
    
  5. Buat skrip shell untuk menginisialisasi lingkungan Anda 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 menginisialisasi lingkungan Anda. Pilih Y jika diminta untuk mengaktifkan compute.googleapis.com:

    chmod +x ./init-egress-tutorial.sh
    source ./init-egress-tutorial.sh
    
  8. Menyiapkan infrastruktur

    Buat jaringan dan subnet VPC

    1. Buat jaringan VPC baru:

      gcloud compute networks create vpc-network \
          --subnet-mode custom
      
    2. Buat subnet untuk cluster yang akan dijalankan dengan rentang alamat IP sekunder yang telah ditetapkan untuk Pod dan layanan. Akses Google Pribadi diaktifkan sehingga aplikasi dengan hanya alamat IP internal dapat menjangkau 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 workload tanpa alamat IP eksternal terhubung ke tujuan di internet dan menerima respons masuk dari tujuan tersebut.

    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
      

    Buat akun layanan untuk setiap node pool GKE

    Buat dua akun layanan untuk digunakan oleh dua kumpulan node GKE. Akun layanan terpisah ditetapkan ke setiap node pool sehingga Anda dapat menerapkan aturan firewall VPC ke node tertentu.

    1. Buat akun layanan untuk digunakan oleh node di node pool 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 di node pool 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 serangkaian peran IAM minimal ke akun layanan aplikasi dan gateway. Peran ini diperlukan untuk mencatat log, memantau, 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}.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
    

    Membuat aturan firewall

    Pada langkah-langkah berikut, Anda menerapkan aturan firewall ke jaringan VPC sehingga, secara default, semua traffic keluar ditolak. Konektivitas tertentu diperlukan agar cluster dapat berfungsi dan agar node gateway dapat mencapai tujuan di luar VPC. Serangkaian aturan firewall spesifik minimal menggantikan aturan default tolak semua untuk mengizinkan konektivitas yang diperlukan.

    1. Buat 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 dengan akun layanan gateway untuk menjangkau 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"
      
    3. Izinkan node menjangkau 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}.iam.gserviceaccount.com,sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com \
          --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 menyuntikkan proxy sidecar ke dalam beban kerja. Izinkan server API GKE memanggil webhook yang diekspos oleh bidang kontrol service mesh 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}.iam.gserviceaccount.com,sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com \
          --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 cluster. GKE akan otomatis membuat aturan ingress yang sesuai. Tidak ada aturan yang diperlukan untuk konektivitas Layanan karena rantai perutean 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}.iam.gserviceaccount.com,sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com \
          --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 menayangkan 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}.iam.gserviceaccount.com,sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com \
          --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. Izinkan layanan pemeriksa kondisi Google Cloud mengakses pod yang berjalan di cluster. Lihat pemeriksaan kondisi: untuk mengetahui 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}.iam.gserviceaccount.com,sa-gateway-nodes@${PROJECT_ID}.iam.gserviceaccount.com \
          --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 API Google Cloud

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

    Aktifkan Cloud DNS API:

    gcloud services enable dns.googleapis.com
    

    Buat zona DNS pribadi, data CNAME, dan data A agar node dan workload dapat terhubung ke Google API dan layanan 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 data A agar node dapat terhubung ke Container Registry menggunakan Akses Google Pribadi dan 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 Anda agar Anda dapat menambahkannya ke daftar jaringan yang diizinkan untuk mengakses server API cluster Anda:

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

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

      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}.iam.gserviceaccount.com" \
          --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}
      

      Perlu waktu beberapa menit untuk membuat cluster. Cluster memiliki node pribadi dengan alamat IP internal. Pod dan layanan diberi IP dari rentang sekunder bernama yang Anda tentukan saat membuat subnet VPC.

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

      Google merekomendasikan agar cluster berlangganan saluran rilis "reguler" 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 panel kontrol dalam cluster, lihat prasyarat dalam cluster.

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

      Workload Identity Federation for GKE diaktifkan di cluster. Cloud Service Mesh memerlukan Workload Identity Federation for GKE dan merupakan cara yang direkomendasikan untuk mengakses Google API dari workload GKE.

    4. Buat node pool bernama gateway. Node pool ini adalah tempat gateway keluar di-deploy. dedicated=gateway:NoSchedule Taint ditambahkan ke setiap node di node pool 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"
      

      Taint dan toleransi Kubernetes membantu memastikan bahwa hanya Pod gateway keluar yang berjalan di node dalam kumpulan node gateway.

    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 menginstal Cloud Service Mesh, hentikan dan kembali ke tutorial ini tanpa menginstal gateway ingress atau egress.

    Menginstal gateway keluar

    1. Buat namespace Kubernetes untuk gateway keluar:

      kubectl create namespace istio-egress
      
    2. Aktifkan namespace untuk injeksi. Langkah-langkahnya bergantung pada implementasi bidang kontrol Anda.

      Terkelola (TD)

      Terapkan label injeksi default ke namespace:

      kubectl label namespace istio-egress \
          istio.io/rev- istio-injection=enabled --overwrite
      

      Dikelola (Istiod)

      Direkomendasikan: Jalankan perintah berikut untuk menerapkan label injeksi default ke namespace:

        kubectl label namespace istio-egress \
            istio.io/rev- istio-injection=enabled --overwrite
      

      Jika Anda adalah pengguna lama dengan Managed Istiod control plane: Sebaiknya gunakan injeksi default, tetapi injeksi berbasis revisi didukung. Gunakan petunjuk berikut:

      1. Jalankan perintah berikut untuk menemukan saluran rilis yang tersedia:

        kubectl -n istio-system get controlplanerevision
        

        Outputnya mirip dengan hal berikut ini:

        NAME                AGE
        asm-managed-rapid   6d7h
        

        Dalam output, nilai di kolom NAME adalah label revisi yang sesuai dengan saluran rilis yang tersedia untuk versi Cloud Service Mesh.

      2. Terapkan label revisi ke namespace:

        kubectl label namespace istio-egress \
            istio-injection- istio.io/rev=REVISION_LABEL --overwrite
        

      Dalam cluster

      Direkomendasikan: Jalankan perintah berikut untuk menerapkan label injeksi default ke namespace:

        kubectl label namespace istio-egress \
            istio.io/rev- istio-injection=enabled --overwrite
      

      Sebaiknya gunakan penyisipan default, tetapi penyisipan berbasis revisi didukung: Gunakan petunjuk berikut:

      1. Gunakan perintah berikut untuk menemukan label revisi di istiod:

        kubectl get deploy -n istio-system -l app=istiod -o \
           jsonpath={.items[*].metadata.labels.'istio\.io\/rev'}'{"\n"}'
        
      2. Terapkan label revisi ke namespace. Dalam perintah berikut, REVISION_LABEL adalah nilai label revisi istiod yang Anda catat di langkah sebelumnya.

        kubectl label namespace istio-egress \
            istio-injection- istio.io/rev=REVISION_LABEL --overwrite
        
    3. Buat 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
      
    4. Download alat istioctl. Anda harus menggunakan versi 1.16.2-asm.2 atau yang lebih baru meskipun Anda menggunakan Cloud Service Mesh versi 1.15 atau yang lebih lama. Lihat Mendownload versi istioctl yang benar.

    5. Setelah mengekstrak arsip yang didownload, tetapkan variabel lingkungan untuk menyimpan jalur ke alat istioctl dan tambahkan ke skrip inisialisasi Anda:

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

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

      kubectl apply --recursive --filename egressgateway/
      
    8. Periksa apakah gateway keluar berjalan di node dalam kumpulan node gateway:

      kubectl get pods -n istio-egress -o wide
      
    9. Pod gateway keluar memiliki affinity untuk node di node pool gateway dan toleransi yang memungkinkan pod berjalan di node gateway yang terkena taint. Periksa afinitas node dan toleransi 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 jenis Cloud Service Mesh Anda, baik terkelola maupun dalam cluster:

    Menyiapkan mesh dan aplikasi pengujian

    1. Pastikan TLS bersama STRICT diaktifkan. Terapkan kebijakan PeerAuthentication default untuk mesh di 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 resource PeerAuthentication di namespace tertentu.

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

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

      kubectl label namespace team-x team=x
      kubectl label namespace team-y team=y
      
    4. Agar Cloud Service Mesh otomatis memasukkan sidecar proxy, Anda harus menetapkan label revisi bidang kontrol pada namespace beban kerja:

      kubectl label ns team-x istio.io/rev- istio-injection=enabled --overwrite
      kubectl label ns team-y istio.io/rev- istio-injection=enabled --overwrite
      
    5. Buat file YAML untuk digunakan dalam membuat 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. Pastikan aplikasi pengujian di-deploy ke node di pool default dan penampung sidecar proxy disuntikkan. Ulangi perintah 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 penampung berstatus Running. Satu penampung adalah aplikasi pengujian dan yang lainnya adalah file bantuan proxy.

      Pod berjalan di node dalam node pool default.

    8. Verifikasi bahwa permintaan HTTP tidak dapat dibuat dari penampung pengujian 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 sidecar dibuat karena aturan firewall global-deny-egress-all menolak koneksi upstream.

    Menggunakan resource Sidecar untuk membatasi cakupan konfigurasi proxy sidecar

    Anda dapat menggunakan resource Sidecar untuk membatasi cakupan pendengar keluar yang dikonfigurasi untuk proxy sidecar. Untuk mengurangi pembengkakan konfigurasi dan penggunaan memori, sebaiknya terapkan resource Sidecar default untuk setiap namespace.

    Proxy yang dijalankan Cloud Service Mesh di sidecar adalah Envoy. Dalam terminologi Envoy, cluster adalah grup endpoint upstream yang secara logis serupa dan digunakan sebagai tujuan untuk load balancing.

    1. Periksa cluster keluar yang dikonfigurasi di proxy sidecar 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 cluster Envoy dalam daftar, termasuk beberapa untuk gateway keluar.

    2. Membatasi konfigurasi proxy ke rute keluar yang telah ditetapkan secara eksplisit dengan entri layanan di namespace keluar dan team-x. 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 membatasi konfigurasi proxy untuk hanya menyertakan host eksternal yang telah ditambahkan secara eksplisit ke pendaftaran layanan mesh dengan menentukan entri layanan.

      Menyetel egress.hosts menentukan bahwa proxy sidecar hanya memilih rute dari namespace keluar yang tersedia dengan menggunakan atribut exportTo. Bagian 'team-x/*' mencakup rute apa pun yang telah dikonfigurasi secara lokal di namespace team-x.

    3. Lihat cluster keluar yang dikonfigurasi di proxy sidecar Envoy, dan bandingkan dengan daftar cluster yang dikonfigurasi sebelum menerapkan 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 untuk pod pengujian itu sendiri.

    Mengonfigurasi Cloud Service Mesh untuk merutekan 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 namespace keluar dan menangani traffic untuk host mana pun.

      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. Buat DestinationRule untuk gateway keluar dengan TLS bersama untuk autentikasi dan enkripsi. Gunakan satu aturan tujuan bersama untuk semua 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 mendaftarkan example.com secara eksplisit di pendaftaran layanan mesh untuk namespace team-x:

      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 merutekan traffic ke example.com melalui gateway keluar. Ada dua kondisi kecocokan: kondisi pertama mengarahkan traffic ke gateway keluar, dan kondisi kedua mengarahkan traffic dari gateway keluar ke host tujuan. Properti exportTo mengontrol namespace 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 melihat kode status 200 untuk keempat respons.

    7. Pastikan permintaan diarahkan melalui gateway keluar dengan memeriksa log akses proxy. Pertama, periksa log akses untuk proxy sidecar 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 Anda kirim, 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 Anda kirim, Anda akan melihat entri log akses gateway keluar yang mirip dengan 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 perutean yang berbeda untuk namespace kedua

    Konfigurasi perutean untuk host eksternal kedua guna mempelajari cara mengonfigurasi konektivitas eksternal yang berbeda 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 dan ekspor ke namespace team-x dan 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 merutekan traffic 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 akan 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 akan 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 sehingga hanya administrator jaringan yang dapat mengakses namespace istio-egress.

    1. Buat AuthorizationPolicy sehingga aplikasi di namespace team-x dapat terhubung ke example.com, tetapi tidak ke host eksternal lain saat mengirim permintaan menggunakan port 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. Verifikasi bahwa Anda dapat membuat permintaan 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
      

      Anda akan melihat respons 200 OK.

    3. Coba buat permintaan ke httpbin.org 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 -s -w " %{http_code}\n" \
          http://httpbin.org
      

      Permintaan gagal dengan pesan RBAC: access denied dan kode status 403 Forbidden. Anda mungkin perlu menunggu beberapa detik karena sering kali ada penundaan singkat sebelum kebijakan otorisasi diterapkan.

    4. Kebijakan otorisasi memberikan kontrol yang lengkap atas traffic yang diizinkan atau ditolak. Terapkan kebijakan otorisasi berikut untuk mengizinkan aplikasi pengujian di ruang nama team-y membuat permintaan ke httpbin.org dengan menggunakan satu jalur URL tertentu saat mengirim permintaan menggunakan port 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-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. Coba hubungkan ke httpbin.org dari aplikasi pengujian di 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
      

      Permintaan gagal dengan pesan RBAC: access denied dan kode status 403 Forbidden.

    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 cocok dengan pola dalam kebijakan otorisasi. Outputnya mirip dengan hal berikut ini:

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

    TLS origination di gateway keluar

    Anda dapat mengonfigurasi gateway keluar untuk upgrade (memulai) permintaan HTTP biasa ke TLS atau TLS bersama. Mengizinkan aplikasi membuat permintaan HTTP biasa memiliki beberapa keuntungan jika digunakan dengan TLS bersama Istio dan TLS origination. Untuk mengetahui informasi selengkapnya, lihat panduan praktik terbaik.

    TLS origination di gateway keluar

    1. Buat DestinationRule. The DestinationRule menentukan bahwa gateway memulai koneksi TLS ke 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:
              portLevelSettings:
              - port:
                  number: 443
                tls:
                  mode: SIMPLE
                  sni: example.com
      EOF
      
    2. Perbarui layanan virtual untuk example.com sehingga permintaan ke port 80 di gateway di-upgraded ke TLS di port 443 saat 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 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
      

      Seperti sebelumnya, permintaan berhasil dengan respons 200 OK.

    4. Periksa log gateway keluar untuk memverifikasi bahwa gateway merutekan permintaan ke host tujuan dengan memulai koneksi TLS:

      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 -
      

      Proxy sidecar mengirim permintaan ke gateway menggunakan port 80 dan TLS berasal dari port 443 untuk mengirim permintaan ke host tujuan.

    Penerusan koneksi HTTPS/TLS

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

    tls pass through

    1. Ubah konfigurasi Anda agar gateway keluar menggunakan TLS pass-through untuk koneksi ke port 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 subset kedua untuk port 443 di gateway. Subkumpulan baru ini tidak menggunakan TLS bersama. TLS mutual Istio tidak didukung untuk meneruskan koneksi TLS. Koneksi di port 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. Perbarui layanan virtual untuk example.com sehingga traffic TLS di 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. Perbarui layanan virtual untuk httpbin.org sehingga traffic TLS di 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 layanan gateway keluar. targetPort yang sesuai di pod gateway 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. Buat 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 respons.

    9. Lihat log gateway keluar lagi:

      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 telah diperlakukan sebagai traffic TCP dan diteruskan melalui gateway ke host tujuan, sehingga tidak ada informasi HTTP yang disertakan dalam log.

    Menggunakan Kubernetes NetworkPolicy sebagai kontrol tambahan

    Ada banyak skenario saat aplikasi dapat melewati proxy sidecar. Anda dapat menggunakan NetworkPolicy Kubernetes untuk menentukan lebih lanjut koneksi mana yang diizinkan untuk dibuat oleh workload. Setelah satu kebijakan jaringan diterapkan, semua koneksi yang tidak diizinkan secara khusus akan ditolak.

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

    1. Izinkan workload dan proxy yang di-deploy di namespace team-x untuk terhubung 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 membuat kueri 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 API dan layanan Google, 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 server metadata 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 # 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 workload dan proxy di namespace team-x untuk membuat koneksi 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 workload dan proxy di namespace team-x untuk membuat koneksi ke workload yang di-deploy oleh tim lain:

      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 sidecar tetap ada. Koneksi yang ada tidak ditutup saat Anda menerapkan kebijakan jaringan baru. Mulai ulang workload di namespace team-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. Saat pod dengan alamat IP alias native VPC membuat koneksi ke Google API menggunakan Akses Google Pribadi, traffic tidak pernah keluar dari jaringan Google.

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

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

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

      gcloud iam service-accounts create sa-test-app-team-x
      
    2. Izinkan akun layanan Kubernetes meniru identitas akun layanan 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
      
    3. Anotasikan 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}.iam.gserviceaccount.com
        name: test
        namespace: team-x
      EOF
      
    4. Pod aplikasi pengujian harus dapat mengakses server metadata Google (berjalan sebagai DaemonSet) untuk mendapatkan kredensial sementara guna memanggil Google API. Buat entri layanan untuk server metadata GKE:

      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. Pastikan 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 yang tercantum sebagai identitas 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 izin akun layanan untuk mencantumkan 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}.iam.gserviceaccount.com \
          --role=roles/storage.objectViewer
      
    9. Pastikan 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 pada 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 untuk tutorial.

    1. In the Google Cloud console, go to the Manage resources page.

      Go to Manage resources

    2. In the project list, select the project that you want to delete, and then click Delete.
    3. In the dialog, type the project ID, and then click Shut down to delete the project.

    Langkah berikutnya