Condividi tramite


Esporre Apache Superset su Internet

Questo articolo descrive come esporre Apache Superset a Internet.

Selezione del nome host

  1. Scegliere un nome host per Superset.

    A meno che non si usi un nome DNS personalizzato, questo nome host deve corrispondere al modello <superset-instance-name>.<azure-region>.cloudapp.azure.com. Il superset-instance-name deve essere univoco all'interno dell'area di Azure.

    Esempio: myuniquesuperset.westus3.cloudapp.azure.com

  2. Ottenere un certificato TLS per il nome host e inserirlo nel Key Vault, dandogli il nome aks-ingress-tls. Informazioni su come inserire un certificato in un Azure Key Vault.

Configurare l'ingresso

Le istruzioni seguenti aggiungono un secondo livello di autenticazione sotto forma di proxy di autorizzazione OAuth usando Oauth2Proxy. Questo livello significa che nessun client non autorizzato raggiunge l'applicazione Superset.

  1. Aggiungi i seguenti segreti al tuo Key Vault.

    Nome segreto Descrizione
    ID cliente ID cliente principale del servizio di Azure. Il proxy OAuth richiede che questo ID sia un segreto.
    oauth2proxy-redis-password Password della cache proxy. Password usata dal proxy OAuth per accedere all'istanza di distribuzione Redis back-end in Kubernetes. Generare una password sicura.
    oauth2proxy-cookie-secret Segreto cookie di 32 caratteri, usato per crittografare i dati del cookie. Questo segreto deve avere una lunghezza di 32 caratteri.
  2. Aggiungere i callback nella configurazione dell'applicazione Superset Azure AD.

    • https://{{superset_hostname}}/oauth2/callback
      • per OAuth2 Proxy
    • https://{{superset_hostname}}/oauth-authorized/azure
      • per Superset
  3. Distribuire il controller ingress nginx nello spazio dei nomi 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"
    

    Per istruzioni dettagliate, vedere le istruzioni di Azure qui .

    Nota

    I passaggi del controller Ingress NGINX utilizzano lo spazio dei nomi Kubernetes ingress-basic. Questa operazione deve essere modificata usando lo spazio dei nomi default. ad esempio NAMESPACE=default

  4. Creare la classe del provider di segreto TLS.

    Questo passaggio descrive come il certificato TLS viene letto dal Key Vault e trasformato in un segreto Kubernetes da utilizzare da ingress:

    Eseguire l'aggiornamento nel file yaml seguente:

    • {{MSI_CLIENT_ID}} : ID client dell'identità gestita assegnata al cluster Superset ($MANAGED_IDENTITY_RESOURCE).
    • {{KEY_VAULT_NAME}}: nome di Azure Key Vault contenente i segreti.
    • {{KEY_VAULT_TENANT_ID}}: GUID del tenant di Azure dove si trova il Key Vault.

    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. Creare la OauthProxy Secret Provider Classe.

    Eseguire l'aggiornamento nel file yaml seguente:

    • {{MSI_CLIENT_ID}} : ID client dell'identità gestita assegnata al cluster Superset ($MANAGED_IDENTITY_RESOURCE).
    • {{KEY_VAULT_NAME}}: Il nome dell'Azure Key Vault contenente i segreti.
    • {{KEY_VAULT_TENANT_ID}} - Il GUID del tenant di Azure in cui si trova la cassaforte delle chiavi.

    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. Creare la configurazione per il proxy OAuth.

    Eseguire l'aggiornamento nel file yaml seguente:

    • {{superset_hostname}}: nome host con connessione Internet scelto nella selezione del nome host
    • {{tenant-id}}: GUID dell'identificatore del tenant di Azure in cui è stata creata l'entità servizio.

    Facoltativo: aggiornare l'elenco dei domini email. Esempio: 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. Distribuire le risorse proxy OAuth.

    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. Aggiornare l'etichetta DNS nell'indirizzo IP pubblico associato.

    1. Apri il tuo cluster Kubernetes Superset AKS nel portale di Azure.

    2. Selezionare "Proprietà" dalla barra di navigazione a sinistra.

    3. Aprire il collegamento "Gruppo di risorse infrastrutturali".

    4. Trovare l'indirizzo IP pubblico con questi tag:

      {
        "k8s-azure-cluster-name": "kubernetes",
        "k8s-azure-service": "default/ingress-nginx-controller"
      }
      
    5. Selezionare "Configurazione" dalla sezione di navigazione a sinistra sotto "IP pubblico."

    6. Immettere l'etichetta del nome DNS definita con il <superset-instance-name> nella selezione del nome host .

  9. Verificare che l'ingresso per OAuth sia configurato.

    Eseguire kubectl get ingress per visualizzare i due ingressi creati azure-trino-superset e oauth2-oauth2-proxy. L'indirizzo IP corrisponde all'indirizzo IP pubblico del passaggio precedente.

    Analogamente, quando si esegue kubectl get services si noterà che ingress-nginx-controller è stato assegnato un EXTERNAL-IP.

    Consiglio

    È possibile aprire http://{{superset_hostname}}/oauth2 per verificare che il percorso OAuth funzioni.

  10. Definire un ingresso per fornire l'accesso a Superset, ma reindirizzare tutte le chiamate non autorizzate a /oauth.

    Eseguire l'aggiornamento nel file yaml seguente:

    • {{superset_hostname}}: nome host con connessione Internet scelto nella selezione del nome host

    in ingresso.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. Implementare il vostro ingresso.

          kubectl apply -f ingress.yaml
    
  12. Test.

    Aprire https://{{superset_hostname}}/ nel browser.

Risoluzione dei problemi di ingresso

Suggerimento

Per reimpostare la distribuzione in ingresso, eseguire questi comandi:

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

Dopo aver eliminato queste risorse, sarà necessario riavviare queste istruzioni dall'inizio.

Certificato di sicurezza non valido: Certificato falso del controller di ingresso Kubernetes

Ciò causa un errore di verifica del certificato TLS nel browser o nel client. Per visualizzare questo errore, controllare il certificato in un browser.

La causa consueta di questo problema è che il certificato non è configurato correttamente:

  • Verificare che sia possibile visualizzare il certificato in Kubernetes: kubectl get secret ingress-tls-csi --output yaml

  • Verificare che il CN corrisponda al CN fornito nel certificato.

    • La mancata corrispondenza CN viene registrata nel pod di ingresso. Questi log possono essere visualizzati eseguendo kubectl logs <ingress pod>.

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

    L'errore di mancata corrispondenza CN viene descritto con questa riga di Log:

    Il certificato SSL "default/ingress-tls-csi" non contiene un nome comune o un nome alternativo soggetto per il server "{nome server}": x509: certificato valido per {nome host non valido}, non {nome host effettivo}

Impossibile risolvere l'host

Se il nome host non può essere risolto per l'istanza superset, all'indirizzo IP pubblico non è assegnato un nome host. Senza questa assegnazione, DNS non è in grado di risolvere il nome host.

Verificare i passaggi nella sezione Aggiornare l'etichetta DNS nell'indirizzo IP pubblico associato.

404/ nginx

Il controller di ingresso Nginx non riesce a trovare Superset. Assicuratevi che Superset sia implementato eseguendo kubectl get services e verificando la presenza di un servizio superset. Verificare che il servizio backend in ingress.yaml corrisponda al nome del servizio usato per Superset.

503 Servizio temporaneamente non disponibile/nginx

Il servizio è in esecuzione ma inaccessibile. Controllare i numeri di porta del servizio e il nome del servizio.