Gom3rye 2025. 8. 5. 19:56
728x90
반응형

RDS를 생성 → 베스천 호스트를 생성, 베스천 호스트는 RDS에 접근하기 위한 유일한 포인트이다.

이때 베스천 호스트는 EC2 인스턴스가 될 것

RDS와 EC2 인스턴스는 동일한 VPC를 가지고 있다.

RDS는 public 접근 가능 → 샘플 데이터 삽입, 외부 접속 도구 이용, 환경 설정 x

EC2 인스턴스는 외부접속도구 설치해서 application을 생성, sample data 삽입

✅ 구성 요소와 역할

구성 요소                           설명

RDS (Relational Database Service) - 데이터베이스를 호스팅하는 서비스- 샘플 데이터를 삽입하고 외부 도구(MySQL Workbench 등)로 접근 가능하게 퍼블릭 접근 허용
Bastion Host (EC2 인스턴스) - 외부에서 RDS에 접근할 수 있는 유일한 경로- 사용자 또는 애플리케이션이 이 EC2에 접속한 뒤 RDS에 연결- 외부 접속 도구 설치 가능 (예: DBeaver, MySQL CLI 등)
VPC (Virtual Private Cloud) - RDS와 EC2가 같은 네트워크(VPC) 내에 있음- 같은 서브넷 또는 연결 가능한 서브넷에 위치해야 통신 가능

🔁 흐름 요약

  1. RDS 생성
    • 퍼블릭 접근 허용 (예: Yes)
    • 샘플 데이터 삽입 가능
    • 외부 DB 클라이언트(MySQL Workbench 등)로 직접 접속 가능
  2. EC2 인스턴스 생성 (Bastion Host)
    • 동일 VPC에 생성
    • 퍼블릭 IP 부여하여 외부에서 SSH 접속 가능
    • DB 접속용 툴 설치 가능
  3. 접속 경로
    • 사용자 → SSH로 EC2 접속 (Bastion)
    • EC2 내에서 RDS 접속 (DB 클라이언트 또는 커맨드라인 이용)

⚙️ 왜 이렇게 구성하나요?

이유               설명

보안 강화 RDS를 퍼블릭하게 둘 수도 있지만, 장기적으로는 EC2(Bastion)를 통해서만 접근하게 하여 더 안전함
접속 제어 Bastion Host를 통해 누가 언제 DB에 접근했는지 추적 가능
실습 목적 퍼블릭 설정을 통해 데이터 삽입과 외부 접속이 가능하므로, 테스트와 개발에 편리

📝 한 줄 요약

RDS는 퍼블릭 접근 가능하지만, 실제 DB 연결은 Bastion Host 역할을 하는 EC2 인스턴스를 통해서만 진행하는 구조로 보안과 통제를 강화한 구성입니다.

어제 수업 이어서,,,

  • 베스천 호스트 접속
    • 세션 서비스 관리자(Systems Manager)로 접속
    • 세션 관리자에서 세션 시작을 클릭 (자동으로 생성된 EC2 인스턴스에는 접근할 수 있지만 직접 생성한 EC2 인스턴스에는 세션 관리자에서 접속이 안된다.)
    • 동일한 VPC 안에 있는 어떤 EC2 인스턴스도 베스천 호스트가 될 수 있음
    • 아무 인스턴스나 선택해서 세션 시작을 클릭
    • 세션에서 명령어를 수행
    sudo yum install -y git
    sudo amazon-linux-extras install -y postgresql11 # 이 명령은 amazon linux로 만들어진 인스턴스에서만 수행이 가능하다.
    
    • 데이터베이스 엔드포인트 확인
    • 데이터베이스 유저 와 비밀번호 확인(AWS Secrets Manager가 비밀번호를 생성)
      • 개요에서 확인: eksdbadmin(yaml 파일에서 생성), 8hO3hPa_OVPh5=QK(자동 생성) mywork, )V1+~wRSm4fLIK)o
    • 유저 비밀번호 변경
      • createuser -d -U 관리자계정 -P -h RDS엔드포인트 사용자계정
      • 비밀번호를 입력하는 란이 3번 출력 되는데 앞의 2번은 사용자의 비밀번호이고 마지막 1번은 관리자의 비밀번호이다.
    • 데이터베이스 생성

Backend Application이 사용할 RDS를 CloudFormation으로 생성

CloudFormation

CloudFormation(yaml 파일이나 GUI Builder를 이용해서 AWS Resource를 생성하는 서비스) 이 사용할 yaml파일 생성

