DevOps/CI&CD

๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์‹ค์Šต ๊ธฐ๋ณธ ์…‹ํŒ… (Github Actions, Nginx ํ™œ์šฉ)

ํ”„๋กœ๊ทธ๋ž˜๋จธ ์˜ค์›” 2024. 8. 13.

๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ด๋ก ์— ๋Œ€ํ•ด์„œ ํ•™์Šต์„ ํ•˜์˜€๊ณ , ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ๋ฅผ ์ด์   ์‹ค์Šตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค. 

์ด๋ก ์— ๊ด€ํ•ด์„œ๋Š” ์•„๋ž˜ ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ  ํ•ด์ฃผ์„ธ์š”.
https://programmer-may.tistory.com/209

 

๋ฌด์ค‘๋‹จ ๋ฐฐํฌ(Zero-downtime Deployment) ์ „๋žต

๐Ÿšฉ๊ฐœ์š”๋‹ค์šด ํƒ€์ž„(Downtime)์€ ์‹œ์Šคํ…œ, ์„œ๋ฒ„, ๋„คํŠธ์›Œํฌ, ์• ํ”Œ๋ฆฌ์ผ€์ด์…˜ ๋˜๋Š” ์„œ๋น„์Šค๊ฐ€ ์ •์ƒ์ ์œผ๋กœ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ์‹œ๊ฐ„์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์‚ฌ์šฉ์ž๊ฐ€ ํ•ด๋‹น ์‹œ์Šคํ…œ์ด๋‚˜ ์„œ๋น„์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋Š” ์ƒํƒœ๋ฅผ

programmer-may.tistory.com

 

๋ณธ ์‹ค์Šต์—์„œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ง„ํ–‰ ๊ณผ์ •

์ œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์‹ค์Šต์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ง„ํ–‰๋์Šต๋‹ˆ๋‹ค. ์ตœ์†Œํ•œ์˜ ๊ธฐ์ˆ ๋กœ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ๋ฅผ ์ฒ˜์Œ ๋„์ž…ํ•ด๋ณด๋Š” ์‹ค์Šต์ž์—๊ฒŒ ๋ถ€๋‹ด์—†์ด ๋‹ค๊ฐ€๊ฐˆ ์ˆ˜ ์žˆ๊ฒŒ ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋„์ปค๋ฅผ ํ•จ๊ป˜ํ•ด์„œ ๋„์ปค ์ด๋ฏธ์ง€๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜๋„ ์žˆ์ง€๋งŒ, ๋Ÿฌ๋‹ ์ปค๋ธŒ๋ฅผ ์ตœ์†Œํ•œ์œผ๋กœ ํ•˜๊ฒŒ ํ•˜๋Š” ๊ฒƒ์ด ๋ชฉํ‘œ์˜€์Šต๋‹ˆ๋‹ค. ์–ด๋ ค์›€์€ ์ตœ๋Œ€ํ•œ ๋œ๋˜ ํƒ„ํƒ„ํ•œ์€ ๊ฐ–๋„๋ก ์ €์˜ ๊ธฐ์ค€์—์„œ ์ตœ์†Œํ•œ์œผ๋กœ ํ•„์š”ํ•œ ๊ธฐ์ˆ ๋“ค์„ ์ ์šฉํ•ด ๋ณด์•˜์Šต๋‹ˆ๋‹ค.

 

 

 

1. Github Actions : ์•ก์…˜์Šค๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ž๋™ ๋ฐฐํฌ ํŒŒ์ดํ”„๋ผ์ธ์„ ๊ตฌ์ถ•ํ•˜์˜€๊ณ , cicd๋ฅผ ํ†ตํ•ด์„œ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ๋„์ž… ์ „์—” ์ง์ ‘ jar ํŒŒ์ผ์„ ๋””๋ ‰ํ† ๋ฆฌ๋กœ ์˜ฎ๊ธฐ๊ณ , jar ํŒŒ์ผ์„ ์‹คํ–‰ ์‹œ์ผฐ์Šต๋‹ˆ๋‹ค. ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ๋„์ž… ํ›„์—” AWS EC2 ํŠน์ • ๋””๋ ‰ํ† ๋ฆฌ ์•ˆ์— deploy.sh ์‰˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๋‘์–ด Github Actions ์„ ํ†ตํ•ด cd yml ํŒŒ์ผ์—์„œ ๋ช…๋ น์–ด๋กœ ๊ทธ ์‰˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ์‹คํ–‰ํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

2. Sell Script : ์‰˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ํ™œ์šฉํ•˜์—ฌ, ๋ฐฐํฌ ๋ฐ ํ—ฌ์Šค ์ฒดํฌ๋ฅผ ์ง„ํ–‰ํ•˜๊ณ , ๋กค๋ฐฑ ๋˜ํ•œ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค. ๋˜ํ•œ ์—”์ง์—”์Šค์˜ ์„ค์ • ํŒŒ์ผ์„ ๋™์ ์œผ๋กœ ๋ฐ”๊พธ์–ด ํŠธ๋ž˜ํ”ฝ์„ ์‹  ๋ฒ„์ „์ด ์‹คํ–‰๋œ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ ๋ฐ”๊พธ๊ฑฐ๋‚˜ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ์„ ์„ค์ •์„ ๋™์ ์œผ๋กœ ๋ณ€ํ™”์‹œ์ผœ์คฌ์Šต๋‹ˆ๋‹ค.

 

3. Nginx : ์—”์ง„์—‘์Šค์˜ /etc/nginx/sites-available/default ํŒŒ์ผ์„ ๋™์ ์œผ๋กœ ๋ณ€ํ™”์‹œ์ผœ ๋กœ๋“œ ๋ฐธ๋Ÿฐ์‹ฑ์„ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ „๋žต์— ๋งž๊ฒŒ ๋ฐ”๊พธ์—ˆ์Šต๋‹ˆ๋‹ค. ์—”์ง„์—‘์Šค์— SSL Termination ๊นŒ์ง€ ์ ์šฉํ•˜๋ ค๋ฉด ๋„๋ฉ”์ธ๋„ ์žˆ์–ด์•ผ ํ•˜๊ณ , ๊ณผ์ •์ด ๋ณต์žกํ•˜์—ฌ HTTPS ๊ฐ€ ์•„๋‹Œ HTTP ์š”์ฒญ์„ ๊ธฐ์ค€์œผ๋กœ๋งŒ ์ง„ํ–‰ํ•˜์˜€์Šต๋‹ˆ๋‹ค. Nginx ์—์„œ SSL Termination ๊นŒ์ง€ ์ง„ํ–‰ํ•˜๊ณ  ์‹ถ์œผ์‹  ๋ถ„์€ ์ œ ๋ธ”๋กœ๊ทธ์— Nginx ๊ตฌ์ถ• ํฌ์ŠคํŒ…์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”!

 

4. Spring Boot : ๊ธฐ๋ณธ์ ์œผ๋กœ 8081 ํฌํŠธ์—” ๊ตฌ๋ฒ„์ „์ด, 8082ํฌํŠธ์—” ์‹ ๋ฒ„์ „ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜ ๊ตฌ๋™ ๋˜๊ณ  ์„ค์ • ํ–ˆ๊ณ , ๋กค๋ง ์ „๋žต ๊ฒฝ์šฐ ๋‘ ํฌํŠธ ๋ชจ๋‘์—์„œ ๊ตฌ ๋ฒ„์ „, ์‹  ๋ฒ„์ „์ด ๋Œ์•„๊ฐ€๊ฒŒ๋” ํ–ˆ์Šต๋‹ˆ๋‹ค.
ํ—ฌ์Šค ์ฒดํฌ๋กœ๋Š” Spring actuator ์˜์กด์„ฑ์„ ๋ฐ›์•„, {http:// EC2 ํผ๋ธ”๋ฆญ IP }:{ํ—ฌ์Šค ์ฒดํฌ ํ•˜๋ ค๋Š” ํฌํŠธ๋ฒˆํ˜ธ}/autator/health ๋ฅผ ํ†ตํ•ด ์‘๋‹ต์ด ์ž˜ ์˜ค๋Š” ์ง€ ํ™•์ธํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

5. Termius : SSH Client ๋กœ๋Š” Termius ๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์›๋ž˜๋Š” MobaXterm ์„ ์‚ฌ์šฉํ–ˆ์ง€๋งŒ, ์ „์ž์ฑ…์„ ์ฝ๋Š” ๋…์ž์˜ ์ปดํ“จํ„ฐ OS ๊ฐ€ Window ๊ฐ€ ์•„๋‹Œ ๊ฒฝ์šฐ์—” ์‚ฌ์šฉ์ด ๋ถˆ๊ฐ€๋Šฅ ํ•˜๊ธฐ์—, macOS, Window ๋‘๊ฐ€์ง€ OS ๋ชจ๋‘ ์ง€์›ํ•˜๋Š” ํˆด์„ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.

Termius ๋ฅผ ํ™œ์šฉํ•˜์—ฌ CLI ๋กœ JDK ์™€ ์—”์ง„์—‘์Šค๋ฅผ ์„ค์น˜ํ•˜๊ณ  ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ณ , deploy.sh ํŒŒ์ผ๋„ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

6. Apache JMeter : ํ…Œ์ŠคํŒ… ํˆด๋กœ๋Š” ์•„ํŒŒ์น˜ ์ œ์ด๋ฏธํ„ฐ๋ฅผ ํ™œ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. ์ €์—๊ฒŒ ์ต์ˆ™ํ•˜๊ธฐ๋„ ํ•˜๊ณ , simple http request ํ…œํ”Œ๋ฆฟ๋„ ์ง€์›ํ•ด์ฃผ๊ธฐ์— ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค. {ํ˜ธ์ŠคํŠธ ์ฃผ์†Œ}/hello ์š”์ฒญ์„ ์ง€์†์ ์œผ๋กœ ๋ณด๋‚ด์–ด ์‘๋‹ต๊ฐ’์„ ํ™•์ธ ํ•˜์—ฌ, ์ œ๋Œ€๋กœ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ๊ฐ€ ๋‹ค์šด ํƒ€์ž„ ์—†์ด ์ง„ํ–‰์ด ๋๋Š”์ง€ ํ™•์ธํ•˜์˜€์Šต๋‹ˆ๋‹ค. ํŠนํžˆ๋‚˜ ๋กค๋ง ์ „๋žต์ด๋‚˜ ์นด๋‚˜๋ฆฌ ์ „๋žต์€ ํŠธ๋ž˜ํ”ฝ์„ ๋™์ ์œผ๋กœ ๋ฐ”๊พธ๋Š” ๋ถ€๋ถ„์ด ํฌ๊ธฐ์— ์‹ค์‹œ๊ฐ„์œผ๋กœ ์–ด๋”” ํฌํŠธ์—” ํŠธ๋ž˜ํ”ฝ์ด ์•ˆ๊ฐ€๊ณ  ๊ฐ€๋Š”์ง€๋„ ํ™•์ธ์ด ๊ฐ€๋Šฅํ–ˆ์Šต๋‹ˆ๋‹ค.

 

7. Postman : ์•„ํŒŒ์น˜ ์ œ์ด๋ฏธํ„ฐ๋กœ ์š”์ฒญ์— ๋Œ€ํ•œ ์‘๋‹ต์„ ๊ณ„์† ํ™•์ธํ–ˆ๋‹ค๋ฉด, ํฌ์ŠคํŠธ๋งจ์„ ์ด์šฉํ•ด์„œ๋Š” ๋กœ์ปฌ์—์„œ ํ—ฌ์Šค ์ฒดํฌ๋ฅผ ์ง„ํ–‰ ํ–ˆ์Šต๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ๊ฐ€ ์ด๋ฃจ์–ด์ง€๊ณ ๋‚˜์„œ, ๊ตฌ๋ฒ„์ „์ด ์žˆ๋˜ ํฌํŠธ์˜ ํ”„๋กœ์„ธ์Šค๋Š” kill ๋˜์–ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ํ—ฌ์Šค ์ฒดํฌ๋ฅผ ํ•ด๋„ ์ปค๋„ฅ์…˜ ์—๋Ÿฌ๊ฐ€ ์ƒ๊ฒจ์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ๊ฐ€ ์ž˜ ์ด๋ค„์กŒ๋Š”์ง€ ๋กœ์ปฌ์—์„œ ํ™•์ธ ์šฉ์œผ๋กœ ํฌ์ŠคํŠธ๋งจ์„ ์‚ฌ์šฉํ–ˆ๊ณ ,

{ http:// EC2 ํผ๋ธ”๋ฆญ IP }:{๊ตฌ๋ฒ„์ „์˜ jar ๊ฐ€ ์‹คํ–‰๋œ ํ”„๋กœ์„ธ์Šค์˜ ํฌํŠธ๋ฒˆํ˜ธ}/autator/health ํ†ตํ•˜์—ฌ ์š”์ฒญ์ด ๊ฐ€๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์—๋Ÿฌ๊ฐ€ ์ž˜ ์˜ค๋Š”์ง€ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.

 

์‹ค์Šต ๋ธŒ๋žœ์น˜ ์ „๋žต

์‹ค์Šต ๋ธŒ๋žœ์น˜ ์ „๋žต์€ ์•„๋ž˜ ๊ทธ๋ฆผ์œผ๋กœ ์ •๋ฆฌํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

 

ver1์€ ๊ฐ๊ฐ์˜ ๋ธŒ๋žœ์น˜์˜ ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ ์šฉ ์ „ ๋ฐฐํฌ ํ™˜๊ฒฝ์„ ๊ตฌ์ถ•ํ•œ ๊ฒƒ์ด๊ณ , ver2 ๋Š” ๊ฐ๊ฐ์˜ ๋ธŒ๋žœ์น˜์— ๋งž๋Š” ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์ „๋žต์„ ์ ์šฉํ•œ ๋ธŒ๋žœ์น˜์ž…๋‹ˆ๋‹ค.

bluegreen, rolling, canary ๋ธŒ๋žœ์น˜๋Š” ๊ฐ๊ฐ push ํŠธ๋ฆฌ๊ฑฐ๊ฐ€ ์ •ํ•ด์ ธ ์žˆ์–ด ver1 ๋˜๋Š” ver2 ์„ ํ’€๋ฆฌํ€˜์ŠคํŠธ ๋ณด๋‚ด๊ณ  ํ•ด๋‹น ๋ธŒ๋žœ์น˜์— merge ํ•˜๋ฉด Github Actions ๊ฐ€ ์‹คํ–‰๋˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

on:
  push:
    branches:
      - [๊ฐ๊ฐ์˜ ๋ธŒ๋žœ์น˜]

 

์‹ค์Šต ์ „ ์…‹ํŒ…

์‹ค์Šต์„ ๋”ฐ๋ผํ•˜์‹œ๊ธฐ ์ „์— ์…‹ํŒ…์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

1. ํ™˜๊ฒฝ ์…‹ํŒ…

๋จผ์ € EC2์— ์›๊ฒฉ ์ ‘์†์„ ํ•˜์—ฌ JDK17 ๊ณผ Nginx ๋ฅผ ์„ค์น˜ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

Termius ๋ฅผ ํ†ตํ•ด ์ง„ํ–‰ ํ•  ๊ฒƒ์ธ๋ฐ, Termius ์—์„œ EC2 ์›๊ฒฉ ์ ‘์†์€ ์•„๋ž˜ ๋ธ”๋กœ๊ทธ ํฌ์ŠคํŒ…์— ์ž์„ธํ•˜๊ฒŒ ์ •๋ฆฌ ํ•ด๋‘์—ˆ์Šต๋‹ˆ๋‹ค.

https://programmer-may.tistory.com/212

 

Termius ๋‹ค์šด๋กœ๋“œ ๋ฐ ์‹คํ–‰, EC2 ์ ‘์†

๊ฐœ์š”์›๊ฒฉ ๋ฐ์Šคํฌํ†ฑ ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์œผ๋กœ MobaXterm ์„ ์ž˜ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์—ˆ๋Š”๋ฐ, ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ์‹ค์Šต์„ ํ•˜๊ธฐ ์œ„ํ•ด์„œ ํŒ€์›๋“ค๊ณผ ๊ฐ™์€ ํˆด์„ ๋ฐ”๊ฟ”์•ผ ํ–ˆ๋‹ค.Telnet, SSH ์ ‘์†์„ ์œ„ํ•ด PuTTY๋‚˜ XShell์„ ๊น”๊ณ , FTP/SFTP์ ‘์†

programmer-may.tistory.com

 

์ ‘์†์„ ํ•œ ๋’ค CLI ์— ๋ช…๋ น์–ด๋ฅผ ์ž…๋ ฅํ•˜์—ฌ ํ•„์š”ํ•œ ํŒŒ์ผ์„ ๋‹ค์šด์„ ๋ฐ›์•„ ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋จผ์ € ์—…๋ฐ์ดํŠธ๋ฅผ ํ•˜๊ธฐ ์œ„ํ•ด apt update๋ฅผ ์ž…๋ ฅํ•ด์ค๋‹ˆ๋‹ค.

$ sudo apt update

 

JDK 17 ์„ค์น˜, ์ค‘๊ฐ„์— ๋™์˜ ๊ตฌํ•˜๋Š” ๊ฑด ๋””์Šคํฌ๋ฅผ ์–ผ๋งŒํผ ์ฐจ์ง€ํ•˜๋Š”๋ฐ ์„ค์น˜ ํ•  ๊ฒƒ์ธ๊ฐ€์— ๊ด€ํ•œ ๊ฒƒ์ด๋‹ˆ y ๋ฅผ ์ž…๋ ฅํ•ด์ค๋‹ˆ๋‹ค.

$ sudo apt install openjdk-17-jdk

 

JDK๊ฐ€ ์ž˜ ์„ค์น˜ ๋˜์—ˆ๋Š”์ง€ ๋ฒ„์ „ ํ™•์ธ

$ java -version

์ด๋ ‡๊ฒŒ 17.xxx ๋กœ ๋ฒ„์ „์ด ์ž˜ ๋‚˜์˜ค๋ฉด ์ž˜ ์„ค์น˜ ๋œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

Nginx ์„ค์น˜

$ sudo apt install nginx
$ nginx -v

์—”์ง„์—‘์Šค์˜ ๋ฒ„์ „์„ ํ™•์ธํ•˜์—ฌ ์ž˜ ์„ค์น˜ ๋˜์–ด ์žˆ๋Š”์ง€ ํ™•์ธํ•ด๋ด…๋‹ˆ๋‹ค.

 

 

์„ค์ • ํŒŒ์ผ์„ ์ผœ์„œ ์„ค์ • ํŒŒ์ผ ์˜ˆ์‹œ๋ฅผ ํ™•์ธํ•ด ๋ด…๋‹ˆ๋‹ค.

$ sudo nano /etc/nginx/sites-available/default

 

๋ง‰๋Œ€ํ•œ ์ฃผ์„๋ฌธ์œผ๋กœ ์„ค์ •ํŒŒ์ผ ์˜ˆ์‹œ์™€ ์„ค๋ช…์ด ์žˆ๋Š” ํŒŒ์ผ์ด ์ผœ์กŒ๋‹ค๋ฉด, ์ œ๋Œ€๋กœ ์„ค์น˜๊ฐ€ ๋œ ๊ฒƒ์ด๊ณ , ํ…… ๋น„์–ด์žˆ๊ฑฐ๋‚˜ ๊ฒฝ๋กœ๋ฅผ ์ฐพ์„ ์ˆ˜๊ฐ€ ์—†๋‹ค๊ณ  ๋‚˜ํƒ€๋‚˜๋ฉด ๊ฒฝ๋กœ๋ฅผ ์ž˜๋ชป ๊ธฐ์ž…ํ•œ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

ctrl +k ๋ฅผ ๋ˆŒ๋Ÿฌ ์ฃผ์„๋ฌธ๊ณผ ์˜ˆ์‹œ๋ฅผ ๋ชจ๋‘ ๋‚ ๋ ค ๋ฒ„๋ฆฌ๊ณ  ๊ธฐ๋ณธ nginx ์„ค์ • ํŒŒ์ผ์„ ๋ณต๋ถ™ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

๊ฐ๊ฐ ์ „๋žต๋งˆ๋‹ค ์ดˆ๊ธฐ ์—”์ง„์—‘์Šค ์„ค์ •์ด ๋‹ค๋ฅธ๋ฐ, ๋ธ”๋ฃจ ๊ทธ๋ฆฐ ๊ธฐ์ค€์œผ๋กœ ๋จผ์ € ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

server {
    listen 80;
    server_name _;

    location / {
        proxy_pass http://127.0.0.1:8081;  # ์ด ๋ถ€๋ถ„์€ deploy.sh์—์„œ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝ๋ฉ๋‹ˆ๋‹ค.
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}


Termius ๊ธฐ์ค€ ๋ณต์‚ฌ๋Š” ctrl + shift + c ์ด๊ณ  ๋ถ™์—ฌ๋„ฃ๊ธฐ๋Š” ctrl + shift + v ์ž…๋‹ˆ๋‹ค.
nano ๋ช…๋ น์–ด๋กœ ํ‚จ ํŽธ์ง‘๊ธฐ์— ์ €์žฅ์„ ์œ„ํ•ด์„  ctrl + o ๋ฅผ ์ž…๋ ฅํ•˜๊ณ  ์—”ํ„ฐ๋ฅผ ๋ˆŒ๋Ÿฌ์ฃผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ๋‚˜๊ฐ€๊ธฐ๋ฅผ ํ•˜๋ ค๋ฉด ctrl + x ๋ฅผ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

์„ค์ • ํŒŒ์ผ์ด ์ž˜ ์ €์žฅํ–ˆ๋Š”์ง€ ์œ„์— ๋ช…๋ น์–ด๋ฅผ ๋‹ค์‹œ ํ•œ๋ฒˆ ์ž…๋ ฅํ•˜์—ฌ ํ™•์ธ ํ›„ ๋‚˜๊ฐ€์ค๋‹ˆ๋‹ค.

 

ํ…Œ์ŠคํŠธ๋ฅผ ํ•˜์—ฌ ์—”์ง„์—‘์Šค ์„ค์ •์ด ๋ฌธ์ œ๊ฐ€ ์—†๋Š”์ง€ ํ™•์ธํ•ด์ค๋‹ˆ๋‹ค.

$ sudo nginx -t

๋‹ค์Œ๊ณผ ๊ฐ™์ด ok๊ฐ€ ๋‚˜์˜ค๋ฉด ๋ณ„ ๋ฌธ์ œ ์—†๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์„ค์ •์„ ํ•ด์ฃผ์—ˆ๊ธฐ์— ์—”์ง„์—‘์Šค๋ฅผ ์‹คํ–‰ํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo systemctl start nginx

์—”์ง„์—‘์Šค์˜ ์ƒํƒœ๋ฅผ ํ™•์ธํ•ด์ฃผ๊ฒ ์Šต๋‹ˆ๋‹ค.

$ sudo systemctl status nginx

์œ„์™€ ๊ฐ™์ด active (running) ์ด ๋˜์–ด์žˆ์œผ๋ฉด ์ •์ƒ ์‹คํ–‰์ค‘์ธ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด์   jar ํŒŒ์ผ์„ scp ํ•  ๋””๋ ‰ํ† ๋ฆฌ์™€ ๊ฐ๊ฐ ์ „๋žต์— ๋งž๋Š” deploy.sh ๋ฅผ ์‹คํ–‰ํ•˜๊ธฐ ์œ„ํ•œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค๊ฒ ์Šต๋‹ˆ๋‹ค.

๋จผ์ € ๋ฃจํŠธ ๊ฒฝ๋กœ์—์„œ ๋””๋ ‰ํ† ๋ฆฌ๋ฅผ ๋งŒ๋“ค ๊ฒƒ์ž…๋‹ˆ๋‹ค. ๋ฃจํŠธ๋กœ ์˜ค๋ ค๋ฉด cd ~ ์ž…๋ ฅํ•˜๋ฉด ๋ฃจํŠธ๋กœ ์™€์ง‘๋‹ˆ๋‹ค.

$ mkdir cicd

cicd ํด๋”๋ฅผ ๋งŒ๋“ค์–ด์„œ ์•ž์œผ๋กœ ์ €ํฌ๊ฐ€ ๋งŒ๋“  ์–ดํ”Œ๋ฆฌ์ผ€์ด์…˜์˜ ์‹  ๋ฒ„์ „์˜ jar ํŒŒ์ผ์€ ์ด๊ณณ์— ๋‘˜๊ฒ๋‹ˆ๋‹ค.

 

cicd ๋””๋ ‰ํ† ๋ฆฌ๋กœ ๊ฒฝ๋กœ๋ฅผ ์ด๋™ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

$ cd cicd

 

์ด๋™ํ›„ ๋‹ค์Œ ๋ช…๋ น์–ด๋ฅผ ํ•œ์ค„ ์”ฉ ์ž…๋ ฅํ•ฉ๋‹ˆ๋‹ค.

$ mkdir old_build
$ mkdir bluegreen
$ mkdir rolling
$ mkdir canary

 

cicd ๋””๋ ‰ํ† ๋ฆฌ ์•„๋ž˜์— old_build ๋””๋ ‰ํ† ๋ฆฌ์—๋Š” ๋ฐฐํฌํ›„ ๊ตฌ๋ฒ„์ „์˜ jar ํŒŒ์ผ์ด ์ด๊ณณ์œผ๋กœ ์˜ฎ๊ฒจ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

๊ทธ๋ฆฌ๊ณ  ๊ฐ๊ฐ์˜ ๋ฐฐํฌ ์ „๋žต์— ๋งž๋Š” deploy.sh ์‰˜ ์Šคํฌ๋ฆฝํŠธ๋ฅผ ๊ฐ๊ฐ ๋ฐฐํฌ์ „๋žต ๋””๋ ‰ํ† ๋ฆฌ ์•„๋ž˜์— ์ƒ์„ฑํ•  ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

2. ํ”„๋กœ์ ํŠธ ์…‹ํŒ…

ํ”„๋กœ์ ํŠธ์˜ cd yml ํŒŒ์ผ์„ ๋ณด๋ฉด Repository Secrets ๋ฅผ ๋‘์–ด ๋™์ ์œผ๋กœ ๋ฐ”์ธ๋”ฉํ•˜์—ฌ ๋ฐฐํฌํ•˜๋Š” ๊ฑธ ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

๊ฐœ์ธ์ ์ธ ์ •๋ณด๊ฐ€ ๋“ค์–ด๊ฐ€๊ธฐ์— ๊นƒํ—ˆ๋ธŒ์— ์˜คํ”ˆ๋œ ๊ณต๊ฐ„์— ์ €์žฅํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•ด Secrets ๋งŒ๋“ค์–ด์„œ ๊ด€๋ฆฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

์ด 4๊ฐ€์ง€๋ฅผ ๋งŒ๋“ค๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

 

์ž์‹ ์˜ EC2์˜ pem Key ๋ฅผ ์—ด์–ด ๋‚ด์šฉ์„ ์ „์ฒด ๋ณต๋ถ™ ํ•ด์ค๋‹ˆ๋‹ค. ๋งŒ์•ฝ OpenSSH  ํ‚ค๊ฐ€ ์•„๋‹ˆ๋ผ๋ฉด ๋ณ€ํ™˜ํ•ด์•ผํ•˜๋Š”๋ฐ, ๋ณ€ํ™˜ํ•˜๋Š” ๊ณผ์ •์€ ์ œ ๋ธ”๋กœ๊ทธ์˜ ๋‹ค๋ฅธ ๊ธ€์„ ์ฐธ๊ณ ํ•ด์ฃผ์„ธ์š”.

 

Name์— SSH_PRIVATE_KEY ๋ฅผ ์ ๊ณ  ๋ถ™์–ด ๋„ฃ์–ด์ค๋‹ˆ๋‹ค.

์ƒ์„ฑํ•œ ๋’ค ๋‹ค์Œ๋„ ๋˜‘๊ฐ™์ด ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

 

APPLICATION_YML

management:
  endpoints:
    web:
      exposure:
        include: health,info
  endpoint:
    health:
      show-details: always

 

SERVER_IP

์ž์‹ ์˜ EC2์˜ ํผ๋ธ”๋ฆญ IP ์ฃผ์†Œ ๋˜๋Š” ํผ๋ธ”๋ฆญ DNS ์ฃผ์†Œ

 

SERVER_USERNAME

ubuntu

SERVER_USERNAME์˜ ๊ฒฝ์šฐ EC2 AMI ์˜ OS ๋งˆ๋‹ค ๊ฐ๊ฐ ๋‹ค๋ฅผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ €๋Š” EC2์˜ AMI ๋ฅผ ์šฐ๋ถ„ํˆฌ๋กœ ํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์— username ์ด ubuntu ์ž…๋‹ˆ๋‹ค. ์ž์‹ ์—๊ฒŒ ๋งž๋Š” ๊ฒƒ์„ ๋„ฃ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

๋ชจ๋‘ ๋‹ค ํ–ˆ๋‹ค๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

 

main ๋ธŒ๋žœ์น˜ ์…‹ํŒ…

๋ฉ”์ธ ๋ธŒ๋žœ์น˜๋Š” ๊ฐ๊ฐ bluegreen, rolling, canary ๋ธŒ๋žœ์น˜์˜ ํ† ๋Œ€๊ฐ€ ๋˜๋Š” ๋ธŒ๋žœ์น˜๋กœ bulid.gradle ์„ค์ •, Test API ์ƒ์„ฑ, Custom Health Indicator ์ƒ์„ฑ, ci.yml ์ƒ์„ฑ์„ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. 

 

bulid.gradle 

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-actuator'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
    testRuntimeOnly 'org.junit.platform:junit-platform-launcher'
}

tasks.named("jar") {
    enabled = false
}

 

์˜์กด์„ฑ ์œผ๋กœ๋Š” Spring web ๊ณผ Spring actuator ๋ฅผ ์ฃผ์ž… ๋ฐ›๊ณ  jar ํŒŒ์ผ ์ƒ์„ฑ์„ false ๋กœ ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ๊นƒํ—ˆ๋ธŒ ์•ก์…˜์Šค์˜ ๋ช…๋ น์–ด์—์„œ๋„ jar ํŒŒ์ผ์„ ๋งŒ๋“ค๊ธฐ ๋•Œ๋ฌธ์— false ํ•ด์ฃผ์ง€ ์•Š์œผ๋ฉด jar ํŒŒ์ผ์ด ๋ณต์ˆ˜๊ฐœ๋ผ์„œ ์–ด๋А ๊ฒƒ์„ ๋ฐฐํฌํ•  jar์ธ์ง€ ๋ชจ๋ฅด๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.

 

Test API ์ƒ์„ฑ

import org.springframework.boot.web.server.WebServer;
import org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {
    private final ServletWebServerApplicationContext webServerAppContext;
    private static final String RESPONSE_BODY_MESSAGE = "๋ฒ„์ „ 1 ์‘๋‹ต๊ฐ’์ž…๋‹ˆ๋‹ค. ๋ฌด์ค‘๋‹จ ๋ฐฐํฌ ๋„์ž… ์ „์ž…๋‹ˆ๋‹ค.";

    public TestController(ServletWebServerApplicationContext webServerAppContext) {
        this.webServerAppContext = webServerAppContext;
    }

    @GetMapping("/hello")
    public ResponseEntity<String> test() {
        WebServer webServer = webServerAppContext.getWebServer();
        int port = webServer.getPort();
        String response = RESPONSE_BODY_MESSAGE + "\n์‹คํ–‰ ์ค‘์ธ ํฌํŠธ๋Š” " + port + "์ž…๋‹ˆ๋‹ค.";
        return ResponseEntity.ok(response);
    }
}

 

์–ด๋А ๋ฒ„์ „์ธ์ง€ ์‘๋‹ต์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๊ณ  ํฌํŠธ ๋ฒˆํ˜ธ๋ฅผ ์•Œ ์ˆ˜ ์žˆ๊ฒ ๋” API ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ์ƒ์„ฑ์ž ์ฃผ์ž…์„ ํ–ˆ๊ธฐ๋•Œ๋ฌธ์— ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋œ Test ํด๋”์˜ TestController ํ…Œ์ŠคํŠธ ํŒŒ์ผ์€ ์ง€์›Œ์ฃผ์…”์•ผํ•ฉ๋‹ˆ๋‹ค. ์•ˆ๊ทธ๋Ÿฌ๋ฉด ๋‚˜์ค‘์— pr ์‹œ CI ์ฒดํฌ์—์„œ ๋นŒ๋“œ ํ…Œ์ŠคํŠธ๋ฅผ ํ†ต๊ณผ ๋ชปํ•˜๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์—ฌ๊ธด ์˜์กด์„ฑ ์ฃผ์ž…์ด ๋๋Š”๋ฐ, Test ํŒŒ์ผ์—” ์˜์กด์„ฑ ์ฃผ์ž…์ด ์•ˆ๋๊ธฐ ๋•Œ๋ฌธ์ด์ฃ .

 

Custom Health Indicator ์ƒ์„ฑ

import org.springframework.boot.actuate.health.Health;
import org.springframework.boot.actuate.health.HealthIndicator;
import org.springframework.stereotype.Component;

@Component
public class CustomHealthIndicator implements HealthIndicator {

    @Override
    public Health health() {
        boolean isHealthy = checkSomeCondition();
        if (isHealthy) {
            return Health.up().withDetail("customHealth", "All systems go!").build();
        } else {
            return Health.down().withDetail("customHealth", "Something is wrong!").build();
        }
    }

    private boolean checkSomeCondition() {
        long freeMemory = Runtime.getRuntime().freeMemory();
        long totalMemory = Runtime.getRuntime().totalMemory();
        return freeMemory > (totalMemory * 0.15);
    }
}

 

Actuator ๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ปค์Šคํ…€์œผ๋กœ ํ—ฌ์Šค ํ™•์ธ์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. DB ์ปค๋„ฅ์…˜์„ ํ™•์ธ ํ•œ๋‹ค๊ฑฐ๋‚˜, ์™ธ๋ถ€ API๊ฐ€ ์ž˜ ํ˜ธ์ถœ ๋˜๋Š”์ง€ ํ™•์ธ ํ•œ๋‹ค๊ฑฐ๋‚˜, ์•„๋‹ˆ๋ฉด ์ž์‹ ์ด ๋งŒ๋“  ์„œ๋น„์Šค์˜ ๊ธฐ๋Šฅ์ด ์ž˜ ๋™์ž‘ํ•˜๋Š”์ง€ ํ™•์ธ์„ ํ•  ์ˆ˜๋„ ์žˆ๊ฒ ์ฃ .

์ „ DB ์—ฐ๋™์ด๋‚˜ ๋‹ค๋ฅธ ์™ธ๋ถ€์ ์ธ ์š”์ธ์ด ์—†๊ธฐ์—, ๊ทธ๋ƒฅ return true ๋กœ ํ•˜๋ฉด ์‹ฌ์‹ฌํ•˜๋‹ˆ ๊ฐ€์šฉ ๋ฉ”๋ชจ๋ฆฌ๊ฐ€ ์ „์ฒด ๋ฉ”๋ชจ๋ฆฌ์˜ 15% ์ด์ƒ์ธ์ง€ ํ™•์ธํ•˜๋Š” ๋กœ์ง์„ ๋„ฃ์–ด ๋ดค์Šต๋‹ˆ๋‹ค.

 

๋ชจ๋“  ์…‹ํŒ…์€ ๋๋‚ฌ๊ธฐ์— ์ด์   ๊ฐ๊ฐ์˜ ์ „๋žต์— ๋งž๋Š” ์‹ค์Šต์„ ์ง„ํ–‰ํ•ด ๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋Œ“๊ธ€