Amazon Web Services ブログ

Amazon API Gateway を Amazon EKS における Ingress として利用する

2023/09/13 追記 : この記事で紹介している Amazon API Gateway Ingress Controller プロジェクトは、現在メンテナンスされていません。そのため、Amazon EKS と Amazon API Gateway の連携については、代わりに AWS Controller for Kubernetes (ACK) プロジェクトの利用を検討してください。連携方法の詳細は、Integrate Amazon API Gateway with Amazon EKS でご確認いただけます。

チームが Amazon EKS にマイクロサービスをデプロイすると、通常、フロントエンドおよびサードパーティーアプリケーションで使用する REST API を公開します。ベストプラクティスは、これらの API を API Gateway で管理することです。

これにより、API の一意のエントリポイントが提供され、各マイクロサービスのセキュリティ、キャッシュ、スロットル、監視などの API 固有のコードを実装する必要もなくなります。このパターンは、ALB Ingress Controller と Amazon API Gateway を使用して実装できます。Amazon API Gateway は、あらゆる規模でセキュアな API を管理するための完全マネージドサービスです。このアプローチは機能しますが、いくつかの構成ファイルを作成する必要があります。このタスクをどのように自動化できますか?

この記事では、オープンソースソリューション API Gateway Ingress Controller の使用方法を示します。これは、Amazon API Gateway の HTTP プロキシモードを活用して Amazon EKS で実行する API をすばやく設定することで、手動手順を削減します。API Gateway Ingress Controller は、リバースプロキシポッドの前に Network Load Balancer を構成します。これは、パスベースのルーティングを処理し、HTTP リクエストをポッドにルーティングします。次の図は、この記事で説明した高レベルのアーキテクチャを示しています。

Kubernetes Ingress と Amazon API Gateway Ingress Controller の連携方法

次の図は、ユーザーが Ingress リソースを作成するときに Amazon API Gateway Ingress Controller によって作成される AWS コンポーネントの詳細を示しています。Ingress リソースは、API Gateway VPC リンクを介してプライベート Network Load Balancer を使用して、API Gateway から Kubernetes クラスターに Ingress トラフィックをルーティングします。

Ingress の作成

上の図で青い丸の番号付き手順通りに実行します。

  1. API Gateway Ingress Controller は、API サーバーからの Ingress イベントを監視します。要件を満たす Ingress リソースを見つけると、AWS リソースの作成を開始します。
  2. API Gateway API が作成され、Ingress アノテーションで説明されている指定済みの API Gateway ステージが作成されます。
  3. Ingress リソース用にプライベート Network Load Balancer が作成され、パス構成で指定されたすべてのポートに対してリスナーが作成されます。
  4. API Gateway がプライベート Network Load Balancer と通信するために、プライベート API Gateway VPC リンクが作成されます。
  5. ターゲットグループは、Ingress リソースで指定されたリバースプロキシ用に作成されます。
  6. API Gateway Ingress Controller は NGINX をリバースプロキシとしてデプロイし、Ingress リソースで指定された各パスに対してリバースプロキシのルールが作成されます。これにより、特定のパスへのトラフィックが正しいポッドにルーティングされるようになります。

手順 1:AWS Cloud9 IDE を作成する

このブログの指示を作成するために使用された AWS Cloud9 IDE を使用することをお勧めします。

AWS Cloud9 環境を作成する

この deep-link 通りに、オレゴンリージョンで作成してください

  • [eksworkshop] という名前を付けて、[次へ] をクリックします。
  • インスタンスタイプに [t2.small] を選択し、すべてのデフォルト値を取得して、[環境を作成] をクリックします
  • 起動したら、[ようこそ] タブと下の作業領域を閉じて、メインの作業領域で新しい [ターミナル] タブを開いて、環境をカスタマイズします。

