Ansible 을 사용해서 컨테이너 만들기
- 젠킨스가 github 에서 코드를 갖고 온다.
- 아티팩트를 만들어서 Ansable Server 에 복사한다.
- Ansible 이 docker 로 이미지를 만들어 docker hub 에 푸쉬한다.
- 배포할 때는 docker 가 dockerhub 에서 이미지를 당겨와서 사용한다.
- docker host 를 ansible 로 관리한다.
Ansible 서버 준비하기
EC2 인스턴스 생성 후 hostname 변경
sudo su -
vi /etc/hostname
---
# 호스트 이름 변경 후
---
# 시스템 재시작
init 6
ansible 용 유저 추가
sudo su -
# user 추가
useradd ansadmin
passwd ansadmin
---
# 패스워드 추가 작업
---
# visudo 에서 권한 변경
visudo
## Allows people in group wheel to run all commands
# %wheel ALL=(ALL) ALL
ansadmin ALL=(ALL) ALL
# ansadmin 이 암호 없이 명령 실행 가능하도록 변경
vi /etc/ssh/sshd_config
PasswordAuthentication yes
# PermitEmptyPasswords no
# reload
service sshd reload
ssh-key 만들기
sudo su - ansadmin
# 이 명령어로 ssh key 를 만들어준다. 참고로 경로 다 기본경로로 할거면 계속 엔터만 하면 됨.
ssh-keygen
Ansible 설치
sudo su -
yum install ansible
ansible --version
dockerhost 를 Ansible 에 추가
앤서블 서버가 docker 를 관리할 수 있도록 설정을 해주자.
docker 서버에 유저 추가
sudo su -
useradd ansadmin
passwd ansadmin
권한 변경
visudo
## Same thing without a password
# %wheel ALL=(ALL) NOPASSWD: ALL
ansadmin ALL=(ALL) NOPASSWD: ALL
# 암호 인증 활성화 여부 확인
# 만약 활성화되어있지않으면
# vi /etc/ssh/sshd_config 해서 수정하면 됨.
grep Password /etc/ssh/sshd_config
ansible 서버에 docker host 추가
vi /etc/ansible/hosts
# 해당 파일에 내용이 있다면 전부 다 지운 후,
# 해당 파일이 없다면 새 파일을 추가한다.
# 파일 내용은 dockerhost 의 privateIP 를 적어주면 된다.
예) (없는 IP 쓴 것임, 이렇게 달랑 쓰기만 하면 됨)
176.144.12.1
관리자 key 복사
sudo su - ansadmin
# 아까 만들었던 ansadmin 용 ssh key 를 docker host 로 보낸다.
ssh-copy-id (dockerhostPrivateIP)
확인 작업
# in ansible-server
sudo su - ansadmin
ansible all -m ping
ansible all -m command -a uptime
# in docker-host
sudo su - ansadmin
uptime
- 둘의 uptime 은 같을 것이다. 그러면 서로 잘 통신하고 있다는 것을 확인 가능 :)
Ansible with Jenkins
때가 왔다. 앤서블과 젠킨스를 통합해주자.
jenkins 에 ansible-server 설정
- ansible 서버 설정을 해준다.
- Hostname 에는 ansible 의 privateIP 를 적으면 되고, Password 에는 ansadmin 의 비밀번호를 적으면 됨.
새 작업 생성
- 기존 작업을 카피해서 새 아이템을 생성해준당.
- 기존 SSH-Server 를 ansible-server 로 변경한다.
- Exec command 는 삭제해준다.
- Remote directory 경로는 ansible 서버에는 존재하지 않기 때문에, 만들어줘야한다.
cd /opt
sudo mkdir docker
# docker 디렉토리의 권한을 ansadmin 으로 바꿔줘야한다.
# 그래야 ansadmin 호스트에서 접근 가능.
sudo chown ansadmin:ansadmin docker
- 설정 완료 후 정상 빌드됐을 때, ansible-server 에서 확인해보자.
cd /opt/docker
ll
# ll 했을 때 이렇게 webapp.war 파일이 존재한다면 빌드가 성공적이었음을 확인할 수 있다 :)
-rw-rw-r--. 1 ansadmin ansadmin 2540 May 14 01:44 webapp.war
Ansible 로 도커 이미지를 빌드하고 컨테이너 만들기
도커 설치
# in ansible-server
sudo yum install docker
# 이제 ansadmin 을 여기서 보이는 docker group 에 추가해서 명령어를 사용하게 해줄 것임.
cat /etc/group
# ansadmin 을 docker 그룹에 추가
sudo usermod -aG docker ansadmin
# 여기에서 도커 그룹에 속해있다고 뜬다면 성공적으로 그룹에 넣은 것.
id ansadmin
# 도커 시작
sudo service docker start
도커파일 작성
cd /opt/docker
vi Dockerfile
---
# docker-host 에서 작성했던 도커파일을 그대로 복붙.
FROM tomcat:latest
RUN cp -R /usr/local/tomcat/webapps.dist/* /usr/local/tomcat/webapps
COPY ./*.war /usr/local/tomcat/webapps
---
# 하면 권한이 없다고 빌드가 안 됨.
# 권한을 줘야 가능.
docker build -t regapp:v1 .
# 앞에 sudo 를 붙여서 관리자 권한으로 실행할 수도 있지만 매번 실행할 때마다 sudo 를 추가해줘야해서 귀찮으니
# 도커에 읽기 전용 권한을 줘서 빌드를 가능하도록 두자.
sudo chmod 777 /var/run/docker.sock
# 다시 빌드하면 잘 됨.
docker build -t regapp:v1 .
# 컨테이너 실행, -t 해서 컨테이너에 접속해보면 무리없이 잘 동작하는 걸 확인 가능 '-'
docker run -t --name regapp-server -p 8081:8080 regapp:v1
- ansibleServerPublicIP:8081 로 접속하면 실행되고 있는 톰캣 컨테이너를 확인 가능
Ansible Playbook 만들기
- 출처 : redHat
- 자동화를 담당하는 기술이다.(인 것 같다..)
- playbook을 만들어 이미지를 만들어 도커 허브에 푸쉬하고 배포하는 작업을 자동화해보자 😊
ansible 호스트 서버 추가
ansible 에서 접속할 수 있도록 서버를 추가해줘야 함. (본인 ip 도 추가해줘야 한다.)
sudo vi /etc/ansible/hosts
---
[dockerhost]
172.11.5.15
# ansible 서버를 추가해준다. private IP 를 사용하면 됨.
[ansible]
172.12.30.1
---
# ansible 과는 통신이 안 될 것이다. (FAILED)
# dockerhost 를 사용할 때 했듯이 ssh key 를 만들어 추가해줘야
ansible all -a uptime
# ansible 서버 ssh key 가져오기
ssh-copy-id 172.12.30.1
# 사실 이것도 되긴 한다. 어쨌든 ansible 로컬에서 실행하는 거니까.
ssh-copy-id localhost
# 다시 실행하면 전부 신호가 갑니다.
ansible all -a uptime
regapp.yml
- playbook을 만들기 위한 설정 파일을 작성해준다.
cd /opt/docker
vi regapp.yml
# regapp.yml (---부터 시작이다. --- 추가해줘야함.)
---
# all 로 모든 호스트를 추가해줘도 되지만, ansible 호스트가 할 행동임을 명시하자.
- hosts: ansible
tasks:
# 작업 제목
- name: create docker image
# 리눅스 명령으로 shell 실행
command: docker build -t regapp:latest .
args:
# /opt/docker 아래에 명령을 실행하겠다는 얘기.
chdir: /opt/docker
플레이북 생성 후 이미지 자동 빌드
# check 하면 성공 실패 문법실패여부 확인 가능
ansible-playbook regapp.yml --check
# check 하고 이상 없으면 플레이북 실행!
ansible-playbook regapp.yml
# 이미지가 생성된 것 확인하기
docker images
Ansible 아 Docker container 를 만들어줘
push image to docker hub
- 도커허브에 가입된 아이디가 있어야 한다.
# in ansible-server
docker login
# 내 도커허브 아이디/비번으로 로그인해줌
# 태그를 변경해줌. 접두사로 내 도커허브 아이디를 적어줘야 도커허브에 푸쉬 가능.
docker tag IMAGE_ID holidaykang/regapp:latest
docker push holidaykang/regapp:latest
- 레포가 자동으로 생성된당.
update regapp.yml
---
- hosts: ansible
tasks:
- name: create docker image
command: docker build -t regapp:latest .
args:
chdir: /opt/docker
- name: create tag to push image to dockerhub
command: docker tag regapp:latest holidaykang/regapp:latest
- name: push docker image
command: docker push holidaykang/regapp:latest
- push image to dockerhub 과정을 yml 파일에 담기 위해 기존 파일을 수정해준다.
ansible-playbook regapp.yml --check
# 이제까지는 ansible group 에게 전부 하는 행동이었지만
# 그룹 중에서도 IP 한정으로 할 수도 있다.
# 근데 어차피 지금은 /etc/ansible/hosts 에 [ansible] 그룹에 ip 하나밖에 없음.
# 이렇게 명시 안 해도 상관 없다.
ansible-playbook regapp.yml --limit 172.12.3.91
Jenkins 에게 ansible-playbook 명령 대신 실행하게 하기
- jenkins 에서 Exec command 에 해당 명령을 실행하게 한다.
- ansible-playbook /opt/docker/regapp.yml
- 그리고 업데이트 1분마다 확인해서 pull 해오도록 설정을 변경해주자.
deploy_regapp.yml
- vi deploy_regapp.yml
---
- hosts: dockerhost
tasks:
- name: create container
command: docker run -d --name regapp-server -p 8082:8080 holidaykang/regapp:latest
- 컨테이너를 만드는 명령을 하도록 설정 파일을 추가한다.
- 이미지를 당겨와서 컨테이너를 만드는 건 dockerhost 호스트가 처리하도록 설정했다.
ansible 에서 yml 파일을 playbook 으로 만들기
ansible-playbook deploy_regapp.yml --check
# check 실행 후 문제없으면 실행
ansible-playbook deploy_regapp.yml
# 만약 --check 할 땐 문제없었는데 실제로 실행할 때 문제가 있고 permission denied 오류가 뜬다면
# 해당 명령어를 dockerhost 서버에서 실행해주자.(읽기 권한 허용)
chmod 777 /var/run/docker.sock
# 이러고 다시 실행하면 성공함.
ansible-playbook deploy_regapp.yml
- dockerhost 용 publicIP 로 접속해보면 변경사항이 그대로 반영된 것을 확인 가능..
문제
ansible-playbook deploy_regapp.yml
- 다시 이 명령을 하면 실패한다.
- 이미 같은 이름의 컨테이너가 있다는 오류.
- 이 오류를 해결해줘야 함. → 컨테이너를 만들기 전 기존 컨테이너와 이미지를 지워야겠죠?
update deploy_regapp.yml
- 기존 컨테이너와 이미지를 지우는 명령을 추가하자.
---
- hosts: dockerhost
tasks:
- name: stop existing container
command: docker stop regapp-server
ignore_errors: yes
- name: remove the container
command: docker rm regapp-server
ignore_errors: yes
- name: remove image
command: docker rmi holidaykang/regapp:latest
ignore_errors: yes
- name: create container
command: docker run -d --name regapp-server -p 8082:8080 holidaykang/regapp:latest
- ignore_errors: yes 는 해당 명령을 입력했을 때 에러가 뜨더라도 스킵시키는 설정이다.
- 이미지나 컨테이너가 존재하지 않을 경우 해당 명령이 에러를 일으켜 playbook 실행이 중단되지만, 해당 설정을 해두면 이미지나 컨테이너가 없어 해당 구간에 오류가 일어나더라도 스킵한다 😊
deploy_regapp.yml 실행
ansible-playbook deploy_regapp.yml --check
ansible-playbook deploy_regapp.yml
- 정상 실행되는 것을 확인 가능.
docker image module - ansible
community.docker.docker_image module – Manage docker images — Ansible Community Documentation
- 해당 사이트에 들어가면 설명과 예시가 있다.
마지막 : 위의 과정 전부 자동화하기
이제 자동화의 시간이다.
jenkins 설정 추가
ansible-playbook /opt/docker/regapp.yml;
sleep 10;
ansible-playbook /opt/docker/deploy_regapp.yml
- 둘 다 바로 렌더링 할 순 없으니 sleep 10 명령어로 10초 뒤에 다음 명령이 실행되도록 한다.
저장 후 깃에 새 코드를 푸쉬해주면..
- Email -> Enter Email 로 이름 바뀜
- docker-host:8082 로 접속해보면 코드 변경사항이 자동으로 적용되는 것을 확인 가능! ^0^/
자동화 했으나… 문제점
- docker container 가 내려가고 올라가는 사이에 서버가 내려감. 그 때 사용자가 서버에 접속할 수 없음..
- 혹시 도커 컨테이너가 죽으면 복구 방법이 없음.
💡 쿠버네티스를 사용하면 해결된다. ^0^/ 다음 포스팅에선 쿠버네티스로 배포하기로!
728x90
'개발공부 개발새발 > CICD' 카테고리의 다른 글
CI/CD ) Docker 와 함께 자동 배포하기 (0) | 2024.05.13 |
---|---|
CD ) Tomcat 과 함께 자동 배포까지 (0) | 2024.05.10 |
CI ) Jenkins 로 빌드 및 테스트 자동화하기 (0) | 2024.05.10 |
CI/CD ) CI/CD 가 뭘까 (0) | 2024.05.10 |