CloudNet@ 팀의 가시다님께서 Leading 하시는 AEWS Study 2주차 도전과제 정리
이번 포스팅에서는 EKS VPC CNI 를 사용할 때의 기능 중 하나인 Security Groups Per Pod 에 대해 알아보겠습니다.
1. Security Groups Per Pod
AWS 에서 EC2 인스턴스를 사용할 때 가장 기본이 되는 보안 설정은 ENI 수준에서 설정 가능한 Security Group 입니다.
컨테이너 환경인 EKS 에서는 EC2 인스턴스 위에 무수히 많은 Pod 가 배포되어 있고,
Pod 마다 다른 서비스를 사용하는 경우 도 있습니다.
그러나 EC2 위에 배포된 Pod 는 기본적으로 모두 같은 보안 그룹을 공유하는 방식 이었고,
이는 보안 규정에 위배되는 등의 번거로운 상황을 야기했습니다.
때문에 Pod 의 서비스 별로 보안 규칙을 설정할 필요 가 생기는 데, 이를 해결하기 위해 나온 것이 바로 Security Groups Per Pod 입니다. SG Per Pod 는 기존의 인스턴스 별 보안 그룹이 아닌 Pod 별 보안 그룹을 설정할 수 있어 보다 유연하게 보안 규칙을 적용 할 수 있게 되었습니다.
1.1. SG Per Pod 제약 조건
a. Windows Node 에서는 사용 불가 b. T
시리즈 EC2 인스턴스는 사용 불가 c. VPC CNI 버전 1.7.7 이상
kubectl describe daemonset aws-node --namespace kube-system | grep amazon-k8s-cni: | cut -d : -f 3
d. EKS Cluster Role 에 AmazonEKSVPCResourceController
정책 부여
2. Security Groups Per Pod 활성화
kubectl describe daemonsets aws-node -n kube-system | grep ADDITIONAL_ENI_TAGS: -B1 -A26
아래의 ENABLE_POD_ENI 옵션 이 Security Groups Per Pod 기능 이다.
2.1. ENABLE_POD_ENI 활성화
앞서 설명한 것과 같이 t 타입의 EC2 는 해당 기능을 사용하지 못하는 관계로 m5.large 타입으로 테스트를 진행 했습니다.
kubectl set env daemonset aws-node -n kube-system ENABLE_POD_ENI=true
ENABLE_POD_ENI 가 활성화되면,
각 노드에 vpc.amazonaws.com/has-trunk-attached: "true"
라는 레이블이 부여 됩니다.
kubectl get nodes -o yaml | grep vpc.amazonaws.com/has-trunk-attached -A1
2.2. Security Group Policy 설정
Security Group Per Pod 가 활성화 되면, securitygrouppolicies.vpcresources.k8s.aws 라는 이름의 CRD 를 생성할 수 있습니다.
해당 CRD 로 Pod 별 SG 를 설정할 수 있게됩니다.
kubectl get crd
a. 테스트를 위한 네임스페이스 생성
kubectl create ns my-namespace
b. Pod 별 보안그룹 설정을 위해, AWS 콘솔에서 보안그룹을 1개 생성해줍니다.
이 때 생성할 Pod 와 EKS Cluster 간 CoreDNS 질의 를 위해,
Cluster SG 에서 DNS(TCP/UDP) 53 포트를 인바운드로 허용 해줍니다.
c. CRD yaml 을 생성 합니다. 이 때, groupIds 에는 앞서 생성했던 보안그룹의 ID를 입력 합니다.
# my-security-group-policy.yaml
apiVersion: vpcresources.k8s.aws/v1beta1
kind: SecurityGroupPolicy
metadata:
name: my-security-group-policy
namespace: my-namespace
spec:
podSelector:
matchLabels:
role: my-role
securityGroups:
groupIds:
- sg-0ef10865c2ab90d9c
kubectl apply -f my-security-group-policy.yaml
kubectl get securitygrouppolicies.vpcresources.k8s.aws -n my-namespace
d. Sample App 배포, 앞서 배포했던 CRD의 레이블 설정과 일치하는 레이블을 지닌 pod가 CRD 설정의 적용 대상 입니다.
# sample-application.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-deployment
namespace: my-namespace
labels:
app: my-app
spec:
replicas: 4
selector:
matchLabels:
app: my-app
template:
metadata:
labels:
app: my-app
role: my-role
spec:
terminationGracePeriodSeconds: 120
containers:
- name: nginx
image: public.ecr.aws/nginx/nginx:1.23
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: my-app
namespace: my-namespace
labels:
app: my-app
spec:
selector:
app: my-app
ports:
- protocol: TCP
port: 80
targetPort: 80
kubectl apply -f sample-application.yaml
e. Security Group 테스트
배포한 Pod 중 하나에 접속하여 CoreDNS 에 질의를 시도합니다.
kubectl get pods -n my-namespace
kubectl exec -it -n my-namespace my-deployment-5cb557c48b-lwnfv -- /bin/bash
배포된 서비스를 아래의 명령어를 입력하여 불러옵니다.
curl my-app
nginx 서비스가 정상적으로 응답 해줍니다.
f. Security Groups 제거
그렇다면 Deployment Pod 가 CoreDNS 에 도달하지 못하도록 Cluster 보안그룹에서 해당 규칙을 삭제 해줍니다.
똑같은 Pod에서 다시 한 번 nginx 서비스를 불러봅시다.
curl my-app
Cluster 보안그룹에서 DNS 관련 규칙을 삭제했을 뿐인데, DNS 질의를 하지 못하는 것을 확인 할 수 있습니다.
이렇게 EKS 에서는 securitygrouppolicies 라는 CRD 를 통해 Pod 별 보안그룹을 설정할 수 있음 을 테스트해보았습니다.
참고 문서
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/security-groups-for-pods.html#security-groups-pods-deployment
https://www.eksworkshop.com/docs/networking/security-groups-for-pods/
https://aws.github.io/aws-eks-best-practices/networking/sgpp/
https://archive.eksworkshop.com/beginner/115_sg-per-pod/10_secgroup/