Cloud Service Mesh berdasarkan contoh: mTLS


Di Cloud Service Mesh 1.5 dan yang lebih baru, TLS bersama otomatis (mTLS otomatis) diaktifkan secara default. Dengan mTLS otomatis, proxy sidecar sisi klien akan otomatis mendeteksi apakah server memiliki sidecar. Sidecar klien mengirim mTLS ke workload dengan sidecar dan mengirim teks biasa ke workload tanpa sidecar. Namun, layanan menerima traffic plaintext dan mTLS. Saat Anda menyuntikkan proxy file bantuan ke Pod, sebaiknya konfigurasi juga layanan Anda agar hanya menerima traffic mTLS.

Dengan Cloud Service Mesh, Anda dapat menerapkan mTLS, di luar kode aplikasi, dengan menerapkan satu file YAML. Cloud Service Mesh memberi Anda fleksibilitas untuk menerapkan kebijakan autentikasi ke seluruh mesh layanan, ke namespace, atau ke workload individual.

mTLS bersama

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

Men-deploy gateway masuk

  1. Tetapkan konteks saat ini untuk kubectl ke cluster:

    gcloud container clusters get-credentials CLUSTER_NAME  \
    --project=PROJECT_ID \
    --zone=CLUSTER_LOCATION 
    
  2. Buat namespace untuk gateway masuk Anda:

    kubectl create namespace asm-ingress
    
  3. Aktifkan namespace untuk injeksi. Langkah-langkahnya bergantung pada implementasi bidang kontrol Anda.

    Terkelola (TD)

    Terapkan label injeksi default ke namespace:

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

    Dikelola (Istiod)

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

      kubectl label namespace asm-ingress \
          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 asm-ingress \
          istio-injection- istio.io/rev=REVISION_LABEL --overwrite
      
  4. Deploy gateway contoh di repositori anthos-service-mesh-samples:

    kubectl apply -n asm-ingress \
    -f docs/shared/asm-ingress-gateway
    

    Output yang diharapkan:

    serviceaccount/asm-ingressgateway configured
    service/asm-ingressgateway configured
    deployment.apps/asm-ingressgateway configured
    gateway.networking.istio.io/asm-ingressgateway configured
    

Men-deploy contoh aplikasi Butik Online

  1. Jika belum, tetapkan konteks saat ini untuk kubectl ke cluster:

      gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  2. Buat namespace untuk aplikasi contoh:

      kubectl create namespace onlineboutique
    
  3. Beri label pada namespace onlineboutique untuk otomatis memasukkan proxy Envoy. Ikuti langkah-langkah untuk mengaktifkan injeksi sidecar otomatis.

  4. Deploy aplikasi contoh, VirtualService untuk frontend, dan akun layanan untuk workload. Untuk tutorial ini, Anda akan men-deploy Online Boutique, aplikasi demo microservice.

      kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/virtual-service.yaml
      kubectl apply \
      -n onlineboutique \
      -f docs/shared/online-boutique/service-accounts
    

Melihat layanan Anda

  1. Lihat pod di namespace onlineboutique:

    kubectl get pods -n onlineboutique
    

    Output yang diharapkan:

    NAME                                     READY   STATUS    RESTARTS   AGE
    adservice-85598d856b-m84m6               2/2     Running   0          2m7s
    cartservice-c77f6b866-m67vd              2/2     Running   0          2m8s
    checkoutservice-654c47f4b6-hqtqr         2/2     Running   0          2m10s
    currencyservice-59bc889674-jhk8z         2/2     Running   0          2m8s
    emailservice-5b9fff7cb8-8nqwz            2/2     Running   0          2m10s
    frontend-77b88cc7cb-mr4rp                2/2     Running   0          2m9s
    loadgenerator-6958f5bc8b-55q7w           2/2     Running   0          2m8s
    paymentservice-68dd9755bb-2jmb7          2/2     Running   0          2m9s
    productcatalogservice-84f95c95ff-c5kl6   2/2     Running   0          114s
    recommendationservice-64dc9dfbc8-xfs2t   2/2     Running   0          2m9s
    redis-cart-5b569cd47-cc2qd               2/2     Running   0          2m7s
    shippingservice-5488d5b6cb-lfhtt         2/2     Running   0          2m7s
    

    Semua pod untuk aplikasi Anda harus aktif dan berjalan, dengan 2/2 di kolom READY. Hal ini menunjukkan bahwa proxy file bantuan Envoy di pod telah berhasil disuntikkan. Jika 2/2 tidak muncul setelah beberapa menit, buka Panduan pemecahan masalah.

  2. Dapatkan IP eksternal, dan tetapkan ke variabel:

    kubectl get services -n asm-ingress
    export FRONTEND_IP=$(kubectl --namespace asm-ingress \
    get service --output jsonpath='{.items[0].status.loadBalancer.ingress[0].ip}' \
    )
    

    Anda akan melihat output yang mirip dengan berikut ini:

    NAME                   TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)                                      AGE
    asm-ingressgateway   LoadBalancer   10.19.247.233   35.239.7.64   80:31380/TCP,443:31390/TCP,31400:31400/TCP   27m
    
    
  3. Buka alamat EXTERNAL-IP di browser web Anda. Anda akan melihat toko Online Boutique di browser Anda.

    frontend butik online

