[2023.01.15] 개발자 교육 79일 차 : 강의-AWS, Docker, Jenkins 학습(Mac) [구디 아카데미]

DaramGee·2024년 1월 15일
0

강의 내용

AWS 학습 돌아보기, 금일 학습 목표

  • 현재 진행 내용

  • svr1 AWS EC2 생성 docker 설치 : Mariadb 컨테이너 생성

  • svr2 AWS EC2 생성 후 docker 설치
    - jdk, docker 설치, guestbook 소스 파일로 컨테이너 생성
    - guestbook컨테이너로 도커이미지 생성(guestbookapp)
    - 도커이미지 도커허브에 Push(업로드)
    - 도커이미지 pull하여 실행하면 자동으로 실행이 되고, 똑같은 환경을 맞출 수 있음.

  • 실습 예정

  • 기존은 개발자가 수동으로 빌드까지 하고 이미지를 업로드하고, 이미지를 pull하여 같은 환경의 컨테이너를 생성했다면, 오늘은 Jenkins를 활용하여 자동 이미지 빌드 및 푸쉬 & 성공시 배포서버로 이동하는 것까지 실습할 예정이다.


jenkins는?

  • 그렇다면 jenkins는 뭘까?? 앞서 말한 것처럼, 개발자가 수동으로 해오던 빌드, 푸쉬, 배포를 자동으로 할 수 있도록 지원하는 도구이다.
  • 전문용어로 설명하면 오픈 소스 지속적 통합(CI) 및 지속적 배포(CD) 도구로, 소프트웨어 개발 프로세스의 빌드, 테스트, 배포 등을 자동화하고 관리할 수 있다.
  • 즉, 개발된 프로그램에 대해 버전이 업데이트되면 자동으로 빌드, 푸쉬하여 추후 배포 시 사용할 수 있도록 자동화되는 작업을 도와주는 것이다.

CI/CD가 그럼 무엇인가?

  • 앞서 도커를 사용한 배포의 흐름을 본 적이 있다. 배포파일, 여러 설정을 담은 이미지를 컨테이너 레지스트리(도커 허브)에 Push했었다.
  • CI : 지속적인 통합, 이처럼 같은 레포에 작성 코드를 통합하여 효율적 협업을 지원한다.
  • CD : 지속적인 배포, 변경사항에 따라 자동화된 테스트, 빌드를 거쳐 사용자에게 자동으로 배포해줄 수 있다.
  • 이전 도커로 직접 빌드, 배포를 하는 방식을 학습했다면, 오늘 배울 jenkins를 통한다면 변경되는 설정을 push하면 이에 대해 빌드, 테스트, 배포까지 되는 과정이 자동으로 이루어질 수 있다.(아래 그림 참고)

젠킨스 핵심

  • 파이프라인 -> 변경사항 감지 및 개발자가 정의한 파이프라인 실행(수업 예정)
  • 트리거 및 웹훅 -> 변경사항 있으면 빌드 및 테스트 진행
  • 결과 및 로그 저장 -> 로그 수집 및 분석하여 최적화 포인트 식별 가능
  • 알람 -> 빌드 및 테스트 결과 알림 가능, 슬랙 연동(수업 예정)


Jenkins 실습

인스턴스 세팅

  • EC2 서버 2개 - 설치 파일
    - SVR1 - 리눅스 2, jenkins 서버 : github에서 서버에 접속이 가능해야함.(로컬로 불가능), git
    - SVR2 - 리눅스 2, 배포서버(Staging Server), DB서버(mariaDB), docker
  • SVR1 : jdk17(jenkins용 jdk), docker, jenkins, git

guestbook은 jdk 8인데? svr이랑 안맞춰도 되나??
컨테이너 안에서 작동하는 것이기 때문에 상관 x

SVR1

  • AMI : 리눅스 2
  • 주설정 : jdk17, jenkins, git, docker
  • 인스턴스유형 : t2.medium(micro보다 속도 빠름)
  • 보안그룹(인바운드규칙 - 8080 포트 추가된 보안그룹으로 설정하기)
  • 생성시 실행 script(고급세부정보)
