티스토리 뷰

반응형

이번에는 저번부터 진행했던 서버 마이그레이션에 이어서 실제 서버에 배포도구로 사용할 젠킨스 서버를 구축하려고 하였습니다. 기존에 사용했던 서버의 스펙은 아래와 같습니다. 

 

EC2 Ubuntu 20.04 (x86)
4GB RAM / 2vCPU

 

이전 글에서 제가 아마존 리눅스2 OS로 변경하면서 아키텍쳐도 같이 변경되어 비용이 절감되었다고 글을 작성한 적이 있었습니다 :)

https://abbo.tistory.com/304

 

AWS EC2 Amazon Linux 인스턴스 생성하기

이번에 AWS Summit 을 확인하고나서 DevOps 중에 비용을 줄이고 고도화를 진행할 필요가 있다고 생각하여 현재 사용중이었던 인스턴스들을 전부 Amazon Linux (아마존 웹 서비스에서만 제공하는 인스턴

abbo.tistory.com

 

아무래도 기존에 사용하였던 아키텍쳐와 운영체제가 다른 점을 참고하다보니, 실제 서버에서 사용하고 있는 Docker Image 파일로 Jenkins 배포 서버를 구축하면 어떨지 싶어서 전환을 하던 와중의 내용을 글로 작성해보려 합니다. 

Docker 설치와 ECR 설정까지 추가를 하는 경우 글이 많이 길어질 것을 우려해서 이전에 제가 작성해둔 글을 링크로 걸어두려고 합니다 :)

https://abbo.tistory.com/306

 

ARM Amazon Linux2 Docker Compose 설정하기

저번 글에서 AMI 를 생성하여 EC2를 본격적으로 세팅해보려고 합니다. Amazon Linux2 설정하기 1. 접속하기 기본적으로 인스턴스를 생성하게 되면 ec2-user 라는 계정으로 접속이 가능하도록 설정됩니다

abbo.tistory.com

https://abbo.tistory.com/308

 

AWS의 DockerHub 인 ECR 에 대해 알아보자

Docker를 사용하면서 뭔가 배포와 관련된 내용들을 많이 올리게 되었습니다. 그래서 그런지 Dockerfile로 생성한 Image들의 대한 관리가 이루어지는 원격 리포지토리가 없을까 생각하다가 찾아보니 Do

abbo.tistory.com

 

아래 내용은 로컬에서 작업을 진행하고 실제 서버에는 이미지 파일과 리소스 파일만 올려두었습니다.

 

1. Docker Image pull & run

가장 먼저 Jenkins 의 이미지를 Pull 받아야 할 것입니다. 하지만 몰랐던 부분이 있었습니다. 마이그레이션을 하기 전에 구축하였었을 때는 jenkins 라는 이미지 명으로 그냥 다운로드를 받으면 되었지만, 현재 해당 이미지는 deprecated 되어버려 사용이 불가능하였습니다. 찾아보니 jenkins/jenkins 라는 이미지로 현재 지원중에 있었습니다. 

docker pull jenkins/jenkins:lts

lts는 최근 버전을 의미합니다.

 

pull 이 정상적으로 잘 진행되었다면 아래 명령어로 시작이 가능합니다. 

docker run -p 80:8080 -p 50000:50000 -v ~:/var/jenkins_home jenkins/jenkins

 

포트를 2개 사용하는 이유는 볼륨마다 다르게 설정하기 위함인데, 저는 처음에 80 하나만을 사용하긴 했었습니다. 50000 포트는 젠킨스의 플러그인들을 설치하는데 사용합니다. 이는 다시 세팅하면서 Dockerfile로 변환되긴 해서 이후에 이미지를 빌드하기 위해 docker build 명령어를 사용했습니다.


2.  도커 이미지의 Jenkins 기본 설정하기

다음으로 Jenkins의 설정에 대해 알아보려 하는데 이는 이전에 제가 작성한 글에도 나와 있더라구요. Docker라고 하여 설정 방법이 다른줄 알았지만 초기 비밀번호의 세팅 방법은 같았습니다.

https://abbo.tistory.com/185

 

Ubuntu 20.04 Jenkins 설정하기

지난 글에서 ubuntu 20.04에 jenkins를 설정하였다면 이번에는 접속방법과 포트 변경 방법을 알아보고자 합니다. 1. 포트 변경방법 sudo vi /etc/default/jenkins 이제 아래 부분을 사용할 포트로 변경합니다.

abbo.tistory.com


3. 기존에 사용했던 리소스 다운로드