Buat pod TestCurl

Buat pod TestCurl untuk mengirim traffic teks biasa untuk pengujian.

  apiVersion: v1
  kind: Pod
  metadata:
    name: testcurl
    namespace: default
    annotations:
      sidecar.istio.io/inject: "false"
  spec:
    containers:
    - name: curl
      image: curlimages/curl
      command: ["sleep", "600"]

Mengakses Online Boutique

  1. Tetapkan konteks saat ini untuk kubectl ke cluster tempat Anda men-deploy Butik Online:

    gcloud container clusters get-credentials CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  2. Mencantumkan layanan di namespace frontend:

    kubectl get services -n frontend
    

    Perhatikan bahwa frontend-external adalah LoadBalancer, dan memiliki alamat IP eksternal. Aplikasi contoh mencakup layanan yang merupakan load balancer sehingga dapat di-deploy di GKE tanpa Cloud Service Mesh.

  3. Buka aplikasi di browser Anda menggunakan alamat IP eksternal layanan frontend-external:

    http://FRONTEND_EXTERNAL_IP/
    
  4. Cloud Service Mesh memberi Anda kemampuan untuk men-deploy gateway ingress. Anda juga dapat mengakses Online Boutique menggunakan alamat IP eksternal gateway ingress. Dapatkan IP eksternal gateway. Ganti placeholder dengan informasi berikut:

    • GATEWAY_SERVICE_NAME : Nama layanan gateway ingress. Jika Anda men-deploy gateway contoh tanpa modifikasi, atau jika Anda men-deploy gateway ingress default, namanya adalah istio-ingressgateway.
    • GATEWAY_NAMESPACE: Namespace tempat Anda men-deploy gateway ingress. Jika Anda men-deploy gateway ingress default, namespace-nya adalah istio-system.
    kubectl get service GATEWAY_NAME -n GATEWAY_NAMESPACE
    
  5. Buka tab lain di browser Anda dan kunjungi aplikasi menggunakan alamat IP eksternal gateway ingress:

    http://INGRESS_GATEWAY_EXTERNAL_IP/
    
  6. Jalankan perintah berikut untuk curl layanan frontend dengan HTTP biasa dari Pod lain. Karena layanan berada di namespace yang berbeda, Anda perlu melakukan curl pada nama DNS layanan frontend.

    kubectl debug --image istio/base --target istio-proxy -it \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Permintaan Anda berhasil dengan status 200, karena secara default, traffic TLS dan plaintext diterima.

Mengaktifkan TLS bersama per namespace

