Mengamankan dan mengenkripsi komunikasi antara cluster GKE Enterprise menggunakan Anthos Service Mesh

Last reviewed 2021-04-30 UTC

Tutorial ini menjelaskan cara menggunakan gateway keluar dan masuk Anthos Service Mesh untuk membantu mengamankan lalu lintas antar cluster dengan menggunakan mutual Keamanan Lapisan Transportasi (mTLS). Tutorial ini ditujukan untuk administrator cluster Kubernetes yang bertanggung jawab atas aspek jaringan, keamanan, dan platform. Kontrol yang dijelaskan di sini mungkin berguna khususnya bagi organisasi yang memiliki persyaratan keamanan yang tinggi atau untuk memenuhi prasyarat peraturan. Tutorial ini dilengkapi dengan panduan konsep pelengkap.

Tutorial ini berarti bahwa Anda sudah memahami Kubernetes dan Anthos Service Mesh.

Tujuan

  • Menerapkan Terraform untuk memasang infrastruktur:
    • Membuat jaringan VPC kustom dengan dua subnet pribadi.
    • Membuat dua cluster Kubernetes dengan Anthos Service Mesh yang telah diaktifkan:
    • Mendaftarkan cluster pada GKE Hub.
  • Menerapkan klien MySQL di cluster GKE.
  • Menerpkan server MySQL di cluster kOps.
  • Konfigurasikan gateway keluar dan masuk untuk mengekspos server dengan menggunakan mTLS.
  • Uji akses ke server MySQL menggunakan klien MySQL yang berjalan di berbagai cluster atau VPC.

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 tugas yang dijelaskan dalam dokumen ini, Anda dapat menghindari penagihan berkelanjutan dengan menghapus resource yang Anda buat. Untuk mengetahui informasi selengkapnya, lihat Pembersihan.

Sebelum memulai

Untuk tutorial ini, Anda memerlukan proyek Google Cloud. Anda dapat membuat yang baru, atau memilih proyek yang sudah Anda buat

  1. Di konsol Google Cloud, buka halaman Pemilih project.

    Buka pemilih project

  2. Pilih atau buat project Google Cloud.

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

  4. Di konsol Google Cloud, buka Cloud Shell.

    Buka Cloud Shell

    Di bagian bawah Google Cloud Console, sesi Cloud Shell akan terbuka dan menampilkan perintah command line. Cloud Shell adalah lingkungan shell dengan Google Cloud CLI yang sudah terinstal, termasuk Google Cloud CLI Perlu waktu beberapa detik untuk sesi dimulai.

  5. Di Cloud Shell, pastikan mengerjakan project yang Anda buat atau pilih:
    export PROJECT_ID=PROJECT_ID
    gcloud config set project ${PROJECT_ID}
    

    Ganti PROJECT_ID dengan project ID Anda.

  6. Buat variabel lingkungan untuk alamat email yang Anda gunakan untuk Google Cloud:
    export GOOGLE_CLOUD_EMAIL_ADDRESS=GOOGLE_CLOUD_EMAIL_ADDRESS
    

    Ganti GOOGLE_CLOUD_EMAIL_ADDRESS dengan alamat email yang Anda gunakan pada Google Cloud.

  7. Tetapkan wilayah dan zona untuk sumber daya komputasi Anda:
    export REGION=us-central1
    export ZONE=us-central1-b
    gcloud config set compute/region ${REGION}
    gcloud config set compute/zone ${ZONE}
    

    Tutorial ini menggunakan us-central1 untuk region dan us-central1-b untuk zona. Anda dapat men-deploy ke region pilihan Anda.

  8. Tetapkan peran Identity and Access Management (IAM) yang diperlukan. Jika Anda adalah Pemilik Project, Anda memiliki semua izin yang diperlukan untuk menyelesaikan pemasangan. Jika tidak, mintalah administrator Anda untuk memberikan Peran Identity and Access Management (IAM) dengan menjalankan perintah berikut di Cloud Shell:
    ROLES=(
    'roles/container.admin' \
    'roles/gkehub.admin' \
    'roles/iam.serviceAccountAdmin' \
    'roles/iam.serviceAccountKeyAdmin' \
    'roles/resourcemanager.projectIamAdmin' \
    'roles/compute.securityAdmin' \
    'roles/compute.instanceAdmin' \
    'roles/storage.admin' \
    'roles/serviceusage.serviceUsageAdmin'
    )
    for role in "${ROLES[@]}"
    do
     gcloud projects add-iam-policy-binding ${PROJECT_ID} \
      --member "user:${GOOGLE_CLOUD_EMAIL_ADDRESS}" \
      --role="$role"
    done
    
  9. Aktifkan API yang diperlukan untuk tutorial:
    gcloud services enable \
        anthos.googleapis.com \
        anthosgke.googleapis.com \
        anthosaudit.googleapis.com \
        compute.googleapis.com \
        container.googleapis.com \
        cloudresourcemanager.googleapis.com \
        serviceusage.googleapis.com \
        stackdriver.googleapis.com \
        monitoring.googleapis.com \
        logging.googleapis.com \
        cloudtrace.googleapis.com \
        meshca.googleapis.com \
        meshconfig.googleapis.com \
        iamcredentials.googleapis.com \
        gkeconnect.googleapis.com \
        gkehub.googleapis.com
    

