Compartir a través de


Exposición de Apache Superset a Internet

En este artículo se describe cómo exponer Apache Superset a Internet.

Selección de nombre de host

  1. Decida sobre un nombre de host para Superset.

    A menos que use un nombre DNS personalizado, este nombre de host debe coincidir con el patrón: <superset-instance-name>.<azure-region>.cloudapp.azure.com. El nombre de instancia de superconjunto debe ser único en la región de Azure.

    Ejemplo: myuniquesuperset.westus3.cloudapp.azure.com

  2. Obtenga un certificado TLS para el nombre de host y colóquelo en Key Vault y llámelo aks-ingress-tls. Aprenda a colocar un certificado en una instancia de Azure Key Vault.

Entrada de instalación

En las instrucciones siguientes se agrega una segunda capa de autenticación en forma de proxy de autorización de OAuth mediante Oauth2Proxy. Esta capa significa que ningún cliente no autorizado llega a la aplicación Superset.

  1. Agregue los siguientes secretos a la instancia de Key Vault.

    Nombre del secreto Descripción
    client-id Id. de cliente de la entidad de servicio de Azure. El proxy de OAuth requiere que este identificador sea un secreto.
    oauth2proxy-redis-password Contraseña de caché del proxy. Contraseña usada por el proxy de OAuth para acceder a la instancia de implementación de Redis back-end en Kubernetes. Genere una contraseña segura.
    oauth2proxy-cookie-secret Secreto de cookies de 32 caracteres, que se usa para cifrar los datos de la cookie. Este secreto debe tener 32 caracteres de longitud.
  2. Agregue estas devoluciones de llamada en la configuración de la aplicación superconjunto de Azure AD.

    • https://{{superset_hostname}}/oauth2/callback
      • para el Proxy de OAuth2
    • https://{{superset_hostname}}/oauth-authorized/azure
      • para Superset
  3. Implementación del controlador ngninx de entrada en el espacio de nombres 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"
    

    Para obtener instrucciones detalladas, consulte instrucciones de Azure aquí.

    Nota:

    Los pasos del controlador nginx de entrada usan el espacio de nombres de Kubernetes ingress-basic. Esto debe modificarse mediante el espacio de nombres default. p. ej. NAMESPACE=default

  4. Cree la clase de proveedor de secretos TLS.

    En este paso se describe cómo se lee el certificado TLS de Key Vault y se transforma en un secreto de Kubernetes que usará la entrada:

    Actualice el siguiente código de YAML:

    • {{MSI_CLIENT_ID}}: el id. de cliente de la identidad administrada asignada al clúster de Superset ($MANAGED_IDENTITY_RESOURCE).
    • {{KEY_VAULT_NAME}}: el nombre de la instancia de Azure Key Vault que contiene los secretos.
    • {{KEY_VAULT_TENANT_ID}}: el GUID de identificador del inquilino de Azure donde se encuentra la instancia de 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. Crear la clase de proveedor secreto de OauthProxy.

    Actualice el siguiente código de YAML:

    • {{MSI_CLIENT_ID}}: el id. de cliente de la identidad administrada asignada al clúster de Superset ($MANAGED_IDENTITY_RESOURCE).
    • {{KEY_VAULT_NAME}}: el nombre de la instancia de Azure Key Vault que contiene los secretos.
    • {{KEY_VAULT_TENANT_ID}}: el GUID de identificador del inquilino de Azure donde se encuentra el almacén de claves.

    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. Cree la configuración para el Proxy de OAuth.

    Actualice el siguiente código de YAML:

    • {{superset_hostname}}: el nombre de host accesible desde Internet elegido en selección de nombre de host
    • {{tenant-id}}: el GUID de identificador del inquilino de Azure donde se creó la entidad de servicio.

    Opcional: actualizar la lista de email_domains. Ejemplo: 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. Implemente recursos proxy de 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. Actualice la etiqueta DNS en la dirección IP pública asociada.

    1. Abra el clúster de Kubernetes de AKS de Superset en Azure Portal.

    2. Seleccione "Propiedades" en el panel de navegación izquierdo.

    3. Abra el vínculo "Grupo de recursos de infraestructura".

    4. Busque la dirección IP pública con estas etiquetas:

      {
        "k8s-azure-cluster-name": "kubernetes",
        "k8s-azure-service": "default/ingress-nginx-controller"
      }
      
    5. Seleccione "Configuración" en el panel de navegación izquierdo de la dirección IP pública.

    6. Escriba la etiqueta de nombre DNS con el <superset-instance-name> definido en selección de nombre de host.

  9. Compruebe que la entrada de OAuth está configurada.

    Ejecute kubectl get ingress para ver las dos entradas creadas azure-trino-superset y oauth2-oauth2-proxy. La dirección IP coincide con la dirección IP pública del paso anterior.

    Del mismo modo, al ejecutar kubectl get services debería ver que a ingress-nginx-controller se le asignó un EXTERNAL-IP.

    Sugerencia

    Puede abrir http://{{superset_hostname}}/oauth2 para probar que la ruta de acceso de OAuth funciona.

  10. Defina una entrada para proporcionar acceso a Superset, pero redirija todas las llamadas no autorizadas a /oauth.

    Actualice el siguiente código de 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. Implemente la entrada.

          kubectl apply -f ingress.yaml
    
  12. Hacer pruebas.

    Abra https://{{superset_hostname}}/ en el explorador.

Solución de problemas de entrada

Sugerencia

Para restablecer la implementación de entrada, ejecute estos comandos:

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

Después de eliminar estos recursos, deberá reiniciar estas instrucciones desde el principio.

Certificado de seguridad no válido: Certificado falso del controlador de entrada de Kubernetes

Esto provoca un error de comprobación de certificados TLS en el explorador o cliente. Para ver este error, inspeccione el certificado en un explorador.

La causa habitual de este problema es que el certificado está mal configurado:

  • Compruebe que puede ver el certificado en Kubernetes: kubectl get secret ingress-tls-csi --output yaml

  • Compruebe que el CN coincide con el CN proporcionado en el certificado.

    • La falta de coincidencia de CN se registra en el pod de entrada. Estos registros se pueden ver ejecutando kubectl logs <ingress pod>.

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

    El error de coincidencia de CN se describe con esta línea de registro:

    El certificado SSL "default/ingress-tls-csi" no contiene un nombre común ni un nombre alternativo del firmante para el servidor "{nombre de servidor}": x509: el certificado es válido para {nombre de host no válido}, no {nombre de host real}

No se pudo resolver el host

Si el nombre de host no se puede resolver para la instancia de Superset, la dirección IP pública no tiene asignado un nombre de host. Sin esta asignación, DNS no puede resolver el nombre de host.

Compruebe los pasos de la sección Actualizar la etiqueta DNS en la dirección IP pública asociada.

404 / nginx

El controlador de entrada Nginx no encuentra Superset. Asegúrese de que Superset se implementa ejecutando kubectl get services y comprobando la presencia de un servicio de superset. Compruebe que el servicio back-end de ingress.yaml coincide con el nombre de servicio usado para Superset.

503 Servicio temporalmente no disponible / nginx

El servicio se está ejecutando, pero no es accesible. Compruebe los números de puerto del servicio y el nombre del servicio.