HomeAbout
[DevOps] Docker와 Jenkins로 최적화 CI/CD 자동화 파이프라인 구축 : Application Env Build
DevOps
[DevOps] Docker와 Jenkins로 최적화 CI/CD 자동화 파이프라인 구축 : Application Env Build
NASA1515
NASA1515
August 04, 2021
3 min

목차

01
✔ 환경구성
02
✔ CI
03
✌ (CI) 이미지 Build & push
04
🙌 GitLab에서 integration webhook 등록

이번에 사용 예정인 Tools은 다음과 같습니다.

  • gitlab
  • Jenkins
  • Docker, dockerhub

✔ 환경구성


환경 구성은 아래와 같습니다

캡처

  • jenkins : 젠킨스 서버의 역할을 하는 서버 (Docker in Docker)
  • Rancher-master : Rancher 기반의 k8s Master
  • nasa-node1~2 : Rancher 기반의 K8s Worker


✔ CI


JENKINS 설치


Jenkins

  • Jenkins의 경우 Docker in Docker 방식으로 구성했습니다. 현재는 Docker 기반의 서비스 환경에서의 테스트 용도이지만 최종적으로는 IaaS 현태로 배포 예정입니다.

Docker in Docker (DinD)

  • DinD는 Docker 바이너리를 설정하고 Container 내부의 격리된 Docker Daemon을 실행하는 작업을 의미합니다. 즉, DockerDaemon이 2개가 실행되는 것 입니다.
    CI측면에서 접근한다면 Task를 수행하는 Agent가 Docker Client와 Docker Daemon 역할까지 하게되어 Docker명령들을 수행하는데 문제가 없어집니다.
    이렇게 말로만 들으면 아름답고 문제가 없어보이지만 이 접근에는 큰 단점이 존재합니다.

호스트 Docker Container가 privilieged mode로 실행되어야 한다.

$ docker run --privileged --name dind1 -d docker:1.8-dind
  • privilieged 플래그를 사용한다면 호스트Container가 호스트 머신에서 할 수 있는 거의 모든 작업을 할 수 있게 됩니다, 이는 큰 ""보안 위험""을 초래할 수 있습니다.

DinD 사용법과 원리에 대해 잘 정리된 포스트


우선 jenkins 설치 시 사용할 Home Directory 생성해줍니다

# mkdir -p /docker/jenkins
# chmod 666 /docker/jenkins

Docker로 Jenkins를 옵려줍시다!

# docker run -itd --name jenkins -p 8080:8080 -p 50000:50000 -v /docker/jenkins:/var/jenkins_home -v /var/run/docker.sock:/var/run/docker.sock -e TZ=Asia/Seoul -u rootjenkins/jenkins:latest

주요 옵션 설명

-v /docker/jenkins:/var/jenkins_home
    

local volume의 /docker/jenkins 디렉토리와 container volume의 /var/jenkins_home 디렉토리 매핑

-v /var/run/docker.sock:/var/run/docker.sock
제일 중요한 옵션
docker in docker를 구현하기 위해 사용하는 옵션

-u root
Docker 사용자를 root로 설정

-p 8080:8080 -p 50000:50000
local port와 container port 연결
8080은 Jenkins 기본 port
50000dms Jenkins slave port

-e TZ=Asia/Seoul
jenkins 내의 timezone 설정

Jenkins Container가 제대로 생성된 것을 확인!

[root@jenkins devops-pipeline]# docker ps
CONTAINER ID        IMAGE                    COMMAND                  CREATED             STATUS              PORTS                                              NAMES
d8cbbb69e267        jenkins/jenkins:latest   "/sbin/tini -- /usr/…"   2 minutes ago       Up 2 minutes        0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp   jenkins


GCP 방화벽(Firewall) 설정

  • 기본적으로 Jenkins는 8080포트를 사용하기에 GCP에서의 외부 통신을 위해선 방화벽 설정이 필요합니다.

그림과 같이 인스턴스의 [네트워크 세부정보 보기] 탭으로 접속합니다


[방화벽 규칙] - [방화벽 규칙 만들기] 탭을 이용해 아래와 같이 규칙을 생성합니다.

  • 0.0.0.0/0은 모든 IP 대역에 대한 허용입니다. 현재는 기능테스트를 위해서 모든 대역으로 잡아놨지만 후에 특정 인스턴스의 IP로만 허용 할 예정입니다

그럼 아래 같은 방화벽이 추가된 것을 GCP에서 확인 할 수 있습니다.

스크린샷, 2020-09-22 12-16-29


이제 브라우저로 젠킨스에 접속 해봅시다

  • 접속 주소는 http://인스턴스 외부 IP:8080 입니다.

즉 GCP에서 인스턴스에 외부 IP 설정이 필요합니다!!

스크린샷, 2020-09-22 13-28-43


해당 인스턴스의 외부 IP : 34.64.93.209로 접속!!

  • 이렇게 Jenkins가 지원하는 웹페이지가 정상 구동됩니다