Mempersiapkan lingkungan Andaa

  1. Di Cloud Shell, clone repositori berikut:

    git clone https://github.com/GoogleCloudPlatform/anthos-service-mesh-samples
    cd anthos-service-mesh-samples/docs/mtls-egress-ingress
    
  2. Memperbarui Terraform untuk lingkungan Anda. Secara default, konsol Google Cloud dilengkapi dengan Terraform 0.12. Tutorial ini mengasumsikan bahwa Anda telah menginstal Terraform 0.13.5 atau yang lebih baru. Anda dapat menggunakan Terraform versi lain untuk sementara dengan menjalankan perintah berikut:

    mkdir ~/bin
    curl https://releases.hashicorp.com/terraform/0.13.5/terraform_0.13.5_linux_amd64.zip -o ~/bin/terraform.zip
    unzip ~/bin/terraform.zip -d ~/bin/
    
  3. Buka subfolder terraform dan lakukan inisialisasi Terraform:

    cd terraform/
    ~/bin/terraform init
    
  4. Buat file terraform.tfvars (berdasarkan variabel lingkungan yang Anda buat sebelumnya):

    cat << EOF > terraform.tfvars
    project_id = "${PROJECT_ID}"
    region = "${REGION}"
    zones = ["${ZONE}"]
    EOF
    

    Pada langkah berikutnya, Anda buat infrastruktur awal. Untuk melakukannya, Anda akan membuat dan menerapkan rencana eksekusi Terraform untuk konfigurasi ini. Skrip dan modul dalam rencana ini membuat hal berikut:

    • Jaringan VPC khusus dengan dua subnet pribadi
    • Dua cluster Kubernetes dengan Anthos Service Mesh diaktifkan
    • Satu cluster GKE
    • Satu cluster kOps yang berjalan di jaringan VPC khusus

    Rencana pelaksanaan ini juga mendaftarkan cluster ke GKE Hub.

  5. Jalankan rencana pelaksanaan:

    ~/bin/terraform plan -out mtls-terraform-plan
    ~/bin/terraform apply "mtls-terraform-plan"
    

    Outputnya mirip dengan yang berikut ini:

    Apply complete! Resources: 27 added, 0 changed, 0 destroyed.
    Outputs:
    server_token = <sensitive>
    

    Bagian <sensitive> adalah variabel output Terraform yang tidak ditampilkan di konsol, tetapi dapat dikueri misalnya, ~/bin/terraform output server_token.

  6. Dapatkan file kubeconfig cluster server dari direktori terraform. Kemudian, gabungkan dengan file konfigurasi client-cluster:

    cd ..
    export KUBECONFIG=client-server-kubeconfig
    cp ./terraform/server-kubeconfig $KUBECONFIG
    gcloud container clusters get-credentials client-cluster --zone ${ZONE} --project ${PROJECT_ID}
    

    File client-server-kubeconfig kini menyimpan konfigurasi untuk kedua cluster tersebut, yang dapat Anda verifikasi dengan menjalankan perintah berikut:

    kubectl config view -ojson | jq -r '.clusters[].name'
    

    Outputnya adalah sebagai berikut:

    gke_PROJECT_ID_us-central1-c_client-cluster
    server-cluster.k8s.local
    
  7. Dapatkan konteks kedua klaster tersebut untuk digunakan nanti:

    export CLIENT_CLUSTER=$(kubectl config view -ojson | jq -r '.clusters[].name' | grep client)
    export SERVER_CLUSTER=$(kubectl config view -ojson | jq -r '.clusters[].name' | grep server)
    echo -e "${CLIENT_CLUSTER}\n${SERVER_CLUSTER}"
    

    Outputnya (lagi) adalah sebagai berikut:

    gke_PROJECT_ID_us-central1-c_client-cluster
    server-cluster.k8s.local
    

    Kini Anda dapat menggunakan nama cluster ini sebagai konteks untuk perintah kubectllebih lanjut.

  8. Referensikan cluster klien:

    kubectl --context ${CLIENT_CLUSTER} get pods -n istio-system
    
  9. Referensikan cluster server:

    kubectl --context ${SERVER_CLUSTER} get pods -n istio-system
    

Mengonfigurasi sisi klien

Seperti disebutkan dalam panduan konsep, sisi klien mengharuskan Anda mengonfigurasi gateway keluar di Anthos Service Mesh.

