Menggunakan beberapa sertifikat SSL di load balancing HTTPS dengan Ingress


Halaman ini menunjukkan cara mengonfigurasi beberapa sertifikat SSL untuk resource Ingress di cluster Google Kubernetes Engine (GKE).

Ringkasan

Jika Anda ingin menerima permintaan HTTPS dari klien, Load Balancer Aplikasi harus memiliki sertifikat agar dapat membuktikan identitasnya kepada klien Anda. Load balancer juga harus memiliki kunci pribadi untuk menyelesaikan handshake HTTPS.

Saat load balancer menerima permintaan HTTPS dari klien, traffic antara klien dan load balancer dienkripsi menggunakan TLS. Namun, load balancer menghentikan enkripsi TLS dan meneruskan permintaan tanpa enkripsi ke aplikasi. Saat mengonfigurasi Load Balancer Aplikasi melalui Ingress, Anda dapat mengonfigurasi load balancer untuk memberikan hingga sepuluh sertifikat TLS kepada klien.

Load balancer menggunakan Server Name Indication (SNI) untuk menentukan sertifikat yang akan ditampilkan kepada klien, berdasarkan nama domain di handshake TLS. Jika klien tidak menggunakan SNI, atau jika klien menggunakan nama domain yang tidak cocok dengan Nama Umum (CN) di salah satu sertifikat, load balancer akan menggunakan sertifikat pertama yang tercantum di Ingress.

Diagram berikut menunjukkan load balancer yang mengirimkan traffic ke backend yang berbeda, bergantung pada nama domain yang digunakan dalam permintaan:

beberapa sertifikat SSL dengan diagram sistem Ingress

Anda dapat menyediakan Load Balancer Aplikasi dengan sertifikat SSL menggunakan metode berikut:

  • Sertifikat SSL Google Cloud yang Anda kelola sendiri. Sertifikat SSL menggunakan sertifikat yang dibagikan sebelumnya yang Anda upload ke project Google Cloud.

  • Secret Kubernetes. Secret menyimpan sertifikat dan kunci yang Anda buat sendiri. Anda menambahkan nama Secret ke kolom tls dari manifes Ingress.

Anda bisa menggunakan lebih dari satu metode dalam Ingress yang sama. Hal ini memungkinkan migrasi tanpa periode nonaktif antar-metode.

Gambaran besarnya

Berikut adalah ringkasan langkah-langkah dalam dokumen ini:

  1. Membuat Deployment.

  2. Membuat Service.

  3. Buat dua file sertifikat dan dua file kunci atau dua objek ManagedCertificate. Anda harus mengonfigurasi sertifikat ini dalam project dan namespace yang sama dengan tempat load balancer di-deploy.

  4. Membuat Ingress yang menggunakan Secret atau sertifikat yang dibagikan sebelumnya. Saat Anda membuat Ingress, GKE akan membuat dan mengonfigurasi Load Balancer Aplikasi.

  5. Menguji Load Balancer Aplikasi.

Sebelum memulai

Sebelum memulai, pastikan Anda telah menjalankan tugas berikut:

  • Aktifkan Google Kubernetes Engine API.
  • Aktifkan Google Kubernetes Engine API
  • Jika ingin menggunakan Google Cloud CLI untuk tugas ini, instal lalu initialize gcloud CLI. Jika sebelumnya Anda telah menginstal gcloud CLI, dapatkan versi terbaru dengan menjalankan gcloud components update.
  • Anda harus memiliki dua nama domain. Nama domain tidak boleh lebih dari 63 karakter.

Batasan

  • Untuk Load Balancer Aplikasi internal, Anda harus menonaktifkan HTTP dalam manifes Ingress. Hal ini tidak diperlukan untuk load balancer eksternal.
  • Anda tidak boleh mengubah atau mengupdate konfigurasi Load Balancer Aplikasi secara manual. Ini berarti Anda tidak boleh mengedit komponen load balancer apa pun, termasuk proxy target, peta URL, dan layanan backend. Setiap perubahan yang Anda buat akan ditimpa oleh GKE.

