System Engineering/CI, CD

CI/CD #12. Jenkins(젠킨스)를 이용한 Kubernetes(쿠버네티스) 배포

ZunoXI 2021. 6. 24.

개요

jenkins를 이용하여 kubernetes 클러스터에 배포

jenkins kubernetes deploy

지난 포스팅에서는 jenkins의 SSH plugin을 이용하여 원격 서버에 배포를 해봤다. 사실 cicd자체를 쓰는 환경 자체가 devops 혹은 MSA 환경을 지향하며 환경 세팅을 하는 경우가 많을 텐데, 이경우 실제 운영환경이 쿠버네티스 클러스터일 경우가 많다. 또한, 쿠버네티스 클러스터 내에 jenkins를 컨테이너로 구동시키고 클러스터 내에서 jenkins를 운영하는 방법이 있고 실제 대부분의 기술 블로그에서는 이 방법에 대해 기술하고 있다.

 

필자의 환경은 쿠버네티스 클러스터와 독립적으로 jenkins를 운영해야 하며, 원격으로 jenkins가 설치된 VM에서 원격 K8S클러스터로의 배포를 해야 하는 상황이다. 따라서 이번 포스팅은 jenkins to 원격 kubernetes 클러스터 배포에 대한 포스팅이다.

 

 


 

1. Plug-in 설치 및 설정

 

먼저 이번 파이프라인을 구성하는데 필요한 plugin(이하 플러그인)들을 설치해준다. 필요한 플러그인은 'docker, kubernetes Credentials', 'kubernetes Continuous Deploy'이다. Jenkins 관리에서 Plugin Manger(플러그인 관리)로 들어간다음, 설치 가능 탭을 누른 후 아래와 같이 검색 후 설치한다.

 

 

 

 

 

2. docker, kubectl 설치

 

쿠버네티스 클러스터에 배포를 하려면 먼저 jenkins에 빌드되는 소스를 컨테이너 이미지로 만들어서 docker registry에 업로드하는 작업을 젠킨스를 통해 실행해야 한다. 즉, 젠킨스가 구동되는 환경에서 docker가 구동되어야 한다. 마찬가지로 쿠버네티스 클러스터를 원격 제어하려면 원격 클러스터의 kubeconfig 기반으로 kubectl을 사용해야 하므로 kubectl도 함께 설치해줘야 한다.

 

docker 설치

 

docker설치는 다음 포스팅을 참고.

 

Docker #2. 윈도우/리눅스에 도커(Docker) 설치

이번 포스팅에서는 서버에 띄우기 위한 도커파일을 만들기 위해 윈도우와 리눅스에서 도커를 설치해 보려한다. 리눅스가 개발환경인 경우의 설치방법은 생각보다 간편하다. 물론, 테스트 서버

zunoxi.tistory.com

간단하게 CentOS7에 설치하는 경우를 기술한다.

 

# Docker & Docker Registry 설치
yum -y install docker docker-registry

#부팅시 실행하도록 등록
systemctl enable docker.service

# Docker 실행
systemctl start docker.service

# docker 스테이터스 확인
systemctl status docker.service

## 설치 후 재시작
reboot

 

 

docker 소켓에대한 권한부여
sudo usermod -a -G docker $USER   #경우에 따라 dockerroot로 설정
sudo chmod 777 /var/run/docker.sock
sudo chown root:docker /var/run/docker.sock

위 내용관련 더 자세한정보는 다음 포스팅을 참고

 

Docker #12. Got permission denied while trying to connect to the Docker daemon socket 해결방법 #Jenkins

개요 Docker socket에대한 permission 권한부여 Docker Socket Permission 오늘포스팅은 아주 짧지만 해당 방법을 얻고자 필자가 들인시간은 꽤 길다. 기존 CI/CD 파이프라인을 구축하던 중 docker를 통한 k8s 환..

zunoxi.tistory.com

 

 

 

 