WorkSpace の IAM ロールを作成します

  • この deep-link 通りに、AdministratorAccess で IAM ロールを作成します。
  • AWS サービスと EC2 が選択されていることを確認し、[次へ] をクリックして権限を表示します。
  • AdministratorAccess がチェックされていることを確認し、[次へ: タグ] をクリックしてタグを割り当てます。
  • デフォルトを使用し、[次へ: レビュー] をクリックしてレビューします。
  • 名前に [eksworkshop-admin] と入力し、[ロールを作成] をクリックします。

IAM ロールを WorkSpace にアタッチします

  • この deep-link 通りに、AWS Cloud9 EC2 インスタンスを見つけてください
  • インスタンスを選択し、[アクション] / [インスタンス設定] / [IAM ロールをアタッチ/置換] を選択します
  • IAM ロールのドロップダウンから eksworkshop-admin を選択し、[適用] を選択します

WorkSpace の IAM 設定を更新する

  • WorkSpaces の右上隅にある clog をクリックします
  • AWS 設定を選択
  • AWS マネージドの一時認証情報をオフにする
  • [設定] タブを閉じます

一時的な認証情報がまだ設定されていないことを確認するために、既存の認証情報ファイルも削除します。

rm -vf ${HOME}/.aws/credentials

GetCallerIdentity CLI コマンドを使用して、AWS Cloud9 IDE が正しい IAM ロールを使用していることを検証します。

aws sts get-caller-identity
#The output assumed-role name should contain
eksworkshop-admin

kubectl およびその他のツールをインストールする

kubectl インストールの詳細については、kubectl のインストールを参照してください。

sudo curl --silent --location -o /usr/local/bin/kubectl \
 https://amazon-eks.s3-us-west-2.amazonaws.com/1.14.6/2019-08-22/bin/linux/amd64/kubectl
 sudo chmod +x /usr/local/bin/kubectl

jq、envsubst (GNU gettext ユーティリティから)、および bash-completion をインストールします

sudo yum -y install jq gettext bash-completion

eksctl バイナリをダウンロードしてインストールします

curl --silent --location \
 "https://github.com/weaveworks/eksctl/releases/download/latest_release/eksctl_$(uname -s)_amd64.tar.gz" \
  | tar xz -C /tmp
  
sudo mv -v /tmp/eksctl /usr/local/bin

eksctl コマンドが機能することを確認します

eksctl version

ブログの GitHub プロジェクトを複製します。このブログに必要なすべての YAML ファイルが含まれています。

cd ~/environment/
git clone https://github.com/aws-samples/amazon-apigateway-ingress-controller-blog.git

手順 2: Amazon EKS クラスターを作成する

eksctl を使用して、Amazon EKS クラスターとノードを起動して構成します。

eksctl create cluster --name=eksworkshop-blog  --nodes=3 --region=us-west-2

Amazon EKS クラスターの作成には最大 15 分かかります。クラスターが実行されたら、次のコマンドを実行してクラスターにアクセスできます。

kubectl get nodes 
# 3 つのノードが表示された場合、正しく認証されたことがわかり、クラスターが起動されます

手順 3:kube2iam ロールを設定する

Amazon API Gateway Ingress Controller には、AWS リソースを作成するための 4 つのポリシー (AutoScallingFullAccess、AmazonAPIGatewayAdministrator、AmazonVPCFullAccess、および AWSCloudFormationFullAccess) が必要です。1 つのオプションは、これらのポリシーをノードのインスタンスロールに追加することですが、推奨しません。 サービスアカウントの IAM ロールが最適なオプションです。現在、API Gateway Ingress Controller はこのオプションをサポートしていません。プロジェクトの予定リストにあります。Ingress Controller ポッドにロールを割り当てるために kube2iam をセットアップします。このロールを作成しましょう。

ノードのロールを取得する

クラスターのノードにロール名を付けるには、次の 3 つのコマンドが必要です。

STACK_NAME=$(eksctl get nodegroup --cluster eksworkshop-blog -o json | jq -r '.[].StackName')
ROLE_NAME=$(aws cloudformation describe-stack-resources --stack-name $STACK_NAME | jq -r '.StackResources[] | select(.ResourceType=="AWS::IAM::Role") | .PhysicalResourceId')
aws iam get-role --role-name $ROLE_NAME | jq -r  .Role.Arn

