DevOps

CI/CD 파이프라인 구축하기 - 4.2 (Ansible Playbook을 이용한 Docker 컨테이너 배포)

우잉~ 2024. 12. 16. 23:59

아래 포스팅에서 이어집니다.

https://wooinge.tistory.com/143

 

CI/CD 파이프라인 구축하기 - 4.1 (Ansible 서버 구축 및, Jenkins, Docker 통합)

아래 포스팅에서 이어집니다!https://wooinge.tistory.com/142 CI/CD 파이프라인 구축하기 - 3.2 (Docker 컨테이너 자동 빌드 및 자동 배포)아래 포스팅에서 이어집니다!https://wooinge.tistory.com/141 CI/CD 파이프라

wooinge.tistory.com

 

앞에서 Ansible Server 구축과 Jenkins - Ansible - Docker를 통합하는 과정을 거쳤다.

이번에는 Ansible Playbook으로 실행할 코드를 직접 작성하고 도커 이미지 빌드와 컨테이너를 자동으로 생성할 것이다.

 

이번 포스팅에서 진행할 과정

 

 

5. ansible playbook으로 이미지 생성하기

이제 Ansible 서버에서 Docker에 컨테이너를 배포할 것이다.

현재 진행할 부분

 

playbook을 이용하여 컨테이너를 배포할 예정이기 때문에 /etc/ansible/hosts(인벤토리)에 로컬 호스트(ansible-server)의 IP도 넣어준다.

대괄호([])는 그룹을 뜻한다.

/etc/ansible/hosts 파일 수정

 

인벤토리에 새로 등록한 IP와 통신할 수 있는지 확인하기 위해 uptime 명령을 써보지만, 현재 인증키를 등록하지 않아서 연결을 진행할 수 없는 상태이다.

* 이전 포스팅에서  ansible-server에서 ssh-keygen 명령을 이용하여 키를 생성하였고, dockerhost에게만 키를 복사한 상태였다.

ssh-copy-id 명령어를 사용하여 로컬호스트에게도 인증키를 등록해준다.

인증키 없어서 그대로 멈춰버린 터미널. 빠져나오기 위해 ctrl+c 입력
인증을 위한 공개키 복사 완료

 

복사가 완료되면 정상적으로 작동하는 것을 확인할 수 있다~!

/etc/ansible/hosts에 등록된 모든 IP와 통신이 가능해진 상태

 

이제 컨테이너 실행을 위한 이미지를 생성하는 YAML 파일을 작성할 것이다.

해석하면 다음과 같다.

  • ---: YAML 파일의 시작을 나타냄
  • - hosts: [etc/ansible/hosts에 등록된 대상 호스트 그룹]: 해당 작업이 시작될 호스트 그룹을 지정하여 이 그룹에 속한 서버에서 작업이 실행되도록 함
  • tasks: 플레이북에서 실행할 작업 목록을 정의하여 순차적으로 실행되도록 함
  • -  name: 작업의 이름
  • command: 모듈을 사용하여 명령어를 실행함
  • args: command 모듈의 추가 인자를 설정함
  • chdir: [작업 디렉토리]: 작업 실행 전 작업 디렉토리를 변경

regapp.yml 파일 작성

 

 

ansible-playbook [yaml 파일 이름]으로 실행할 수 있다.

명령어를 실행하고 이미지 목록을 살펴보면 yaml 파일에서 지정한 regapp:latest라는 이미지가 새로 생성된 것을 확인할 수 있다.

그런데 실제 이미지가 생성된 시간은 두 이미지 모두 48분전으로 동일하다.

생성 시간이 동일한 이유는 바로 webapp.war 파일에 변동이 없기 때문이다.

깔끔하게 정리해서 말하자면 두 이미지는 같은 버전의 빌드 산출물을 이용하여 이미지를 생성했단 뜻이다.

ansible-playbook regapp.yaml 실행 결과

 

 

6. 생성 이미지 docker hub로 복사하기(수동작업)

이제는 ansible-server에서 생성한 이미지를 바로  docker hub 레포지토리로 업로드할 것이다.

현재 진행할 부분

 

Docker hub에 이미지를 업로드하기 위해서는 아래의 사이트에서 회원가입 및 로그인이 필요하다,,,

 

도커 허브 사이트

https://hub.docker.com/

 

Docker Hub Container Image Library | App Containerization

Increase your reach and adoption on Docker Hub With a Docker Verified Publisher subscription, you'll increase trust, boost discoverability, get exclusive data insights, and much more.

hub.docker.com

 

 

ansible-server에서 생성한 이미지를 도커 허브 레포지토리에 푸시하기 위해서는 우선,,, 로그인을 서버에서도 진행해야 한다.

자신이 회원가입한 아이디와 비밀번호를 입력하여 로그인한다.

로그인 완료

 

이제 우리가 playbook으로 만든 이미지를 레포지토리에 보내본다.

잘 되는 것 같았는데 갑자기 거부되면서 실행이 취소된다.

이 에러는 레포지토리의 경로를 제대로 설정해주지 않았기 때문에 발생한 것이다.

경로 미설정으로 인한 push 에러

 

docker hub 레포지토리의 경로는 namespace/repository name으로 이루어져 있다.

그에 맞게 이미지의 이름을 변경해주는 작업이 필요하다.

docker의 이미지 이름을 변경하는 명령어는 tag이다.

※ 여기서 기존에 있던 이미지의 이름이 변경되는 것이 아니라, 새로 생성이 되는 것을 확인할 수 있다.

이미지 이름 변경 완료

 

이제 레포지토리 경로를 명시하여 push 명령어를 사용하면 제대로 레포지토리에 이미지가 업로드되는 것을 확인할 수 있다.

push 명령어 성공 화면

 

새로 생긴 docker hub repository

 

 

7. 생성 이미지 docker hub로 복사하기(자동화)

이제 도커 허브 레포지토리에 이미지를 업로드하는 방법을 알았으니 playbook을 이용하여 업로드하는 것을 자동화해보겠다.

코드 수정

 

yml 파일을 실행할 때 --check 명령어를 사용하게 되면 지정된 실행 내용이 어떻게 수정되는지 보여주는데, 실제로 실행되는 것은 아니다. → 테스트 용도로 사용!

 

테스트

 

ansible-playbook의 옵션 중 --limit은 인벤토리 파일(/etc/ansible/hosts)에 저장된 호스트를 제한할 수 있다.

그리고 --check와는 다르게 실제로 실행되기 때문에 도커 허브에 이미지가 업로드된 것을 확인할 수 있다.

실제 실행
이미지 변경사항 업로드

 

이미지가 잘 올라가는 것도 직접 확인했으니 이제 정말 자동으로 이미지를 업로드할 수 있게 Jenkins 프로젝트의 설정을 변경해보겠다.

Exec command에 작성한 명령어들은 모두 webapp.war 파일이 생성되어 복사된 후에 실행될 내용들이다.

그렇기 때문에 새로운 .war 파일이 생성되면 ansible-server에서는 이 새로운 빌드 파일을 이용하여 이미지를 새로 만들고, 도커 허브에 업로드하는 흐름으로 진행해야 된다.

ansible-playbook regapp.yml를 작성해준다.

 

 

regapp.yml 파일의 경로를 제대로 입력해주지 않아서 UNSTABLE 상태로 빌드가 완료되어 버렸다.

정확한 경로로 수정하여 재빌드한다.

경로 수정
성공적인 빌드

 

레포지토리에 자동으로 업로드된 이미지 확인
실제 서버에서도 이미지가 생성되었다.

 

 

8. docker hub 레포지토리 이미지를 이용하여 dockerhost에서 컨테이너 실행하기

지금까지는 ansible 서버에서 이미지를 생성하고 컨테이너를 실행해보았다.

이제는 실제로 dockerhost에서 레포지토리에 업로드된 이미지를 가져와 이 이미지로 컨테이너를 실행해볼 것이다.

현재 진행할 부분

 

dockerhost에 배포하기 위한 yaml 파일을 새로 생성한다.

 

확실하게 하기 위해 dockerhost에서 기존에 생성했던 컨테이너와 이미지를 모두 삭제한 후 진행하였다.

이미지와 컨테이너 모두 삭제

 

ansible-playbook 명령을 이용하여 실행해보았으나 에러가 발생했다.

/var/run/docker.sock 파일의 권한이 거부되었다는 익숙한 문구가 보인다.

해당 파일의 권한을 수정한 뒤 다시 실행해본다.

권한 거부 에러

 

파일 권한 부여

 

--check 옵션을 이용하여 변경 사항을 테스트해본다.

--check 옵션 사용

 

에러가 존재하지 않으므로 --check  옵션을 제거하고 실행을 해보니 컨테이너와 이미지가 제대로 받아와진 것을 확인할 수 있었다.

실행 중인 컨테이너
도커 허브 레포지토리에서 받아온 이미지가 생성되었음

 

지정된 포트 8082로 접속하면 해당 화면을 확인할 수 있다.

무사히 실습이 진행되었다.

하지만 빌드를 다시 하면... 컨테이너의 이름이 동일하기 때문에 오류가 발생하는 것을 확인할 수 있다.

 

 

9. ansible playbook을 이용한 지속적인 컨테이너 배포 실행하기

컨테이너의 이름이 같기 때문에 빌드를 딱 한 번만 하는 건 너무 억울하다.

그래서 기존에 있던 컨테이너와 이미지를 모두 삭제하는 과정을 yaml 파일에 추가해준다.

파일 수정

 

이제 여러번 실행해도 무사히 컨테이너가 실행되는 것을 확인할 수 있다.

파일 실행 완료
실행 중인 컨테이너

 

 

10. jenkins를 이용하여 ansible과 dockerhost에 컨테이너 배포하기

이제 모든 코드를 조합하여 CI/CD 파이프라인을 완성할 수 있다.

두 개의 명령을 동시에 사용하여 성능이 나빠지는 것을 대비하기 위해 중간에 sleep 10; 명령을 사용해 실행 텀을 준다.

커맨드 추가

 

변경된 코드 적용 완료