kubectl 설치

 

kubectl은 쿠버네티스 클러스터를 조작하기 위한 CLI 툴이며 아래와 같이 설치한다(리눅스인 경우) 

(참고 : 원문 링크 , 쿠버네티스 공식 페이지)

 

리눅스에 kubectl 설치 및 설정

시작하기 전에 클러스터의 마이너(minor) 버전 차이 내에 있는 kubectl 버전을 사용해야 한다. 예를 들어, v1.21 클라이언트는 v1.20, v1.21, v1.22의 컨트롤 플레인과 연동될 수 있다. 최신 버전의 kubectl을

kubernetes.io

 

1. 최신 릴리스 curl을 이용하여 다운로드

curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"

 

2. 바이너리 검증

 

kubectl 체크섬(checksum) 파일을 다운로드

curl -LO "https://dl.k8s.io/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl.sha256"

 

kubectl 바이너리를 체크섬 파일을 통해 검증한다.

echo "$(<kubectl.sha256) kubectl" | sha256sum --check

 

검증이 성공한다면, 출력 메시지는 아래와 같다.

 

kubectl: OK

 

3. kubectl 설치

sudo install -o root -g root -m 0755 kubectl /usr/local/bin/kubectl

 

4. 설치한 버전을 확인

kubectl version --client

 

 

3. kube-config 확인 및 kubernetes Credential 설정

 

kubernetes원격 클러스터를 컨트롤하기 위해 kube-config.yaml 파일에 접근해야 한다. 먼저 jenkins내의 kubernetes Credentials을 설정함으로써 원격 접속 권한을 얻어보자.

 

 

Jenkins 관리 > Manage Credentials 클릭

 

 

새로운 Credentials를 만든다.

 

 

Global Credenitals를 클릭 > 왼쪽 메뉴에서 Add Credentials를 클릭

 

 

 

이 부분이 좀 중요한데 앞서 기술한 플러그인 설치 시 Kubernetes Credentials 플러그인을 정상적으로 설치했다면 Kind 선택란에 Kubernetes configuration (kubeconfig)라는 선택지가 나온다. 해당 항목을 클릭한다.

 

 

이후 ID와 Description은 임의로 기입해주고 Kubeconfig를 선택해준다.

 

 

 

Kubeconfig 옵션
  • Enter directly : 쿠버네티스 마스터 노드의. kube/config의 내용을 다이렉트로 읽어오는 방법이다. 이 방법은 /root/.kube/config에 kube-config.yaml 파일의 내용을 복사하여 붙여 넣는 방법
  • From a file on the Jenkins master : 마스터 노드의 kube-config.yaml 파일을 jenkins 서버 특정 위치에 위치시키고 경로를 기입함으로써 읽는 방법
  • From a file on the Kubernetes master node : SSH로 쿠버네티스 마스터 노드에 원격 접속하여 kube-config.yaml 파일을 읽는 방식

 

필자는 위 옵션 중 From a file on the Jenkins master 방법을 사용했다. 먼저 배포하고자 하는 쿠버네티스 클러스터 마스터 노드(서버)의 kubeconfig파일에 접근한다. 일반적으로 /root/.kube/config에 kube-config.yaml 파일이 있다. 해당 파일을 젠킨스 서버에 복사한다. 필자 같은 경우는 젠킨스 서버도 linux이기에 scp를 이용하여 전송하였다. 해당 파일은 후에 jenkins 파일을 이용하여 원격으로 붙을 때 필요한 속성으로 반드시 필요한 작업이다.

 

# scp 사용예
scp -r kube-config.yaml root@ip:/u01

# jenkins server에서 권한 설정(복사된 폴더에서)
chmod 755 kube-config.yaml

 

이후 아래와 같이 기입한다.

 

 

4. dockerhub Credentials설정

 

위 Credentials 설정과 같은 페이지로 이동후 Username with password Kind를 선택후 아래와 같이 입력한다.

 

 

 

 