Di bagian ini, Anda akan mengonfigurasi elemen Anthos Service Mesh untuk mengidentifikasi traffic eksternal berdasarkan asalnya dan menggunakan sertifikat kustom untuk mengenkripsi komunikasi. Selain itu, Anda hanya perlu merutekan traffic tersebut ke tujuannya (DB MySQL dalam sebuah container). Biasanya, Anda melakukannya dengan menggunakan layanan di Kubernetes. Dalam hal ini, Anda perlu menangkap traffic tersebut di dalam komunikasi mesh. Untuk menangkap traffic, gunakan elemen Istio untuk membuat definisi khusus layanan. Anda menentukan elemen berikut:

  • Gateway keluar
  • Entri layanan
  • Layanan Virtuall
  • Sertifikat TLS (sebagai rahasia)
  • Aturan tujuan
  1. Di Cloud Shell, dapatkan alamat IP gateway masuk di sisi server dengan membuat kueri alamat IP load balancer dari layanan istio-ingressgateway menggunakan konteks sisi server ($SERVER_CLUSTER, yang telah Anda buat sebelumnya):

    INGRESS_HOST=$(kubectl -n istio-system --context ${SERVER_CLUSTER} get service istio-ingressgateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}')
    

    Karena INGRESS_HOST hanyalah bagian alamat IP dari host, Anda harus membuat nama domain yang sepenuhnya memenuhi syarat (FQDN). Langkah ini diperlukan karena, agar dapat berfungsi dengan benar, sertifikat memerlukan nama domain.

    Dalam tutorial ini, Anda akan menggunakan layanan DNS karakter pengganti nip.io untuk membuat FQDN bagi alamat IP masuk. Layanan ini memungkinkan Anda membuat FQDN tanpa harus memiliki domain.

  2. Simpan URL layanan FQDN dalam variabel lingkungan:

    export SERVICE_URL="${INGRESS_HOST}.nip.io"
    

    Setelah SERVICE_URL ditetapkan sebagai FQDN, Anda dapat mulai menentukan bagian Istio dari cluster klien.

Membuat gateway keluarr

Anda memulai dengan membuat gateway keluar untuk memproses traffic yang ditujukan untuk layanan eksternal.

Gateway keluar yang memproses traffic yang ditujukan untuk layanan eksternal.

  1. Di Cloud Shell, buat file YAML berikut dan beri nama client-egress-gateway.yaml:

    cat <<EOF > client-egress-gateway.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
     name: istio-egressgateway-mysql
    spec:
     selector:
       istio: egressgateway
     servers:
     - port:
         number: 15443
         name: tls
         protocol: TLS
       hosts:
       - $SERVICE_URL
       tls:
         mode: ISTIO_MUTUAL
    EOF
    
  2. Terapkan file YAML sebelumnya ke cluster klien:

    kubectl --context ${CLIENT_CLUSTER} apply -f client-egress-gateway.yaml
    

    Perhatikan portnya. Anda telah menggunakan port default di sini untuk tombol server keluar, yaitu 15443. Jika ingin menggunakan port lain, Anda perlu mengedit objek service gateway keluar untuk menambahkan port khusus.

    Tombol hosts menentukan endpoint, tempat traffic harus diarahkan.

Menentukan entri layanan

Langkah berikutnya adalah memberi tahu mesh layanan tentang layanan eksternal. Istio memiliki registry sendiri yang menyimpan endpoint layanan untuk mesh. Jika Istio diinstal di atas Kubernetes, layanan yang ditentukan dalam cluster akan ditambahkan ke registry Istio secara otomatis. Dengan definisi entri layanan, Anda dapat menambahkan endpoint baru ke registry Istio seperti yang ditunjukkan dalam diagram berikut.

Menambahkan endpoint ke registry Istio menggunakan definisi entri layanan.

  1. Di Cloud Shell, buat file YAML berikut dan beri nama client-service-entry.yaml:

    cat <<EOF > client-service-entry.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: ServiceEntry
    metadata:
     name: mysql-external
    spec:
     hosts:
       - $SERVICE_URL
     location: MESH_EXTERNAL
     ports:
       - number: 3306
         name: tcp
         protocol: TCP
       - number: 13306
         name: tls
         protocol: TLS
     resolution: DNS
     endpoints:
       - address: $SERVICE_URL
         ports:
           tls: 13306
    EOF
    
  2. Terapkan file YAML sebelumnya ke cluster klien:

    kubectl --context ${CLIENT_CLUSTER} apply -f client-service-entry.yaml
    

    Definisi layanan klien dalam file YAML ini memberi tahu layanan jenis traffic yang diharapkan (MySQL L4 - lapisan jaringan empat, menggunakan port 3306). Anda juga mendefinisikan bahwa komunikasi akan berupa "mesh eksternal". Di bagian endpoint, Anda menentukan bahwa alur harus mengarah ke alamat FQDN $SERVICE_URL yang telah Anda tetapkan sebelumnya dan yang dipetakan ke gateway masuk di cluster server (kOps).

Menentukan layanan virtual

Layanan virtual adalah seperangkat aturan perutean traffic yang akan diterapkan saat host ditangani. Setiap aturan perutean menentukan kriteria yang cocok untuk lalu lintas protokol tertentu. Jika traffic cocok, traffic akan dikirim ke layanan tujuan bernama (atau subset atau versinya) yang ditentukan dalam registry. Untuk mengetahui informasi selengkapnya, baca dokumentasi Terraform.

Menentukan layanan virtual yang memberi tahu Istio cara menerapkan perutean untuk traffic yang mencapai layanan eksternal.

