CICD 구성 (Jenkisfile)

이정훈·2023년 7월 7일
0

CI/CD

목록 보기
8/11
post-thumbnail

1. Slack 알람 설정!

  • Jenkisfile을 구성하기 전에 우린 알람을 설정하고자 한다. 실패했는지, 성공했는지 그러기 위해서 일단 Slack에 하나의 워크스페이스를 만들어줬다.

  • 앱 관리에서 jenkins CI를 설치해준다!

  • Slack에 추가를 눌러준다!

  • 채널을 선택해주는데 토큰값을 받기 위함이다 하나를 만들어서 설정해주던가 아니면 그냥 일반을 선택해도 무관하다!

  • 일반을 선택해서 하면 이제 친절하게 Jenkins에서 어떻게 설정하라고 하는지 알려주기는 한다!
  • 그 아래에 통합설정 부분이 있는데 여기서 중요한 것은 토큰값을 저장해놔야한다!!

  • 저장한 토큰값을 Jenkins에 저장해줘야한다! 이건 앞에서 계속했던 것들이다.

  • Slack plugin 설치해주자!

  • system에 저장된 토큰값을 불러들어와서 접속이 되는지 확인한다!
  • 여기서 중요한점! 우린 각각 알람을 받고 싶은 채널 각 각 알람을 받을 수 있도록 설정하기 위해,
    Default channel에 #채널명, #채널명을 입력해줘야한다!
  • 그리고 test connection을 해주자

  • 이렇게 구성해주면 Jenkinsfile 아래와 같은 코드를 입력해줄 수 있다!
  • 알람은 어느 채널로 보낼 것이고 메세지앞에 색은 빨간색, 그리고 메세지는 이렇게!
slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: Git Clone")

2. Jenkins 구성

2-1 pipeline 구성

  • app 이라는 pipeline을 만들어 주자

  • GitHub Project를 할것이니깐 url을 적어주자

  • githook을 관찰합시다

  • pipeline은 아래와 같이 설정할 것이다!
  • git SCM 으로 클론이랑 이런것들을 쉽게 할 수 있다.
  • url을 넣어줘도 지금 접점이 없다.. 그래서 credentials을 연결해줘야한다.

  • Add - Jenkins를 눌러 추가해주자!

  • 만들어준 자격증명을 넣어주면 저 에러가 사라진다!

  • 아래 Script Path 부분에 Jenkinsfile
  • 이 부분은 우리가 실행하고자 하는 Jenkinsfile의 위치가 어디에 있냐? 이것을 물어보는것이다.
  • 나는 Git repo 에 그냥 넣어놨기 때문에 경로를 그냥 바로 읽을 수 있도록! 했다.

2-2 jenkinsfile

  • 깃에 Push를 하면 Jenkisn Master가 접수를 받고 Slave에게 일을 배정할 것이다. 일단 전체적인 Jenkinsfile내용을 보고 시작하자!
  • 아래에서 하나씩 살펴보고자 한다.
  • Jenkinsfile을 실행하면서 실패할것이다! 왜냐?? 우린 설정을 다 안해줬으니깐!!
pipeline {
    agent {
        label 'Slave01'
    }

    environment {
        AWS_REGION = credentials('AWS_REGION')
        AWS_ACCOUNT_ID_ECR = credentials('AWS_ACCOUNT_ID_ECR')
        githubCredential = 'github-user-account'
        gitEmail = 'gugucone999@gmail.com'
        gitName = 'ONE-OF-WORLD'
        IMAGE_NAME = "app:${env.BUILD_NUMBER}"
    }

    stages {
        stage('Git Clone') {
            steps {
                checkout scm
            }
            post {
                failure {
                    echo 'Repository clone failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: Git Clone")

                }
                success {
                    echo 'Repository clone success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: Git Clone")
                }
            }
        }

        stage('Docker Image Build') {
            steps {
                sh "docker build -t ${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_NAME} --file Dockerfile ."
            }
            
            post {
                failure {
                    echo 'Docker Image Build failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: Docker Image Build ${IMAGE_NAME}")
                }
                success {
                    echo 'Docker Image Build success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: Docker Image Build ${IMAGE_NAME}")
                }
            }
        }
            
        stage('ECR Login') {
            steps {
                sh "aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com"
            }
            
            post {
                failure {
                    echo 'ECR login failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: ECR Login")

                    
                }
                success {
                    echo 'ECR login success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: ECR Login")
                }
            }
        }
            
        stage('ECR Image Push') {
            steps {
                sh "docker push ${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_NAME}"
            }
            
            post {
                failure {
                    echo 'ECR Push failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: ECR Push ${IMAGE_NAME}")

                }
                success {
                    echo 'ECR Push success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: ECR Push ${IMAGE_NAME}")
                }
            }
        }
        
        stage('K8S Manifest Update') {
            steps {
                git credentialsId: githubCredential,
                    url: 'https://github.com/ONE-OF-WORLD/Deploy.git',
                    branch: 'main'
                sh "git config --global user.email ${gitEmail}"
                sh "git config --global user.name ${gitName}"
                sh "sed -i -r 's|(${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com/app:)[0-9]+|\\1${BUILD_NUMBER}|g' app/create-back-pod.yaml"
                sh "git add ."
                sh "git commit -m 'fix: Update ${IMAGE_NAME} image version'"
                sh "git branch -M main"
                sh "git remote remove origin"
                sh "git remote add origin git@github.com:ONE-OF-WORLD/Deploy.git"
                sh "git push -u origin main"
                }
            
            post {
                failure {
                    echo 'K8S Manifest failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: K8S Manifest Update ${IMAGE_NAME}")
                }
                success {
                    echo 'K8S Manifest success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: K8S Manifest Update ${IMAGE_NAME}")
                }
            }        
        }
    }
}

