Menggunakan gateway keluar Anthos Service Mesh di cluster GKE: Tutorial


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

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 Anthos Service Mesh:
  • Instal Anthos Service Mesh dengan gateway keluar yang berjalan di kumpulan node 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 traffic keluar proxy sidecar untuk setiap namespace.
  • Mengonfigurasi kebijakan otorisasi untuk menerapkan aturan traffic keluar.
  • Konfigurasikan gateway keluar untuk mengupgrade permintaan HTTP biasa ke TLS (asal TLS).
  • Konfigurasi gateway keluar agar dapat meneruskan traffic TLS.
  • Siapkan kebijakan jaringan Kubernetes sebagai kontrol traffic keluar tambahan.
  • Mengonfigurasi akses langsung ke Google API menggunakan izin Akses Google dan Identity and Access Management (IAM) Pribadi.

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 Anda buat. 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 untuk digunakan selagi mengikuti tutorial:

    mkdir -p ~/WORKING_DIRECTORY
    cd ~/WORKING_DIRECTORY
    
  5. Buat skrip shell untuk melakukan inisialisasi lingkungan Anda untuk tutorial. Ganti dan edit variabel sesuai dengan proyek 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. Jadikan skrip dapat dieksekusi dan jalankan dengan perintah source untuk menginisialisasi lingkungan Anda:

    chmod +x ./init-egress-tutorial.sh
    source ./init-egress-tutorial.sh
    
  7. Tetapkan peran Identity and Access Management (IAM) yang diperlukan. Jika Anda adalah Project Owner, Anda memiliki semua izin yang diperlukan untuk menyelesaikan penginstalan. Jika Anda bukan Project Owner, minta administrator untuk memberi Anda peran IAM berikut. Dengan perintah berikut, ubah PROJECT_EMAIL_ADDRESS ke akun yang Anda gunakan untuk login ke Google Cloud.

    gcloud projects add-iam-policy-binding ${PROJECT_ID} \
        --member user:PROJECT_EMAIL_ADDRESS \
        --role=roles/editor \
        --role=roles/compute.admin \
        --role=roles/container.admin \
        --role=roles/resourcemanager.projectIamAdmin \
        --role=roles/iam.serviceAccountAdmin \
        --role=roles/iam.serviceAccountKeyAdmin \
        --role=roles/gkehub.admin \
        --role=roles/serviceusage.serviceUsageAdmin
    
  8. Aktifkan API yang diperlukan untuk tutorial:

    gcloud services enable \
        dns.googleapis.com \
        container.googleapis.com \
        compute.googleapis.com \
        monitoring.googleapis.com \
        logging.googleapis.com \
        cloudtrace.googleapis.com \
        meshca.googleapis.com \
        meshtelemetry.googleapis.com \
        meshconfig.googleapis.com \
        iamcredentials.googleapis.com \
        gkeconnect.googleapis.com \
        gkehub.googleapis.com \
        cloudresourcemanager.googleapis.com \
        stackdriver.googleapis.com
    

    Pengaktifan API dapat memerlukan waktu satu menit atau lebih. Saat API diaktifkan, Anda akan melihat output yang mirip dengan berikut ini:

    Operation "operations/acf.601db672-88e6-4f98-8ceb-aa3b5725533c" finished
    successfully.
    

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 rentang alamat IP sekunder yang telah ditetapkan sebelumnya untuk Pod dan layanan. Akses Google Pribadi diaktifkan sehingga aplikasi yang hanya memiliki alamat IP internal 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

Dengan Cloud NAT, beban kerja tanpa alamat IP eksternal dapat 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
    

Membuat akun layanan untuk setiap kumpulan node GKE

Buat dua akun layanan untuk digunakan oleh dua kumpulan node GKE. 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 serangkaian peran IAM minimal ke akun layanan aplikasi dan gateway. Peran ini diperlukan untuk logging, pemantauan, dan pengambilan 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 {i>firewall<i}