#!/bin/bash
yum install -y java-17-amazon-corretto
yum install -y git
yum install -y docker
systemctl start docker
systemctl enable docker
usermod -aG docker ec2-user
yum update -y
wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
yum upgrade
yum install jenkins -y
systemctl start jenkins

SVR2

  • AMI : 리눅스 2
  • 주설정 : docker, DB(mariadb)
  • 인스턴스유형 : t2.micro
  • 보안그룹(인바운드규칙 - 8080 포트 추가된 보안그룹으로 설정하기)
  • 생성시 실행 script(고급세부정보)
#!/bin/bash
yum install -y docker
systemctl start docker
systemctl enable docker
usermod -aG docker ec2-user
docker container run -d \
    --name=mydb \
    --restart=always \
    -e MYSQL_ROOT_PASSWORD=education \
    -e MYSQL_DATABASE=guestbook \
    -p 3306:3306 \
    mariadb
  • 실행순서
  • 도커 접속->설치여부 확인->젠킨슨 실행 및 시스템 정보확인 sudo systemctl status jenkins (비번확인) -> 주소 접속(http://52.69.224.147:8080/) -> password 입력 ->Jenkins 회원가입 -> 파이프라인 실습
[ec2-user@ip-172-31-44-84 ~]$ sudo systemctl status jenkins
● jenkins.service - Jenkins Continuous Integration Server
   Loaded: loaded (/usr/lib/systemd/system/jenkins.service; disabled; vendor preset: disabled)
   Active: active (running) since 월 2024-01-15 01:44:32 UTC; 9s ago
 Main PID: 5792 (java)
   CGroup: /system.slice/jenkins.service
           └─5792 /usr/bin/java -Djava.awt.headless=true -jar /usr/share/java/jenkins.war --webroot=%C/jenkins/war --httpPort=8080

 1월 15 01:44:05 ip-172-31-44-84.ap-northeast-1.compute.internal jenkins[5792]: {jenkins 비번 출력 부분}
 1월 15 01:44:05 ip-172-31-44-84.ap-northeast-1.compute.internal jenkins[5792]: This may also be found at: /var/lib/jenkins/secrets/initialAdminPassword
 1월 15 01:44:05 ip-172-31-44-84.ap-northeast-1.compute.internal jenkins[5792]: *************************************************************
 1월 15 01:44:05 ip-172-31-44-84.ap-northeast-1.compute.internal jenkins[5792]: *************************************************************
 1월 15 01:44:05 ip-172-31-44-84.ap-northeast-1.compute.internal jenkins[5792]: *************************************************************
 ...

만약, 무언가의 오류(정말 다양한 오류 있음.. 예 : 스크립트 오타, 바운드 규칙 등)로 생성시 자동실행이 되지 않았다면???
자동실행에 넣어둔 파일의 설치여부를 확인한 뒤, self로 설치 명령어를 입력해야 한다. (스크립트 문에 있는 명령어로)
혹, 설치중에 에러로 인해 비정상적으로 정지되어 추가적인 설치가 되지 않을 수 있다.
그럴 때는 다른 Install이 진행되지 않으니까..
반드시 sudo kill -9 yum 을 눌러 설치에러가 난 yum을 멈춘 뒤, 다시 install을 진행하자!! (한참 걸림 ㅠㅠ)

주의!
EC2 생성 시 아웃바운드 규칙 편집 주의해야함.
아예 없어도 외부와 소통이 되지 않고, 특정 서버만 들어가 있을 경우, 그 포트로만 외부 소통이 가능하기 때문에
0.0.0.0/0으로 열어놓는 설정이 유지되어 있어야 함.


젠킨스 실습!

  • 회원가입 진행하기

  • 젠킨스를 설치한 서버를 실행한 뒤, status를 확인하여 젠킨스 비밀번호를 미리 확인해둔다.(sudo systemctl status jenkins)
  • 젠킨스 설치 서버의 퍼블릭주소+:8080(인바운드 규칙시 넣은 포트번호) 예 : http://52.69.224.147:8080/
  • 비밀번호를 입력하는 곳에 터미널을 통해 확인한 비번을 입력하면 회원가입을 진행할 수 있게 된다.
  • 아이디, 비밀번호를 입력하여 가입한다.

파이프라인 만들기 1 - guestbook_cicp

  • 배포파일 변경사항 감지하여 실행할 내용을 설정해둔다.
  • Pipeline 생성법 : 대쉬보드 -> new item+ -> Pipeline 선택 -> name 입력(guestbook_cicp) -> 확인
  • 실행내용 입력 : 아래 Definition을 통해 실행문 입력(우선은 간단한 테스트, 하나씩 연결하며 추가하자)
  • Pipeline(젠킨스 문법 사용-group) 작성법 -> try sample로 작성법에 대해 예시 확인 가능
  • 실행여부 확인하기 : 대쉬보드 -> 해당 파이프라인 -> ▶️지금 빌드
  • 빌드 실패 시 : 로그확인하여 General(구성)을 눌러 파이프라인 내용 수정한 뒤 다시 빌드
  • 콘솔아웃(단계별 작업지정, 자동으로 수행되게끔 지정하는 것이 파이프라인!!)
  • 1차 Script : 문구 실행
pipeline {
	agent any
	stages {
		stage('Hello') {
			steps {
				echo 'Hello World'
			}
		}
	}
}
  • 2차 Script : 문구 실행, 파일 복사
pipeline {
	agent any
	stages {
		stage('Hello') {
			steps {
				echo 'Hello World'
			}
		}
		stage('File Copy'){
			steps{
				sh 'cp /etc/profile /tmp'
			}
		}
	}
}

3차 Script

import java.text.SimpleDateFormat

def TODAY = (new SimpleDateFormat("yyyyMMdd")).format(new Date())

pipeline {
    agent any
    environment {
        strDockerTag = "${TODAY}_${BUILD_ID}"
        strDockerImage ="{도커 아이디}/{도커 레포이름}:${strDockerTag}"
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url:'https://github.com/{깃허브 유저이름}/{깃허브 레포이름}.git'
            }
        }
        stage('Build') {
            steps {
                sh 'chmod u+x mvnw'
                sh './mvnw clean package'
            }
        }
        stage('Docker Image Build') {
            steps {
                script {
                    oDockImage = docker.build(strDockerImage, "--build-arg VERSION=${strDockerTag} -f Dockerfile .")
                }
            }
        }
        stage('Docker Image Push') {
            steps {
                script {
                    docker.withRegistry('', 'DockerHub_{도커유저이름}') {
                        oDockImage.push()
                    }
                }
            }
        }

    }
}

credentialsId: 'jenkins3' 같은 경우도 추후 깃허브 레포지토리를 private으로 만들었을 경우, stage('Checkout') steps 중괄호 안에 추가해야 한다.


파이프라인 만들기 2 - slack-test(슬랙 알림 설정)

  • 순서

  • 1. 슬랙 설정 순서

  • 슬랙 워크스페이스 생성 -> 슬랙 찾아보기 -> 앱 -> 추가(젠킨스 CI 추가) -> 슬랙에 추가 -> 채널 선택(젠킨스 알림 설정할 슬랙 채널 선택 or 생성) -> Jenkins CI 통합 앱 추가 -> 설정지침 확인(과정확인, 도메인 및 토큰 ID 확인->추후 젠킨스에서 파이프라인 설정 시 사용)
  • 2. 젠킨스 설정 순서

  • 1) 시스템 - 슬랙 설정
  • 플러그인 설치 : 대쉬보드 -> 젠킨스 관리 -> 사용가능 플러그인 -> slack 설치
  • 토큰 설정(대쉬보드 -> 젠킨스 관리 -> 시스템 -> 맨 아래 slack 부분)
    - Credential Add
    - Kind : Secret text
    - 시크릿 : 토큰(슬랙에서 확인한 통합 토큰 자격증명 ID)
    - Id, decription : slack-token(알아보기 편한 이름)
  • add 후 입력
    - 워크스페이스 : 도메인(슬랙에서 확인한 팀 하위 도메인)
    - Credential : slack-token 선택
    - Default channel : 슬랙에서 알림설정 사용하기로 한 채널명 입력
  • 테스트 : 테스트 커넥션 클릭하여 연결 확인 가능(슬랙에 알림 오면 성공!👍 or 직접 슬랙에서 확인 가능)

  • 2) 파이프라인 - slack-test 생성
  • 방법, 테스트, 수정은 위 guestbook_cicp와 동일
  • 1차 Script :