5. Item 생성

 

이제 kubernetes연결을 위한 설정은 완료되었다. 이제 Jenkinsfile을 작성하여 파이프라인을 구축해보자. k8s_deploy라는 이름으로 item명을 기입했다.

 

 

필자는 Webhook을 통해 gitlab에 소스 push시 즉시 빌드가 이루어지게끔 설정했다. 관련 방법은 다음 포스팅을 참고하면 될 것 같다. 

 

CI/CD #8. Gitlab Webhook으로 Jenkins 빌드 유발하기

개요 webhook 기술을 통해 Gitlab과 Jesnkins Build 유발하기 Gitlab Webhook 앞선 포스팅을 통해 gitlab과 jenkins를 연동하고 gitlab저장소에 있는 소스를 기반으로 Maven 빌드하는 과정을 기술했었다. 이번 포..

zunoxi.tistory.com

 

 

다음 pipeline 탭으로 이동한다. pipeline 스크립트는 직접 기입해도 되지만 pipeline도 일종의 버전 관리를 하기 위해, 또한 IDE에서 쉽게 편집하기 위해 git프로젝트 root폴더에 jenkinsfile을 읽게 설정한다. 이는 Definition선택창에서 Pipeline script from SCM을 선택하면 된다. 이후 SCM은 git, Repositories url은 gitlab프로젝트의 url, Credenials은 jenkins에 설정해둔 gitlab용 url이다. 사전에 설정한 Credentials이 없다면 Add 버튼을 눌러서 만들면 된다.

 

Script Path는 jenkinsfile.groovy로 설정하고 저장한다. (jenkinsfile은 groovy문법을 사용한다.)

 

 

 

6. Jenkinsfile 작성

 

파이프라인에서 가장 중요하다고 할 수 있는 Jenkinsfile을 작성하고 프로젝트 소스의 root에 위치시킨다. 필자가 작성한 Jenkins 파일 샘플은 다음과 같다.

 

/* pipeline 변수 설정 */
def app

node {
    // gitlab으로부터 소스 다운하는 stage
    stage('Checkout') {
            checkout scm   
    }
 
    // mvn 툴 선언하는 stage, 필자의 경우 maven 3.6.0을 사용중
    stage('Ready'){  
        sh "echo 'Ready to build'"
        mvnHome = tool 'Maven 3.6.0'
    }

    // mvn 빌드로 jar파일을 생성하는 stage
    stage('Build'){  
        sh "echo 'Build Spring Boot Jar'"
        sh "'${mvnHome}/bin/mvn' clean package"
    }

    //sonarqube 정적분석 실행하는 stage, jenkins와 sonarqube연동을 하지 않았다면 이부분은 주석처리
    stage('Static Code Analysis') {  
        sh "'${mvnHome}/bin/mvn' clean verify sonar:sonar -Dsonar.projectName=pipeline_test -Dsonar.projectKey=pipeline_test -Dsonar.projectVersion=$BUILD_NUMBER"
    }

    //dockerfile기반 빌드하는 stage ,git소스 root에 dockerfile이 있어야한다
    stage('Build image'){   
        app = docker.build("cross9308/dockertest")
    }


    //docker image를 push하는 stage, 필자는 dockerhub에 이미지를 올렸으나 보통 private image repo를 별도 구축해서 사용하는것이 좋음
    //docker.withRegistry에 dockerhub는 앞서 설정한 dockerhub credentials의 ID이다.
    stage('Push image') {   
        docker.withRegistry('https://registry.hub.docker.com', 'dockerhub') {
            app.push("${env.BUILD_NUMBER}")
            app.push("latest")
        }
    }
    
    // kubernetes에 배포하는 stage, 배포할 yaml파일(필자의 경우 test.yaml)은 jenkinsfile과 마찬가지로 git소스 root에 위치시킨다.
    // kubeconfigID에는 앞서 설정한 Kubernetes Credentials를 입력하고 'sh'는 쿠버네티스 클러스터에 원격으로 실행시킬 명령어를 기술한다.
    stage('Kubernetes deploy') {
        kubernetesDeploy configs: "test.yaml", kubeconfigId: 'Kuberconfig'
        sh "/usr/local/bin/kubectl --kubeconfig=/u01/kube-config.yaml rollout restart deployment/test-deployment -n zuno"
    }

    stage('Complete') {
        sh "echo 'The end'"
    }
}

 