Pada langkah-langkah berikut, Anda menerapkan aturan firewall ke jaringan VPC sehingga, secara default, semua traffic keluar ditolak. Konektivitas khusus diperlukan agar cluster dapat berfungsi dan agar node gateway dapat menjangkau tujuan di luar VPC. Rangkaian minimal aturan firewall tertentu akan menggantikan aturan tolak semua default 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 yang 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 mencapai bidang kontrol Kubernetes:

    gcloud compute firewall-rules create allow-egress-to-api-server \
        --action ALLOW \
        --direction EGRESS \
        --rules tcp:443,tcp:10250 \
        --destination-ranges 10.5.0.0/28 \
        --network vpc-network \
        --priority 1000 \
        --description "Allow nodes to reach the Kubernetes API server."
    
  4. Anthos Service Mesh menggunakan webhook saat memasukkan proxy file bantuan ke dalam beban kerja. Izinkan server GKE API untuk memanggil webhook yang 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 \
        --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 traffic keluar antara pod dan layanan yang berjalan di cluster. Perlu diperhatikan bahwa GKE otomatis membuat aturan ingress yang sesuai.

    gcloud compute firewall-rules create allow-egress-pods-and-services \
        --action ALLOW \
        --direction EGRESS \
        --rules all \
        --destination-ranges 10.1.0.0/16,10.2.0.0/20 \
        --network vpc-network \
        --priority 1000 \
        --description "Allow pods and services on nodes to reach each other"
    
  6. Layanan bernama Calico menyediakan fungsi NetworkPolicy API untuk GKE. Izinkan konektivitas untuk Calico dalam subnet:

    gcloud compute firewall-rules create allow-egress-calico \
        --action ALLOW \
        --direction EGRESS \
        --rules tcp:5473 \
        --destination-ranges 10.0.0.0/24 \
        --network vpc-network \
        --priority 1000 \
        --description "Allow Calico Typha within the subnet"
    
  7. Port hanya baca kubelet diperlukan agar GKE dapat membaca metrik node. Izinkan akses ke subnet tersebut:

    gcloud compute firewall-rules create allow-egress-kubelet-readonly \
        --action ALLOW \
        --direction EGRESS \
        --rules tcp:10255 \
        --destination-ranges 10.0.0.0/24 \
        --network vpc-network \
        --priority 1000 \
        --description "Allow access to the kubelet read-only port within the subnet"
    
  8. 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 \
        --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)"
    
  9. Izinkan layanan health checker Google Cloud mengakses pod yang berjalan di cluster:

    gcloud compute firewall-rules create allow-ingress-gcp-health-checker \
        --action ALLOW \
        --direction INGRESS \
        --rules tcp:80,tcp:443 \
        --source-ranges 130.211.0.0/22,35.191.0.0/16,35.191.0.0/16,209.85.152.0/22,209.85.204.0/22 \
        --network vpc-network \
        --priority 1000 \
        --description "Allow workloads to respond to Google Cloud health checks"
    

Mengonfigurasi akses pribadi ke Google Cloud API

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 disalurkan dari IP eksternal, traffic dari node tidak pernah keluar dari jaringan Google saat menggunakan Akses Google Pribadi.

Buat zona DNS pribadi, data 'CNAME', dan 'A' agar node dan beban kerja 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 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 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 Anda dapat berubah. Jika itu terjadi, Anda harus memperbarui daftar jaringan yang diizinkan 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. Membuat cluster GKE pribadi:

    gcloud container clusters create cluster1 \
        --enable-ip-alias \
        --enable-private-nodes \
        --release-channel "regular" \
        --no-enable-basic-auth \
        --no-issue-client-certificate \
        --enable-master-authorized-networks \
        --master-authorized-networks ${SHELL_IP//\"}/32 \
        --master-ipv4-cidr 10.5.0.0/28 \
        --enable-network-policy \
        --service-account "sa-application-nodes@${PROJECT_ID}.iam.gserviceaccount.com" \
        --machine-type "e2-standard-4" \
        --num-nodes "4" \
        --network "vpc-network" \
        --subnetwork "subnet-gke" \
        --cluster-secondary-range-name "pods" \
        --services-secondary-range-name "services" \
        --workload-pool "${PROJECT_ID}.svc.id.goog" \
        --zone ${ZONE}
    

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

    Anthos Service Mesh memerlukan node cluster untuk menggunakan jenis mesin yang memiliki setidaknya 4 vCPU. Google merekomendasikan agar cluster berlangganan ke saluran rilis "reguler" untuk membantu memastikan bahwa node menjalankan versi Kubernetes yang didukung oleh Anthos Service Mesh. Untuk mengetahui informasi selengkapnya, lihat panduan penginstalan Anthos Service Mesh.

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

  3. Buat kumpulan node yang disebut gateway. Kumpulan node ini adalah tempat di-deploy gateway keluar. taint dedicated=gateway:NoSchedule ditambahkan ke setiap node di 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}.iam.gserviceaccount.com" \
        --num-nodes "1"
    

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

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

    gcloud container clusters get-credentials cluster1
    
  5. 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 Anthos Service Mesh

