## clb-test-01 namespace의 pod 확인
kubectl -n clb-test-01 get pod -o wide
## clb-test-01 namespace의 service 확인
kubectl -n clb-test-01 get service -o wide
다음과 같은 결과를 얻을 수 있습니다
kubectl -n clb-test-01 get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
clb-test-01-66f4b975ff-25mvk 0/1 Running 0 9s 10.11.3.103 ip-10-11-10-88.ap-northeast-2.compute.internal <none> <none>
clb-test-01-66f4b975ff-hmm52 1/1 Running 0 9s 10.11.40.163 ip-10-11-35-39.ap-northeast-2.compute.internal <none> <none>
clb-test-01-66f4b975ff-vrmx5 0/1 Running 0 9s 10.11.30.212 ip-10-11-30-67.ap-northeast-2.compute.internal <none> <none>
kubectl -n clb-test-01 get service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
clb-test-01-svc LoadBalancer 172.20.238.198 a2bb893008047439ba29a8df77944bcf-1758389191.ap-northeast-2.elb.amazonaws.com 8080:30975/TCP 10s app=clb-test-01
아래와 같이 구성됩니다 . nodeport는 별도의 지정이 없으면 생성할때 자동으로 지정됩니다.
아래와 같이 배포된 pod에 접속을 편리하게 하기 위해 Cloud9 IDE terminal Shell에 등록 합니다. (Option)
export Clb_Test_Pod01=$(kubectl -n clb-test-01 get pod -o wide | awk 'NR==2' | awk '/clb-test-01/{print $1 } ')
export Clb_Test_Pod02=$(kubectl -n clb-test-01 get pod -o wide | awk 'NR==3' | awk '/clb-test-01/{print $1 } ')
export Clb_Test_Pod03=$(kubectl -n clb-test-01 get pod -o wide | awk 'NR==4' | awk '/clb-test-01/{print $1 } ')
echo "export Clb_Test_Pod01=${Clb_Test_Pod01}" | tee -a ~/.bash_profile
echo "export Clb_Test_Pod02=${Clb_Test_Pod02}" | tee -a ~/.bash_profile
echo "export Clb_Test_Pod03=${Clb_Test_Pod03}" | tee -a ~/.bash_profile
source ~/.bash_profile
ClbTestPod01에 접속해서 아래와 같이 확인해 봅니다. K9s에서 접속해도 됩니다.
Cloud9 IDE Terminal에서 CLB External IP:8080 으로 접속합니다.
## clb-test-01-svc external hostname 변수 등록
kubectl -n clb-test-01 get svc clb-test-01-svc --output jsonpath='{.status.loadBalancer.ingress[*].hostname}'
export clb_test_01_svc_name=$(kubectl -n clb-test-01 get svc clb-test-01-svc --output jsonpath='{.status.loadBalancer.ingress[*].hostname}')
echo "export clb_test_01_svc_name=${clb_test_01_svc_name}" | tee -a ~/.bash_profile
source ~/.bash_profile
## clb-test-01-svc external hostname 으로 접속
curl $clb_test_01_svc_name:8080
Node에서 iptable에 설정된 NAT Table, Loadbalancing 구성을 확인해 봅니다.
CLB에서는 아래와 같은 다양한 Annotation을 추가하여 CLB의 속성 또는 AWS 자원을 연결해서 사용할 수 있습니다
metadata:
name: my-service
annotations:
service.beta.kubernetes.io/aws-load-balancer-connection-idle-timeout: "60"
# 로드 밸런서가 연결을 닫기 전에, 유휴 상태(연결을 통해 전송 된 데이터가 없음)의 연결을 허용하는 초단위 시간
service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
# 로드 밸런서에 교차-영역(cross-zone) 로드 밸런싱을 사용할 지 여부를 지정
service.beta.kubernetes.io/aws-load-balancer-additional-resource-tags: "environment=prod,owner=devops"
# 쉼표로 구분된 key-value 목록은 ELB에
# 추가 태그로 기록됨
service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: ""
# 백엔드가 정상인 것으로 간주되는데 필요한 연속적인
# 헬스 체크 성공 횟수이다. 기본값은 2이며, 2와 10 사이여야 한다.
service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "3"
# 백엔드가 비정상인 것으로 간주되는데 필요한
# 헬스 체크 실패 횟수이다. 기본값은 6이며, 2와 10 사이여야 한다.
service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "20"
# 개별 인스턴스의 상태 점검 사이의
# 대략적인 간격 (초 단위). 기본값은 10이며, 5와 300 사이여야 한다.
service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout: "5"
# 헬스 체크 실패를 의미하는 무 응답의 총 시간 (초 단위)
# 이 값은 service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval
# 값 보다 작아야한다. 기본값은 5이며, 2와 60 사이여야 한다.
service.beta.kubernetes.io/aws-load-balancer-security-groups: "sg-53fae93f"
# 생성된 ELB에 설정할 기존 보안 그룹(security group) 목록.
# service.beta.kubernetes.io/aws-load-balancer-extra-security-groups 어노테이션과 달리, 이는 이전에 ELB에 할당된 다른 모든 보안 그룹을 대체하며,
# '해당 ELB를 위한 고유 보안 그룹 생성'을 오버라이드한다.
# 목록의 첫 번째 보안 그룹 ID는 인바운드 트래픽(서비스 트래픽과 헬스 체크)이 워커 노드로 향하도록 하는 규칙으로 사용된다.
# 여러 ELB가 하나의 보안 그룹 ID와 연결되면, 1줄의 허가 규칙만이 워커 노드 보안 그룹에 추가된다.
# 즉, 만약 여러 ELB 중 하나를 지우면, 1줄의 허가 규칙이 삭제되어, 같은 보안 그룹 ID와 연결된 모든 ELB에 대한 접속이 막힌다.
# 적절하게 사용되지 않으면 이는 다수의 서비스가 중단되는 상황을 유발할 수 있다.
service.beta.kubernetes.io/aws-load-balancer-extra-security-groups: "sg-53fae93f,sg-42efd82e"
# 생성된 ELB에 추가할 추가 보안 그룹 목록
# 이 방법을 사용하면 이전에 생성된 고유 보안 그룹이 그대로 유지되므로, 각 ELB가 고유 보안 그룹 ID와 그에 매칭되는 허가 규칙 라인을 소유하여
# 트래픽(서비스 트래픽과 헬스 체크)이 워커 노드로 향할 수 있도록 한다. 여기에 기재되는 보안 그룹은 여러 서비스 간 공유될 수 있다.
service.beta.kubernetes.io/aws-load-balancer-target-node-labels: "ingress-gw,gw-name=public-api"
# 로드 밸런서의 대상 노드를 선택하는 데
# 사용되는 키-값 쌍의 쉼표로 구분된 목록
7.CLB Application 배포
CLB 로드밸런서를 사용하는 간단한 게임 앱을 배포해 봅니다.
kubectl create namespace mario
kubectl apply -f ~/environment/myeks/sample/super_mario.yml
정상적으로 배포되었는지 확인해 봅니다.
kubectl -n mario get pods,svc
아래와 같이 배포된 것을 확인 할 수 있습니다.
$ kubectl -n mario get pods,svc
NAME READY STATUS RESTARTS AGE
pod/mario-7f947cb549-f6nvj 1/1 Running 0 47m
pod/mario-7f947cb549-jbtwd 1/1 Running 0 30m
pod/mario-7f947cb549-vcbz4 1/1 Running 0 30m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mario LoadBalancer 172.20.239.185 a5464e237441947b081e54bc3d0d6031-347620742.ap-northeast-2.elb.amazonaws.com 80:30436/TCP 47m
실제 deployment에 사용된 YAML 을 확인해 봅니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: mario
labels:
app: mario
namespace: mario
spec:
replicas: 3
selector:
matchLabels:
app: mario
template:
metadata:
labels:
app: mario
spec:
containers:
- name: mario
image: pengbai/docker-supermario
nodeSelector:
nodegroup-type: "managed-frontend-workloads"
---
apiVersion: v1
kind: Service
metadata:
name: mario
namespace: mario
spec:
selector:
app: mario
ports:
type: LoadBalancer
ports:
- protocol: TCP
port: 80
targetPort: 8080
아래 명령을 통해서 게임앱 URL을 확인하고에 브라우저를 통해 접속해 봅니다.
kubectl -n mario get svc mario | tail -n 1 | awk '{ print "mario URL = http://"$4 }'
3~4분 뒤에 웹 브라우저를 통해 위 명령에서 실행된 URL을 접속하면 , CLB를 통해서 아래와 같이 게임이 실행됩니다.
"s" - 게임시작
방향키로 각 스테이지 이동
"s" - 점프
방향키 - 마리오 이동
8. Loadbalancer 확인.
이제 서비스 타입을 확인하기 위해서 EC2 대시보드에서 Loadbalancer를 확인합니다.
NLB Loadbalancer 서비스 기반 구성
9. NLB 기반 Service Type
Service Type 필드를 LoadBalancer로 설정하여 프로브저닝합니다. CLB와 다르게 반드시 annotation을 통해 NLB를 지정해야 합니다. NLB도 내부 또는 외부 로드밸런서로 지정이 가능합니다. 또한 NLB는 외부의 IP를 PoD까지 그대로 전달 할 수 있습니다
kubectl -n nlb-test-01 get pod -o wide
kubectl -n nlb-test-01 get service -o wide
다음과 같은 결과를 얻을 수 있습니다.
kubectl -n nlb-test-01 get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nlb-test-01-7c5cf9bd5-c8qfj 1/1 Running 0 6m15s 10.11.13.246 ip-10-11-10-88.ap-northeast-2.compute.internal <none> <none>
nlb-test-01-7c5cf9bd5-d8j76 1/1 Running 0 6m15s 10.11.39.128 ip-10-11-35-39.ap-northeast-2.compute.internal <none> <none>
nlb-test-01-7c5cf9bd5-gsxlk 1/1 Running 0 6m15s 10.11.27.219 ip-10-11-30-67.ap-northeast-2.compute.internal <none> <none>
kubectl -n nlb-test-01 get service -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
nlb-test-01-svc LoadBalancer 172.20.18.55 aaa7c67484fd94ea8a2b6bf1fa091017-374347eabaa0875f.elb.ap-northeast-2.amazonaws.com 8080:31965/TCP 28s app=nlb-test-01
아래와 같이 구성됩니다 . nodeport는 별도의 지정이 없으면 생성할때 자동으로 지정됩니다.
아래와 같이 배포된 pod에 접속을 편리하게 하기 위해 Cloud9 IDE terminal Shell에 등록 합니다.
export Nlb_Test_01_Pod01=$(kubectl -n nlb-test-01 get pod -o wide | awk 'NR==2' | awk '/nlb-test-01/{print $1 } ')
export Nlb_Test_01_Pod02=$(kubectl -n nlb-test-01 get pod -o wide | awk 'NR==3' | awk '/nlb-test-01/{print $1 } ')
export Nlb_Test_01_Pod03=$(kubectl -n nlb-test-01 get pod -o wide | awk 'NR==4' | awk '/nlb-test-01/{print $1 } ')
echo "export Nlb_Test_01_Pod01=${Nlb_Test_01_Pod01}" | tee -a ~/.bash_profile
echo "export Nlb_Test_01_Pod02=${Nlb_Test_01_Pod02}" | tee -a ~/.bash_profile
echo "export Nlb_Test_01_Pod03=${Nlb_Test_01_Pod03}" | tee -a ~/.bash_profile
source ~/.bash_profile
앞서 생성된 NLB 주소로 접속을 시도해 봅니다.Cloud9 IDE Terminal에서 NLB External IP:8080 으로 접속합니다.
## nlb-test-01-svc external hostname 변수 등록
export nlb_test_01_svc_name=$(kubectl -n nlb-test-01 get svc nlb-test-01-svc --output jsonpath='{.status.loadBalancer.ingress[*].hostname}')
echo "export nlb_test_01_svc_name=${nlb_test_01_svc_name}" | tee -a ~/.bash_profile
source ~/.bash_profile
## nlb-test-01-svc external hostname 으로 접속
curl $nlb_test_01_svc_name:8080
NlbTestPod01에 접속해서 아래와 같이 확인해 봅니다.
#Nlb_Test_01_Pod01 Container 접속
kubectl -n nlb-test-01 exec -it $Nlb_Test_01_Pod01 -- /bin/sh
#Nlb_Test_01_Pod01 Container 에서 HTTP 접속 확인
tcpdump -i eth0 dst port 80 | grep "HTTP: GET"