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가 해결하는 문제는 무엇인가요?
조직 내에 Private CA가 없을 때 내부 애플리케이션을 배포하기 위해 자체 서명된 인증서가 사용됩니다. 이러한 애플리케이션이 서로 접근하려고 할 때, 인증서가 신뢰할 수 없기 때문에 서로의 접근을 거부할 수 있습니다. 알 수 없는 애플리케이션 소스를 무작정 신뢰하는 것은 보안 위험을 초래할 수 있습니다. 이 경우, 조직 내의 모든 애플리케이션이 신뢰할 수 있도록 CA 계층을 생성하고 관리할 수 있는 호스팅된 Private CA 서비스가 필요합니다.
ACM Private CA는 조직을 위한 내부 PKI를 생성하고 유지하는 고가용성 호스팅 서비스로, 지속적인 유지 관리 비용을 없앱니다. 개인 키는 FIPS 140-2로 검증된 AWS 호스팅 하드웨어 보안 모듈(HSM)에 저장되며, 이는 Kubernetes의 기본 CA에 비해 더 안전한 인증서 발급 조직 솔루션을 제공합니다.
Kubernetes에서 ACM을 사용하는 방법은 무엇인가요?
Kubernetes에서 TLS 인증서를 종료하는 두 가지 다른 구성이 있습니다:
- Ingress에서 TLS 인증서 종료: 애플리케이션 간에 암호화가 필요할 때, Ingress 컨트롤러에서 TLS를 종료해야 합니다. 각 애플리케이션은 Ingress를 통해 자체 인증서를 관리할 수 있으며 서로 간섭하지 않습니다. 이 방법은 구성 및 관리가 더 쉽고 애플리케이션 간 통신이 신뢰할 수 있도록 보장합니다.
- NLB에서 TLS 인증서 종료: NLB 수준에서 TLS 인증서를 종료하는 것은 공개적으로 신뢰할 수 있는 인증서를 사용하는 가장 일반적인 사용 사례입니다. 이 방법은 ACM 공개적으로 신뢰할 수 있는 인증서를 NLB에 쉽게 구성하고 바인딩할 수 있습니다. 클러스터 내부 애플리케이션에 대한 접근은 여전히 HTTP를 사용하며 추가 암호화 및 복호화 작업이 필요하지 않습니다.
다음 예제에서는 Amazon EKS에서 직접 APISIX Ingress를 구성할 수 있습니다. 이 두 가지 방법을 사용하여 APISIX Ingress가 ACM(및 ACM Private CA)과 어떻게 작동하는지 보여드리겠습니다.
사전 요구 사항
시작하기 전에 다음 요구 사항을 충족해야 합니다:
- AWS AWS 계정 및 AWS 명령줄 인터페이스 (AWS CLI)
- Amazon EKS IAM 역할 및 서비스 관련 역할 AWS CloudFormation, Amazon Virtual Private Cloud (Amazon VPC) 및 관련 리소스를 사용할 수 있는 권한이 있어야 합니다. IAM 사용자 매뉴얼의 "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
를 구성하여 영구 볼륨을 사용하지 않음을 선언하세요.
- 다음 명령을 실행하여 상태를 확인하고 모든 파드가
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는 다양한 소스에서 TLS 인증서를 자동으로 관리하고 발급할 수 있는 Kubernetes 애드온입니다. cert-manager를 설치하는 일반적인 방법을 사용하세요.
ACM Private CA 생성
- ACM PCA 콘솔을 열고 "Private 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 인증서를 종료하는 두 가지 구성: NLB 및 Ingress에서 TLS 인증서 종료를 소개합니다. ACM + NLB 구성은 공개적으로 신뢰할 수 있는 인증서에 더 적합합니다. 애플리케이션 간 암호화 요구 사항이 있는 경우, ACM Private CA가 더 안전한 호스팅 관리 서비스를 제공할 수 있습니다.
이러한 실습 글이 독자들이 AWS EKS 클러스터에서 TLS 트래픽을 더 효과적으로 구성하고 관리하는 데 도움이 되길 바랍니다. API 게이트웨이에 대한 더 많은 정보는 블로그를 방문하거나 문의하기를 참조하세요.