Anda menerapkan mTLS dengan menerapkan kebijakan PeerAuthentication dengan kubectl.

  1. Simpan kebijakan autentikasi berikut sebagai mtls-namespace.yaml.

    cat <<EOF > mtls-namespace.yaml
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "namespace-policy"
    spec:
      mtls:
        mode: STRICT
    EOF
    

    Baris mode: STRICT dalam YAML mengonfigurasi layanan agar hanya menerima mTLS. Secara default, mode adalah PERMISSIVE, yang mengonfigurasi layanan untuk menerima teks biasa dan mTLS.

  2. Terapkan kebijakan autentikasi untuk mengonfigurasi semua layanan Online Boutique agar hanya menerima mTLS:

    for ns in ad cart checkout currency email frontend loadgenerator \
         payment product-catalog recommendation shipping; do
    kubectl apply -n $ns -f mtls-namespace.yaml
    done
    

    Output yang diharapkan:

    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created
    peerauthentication.security.istio.io/namespace-policy created

  3. Buka tab di browser Anda yang mengakses Butik Online menggunakan alamat IP eksternal layanan frontend-external:

    http://FRONTEND_EXTERNAL_IP/
    
  4. Muat ulang halaman. Browser menampilkan error berikut:

    situs tidak dapat dijangkau

    Memuat ulang halaman akan menyebabkan teks biasa dikirim ke layanan frontend. Karena STRICTkebijakan otentikasi, proxy sidecar memblokir permintaan ke layanan.

  5. Buka tab di browser Anda yang mengakses Butik Online menggunakan alamat IP eksternal istio-ingressgateway, lalu muat ulang halaman, yang ditampilkan dengan berhasil. Saat Anda mengakses Butik Online menggunakan gateway ingress, permintaan akan mengambil jalur berikut:

    mTLS bersama

    Alur autentikasi mTLS:

    1. Browser mengirimkan permintaan HTTP teks biasa ke server.
    2. Container proxy gateway ingress mencegat permintaan.
    3. Proxy gateway masuk melakukan handshake TLS dengan proxy sisi server (layanan frontend dalam contoh ini). Proses handshake ini mencakup pertukaran sertifikat. Sertifikat ini telah dimuat sebelumnya ke dalam container proxy oleh Cloud Service Mesh.
    4. Proxy gateway ingress melakukan pemeriksaan penamaan yang aman pada sertifikat server, yang memverifikasi bahwa identitas yang sah menjalankan server.
    5. Gateway masuk dan proxy server membuat koneksi TLS dua arah, dan proxy server meneruskan permintaan ke penampung aplikasi server (layanan frontend).
  6. Jalankan perintah berikut untuk curl layanan frontend dengan HTTP biasa dari Pod lain.

    kubectl exec testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Permintaan Anda gagal karena kami mengirim traffic teks biasa dari workload tanpa sidecar yang menerapkan kebijakan peerAuthenticationSTRICT.

Menemukan dan menghapus kebijakan autentikasi

  1. Untuk mengetahui daftar semua kebijakan PeerAuthentication di service mesh:

    kubectl get peerauthentication --all-namespaces
    

    Outputnya mirip dengan hal berikut ini:

    NAMESPACE         NAME               MODE     AGE
    ad                namespace-policy   STRICT   17m
    cart              namespace-policy   STRICT   17m
    checkout          namespace-policy   STRICT   17m
    currency          namespace-policy   STRICT   17m
    email             namespace-policy   STRICT   17m
    frontend          namespace-policy   STRICT   17m
    loadgenerator     namespace-policy   STRICT   17m
    payment           namespace-policy   STRICT   17m
    product-catalog   namespace-policy   STRICT   17m
    recommendation    namespace-policy   STRICT   17m
    shipping          namespace-policy   STRICT   17m
    
  2. Hapus kebijakan autentikasi dari semua namespace Online Boutique:

    for ns in ad cart checkout currency email frontend loadgenerator payment \
      product-catalog recommendation shipping; do
        kubectl delete peerauthentication -n $ns namespace-policy
    done;
    

    Output yang diharapkan:

    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    peerauthentication.security.istio.io "namespace-policy" deleted
    
  3. Akses Online Boutique menggunakan alamat IP eksternal layanan frontend-external, lalu muat ulang halaman. Halaman ditampilkan seperti yang diharapkan.

  4. Jalankan perintah berikut untuk curl layanan frontend dengan HTTP biasa dari Pod lain.

    kubectl debug --image istio/base --target istio-proxy -it \
      $(kubectl get pod -l app=productcatalogservice -n product-catalog -o jsonpath={.items..metadata.name}) \
      -n product-catalog -- \
      curl http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Permintaan Anda berhasil dengan status 200, karena secara default, traffic TLS dan plaintext diterima.

Jika Anda memuat ulang halaman di konsol Google Cloud yang menampilkan daftar Workloads, halaman tersebut kini menunjukkan bahwa status mTLS adalah Permissive.

Mengaktifkan TLS bersama per beban kerja

Untuk menyetel kebijakan PeerAuthentication untuk beban kerja tertentu, Anda harus mengonfigurasi bagian selector dan menentukan label yang cocok dengan beban kerja yang diinginkan. Namun, Cloud Service Mesh tidak dapat menggabungkan kebijakan tingkat workload untuk traffic mTLS keluar ke layanan. Anda perlu mengonfigurasi aturan tujuan untuk mengelola perilaku tersebut.

  1. Menerapkan kebijakan autentikasi ke workload tertentu. Perhatikan bagaimana kebijakan berikut menggunakan label dan pemilih untuk menargetkan frontend deployment tertentu.

    cat <<EOF | kubectl apply -n frontend -f -
    apiVersion: "security.istio.io/v1beta1"
    kind: "PeerAuthentication"
    metadata:
      name: "frontend"
      namespace: "frontend"
    spec:
      selector:
        matchLabels:
          app: frontend
      mtls:
        mode: STRICT
    EOF
    

    Output yang diharapkan:

    peerauthentication.security.istio.io/frontend created
  2. Konfigurasi aturan tujuan yang cocok.

    cat <<EOF | kubectl apply -n frontend -f -
    apiVersion: "networking.istio.io/v1alpha3"
    kind: "DestinationRule"
    metadata:
      name: "frontend"
    spec:
      host: "frontend.demo.svc.cluster.local"
      trafficPolicy:
        tls:
          mode: ISTIO_MUTUAL
    EOF
    

    Output yang diharapkan:

    destinationrule.networking.istio.io/frontend created
  3. Akses Online Boutique menggunakan alamat IP eksternal layanan frontend-external, lalu muat ulang halaman. Halaman tidak ditampilkan karena frontend service disetel ke mTLS STRICT, dan proxy sidecar memblokir permintaan.

  4. Jalankan perintah berikut untuk curl layanan frontend dengan HTTP biasa dari Pod lain.

    kubectl exec testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Permintaan Anda gagal karena kami mengirim traffic teks biasa dari workload tanpa sidecar yang menerapkan kebijakan peerAuthenticationSTRICT.

  5. Hapus kebijakan autentikasi:

    kubectl delete peerauthentication -n frontend frontend
    

    Output yang diharapkan:

    peerauthentication.security.istio.io "frontend" deleted
    
  6. Hapus aturan tujuan:

    kubectl delete destinationrule -n frontend frontend
    

    Output yang diharapkan:

    destinationrule.networking.istio.io "frontend" deleted
    

Menerapkan mTLS di seluruh mesh

Untuk mencegah semua layanan Anda di mesh menerima traffic teks biasa, tetapkan kebijakan PeerAuthentication di seluruh mesh dengan mode mTLS yang ditetapkan ke STRICT. Kebijakan PeerAuthentication di seluruh mesh tidak boleh memiliki pemilih dan harus diterapkan di namespace root, istio-system. Saat Anda men-deploy kebijakan, bidang kontrol akan otomatis menyediakan sertifikat TLS sehingga beban kerja dapat saling mengautentikasi.

  1. Menerapkan mTLS di seluruh mesh:

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

    Output yang diharapkan:

    peerauthentication.security.istio.io/mesh-wide created

  2. Akses Online Boutique menggunakan alamat IP eksternal layanan frontend-external, lalu muat ulang halaman. Halaman tidak ditampilkan.

  3. Jalankan perintah berikut untuk curl layanan frontend dengan HTTP biasa dari Pod lain.

    kubectl exec testcurl -n default -- curl \
      http://frontend.frontend.svc.cluster.local:80/ -o /dev/null -s -w '%{http_code}\n'
    

    Permintaan Anda gagal karena kami mengirim traffic teks biasa dari workload tanpa sidecar yang menerapkan kebijakan peerAuthenticationSTRICT.

  4. Hapus kebijakan mesh-wide:

    kubectl delete peerauthentication -n istio-system mesh-wide
    

    Output yang diharapkan:

    peerauthentication.security.istio.io "mesh-wide" deleted
    

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.

  • Jika Anda ingin mencegah tagihan tambahan, hapus cluster:

    gcloud container clusters delete  CLUSTER_NAME  \
        --project=PROJECT_ID \
        --zone=CLUSTER_LOCATION 
    
  • Jika Anda ingin mempertahankan cluster dan menghapus contoh Butik Online:

    1. Hapus namespace aplikasi:
      kubectl delete -f online-boutique/kubernetes-manifests/namespaces
    

    Output yang diharapkan:

    namespace "ad" deleted
    namespace "cart" deleted
    namespace "checkout" deleted
    namespace "currency" deleted
    namespace "email" deleted
    namespace "frontend" deleted
    namespace "loadgenerator" deleted
    namespace "payment" deleted
    namespace "product-catalog" deleted
    namespace "recommendation" deleted
    namespace "shipping" deleted
    
    1. Hapus entri layanan:
      kubectl delete -f online-boutique/istio-manifests/allow-egress-googleapis.yaml
    

    Output yang diharapkan:

    serviceentry.networking.istio.io "allow-egress-googleapis" deleted
    serviceentry.networking.istio.io "allow-egress-google-metadata" deleted
    

Langkah berikutnya