본문 바로가기
연구소👨‍💻/CS연구소

EC2-NGINX-도커-젠킨스 설정

by 신그자체김상범 2024. 11. 6.

이런 것에 대한 정보를 담고 있다

  1. 젠킨스를 설정하는 법.
  2. 젠킨스를 도커 안에서 여는 법
  3. EC2 속 젠킨스를 운영하는법.
  4. 엔진엑스와 도커 연결
  5. 작업 간 이슈

이런 것에 대한 정보는 담겨있지 않다

  1. 젠킨스 CD하는법 (아직 안 함)

1. 젠킨스를 설정하는 법.

젠킨스는 보통 커밋, 푸시와 이에 대한 통합과 배포를 자동화하는 것으로 유명하다. 그리고 생각보다 처음 접근할때 어렵게 느껴지는 내용중 하나다. 하지만 막상 하나씩 떼어놓고 보면 우리가 의식으로 해석하는데 어려움이 없다

1. 1 젠킨스는 어디에 위치하냐.

통합과, 자동화라는 측면에서만 해석한다면 젠킨스는

“서로 다른 환경에서 프로젝트의 버전 차이를 인식하고 사람이 손쓰기 전에 통합한다.“라고 정의할 수 있겠다.

즉 젠킨스는 서로다른 개발환경 사이에 위치한다. 그리고 커밋같은 버전차이를 인식하게 되면 자동으로 이를 통합한다는건, 반대편에서 pull이나 merge를 버전을 일치시켜주는 것과 같다. 따라서 젠킨스는 서로 다른 개발환경 사이에 존재하며 간단한 프로젝트의 경우에 한하겠지만, 버전 통합등을 위해 주로 업데이트를 시켜줘야하는 배포환경에 많이 위치한다.

1. 2 젠킨스엔 어떤 기능이 필요하냐

예를들어 내가 프로젝트를 내 노트북과 EC2 두개의 환경에 담았다면 주 개발환경은 당연히 노트북이고, EC2는 배포 환경이 될 것이다. 이런 상황에서 원래는 노트북에서 커밋, 푸시를 하면 EC2에서 통합, 배포를 해줘야 했다.

하지만 젠킨스가 존재한다면 github같은 서버가 버전이 업데이트 됐다는 정보를 젠킨스가 받게하고 이에따라 pull 요청을 보내고 데이터를 받을 수 있게 함으로써 버전 통합을 자동화 할 수 있는 것이다.

따라서 젠킨스가 필요로 하는 기능은

  1. github 같은 원격 저장소에서 보내주는 신호를 받고 행동을 할 수 있는 기능
  2. 신호를 받는 것과 pull 요청을 보내는 일을 위해 원격 저장소와 통신할 수 있는 기능
  3. pull 받은 데이터를 실제 배포환경에 적용하는 기능

3가지가 필요하다고 볼 수 있다. 일단 이번에는 3가지 기능중 1, 2번을 구현하는 방법에 대해서 설명한다.

2. 젠킨스를 도커 안에서 여는 법

일단 젠킨스는 외부 영향을 최소화하는걸 지향하기 위해서 도커로 열려고 한다. 이걸 위해선 우선 도커 파일을 정의해줘야한다.

FROM jenkins/jenkins:jdk17 AS jenkins

USER root
RUN apt-get update &&\\
    apt-get upgrade -y &&\\
    apt-get install -y openssh-client &&\\
    apt-get install sudo

RUN apt-get install -y systemctl &&\\
        apt-get install -y vim

COPY ssh/ .ssh/
COPY default/jenkins etc/default/jenkins
EXPOSE 8080 8085

FROM 구문에서는

 

3. EC2 속 젠킨스를 운영하는법.

젠킨스를 처음 키면 앞서 말한 신호를 받는 기능, 요청을 보내는 기능이 필요하다. 그러기 위해서는 당연히 어떤 보안 관련된 작업이 먼저 오가야한다.

3.1 젠킨스 관리 → Credential : 보안 설정을 하는 곳

이 탭에 들어가면 Credential을 만들 수 있는 페이지가 뜬다 여기서 새로운 젠킨스 Credential을 만들 수 있다. Credential은 당연히 내 젠킨스가 프로젝트의 정보를 요청할 수 있는 곳과 연결된 보안 정보여야한다. 깃허브의 경우 깃허브의

3.2 Profile → Developer Setting → Personal access tokens → Tokens : 토큰 만드는 장소

나는 인증방식으로 깃허브의 토큰을 선택했다. 유지 기간이 짧아서 잃어버려도 크게 걱정할 필요가 없고, 만들기도 쉽기 때문이다. 토큰을 만드는 경로는 깃허브에서 위의 경로를 따라가면 되고 자세한 설명은 이외에도 많으니 하지 않는다.

일단 토큰을 생성하면

Credentia을 만드는 페이지에

Kind : Username with password

Username : 토큰을 발급받은 깃허브 아이디

Password : 발급받은 토큰의 값

ID, Description : 필수는 아니지만 나중에 앱에서 인증을 확인할 때 구별하기위해 특징적으로 짓는다.

와 같은 값들을 채워고 생성한다. 이제 그러면 외부와 통신할 시스템만 만들어주면 된다.

3.3 Dashboard → 새로운 Item : 새로운 빌드 시스템 생성

위의 링크로 작업을 하나 생성하게되면 구성을 통해서 깃허브 경로나, pull을 받을 브랜치등을 설정할 수 있고 CD를 위해서 pull 작업뒤 해야할 일을 지시할 수도 있다.

