jenkins를 이용한 자동화 배포 및 컨테이터 환경 구성 실습

2019-07-30

.

Data_Engineering_TIL_(20190713)

study program : https://www.fastcampus.co.kr/dev_camp_devb

[학습목표]

  • AWS에서 제공하는 네트워크 환경 이해

  • Jenkins를 기반으로 하는 자동화 배포 과정 진행

  • 컨테이너 환경으로 이전 준비

[학습기록]

1. AWS에서 제공하는 네트워크 환경 이해

  • AWS에서 제공하는 네트워크 환경중에 가장 큰 개념이 region이다. AWS는 글로벌 클라우드 컴퓨팅 서비스 밴더이기 때문이다. 이 region에 따라서 EC2나 ELB나 RDS같은 경우에는 내가 서울 region에서 생성했다면 서울 region에 있는 아마존 물리 장비에 생성되었다고 보면 된다.

  • AWS 클라우드 포메이션이나 테라폼과 같은 코드인프라 프로비저닝 툴을 이용하면 예를 들어서 서울에서 서비스하고 있는 인프라를 다른 region에 똑같이 배포할 수 있다. 클라우드 포메이션으로 인프라에 대한 스텍을 만들고 그대로 다른 리전에 배포하면 된다. 단 DNS나 엔드포인트는 당연히 그 리전에 맞게 설정은 해줘야 한다.

  • AWS region

1) 세계 각지에 위치한 AWS IDC

2) AWS의 서비스가 위치한 지리적인 장소이며, 글로벌 기준으로 지역적 위치를 묶어서 관리하는 단위. 즉 리전에는 여러개의 물리서버 센터들이 그룹핑 되어 있다는 말이다.

3) 사용자와 가까운 위치에 있는 리전일수록 응답속도가 빠르다.

4) 하나의 리전은 여러 개의 가용 영역(AZ)로 구성된다. 여기서 가용영역 = 물리서버센터라고 보면된다. 이 가용영역의 그룹이 region이다.

  • AWS AZ(Availability zone)

1) AZ = IDC (물리적으로 독립된 실제 컴퓨팅(베어메탈)이 운영되는 곳

2) 하나의 리전은 물리적으로 독립된 여러 곳의 IDC(가용 영역)으로 구성

3) 가용 영역은 low latency link로 연결되어 물리적으로 떨어져 생기는 네트워크 latency를 보장

4) 리전 / AZ를 통해 손 쉽게 멀티 IDC를 운영하는 이점을 가질 수 있음

5) 서울 리전은 세 곳의 AZ로 구성되어 있음

6) RDS의 Multi AZ 구성이 해당 개념을 바탕으로 구성됨 (고가용성 보장)

7) 예를들어서 서울 region 기준으로 RDS를 생성할때 고가용성 보장 옵션을 선택하면 우리는 하나의 RDS를 생성했지만 실제로는 세개의 AZ에 RDS가 생성이된다. 또는 로드밸런서 생성할때도 여러가용성에 구성한다는 옵션을 선택하면 우리는 하나의 로드밸런서를 생성하지만 실제로는 3대의 로드밸런서가 생성된다. 이렇게 세군대의 AZ에 똑같은 것을 만들어 두면 한곳의 AZ에 재난 등의 긴급상황시에도 다른영역에서 서비스를 해주면 되기 때문에 서비스의 안정성을 높여준다.

8) 과거 서울 리전(AZ 2개있던 시절)에서 고가용성의 ELB를 구축했다고치자. AZ의 한쪽 운영중인 로드밸런서가 다른 AZ의 EC2에 부하분산을 하면 가용영역이 한쪽과 다른한쪽이 물리적으로 떨어져 있기 때문에 네트워크 latency가 발생하지 않느냐라는 의문이 생긴다. 하나의 리전에 묶여 있는 각 AZ는 광케이블 등의 로우 latency링크로 묶여있다. 이말은 AZ의 한쪽에서 운영중인 로드밸런서가 다른 AZ의 EC2에 부하분산을 보낸다고해도 이 로우 latency링크를 통해서 보내기 때문에 물리적으로는 떨어져 있지만 마치 같은 곳에서 사용하는 것처럼 네트워크 성능을 보장해준다.

  • VPC

