Siapkan Driver CSI Secrets Store untuk mengaktifkan Pengontrol Ingress NGINX dengan TLS

Artikel ini memandu Anda melalui proses mengamankan Pengontrol Ingress NGINX dengan TLS menggunakan kluster Azure Kubernetes Service (AKS) dan instans Azure Key Vault (AKV). Untuk informasi selengkapnya, lihat TLS di Kubernetes.

Anda dapat mengimpor sertifikat TLS ingress ke kluster menggunakan salah satu metode berikut:

  • Aplikasi: Manifes penyebaran aplikasi mendeklarasikan dan memasang volume penyedia. Hanya ketika Anda menyebarkan aplikasi adalah sertifikat yang tersedia di kluster. Saat Anda menghapus aplikasi, rahasia juga dihapus. Skenario ini sesuai dengan tim pengembangan yang bertanggung jawab atas infrastruktur keamanan aplikasi dan integrasinya dengan kluster.
  • Pengontrol Ingress: Penyebaran ingress dimodifikasi untuk mendeklarasikan dan memasang volume penyedia. Rahasia diimpor ketika pod ingress dibuat. Pod aplikasi tidak memiliki akses ke sertifikat TLS. Skenario ini sesuai dengan skenario tempat satu tim (misalnya, TI) mengelola dan membuat komponen infrastruktur dan jaringan (termasuk sertifikat HTTPS TLS) dan tim lain mengelola siklus hidup aplikasi.

Prasyarat

Buat sertifikat TLS

  • Buat sertifikat TLS menggunakan perintah berikut.

    export CERT_NAME=aks-ingress-cert
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
        -out aks-ingress-tls.crt \
        -keyout aks-ingress-tls.key \
        -subj "/CN=demo.azure.com/O=aks-ingress-tls"
    

Impor sertifikat ke AKV

  1. Ekspor sertifikat ke file PFX menggunakan perintah berikut.

    export AKV_NAME="[YOUR AKV NAME]"
    openssl pkcs12 -export -in aks-ingress-tls.crt -inkey aks-ingress-tls.key  -out $CERT_NAME.pfx
    # skip Password prompt
    
  2. Impor sertifikat menggunakan az keyvault certificate import perintah .

    az keyvault certificate import --vault-name $AKV_NAME -n $CERT_NAME -f $CERT_NAME.pfx
    

Sebar SecretProviderClass

  1. Ekspor namespace baru menggunakan perintah berikut.

    export NAMESPACE=ingress-basic
    
  2. Buat namespace menggunakan kubectl create namespace perintah .

    kubectl create namespace $NAMESPACE
    
  3. Pilih metode untuk memberikan identitas akses dan konfigurasikan YAML SecretProviderClass Anda dengan sesuai.

    • Pastikan untuk menggunakan objectType=secret, yang merupakan satu-satunya cara untuk mendapatkan kunci privat dan sertifikat dari AKV.
    • Atur kubernetes.io/tls seperti type di bagian secretObjects Anda.

    Lihat contoh berikut tentang tampilan SecretProviderClass Anda:

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: azure-tls
    spec:
      provider: azure
      secretObjects:                            # secretObjects defines the desired state of synced K8s secret objects
        - secretName: ingress-tls-csi
          type: kubernetes.io/tls
          data: 
            - objectName: $CERT_NAME
              key: tls.key
            - objectName: $CERT_NAME
              key: tls.crt
      parameters:
        usePodIdentity: "false"
        useVMManagedIdentity: "true"
        userAssignedIdentityID: <client id>
        keyvaultName: $AKV_NAME                 # the name of the AKV instance
        objects: |
          array:
            - |
              objectName: $CERT_NAME
              objectType: secret
        tenantId: $TENANT_ID                    # the tenant ID of the AKV instance
    
  4. Terapkan SecretProviderClass ke kluster Kubernetes Anda menggunakan kubectl apply perintah .

    kubectl apply -f secretProviderClass.yaml -n $NAMESPACE
    

Menyebarkan pengontrol ingress

Tambahkan repositori bagan ingress resmi

  • Tambahkan repositori bagan ingress resmi menggunakan perintah berikut helm .

    helm repo add ingress-nginx https://kubernetes.github.io/ingress-nginx
    helm repo update
    

Konfigurasikan dan sebarkan ingress NGINX

Bergantung pada skenario Anda, Anda dapat memilih untuk mengikat sertifikat ke aplikasi atau ke pengontrol ingress. Ikuti petunjuk di bawah ini sesuai dengan pilihan Anda:

Ikat sertifikat ke aplikasi

  • Ikat sertifikat ke aplikasi menggunakan helm install perintah . Penyebaran aplikasi mereferensikan penyedia Azure Key Vault Driver Secrets Store CSI.

    helm install ingress-nginx/ingress-nginx --generate-name \
        --namespace $NAMESPACE \
        --set controller.replicaCount=2 \
        --set controller.nodeSelector."kubernetes\.io/os"=linux \
        --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
        --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux
    

Ikat sertifikat ke pengontrol ingress

  1. Ikat sertifikat ke pengontrol ingress menggunakan helm install perintah . Penyebaran pengontrol ingress mereferensikan penyedia Azure Key Vault Driver Secrets Store CSI.

    Catatan

    • Jika tidak menggunakan identitas yang dikelola pod Microsoft Entra sebagai metode akses Anda, hapus baris dengan --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME .

    • Selain itu, mengikat SecretProviderClass ke pod diperlukan agar Driver Secrets Store CSI memasangnya dan menghasilkan rahasia Kubernetes. Lihat Menyinkronkan konten yang dipasang dengan rahasia Kubernetes .

    helm install ingress-nginx/ingress-nginx --generate-name \
        --namespace $NAMESPACE \
        --set controller.replicaCount=2 \
        --set controller.nodeSelector."kubernetes\.io/os"=linux \
        --set defaultBackend.nodeSelector."kubernetes\.io/os"=linux \
        --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
        --set controller.podLabels.aadpodidbinding=$AAD_POD_IDENTITY_NAME \
        -f - <<EOF
    controller:
      extraVolumes:
          - name: secrets-store-inline
            csi:
              driver: secrets-store.csi.k8s.io
              readOnly: true
              volumeAttributes:
                secretProviderClass: "azure-tls"
      extraVolumeMounts:
          - name: secrets-store-inline
            mountPath: "/mnt/secrets-store"
            readOnly: true
    EOF
    
  2. Verifikasi bahwa rahasia Kubernetes dibuat menggunakan kubectl get secret perintah .

    kubectl get secret -n $NAMESPACE
    
    NAME                                             TYPE                                  DATA   AGE
    ingress-tls-csi                                  kubernetes.io/tls                     2      1m34s
    

Menyebarkan aplikasi

Sekali lagi, instruksi sedikit berubah tergantung pada skenario Anda. Ikuti instruksi yang sesuai dengan skenario yang Anda pilih.

Sebarkan aplikasi menggunakan referensi aplikasi

  1. Buat file bernama aks-helloworld-one.yaml dengan konten berikut.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-one  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-one
      template:
        metadata:
          labels:
            app: aks-helloworld-one
        spec:
          containers:
          - name: aks-helloworld-one
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
            volumeMounts:
            - name: secrets-store-inline
              mountPath: "/mnt/secrets-store"
              readOnly: true
          volumes:
          - name: secrets-store-inline
            csi:
              driver: secrets-store.csi.k8s.io
              readOnly: true
              volumeAttributes:
                secretProviderClass: "azure-tls"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-one  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-one
    
  2. Buat file bernama aks-helloworld-two.yaml dengan konten berikut.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-two  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-two
      template:
        metadata:
          labels:
            app: aks-helloworld-two
        spec:
          containers:
          - name: aks-helloworld-two
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "AKS Ingress Demo"
            volumeMounts:
            - name: secrets-store-inline
              mountPath: "/mnt/secrets-store"
              readOnly: true
          volumes:
          - name: secrets-store-inline
            csi:
              driver: secrets-store.csi.k8s.io
              readOnly: true
              volumeAttributes:
                secretProviderClass: "azure-tls"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-two
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-two
    
  3. Terapkan file YAML ke kluster Anda menggunakan kubectl apply perintah .

    kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE
    kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
    
  4. Verifikasi bahwa rahasia Kubernetes dibuat menggunakan kubectl get secret perintah .

    kubectl get secret -n $NAMESPACE
    
    NAME                                             TYPE                                  DATA   AGE
    ingress-tls-csi                                  kubernetes.io/tls                     2      1m34s
    

Sebarkan aplikasi menggunakan referensi pengontrol ingress

  1. Buat file bernama aks-helloworld-one.yaml dengan konten berikut.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-one  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-one
      template:
        metadata:
          labels:
            app: aks-helloworld-one
        spec:
          containers:
          - name: aks-helloworld-one
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "Welcome to Azure Kubernetes Service (AKS)"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-one
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-one
    
  2. Buat file bernama aks-helloworld-two.yaml dengan konten berikut.

    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: aks-helloworld-two  
    spec:
      replicas: 1
      selector:
        matchLabels:
          app: aks-helloworld-two
      template:
        metadata:
          labels:
            app: aks-helloworld-two
        spec:
          containers:
          - name: aks-helloworld-two
            image: mcr.microsoft.com/azuredocs/aks-helloworld:v1
            ports:
            - containerPort: 80
            env:
            - name: TITLE
              value: "AKS Ingress Demo"
    ---
    apiVersion: v1
    kind: Service
    metadata:
      name: aks-helloworld-two  
    spec:
      type: ClusterIP
      ports:
      - port: 80
      selector:
        app: aks-helloworld-two
    
  3. Terapkan file YAML ke kluster Anda menggunakan kubectl apply perintah .

    kubectl apply -f aks-helloworld-one.yaml -n $NAMESPACE
    kubectl apply -f aks-helloworld-two.yaml -n $NAMESPACE
    