사실 이 부분에서 제일 많은 염려가 되었습니다. 기존에 사용하였던 아이템들과 Git이나 Gradle, Docker 플러그인들의 설치가 전체적으로 잘 진행될지 걱정이었습니다. 우선 리소스 파일을 전부 다운로드하고 그 리소스를 Docker Image의 볼륨에 추가를 하여 설정하는 것을 먼저 찾아보았습니다. 

기존에 사용하였던 ubuntu 에서의 jenkins 파일들은 전체적으로 내용이 원격 리포지토리에 따라 워크스페이스가 분리되어 있어 같은 디렉터리가 아닌 다른 곳에 위치하는 경우도 있었지만 저의 경우 아래의 디렉터리를 Docker Image의 볼륨으로 잡고 시작했습니다. 그렇게 하기 위해서는 기존에 사용하고 있던 Jenkins 서버를 잠시 내려야만 했습니다. 왜냐면 서버가 작동하면서 추가로 들어오는 요청이라던지 설정이 변경될 소지가 있기 때문입니다. 

기존의 젠킨스 워크스페이스 Directory: /var/lib/jenkins

다운로드가 전부 완료되니 약 7GB의 리소스를 사용중이었습니다. 그래서 다운로드받는데만 대략 3시간 정도가 걸린 것 같습니다. 2번에서 Jenkins 기본 세팅을 하는데 플러그인을 다운로드받고 약 1시간 정도가 걸린거에 비하면 리소스 파일을 CDN을 사용하는게 아닌 모두 로컬 스토리지에서 사용하기 때문인 것 같습니다.


4. Dockerfile 설정하기

데이터 마이그레이션이 전부 끝난 후 volume 을 다운로드받은 디렉터리로 설정하고 build하기 위해 아래와 같이 Dockerfile 을 생성하였습니다. 

먼저 Dockerfile을 기반으로 이미지를 빌드하는 명령어는 아래처럼 입력하면 됩니다.

docker build ~ -t jenkins-server

Dockerfile

FROM jenkins/jenkins:lts
LABEL maintainer=abbo
LABEL version=1.0
USER root
VOLUME ~/jenkins:/var/jenkins_home

 

하지만 이렇게 설정하고 build를 진행한 경우 빌드는 정상적으로 진행되지만 다른 설정을 bash 로 들어가서 설정하는게 불가능했습니다. 아무래도 가상 머신위에서 작동되는 이미지이다보니 인증과 관련된 부분에서 제대로 진행되지 않는 것이었습니다. 

위의 Dockerfile을 사용하였을 때 발생한 에러는 아래처럼 나왔습니다.

