PaaS/CI CD

(Jenkins, Dockerhub, Github, Kubernetes) Github에서 소스를 가져와 Kubernetes에 Jenkins 통해서 배포하기

armyost 2021. 7. 22. 10:49
728x90

우선 대단원의 막을 내고자 최종적으로 정리한다. 

 

Jenkins를 통해서 Kubernetes에 배포하는 파이프라인을 전체적으로 설명하고자 한다. 

 

전제조건으로 건강한 Kubernetes Cluster(Worker노드 1개 이상) 이 있어야 하고,

Jenkins-leader가 Kubernetes안에 pod로 올라가 있어야 한다. (만약 Kubernetes 외부에 있으면 Kubernetes 연결작업이  좀더 복잡해진다고 생각하면 된다)

 

파이프라인은 이렇게 움직인다.

1) Github에서 Iac (Infra As Coding) 형식의 파일을 Jenkins로 pull 받기

2) Jenkins에서 pull받은 DockerFile을 참고해서 Kubernetes Cluster로 docker build/push 등등 docker 관련 수행 커맨드 전송

3) Kubernetes Cluster에서 해당 커맨드를 수행하면서 push 이벤트 발생 시 DockerHub에 push

4) Dockerhub에서 Kubernetes Cluster로 Docker Image를 pull받아서 리소스(deployment) Create

 

 

 

 

파이프라인 구성 작업은 다음과 같은 순서로 진행해야한다. 

0) Jenkins 플러그인 설치


Pipeline Utility Steps
Docker Pipeline

Docker 관련
Kubernetes 관련
GitLab
GitLabHook


 

 

1) Github에 Iac(Infa As Coding) 파일 올리기 (직접안올리고 제것을 사용해도 됩니다.)

 

해당파일은 다음 Github에서 참고할 수 있습니다. https://github.com/armyost/testPagePy.git

 

GitHub - armyost/testPagePy: This Python page is showing basic information of server's IP and so on. And It has Dockerfile and e

This Python page is showing basic information of server's IP and so on. And It has Dockerfile and etc. - GitHub - armyost/testPagePy: This Python page is showing basic information of server'...

github.com

 

 

2) Dockerhub에 레포지토리 생성하기

https://hub.docker.com/ 계정을 생성합니다.

 

Docker Hub

 

hub.docker.com

그리고 이미지 이름을 참고해서 레포지토리를 생성합니다. 저의 경우에는 armyost/hellopython 으로 되어 있습니다.

 

3) Jenkins와 DockerHub 연결을 위한 Credential 생성

 

Jenkins 관리 - Manager Credential 클릭

 

Add Credential을 클릭하여 신규 생성

DockerHub로그인 정보를 입력하고 ID에 registry_credential 이라고 입력합니다.(해당 ID는 pipeline.properties에서 참고하는 이름입니다.)

4) Jenkins Item 생성

 

새 item 생성을 누른다음 Pipeline을 클릭합니다.

 

Pipeline정보를 아래와 같이 입력합니다. 여기서 Github 레포지토리 URL을 입력합니다.

 

거의 Default 설정을 사용하겠지만 아래 ScriptPath응 바꿔주세요.

 

5) Kubernetes Cluster 등록

Jenkins에서 설정의 노드관리를 들어갑니다.

 

그리고 configure clouds를 클릭합니다.

Add a new cloud를 누른다음 Kubernetes를 선택하고 

 

 

Kubernetes Cloud details를 클릭합니다.

거의 Default로 쓰면 되는데 Disable https certificate check에 체크해주시고

Namespace는 ns-jenkins라고 별도로 주는게 관리하기 좋습니다. (만약 다른 namespace를 쓸거라면 제 github에 있는 pipleline.properties에 있는 파라미터도 바꿔서 빌드해주세요.)

 

이제 Jenkins에서 빌드를 돌려보면 정상적으로 수행될 것입니다.

 

CI/CD 파일은 다음과 같이 구성이 되어 있다.

1) Jenkinsfile

여기서 docker login 부분에서 정보를 본인것으로 수정해야 한다.

def label = "hellopython-${UUID.randomUUID().toString()}"


podTemplate(
	label: label, 
	containers: [
		containerTemplate(name: "docker", image: "docker:latest", ttyEnabled: true, command: "cat"),
		containerTemplate(name: "kubectl", image: "lachlanevenson/k8s-kubectl", command: "cat", ttyEnabled: true)
	],
	volumes: [
		hostPathVolume(hostPath: "/var/run/docker.sock", mountPath: "/var/run/docker.sock")
	]
) 
{
	node(label) {
		stage("Get Source") {
			checkout scm
        } 

		def props = readProperties  file:"deployment/pipeline.properties"
		def tag = props["version"]
		def dockerRegistry = props["dockerRegistry"]
		def credential_registry=props["credential_registry"]
		def image = props["image"]
		def deployment = props["deployment"]
		def service = props["service"]
		def ingress = props["ingress"]
		def selector_key = props["selector_key"]
		def selector_val = props["selector_val"]
		def namespace = props["namespace"]

		try {
			stage("Build Microservice image") {
				container("docker") {
					docker.withRegistry("${dockerRegistry}", "${credential_registry}") {
						sh "docker build -f ./deployment/Dockerfile -t ${image}:${tag} ."
						sh "docker login -u 'armyost' -p '******' docker.io"
						sh "docker push ${image}:${tag}"
						sh "docker tag ${image}:${tag} ${image}:latest"
						sh "docker push ${image}:latest"
					}
				}
			}
			stage( "Clean Up Existing Deployments" ) {
				container("kubectl") {
					sh "kubectl delete deployments -n ${namespace} --selector=${selector_key}=${selector_val}"
				}
			}

			stage( "Deploy to Cluster" ) {
				container("kubectl") {
					sh "kubectl apply -n ${namespace} -f ${deployment}"
					sh "sleep 5"
					sh "kubectl apply -n ${namespace} -f ${service}"
					sh "kubectl apply -n ${namespace} -f ${ingress}"
				}
			}

		} catch(e) {
			currentBuild.result = "FAILED"
		}
	}
}

 

2) Dockerfile

여기서 본인의 어플리케이션에 맞추어서 수정해야 한다. 필자는 python을 사용해서 pip install등을 사용한 것이다.

FROM python:3.8

LABEL maintainer="armyost@naver.com"

COPY . /app/server

WORKDIR /app/server

EXPOSE 80

RUN pip3 install -r ./deployment/requirements.txt

ENTRYPOINT ["python", "run.py"]