Membuat Deployment

  1. Simpan manifes berikut sebagai my-mc-deployment.yaml:

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: my-mc-deployment
    spec:
      selector:
        matchLabels:
          app: products
          department: sales
      replicas: 3
      template:
        metadata:
          labels:
            app: products
            department: sales
        spec:
          containers:
          - name: hello
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:1.0"
            env:
            - name: "PORT"
              value: "50001"
          - name: hello-again
            image: "us-docker.pkg.dev/google-samples/containers/gke/hello-app:2.0"
            env:
            - name: "PORT"
              value: "50002"
    

    Manifes ini menjelaskan Deployment dengan tiga Pod. Setiap Pod memiliki dua container. Satu container menjalankan hello-app:1.0 dan memproses di port TCP 50001. Penampung lainnya menjalankan hello-app:2.0 dan memproses port TCP 50002.

  2. Terapkan manifes ke cluster Anda:

    kubectl apply -f my-mc-deployment.yaml
    

Membuat Service

  1. Simpan manifes berikut sebagai my-mc-service.yaml:

    apiVersion: v1
    kind: Service
    metadata:
      name: my-mc-service
    spec:
      type: NodePort
      selector:
        app: products
        department: sales
      ports:
      - name: my-first-port
        protocol: TCP
        port: 60001
        targetPort: 50001
      - name: my-second-port
        protocol: TCP
        port: 60002
        targetPort: 50002
    

    Manifes ini menjelaskan Service dengan kolom berikut:

    • selector: menentukan bahwa setiap Pod yang memiliki label app: products dan label department: sales adalah anggota Layanan ini.
    • ports: menentukan bahwa saat klien mengirim permintaan ke Layanan pada my-first-port, GKE akan meneruskan permintaan tersebut ke salah satu Pod anggota di port 50001. Saat klien mengirim permintaan ke Layanan pada my-second-port, GKE akan meneruskan permintaan tersebut ke salah satu Pod anggota di port 50002.
  2. Terapkan manifes ke cluster Anda:

    kubectl apply -f my-mc-service.yaml
    

Membuat sertifikat dan kunci

Untuk melakukan latihan di halaman ini, Anda memerlukan dua sertifikat, masing-masing dengan kunci yang sesuai. Setiap sertifikat harus memiliki Nama Umum (CN) yang sama dengan nama domain yang Anda miliki.

Jika sudah memiliki dua file sertifikat dengan nilai yang sesuai untuk Nama Umum, Anda dapat langsung melanjutkan ke bagian berikutnya.

Sertifikat yang dikelola pengguna

  1. Buat kunci pertama Anda:

    openssl genrsa -out test-ingress-1.key 2048
    
  2. Buat permintaan penandatanganan sertifikat pertama Anda:

    openssl req -new -key test-ingress-1.key -out test-ingress-1.csr \
        -subj "/CN=FIRST_DOMAIN"
    

    Ganti FIRST_DOMAIN dengan nama domain yang Anda miliki, seperti example.com.

  3. Buat sertifikat pertama Anda:

    openssl x509 -req -days 365 -in test-ingress-1.csr -signkey test-ingress-1.key \
        -out test-ingress-1.crt
    
  4. Buat kunci kedua:

    openssl genrsa -out test-ingress-2.key 2048
    
  5. Buat permintaan penandatanganan sertifikat kedua Anda:

    openssl req -new -key test-ingress-2.key -out test-ingress-2.csr \
        -subj "/CN=SECOND_DOMAIN"
    

    Ganti SECOND_DOMAIN dengan nama domain lain yang Anda miliki, seperti examplepetstore.com.

  6. Buat sertifikat kedua Anda:

    openssl x509 -req -days 365 -in test-ingress-2.csr -signkey test-ingress-2.key \
        -out test-ingress-2.crt
    

Untuk mengetahui informasi selengkapnya tentang sertifikat dan kunci, lihat Ringkasan sertifikat SSL.

Anda sekarang memiliki dua file sertifikat dan dua file kunci.

