Amazon EKS
클러스터는 다양한 방식으로 배포될 수 있지만 해당 실습에서는eksctl
을 사용하여 EKS 클러스터를 생성
/home/ec2-user/environment
) 위치에서 아래의 값을 붙여넣음cd ~/environment
cat << EOF > eks-demo-cluster.yaml
---
apiVersion: eksctl.io/v1alpha5
kind: ClusterConfig
metadata:
name: eks-demo # 생성할 EKS 클러스터명
region: ${AWS_REGION} # 클러스터를 생성할 리전
version: "1.23"
vpc:
cidr: "10.0.0.0/16" # 클러스터에서 사용할 VPC의 CIDR
nat:
gateway: HighlyAvailable
managedNodeGroups:
- name: node-group # 클러스터의 노드 그룹명
instanceType: m5.large # 클러스터 워커 노드의 인스턴스 타입
desiredCapacity: 3 # 클러스터 워커 노드의 갯수
volumeSize: 20 # 클러스터 워커 노드의 EBS 용량 (단위: GiB)
privateNetworking: true
ssh:
enableSsm: true
iam:
withAddonPolicies:
imageBuilder: true # Amazon ECR에 대한 권한 추가
albIngress: true # albIngress에 대한 권한 추가
cloudWatch: true # cloudWatch에 대한 권한 추가
autoScaler: true # auto scaling에 대한 권한 추가
ebs: true # EBS CSI Driver에 대한 권한 추가
cloudWatch:
clusterLogging:
enableTypes: ["*"]
iam:
withOIDC: true
EOF
Cluster
배포(약 20분 정도 소요됨)eksctl create cluster -f eks-demo-cluster.yaml
node
가 제대로 배포 완료되었는지 확인AWS Load Balancer Controller
를 사용하여 실습 진행
Ingress
(인그레스)
TLS/SS
인증서 처리, HTTP
경로에 대한 라우팅 등을 설정L7
영역의 요청 처리Ingress Controller
: 이런 설정이 동작하기 위해서 필요한 것(직접 구현 필요)Amazon EKS
의 Application Load Balancing
ALB(Application Load Balancer)
및 필요한 자원이 생성되도록 트리거하는 컨트롤러ALB
를 구성하여 HTTP
또는 HTTPS
트래픽을 클러스터 내 파드로 라우팅Ingress
의 경우, Application Load Balancers
으로 프로비저닝Service
의 경우, etwork Load Balancers
으로 프로비저닝AWS Load Balancer Controller
에서 지원하는 트래픽 모드
Instance(default)
IP
controller
가 워커 노드 위에서 동작되기 때문에 IAM permissions
를 통해, AWS ALB/NLB
리소스에 접근할 수 있도록 만들어야 함
클러스터에 대한 IAM OIDC(OpenID Connect) identity Provider
를 생성
service account
에 IAM role
을 사용하기 위해, 생성한 클러스터(현재 실습에서의 eks-demo)에 IAM OIDC provider
가 존재해야 함eksctl utils associate-iam-oidc-provider \
--region ${AWS_REGION} \
--cluster eks-demo \
--approve
클러스터의 OIDC provider URL
확인하고, 결과 값에서 /id/
뒤에 있는 값을 복사한 후, 아래와 같이 명령어 수행
결과 값이 출력되지 않았으면 생성 작업을 수행해야 함
AWS Load Balancer Controller
에 부여할 IAM Policy
를 생성하는 작업 수행
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
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
AWS Load Balancer controller
를 클러스터에 추가하는 작업을 수행cert-manager
를 설치Cert-manager
: 쿠버네티스 클러스터 내에서 TLS인증서를 자동으로 프로비저닝 및 관리하는 오픈 소스kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v1.5.4/cert-manager.yaml
Load balancer controller yaml
파일을 다운로드wget https://github.com/kubernetes-sigs/aws-load-balancer-controller/releases/download/v2.4.4/v2_4_4_full.yaml
yaml
파일에서 클러스터의 cluster-name
을 편집
yaml 파일에서 ServiceAccount yaml spe
을 없애줌
ServiceAccount
를 이미 생성했기 때문에변경 내역 저장 후 AWS Load Balancer controller
파일 배포
kubectl apply -f v2_4_4_full.yaml
배포가 성공적으로 되고 컨트롤러가 실행되는지 확인(결과값이 도출되면 정상)
service account
생성 확인
클러스터 내부에서 필요한 기능들을 위해 실행되는 파드들을 애드온(Addon
)이라고 함
kube-system
인데, Yaml 파일에서 네임스페이스를 kube-system
으로 명시했기에 위의 명령어로 파드 이름이 도출되면 정상적으로 배포된 것kubectl logs -n kube-system $(kubectl get po -n kube-system | egrep -o "aws-load-balancer[a-zA-Z0-9-]+")
자세한 속성 값 파악
ALBPOD=$(kubectl get pod -n kube-system | egrep -o "aws-load-balancer[a-zA-Z0-9-]+")
kubectl describe pod -n kube-system ${ALBPOD}
Amazon EKS
에 배포
- 소스 코드 다운로드
Amazon ECR
에 각 서비스에 대한 리포지토리 생성Dockerfile
을 포함한 소스 코드 위치에서Container image
를 build한 후Repository
에 push- 각 서비스에 대한
Deployment
,Service
,Ingress
매니페스트 파일 생성 및 배포
manifests
폴더 위치로(/home/ec2-user/environment/manifests
)로 이동cd ~/environment/manifests/
deploy manifest
를 생성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 manifest
파일을 생성cat <<EOF> flask-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: "flask-backend-ingress"
namespace: default
annotations:
kubernetes.io/ingress.class: alb
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:
rules:
- http:
paths:
- path: /contents
pathType: Prefix
backend:
service:
name: "demo-flask-backend"
port:
number: 8080
EOF
Ingree
를 생성하면 AWS Application Load Balancer(ALB)
가 프로비저닝됨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
인그레이스 오브젝트가 배포되는 동안 약간의 시간이 소요되기 때문에, EC2 콘솔창에서 Load Balancers
상태가 active
가 될 때까지 기다려야 함
현재까지의 아키텍처
cd ~/environment/manifests/
deploy manifest
를 생성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
ingree 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
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
http://k8s-eksdemogroup-ac5f71b163-2133791238.ap-northeast-2.elb.amazonaws.com/services/all
cd /home/ec2-user/environment
git clone https://github.com/joozero/amazon-eks-frontend.git
AWS CLI
를 통해 이미지 리포지토리 생성aws ecr create-repository \
--repository-name demo-frontend \
--image-scanning-configuration scanOnPush=true \
--region ${AWS_REGION}
두 개의 백엔드 결과 값을 화면에 뿌리기 위해 일부 소스 코드를 수정해야 함
App.js
파일의 url 값을 앞서 배포한 인그레이스 주소로 변경
echo http://$(kubectl get ingress/flask-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/contents/'${search}'
page/UpperPage.js
파일의 url 값을 앞서 배포한 인그레이스 주소로 변경
echo http://$(kubectl get ingress/nodejs-backend-ingress -o jsonpath='{.status.loadBalancer.ingress[*].hostname}')/services/all
amazon-eks-frontend
폴더에서 아래 명령어 수행
cd /home/ec2-user/environment/amazon-eks-frontend
npm install
npm install
이후 vulnerability
가 나온다면, nam audit fix
명령어를 수행한 후 npm run build
를 적용해야 함nam audit fix
npm run build
docker build -t demo-frontend .
docker tag demo-frontend:latest $ACCOUNT_ID.dkr.ecr.$AWS_REGION.amazonaws.com/demo-frontend:latest
manifests
폴더로 이동하여 deploy manifests
생성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
service manifests
생성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
ingress manifests
생성cat <<EOF> frontend-ingress.yaml
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: "frontend-ingress"
namespace: default
annotations:
kubernetes.io/ingress.class: alb
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:
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}')
상단은 Nodejs api
, 하단은 Flask api
현재의 아키텍처