2-2-1 누구에게? 환경은?

  • Slave 01에게 일을 배정, Label Slave01로 지정
  • 환경 구성은 AWS_REGION, AWS_ACCOUNT_ID_ECR, githubCredential 이 두 개는 Credential에 등록해 놓은 것들이다.
  • gitEmail, gitName은 처음 설정할 때, 뭘 집어 넣어야 할지 헷갈릴 수 있어 남겨 두었다!
    내가 접속할 때 사용하였던 email과 github의 이름을 넣어줘야 한다! 계정 이름이 아니다!
  • IMAGE_NAME 는 app:빌드번호 로 들어가도록 설정해 주었다.
agent {
        label 'Slave02'
    }

    environment {
        AWS_REGION = credentials('AWS_REGION')
        AWS_ACCOUNT_ID_ECR = credentials('AWS_ACCOUNT_ID_ECR')
        githubCredential = 'github-user-account'
        gitEmail = 'gugucone999@gmail.com'
        gitName = 'ONE-OF-WORLD'
        IMAGE_NAME = "app:${env.BUILD_NUMBER}"
    }

2-2-2 Git Clone

  • 자 이제 stages들이 시작될 것이다! 처음에 우린 git에서 내용들을 받아와야 작업이 진행 되니깐 git clone을 하자!
  • 근데 우리는 이미 git scm을 등록했기 때문에 checkout scm 으로 해결할 수 있다.
    stages {
        stage('Git Clone') {
            steps {
                checkout scm
            }
            post {
                failure {
                    echo 'Repository clone failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: Git Clone")

                }
                success {
                    echo 'Repository clone success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: Git Clone")
                }
            }
        }
  • git clone이 성공된 것을 확인할 수 있다!

2-2-3 Docker Image Build

  • 우린 ECR에다가 Image를 업로드 해야 하기 때문에 미리 만들어놔야한다!
  • 또한 Slave01이 docker를 실행하기 때문에 docker를 설치해줘야 한다!
  • 그리고 마지막으로 Jenkins에서 docker, docker pipeline plugin도 설치해주자!
  • 여기서는 app 만 사용할 것이다!

  • repo를 만들어 줬고 docerk 설치해 줬고 빌드하자!
  • 현재 디렉토리에 있는 Dockerfile을 사용하여 ${IMAGE_NAME}으로 지정된 Docker 이미지를 빌드하고, ${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com과 함께 태그를 지정하겠다!
stage('Docker Image Build') {
            steps {
                sh "docker build -t ${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_NAME} --file Dockerfile ."
            }
            
            post {
                failure {
                    echo 'Docker Image Build failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: Docker Image Build ${IMAGE_NAME}")
                }
                success {
                    echo 'Docker Image Build success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: Docker Image Build ${IMAGE_NAME}")
                }
            }
        }
  • Docker Image Build가 실패했다…오류를 살펴보니 권한이 없다!

  • var/run.docker.sock 에 권한이 없어서 안되고 있다.
  • 그럼 아래와 같이 권한을 주자!
sudo chmod 666 /var/run/docker.sock
  • 그럼 이제 빌드가 성공된 것을 확인할 수 있다!
  • 이미지도 잘 만들어 진 것을 확인!

2-2-4 ECR Login

  • ECR에서 repo를 만들고 안에 들어가면 푸시 명령보기가 있다!
  • 푸시명령보기에서 AWS CLI 를 통해 로그인하는 코드가 적혀있다.

  • AWS CLI를 사용하여 AWS ECR에 등록된 Docker registry에 로그인 하겠다 이다.
stage('ECR Login') {
            steps {
                sh "aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com"
            }
            
            post {
                failure {
                    echo 'ECR login failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: ECR Login")

                    
                }
                success {
                    echo 'ECR login success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: ECR Login")
                }
            }
        }
  • 근데 아래와 같이 오류가 나왔다.

  • Jenkins에서 credential로 설정해줄 수 있지만 나는 하나의 jenkis서버에서 하나의 작업만 진행해 줄 것이기 때문에 Slave 서버에 직접 AWS CLI를 설치후 AWS Configure을 해줄 것이다!
sudo apt install awscli -y
aws configure 
	AWS Access Key ID
	AWS Secret Access Key
	Default region name

  • aws configure를 해주니깐 ECR Login 성공!
  • 추후 이 작업을 서버에서 직접하지말고 Jenknis에서 설정할 수 있도록 바꿔보고자 한다!
  • 여기서 사용하는 AWS_ACCOUNT_ID_ECR = credentials('AWS_ACCOUNT_ID_ECR') 이 친구와 동일해야한다!

2-2-5 ECR Image Push

  • 위에서 AWS configure를 등록해 줬으면 순조롭게 아래 이미지 Push도 같이 될 것이다!
        stage('ECR Image Push') {
            steps {
                sh "docker push ${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com/${IMAGE_NAME}"
            }
            
            post {
                failure {
                    echo 'ECR Push failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: ECR Push ${IMAGE_NAME}")

                }
                success {
                    echo 'ECR Push success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: ECR Push ${IMAGE_NAME}")
                }
            }
        }

2-2-6 K8S Manifest Update

  • 이제 수정한 파일들을 Argo가 읽도록 수정해줘야 한다!
    image:tag를 수정해서 올려주도록 하자!
  • 여기서 새로운 git repo가 필요하다! 기존에 쓰던 repo를 사용하면 무한 반복의 길을 걷게 될 것이다.
  • 자격증명 생성해주고, 변수들을 불러와서 각 git 명령어가 실행되도록 해줘야 한다.
        stage('K8S Manifest Update') {
            steps {
                git credentialsId: githubCredential,
                    url: 'https://github.com/ONE-OF-WORLD/Deploy.git',
                    branch: 'main'
                sh "git config --global user.email ${gitEmail}"
                sh "git config --global user.name ${gitName}"
                sh "sed -i -r 's|(${AWS_ACCOUNT_ID_ECR}.dkr.ecr.${AWS_REGION}.amazonaws.com/app:)[0-9]+|\\1${BUILD_NUMBER}|g' app/create-back-pod.yaml"
                sh "git add ."
                sh "git commit -m 'fix: Update ${IMAGE_NAME} image version'"
                sh "git branch -M main"
                sh "git remote remove origin"
                sh "git remote add origin git@github.com:ONE-OF-WORLD/Deploy.git"
                sh "git push -u origin main"
                }
            
            post {
                failure {
                    echo 'K8S Manifest failure'
                    slackSend (channel: "#app-build-state", color: '#FF0000', message: "FAILED: K8S Manifest Update ${IMAGE_NAME}")
                }
                success {
                    echo 'K8S Manifest success'
                    slackSend (channel: "#app-build-state", color: '#0AC9FF', message: "SUCCESS: K8S Manifest Update ${IMAGE_NAME}")
                }
            }        
        }
  • 내가 만든 것은 deploy라는 레포에 폴더를 만들어서 사용할 것이다.
  • app, wep 두개의 폴더를 사용할 것이다. 그리고 그 친구들의 파일은 app/create-back-pod.yaml 이렇게 구성을 해줬다.

  • 잘 실행되다가 push를 해야하지만 Slave 서버와 git이 서로 통신을 못하고 있기 때문에 연결 해줘야한다!
  • 내가 만든 Slave는 프라이빗이고 ssh 접근이기 때문에 있기때문이다!

  • 그래서 Slave 서버 에서 ssh-keygen을 생성해서 서로 연결이 되도록 해줘야한다!
ssh-keygen
cat .ssh/id_rsa.pub

  • 위에 나온 값을 github내 계정의 ssh key쪽에 넣어줘야한다!!

  • 그런 다음에 Slave 서버에서
ssh -T git@github.com
  • 위 명령어를 입력한다음 yes! 해주면 인사해준다!

  • git에도 잘 들어와있는 것을 확인할 수 있다!!

  • 현재는 app 만 만들었는데 web도 동일한 방법으로 진행해 주면 된다!

  • 우리가 만든 repo에 배포하고자하는 파일들을 넣어준 다음에 Argo가 바라보게 한다면 구르굿! 다음장에 설명하겠다!

profile
싱숭생숭늉

0개의 댓글