Tutorial ini menggunakan fitur opsional Anthos Service Mesh. Untuk mempelajari cara menginstal Anthos Service Mesh dengan skrip, baca panduan penginstalan dalam dokumentasi.

  1. Buat namespace untuk bidang kontrol mesh layanan dan gateway keluar yang akan di-deploy di:

    kubectl create ns istio-system
    kubectl create ns istio-egress
    
  2. Beri label pada namespace istio-egress, istio-system, dan kube-system:

    kubectl label ns istio-egress istio=egress istio-injection=disabled
    kubectl label ns istio-system istio=system
    kubectl label ns kube-system kube-system=true
    

    Label ini digunakan nanti untuk menerapkan Kubernetes NetworkPolicy. Label istio-injection=disabled mencegah peringatan palsu saat menjalankan analisis istioctl.

  3. Buat file manifes untuk menyesuaikan penginstalan Anthos Service Mesh menggunakan Istio OperatorAPI:

    cat << 'EOF' > ./asm-custom-install.yaml
    apiVersion: install.istio.io/v1alpha1
    kind: IstioOperator
    metadata:
      name: "egress-gateway"
    spec:
      meshConfig:
        accessLogFile: "/dev/stdout"
      components:
        egressGateways:
          - name: "istio-egressgateway"
            enabled: true
            namespace: "istio-egress"
            label:
              istio: "egress"
            k8s:
              tolerations:
              - key: "dedicated"
                operator: "Equal"
                value: "gateway"
              nodeSelector:
                cloud.google.com/gke-nodepool: "gateway"
    EOF
    

    File ini diberikan sebagai argumen untuk skrip penginstalan dan menentukan konfigurasi berikut:

    • Deployment gateway keluar yang berjalan di namespace istio-egress dengan toleransi dan nodeSelector sehingga hanya berjalan pada node gateway.
    • Akses logging ke 'stdout' untuk semua proxy file bantuan.
  4. Download skrip penginstalan:

    curl -O https://storage.googleapis.com/csm-artifacts/asm/install_asm
    
  5. Download tanda tangan SHA-256 file ke direktori kerja:

    curl -O https://storage.googleapis.com/csm-artifacts/asm/install_asm.sha256
    
  6. Verifikasi download dengan kedua file dalam direktori yang sama:

    sha256sum -c --ignore-missing install_asm.sha256
    

    Jika verifikasi berhasil, output-nya adalah:

    install_asm: OK
    

    Untuk kompatibilitas, file install_asm.sha256 menyertakan checksum dua kali untuk memungkinkan nama versi skrip apa pun diganti menjadi install_asm. Jika Anda mendapatkan error bahwa --ignore-missing tidak ada, jalankan kembali perintah sebelumnya tanpa flag --ignore-missing.

  7. Buat agar skrip dapat dieksekusi:

    chmod +x install_asm
    
  8. Instal Anthos Service Mesh dengan menjalankan skrip:

    ./install_asm \
        --mode install \
        --project_id ${PROJECT_ID} \
        --cluster_name cluster1 \
        --cluster_location ${ZONE} \
        --custom_overlay ./asm-custom-install.yaml \
        --output_dir ./ \
        --enable_all
    
  9. Setelah skrip selesai, tetapkan variabel lingkungan untuk menampung jalur ke alat istioctl, lalu tambahkan ke skrip inisialisasi Anda:

    ISTIOCTL=$(find "$(pwd -P)" -name istioctl)
    echo "ISTIOCTL=\"${ISTIOCTL}\"" >> ./init-egress-tutorial.sh
    