Definisi layanan virtual memberi tahu Istio cara menerapkan perutean untuk traffic yang mencapai layanan eksternal. Dengan definisi berikut, Anda memberi tahu mesh untuk merutekan traffic dari klien ke gateway keluar pada port 15443. Dari gateway keluar, selanjutnya Anda mengarahkan traffic ke $SERVICE_URL host di port 13306 (tempat gateway masuk sisi server Anda memproses).

  1. Buat file YAML berikut dan beri nama client-virtual-service.yaml:

    cat <<EOF > client-virtual-service.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
     name: direct-mysql-through-egress-gateway
    spec:
     hosts:
       - $SERVICE_URL
     gateways:
       - istio-egressgateway-mysql
       - mesh
     tcp:
       - match:
           - gateways:
               - mesh
             port: 3306
         route:
           - destination:
               host: istio-egressgateway.istio-system.svc.cluster.local
               subset: mysql
               port:
                 number: 15443
             weight: 100
       - match:
           - gateways:
               - istio-egressgateway-mysql
             port: 15443
         route:
           - destination:
               host: $SERVICE_URL
               port:
                 number: 13306
             weight: 100
    EOF
    
  2. Terapkan definisi YAML ke cluster klien:

    kubectl --context ${CLIENT_CLUSTER} apply -f client-virtual-service.yaml
    

    Anda dapat menentukan gateway mana yang harus diterapkan konfigurasi dengan mengedit tombol gateways di file YAML.

    Bagian penting dalam definisi ini adalah penggunaan kata yang dicadangkan mesh, yang menyiratkan semua file bantuan di mesh. Menurut dokumentasi Istio, jika kolom ini dihilangkan, gateway default (mesh) akan digunakan, dengan menerapkan aturan pada semua file bantuan di mesh. Jika Anda memberikan daftar nama gateway, aturan hanya berlaku untuk gateway tersebut. Untuk menerapkan aturan ke gateway dan file bantuan, tetapkan mesh sebagai salah satu nama gateway.

Di bagian berikutnya, Anda akan menentukan cara menangani traffic yang keluar dari proxy produksi klien, match.gateways.mesh. Anda juga menentukan cara mengalihkan traffic dari traffic keluar ke layanan eksternal menggunakan tombol match.gateways.istio-egressgateway-mysql.

Tentukan aturan tujuan (dari klien ke gateway keluar)

Setelah menentukan cara mengarahkan traffic ke layanan eksternal, Anda perlu menentukan kebijakan traffic yang harus diterapkan. Layanan virtual yang baru saja Anda tetapkan menangani dua kasus {i>routing<i} sekaligus. Satu project menangani traffic dari proxy file bantuan ke gateway keluar, dan satunya lagi menangani traffic dari gateway keluar ke layanan eksternal.

Untuk mencocokkan kasus ini dengan aturan tujuan, Anda memerlukan dua aturan yang terpisah. Diagram berikut menunjukkan aturan pertama, yang menangani traffic dari proxy ke gateway keluar. Dalam definisi ini, Anda memberi tahu Anthos Service Mesh agar menggunakan sertifikat defaultnya untuk komunikasi mTLS.

Aturan tujuan yang menentukan cara menangani traffic dari proxy file bantuan ke gateway keluar.

  1. Di Cloud Shell, buat file YAML berikut dan beri nama client-destination-rule-to-egress-gateway.yaml:

    cat <<EOF > client-destination-rule-to-egress-gateway.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
      name: egressgateway-for-mysql
    spec:
      host: istio-egressgateway.istio-system.svc.cluster.local
      subsets:
        - name: mysql
          trafficPolicy:
            loadBalancer:
              simple: ROUND_ROBIN
            portLevelSettings:
              - port:
                  number: 15443
                tls:
                  mode: ISTIO_MUTUAL
                  sni: $SERVICE_URL
    EOF
    
  2. Terapkan definisi YAML sebelumnya ke cluster klien:

    kubectl --context ${CLIENT_CLUSTER} apply -f client-destination-rule-to-egress-gateway.yaml
    

    Dalam file YAML sebelumnya, Anda menggunakan tombol hosts untuk menentukan cara merutekan traffic dari proxy klien ke gateway keluar. Selain itu, Anda telah mengonfigurasi mesh untuk menggunakan ISTIO_MUTUAL pada port 15443, yang merupakan salah satu port yang otomatis terbuka di gateway keluar.

Buat aturan tujuan (dari gateway keluar ke layanan eksternal)

Diagram berikut menunjukkan aturan tujuan kedua, yang memberi tahu mesh cara menangani traffic dari gateway keluar ke layanan eksternal.

Aturan tujuan kedua yang menentukan cara menangani traffic dari gateway keluar ke layanan eksternal.

