-
[Kubernetes] EKS Workshop #2Kubernetes/EKS 2024. 6. 9. 19:11
인그레스 컨트롤러 만들기(Ingress Controller)
- 인그레스는 클러스터 외부에서 내부로 접근할때, 요청들을 어떻게 처리할지 정의해놓은 규칙
- 외부 요청에 대한 로드 밸런성, TLS/SSL 인증서 처리, HTTP 경로에 대한 라우팅 등 설정 (L7의 영역)
- Nodeport나 LoadBalancer로도 외부에 노출할 순 있지만,, 라우팅 규칙등의 상세한 옵션을 더 추가해야함-> 인그레스 필요
- 인그레스 설정을 동작하기 위해 인그레스 컨트롤러를 만들어야함 -> 이 컨트롤러는 클러스터 생성할때 자동으로 생성되는게 아니라 직접 구현이 필요함
AWS Load Balancer 컨트롤러 만들기
- 클러스터에 인그레이스 자원이 생성될 때 ALB 및 필요한 자원이 새성되로록 트리거하는 컨트롤러임
- 구성해놓은걸 가지고 ALB를 만들고 http(s) 트래픽을 파드로 라우팅 시켜줌
- 쿠버네티스의 Ingress의 경우, Application Load Balancers으로 프로비저닝
- 쿠버네티스의 Service의 경우, Network Load Balancers으로 프로비저닝
AWS Load Balancer 컨트롤러에서 지원하는 트래픽 모드는 아래의 두 가지
- Instance(default): 클러스터 내 노드를 ALB의 대상으로 등록/ ALB에 도달하는 트래픽은 NodePort로 라우팅된 다음 파드로 프록시
- IP: 파드를 ALB 대상으로 등록함 / ALB에 도달하는 트래픽은 파드로 직접 라우팅됨 / 해당 트래픽 모드를 사용하기 위해선 ingress.yaml 파일에 주석을 사용하여 명시적으로 지정해야 함
# 인그레스 컨트롤러 설정할 위치 cd ~/environment mkdir -p manifests/alb-ingress-controller && cd manifests/alb-ingress-controller # 최종 폴더 위치 /home/ec2-user/environment/manifests/alb-ingress-controller
- 컨트롤러가 워커노드위에서 동작하기 때문에 IAM permission을 통해 LB에 접근하도록 만들어야함. iam role 붙이기!
# IAM OIDC(OpenID Connect) identity Provider 생성 # service account에 얘를 생성해야함 eksctl utils associate-iam-oidc-provider \ --region ${AWS_REGION} \ --cluster eks-demo \ --approve # 클러스터의 OIDV provider URL 확인 aws eks describe-cluster --name eks-demo --query "cluster.identity.oidc.issuer" --output text # /id/ 뒤 값 복사하고 grep aws iam list-open-id-connect-providers | grep 8A6E78112D7F1C4DC352B1B511DD13CF
# IAM 정책 생성하는 작업 수행 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 # AWS Load Balancer Controller를 위한 ServiceAccount를 생성 eksctl create iamserviceaccount \ --cluster eks-demo \ --namespace kube-system \ --name aws-load-balancer-controller \ --attach-policy-arn arn:aws:iam::$ACCOUNT_ID:policy/AWSLoadBalancerControllerIAMPolicy \ --override-existing-serviceaccounts \ --approve
클러스터에 컨트롤러 추가하기
- Cert-manager는 쿠버네티스 클러스터 내에서 TLS인증서를 자동으로 프로비저닝 및 관리하는 오픈 소스
# cert-manager 설치 kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.12.0/cert-manager.yaml # lb controller yaml 파일 다운로드 curl -Lo v2_5_4_full.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.5.4/v2_5_4_full.yaml # 기존 manifest파일의 service account 제거 sed -i.bak -e '596,604d' ./v2_5_4_full.yaml # 클러스터 이름 변경 sed -i.bak -e 's|your-cluster-name|eks-demo|' ./v2_5_4_full.yaml # AWS Load Balancer controller 파일을 배포 kubectl apply -f v2_5_4_full.yaml # IngressClass 및 IngressClassParams 매니페스트를 다운로드 curl -Lo v2_5_4_ingclass.yaml https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.5.4/v2_5_4_ingclass.yaml kubectl apply -f v2_5_4_ingclass.yaml # 배포 성공 여부 kubectl get deployment -n kube-system aws-load-balancer-controller # service account 생성 확인 kubectl get sa aws-load-balancer-controller -n kube-system -o yaml
서비스 배포하기
- 웹서비스를 구성하는 백엔드, 프론트앤드를 eks에 배포해보자
- 소스 코드 다운로드
- Amazon ECR에 각 서비스에 대한 리포지토리 생성
- Dockerfile을 포함한 소스 코드 위치에서 컨테이너 이미지 빌드 후, 리포지토리에 푸시
- 각 서비스에 대한 Deployment, Service, Ingress 매니페스트 파일 생성 및 배포
1) 첫번째 백엔드 배포 (flask 백엔드 배포)
# 매니페스트 폴더 위치 cd ~/environment/manifests/ # deploy manifest yaml파일 작성 cat <<EOF> flask-deployment.yaml --- apiVersion: apps/v1 kind: Deployment metadata: name: demo-flask-backend namespace: default spec: replicas: 3 selector: matchLabels: app: demo-flask-backend template: metadata: labels: app: demo-flask-backend spec: containers: - name: demo-flask-backend image: $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/demo-flask-backend:latest imagePullPolicy: Always ports: - containerPort: 8080 EOF
# service manifest cat <<EOF> flask-service.yaml --- apiVersion: v1 kind: Service metadata: name: demo-flask-backend annotations: alb.ingress.kubernetes.io/healthcheck-path: "/contents/aws" spec: selector: app: demo-flask-backend type: NodePort ports: - port: 8080 # 서비스가 생성할 포트 targetPort: 8080 # 서비스가 접근할 pod의 포트 protocol: TCP EOF
# ingress cat <<EOF> flask-ingress.yaml --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: "flask-backend-ingress" namespace: default annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/group.name: eks-demo-group alb.ingress.kubernetes.io/group.order: '1' spec: ingressClassName: alb rules: - http: paths: - path: /contents pathType: Prefix backend: service: name: "demo-flask-backend" port: number: 8080 EOF
순서대로 배포
kubectl apply -f flask-deployment.yaml kubectl apply -f flask-service.yaml kubectl apply -f flask-ingress.yaml echo http://$(kubectl get ingress/flask-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/contents/aws
2) 두번째 백엔드 배포 (express 백엔드 배포)
# 매니페스트 폴더 위치 cd ~/environment/manifests/ # deploy manifest yaml파일 작성 cat <<EOF> nodejs-deployment.yaml --- apiVersion: apps/v1 kind: Deployment metadata: name: demo-nodejs-backend namespace: default spec: replicas: 3 selector: matchLabels: app: demo-nodejs-backend template: metadata: labels: app: demo-nodejs-backend spec: containers: - name: demo-nodejs-backend image: public.ecr.aws/y7c9e1d2/joozero-repo:latest imagePullPolicy: Always ports: - containerPort: 3000 EOF
# service manifest cat <<EOF> nodejs-service.yaml --- apiVersion: v1 kind: Service metadata: name: demo-nodejs-backend annotations: alb.ingress.kubernetes.io/healthcheck-path: "/services/all" spec: selector: app: demo-nodejs-backend type: NodePort ports: - port: 8080 targetPort: 3000 protocol: TCP EOF
# ingress cat <<EOF> nodejs-ingress.yaml --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: "nodejs-backend-ingress" namespace: default annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/group.name: eks-demo-group alb.ingress.kubernetes.io/group.order: '2' spec: ingressClassName: alb rules: - http: paths: - path: /services pathType: Prefix backend: service: name: "demo-nodejs-backend" port: number: 8080 EOF
순서대로 배포
kubectl apply -f nodejs-deployment.yaml kubectl apply -f nodejs-service.yaml kubectl apply -f nodejs-ingress.yaml echo http://$(kubectl get ingress/nodejs-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/services/all
3) React 프론트엔드 배포하기
# 소스코드 다운로드 cd /home/ec2-user/environment git clone https://github.com/joozero/amazon-eks-frontend.git # 리포지토리 생성 aws ecr create-repository \ --repository-name demo-frontend \ --image-scanning-configuration scanOnPush=true \ --region ${AWS_REGION} # flask 인그레스 주소 echo http://$(kubectl get ingress/flask-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/contents/'${search}' # node 인그레스 주소 echo http://$(kubectl get ingress/nodejs-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/services/all
cd /home/ec2-user/environment/amazon-eks-frontend npm install npm run build
ecr 에 이미지 똑같이 push하고, 프론트엔드용 manifest 폴더 배포하기
cd /home/ec2-user/environment/manifests cat <<EOF> frontend-deployment.yaml --- apiVersion: apps/v1 kind: Deployment metadata: name: demo-frontend namespace: default spec: replicas: 3 selector: matchLabels: app: demo-frontend template: metadata: labels: app: demo-frontend spec: containers: - name: demo-frontend image: $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/demo-frontend:latest imagePullPolicy: Always ports: - containerPort: 80 EOF
cat <<EOF> frontend-service.yaml --- apiVersion: v1 kind: Service metadata: name: demo-frontend annotations: alb.ingress.kubernetes.io/healthcheck-path: "/" spec: selector: app: demo-frontend type: NodePort ports: - protocol: TCP port: 80 targetPort: 80 EOF
cat <<EOF> frontend-ingress.yaml --- apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: "frontend-ingress" namespace: default annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip alb.ingress.kubernetes.io/group.name: eks-demo-group alb.ingress.kubernetes.io/group.order: '3' spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Prefix backend: service: name: "demo-frontend" port: number: 80 EOF
kubectl apply -f frontend-deployment.yaml kubectl apply -f frontend-service.yaml kubectl apply -f frontend-ingress.yaml echo http://$(kubectl get ingress/frontend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')
배포 성공?
'Kubernetes > EKS' 카테고리의 다른 글
[EKS] EKS 업그레이드 후기 (2) 2024.10.27 [Kubernetes] EKS Workshop #3 (0) 2024.06.09 [Kubernetes] EKS Workshop #1 (1) 2024.06.09