새소식

AWS/EKS

[EKS Study 2주차] EKS Networking - Security Groups Per Pod

  • -

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

 

 

  • CRD 배포 및 확인
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/

Contents

포스팅 주소를 복사했습니다