728x90
CNI
- Container Network Inferface로 컨테이너 간 네트워크를 구성
- 다양한 CNI가 존재( Flannel, Calico, Cilium, Weave Net, AWS VPC )
AWS VPC CNI
- Node와 Pod의 IP 대역이 같아 직접 통신이 가능하여 네트워크 통신의 최적화(성능, 지연)
- VPC 와 통합 : VPC Flow logs , VPC 라우팅 정책, 보안 그룹(Security group) 을 사용 가능함
- VPC ENI 에 미리 할당된 IP(=Local-IPAM Warm IP Pool)를 파드에서 사용할 수 있음
Node Network 정보
- aws-node(cni)dhk kube-proxy는 Node의 Root Net Namespace를 사용
- aws-node와 kube-proxy의 경우 Node의 IP를 그대로 사용
- core-dns의 경우 Per Pod Net Namespace를 사용
- core-dns는 Node의 IP가 아닌 별도의 IP를 사용
EKS 내 노드 간 Pod 통신 확인
- AWS CNI 특징으로 Node IP 대역과 Pod IP이 동일하여 직접 통신이 가능
- 일반적인 K8S CNI의 경우 오버레이 통신
- Test Pod 생성
# 테스트용 파드 netshoot-pod 생성
cat <<EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
name: netshoot-pod
spec:
replicas: 3
selector:
matchLabels:
app: netshoot-pod
template:
metadata:
labels:
app: netshoot-pod
spec:
containers:
- name: netshoot-pod
image: nicolaka/netshoot
command: ["tail"]
args: ["-f", "/dev/null"]
terminationGracePeriodSeconds: 0
EOF
- Pod 접속 후 다른 노드에 배치된 Pod로 Ping 통신
# 파드1 Shell 에서 파드2로 ping 테스트
kubectl exec -it $PODNAME1 -- ping -c 2 $PODIP2
# 파드2 Shell 에서 파드3로 ping 테스트
kubectl exec -it $PODNAME2 -- ping -c 2 $PODIP3
# 파드3 Shell 에서 파드1로 ping 테스트
kubectl exec -it $PODNAME3 -- ping -c 2 $PODIP1
- 각각 워커 노드 접속 후 tcpdump를 통해 통신 확인
# 워커 노드 EC2 : TCPDUMP 확인
sudo tcpdump -i any -nn icmp
- pod1 IP: 192.168.3.246
- pod2 IP: 192.168.2.8
- pod3 IP: 192.168.1.119
- tcpdump를 통해 ping 통신 확인 결과, 노드 간 Pod 통신에서 Pod IP로 직접 통신하는 것을 확인
EKS Pod에서 외부 통신 확인
파드에서 외부 통신 흐름 : iptable 에 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신됨
- 워커 노드의 공인 IP 확인
- Pod 내 공인 IP 확인
Node의 공인IP와 Pod 내 공인IP가 동일 → Pod가 외부랑 통신하는 경우, 해당하는 워커노드의 eth0에 매핑되어 있는 공인IP를 통해 외부 통신
- Pod에서 Google도메인으로 ping 통신 확인 (외부 통신)
- 워커노드에서 tcpdump를 통해 Google과 ping 통신 확인
노드에 파드 생성 갯수 제한
- 사전준비 - kube-ops-view
- 웹페이지를 통해 현재 워커 노드의 정보와 Pod의 상태 정보를 실시간으로 확인
# kube-ops-view
helm repo add geek-cookbook https://geek-cookbook.github.io/charts/
helm install kube-ops-view geek-cookbook/kube-ops-view --version 1.2.2 --set env.TZ="Asia/Seoul" --namespace kube-system
kubectl patch svc -n kube-system kube-ops-view -p '{"spec":{"type":"LoadBalancer"}}'
# kube-ops-view 접속 URL 확인 (1.5 배율)
kubectl get svc -n kube-system kube-ops-view -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "KUBE-OPS-VIEW URL = http://"$1":8080/#scale=1.5"}'
- 노드 공간 바닦에 배치된 Pod는 kube-system 네임스페이스에 배치된 Pod
- 노드 공간 윗쪽에 배치된 Pod는 사용자가 생성한 Pod가 순차적으로 배치
- AWS Instance 종류 별(워커노드) Pod 생성 갯수
- 최대 파드 생성 갯수 : (Number of network interfaces for the instance type × (the number of IP addressess per network interface - 1)) + 2
- 현재 실습으로 사용하고 있는 t3.medium의 경우 ENI3개를 사용 할 수 있으며, 최대 할당 가능 IP는 15
(yjsong@myeks:default) [root@myeks-bastion-EC2 ~]# 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 |
| 12 | 3 | t3.large |
| 15 | 4 | t3.xlarge |
| 6 | 3 | t3.medium |
| 2 | 2 | t3.micro |
| 2 | 2 | t3.nano |
| 4 | 3 | t3.small |
+----------+----------+--------------+
- 워커 노드의 스펙이 올라가면 더 많은 Pod 생성 가능 - C Type 인스턴스
(yjsong@myeks:default) [root@myeks-bastion-EC2 ~]# aws ec2 describe-instance-types --filters Name=instance-type,Values=c5*.* \
> --query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}" \
> --output table
----------------------------------------
| DescribeInstanceTypes |
+----------+----------+----------------+
| IPv4addr | MaxENI | Type |
+----------+----------+----------------+
| 30 | 8 | c5d.12xlarge |
| 10 | 3 | c5d.large |
| 10 | 3 | c5n.large |
| 30 | 8 | c5.4xlarge |
| 15 | 4 | c5n.2xlarge |
| 30 | 8 | c5n.9xlarge |
| 15 | 4 | c5d.2xlarge |
| 15 | 4 | c5.xlarge |
...
- 파드 사용 가능 계산 : aws-node 와 kube-proxy 파드는 host-networking 사용으로 IP 2개 남음 / ((MaxENI * (IPv4addr-1[워커노드 자신 IP])) + 2)
- 예시)t3.medium 경우 : ((3 * (6 - 1) + 2 ) = 17개 >> aws-node 와 kube-proxy 2개 제외하면 15개
- 워커 노드의 상세정보를 통해서도 확인 가능
kubectl describe node | grep Allocatable: -A6
Allocatable:
cpu: 1930m
ephemeral-storage: 27905944324
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3388360Ki
pods: 17
- 최대 Pod TEST - replicas=50
(yjsong@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl get pods | grep Pending
nginx-deployment-f7f5c78c5-2c268 0/1 Pending 0 111s
nginx-deployment-f7f5c78c5-9l9pw 0/1 Pending 0 111s
nginx-deployment-f7f5c78c5-jnbff 0/1 Pending 0 111s
nginx-deployment-f7f5c78c5-ktglf 0/1 Pending 0 111s
nginx-deployment-f7f5c78c5-l9qvk 0/1 Pending 0 111s
nginx-deployment-f7f5c78c5-ljhbq 0/1 Pending 0 111s
nginx-deployment-f7f5c78c5-m4qzx 0/1 Pending 0 111s
nginx-deployment-f7f5c78c5-ppdpc 0/1 Pending 0 111s
(yjsong@myeks:default) [root@myeks-bastion-EC2 ~]# kubectl describe pods nginx-deployment-f7f5c78c5-2c268
...
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Warning FailedScheduling 117s (x2 over 7m21s) default-scheduler 0/3 nodes are available: 3 Too many pods. preemption: 0/3 nodes are available: 3 No preemption victims found for incoming pod..
- 최대 생성 Pod의 수를 넘었기 때문에 8개 Pod는 실행되지 못하고 Pending 상태
- kube-ops-view 설치로 워커 노드 별 kube-system pod 추가 → 따라서 워커 노드 당 14개 Pod 할당 가능
- AWS Console 내 ec2 정보 확인 시 3개 eni 할당 및 15개 보조 프라이빗 주소(Secondary IP)가 할당되어 있는것을 확인
- Pod 삭제 또는 replicas 감소 시 유동적으로 ENI 및 보조 프라이빗 주소 감소
Service & AWS LoadBalancer Controller
- Service
- Pod는 생성 및 삭제 될때 마다 내부 IP가 변경하는 특성이 있음.
- Service는 이러한 Pod에 탑재된 애플리케이션이 외부와 상호 통신이 가능하도록 하는 역할 수행
- Pod가 외부와 통신할 수 있도록 클러스터 내부에서 고정 IP를 갖는 Service를 이용할 수 있도록 함
- Deployment, Statefulset 처럼 같은 애플리케이션을 구동하도록 구성된 여러 파드들에게 단일 네트워크 진입점을 부여하는 역할
- ClusterIP
- NodePort
- LoadBalancer
- ExternalName
- LoadBalancer Controller
- 일반적인 Service에서 Loadbalancer의 경우 로드벨런서를 거쳐 각 Node의 iptable 정책에 따라 Pod에 분산되게 설정
- VPC CNI의 경우, 로드밸런서에 Node의 IP가 아닌, Pod의 IP를 직접 매핑하여, 부하분산
- Pod의 IP를 직접 로드밸런서에 연결 할 수 있는 이유는 Loadbalancer Controller가 Pod의 정보를 AWS ELB에 제공하기 때문에 가능
- AWS LoadBalancer Controller 배포 with IRSA
# 1. OIDC 확인
aws iam list-open-id-connect-providers | jq
# 2. IAM Policy (AWSLoadBalancerControllerIAMPolicy) 생성
curl -O https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.5.4/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json
# 3. 쿠버네티스와 AWS 간 권한을 매핑하여 마춤(IRSA 세팅)
eksctl create iamserviceaccount --cluster=$CLUSTER_NAME --namespace=kube-system --name=aws-load-balancer-controller --role-name AmazonEKSLoadBalancerControllerRole \
--attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --approve
# 4. ## IRSA 정보 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
# 5. 서비스 어카운트 확인
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml | yh
# 6. Helm Chart 설치
helm repo add eks https://aws.github.io/eks-charts
helm repo update
helm install aws-load-balancer-controller eks/aws-load-balancer-controller -n kube-system --set clusterName=$CLUSTER_NAME \
--set serviceAccount.create=false --set serviceAccount.name=aws-load-balancer-controller
# 7. 설치 확인 : aws-load-balancer-controller:v2.7.1
kubectl get crd
kubectl get deployment -n kube-system aws-load-balancer-controller
# 8. 클러스터롤, 롤 확인
kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding
kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role
- Service/Pod 배포 Test with NLB
# Deployment & Service 배포
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/echo-service-nlb.yaml
kubectl apply -f echo-service-nlb.yaml
# kubectl get svc,ep,ingressclassparams,targetgroupbindings
# (옵션) 빠른 실습을 위해서 등록 취소 지연(드레이닝 간격) 수정 : 기본값 300초
vi echo-service-nlb.yaml
annotations:
service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: deregistration_delay.timeout_seconds=60(추가)
# 옵션 추가 후 적용
kubectl apply -f echo-service-nlb.yaml
# AWS ELB(NLB) 정보 확인
ALB_ARN=$(aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-default-svcnlbip`) == `true`].LoadBalancerArn' | jq -r '.[0]')
aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq
TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq -r '.TargetGroups[0].TargetGroupArn')
aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN | jq
# 웹 접속 주소 확인
kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'
- Target group 정보 확인 시 Node의 IP가 아닌 Pod의 IP가 설정되어 있는 것을 확인
- 부하분산 확인
NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})
(yjsong@myeks:default) [root@myeks-bastion-EC2 ~]# for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
54 Hostname: deploy-echo-7f579ff9d7-pfnn8
46 Hostname: deploy-echo-7f579ff9d7-w244z
- Pod 수량 변경 Test
# 작업용 EC2 - 파드 4개 설정
kubectl scale deployment deploy-echo --replicas=4
for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
(yjsong@myeks:default) [root@myeks-bastion-EC2 ~]# for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
27 Hostname: deploy-echo-7f579ff9d7-w244z
25 Hostname: deploy-echo-7f579ff9d7-rq9j9
25 Hostname: deploy-echo-7f579ff9d7-27589
23 Hostname: deploy-echo-7f579ff9d7-pfnn8
AWS LoadBalancer Controller & Ingress
- 클러스터 내부의 서비스(ClusterIP, NodePort, Loadbalancer)를 외부로 노출(HTTP/HTTPS)
# 게임 파드와 Service, Ingress 배포
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ingress1.yaml
kubectl apply -f ingress1.yaml
# 모니터링
watch -d kubectl get pod,ingress,svc,ep -n game-2048
# 생성 확인
kubectl get-all -n game-2048
kubectl get ingress,svc,ep,pod -n game-2048
kubectl get targetgroupbindings -n game-2048
# ALB 생성 확인
aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-game2048`) == `true`]' | jq
ALB_ARN=$(aws elbv2 describe-load-balancers --query 'LoadBalancers[?contains(LoadBalancerName, `k8s-game2048`) == `true`].LoadBalancerArn' | jq -r '.[0]')
aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN
TARGET_GROUP_ARN=$(aws elbv2 describe-target-groups --load-balancer-arn $ALB_ARN | jq -r '.TargetGroups[0].TargetGroupArn')
aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN | jq
# Ingress 확인
kubectl describe ingress -n game-2048 ingress-2048
kubectl get ingress -n game-2048 ingress-2048 -o jsonpath="{.status.loadBalancer.ingress[*].hostname}{'\n'}"
# 게임 접속 : ALB 주소로 웹 접속
kubectl get ingress -n game-2048 ingress-2048 -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Game URL = http://"$1 }'
# 파드 IP 확인
kubectl get pod -n game-2048 -owide
- NLB와 동일하게 Pod의 IP가 Target Group에 바인딩 되어 있는 것을 확인 할 수 있음
728x90
'AEWS Study' 카테고리의 다른 글
5주차 - EKS Autoscaling - (Node Autoscaling) (0) | 2024.04.05 |
---|---|
5주차 - EKS Autoscaling - (Pod Autoscaling) (0) | 2024.04.05 |
4주차 - EKS Observability (0) | 2024.03.31 |
3주차 - EKS Storage & Nodegroup (0) | 2024.03.24 |
1주차 - Amzaon EKS 설치 및 기본 사용 (0) | 2024.03.10 |