프런트엔드와 배치 애플리케이션 빌드와 배포(1/3)
완성 아키텍처
- 본 포스팅은 클라우드 네이티브를 위한 쿠버네티스 실전 프로젝트 내용을 기반으로 작성 되었습니다.
- 소스 코드를 아래 깃헙에서 다운 받은 후 작업해주세요.https://github.com/yuran777/k8s-aws-book.git
1. Base environment
- Region: 서울 리전 (ap-northeast-2)
- AZ: 3개 리전 사용 (ap-northeast-2a, ap-northeast-2b, ap-northeast-2c)
- Subnet: Worker Node 용 3개 + 베스천 호스트용 1개 + RDS용 2개
- IGW 통해서 외부와 통신할 수 있게 Routing table 설정
아래 Cludformation 템플릿으로 스택 생성
https://github.com/yuran777/k8s-aws-book/blob/master/eks-env/01_base_resources_cfn.yaml
2. EKS 클러스터 구축(워커 노드 2개 만들기)
2.1 eksctl 명령어로 클러스터 구축
eksctl create cluster \
--vpc-public-subnets <subnet ID> \ #subnet-0a43a15d4c3f2db30 형태의 subnet id 3개
--name eks-work-cluster \ #eks cluster 이름
--region ap-northeast-2 \ #cluster 만들 리전
--version 1.19 \
--nodegroup-name eks-work-nodegroup \ #nodegroup 이름
--node-type t2.medium \ #노드 크기
--nodes 2 \ #노드 갯수
--nodes-min 2 \ #노드 최소 갯수
--nodes-max 5 #노드 최대 갯수
2.2 클러스터 구축시 EKS 클러스터 접속을 위한 인증 정보가 kubeconfig 파일에 업데이트 됨
참고) 파일 저장 경로: 맥 /home/USER명/.kube/config
kubectl config get-contexts
2.3 노드 상태 확인
kubectl get ndoes
NAME STATUS ROLES AGE VERSION
ip-주소.ap-northeast-2.compute.internal Ready <none> 2d23h v1.19.15-eks-9c63c4
ip-주소.ap-northeast-2.compute.internal Ready <none> 2d23h v1.19.15-eks-9c63c4
3. 데이터베이스 설정
- 데이터베이스 구축
- 베스천 호스트 구축
- 베스천 호스트 설정
3.1 데이터베이스 구축
https://github.com/yuran777/k8s-aws-book/blob/master/eks-env/10_rds_ope_cfn.yaml
위 Cludformation 템플릿으로 스택 생성
- 초기 파라미터 값 설정이 필요한 항목: VPC, OpeserverRoutetable
3.2 DB 및 베스천 호스트 생성 후 베스천 호스트에서 사용할 기본 도구 설치
- git
- postgreSQL
3.2.1 git 설치
sudo yum install git -y
3.2.2 postgreSQL 설치
sudo amazon-linux-extras install -y postgresql11
3.2.3 github에서 클론하기
cd /home/ssm-user
git clone https://github.com/yuran777/k8s-aws-book.git
3.2.4 CloudFormation으로 만든 데이터 베이스 정보 확인
CloudFormation 템플릿 중 아래 부분을 통해 만들어 짐.
EksWorkDB:
Type: "AWS::RDS::DBInstance"
Properties:
DBInstanceIdentifier: eks-work-db
Engine: postgres # https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/aws-properties-rds-database-instance.html#aws-properties-rds-database-instance-properties
EngineVersion: 11 # https://docs.aws.amazon.com/AmazonRDS/latest/UserGuide/CHAP_MySQL.html#MySQL.Concepts.VersionMgmt
DBInstanceClass: db.t2.micro
AllocatedStorage: 30
StorageType: gp2
DBName: eksworkdb
MasterUsername: !Join ['', ['' ]]
MasterUserPassword: !Join ['', ['' ]]
DBSubnetGroupName: !Ref EksWorkDBSubnetGroup
PubliclyAccessible: false
MultiAZ: false
PreferredBackupWindow: 18:00-18:30
PreferredMaintenanceWindow: sat:19:00-sat:19:30
AutoMinorVersionUpgrade: false
DBParameterGroupName: !Ref EksWorkDBParameterGroup
VPCSecurityGroups:
- !Ref RdsSecurityGroup
CopyTagsToSnapshot: true
BackupRetentionPeriod: 7
DeletionProtection: false
RdsMasterSecret:
Type: AWS::SecretsManager::Secret
Properties:
GenerateSecretString:
SecretStringTemplate: '{"username": "eksdbadmin"}'
GenerateStringKey: 'password'
PasswordLength: 16
ExcludeCharacters: '"@/\'''
Name: RdsMasterSecret
RdsUserSecret:
Type: AWS::SecretsManager::Secret
Properties:
GenerateSecretString:
SecretStringTemplate: '{"username": "mywork"}'
GenerateStringKey: 'password'
PasswordLength: 16
ExcludeCharacters: '"@/\''{}#%&*<>[]^`|'
Name: RdsUserSecret
RdsSecretAttachment:
Type: AWS::SecretsManager::SecretTargetAttachment
Properties:
SecretId: !Ref RdsMasterSecret
TargetId: !Ref EksWorkDB
TargetType: AWS::RDS::DBInstance
3.2.5 데이터 베이스 엔드포인트 주소 확인
- 데이터 베이스 관리자 비밀 번호 확인
AWS Secrets Manager > 보안 암호 > RdsMasterSecret 클릭 후, 보안 암호 값 > 보안 암호 검색
- 애플리케이션용 데이터베이스 사용자 비밀번호 확인
AWS Secrets Manager > 보안 암호 > RdsUserSecret 클릭 후, 보안 암호 값 > 보안 암호 검색
3.3 데이터베이스 세부 작업
- 애플리케이션용 데이터베이스 사용자 생성
- 애플리케이션용 데이터베이스 생성
- DDL 실행
3.3.1 애플리케이션용 데이터베이스 사용자 생성
createuser -d -U eksdbadmin -P -h <rds 엔드포인트> mywork
#앞에 두번 mywork사용자으 비밀번호 입력 : 위에서 찾은 RdsUserSecret 비밀 번호 사용하면 됨
#마지막은 eksadmin으 비밀번호를 입력 : 위에서 찾은 RdsMasterSecret 비밀번호 사용하면 됨
참고: postgresql createuser 명령어 옵션 https://postgresql.kr/docs/11/app-createuser.html
3.3.2 애플리케이션용 데이터베이스 생성
createdb -U mywork -h <rds 엔드포인트> -E UTF8 myworkdb
#password는 앞에서 만든 mywork 사용자의 비밀 번호
참고: postgresql createdb 명령어 옵션 https://postgresql.kr/docs/11/app-createdb.html
3.3.3 DDL 실행과 예제 데이터 불러오기
psql -U mywork -h <rds 엔드포인트 주소> mywork
myworkdb=> \i k8s-aws-book/backend-app/scripts/10_ddl.sql
myworkdb=> \i k8s-aws-book/backend-app/scripts/20_insert_sample_data.sql
myworkdb=> \q
4. API 애플리케이션 빌드와 배포
4.1 필요 도구 준비
- AWS에서 애플리케이션을 동작시키기에 AWS 친화적인 오픈JDK인 Amazon Cooretto를 설치합니다.
- 자바 버전은 LTS 버전인 11을 이용합니다.
- 컨테이너 이미지를 푸시하기 위헤 도커데스크톱을 설치합니다.
4.1.1 Amazon Corretto 11 다운로드
https://docs.aws.amazon.com/ko_kr/corretto/latest/corretto-11-ug/macos-install.html 위 링크 가이드에 따라 다운 후 java -version, javac -version 명령어로 잘 설치 되었는지 확인해 봅니다.
java -version
openjdk version "11.0.14.1" 2022-02-08 LTS
OpenJDK Runtime Environment Corretto-11.0.14.10.1 (build 11.0.14.1+10-LTS)
OpenJDK 64-Bit Server VM Corretto-11.0.14.10.1 (build 11.0.14.1+10-LTS, mixed mode)
javac -version
javac 11.0.14.1
4.1.2 JAVA_HOME 환경 변수 설정
Amazon Corretto 설치 작업이 끝났다면 마지막으로 JAVA_HOME 환경 변수를 설정합니다.
echo 'export JAVA_HOME=$(/usr/libexec/java_home -v 11)' >> ~/.zprofile
4.1.3 도커 데스크톱 다운로드
아래 사이트에서 다운 받은 후 https://www.docker.com/products/docker-desktop
docker version 명령어를 통해 잘 설치 되었는지 확인해 봅니다.
docker version
Client:
Cloud integration: v1.0.22
Version: 20.10.12
API version: 1.41
Go version: go1.16.12
Git commit: e91ed57
Built: Mon Dec 13 11:46:56 2021
OS/Arch: darwin/amd64
Context: default
Experimental: true
Server: Docker Desktop 4.5.0 (74594)
Engine:
Version: 20.10.12
API version: 1.41 (minimum version 1.12)
Go version: go1.16.12
Git commit: 459d0df
Built: Mon Dec 13 11:43:56 2021
OS/Arch: linux/amd64
Experimental: false
containerd:
Version: 1.4.12
GitCommit: 7b11cfaabd73bb80907dd23182b9347b4245eb5d
runc:
Version: 1.0.2
GitCommit: v1.0.2-0-g52b36a2
docker-init:
Version: 0.19.0
GitCommit: de40ad0
4.2 소스 코드 빌드와 컨테이너 이미지 생성
4.2.1 소스 코드 빌드
소스 코드 빌드네는 자바 애플리케이션용 빌드 도구인 그래들을 이용합니다. 그래들은 기본적으로 독립된 도구로 설치해서 사용하지만, 그래들 래퍼라는 구조를 사용하면 그래들이 미설치된 환경에서도 필요한 라이브러리를 자동적으로 다운로드하고 빌드할 수 있습니다.
cd <위에 깃헙 링크를 통해 다운받은 파일의 위치>/backend-app
sudo chmod 755 ./gradlew
./gradlew clean build
위의 명령어를 실행하여 정상적으로 빌드 되면 콘솔에 ‘BUILD SUCCESSFUL’이라고 표시되며 다음 작업이 수행됨
- 의존성 라이브러리 다운로드
- 프로그램 컴파일
- 테스트 프로그램 컴파일
- 테스트 실행
- 프로그램 실행용 아카이브 파일 생성
또한, Bckend-app/build/libs/backend-app-1.0.0.jar 파일이 생성됨
4.2.2 컨테이너 이미지 생성
컨테이너 이미지를 정의하는 dockerfile을 생성하고 docker build 명령어 사용
sudo docker build -t k8sbook/batch-app:1.0.0 --build-arg \
JAR_FILE=build/libs/batch-app-1.0.0.jar .
4.3 컨테이너 레지스트리 준비
aws management console > amazon container service > amazon ecr > ‘레포지토리 생성’ 클릭
‘리포지토리 이름’ 항목에 k8sbook/backend-app (namespace/repo-name) 입력 후 클릭 클릭 해서 레포지토리 생성
생성 시 ‘<어카운트>.dkr.ecr.ap-northeast-2.amazonaws.com/k8sbook/backend-app' 형태의 레파지토리 주소가 생성되며 이는 컨테이너 이미지를 푸시/풀 할때 설정함어카운트>
4.4 컨테이너 이미지 푸시
4.4.1 ECR 로그인
aws ecr get login-password --region ap-northeast-2 | \
docker login --username AWS --password-stdin \
<어카운트 id>.dkr.ecr.ap-northeast-2.amazonaws.com
4.4.2 컨테이너 이미지 태그 설정과 푸시
4.4.1 과정을 통해 ecr에 로그인 되었다면 이제는 컨테이너 이미지를 이미지를 저장
- docker tag 명령으로 컨테이너 이미지에 태그 설정
-
해당 태그에 대해 docker push 명령 실행
- docker tag 명령으로 컨테이너 이미지에 태그 설정
docker tag k8sbook/batch-app:1.0.0 <aws account id>.dkr.ecr.ap-northeast-2.amazonaws.com/yuran/batch-app:1.0.0
- 해당 태그에 대해 docker push 명령 실행
docker push <aws account id>.dkr.ecr.ap-northeast-2.amazonaws.com/k8sbook/batch-app:1.0.0
실행하면 설정한 태그에 따라 ECR 컨테이너 이미지가 전송됨. 이렇게 API 어플리케이션 컨테이너 이미지가 ECR에 저장됨
4.5 EKS 클러스터에 API 애플리케이션 배포
4.5.1네임스페이스 생성
- createnamespace.yaml
apiVersion: v1 kind: Namespace metadata: name: eks-work
kubectl apply -f createnamespace.yaml
- kubeconfig에 네임스페이스 반영
~~~bash
kubectl config set-context eks-work –cluster eks-work-cluster.ap-northeast-2.eksctl.io
–user\ --namespace eks-work
kubectl config get-contexts
- 데이터베이스 접속용 시크릿 등록
~~~bash
DB_URL=jdbc:postgresql://<RDS 엔드포인트 주소>myworkdb \
DB_PASSWORD='<DB사용자 주소>' \
envsubst < 21_db_config_k8s.yaml.template | \
kubectl apply -f -
21_db_config_k8s.yaml.template
apiVersion: apps/v1
kind: Deployment
metadata:
name: backend-app
labels:
app: backend-app
spec:
replicas: 2
selector:
matchLabels:
app: backend-app
template:
metadata:
labels:
app: backend-app
spec:
containers:
- name: backend-app
image: ${ECR_HOST}/k8sbook/backend-app:1.0.0
imagePullPolicy: Always
ports:
- containerPort: 8080
env:
- name: DB_URL
valueFrom:
secretKeyRef:
key: db-url
name: db-config
- name: DB_USERNAME
valueFrom:
secretKeyRef:
key: db-username
name: db-config
- name: DB_PASSWORD
valueFrom:
secretKeyRef:
key: db-password
name: db-config
readinessProbe:
httpGet:
port: 8080
path: /health
initialDelaySeconds: 15
periodSeconds: 30
livenessProbe:
httpGet:
port: 8080
path: /health
initialDelaySeconds: 30
periodSeconds: 30
resources:
requests:
cpu: 100m
memory: 512Mi
limits:
cpu: 250m
memory: 768Mi
lifecycle:
preStop:
exec:
command: ["/bin/sh", "-c", "sleep 2"]
~~~
- API 애플리케이션 배포
ECR_HOST=
- API 애플리케이션 외부 공개
~~~bash
kubectl apply -f 23_service_backend-app_k8s.yaml
apiVersion: v1
kind: Service
metadata:
name: backend-app-service
spec:
type: LoadBalancer
selector:
app: backend-app
ports:
- protocol: TCP
port: 8080
targetPort: 8080
프런트엔드 애플리케이션 배포 빌드 및 배포 부터는 다음 포스팅에
5. 프런트엔드 애플리케이션 빌드와 배포
5.1 Node.js 설치
https://nodejs.org/en/ 에서 LTS버전 다운로드
5.2 프런트엔드 애플리케이션 빌드
# 프런트엔드 소스코드가 있는 디렉토리로 이동
cd k8s-aws-book/frontend-app
# 라이브러리 다운로드
npm install
5.2.1 API 기본 URL 확인
kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/backend-app-service LoadBalancer 10.100.91.195 00000-175018810.ap-northeast-2.elb.amazonaws.com 8080:32543/TCP 5d3h
5.2.2 빌드 실행
BASE_URL=<EXTERNAL-IP>8080 npm run build
빌드 결과 파일은 dist 디렉토리 아래에 출력됨 이 디렉토리를 웹 서버에 저장하면 프런트엔드 애플리케이션을 공개할 수 있음
5.3 S3 버킷과 CloudFront 배포 생성
k8s-aws-book/eks-env/30_s3_cloudfront_cfn.yaml 로 스택 생성 스택 이름: eks-work-frontend BucketSuffix: 마음대로
5.3.1 콘텐츠 업로드
aws s3 sync dist s3://eks-work-frontend-yrkim \ ok 04:48:36 PM
--delete --include "*" --acl public-read
5.3.2 CloudFront 배포 캐시 무효화
오래된 캐시가 보이지 않게 하기 위해 캐시 무효화를 한다 Distribution Id 값은 eks-work-frontend 스택의 출력 부분에서 확인 가능
aws cloudfront create-invalidation --distribution-id <Distribution ID값> \ INT 9s 04:52:22 PM
--path "/*"
els-work-frontend 스택 부분 출력에 있는 cloudfront 주소로 테스트 페이지 접속 가능
6. 배치 애플리케이션 빌드와 배포
6.1 배치 애플리케이션 빌드와 컨테이너 이미지 생성
6.1.1 소스 코드 빌드
cd k8sbook/batch-app
./gradlew clean build
코드 빌드 완료시 libs 아래 .jar 파일이 만들어짐
6.1.2 ECR 리포지터리 생성
이전에 backend 리포지터리 생성했을때와 동일하게 Amazon ECR> 리포지토리 > ‘리포지토리 생성’ 리포지터리 이름: k8sbook/batch-app
6.2 컨테이너 이미지 푸시
6.2.1 ECR 로그인
로그인 한지 12시간이 되지 않았다면 할 필요 없음
aws ecr get-login-password --region ap-northeast-2 | \ ok 33s 05:09:59 PM
docker login --username AWS --password-stdin \
<aws_acount_id>.dkr.ecr.ap-northeast-2.amazonaws.com
6.2.2 컨테이너 이미지 태그 생성과 푸시
docker tag k8sbook/batch-app:1.0.0 <aws_acount_id>.dkr.ecr.ap-northeast-2.amazonaws.com/yuran/batch-app:1.0.0
docker push <aws_acount_id>.dkr.ecr.ap-northeast-2.amazonaws.com/yuran/batch-app:1.0.0
6.3 s3 버킷 생성과 설정
6.3.1 s3 버킷 생성과 설정
k8s-aws-book/eks-env/40_s3_batch_cfn.yaml 로 스택 생성 스택 이름: eks-work-batch BucketSuffix: 마음대로
6.3.2 s3 컨피그맵 생성
BUCKET_SUFFIX=eks-work-batch-yrkim \ INT 05:21:23 PM
envsubst < 41_config_map_batch_k8s.yaml.template | kubectl apply -f -
6.3.3 s3 접속용 액세스 키 확인 및 시크릿 생성
-
액세스 키 확인 AWS Systems Manager > 파라미터 스토어
-
시크릿 생성
AWS_ACCESSKEY=<액세스키> \ INT eks-work/eks-work kube 05:21:23 PM AWS_SECRETKEY=<비밀 액세스키> \ envsubst < 42_batch_secrets_k8s.yaml.template | kubectl apply -f -
6.4 입력 파일 업로드
aws s3 sync dist s3://eks-work-frontend-yrkim \ INT 05:26:37 PM
--delete --include "*" --acl public-read
6.5 배치 애플리케이션 배포
6.5.1 DB 내용 확인
sh-4.2$ psql -U mywork -h <rds 엔드포인트 주소> myworkdb
Password for user mywork:
myworkdb=> select * from location limit 50;
location_id | location_name | region_id | note
-------------+-----------------+-----------+--------------------------------------------------------------------------------------
1 | 테디베어 뮤지엄 | 9 | 테디베어의 역사는 물론 예술, 세계여행 등의 테마를 제공하는 테마 뮤지엄 브랜드입니다.
2 | 성산 일출봉 | 9 | 유네스코 세계자연유산에 등재된 제주도의 랜드마크.
(2 rows)
6.5.2 배치 애플리케이션 배포
크론잡 수행
ECR_HOST=<aws_account_id>.dkr.ecr.ap-northeast-2.amazonaws.com \ ok eks-work/eks-work kube 05:38:13 PM
envsubst < 43_cronjob_k8s.yaml.template | \
kubectl apply -f -
kubectl get all
NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
cronjob.batch/batch-app */5 * * * * False 14 4m45s 69m
6.5.2 배치 애플리케이션 실행 후 확인
sh-4.2$ psql -U mywork -h <rds 엔드포인트 주소> myworkdb
Password for user mywork:
myworkdb=> select * from location limit 50;
댓글남기기