Tugas yang tersisa menggunakan placeholder berikut untuk merujuk ke domain, sertifikat, dan kunci Anda:

  • FIRST_CERT_FILE: jalur ke file sertifikat pertama Anda.
  • FIRST_KEY_FILE: jalur ke file kunci yang mengarah dengan sertifikat pertama Anda.
  • FIRST_DOMAIN: nama domain yang Anda miliki.
  • FIRST_SECRET_NAME: nama Secret yang berisi sertifikat dan kunci pertama Anda.
  • SECOND_CERT_FILE: jalur ke file sertifikat kedua Anda.
  • SECOND_KEY_FILE: jalur ke file kunci yang sesuai dengan sertifikat kedua Anda.
  • SECOND_DOMAIN: nama domain kedua yang Anda miliki.
  • SECOND_SECRET_NAME: nama Secret yang berisi sertifikat dan kunci kedua Anda.

Menentukan sertifikat untuk Ingress Anda

Langkah selanjutnya adalah membuat objek Ingress. Dalam manifes Ingress, Anda dapat menggunakan salah satu metode berikut untuk memberikan sertifikat bagi load balancer:

  • Rahasia
  • Sertifikat yang dibagikan sebelumnya

Rahasia

  1. Buat Secret yang menyimpan sertifikat dan kunci pertama Anda:

    kubectl create secret tls FIRST_SECRET_NAME \
        --cert=FIRST_CERT_FILE \
        --key=FIRST_KEY_FILE
    
  2. Buat Secret yang menyimpan sertifikat dan kunci kedua Anda:

    kubectl create secret tls SECOND_SECRET_NAME \
        --cert=SECOND_CERT_FILE \
        --key=SECOND_KEY_FILE
    

Membuat Ingress

  1. Simpan manifes berikut sebagai my-mc-ingress.yaml:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-mc-ingress
    spec:
      tls:
      - secretName: FIRST_SECRET_NAME
      - secretName: SECOND_SECRET_NAME
      rules:
      - host: FIRST_DOMAIN
        http:
          paths:
          - pathType: ImplementationSpecific
            backend:
              service:
                name: my-mc-service
                port:
                  number: 60001
      - host: SECOND_DOMAIN
        http:
          paths:
          - pathType: ImplementationSpecific
            backend:
              service:
                name: my-mc-service
                port:
                  number: 60002
    

    Ganti FIRST_DOMAIN dan SECOND_DOMAIN dengan nama domain yang Anda miliki, misalnya example.com dan examplepetstore.com.

  2. Terapkan manifes ke cluster Anda:

    kubectl apply -f my-mc-ingress.yaml
    
  3. Uraikan Ingress Anda:

    kubectl describe ingress my-mc-ingress
    

    Outputnya mirip dengan hal berikut ini:

    Name: my-mc-ingress
    Address: 203.0.113.1
    ...
    TLS:
      FIRST_SECRET_NAME terminates
      SECOND_SECRET_NAME terminates
    Rules:
      Host              Path  Backends
      ----              ----  --------
      FIRST_DOMAIN
                          my-mc-service:my-first-port (<none>)
      SECOND_DOMAIN
                          my-mc-service:my-second-port (<none>)
    Annotations:
    ...
    Events:
      Type    Reason  Age   From                     Message
      ----    ------  ----  ----                     -------
      Normal  ADD     3m    loadbalancer-controller  default/my-mc-ingress
      Normal  CREATE  2m    loadbalancer-controller  ip: 203.0.113.1
    

    Output menunjukkan bahwa dua Secret dikaitkan dengan Ingress. Output juga menampilkan alamat IP eksternal load balancer. Jika alamat IP eksternal tidak ditetapkan, tunggu beberapa menit dan coba perintahnya lagi.