pipeline {
    agent any
    stages {
        stage("Slack Notification") {
            steps {
                slackSend(tokenCredentialId: 'slack-token'
                        , channel: '#jenkins'
                        , color: 'good'
                        , message: 'CICD 테스트 메세지')
            }
        }
    }
}
  • 2차 Script :
pipeline {
    agent any
    stages {
        stage("Slack Notification") {
            steps {
                slackSend(tokenCredentialId: 'slack-token'
                        , channel: '#jenkins'
                        , color: 'good'
                        , message: 'CICD 테스트 메세지')
            }
        }
    }
    post { 
        always { 
            slackSend(tokenCredentialId: 'slack-token'
                , channel: '#jenkins'
                , color: 'good'
                , message: "빌드가 끝났습니다. ")
        }
        success { 
            slackSend(tokenCredentialId: 'slack-token'
                , channel: '#jenkins'
                , color: 'good'
                , message: "빌드가 성공적으로 끝났습니다. ")
        }
        failure { 
            slackSend(tokenCredentialId: 'slack-token'
                , channel: '#jenkins'
                , color: 'danger'
                , message: "빌드가 실패하였습니다.")
    }
  }        
}
  • 슬랙에서 확인 가능
  • 파이프라인 생성(슬랙 테스트)

파이프라인 만들기 3 - git-test(깃허브 연결 설정)

  • 순서

  • 1. 시스템 - 깃허브 레포 설정 및 토큰 생성

  • 레포지토리 생성(guestbookapp) : https://github.com/{깃허브 유저이름}/{깃허브 레포이름}.git

  • 레포지토리 설정
    - 웹훅, 젠킨스 주소(http://52.69.224.147:8080/)참고하여 작성
    - http://52.69.224.147:8080/github-webhook/
    - 젠킨스와 호환여부 표시됨 (ping)

  • 토큰 생성 방법 : 아이콘 -> settings -> Developer settings -> personal access tokens -> Tokens(classic) -> Generate new token

  • 토큰 생성 입력 시
    - Note : 토큰명(예 : CICD-token)
    - Expiration : 사용기간(30일)
    - Select scopes : repo, admin:repo_hook, user 클릭 & Generate token
    - 생성되는 토큰 개별 저장!! (추후 사용 예정)


  • 2. 젠킨스 설정 순서

  • 1) 시스템 - 트리거 추가, 플러그인 설치, GitHub Servers 설정
  • 트리거 추가 방법 : 대쉬보드 -> 관리 -> 구성 -> 깃허브 빌드 트리거 추가(구성)
  • 플러그인 설치 : 대쉬보드 -> 관리 -> 플러그인 ->
  • 토큰 설정(대쉬보드 -> 젠킨스 관리 -> 시스템 -> GitHub Servers)
    - Credential Add
    - Kind : Secret text
    - 시크릿 : 토큰(깃허브에서 발급받은 personal access token (classic))
    - Id, decription : github-token(알아보기 편한 이름)
  • add 후 입력
    - Name : 깃허브 이름
    - Credential : github-token 선택
  • 테스트 : 테스트 커넥션 클릭하여 연결 확인 가능(Credentials verified for user ~!!@ 출력시 성공!👍 or 파이프라인 생성 후 직접 push 하여 빌드 여부 확인하기)

  • 2) 파이프라인 생성 - git-test
  • 대시보드-관리-플러그인-깃플러그인 설치 (플러그인 확인 필요)
  • 방법, 수정은 위 guestbook_cicp와 동일
  • 테스트의 경우, 해당 레포지토리에 진짜 push가 일어날 때, stage view에 빌드가 표시됨을 확인할 수 있다.
  • Script :
