-
Notifications
You must be signed in to change notification settings - Fork 5
219 lines (194 loc) · 9.59 KB
/
cd.yml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
name: kernelsquare prod deploy
on:
pull_request:
types:
- closed
permissions:
contents: read
jobs:
if-merge:
if: github.event.pull_request.merged == true && github.event.pull_request.base.ref == 'main'
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
with:
ref: ${{ github.event.pull_request.head.sha }}
- name: Set up JDK 21
uses: actions/setup-java@v3
with:
java-version: '21'
distribution: 'temurin'
- name: Set up DataHub with Docker
run: |
echo "${{ secrets.CI_DOCKER_COMPOSE }}" > docker-compose.yml
docker-compose up -d
docker ps
- name: Set up member-api application-common.yml
uses: microsoft/variable-substitution@v1
with:
files: ./member-api/src/main/resources/application-common.yml
env:
jasypt.password: ${{ secrets.JASYPT_PASSWORD }}
- name: Build member-api with Gradle
run : |
cd member-api
chmod +x ./gradlew
./gradlew build
- name: Login to DockerHub
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Build member-api with Docker
run : docker build -t ${{ secrets.DOCKERHUB_USERNAME }}/kernelsquare ./member-api
- name: member-api Docker push
run : docker push ${{ secrets.DOCKERHUB_USERNAME }}/kernelsquare:latest
deploy:
needs: if-merge
runs-on: ubuntu-latest
steps:
# 깃허브 액션 러너의 아이피를 얻어온다.
- name: Get Github action IP
id: ip
uses: haythem/[email protected]
# 환경변수 설정.
- name: Setting environment variables
run: |
echo "AWS_DEFAULT_REGION=ap-northeast-2" >> $GITHUB_ENV
# AWS 설정
- name: Configure AWS credentials
uses: aws-actions/configure-aws-credentials@v1
with:
# 아이엠 키 설정, 인바운드 룰 수정을 위해 설정합니다.
# IAM 설정하실 때, AWSEC2FullAccess 권한을 부여해주세요.
# 더 자세한 사항은 제 블로그 이전 Github Actions 게시물을 참고해주세요.
aws-access-key-id: ${{ secrets.AWS_IAM_ACCESS_KEY_ID }}
aws-secret-access-key: ${{ secrets.AWS_IAM_SECRET_KEY }}
aws-region: ${{ env.AWS_DEFAULT_REGION }}
# 깃허브 액션의 아이피를 인바운드 룰에 임시 등록
- name: Add Github Actions IP to Security group
run: |
aws ec2 authorize-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 authorize-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 80 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 authorize-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 443 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 authorize-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 8501 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 authorize-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 8502 --cidr ${{ steps.ip.outputs.ipv4 }}/32
# 블루/그린 헬스체크로 변수 초기화
- name: Blue/Green health check
run: |
echo "INSTANCE_ENV=$(curl -s "https://${{ secrets.NGINX_IP }}/environment")" >> $GITHUB_ENV
# 헬스 체크를 통한 인스턴스 체크, 어떤 환경이 운영중인가?
- name: Set target ip
# prod1, prod2 둘 다 검사해야 하지만, 현재는 prod1만 검사
# CURRENT_UPSTREAM : env로 요청 보내서 blue 인지, green인지 알아옴. 이걸 curl로 해서 변수로 만든다. 즉 blue,green,오류 중에 하나
# CURRENT_IP : 만약 환경이 blue라면 blue 인스턴스의 prod1의 ip(111.111.111.111:8080)가 들어감
# STOPPED_IP : 만약 환경이 blue라면 멈춰있는 green의 prod1 ip가 들어감.
# TARGET_UPSTREAM : 바꿀 env
run: |
CURRENT_UPSTREAM=$(curl -s "https://${{ secrets.NGINX_IP }}/environment")
echo $CURRENT_UPSTREAM
if [ $CURRENT_UPSTREAM = "blue" ]; then
echo "CURRENT_IP=${{ secrets.BLUE_IP }}" >> $GITHUB_ENV
echo "STOPPED_IP=${{ secrets.GREEN_IP }}" >> $GITHUB_ENV
echo "TARGET_UPSTREAM=green" >> $GITHUB_ENV
echo "blue"
elif [ $CURRENT_UPSTREAM = "green" ]; then
echo "CURRENT_IP=${{ secrets.GREEN_IP }}" >> $GITHUB_ENV
echo "STOPPED_IP=${{ secrets.BLUE_IP }}" >> $GITHUB_ENV
echo "TARGET_UPSTREAM=blue" >> $GITHUB_ENV
echo "green"
else
echo "error"
exit 1
fi
# 멈춰있는 서버에 있는 도커 컴포즈 실행, 혹시 실행되고 있는 인스턴스가 있을 수 있으므로, 추후에 중단하는 작업도 추가해야함.
- name: Execute Server Docker compose
uses: appleboy/ssh-action@master
with:
username: ${{ secrets.SSH_USER }}
host: ${{ env.STOPPED_IP }}
# key: ${{ secrets.BLUE_SSH_KEY }}
password: ${{ secrets.SSH_PASSWORD }}
script_stop: true
script: |
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/kernelsquare
sudo docker-compose up -d
if: ${{ env.TARGET_UPSTREAM == 'blue' }}
- name: Execute Server Docker compose
uses: appleboy/ssh-action@master
with:
username: ${{ secrets.SSH_USER }}
host: ${{ env.STOPPED_IP }}
key: ${{ secrets.GREEN_SSH_KEY }}
script_stop: true
script: |
sudo docker pull ${{ secrets.DOCKERHUB_USERNAME }}/kernelsquare
sudo docker-compose up -d
if: ${{ env.TARGET_UPSTREAM == 'green' }}
- name: Check the deployed prod1 service URL
uses: jtalk/url-health-check-action@v3
with:
url: http://${{ env.STOPPED_IP }}:8501/environment
# 총 5번 하는데, 30초의 간격을 두고함. 이때까지 응답이 정상이 아니라면 배포 실패
max-attempts: 5 # Optional, defaults to 1
retry-delay: 30s # Optional, only applicable to max-attempts > 1
- name: Check the deployed prod2 service URL
uses: jtalk/url-health-check-action@v3
with:
url: http://${{ env.STOPPED_IP }}:8502/environment
# 총 5번 하는데, 30초의 간격을 두고함. 이때까지 응답이 정상이 아니라면 배포 실패
max-attempts: 5 # Optional, defaults to 1
retry-delay: 30s # Optional, only applicable to max-attempts > 1
# 엔진엑스의 프록시 변경
- name: Change nginx upstream
uses: appleboy/ssh-action@master
with:
username: ${{ secrets.SSH_USER }}
host: ${{ secrets.NGINX_HOST }}
# key: ${{ secrets.NGINX_SSH_KEY }}
password: ${{ secrets.SSH_PASSWORD }}
script_stop: true
# 도커로 들어가서 service_env를 바꿔주고 reload
# 여기서 -i가 아닌 -it로 진행하면 오류가 발생하고, -c가 없으면 도커가 아닌 호스트에서 경로를 찾는다. 주의
script: |
sudo docker exec -i webserver bash -c 'echo "set \$service_env ${{ env.TARGET_UPSTREAM }};" > /etc/nginx/conf.d/service-env.inc && nginx -s reload'
# 기존 인스턴스 중단
- name: Terminate prev instance
uses: appleboy/ssh-action@master
with:
username: ${{ secrets.SSH_USER }}
host: ${{ env.CURRENT_IP }}
# key: ${{ secrets.BLUE_SSH_KEY }}
password: ${{ secrets.SSH_PASSWORD }}
script_stop: true
script: |
sudo docker stop prod1
sudo docker stop prod2
sudo docker rm prod1
sudo docker rm prod2
if: ${{ env.TARGET_UPSTREAM == 'green' }}
# 기존 인스턴스 중단
- name: Terminate prev instance
uses: appleboy/ssh-action@master
with:
username: ${{ secrets.SSH_USER }}
host: ${{ env.CURRENT_IP }}
key: ${{ secrets.GREEN_SSH_KEY }}
script_stop: true
script: |
sudo docker stop prod1
sudo docker stop prod2
sudo docker rm prod1
sudo docker rm prod2
if: ${{ env.TARGET_UPSTREAM == 'blue' }}
# 깃허브 러너 아이피를 인바운드 룰에서 제거
- name: Remove Github Actions IP from security group
# if: always()를 해놓으면 무조건 실행됨. 따라서 위에서 deploy가 실패해도 인바운드 룰로 열어놨던 ip를 모두 닫음.
if: always()
run: |
aws ec2 revoke-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 22 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 revoke-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 80 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 revoke-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 443 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 revoke-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 8501 --cidr ${{ steps.ip.outputs.ipv4 }}/32
aws ec2 revoke-security-group-ingress --group-name ${{ secrets.AWS_SG_NAME }} --protocol tcp --port 8502 --cidr ${{ steps.ip.outputs.ipv4 }}/32