# ノードのロール Arn を表示し、コピーします ~/environment/apigw-ingress-controller-blog/kube2iam-ingress-trust-policy.yml を編集し、ロール ARN を置き換えます。
.....
"Principal": {
"AWS": "arn:aws:iam::xx:role/eksctl-eksworkshop-blog-nodegroup-NodeInstanceRole-xxxxxx"
},
......

Kube2Iam ロールを作成する

kub2iam-ingress-role という名前のロールを作成します。名前は ~/environment/apigw-ingress-controller-blog/AmazonAPIGWHelmChart/template/statefulset.yaml で設定されているため重要です。

cd ~/environment/apigw-ingress-controller-blog

aws iam create-role --role-name kube2iam-ingress-role \
 --assume-role-policy-document file://kube2iam-ingress-trust-policy.yml

4 つのポリシーを kub2iam-ingress-role に追加する必要があります。Amazon API Gateway Ingress Controller はこれを使用して AWS リソースを作成します。

aws iam attach-role-policy --role-name kube2iam-ingress-role --policy-arn \
 arn:aws:iam::aws:policy/AutoScalingFullAccess  
aws iam attach-role-policy --role-name kube2iam-ingress-role --policy-arn \
 arn:aws:iam::aws:policy/AmazonAPIGatewayAdministrator
aws iam attach-role-policy --role-name kube2iam-ingress-role --policy-arn \
 arn:aws:iam::aws:policy/AmazonVPCFullAccess 
aws iam attach-role-policy --role-name kube2iam-ingress-role --policy-arn \
 arn:aws:iam::aws:policy/AWSCloudFormationFullAccess 
aws iam attach-role-policy --role-name kube2iam-ingress-role --policy-arn \
 arn:aws:iam::aws:policy/ElasticLoadBalancingFullAccess
 

手順 4:Helm をセットアップしてチャートをデプロイする

現在、API Gateway Ingress Controller は Helm チャートとして利用できます。以下の手順通りに、Helm をインストールします。

Helm CLI をインストールする

cd ~/environment
curl https://raw.githubusercontent.com/kubernetes/helm/master/scripts/get > get_helm.sh
chmod +x get_helm.sh
./get_helm.sh

RBAC を使用して Helm アクセスを構成する

cd ~/environment/apigw-ingress-controller-blog
kubectl apply -f helm-rbac.yml
helm init --service-account tiller

kube2iam チャートをデプロイする

kube2iam Helm チャートをインストールします。

helm install \
  --set rbac.create=true \
  --set host.iptables=true \
  --set host.interface=eni+ \
  --set=extraArgs.auto-discover-base-arn= \
  stable/kube2iam

kube2iam ポッドがインストールされ、実行されていることを確認します。

kubectl get pods
# 名前に kube2iam を含む 3 つのポッドが表示されます

# ポッドの 1 つのログを表示し、ポッド名を置き換えます  
kubectl logs xxxx-kube2iam-xxx

# ログには「ベース ARN 自動検出」が含まれている必要があります
time="2019-12-27T23:08:26Z" level=info msg="base ARN autodetected, arn:aws:iam::xx:role/"

API Gateway Ingress Controller チャートをデプロイ

API Ingress Controller Helm チャートをインストールします。

cd ~/environment/apigw-ingress-controller-blog/AmazonAPIGWHelmChart

helm install --debug ./amazon-apigateway-ingress-controller \
 --set image.repository="karthikk296d/aws-apigw-ingress-controller"

API Gateway Ingress Controller がインストールされていることを確認し、次のコマンドを実行します。

kubectl get pods
# apigw イングレスコントローラのポッドが 1 つ表示されます
NAME                                            READY   STATUS             RESTARTS   AGE
virtuous-markhor-amzn-apigw-ingress-controller-0   1/1     Running   0          22s          26s

