[PKOS Study 2주차] 쿠버네티스 Service, Ingress (LoadBalancer controller)
- -
CloudNet@ 팀의 가시다님께서 Leading 하시는 PKOS 2기 Study 내용 요약
해당 Kubernetes Study 는 '24단계 실습으로 정복하는 쿠버네티스' 책을 기반으로 진행 중입니다.
이번 포스팅에서는 쿠버네티스에서 AWS LoadBalancer 를 사용할 수 있게 해주는 LoadBalancer Controller 에 대해서 알아보겠습니다.
1. Service
로드밸런서 컨트롤러를 알아보기에 앞서, 쿠버네티스 서비스 오브젝트에 대해 간략하게만 짚고 넘어가겠습니다.
Service 오브젝트는 쿠버네티스에서 관리되는 무수히 많은 Pod 에 접근할 수 있는 쿠버네티스의 단일 진입점이라고 생각하면 됩니다.
Service 에는 ClusterIP , NodePort , LoadBalancer 타입이 존재합니다.
ClusterIP
쿠버네티스 내부에서만 사용할 수 있는 ClusterIP 로 접근, 외부에서 접근 불가NodePort
외부에서 쿠버네티스 내부의 Pod로 접근하기 위해 실제 Worker Node 의 Port 하나를 지정하여 접근LoadBalancer
외부에서 로드밸런서를 통해 쿠버네티스 클러스터 내부 Pod 로 접근 가능
온프레미스에서는 MetalLB 를 주로 사용하고, 클라우드에서는 각 CSP 의 LoadBalancer 를 이용합니다.
이 때, 클라우드에서 제공하는 LB 서비스를 사용하기 위해서는 LoadBalancer Controller 가 필요합니다.
2. LoadBalancer Controller 배포
2.1. AWS IAM Policy 생성
쿠버네티스가 AWS LB 의 생성 및 Target Group 등을 만들 수 있도록 권한을 부여해주어야 합니다.
AWS CLI를 통해 다음과 같은 IAM Policy 를 생성합니다.
curl -o iam_policy.json https://raw.githubusercontent.com/kubernetes-sigs/aws-load-balancer-controller/v2.4.5/docs/install/iam_policy.json
aws iam create-policy --policy-name AWSLoadBalancerControllerIAMPolicy --policy-document file://iam_policy.json
그 후, 생성한 IAM Policy 를 EC2 인스턴스 Role 에 연결해줍니다.
- 아직 해당 kops 클러스터에 irsa 를 적용하지 않았기에 Service Account 를 생성하지 않고 EC2 인스턴스 역할에 정책을 연결해줍니다.
KOPS_CLUSTER_NAME=kimalarm.net
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name masters.$KOPS_CLUSTER_NAME
aws iam attach-role-policy --policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy --role-name nodes.$KOPS_CLUSTER_NAME
2.2. AWS LoadBalancer Controller 설치
현재 클러스터 환경은 kops 로 구성되어 있기 때문에, 아래 명령어를 통해 kops 에 LB Controller 를 구성해줍니다.
kops edit cluster --name ${KOPS_CLUSTER_NAME}
-----
spec:
certManager:
enabled: true
awsLoadBalancerController:
enabled: true
-----
- 이후 클러스터 업데이트를 실행합니다.
kops update cluster --yes && echo && sleep 5 && kops rolling-update cluster
- 업데이트 완료 후 컨트롤러를 확인해봅니다.
kubectl describe deploy -n kube-system aws-load-balancer-controller
EKS에서 LB Controller 를 설치하려면 아래 Docs 를 참고해주세요.
2.3. 서비스 배포
다음 명령어를 통해 테스트 디플로이먼트를 배포합니다.
- 2개의 테스트용 Pod 를 Deployment 형식으로 배포하고, NLB 타입의 로드밸런서를 해당 Deployment 와 연결해줍니다.
cat << EOF | kubectl create -f -
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
EOF
배포를 확인합니다.
kubectl get svc,targetgroupbindings
NLB 엔드포인트와 Target Group 이 생성된 것을 확인할 수 있습니다.
- 동일한 NLB 도메인 주소
- 특이한 것은 대상 그룹에 등록된 IP 가 현재 서비스 중인 Pod 의 IP 와 Direct 로 연결된다는 것입니다.
실제로 LB 가 정상적으로 부하를 분산하는 지 확인해봅시다.
NLB=$(kubectl get svc svc-nlb-ip-type -o jsonpath={.status.loadBalancer.ingress[0].hostname})
for i in {1..100}; do curl -s $NLB | grep Hostname ; done | sort | uniq -c | sort -nr
- 정상적으로 부하를 분산합니다.
2.4. AWS LB 대상 그룹 동작 확인
- Pod 의 개수가 변경될 때 LB와 함께 배포되어 있는 대상 그룹의 설정은 어떻게 변할 지 확인해봅시다.
- Pod 의 개수를 줄여봅니다.
kubectl scale deployment deploy-echo --replicas=1
Pod 가 삭제되자 해당 Pod 의 IP 를 대상 그룹에서 자동으로 제거해줍니다.
- 반대로 Pod 의 개수를 늘려봅니다.
kubectl scale deployment deploy-echo --replicas=3
Pod 가 생성되자 해당 Pod 의 IP 를 자동으로 등록해줍니다.
3. Ingress
Ingress 는 클러스터 내부 서비스를 외부로 노출 (http/https) 하는 Web Proxy 역할을 하는 Object 입니다.
- Service 의 LoadBalancer Type 이 4계층의 NLB 서비스를 배포하는 것이었다면,
Ingress 는 7 계층의 ALB 서비스를 배포하는 것입니다.
때문에, Domain Path 를 기반으로 각각 다른 서비스에 접근 할 수 있도록 해주는 것이 가능합니다.
3.1. Cluster에 Ingress 권한 부여
Ingress 또한 ALB 를 생성할 수 있어야 하므로, Service 와 똑같이 LB 권한을 부여합니다.
또한, ALB 에 ExternalDNS 를 부여하기 위해 Route53 권한도 추가해줍니다.
- 이후, 클러스터를 편집합니다.
kops edit cluster
-----
spec:
certManager:
enabled: true
awsLoadBalancerController:
enabled: true
externalDns:
provider: external-dns
-----
kops update cluster --yes && echo && sleep 3 && kops rolling-update cluster
3.2. Ingress 배포
다음 명령어를 통해 Ingress 오브젝트를 배포합니다.
2048 게임을 실행시키는 2개의 pod 를 가진 deployment 를 생성하고, 서비스를 생성한 뒤 Ingress 를 통해 /
Path 로 진입 시 2048 게임으로 이동하도록 설정해둔 yaml 파일입니다.
cat << EOF > ingress-test.yaml
apiVersion: v1
kind: Namespace
metadata:
name: game-2048
---
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: game-2048
name: deployment-2048
spec:
selector:
matchLabels:
app.kubernetes.io/name: app-2048
replicas: 2
template:
metadata:
labels:
app.kubernetes.io/name: app-2048
spec:
containers:
- image: public.ecr.aws/l6m2t8p7/docker-2048:latest
imagePullPolicy: Always
name: app-2048
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
namespace: game-2048
name: service-2048
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
type: NodePort
selector:
app.kubernetes.io/name: app-2048
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: game-2048
name: ingress-2048
annotations:
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: service-2048
port:
number: 80
EOF
kubectl apply -f ingress-test.yaml
ALB 생성 확인 가능
3.3. Ingress Domain Path 편집
Ingress 타입은 Domain 을 기반으로 서비스할 위치를 변경할 수 있습니다.
AWS 에서 제공하는 다음 그림을 보면 이해하시기 편합니다.
2048 게임은 /2048
으로 들어오게 만들고, 마리오 게임은 /mario
로 들어오게 만들어 봅시다.
그러기 위해서는 우선 마리오 게임을 배포해야 합니다.
실습을 위해 마리오 게임 또한 game-2048 Namespace 위에 배포합니다.
cat << EOF | kubectl create -f -
apiVersion: apps/v1
kind: Deployment
metadata:
namespace: game-2048
name: mario
labels:
app: mario
spec:
replicas: 1
selector:
matchLabels:
app: mario
template:
metadata:
labels:
app: mario
spec:
containers:
- name: mario
image: pengbai/docker-supermario
---
apiVersion: v1
kind: Service
metadata:
namespace: game-2048
name: mario
spec:
selector:
app: mario
ports:
- port: 80
protocol: TCP
targetPort: 8080
type: NodePort
EOF
이후 기존의 Ingress 를 삭제하고 다음과 같은 구성의 Ingress 를 재배포 합니다.
cat << EOF > ingress-path.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
namespace: game-2048
name: ingress-2048
annotations:
kubernetes.io/ingress.class: alb
alb.ingress.kubernetes.io/scheme: internet-facing
alb.ingress.kubernetes.io/target-type: ip
spec:
ingressClassName: alb
rules:
- http:
paths:
- path: /game
pathType: Prefix
backend:
service:
name: service-2048
port:
number: 80
paths:
- path: /mario
pathType: Prefix
backend:
service:
name: mario
port:
number: 80
EOF
'AWS > EKS' 카테고리의 다른 글
[PKOS Study 3주차] GitOps System - Harbor 설치 (0) | 2023.03.26 |
---|---|
[PKOS Study 2주차] Kubernetes Storage ( emptyDir, hostPath, PV/PVC ) (0) | 2023.03.19 |
[PKOS Study 2주차] Kubernetes Network ( AWS VPC CNI ) (0) | 2023.03.18 |
[PKOS Study 1주차] Kubernetes External DNS (0) | 2023.03.14 |
[PKOS Study 1주차] AWS에 kops 로 쿠버네티스 클러스터 생성 (0) | 2023.03.11 |