전편에 이어지는 내용으로, 이번에는 예제 프로젝트인 hugo-app 을 대상으로 개발~배포~실행까지 Pipeline을 구성하여 CI/CD 과정을 구현해 보자
Jenkins-leader 서비스 기동
- 새로운 프로젝트를 시작할 때, 전용의 Jenkins 빌더 셋을 만드는 과정에 해당
- 기존에 제작/테스트 했던 jenkins 서비스 환경을 tear-down 하고 Custom Jenkins 빌더로 새로 시작
[root@kubemaster 00-jenkins-custom-image]# kubectl delete -f 02-jenkins-dep-svc.yaml -n ns-jenkins
[root@kubemaster 00-jenkins-custom-image]# kubectl delete -f 01-jenkins-leader-pvc.yaml -n ns-jenkins
[root@kubemaster 00-jenkins-custom-image]# kubectl delete -f 00-jenkins-sa-clusteradmin-rbac.yaml
- 새로운 시작
[root@kubemaster ~]# mkdir jenkins-custom-k8s-cicd/01-jenkins-custom-deploy
[root@kubemaster ~]# cd jenkins-custom-k8s-cicd/01-jenkins-custom-deploy
[root@kubemaster 01-jenkins-custom-deploy]# cp ../00-jenkins-custom-image/0*.yaml .
[root@kubemaster 01-jenkins-custom-deploy]# export JENKINS_LEADER_IMAGE="drlee001/jenkins-leader:2.60.3-ns-version"
[root@kubemaster 01-jenkins-custom-deploy]# sed -i -e "s|image: .*|image: ${JENKINS_LEADER_IMAGE}|g" 02-jenkins-dep-svc.yaml
[root@kubemaster 01-jenkins-custom-deploy]# kubectl create -f 00-jenkins-sa-clusteradmin-rbac.yaml
[root@kubemaster 01-jenkins-custom-deploy]# kubectl create -f 01-jenkins-leader-pvc.yaml -n ns-jenkins
[root@kubemaster 01-jenkins-custom-deploy]# kubectl create -f 02-jenkins-dep-svc.yaml -n ns-jenkins
* Docker Hub 에 Push된 Custom Jenkins 빌더 이미지 Deploy
GitHub 프로젝트 연동을 위한 Jenkins 설정
앞선 1/2 의 내용대로 jenkins-leader 이미지를 생성하였다면 admin / admin 으로 Jenkins console 에서 로그인할 수 있을 것이다. Manage Jenkins > Configure System 선택
GitHub : GitHub Server > Add GitHub Server - GitHub Server 클릭
아래로 펼쳐진 항목들 중 두 번 째 Advanced 버튼 클릭
Additional Actions: Manage additional GitHub actions - Convert login and password to token 클릭
아래로 펼쳐지는 항목들 중 From login and password 선택 > 본인의 GitHub 로그인 계정 입력 > Create token credentials 클릭 > Created ... 성공 메시지가 나오면 하단 Save 클릭
* 주의: Create token credential 단계에서 "GH token 생성 오류" 발생시, 이미 plugin 을 위한 토큰이 생성된 경우이므로, github account > Settings > Developer settings > Personal access tokens 의 "Jenkins Github Plugin token" 을 삭제해 주어야 한다
메인 메뉴 Manage Jenkins > Configure System > GitHub: GitHub Server - Credentials > None 클릭 > GitHub (https://api...) 항목 클릭 > 아래 두 번 째 Advanced 버튼 클릭
아래 펼쳐지는 항목들 중 Shared secret: none 클릭 > GitHub (https://api...) 항목 클릭 > 하단 Save 버튼 클릭
대상 프로젝트 Pull(Clone), Build & Deploy
- 아래 예제로 제공되는 간단한 Static Web 프로젝트를 대상으로 CI/CD 과정을 수행해 보자(이 과정을 응용하면 일반적인 다른 프로젝트들도 역시 연동이 가능하게 될 것이다). 실제 테스트를 위해 GitHub의 아래 프로젝트로 이동하여 본인의 GitHub 계정으로 fork 하고 GITHUB_ACCOUNT 변수에 본인의 Account 를 할당해서 사용할 것을 추천한다.
[참고] 여기까지 수행하였다면, 본 CI/CD 시리즈의 전체 디렉토리 구조는 다음과 같이 나타난다
[root@kubemaster jenkins-custom-k8s-cicd]# ls -l
total 4
drwxr-xr-x. 2 root root 115 4월 9 00:32 00-jenkins-custom-image
drwxr-xr-x. 2 root root 115 4월 9 00:33 01-jenkins-custom-deploy
drwxr-xr-x. 3 root root 39 4월 9 12:17 docker
-rw-r--r--. 1 root root 376 10월 24 17:35 README.md
drwxr-xr-x. 4 root root 148 4월 9 13:52 test-webapp
- Clone 받은 프로젝트(또는 본인의 연동 대상 프로젝트)로 이동하고 파일 목록을 확인해 보자. 실제 상황에서 빌드 대상이 되는 파일들은 applications 내의 하위 폴더로 적절히 위치시키면 된다.
- 실제 Build 대상이 되는 프로그램의 리소스들은 다음과 같다. 실제로도 유사한 형태로 구성하면 된다.
apiVersion: v1
kind: Service
metadata:
name: test-webapp-1
labels:
app: test-webapp
spec:
ports:
- port: 80
targetPort: 80
selector:
app: test-webapp
tier: test
type: NodePort
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: test-webapp-1
labels:
app: test-webapp
spec:
strategy:
type: Recreate
template:
metadata:
labels:
app: test-webapp
tier: test
spec:
containers:
- image: YourDockerHubAccount/test-webapp-1:latest
name: test-webapp-1
ports:
- containerPort: 80
name: test-webapp-1
대상 프로그램의 Containerizing
- 다음 스크립트 내용을 수행하여 대상 프로그램을 Docker Image 로 만들고 Docker Hub 에 Push
- 다음 스크립트를 수행하여 Kubernetes 내에 대상 프로그램의 Service/Pod 를 기동
- 웹브라우저를 사용하여 대상 프로그램(Webapp)에 접속, 확인해 보자
'Docker Hub로의 Push' 와 'Kubectl 실행'을 위한 Token 생성
- Jenkins-leader 에서 등록한 작업(item)은 jenkins-slave Pod가 동적으로 생성되면서 그 내부에서 처리되고, 완료 후 해당 Pod는 자동으로 종료된다.
- Jenkinsfile의 container 영역에서 정의한 작업이 수행되는 과정에서, Docker Hub 쪽으로 컨테이너 이미지 Push, Kubernetes Cluster의 deploy된 Pod/container 이미지를 교체할 때 각각, 인증을 위한 token 이 Kubernetes 내에 secret 형태로 존재해야 한다.
- DOCKER_ACCOUNT 변수에 본인의 Docker Hub 계정을 사용한다.
# export DOCKER_ACCOUNT="drlee001"
# docker login -u $DOCKER_ACCOUNT
password:
Login Succeeded
# kubectl create secret -n ns-jenkins generic docker-config --from-file=$HOME/.docker/config.json
secret "docker-config" created
# kubectl create secret -n ns-jenkins generic kube-config --from-file=$HOME/.kube/config
secret "kube-config" created
# kubectl get secret -n ns-jenkins
NAME TYPE DATA AGE
default-token-chxlp kubernetes.io/service-account-token 3 3d
docker-config Opaque 1 2m
jenkins-token-dhx8s kubernetes.io/service-account-token 3 3d
kube-config Opaque 1 2m
- GitHub으로 연동되는 빌드 대상 프로젝트 repository 의 Jenkinsfile 내용은 다음과 같다. 여기서 정의한 Pod/container 구성에 맞춰진 jenkins-slave Pod가 동적으로 수행된다.
- 아래 구성대로 기동되는 Pod는 내부에 총 3개의컨테이너를 포함한다(docker, kubectl 그리고 jnlp 컨테이너).
#!groovy
podTemplate(label: 'test-webapp-1', containers: [
containerTemplate(name: 'kubectl', image: 'smesch/kubectl', ttyEnabled: true, command: 'cat',
volumes: [secretVolume(secretName: 'kube-config', namespace: 'ns-jenkins', mountPath: '/root/.kube')]),
containerTemplate(name: 'docker', image: 'docker', ttyEnabled: true, command: 'cat',
envVars: [containerEnvVar(key: 'DOCKER_CONFIG', value: '/tmp/'),])],
volumes: [secretVolume(secretName: 'docker-config', namespace: 'ns-jenkins', mountPath: '/tmp'),
hostPathVolume(hostPath: '/var/run/docker.sock', mountPath: '/var/run/docker.sock')
]) {
node('test-webapp-1') {
def DOCKER_HUB_ACCOUNT = 'YourDockerHubAccount'
def DOCKER_IMAGE_NAME = 'test-webapp-1'
def K8S_DEPLOYMENT_NAME = 'test-webapp-1'
def POD_NAMESPACE = 'default'
stage('Clone test-webapp-1 App Repository') {
checkout scm
container('docker') {
stage('Docker Build & Push Current & Latest Versions') {
sh ("docker build -t ${DOCKER_HUB_ACCOUNT}/${DOCKER_IMAGE_NAME}:${env.BUILD_NUMBER} -f applications/test-webapp-1/Dockerfile applications/test-webapp-1/")
sh ("docker push ${DOCKER_HUB_ACCOUNT}/${DOCKER_IMAGE_NAME}:${env.BUILD_NUMBER}")
sh ("docker tag ${DOCKER_HUB_ACCOUNT}/${DOCKER_IMAGE_NAME}:${env.BUILD_NUMBER} ${DOCKER_HUB_ACCOUNT}/${DOCKER_IMAGE_NAME}:latest")
sh ("docker push ${DOCKER_HUB_ACCOUNT}/${DOCKER_IMAGE_NAME}:latest")
}
}
container('kubectl') {
stage('Deploy New Build To Kubernetes') {
sh ("kubectl set image -n ${POD_NAMESPACE} deployment/${K8S_DEPLOYMENT_NAME} ${K8S_DEPLOYMENT_NAME}=${DOCKER_HUB_ACCOUNT}/${DOCKER_IMAGE_NAME}:${env.BUILD_NUMBER}")
}
}
}
}
}
Jenkins pipeline 작업을 통한 자동 빌드 & 배포 실행
- 대상 프로그램의 리소스 중 일부를 수정해서 Jenkins pipeline 작업을 수행해 보자
[root@kubemaster test-webapp]# vi applications/test-webapp-1/index.html
<html>
<head>
</head>
<body>
<p>
<h2 style="font-family:sans-serif">Hello from K8s-Jenkins pipeline! You've successfully built and run the Test-Webapp-1 app.</h2>
<br>Version: v04
</p>
<p style="font-family:sans-serif">
This app is a simple static web page running on <a href="https://hub.docker.com/_/nginx/">nginx base image</a>.
</p>
<p>
<img src="DockerFileEx.jpg">
</p>
</body>
</html>
[root@kubemaster test-webapp]# git add .
[root@kubemaster test-webapp]# git commit -a -m "Update - index.html"
[master fce13d5] Update - index.html
2 files changed, 5 insertions(+), 4 deletions(-)
[root@kubemaster test-webapp]# git push origin master
Username for 'https://github.com': YourGitHubAccount
Password for 'https://YourGitHubAccount@github.com': YourGitHubPassword
Counting objects: 11, done.
Delta compression using up to 2 threads.
Compressing objects: 100% (5/5), done.
Writing objects: 100% (6/6), 609 bytes | 0 bytes/s, done.
Total 6 (delta 3), reused 0 (delta 0)
remote: Resolving deltas: 100% (3/3), completed with 3 local objects.
To https://github.com/YourGitHubAccount/test-webapp.git
24c9645..fce13d5 master -> master
* 프로그램 소스 일부를 수정하고 Commit & Push 한다
Jenkins-leader UI 화면에서 새로운 Item 을 등록한다(이후의 과정은 포스팅 시리즈 1/2(http://bryan.wiki/295 - 빌드테스트 섹션)과 동일하므로 별도 설명 생략)
Console Output 의 마지막에 Finished: SUCCESS 메시지까지 나타나면 성공적으로 빌드 & 배포가 완료된 것이다. 이제 위의 Webapp 접속 화면을 확인하면 수정/변경된 내용을 확인할 수 있을 것이다.
- Barracuda -
[관련 글]
2018/03/20 - [Technical/Cloud, 가상화, PaaS] - [Kubernetes - CI/CD] Customized Jenkins 제작과 활용 - 1/2
'Technical > Cloud, Virtualization, Containers' 카테고리의 다른 글
[Kubernetes StatefulSet] Mongodb Replicaset by StatefulSet(2/5) (2) | 2018.09.16 |
---|---|
[Kubernetes StatefulSet] 개요 & Nginx Web Cluster(1/5) (0) | 2018.05.24 |
[Kubernetes - CI/CD] Customized Jenkins 제작과 활용 - 1/2 (0) | 2018.03.20 |
[Kubernetes Cluster 관리] 클러스터 컨텍스트 변경과 kubectl을 통한 multi-cluster 접속 (0) | 2017.12.20 |
[Kubernetes RBAC] API 연결로 확인해 보는 RBAC 설정 방법 (0) | 2017.12.01 |