手順 5:サンプル REST API をデプロイする

書籍と著者をデプロイする: このブログのサンプルマイクロサービスです。

cd ~/environment/apigw-ingress-controller-blog
kubectl apply -f book-deployment.yml
kubectl apply -f book-service.yml 
kubectl apply -f author-deployment.yml
kubectl apply -f author-service.yml 

本と著者はどのタイプのサービスですか? book-service.yml を覗いてみましょう。書籍サービスと著者サービスは、どちらも ClusterIP タイプです。ClusterIP は、Amazon EKS クラスター内からのみ呼び出すことができます。

......
  name: bookservice
spec:
  type: ClusterIP
  selector:
    app: books
....

これで、クラスターで次のポッドが実行されていることがわかります。

kubectl get pods
# 実行中の著者と書籍ポッドが表示されます
NAME                                            READY   STATUS    RESTARTS   AGE
author-deployment-658d67f7dc-9z4r6              1/1     Running   0          14m
book-deployment-577b7577ff-pn5ng 

また、次のサービスが実行されていることがわかります。

kubectl get svc
# authorservice と booksservice が実行されます
NAME               TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)   AGE
authorservice      ClusterIP   10.100.10.144    <none>        80/TCP    15m
bookservice        ClusterIP   10.100.128.1     <none>        80/TCP    15m

手順 6:API Gateway Ingress Controller リソースをデプロイする

API Gateway Ingress は現在、IAM 認証を使用して REST API を保護しています。サンプル REST API を呼び出すために使用するユーザーを作成しましょう。

aws iam create-user --user-name apigw-user
# apigw-user という名前のユーザーが作成されます

~/environment/apigw-ingress-controller-blog/api_ingress.yml の apigateway.ingress.kubernetes.io/client-arns デフォルトユーザー ARN をapigw-user の Arn に置き換えます。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    *# arn::foo,arn::bar を apigw-user の Arn に置き換えます*
    apigateway.ingress.kubernetes.io/client-arns: arn:aws:iam::xxxxx:user/apigw-user
    apigateway.ingress.kubernetes.io/stage-name: prod
    kubernetes.io/ingress.class: apigateway
  name: api-95d8427d
  namespace: default
spec:
  rules:
  - http:
      paths:
      - backend:
          serviceName: bookservice
          servicePort: 80
        path: /api/book
      - backend:
          serviceName: authorservice
          servicePort: 80
        path: /api/author

api_ingress.yml ファイルを編集したら、次のコマンドを実行してデプロイします。

cd ~/environment/apigw-ingress-controller-blog/
kubectl apply -f api_ingress.yml

Ingress が稼働していることを確認します。

kubectl get ingress
# api-95d8427d という名前の 1 つのイングレスがデプロイされます

リバースプロキシのデプロイを確認します。

kubectl get pods
# 3 つのリバースプロキシポッドが実行されています
NAME                                               READY   STATUS    RESTARTS   AGE
api-95d8427d-reverse-proxy-5fc845fc67-bx7t2        1/1     Running   0          4s
api-95d8427d-reverse-proxy-5fc845fc67-d7gxf        1/1     Running   0          4s
api-95d8427d-reverse-proxy-5fc845fc67-mttkm        1/1     Running   0          4s

Ingress リソース作成の進行状況を確認するには、xxxx-amzn-apigw-ingress-controller ポッドのログを表示します。AWS マネジメントコンソール CloudFormation を使用して進行状況を表示することもできます。

kubectl logs xxxx-markhor-amzn-apigw-ingress-controller-0 -f

# 作成中、メッセージが表示されます
"Not complete, requeuing","status":"CREATE_IN_PROGRESS"}

# すべてのリソースは約 15 分で作成されます
{"level":"info",........,"msg":"Stack Create/Update Complete"}

手順 7: デプロイをテストする

API Gateway コンソールで api-95d8427d の作成を確認します。

api-95d8427d をクリックして、構成を確認しましょう。