Sertifikat yang dibagikan sebelumnya

  1. Buat sertifikat:

    gcloud compute ssl-certificates create FIRST_CERT_NAME \
        --certificate=FIRST_CERT_FILE \
        --private-key=FIRST_KEY_FILE
    

    Ganti kode berikut:

    • FIRST_CERT_NAME: nama sertifikat pertama Anda.
    • FIRST_CERT_FILE: file sertifikat pertama.
    • FIRST_KEY_FILE: file kunci pertama Anda.
  2. Buat sertifikat kedua:

    gcloud compute ssl-certificates create SECOND_CERT_NAME \
        --certificate=SECOND_CERT_FILE \
        --private-key=SECOND_KEY_FILE
    

    Ganti kode berikut:

    • SECOND_CERT_NAME: nama sertifikat kedua Anda.
    • SECOND_CERT_FILE: file sertifikat kedua Anda.
    • SECOND_KEY_FILE: file kunci kedua Anda.
  3. Lihat resource sertifikat Anda:

    gcloud compute ssl-certificates list
    

    Outputnya mirip dengan hal berikut ini:

    NAME                   CREATION_TIMESTAMP
    FIRST_CERT_NAME      2018-11-03T12:08:47.751-07:00
    SECOND_CERT_NAME     2018-11-03T12:09:25.359-07:00
    

Membuat Ingress

  1. Simpan manifes berikut sebagai my-psc-ingress.yaml:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: my-psc-ingress
      annotations:
        ingress.gcp.kubernetes.io/pre-shared-cert: "FIRST_CERT_NAME,SECOND_CERT_NAME"
    spec:
      rules:
      - host: FIRST_DOMAIN
        http:
          paths:
          - pathType: ImplementationSpecific
            backend:
              service:
                name: my-mc-service
                port:
                  number: 60001
      - host: SECOND_DOMAIN
        http:
          paths:
          - pathType: ImplementationSpecific
            backend:
              service:
                name: my-mc-service
                port:
                  number: 60002
    

    Ganti FIRST_DOMAIN dan SECOND_DOMAIN dengan nama domain Anda.

    Manifes ini menjelaskan Ingress yang mencantumkan resource sertifikat yang dibagikan sebelumnya dalam anotasi.

  2. Terapkan manifes ke cluster Anda:

    kubectl apply -f my-psc-ingress.yaml
    
  3. Uraikan Ingress Anda:

    kubectl describe ingress my-psc-ingress
    

    Outputnya mirip dengan hal berikut ini:

    Name:             my-psc-ingress
    Address:          203.0.113.2
    ...
    Rules:
      Host              Path  Backends
      ----              ----  --------
      FIRST_DOMAIN
                          my-mc-service:my-first-port (<none>)
      SECOND_DOMAIN
                          my-mc-service:my-second-port (<none>)
    Annotations:
      ...
      ingress.gcp.kubernetes.io/pre-shared-cert:    FIRST_CERT_NAME,SECOND_CERT_NAME
      ...
      ingress.kubernetes.io/ssl-cert:               FIRST_CERT_NAME,SECOND_CERT_NAME
    Events:
      Type    Reason  Age   From                     Message
      ----    ------  ----  ----                     -------
      Normal  ADD     2m    loadbalancer-controller  default/my-psc-ingress
      Normal  CREATE  1m    loadbalancer-controller  ip: 203.0.113.2
    

    Output menunjukkan bahwa Ingress dikaitkan dengan sertifikat yang dibagikan sebelumnya bernama FIRST_CERT_NAME dan SECOND_CERT_NAME. Output juga menunjukkan alamat IP eksternal load balancer. Jika alamat IP eksternal belum ditetapkan, tunggu beberapa menit dan coba kembali perintahnya.

Menguji load balancer

Tunggu sekitar lima menit hingga GKE selesai mengonfigurasi load balancer.

Untuk menguji load balancer, Anda harus memiliki dua nama domain, dan kedua nama domain tersebut harus me-resolve alamat IP eksternal Load Balancer Aplikasi eksternal.

  1. Kirim permintaan ke load balancer menggunakan nama domain pertama Anda:

    curl -v https://FIRST_DOMAIN
    

    Anda mungkin perlu menggunakan opsi curl -k untuk melakukan transfer SSL yang tidak aman, sehingga curl akan menerima sertifikat yang ditandatangani sendiri.

    Outputnya mirip dengan hal berikut ini:

    ...
    *   Trying 203.0.113.1...
    ...
    * Connected to FIRST_DOMAIN (203.0.113.1) port 443 (#0)
    ...
    * TLSv1.2 (IN), TLS handshake, Certificate (11):
    ...
    * Server certificate:
    *  subject: CN=FIRST_DOMAIN
    ...
    > Host: FIRST_DOMAIN.com
    ...
    Hello, world!
    Version: 1.0.0
    ...
    

    Output ini menunjukkan bahwa sertifikat pertama Anda digunakan di TLS handshake.

  2. Kirim permintaan ke load balancer menggunakan nama domain kedua Anda:

    curl -v https://SECOND_DOMAIN
    

    Outputnya mirip dengan hal berikut ini:

    ...
    *   Trying 203.0.113.1...
    ...
    * Connected to SECOND_DOMAIN (203.0.113.1) port 443 (#0)
    ...
    * Server certificate:
    *  subject: CN=SECOND_DOMAIN
    ...
    > Host: SECOND_DOMAIN
    ...
    Hello, world!
    Version: 2.0.0
    

    Output ini menunjukkan bahwa sertifikat kedua Anda digunakan dalam handshake TLS.

Kolom host objek Ingress

IngressSpec memiliki kolom tls yang merupakan array objek IngressTLS. Setiap objek IngressTLS memiliki kolom hosts dan kolom SecretName. Di GKE, kolom hosts tidak digunakan. GKE membaca Nama Umum (CN) dari sertifikat di Secret. Jika Nama Umum cocok dengan nama domain dalam permintaan klien, load balancer akan memberikan sertifikat yang cocok kepada klien.

Sertifikat mana yang diberikan?

Load balancer memilih sertifikat sesuai dengan aturan berikut:

  • Jika Secret dan sertifikat yang dibagikan sebelumnya tercantum di Ingress, sertifikat yang dibagikan sebelumnya akan lebih diprioritaskan daripada Secret. Dengan kata lain, Secret masih disertakan, tetapi sertifikat yang dibagikan sebelumnya akan ditampilkan terlebih dahulu.

  • Jika tidak ada sertifikat yang memiliki Nama Umum (CN) yang cocok dengan nama domain dalam permintaan klien, load balancer akan menampilkan sertifikat utama.

  • Untuk Secret yang tercantum dalam blok tls, sertifikat utama berada di Secret pertama dalam daftar.

  • Untuk sertifikat yang dibagikan sebelumnya yang tercantum dalam anotasi, sertifikat utama adalah sertifikat pertama dalam daftar.

Praktik terbaik rotasi sertifikat

Jika Anda ingin merotasi konten Secret atau sertifikat yang dibagikan sebelumnya, berikut beberapa praktik terbaik:

  • Buat Secret baru atau sertifikat yang dibagikan sebelumnya dengan nama berbeda yang berisi data sertifikat baru. Lampirkan resource ini (beserta resource yang ada) ke Ingress menggunakan petunjuk yang diberikan sebelumnya. Setelah puas dengan perubahannya, Anda dapat menghapus sertifikat lama dari Ingress.
  • Jika tidak keberatan mengganggu traffic, Anda dapat menghapus resource lama dari Ingress, menyediakan resource baru dengan nama yang sama, tetapi dengan konten yang berbeda, lalu melampirkannya kembali ke Ingress.

Pemecahan masalah

Penentuan Secret yang tidak valid atau tidak ada akan menyebabkan error peristiwa Kubernetes. Anda dapat memeriksa peristiwa Kubernetes untuk Ingress sebagai berikut:

kubectl describe ingress

Outputnya mirip dengan hal berikut ini:

Name:             my-ingress
Namespace:        default
Address:          203.0.113.3
Default backend:  hello-server:8080 (10.8.0.3:8080)
TLS:
  my-faulty-Secret terminates
Rules:
  Host  Path  Backends
  ----  ----  --------
  *     *     my-service:443 (10.8.0.3:443)
Events:
   Error during sync: cannot get certs for Ingress default/my-ingress:
 Secret "my-faulty-ingress" has no 'tls.crt'

Langkah selanjutnya