pipeline {
    agent any
    stages {
        stage('Checkout') {
            steps {
                git branch: 'main',  url:'https://github.com/{깃허브 유저이름}/{깃허브 레포이름}.git'
            }
        }
        stage('Build') {
            steps {
                sh 'chmod u+x mvnw'
                sh './mvnw clean package'
            }
        }

    }
}  
  • 경로이동(guestbook 저장된 로컬파일 경로로 이동) : /var/lib/jenkins/workspace/guestbook_cicd
  • 파일수정 & git add . & git commit & git push 테스트

github에 새롭게 push를 하게 되면, Checkout(브랜치 변경), Build(메이븐 빌드, 클린)가 실행되는 것을 확인할 수 있다.
안된다면?? 현재 jenkins를 설치해 둔 서버에 git이 설치되어있는지, 연결되어있는지 확인해보자. 아니라면? 설치하고 해당 레포지토리랑 연결하면 지금빌드가 정상적으로 실행되는 것을 확인할 수 있을 것이다.(sudo yum install -y git)


파이프라인 만들기 4 - docker-test

  • 순서

  • 1. 코드 수정 및 권한 부여

  • svr1 코드(jenkins usermod, restart 진행)
  117  cd guestbook_cicp
  118  sudo usermod -aG docker jenkins
  119  sudo systemctl restart jenkins
  120  cd
  121  sudo systemctl restart jenkins
  122  sudo usermod -aG docker jenkins
  123  sudo systemctl restart jenkins
  • 로컬에서 guestbook 파일 수정 및 푸시하여 작동 확인
cd src/main/resources/templates
vi index.html
cd ../../../../
git add .
git commit -m "2"
git push origin main

  • 2. 젠킨스 설정 순서

  • 1) credential 생성
  • 시스템 - Global credential 생성
  • 방법 : 대쉬보드 -> 관리 -> credential -> system -> global credentials -> add credentials
  • 내용(정확한 확인 필요)
    - Kind : Secret text
    - 시크릿 : 도커허브 비밀번호
    - Id, decription : docker-auth
    - 도커허브 아이디
    - 워크스페이스 : 도커허브 레포이름
  • 2) 파이프라인 생성 - docker-test
  • 대시보드-관리-플러그인-깃플러그인 설치 (Docker Pipeline)
  • 방법, 수정은 위 guestbook_cicp와 동일
  • 테스트의 경우, 해당 레포지토리에 진짜 push가 일어날 때, stage view에 빌드가 표시됨을 확인할 수 있다.
  • Script :
import java.text.SimpleDateFormat

def TODAY = (new SimpleDateFormat("yyyyMMdd")).format(new Date())

pipeline {
    agent any
    environment {
        strDockerTag = "${TODAY}_${BUILD_ID}"
        strDockerImage ="{도커아이디}/{도커 레포이름}:${strDockerTag}"
    }

    stages {
        stage('Checkout') {
            steps {
                git branch: 'main', url:'https://github.com/{깃허브 유저이름}/{깃허브 레포이름}.git'
            }
        }
        stage('Build') {
            steps {
                sh 'chmod u+x mvnw'
                sh './mvnw clean package'
            }
        }
        stage('Docker Image Build') {
            steps {
                script {
                    oDockImage = docker.build(strDockerImage, "--build-arg VERSION=${strDockerTag} -f Dockerfile .")
                }
            }
        }
        stage('Docker Image Push') {
            steps {
                script {
                    docker.withRegistry('', 'docker-auth') {
                        oDockImage.push()
                    }
                }
            }
        }

    }
}

0개의 댓글