Memverifikasi penginstalan Anthos Service Mesh

  1. Pastikan komponen bidang kontrol Anthos Service Mesh berjalan di namespace istio-system:

    kubectl get pod -n istio-system
    

    Anda melihat pod istio-ingressgateway dan istiod-asm berjalan.

  2. Pastikan pod gateway keluar berjalan di namespace istio-egress dan di node dalam kumpulan node gateway:

    kubectl get pods -n istio-egress -o wide
    
  3. Pod gateway keluar memiliki nodeSelector untuk memilih node di kumpulan node gateway dan toleransi yang memungkinkan node tersebut berjalan di node gateway yang di-taint. Periksa nodeSelector dan toleransi untuk pod gateway keluar:

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

    Outputnya mirip dengan hal berikut ini:

    name                                   nodeSelector                                 tolerations
    istio-egressgateway-74687946f5-dg9mp   map[cloud.google.com/gke-nodepool:gateway]   map[key:dedicated operator:Equal value:gateway]
    

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 dalam namespace tertentu.

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

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

    kubectl label namespace team-x team=x
    kubectl label namespace team-y team=y
    
  4. Agar Anthos Service Mesh memasukkan file bantuan proxy secara otomatis, Anda harus menetapkan label revisi pada namespace beban kerja. Label revisi harus cocok dengan revisi bidang kontrol Anthos Service Mesh yang telah di-deploy ke cluster Anda. Cari label revisi pada pod istiod dan simpan dalam variabel lingkungan:

    REVISION_LABEL=$(kubectl get pod -n istio-system -l app=istiod \
      -o jsonpath='{.items[0].metadata.labels.istio\.io/rev}')
    
  5. Tetapkan label revisi pada namespace team-x dan team-y:

    kubectl label ns team-x istio.io/rev=${REVISION_LABEL}
    kubectl label ns team-y istio.io/rev=${REVISION_LABEL}
    
  6. 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
    
  7. Deploy aplikasi pengujian ke namespace team-x:

    kubectl -n team-x create -f ./test.yaml
    
  8. Pastikan aplikasi pengujian di-deploy ke node dalam kumpulan default dan penampung file bantuan proxy dimasukkan. Ulangi perintah berikut sampai 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 adalah Running. Satu penampung adalah aplikasi pengujian dan yang lainnya adalah file bantuan proxy.

    Pod berjalan pada node di kumpulan node default.

  9. Pastikan 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 File bantuan untuk membatasi cakupan konfigurasi proxy bantuan

Anda dapat menggunakan Resource file bantuan untuk membatasi cakupan pemroses keluar yang dikonfigurasi untuk proxy file bantuan. Untuk mengurangi penggelembungan konfigurasi dan penggunaan memori, praktik yang baik adalah menerapkan resource Sidecar default untuk setiap namespace.

Proxy yang dijalankan Anthos Service Mesh di file bantuan adalah Envoy. Dalam terminologi Envoy, cluster adalah grup endpoint upstream yang mirip secara logis yang digunakan sebagai tujuan untuk 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
    

    Terdapat sekitar 20 cluster Envoy dalam daftar, termasuk beberapa cluster untuk gateway keluar.

  2. Batasi konfigurasi proxy ke rute keluar yang telah ditentukan secara eksplisit dengan entri layanan di namespace istio-egress 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
    

    Menyetel mode kebijakan traffic keluar ke REGISTRY_ONLY akan membatasi konfigurasi proxy agar hanya menyertakan host eksternal yang telah ditambahkan secara eksplisit ke registry layanan mesh dengan menentukan entri layanan.

    Bagian 'istio-egress/*' menentukan bahwa proxy file bantuan memilih rute dari namespace istio-egress yang disediakan menggunakan atribut exportTo. Bagian 'team-x/*' mencakup semua rute yang telah dikonfigurasi secara lokal di namespace team-x.

  3. Lihat cluster keluar yang dikonfigurasi di proxy file bantuan 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
    

    Output-nya hanya mencakup beberapa cluster untuk gateway keluar dan satu cluster untuk pod pengujian itu sendiri.

