12주차 - aws lattice, gateway api

개요

사전 지식

실습 진행

간단한 서버 통신


첫번째 라티스 활용 실습은 위와 같이 기본적인 eks 클러스터를 구축하고, 다른 vpc에서 접근하여 통신하는 것이다.[1]
이번에도 최대한 실습을 잘 따라가면서 내용을 정리하는 것을 주목적으로 삼는다.
내 커스텀 설정을 넣어서 실습을 하고 싶지만 그러기에 당장 시간이 조금 부족하다..

git clone https://github.com/aws-ia/terraform-aws-eks-blueprints.git

블루프린트 레포 파일을 받는다.
image.png
/patterns/vpc-lattice/client-server-communication/main.tf에서 리전 정보만 바꿔주면 기본 준비는 끝이다.

terraform init
terraform apply -target="module.client_vpc" -auto-approve
terraform apply -target="module.cluster_vpc" -auto-approve
terraform apply -target=aws_route53_zone.primary -auto-approve

terraform apply -target="module.client_sg" -auto-approve
terraform apply -target="module.endpoint_sg" -auto-approve

terraform apply -target="module.client" -auto-approve
terraform apply -target="module.vpc_endpoints" -auto-approve

terraform apply -target="module.eks" -auto-approve
terraform apply -target="module.addons" -auto-approve

terraform apply -auto-approve

aws eks update-kubeconfig --name client-server-communication --alias client-server-communication --region ap-northeast-2

내가 가장 싫어하는 타겟 방식..
내 생각에는 테라폼에는 파이프라인 스크립트 기능이 필요하다.
각 리소스 간 종속성을 관리해주는 것은 좋지만 세팅을 하다보면 필연적으로 어떤 리소스가 적용돼야만 다른 리소스를 사용할 수 있다던가 하는 것들이 있다.
이럴 때 파일을 단계적으로 적용시켜서 순서를 명확히 할 수 있는 기능이 있다면 관리가 훨씬 편해질 것이다.

코드 분석

image.png
client 파일에는 eks와 통신하기 위한 ec2와 vpc에 대한 세팅이 담겨 있다.
SSM으로 세션 연결을 할 수 있도록 정책이 포함돼있다.
image.png
vpc 엔드포인트가 뚫리는데, SSM을 사용하기 위한 세팅이며, 이를 위한 보안 그룹도 세팅된다.

image.png
다음으로 eks는 1.30버전으로 별도의 vpc에 프라이빗 서브넷 쪽에 만들어진다.
image.png
프라이빗 서브넷에 eks가 배치되니 기본적으로 인터넷으로 나가기 위한 nat 게이트웨이도 만든다.
image.png
다음으로는 게이트웨이api 컨트롤러와 external dns를 설치한다.
external dns 부분은 아래에서 다루겠다.
image.png
그 다음 데모 어플리케이션을 헬름을 통해 배포하는 것을 확인할 수 있다.
차트는 같은 디렉토리에서 찾아볼 수 있다.

apiVersion: gateway.networking.k8s.io/v1beta1
kind: GatewayClass
metadata:
  name: amazon-vpc-lattice
spec:
  controllerName: application-networking.k8s.aws/gateway-api-controller
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: my-services
  namespace: apps
spec:
  gatewayClassName: amazon-vpc-lattice
  listeners:
    - name: http
      protocol: HTTP
      port: 80
---
apiVersion: gateway.networking.k8s.io/v1beta1
kind: HTTPRoute
metadata:
  name: server
  namespace: apps
spec:
  hostnames:
    - server.example.com
  parentRefs:
    - name: my-services
      sectionName: http
  rules:
    - backendRefs:
        - name: server
          kind: Service
          port: 8090
      matches:
        - path:
            type: PathPrefix
            value: /