Anda harus memberi tahu mesh agar menggunakan sertifikat yang dimasukkan untuk komunikasi TLS dengan layanan eksternal.

  1. Di Cloud Shell, dari direktori anthos-service-mesh-samples/docs/mtls-egress-ingress, buat sertifikat:

     ./create-keys.sh
    

    Pastikan untuk memberikan sandi saat skrip memintanya.

  2. Salin file yang dihasilkan ke direktori saat ini:

    cp ./certs/2_intermediate/certs/ca-chain.cert.pem ca-chain.cert.pem
    cp ./certs/4_client/private/$SERVICE_URL.key.pem client-$SERVICE_URL.key.pem
    cp ./certs/4_client/certs/$SERVICE_URL.cert.pem client-$SERVICE_URL.cert.pem
    
  3. Buat rahasia Kubernetes yang menyimpan sertifikat agar dapat direferensikan nanti di gateway:

     kubectl --context ${CLIENT_CLUSTER} create secret -n istio-system \
      generic client-credential \
      --from-file=tls.key=client-$SERVICE_URL.key.pem \
      --from-file=tls.crt=client-$SERVICE_URL.cert.pem \
      --from-file=ca.crt=ca-chain.cert.pem
    

    Perintah sebelumnya menambahkan file sertifikat berikut ke secret:

    client-$SERVICE_URL.key.pem
    client-$SERVICE_URL.cert.pem
    ca-chain.cert.pem
    

    Praktik terbaik saat ini untuk mendistribusikan sertifikat diikuti di sini dengan menggunakan layanan penemuan rahasia (SDS), bukan pemasangan file. Praktik ini akan menghindari proses mulai ulang pod saat menambahkan sertifikat baru. Mulai dari Istio 1.8/1.9, dengan teknik ini, Anda tidak lagi memerlukan hak akses baca (RBAC) untuk rahasia gateway.

  4. Tambahkan sertifikat ke DestinationRule dan beri nama client-destination-rule-to-external-service.yaml:

    cat <<EOF > client-destination-rule-to-external-service.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: DestinationRule
    metadata:
     name: originate-mtls-for-mysql
    spec:
     host: $SERVICE_URL
     trafficPolicy:
       loadBalancer:
         simple: ROUND_ROBIN
       portLevelSettings:
       - port:
           number: 13306
         tls:
           mode: MUTUAL
           credentialName: client-credential
           sni: $SERVICE_URL
    EOF
    
  5. Terapkan definisi YAML sebelumnya ke cluster klien:

    kubectl --context ${CLIENT_CLUSTER} apply -f client-destination-rule-to-external-service.yaml
    

    Aturan ini hanya berfungsi jika Anda telah membuat rahasia terlebih dahulu. Rahasia ini memastikan bahwa sertifikat digunakan untuk enkripsi mTLS dari gateway keluar ke endpoint eksternal.

Setelah menyelesaikan langkah-langkah ini, penyiapan sisi klien Anda sudah selesai dan akan terlihat seperti diagram berikut.

Penyiapan sisi klien akhir.

Mengonfigurasi sisi server

Seperti yang telah dibahas dalam panduan konsep, untuk sisi server, Anda harus mengonfigurasi gateway ingress di Anthos Service Mesh. Sebelum Anda membuat file yang diperlukan, sebaiknya tinjau komponen mana yang diperlukan untuk mewujudkan bagian server dari solusi.

Pada dasarnya, Anda ingin mengidentifikasi traffic masuk berdasarkan asal dan sertifikatnya. Anda juga ingin secara khusus merutekan traffic tersebut ke tujuannya: DB MySQL Anda dalam sebuah container. Biasanya Anda menggunakan layanan di Kubernetes untuk melakukannya, tetapi dalam contoh ini, Anda mengidentifikasi traffic masuk di dalam komunikasi mesh, sehingga Anda memerlukan definisi khusus layanan yang mencakup hal-hal berikut:

  • Sertifikat TLS (sebagai rahasia)
  • Gateway masuk
  • Layanan Virtuall

Membuat rahasia untuk gateway masuk

Seperti yang Anda lakukan untuk gateway keluar, Anda memerlukan sertifikat yang sama guna mengamankan komunikasi untuk gateway masuk. Untuk melakukannya, simpan sertifikat di rahasia dan tentukan rahasia ini dengan objek gateway masuk Anda.

  1. Di Cloud Shell, salin file yang dihasilkan ke lokasi tempat Anda menjalankan perintah berikutnya:

    cp ./certs/3_application/private/$SERVICE_URL.key.pem server-$SERVICE_URL.key.pem
    cp ./certs/3_application/certs/$SERVICE_URL.cert.pem server-$SERVICE_URL.cert.pem
    
  2. Buat rahasia server:

    kubectl --context ${SERVER_CLUSTER} create secret -n istio-system \
        generic mysql-credential \
        --from-file=tls.key=server-$SERVICE_URL.key.pem \
        --from-file=tls.crt=server-$SERVICE_URL.cert.pem \
        --from-file=ca.crt=ca-chain.cert.pem
    

    Anda baru saja menambahkan file sertifikat berikut ke secret:

    server-$SERVICE_URL.key.pem
    server-$SERVICE_URL.cert.pem
    ca-chain.cert.pem
    

Menentukan gateway masuk

Untuk menerima traffic dari cluster sisi klien, Anda harus menentukan gateway masuk yang dapat mendekripsi dan memverifikasi komunikasi TLS menggunakan sertifikat.

Menentukan gateway masuk yang memeriksa traffic untuk melihat apakah gateway tersebut sesuai dengan kriteria keamanan dan penerusan.