kubernete deploy stage에 대한 부연설명으로 최초 배포 시에는 서비스, 디플로이먼트 정보가 포함된 yaml파일이 필요하기 때문에 해당 방식으로 배포하면 된다. 이후 롤링만 해주면 되는 작업은 'sh'로 직접 명령을 내려서 수행이 가능하다. 이때 /usr/local/bin/kubectl은 jenkins내에 kubectl이 설치된 위치이며 그 이후 문법은 쿠버네티스에 대한 기본적인 디플로이먼트, 서비스 등에 대한 지식이 필요하므로 k8s 공식 사이트를 참고하는 것을 추천한다.

 

위 내용을 기반으로 build now혹은 webhook이 설정된 경우는 소스 push를 통해 정상적으로 배포가 되는지 확인하면 완료된다. 확인은 쿠버네티스 서버에서 배포 현황이나 브라우저(ip:port)를 통해 확인하면 되겠다.

 

 

 

참고로 모든 동작이 정상적으로 수행될 수 있게 gitlab에 올라간 root위치의 소스들은 다음과 같다.

 

 

 

 

 

7. Troubleshooting

 

경우에따라 번거롭지만 젠킨스내의 플러그인 버전 문제로 아래 몇가지 설정을 해줘야한다.(이거 진짜 고급정보인데..) 기술된대로 파이프라인을 구성하다보면 쿠버네티스 디플로이시 아래와 같은 에러를 확인할 수 있다.

 

 

ERROR: ERROR: Can't construct a java object for tag:yaml.org,2002:io.kubernetes 어쩌구 저쩌구... 이는 jackson2-api와 snakeyaml 플러그인들이 서로 꼬여서 yaml파일을 제대로 읽지못하는 문제라고한다. 여러가지로 구글링을 해보며 다운그레이드도 해봤는데 결론은 kubernetes-cd라는 플러그인만 1.0으로 다운그레이드 해주면 된다.

 

우선 다운받을 https://updates.jenkins-ci.org/download/plugins/ 사이트는 이며, 이곳에서 kubernetes-cd(kubernetes Continuous Deploy) 1.0.0 버전을 다운로드하여 서버에 업로드한다. 다음 젠킨스서버에서 플러그인파일들이 위치한 폴더로 접근후 다음 명령어로 kubernetes-cd 플러그인을 삭제한다.

 

rm -rf /var/lib/jenkins/plugins kubernetes-cd*

 

이후 다운받고 업로드한 hpi파일을 해당 플러그인 폴더에 이동시키고 권한 설정 및 jenkins를 재기동하면 플러그인이 해당버전으로 재설치 된다. (처음부터 서버로 바로 받을 수 있으면 더 간편하게 할 수 있을것 같다..)

$ cp kubernetes-cd.hpi /var/lib/jenkins/plugins/
$ cd /var/lib/jenkins/plugins/
$ chown jenkins:jenkins kubernetes-cd.hpi
$ chmod 755 kubernetes-cd.hpi
$ systemctl restart jenkins.service

 

재기동 후 설치된 플러그인을 확인해보면 아래와 같이 kubernetes continuous deploy가 1.0 버전으로 설치된 것을 알 수 있다. 이후 다시 빌드를 시전한다.

 

 

 

정상적으로 빌드가 완료되었다 :) 해당포스팅은 https://zunoxi.tistory.com/110에 별도 기술.

반응형

댓글