次の方法で共有


Apache Superset をインターネットに公開する

この記事では、Apache Superset をインターネットに公開する方法について説明します。

ホスト名の選択

  1. スーパーセットのホスト名を決定します。

    カスタム DNS 名を使用している場合を除き、このホスト名は次のパターンと一致する必要があります: <superset-instance-name>.<azure-region>.cloudapp.azure.comsuperset-instance-name は、Azure リージョン内で一意である必要があります。

    例: myuniquesuperset.westus3.cloudapp.azure.com

  2. ホスト名の TLS 証明書を取得して Key Vault に配置し、aks-ingress-tls呼び出します。 Azure Key Vaultに証明書を配置する方法について説明します。

イングレスを設定する

次の手順では、Oauth2Proxy を使用して、OAuth 承認プロキシの形式で認証の 2 番目のレイヤーを追加します。 このレイヤーは、承認されていないクライアントがスーパーセット アプリケーションに到達しなかったことを意味します。

  1. 次のシークレットを Key Vault に追加します。

    シークレット名 説明
    クライアントID Azure サービス プリンシパル クライアント ID。 OAuth プロキシでは、この ID がシークレットである必要があります。
    oauth2proxy-redis-password プロキシ キャッシュのパスワード。 Kubernetes 上のバックエンド Redis デプロイ インスタンスにアクセスするために OAuth プロキシによって使用されるパスワード。 強力なパスワードを生成します。
    oauth2proxy-cookie-secret 32 文字の Cookie シークレット。Cookie データの暗号化に使用されます。 このシークレットの長さは 32 文字にする必要があります。
  2. これらのコールバックを Superset Azure AD アプリケーション構成に追加します。

    • https://{{superset_hostname}}/oauth2/callback
      • OAuth2 プロキシの場合
    • https://{{superset_hostname}}/oauth-authorized/azure
      • スーパーセットの場合
  3. イングレス 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

  4. TLS シークレット プロバイダー クラスを作成します。

    この手順では、TLS 証明書が Key Vault から読み取られ、イングレスで使用される Kubernetes シークレットに変換される方法について説明します。

    次の yaml で更新します。

    • {{MSI_CLIENT_ID}} - スーパーセット クラスターに割り当てられたマネージド ID のクライアント ID ($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}}"
    
  5. OauthProxy シークレット プロバイダー クラスを作成します。

    次の yaml で更新します。

    • {{MSI_CLIENT_ID}} - スーパーセット クラスターに割り当てられたマネージド ID のクライアント ID ($MANAGED_IDENTITY_RESOURCE)。
    • {{KEY_VAULT_NAME}} - シークレットを含む Azure Key Vault の名前。
    • {{KEY_VAULT_TENANT_ID}} - キー ボールトが配置されている 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
    
  6. OAuth プロキシの構成を作成します。

    次の 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
    
  7. 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. 関連付けられているパブリック IP の DNS ラベルを更新します。

    1. Azure portal で Superset AKS Kubernetes クラスターを開きます。

    2. 左側のナビゲーションから [プロパティ] を選択します。

    3. [インフラストラクチャ リソース グループ] リンクを開きます。

    4. 次のタグを持つパブリック IP アドレスを見つけます。

      {
        "k8s-azure-cluster-name": "kubernetes",
        "k8s-azure-service": "default/ingress-nginx-controller"
      }
      
    5. パブリック IP の左側のナビゲーションから [構成] を選択します。

    6. のホスト名選択でに定義されている <superset-instance-name> の DNS 名ラベルを入力します。

  9. OAuth のイングレスが構成されていることを確認します。

    kubectl get ingress を実行して、azure-trino-supersetoauth2-oauth2-proxyに作成された 2 つのイングレスを確認します。 IP アドレスは、前の手順のパブリック IP と一致します。

    同様に、kubectl get services を実行すると、ingress-nginx-controllerEXTERNAL-IPが割り当てられていることがわかります。

    ヒント

    http://{{superset_hostname}}/oauth2 を開いて、OAuth パスが動作していることをテストできます。

  10. 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
    
  11. イングレスを配備しなさい。

          kubectl apply -f ingress.yaml
    
  12. テスト。

    ブラウザーで 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 の不一致がイングレス ポッドに記録されます。 これらのログは、kubectl logs <ingress pod>を実行することで確認できます。

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

    CN 不一致エラーは、次のログ行で説明されています。

    SSL 証明書 "default/ingress-tls-csi" にサーバー "{server name}" の共通名またはサブジェクトの別名が含まれていません: x509: 証明書は {invalid hostname} に対して有効であり、{実際のホスト名} には含まれません

ホストを解決できませんでした

スーパーセット インスタンスのホスト名を解決できない場合、パブリック IP にはホスト名が割り当てられません。 この割り当てがないと、DNS はホスト名を解決できません。

関連するパブリック IP の DNS ラベルを更新セクションの手順を確認します。

404 / nginx

Nginx イングレス コントローラーがスーパーセットを見つけることができません。 kubectl get services を実行し、superset サービスの存在を確認して、Superset がデプロイされていることを確認します。 ingress.yaml のバックエンド サービスが、Superset に使用されるサービス名と一致するかどうかを確認します。

503 サービス一時的に利用できない/nginx

サービスは実行中ですが、アクセスできません。 サービス ポート番号とサービス名を確認します。