以下の構成を作成し、Cognito 認証を終えたトラフィックのみ eks の世界に到達できるようにします。
環境
Kubernetes バージョン : 1.14
AWS ALB Ingress Controller バージョン : v1.1.5
EKS クラスター作成
- まずクラスターを作成
eksctl create cluster --name=k8s-cluster
ALB Ingress Controller のデプロイ
- Ingress リソースがデプロイされたタイミングで ALB を作成させる
- 
IAM OIDC(OpenID Connect) プロバイダーを作成してクラスターに関連付ける - k8s 内のリソース ServiceAccount と IAM の橋渡しをさせる
- 参考: [アップデート] EKS で IAM ロールを使った Pod 単位のアクセス制御が可能になりました!
 $ eksctl utils associate-iam-oidc-provider --region=ap-northeast-1 --cluster=k8s-cluster --approve
- 
AWS IAM => ID プロバイダーを確認し、タイプ OpenIDConnect のプロバイダが作成されていることを確認 
- 
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
- 
返ってきたARNを控える { "Policy": { "PolicyName": "ALBIngressControllerIAMPolicy", "PermissionsBoundaryUsageCount": 0, "AttachmentCount": 0, "IsAttachable": true, "PolicyId": "POLICYID", "DefaultVersionId": "v1", "Path": "/", "Arn": "{ALBIngressControllerIAMPolicyのARN}" } }
- 
ALB Ingress Controller マニフェストを DL wget https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.5/docs/examples/alb-ingress-controller.yaml
- 
クラスター名を作成したクラスター名に編集 - --cluster-name=k8s-cluster
- 
RBAC ロールマニフェストをデプロイする kubectl apply -f https://raw.githubusercontent.com/kubernetes-sigs/aws-alb-ingress-controller/v1.1.5/docs/examples/rbac-role.yaml
- 
作成したサービスアカウントに 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
- 
ALB Ingress Controller をデプロイする kubectl apply -f alb-ingress-controller.yaml
- 
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 のレコードを作成する
- 
IAM ポリシー(AllowExternalDNSUpdates)を作成 - ExternalDNSPod に Route53 リソースレコードセットとホストゾーンを更新させるために IAM ポリシーを作成
- IAM ポリシーの元ネタを get
 aws iam create-policy --policy-name AllowExternalDNSUpdates --policy-document file://AllowExternalDNSUpdates.json
- 
返ってきたARNを控える { "Policy": { "PolicyName": "AllowExternalDNSUpdates", "PermissionsBoundaryUsageCount": 0, "AttachmentCount": 0, "IsAttachable": true, "PolicyId": "POLICYID", "DefaultVersionId": "v1", "Path": "/", "Arn": "{AllowExternalDNSUpdatesのARN}" } }
- 
サービスアカウント(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
- 
IAM -> ポリシー AllowExternalDNSUpdates -> ポリシーの使用状況タブを見て、ロールが作成されていることを確認 
- 
Route 53 ホストゾーンを設定する - public に レコードと SOA レコードを作成する
 
- 
ExternalDNS を deploy する - externaldns.yaml の元ネタを get する
- externaldns の ServiceAccount の annotaions に AllowExternalDNSUpdates ポリシーがアタッチされているロールの arn を記載する
- $ kubectl apply -f externaldns.yaml
 
- 
ExternalDNS の作成を確認 kubectl logs -n kube-system $(kubectl get po -n kube-system | egrep -o "external-dns[a-zA-Z0-9-]+")
- 
ExternalDNSPod にロールがアタッチされていることを確認 kubectl exec -n kube-system external-dns-576fb7578c-zmvlt env | grep AWS AWS_ROLE_ARN={ロールのarn}
Cognito / ALB Ingress Controller のセットアップ
- Cognito ユーザープール作成
- 
ベースはインフラエンジニアが一切コードを書かずにWebサーバーに認証機能を実装した話をみつつ作成する - アプリクライアントのシークレットを生成するに
- ALLOW_USER_PASSWORD_AUTH にチェック
 
- 
Certificate Manger (バージニア北部) にてドメインの証明書を発行する - 証明書を Cognito でリクエストまたはインポートするには、ACM コンソールで AWS リージョンを米国東部 (バージニア北部) に変更する必要がある。
 
- 
Route53 でサブドメイン無しの A レコードを適当に設定 - 1.1.1.1 とかでも よい
 
- 
アプリケーション統合の構成 - Callback URL
- https://<your-domain>/oauth2/idpresponse
 
- 許可されている OAuth フロー
- Authorization code grant
 
- 許可されている OAuth スコープ
- openid
 
- ドメイン名
- auth.<your-domain>
- AWS マネージド証明書に CM(バージニア北部)で発行した証明書を指定
 
 
- Callback URL
- 
ドメインのステータスが 15 分程度かかって Active になったらドメイン名とエイリアスターゲットを Route53 に登録する - タイプ CNAME
- 例) auth. → xxxxxxxxxxxxxx.cloudfront.net
 
Ingress をデプロイ
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
- 
ドメインの証明書の arn(alb.ingress.kubernetes.io/certificate-arn) を変更 - クラスターのあるリージョンで申請した SSL 証明書の ARN を設定しないとエラーがでた
 
- 
Cognito 設定(alb.ingress.kubernetes.io/auth-idp-cognito)を変更 kubectl apply -f ingress.yaml
- 
確認(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-serviceaccountapiVersion: 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``` </div></details>- 
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-serviceaccountapiVersion: 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``` </div></details>確認- ALB が作成されていること
- Route 53 に ALB への A レコードと TXT レコードが作成されていること
 でCognito認証 + ALB → EKS内への連携が出来ている筈
 
- 
 
- 
 
- 
