LoginSignup
3
4

More than 3 years have passed since last update.

AWS ALB Ingress Controller を External DNS と Cognito と連携させる on EKS

Last updated at Posted at 2020-02-28

以下の構成を作成し、Cognito 認証を終えたトラフィックのみ eks の世界に到達できるようにします。

20200228_CognitoALBExternalDNSonk8s.png

環境

Kubernetes バージョン : 1.14
AWS ALB Ingress Controller バージョン : v1.1.5

EKS クラスター作成

  • まずクラスターを作成

eksctl create cluster --name=k8s-cluster

ALB Ingress Controller のデプロイ

  • Ingress リソースがデプロイされたタイミングで ALB を作成させる
  1. IAM OIDC(OpenID Connect) プロバイダーを作成してクラスターに関連付ける

    $ eksctl utils associate-iam-oidc-provider --region=ap-northeast-1 --cluster=k8s-cluster --approve

  2. AWS IAM => ID プロバイダーを確認し、タイプ OpenIDConnect のプロバイダが作成されていることを確認

  3. ALB Ingress Controller Pod にアタッチする IAM ポリシー作成

    aws iam create-policy \
        --policy-name ALBIngressControllerIAMPolicy \
        --policy-document https://kubernetes-sigs.github.io/aws-alb-ingress-controller/examples/iam-policy.json
    
  4. 返ってきたARNを控える

    {
        "Policy": {
            "PolicyName": "ALBIngressControllerIAMPolicy",
            "PermissionsBoundaryUsageCount": 0,
            "AttachmentCount": 0,
            "IsAttachable": true,
            "PolicyId": "POLICYID",
            "DefaultVersionId": "v1",
            "Path": "/",
            "Arn": "{ALBIngressControllerIAMPolicyのARN}"
        }
    }
    
  5. ALB Ingress Controller マニフェストを DL

    wget https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.5/docs/examples/alb-ingress-controller.yaml
    
  6. クラスター名を作成したクラスター名に編集

    - --cluster-name=k8s-cluster

  7. RBAC ロールマニフェストをデプロイする

    kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.5/docs/examples/rbac-role.yaml

  8. 作成したサービスアカウントに IAM ポリシーをアタッチする

    eksctl create iamserviceaccount \
        --region ap-northeast-1 \
        --name alb-ingress-controller \
        --namespace kube-system \
        --cluster k8s-cluster \
        --attach-policy-arn {さっき控えたALBIngressControllerIAMPolicyのARN} \
        --override-existing-serviceaccounts \
        --approve
    
  9. ALB Ingress Controller をデプロイする

    kubectl apply -f alb-ingress-controller.yaml
    
  10. ALB Ingress Controller の作成を確認

    kubectl logs -n kube-system $(kubectl get po -n kube-system | egrep -o "alb-ingress[a-zA-Z0-9-]+")
    

ExternalDNS のデプロイ

  • ingress リソースのホスト情報に基づいて DNS レコードをプロビジョニングする
  • alb-ingress-controller がデプロイした ALB を指す Route 53 のレコードを作成する
  1. IAM ポリシー(AllowExternalDNSUpdates)を作成

    • ExternalDNSPod に Route53 リソースレコードセットとホストゾーンを更新させるために IAM ポリシーを作成
    • IAM ポリシーの元ネタを get
    aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://AllowExternalDNSUpdates.json
    
  2. 返ってきたARNを控える

    {
    "Policy": {
    "PolicyName": "AllowExternalDNSUpdates",
    "PermissionsBoundaryUsageCount": 0,
    "AttachmentCount": 0,
    "IsAttachable": true,
    "PolicyId": "POLICYID",
    "DefaultVersionId": "v1",
    "Path": "/",
    "Arn": "{AllowExternalDNSUpdatesのARN}"
        }
    }
    
  3. サービスアカウント(external-dns)と IAM ロールを作成

    eksctl create iamserviceaccount \
        --region ap-northeast-1 \
        --name external-dns \
        --namespace kube-system \
        --cluster k8s-cluster \
        --attach-policy-arn {AllowExternalDNSUpdatesのARN} \
        --override-existing-serviceaccounts \
        --approve
    
  4. IAM -> ポリシー AllowExternalDNSUpdates -> ポリシーの使用状況タブを見て、ロールが作成されていることを確認

  5. Route 53 ホストゾーンを設定する

    • public に レコードと SOA レコードを作成する
  6. ExternalDNS を deploy する

    • externaldns.yaml の元ネタを get する
    • externaldns の ServiceAccount の annotaions に AllowExternalDNSUpdates ポリシーがアタッチされているロールの arn を記載する
    • $ kubectl apply -f externaldns.yaml
  7. ExternalDNS の作成を確認

    kubectl logs -n kube-system $(kubectl get po -n kube-system | egrep -o "external-dns[a-zA-Z0-9-]+")
    
  8. ExternalDNSPod にロールがアタッチされていることを確認

    kubectl exec -n kube-system external-dns-576fb7578c-zmvlt env | grep AWS
    AWS_ROLE_ARN={ロールのarn}
    