CloudFormation에 접속해서 작업

  • yaml 파일을 이용해서 스택을 생성
  • 2개의 파라미터만 직접 설정
    • EksWorkVPC인데 이 부분은 이미 만들어진 VPC 중 EKS와 관련된 VPC를 선택
      • Eks Cluster와 동일한 VPC에 만들면 통신 비용을 지불하지 않는다.
      • OpeServeRouteTable을 설정해야 하는데 이 부분은 이전에 만든 eks-work-base 스택의 출력 부분에서 RouteTable 값을 찾아서 선택
  • 생성에 성공하면 EC2 인스턴스가 하나 만들어지고 RDS에 데이터베이스가 생성된다.
  • 데이터베이스에 접속
    • 이 데이터베이스는 외부에 노출이 되지 않으므로 VPC 외부의 컴퓨터에서는 접속이 불가능하다.
    • 베스천 호스트에 접속을 하기 위해서 EC2 인스턴스에 연결하는 방법과 Session Manager를 이용해야 한다.
    • 베스천 호스트에 postgresql 클라이언트를 설치(amazon linux라서 설치 방법이 조금 다른다.)
      • sudo amazon-linux-extras install -y postgresql11
    • End Point 확인: RDS에서 확인 가능하고 CloudFormation의 Stack의 출력 탭에서 확인 가능
    • 관리자 비밀번호 확인
      • 관리자 아이디는 yaml 파일에서 설정했지만 비밀번호는 AWS Secrets Manager가 만들도록 설정했으므로 Secrets Manager에서 확인해야 한다.
      • 관리자 계정은 eksdbadmin
      • 관리자 비밀번호는 마스터시크릿값 → 보안 암호값 → 확인
  • 계정 생성
    • create user -d -U eksdbadmin -P -h <RDS End Point> <계정>
  • 데이터베이스 생성
    • create -U 계정 -h <RDS End Point> -E UTF8 계정
  • 데이터베이스 접속
    • psql -U 계정 -h <RDS End Point> 데이터베이스이름
  • Spring의 JPA는 Entity에 매핑되는 테이블이 없으면 자동으로 생성해주지만 실무에서는 대부분 테이블을 만들고 연결시키는 방식을 선택한다.
    • 데이터베이스 테이블을 원하는 옵션으로 만들기 어렵기 때문
  • 테이블 생성
CREATE TABLE region(
	region_id SERIAL PRIMARY KEY,
	region_name VARCHAR(100) NOT NULL,
	creation_timestamp TIMESTAMP NOT NULL
);
CREATE TABLE location(
	location_id BIGSERIAL PRIMARY KEY,
	location_name VARCHAR(200) NOT NULL,
	region_id BIGINT NOT NULL,
	note TEXT,
	FOREIGN KEY (region_id) REFERENCES region (region_id)
);
CREATE TABLE batch_processing(
	batch_name VARCHAR(20) PRIMARY KEY,
	last_execution_date_time TIMESTAMP
);
CREATE TABLE batch_processing_file(
	batch_processing_file_id BIGSERIAL PRIMARY KEY,
	batch_name VARCHAR(20) NOT NULL,
	file_name VARCHAR(300) NOT NULL
);

BackEnd Application을 EKS Cluster 에 배포

1)작업 과정

=>네임스페이스 생성

=>kubeconfig에 네임스페이스 반영

=>데이터베이스 접속용 시크릿 등록

=>API Application을 배포

=>API Application을 외부 공개

2)네임스페이스 생성

=>네임스페이스

  • 쿠버네티스는 기본적으로 클러스터 단위로 물리적 구분
  • 하나의 클러스터를 네임스페이라는 논리적 구획으로 구분해서 관리하는 것이 가능

=>네임스페이스 생성을 위한 yaml 파일 작성(create_namespace_k8s.yaml)

apiVersion: v1
kind: Namespace
metadata:
  name: eks-work
 
# 리소스 생성
kubectl apply -f create_namespace_k8s.yaml

3)네임스페이스를 반영

=>사용 중인 컨텍스트 정보 확인

kubectl config get-contexts

현재 클러스터 이름: 클러스터 이름: eks-work-cluster.ap-northeast-2.eksctl.io

현재 AUTHINFO 값: adam@eks-work-cluster.ap-northeast-2.eksctl.io

=>현재 컨텍스트에 네임스페이스 반영

kubectl config set-context 컨텍스트이름 --cluster 클러스터이름 --user AUTHINFO값 --namespace 네임스페이스 이름

