AWS - 1

Tadap·2023년 11월 4일

캡스톤

목록 보기
2/2

캡스톤 디자인을 진행하면서 AWS를 한 내용을 정리해 보려 합니다.
사용해보지 않은 부분위주로 작성하겠습니다.

위 이미지는 현재 구성하고 있는 AWS의 상태입니다.
정확하지 않은 부분이 있을수도 있으니 혹시 알게되시면 알려주시면 감사하겠습니다.

프로젝트 초기부터 해보고 싶은것이 Jenkins를 이용하여 CI/CD 파이프라인 구축과, Kubernetes를 통한 배포였다.
둘 다 해본적이 없었으나. 다행이 Jenkins를 이용한 CI/CD 파이프라인 구축은 학교 AWS시간에 해볼 수 있었다. 링크 참조
kubernetes를 이용한 강의도 있지만... 뭔가 정확하지 않고 오류가 나 시도했으나 실패했었다.
이번에는 직접 찾은 정보를 가지고 시작한다.

1. Doamin구매

도메인은 구글을 이용하여 구매했다. 한국에서는 지원하지 않지만 편법을 이용해서 미국 주소로 바꾸면 구매 가능하다. 가격 차이도 크지 않고(없었던 것으로 기억) UI가 편해 보여서 구글로 선택하였다.

2. EC2 구성

현재는 BackendServer까지만 Kubernetes로 구성이 완료 된 상태이다.

이번 프로젝트는 1. 비용을 줄이고 2. 기술 사용에 목적을 두었기 때문에 AWS의 DB, K8S서비스를 이용하지 않고 EC2로 구성을 하였다.
따라서 K8S를 사용해 보지만 여러개의 노드를 펼치지 않고. 하나의 노드에 팟도 하나만 띄운다. 실제 환경에서는 여러 가용영역에 걸쳐 여러개의 서버에 여러개의 팟을 띄우면 될 것 같다. AWSK8S를 사용하면 이것도 자동으로 가능하나 API요청 하나당 100원...

3. Docker부터

먼저 이미지를 올리는것부터 해본 적이 없기 때문에 Dockerfile을 이용해서 이미지를 빌드해서 올리는것부터 시도했다.

FROM openjdk:17-jdk-alpine
LABEL authors="gusvy"
ENV SPRING_PROFILES_ACTIVE=prod
ARG JAR_FILE=./build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java", "-jar", "/app.jar"]
EXPOSE 8080
  1. FROM 위치에는 원하는 환경을 적어준다. SpringBoot이기 때문에 Java로 설정하였다
  2. LABEL은 제작자를 의미한다.
  3. ENV는 환경변수인데 Spring을 dev, prod로 나누어 진행해 두었다. 따라서 prod환경에서 실행시키기 위해 변수를 추가해 주었다.
  4. ARG는 Argument로 실행을 위한 JAR 파일의 위치를 JAR_FILE에 저장해 두었다.
  5. ENTRYPOINT 는 Docker컨테이너가 실행될 때 진입점을 지정한다.
  6. EXPOSE는 도커의 포트를 외부로 노출시키기 위해 있다. 8080번 포트를 열어두었다.

이후 인텔리제이를 이용하여 dockerhub에 이미지를 올렸다.

4. Jenkins

젠킨스 설치는 공식 문서를 참조하면 된다.
자바에서 돌아가기 때문에 자바도 설치해줘야한다.

여담으로, 요즘엔 Kubernetes를 이용해서 Jenkins를 돌리는것 같다. Master, Worker Node처럼 Jenkins의 Master에서 일을 다 받고. 처리가 필요할 때 마다 pod로 worker를 생성해서 이미지를 빌드하는 방식으로 보인다.
이렇게 하면 이후 Kubernetes에 이미지를 올리기도 편해 보인다.

현재 3개가 되어있다.

1. Build

빌드는 아직 미완성으로 볼 수 있다.
FreeStyleProject로 만들었는데 Pipeline으로 바꿀수 있을 것 같다.(추후 공부 후 해보는 걸로)
링크를 참고해서 만들었다.


