將 Apache Superset 公開至網際網路
本文會說明如何將 Apache Superset 公開至網際網路。
主機名稱選取範圍
決定 Superset 的主機名稱。
除非您正在使用自訂 DNS 名稱,否則此主機名應該符合模式:
<superset-instance-name>.<azure-region>.cloudapp.azure.com
。 superset-instance-name 必須是 Azure 區域中的唯一名稱。範例:
myuniquesuperset.westus3.cloudapp.azure.com
取得主機名稱的 TLS 憑證,將它放入您的 Key Vault,並將其稱爲
aks-ingress-tls
。 了解如何將憑證放入 Azure Key Vault。
設定輸入
下列指示會使用 Oauth2Proxy,以 OAuth 授權 Proxy 的形式新增第二層驗證。 此層表示沒有任何未經授權的用戶端觸達 Superset 應用程式。
將下列秘密新增至您的 Key Vault。
祕密名稱 描述 client-id 您的 Azure 服務主體用戶端識別碼。 OAuth Proxy 需要此標識符為秘密。 oauth2proxy-redis-password Proxy 快取密碼。 OAuth Proxy 用來存取 Kubernetes 上後端 Redis 部署實例的密碼。 產生強式密碼。 oauth2proxy-cookie-secret 32 個字元的 Cookie 秘密,用來加密 Cookie 資料。 這個祕密必須是 32 個字元。 在 Superset Azure AD 應用程式設定中新增這些回撥。
https://{{superset_hostname}}/oauth2/callback
- for OAuth2 Proxy
https://{{superset_hostname}}/oauth-authorized/azure
- 適用於 Superset
將輸入 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
建立 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}}"
建立 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
建立 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
部署 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
更新相關聯公用 IP 中的 DNS 標籤。
在 Azure 入口網站中開啟您的 Superset AKS Kubernetes 叢集。
在左側導覽中,選取 [屬性]。
開啟 [基礎結構資源群組] 連結。
尋找有這些標籤的公用 IP 位址:
{ "k8s-azure-cluster-name": "kubernetes", "k8s-azure-service": "default/ingress-nginx-controller" }
從 [公用 IP] 左側導覽中選取 [設定]。
輸入 DNS 名稱標籤,將 [主機名稱選取範圍] 定義為
<superset-instance-name>
。
確認您已設定 OAuth 的輸入。
執行
kubectl get ingress
以查看建立的兩個輸入azure-trino-superset
和oauth2-oauth2-proxy
。 IP 位址符合上一個步驟中的公用 IP。同樣地,在執行
kubectl get services
時,您應該會看到ingress-nginx-controller
已獲指派EXTERNAL-IP
。提示
您可以開啟
http://{{superset_hostname}}/oauth2
來測試 OAuth 路徑是否正常運作。定義輸入以提供對 Superset 的存取權,但將所有未經授權的呼叫重新導向至
/oauth
。在下列 YAML 中更新:
{{superset_hostname}}
- 主機名稱選取範圍 中所選的面向網際網路主機名稱
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
部署您的輸入。
kubectl apply -f ingress.yaml
測試。
在您的瀏覽器中開啟
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
服務正在執行,但無法存取。 檢查服務連接埠號碼和服務名稱。