⭐ 가시다(gasida) 님이 진행하는 AWS EKS Workshop 실습 스터디 게시글입니다.
1. AWS VPC CNI
CNI: Container Network Interface 의 약자. K8s의 네트워크 환경을 구성해준다
AWS VPC CNI: Pod의 IP를 할당해준다, Pod의 IP Network대역 - Worker node의 IP Network 대역을 동일하게 가져간다.
On-premise(Calico CNI) vs AWS VPC CNI
작동흐름 비교
각각 CNI 별 특징
- Calioco CNI: Source Pod 에서 Target Pod를 향할때 오버레이통신을 하게되는데, 이때 Outer Packet 으로 감싸져서(Capsulate) 전송된다(해제할땐 Encapsulate).
- AWS VPC CNI: Source Pod 와 Target Pod의 네트워크 대역이 같아서, 오버레이 통신을 할 이유가 없다. 따라서 Capusate, Encapsulate 의 필요성이 존재하지 않는다.
실습으로 확인
# 노드 IP 확인
**aws ec2 describe-instances --query "Reservations[*].Instances[*].{PublicIPAdd:PublicIpAddress,PrivateIPAdd:PrivateIpAddress,InstanceName:Tags[?Key=='Name']|[0].Value,Status:State.Name}" --filters Name=instance-state-name,Values=running --output table**
# 파드 IP 확인
**kubectl get pod -n kube-system -o=custom-columns=NAME:.metadata.name,IP:.status.podIP,STATUS:.status.phase**
Node IP 대역은 192.168.3.76
, 192.168.1.128
, 192.168.2.236
인데
Pod IP 대역(특히 kube-proxy, aws-node daemonset) 는 192.168.3.76
, 192.168.1.128
, 192.168.2.236
을 동일하게 가져가는 모습을 확인할 수 있다.
(이유: kube-proxy와 aws-node 는 host network 의 namespace 를 공유해서 사용한다, core-dns 는 분리해서 사용한다.)
노드의 네트워크정보확인
# CNI 정보 확인
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i tree /var/log/aws-routed-eni; echo; done
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/plugin.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/ipamd.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/egress-v6-plugin.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/ebpf-sdk.log | jq
ssh ec2-user@$N1 sudo cat /var/log/aws-routed-eni/network-policy-agent.log | jq
# 네트워크 정보 확인 : eniY는 pod network 네임스페이스와 veth pair
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -br -c addr; echo; done
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c addr; echo; done
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done
ssh ec2-user@$N1 sudo iptables -t nat -S
ssh ec2-user@$N1 sudo iptables -t nat -L -n -v
2. 노드에서 기본 네트워크 정보 확인
EKS 에서 제공하는 Pod(coredns, aws-node, kube-proxy)
Network namespace: 는 호스트(Root) 와 파드별(Per Pod)로 구분된다.
- aws-node, kubeproxy : Host Namespace 를 그대로 사용하기때문에, Host 의 IP 를 그대로 사용한다(Pod 의 Host network 옵션이다)
- coredns: Host Namespace 와 다른 Namespace 를 사용하기때문에, Host 의 IP를 그대로 사용하지 않는다.
노드정보, 파드정보 확인
aws-node, kube-proxy 는 모든 노드에 한개씩 존재하지만, core-dns 는 2개에만 존재하는 상황이다.
노드정보, 파드정보 확인(자세히)
# 노드의 라우팅 정보 확인 >> EC2 네트워크 정보의 '보조 프라이빗 IPv4 주소'와 비교해보자
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i **sudo ip -c route**; echo; done
# [터미널1~3] 노드 모니터링
ssh ec2-user@$N1
**watch -d "ip link | egrep 'eth|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"**
ssh ec2-user@$N2
**watch -d "ip link | egrep 'eth|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"**
ssh ec2-user@$N3
**watch -d "ip link | egrep 'eth|eni' ;echo;echo "[ROUTE TABLE]"; route -n | grep eni"**
위에서 eth 라고 하는건 하나의 네트워크 인터페이스 칩(chip)혹은 ENI 1개 라고 생각하면 무방할것 같다.
노드 192.168.1.128
은 네트워크인터페이스 칩이 1개, 나머지노드는 네트워크인터페이스 칩이 2개인 상태이다. 또한 coredns 도 배포되지 않아있다.
네트워크 인터페이스 칩 1개당 보조 Private IPv4 주소 5개를 최대로 가질수 있다는 특징이있다
테스트용 파드 생성(netshoot)
# 테스트용 파드 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
파드 배포하기 전
파드 배포한 이후
노드 192.168.1.128
에 변화가 생긴 모습인데
ENI가 한개 추가되었고, AWS 에서 Private IPv4 에서도 추가 된 모습이다.
파드배포 확인
# 파드 이름 변수 지정
PODNAME1=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[0].metadata.name})
PODNAME2=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[1].metadata.name})
PODNAME3=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[2].metadata.name})
# 파드 확인
kubectl get pod -o wide
kubectl get pod -o=custom-columns=NAME:.metadata.name,IP:.status.podIP
노드 하나씩에 netshoot 하나씩 잘 배포된 모습을 확인할 수 있다.
이때 Pod IP 는 192.168.1.245
, 192.168.3.217
, 192.168.2.200
이다.
라우팅테이블 확인
# 노드에 라우팅 정보 확인
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i sudo ip -c route; echo; done
라우팅 정보를 확인하면 각각의 노드의 라우팅테이블을 확인할 수 있는데
netshoot pod 를 배포했던 192.168.1.245, 192.168.2.200, 192.168.3.217 이 모두 존재한다.
테스트용 파드 eniY 정보 확인 - 워커 노드 EC2
# **노드3**에서 네트워크 인터페이스 정보 확인
ssh ec2-user@$N3
----------------
ip -br -c addr show
ip -c link
ip -c addr
ip route # 혹은 route -n
# 마지막 생성된 네임스페이스 정보 출력 -t net(네트워크 타입)
sudo lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}' | tail -n 1
# 마지막 생성된 네임스페이스 net PID 정보 출력 -t net(네트워크 타입)를 변수 지정
MyPID=$(sudo lsns -o PID,COMMAND -t net | awk 'NR>2 {print $1}' | tail -n 1)
# PID 정보로 파드 정보 확인
sudo nsenter -t $MyPID -n ip -c addr
sudo nsenter -t $MyPID -n ip -c route
exit
----------------
테스트용 파드 접속(exec) 후 확인
# 테스트용 파드 접속(exec) 후 Shell 실행
**kubectl exec -it $**PODNAME1 **-- zsh**
# 아래부터는 pod-1 Shell 에서 실행 : 네트워크 정보 확인
----------------------------
ip -c addr
ip -c route
route -n
ping -c 1 <pod-2 IP>
ps
cat /etc/resolv.conf
exit
----------------------------
# 파드2 Shell 실행
**kubectl exec -it $**PODNAME2 **-- ip -c addr**
# 파드3 Shell 실행
**kubectl exec -it $**PODNAME3 **-- ip -br -c addr**
3. 노드 간 파드 통신
서로다른 노드에 있는 Pod끼리 통신하는 그림
On-Prem 으로 배포한 CNI(e.g. Calico) 는 워커노드1 → 워커노드2 로 향할때 Capsulate 되어서(Tunneling 되어) 정보가 전달될테지만
AWS VPC CNI 에서는 워커노드 1 → 워커노드2로 향할때 Capsulate 되어서 전달되지않는다(그림상에서는 Virtual Router가 생략되어있다).
이를 확인하는 방법으로 tcpdump 를 떠서 확인한다.
# 파드 IP 변수 지정
PODIP1=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[0].status.podIP})
PODIP2=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[1].status.podIP})
PODIP3=$(kubectl get pod -l app=netshoot-pod -o jsonpath={.items[2].status.podIP})
워커노드에서 진행
# 워커 노드 EC2 : TCPDUMP 확인하는 명령어.
# 각각 한줄씩 입력한 상태에서, 아래의 핑 테스트를 진행한다.
sudo tcpdump -i any -nn icmp
sudo tcpdump -i eth1 -nn icmp
sudo tcpdump -i eth0 -nn icmp
sudo tcpdump -i eniYYYYYYYY -nn icmp
# 파드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
이게 되는 이유는 ?
- AWS VPC CNI 를 사용하면, POD가 서로 같은 대역(동일대역) 에서 직접통신을 하기 때문이다.
[워커 노드1]
# routing policy database management 확인
ip rule
# routing table management 확인
ip route show table local
# 디폴트 네트워크 정보를 eth0 을 통해서 빠져나간다
ip route show table main
default via 192.168.1.1 dev eth0
...
4. 파드에서 외부 통신
흐름 : iptable 에 SNAT 을 통하여 노드의 eth0 IP로 변경되어서 외부와 통신이 가능하다.
워커노드
# 워커 노드 EC2 : TCPDUMP 확인
sudo tcpdump -i any -nn icmp
작업용EC2
# 작업용 EC2 : pod-1 Shell 에서 외부로 ping
#파드1번이 www.google.com 으로 핑 보내는것
kubectl exec -it $PODNAME1 -- ping -c 1 www.google.com
**# 워커 노드 EC2** : 퍼블릭IP 확인
for i in $N1 $N2 $N3; do echo ">> node $i <<"; ssh ec2-user@$i curl -s ipinfo.io/ip; echo; echo; done
**# 작업용 EC2 :** pod-1 Shell 에서 외부 접속 확인 - 공인IP는 어떤 주소인가?
for i in $PODNAME1 $PODNAME2 $PODNAME3; do echo ">> Pod : $i <<"; kubectl exec -it $i -- curl -s ipinfo.io/ip; echo; echo; done
퍼블릭IP : 각각의 노드가 외부의 공인IP 와 통신할 때 사용하는 IP
각각의 워커노드에서 curl 로 접근했을때 나온 주소: 각각 노드의 퍼블릭 IPv4
- 워커노드 애들도 자기한테 매핑되어있는 공인IP로 Source NAT 가 되어있는 주소가 출력된다.
각각의 파드에서 curl 로 접근했을때 나온 주소를 출력
워커노드에서 curl 로 접근했을때, 파드에서 curl 로 접근했을때 나온 주소가 같다?
- Pod가 외부로 네트워크 할때에는, 해당하는 Worker Node 의 Eth 0번에 매칭되어있는 유동공인IP 로 Source NAT 되어있는 상태다. 라고 하는것이다.
다른실습을 위해서 파드 삭제
kubectl delete deploy netshoot-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**"}}'
배포 이후 실행
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"}'
**# http://a3068229a067e461ba87c76a94cb4abd-1796853531.ap-northeast-2.elb.amazonaws.com:8080/#scale=1.5**
5. 노드에 파드 생성 갯수 제한
워커노드의 인스턴스 타입 별, 파드 생성 갯수가 제한되어있음.
인스턴스 타입 별 ENI 최대 갯수가 정해져있고, ENI 1개당 Pod 5개 를 배치가능함.
- aws-node, kube-proxy는 Host Namespace 를 사용하기때문에 제외한 숫자이다.
- t3.medium 은 ENI가 총 3개이며, 따라서 15개의 파드를 배치할 수 있다.
# 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 |
+----------+----------+--------------+
# c5 타입의 정보(필터) 확인
aws ec2 describe-instance-types --filters Name=instance-type,Values=c5*.* \
--query "InstanceTypes[].{Type: InstanceType, MaxENI: NetworkInfo.MaximumNetworkInterfaces, IPv4addr: NetworkInfo.Ipv4AddressesPerInterface}" \
--output table
# 파드 사용 가능 계산 예시 : 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: 1930m
ephemeral-storage: 27905944324
hugepages-1Gi: 0
hugepages-2Mi: 0
memory: 3388360Ki
pods: 17
# 워커 노드 EC2 - 모니터링
while true; do ip -br -c addr show && echo "--------------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done
# 작업용 EC2 - 터미널1
watch -d 'kubectl get pods -o wide'
# 작업용 EC2 - 터미널2
# 디플로이먼트 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/nginx-dp.yaml
**kubectl apply -f nginx-dp.yaml**
배포전
배포후
(화면 상에서는 아래좌,우에 해당한다)
# 워커 노드 EC2 - 모니터링
while true; do ip -br -c addr show && echo "--------------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done
# 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인
kubectl scale deployment nginx-deployment --replicas=8
# 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인 >> 어떤일이 벌어졌는가?
kubectl scale deployment nginx-deployment --replicas=15
# 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인 >> 어떤일이 벌어졌는가?
kubectl scale deployment nginx-deployment --replicas=30
좌우에서 eth2 가 각각 생긴것을 확인할 수 있는데
이는 각각의 노드에 Pod 가 생성되어야하는데, 현재 갖고있는 랜카드가 부족하여 Pod 를 배포하지 못하자
랜카드를 늘려서 Pod 를 배포할 수 있게 설정한것이다.
# 파드 증가 테스트 >> 파드 정상 생성 확인, 워커 노드에서 eth, eni 갯수 확인 >> 어떤일이 벌어졌는가?
**kubectl scale deployment nginx-deployment --replicas=50**
replicas 갯수를 50개로 늘려버리자, Node 에 할당되지 못해서 Pending 이 되어있는 상태이다.
# 디플로이먼트 삭제
**kubectl delete deploy nginx-deployment**
eth가 하나씩 제거 된 모습을 확인 할 수 있다.
6. AWS LB Controller
Object 를 외부로 노출시킬때 사용하는 것 중에 하나는 Load Balancer 이다.
일반 LoadBalancer
- 일반 LB(e.g. Metal LB) 는 노드1에 NodePort 로 들어와서 → iptables 로 분산되는 매커니즘을 갖고있다.
AWS LoadBalancer(ALB)
- AWS LB(ALB)는 다르노드의 NodePort 를 거칠필요없이, 바로 서로다른 노드의 Pod 로 접근이 가능하다.
- 가능하게 하는 이유는 AWS VPC CNI 때문이다.
- ALB 는 AWS의 소유이고, Pod의 정보는 EKS의 소유라서 ALB가 Pod의 정보를 알고있어야하는데, 이 역할을 Load Balancer Controller Pod 가 제공해준다.
ALB Controller 배포 (with IRSA)
# OIDC 확인
aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text
aws iam list-open-id-connect-providers | jq
# 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
# 혹시 이미 IAM 정책이 있지만 예전 정책일 경우 아래 처럼 최신 업데이트 할 것
# aws iam update-policy ~~~
# 생성된 IAM Policy Arn 확인
aws iam list-policies --scope Local | jq
aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy | jq
aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --query 'Policy.Arn'
# AWS Load Balancer Controller를 위한 ServiceAccount를 생성 >> 자동으로 매칭되는 IAM Role 을 CloudFormation 으로 생성됨!
# IAM 역할 생성. AWS Load Balancer Controller의 kube-system 네임스페이스에 aws-load-balancer-controller라는 Kubernetes 서비스 계정을 생성하고 IAM 역할의 이름으로 Kubernetes 서비스 계정에 주석을 답니다
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
## IRSA 정보 확인
eksctl get iamserviceaccount --cluster $CLUSTER_NAME
## 서비스 어카운트 확인
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml | yh
# 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
## 설치 확인 : aws-load-balancer-controller:v2.7.1
kubectl get crd
kubectl get deployment -n kube-system aws-load-balancer-controller
kubectl describe deploy -n kube-system aws-load-balancer-controller
kubectl describe deploy -n kube-system aws-load-balancer-controller | grep 'Service Account'
Service Account: aws-load-balancer-controller
# 클러스터롤, 롤 확인
kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding
kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role
...
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
targetgroupbindings.elbv2.k8s.aws [] [] [create delete get list patch update watch]
events [] [] [create patch]
ingresses [] [] [get list patch update watch]
services [] [] [get list patch update watch]
ingresses.extensions [] [] [get list patch update watch]
services.extensions [] [] [get list patch update watch]
ingresses.networking.k8s.io [] [] [get list patch update watch]
services.networking.k8s.io [] [] [get list patch update watch]
endpoints [] [] [get list watch]
namespaces [] [] [get list watch]
nodes [] [] [get list watch]
pods [] [] [get list watch]
endpointslices.discovery.k8s.io [] [] [get list watch]
ingressclassparams.elbv2.k8s.aws [] [] [get list watch]
ingressclasses.networking.k8s.io [] [] [get list watch]
ingresses/status [] [] [update patch]
pods/status [] [] [update patch]
services/status [] [] [update patch]
targetgroupbindings/status [] [] [update patch]
ingresses.elbv2.k8s.aws/status [] [] [update patch]
pods.elbv2.k8s.aws/status [] [] [update patch]
services.elbv2.k8s.aws/status [] [] [update patch]
targetgroupbindings.elbv2.k8s.aws/status [] [] [update patch]
ingresses.extensions/status [] [] [update patch]
pods.extensions/status [] [] [update patch]
services.extensions/status [] [] [update patch]
targetgroupbindings.extensions/status [] [] [update patch]
ingresses.networking.k8s.io/status [] [] [update patch]
pods.networking.k8s.io/status [] [] [update patch]
services.networking.k8s.io/status [] [] [update patch]
targetgroupbindings.networking.k8s.io/status [] [] [update patch]
배포테스트
# 모니터링
watch -d kubectl get pod,svc,ep
# 작업용 EC2 - 디플로이먼트 & 서비스 생성
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/2/echo-service-nlb.yaml
cat echo-service-nlb.yaml | yh
kubectl apply -f echo-service-nlb.yaml
# 확인
kubectl get deploy,pod
kubectl get svc,ep,ingressclassparams,targetgroupbindings
kubectl get targetgroupbindings -o json | jq
# (옵션) 빠른 실습을 위해서 등록 취소 지연(드레이닝 간격) 수정 : 기본값 300초
vi echo-service-nlb.yaml
..
apiVersion: v1
kind: Service
metadata:
name: svc-nlb-ip-type
annotations:
service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: ip
service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing
service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "8080"
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
service.beta.kubernetes.io/aws-load-balancer-target-group-attributes: deregistration_delay.timeout_seconds=60
...
:wq!
kubectl apply -f echo-service-nlb.yaml
# AWS ELB(NLB) 정보 확인
aws elbv2 describe-load-balancers | jq
aws elbv2 describe-load-balancers --query 'LoadBalancers[*].State.Code' --output text
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
{
"TargetHealthDescriptions": [
{
"Target": {
"Id": "192.168.2.153",
"Port": 8080,
"AvailabilityZone": "ap-northeast-2b"
},
"HealthCheckPort": "8080",
"TargetHealth": {
"State": "initial",
"Reason": "Elb.RegistrationInProgress",
"Description": "Target registration is in progress"
}
},
...
# 웹 접속 주소 확인
kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'
# 파드 로깅 모니터링
kubectl logs -l app=deploy-websrv -f
# 분산 접속 확인
NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})
curl -s $NLB
for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
# 52 Hostname: deploy-echo-55456fc798-2w65p
# 48 Hostname: deploy-echo-55456fc798-cxl7z
# 지속적인 접속 시도 : 아래 상세 동작 확인 시 유용(패킷 덤프 등)
while true; do curl -s --connect-timeout 1 $NLB | egrep 'Hostname|client_address'; echo "----------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done
# (신규 터미널) 모니터링
while true; do aws elbv2 describe-target-health --target-group-arn $TARGET_GROUP_ARN --output text; echo; done
# 작업용 EC2 - 파드 1개 설정
kubectl scale deployment deploy-echo --replicas=1
# 확인
kubectl get deploy,pod,svc,ep
curl -s $NLB
for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
# 작업용 EC2 - 파드 3개 설정
kubectl scale deployment deploy-echo --replicas=3
# 확인 : NLB 대상 타켓이 아직 initial 일 때 100번 반복 접속 시 어떻게 되는지 확인해보자!
kubectl get deploy,pod,svc,ep
curl -s $NLB
for i in {1..100}; do curl -s --connect-timeout 1 $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
#
kubectl describe deploy -n kube-system aws-load-balancer-controller | grep -i 'Service Account'
Service Account: aws-load-balancer-controller
# [AWS LB Ctrl] 클러스터 롤 바인딩 정보 확인
kubectl describe clusterrolebindings.rbac.authorization.k8s.io aws-load-balancer-controller-rolebinding
# [AWS LB Ctrl] 클러스터롤 확인
kubectl describe clusterroles.rbac.authorization.k8s.io aws-load-balancer-controller-role
- 실습 리소스 삭제:
kubectl delete deploy deploy-echo; kubectl delete svc svc-nlb-ip-type
7. INGRESS
INGRESS: 클러스터 내부의 서비스 를 외부로 노출(7계층, HTTP/HTTPS) - Web Proxy 역할
# 게임 파드와 Service, Ingress 배포
curl -s -O https://raw.githubusercontent.com/gasida/PKOS/main/3/ingress1.yaml
cat ingress1.yaml | yh
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**
NAME SERVICE-NAME SERVICE-PORT TARGET-TYPE AGE
k8s-game2048-service2-e48050abac service-2048 80 ip 87s
# 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**
'외부활동' 카테고리의 다른 글
[AEWS] 2기 스터디: Observability (1) | 2024.03.31 |
---|---|
[AEWS] 2기 스터디: EKS Storage 에 대해서 (1) | 2024.03.24 |
[AEWS] 2기 스터디: 스터디 기본지식 + EKS내용정리 (0) | 2024.03.10 |
코딩테스트 준비 플랫폼 추천: 코드트리 (0) | 2024.03.03 |
[DOIK2] 스터디: Stackable 로 Airflow 배포하기 + 스터디후기 (3) | 2023.11.26 |