brunch

You can make anything
by writing

C.S.Lewis

by Master Seo Oct 23. 2023

EKS 9탄-3. EKS DB - EKS 설치-3/18

쿠버네티스 네트워크

EKS 네트워크와 서비스, NLB , ALB 등 알아보자~



<1> 쿠버네티스 네트워크

<2> [실습] 테스트용 파드 생성

<3> 서비스 Service = 쿠버네티스 클러스터 내부를 외부에 노출,NLB

<4> 서비스 Service = 쿠버네티스 클러스터 내부를 외부에 노출, Ingress(ALB)

<5>  ExternalDNS 

<6> Stateful Application =  상태가 저정되는 어플리케이션




<1> 쿠버네티스 네트워크


1

K8S CNI

Container Network Interface 는 k8s 네트워크 환경을 구성해준다.

https://kubernetes.io/docs/concepts/cluster-administration/networking/


다양한 플러그인이 존재

https://kubernetes.io/docs/concepts/cluster-administration/addons/#networking-and-network-policy



2

AWS VPC CNI

파드의 IP를 할당해준다

파드의 IP 네트워크 대역과 노드(워커)의 IP 대역이 같아서 직접 통신이 가능하다.




<2> [실습] 테스트용 파드 생성


https://github.com/nicolaka/netshoot


1

# 테스트용 파드 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



# 파드 이름 변수 지정

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



2

테스트용 파드 접속(exec) 후 확인


# 테스트용 파드 접속(exec) 후 Shell 실행

kubectl exec -it $PODNAME1 -- zsh



# 아래부터는 pod-1 Shell 에서 실행 : 네트워크 정보 확인

----------------------------

ip -c addr

ip -c route

route -n

ping -c 2 <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

[실습] 파드에서 외부 통신 테스트 및 확인

파드 shell 실행 후 외부로 ping 테스트 & 워커 노드에서 tcpdump 및 iptables 정보 확인.


# 작업용 EC2 : pod-1 Shell 에서 외부로 ping

kubectl exec -it $PODNAME1 -- ping -c 1 www.google.com

kubectl exec -it $PODNAME1 -- ping -i 0.1 www.google.com



# 워커 노드 EC2 : 퍼블릭IP 확인

ssh ec2-user@$N1 curl -s ipinfo.io/ip ; echo

ssh ec2-user@$N2 curl -s ipinfo.io/ip ; echo

ssh ec2-user@$N3 curl -s ipinfo.io/ip ; echo



# 작업용 EC2 : pod-1 Shell 에서 외부 접속 확인 - 공인IP는 어떤 주소인가?


워커 노드의 공인ip를 사용한다.


## The right way to check the weather - 링크

kubectl exec -it $PODNAME1 -- curl -s ipinfo.io/ip ; echo

kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul

kubectl exec -it $PODNAME1 -- curl -s wttr.in/seoul?format=3

kubectl exec -it $PODNAME1 -- curl -s wttr.in/Moon

kubectl exec -it $PODNAME1 -- curl -s wttr.in/:help



다음 실습을 위해서 파드 삭제.

kubectl delete deploy netshoot-pod




<3> 서비스 Service = 쿠버네티스 클러스터 내부를 외부에 노출,NLB


[실습] 서비스/파드 배포 테스트 with NLB




https://kubernetes-sigs.github.io/aws-load-balancer-controller/v2.4/guide/service/nlb/


https://docs.aws.amazon.com/eks/latest/userguide/network-load-balancing.html


1

watch -d kubectl get pods,svc



# 작업용 EC2 - 디플로이먼트 & 서비스 생성 = deploy-echo


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



# AWS ELB(NLB) 정보 확인

aws elbv2 describe-load-balancers | jq

aws elbv2 describe-load-balancers --query 'LoadBalancers[*].State.Code' --output text



# 웹 접속 주소 확인

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




2

# 작업용 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


# 확인

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



3

삭제

kubectl delete deploy deploy-echo; kubectl delete svc svc-nlb-ip-type





<4> 서비스 Service = 쿠버네티스 클러스터 내부를 외부에 노출, Ingress(ALB)


Ingress : 클러스터 내부의 서비스(ClusterIP, NodePort, Loadbalancer)를 외부로 노출(HTTP/HTTPS) - Web Proxy 역할



[실습] 서비스/파드 배포 테스트 with Ingress(ALB)


1

# 게임 파드와 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



# Ingress 확인

kubectl describe ingress -n game-2048 ingress-2048


# 게임 접속 : 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



2

# 터미널1

watch kubectl get pod -n game-2048



# 터미널2 : 파드 3개로 증가

kubectl scale deployment -n game-2048 deployment-2048 --replicas 3



3

# 터미널2 : 파드 1개로 감소

kubectl scale deployment -n game-2048 deployment-2048 --replicas 1



4

kubectl delete ingress ingress-2048 -n game-2048

kubectl delete svc service-2048 -n game-2048 && kubectl delete deploy deployment-2048 -n game-2048 && kubectl delete ns game-2048




<5>  ExternalDNS 


ExternalDNS : K8S 서비스/인그레스 생성 시 도메인을 설정하면, AWS(Route 53), Azure(DNS), GCP(Cloud DNS) 에 레코드 자동 생성/삭제


Service(NLB) + 도메인 연동(ExternalDNS) 

체크 사이트 https://www.whatsmydns.net/



1

# 터미널1 (모니터링)

watch -d 'kubectl get pod,svc'

kubectl logs deploy/external-dns -n kube-system -f


2

# 테트리스 디플로이먼트 배포