Diagram ini menunjukkan letak gateway ingress di cluster Anda. Traffic akan melewati dan diperiksa jika memenuhi kriteria keamanan dan penerusan.

  1. Di Cloud Shell, gunakan file YAML berikut dan beri nama server-ingress-gatway.yaml:

    cat <<EOF > server-ingress-gatway.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: Gateway
    metadata:
     name: gateway-mysql
    spec:
     selector:
       istio: ingressgateway # Istio default gateway implementation
     servers:
     - port:
         number: 13306
         name: tls-mysql
         protocol: TLS
       tls:
         mode: MUTUAL
         credentialName: mysql-credential
       hosts:
       - "$SERVICE_URL"
    EOF
    
  2. Terapkan definisi YAML sebelumnya ke cluster klien:

    kubectl --context ${SERVER_CLUSTER} apply -f server-ingress-gatway.yaml
    

    Perhatikan bagian tls: karena bagian ini sangat penting. Di bagian ini, Anda menentukan bahwa Anda ingin mTLS. Untuk memastikannya berfungsi seperti yang diharapkan, Anda harus memberikan secret yang Anda buat yang berisi sertifikat tersebut.

  3. Aktifkan port 13306 dengan mem-patch layanan ingress. Anda mengaktifkan port ini dengan membuat file JSON berikut dan menamakannya gateway-patch.json:

    cat <<EOF > gateway-patch.json
    [{
      "op": "add",
      "path": "/spec/ports/0",
      "value": {
        "name": "tls-mysql",
        "protocol": "TCP",
        "targetPort": 13306,
        "port": 13306
      }
    }]
    EOF
    
  4. Terapkan patch ke layanan gateway:

    kubectl --context ${SERVER_CLUSTER} -n istio-system patch --type=json svc istio-ingressgateway -p "$(cat gateway-patch.json)"
    

Setelah membuka port di gateway masuk, Anda harus mengambil traffic yang berasal dari gateway ingress baru Anda dan mengarahkannya ke Pod database. Untuk melakukannya, gunakan objek internal mesh: layanan virtual.

Menentukan layanan virtual

Seperti yang dibahas sebelumnya, layanan virtual adalah definisi pola pencocokan traffic yang membentuk traffic dalam mesh Anda. Anda perlu mengidentifikasi dan meneruskan traffic dengan benar dari gateway ingress ke layanan MySQL DB, seperti yang ditunjukkan pada diagram berikut.

Mengidentifikasi dan meneruskan traffic dari gateway masuk ke layanan DB MySQL.

  1. Di Cloud Shell, buat file YAML berikut dan beri nama server-virtual-service.yaml:

    cat <<EOF > server-virtual-service.yaml
    apiVersion: networking.istio.io/v1alpha3
    kind: VirtualService
    metadata:
     name: mysql-virtual-service
    spec:
     hosts:
       - "$SERVICE_URL"
     gateways:
       - gateway-mysql
     tcp:
       - route:
         - destination:
             port:
               number: 3306
             host: mysql.default.svc.cluster.local
    EOF
    

    Layanan virtual ini harus merujuk ke gateway masuk tempat traffic berasal. Gateway diberi nama gateway-mysql.

    Karena layanan virtual ini diterapkan di L4, Anda perlu memberikan flag tcp untuk mendeskripsikan traffic MySQL. Penanda ini pada dasarnya memberi tahu {i> mesh<i} bahwa L4 digunakan untuk lalu lintas ini.

    Anda mungkin telah mengetahui bahwa layanan ingress menggunakan port 13306 untuk meneruskan traffic. Layanan virtual mengambilnya dan menerjemahkannya kembali ke 3306.

    Terakhir, Anda meneruskan traffic ke server MySQL di cluster Kubernetes server. Untuk contoh ini, server memproses port MySQL standar 3306.

  2. Terapkan definisi YAML ke cluster server:

    kubectl --context ${SERVER_CLUSTER} apply -f server-virtual-service.yaml
    

Kedua definisi ini mendekripsi permintaan klien MySQL yang dienkapsulasi mTLS dan meneruskannya ke database MySQL di dalam mesh.

Penting untuk memahami bahwa penerusan internal mesh juga dilakukan menggunakan enkripsi. Namun, dalam hal ini, enkripsi didasarkan pada sertifikat internal mesh. Penghentian mTLS terjadi di gateway.

Sekarang Anda memiliki cara berkomunikasi yang sepenuhnya terenkripsi satu sama lain dengan server MySQL. Bentuk enkripsi ini bersifat transparan untuk klien dan server MySQL, sehingga aplikasi tidak perlu diubah. Dengan begitu, tugas seperti mengubah atau merotasi sertifikat menjadi mudah. Juga, cara komunikasi ini dapat digunakan untuk banyak skenario yang berbeda.

Menguji penyiapan

Setelah memiliki sisi klien dan server, Anda dapat menguji penyiapannya.

Menguji alur traffic dari sisi klien ke sisi server.