1) 한 리전 내 여러 가용 영역을 걸쳐 논리적으로 분리하여 독립적으로 구성한 AWS 계정 전용 가상 네트워크(Virtual Private Cloud)를 말한다. 계정별로 VPC를 구축하면 가용영역별로 컴퓨팅 리소스를 분산 배치하여 원하는 서비스 아키텍처를 구성할 수 있다.

000

2) AWS에서 기본으로 제공하는 논리적 가상 네트워크

3) 한 리전 내 여러 가용 영역을 걸쳐 운영 가능. 여러 리전에다가 VPC를 만들수는 없다는 말이다.

4) 필요한 경우 네트워크를 만들어 Private subnet, Public subnet을 운용할 수 있다

5) Public subnet 내 인스턴스(EC2, RDS, ELB 등등)는 외부 인터넷과 통신 가능한 public IP와 VPC 안에서만 사용 가능한 private IP를 할당받는다

6) Private subnet 내 인스턴스는 private IP만 할당받는다

7) VPC의 주요용도

7-1) 다른 계정에서 AWS 리소스 격리

7-2) 인스턴스와의 네트워크 트래픽 라우팅

7-3) 네트워크 침입으로부터 인스턴스 보호

7-4) 한 리전에선 최대 5개의 VPC 생성 가능

  • subnet

1) VPC의 아이피주소 범위를 말한다. VPC는 AWS에서 특정 아이피 대역을 할당해줘서 여기서만 쓸 수 있게 제공을 해주는 것인데 이 말은 VPC를 만들면 특정 아이피 대역 블록이 나에게 지정이 되는 것이다. 그러면 VPC 내에서도 예를들어 DMZ서버는 또 특정 아이피 대역을 분리해서 할당해주고 DB서버는 프라이빗 IP 대역만 할당해 줄 수 있다. VPC에서 아이피 대역을 할당해줬는데 서브넷은 할당받은 이 아이피 대역에 대해서 퍼블릭 서브넷, 프라이빗 버스넷 또는 필요한 용도에 따라서 IP 대역을 구분지을 수 있고 그거를 실현해줄 수 있는 방법이 서브넷이다.

참고로 디폴트 서브넷은 퍼블릭 서브넷으로 구성되어 있어서 인스턴스 등을 생성하면 퍼블릭 아이피와 퍼블릭 DNS를 부여받는다.

2) VPC의 ip 주소 범위

3) IP block을 구분 짓는 네 트워크 구성 그룹으로 각 가용 영역에 하나 이상의 서브넷 생성 가능

4) 지정된 서브넷으로 AWS 리소스(EC2, RDS 등) 실행

000-1

예를 들어 위의 오른쪽 그림처럼 서브넷을 두개 만들고 10.0.0.0/24 대의 블록에 위치에 있는 인스턴스들은 퍼블릭 서브넷으로 만들어 이 서브넷에 위치해 있는 인스턴스들은 퍼블릭 아이피를 부여해줄 수 있고, 반면에 10.0.1.0/24 대의 블록 위에 인스턴스들은 프라이빗 서브넷으로 지정하여 프라이빗 아이피만 부여할 수 있다. 위의 내용을 구체적으로 표현한 그림이 아래에 있는 그림이다.

000-2

위에 그림처럼 서브넷 위에 서브넷 블락 위에서 인스턴스가 생성이되면 해당 블락에 맞게 브라이빗 아이피가 자동으로 부여가 되고 VPC 내부의 인스턴스 끼리는 자유롭게 프라이빗 아이피로 통신이 가능하다.

프라이빗 서브넷의 인스턴스의 경우 퍼블릭 아이피를 부여하지 않아도 프라이빗 아이피로 VPC 내의 다른 인스턴스와 통신이 가능하다. 예를들어서 외부에서 들어오는 트레픽에 대해 퍼블릭 서브넷에 있는 엔진엑스 서버가 받아서 와스 트레픽이라고 판단하면 리버스 프록시로 프라이빗 서브넷에 있는 와스서버에 프라이빗 아이피로 쏴줄 수 있다.

000-3

