以下の構成を作成し、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内への連携が出来ている筈
-
-
-