📕 목차
1. 고민해봐야 할 것들
2. NCP CLI
3. Github Action script
1. 고민해봐야 할 것들
요새 밥도 안 먹고, 잠도 안 자고 하루종일 개발만 하느라 포스팅 수도 확 줄어버렸네.
최근 DB Query 최적화 문제도 그렇고 포스팅 할 게 제법 많아서, 하나씩 정리해둘 생각.
📌 ACG
22번 포트를 자유롭게 두면, 거기만 집중적으로 찔러보고 다니는 매크로에 당할 수 있다.
그래서 보통 개발자가 서버에 접근하는 주요 IP만을 제외하고 모두 막아야 한다.
문제는 Github action의 host를 사용하면 IP 주소를 특정할 수 없다는 점인데,
처음에는 그냥 귀찮아서 포트포워딩 해버리고 해당 port를 전체 개방해버릴 심산이었다.
일단 동작하는 거 확인하고 나중에 바꾸려던 거였는데...
근데 웬걸, 내 거 왜 포트포워딩 설정 안 됨????
온갖 공식 문서랑 블로그 다 뒤져봐도 저기에 포트포워딩 설정 버튼이 있어야 하는데 나만 없었다.
그렇다고 22번 포트를 전체 개방하는 건 진짜 아닌 것 같아서 고민을 많이 했는데, 결과적으로 NCP CLI로 해결했다.
다만 이걸 github action에 적용한다고 살짝 골머리 좀 앓긴 했다.
AWS는 관련 소스가 많은 반면, NCP는 그런 게 없어서 직접 세팅해야 한다.
📌 ip 찾기
ssh를 전부 개방하는 상남자식 CD라면 몰라도, 그게 아닌 이상 ACG에 잠깐 허용 ip를 갱신해야 한다.
문제는 이게 github action의 가상 서버를 사용하다보니 ip 주소가 매번 바뀐다는 이슈가 있는데,
관련 라이브러리가 있어서 쉽게 해결하긴 했다.
다만 0.0.0.0/0 과 같은 포맷을 지켜야 했는데, 라이브러리가 알려주는 정보엔 subnet mask는 포함되어 있지 않았다.
상당히 심란했는데 /32로 고정하니까 그냥 됨..ㅋ
더 쓰려고 보니 위에 저 두 가지 말고는 딱히 이슈가 없었다.
아니, 없진 않았고 그냥 개인적인 이슈라서 고민해봐야 할 거린 아닌 거 같아서 적기가 애매하다.
2. NCP CLI
📌 아이디어
AWS는 조금만 구글링 해봐도 편한 방법들이 너~~무 많으니까 굳이 NCP처럼 노가다를 할 필요가 없다.
여튼 아이디어는 이러하다.
- 실행 중인 가상 서버의 IP를 알아낸다.
- 해당 IP에 대해서 22번 port를 개방하도록 ACG에 CLI 명령어로 추가한다.
- Server에 접근해서 작업 수행
- 끝나면 등록했던 레코드를 삭제한다.
Github Action에서 동작하는 가상 서버의 IP 주소 범위를 특정해서 상시 개방해둘까 고민도 해봤는데,
아무리 찾아도 정확한 정보라고 판단할 수 있는 걸 못 찾아서 포기했다.
📌 AWS CLI를 사용할 수는 없을까?
마치 Object Storage를 S3 다루듯이 aws cli를 사용했던 것처럼, ACG도 비슷한 짓이 가능할까 싶었다.
결론적으로 이 방법은 불가능하다.
📌 NCP CLI 설치
aws 명령어로 안 되길래 포기해야 하나 싶었는데, NCP에서도 CLI를 제공한다. (제공하긴 하는데 뭔가 이 애매함..)
그래서 몇 가지 테스트를 해봤다.
공식 문서에서도 ACG 원격 설정이 가능하다고 하므로 바로 가상 머신 돌려서 Linux 환경으로 돌려봤다.
ncloud vserver addAccessControlGroupInboundRule
--regionCode KR --vpcNo ${VPC_NO} --accessControlGroupNo ${AGC_NO}
--accessControlGroupRuleList "protocolTypeCode='TCP',
ipBlock='***.***.0.0/0', portRange='22'"
대충 아무 IP나 설정해서 보내봤는데, 바로 되는 거 확인.
유일하게 문제였던 NCP CLI 설치파일을 가상환경에 올리는 작업은 wget 명령어로 해결할 수 있었다.
wget https://www.ncloud.com/api/support/download/5/65
unzip 65
./cli_linux
저기서 ncloud로 요청을 보내면 된다.
📌 NCP configure 설정
아무나 ACG 설정을 건드릴 수 있으면 안 되니 configure을 설정해주어야 한다.
문제는 이게 `ncloud configure` 명령을 실행하고 하나하나 사용자가 입력해주어야 한다.
나는 명령어를 그렇게까지 깔쌈하게 다룰 수 있는 능력자가 아니다 보니, 편법을 쓰기로 했다.
ncloud configure 명령으로 생성되는 파일을 그냥 해당 경로에 꽂아버리면 된다.
`ncloud configure` 명령을 실행하고 아무 값이나 넣어보면 홈 경로에 디렉토리가 하나 생기는 것을 확인할 수 있다.
echo -e "[DEFAULT]\nncloud_access_key_id = ${{ secrets.NCP_ACCESS_KEY }}\n
ncloud_secret_access_key = ${{ secrets.NCP_SECRET_KEY }}\n
ncloud_api_url = ${{ secrets.NCP_API_URL }}" >> ~/.ncloud/configure
위 명령어로 configure를 실행하지 않고, 바로 configure 파일을 생성해서 주입해버릴 예정이다.
3. Github Action script
📌 Overview
name: Continuous Deployment
on:
push:
branches: ["develop", "hotfix/86"]
workflow_dispatch:
inputs:
logLevel:
description: "Log level"
required: true
default: "warning"
type: choice
options:
- info
- warning
- error
environment:
description: "Environment"
required: false
type: environment
permissions:
contents: read
jobs:
continuous-deployment:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Setup JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: 'gradle'
- name: Build Gradle
run: |
chmod +x ./gradlew
./gradlew -version
./gradlew bootJar
shell: bash
- name: docker image build & push
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_NICKNAME }}/fitapet:latest .
docker push ${{ secrets.DOCKER_NICKNAME }}/fitapet:latest
- name: Get Github Actions IP
id: ip
uses: haythem/public-ip@v1.2
- name: Setting NCP CLI & Credentials
run: |
cd ~
wget https://www.ncloud.com/api/support/download/5/65
unzip 65
mkdir ~/.ncloud
echo -e "[DEFAULT]\nncloud_access_key_id = ${{ secrets.NCP_ACCESS_KEY }}\nncloud_secret_access_key = ${{ secrets.NCP_SECRET_KEY }}\nncloud_api_url = ${{ secrets.NCP_API_URL }}" >> ~/.ncloud/configure
- name: Add Github Action Ip to Security group
run: |
chmod -R 777 ~/cli_linux
cd ~/cli_linux
./ncloud vserver addAccessControlGroupInboundRule --regionCode KR --vpcNo ${{ secrets.NCP_VPC_NO }} --accessControlGroupNo ${{ secrets.NCP_AGC_NO }} --accessControlGroupRuleList "protocolTypeCode='TCP', ipBlock='${{ steps.ip.outputs.ipv4 }}/32', portRange='${{ secrets.SSH_PORT }}'"
- name: deploy
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
password: ${{ secrets.SSH_PASSWORD }}
username: ${{ secrets.SSH_USERNAME }}
script: |
./start.sh
- name: Remove Github Action Ip to Security group
run: |
chmod -R 777 ~/cli_linux
cd ~/cli_linux
./ncloud vserver removeAccessControlGroupInboundRule --regionCode KR --vpcNo ${{ secrets.NCP_VPC_NO }} --accessControlGroupNo ${{ secrets.NCP_AGC_NO }} --accessControlGroupRuleList "protocolTypeCode='TCP', ipBlock='${{ steps.ip.outputs.ipv4 }}/32', portRange='${{ secrets.SSH_PORT }}'"
어차피 개인 정리용이니까 Github Actions 스크립트에 대한 기초 이해도가 없는 분은
다른 블로그에 설명 아주 잘 되어 있으니, 거길 참고하시는 게 빠릅니다~
📌 Build
- name: Setup JDK 17
uses: actions/setup-java@v3
with:
java-version: '17'
distribution: 'adopt'
cache: 'gradle'
- name: Build Gradle
run: |
chmod +x ./gradlew
./gradlew -version
./gradlew bootJar
shell: bash
- 내 프로젝트에 맞게 JDK 17 버전으로 설치
- Cache도 쓰려고 했는데, 속도 차이 거의 안 나서 쓰나마나
- 빌드하기 전에 gradlew의 권한을 지정해주지 않으면 permission error가 발생한다. (나도 알고 싶지 않았다.)
📌 Docker image build & push
- name: docker image build & push
run: |
docker login -u ${{ secrets.DOCKER_USERNAME }} -p ${{ secrets.DOCKER_PASSWORD }}
docker build -t ${{ secrets.DOCKER_NICKNAME }}/fitapet:latest .
docker push ${{ secrets.DOCKER_NICKNAME }}/fitapet:latest
- docker login 해주고 build한 후에 push하면 끝
📌 현재 가상서버 IP 주소 ACG Inbound 추가
- name: Get Github Actions IP
id: ip
uses: haythem/public-ip@v1.2
- name: Setting NCP CLI & Credentials
run: |
cd ~
wget https://www.ncloud.com/api/support/download/5/65
unzip 65
mkdir ~/.ncloud
echo -e "[DEFAULT]\nncloud_access_key_id = ${{ secrets.NCP_ACCESS_KEY }}\nncloud_secret_access_key = ${{ secrets.NCP_SECRET_KEY }}\nncloud_api_url = ${{ secrets.NCP_API_URL }}" >> ~/.ncloud/configure
- name: Add Github Action Ip to Security group
run: |
chmod -R 777 ~/cli_linux
cd ~/cli_linux
./ncloud vserver addAccessControlGroupInboundRule --regionCode KR --vpcNo ${{ secrets.NCP_VPC_NO }} --accessControlGroupNo ${{ secrets.NCP_AGC_NO }} --accessControlGroupRuleList "protocolTypeCode='TCP', ipBlock='${{ steps.ip.outputs.ipv4 }}/32', portRange='${{ secrets.SSH_PORT }}'"
- `haythem/public-ip@v1.2` 이걸로 ip 주소를 가져오면 되는데, subnet mask 없으면 포맷 안 맞다고 에러뜨니 뒤에 `/32`붙여주면 된다.
- configure 경로 잘못 잡으면 ./ncloud 쓸 때 계속 파일 못 찾아서 해매니까, 그냥 편하게 홈 디렉토리로 잡는 게 가장 편하다.
- cli_linux 하위 모든 파일 권한 설정 해주는 이유는 자꾸 하나씩 권한 문제 나길래, 화나서 전부 풀어버렸다.
📌 Deployment
- name: deploy
uses: appleboy/ssh-action@v0.1.6
with:
host: ${{ secrets.SSH_HOST }}
port: ${{ secrets.SSH_PORT }}
password: ${{ secrets.SSH_PASSWORD }}
username: ${{ secrets.SSH_USERNAME }}
script: |
./start.sh
- 여기서 password 대신 key를 사용하면 private key로 접속하게 된다.
- 나는 계속 에러가 나서 뭔가 했는데, 인증키가 제대로 작동을 안 하는 이슈가 있었는데 지금껏 몰랐다..모르고 그냥 비번치고 잘 쓰고 있었던 거였다.
- 서버 문제라서 나중에 수정하려고 password 인증 방식을 쓰긴 했는데, 유효한 pem키 있는 사람은 그거 그대로 복붙해서 key를 사용하면 된다.
- 참고로 key와 password를 모두 쓰면, 그런 식으로 쓰지 말라고 빨간줄 그어버리면서 job이 끝나버린다.
✒️ 내가 쓰는 shell script
#!/bin/sh
docker-compose down
docker image rm -f $(docker image ls -f reference='jaeseo/*' -q)
docker container rm fitapet-api
docker-compose up -d
- 생각해보니 container rm 명령어는 왜 있는 거지...제외해도 무방
- shell script 안 하고, 위의 action 스크립트에 명령어 줄줄 써도 똑같이 동작한다.
📌 현재 IP 주소 ACG 해제
- name: Remove Github Action Ip to Security group
run: |
chmod -R 777 ~/cli_linux
cd ~/cli_linux
./ncloud vserver removeAccessControlGroupInboundRule --regionCode KR --vpcNo ${{ secrets.NCP_VPC_NO }} --accessControlGroupNo ${{ secrets.NCP_AGC_NO }} --accessControlGroupRuleList "protocolTypeCode='TCP', ipBlock='${{ steps.ip.outputs.ipv4 }}/32', portRange='${{ secrets.SSH_PORT }}'"
- 꼭꼭 풀어주자. 안 그러면 고생한 의미가 없다.
- 이렇게 하면 상시 개방된 ssh 접근도 없고, 매우 깔끔하게 CD 파이프라인을 구축할 수 있다.