Freigeben über


Verfügbarmachen von Apache Superset im Internet

In diesem Artikel erfahren Sie, wie Apache Superset im Internet verfügbar gemacht wird.

Hostnamenauswahl

  1. Entscheiden Sie sich für einen Hostnamen für Superset.

    Sofern Sie keinen benutzerdefinierten DNS-Namen verwenden, sollte dieser Hostname mit dem folgenden Muster übereinstimmen: <superset-instance-name>.<azure-region>.cloudapp.azure.com. Der superset-instance-name muss innerhalb der Azure-Region eindeutig sein.

    Beispiel: myuniquesuperset.westus3.cloudapp.azure.com

  2. Rufen Sie ein TLS-Zertifikat für den Hostnamen ab, platzieren Sie es in Ihrer Key Vault-Instanz, und nennen Sie es aks-ingress-tls. Eine entsprechende Anleitung finden Sie unter Erste Schritte mit Key Vault-Zertifikaten.

Einrichten des Eingangs

Die folgende Anleitung fügt eine zweite Authentifizierungsebene in Form eines OAuth-Autorisierungsproxys unter Verwendung von Oauth2Proxy hinzu. Diese Ebene bedeutet, dass keine nicht autorisierten Clients die Superset-Anwendung erreichen.

  1. Fügen Sie ihrer Key Vault-Instanz die folgenden Geheimnisse hinzu:

    Geheimnisname Beschreibung
    client-id Die Client-ID Ihres Azure-Dienstprinzipals. Für den OAuth-Proxy muss diese ID ein Geheimnis sein.
    oauth2proxy-redis-password Das Kennwort für den Proxycache. Hierbei handelt es sich um das Kennwort, das vom OAuth-Proxy verwendet wird, um auf die Back-End-Redis-Bereitstellungsinstanz in Kubernetes zuzugreifen. Generieren Sie ein sicheres Kennwort.
    oauth2proxy-cookie-secret Cookie-Geheimnis mit 32 Zeichen für die Verschlüsselung von Cookie-Daten. Dieses Geheimnis muss 32 Zeichen lang sein.
  2. Fügen Sie in Ihrer Superset Azure AD-Anwendungskonfiguration die folgenden Rückrufe hinzu:

    • https://{{superset_hostname}}/oauth2/callback
      • Für den OAuth2-Proxy
    • https://{{superset_hostname}}/oauth-authorized/azure
      • Für Superset
  3. Stellen Sie den ngninx-Eingangsdatencontroller im Namespace default bereit.

    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"
    

    Ausführliche Anweisungen finden Sie unter Azure-Anweisungen hier.

    Hinweis

    In den Schritten für den nginx-Eingangsdatencontroller wird der Kubernetes-Namespace ingress-basic verwendet. Dies muss mithilfe des Namespace default geändert werden. Beispiel: NAMESPACE=default

  4. Erstellen Sie die TLS-Geheimnisanbieterklasse.

    In diesem Schritt erfahren Sie, wie das TLS-Zertifikat aus der Key Vault-Instanz gelesen und in ein Kubernetes-Geheimnis umgewandelt wird, das für eingehenden Datenverkehr verwendet wird:

    Aktualisieren Sie den folgenden YAML-Code:

    • {{MSI_CLIENT_ID}}: Die Client-ID der verwalteten Identität, die dem Superset-Cluster zugewiesen ist ($MANAGED_IDENTITY_RESOURCE).
    • {{KEY_VAULT_NAME}}: Der Name der Azure Key Vault-Instanz, die die Geheimnisse enthält.
    • {{KEY_VAULT_TENANT_ID}}: Die Bezeichner-GUID des Azure-Mandanten, in dem sich die Key Vault-Instanz befindet.

    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. Erstellen Sie die OauthProxy-Geheimnisanbieterklasse.

    Aktualisieren Sie den folgenden YAML-Code:

    • {{MSI_CLIENT_ID}}: Die Client-ID der verwalteten Identität, die dem Superset-Cluster zugewiesen ist ($MANAGED_IDENTITY_RESOURCE).
    • {{KEY_VAULT_NAME}}: Der Name der Azure Key Vault-Instanz, die die Geheimnisse enthält.
    • {{KEY_VAULT_TENANT_ID}}: Die Bezeichner-GUID des Azure-Mandanten, in dem sich der Schlüsseltresor befindet.

    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. Erstellen Sie die Konfiguration für den OAuth-Proxy.

    Aktualisieren Sie den folgenden YAML-Code:

    • {{superset_hostname}} – der Internet-Hostname, der bei der Hostnamenauswahl ausgewählt wurde
    • {{tenant-id}}: Die Bezeichner-GUID des Azure-Mandanten, in dem Ihr Dienstprinzipal erstellt wurde.

    Optional: Aktualisieren Sie die Liste „email_domains“. Beispiel: 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. Stellen Sie OAuth-Proxyressourcen bereit.

    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. Aktualisieren Sie die DNS-Bezeichnung in der zugeordneten öffentlichen IP-Adresse.

    1. Öffnen Sie Ihren Superset AKS-Kubernetes-Cluster im Azure-Portal.

    2. Wählen Sie im linken Navigationsbereich die Option „Eigenschaften“ aus.

    3. Öffnen Sie den Link „Infrastrukturressourcengruppe“.

    4. Suchen Sie nach der öffentlichen IP-Adresse mit folgenden Tags:

      {
        "k8s-azure-cluster-name": "kubernetes",
        "k8s-azure-service": "default/ingress-nginx-controller"
      }
      
    5. Wählen Sie im linken Navigationsbereich für die öffentliche IP-Adresse die Option „Konfiguration“ aus.

    6. Geben Sie die DNS-Namensbezeichnung mit dem in der Hostnamenauswahl definierten <superset-instance-name> ein.

  9. Vergewissern Sie sich, dass Ihre eingehenden Daten für OAuth konfiguriert sind.

    Führen Sie kubectl get ingress aus, um die zwei erstellten Eingänge azure-trino-superset und oauth2-oauth2-proxy zu sehen. Die IP-Adresse entspricht der öffentlichen IP-Adresse aus dem vorherigen Schritt.

    Ebenso sollte beim Ausführen von kubectl get services zu sehen sein, dass ingress-nginx-controller eine externe IP-Adresse (EXTERNAL-IP) zugewiesen wurde.

    Tipp

    Sie können http://{{superset_hostname}}/oauth2 öffnen, um zu testen, dass der OAuth-Pfad funktioniert.

  10. Definieren Sie einen Eingang, um Zugriff auf Superset bereitzustellen, leiten Sie jedoch alle nicht autorisierten Aufrufe an /oauth um.

    Aktualisieren Sie den folgenden YAML-Code:

    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. Stellen Sie Ihre eingehenden Daten bereit.

          kubectl apply -f ingress.yaml
    
  12. Tests durchführen

    Öffnen Sie https://{{superset_hostname}}/ in Ihrem Browser.

