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
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
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.
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. 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
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 nombresdefault
. p. ej.NAMESPACE=default
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}}"
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
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
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
Actualice la etiqueta DNS en la dirección IP pública asociada.
Abra el clúster de Kubernetes de AKS de Superset en Azure Portal.
Seleccione "Propiedades" en el panel de navegación izquierdo.
Abra el vínculo "Grupo de recursos de infraestructura".
Busque la dirección IP pública con estas etiquetas:
{ "k8s-azure-cluster-name": "kubernetes", "k8s-azure-service": "default/ingress-nginx-controller" }
Seleccione "Configuración" en el panel de navegación izquierdo de la dirección IP pública.
Escriba la etiqueta de nombre DNS con el
<superset-instance-name>
definido en selección de nombre de host.
Compruebe que la entrada de OAuth está configurada.
Ejecute
kubectl get ingress
para ver las dos entradas creadasazure-trino-superset
yoauth2-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 aingress-nginx-controller
se le asignó unEXTERNAL-IP
.Sugerencia
Puede abrir
http://{{superset_hostname}}/oauth2
para probar que la ruta de acceso de OAuth funciona.Defina una entrada para proporcionar acceso a Superset, pero redirija todas las llamadas no autorizadas a
/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
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
Implemente la entrada.
kubectl apply -f ingress.yaml
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.