jenkins-CI/CD

kiyeon·2022년 12월 12일
0


위 이미지와 같이 Jenkins 를 활용하여 CI/CD 이미지 배포를 셋팅하려고한다.
Jenkinsfile 은 4단계로 나눠진다.
Jenkinsfile

  • Build Docker Image
    - Jenkins 서버에서 dockerfile 이미지 빌드
  • Run test code
    - 파이썬으로 빌드된 이미지를 pytest 로 확인
  • Push Docker Image
    - 빌드된 이미지를 도커 저장소로 push
  • Deploy workload
    - docker-compose.yml 파일을 --> 서버(EC2) 복사한다.
    • 원격 ssh 접속하여 docker-compose.yml 실행하여 도커 저장소로부터 이미지를 내려받아 컨테이너 생성
  • 기타
    - slack 알림메세지 설정

GithubJenkins연동
JenkinsSlack연동

pipeline {
    agent any

    parameters {
        booleanParam(name : 'BUILD_DOCKER_IMAGE', defaultValue : true, description : 'BUILD_DOCKER_IMAGE')
        booleanParam(name : 'RUN_TEST', defaultValue : true, description : 'RUN_TEST')
        booleanParam(name : 'PUSH_DOCKER_IMAGE', defaultValue : true, description : 'PUSH_DOCKER_IMAGE')
        booleanParam(name : 'DEPLOY_WORKLOAD', defaultValue : true, description : 'DEPLOY_WORKLOAD')
        
        // CI
        string(name : 'ACCOUNT_ID', defaultValue : 'hwang088', description : 'ACCOUNT_ID')
        string(name : 'DOCKER_IMAGE_NAME', defaultValue : 'pipeline-test', description : 'DOCKER_IMAGE_NAME')
        string(name : 'DOCKER_TAG', defaultValue : '1.0.0', description : 'DOCKER_TAG')

        // CD
        string(name : 'TARGET_SVR_USER', defaultValue : 'ec2-user', description : 'TARGET_SVR_USER')
        string(name :'TARGET_SVR_DIR', defaultValue : '/home/ec2-user/', description : 'TARGET_SVR_PATH')
        string(name : 'TARGET_SVR', defaultValue : '10.0.1.251', description : 'TARGET_SVR')


    }

    environment {
        REGION = "ap-northeast-1"
        ECR_REPOSITORY = "${params.ACCOUNT_ID}/${params.DOCKER_IMAGE_NAME}"
        ECR_DOCKER_TAG = "${params.DOCKER_TAG}"
        DOCKER_ACCOUNT_ID = "${params.ACCOUNT_ID}"
        TARGET_SERVER = "${params.TARGET_SVR_USER}@${params.TARGET_SVR}"
        TARGET_PATH = "${params.TARGET_SVR_DIR}"

    }

    stages {
        stage('============ Build Docker Image ============') {
            when {
                expression {return params.BUILD_DOCKER_IMAGE}
            }
            steps {
                dir("${env.WORKSPACE}") {
                    sh 'docker build -t ${ECR_REPOSITORY}:${ECR_DOCKER_TAG} .'
                }
            }
            post {
                always {
                    echo "Docker build success!!"
                }
            }
        }
        stage('============ Run test code ============') {
            when { expression { return params.RUN_TEST }}
            steps {
                sh('docker run --rm ${ECR_REPOSITORY}:${ECR_DOCKER_TAG} /root/.local/bin/pytest -v ')
                echo 'good'
            }
        }
        stage('============ Push Docker Image ============') {
            when { expression { return params.PUSH_DOCKER_IMAGE }}
            steps {
                
                sh '''
                   cat ~/my_password.txt | docker login --username ${DOCKER_ACCOUNT_ID} --password-stdin
                   docker push ${ECR_REPOSITORY}:${ECR_DOCKER_TAG}
                '''
                echo "Push Docker Image to Docker_hub"
            
            }
        }
        stage('============ Deploy workload ============') {
            when { expression { return params.DEPLOY_WORKLOAD}}
            steps {
                sshagent (credentials: ['aws_ec2_user_ssh']) {
            
                    sh """#!/bin/bash
                        scp -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
                            deploy/docker-compose.yml \
                            ${TARGET_SERVER}:${TARGET_PATH};

                        ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no \
                            ${TARGET_SERVER} \
                            'cat ~/my_password.txt | docker login --username ${DOCKER_ACCOUNT_ID} --password-stdin; \
                            export IMAGE=${ECR_REPOSITORY}; \
                            export TAG=${ECR_DOCKER_TAG}; \
                            docker-compose -f docker-compose.yml down;
                            docker-compose -f docker-compose.yml up -d';
                """
                
                    echo "complete" 



                }
            }
        }
    }
    post {
        success {
            slackSend(
                channel: "#jenkins_test",
                color: "good",
                message: "[Successful] Job:${env.JOB_NAME}, Build num:#${env.BUILD_NUMBER} (<${env.RUN_DISPLAY_URL}|open job detail>)"
            )
        }
        failure {
            slackSend(
                channel: "#jenkins_test",
                color: "danger",
                message: "[Failed] Job:${env.JOB_NAME}, Build num:#${env.BUILD_NUMBER} @channel (<${env.RUN_DISPLAY_URL}|open job detail>)"
            )
        }
    }
}

jenkinsfile 작성하는데 있어 많은 시간을 소비했다 확인해보니 이상하게도 파라미터 ${params.NAME} 사용하니깐 변수를 못받았다
여러 블로그를 참조하니 파라미터를 사용하길래 당연히 될줄알고 사용했는데 이럴줄몰랐다. 그래서 우선 환경변수(ENV)로 등록하여 사용하니 정상작동을 했다.
기타
- ssh key 생성
- ssh-keygen -t rsa
- ssh-copy-id -i ~/.ssh/rd_rsa.pub 호스트네임@IP
- 호스트 .ssh 소유자 및 권한 확인 (소유자:호스트, 권한: 700)

  • jenkins에 private 키 입력시 마지막 뛰어쓰기가(enter) 되어있어야한다
  • 원격 접속 후 스크립트 실행 시 명령어 앞뒤 ' ' 추가해야지 그안에서 실행 되면 안할시 jenkins 서버에서 명령어 실행됨
  • docker push image tag command not found 위와 같이 젠킨스 장애 시 yum install -y docker-ce-cli 설치 되어있는지 확인

0개의 댓글