Behandeln von Problemen mit eingehenden Daten

Tipp

Die Bereitstellung kann durch Ausführen dieser Befehle zurückgesetzt werden:

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

Nach dem Löschen dieser Ressourcen müssen Sie wieder mit dem ersten Schritt dieser Anleitung beginnen.

Ungültiges Sicherheitszertifikat: Gefälschtes Zertifikat für den Kubernetes-Eingangsdatencontroller

Das verursacht einen TLS-Zertifikatüberprüfungsfehler in Ihrem Browser/Client. Um diesen Fehler anzuzeigen, überprüfen Sie das Zertifikat in einem Browser.

Die Ursache für dieses Problem besteht meist darin, dass Ihr Zertifikat falsch konfiguriert ist:

  • Vergewissern Sie sich, dass das Zertifikat in Kubernetes angezeigt wird: kubectl get secret ingress-tls-csi --output yaml

  • Vergewissern Sie sich, dass Ihr CN dem CN aus Ihrem Zertifikat entspricht.

    • Der CN-Konflikt wird im Eingangspod protokolliert. Diese Protokolle können durch Ausführen von kubectl logs <ingress pod>angezeigt werden.

      Beispiel: kubectl logs ingress-nginx-superset-controller-f5dd9ccfd-qz8wc

    Der CN-Konfliktfehler wird mit dieser Protokollzeile beschrieben:

    Das SSL-Zertifikat „default/ingress-tls-csi” enthält keinen allgemeinen Namen oder alternativen Antragstellernamen für den Server „{Servername}”: x509: Zertifikat ist gültig für {ungültiger Hostname}, nicht {tatsächlicher Hostname}

Host konnte nicht aufgelöst werden

Wenn der Hostname für die Superset-Instanz nicht aufgelöst werden kann, ist der öffentlichen IP-Adresse kein Hostname zugewiesen. Ohne diese Zuordnung kann DNS den Hostnamen nicht auflösen.

Überprüfen Sie die Schritte im Abschnitt Aktualisieren der DNS-Bezeichnung in der zugeordneten öffentlichen IP-Adresse.

404 / nginx

Der Nginx-Eingangscontroller kann Superset nicht finden. Stellen Sie sicher, dass Superset bereitgestellt wird, indem Sie kubectl get services ausführen und überprüfen, ob ein superset-Dienst vorhanden ist. Überprüfen Sie, ob der Back-End-Dienst in ingress.yaml dem für Superset verwendeten Dienstnamen entspricht.

503 Service temporarily unavailable / nginx

Der Dienst wird ausgeführt, ist aber nicht zugänglich. Überprüfen Sie die Dienstportnummern und den Dienstnamen.