해당 차트에는 기본적인 게이트웨이 api 리소스들에 대한 양식이 정의돼있다.
게이트웨이에 정의된 80번 포트는 httpRoute에서 받아 데모 서비스의 8090포트로 보내도록 돼있다.
image.png
마지막으로 클러스터 노드들의 보안 그룹에 lattice의 ip 대역을 받을 수 있도록 룰을 추가한다.

image.png
lattice 파일에서는 라티스 서비스 네트워크를 만들고, 여기에 각 vpc를 연결한다.
데모 어플리케이션이 배포된 이후 2분을 강제로 기다리도록 세팅돼 있는데, 이걸 depends 하는 블록이 아무것도 없다.
그냥 프로비저닝 단계에서 다른 리소스들이 배포될 동안 시간을 버는 리소스라 생각하면 될 것 같다.
image.png
마지막으로 데모 어플리케이션으로 사용할 도메인에 대해 클라이언트 vpc에서 route53을 사용하도록 세팅한다.
image.png
eks 파일에서 external dns는 이 도메인을 위해서 존재한다.
즉, example.com은 external dns를 통해 route53에 등록되고 클라이언트 vpc는 해당 존의 영향을 받게 되므로 데모 주소를 현재 아키텍쳐 내에서 질의 받을 수 있게 되는 구조이다.

클라이언트에서 데모 어플리케이션 통신

image.png
배포된 환경을 분석하기 이전에 제대로 배포됐는지 확인해보자.
블루프린트 예제는 기본적으로 직접 세팅할 게 없다보니 실습 후, 사후 분석을 하는 방식으로 진행하게 되더라.

kubectl logs -f deployment/server -n apps --all-containers=true --since=1m

통신이 제대로 되는지 확인하기 위해 서버 쪽에서도 로그를 잠시 걸어둔다.

curl -i http://server.example.com

ssm으로 들어간 인스턴스에서는 그냥 요청을 날리기만 하면 된다.
image.png
응답이 제대로 파드로부터 오는 것이 확인된다.
image.png
서버 파드를 보아도 라티스에서 실행되는 헬스체킹들이 보이나 제대로 curl 요청을 받은 것을 확인할 수 있다.

