사용하게 된 계기
- CICD에는 여러가지 툴들이 존재한다.
- Github Action CI/CD
- Jenkins
- Travis CI + AWS CodeDeploy
- AWS CodePipeline
- Jenkins를 사용해 본 결과 AWS EC2를 오로지 Jenkins를 위해 인스턴스를 하나 사용해야한다.
- 위와 같은 단점으로 인해 나머지 Github Action CI/CD, Travis CI + AWS CodeDeploy, AWS CodePipeline 툴중에 고민을 해보았다.
- Travis CI + AWS CodeDeploy
- Github와의 연동성과 설치가 필요없다는 장점이 있지만, Private Repo일 경우 유로이다. (1달에 69$이다.)
- 유료여서 배제하였다.
- AWS CodePipeline
- AWS 하나로 관리가 가능하다는 장점이 있지만, 파이프라인 1개당 1$ + 추가요금이 발생한다.
- 유료여서 배제하였다.
- Github Action CI/CD
- 설치가 필요없고 바로 해당 Repo에서 관리가 가능하고 yml파일로 설정이 쉬운 장점이 있다.
- 하지만 위도 Private Repo에서는 요금이 발생하지만 Action 시간이 2000시간까지는 무료여서 해당 툴을 선택하였다.
실행과정
1. health check code를 작성한다.
@RestController
public class HealthCheckController {
@RequestMapping("/healthCheck")
public String healthCheck() {
return "200 ok";
}
}
2. dockerfile 작성한다. → 해당 파일에 최상위 root directory에 파일을 만든다.
- dockerfile
FROM openjdk:11
ARG JAR_FILE=build/libs/*.jar
COPY ${JAR_FILE} app.jar
ENTRYPOINT ["java","-jar","/app.jar"]
3. docker-compose 작성한다. → docker-compose.yaml를 작성하자면, 컨테이너는 한개만 올려두면 사실 docker-compose를 사용할 필요가 없긴하지만 추후에 컨테이너를 더 증가시킬 여부가 다분하기에 docker-compose로 작성하였습니다.
version: '3'
services:
web:
container_name: web
image: taeyun1215/ewm
expose:
- 8081
ports:
- 8081:8081
- 컨테이너는 web 서버 컨테이너 하나만 띄울거고 Github Action으로 Docker hub에 올려둔 image를 사용할 예정이므로 파일에 image 부분에 Docker hub 올려둔 image 이름을 적어줍니다.
- 포트도 작성하고 해당 EC2 서버에 올려둡니다.
4. Github Action 작성
- 해당 Repo에 들어가서 Action → java with gradle를 검색후 → configure 클릭
- 기존에 작성되어 있는 default가 있는데 해당 default는 가장 기본적인것이므로 무시하고 새로 만들면 됩니다.
- 저는 밑과 같이 작성하였습니다.
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
permissions:
contents: read
jobs:
build:
runs-on: ubuntu-18.04
steps:
- name: Get Github Actions IP
id: ip
uses: haythem/public-ip@v1.2
- name: checkout
uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
## gradle build
- name: Build with Gradle
run: ./gradlew bootJar
## 웹 이미지 빌드 및 도커허브에 push
- name: web docker build and push
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_REPO }}/ewm .
docker push ${{ secrets.DOCKER_REPO }}/ewm
## docker compose up
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: |
docker pull ${{ secrets.DOCKER_REPO }}/ewm
docker-compose up -d
docker image prune -f
- 밑에서 하나하나 설명하겠습니다.
- 기본 설정
name: Java CI with Gradle
on:
push:
branches: [ "main" ]
permissions:
contents: read
- name : Action으로 실행할 이름을 정한다.
- on은 어떤 조건에서 workflow를 실행할지 적어주는 부분이다.
- 위는 main 브랜치에 push 될 때마다 재배포하는 것으로 했습니다.
- 자바 설치
jobs:
build:
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- jobs → 이제부터 어떤 일을 시작할지 적어줍니다.
- runs-on → 어떤 OS에서 실행될지 지정해준다.
- steps → 하나씩 실행할 순서를 정한다.
- name → 이름을 적어준다.
- uses → 이미 만들어진 것을 가져다 쓰는 것이다.
- with → 사용할 Java version 과 JDK는 Temurin를 사용한다.
- 빌드하기
## gradle build
- name: Build with Gradle
run: ./gradlew bootJar
- 메인 브런치에 대한 코드를 기반으로 빌드파일을 만들어준다.
- 빌드하게 되면 build 폴더 안에 .jar 파일이 생성된다.
- 도커 빌드 및 도커 허브에 푸쉬
## 웹 이미지 빌드 및 도커허브에 push
- name: web docker build and push
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_REPO }}/ewm .
docker push ${{ secrets.DOCKER_REPO }}/ewm
- run 부분에 script를 작성하여 해당 script가 실행되도록 만든다.
- ${{ secrets.DOCKER_USERNAME }}, ${{ secrets.DOCKER_PASSWORD }, ${{ secrets.DOCKER_REPO }} 3가지 매개변수는 github repo에 있는 secret 탭에 다 넣어두었습니다.
- 위 부분은 코드 설명이 다 끝나고 적어두겠습니다.
- docker login → docker build → docker push 로 이어지는 로직이며 간단한 도커 명령어이기에 넘어가겠습니다.
- AWS EC2 접속 및 도커로 배포하기
## docker compose up
- name: executing remote ssh commands using password
uses: appleboy/ssh-action@master
with:
host: ${{ secrets.HOST }}
username: ${{ secrets.USERNAME }}
key: ${{ secrets.KEY }}
script: |
docker pull ${{ secrets.DOCKER_REPO }}/ewm
docker-compose up -d
docker image prune -f
- 이미 만들어진 ssh 접속 방식(appleboy/ssh-action@master)을 이용하여 EC2 서버에 들어간다.
- ${{ secrets.HOST }}, ${{ secrets.USERNAME }}, ${{ secrets.KEY }} 3가지 매개변수도 secret 탭에 넣어두었습니다.
- script → EC2 서버 내에서 실행시킬 script를 작성한다.
- docker pull → docker-compose up -d → docker image prune -f 로 이어지는 로직이며 docker hub에 있는 image를 pull 받고 기존에 만들어둔 docker-compose 파일을 up -d 명령어로 실행시킨다.
5. Secret 등록
- Github Repo → Settings → Secret and variables → Action에 접속한다.
- 위 페이지에서 New repo secret를 클릭하여 하나씩 생성해준다.
- DOCKER_REPO → ewm (제가 올린 repo 이름 기준입니다.)
- DOCKER_USERNAME → taeyun1215
- DOCKER_PASSWORD → 해당 password
- HOST → EC2 Public IPv4 및 EC2 Public IPv4 DNS
- USERNAME → ec2-user (최신 EC2이면 고정입니다.)
- KEY → EC2 생성시 등록했던 pem key
- 해당 pem key를 찾기 위해서는 로컬에서 cat ~/.ssh/지정한 pem key 이름.pem으로 검색하면 밑에 -----BEGIN RSA PRIVATE KEY----- ~~~ -----END RSA PRIVATE KEY----- 통째로 다 복사해서 넣어줘야한다. 맨 마지막에 “%”는 제외입니다.
6. Action Run
- Github Repo에 main 브런치에 푸쉬하게 되면 자동으로 Action이 실행된다.
- 해당 실행 이름은 내가 지정한 Java Ci with Gradle이고 지금은 Build 하나로 퉁쳤기에 하나만 나오게 된 것이다.
- checkout, Set up JDK 11 등 내가 지정한 이름으로 하나씩 실행이 되며 어디서 실패했는지 확인이 가능하다.
'DevOps' 카테고리의 다른 글
Nextjs Springboot Nginx Docker-compose (0) | 2023.03.16 |
---|---|
AWS S3 Bucket (1) | 2023.02.22 |
AWS CM, ELB, Nginx use HTTPS server building (0) | 2023.01.25 |
__AWS Route 53 DNS and EC2 linkage__ (0) | 2023.01.25 |
AWS EC2 mariadb download (1) | 2023.01.25 |