728x90
[실습 2] Multi Cluster secure communication
- 멀티 클러스터 환경 간에서 Amazon VPC Lattice를 활용한 안전한 통신 방법에 대해 실습
주요 컴포넌트
- 인프라 구성
- 두 개의 VPC: VPC cluster 1과 VPC cluster 2가 독립적으로 구성
- 두 개의 EKS 클러스터: 각 VPC에 EKS Cluster 1과 EKS Cluster 2 배포
- VPC Lattice: 두 VPC 간의 서비스 통신을 위한 중앙 관리형 연결 서비스
- 애플리케이션 구성
- EKS Cluster 1 애플리케이션:
- App1 Service가 Pod로 배포됨
- Envoy sidecar 프록시를 통한 서비스 메시 구성
- HTTP Route를 통한 외부 트래픽 라우팅
- EKS Cluster 2 애플리케이션:
- App2 Service가 Pod로 배포됨
- 마찬가지로 Envoy sidecar 프록시와 HTTP Route 구성
- EKS Cluster 1 애플리케이션:
- 정책 및 보안
- Kyverno: 각 클러스터에 적용된 정책 관리 도구로 사이드카 주입 등을 관리
- IAM Auth Policy: 두 클러스터 간의 인증 및 권한 정책 설정
- Private Certificate Authority: 중앙 인증서 관리
- Certificate Manager: *.example.com 도메인을 위한 인증서 관리
- 네트워킹
- AWS Gateway API Controller: 각 클러스터의 API 트래픽 제어
- DNS 구성:
- ExternalDNS를 통한 DNS 레코드 관리
- demo-cluster1.example.com 및 demo-cluster2.example.com으로 각 클러스터 서비스 노출
- Amazon Route 53을 통한 도메인 관리
주요 흐름 및 프로세스
- VPC Lattice를 통해 HTTPS 트래픽이 두 클러스터 간에 라우팅됨
- 각 클러스터의 IAM Auth Policy가 접근 권한을 제어
- Pod Identity 기능을 통해 Envoy SigV4 proxy 컨테이너에 ACM에 대한 권한 및 VPC Lattice service invoke 권한 부여
- AWS Gateway API Controller가 각 클러스터의 인그레스 트래픽을 관리
- ExternalDNS가 자동으로 DNS 레코드를 생성하여 서비스 디스커버리 지원
Terraform 코드 준비 및 프로비저닝
- environment 프로비저닝
- environment 환경에서는 실습에 필요한 사전 환경(Route53, VPC Lattice, IAM Role, ACM 등)을 프로비저닝
cd terraform-aws-eks-blueprints/patterns/vpc-lattice/cross-cluster-pod-communication/environment/
#main.tf 파일을 열고, 7번째 라인의 region을 ap-northeast-2로 수정
5 locals {
6 name = "vpc-lattice"
7 region = "ap-northeast-2"
8
9 domain = var.custom_domain_name
10
11 tags = {
12 Blueprint = local.name
13 GithubRepo = "github.com/aws-ia/terraform-aws-eks-blueprints"
14 }
15 }
terraform init
terraform apply --auto-approve
- cluster 프로비저닝
- 실습에 사용할 두 개의 EKS 클러스터 및 데모 애플리케이션을 구성
cd ../cluster/
#main.tf 파일을 열고, 31번째 라인의 region을 ap-northeast-2로 수정
29 locals {
30 name = "eks-${terraform.workspace}"
31 region = "us-west-2"
32
33 cluster_vpc_cidr = "10.0.0.0/16"
34 azs = slice(data.aws_availability_zones.available.names, 0, 3)
35
36 domain = data.terraform_remote_state.environment.outputs.custom_domain_name
37 certificate_arn = data.terraform_remote_state.environment.outputs.aws_acm_cert_arn
38 acmpca_arn = data.terraform_remote_state.environment.outputs.aws_acmpca_cert_authority_arn
39 custom_domain = data.terraform_remote_state.environment.outputs.custom_domain_name
./deploy.sh cluster1
# 배포 완료 후, 아래 명령으로 kubectl config 설정을 완료합니다.
eval `terraform output -raw configure_kubectl`
./deploy.sh cluster2
# 배포 완료 후, 아래 명령으로 kubectl config 설정을 완료합니다.
eval `terraform output -raw configure_kubectl`
- Access > Pod Identity associations 순으로 콘솔을 이동하면 아래와 같은 내용을 확인
- vpc-lattice-sig4-client라는 IAM role이 apps라는 네임스페이스의 default라는 Service account에 associate 된 것을 확인
- IAM role은 ACM의 PCA에 대한 여러 액세스 권한과 VPC Lattice Service에 대한 invoke 권한이 설정
- 데모 애플리케이션 Pod(demo-cluster1-v1)의 구성을 확인
kubectl describe po demo-cluster1-v1-7b8b98f676-mq7mp -n apps
..
..
#Init Containers를 통해 envoy-sigv4 컨테이너를 위한 IPTables 세팅이 수행
Init Containers:
iptables-init:
Container ID: containerd://2970fc0a891bae5b736d6e2b15714bad5d81f199150e80802c40e0f0ed1055c7
Image: public.ecr.aws/seb-demo/iptables:v1
Image ID: public.ecr.aws/seb-demo/iptables@sha256:32f68e35a3c5925c7ee4cc664411063579418975e99754e0b9a53b1405b49e03
Port: <none>
Host Port: <none>
Command:
/bin/sh
-c
iptables -t nat -N EGRESS_PROXY; iptables -t nat -A OUTPUT -p tcp -d 169.254.171.0/24 -j EGRESS_PROXY; iptables -t nat -A EGRESS_PROXY -m owner --gid-owner 0 -j RETURN; iptables -t nat -A EGRESS_PROXY -p tcp -j REDIRECT --to-ports 8080; iptables -t nat -L -n -v;
..
..
#envoy-sigv4 컨테이너와 데모 애플리케이션 컨테이너 확인
Containers:
envoy-sigv4:
Container ID: containerd://8e738c2e008c3337cc6dd89d60f95435253eff26b3f49b4afc93f0cba1e7bf4d
Image: public.ecr.aws/seb-demo/envoy-sigv4:v0.5
Image ID: public.ecr.aws/seb-demo/envoy-sigv4@sha256:097a68853c38c9cc2cf44d1de31e10538dd5b312cbc9092b12d2e49f7f92fdee
Port: 8080/TCP
Host Port: 0/TCP
Args:
-l
info
State: Running
Started: Mon, 28 Apr 2025 01:29:01 +0900
Ready: True
Restart Count: 0
Environment:
APP_DOMAIN: example.com
CA_ARN: arn:aws:acm-pca:ap-northeast-2:890742582773:certificate-authority/eba23575-525f-41c1-8038-8c965a2cf1b3
AWS_STS_REGIONAL_ENDPOINTS: regional
AWS_DEFAULT_REGION: ap-northeast-2
AWS_REGION: ap-northeast-2
AWS_CONTAINER_CREDENTIALS_FULL_URI: http://169.254.170.23/v1/credentials
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8wvph (ro)
/var/run/secrets/pods.eks.amazonaws.com/serviceaccount from eks-pod-identity-token (ro)
demo-cluster2-v1:
Container ID: containerd://9c8e91ce1521559befbd12414fd21c7378d7edb15362c4343cef3150c4be2eb1
Image: public.ecr.aws/seb-demo/http-server:latest
Image ID: public.ecr.aws/seb-demo/http-server@sha256:05b913f6c411303f8967ed556b12c80ca49c63a9a37005bc8651c18df54266a6
Port: <none>
Host Port: <none>
State: Running
Started: Mon, 28 Apr 2025 01:29:15 +0900
Ready: True
Restart Count: 0
Environment:
PodName: Hello from demo-cluster2-v1
AWS_STS_REGIONAL_ENDPOINTS: regional
AWS_DEFAULT_REGION: ap-northeast-2
AWS_REGION: ap-northeast-2
AWS_CONTAINER_CREDENTIALS_FULL_URI: http://169.254.170.23/v1/credentials
AWS_CONTAINER_AUTHORIZATION_TOKEN_FILE: /var/run/secrets/pods.eks.amazonaws.com/serviceaccount/eks-pod-identity-token
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-8wvph (ro)
/var/run/secrets/pods.eks.amazonaws.com/serviceaccount from eks-pod-identity-token (ro)
- 통신 테스트 및 동작방식 확인
- eks-cluster1의 데모 애플리케이션에서 eks-cluster2의 데모 애플리케이션으로 간단한 요청
kubectl --context eks-cluster1 \
exec -ti -n apps deployments/demo-cluster1-v1 -c demo-cluster1-v1 \
-- curl demo-cluster2.example.com
##응답
Requsting to Pod(demo-cluster2-v1-69cdbfd45b-mpkjt): Hello from demo-cluster2-v1
- eks-cluster1의 데모 애플리케이션에서 그대로 eks-cluster1의 데모 애플리케이션으로 요청
kubectl --context eks-cluster1 \
exec -ti -n apps deployments/demo-cluster1-v1 -c demo-cluster1-v1 \
-- curl demo-cluster1.example.com
##응답
AccessDeniedException: User: arn:aws:sts::890742582773:assumed-role/vpc-lattice-sigv4-client/eks-eks-cluste-demo-clust-583f641c-89e6-4242-8833-14b2f7ce4044 is not authorized to perform: vpc-lattice-svcs:Invoke on resource: arn:aws:vpc-lattice:ap-northeast-2:890742582773:service/svc-05a011bb3aacd80e4/ because no service-based policy allows the vpc-lattice-svcs:Invoke action
- eks-cluster1의 IAMAuthPolicy에서 eks-cluster2 으로만 호출 가능하도록 설정되어 있기 때문에 에러가 발생
app-httproute.yaml 확인
...
...
apiVersion: application-networking.k8s.aws/v1alpha1
kind: IAMAuthPolicy
metadata:
name: {{ .Release.Name }}-iam-auth-policy
namespace: {{ .Release.Namespace }}
spec:
targetRef:
group: "gateway.networking.k8s.io"
kind: HTTPRoute
namespace: {{ .Release.Namespace }}
name: {{ .Release.Name }}
policy: |
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::{{ .Values.awsAccountID }}:root"
},
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/eks-cluster-name": "{{ .Values.allowedCluster }}",
"aws:PrincipalTag/kubernetes-namespace": "{{ .Values.allowedNamespace }}"
- IAMAuthPolicy란?
- IAMAuthPolicy는 Gateway API의 직접 정책 연결(Direct Policy Attachment)을 구현(implements)하는 GEP-713: 메타리소스 및 정책 연결
- IAMAuthPolicy는 Gateway, HTTPRoute 또는 GRPCRoute에 연결될 수 있습니다.
- IAMAuthPolicy는 VPC Lattice의 Service Network 또는 Service에 첨부되는 IAM Policy 문서로, 주체(principal)가 첨부된 Service Network의 Service 또는 특정 첨부된 Service에 접근하는 권한을 제어
- IAMAuthPolicy는 Gateway, HTTPRoute, GRPCRoute를 통해 이동하는 트래픽에 대해서만 권한 부여를 수행할 수 있습니다. 클라이언트가 직접 k8s 서비스 DNS로 트래픽을 전송하는 경우에는 권한 부여가 적용되지 않습니다.
- eks-cluster1의 IAMAuthPolicy 설정 확인
- VPC Lattice Serivce를 invoke하는 액션 중에서 클러스터 명(eks-cluster-name)이 eks-cluster2 여야하고, 네임스페이스가 apps일 때에만 Invoke를 허용
kubectl --context eks-cluster1 \
get IAMAuthPolicy -n apps demo-cluster1-iam-auth-policy \
-o json | jq ".spec.policy | fromjson"
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"AWS": "arn:aws:iam::890742582773:root"
},
"Action": "vpc-lattice-svcs:Invoke",
"Resource": "*",
"Condition": {
"StringEquals": {
"aws:PrincipalTag/eks-cluster-name": "eks-cluster2",
"aws:PrincipalTag/kubernetes-namespace": "apps"
}
}
}
]
}
- IAMAuthPolicy의 자세한 내용을 확인
kubectl describe IAMAuthPolicy demo-cluster1-iam-auth-policy -n apps
- IAMAuthPolicy의 적용 대상(Target Ref)이 demo-cluster1 라는 이름을 가진, apps 네임스페이스의 HTTPRoute 리소스임을 확인
- 대상이 되는 HTTPRoute를 조회하기 위해 아래 명령을 수행
kubectl describe HTTPRoute demo-cluster1 -n apps
Name: demo-cluster1
Namespace: apps
Labels: app.kubernetes.io/managed-by=Helm
Annotations: application-networking.k8s.aws/lattice-assigned-domain-name:
demo-cluster1-apps-05a011bb3aacd80e4.7d67968.vpc-lattice-svcs.ap-northeast-2.on.aws
meta.helm.sh/release-name: demo-cluster1
meta.helm.sh/release-namespace: apps
API Version: gateway.networking.k8s.io/v1beta1
Kind: HTTPRoute
Metadata:
Creation Timestamp: 2025-04-27T16:13:21Z
Finalizers:
httproute.k8s.aws/resources
Generation: 1
Resource Version: 7133
UID: d4c02e23-a61b-4ccd-a7e5-a0d2612283e7
Spec:
Hostnames:
demo-cluster1.example.com
Parent Refs:
Group: gateway.networking.k8s.io
Kind: Gateway
Name: lattice-gateway
Namespace: lattice-gateway
Section Name: http-listener
Group: gateway.networking.k8s.io
Kind: Gateway
Name: lattice-gateway
Namespace: lattice-gateway
Section Name: https-listener-with-custom-domain
Rules:
Backend Refs:
Group:
Kind: Service
Name: demo-cluster1-v1
Port: 80
Weight: 1
Matches:
Path:
Type: PathPrefix
Value: /
..
..
- HTTPRoute로 라우팅 되는 대상이 demo-cluster1-v1 이라는 Service임을 확인
- 해당 Service 명세를 확인
kubectl describe svc demo-cluster1-v1 -n apps
Name: demo-cluster1-v1
Namespace: apps
Labels: app.kubernetes.io/managed-by=Helm
Annotations: meta.helm.sh/release-name: demo-cluster1
meta.helm.sh/release-namespace: apps
Selector: app=demo-cluster1-v1
Type: ClusterIP
IP Family Policy: SingleStack
IP Families: IPv4
IP: 172.20.251.14
IPs: 172.20.251.14
Port: <unset> 80/TCP
TargetPort: 8090/TCP
Endpoints: 10.0.30.19:8090
Session Affinity: None
Internal Traffic Policy: Cluster
Events: <none>
- Service를 통해 라우팅 되는 대상이 10.0.30.19:8090 임을 확인할 수 있습니다. (demo-cluster1-v1)\
- VPC 콘솔 > PrivateLink and Lattice > Lattice service 로 이동하여 demo-cluster1-apps의 체크박스를 클릭하고, Routing 탭을 클릭하면 아래와 같이 라우팅 대상 그룹을 확인
- 실습 리소스 정리
#클러스터 정리
cd /workshop/terraform-aws-eks-blueprints/patterns/vpc-lattice/cross-cluster-pod-communication/cluster/
./destroy.sh cluster2
./destroy.sh cluster1
#environment 환경 정리
SN=$(aws vpc-lattice list-service-networks --query 'items[?name==`lattice-gateway`].id' --output text)
if [ -n "$SN" ]; then
aws vpc-lattice delete-service-network --service-network-id "$SN"
fi
cd /workshop/terraform-aws-eks-blueprints/patterns/vpc-lattice/cross-cluster-pod-communication/environment/
terraform destroy -auto-approve
728x90
'2025_AEWS Study' 카테고리의 다른 글
11주차 - ML Infra(GPU) on EKS(2) (0) | 2025.04.28 |
---|---|
11주차 - ML Infra(GPU) on EKS(1) (0) | 2025.04.28 |
12주차 - Amazon VPC Lattice for Amazon EKS(1) (0) | 2025.04.27 |
10주차 - K8s 시크릿 관리 Update(5) (0) | 2025.04.14 |
10주차 - K8s 시크릿 관리 Update(4) (0) | 2025.04.14 |