cat <<EOF | kubectl create -f -

apiVersion: apps/v1

kind: Deployment

metadata:

  name: tetris

  labels:

    app: tetris

spec:

  replicas: 1

  selector:

    matchLabels:

      app: tetris

  template:

    metadata:

      labels:

        app: tetris

    spec:

      containers:

      - name: tetris

        image: bsord/tetris

---

apiVersion: v1

kind: Service

metadata:

  name: tetris

  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-cross-zone-load-balancing-enabled: "true"

    service.beta.kubernetes.io/aws-load-balancer-backend-protocol: "http"

    #service.beta.kubernetes.io/aws-load-balancer-healthcheck-port: "80"

spec:

  selector:

    app: tetris

  ports:

  - port: 80

    protocol: TCP

    targetPort: 80

  type: LoadBalancer

  loadBalancerClass: service.k8s.aws/nlb

EOF



3

# 배포 확인 : CLB 배포 확인

kubectl get deploy,svc,ep tetris



# NLB에 ExternanDNS 로 도메인 연결

kubectl annotate service tetris "external-dns.alpha.kubernetes.io/hostname=tetris.$MyDomain"


# Route53에 A레코드 확인

aws route53 list-resource-record-sets --hosted-zone-id "${MyDnsHostedZoneId}" --query "ResourceRecordSets[?Type == 'A']" | jq

aws route53 list-resource-record-sets --hosted-zone-id "${MyDnsHostedZoneId}" --query "ResourceRecordSets[?Type == 'A'].Name" | jq .[]



# 확인

dig +short tetris.$MyDomain @8.8.8.8

dig +short tetris.$MyDomain


# 도메인 체크

echo -e "My Domain Checker = https://www.whatsmydns.net/#A/tetris.$MyDomain"


# 웹 접속 주소 확인 및 접속

echo -e "Tetris Game URL = http://tetris.$MyDomain"



4

kubectl delete deploy,svc tetris




<6> Stateful Application =  상태가 저정되는 어플리케이션


1

https://kubernetes.io/docs/tutorials/stateful-application/basic-stateful-set/



# 모니터링

watch -d 'kubectl get sts,pods,svc,pvc,pv'


# 스테이트풀셋 & 헤드리스서비스 배포

curl -s -O https://raw.githubusercontent.com/kubernetes/website/main/content/en/examples/application/web/web.yaml


cat web.yaml | yh

kubectl apply -f web.yaml && kubectl get pods -w -l app=nginx



# 파드 hostname 확인

for i in 0 1; do kubectl exec "web-$i" -- sh -c 'hostname'; done

kubectl df-pv



# netshoot 이미지로 netdebug 파드에 zsh 실행

kubectl run -it --rm netdebug --image=nicolaka/netshoot --restart=Never -- zsh

--------------------

nslookup nginx

nslookup -type=srv nginx

nslookup web-0.nginx

nslookup web-1.nginx

exit


--------------------

# 파드 삭제 실행 후 재실행 시 생성 순서 확인

kubectl delete pod -l app=nginx && kubectl get pods -w -l app=nginx


# 파드 hostname 확인

for i in 0 1; do kubectl exec web-$i -- sh -c 'hostname'; done



# netshoot 이미지로 netdebug 파드에 zsh 실행

kubectl run -it --rm netdebug --image=nicolaka/netshoot --restart=Never -- zsh

--------------------

nslookup nginx

nslookup -type=srv nginx

nslookup web-0.nginx

nslookup web-1.nginx

exit

--------------------

첫번째 파드, 2번째 파드 순서대로 된다.



# PVC 확인

kubectl get pvc -l app=nginx

NAME        STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE

www-web-0   Bound    pvc-464030d6-f732-406f-aac4-dc35add63b2b   1Gi        RWO            local-path     7m6s

www-web-1   Bound    pvc-04c73836-e842-4abd-b19e-870c16b2b51c   1Gi        RWO            local-path     6m59s



# 웹 서버 index.html 에 hostname 추가 후 웹 접속 해서 확인



# 웹 서버 파드는 볼륨 마운트 정보 : Mounts: /usr/share/nginx/html from www (rw) - 


PersistentVolumeClaim

for i in 0 1; do kubectl exec "web-$i" -- sh -c 'echo "$(hostname)-pv-test" > /usr/share/nginx/html/index.html'; done

for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done



# 파드 삭제 실행 후 재실행 시 생성 순서 확인

kubectl delete pod -l app=nginx && kubectl get pods -w -l app=nginx


# 웹 접속 해서 확인 : PV 저장소 확인

for i in 0 1; do kubectl exec -i -t "web-$i" -- curl http://localhost/; done




파드 증가~~

1,2,3,4 순서 대로 뜬다.


# 파드 증가

kubectl scale sts web --replicas=5 && kubectl get pods -w -l app=nginx


# 파드 감소

kubectl patch sts web -p '{"spec":{"replicas":3}}' && kubectl get pods -w -l app=nginx


# 삭제

kubectl delete -f web.yaml && kubectl delete pvc --all




3

자원 삭제

실습 완료후 삭제.

15분 걸림.


eksctl delete cluster --name $CLUSTER_NAME && aws cloudformation delete-stack --stack-name $CLUSTER_NAME



주말 CloudNet  스터디 내용 참고하여  정리한 부분입니다.

https://gasidaseo.notion.site/gasidaseo/CloudNet-Blog-c9dfa44a27ff431dafdd2edacc8a1863  




다음은

https://brunch.co.kr/@topasvga/3488




브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari