본문 바로가기

로컬 환경 구성/로컬 개발환경 구성

8. Jenkins과 Ansible 연동 및 Ansible Playbook 사용하기

# Jenkins과 Ansible을 연동하기

1. Jenkins의 시스템 설정으로 이동한다.

하단으로 이동하면 ssh 서버를 등록하는 메뉴가 존재한다.

거기에 추가 아이콘을 클릭하여 Ansible 서버를 등록해 준다.

아래와 같이 기본정보를 입력해주고, 고급 버튼을 클릭하여 추가 정보를 입력한다.

- 추가 설정은 아래와 같다.

테스트 커넥션을 클릭하여 연결이 정상적으로 되는지 확인한다.

위의 Success를 확인한다. 정상적으로 연결이 되었음을 확인할 수 있다.

2. Jenkins와 Ansible의 플레이북 사용하기

만약 아래와 같은 오류가 발생 했을 때에는 해당 경로의 내용을 삭제 해줘야 한다.

seungkim@Local-ENV:~$ ssh root@localhost -p 10022
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ED25519 key sent by the remote host is
Please contact your system administrator.
Add correct host key in /home/seungkim/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/seungkim/.ssh/known_hosts:2
  remove with:
  ssh-keygen -f "/home/seungkim/.ssh/known_hosts" -R "[localhost]:10022"
Host key for [localhost]:10022 has changed and you have requested strict checking.

위에 경로중에서 /home/seungkim/.ssh/known_hosts 내용을 vi를 열고 삭제 해준뒤 다시 ssh로 접속하면 정상적으로 접근이 가능하다.

- Jenkins로 이동하여 신규 프로젝트를 생성한다.

Ansible Project라고 명명후 이전에 생성된 프로젝트를 기반으로 생성을 한다. 빌드후 조치에 어떤 내용이 존재 한다면 삭제 한다. 그리고 젠킨스에서 생성한 결과물을 ssh를 통해 전달을 해야 하므로 Send build artifacts over SSH 항목을 클릭하여 신규로 생성한다. 그리고 젠킨스에서 생성한 결과물을 Ansible-Server로 복사할 예정이므로 Ansible-Server로 선택한다.

아래와 같이 설정 후 적용 및 저장한다.

- 현재 까지 적용된 내용을 기반으로 빌드를 수행해보자.

"지금빌드" 버튼을 클릭하여 빌드를 수행하면 정상적으로 빌드가 수행이 된것을 확인 할수 있다.

- 그렇다면 ssh 서버로 설정한 Ansible-Server로 이동하여 정상적으로 war 파일이 복사가 되었는지 확인한다.

[root@ansible-server ~]# ls -l
total 7888
-rw------- 1 root root    2361 Sep 15  2021 anaconda-ks.cfg
-rw-r--r-- 1 root root     608 Sep 15  2021 anaconda-post.log
-rw-r--r-- 1 root root     129 Sep 20  2022 Dockerfile
-rw-r--r-- 1 root root 8025961 May  9 23:52 hello-world.war
-rw------- 1 root root    2059 Sep 15  2021 original-ks.cfg
-rw-r--r-- 1 root root   27980 Jan 25  2020 sshpass-1.06-8.el8.x86_64.rpm
-rw-r--r-- 1 root root      16 May  9 05:38 test

위의 목록에서 helloword.war 파일을 확인 할 수 있다.

3. AnsiblePlaybook을 생성하여 활용하기

- Playbook은 Ansible 서버에 생성을 해야한다.

그리고 root 경로에 first-devops-playbook.yml 이라는 파일을 하나 생성한다.

그리고 아래와 같은 내용을 입력 후 저장한다.

- 경로 : /root

- 파일내용은 아래와 같다.

- hosts: all
#   become: true

  tasks:
  - name: build a docker image with deployed war file
    command: docker build -t cicd-project-ansible .
    args:
        chdir: /root

여기서 command 명령을 보면 docker 를 빌드하는 명령이 들어가 있다. 해당 명령은 Dockerfile을 실행시키는 명령이므로 동일한 경로의 폴더에 Dockerfile도 존재 해야만 한다.

Dockerfile의 내용을 보면 아래와 같다.

FROM tomcat:9.0

COPY ./hello-world.war /usr/local/tomcat/webapps

그리고 현재 경로에 hosts 파일을 생성하여 적용할 대상을 선정할 수 있다.

vi hosts 명령으로 파일을 생성 후 172.17.0.3를 입력하여 대상 ip를 선정한다.

- 생성한 플레이북 파일을 실행

[root@ansible-server ~]# ansible-playbook -i hosts first-devops-playbook.yml

PLAY [all] **************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [172.17.0.3]

TASK [build a docker image with deployed war file] **********************************************************************************************************
changed: [172.17.0.3]

PLAY RECAP **************************************************************************************************************************************************
172.17.0.3                 : ok=2    changed=1    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

위와 같은 결과를 확인 할 수 있다.

docker image를 확인하면 아래와 같이 위의 플레이북을 통해 생성한 이미지를 확인 할수 있다.

[root@ansible-server ~]# docker images
REPOSITORY             TAG       IMAGE ID       CREATED          SIZE
cicd-project-ansible   latest    b3852bbe6187   37 seconds ago   484MB
tomcat                 9.0       3f55087df9b4   5 days ago       476MB

- 컨테이너를 생성하고 실행하는 명령어를 플레이북에 추가하기

위에서 생성한 플레이북 파일에 아래의 명령어를 파일 하단에 추가해 준다.

  - name: create a container using cicd-project-ansible image
    command: docker run -d --name my_cicd_project -p 8080:8080 cicd-project-ansible

그러면 전체 파일의 내용은 아래와 같을 것이다.

- hosts: all
#   become: true

  tasks:
  - name: build a docker image with deployed war file
    command: docker build -t cicd-project-ansible .
    args:
        chdir: /root

  - name: create a container using cicd-project-ansible image
    command: docker run -d --name my_cicd_project -p 8080:8080 cicd-project-ansible

 

변경한 플레이북으로 실행을 하면 아래와 같은 결과를 얻을 수 있다.

[root@ansible-server ~]# docker images
REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
cicd-project-ansible   latest    b3852bbe6187   5 minutes ago   484MB
tomcat                 9.0       3f55087df9b4   5 days ago      476MB
[root@ansible-server ~]# docker ps -a
CONTAINER ID   IMAGE     COMMAND   CREATED   STATUS    PORTS     NAMES
[root@ansible-server ~]# ansible-playbook -i hosts first-devops-playbook.yml

PLAY [all] **************************************************************************************************************************************************

TASK [Gathering Facts] **************************************************************************************************************************************
ok: [172.17.0.3]

TASK [build a docker image with deployed war file] **********************************************************************************************************
changed: [172.17.0.3]

TASK [create a container using cicd-project-ansible image] **************************************************************************************************
changed: [172.17.0.3]

PLAY RECAP **************************************************************************************************************************************************
172.17.0.3                 : ok=3    changed=2    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0

- 이미지와 컨테이너가 정상적으로 실행 되었는지 확인하면 아래와 같다.

[root@ansible-server ~]# docker images
REPOSITORY             TAG       IMAGE ID       CREATED         SIZE
cicd-project-ansible   latest    b3852bbe6187   6 minutes ago   484MB
tomcat                 9.0       3f55087df9b4   5 days ago      476MB
[root@ansible-server ~]# docker ps -a
CONTAINER ID   IMAGE                  COMMAND             CREATED          STATUS          PORTS                    NAMES
415b7af6702b   cicd-project-ansible   "catalina.sh run"   37 seconds ago   Up 33 seconds   0.0.0.0:8089->8080/tcp   my_cicd_project

정상적으로 실행 된것을 확인할 수 있다. 해당 작업을 젠킨스에서 실행시키고 결과를 확인하기 위해 위의 작업내역을 삭제한다. 이미지와 프로세스를 삭제하면 된다.

결국 젠킨스에서 우리가 위에서 생성한 first-devops-playbook.yml 파일을 실행하면 위와같은 결과를 얻을수 있을것이다. 그럼 젠킨스에서 first-devops-playbook.yml파일을 실행하도록 구성을 해보자.

