본문 바로가기

study/AEWS 2기

AEWS 2기 7주차 첫번째

7주차는 CI/CD입니다.

 

젠킨스부터 알아보겠습니다.

  • jenkins 소개 : 지속적인 통합과 배포 → Work flow를 제어 - Link
    1. 최신 코드 가져오기 : 개발을 위해 중앙 코드 리포지터리에서 로컬 시스템으로 애플리케이션의 최신 코드를 가져옴
    2. 단위 테스트 구현과 실행 : 코드 작성 전 단위 테스트 케이스를 먼저 작성
    3. 코드 개발 : 실패한 테스트 케이스를 성공으로 바꾸면서 코드 개발
    4. 단위 테스트 케이스 재실행 : 단위 테스트 케이스 실행 시 통과(성공!)
    5. 코드 푸시와 병합 : 개발 소스 코드를 중앙 리포지터리로 푸시하고, 코드 병합
    6. 코드 병합 후 컴파일 : 변경 함수 코드가 병함되면 전체 애플리케이션이 컴파일된다
    7. 병합된 코드에서 테스트 실행 : 개별 테스트뿐만 아니라 전체 통합 테스트를 실행하여 문제 없는지 확인
    8. 아티팩트 배포 : 애플리케이션을 빌드하고, 애플리케이션 서버의 프로덕션 환경에 배포
    9. 배포 애플리케이션의 E-E 테스트 실행 : 셀레늄 Selenium과 같은 User Interface 자동화 도구를 통해 애플리케이션의 전체 워크플로가 정상 동작하는지 확인하는 종단간 End-to-End 테스트를 실행.
    • The leading open source automation server, Jenkins provides hundreds of plugins to support building, deploying and automating any project.
    • Continuous Integration Server + Continuous Development, Build, Test, Deploy
    • 소프트웨어 개발 프로세스의 다양한 단계자동화하는 도구로서 중앙 소스 코드 리포지터리에서 최신 코드 가져오기, 소스 코드 컴파일, 단위 테스트 실행, 산출물을 다양한 유형으로 패키징, 산출물을 여러 종류의 환경으로 배포하기 등의 기능을 제공.
    • 젠킨스는 아파치 톰캣처럼 서블릿 컨테이너 내부에서 실행되는 서버 시스템이다. 자바로 작성됐고, 소프트웨어 개발과 관련된 다양한 도구를 지원.
    • 젠킨스는 DSL Domain Specific Language (jenkins file)로 E-E 빌드 수명 주기 단계를 구축한다.
    • 젠킨스는 파이프라인이라고 부르는 스크립트를 작성할 수 있는데, 이를 사용해서 각 빌드 단계마다 젠킨스가 수행할 태스트 및 하위 태스크의 순서를 정의.
      • 순차적이고 종속적인 단계가 시작부터 끝까지 실행되면 최종적으로 사용자가 실행할 수 있는 빌드가 생성됨.
      • 만약 빌드 프로세스를 진행하는 중에 특정 단계에서 실패가 발생하며, 이 단계의 출력 결과를 사용하는 다음 단계는 실행되지 않으며 빌드 프로세스 전체가 실패한다.
    • 다양한 Plugins 연동
      • Build Plugins : Maven, Ant, Gradle …
      • VCS Plugins : Git, SVN …
      • Languages Plugins : Java, Python, Node.js …

 

설치 및 설정

# 실습 편리를 위해서 root 계정 전환
sudo su -

# Add required dependencies for the jenkins package
# https://docs.aws.amazon.com/corretto/latest/corretto-17-ug/amazon-linux-install.html
sudo yum install fontconfig java-17-amazon-corretto -y
java -version
alternatives --display java
JAVA_HOME=/usr/lib/jvm/java-17-amazon-corretto.x86_64
echo $JAVA_HOME

# 젠킨스 설치
sudo wget -O /etc/yum.repos.d/jenkins.repo https://pkg.jenkins.io/redhat-stable/jenkins.repo
sudo rpm --import https://pkg.jenkins.io/redhat-stable/jenkins.io-2023.key
sudo yum upgrade
sudo yum install jenkins -y
sudo systemctl daemon-reload
sudo systemctl enable jenkins && sudo systemctl start jenkins   # 다소 시간 걸림
sudo systemctl status jenkins

# 초기 암호 확인
sudo systemctl status jenkins
cat /var/lib/jenkins/secrets/initialAdminPassword

# 접속 주소 확인 
curl -s ipinfo.io/ip | awk '{ print "Jenkins = http://"$1":8080" }'

 

젠킨스 생성 후 플러그 인 설치

 

완료

 

 

기본 사용 , Tools 설정 : First-Project

JDK installations : jdk-17 , /usr/lib/jvm/java-17-amazon-corretto.x86_64 → Save

 

 

  • 첫번째 Item(Project) 생성
    • 새로운 Item 클릭 → Name : First-Project , Freestyle project ⇒ 하단 OK 클릭

 

 

Build Steps → Add build step ⇒ Execute shell 클릭

간단한 문장 출력 될 수 있게 입력 : echo "Aws Workshop Study" → 하단 Apply 후 저장

 

 

빌드 후 확인

 

 

  • 상위 메뉴 - 구성 : 아래 명령어 한줄 추가 java -version → Apply 저장
    • 한줄 더 추가 : whoami
    • 한줄 더 추가 : touch hello.txt
  • 최상위 - 프로젝트 화살표 선택 → 지금 빌드
    • 이후 콘솔 출력 확인

 

 

 

Item(Job) 프로젝트 디텍토리 확인 : 혹은 젠킨스 작업 공간 확인

 

 

Docker 사용 : Docker-Project

# jenkins 유저로 docker 사용 가능하게 설정
grep -i jenkins /etc/passwd
usermod -s /bin/bash jenkins
grep -i jenkins /etc/passwd

# jenkins 유저 전환
su - jenkins
whoami
pwd
docker info
exit

#
chmod 666 /var/run/docker.sock
usermod -aG docker jenkins

# Jeknins 유저로 확인
su - jenkins
docker info

# Dockerhub로 로그인 하기
docker login
Username: <자신의 계정명>
Password: <자신의 암호>

# myweb:v2.0.0 컨테이너 이미지 생성을 위한 Dockerfile 준비
# 실습을 위한 디렉터리 생성 및 이동
mkdir -p ~/myweb2 && cd ~/myweb2

# Dockerfile 파일 생성
vi Dockerfile
FROM ubuntu:20.04
ENV TZ=Asia/Seoul VERSION=2.0.0 NICK=<자신의 닉네임>
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
    sed -i 's/archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list && \
    sed -i 's/security.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list && \
    apt-get update && apt-get install -y apache2 figlet && \
    echo "$NICK Web Server $VERSION<br>" > /var/www/html/index.html && \
    echo "<pre>" >> /var/www/html/index.html && \
    figlet AEWS Study >> /var/www/html/index.html && \
    echo "</pre>" >> /var/www/html/index.html
EXPOSE 80
CMD ["usr/sbin/apache2ctl", "-DFOREGROUND"]

vi Dockerfile
FROM ubuntu:20.04
ENV TZ=Asia/Seoul VERSION=2.0.0 NICK=gasida
RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone && \
    sed -i 's/archive.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list && \
    sed -i 's/security.ubuntu.com/mirror.kakao.com/g' /etc/apt/sources.list && \
    apt-get update && apt-get install -y apache2 figlet && \
    echo "$NICK Web Server $VERSION<br>" > /var/www/html/index.html && \
    echo "<pre>" >> /var/www/html/index.html && \
    figlet AEWS Study >> /var/www/html/index.html && \
    echo "</pre>" >> /var/www/html/index.html
EXPOSE 80
CMD ["usr/sbin/apache2ctl", "-DFOREGROUND"]

# 모니터링
watch -d 'docker images; echo; docker ps'

-----------
# (참고) 이미지 빌드
docker build -t myweb:v2.0.0 -f /var/lib/jenkins/myweb2/Dockerfile

# (참고) 컨테이너 실행
docker run -d -p 80:80 --rm --name myweb myweb:v2.0.0

 

item : Docker-Project , freestyle

  • Build Steps : Execute shell
cd /var/lib/jenkins/myweb2
docker build -t myweb:v2.0.0 .

 

 

Add build Steps : Execute shell

docker run -d -p 80:80 --rm --name myweb myweb:v2.0.0

 

 

빌드 후 확인

 

 

실습 리소스 삭제

docker rm -f myweb
docker rmi myweb:v2.0.0

 

 

  • 파라미터, 빌드 유발(SCM - Git) 사용 : Trigger-Project
    • Item : Trigger-Project, freestyle
      • 빌드 매개변수 : String
        • 변수명(VERSION), Default Vault(v1.0.0)
        • 변수명(NICK), Default Vault(<자신의 계정명>)
      • 소스 코드 관리 : Git
        • Repo URL : https://github.com/**<자신의 계정명>**/aews-cicd
        • Branch : */main
        • Additional Behaviours → Sparse Checkout paths (Path) : 1
      • 빌드 유발 : Poll SCM (* * * * *)
      • Build Steps : Execute shell
cd /var/lib/jenkins/myweb2
rm -rf Dockerfile
wget https://raw.githubusercontent.com/$NICK/aews-cicd/main/1/Dockerfile

 

Add build Steps : Execute shell

docker build -t myweb:$VERSION .
docker run -d -p 80:80 --rm --name myweb myweb:$VERSION

 

 

자신의 Github Repo 1 에서 Dockerfile에 VERSION 정보를 수정 후 Commit → 1분 정도 후에 젠킨스에서 확인

 

 

오류 발생..

 

요건 나중에 다시 시도해보겠습니다.

 

 

 

 

  • **Jenkins 작업** (프로젝트, Job, Item) : 3가지 유형의 지시 사항 포함
    1. 작업을 수행하는 시점 Trigger
      • 작업 수행 태스크 task가 언제 시작될지를 지시
    2. 작업을 구성하는 단계별 태스크 Built step
      • 특정 목표를 수행하기 위한 태스크를 단계별 step로 구성할 수 있다.
      • 이것을 젠킨스에서는 빌드 스텝 build step이라고 부른다.
    3. 태스크가 완료 후 수행할 명령 Post-build action
      • 예를 들어 작업의 결과(성공 or 실패)를 사용자에게 알려주는 후속 동작이나, 자바 코드를 컴파일한 후 생성된 클래스 파일을 특정 위치로 복사 등
    • (참고) 젠킨스의 빌드 : 젠킨스 작업의 특정 실행 버전
      • 사용자는 젠킨스 작업을 여러번 실행할 수 있는데, 실행될 때마다 고유 빌드 번호가 부여된다.
      • 작업 실행 중에 생성된 아티팩트, 콘솔 로드 등 특정 실행 버전과 관련된 모든 세부 정보가 해당 빌드 번호로 저장된다.

 

파이프라인 Pipeline : CD 파이프라인을 구현하고 통합할 때 사용하는 플러그인 스크립트 모음 - Docs

 

Pipeline

Jenkins – an open source automation server which enables developers around the world to reliably build, test, and deploy their software

www.jenkins.io

 

 

  • 파이프라인 장점
    • 코드 : 애플리케이션 CI/CD 프로세스를 코드 형식으로 작성할 수 있고, 해당 코드를 중앙 리포지터리에 저장하여 팀원과 공유 및 작업 가능
    • 내구성 : 젠킨스 서비스가 의도적으로 또는 우발적으로 재시작되더라도 문제없이 유지됨
    • 일시 중지 가능 : 파이프라인을 실행하는 도중 사람의 승인이나 입력을 기다리기 위해 중단하거나 기다리는 것이 가능
    • 다양성 : 분기나 반복, 병렬 처리와 같은 다양한 CI/CD 요구 사항을 지원
  • 파이프라인 용어
    • 파이프라인 : 전체 빌드 프로세스를 정의하는 코드.
    • 노드 node : 파이프라인을 실행하는 시스템.
    • 스테이지 stage : 특정 단계에서 수행되는 작업들의 정의.
    • 스텝 step : 파이프라인의 특정 단계에서 수행되는 단일 작업을 의미.
  • 파이프라인 3가지 구성 형태
    • Pipeline script : 일반적인 방식으로 Jenkins 파이프라인을 생성하여 Shell Script를 직접 생성하여 빌드하는 방식
    • Pipeline script from SCM : 사전 작성한 JenkinsFile을 형상관리 저장소에 보관하고, 빌드 시작 시 파이프라인 프로젝트에서 호출 실행하는 방식
      • In SCM - you can write a Jenkinsfile manually, which you can commit to your project’s source control repository.
  • Blue Ocean 기반 : UI기반하여 시각적으로 파이프라인을 구성하면, JenkinsFile이 자동으로 생성되어 실행되는 방식
    • Through Blue Ocean - after setting up a Pipeline project in Blue Ocean, the Blue Ocean UI helps you write your Pipeline’s Jenkinsfile and commit it to source control.

 

 

  • 파이프라인 2가지 구문 : 선언형 파이프라인(권장)과 스크립트형 파이프라인
    • 선언형 파이프라인 : 쉽게 작성 가능, 최근 문법이고 젠킨스에서 권장하는 방법, step 필수!
    • 스크립트형 파이프라인 : 커스텀 작업에 용이, 복잡하여 난이도가 높음, step은 필수 아님

 

 