2025/04/26 11:20:41 Receiving %!(EXTRA *http.Request=&{GET / HTTP/1.1 1 1 map[Accept:[*/*] User-Agent:[curl/8.3.0] X-Amzn-Lattice-Network:[SourceVpcArn=arn:aws:ec2:ap-northeast-2::vpc/vpc-037b672c4bad7e46c] X-Amzn-Lattice-Target:[ServiceArn=arn:aws:vpc-lattice:ap-northeast-2::service/svc-06159a634e1a2693d; ServiceNetworkArn=arn:aws:vpc-lattice:ap-northeast-2::servicenetwork/sn-0e258440c1c304c69; TargetGroupArn=arn:aws:vpc-lattice:ap-northeast-2::targetgroup/tg-07f926c2415770d89] X-Amzn-Source-Vpc:[vpc-037b672c4bad7e46c] X-Forwarded-For:[10.1.2.114]] {} <nil> 0 [] false server.example.com map[] map[] <nil> map[] 169.254.171.196:7250 / <nil> <nil> <nil> 0xc0001c8940})

해당 로그를 조금 더 자세히 보면 들어온 요청의 헤더값들을 확인할 수 있다.
일단 요청이 온 vpc의 arn 정보와 라티스 서비스 arn도 나온다.
image.png
해당 도메인으로의 질의는 라티스를 거친다는 것을 간략하게 짐작할 수 있다.

콘솔을 통한 분석

그럼 본격적으로 어떻게 환경이 구성됐길래 이게 가능한 건지도 알아보자.
image.png
먼저 vpc 콘솔에서 라티스에 서비스 네트워크를 들어가보면 하나의 서비스 네트워크가 생성된 것을 확인할 수 있다.
사진으로 찍진 않았으나 테라폼에서 설정했던 두 개의 vpc 연결도 확인할 수 있다.
이 서비스 네트워크에 등록된 하나의 서비스가 보이는데, 이것이 gateway api controller에 의해 만들어진 것으로 짐작할 수 있다.
image.png
해당 서비스 연결 id를 보면 도메인 이름이 두 개 있는 것을 볼 수 있다!
그 중 하나는 http route에서 설정한 도메인이다.
image.png
아예 해당 서비스에 들어가서 보면 라우팅 탭에 위에서 게이트웨이api 리소스로 설정했던 값들이 반영된 것이 보인다.
route에서 match 쪽 필드 그대로 리스너 룰로 만들어졌고, 어떤 서버로 포워딩을 하는 것을 확인할 수 있다.
image.png
구체적으로 해당 리소스는 타겟그룹으로, 이 타겟 그룹에는 데모 파드들이 위치한다.
image.png
위 파드들은 route에서 설정했던 서비스의 엔드포인트들이다.

하지만 이 정도로는 만족할 수 없다.
image.png
위의 설정들에 나온 도메인 이름이 구체적으로 ip 추적이 가능한 이유는 위에서 만들었던 route53 덕분이다.
보다시피 server.example.com에 대해 cname 레코드가 만들어진 것을 볼 수 있다.
그리고 이에 대한 값은 서비스가 기본으로 가지던 이름이다.
image.png
이를 기반으로 다시 라티스 서비스를 들어가보면 조금 더 명확해진다.
이 서비스는 위 route53에 의해 질의가 될 수 있도록 세팅돼있는 상태이다.
image.png
클라이언트 vpc에서 도메인 질의를 했을 때 나왔던 169로 시작하는 ip는 aws에서 관리하는 ip 대역이다.
조금 더 구체적으로는 aws 관리형 접두사 리스트라고 해서, 서비스마다 부여하는 ip 대역이 있다.[2]
이 대역으로 가는 트래픽은 aws 측으로 넘어가는데 이 부분부터는 aws에서 알아서 트래픽이 우리가 설정한 리소스나 엔드포인트로 갈 수 있도록 도와준다.
마치 인스턴스에서 IMDS를 얻어오는 것과 같은 원리라고 보면 되겠다.

gateway api controller 동작 추적

kubectl logs deployment/aws-gateway-api-controller-aws-gateway-controller-chart -n aws-application-networking-system --all-containers=true > lattice.log

도대체 gateway api controller는 무슨 일을 했던 걸까?
로그를 뜯어본다.
image.png
가장 초반에는 실행이 시작되며 게이트웨이api 리소스에 와치를 걸고, 이후에 해당 리소스들이 생성되자 콘솔에서 봤던 것들이 정직하게 만들어지는 것을 확인할 수 있다.
image.png
이러한 동작을 할 수 있는 이유는 위와 같이 라티스에 대한 조작, 그리고 필요한 정보를 조회하기 위한 읽기 권한을 가지고 있기 때문이다.

리소스 정리

terraform destroy -target="module.client_vpc" -auto-approve
terraform destroy -target="module.cluster_vpc" -auto-approve
terraform destroy -target=aws_route53_zone.primary -auto-approve

terraform destroy -target="module.client_sg" -auto-approve
terraform destroy -target="module.endpoint_sg" -auto-approve

terraform destroy -target="module.client" -auto-approve
terraform destroy -target="module.vpc_endpoints" -auto-approve

terraform destroy -target="module.eks" -auto-approve
terraform destroy -target="module.addons" -auto-approve

terraform destroy -auto-approve

실습에 사용했던 것들을 일일히 지워준다.
image.png
역시나 문제가 발생한다.
gatewayapi 컨트롤러를 통해 만들어진 서비스가 삭제되지 않아서 기본 라티스를 지우는데 실패했고, 해당 서비스는 심지어 route53에 레코드를 등록하고 있기 때문에 발생하는 문제로 보인다.
공식 문서에서도 리소스를 정리할 때 직접적으로 먼저 배포된 리소스들을 정리하라고 나온다.[3]
image.png
이를 위해서는 서비스를 지워야 하는데, 그러려면 또 서비스 네트워크와의 연결을 먼저 지워야 한다;;
지금이야 전체 아키텍쳐를 한번에 지우려고 하니까 발생하는 이슈라고 칠 수 있는데, gateway api 리소스를 지울 때도 이런 문제가 생기진 않겠지?
image.png
route53도 직접 지웠고, 이후에 다시 테라폼 디스트로이를 시켰다.
image.png
호호 또 문제가 발생한다..
확인해봤을 때는 vpc, eks 전부 잘 삭제됐기 때문에 추가적으로 iam에 들어가서 라티스를 위한 롤만 직접 삭제해주었다.

멀티 클러스터 보안 통신 구축

이제 생소한 라티스와 게이트웨이api 맛보기는 끝났다.
조금 더 복잡한 아키텍처를 구성하고, 클러스터 내부에서 어떻게 설정이 이뤄졌는지도 조금 더 상세하게 보도록 한다.

이번에는 이렇게 아키텍처를 구성한다![4]
보기만 해도 어지러운데, 차근차근 뜯어보자.
먼저 전체 구성의 목표는 멀티 클러스터 간 보안 통신을 하는 것이다.[5]
각 클러스터는 다른 VPC에 위치하고 있는 상태에서 암호 통신을 할 것이다.
이때 흔한 서비스 메시가 그렇듯이, 각 클러스터의 어플리케이션은 통신 간 암호화와 보안에 대해 신경 쓸 필요 없게 세팅한다.
그래서 어플리케이션 코드의 수정을 하지 않을 수 있도록 각 어플리케이션 앞단에 사이드카 프록시로 엔보이를 둘 것이다.
이 엔보이를 배치하기 위해, 각 워크로드가 배치될 때 Mutating Admission Webhook을 해주는 Kyverno를 둔다.
키베르노는 배치되는 워크로드에 두 가지 작업을 한다.

그리고 이렇게 배치된 엔보이가 해주는 역할은 구체적으로 다음과 같다.

그럼 위 아키텍쳐에 나온 번호에 맞춰 각 리소스와 동작을 정리하자면,

  1. HttpRoute 설정
    1. 라티스 gateway api로 서비스를 노출한다.
    2. 백엔드 서비스와 경로, 라우팅 규칙을 명시한다.
    3. 키베르노 정책을 설정한다.
  2. 엔보이 사이드카 주입
    1. aws 신원을 통해 aws api로의 요청을 서명한다.Automatically signs AWS API requests with AWS credentials
    2. 서비스 간 통신을 암호화한다.
  3. PCA
    1. 인증서를 관리한다.
    2. 구체적으로 라티스의 커스텀 도메인에 대한 인증서를 설정한다.
    3. 이를 기반으로 TLS 통신이 가능하게 한다.
  4. IAM 정책
  5. External DNS
    1. gateway api 컨트롤러의 DNS엔드포인트를 모니터링한다.
    2. 이에 대한 DNS 레코드를 Route53에 만들고 업데이트한다.
  6. App1 → App2 요청 흐름
    1. 서비스 네트워크를 통해 라우팅된다.
    2. IAM 정책을 통해 인증된다.
    3. 위에서 설정된 인증서를 통해 암호화 통신을 한다.
  7. App2 → App1 응답 흐름
    1. 사실 그냥 위와 같다.

여기에서 확인할 포인트는 이 정도로 정리했다.

환경 세팅

기본 환경 세팅


이번 실습도 몇 가지 단계를 거쳐서 세팅을 해야 하는데, 먼저 두 클러스터가 사용하게 될 기본 인프라를 구성해야 한다.
https를 위한 기본적인 인증서 세팅, 도메인, 라티스 세팅을 진행해야 한다.
image.png
environment 디렉토리에 main.tf에서 리전을 수정해준다.

cd terraform-aws-eks-blueprints/patterns/vpc-lattice/cross-cluster-pod-communication/environment/
terraform init
terraform apply --auto-approve

일단 기본 환경을 배포한다.
image.png
여기에는 기본적인 route53과, 라티스에 통신을 하기 위해 사용되는 기본적인 롤이 들어있다.
이름을 보면 알겠지만, 이 롤은 나중에 엔보이를 위해 쓰인다.

각 클러스터 세팅

다음으로는 각 클러스터를 구축해야 한다.
image.png
cluster 디렉토리에서도 마찬가지로 main.tf에서 리전을 수정해주자.
보다시피 클러스터의 ip 대역을 동일하게 세팅한다.
대역 충돌이 발생하지 않는 라티스의 장점을 간접적으로 체험해볼 수 있으렷다.

cd ../cluster/
./deploy.sh cluster1
eval `terraform output -raw configure_kubectl`

./deploy.sh cluster2
eval `terraform output -raw configure_kubectl`

다음 각 클러스터를 배포한다.
image.png
해당 스크립트는 테라폼 워크스페이스를 분리해서 각각을 적용하도록 돼있다.

클러스터 코드 분석

테라폼 코드로 보면 전체적으로 이전 실습과 비슷하다.
image.png
그러나 주의 깊게 볼 부분이 있는데, 이번에는 컨트롤러를 설치할 때 사용할 서비스 네트워크를 명시한다.
두 클러스터가 배포될 때 둘다 lattice-gateway를 사용하게 되어 결과적으로 같은 서비스 네트워크를 사용한다.
image.png
다만 뮤테이팅을 걸기 위해 키베르노를 설치한다.
image.png
이번에는 단계를 나누어 플랫폼 차트를 먼저 배포하는 것을 볼 수 있다.
데모 어플리케이션이 배포되기 이전에 설정돼야 하는 키베르노 정책 리소스와 게이트웨이 리소스를 먼저 배포하는 것이다.
여기에 allowedCluster 부분이 설정돼있는데, 코드를 뜯어본 바로는 이 부분은 사실 없어도 된다.
(구체적으로는 플랫폼 차트 values 파일에 해당 필드가 없어도 된다.)
image.png
게이트웨이 리소스에 조금 변화가 있는데, 이번에는 네임스페이스를 지정하면서 셀렉터를 기반으로 매칭한다.
image.png
tls 세팅에 대해서는 두 가지 진입점을 만드는데, 이것도 실습 세팅 상에서는 사실 custom domain쪽만 있으면 된다.
image.png
여기에 aws gateway api controller만의 리소스인 IAMAuthPolicy도 볼 수 있다.
게이트웨이에 라티스의 서비스를 호출할 수 있는 권한을 정의한다.
image.png
여기에 키베르노의 리소스도 정의돼있다.
보다시피 초기화 컨테이너로 iptables를 건드려서 트래픽이 엔보이를 향하도록 두고 있고, 동시에 엔보이도 배포한다.
iptables 명령어는 다음의 설정을 담고 있다.

즉, 나가는 모든 요청은 엔보이를 거치게 된다는 것이다.
근데 여기에서 조금 주의해서 봐야할 부분이 있다고 생각이 든다.
내가 iptables를 제대로 보고 있는 게 맞다면, 이건 들어오는 트래픽에 대해서는 작동하지 않는다.
아까 위에서 어플리케이션은 http로 통신을 한다고 했는데, 요청을 보내는 측에서 http 요청을 보내는 것이 https로 변환되는 것만 제대로 보장되는 세팅인 것이다.
하지만 위에서 httproute에 tls 관련 라우팅 시 터미네이션이 일어나도록 세팅됐기 때문에 결과적으로는 요청을 받는 측도 http 요청을 받게 될 것이다.

그럼 엔보이는 어떤 식으로 세팅이 되는가?
해당 설정은 여기에서 확인할 수 있다.[6]
image.png
일단 이건 엔보이 설정 파일이다.
http 필터에 흥미로운 게 두 개 보인다.
일단 아래에는 SigV4 서명 설정 필터가 여기에 있는데, 특정 헤더를 제외한 트래픽에 대해 서명을 진행하는 설정이 담겨있다.
그리고 그 위로 포워드 프록시로서의 필터가 들어가는데, dns 질의를 127.0.0.1로 거는 것이 보인다..
사실 이 부분은 명확하게 아직 파악을 못 했다.
image.png
다만 일반적인 엔보이 세팅에 기반해 추측을 하자면, 단서는 클러스터 쪽 설정에 있다.
클러스터에는 엔드포인트가 있어야 하는데, 여기에는 엔드포인트가 보이지 않는다.
대신 클러스터 타입에 대한 정의가 내려져 있는데, 여기에도 동적 포워드 프록시로 세팅이 들어간다.
즉 현재 엔보이가 포워드 프록시로서 동작하고 있으며 실제 트래픽을 보내야 하는 업스트림 호스트를 dns 질의를 통해 찾아 보내도록 하는 세팅이라는 것이다.

클러스터 쪽에 tls 설정이 들어간 것이 보인다.

cat /etc/envoy/envoy.yaml.in | envsubst \$AWS_REGION,\$JWT_AUDIENCE,\$JWT_JWKS,\$JWT_ISSUER,\$JWKS_HOST,\$APP_DOMAIN > /etc/envoy/envoy.yaml
aws acm-pca get-certificate-authority-certificate --certificate-authority-arn $CA_ARN --region $AWS_REGION --output text > /etc/pki/ca-trust/source/anchors/internal.pem
update-ca-trust extract

cat /etc/envoy/envoy.yaml
/usr/local/bin/envoy --base-id 1 -l trace -c /etc/envoy/envoy.yaml

실제 엔보이가 실행될 때는 이 스크립트를 거친다.
위에 환경변수로서 세팅된 값들을 먼저 갈아치우고, PCA로부터 인증서를 받아온다.
(이게 아까 기본 환경 세팅 부분에서 봤던 롤이 사용되는 부분이다.)
그리고 컨테이너 속 신뢰된 CA 정보를 업데이트한다.
결과적으로 앞으로 통신할 때 사용되는 인증서를 서명한 CA에 대해 엔보이는 정말 신뢰할 수 있는 신뢰 기관으로서 인식하게 될 것이다.

image.png
위 플랫폼 차트가 배포된 이후에 데모 어플리케이션 차트가 배포된다.
image.png
디플로이먼트에서는 실행 프로세스의 그룹이 1000이 되도록 세팅한다.
결과적으로 데포 어플리케이션의 트래픽은 위 iptables 규칙 상에서 8080포트로 보내질 것이다.
image.png
httproute는 여기에 있는데, 위에서 본 두 개의 tls 게이트웨이 중 커스텀 도메인 부분만 활용하는 것을 확인할 수 있다.
image.png
이번에는 httproute에 대한 IAMAuthPolicy 리소스도 만든다.
여기에서 allowed 관련 필드가 사용되는데, 이 httpRoute로 들어올 수 있는 트래픽의 명세를 정의하는 것으로 보인다.
이 설정은 라티스 서비스로 들어가는 트래픽에 대해 위 조건을 만족시키지 않는 요청을 거부시킬 것이다.

확인

kubectl --context eks-cluster1 \
  exec -ti -n apps deployments/demo-cluster1-v1 -c demo-cluster1-v1 \
  -- curl demo-cluster2.example.com

image.png
각 클러스터에서 서로를 향해 요청을 날렸을 때 응답이 돌아온다면 성공이다.

kubectl --context eks-cluster1 exec -ti -n apps deployments/demo-cluster1-v1 -c demo-cluster1-v1 -- curl demo-cluster1.example.com

image.png
그러나 보다시피 자신을 향한 요청은 성공하지 못한다.
이건 위에서 IAMAuthPolicy에 서로의 클러스터에 대해서만 통신을 허용했기 때문이다.

kubectl --context eks-cluster1 exec -ti -n apps deployments/demo-cluster1-v1 -c demo-cluster1-v1 -- curl demo-cluster1-v1 

image.png
물론 위 통신은 라티스를 통하는 도메인을 이용했기 때문에 막히는 거고, 그냥 클러스터 내부의 서비스 도메인을 이용해 요청하면 당연히 통신이 가능하다.

apiVersion: v1
kind: Pod
metadata:
  name: debug
  namespace: apps
spec:
  containers:
  - image: nicolaka/netshoot
    name: debug
    command: [sh,-c,"tail -f /dev/null"]
  terminationGracePeriodSeconds: 1

간단하게 테스트를 할 수 있는 파드를 배포해보자.

keti -n apps debug -- curl demo-cluster2.example.com 

image.png
이 요청 역시 실패하는데, 이 파드는 위 엔보이가 세팅돼있지 않기에 라티스로 통신할 권한이 없기 때문이다.

하지만 언뜻 생각하면 이상하게 느껴지기도 한다.
일단 IAMAuthPolicy 상에서는 클러스터와 네임스페이스만 따지기 때문에 위 파드를 제한을 받을 일이 없다.
image.png
image.png
또한 eks 클러스터 콘솔에서 파드 아이덴티티 설정에 들어가보면, apps 네임스페이스의 default 서비스어카운트를 가지는 파드는 이 파드 아이덴티티를 가지고 aws 리소스와 통신을 할 수 있다.
이때 파드 아이덴티티는 이 조건을 만족하는 파드들이 해당 롤의 권한을 가진다는 의미 정도밖에 되지 않는다.
image.png
서비스 네트워크 액세스 정책을 보면 anonymous 주체는 통신을 할 수 없도록 돼있다.
방금 만든 디버그용 파드는 SigV4 서명이 돼있지 않기에 권한은 있을지라도 정확하게 신원이 누구인지 확인이 되지 않는다.
그렇기 때문에 익명으로서 요청이 인식되고 라티스의 서비스를 호출할 권한이 없다고 인식되어버리는 것이다.

하지만 데모 어플리케이션의 통신 주체는 엔보이이다.
엔보이는 위에서 보았듯이 http 요청에 대해 SigV4 서명을 받는 필터를 거친 후에 프록시 작업을 수행한다.
그렇기 때문에 엔보이의 신원은 명확하게 인식되고, 이로부터 통신이 가능해지게 되는 것이다.

그럼 어떻게 해야 내가 만든 커스텀 워크로드가 통신을 할 수 있을까?

apiVersion: apps/v1
kind: Deployment
metadata:
  name: debug
  namespace: apps
spec:
  selector:
    matchLabels:
      app: debug
  replicas: 1
  template:
    metadata:
      labels:
        app: debug
    spec:
      containers:
      - image: nicolaka/netshoot
        name: debug
        command: [sh,-c,"tail -f /dev/null"]
      terminationGracePeriodSeconds: 1

image.png
키베르노의 정책으로 디플로이먼트면 뮤테이팅이 발동하게 했으니 이렇게만 세팅하면 당연히 주입이 일어날 거라 생각했는데, 왜인지 주입이 일어나지 않았다.

리소스 정리

./destroy.sh cluster2
./destroy.sh cluster1

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 ../environment
terraform destroy -auto-approve

결론

스터디 내용만 보고 실습을 먼저 진행해서 감을 잡고 작동 원리와 문서를 정리하려고 했는데, 상당히 난항을 겪었다.
게이트웨이 api를 이스티오에 적용하는 것을 먼저 해보다보니 자연스럽게 이스티오 기준으로 생각을 하면서 진행했던 것이 화근이었던 것 같다.
그걸 떠나서도 이번 실습이 AWS에 빠삭하지 않는 내게 꽤나 어려웠다는 것도 한 몫한 것 같다.
이번에 얻었던 수확 중 하나는 라티스에 대한 기본적인 사용법, 그리고 AWS sdk를 거치지 않는 요청은 파드 아이덴티티를 통하더라도 SigV4 서명이 되지 않는 다는 것.

이번 내용은 조금 더 개인 정리가 필요할 것 같다.

번외 - gateway 리소스로 새로운 서비스 네트워크 만들기?

apiVersion: gateway.networking.k8s.io/v1beta1
kind: Gateway
metadata:
  name: test
  namespace: lattice-gateway
spec:
  gatewayClassName: amazon-vpc-lattice
  listeners:
    - name: http-listener
      port: 81
      protocol: HTTP
      allowedRoutes:
        kinds:
          - kind: HTTPRoute
        namespaces:
          from: Selector
          selector:
            matchLabels:
              allow-attachment-to-infra-gw: "true"

게이트웨이는 서비스 네트워크를 나타낸다고 했으니, 임의로 하나를 만들면 새로운 서비스 네트워크가 만들어질 것이라고 생각했다.
image.png
그러나 막상 해보니 서비스 네트워크를 찾을 수 없다면서 게이트웨이는 계속 준비되지 않았다.
image.png
여태까지 보니까 게이트웨이의 이름은 곧 서비스 네트워크의 이름이다.
그래서 서비스 네트워크를 만들어봤다.
image.png
그러자 성공적으로 게이트웨이가 초기화됐다.
여기에서 알 수 있었던 것은, AWS에서는 게이트웨이를 만든다고 해서 실제 리소스가 생성되는 것이 아니란 것이었다.
이것은 이스티오에서 게이트웨이 api를 사용할 때와 매우 다른 동작이다.
AWS에서는 gateway api로 라티스를 전체적으로 관리할 수 있도록 설계하고 만든 게 아닌 것으로 보인다.
오히려 이미 존재하는 라티스의 서비스 네트워크를 기반으로 그 위에 서비스를 설정할 수 있도록 만든 것이다.
image.png
게이트웨이 리소스가 활성화되도 vpc 결합조차 일어나지 않는다.
image.png
혹시 vpc 연결을 하는 리소스가 있지 않을까 해서 찾아보니 있긴 있었다.
어쩌면 서비스 네트워크가 알아서 만들어지지 않는다는 점에서 내가 너무 비약적으로 추측을 하고 있는 것일 수도 있겠다.

aws gateway api controller에 대한 생각 정리

아직 완전히 정리되지는 않았지만, 중간 중간 들었던 생각을 잠시 나열한다.

생소해서 그런 것도 있겠지만 라티스를 기반으로 하는 gateway api에는 조금 이질감이 들었다.

gateway api는 다양한 설정과 기능을 담을 수 있도록 계속 개발이 진행되고 있는 만큼, 지금 섣불리 판단하기는 이르다고 본다.
무엇보다 아직 내가 aws gateway api controller에 대해 함부로 판단을 할 수 있을 만큼의 지식이 없다.

관련 문서

이름 noteType created

참고


  1. https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/network/client-server-communication/ ↩︎

  2. https://docs.aws.amazon.com/vpc/latest/userguide/working-with-aws-managed-prefix-lists.html ↩︎

  3. https://www.gateway-api-controller.eks.aws.dev/latest/guides/getstarted/#cleanup ↩︎

  4. https://aws-ia.github.io/terraform-aws-eks-blueprints/patterns/network/cross-cluster-pod-communication/ ↩︎

  5. https://aws.amazon.com/ko/blogs/containers/secure-cross-cluster-communication-in-eks-with-vpc-lattice-and-pod-identity-iam-session-tags/ ↩︎

  6. https://github.com/aws-samples/amazon-eks-security-immersion-day/blob/mainline/docker/envoy/envoy.yaml.in ↩︎