컨텍스트 생성: kubectl config set-context eks-work --cluster eks-work-cluster.ap-northeast-2.eksctl.io --user adam@eks-work-cluster.ap-northeast-2.eksctl.io --namespace eks-work

=>컨텍스트 변경

kubectl config use-context 컨텍스트이름

kubectl config use-context eks-work

4)데이터베이스 접속 정보를 위한 시크릿 생성

=>데이터베이스 접속 정보는 소스 코드에 포함되어 있는 경우 소스 코드를 형상 관리 사이트에 업로드하는 것은 바람직하지 않습니다.

=>접속 정보는 배포가 될 때 시크릿을 이용해서 배포하는 것을 권장합니다.

=>소스 코드를 수정해서 ECR에 이미지를 푸시

  • application.properties 파일을 수정

spring.datasource.url=${DB_URL}

spring.datasource.username=${DB_USERNAME}

spring.datasource.password=${DB_PASSWORD}

  • 아카이브 파일(자바로 실행할 수 있는 압축 파일: jar, war) 생성

리눅스에서 수행하는 명령: sudo chmod 755 ./gradlew

./gradlew clean build

  • 빌드 과정

의존성 라이브러리 다운로드

프로그램 컴파일(기본 디렉토리의 파일과 테스트 디렉토리의 파일 모두 컴파일)

테스트 실행(실제 데이터베이스 접속 정보가 없으면 에러가 발생할 수 있는데 이를 해결하는 방법은 테스트 코드를 삭제하거나 테스트를 별도의 데이터베이스 설정을 추가합니다.)

실행 가능한 아카이브 파일 생성(spring boot 프로젝트는 build/libs 디렉토리에 프로젝트이름-0.0.1-SNAPSHOT.jar 파일로 만들어 짐)

  • 도커 이미지 빌드

sudo docker build -t k8s/backend-app:1.0.0 --build-arg JAR_FILE=build/libs/eks_backend-0.0.1-SNAPSHOT.jar .

  • AWS CLI를 이용해서 ECR에 이미지 배포

레포지토리 생성(k8s/backend-app)

ECR에 로그인: aws ecr get-login-password --region 리전 | docker login --username AWS --password-stdin AWS계정.dkr.ecr.리전.amazonaws.com

aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin 208060188195.dkr.ecr.ap-northeast-2.amazonaws.com

이미지 태그 수정: AWS계정.dkr.ecr.리전/레포리지토리이름:태그

docker tag k8s/backend-app:1.0.0 208060188195.dkr.ecr.ap-northeast-2.amazonaws.com/k8s/backend-app:1.0.0

도커 푸시: docker push 208060188195.dkr.ecr.ap-northeast-2.amazonaws.com/k8s/backend-app:1.0.0

  • 시크릿을 저장하기 위한 template 파일을 생성: db_config_k8s.yaml.template
apiVersion: v1
kind: Secret
type: Opaque
metadata:
  name: db-config
stringData:
  db-url: ${DB_URL}
  db-username: mywork
  db-password: ${DB_PASSWORD}
  • 시크릿에 값을 채워 넣기

DB_URL=jdbc:postgresql://데이터베이스경로/myworkdb DB_PASSWORD=비밀번호 envsubst < db_config_k8s.yaml.template | kubectl apply -f -

DB_URL=jdbc:postgresql://eks-work-db.c5iksoio0fsi.ap-northeast-2.rds.amazonaws.com/myworkdb DB_PASSWORD='wnddkd' envsubst < db_config_k8s.yaml.template | kubectl apply -f -

=>애플리케이션을 배포

  • 배포를 위한 템플릿 파일 생성: deployment_backend_app_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}/k8s/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
  • 리소스 생성

ECR_HOST = 계정.dkr.ecr.ap-northeast-2.amazonaws.com envset < deployment_backend_app_k8s.yaml.template | kubectl apply -f -

5)Windows에서 실행해보기 위한 수정(Secret 사용 안함)

=>application.properties의 환경 변수를 제거하고 실제 값을 설정

=>프로젝트 빌드

./gradlew clean build

=>이미지 생성

docker build -t 208060188195.dkr.ecr.ap-northeast-2.amazonaws.com/k8s/backend-app:1.0.0 --build-arg JAR_FILE=build/libs/eks_backend-0.0.1-SNAPSHOT.jar .

=>이미지 푸시

docker push 208060188195.dkr.ecr.ap-northeast-2.amazonaws.com/k8s/backend-app:1.0.0

=>배포를 위한 yaml 파일 생성

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-container
        image: 208060188195.dkr.ecr.ap-northeast-2.amazonaws.com/k8s/backend-app:1.0.0
        imagePullPolicy: Always
        ports:
        - containerPort: 80

=>리소스 생성

=>상태 확인

kubectl get all

6)서비스를 외부에 공개

=>API Application을 배포를 했지만 클러스터 외부에서는 API 호출이 불가능

=>Load Balancer 나 Node Port를 이용하면 외부에서 접속이 가능

=>LoadBalancer를 만들어서 파드를 외부에서 접속할 수 있도록 공개

apiVersion: v1
kind: Service
metadata:
  name: backend-app-service
spec:
  type: LoadBalancer
  selector:
    app: backend-app
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

=>리소스 생성

=>LoadBalancer 생성을 확인하고 DNS를 이용해서 웹 브라우저에서 접근

3.애플리케이션 환경 삭제

=>삭제 순서

  • 쿠버네티스 상의 애플리케이션 과 서비스를 삭제
  • EKS 클러스터 삭제
  • 데이터베이스 와 베스천 호스트 삭제
  • 기본 리소스 삭제

=>쿠버네티스 상의 애플리케이션 과 서비스를 삭제

  • 서비스 삭제: kubectl delete service backend-app-service
  • 디플로이먼트 삭제: kubectl delete deployment backend-app
  • 확인: kubectl get all

=>EKS 클러스터 삭제

eksctl delete cluster --name 클러스터이름

워커 노드 와 컨트롤 플레인의 삭제가 실행됩니다.

eksctl 명령으로 클러스터를 삭제하면 워커 노드의 삭제가 끝나고 컨트롤 플레인 삭제 처리를 시작한 시점에 프롬프트가 입력 가능한 상태로 돌아옵니다.

프롬프트가 다시 표시된 후에서 CloudFormation에서는 DELETE_IN_PROGRESS 일 수 있습니다.

=>데이터베이스 와 베스천 호스트 삭제

  • 데이터베이스는 CloudFormation에서 생성할 때 사용한 스택을 삭제

=>기본 리소스를 삭제: VPC 생성을 삭제

4.서비스 환경에 대한 고려

1)모니터링

=>모니터링 하기 위한 별도의 툴이 필요없는데 AWS에서 기본적으로 제공

=>클러스터 상태 파악

  • EKS 서비스에서 구성 부분을 확인
  • 데이터 플레인을 EC2로 구축하는 경우는 노드를 스스로 관리해야 합니다.

EKS에만 적용되는 것이 아니고 AWS 서비스로 일반적인 관리 및 운영을 실행하면 됩니다.

  • Auto Scaling 기능을 이용해서 데이터 플레인을 구축하기 때문에 최소 숫자의 서버가 동작하도록 되어 있습니다.

AutoScaling 그룹 설정에서 최소 서버 대수를 설정하면 그 대수 아래로 떨어지지 않도록 AWS에서 자동으로 관리

  • 데이터 플레인 전체의 부하 상태는 Amazon CloudWatch에서 확인할 수 있습니다.

AutoScaling 그룹 단위의 CPU 사용률 등을 확인할 수 있습니다.

=>애플리케이션 상태 파악

  • CloudWatch에는 Container Insights 라는 기능이 존재
  • 클러스터 노드, 파드, 네임스페이스, 서비스 레벨의 메트릭을 참조할 수 있습니다.
  • CloudWatch Agent 라는 데몬셋으로 동작시킨 후 필요한 메트릭을 CloudWatch로 전송
  • 데이터 노드의 IAM 역할에 정책 추가

EC2 관리 콘솔에서 데이터 노드에 해당하는 인스턴스를 선택한 후 상세 정보 페이지에 있는 내용 중 중간에 있는 IAM 역할 아래의 링크를 클릭한 후 정책 연결 버튼을 클릭해서 CloudWatchAgentServerPolicy를 선택해주면 됩니다.

  • CloudWatch용 네임스페이스 생성

kubectl apply -f cloudwatch-namespace.yaml

  • 파드가 사용할 서비스 계정 생성

kubectl apply -f cwagent-serviceaccount.yaml

  • 에이전트가 사용할 configmap 생성

kubectl apply -f cwagent-configmap.yaml

  • 데몬셋으로 실행

kubectl apply -f cwagent-daemonset.yaml

RegionLocation

→ 오라클: REGIONLOCATION

→ Postgresql: regionlocation

→ mysql: region_location

mysql은 기본적으로 테이블명에 대문자를 쓰지 않는다.

728x90
반응형