안녕하세요. 이 글은 security group for pod 시리즈 중 첫번째 글입니다. security group for pod를 사용하기 앞서 왜 등장하게 이 기능이 등장하게 되었는지 배경을 설명합니다.
security group for pod 시리즈 목차
- EKS cluster security group과 불편한점: https://malwareanalysis.tistory.com/648
- pod에 security group적용 방법: https://malwareanalysis.tistory.com/649
1. 제약사항
1.1 인스턴스 타입
security group for pod는 모든 EC2인스턴스 타입에서 사용하지 못합니다. 23.9월 기준으로 m5, c5, r5, p3, m6g, c6g 및 r6g인스턴스 타입을 지원합니다.
security group for pod를 사용할 수 있는 노드는 Capacity와 Allocatable필드에 pod-eni가 보입니다.
1.2 CNI 호환
security group for pod는 VPC CNI만 지원합니다. 그리고 VPC CNI 1.7.7이상 버전만 security group for pod 기능을 사용할 수 있습니다.
1.3 pod 재부팅 필요
아쉽게도 security group for pod를 적용하고, 적용한 pod는 재부팅 해야 합니다.
2. 실습 환경생성
저는 security group for pod를 실습하기 위해 eksctl로 EKS를 생성했습니다. security group for pod를 사용할 수 있는 인스턴스를 지정하고 비용을 절약하기 위해 spot인스턴스를 사용했습니다.
3. EKS 설정
3.1 EKA IAM role 설정
EKS IAM role에 AmazonEKSVPCResourceController Policy를 추가합니다. eksctl는 EKS 생성할 때 자동으로 해당policy를 추가합니다.
3.2. aws-node daemonset 설정
VCP CNI인 aws-node daemonset을 수정합니다.
kubectl set env daemonset aws-node -n kube-system ENABLE_POD_ENI=true
daemonset 설정을 수정하면 aws-node pod가 재부팅 됩니다.
3.3 노드 라벨 확인
aws-node pod가 재부팅 되면 sg for pod를 사용할 수 있는 노드에 라벨이 추가됩니다. 라벨이 설정된 노드가 한 개도 없다면 실습을 진행못합니다.
kubectl get nodes -o wide -l vpc.amazonaws.com/has-trunk-attached=true
라벨이 설정된 노드를 describe해보세요. capacity필드와 allocatable필드에 pod-eni가 추가되어 있습니다.
4. pod에 security group 적용 방법
4.1 security group 생성
pod에 적용할 security group을 생성합니다. VPC는 EKS가 있는 VPC를 선택합니다. 그리고 inbound, outbound 규칙을 전부 제거합니다.
4.2 쿠버네티스 SecurityGroupPolicy리소스 생성
SecurityGroupPolicy 리소스를 생성합니다. pod와 securitygroup을 지정해야 합니다. security group은 이전에 생성한 securitygroup을 사용합니다.
- github 예제 코드 링크: https://github.com/choisungwook/eks_pod_security_group/blob/main/k8s_manifests/netshoot_with_securitygroup.yaml
kubectl apply -f securitygroup.yaml
securitygrouppolicy가 생성되었는지 확인합니다.
kubectl get sgp
4.3 (옵션) pod 재시작
만약 securitygrouppolicy리소스에 선택한 pod가 기존에 실행 중인 pod이면, pod를 재부팅 합니다. pod를 재부팅 하지 않으면 securitygrouppolicy가 적용되지 않습니다.
4.4 pod상태 확인
securitygrouppolicy에 적용한 pod가 잘 실행되고 있는지 확인합니다. securitygrouppolicy가 올바르지 않거나 스케쥴링 가능한 노드가 없으면 pod는 오류상태에 있습니다.
5. 테스트
security group을 적용한 pod에서 네트워크 통신이 잘 되는지 테스트하는 챕터입니다. 테스트 pod는 네트워크 디버깅 도구가 있는 netshoot pod를 사용했습니다.
- github 예제 코드 링크: https://github.com/choisungwook/eks_pod_security_group/blob/main/k8s_manifests/netshoot_with_securitygroup.yaml
5.1 시나리오1: pod와 외부 IP ping 테스트
■ 시나리오
pod가 외부IP로 ping이 되는지 테스트합니다.
■ 테스트 결과
netshoot pod에서 8.8.8.8에 ping을 실행하면 응답을 받지 못합니다.
■ 오류 분석&해결
왜냐하면 netshot pod에 적용한 securitygroup outbound에서 ICMP허용 규칙이 없기 때문입니다.
outbound에 ICMP프로토콜을 추가합니다.
그리고 다시 netshoot pod에서 8.8.8.8에 ping을 날리면 응답을 받습니다.
5.2 시나리오2: DNS 쿼리 테스트
■ 시나리오
2번째 테스트는 DNS쿼리 응답을 받는지 테스트합니다.
■ 테스트 결과
netshoot pod에서 google서버로 nslookup을 하면 응답을 받지 못합니다.
■ 오류 분석&해결
왜냐하면 netshot pod에 적용한 securitygroup outbound에서 DNS허용 규칙이 없기 때문입니다. outbound에 DNS허용 규칙을 추가하려면 쿠버네티스 DNS원리를 이해해야 합니다.
쿠버네티스에서 DNS 관리는 coredns가 합니다. coredns는 cluster security group영향을 받기 때문에, pod가 사용하는 securitygroup과 cluster security group 모두 설정해야 합니다.
security group for pod 문서에서도 coredns를 사용하기 위해, DNS프로토콜을 security group에 설정하라고 가이드합니다.
cluster security group inbound에 DNS프로토콜 TCP/UDP를 추가합니다. 소스는 netshoot pod에 적용된 security group입니다.
netshoot pod에 적용된 security group에는 outbound에 DNS 프로토콜 TCP/UDP를 추가합니다. 소스는 cluster security group입니다.
security group설정 후 다시 nslookup을 하면 DNS응답을 받습니다.
5.3 시나리오3: route53 public hostzone통신 테스트
■ 시나리오
3번째 시나리오는 2번째 시나리오 확장입니다. security group가 적용된 netshoot pod에서 nginx pod를 접근할 때 도메인으로 접근할 수 있는지 테스트합니다. nginx pod를 생성하고 외부에서 pod를 접속할 수 있도록 ALB Ingress와 Route53을 설정했습니다.
■ 테스트 결과
3번째 시나리오 테스트를 위하 ALB controller, External DNS controller 오픈소스를 사용할 줄 알아야 합니다. 오픈 소스 사용방법은 저의 블로그나 공식문서를 참고해주시면 감사드립니다.
- ALB controller 블로그 정리: https://malwareanalysis.tistory.com/597
nginx pod와 service, ingress를 생성합니다. 쿠버네티스 리소스와 AWS 리소스가 잘 생성되었는지 확인합니다.
웹 브라우저에서 nginx가 잘 접속되는지 확인합니다.
security group이 적용된 netshoot pod에서 우리가 생성한 nginx를 호출합니다. netshoot pod에서 nginx를 호출하지 못했습니다.
■ 오류 분석&해결
2번 테스트 시나리오에서 DNS 프로토콜을 security group에 설정했으므로 DNS는 잘 실행됩니다. 하지만 pod가 사용하는 security group outbound에 http프로토콜을 허용하지 않았으므로, netshoot -> ALB간 네트워크 통신이 되지 않습니다. 그래서 netshoot pod가 nginx를 호출하지 못했습니다.
netshoot pod에 적용한 security group outbound에 80번을 추가 합니다. 소스는 ALL인 0.0.0.0으로 설정했습니다. HTTP프로토콜은 AWS API 등에도 사용하므로 ALL로 설정했습니다.
security group설정 후 netshoot에서 다시 nginx를 호출해보세요. 호출이 성공하여 welcome to nginx 응답을 받습니다.
5.4 시나리오4: pod probe
■ 시나리오
4번째 시나리오는 security group이 적용된 pod에 probe를 설정하는 테스트입니다. 저는 nginx pod에 livenessprobe를 설정했습니다.
■ 테스트 결과
kubectl get pod로 상태를 확인하면 pod가 CrashLookBackOff 상태입니다.
■ 오류 분석&해결
pod가 왜 정상이 아닌지 describe명령어로 확인할 수 있습니다. liveness probe가 실패하여 pod가 비정상상태입니다.
pod에 적용한 security group inbound 규칙에 probe port를 추가하면 오류가 사라집니다. probe체크는 kubelet이 하므로, kubelet이 pod에 접근할 수 있도록 security group inbound설정이 필요합니다.
security group for pod 문서에서도 probe사용시 주의사항을 가이드합니다.
pod가 사용하는 security grouppolicy inbound에 probe 포트를 추가합니다. 소스는 노드 IP를 적어야 하는데, pod가 재생성되어 다른 노드로 변경되면 노드 IP가 변경됩니다. 그래서 저는 테스트이기 때문에 vpc cidr를 설정했습니다. 실제 업무에 적용한다면 subnet대역을 설정할 것 같습니다.
nginx pod를 삭제하고 상태를 확인해보지만 여전히 pod가 비정상정입니다. nginx pod가 probe를 실패하여 계속 재시작되고 있습니다.
security group for pod가 probe를 사용하려면 VPC CNI설정이 필요합니다. security group for pod 문서를 확인하면 probe를 사용하기 위해 TCP early demux를 disable해야 한다고 설명합니다.
VCP CNI를 설정하면 aws-node pod가 재부팅됩니다. aws-node pod가 정상상태인 것을 확인합니다.
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"}]}}}}'
저는 pod상태를 깔끔히 확인하기 위해 기존 pod를 삭제했습니다. pod가 probe조건을 통과하여 Running상태입니다.
'전공영역 공부 기록' 카테고리의 다른 글
kubectl krew 플러그인 - resource-capacity (0) | 2023.09.20 |
---|---|
AWS WAF 사용방법과 운영 적용방안 (4) | 2023.09.17 |
security group for pod 1편: EKS cluster security group과 불편한점 (0) | 2023.09.10 |
게임으로 배우는 AWS S3(부제 S3 game) (0) | 2023.08.27 |
aws 환경변수 초기화 (0) | 2023.08.21 |