소스코드 관리에서 git을 선택한뒤 git url을 작성한다 여기서 url은 pull 받을 github 브랜치의 코드창에 있는 경로중 하나를 복사하면 된다. ssh나 http방식 둘다 상관없다고 알고있으나 난 도커안에 젠킨스를 넣고 http 포트를 열어뒀기 때문에 일단은 http경로를 넣었다.

그리고 여기서 빌드유발탭의 GitHub hook trigger for GITScm polling을 체크한다 이걸통해서 나중에 깃허브가 보내는 업데이트 신호를 받을 수 있다.

3.4 해당 레포지토리 → Settings → Webhooks : 업데이트 신호를 설정

그리고 이제 github에서 내 ec2 ip와 웹훅에 필요한 경로를 설정해준다. 근데 여기서 이제 요청을 보내기 위해서는 url을 포트포워딩해서 전달해주는 과정이 필요하다. 그래서 이 기능을 위해 nginx를 설치하게된다.

4. etc → nginx → sites-available → default 엔진엑스와 도커 연결

	location /jenkins/ {
        proxy_pass <http://localhost:8085/jenkins/>;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_redirect <http://localhost:8085/jenkins/> /jenkins/;
		
        # 경로 재작성
				root /root/jenkins/war;
    }

다음의 파일을 분석한다.

  1. location : /jenkins
  2. nginx에서 location은 url을 치환하는 역할이라고 생각하면 된다 /jenkins/ 경로를 <ip>/jenkins 가 다른 위치로 치환되는 것이다
  3. proxy_pass는 location의 목적지에 해당하는 정보다. 현재 파일에선 http://localhost:8085/jenkins/로 치환된다
  4. proxy_redirect는 촉발된 리다이렉션에 대해 오른쪽의 위치로 리다이렉션 시켜준다.
  5. root는 이 로케이션에 대해서 소스파일들 (html, css) 등의 파일의 루트 경로가될 경로를 설정하는 칸이다.

이런 설정을

5. 프리티어 EC2에서 젠킨스 + 도커를 실행할시 발생한 문제

실서비스를 운영중이 아닌 이상 EC2를 결제해서 사용하는 사람들은 많지 않을 것이다. 그렇다보니 보통은 프리티어를 사용할텐데. 프리티어는 용량이나 메모리 측면에서 모두 낮은 성능이다보니 몇가지 어려움이 있다.

메모리 문제

ec2에서 제대로된 작업을 하기위해선 단순히 ssh로 연결되는 것 이상의 것이 필요하다. vscode등으로 remote -ssh 확장을 설치해 원격처럼 작업할 수 있다. 그러나 프리티어로 원격에 연결하다보면 심심찮게 원격이 꺼지는 현상을 발견할 수 있다. 이건 기본적으로 프리티어의 메모리가 작아서 그렇고, 이걸 해결하기 위해서는 더 좋은 상품을 결제하거나, 강제로 메모리를 늘리는 방법을 선택해야한다. 강제로 메모리를 늘리는 방법은 swapfile이라는 명령어를 통해서 할 수 있다.

포트 문제

내가 이번에 젠킨스를 설치하면서 가장 큰 어려움을 겪었던 부분이 리다이렉션 부분인데, 외부의 8085 포트를 도커 내부의 8080 포트와 연결하면서 nginx에서 소스파일을 로드하는데 큰 어려움을 겪었다. 젠킨스가 리다이렉션을 자동적으로 localhost:8080으로 하려하기 때문이다. 이걸 방지하기 위해선 애초에 포트를 동일하게 설정하거나 리다이렉션 처리를 제대로할 필요가 있다.

젠킨스 루트 url 초기 설정 문제

아마 도커파일에서

FROM jenkins/jenkins:jdk17 AS jenkins

다음과 같이 젠킨스를 설치하게 된다면, nginx에서 proxy_pass를 정하는데 문제가 있을 수 있다. 젠킨스는 기본 url을 localhost:8080/ 으로 설정해놓는 것으로 보인다. 근데 만약 8080 포트를 여러곳에 써야한다면 기본 젠킨스의 url을 localhost:8080/jenkins 와 같이 변형해서 입력해야할 수도 있다.

어떻게 url을 변경하는가?

다행히 이런 url변형을 ui에서 할 수 있으나 문제는 젠킨스를 재시작해야한다는 문제가 있다. 젠킨스 자체는 /restart url 에 접근해 할 수 있지만 젠킨스를 베이스로한 도커는 젠킨스가 종료되면 자동으로 도커도 종료된다. 컨테이너가 종료된다는건 데이터가 휘발된다는 것을 뜻하기에 설정이 고정이 안된다는 문제가 있다.

도커를 실행할 때 젠킨스설정을 하지 못하나?

물론 도커를 처음 Run 할 때 이것에 대한 대비를 할 수 있다. 도커에서 enviroment 변수를 통해 실행 환경의 설정을 할 수 있다. 다음은 내가 만든 도커 컴포즈 파일이다.

root/docker-compose.yml
version: "3"
services:
  jenkins:
    image: jenkins
    user: root
    environment:
      - JENKINS_OPTS=--prefix=/jenkins --httpPort=8085
    volumes:
      - ./jenkins:/var/jenkins_home
    ports:
      - 8085:8085
      - 8081:8081

environment을 통해서 포트와, 젠킨스 기본 url prefix를 설정해 놓은 것을 볼 수 있다. 다만 여기서 주의해야하는게 도커 컴포즈는 쌍따옴표설정을 먹지 않는다

- JENKINS_OPTS=--prefix=/"jenkins" --httpPort="8085"

예를들어 이런식으로 설정한다면 각각의 설정을 이해하지 못하고 터져버린다. 이점을 주의해서 설정해준다면 큰 문제는 없다.