Mengonfigurasi Anthos Service Mesh untuk mengarahkan traffic melalui gateway keluar

  1. Konfigurasi Gateway untuk traffic HTTP di port 80. Gateway memilih proxy istio-egressgateway yang di-deploy oleh penginstal ke namespace istio-egress. Konfigurasi Gateway diterapkan ke namespace istio-egress dan menangani traffic untuk semua host.

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.istio.io/v1beta1
    kind: Gateway
    metadata:
      name: egress-gateway
      namespace: istio-egress
    spec:
      selector:
        istio: egress
      servers:
      - port:
          number: 80
          name: https
          protocol: HTTPS
        hosts:
          - '*'
        tls:
          mode: ISTIO_MUTUAL
    EOF
    
  2. Buat DestinationRule untuk gateway keluar dengan TLS bersama untuk autentikasi dan enkripsi. Menggunakan 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:
          loadBalancer:
            simple: ROUND_ROBIN
          tls:
            mode: ISTIO_MUTUAL
    EOF
    
  3. Buat ServiceEntry di namespace istio-egress guna mendaftarkan example.com secara eksplisit di registry 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
    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 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
    

    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 permintaan diarahkan melalui gateway keluar dengan memeriksa log akses proxy. Pertama, periksa log akses untuk file bantuan proxy 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 seperti berikut:

    [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=egress \
        -o jsonpath="{.items[0].metadata.name}") istio-proxy
    

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

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

    Anda akan melihat:

    ✔ No validation issues found when analyzing namespace: istio-egress.
    
  6. Buat permintaan ke httpbin.org dari aplikasi uji coba 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. Ajukan juga permintaan ke httpbin.org dari aplikasi uji coba 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 Kubernetes RBAC sehingga hanya administrator jaringan yang dapat mengakses namespace istio-egress.

  1. Buat AuthorizationPolicy agar aplikasi di namespace team-x dapat terhubung ke example.com, tetapi tidak ke host eksternal lainnya saat mengirim permintaan menggunakan port 80. 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-x-to-example-com
      namespace: istio-egress
    spec:
      rules:
        - from:
          - source:
              namespaces:
              - 'team-x'
          to:
          - operation:
              hosts:
                - 'example.com'
          when:
          - key: destination.port
            values: ["8080"]
    EOF
    
  2. Pastikan bahwa Anda dapat membuat permintaan ke example.com dari aplikasi pengujian 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 akan melihat respons 200 OK.

  3. Coba buat permintaan ke httpbin.org dari aplikasi pengujian 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 -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 terkait traffic mana yang diizinkan atau ditolak. Terapkan kebijakan otorisasi berikut untuk mengizinkan aplikasi pengujian di namespace team-y membuat permintaan ke httpbin.org 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:
      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 403Forbidden.

  6. Sekarang, ajukan 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 jalurnya sesuai dengan pola di kebijakan otorisasi. Outputnya mirip dengan hal berikut ini:

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

Asal TLS di gateway keluar

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

