APISIX Ingress Controller と AWS ACM の使用
Xin Rong
December 30, 2022
なぜAWS ACMが必要なのか?
手動管理による問題
証明書には、所有者、発行者、有効期限などの情報が含まれており、有効期限が切れた証明書は使用できず、期限切れ前に更新する必要があります。そのため、証明書情報を記録する必要があります。例えば、手動でスプレッドシートに記録し、証明書が適時に失効および更新されるようにします。
しかし、証明書が増えるにつれて、手動管理方法では証明書を正確かつ効率的に管理できなくなります。スプレッドシートは自動通知を送信できず、期限切れ時に自動的に証明書を更新することもないため、不必要なリスクをもたらします。
証明書の中断リスクを回避し、新しい情報や規制に基づいて自動更新を維持するために、自動化された証明書管理が登場し、証明書の期限切れリスクを減らし、開発者の負担を軽減します。
ACMによる自動証明書管理
AWS Certificate Manager (ACM) は、SSL/TLS証明書のプロビジョニング、管理、デプロイ、更新を簡単に行えます。ACMを通じて直接証明書を発行し、AWSのウェブサイトやアプリケーションを保護したり、サードパーティの証明書をACM管理システムにインポートしたりできます。
ACMを使用すると、以前のようにSSL/TLS証明書の使用と管理に関連する手動プロセスを経る必要がなくなります。また、AWS Private CAによって署名されたACM証明書をエクスポートして、内部PKI内の任意の場所で使用することもできます。さらに、AWS Elastic Load Balancing (ELB) と統合されています。
ACM Private CAが解決する問題
組織内にプライベートCAがない場合、自己署名証明書を使用して内部アプリケーションをデプロイします。これらのアプリケーションが互いにアクセスしようとすると、証明書が信頼されていないため、互いのアクセスを拒否する可能性があります。未知のアプリケーションソースを盲目的に信頼することは、セキュリティリスクをもたらす可能性があります。この場合、組織内のすべてのアプリケーションが信頼されるように、CA階層を作成および管理するホスト型プライベートCAサービスが必要です。
ACM Private CAは、組織の内部PKIを作成および維持する高可用性のホスト型サービスであり、継続的なメンテナンスコストを削減します。プライベートキーは、FIPS 140-2で検証されたAWSホストのハードウェアセキュリティモジュール(HSM)に保存され、KubernetesのデフォルトCAと比較して、より安全な証明書発行組織ソリューションを提供します。
KubernetesでACMを使用する方法
KubernetesでTLS証明書を終端するには、2つの異なる構成があります:
- IngressでTLS証明書を終端する: アプリケーション間で暗号化が必要な場合、IngressコントローラーでTLSを終端する必要があります。各アプリケーションは、Ingressを通じて証明書を管理し、互いに干渉することなく通信を信頼できます。この方法は構成と管理が容易で、アプリケーション間の通信が信頼されることを保証します。
- NLBでTLS証明書を終端する: NLBレベルでTLS証明書を終端することは、公開信頼証明書を使用する最も一般的なユースケースです。この方法は、ACMの公開信頼証明書をNLBにバインドするのが簡単で、クラスタ内のアプリケーションへのアクセスはHTTPのままで、追加の暗号化および復号化操作は必要ありません。
以下の例では、Amazon EKS上で直接APISIX Ingressを構成します。これらの2つの方法を使用して、APISIX IngressがACM(およびACM Private CA)とどのように連携するかを示します。
前提条件
開始する前に、以下の要件を満たす必要があります:
- AWS AWSアカウントとAWSコマンドラインインターフェース (AWS CLI)
- Amazon EKS IAMロールとサービス関連ロール AWS CloudFormation, Amazon Virtual Private Cloud (Amazon VPC) および関連リソースを使用する権限が必要です。IAMユーザーマニュアルの記事 "Operations, resources, and condition keys for Amazon Elastic Container Service for Kubernetes" を確認し、サービス関連ロール を使用してください。さらに、このIAMセキュリティプリンシパルには、AWSCertificateManagerPrivateCAFullAccess IAM管理ポリシーがアタッチされている必要があります。
- kubectl と eksctl ツールをインストールおよび構成します。
Amazon EKSクラスタ
Amazon EKSは、AWS上でKubernetesを実行し、Kubernetesクラスタを簡単にデプロイおよび管理できるホスト型サービスです。この記事では、eksctlコマンドツールを使用してクラスタを管理します。
- eksctlのデフォルト構成を使用してクラスタを作成します(既にEKSクラスタがある場合はこの部分を無視してください)
eksctl create cluster
APISIX Ingressのインストール
- EKSクラスタにAPISIX Ingressをインストールし、LoadBalancerタイプに設定します。
helm repo add apisix https://charts.apiseven.com
helm repo add bitnami https://charts.bitnami.com/bitnami
helm repo update
helm install apisix apisix/apisix \
--set gateway.type=LoadBalancer \
--set gateway.tls.enabled=true \
--set ingress-controller.enabled=true \
--namespace ingress-apisix \
--create-namespace
注意:
クラスタが永続ボリュームを追加できることを確認してください。詳細については、Amazon EKS Storage を参照してください。このチュートリアルを試すだけの場合は、インストール時に --set etcd.persistence.enabled=false
を設定して、永続ボリュームを使用しないことを宣言してください。
- 以下のコマンドを実行してステータスを確認し、すべてのPodが
Running
ステータスであることを確認します。
$ kubectl get pods -n ingress-apisix
NAME READY STATUS RESTARTS AGE
apisix-78bfc58588-qspmm 1/1 Running 0 103s
apisix-etcd-0 1/1 Running 0 103s
apisix-etcd-1 1/1 Running 0 103s
apisix-etcd-2 1/1 Running 0 103s
apisix-ingress-controller-6ff56cd4b4-rktr9 1/1 Running 0 103s
- NLBのステータスを確認します。PORT(S) と EXTERNAL-IP に注意してください。
$ kubectl get svc apisix-gateway -n ingress-apisix
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
apisix-gateway LoadBalancer 10.100.178.65 a6cffe9f6fc5c47b9929cb758610fc5a-2074689558.ap-northeast-1.elb.amazonaws.com 80:30851/TCP,443:32735/TCP 103s
NLBでTLS証明書を終端する
ACM証明書の準備
- ACMコンソール を開き、カスタムドメインの公開ACM証明書を申請するか、カスタム証明書をインポートします。
LoadBalancerに証明書を設定
- EC2コンソール を開き、ロードバランサー -> リスナー -> 編集 を選択します。
- NLBのプロトコルをHTTPSに設定し、ポートを443に、インスタンスプロトコルをHTTPに、ポートを30851に設定します。
- ACMからTLS証明書をNLBにアタッチします。
カスタムドメインをロードバランサー名に関連付ける
DNSプロバイダーのコンソールを使用して、アプリケーションのDNSレコードをCNAME経由でNLBのURLにリダイレクトできます。例えば、Route53 を使用して、NLBにリダイレクトするCNAMEレコードを構成 します。
httpbin.example-test.org CNAME a6cffe9f6fc5c47b9929cb758610fc5a-2074689558.ap-northeast-1.elb.amazonaws.com
アプリケーションのドメインにアクセス
curl https://httpbin.example-test.org
IngressでTLS証明書を終端する
この例を開始する前に、AWS NLBの構成が以下の画像のように復元されていることを確認してください。
cert-managerのインストール
Cert-managerは、Kubernetesのアドオンで、さまざまなソースからTLS証明書を自動的に管理および発行できます。cert-manager をインストールする一般的な方法を使用します。
ACM Private CAの作成
- ACM PCAコンソールを開き、「プライベートCAを作成」を選択してインストールします。
- CAが正常に作成され、ステータスがアクティブになった後、PCAの ARN が後続のセクションで頻繁に使用されます。
ACM Private CAのためのEKSノードの権限設定
デフォルトでは、発行権限がありません。ACM Private CAから証明書を発行するには、EKS NodeInstanceRoleにIAMポリシーを追加する必要があります。これには、iamserviceaccountサービスロールが含まれます。
pca-iam-policy.json
ファイルを作成し、${PCA_ARN}
を自分のPCA_ARNに置き換えます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "awspcaissuer",
"Action": [
"acm-pca:DescribeCertificateAuthority",
"acm-pca:GetCertificate",
"acm-pca:IssueCertificate"
],
"Effect": "Allow",
"Resource": "${PCA_ARN}"
}
]
}
- pca-iam-policy.jsonに基づいてIAMとiamserviceaccountを作成し、
${account_id}
を自分のAWS IDに置き換えます。
aws iam create-policy \
--policy-name AWSPCAIssuerIAMPolicy \
--policy-document file://pca-iam-policy.json
# 名前空間を作成
kubectl create namespace aws-pca-issuer
eksctl create iamserviceaccount \
--cluster=${cluster_name} \
--namespace=aws-pca-issuer \
--name=aws-pca-issuer \
--attach-policy-arn=arn:aws:iam::${account_id}:policy/AWSPCAIssuerIAMPolicy \
--override-existing-serviceaccounts \
--approve
aws-privateca-issuerのインストール
AWS PrivateCA Issuerは、cert-managerのアドオンとして機能し(外部発行者)、証明書リクエストに署名します。
- Helmを使用してインストールします。
helm repo add awspca https://cert-manager.github.io/aws-privateca-issuer
helm repo update
helm install aws-pca-issuer awspca/aws-privateca-issuer \
-n aws-pca-issuer \
--set serviceAccount.create=false \
--set serviceAccount.name=aws-pca-issuer
- ステータスを確認します。
$ kubectl get pods -n aws-pca-issuer
NAME READY STATUS RESTARTS AGE
aws-pca-issuer-aws-privateca-issuer-5cdd4b4687-z52n7 1/1 Running 0 20s
発行者を作成し、証明書を申請
issuer-cert.yaml
ファイルの${PCA_ARN}
を自分の構成に置き換え、以下のコマンドを実行します:
kubectl apply -f issuer-cert.yaml
# issuer-cert.yaml
apiVersion: awspca.cert-manager.io/v1beta1
kind: AWSPCAClusterIssuer
metadata:
name: demo-test-root-ca
spec:
arn: ${PCA_ARN}
---
kind: Certificate
apiVersion: cert-manager.io/v1
metadata:
name: nlb-lab-tls-cert
spec:
commonName: httpbin.example-test.org # カスタムドメイン名に置き換える必要があります
dnsNames:
- httpbin.example-test.org # カスタムドメイン名に置き換える必要があります
duration: 2160h0m0s
issuerRef:
group: awspca.cert-manager.io
kind: AWSPCAClusterIssuer
name: demo-test-root-ca
renewBefore: 360h0m0s
secretName: nlb-tls-app-secret
usages:
- server auth
- client auth
privateKey:
algorithm: "RSA"
size: 2048
- 以下のコマンドを実行して、証明書が発行され、シークレットが生成されたことを確認します。
$ kubectl get cert
NAME READY SECRET AGE
nlb-lab-tls-cert True nlb-tls-app-secret 10s
$ kubectl get secret
NAME TYPE DATA AGE
nlb-tls-app-secret kubernetes.io/tls 3 8s
httpbinアプリケーションの公開と保護
APISIX Ingressが正常にインストールされていることを確認してください。この セクション を確認してください。
- httpbinアプリケーションをデプロイします。
kubectl run httpbin --image kennethreitz/httpbin --port 80
kubectl expose pod httpbin --port 80
- Ingressを作成してhttpbinアプリケーションを公開および保護します。
kubectl apply -f ingress-httpbin.yaml
```yaml
# ingress-httpbin.yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: httpbin-demo-apisix
spec:
ingressClassName: apisix
tls:
- hosts:
- httpbin.example-test.org
secretName: nlb-tls-app-secret
rules:
- host: httpbin.example-test.org
http:
paths:
- backend:
service:
name: httpbin
port:
number: 80
path: /
pathType: Prefix
- アプリケーションのドメイン名にアクセスします。
カスタムドメイン名とロードバランサーの名前が関連付けられていることを確認してください。この セクション を確認してください。
$ curl https://httpbin.example-test.org/headers --cacert acm-pca/cacert.pem
{
"headers": {
"Accept": "*/*",
"Host": "httpbin.example-test.org",
"User-Agent": "curl/7.74.0",
"X-Forwarded-Host": "httpbin.example-test.org"
}
}
結論
この記事では、APISIX IngressとAWS ACMおよびACM Private CAコンポーネントの使用を実践的な例を通じて示し、KubernetesでTLS証明書を終端する2つの構成(NLBとIngressでのTLS証明書の終端) を紹介しました。ACM + NLB構成は、公開信頼証明書に適しています。アプリケーション間で暗号化が必要な場合、ACM Private CAはより安全なホスト型管理サービスを提供できます。
これらの実践記事が、読者がAWS EKSクラスタでTLSトラフィックを効果的に構成および管理するのに役立つことを願っています。APIゲートウェイに関する詳細情報については、ブログ または お問い合わせ をご覧ください。