Saatnya untuk menghasilkan beberapa lalu lintas dari sisi klien ke sisi server. Anda ingin mengikuti alur traffic dan memastikan bahwa traffic dirutekan, serta dienkripsi dan didekripsi seperti yang Anda inginkan.

  1. Di Cloud Shell, deploy server MySQL ke cluster server:

    kubectl --context ${SERVER_CLUSTER} apply -f server/mysql-server/mysql.yaml
    
  2. Mulai klien MySQL di cluster klien:

    kubectl run --context ${CLIENT_CLUSTER} --env=SERVICE_URL=$SERVICE_URL -it --image=mysql:5.6 mysql-client-1 --restart=Never -- /bin/bash
    

    Saat container dimulai, Anda akan melihat shell, yang akan terlihat seperti berikut:

    root@mysql-client-1:/#
    
  3. Hubungkan ke server MySQL Anda:

    mysql -pyougottoknowme -h $SERVICE_URL
    
  4. Gunakan perintah berikut untuk menambahkan DB dan tabel:

    CREATE DATABASE test_encrypted_connection;
    USE test_encrypted_connection;
    CREATE TABLE message (id INT, content VARCHAR(20));
    INSERT INTO message (id,content) VALUES(1,"Crypto Hi");
    
  5. Setelah menghubungkan dan menambahkan tabel, keluar dari koneksi MySQL dan Pod:

    exit
    exit
    

    Anda harus mengetik exit dua kali—pertama, untuk meninggalkan koneksi DB, dan kedua, untuk keluar dari Pod. Jika Pod berhenti merespons saat keluar, tekan Control+C untuk membatalkan bash shell.

Dengan mengikuti langkah-langkah ini, Anda akan menghasilkan beberapa output logging penting yang sekarang dapat dianalisis lebih lanjut.

Di bagian berikutnya, Anda perlu memeriksa apakah traffic sisi klien meneruskan proxy dan gateway keluar. Anda juga akan menguji apakah traffic yang masuk ke sisi server dapat dilihat melalui gateway masuk.

Menguji gateway keluar dan proxy sisi klien

  1. Di Cloud Shell, pada proxy sisi klien, pastikan Anda dapat melihat log proxy Istio:

    kubectl --context ${CLIENT_CLUSTER} logs -l run=mysql-client-1 -c istio-proxy -f
    

    Outputnya terlihat mirip dengan yang berikut ini:

    [2021-02-10T21:19:08.292Z] "- - -" 0 - "-" "-" 176 115 10 - "-" "-" "-" "-" "192.168.1.4:15443" outbound|15443|mysql|istio-egressgateway.istio-system.svc.cluster.local 192.168.1.12:58614 34.66.165.46:3306 192.168.1.12:39642 - -
    

    Tekan Control+C untuk keluar dari output log.

    Dalam entri log ini, Anda dapat melihat bahwa klien meminta server yang berjalan di alamat IP 34.66.165.46pada port 3306. Permintaan diteruskan (outbound) ke istio-egressgateway yang memproses alamat IP port 192.168.1.4 15443. Anda menentukan penerusan ini dalam layanan virtual Anda (client-virtual-service.yaml).

  2. Baca log proxy gateway keluar:

    kubectl --context ${CLIENT_CLUSTER} logs -n istio-system -l app=istio-egressgateway -f
    

    Outputnya mirip dengan yang berikut ini:

    [2021-02-10T21:19:08.292Z] "- - -" 0 - "-" "-" 176 115 19 - "-" "-" "-" "-" "34.66.165.46:13306" outbound|13306||34.66.165.46.nip.io 192.168.1.4:53542 192.168.1.4:15443 192.168.1.12:58614 34.66.165.46.nip.io -
    

    Tekan Control+C untuk keluar dari output log.

    Dalam entri log ini, Anda dapat melihat bahwa permintaan klien yang dirutekan ke istio-egressgateway yang memproses port 192.168.1.4 alamat IP 15443 diteruskan lebih lanjut ke luar mesh layanan ke port eksternal layanan yang memproses alamat IP 34.66.165.46 pada port 13306. Anda menentukan penerusan ini di bagian kedua layanan virtual Anda (client-virtual-service.yaml).