일부 내용은 회사와 관련된 정보라서 지웠습니다 ㅎㅎ

  • Plugin 업데이트가 되지 않음 (특히 배포 서버 내에 Docker Image를 빌드해서 ECR에 푸시하는 내용이 있는데 Docker 설치가 안되었다고 나옵니다. 
  • awscli가 설치되어 있지 않다고 뜸
  • 아이템 실행 시간(배포 시작시간)이 UTC임
  • 다른 라이브러리 업데이트가 root 권한으로 하여도 불가능함 (sudo 명령어가 통하지 않음)

 

그래서 이를 해결하기 위해 찾아본 결과 Dockerfile에 여러 가지 부가 옵션들이 추가되게 되었습니다. 

RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime \
    && apt-get update \
    && apt-get install -y ca-certificates curl gnupg lsb-release htop sudo vim unzip \
    && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
    $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
    && apt-get update -y \
    && apt-get install -y docker-ce docker-ce-cli containerd.io systemctl \
    && usermod -aG docker root
    
RUN apt install python3-pip -y
RUN pip3 install awscli

옵션을 하나씩 설명해보도록 하겠습니다. RUN은 하나의 명령어 실행 옵션 (/bin/sh가 앞에 붙어 작동하는 Cmd)입니다.

 


ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime \

이미지내에서 Timezone을 설정합니다. docker-compose.yml 파일 안에서 설정도 가능합니다.


apt-get update && apt-get install -y ca-certificates curl gnupg lsb-release htop sudo vim unzip

apt-get 을 업데이트하고 추가적인 서비스들이 처음에 시작했을 때 설치가 안되어 있어 설치해줍니다. 또 Docker 이미지 내의 인증서 오류를 해결해줍니다.


curl -fsSL https://download.docker.com/linux/debian/gpg | 
gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \ 
&& echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian 
\ $(lsb_release -cs) stable" 
| tee /etc/apt/sources.list.d/docker.list > /dev/null \

Docker Image 내에 Docker Plugin을 사용할 수 있도록 도커를 다운로드받고, 이 도커를 지금 Jenkins를 사용하는 Docker container와 경유합니다. 그리고 위 옵션이 실행되면 아래 옵션도 사용할 수 있게 됩니다.


apt-get update -y \
    && apt-get install -y docker-ce docker-ce-cli containerd.io systemctl \

Docker 패키지를 다운로드하고 링크를 걸어두었기 때문에 서비스에 등록하기 위해 docker 관련 서비스들을 apt-get 명령어를 사용하여 설치해줍니다. 


usermod -aG docker root

Docker 사용자의 권한을 root로 설정합니다.


RUN apt install python3-pip -y
RUN pip3 install awscli

실제로 원래 서버에서는 apt install awscli 로 설치가 가능한 부분이지만, 권한 문제 때문에 설치가 안되는 증상이 발생해서 pip3을 경유해서 설치하는 옵션입니다.

 

4-1. Dockerfile 에 AWS CLI 인증 파일 넣기 

aws-cli를 사용하기 위해서는 AMI에 인증된 credentials 파일을 사용하는데 여기서 로그인 명령어를 젠킨스가 런타임중에 실행해주지 않으면 cannot login 에러가 발생하여 ECR로 발생하는 시점에 오류가 발생합니다. 그렇기 때문에 Dockerfile 에서 RUN 이 끝난 후 fc-login.sh 파일을 복사하는 옵션을 추가해줍니다.

COPY fc-login.sh /usr

그리고 fc-login.sh 파일 안에 아래와 같이 실행하는 명령어를 넣어줍니다.

aws ecr get-login-password --region ap-northeast-2 | docker login --username AWS --password-stdin ${ECR_ID}.dkr.ecr.ap-northeast-2.amazonaws.com

그래서 최종적으로 작성된 Dockerfile은 아래와 같은 모습입니다.

FROM jenkins/jenkins:lts

LABEL maintainer=abbo
LABEL version=1.0
ENV DEBCONF_NOWARNINGS yes
USER root

RUN ln -sf /usr/share/zoneinfo/Asia/Seoul /etc/localtime \
    && apt-get update \
    && apt-get install -y ca-certificates curl gnupg lsb-release htop sudo vim unzip \
    && curl -fsSL https://download.docker.com/linux/debian/gpg | gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg \
    && echo "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/debian \
    $(lsb_release -cs) stable" | tee /etc/apt/sources.list.d/docker.list > /dev/null \
    && apt-get update -y \
    && apt-get install -y docker-ce docker-ce-cli containerd.io systemctl \
    && usermod -aG docker root

RUN apt install python3-pip -y
RUN pip3 install awscli

COPY fc-login.sh /usr

VOLUME /home/ec2-user/jenkins:/var/jenkins_home

5. Docker Image 다시 빌드하기 

위에서 만들어진 Dockerfile을 기반으로 docker image를 다시 빌드합니다.

docker build -t jenkins_awscli .

여기에서 만들어지는 이미지의 명은 jenkins_awscli 가 되고, 이미지는 아래의 docker compose에서 사용하게 됩니다.


6. docker-compose.jenkins.yml 파일 설정하기

이번에는 docker-compose를 사용하여 docker image를 docker container 내에 띄울 준비를 할 세팅 파일을 준비합니다. 

version: '3.8'

services:
  jenkins-server:
    restart: always
    container_name: jenkins-server
    image: jenkins_awscli
    ports:
      - 80:8080
      - 50000:50000
    environment:
      - TZ=Asia/Seoul
      - CATALINA_OPTS=-Xms1024M -Xmx4096M -XX:MaxPermSize=1024m
    volumes:
      - "~/jenkins:/var/jenkins_home"
      - "~/.aws:/root/.aws"
      - /var/run/docker.sock:/var/run/docker.sock
    deploy:
      update_config:
        delay: 10s
        order: start-first
        failure_action: rollback

위 내용에서는 설명할 것이 key: value 형식으로 명시가 되어있습니다. 

  • jenkins-server: Docker Compose 에서 관리하는 컨테이너의 명입니다. 
  • restart: Docker compose 서비스가 시작할 때 자동으로 실행되는지의 옵션입니다. always는 항상 자동실행할 때 씁니다.
  • container_name: 보통 컨테이너 이름과 많이 맞춥니다.
  • ports: 처음에 이미지 빌드 할 때 썼던 포트들의 넘버입니다. 2개를 사용한 것은 80은 jenkins 접속 경로, 50000은 플러그인 설치 전용 포트입니다. 
  • environment: 실행되면서 환경 변수를 입력할 수 있습니다. TZ는 타임존 세팅이고, CATALINA_OPTS는 jenkins 가 JVM을 기반으로 실행되기 때문에 메모리 옵션을 주게 되었죠. 
  • volumes: 사용하려고 하는 컨테이너의 볼륨값입니다. 여기서 ':'을 기준으로 나뉘게 되는데 왼쪽은 내 로컬/서버 디렉터리가 되고 오른쪽은 docker 가상 이미지 내 경로입니다. 특이한 것은 jenkins_home을 기존의 /var/lib/jenkins와 매핑시킨 것은 이해가 가지만 docker.sock 파일을 로컬의 도커와 같은 양식으로 매핑시켜 서버의 도커를 경유한다는 방법이었습니다. 이런 방식을 DooD(Docker out of Docker) 방법이라고 합니다. 
 

도커 컨테이너 안에서 도커 실행하기(Docker in Docker, Docker Out of Docker)

이번 시간은 도커를 사용해 컨테이너에서 컨테이너를 실행하는 방법을 알아봅니다. 도커 컨테이너 내에서 ...

blog.naver.com

  • deploy: 이미지가 시작된 후에 배포 옵션을 걸수도 있습니다. 

 

6-1. AWS 인증서 

현재 디렉터리 내를 username 이라고 하면 /Users/username/.aws 가 제대로 존재하는지 확인해보아야 합니다. Amazon Linux의 경우 기본 사용자 디렉터리인 /home/ec2-user/.aws 가 될 것입니다.

Jenkins 컨테이너 내에 awscli를 설치하였기 때문에 container 내에서 명령어를 실행하는 것은 문제가 없지만, 파일이 존재하지 않은 경우 인증과 관련된 문제가 발생할 수 있습니다. 그래서 aws configure 명령어를 container kernal 안에서 실행하는 것보다 물리적으로 존재하는 파일을 volume 설정하면서 넣어주는게 좋습니다. 

기본적으로 .aws 디렉터리 안에는 credentials 이라는 확장자가 없는 파일이 존재하게 되는데 aws 명령어를 사용하면 이 경로를 직접 체크하게 됩니다. 그래서 volumes 내에 "~/.aws:/root/.aws" 라는 디렉터리가 들어가게 되었습니다.

.aws/credentails

[default]
aws_secret_access_key = <key>
aws_access_key_id = <key>

이렇게 설정한 경우 IAM에서 생성한 값들을 각각 넣어주면 됩니다. 액세스 키를 생성하는 방법은 아래 링크를 참조하시면 됩니다!

https://abbo.tistory.com/307

 

AWS CLI 설치하기

AWS 를 사용하다 보면 AWS CLI 라는 녀석이 있는데 이 녀석은 무엇일까요? 우리는 서버에 접속할 때 대부분 cli 기반으로 움직이고, 특히 AMI 서비스를 많이 운영하는 AWS 에서는 자체 서비스를 운영하

abbo.tistory.com


7. Docker Compose 명령어를 활용해 Docker Image 실행

이렇게 docker-compose.yml 파일이 만들어지면 한 번 로컬에서 실행해봅니다. 

docker-compose -p jenkins-server -f docker-compose.jenkins.yml up -d

 

잘 실행이 되었다면 이 이미지 파일을 ECR에 올리거나 SFTP를 사용하여 리소스 파일을 올린 후 Dockerfile build -> Docker Compose up 명령어를 실행해 젠킨스가 잘 되는지 테스트합니다. 


8. Jenkins 페이지 체크 

Plugin이 기존의 버전에 물려있어 업데이트가 필요할 경우도 있습니다. 그리고 마이그레이션을 진행하면서 누락된 아이템들, 배포 스크립트와 다른 SSH credential 들의 연결구조가 잘 유지되어 있는지 체크해볼 필요가 있습니다. 

 

마무리

진짜 기존의 사용하던 Jenkins 세팅과 Docker Jenkins Image 구성하는 방법이 너무 달랐기에 러닝 커브도 심하고 계속계속 테스트를 하는 과정이 생각보다 험난하기도 하였습니다. 그치만 한 번 구성해두니 진짜 손쉽게 서버 마이그레이션을 가능하도록 할 수 있어 (많이 쓸 일은 드물겠지만..) 상당히 유용하다는 생각이 들었습니다. 

Reference: https://pks2974.medium.com/jenkins-%EC%99%80-docker-%EA%B7%B8%EB%A6%AC%EA%B3%A0-aws-cli-%EC%82%BD%EC%A7%88%EA%B8%B0-%EC%A0%95%EB%A6%AC%ED%95%98%EA%B8%B0-e728986960e2

 

Jenkins 와 Docker 그리고 AWS CLI 삽질기 정리하기

최근에 Jenkins 서버를 분리할 일이 생겼는데, Jenkins 를 다시 설정 하면서 배웠던 삽집기를 정리 해보고자 한다.

pks2974.medium.com

 

반응형
댓글
공지사항