파이널 프로젝트 - 15주차 2일(3/28)

최수환·2023년 3월 28일
0

Kubernetes

목록 보기
67/75
post-thumbnail

Backend CI/CD 파이프라인

  • 일단 어제 지금까지만 개발된 백엔드 코드에 대한 도커라이징을 테스트했다.
  • 이제부터 Jenkins를 이용해 파이프라인을 구축할 것이다.

1 . 백엔드 코드 수정 및 변경

  • 개발자님의 백엔드코드를 나의 git으로 fork해서 가져온뒤 workDIR에 clone을 통해 remote로 연결하였다. 이후 정상적으로 PUSH가 되는지 테스트하였다.
  • 개발자님의 백엔드 코드중 교수등록 부분은 개발중이기 때문에 해당 기능과 관련된 파일은 삭제하였다.
  • DB연결은 추후에 할 예정이다. ( application-aws.yaml )
  • ApplicationTests.java파일에서 테스트부분이 계속 오류가 났는데 아래와 같이 주석처리로 해결하였다.
//@SpringBootTest
  • Jenkins에서 개발코드가 있는 git을 checkout할때 git전체에 대해서만 url을 등록할 수 있고, git에서 내가 빌드하길 원하는 코드가 있는 디렉터리만을 등록할 수 없었다. 따라서 그냥 해당 디렉터리에 있는 모든 파일들을 루트 디렉터리로 가져왔다.
    -> 나머지 디렉터리는 모두 삭제하고, 관계없는 파일 또한 삭제하였다.
    -> 그리고 git을 등록하니 정상적으로 checkout해서 빌드하였다

    사실 이렇게하면 필요한 디렉터리나 파일들이 삭제되는 경우가 발생할 것이고, 루트 디렉터리에서 모든 파일이 존재하다보니 관리가 어려울 것이다. 따라서 개발 코드를 디렉터리별로 관리하고 git을 등록할때도 그냥 전체 git주소를 등록하면 된다. 다만 아래와 같이 Pipeline코드를 짤때 빌드하길 원하는 git의 디렉터리를 지정해주면 된다.

    dir('backend/spring'){ # 특정 디렉터리 지정 
        sh 'gradle wrapper --gradle-version 8.0.2'
     }
     

2 . Jenkinsfile 작성

  • Jenkinsfile 작성에 앞서 플러그인관리에 들어가 Gradle Plugin을 설치해준다
pipeline{
    agent{
        kubernetes{
yaml '''
apiVersion: v1
kind: Pod
spec:
  containers:
  - name: gradle
    image: gradle:8.0.2-jdk11
    command: ['sleep']
    args: ['infinity']
  - name: kaniko
    image: gcr.io/kaniko-project/executor:debug
    command: ['sleep']
    args: ['infinity']
    volumeMounts:
    - name: registry-credentials
      mountPath: /kaniko/.docker
  volumes: 
  - name: registry-credentials
    secret:
      secretName: regcred  
      items:
      - key: .dockerconfigjson
        path: config.json
'''
      }
    }

    stages{
        stage('checkout'){
          steps{
            container('gradle'){
              git branch: 'main', url:'https://github.com/suhwan12/GoormUniversity-course-registration.git'
              } # 루트 디렉터리에 다 모아놓고 git주소를 등록
               # 루트 디렉터리에 모아놓지 않아도 dir로 빌드하길 원하는 디렉터리 지정 가능 
            }
        }
        stage('install gradlew'){ # gradlew 설치 
            steps{
              container('gradle'){
                sh 'gradle wrapper --gradle-version 8.0.2'
                }
            }
        }

        stage('gradle build project'){ # build와 libs 디렉터리 생성 및 jar파일 생성 
            steps{
              container('gradle'){
                sh './gradlew build'
                }
             }
        }
        stage('Build & Tag dokcer image'){ # Dockerfile 빌드
            steps{
                container('kaniko'){
                    sh "executor --dockerfile=Dockerfile \
                    --context=dir://${env.WORKSPACE} \
                    --destination=suhwan11/backend:latest \
                    --destination=suhwan11/backend:${env.BUILD_NUMBER}"

                }
            }
        }
        stage('Update K8s to New Deployment'){ # 새로운 이미지로 교체 
            steps{
                container('gradle'){
                    git branch: 'main' , url:'https://github.com/suhwan12/finalproject-argocd.git'
                    sh 'sed -i "s/image:.*/image: suhwan11\\/backend:${BUILD_NUMBER}/g" back-deployment.yaml'
                    sh 'git config --global user.name suhwan12'
                    sh 'git config --global user.email xman0120@naver.com'
                    sh 'git config --global --add safe.directory /home/jenkins/agent/workspace/suhwan-test-pipe'
                    sh 'git add back-deployment.yaml'
                    sh 'git commit -m "Jenkins Build Number - ${BUILD_NUMBER}"'
                    withCredentials([gitUsernamePassword(credentialsId: 'github-credentials', gitToolName: 'Default')]) {
                        sh 'git push origin main'
                    }
                }
            }
        }
    }
}
  • Dockerfile을 빌드하기 위하여 Kaniko를 사용하였는데, Kaniko를 사용하여 빌드하고 태깅하여 Docker Hub에 Push하려면 Docker Hub에 대한 권한이 있어야 하기 때문에 Docker Hub에서 토큰을 생성해서 토큰을 이용하여 secret을 만들어준다.
  • 생성한 secret을 볼륨으로 마운트한 컨테이너를 파드에 추가한다. Agent는 container로 kaniko가 지정되면 파드에서 임시로 kaniko컨테이너를 생성하고 해당 컨테이너 환경에서 작업을 수행한다.
    -> 컨트롤러가 직접 작업을 하는 것이 아니라 파드에서 해당 작업에 필요한 환경을 갖춘 컨테이너를 임시적으로 띄워서 수행하기 때문에 항상 인스턴스를 띄울 필요가 없는 Jenkins에서의 노드 개념이다.
    = 컴퓨팅 리소스 자원과 비용을 아낄 수 있다.
    -> 또한 필요한 환경을 갖추었기 때문에 작업을 문제없이 수행한다.
  • 마지막 stage에서 sed명령어를 통해 Docker Hub에 Push된 이미지를 ArgoCD와 연동중인 git에서 배포하고 있는
    back-deployment의 image와 교체한다.
    -> 이미지를 교체할 yaml파일을 정확하게 입력해야한다.
    -> git에서 발급받은 토큰으로 Jenkins에서 credential을 생성하고 이것을 이용해 Jenkins가 Git에 접근할 권한을 가지게 한다.
    이를 통해 push가 가능해진다.
  • 빌드하는 과정에서 계속 오류가 발생하였는데 안전하지 않은 디렉터리라는 오류가 발생하였다. 따라서 아래와 같이 프로젝트 경로의 디렉터리에 안전한 디렉터리인것을 명시했다.