Cognito / ALB Ingress Controller のセットアップ

  • Cognito ユーザープール作成
  1. ベースはインフラエンジニアが一切コードを書かずにWebサーバーに認証機能を実装した話をみつつ作成する

    • アプリクライアントのシークレットを生成するに
    • ALLOW_USER_PASSWORD_AUTH にチェック
  2. Certificate Manger (バージニア北部) にてドメインの証明書を発行する

    • 証明書を Cognito でリクエストまたはインポートするには、ACM コンソールで AWS リージョンを米国東部 (バージニア北部) に変更する必要がある。
  3. Route53 でサブドメイン無しの A レコードを適当に設定

    • 1.1.1.1 とかでも よい
  4. アプリケーション統合の構成

    • Callback URL
      • https://<your-domain>/oauth2/idpresponse
    • 許可されている OAuth フロー
      • Authorization code grant
    • 許可されている OAuth スコープ
      • openid
    • ドメイン名
      • auth.<your-domain>
      • AWS マネージド証明書に CM(バージニア北部)で発行した証明書を指定
  5. ドメインのステータスが 15 分程度かかって Active になったらドメイン名とエイリアスターゲットを Route53 に登録する

    • タイプ CNAME
    • 例) auth. → xxxxxxxxxxxxxx.cloudfront.net

Ingress をデプロイ

ingress.yaml
apiVersion: networking.k8s.io/v1beta1
kind: Ingress
metadata:
  name: "ingress"
  annotations:
    kubernetes.io/ingress.class: alb
    alb.ingress.kubernetes.io/scheme: internet-facing
    alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS": 443}]'

    # ドメインの証明書のarn
    alb.ingress.kubernetes.io/certificate-arn: {ドメインの証明書のarn}
    # http -> https のリダイレクト
    alb.ingress.kubernetes.io/actions.ssl-redirect: '{"Type": "redirect", "RedirectConfig": { "Protocol": "HTTPS", "Port": "443", "StatusCode": "HTTP_301"}}'

    # Authentication type must be cognito
    alb.ingress.kubernetes.io/auth-type: cognito

    # Required parameter for ALB/Cognito integration
    alb.ingress.kubernetes.io/auth-scope: openid

    # Session timeout on authentication credentials
    alb.ingress.kubernetes.io/auth-session-timeout: '3600'

    # Session cookie name
    alb.ingress.kubernetes.io/auth-session-cookie: AWSELBAuthSessionCookie

    # Action to take when a request is not authenticated
    alb.ingress.kubernetes.io/auth-on-unauthenticated-request: authenticate

    # Cognito parameters required for creation of authentication rules
    # The subdomain name only is sufficient for `UserPoolDomain`
    # e.g. if `FQDN=app.auth.ap-northeast-1.amazoncognito.com` then `UserPoolDomain=app`
    alb.ingress.kubernetes.io/auth-idp-cognito: '{"UserPoolArn": "arn:aws:cognito-idp:<region>:<account-id>:userpool/<region><cognito-id>","UserPoolClientId":"<user-pool-client-id>","UserPoolDomain":"<user-pool-authentication-domain>"}'


  labels:
    app: ingress
spec:
  rules:
    - host: <your-domain>
      http:
        paths:
          - path: /*
            backend:
              serviceName: "bff-service"
              servicePort: 3000
  1. ドメインの証明書の arn(alb.ingress.kubernetes.io/certificate-arn) を変更

    • クラスターのあるリージョンで申請した SSL 証明書の ARN を設定しないとエラーがでた
  2. Cognito 設定(alb.ingress.kubernetes.io/auth-idp-cognito)を変更

    kubectl apply -f ingress.yaml

  3. 確認(alb リソースなど完全にできるまで時間がかかる)

アプリをデプロイ

  • アプリは適当に好きなマニフェストでやってください

  • backend deploy

    • kubectl apply -f backend.yaml
    • backend.yaml 例
      ##################################################################################################
      # backend services
      ##################################################################################################
      apiVersion: v1
      kind: Service
      metadata:
      name: backend
      spec:
      type: ClusterIP # クラスタ内でのみ利用可能
      ports:
      - name: http
        protocol: TCP
        port: 8080
        targetPort: 8080
      selector:
      app: backend-pod # 転送先Podを設定
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
      name: backend-serviceaccount
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
      name: backend-deployment
      spec:
      replicas: 2
      selector:
      matchLabels:
          app: backend-pod
          version: v1
      template:
      metadata:
          labels:
              app: backend-pod
              version: v1
      spec:
          serviceAccountName: backend-serviceaccount
          containers:
              - name: backend-container
                image: { container_url }
                imagePullPolicy: Always
                ports:
                    - containerPort: 8080
      ---
      
      

  • bff deploy

    • kubectl apply -f bff.yaml
    • bff.yaml 例
      ##################################################################################################
      # bff service
      ##################################################################################################
      apiVersion: v1
      kind: Service
      metadata:
      name: "bff-service"
      spec:
      type: NodePort # k8sノードのIP:Portで受けたトラフィックをコンテナに転送する
      ports:
      - protocol: TCP
        port: 3000
        targetPort: 3000
      selector:
      app: "bff-pod" # 転送先Podを設定
      ---
      apiVersion: v1
      kind: ServiceAccount
      metadata:
      name: bff-serviceaccount
      ---
      apiVersion: apps/v1
      kind: Deployment
      metadata:
      name: bff-deployment
      spec:
      replicas: 2
      selector:
      matchLabels:
          app: bff-pod
          version: v1
      template:
      metadata:
          labels:
              app: bff-pod
              version: v1
      spec:
          serviceAccountName: bff-serviceaccount
          containers:
              - name: bff-container
                image: { container_url }
                imagePullPolicy: Always
                ports:
                    - containerPort: 3000
      ---
      
      

確認

  1. ALB が作成されていること
  2. Route 53 に ALB への A レコードと TXT レコードが作成されていること

でCognito認証 + ALB → EKS内への連携が出来ている筈

3
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
4