Menguji gateway masuk sisi server

  1. Di Cloud Shell, di sisi server, lihat log proxy gateway masuk:

    kubectl --context ${SERVER_CLUSTER} logs -n istio-system -l app=istio-ingressgateway -f
    

    Output dalam log terlihat mirip dengan berikut ini:

    [2021-02-10T21:22:27.381Z] "- - -" 0 - "-" "-" 0 78 5 - "-" "-" "-" "-" "100.96.4.8:3306" outbound|3306||mysql.default.svc.cluster.local 100.96.1.3:55730 100.96.1.3:13306 100.96.1.1:42244 34.66.165.46.nip.io -
    

    Tekan Control+C untuk keluar dari output log.

    Dalam entri log ini, Anda dapat melihat bahwa permintaan klien eksternal yang dirutekan ke istio-ingressgateway yang memproses port 34.66.165.46 alamat IP 13306 diteruskan lebih lanjut ke layanan MySQL di dalam mesh yang diidentifikasi dengan nama layanan mysql.default.svc.cluster.local pada port 3306. Anda menentukan penerusan ini di gateway masuk (server-ingress-gateway.yaml).

  2. Untuk server MySQL, lihat log proxy Istio:

    kubectl --context ${SERVER_CLUSTER} logs -l app=mysql -c istio-proxy -f
    

    Outputnya terlihat mirip dengan yang berikut ini:

    [2021-02-10T21:22:27.382Z] "- - -" 0 - "-" "-" 1555 1471 4 - "-" "-" "-" "-" "127.0.0.1:3306" inbound|3306|mysql|mysql.default.svc.cluster.local 127.0.0.1:45894 100.96.4.8:3306 100.96.1.3:55730 outbound_.3306_._.mysql.default.svc.cluster.local -
    

    Tekan Control+C untuk keluar dari output log.

    Dalam entri log ini, Anda dapat melihat panggilan masuk ke server database MySQL yang memproses alamat IP 100.96.4.8 port 3306. Panggilan ini berasal dari Pod ingress dengan alamat IP 100.96.1.3.

    Untuk mengetahui informasi selengkapnya tentang format logging Envoy, lihat Mendapatkan Log Akses Envoy.

  3. Uji database Anda untuk melihat input yang dihasilkan:

    MYSQL=$(kubectl --context ${SERVER_CLUSTER} get pods -n default | tail -n 1 | awk '{print $1}')
    kubectl --context ${SERVER_CLUSTER} exec $MYSQL -ti -- /bin/bash
    
  4. Verifikasi database yang dibuat:

    mysql -pyougottoknowme
    USE test_encrypted_connection;
    SELECT * from message;
    

    Outputnya mirip dengan hal berikut ini:

    +------+-----------+
    | id   | content   |
    +------+-----------+
    |    1 | Crypto Hi |
    +------+-----------+
    1 row in set (0.00 sec)
    
  5. Biarkan database MySQL:

    exit
    exit
    

    Anda perlu mengetik exit dua kali—pertama, untuk meninggalkan koneksi DB, dan kedua, untuk keluar dari Pod.

Menguji akses dengan menghapus sertifikat

Setelah menguji dan memverifikasi bahwa akses berfungsi menggunakan sertifikat yang dimasukkan, uji juga hal sebaliknya: apa yang terjadi jika Anda menghilangkan gateway keluar dan injeksi sertifikat. Pengujian ini juga disebut pengujian negatif.

Anda dapat melakukan pengujian ini dengan meluncurkan Pod lain dalam namespace tanpa mengaktifkan injeksi side proxy.

  1. Di Cloud Shell, buat namespace baru:

    kubectl --context ${CLIENT_CLUSTER} create ns unencrypted
    
  2. Buat Pod dan mulai shell interaktif di dalam container:

    kubectl --context ${CLIENT_CLUSTER} run -it --image=mysql:5.6 \
    mysql-client-2 --env=SERVICE_URL=$SERVICE_URL \
    -n unencrypted --restart=Never -- /bin/bash
    
  3. Coba hubungkan ke database setelah shell interaktif dimulai:

    mysql -pyougottoknowme -h $SERVICE_URL
    

    Setelah 30 detik, Anda akan melihat output yang mirip dengan berikut ini:

    Warning: Using a password on the command line interface can be insecure.
    ERROR 2003 (HY000): Can't connect to MySQL server on '104.154.164.12.nip.io' (110)
    

    Peringatan ini sudah diperkirakan karena Pod ini menghilangkan gateway keluar dan mencoba menjangkau gateway masuk ($SERVICE_URL) secara langsung melalui internet.

  4. Coba tentukan alamat IP layanan:

    resolveip $SERVICE_URL
    

    Outputnya mirip dengan yang berikut ini. Alamat IP Anda akan berbeda.

    IP address of 104.154.164.12.nip.io is 104.154.164.12
    

    Hal ini membuktikan bahwa FQDN dapat diselesaikan dan bahwa koneksi yang gagal memang karena injeksi sertifikat yang tidak ada.

  5. Keluar dari koneksi MySQL dan Pod server MySQL:

    exit
    exit
    

Penyelidikan Lebih Jauh

Salah satu topik yang tidak dibahas dalam tutorial ini adalah bahwa konfigurasi egress, biasanya dimiliki oleh organisasi atau peran yang berbeda di perusahaan Anda, karena dihosting di namespace istio-system. Konfigurasikan izin RBAC Kubernetes sehingga hanya administrator jaringan yang dapat langsung membuat dan mengubah resource yang dibahas dalam tutorial ini.

Setelah mengetahui cara menggunakan mesh layanan untuk membantu memastikan komunikasi yang aman, Anda dapat mencobanya dengan aplikasi yang perlu bertukar data secara aman, dan tempat Anda ingin mengontrol enkripsi hingga ke lapisan sertifikat singkat ini. Untuk memulai, Anda dapat menginstal Anthos Service Mesh.

Coba gunakan dua cluster GKE dan gabungkan dengan menggunakan teknik dalam tutorial ini. Teknik ini juga dapat digunakan di platform GKE Enterprise antara dua cluster Kubernetes asing.

Mesh layanan adalah cara terbaik untuk meningkatkan keamanan di dalam cluster Anda serta dengan layanan eksternal. Salah satu kasus penggunaan terakhir yang harus dicoba adalah memiliki endpoint mTLS yang bukan merupakan cluster Kubernetes kedua, tetapi penyedia pihak ketiga (seperti penyedia pembayaran).

Pembersihan

Agar tidak menimbulkan biaya pada akun Google Cloud Anda untuk resource yang digunakan dalam tutorial ini, Anda dapat menghapus project Anda.

Menghapus project

  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