4. Jenkins에서 first-devops-playbook.yml 파일을 실행

- 실행하는 간단한 방법은 Exec command에 first-devops-playbook.yml파일을 실행하도록 구성하면 될것이다. 아래와 같이 이 설정을 진행한다.

아래와 같이 입력을 해준다.

ansible-playbook -i hosts first-devops-playbook.yml

- 입력 화면, 터미널에서 실행했던 명령어를 젠킨스에서도 동일하게 사용하겠다는 의미이다.

위와같이 설정 후 적용 및 저장 후 빌드를 실행해보자.

실행 후 Ansible 서버로 이동 후 이미지와 프로세스를 보면 아래와 같이 정상적으로 실행되고 이미지가 생성되어 있는것을 볼 수 있다.

그리고 젠킨스에서 실행된 프로세스의 콘솔 아웃풋을 보면 아래와 같이 플레이북을 실행 후 결과를 확인 할 수 있다.

...
Waiting for Jenkins to finish collecting data
[JENKINS] Archiving /var/jenkins_home/workspace/Ansible-Project/pom.xml to /web/1.0/web-1.0.pom
[JENKINS] Archiving /var/jenkins_home/workspace/Ansible-Project/target/hello-world.war to /web/1.0/web-1.0.war
SSH: Connecting from host [3baf2273d16a]
SSH: Connecting with configuration [Ansible-Server] ...
SSH: EXEC: completed after 22,186 ms
SSH: Disconnecting configuration [Ansible-Server] ...
SSH: Transferred 1 file(s)
Finished: SUCCESS

Ansible 서버에서 이미지와 프로세스를 확인하면 아래와 같은 결과를 볼 수 있다.

위에서 모두 삭제 하였는데 신규로 생성되어 실행된 모습이다.

[root@ansible-server ~]# docker ps -a
CONTAINER ID   IMAGE                  COMMAND             CREATED              STATUS              PORTS                    NAMES
ee02992afa9c   cicd-project-ansible   "catalina.sh run"   About a minute ago   Up About a minute   0.0.0.0:8089->8080/tcp   my_cicd_project
[root@ansible-server ~]# docker images
REPOSITORY             TAG       IMAGE ID       CREATED              SIZE
cicd-project-ansible   latest    0a52d8843758   About a minute ago   484MB
tomcat                 9.0       3f55087df9b4   5 days ago           476MB

- 여기서 포트 포워딩된 정보를 한번 짚고 넘어가보자. 아래의 그림을 보면 정확히 이해가 된다.

- 젠킨스에서 아래와 같이 Poll SCM에 설정을 해주면 코드가 변경되고 git에 커밋 및 푸쉬되어 반영되면 자동으로 실행된다.

- 그리고 플레이북 yml 파일에 docker 프로세스를 중지, 삭제 및 이미지를 삭제하는 과정을 추가하면 아래와 같다.

  - name: stop current running container
    command: docker stop my_cicd_project
    ignore_errors: yes

  - name: remove stopped cotainer
    command: docker rm my_cicd_project
    ignore_errors: yes

  - name: remove current docker image
    command: docker rmi cicd-project-ansible
    ignore_errors: yes

위의 내용처럼 command의 내용만 변경 후 적용하면 된다. 위와 같이 프로세스를 중지 및 삭제 하는 이유는 동일한 프로세스가 실행중이거나 이미지가 있으면 젠키스에서 빌드할때 이미 실행중인 프로세스 및 이미지가 존재한다고 오류가 발생하기 때문이다.

플레이북의 전체 코드를 보면 아래와 같다.

- hosts: all
#   become: true  

  tasks:
  - name: stop current running container
    command: docker stop my_cicd_project
    ignore_errors: yes

  - name: remove stopped cotainer
    command: docker rm my_cicd_project
    ignore_errors: yes

  - name: remove current docker image
    command: docker rmi cicd-project-ansible
    ignore_errors: yes

  - name: build a docker image with deployed war file
    command: docker build -t cicd-project-ansible .
    args: 
        chdir: /root

  - name: create a container using cicd-project-ansible image
    command: docker run -d --name my_cicd_project -p 8080:8080 cicd-project-ansible

- 끝 -