Sebarkan sumber daya ingress yang merujuk pada rahasia

Kita sekarang dapat menyebarkan sumber daya ingress Kubernetes yang merujuk pada rahasia.

  1. Buat nama hello-world-ingress.yaml file dengan konten berikut.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: ingress-tls
      annotations:
        nginx.ingress.kubernetes.io/rewrite-target: /$2
    spec:
      ingressClassName: nginx
      tls:
      - hosts:
        - demo.azure.com
        secretName: ingress-tls-csi
      rules:
      - host: demo.azure.com
        http:
          paths:
          - path: /hello-world-one(/|$)(.*)
            pathType: Prefix
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
          - path: /hello-world-two(/|$)(.*)
            pathType: Prefix      
            backend:
              service:
                name: aks-helloworld-two
                port:
                  number: 80
          - path: /(.*)
            pathType: Prefix      
            backend:
              service:
                name: aks-helloworld-one
                port:
                  number: 80
    
  2. Catat bagian yang tls merujuk rahasia yang dibuat sebelumnya dan terapkan file ke kluster Anda menggunakan kubectl apply perintah .

    kubectl apply -f hello-world-ingress.yaml -n $NAMESPACE
    

Dapatkan alamat IP eksternal dari pengontrol ingress

  • Dapatkan alamat IP eksternal untuk pengontrol ingress menggunakan kubectl get service perintah .

    kubectl get service --namespace $NAMESPACE --selector app.kubernetes.io/name=ingress-nginx
    
    NAME                                       TYPE           CLUSTER-IP     EXTERNAL-IP      PORT(S)                      AGE
    nginx-ingress-1588032400-controller        LoadBalancer   10.0.255.157   EXTERNAL_IP      80:31293/TCP,443:31265/TCP   19m
    nginx-ingress-1588032400-default-backend   ClusterIP      10.0.223.214   <none>           80/TCP                       19m
    

Uji ingress yang diamankan dengan TLS

  1. Pastikan ingress Anda dikonfigurasi dengan benar dengan TLS menggunakan perintah berikut curl . Pastikan Anda menggunakan IP eksternal dari langkah sebelumnya.

    curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com
    

    Karena jalur lain tidak disediakan dengan alamat, pengontrol ingress default ke / rute. Aplikasi demo dikembalikan, seperti yang ditunjukkan dalam output contoh ringkas berikut:

    [...]
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>Welcome to Azure Kubernetes Service (AKS)</title>
    [...]
    

    Parameter -v dalam curl perintah menghasilkan informasi verbose, termasuk sertifikat TLS yang diterima. Setengah dari output curl Anda, Anda dapat memverifikasi bahwa sertifikat TLS Anda sendiri telah digunakan. Parameter -k terus memuat halaman meskipun kita menggunakan sertifikat yang ditandatangani sendiri. Contoh berikut menunjukkan penerbit: CN=demo.azure.com; Sertifikat O=aks-ingress-tls digunakan:

    [...]
     * Server certificate:
     *  subject: CN=demo.azure.com; O=aks-ingress-tls
     *  start date: Oct 22 22:13:54 2021 GMT
     *  expire date: Oct 22 22:13:54 2022 GMT
     *  issuer: CN=demo.azure.com; O=aks-ingress-tls
     *  SSL certificate verify result: self signed certificate (18), continuing anyway.
    [...]
    
  2. Tambahkan jalur /hello-world-two ke alamat, seperti https://demo.azure.com/hello-world-two, dan verifikasi aplikasi demo kedua dikonfigurasi dengan benar.

    curl -v -k --resolve demo.azure.com:443:EXTERNAL_IP https://demo.azure.com/hello-world-two
    

    Aplikasi demo kedua dengan judul kustom dikembalikan, seperti yang ditunjukkan dalam contoh output ringkas berikut:

    [...]
    <!DOCTYPE html>
    <html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <link rel="stylesheet" type="text/css" href="/static/default.css">
        <title>AKS Ingress Demo</title>
    [...]