쿠버네티스 네트워크 스터디를 들어가기 앞서, CNI가 무엇인가에 대해 찾아보았습니다.
CNCF 프로젝트의 일환으로서, 리눅스 컨테이너에서 네트워크 인터페이스를 구성하기 위한 플러그인을 만드는 표준입니다.
CNI의 공식 깃허브 설명에 따르면, 아래와 같이 정의하고 있습니다.
💡 CNI (Container Network Interface), a Cloud Native Computing Foundation project, consists of a specification and libraries for writing plugins to configure network interfaces in Linux containers, along with a number of supported plugins. CNI concerns itself only with network connectivity of containers and removing allocated resources when the container is deleted. Because of this focus, CNI has a wide range of support and the specification is simple to implement.
출처 - https://github.com/containernetworking/cni
awsvpc는 노드와 파드의 네트워크 대역을 동일하게 설정합니다.
파드간 통신하는 경우 일반적으로 K8S Calico CNI
는 오버레이 통신을 하고, awsvpc
는 동일 대역으로 직접 통신을 합니다. 즉, VPC의 주소 공간에 포드에 대한 IP 주소를 할당합니다.
💡 이러한 이점을 통해 컨테이너와 노드는 추가적인 경로 구성이나 오버레이 없이 VPC 네트워크를 통해 직접 통신할 수 있습니다.
출처 - https://medium.com/elotl-blog/kubernetes-networking-on-aws-part-ii-47906de2921d
출처 - pkos 스터디
워커 노드1
기본 네트워크 구성은 다음과 같습니다.
ebs-csi-node의 Pod IP 정보를 확인합니다
kubectl get pod -n kube-system -l app=ebs-csi-node -owide
노드의 라우팅 정보를 확인합니다. >> EC2 네트워크의 정보의 '보조 프라이빗 IPv4 주소'와 비교합니다.
앞서 awsvpc CNI의 특징 중 하나인 VPC 내부에서 파드의 IP 대역과 노드(워커)의 IP 대역이 같으므로 별도의 오버레이(Overlay) 통신 기술 없이, 파드간 직접 통신이 가능합니다.
출처 - https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md
파드에서 외부 통신 흐름 - iptable에 SNAT을 통해서 노드의 eth0 IP로 변경되어서 외부와 통신합니다.
출처 - https://github.com/aws/amazon-vpc-cni-k8s/blob/master/docs/cni-proposal.md
VPC CNI 의 External source network address translation (SNAT
) 설정에 따라, 외부(인터넷) 통신 시 SNAT 하거나 혹은 SNAT 없이 통신을 할 수 있습니다 - 링크
Secondary IPv4 addresses : 인스턴스 유형에 최대 ENI 갯수와 할당 가능 IP 수를 조합하여 선정합니다.
워커 노드의 인스턴스 타입 별 파드 생성 제한
👉🏻 최대 파드 생성 갯수 : (Number of network interfaces for the instance type × (the number of IP addressess per network interface - 1)) + 2
# t3 타입의 정보(필터) 확인
aws ec2 describe-instance-types --filters Name=instance-type,Values=**t3.*** \
--query "InstanceTypes[].{**Type**: InstanceType, **MaxENI**: NetworkInfo.MaximumNetworkInterfaces, **IPv4addr**: NetworkInfo.Ipv4AddressesPerInterface}" \
--output table
--------------------------------------
| DescribeInstanceTypes |
+----------+----------+--------------+
| IPv4addr | MaxENI | Type |
+----------+----------+--------------+
| 15 | 4 | t3.2xlarge |
| **6** | **3** | **t3.medium** |
| 12 | 3 | t3.large |
| 15 | 4 | t3.xlarge |
| 2 | 2 | t3.micro |
| 2 | 2 | t3.nano |
| 4 | 3 | t3.small |
+----------+----------+--------------+
# 파드 사용 가능 계산 예시 : aws-node 와 kube-proxy 파드는 host-networking 사용으로 IP 2개 남음
((MaxENI * (IPv4addr-1)) + 2)
**t3.medium** 경우 : ((3 * (6 - 1) + **2** ) = **17개 >>** aws-node 와 kube-proxy 2개 제외하면 **15개**
# 워커노드 상세 정보 확인 : 노드 상세 정보의 Allocatable 에 pods 에 17개 정보 확인
kubectl describe node | grep Allocatable: -A6
Allocatable:
cpu: 2
ephemeral-storage: 59763732382
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3854320Ki
**pods: 17**
파드 집합에서 실행중인 애플리케이션을 네트워크 서비스로 노출하는 추상화 방법입니다.
즉, 외부로부터 파드에 접근할 수 있는 정책을 정의할 수 있습니다.
쿠버네티스의 서비스는 파드와 비슷하게 REST 오브젝트 형식으로 사용합니다.
이에 대해서 정리한 내용은 아래에 정리되어 있습니다.
쿠버네티스 서비스 타입 - https://velog.io/@xgro/쿠버네티스-서비스-타입
K8S 서비스/인그레스 생성 시 도메인을 설정하면, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) 에 A 레코드(TXT 레코드)로 자동 생성/삭제
목표
: 파드간 통신 시 tcpdump 내용을 확인하고 관련 스샷을 올려주세요
파드1에서 파드2로 ping 테스트를 시행하고, tcpdump 내용을 확인하여 별도의 NAT 동작 없이 통신하는 것을 확인할 수 있었습니다.
# 파드 IP 변수 지정
POD1=$(kubectl get pod pod-1 -o jsonpath={.status.podIP})
POD2=$(kubectl get pod pod-2 -o jsonpath={.status.podIP})
# 파드1 Shell 에서 파드2로 ping 테스트
kubectl exec -it pod-1 -- ping -c 2 $POD2
# 파드2 Shell 에서 파드1로 ping 테스트
kubectl exec -it pod-2 -- ping -c 2 $POD1
목표
: 어떤 방식을 사용하더라고 좋으니, 워커 노드 1대에 100대의 파드가 배포되게 설정하고 관련 스샷을 올려주세요
# 실습 참고참고
kubectl apply -f ~/pkos/2/nginx-dp.yaml
kubectl scale deployment nginx-deployment --replicas=100
EKS worker node pod 한도 늘리기(too many pod 해결) | 너구리는 라쿤이 아니다
https://lcc3108.github.io/articles/2021-08/eks-too-many-pod.html
Amazon EC2 노드에 사용 가능한 IP 주소의 양 늘리기
https://docs.aws.amazon.com/ko_kr/eks/latest/userguide/cni-increase-ip-addresses.html
해당 문제를 해결하면서 재밌기도 하고 좋은 공부가 되었습니다.
문제를 해결하기 위한 과정은 별도의 블로그에 포스팅 하도록 하겠습니다.
인스턴스 타입에 따른 ENI 개수를 확인합니다
Node의 Allocatable 설정의 pods 개수를 확인합니다.
kops edit cluster
명령어를 이용하여 kubelet의 하위 설정에 maxPods: 110 를 추가합니다.
ENABLE_PREFIX_DELEGATION 및 WARM_PREFIX_TARGET 설정합니다
설정이 잘 반영되었는지 확인합니다.
Rolling-update Cluster를 적용하여 변경된 설정에 따라 클러스터를 업데이트합니다.
업데이트 후 다시한번 Node의 Allocatable 설정의 Pods 개수를 확인합니다.
파드 100개를 스케일하여 정상적으로 실행되는지 확인합니다.
목표
: 서비스(NLB)/파드 배포 시 ExternalDNS 설정해서, 각자 자신의 도메인으로 NLB를 통해 애플리케이션(파드)로 접속해보고 관련 스샷을 올려주세요
ExternalDNS 기능을 이용하여, 간단한 설정만으로 원하는 도메인이 생성되며, NLB의 A 레코드에 자동으로 연결되는 과정을 확인 할 수 있습니다.
목표
: 아래 활용 기능 중 1개를 선택해서 실습 후 결과 내용을 올려주세요
NLB에 TLS 적용하기를 실습하였습니다. TLS를 적용하여 기존 http 프로토콜을 https로 운영할 수 있도록 구성하여 접속해보는 과정을 확인하였습니다.
2주차 강의가 성공적으로 종료되었습니다.
쿠버네티스 환경에 익숙하지는 않았지만, 기본적으로 AWS 환경에서 ECS를 운영하고 있는 엔지니어로서 어떤 부분은 실무에서 직접 경험해 본 내용도 있고, 또한 컨테이너 오케스트레이션에서 알지 못했던 내용들에 대해서 많이 배울 수 있는 한주였습니다.
짧은 시간임에도 수준 높은 강의를 만들고, 진행해주신 가시다님께 다시한번 감사드리며, 2주차 블로깅을 끝마치도록 하겠습니다.