Administrator password에는 다음의 명령어로 확인되는 코드를 입력해줍니다.

docker exec -it jenkins cat /var/jenkins_home/secrets/initialAdminPassword

해당 어드민 키를 입력 후 기본적인 정보들을 입력하면 아래와 같이 페이지를 볼 수 있습니다

스크린샷, 2020-09-22 13-43-21



이제 gitlab과 연동해봅시다.

  • 주로 외부 저장소로 GITLAB, GITHUB를 많이 이용하는데 이번 포스트에서는 gitlab을 사용해보겠습니다.

gitlab Gitlab 로그인 후 Settings 메뉴에 접속합니다


아래와 같은 설정으로 토큰을 생성 해줍니다


생성 후 토큰 값이 나올텐데 기록해두세요!!



Docker in Docker (DinD) 작업


우선 Docker를 이용해 이미지 Build 및 Push를 위해 플러그인을 설치해줍니다

123



Jenkins에서 GitLab과 연동을 위한 Credential 추가

  • 우선 Jenkins에서 GitLab token을 사용하는 Credential을 생성합니다.

스크린샷, 2020-09-22 14-54-54

  • docker-build-step, Docker, Docker-pipeline 세가지!

Docker in Docker 구성


Docker Container 접속

$ docker exec -it jenkins bash

Docker설치를 위한 Shell 다운로드

$ curl -fsSL get.docker.com -o get-docker.sh

Docker install shell script 실행

$ sh get-docker.sh

docker 실행 가능 여부 확인

$ docker ps
CONTAINER ID        IMAGE                 COMMAND                  CREATED             STATUS              PORTS                                              NAMES
094c32442200        nasa1415/devops:0.1   "/sbin/tini -- /usr/??   About an hour ago   Up About an hour    0.0.0.0:8080->8080/tcp, 0.0.0.0:50000->50000/tcp   jenkins


여기까지 Jekine에 대한 CI 환결성정은 완료되었습니다.


Build 할 Docker 이미지를 준비합니다.

FROM ubuntu:18.04
RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime
RUN apt upgrade -y
RUN apt-get update -y
RUN apt-get install nginx -y
RUN echo "daemon off;" >> /etc/nginx/nginx.conf

CMD ["nginx"]
  • 위와 같이 간단한 우분투 생성 DockerFile을 만들어서 배포해보죠

✌ (CI) 이미지 Build & push


그전에 배포를 위해 Docker-Hub의 인증키를 생성합니다

  • Jenkins->Credentials->global->Add Credentials

  • 위의 캡쳐와 같이 DOCKERHUB의 ID와 PASSWORD를 적어서 인증키를 생성합니다

생성된 인증키를 확인합니다

스크린샷, 2020-09-25 11-42-25


이제 배포를 위해 Jenkins에서 새로운 item을 누르고, pipeline 선택 후 item의 이름을 입력해주세요.


Pipeline 메뉴에서 Definition을 Pipeline script from SCM을 선택합니다.

  • 이제 Script path를 물어보게 되는데, jenkinsfile-build에 각 단계를 규정해서 액션을 지정하면 됩니다.

  • 레포지토리 항목에는 연동 할 레포지토리 주소를 적어줍니다. 저의 경우 gitlab

모든 설정을 마무리하고 SAVE를 누르면 아래와 같이 아이템이 생성됩니다.

스크린샷, 2020-09-25 11-46-02



Build & Push


git 저장소에 DockerFile과 Jenkinsfile-nasa를 넣어줍니다

  • 저의 경우 GITLAB과 사용하는 노트북저장소를 연결시켜 놨습니다
root@nasa1515:/gitlab/devops-pipeline# ls -alrt 
합계 24
drwxr-xr-x 3 student student 4096  9월 22 15:55 ..
-rw-r--r-- 1 root    root      45  9월 22 16:00 README.md
-rwxrwxrwx 1 root    root     208  9월 24 17:56 Dockerfile
-rwxrwxrwx 1 root    root     355  9월 24 18:10 Jenkinsfile-nasa
drwxr-xr-x 8 root    root    4096  9월 24 18:11 .git
drwxr-xr-x 3 root    root    4096  9월 25 11:50 .

Jenkinsfile-nasa

node {
    stage('Clone repository') {
        checkout scm
    }
    stage('Build image') {
        app = docker.build("nasa1415/devops")
    }
    stage('Push image') {
        docker.withRegistry('https://registry.hub.docker.com', 'nasa1415') {
            app.push("${env.BUILD_NUMBER}")
            app.push("latest")
        }
    }
}


이제 생성한 아이템에서 Build Now 버튼을 눌러 빌드해봅시다


그럼 빌드가 실행되고, 로직을 보여줍니다


이제 Docker Hub에도 빌드 Numver : 10으로 이미지가 업로드가 된 것을 확인 할 수 있죠.


CI 자동화