깃헙 URL과 Credential을 넣어준다 Credential의 경우
Jenkins관리 -> Credentials -> Domain아래 (Global)에서 Add credentials를 통해 넣을 수 있다.
Username with password로 넣고. password의 경우 깃헙에서 토큰을 만들어서 넣으면 된다.

필요한 branch를 선택한 후 넣어준다.

이후 Gradlescript를 작성해 준다. InvokeGradle를 사용했다.
Invoke Gradle과 Gradle Wrapper의 차이점은 Jenkins에서 제공하는 Gradle 사용, 특정 위치에 있는 Gradle 사용이다.
Gradle은 Jenkins관리 -> Tools -> Gradle installations에서 버전과 이름을 넣을 수 있다.

나는 clean, build만 할 것이기 때문에 2개만 넣어줬다.
필요한 대로 설정하면 된다.

트리거를 설정해줘서 github에서 webhook을 걸어 빌드를 걸 수 있다.
이렇게 해줘야 깃헙에 새 코드 등장 -> build -> ... 이 가능하다.
이는 추후 설정할 예정이다.

2. Push

이 부분은 PipeLine으로 구성했다
직접 Syntax를 작성하는건 처음이라 Google과 ChatGPT의 도움을 받았다.

pipeline { 
    environment { 
        repository = "notionlinkedblog/notionlinkedblog_server"  //docker hub id와 repository 이름
        DOCKERHUB_CREDENTIALS = credentials('nlb_hub') // jenkins에 등록해 놓은 docker hub credentials 이름
        dockerImage = '' 
  }
  agent any 
  stages { 
      stage('Building our image') { 
          steps { 
              script { 
                  sh "cp \"/var/lib/jenkins/workspace/nlb_build_backend/003 Code/BE/notion-linked-blog/build/libs/notion-linked-blog-0.0.1-SNAPSHOT.jar\" /var/lib/jenkins/workspace/nlb_dockerHub_upload_backend/" // jar 파일을 현재 위치로 복사 
				  dockerImage = docker.build repository + ":latest"
              }
          } 
      }
      stage('Login'){
          steps{
              sh 'echo $DOCKERHUB_CREDENTIALS_PSW | docker login -u $DOCKERHUB_CREDENTIALS_USR --password-stdin' // docker hub 로그인
          }
      }
      stage('Deploy our image') { 
          steps { 
              script {
                sh 'docker push $repository:latest' //docker push
              } 
          }
      } 
      stage('Cleaning up') { 
		  steps { 
              sh "docker rmi $repository:latest" // docker image 제거
          }
      } 
	}
}
  1. pipeline 안에 작성한다
  2. agent any는 이 파이프라인이 어느 에이전트에서든지 실행될 수 있음을 나타낸다.
  3. 나머지는 크게 2가지로 나뉜다
    1. environment는 변수들을 의미한다
    2. stages는 단계를 의미하는데 이는 추후에 아래처럼 구성된다.

      이후 stage에 제목을 쓰고
      step에 무엇을 할지 정하면 된다.
      만약 써야할 줄이 여러줄이면 script안에 작성하면 된다.

나머지는 각 줄에 주석을 참고하면 된다.
Docker의 경우도 로그인을 위해 Crendential을 등록해 줘야 한다.

3. Update

이건 진자 야매로 만들어서 추후 꼭 수정이 필요하다. 그래서 이름도 test이다.
DockerHub에 이미지가 올라가면 그 이미지를 다운해서 바꿔줘야한다. 이 과정을 종료 없이도 가능하게 할 수 있다.
목표는 위 2번 과정 이후에 kubectl을 이용하여 jenkins -> masterNode에게 바꾸라는 명령을 내리는 것이긴 한데

cp $file test.yaml
cp $config config
kubectl --kubeconfig=config delete deployment my-test
kubectl --kubeconfig=config apply -f test.yaml
rm test.yaml
rm config

현재는 음... 그냥 종료 후 재실행이다.
test.yml을 kubernets에서 pod을 실행시키기 위해 필요한 Deployment와 Service가 들어있다.
config는 masterNode에 접속하기 위해 필요한 정보 파일이다.

일단 동작은 한다. 하지만 이것보다 좋은 방법이 있을 것 같다. 더 찾아봐야겠다.

0개의 댓글