左側のメニューでリソース VPC リンクをクリックします。これは、Amazon API Gateway Ingress Controller によって作成されました。Amazon Virtual Private Cloud (VPC) 内の HTTP リソースへのアクセスを、パブリックインターネットに直接公開することなく提供します。

リソースポリシーの左メニューをクリックし、リソースポリシーを使用して、Amazon API Gateway Ingress Controller がこのプライベート API へのアクセス制御を設定しました。

左側にあるメニューのステージリンクをクリックすると、prod ステージが表示されます。/api/author をクリックしてから、メソッド取得をクリックします。API の呼び出し URL が表示されたら、コピーします。

apigw-user のアクセスキーとシークレットキーを使用して API を呼び出しましょう。このコマンドで認証情報を取得できます。

aws iam create-access-key --user-name apigw-user

# 出力からアクセスキーとシークレットキーをコピーし、
# API の呼び出しに使用できるようにします
{
    "AccessKey": {
        "UserName": "apigw-user",
        "Status": "Active",
        "CreateDate": "2019-12-26T22:11:34Z",
        "SecretAccessKey": "xxxxx",
        "AccessKeyId": "xxxxx"
    }
}

API を呼び出すときに一時的な認証情報を使用することをお勧めします。AWS STS get-session-token コマンドを使用して、一時的な認証情報を取得できます。このコマンドの使用方法については、こちらをご覧ください。

Postman を使用して REST API を呼び出し、コピーした API URL を貼り付け、URL の末尾に次の /api/author/list があることを確認します。

[認証] タブをクリックし、アクセスキーとシークレットキー、およびオプションでセッショントークンを指定して、[送信] をクリックします。

リクエストの出力として著者一覧が表示されます。次の API URL を試して、さまざまな出力を確認できます。

# API URL を次のように変更して、書籍リストを取得します
https://xxxxxxx.execute-api.us-east-1.amazonaws.com/prod/api/book/list

# ISBN13 の 1 つを出力からコピーし、API URL を次のように変更します 
https://xxxxxxx.execute-api.us-east-1.amazonaws.com/prod/api/book/9781617293825        

クリーンアップ

クリーンアップするために、デプロイとサービスを削除しましょう。

cd ~/environment/api-gateway-ingress-blog/
kubectl delete -f book-deployment.yml
kubectl delete -f book-service.yml 
kubectl delete -f author-deployment.yml
kubectl delete -f author-service.yml 

API Gateway Ingress Controller を削除すると、Network Load Balancer、API Gateway API、および作成した他のリソースが削除されます。

kubectl delete ingress api-95d8427d

API Gateway Ingress Controller の Helm チャートを削除します

# 次のコマンドを使用して、API Gateway イングレスチャートの名前を取得します
helm ls

# チャートの名前は異なります 
NAME            REVISION      STATUS          CHART                                           APP VERSION     NAMESPACE
lame-fox        1             DEPLOYED        amazon-apigateway-ingress-controller-0.1.0      1.0             default
NAME                    CHART                                           
filled-butterfly        amazon-apigateway-ingress-controller-0.1.0   
newbie-narwhal          kube2iam-2.1.0        

# 次のコマンドを発行して、両方の Helm チャートを削除します
helm delete filled-butterfly
helm delete newbie-narwhal

Amazon EKS クラスターが不要な場合は、削除できます。

eksctl delete cluster --name=eksworkshop-blog

お試しください

Amazon API Gateway Ingress Controller は、Karthikk Dhandapani と Anand Modh によって維持されている完全にオープンソースのプロジェクトです。Karthikk と Anand は、Amazon のシステム開発エンジニアです。彼らは、Amazon Fulfillment Technologies 内の Amazon EKS の顧客であり、自動化に夢中になっています。彼らは、コンテナ化されたサーバーレスアプリケーションを構築することを好みます。AWS チームは、Amazon EKS で Ingress Controller のテストも行っており、現在、Kubernetes バージョン 1.14 をサポートしています。

その他リソース: