구성한 프로젝트 아키텍쳐
- Blue Green 무중단 배포를 위해 Spring 서버와 React 서버를 각각 포트 2개씩 사용했습니다.
- Dockerfile을 사용해 docker hub에 현재 파일을 업로드하여 버전 관리를 했습니다.
무중단 CI/CD 구축을 위한 과정
1. EC2에 Docker 설치
2. EC2에 Docker로 Jenkins 띄우기
3. EC2에 Nginx 설치
4. https 접근을 위한 Nginx 인증서 설정(SSL 인증서)
5. Jenkins에서 GitLab 접근을 위한 GitLab 토큰 발급
6. Jenkins에서 GitLab 접근 플러그인 설치 및 접근 토큰/GitLab 계정 등록
7. Jenkins 파이프라인 작성
그럼 시작합니다.
1. EC2에 Docker 설치
Docker : 애플리케이션을 컨테이너라는 가벼운 독립 실행 환경에서 실행할 수 있도록 해주는 오픈 소스 플랫폼
# 의존성 설치
sudo apt update
sudo apt install ca-certificates curl gnupg lsb-release
# 레포지토리
sudo mkdir -p /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# 레포지토리 추가
echo "deb [arch=$(dpkg --print-architecture) \
signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 도커 설치하기
sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io docker-compose-plugin
2. EC2에 Docker로 Jenkins 설치
Jenkins : 소프트웨어 개발에서 지속적인 통합(CI) 및 지속적인 배포(CD) 프로세스를 자동화하기 위해 사용되는
오픈 소스 자동화 서버
# 도커 소켓 마운트 하기 (젠킨스 컨테이너에서 도커 명령어 실행되도록 하기)
sudo docker run -itd --name jenkins -p 9005:8080 -v /var/run/docker.sock:/var/run/docker.sock -v /usr/bin/docker:/usr/bin/docker jenkins/jenkins:jdk21
# 도커 명령어가 젠킨스에서 실행이 안되거나 권한 오류가 나면 아래 명령어 실행
sudo chmod 666 /var/run/docker.sock
# 젠킨스 컨테이너 비밀번호 확인 명령어
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
# 젠킨스 컨테이너로 접속해서 도커 명령어 실행 여부 확인 명령어
docker ps
docker exec -it <container_name_or_id> /bin/bash
docker exec -it jenkins /bin/bash
# 젠킨스 컨테이너에 접속해서 Docker 명령어 되는지 확인
docker ps
- Jenkins는 Nginx를 통해 별도의 설정을 하지 않기때문에, https가 아닌 http로 접속해야 합니다.
- 9005:8080는 외부에서 9005번 포트로 접근하지만, 실제 내부에서는 8000번 포트로 접근함을 의미합니다.
- 인터넷 브라우저에서 <url>:9005 을 입력하면 위와 같은 화면을 마주할 수 있습니다.
docker exec jenkins cat /var/jenkins_home/secrets/initialAdminPassword
- 위 입력을 통해 패스워드를 얻어내고, 값을 붙여놓습니다.
- Install suggested plugins 를 선택한 뒤, 플러그인 설치 후 계정 값을 입력하면 오른쪽 페이지가 등장합니다.
- 플러그인 설치 시 입력했던 계정으로 다음부터 로그인할 수 있습니다.
3. EC2에 Nginx 설치
Nginx : 고성능 웹 서버이자 리버스 프록시 서버, 그리고 로드 밸런서 및 HTTP 캐시로도 사용할 수 있는 오픈 소스 소프트웨어
sudo apt update
sudo apt upgrade
sudo apt install nginx
sudo service nginx start
sudo service nginx status
4. https 접근을 위한 Nginx 인증서 설정(SSL 인증서)
0) ssl 인증을 위한 nginx 설정
sudo vi /etc/nginx/sites-available/default
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name <EC2 도메인주소 또는 IP주소> <www.EC2 도메인주소 또는 IP주소>;
location / {
try_files $uri $uri/ =404;
}
location /.well-known/acme-challenge/ {
root /var/www/html;
}
}
1) 20 이전의 우분투 버전에서의 certbot 설치 명령어
wget https://dl.eff.org/certbot-auto
2) 20 이상의 우분투 버전에서의 certbot 설치 명령어
# snap을 이용하여 core 설치 -> snap을 최신 버전으로 유지하기 위해 설치
sudo snap install core
# core를 refresh 해준다.
sudo snap refresh core
# 기존에 잘못된 certbot이 설치되어있을 수도 있으니 삭제 해준다.
sudo apt remove certbot
# certbot 설치
sudo snap install --classic certbot
# certbot 명령을 로컬에서 실행할 수 있도록 snap의 certbot 파일을 로컬의 cerbot과 링크(연결) 시켜준다. -s 옵션은 심볼릭링크를 하겠다는 것.
ln -s /snap/bin/certbot /usr/bin/certbot
3) certbot을 이용해 ssl 인증서를 받아온 뒤 cerbot이 스스로 nginx설정을 해주도록 하는 명령어
sudo apt install python3-certbot-nginx
sudo certbot --nginx
- 명령어 입력 후, 질문에 맞춰 답변을 해주면된다.
- domain을 입력하라는 질문에서는 본인이 사용할 Domain을 입력해주면 된다.
- 만약 실패한다면 ufw에서 80, 443 포트가 열려있는지 확인합니다.
4) 정상적으로 성공한 모습
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Your existing certificate has been successfully renewed, and the new certificate
has been installed.
The new certificate covers the following domains: https://{내가 입력한 도메인} # https가 설정된 도메인을 알려준 것.
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Subscribe to the EFF mailing list (email: woorimprog@gmail.com).
IMPORTANT NOTES:
- Congratulations! Your certificate and chain have been saved at:
/etc/letsencrypt/live/idu-market.shop/fullchain.pem # 공개키 경로이므로 기억해두자.
Your key file has been saved at:
/etc/letsencrypt/live/idu-market.shop/privkey.pem # 비밀키 경로이므로 기억해두자.
Your certificate will expire on 2021-08-15. To obtain a new or
tweaked version of this certificate in the future, simply run
certbot again with the "certonly" option. To non-interactively
renew *all* of your certificates, run "certbot renew"
- If you like Certbot, please consider supporting our work by:
Donating to ISRG / Let's Encrypt: https://letsencrypt.org/donate
Donating to EFF: https://eff.org/donate-le
5) https가 적용된 내 도메인과 비밀키, 공개키가 저장된 경로
1. https가 설정된 도메인
https://{내가 입력한 도메인 주소}
2. 공개키 경로
/etc/letsencrypt/live/{내가 입력한 도메인 주소}/fullchain.pem
3. 비밀키 경로
/etc/letsencrypt/live/{내가 입력한 도메인 주소}/privkey.pem
6) 결과 확인
server {
listen 80 default_server;
listen [::]:80 default_server;
root /var/www/html;
index index.html index.htm index.nginx-debian.html;
server_name j11b204.p.ssafy.io www.j11b204.p.ssafy.io;
location / {
try_files $uri $uri/ =404;
}
location /.well-known/acme-challenge/ {
root /var/www/html;
}
listen [::]:443 ssl ipv6only=on; # managed by Certbot
listen 443 ssl; # managed by Certbot
ssl_certificate /etc/letsencrypt/live/j11b204.p.ssafy.io/fullchain.pem; # managed by Certbot
ssl_certificate_key /etc/letsencrypt/live/j11b204.p.ssafy.io/privkey.pem; # managed by Certbot
include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot
}
# 80 포트로 접근시 443 포트로 리다이렉트 시켜주는 설정
# certbot에서 2번 선택지 선택 시에 적용되는 설정입니다.
server {
if ($host = {내가 입력한 도메인 이름}) {
return 301 https://$host$request_uri;
} # managed by Certbot
listen 80;
server_name {내가 입력한 도메인 이름};
return 404; # managed by Certbot
}
- 5번까지의 과정을 잘 입력했다면, 위와 같이 자동으로 Nginx의 설정이 변한 것을 확인할 수 있다.
7) SSL 인증서 갱신 방법
- certbot을 이용하여 ssl인증서를 발급할 경우 3개월 마다 갱신을 해줘야 한다.
certbot renew
- 일정 기간마다 자동으로 인증서를 갱신시키기 위해서는 아래의 링크를 참고바란다.
(https://devlog.jwgo.kr/2019/04/16/how-to-lets-encrypt-ssl-renew/)
참고자료 : https://gist.github.com/woorim960/dda0bc85599f61a025bb8ac471dfaf7a
5. Jenkins에서 GitLab 접근을 위한 GitLab 토큰 발급
- Setting > Access Tokens > Add new token 를 클릭한다.
- 위 과정을 통해 GitLab에 접근할 수 있는 토큰을 제작할 수 있다.
6. Jenkins에서 GitLab 접근 플러그인 설치 및 접근 토큰/GitLab 계정 등록
1) GitLab 플러그인 설치 ( Dashboard > Jenkins 관리 > Plugins > Available plugins 검색창에 'gitlab' 입력 후 해당 플러그인 설치 )
2) GitLab 계정 및 API 접근 토큰 Credential에 등록
- Dashboard > Jenkins 관리 > Credentials > System > Global credentials (unrestriced) > '+ Add Credentials' 버튼 클릭
3) GitLab 계정 정보 Jenkins에 등록
- Kind : Username with password
- Scope : Global
- Username : GitLab 아이디
- Password : GitLab에서 발급받은 Personal Access Token
- ID : 추후 파이프라인에서 불러올 때 사용할 닉네임(저는 'GitLab_User' 라고 명칭하겠습니다.)
4) GitLab API 접근 토큰 Jenkins에 등록
- Kind : GitLab API token
- Scope : Global
- API token : 위 GitLab에서 발급받은 access token 입력
- ID : 추후 파이프라인 작성 시 닉네임으로 사용될 값으로, 자신이 알아볼 수 있도록 임의로 작성하면 됨
5) GitLab, Jenkins 연결
- Dashboard > Jenkins 관리 > System 이동 후, 스크롤을 내려서 GitLab 파트로 이동
- Connection name : 원하는 값 입력
- GitLab host URL : 내가 만든 GitLab의 레포지토리 URL이 아닌 사용 중인 GitLab의 기본 URL
- Credential : 앞서 Jenkins에 등록한 GitLab AccessToken
-> 입력 후 Test > Success > 저장
7. Jenkins 파이프라인 구축
Dashboard > All > New Item
- 파이프라인 이름으로 사용할 이름 작성
- 파이프라인 선택 후 OK
- OK 이후 스크롤을 내려 위 설정을 맞춥니다.
- Secret token을 Generate 버튼을 통해 생성하고, 이를 보관해둡니다.
pipeline {
agent any
stages {
stage('Git Clone'){
steps {
git branch: 'backend', credentialsId: 'GitLab_User', url: 'https://test.com/test/project.git'
}
post {
failure {
echo 'Repository clone failure !'
}
success {
echo 'Repository clone success !'
}
}
}
}
}
8. WebHook 등록
Settings > Webhooks > Add new webhook
URL : 위에서 등록한 items > 구성 > Build Triggers > webhook URL 입력
Secret token : 위 items 작성에서 Generate 버튼 클릭을 통해 생성해낸 token 입력
Trigger : Push event & Merge request event Click
-> test 브랜치만 설정해두고 싶다면 wildcard 버튼 클릭 후 test 를 입력합니다.
- 위처럼 webhook을 등록했다면, 위 그림에서 Test > Push events 를 통해 웹훅을 날릴 수 있습니다.