일일히 Build 버튼을 누르면 너무 귀찮으니 GITLAB 저장소에 Push Event 발생시 자동 빌드되도록 설정하겠습니다.

  • 우선 GITLAB에서 Access Token을 발급해줍니다

스크린샷, 2020-09-25 12-04-21

  • USER - SETTING - ACCESS TOKEN 메뉴로 들어가 아래와 같이 입력 후 발급된 키를 기억해 두세요

jenkins에서 발급한 키로 아래와 같이 인증키를 생성합니다!

스크린샷, 2020-09-25 12-04-21



이제 Jenkins에서 Credential을 Global Settings에 Gitlab으로 추가해줍니다

  • Jenkins와 Gitlab 연동을 위한 Jenkins의 Manage Jenkins에 Configure System에서 아래와 같은 설정을 추가합니다. credential은 앞서 생성한 credential을 선택합니다.

스크린샷, 2020-09-25 12-07-17

  • 참고할것은 URL내에 http:// 를 필히 입력해야 합니다. URL은 생성해둔 GITLAB의 프로젝트 URL 입니다!!


Jenkins에서 자동 Build trigger 설정


아까 생성해둔 아이템에서 설정에 들어가 아래 메뉴에서 웹훅 URL을 확인합니다

  • 해당 설정 적용 시 build가 push시 자동으로 이루어지도록 합니다. 여기서 webhook URL정보가 출력되니 기억 해 두어야 합니다.

저의 경우 URL: http://34.64.94.209:8080/project/image 입니다.


🙌 GitLab에서 integration webhook 등록


이제 GitLab에서 Push Event가 발생되면 Jenkin의 Job을 build 하는 webhook을 생성하도록 해보겠습니다.


아래와 같이 GitLab의 해당 project에 settings→ integration 으로 이동하여 webhook을 생성합니다.

  • 방금 전 확인했던 URL을 입력하면 됩니다!!

다음과 같은 에러가 발생했습니다

스크린샷, 2020-09-22 15-28-46

  • 검색 결과 WebHook 생성 시 URL만 기입하고 Secret 토큰을 기입하지 않아서였다…

Jenkins 에서 만든 프로젝트에서 설정에 들어가면 아래와 같이 genarator로 발급받을 수 있습니다.


웹훅이 제대로 생성되었다면 테스트 해봅시다

  • 아래 생성된 웹훅에서 Push Events를 클릭하여 테스트 진행해보죠

그럼 아래처럼 정상적으로 푸시 이벤트를 전송했음을 확인 할 수 있습니다

스크린샷, 2020-09-25 12-20-30


자 그럼 이제 모든 설정이 완료되었습니다 git push를 날렸을때 테스트 해보죠

root@nasa1515:/gitlab/devops-pipeline# ls -lart 
합계 28
drwxr-xr-x 3 student student 4096  9월 22 15:55 ..
-rw-r--r-- 1 root    root      45  9월 22 16:00 README.md
-rwxrwxrwx 1 root    root     208  9월 24 17:56 Dockerfile
-rwxrwxrwx 1 root    root     355  9월 24 18:10 Jenkinsfile-nasa
drwxr-xr-x 8 root    root    4096  9월 25 11:57 .git
-rw-r--r-- 1 root    root       5  9월 25 12:22 gitlab-push-test
drwxr-xr-x 3 root    root    4096  9월 25 12:22 .
root@nasa1515:/gitlab/devops-pipeline# git add -A
root@nasa1515:/gitlab/devops-pipeline# git commit -m "event test"
[master 51f5052] event test
1 file changed, 1 insertion(+)
create mode 100644 gitlab-push-test
root@nasa1515:/gitlab/devops-pipeline# git push gitlab
Username for 'https://gitlab.com': nasa1515
Password for 'https://nasa1515@gitlab.com': 
오브젝트 개수 세는 중: 5, 완료.
Delta compression using up to 8 threads.
오브젝트 압축하는 중: 100% (4/4), 완료.
오브젝트 쓰는 중: 100% (5/5), 450 bytes | 450.00 KiB/s, 완료.
Total 5 (delta 2), reused 0 (delta 0)
To https://gitlab.com/nasa1515/devops-pipeline.git
e901329..51f5052  master -> master
  • 저는 다음과 같이 gitlab-push-test라는 파일을 생성해서 PUSH 했습니다

그럼 Jenkins 에서는 Push Event를 읽어와 다름과 같이 자동 빌드합니다


Tags

#DevOps#Jenkins
NASA1515

NASA1515

Data Engineer

Hello I'M Wonseok aka NASA1515

Expertise

Public Cloud
k8s/Docker
Python

Social Media

instagramwebsitelinkedingithub

Related Posts

[DevOps] Maven을 사용한 Java Application 빌드 및 배포 & DevSecOps Pipeline 통합 및 자동화 고도화
[DevOps] Maven을 사용한 Java Application 빌드 및 배포 & DevSecOps Pipeline 통합 및 자동화 고도화
2021-08-20
1 min

Topics

CloudDevelop

Social Media