VPC가 생성되면 자동으로 인터넷 게이트웨이와 라우터 라는 것이 만들어진다. 인터넷 게이트웨이는 말그대로 외부 인터넷에서 접속했을때 VPC 내에 인스턴스에 접근이 가능하도록 연결해주는 것이고, 라우터가 중요하다. 예를 들어서 퍼블릭 서브넷 내에 인스턴스로 트레픽이 가는 중에 라우터는 퍼블릭 서브넷이라는 것을 인지하고 해당 라우터에서 퍼블릭 아이피와 해당 인스턴스의 프라이빗 아이피를 키벨류 형태로 묶어서 테이블 형태로 관리하게 된다. 다시말해서 외부에서 퍼블릭 아이피 형태로 들어오면 라우터는 키벨류 형태로 되어 있는 아이피 세트를 검색해서 해당하는 인스턴스의 퍼블릭 아이피의 프라이빗 아이피로 보내주게 된다.

인터넷 게이트웨이는 외부에서 인터넷으로 접속할 수 있도록 말그대로 게이트 역할을 하는 놈(얘도 일종의 서버다)이고, 라우터는 퍼블릭 서버에 위치해 있는 인스턴스의 프라이빗 아이피를 가져와서 라우터 테이블 내에서 서로 매핑을 해줘서 인터넷 게이트로 들어오는 퍼블릭 아이피를 찾아서 보내준다.

정확하게 모든 VPC 안에 인스턴스들은 프라이빗 아이피만 부여가 되고 퍼블릭 아이피를 가지고 있는 얘는 라우터라는 얘가 프라이빗 아이피와 퍼블릭 아이피를 라우팅 테이블에 매핑해놓은 것이다.

  • 기존에 디폴트 VPC만 사용하던 우리가 앞으로는 아래 그림과 같이 네트워크 환경을 구성할 수 있다.

먼저 VPC와 프라이빗 서브넷을 만들고 나서 인스턴스 만들때 해당 서브넷을 선택해주면 된다.

000-4

2. Jenkins를 기반으로 하는 자동화 웹서버 배포 실습

  • 젠킨스 개요

1) 파이프라인을 통해 지속적인 통합(CI), 전달(CD) 환경 구축을 위한 툴

2) 거의 대부분의 언어를 지원 (자바 환경에 가장 적합)

3) CI/CD 툴 중 가장 많은 third-party 지원

4) 강력한 빌드, 테스트, 배포를 통합적으로 지원

지속적인 통합 : 개발자들이 개발하는 환경은 같은 개발환경이 되야 한다. 아무리 코드를 많이 개발하고 업데이트해도 우리가 만든 코드들이 개발자들이 동일한 테스트 시나리오를 할 수 있고, 모든 버전이 동일한 상황에서 배포를 해야하는데 이런 것을 젠킨스를 이용하면 할 수 있다.

지속적인 배포 : 우리가 관리하고 있는 인스턴스들이 한두대가 아닐것이기 때문에 인스턴스 하나하나에 SSH 접속해서 배포하는 일은 정말 번거롭고 어려운 일이다. 그래서 이 젠킨스는 이런 배포과정도 한번 설정해주면 자동으로 해준다.

  • 실습목표 : 젠킨스를 이용한 지속적인 배포과정 숙달. 웹 프로젝트가 있다고 하면 그 프로젝트를 수정해서 깃허브에 푸쉬하면 깃허브에서는 푸쉬가 되었다는 이벤트를 감지해서 우리의 젠킨스 서버에 깃푸쉬가 되었다는 이벤트 메세지를 깃허브 웹훅으로 보낸다. 깃푸쉬가 되었다는 것은 코드가 업데이트가 되었다고 우리가 정책으로 간주해서 젠킨스가 웹프로젝트 서비스를 제공할 인스턴스에 SSH로 접속해서 깃풀(프로젝트 업데이트)을 자동으로 해주는 과정을 실습할 것이다.

** 참고로 이번실습에 젠킨스 서버와 웹프로젝트 서비스를 제공할 인스턴스를 동일한 하나의 인스턴스로 사용할 것이다.

  • 실습상세

step 1) 젠킨스 사용을 위한 EC2 생성

  • 주의사항 : 젠킨스는 8080 포트를 이용하기 때문에 8080 포트 개방할 것

00

step 2) 젠킨스 사용을 위한 EC2로 접속하여 아래와 같이 명령어 입력 및 실행

1) yum -y update : yum 레포지토리를 최신 상태로 업데이트

2) yum install -y java-1.8.0 : java8 설치 (jenkins는 자바 환경에서 개발됨. 구동을 위해 설치)

3) wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo : yum이 어디서 jenkins를 설치해야 할지 알 수 있도록 Jenkins repository를 추가

4) rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key : Jenkins 를 설치할 때, 파일들이 신뢰할 수 있는 source 로 부터 제공됨을 증명하기 위해 로컬 GPG 키링에 Jenkins GPG key 를 추가

5) yum install -y jenkins : yum 레포지토리로 jenkins 설치

6) yum install -y git : 깃연동을 위해 설치

7) service jenkins start : 젠킨스 구동

8) netstat -na | grep 8080 : Jenkins가 구동 됨에 따라 8080포트가 열려있는 지(제대로 실행되고 있는 지) 확인

00-1

step 3) 젠킨스 사용을 위한 EC2의 {퍼블릭 아이피}:8080를 웹브라우저에 입력하면 아래와 같은 화면이 전시되고 아래와 같이 락이 걸린 젠킨스 화면이 보일 것이다.

그러면 젠킨스 설치한 EC2에 언락을 해제하는 키가 있는데 경로는 아래 그림과 같고 그걸 찾아서 키를 브라우저 화면에 복붙해주면 된다.

00-2

설치가 완료되면 계정을 임의로 만들어준다. 그리고 젠킨스 URL(깃허브 웹훅을 보낼 곳) 설정이 나오는데 디폴트값으로 그냥 사용하면 된다. 그 다음에 세이브 및 스타트 젠킨스 버튼을 누러준다.

step 4) 깃허브에서 웹프로젝트 생성

우리는 기존에 웹프로젝트를 만들어 놓은 것을 갖다가 사용할 것이다. 그래서 https://github.com/owen1025/Fastcampus-web-deploy로 접속을 먼저해준다. 그 다음 아래 그림과 같이 프로젝트를 fork해서 내 깃허브로 복사해서 가져온다.

00-3

step 5) 새로운 젠킨스 빌드아이템(잡 파이프라인) 생성

아래 그림과 같이 수행

1

아래 그림과 같이 빌드아이템이 잘 생성되었는지 확인

7

step 6) 생성한 빌드아이템에 대한 시스템 설정(나의 깃허브 계정 권한부여)

9

9-2

step 7) 푸쉬이벤트 발생 시 깃허브 웹훅을 젠킨스 서버로 보낼 수 있도록 설정

18

step 8) 아래 그림과 같이 실제 내 로컬피시에서 웹프로젝트를 수정하고 깃푸쉬를 했을때 내 젠킨스에 웹훅이 잘 오는지 테스트

22

우리는 깃허브 웹훅까지는 설정하고 아이템까지 실행이 되는 것은 확인했는데 우리가 지금 만든 아이템에는 아무런 내용이 없다. 예를들어 시나리오 테스트를 하라던지, 빌드를 하라던지 이런내용이 아무것도 없다. 그래서 우리는 웹훅 메세지가 젠킨스에 오면 이 아이템이 어떤 잡을 할지 설정을 해줄 것이다.

우리는 수동으로 웹서버에 ssh로 접속해서 수정된 프로젝트를 깃풀해서 웹서버를 최신버전으로 업데이트 했던 과정을 자동화하여 배포를 진행하는 것을 설정해줄 것이다.

step 9) 특정 엔진엑스 서버 인스턴스에 SSH로 접속하여 프로젝트를 업데이트 하는 플러그인 설정

일반적인 CI/CD 플로우 : 코드업데이트 -> 코드테스트 -> 빌드 -> 빌드결과물 배포

26

위의 빈공간으로 되어 있는 것들을 설정해줘야 한다. 그래서 일단 키파일 내용을 확인한다. 그리고 Jenkins 관리 - 시스템 설정 - 화면 중간에 위치한 Publish over SSH 탭으로 이동한 다음에 아래 그림과 같이 조치해주면 된다. 조치가 완료되면 다시 send build artifacts over SSH 설정으로 넘어와서 아래 그림의 같은 내용을 채워주고 저장해준다.

사실 아래 그림과 같이 SSH키를 직접 긁어다 붙이는 건 여러사람이 보는 젠킨스이기 때문에 상당히 위험한 방법임을 알고 있어야 한다.

35-2

[Send build artifacts over SSH]

1) SSH Server : 방금 설정한 SSH Server(배포할 인스턴스, nginx-ec2-instance) 선택