sh 'git config --global --add safe.directory /home/jenkins/agent/workspace/suhwan-test-pipe'

3 . Dockerfile 작성

FROM openjdk:11-jre 
WORKDIR /usr/src/
COPY . /usr/src/
CMD ["java","-jar","/usr/src/build/libs/api-0.0.1-SNAPSHOT.jar"]
  • 처음에는 FROM으로 java 이미지 가져오고 바로 CMD로 jar파일을 실행시키도록 작성하였다.
  • 하지만 경로에 문제로 인하여 실행시킬 jar파일을 찾지 못하는 오류가 발생하였고, 따라서 WORKDIR과 COPY를 통해 특정 경로를 지정하여 빌드된 파일들을 복사했고, 해당 경로를 작업공간으로 지정해서 Jar파일을 실행시키니 정상적으로 빌드되어 이미지가 생성되었다.

4 . 결과 테스트

  • Jenkins에서 새로운 item을 생성해서 Pipeline script from SCM을 선택하고 git주소를 등록하고 main으로 변경하였다.
  • 위에서 생성한 Jenkinsfile을 등록하였다.
    -> 수동으로 빌드하지않아도 Jenkins에서 주기적으로 git에 변경사항이 없는지 모니터링하는 poll SCM은 생략하였다.
    -> 본격적으로 개발 완료된 코드에 대해서는 파이프라인을 구축할 때 poll SCM을 적용시켜 개발자 코드의 변경사항에 대해서도 자동화를 구성할 것이지만, 현재는 테스트기 때문에 수동으로 빌드하는 것이 더 편하다.

  • 정상적으로 구축한 Pipeline이 빌드되는 것을 확인할 수 있다.

  • DockerHub에서도 빌드 순서가 tag되어 생성된 이미지가 Push되어 있는 것을 확인

  • ArgoCD와 연동중인 git에서도 comment와 함께 새로 Push가 된 것을 볼 수 있다.

  • 새로 Push된 yaml파일을 들어가보면 image가 자동으로 DockerHub에 새로 Push된 이미지로 교체되어 있는 것을 확인.

  • ArgoCD가 자신과 연동중인 git에 변경사항이 생긴것을 감지하고 새로 교체된 이미지가 적용된 컨테이너를 가진 파드를 deployment가 새로운 replicaset을 만들어 Rolling Update로 배포되는 것을 확인

  • 백엔드 Deployment를 외부에 노출시키고 있는
    백엔드 Ingress( = ALB)의 Dns Name을 브라우저에 입력하면 정상적으로 웹페이지가 나타나는 것을 확인
    -> 정상적으로 백엔드 서버가 배포 되었다는 것.

추후 계획

  • 오늘은 현재까지 개발된 backend코드에 대해서 CI/CD 파이프라인 구축 테스트를 완료하였다. 다만 아직 데이터베이스 연결이 되지 않았고, 추후에 개발자분이 더 개발하신 것에 대해서 최종적으로 파이프라인을 구축해야 하기 때문에 백엔드에 대한 CI/CD 파이프라인 구축 작업은 앞으로도 계속 진행될 예정이다.
  • 또한 프론트엔드에 대한 CI/CD 파이프라인 구축은 해본적도없고, 자료와 지식이 없기 때문에 기간을 두고 충분한 자료조사와 여러 테스트를 통해 구축할 예정이다.
profile
성실하게 열심히!

0개의 댓글