일반적으로 EKS에서 Pod의 트래픽은 워커 노드의 Security Group을 따른다. 결국 Pod A와 Pod B가 동일한 워커노드에 있다면 Security Group 또한 동일할 것이다.
필자는 EKS를 도입하기전 EC2 별로 서비스들을 운영하면서 보안그룹을 관리하였기에 Pod 별로 보안그룹을 관리하는 방법이 없을까 찾아보게 되었고 SecuriyGroupPolicy라는 것을 알게 되었다. 물론 익숙하지 않은 나에게 Ingree/Egress를 제어하는 방법은 다양한 것으로 보이지만 AWS native하게 설계된 서비스와 AWS VPC CNI를 쓰고 있는 나에게 적절해 보여 적용해보게 되었다. 간단히 말해 Pod 별로 SecuriyGroup를 만들어 관리하는 것이다.
AWS SecuriyGroup은 ENI와 연관된다. ENI가 EC2인스턴스 또는 EKS Pod의 네트워크 인터페이스를 담당하여 ENI에 Security Group을 적용하여 트래픽을 제어할 수 있는 것이다.
기본적으로 EC2에 하나의 ENI가 할당되지만 EKS를 사용하는 경우 여러개의 ENI가 할당될 수 있고 ENI가 가질 수 있는 Private IP Address(파드의 IP)를 여럿 가질 수 있다. 하지만 EC2의 사양에 따라 최대 ENI 및 Private IP 갯수는 제한된다.
https://docs.aws.amazon.com/ko_kr/AWSEC2/latest/UserGuide/using-eni.html
SecuriyGroupPolicy를 사용하기 위해서는 AWS VPC CNI를 사용해야만 가능하다. 그도 그럴만 한 것이 위에 설명한 ENI에 부착된 SecuriyGroup을 활용하기 위함이 아닐까 싶다. VPC CNI를 사용하면 VPC CIDR에 설정한 대역 내에서 파드 IP를 할당받을 수 있다. 또한 별도의 네트워크 대역을 관리할 필요가 없어 EKS를 사용하면 VPC CNI를 사용하는 것 같다.
VPC CNI를 설치하면 CNI를 관리하기 위한 aws-node라는 데몬셋이 생성된다.
aws-node는 Primary ENI를 하나 생성하고 해당 ENI가 생성된 서브넷에서 Secondary IP 주소를 생성한다. Primary ENI는 Private IP를 가지고 있고 해당 Private IP가 EC2 Private IP에 등록된다. kubelet은 컨테이너 생성 요청이오면 aws-node에 IP 할당을 요청하는데 Secondary IP 리스트 중에 사용하지 않는 리스트를 반환하고 Secondary IP 중 여유분이 없는 경우 ENI(Secondary ENI)를 생성한다. 그리고 이 ENI(Secondary ENI)가 가지고 있는 Secondary IP를 받게 된다.
Pod Security Group(파드 보안그룹)
해당 기능은 VPC CNI를 사용할 때만 적용이 가능하며 일부 인스턴스(워커노드)에서 지원한다. AWS가 파드 보안그룹을 지원하기 위한 방식이 바로 ENI Trunking/Branching 이다.
Trunking/Branching은 AWS가 내부적으로 구현한 ENI 관리 방식이다. 원래대로라면 여러 파드가 동일한 ENI를 가지고 SecurityGroup이 연결되었을텐데 Trunking, Branching ENI를 활용하면 파드 각각의 Branching ENI와 연결되고 노드마다 부착된 Truncking ENI에 붙게 된다. 결국 파드 별로 SecuriyGroup을 가질 수 있게 되는 것이다.
실제로 네트워크 인터페이스 유형을 확인하면 다음과 같이 trunk 모드와 branch 모드를 확인할 수 있었다.
적용하는 방법은 어렵지 않았지만 필자가 꽤 삽질한 부분이 하나 있었다.
설치 순서는 다음 문서를 보고 천천히 진행해보면 된다.
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/security-groups-pods-deployment.html
Amazon EKS Pods의 보안 그룹에 대해 Amazon VPC CNI plugin for Kubernetes 구성 - Amazon EKS
다음 단계에 설명된 대로 Amazon VPC CNI plugin for Kubernetes 추가 기능 중 1.11.0 이상을 사용하고 POD_SECURITY_GROUP_ENFORCING_MODE=standard를 설정한 경우에는 이전 명령을 실행할 필요가 없습니다.
docs.aws.amazon.com
kubectl set env daemonset aws-node -n kube-system ENABLE_POD_ENI=true
kubectl patch daemonset aws-node -n kube-system \
-p '{"spec": {"template": {"spec": {"initContainers": [{"env":[{"name":"DISABLE_TCP_EARLY_DEMUX","value":"true"}],"name":"aws-vpc-cni-init"}]}}}}'
(문서 내용을 참고하도록 하자)
필자가 놓친 부분은 다음과 같다. EKS 클러스터 안에서 파드끼리 모두 통신 가능하도록 eks-cluster-sg에 대해 모든 포트가 열려있다면 상관없겠지만 이런 저런 수정하면서 필자의 경우는 모든 TCP에 대해서만 eks-cluster-sg가 열려있어서 Unknownhostexception 같은 것들이 막 발생했다. 나중에 UDP에 대한 53번 포트(DNS)가 열려있어야 함을 천천히 문서보며 깨달았지만 ping도 던져보고 이런 저런 삽질을 했다. 요청/응답이 잘 오는 경우도 있었기 때문에 더 헷갈렸던 거 같다. (기억상 DNS 캐시 때문인지 동일한 DB인데 어떤 파드는 DB의 주소를 찾고 어떤 파드는 DB의 주소를 찾지 못했었다. 물론 나중에는 모두 DB의 주소를 찾지 못했다.)
설치하는 방법은 문서를 보고 참고하면 어렵지 않고,
Amazon VPC CNI 플러그인 버전 1.7.7 이상, m5, c5, r5, m6g, c6g 및 r6g 등 인스턴스 패밀리와 세대는 지원되지만 t 패밀리의 인스턴스 유형은 지원되지 않기에 지원되는 인스턴스 유형의 전체 목록은 하기를 확인하도록 하자.
https://github.com/aws/amazon-vpc-resource-controller-k8s/blob/v1.5.0/pkg/aws/vpc/limits.go
amazon-vpc-resource-controller-k8s/pkg/aws/vpc/limits.go at v1.5.0 · aws/amazon-vpc-resource-controller-k8s
Controller for managing Trunk & Branch Network Interfaces on EKS Cluster using Security Group For Pod feature and IPv4 Addresses for Windows Node. - aws/amazon-vpc-resource-controller-k8s
github.com
'IT' 카테고리의 다른 글
쿠버네티스[EKS] gp2, gp3 마이그레이션 (0) | 2025.02.25 |
---|---|
쿠버네티스[EKS] Cluster, Node, Add ons Upgrade (1) | 2025.02.21 |
쿠버네티스[EKS] IRSA(IAM for ServiceAccount) (0) | 2025.02.20 |
스프링부트 Virtual Thread, Spring Data Redis(Lettuce) 도입기 (0) | 2025.01.09 |
쿠버네티스[EKS] Strimzi Kafka 구축 (Kafka-Exporter, Metrics, Kafka-UI) (1) | 2024.11.18 |