2) Transfers

  • Source files : 어떤 파일을 배포할 것인지 선택

  • **/* : 모든 파일

  • **/*.war : *.war 확장자를 가진 모든 파일

3) Remove prefix : 원격 서버에 배포 후 삭제할 디렉토리

4) Remote directory : 원격 서버에 배포 시 해당 파일이 위치할 디렉토리

5) Exec command : 배포가 끝나고 해당 원격 서버에 실행할 명령어 모음

위와 같이 설정하면 젠킨스가 특정 웹훅 메세지(PUSH하는 순간의 최신버전의 웹프로젝트)를 받으면 나의 SSH로 엔진엑스 서버에 접속해 위의 그림에서 Exec command의 내용의 명령어를 자동으로 실행하도록 설정한 것이다.

step 10) 젠킨스의 자동배포 기능 테스트

step 8)처럼 웹프로젝트를 index.html의 내용을 임의로 수정하고 푸쉬하고 엔진엑스 서버에 접속했을때 아래 그림과 같이 확인되면 된다.

44

위와 같이 새로운 프로젝트가 들어오면 기존에 있던 웹프로젝트를 리무브하고 새로운 웹프로젝트로 대체하는 이 방법은 좋은 방법은 아니다. 왜냐하면 기존에 서비스하던걸 전면 중단하는 시간이 생기기 때문이다. 우리가 추구하는 건 이런 중단과정이 없는 무중단 배포이다. 대표적인 무중단 배포로는 블루그린 무중단 배포가 있다.

무중단 배포의 핵심은 우리가 지금 유지해야하는 transaction은 보장해주고, 새로운 환경에서 프로젝트를 업데이트하자는 것이다. 무중단 배포는 보통 컨테이너를 이용하는 편이다. service nginx restart 같은 것을 할때 모든 연결이 유실되는 경우가 있기 때문에 무중단 배포를 한다.

직접배포 = 중단배포 = 정기점검 => AWS Codedeploy를 활용하여 무중단 배포가 가능

44-2

3. 컨테이너 환경으로의 이전 실습

44-3

step 1) 젠킨스 서버에서 아래 그림과 같이 amazon-linux-extras install -y docker 명령어를 이용하여 도커를 먼저 설치한다.

45

step 2) systemctl docker start로 도커를 실행해주고, 아래와 같이 git clone 명령어로 웹 디플로이 프로젝트를 가져온다.

46

step 3) 아래 그림과 같이 cd 명령어로 웹디플로리 프로젝트 디렉토리로 이동해서 vim Dockerfile 명령어를 입력하여 도커 이미지 빌드를 위한 정의 파일인 Dockerfile 생성한다.

47

step 4) 아래 그림과 같이 작성하고 저장해준다.

48

도커이미지를 빌드하기 위해서는 도커데몬이 도커파일을 참조해야한다. 그리고 도커 데몬은 위와 같은 도커파일의 내용을 그대로 실행하게 된다.

참고로 FROM centos:latest(centos 최신버전 도커이미지를 기반으로 한다는 의미)를 했을때 해당이미지가 없으면 도커 허브에서 관리되고 있는 공식이미지를 알아서 다운로드해서 가져오게 된다.

step 5) 아래 그림과 같이 docker build -t web:0.1 . 명령어를 입력하여 도커 이미지를 빌드시킨다.

docker build -t web:0.1 . 에서 마지막에 . 은 같은 디렉토리(Fastcampus-web-deploy 디렉토리)에 있는 도커파일을 기반으로 빌드를 한다는 것이다.

49

step 6) 빌드가 완료되면 docker images 명령어를 통해 내가 만든 도커이미지가 잘 빌드되었는지 확인한다.

50

step 7) docker run -d -p 8000:80 --name web web:0.1 명령어를 입력하여 web:0.1 이미지를 기반으로한 도커 컨테이너 실행한다.

step 8) vim Dockerfile를 하여 아래 그림과 같이 다시 수정해준다.

참고로 Dockerfile 마지막줄에 CMD 부분은 도커 런 명령어를 때리고 컨테이너가 처음 실행될때 해당 컨테이너 내에서 어떤 프로세스를 어떻게 실행할것인가에 대한 내용이다.

51

step 9) 그럼 아래 그림과 같이 도커 컨테이너 환경 이전이 완료되는 것이다.

52