선언형 Declarative 파이프라인

pipeline {
    agent any     # Execute this Pipeline or any of its stages, on any available agent.
    stages {
        stage('Build') {   # Defines the "Build" stage.
            steps {
                //         # Perform some steps related to the "Build" stage.
            }
        }
        stage('Test') { 
            steps {
                // 
            }
        }
        stage('Deploy') { 
            steps {
                // 
            }
        }
    }
}

 

 

스크립트형 Scripted 파이프라인

node {          # 	Execute this Pipeline or any of its stages, on any available agent.
    stage('Build') {    # Defines the "Build" stage. stage blocks are optional in Scripted Pipeline syntax. However, implementing stage blocks in a Scripted Pipeline provides clearer visualization of each stage's subset of tasks/steps in the Jenkins UI.
        //              # Perform some steps related to the "Build" stage.
    }
    stage('Test') { 
        // 
    }
    stage('Deploy') { 
        // 
    }
}

 

 

Jenkins Pipeline : First-Pipeline

  • Item : First-Pipeline → Pipeline(Pipeline script - 아래 내용 복붙)
    • 먼저 샘플 파이프라인 테스트 해보자!
    • Hello World 테스트
pipeline {
    agent any

    stages {
        stage('정보 확인') {
            steps {
                echo 'Hello World'
                sh 'java -version'
            }
        }
        stage('가라 배포') {
            steps {
                echo "Deployed successfully!";
            }
        }
    }
}

 

확인

 

 

아래 처럼 수정 후 확인: 환경변수 사용, 문자열 보간 → Console Output 확인

pipeline {
    agent any
    environment { 
        STUDYNAME = 'AEWS'
    }
    stages {
        stage('연습') {
            environment { 
                mykey = 'abcd'
            }
            steps {
                echo "${STUDYNAME}";
                sh 'echo ${mykey}'
            }
        }
    }
}

 

확인

 

 

아래 처럼 수정 후 확인: Tools → Console Output 확인

pipeline {
    agent any
    tools {
        maven 'maven_3.8.7' 
    }
    stages {
        stage('Example') {
            steps {
                sh 'mvn --version'
            }
        }
    }
}

 

확인

 

 

아래 처럼 수정 후 확인: 파이프라인 빌드 시작(트리거) → Console Output 확인

pipeline {
    agent any
    triggers {
        cron('* * * * *')
    }
    stages {
        stage('주기 반복') {
            steps {
                echo 'Hello World'
            }
        }
    }
}

 

확인

 

 

아래 처럼 수정 후 확인: 파라미터와 함께 빌드 → Console Output 확인

pipeline {
    agent any
    parameters {
        string(name: 'PERSON', defaultValue: 'gasida', description: 'Who are you?')
        choice(name: 'CHOICE', choices: ['One', 'Two', 'Three'], description: 'Pick something')
    }
    stages {
        stage('파라미터 사용') {
            steps {
                echo "Hello ${params.PERSON}"
                echo "Choice: ${params.CHOICE}"
            }
        }
    }
}

 

 

 

  • 아래 처럼 수정 후 확인: post (빌드 후 조치) → Console Output 확인
    • always: 항상 실행
    • changed: 현재 빌드의 상태가 이번 빌드의 상태와 달라졌다면 실행
    • success: 현재 빌드가 성공했다면 실행
    • failure: 현재 빌드가 실패했다면 실행
    • unstable: 현재 빌드의 상태가 불안하다면 실행
pipeline {
    agent any
    stages {
        stage('배포 후 빌드 후 조치 결과 출력') {
            steps {
                echo 'Hello World'
            }
        }
    }
    post { 
        always { 
            echo 'Always say Hello World!'
        }
    }
}

확인

 

 

post 항목 : 빌드 성공 실패 등 메시지 출력

pipeline {
    agent any
    stages {
        stage('Compile') {
            steps {
                echo "Compiled successfully!";
            }
        }

        stage('JUnit') {
            steps {
                echo "JUnit passed successfully!";
            }
        }

        stage('Code Analysis') {
            steps {
                echo "Code Analysis completed successfully!";
            }
        }

        stage('Deploy') {
            steps {
                echo "Deployed successfully!";
            }
        }
    }

    post {
      always {
        echo "This will always run"
      }
      success {
        echo "This will run when the run finished successfully"
      }
      failure {
        echo "This will run if failed"
      }
      unstable {
        echo "This will run when the run was marked as unstable"
      }
      changed {
        echo "This will run when the state of the pipeline has changed"
      }
    }
}

 

확인

 

 

 

 

Jenkins with Kubernetes

Jenkins 에서 k8s 사용을 위한 사전 준비

# jenkins 사용자에서 아래 작업 진행
whoami
mkdir ~/.kube

# root 계정에서 아래 복사 실행
cp ~/.kube/config /var/lib/jenkins/.kube/config
chown jenkins:jenkins /var/lib/jenkins/.kube/config

# jenkins 사용자에서 aws eks 사용(sts 호출 등)을 위한 자격증명 설정
aws configure
AWS Access Key ID [None]: AKIA5ILF2###
AWS Secret Access Key [None]: ###
Default region name [None]: ap-northeast-2

# jenkins 사용자에서 kubectl 명령어 사용 확인
kubectl get pods -A

 

확인

 

 

파이프라인으로 디플로이먼트/서비스 배포

  • 자신의 Github (웹) Repo 3/deploy/deployment-svc.yaml 파일에 image 부분 수정 → 자신의 도커 허브에 이미지가 있어야함
    • (참고) deployment-svc.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: myweb
spec:
  replicas: 2
  selector:
    matchLabels:
      app: mywebs
  template:
    metadata:
      name: myweb
      labels:
        app: mywebs
    spec:
      containers:
      - name: myweb
        image: gasida/myweb:v1.0.0
      terminationGracePeriodSeconds: 0
---
apiVersion: v1
kind: Service
metadata:
  name: myweb
spec:
  ports:
    - name: webport
      port: 8080
      targetPort: 80
  selector:
    app: mywebs
  type: ClusterIP
---
  • item : k8s-1 , pipeline
pipeline {
    agent any

    tools {
        jdk 'jdk-17'
    }

    environment {
        DOCKERHUB_USERNAME = 'dengo2000'
        GITHUB_URL = 'https://github.com/holajin/aews-cicd.git'
        // deployment-svc.yaml -> image: gasida/myweb:v1.0.0        
        DIR_NUM = '3'
    }

    stages {
        stage('Container Build') {
            steps {	
                // 릴리즈파일 체크아웃
                checkout scmGit(branches: [[name: '*/main']], 
                    extensions: [[$class: 'SparseCheckoutPaths', 
                    sparseCheckoutPaths: [[path: "/${DIR_NUM}"]]]], 
                    userRemoteConfigs: [[url: "${GITHUB_URL}"]])

                // 컨테이너 빌드 및 업로드
                sh "docker build -t ${DOCKERHUB_USERNAME}/myweb:v1.0.0 ./${DIR_NUM}"
                sh "docker push ${DOCKERHUB_USERNAME}/myweb:v1.0.0"
            }
        }

        stage('K8S Deploy') {
            steps {
                sh "kubectl apply -f ./${DIR_NUM}/deploy/deployment-svc.yaml"
            }
        }
    }
}

 

빌드 후 확인

'study > AEWS 2기' 카테고리의 다른 글

AEWS 2기 8주차 첫번째  (0) 2024.04.22
AEWS 2기 7주차 두번째  (0) 2024.04.18
AEWS 2기 6주차 세번째  (0) 2024.04.10
AEWS 2기 6주차 두번째  (0) 2024.04.10
AEWS 2기 6주차 첫번째  (0) 2024.04.10