AEWS 스터디에서는 AWS의 관리형 Kubernetes인 Elastic Kubernetes의 다양한 기능들을 실습해보면서 익혀본다. 이 글은 스터디를 참여하면서 학습한 내용을 정리하는 연재 글이다. 스터디 진도에 맞춰 글을 작성한다.
이 글에서는 EKS의 AWS LB Controller, Ingress에 대해서 알아본다.
1. Kubernetes Serive 종류
ClusterIP 타입
가장 기본적인 방식으로 클러스터 내부에서만 사용된다. pod는 생애주기에 따라 재생성되어 ip가 변경될 가능성이 크기 때문에 고정 진입점을 만들기 위해 사용된다.
NodePort 타입
NodePort 타입은 쿠버네티스 클러스터 내부가 아닌 외부에서 접근할 수 있다. Cluster IP이 기본적으로 할당되고, 노드에 같은 포트가 할당되어 이 포트로 접근하면 서비스로 연결된다. 이후는 Cluster IP와 같이 여러 Pod로 분산된다. 노드의 외부 IP를 통해 외부와도 통신이 가능하다. 물리 호스트 IP를 노출하여 사용해야하기 때문에 외부에 일시적으로 연결할 때만 사용한다.
LoadBalancer 타입 (기본 모드) : NLB 인스턴스 유형
Service (LoadBalancer Controller) : AWS Load Balancer Controller + NLB IP 모드 동작 with AWS VPC CNI
LoadBalancer Controller를 사용하는 경우는 노드포트를 거치지 않고 Pod IP로 그대로 연결된다. LoadBalancer 타입에서 사용하는 NodePort를 사용하지 않아 네트워크 흐름이 굉장히 짧아져 엄청난 이점이 있다.
NLB가 Pod ip를 어떻게 노드 ip 등록하듯 관리하고 연결 가능할까? 그 방법은 AWS LoadBalancer Controller에게 권한 할당에 있다.
2. AWS LoadBalancer Controller
파드가 늘어났을 때 NLB 대상 타겟에 Pod ip를 추가, 삭제를 해줘야한다. 이를 위해 권한이 필요하다. OIDC 인증 연동으로 AWS LoadBalancer Controller가 AWS 리소스들을 통제할 수 있는 권한을 할당받고, 관리하게 된다.
AWS의 EKS를 보면 OpenIDConnectProvider를 확인할 수 있다.
ServiceAccount 생성과 할당
터미널에서 OIDC 확인과 IAM Policy 생성을 해본다. IAM Policy Arn (리소스 넘버) 확인이 가능하다.
ServiceAccount 생성과 할당은 eksctl로 진행할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
# OIDC 확인
aws eks describe-cluster --name $CLUSTER_NAME --query "cluster.identity.oidc.issuer" --output text
https://oidc.eks.ap-northeast-2.amazonaws.com/id/FDAA2DCBBA7D659ACF2CDBBDCF856FF4
aws iam list-open-id-connect-providers | jq
{
"OpenIDConnectProviderList": [
{
"Arn": "arn:aws:iam::991354587926:oidc-provider/oidc.eks.ap-northeast-2.amazonaws.com/id/4404654D53F549BF44BBC41037C4E149"
}
]
}
# IAM Policy (AWSLoadBalancerControllerIAMPolicy) 생성
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.7/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json
# 생성된 IAM Policy Arn 확인
aws iam list-policies --scope Local
aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy
{
"Policy": {
"PolicyName": "AWSLoadBalancerControllerIAMPolicy",
"PolicyId": "ANPA6NUKWRMLAKOIB4B7Y",
"Arn": "arn:aws:iam::991354587926:policy/AWSLoadBalancerControllerIAMPolicy",
"Path": "/",
"DefaultVersionId": "v1",
"AttachmentCount": 0,
"PermissionsBoundaryUsageCount": 0,
"IsAttachable": true,
"CreateDate": "2023-03-16T14:25:37+00:00",
"UpdateDate": "2023-03-16T14:25:37+00:00",
"Tags": []
}
}
aws iam get-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --query 'Policy.Arn'
"arn:aws:iam::991354587926:policy/AWSLoadBalancerControllerIAMPolicy"
# 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 \
--attach-policy-arn=arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --override-existing-serviceaccounts --approve
## 서비스 어카운트 확인
kubectl get serviceaccounts -n kube-system aws-load-balancer-controller -o yaml | yh
apiVersion: v1
kind: ServiceAccount
metadata:
annotations:
eks.amazonaws.com/role-arn: arn:aws:iam::991354587926:role/eksctl-myeks-addon-iamserviceaccount-kube-sy-Role1-MO419OHZC0H
creationTimestamp: "2023-05-07T05:13:07Z"
labels:
app.kubernetes.io/managed-by: eksctl
name: aws-load-balancer-controller
namespace: kube-system
resourceVersion: "20295"
uid: d5e13153-0b59-4e1d-9291-f83605d1789b
|
cs |
클라우드 포메이션 스택이 하나 생성되고 스택을 보면, IAM 역할과 SA가 리소스 넘버 (ARN) 정책이 연동된다.
helm 차트로 aws-load-balancer-controller 배포
SA생성은 false로 하고 위에서 만들어 놓은 SA를 옵션으로 세팅해준다.
설치 후에 kubectl get crd로 확인을 해보면 기존에 없던 crd 2개가 helm차트로 배포된 것이 보인다. ELB 버전 2라고 되어 있는 것을 볼 수 있는데 이것은 aws 서비스를 쿠버네티스 자원처럼 관리 할 수 있도록 배포된 것이라 보면된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
|
# Helm Chart 설치
helm repo add eks https://aws.github.io/eks-charts
"eks" has been added to your repositories
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
NAME: aws-load-balancer-controller
LAST DEPLOYED: Sun May 7 14:20:46 2023
NAMESPACE: kube-system
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
AWS Load Balancer controller installed!
## 설치 확인
kubectl get crd
NAME CREATED AT
eniconfigs.crd.k8s.amazonaws.com 2023-05-07T03:06:14Z
ingressclassparams.elbv2.k8s.aws 2023-05-07T05:20:44Z
securitygrouppolicies.vpcresources.k8s.aws 2023-05-07T03:06:17Z
targetgroupbindings.elbv2.k8s.aws 2023-05-07T05:20:44Z
kubectl get deployment -n kube-system aws-load-balancer-controller
NAME READY UP-TO-DATE AVAILABLE AGE
aws-load-balancer-controller 2/2 2 2 5m45s
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]
|
cs |
서비스/파드 배포 테스트 with NLB
파드를 replicas 2개로 배포해보고 로드밸런서를 확인 해본다. 원래라면 노드의 ip가 등록되야 하지만 Pod의 IP가 등록되어 있는 것을 확인 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
|
# 모니터링
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
apiVersion: apps/v1
kind: Deployment
metadata:
name: deploy-echo
spec:
replicas: 2
selector:
matchLabels:
app: deploy-websrv
template:
metadata:
labels:
app: deploy-websrv
spec:
terminationGracePeriodSeconds: 0
containers:
- name: akos-websrv
image: k8s.gcr.io/echoserver:1.5
ports:
- containerPort: 8080
---
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"
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
type: LoadBalancer
loadBalancerClass: service.k8s.aws/nlb
selector:
app: deploy-websrv
kubectl apply -f echo-service-nlb.yaml
deployment.apps/deploy-echo created
service/svc-nlb-ip-type created
# 확인
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
active
# 웹 접속 주소 확인
kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname} | awk '{ print "Pod Web URL = http://"$1 }'
Pod Web URL = http://k8s-default-svcnlbip-3a3b76eed1-51ee82b13ac69143.elb.ap-northeast-2.amazonaws.com
# 모니터링
watch -d kubectl get pod,svc,ep
Every 2.0s: kubectl get pod,svc,ep Sun Apr 30 22:24:29 2023
NAME READY STATUS RESTARTS AGE
pod/deploy-echo-5c4856dfd6-l67bt 1/1 Running 0 4m7s
pod/deploy-echo-5c4856dfd6-vlv52 1/1 Running 0 4m7s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 46m
service/svc-nlb-ip-type LoadBalancer 10.100.182.230 k8s-default-svcnlbip-bb5bbbf56d-3bfdf4d70fea78ab.elb.ap-northeast-2.amazonaws.com 80:31246/TCP 4m7s
NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.2.138:443,192.168.3.85:443 46m
endpoints/svc-nlb-ip-type 192.168.1.109:8080,192.168.2.63:8080 4m7s
# 파드 로깅 모니터링
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
53 Hostname: deploy-echo-5c4856dfd6-dkbkw
47 Hostname: deploy-echo-5c4856dfd6-5mh8h
# 지속적인 접속 시도 : 아래 상세 동작 확인 시 유용(패킷 덤프 등)
while true; do curl -s --connect-timeout 1 $NLB | egrep 'Hostname|client_address'; echo "----------" ; date "+%Y-%m-%d %H:%M:%S" ; sleep 1; done
|
cs |
AWS 콘솔의 로드 밸런서에도 확인 할 수 있다. 리스너의 타겟 그룹으로 접속해본다.
타겟 그룹에 등록 되어 있는 IP 주소를 확인 해보면 Pod의 IP가 연결되어 있다!
웹페이지에 몇 번씩 재접속해보면 pod log에서 확인 된다.
파드의 스케일을 변경해본다. auto discovery를 확인해보자.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
# 작업용 EC2 - 파드 1개 설정
kubectl scale deployment deploy-echo --replicas=1
deployment.apps/deploy-echo scaled
# 확인
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
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-echo 1/1 1 1 6m13s
NAME READY STATUS RESTARTS AGE
pod/deploy-echo-5c4856dfd6-vlv52 1/1 Running 0 6m13s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.100.0.1 <none> 443/TCP 48m
service/svc-nlb-ip-type LoadBalancer 10.100.182.230 k8s-default-svcnlbip-bb5bbbf56d-3bfdf4d70fea78ab.elb.ap-northeast-2.amazonaws.com 80:31246/TCP 6m13s
NAME ENDPOINTS AGE
endpoints/kubernetes 192.168.2.138:443,192.168.3.85:443 48m
endpoints/svc-nlb-ip-type 192.168.1.109:8080 6m13s
# 작업용 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
#
kubectl describe deploy -n kube-system aws-load-balancer-controller | grep '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
|
cs |
replica 1개로 변경하면 타겟 대상에서 draining 되는 것을 확인 할 수 있다.
다시 replica를 3개로 늘려보면 등록 중인 Pod ip를 확인 할 수 있다.
3. Ingress
AWS Load Balancer Controller + Ingress (ALB) IP 모드 동작 with AWS VPC CNI
위 NLB와 동작은 같고, ALB를 사용한다는 점이 다르다. HTTP, HTTPS 만 사용하고 외부로 노출할 때 사용한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
# 게임 파드와 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
|
cs |
예제 파드를 보면 네임스페이스 생성, 배포, 서비스, 인그레스를 확인 할 수 있다. 배포 후에 인그레스를 확인 해보면 alb가 어노테이션되어 있다.
마찬가지로 AWS LB 타겟 그룹에서 해당 IP를 확인 할 수 있다.
'스터디 > Kubernetes' 카테고리의 다른 글
[AWES] EKS Storage 2/5 - AWS EBS Controller (1) | 2023.05.14 |
---|---|
[AWES] EKS Storage 1/5 - 임시 파일시스템과 local-path 스토리지 클래스 (0) | 2023.05.14 |
[AWES] EKS Networking 특징과 네트워크 흐름 (0) | 2023.05.07 |
[AEWS] Amzaon EKS - Cluster Endpoint 구성 톱아보기 (0) | 2023.04.30 |
[AEWS] Amzaon EKS (0) | 2023.04.30 |