최근 서버 환경을 쿠버네틱스로 변경했기 때문에 지속적 배포 방법을 변경해야 합니다. 오늘은 Github Action으로 구현해 볼 것입니다.
쿠버네틱스에 배포하는 방법은 간단합니다. 원하는 배포사항을 YAML 파일로 작성해 kubectl로 등록해주면 됩니다. 이후에 Github Action에서 SSH로 접속해 YAML 파일을 전달하고 kubectl을 실행해줄 것입니다.
도커 빌드 및 레지스트리 저장
레포지토리명과 브랜치 이름을 바탕으로 이미지 이름을 정할 것입니다. Github Secret 에는 도커 허브 로그인에 사용할 DOCKER_USERNAME와 DOCKER_PASSWORD를 등록하면 됩니다.
스크립트는 다음과 같습니다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: <https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle>
name: Spring/Kotlin Coverage Test on main
on:
push:
branches: [ "main","dev","qa" ]
permissions:
contents: write
jobs:
Deploy-docker-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Build
run: ./gradlew build
- name: Create Test Coverage Report
run: ./gradlew jacocoTestReport
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.1.1
with:
file: ./build/reports/jacoco/test/jacocoTestReport.xml
- name: Unpack JAR
run: |
mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)
- name: Set lowercase repository name without owner environment variable
run: |
echo "REPOSITORY_NAME=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]' | cut -d'/' -f2)" >> $GITHUB_ENV
- name: Get lowercase branch name
run: |
echo "BRANCH_NAME=$(echo $GITHUB_REF_NAME | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Get docker image name
run: |
echo "IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:${{ env.BRANCH_NAME }}" >> $GITHUB_ENV
- name: Build docker image
run: |
docker build -t ${{ env.IMAGE_NAME }} .
docker tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
- name: Push docker image
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker push ${{ env.IMAGE_NAME }}
docker push ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
Plain JAR 생성은 억제해야 합니다. 코틀린의 경우 build.gradle.kts에 아래와 같이 입력합니다.
tasks.getByName<Jar>("jar") {
enabled = false
}
자바인 경우 build.gradle에 아래와 같이 입력합니다.
jar{
enabled = false
}
이렇게 하면 dev 브랜치에 새로운 커밋이 생성될 때마다 그 커밋을 기준으로 도커 이미지를 빌드하고 푸시합니다. 그럼 latest와 dev 두 개가 만들어져 있을 것입니다. 꼭 latest를 만들어야 하는 것은 아닙니다.
EC2에 SSH로 접속하기
이제 SSH에 접속해보겠습니다. ssh-action을 사용하면 상당히 쉽습니다.
접속할 때는 ec2를 생성할 때 적용한 .pem 키 파일을 사용할 예정입니다.
1. 깃헙 시크릿 등록하기
깃헙 시크릿에는 총 3개를 등록해야 합니다.
- 사용자 이름 (AWS_USERNAME)
- EC2 호스트 주소(AWS_HOST)
- 시크릿 키(AWS_SECRET_ACCESS_KEY)
사용자 이름은 기본적으로 ec2-user 입니다.
호스트의 경우 ip 주소 또는 이를 가리키는 도메인을 의미합니다.
시크릿 키는 .pem 파일 값입니다.
메모장 또는 cat 명령어로 .pem 파일 내부의 값을 출력해 복사 후 시크릿으로 등록합니다.
2. 배포 스크립트 작성
k8s에 배포를 위한 스크립트를 작성합니다.
서비스와 배포에 대한 명세를 deploy.yml에 작성합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-demo-deploy
labels:
app: spring-demo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: spring-demo
template:
metadata:
labels:
app: spring-demo
spec:
containers:
- name: spring-demo
image: 'lee01042000/beamworks-backend:dev'
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: spring-service
spec:
type: NodePort
selector:
app: spring-demo
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30007
3. Github Action k8s 배포 스크립트 작성
이제 deploy.yaml을 서버에 전달해 kubectl로 적용하는 스크립트를 작성합니다.
scp, ssh 액션을 사용하면 쉽게 가능합니다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: <https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle>
name: Spring/Kotlin Coverage Test on main
on:
push:
branches: [ "main","dev","qa" ]
permissions:
contents: write
jobs:
Deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Build
run: ./gradlew build
- name: Create Test Coverage Report
run: ./gradlew jacocoTestReport
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.1.1
with:
file: ./build/reports/jacoco/test/jacocoTestReport.xml
- name: Unpack JAR
run: |
mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)
- name: Set lowercase repository name without owner environment variable
run: |
echo "REPOSITORY_NAME=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]' | cut -d'/' -f2)" >> $GITHUB_ENV
- name: Get lowercase branch name
run: |
echo "BRANCH_NAME=$(echo $GITHUB_REF_NAME | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Get docker image name
run: |
echo "IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:${{ env.BRANCH_NAME }}" >> $GITHUB_ENV
- name: Build docker image
run: |
docker build -t ${{ env.IMAGE_NAME }} .
docker tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
- name: Push docker image
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker push ${{ env.IMAGE_NAME }}
docker push ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
- name: Transport deploy.yaml to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.AWS_HOST }}
username: ${{ secrets.AWS_USERNAME }}
key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
overwrite: true
source: ./deploy.yaml
target: ~/
- name: Connect to AWS EC2 with SSH
uses: appleboy/ssh-action@v0.1.8
with:
host: ${{ secrets.AWS_HOST }}
username: ${{ secrets.AWS_USERNAME }}
key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
script: kubectl apply -f deploy.yaml
4. 배포 및 확인
지금까지 작성한 커밋을 dev 브랜치에 커밋하면 Github Action이 실행됩니다.
위와 같이 배포가 잘 이루어지면 서버에 가서 상태를 확인합니다.
아래처럼 새로운 파드가 돌아가면 성공입니다.
쿠버네틱스에 배포하는 방법은 간단합니다. 원하는 배포사항을 YAML 파일로 작성해 kubectl로 등록해주면 됩니다. 이후에 Github Action에서 SSH로 접속해 YAML 파일을 전달하고 kubectl을 실행해줄 것입니다.
도커 빌드 및 레지스트리 저장
레포지토리명과 브랜치 이름을 바탕으로 이미지 이름을 정할 것입니다. Github Secret 에는 도커 허브 로그인에 사용할 DOCKER_USERNAME와 DOCKER_PASSWORD를 등록하면 됩니다.
스크립트는 다음과 같습니다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: <https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle>
name: Spring/Kotlin Coverage Test on main
on:
push:
branches: [ "main","dev","qa" ]
permissions:
contents: write
jobs:
Deploy-docker-image:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Build
run: ./gradlew build
- name: Create Test Coverage Report
run: ./gradlew jacocoTestReport
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.1.1
with:
file: ./build/reports/jacoco/test/jacocoTestReport.xml
- name: Unpack JAR
run: |
mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)
- name: Set lowercase repository name without owner environment variable
run: |
echo "REPOSITORY_NAME=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]' | cut -d'/' -f2)" >> $GITHUB_ENV
- name: Get lowercase branch name
run: |
echo "BRANCH_NAME=$(echo $GITHUB_REF_NAME | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Get docker image name
run: |
echo "IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:${{ env.BRANCH_NAME }}" >> $GITHUB_ENV
- name: Build docker image
run: |
docker build -t ${{ env.IMAGE_NAME }} .
docker tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
- name: Push docker image
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker push ${{ env.IMAGE_NAME }}
docker push ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
Plain JAR 생성은 억제해야 합니다. 코틀린의 경우 build.gradle.kts에 아래와 같이 입력합니다.
tasks.getByName<Jar>("jar") {
enabled = false
}
자바인 경우 build.gradle에 아래와 같이 입력합니다.
jar{
enabled = false
}
이렇게 하면 dev 브랜치에 새로운 커밋이 생성될 때마다 그 커밋을 기준으로 도커 이미지를 빌드하고 푸시합니다. 그럼 latest와 dev 두 개가 만들어져 있을 것입니다. 꼭 latest를 만들어야 하는 것은 아닙니다.
EC2에 SSH로 접속하기
이제 SSH에 접속해보겠습니다. ssh-action을 사용하면 상당히 쉽습니다.
접속할 때는 ec2를 생성할 때 적용한 .pem 키 파일을 사용할 예정입니다.
1. 깃헙 시크릿 등록하기
깃헙 시크릿에는 총 3개를 등록해야 합니다.
- 사용자 이름 (AWS_USERNAME)
- EC2 호스트 주소(AWS_HOST)
- 시크릿 키(AWS_SECRET_ACCESS_KEY)
사용자 이름은 기본적으로 ec2-user 입니다.
호스트의 경우 ip 주소 또는 이를 가리키는 도메인을 의미합니다.
시크릿 키는 .pem 파일 값입니다.
메모장 또는 cat 명령어로 .pem 파일 내부의 값을 출력해 복사 후 시크릿으로 등록합니다.
2. 배포 스크립트 작성
k8s에 배포를 위한 스크립트를 작성합니다.
서비스와 배포에 대한 명세를 deploy.yml에 작성합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: spring-demo-deploy
labels:
app: spring-demo
tier: backend
spec:
replicas: 1
selector:
matchLabels:
app: spring-demo
template:
metadata:
labels:
app: spring-demo
spec:
containers:
- name: spring-demo
image: 'lee01042000/beamworks-backend:dev'
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: spring-service
spec:
type: NodePort
selector:
app: spring-demo
ports:
- protocol: TCP
port: 8080
targetPort: 8080
nodePort: 30007
3. Github Action k8s 배포 스크립트 작성
이제 deploy.yaml을 서버에 전달해 kubectl로 적용하는 스크립트를 작성합니다.
scp, ssh 액션을 사용하면 쉽게 가능합니다.
# This workflow uses actions that are not certified by GitHub.
# They are provided by a third-party and are governed by
# separate terms of service, privacy policy, and support
# documentation.
# This workflow will build a Java project with Gradle and cache/restore any dependencies to improve the workflow execution time
# For more information see: <https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-java-with-gradle>
name: Spring/Kotlin Coverage Test on main
on:
push:
branches: [ "main","dev","qa" ]
permissions:
contents: write
jobs:
Deploy:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up JDK 11
uses: actions/setup-java@v3
with:
java-version: '11'
distribution: 'temurin'
- name: Setup Gradle
uses: gradle/gradle-build-action@v2
- name: Build
run: ./gradlew build
- name: Create Test Coverage Report
run: ./gradlew jacocoTestReport
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v3.1.1
with:
file: ./build/reports/jacoco/test/jacocoTestReport.xml
- name: Unpack JAR
run: |
mkdir -p build/dependency && (cd build/dependency; jar -xf ../libs/*.jar)
- name: Set lowercase repository name without owner environment variable
run: |
echo "REPOSITORY_NAME=$(echo ${{ github.repository }} | tr '[:upper:]' '[:lower:]' | cut -d'/' -f2)" >> $GITHUB_ENV
- name: Get lowercase branch name
run: |
echo "BRANCH_NAME=$(echo $GITHUB_REF_NAME | tr '[:upper:]' '[:lower:]')" >> $GITHUB_ENV
- name: Get docker image name
run: |
echo "IMAGE_NAME=${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:${{ env.BRANCH_NAME }}" >> $GITHUB_ENV
- name: Build docker image
run: |
docker build -t ${{ env.IMAGE_NAME }} .
docker tag ${{ env.IMAGE_NAME }} ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
- name: Push docker image
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker push ${{ env.IMAGE_NAME }}
docker push ${{ secrets.DOCKER_USERNAME }}/${{ env.REPOSITORY_NAME }}:latest
- name: Transport deploy.yaml to server
uses: appleboy/scp-action@master
with:
host: ${{ secrets.AWS_HOST }}
username: ${{ secrets.AWS_USERNAME }}
key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
overwrite: true
source: ./deploy.yaml
target: ~/
- name: Connect to AWS EC2 with SSH
uses: appleboy/ssh-action@v0.1.8
with:
host: ${{ secrets.AWS_HOST }}
username: ${{ secrets.AWS_USERNAME }}
key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
script: kubectl apply -f deploy.yaml
4. 배포 및 확인
지금까지 작성한 커밋을 dev 브랜치에 커밋하면 Github Action이 실행됩니다.
위와 같이 배포가 잘 이루어지면 서버에 가서 상태를 확인합니다.
아래처럼 새로운 파드가 돌아가면 성공입니다.
'Computer Science' 카테고리의 다른 글
Spring Data MongoDB에서 Union 연산을 수행하는법 (0) | 2023.07.19 |
---|---|
Gitlab에 러너를 등록하기 (0) | 2023.07.13 |
앤서블로 카프카 클러스터 구축하기 (0) | 2023.07.13 |