共用方式為


將 Apache Superset 公開至網際網路

本文會說明如何將 Apache Superset 公開至網際網路。

主機名稱選取範圍

  1. 決定 Superset 的主機名稱。

    除非您正在使用自訂 DNS 名稱,否則此主機名應該符合模式: <superset-instance-name>.<azure-region>.cloudapp.azure.comsuperset-instance-name 必須是 Azure 區域中的唯一名稱。

    範例: myuniquesuperset.westus3.cloudapp.azure.com

  2. 取得主機名稱的 TLS 憑證,將它放入您的 Key Vault,並將其稱爲 aks-ingress-tls。 了解如何將憑證放入 Azure Key Vault

設定輸入

下列指示會使用 Oauth2Proxy,以 OAuth 授權 Proxy 的形式新增第二層驗證。 此層表示沒有任何未經授權的用戶端觸達 Superset 應用程式。

  1. 將下列秘密新增至您的 Key Vault。

    祕密名稱 描述
    client-id 您的 Azure 服務主體用戶端識別碼。 OAuth Proxy 需要此標識符為秘密。
    oauth2proxy-redis-password Proxy 快取密碼。 OAuth Proxy 用來存取 Kubernetes 上後端 Redis 部署實例的密碼。 產生強式密碼。
    oauth2proxy-cookie-secret 32 個字元的 Cookie 秘密,用來加密 Cookie 資料。 這個祕密必須是 32 個字元。
  2. 在 Superset Azure AD 應用程式設定中新增這些回撥。

    • https://{{superset_hostname}}/oauth2/callback
      • for OAuth2 Proxy
    • https://{{superset_hostname}}/oauth-authorized/azure
      • 適用於 Superset
  3. 將輸入 ngninx 控制器部署到 default 命名空間

    helm install ingress-nginx-superset ingress-nginx/ingress-nginx \
    --namespace default \
    --set controller.service.annotations."service\.beta\.kubernetes\.io/azure-load-balancer-health-probe-request-path"=/healthz \
    --set controller.config.proxy-connect-timeout="60" \
    --set controller.config.proxy-read-timeout="1000" \
    --set controller.config.proxy-send-timeout="1000" \
    --set controller.config.proxy-buffer-size="'64k'" \
    --set controller.config.proxy-buffers-number="8"
    

    如需詳細指示,請參閱這裡的 Azure 指示

    注意

    輸入 nginx 控制器步驟會使用 Kubernetes 命名空間 ingress-basic。 這需要修改,才能使用 default 命名空間。 例如,NAMESPACE=default

  4. 建立 TLS 秘密提供者類別。

    此步驟會說明如何從 Key Vault 讀取 TLS 憑證,並轉換成輸入所要使用的 Kubernetes 秘密:

    在下列 YAML 中更新:

    • {{MSI_CLIENT_ID}} - 指派給 Superset 叢集之受控識別的用戶端識別碼 ($MANAGED_IDENTITY_RESOURCE)。
    • {{KEY_VAULT_NAME}} - 包含祕密的 Azure Key Vault 名稱。
    • {{KEY_VAULT_TENANT_ID}} - Key Vault 所在 Azure 租用戶的識別碼 Guid。

    tls-secretprovider.yaml

    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: azure-tls
    spec:
      provider: azure
      # secretObjects defines the desired state of synced K8s secret objects
      secretObjects:
      - secretName: ingress-tls-csi
        type: kubernetes.io/tls
        data: 
        - objectName: aks-ingress-tls
          key: tls.key
        - objectName: aks-ingress-tls
          key: tls.crt
      parameters:
        usePodIdentity: "false"
        useVMManagedIdentity: "true"
        userAssignedIdentityID: "{{MSI_CLIENT_ID}}"
        # the name of the AKV instance
        keyvaultName: "{{KEY_VAULT_NAME}}"
        objects: |
          array:
            - |
              objectName: aks-ingress-tls
              objectType: secret
        # the tenant ID of the AKV instance
        tenantId: "{{KEY_VAULT_TENANT_ID}}"
    
  5. 建立 OauthProxy 秘密提供者類別。

    在下列 YAML 中更新:

    • {{MSI_CLIENT_ID}} - 指派給 Superset 叢集之受控識別的用戶端識別碼 ($MANAGED_IDENTITY_RESOURCE)。
    • {{KEY_VAULT_NAME}} - 包含祕密的 Azure Key Vault 名稱。
    • {{KEY_VAULT_TENANT_ID}} - Key Vault 所在 Azure 租用戶的識別碼 Guid。

    oauth2-secretprovider.yaml

    # This is a SecretProviderClass example using aad-pod-identity to access the key vault
    apiVersion: secrets-store.csi.x-k8s.io/v1
    kind: SecretProviderClass
    metadata:
      name: oauth2-secret-provider
    spec:
      provider: azure
      parameters:
        useVMManagedIdentity: "true" 
        userAssignedIdentityID: "{{MSI_CLIENT_ID}}"
        usePodIdentity: "false"              # Set to true for using aad-pod-identity to access your key vault
        keyvaultName: "{{KEY_VAULT_NAME}}"   # Set to the name of your key vault
        cloudName: ""                        # [OPTIONAL for Azure] if not provided, the Azure environment defaults to AzurePublicCloud
        objects: |
          array:
            - |
              objectName: oauth2proxy-cookie-secret
              objectType: secret
            - |
              objectName: oauth2proxy-redis-password
              objectType: secret
            - |
              objectName: client-id
              objectType: secret
            - |
              objectName: client-secret
              objectType: secret
        tenantId: "{{KEY_VAULT_TENANT_ID}}"  # The tenant ID of the key vault
      secretObjects:                             
      - secretName: oauth2-secret
        type: Opaque
        data:
        # OauthProxy2 Secrets
        - key: cookie-secret
          objectName: oauth2proxy-cookie-secret
        - key: client-id
          objectName: client-id
        - key: client-secret
          objectName: client-secret
        - key: redis-password
          objectName: oauth2proxy-redis-password
      - secretName: oauth2-redis
        type: Opaque
        data:
        - key: redis-password
          objectName: oauth2proxy-redis-password
    
  6. 建立 OAuth Proxy 的組態。

    在下列 YAML 中更新:

    • {{superset_hostname}} - 主機名稱選取範圍 中所選的面向網際網路主機名稱
    • {{tenant-id}} - 建立服務主體之 Azure 租用戶的識別碼 Guid。

    選擇性: 更新 email_domains 清單。 範例: email_domains = [ "microsoft.com" ]

    oauth2-values.yaml

    # Force the target Kubernetes version (it uses Helm `.Capabilities` if not set).
    # This is especially useful for `helm template` as capabilities are always empty
    # due to the fact that it doesn't query an actual cluster
    kubeVersion:
    
    # OAuth client configuration specifics
    config:
      # OAuth client secret
      existingSecret: oauth2-secret
      configFile: |-
        email_domains = [ ]
        upstreams = [ "file:///dev/null" ]
    
    image:
      repository: "quay.io/oauth2-proxy/oauth2-proxy"
      tag: "v7.4.0"
      pullPolicy: "IfNotPresent"
    
    extraArgs: 
        provider: oidc
        oidc-issuer-url: https://login.microsoftonline.com/<tenant-id>/v2.0
        login-url: https://login.microsoftonline.com/<tenant-id>/v2.0/oauth2/authorize
        redeem-url: https://login.microsoftonline.com/<tenant-id>/v2.0/oauth2/token
        oidc-jwks-url: https://login.microsoftonline.com/common/discovery/keys
        profile-url: https://graph.microsoft.com/v1.0/me
        skip-provider-button: true
    
    ingress:
      enabled: true
      path: /oauth2
      pathType: ImplementationSpecific
      hosts:
      - "{{superset_hostname}}"
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/proxy_buffer_size: 64k
        nginx.ingress.kubernetes.io/proxy_buffers_number: "8"
      tls:
      - secretName: ingress-tls-csi
        hosts:
         - "{{superset_hostname}}"
    
    extraVolumes:
      - name: oauth2-secrets-store
        csi:
          driver: secrets-store.csi.k8s.io
          readOnly: true
          volumeAttributes:
            secretProviderClass: oauth2-secret-provider
      - name: tls-secrets-store
        csi:
          driver: secrets-store.csi.k8s.io
          readOnly: true
          volumeAttributes:
            secretProviderClass: azure-tls
    
    extraVolumeMounts: 
      - mountPath: "/mnt/oauth2_secrets"
        name: oauth2-secrets-store
        readOnly: true
      - mountPath: "/mnt/tls-secrets-store"
        name: tls-secrets-store
        readOnly: true
    
    # Configure the session storage type, between cookie and redis
    sessionStorage:
      # Can be one of the supported session storage cookie/redis
      type: redis
      redis:
        # Secret name that holds the redis-password and redis-sentinel-password values
        existingSecret: oauth2-secret
        # Can be one of sentinel/cluster/standalone
        clientType: "standalone"
    
    # Enables and configure the automatic deployment of the redis subchart
    redis:
      enabled: true
      auth:
        existingSecret: oauth2-secret
    
    # Enables apiVersion deprecation checks
    checkDeprecation: true
    
  7. 部署 OAuth Proxy 資源。

    kubectl apply -f oauth2-secretprovider.yaml
    kubectl apply -f tls-secretprovider.yaml
    helm repo add oauth2-proxy https://oauth2-proxy.github.io/manifests
    helm repo update
    helm upgrade --install --values oauth2-values.yaml oauth2 oauth2-proxy/oauth2-proxy
    
  8. 更新相關聯公用 IP 中的 DNS 標籤。

    1. 在 Azure 入口網站中開啟您的 Superset AKS Kubernetes 叢集。

    2. 在左側導覽中,選取 [屬性]。

    3. 開啟 [基礎結構資源群組] 連結。

    4. 尋找有這些標籤的公用 IP 位址:

      {
        "k8s-azure-cluster-name": "kubernetes",
        "k8s-azure-service": "default/ingress-nginx-controller"
      }
      
    5. 從 [公用 IP] 左側導覽中選取 [設定]。

    6. 輸入 DNS 名稱標籤,將 [主機名稱選取範圍] 定義為 <superset-instance-name>

  9. 確認您已設定 OAuth 的輸入。

    執行 kubectl get ingress 以查看建立的兩個輸入 azure-trino-supersetoauth2-oauth2-proxy。 IP 位址符合上一個步驟中的公用 IP。

    同樣地,在執行 kubectl get services 時,您應該會看到 ingress-nginx-controller 已獲指派 EXTERNAL-IP

    提示

    您可以開啟 http://{{superset_hostname}}/oauth2 來測試 OAuth 路徑是否正常運作。

  10. 定義輸入以提供對 Superset 的存取權,但將所有未經授權的呼叫重新導向至 /oauth

    在下列 YAML 中更新:

    ingress.yaml

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      annotations:
        kubernetes.io/ingress.class: nginx
        nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start?rd=$escaped_request_uri
        nginx.ingress.kubernetes.io/auth-url: http://oauth2-oauth2-proxy.default.svc.cluster.local:80/oauth2/auth
        nginx.ingress.kubernetes.io/proxy-buffer-size: 64k
        nginx.ingress.kubernetes.io/proxy-buffers-number: "8"
        nginx.ingress.kubernetes.io/rewrite-target: /$1
      generation: 1
      labels:
        app.kubernetes.io/name: azure-trino-superset
      name: azure-trino-superset
      namespace: default
    spec:
      rules:
      - host: "{{superset_hostname}}"
        http:
          paths:
          - backend:
              service:
                name: superset
                port:
                  number: 8088
            path: /(.*)
            pathType: Prefix
      tls:
      - hosts:
        - "{{superset_hostname}}"
        secretName: ingress-tls-csi
    
  11. 部署您的輸入。

          kubectl apply -f ingress.yaml
    
  12. 測試。

    在您的瀏覽器中開啟 https://{{superset_hostname}}/