Asal TLS di gateway keluar

  1. Membuat DestinationRule. The DestinationRule akan menentukan bahwa gateway tersebut berasal dari 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:
            loadBalancer:
              simple: ROUND_ROBIN
            portLevelSettings:
            - port:
                number: 443
              tls:
                mode: SIMPLE
                sni: example.com
    EOF
    
  2. Update layanan virtual untuk example.com agar permintaan ke port 80 di gateway 'diupgrade' ke TLS pada 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 200 OK respons.

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

    kubectl -n istio-egress logs -f $(kubectl -n istio-egress get pod -l istio=egress \
        -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 -
    

    Sidecar proxy mengirim permintaan ke gateway menggunakan port 80 dan TLS berasal pada port 443 untuk mengirim permintaan ke host tujuan.

Pass-through koneksi HTTPS/TLS

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

tls melewati

  1. Ubah konfigurasi Anda agar gateway keluar menggunakan pass-through TLS 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: egress
      servers:
      - port:
          number: 80
          name: https
          protocol: HTTPS
        hosts:
          - '*'
        tls:
          mode: ISTIO_MUTUAL
      - port:
          number: 443
          name: tls
          protocol: TLS
        hosts:
        - '*'
        tls:
          mode: PASSTHROUGH
    EOF
    
  2. Perbarui DestinationRule yang mengarah ke gateway keluar guna menambahkan subset kedua untuk port 443 di gateway tersebut. Subset baru ini tidak menggunakan TLS bersama. TLS bersama Istio tidak didukung untuk penerusan koneksi TLS. Koneksi pada 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:
          loadBalancer:
            simple: ROUND_ROBIN
          portLevelSettings:
          - port:
              number: 80
            tls:
              mode: ISTIO_MUTUAL
      - name: target-egress-gateway-TLS-passthrough
    EOF
    
  3. Update layanan virtual untuk example.com sehingga 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. Update layanan virtual untuk httpbin.org sehingga 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 jenis traffic apa pun yang dikirim ke port 443 layanan gateway keluar. targetPort yang sesuai pada 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:
      rules:
        - when:
          - key: destination.port
            values: ["8443"]
    EOF
    
  6. Jalankan istioctl analyze untuk memeriksa error konfigurasi:

    ${ISTIOCTL} analyze -n istio-egress
    

    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 akan melihat 200 respons.

  9. Lihat kembali log gateway keluar:

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

    Anda akan melihat entri log yang mirip seperti berikut:

    [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 NetworkPolicy Kubernetes sebagai kontrol tambahan

Ada banyak skenario ketika aplikasi dapat mengabaikan proxy file bantuan. Anda dapat menggunakan NetworkPolicy Kubernetes untuk menentukan tambahan beban kerja koneksi yang diizinkan untuk dibuat. Setelah kebijakan jaringan tunggal diterapkan, semua koneksi yang tidak secara khusus diizinkan akan ditolak.

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

  1. Izinkan beban kerja dan proxy yang di-deploy di namespace team-x agar 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:
              istio: system
          podSelector:
            matchLabels:
              istio: istiod
        - namespaceSelector:
            matchLabels:
              istio: egress
          podSelector:
            matchLabels:
              istio: egress
    EOF
    
  2. Izinkan beban kerja 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:
              kube-system: "true"
        ports:
        - port: 53
          protocol: UDP
        - port: 53
          protocol: TCP
    EOF
    
  3. Izinkan beban kerja dan proxy untuk terhubung ke IP yang melayani API dan layanan Google, termasuk Mesh CA:

    cat <<EOF | kubectl apply -f -
    apiVersion: networking.k8s.io/v1
    kind: NetworkPolicy
    metadata:
      name: allow-egress-to-google-apis
      namespace: team-x
    spec:
      podSelector: {}
      policyTypes:
        - Egress
      egress:
      - to:
        - ipBlock:
            cidr: 199.36.153.4/30
        - ipBlock:
            cidr: 199.36.153.8/30
    EOF
    
  4. Izinkan beban kerja dan proxy untuk 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
        ports:
        - protocol: TCP
          port: 988
    EOF
    
  5. Opsional: Izinkan beban kerja dan proxy di namespace team-x untuk terhubung 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 terhubung 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:
              team: 'y'
    EOF
    
  7. Koneksi antara proxy file bantuan tetap ada. Koneksi yang ada tidak akan ditutup saat Anda menerapkan kebijakan jaringan baru. Mulai ulang beban kerja di namespace tim-x untuk memastikan koneksi yang ada ditutup:

    kubectl -n team-x rollout restart deployment
    
  8. Pastikan 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 akan 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. Dengan konfigurasi ini, pod dapat langsung menjangkau Google API tanpa mengirimkan traffic melalui gateway keluar. Anda dapat mengontrol API mana yang tersedia untuk akun layanan Kubernetes tertentu (dan namespace) menggunakan Workload Identity 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 dikonfigurasikan untuk menggunakan Workload Identity, sehingga akun layanan Kubernetes dapat 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 untuk 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
    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
    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 berfungsi 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 aktif dan satu-satunya.

  7. Buat file pengujian di bucket Cloud Storage:

    echo "Hello, World!" > /tmp/hello
    gsutil mb gs://${PROJECT_ID}-bucket
    gsutil cp /tmp/hello gs://${PROJECT_ID}-bucket/
    
  8. Berikan izin pada akun layanan untuk mencantumkan dan melihat file di bucket:

    gsutil iam ch \
    serviceAccount:sa-test-app-team-x@${PROJECT_ID}.iam.gserviceaccount.com:objectViewer \
        gs://${PROJECT_ID}-bucket/
    
  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 \
    -- gsutil 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. 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