疑難排解輸入

提示

若要重設輸入部署,請執行下列命令:

kubectl delete secret ingress-tls-csi
kubectl delete secret oauth2-secret
helm uninstall oauth2-proxy
helm uninstall ingress-nginx-superset
kubectl delete ingress azure-trino-superset

刪除這些資源之後,您必須從頭重新啟動這些指示。

無效的安全性憑證: Kubernetes 輸入控制器假憑證

這會導致您的瀏覽器/客戶端發生 TLS 憑證驗證錯誤。 若要查看此錯誤,請在瀏覽器中檢查憑證。

此問題的一般原因是您的憑證設定錯誤:

  • 確認您可以在 Kubernetes 中看到您的憑證: kubectl get secret ingress-tls-csi --output yaml

  • 確認您的 CN 符合憑證中提供的 CN。

    • CN 不符會記錄在輸入 Pod 中。 執行 kubectl logs <ingress pod> 即可看到這些記錄。

      範例: kubectl logs ingress-nginx-superset-controller-f5dd9ccfd-qz8wc

    CN 不符錯誤會使用此記錄行來描述:

    SSL 憑證 “default/ingress-tls-csi” 不包含一般名稱或伺服器的主體別名 "{server name}": x509: 憑證適用於 {invalid hostname},而不是 {actual hostname}

無法解析主機

如果無法解析 Superset 執行個體的主機名稱,公用 IP 就不會獲指派主機名稱。 如果沒有此指派,DNS 就無法解析主機名稱。

確認區段中的步驟 更新相關聯公用 IP 中的 DNS 標籤

404 / nginx

Nginx 輸入控制器找不到 Superset。 請執行 kubectl get services 並檢查是否有 superset 服務,以確定 Superset 已部署。 確認 ingress.yaml 中的後端服務符合 Superset 所使用的服務名稱。

503 服務暫時無法使用 / nginx

服務正在執行,但無法存取。 檢查服務連接埠號碼和服務名稱。