티스토리 뷰
Jenkins with Kubernetes방식 이해
아래는 Jenkins with kubernetes방식으로 CI/CD Pipeline이 구동되는 모습입니다.
이 pipeline의 단계(Stage)는 아래와 같이 4개 입니다. (번호가 붙어 있는게 Stage입니다.)
각 Stage에서 하는 일은 아래와 같습니다.
1) CI
- Get source: gitlab에서 소스와 CI/CD정의파일을 가져옴
- Build Microservice Image: Image를 build하고 docker hub로 푸시함
2) CD
- Cleanup Existing Deployments: 기존에 배포한 POD를 삭제함
- Deploy to Cluster: docker hub registry에서 Image를 가져와 worker nodes에 배포함
Get source단계 이후의 작업을 Jenkins slave POD안의 container들이 한다는 것을 주의깊게 봐주십시오.
Jenkins with kubernetes방식은 Jenkins (master) POD가 동적으로 Jenkins slave POD를 만들고, 그 안에 필요한 container를 생성합니다. 그리고 모든 작업이 끝나면 slave POD를 삭제합니다.
이렇게 하는 이유는 필요한 리소스(docker, kubectl 등)를 container로 독립적으로 관리하기 위함입니다.
그렇게 해야 리소스 간에 충돌이 없고, 작업량에 따라 자동으로 Slave Pod를 Scale Out/In할 수 있기 때문입니다.
실제로 아래 명령을 실행하고 Pipeline을 build하면 새로운 jenkins slave POD를 확인할 수 있습니다.
CI/CD 정의 파일 만들기
eclipse에서 개발한 hellonode프로젝트에 CI/CD정의 파일을 만들고, gitlab으로 push합니다.
CI/CD정의 파일은 아래와 같은 종류가 있습니다.
- Dockerfile: 배포Image build 정의 파일
- deploy.yaml : POD배포 정의 파일
- svc.yaml: Service 정의 파일
- ing.yaml: Ingress 정의 파일
- Jenkinsfile : Pipeline 정의 파일
- pipeline.properties: Jenkinsfile에서 참조하는 환경변수 정의 파일
먼저, deployment라는 폴더를 만듭니다.
1) Dockerfile
- git에는 .gitignore에 정의한대로 node_modules(필요 라이브러리)가 없습니다. 따라서 image 생성 시 npm install명령으로 설치를 합니다. npm install 전에 package.json파일이 먼저 복사되야 합니다. 그 안에 라이브러리가 정의되어 있기 때문입니다.
- container 외부에 8081포트를 노출시켰습니다. 나중에 deployment 정의 파일에도 동일 port로 정의해야 합니다.
FROM node:carbon
WORKDIR /home/hellonode/
COPY package.json .
RUN [ "npm", "install" ]
COPY . .
EXPOSE 8081
CMD [ "npm", "start" ]
2) deployment 정의 파일: deploy.yaml
Image의 이름에서 'happykube'는 본인의 hub docker의 userid 또는 Organization으로 바꾸셔야 합니다.
apiVersion: apps/v1
kind: Deployment
metadata:
name: hellonode
labels:
app: hellonode
spec:
selector:
matchLabels:
app: hellonode
replicas: 2
template:
metadata:
name: hellonode
labels:
app: hellonode
spec:
containers:
- name: hellonode
image: happykube/hellonode
imagePullPolicy: Always
env:
- name: PORT
value: "8081"
ports:
- name: port1
containerPort: 8081
resources:
requests:
cpu: 500m
memory: 1024Mi
limits:
cpu: 1000m
memory: 2048Mi
3) Service 정의파일: svc.yaml
apiVersion: v1
kind: Service
metadata:
name: hellonode
spec:
type: NodePort
selector:
app: hellonode
ports:
- name: hellonode
port: 8090
targetPort: 8081
4) Ingress정의파일: ing.yaml
host명은 본인의 k8s maste나 worker node의 IP로 변경해야 합니다.
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: hellonode
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /$1
nginx.ingress.kubernetes.io/ssl-redirect: "false"
spec:
rules:
- host: hellonode.169.56.84.35.nip.io
http:
paths:
- path: /(.*)
pathType: Prefix
backend:
service:
name: hellonode
port:
number: 8090
5) Pipeline 정의 파일: Jenkjnsfile
Jenkinsfile은 TAB으로 들여쓰기를 합니다.
TIP) Jenkinsfile은 yaml과 다르게 space로 들여쓰기를 할 필요가 없습니다. java, js와 같은 언어와 같이 space와 tab을 섞어 써도 됩니다.
def label = "hellonode-${UUID.randomUUID().toString()}"
podTemplate(
label: label,
containers: [
//container image는 docker search 명령 이용
containerTemplate(name: "docker", image: "docker:latest", ttyEnabled: true, command: "cat"),
containerTemplate(name: "kubectl", image: "lachlanevenson/k8s-kubectl", command: "cat", ttyEnabled: true)
],
//volume mount
volumes: [
hostPathVolume(hostPath: "/var/run/docker.sock", mountPath: "/var/run/docker.sock")
]
)
{
node(label) {
stage("Get Source") {
//git url:"https://github.com/happykube/hellonode.git", branch: "main", credentialsId: "git_credential"
git branch: 'main', url: 'https://github.com/happykube/hellonode.git'
}
//-- 환경변수 파일 읽어서 변수값 셋팅
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 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"
}
}
}
TIP)
containerTemplate에서 정의한 image이름은 아래와 같이 docker search로 찾을 수 있습니다.
OFFICIAL image를 사용하는 것이 좋고, 없으면 가장 인기가 많은 image를 사용하시면 됩니다.
6) Pipeline 환경설정 파일: pipeline.properties
- image, version은 deploy.yaml에 지정한 container imge와 동일해야 합니다.
image변수의 'happykube'는 docker hub registry의 본인 userid나 Organization으로 바꿔야 합니다.
version=0.1.1
namespace=hklee
dockerRegistry=https://index.docker.io/v1/
credential_registry=registry_credential
image=happykube/hellonode
deployment=deployment/deploy.yaml
service=deployment/svc.yaml
ingress=deployment/ing.yaml
selector_key=app
selector_val=hellonode
docker image registry에 대한 인증 credential 'registry_credential'을 만듭니다.
Pipeline 수행
1) git에 Push하기
git에 먼저 Push합니다.
2) Jenkins 에서 Pipeline Item 만들기
git repository주소, branch, Jenkinsfile의 경로를 정확히 입력하십시오.
3) Pipeline 실행하기
주요 진행상황은 아래와 같습니다.
- jenkins slave POD 생성
- gitlab에서 소스와 CI/CD 정의 파일들 가져오기
- build docker image
- 기존 POD 삭제
- POD, Service, Ingress 배포
- Pipeline 수행 종료
아래와 같이 정상적으로 모든 단계가 완료된 것을 확인할 수 있습니다.
앱 실행 확인
이제 실제로 앱이 정상적으로 배포되었는지 확인합니다.
1) POD, Service, Ingress 확인
$ kubectl get all
$ kubectl get ing
2) 웹브라우저로 접근
위와 같이 페이지가 정상적으로 나오면 성공입니다.
'Agile&DevOps > 실습 with Jenkins' 카테고리의 다른 글
Jenkins 실습 06: git연동 (0) | 2019.09.12 |
---|---|
Jenkins 실습 05: 배포Image 보안 검사 추가 (0) | 2019.09.12 |
Jenkins 실습 04: 소스 정적 검사 추가 (0) | 2019.09.12 |
Jenkins 실습 02: 사전준비 (0) | 2019.09.12 |
Jenkins 실습 01: 실습툴 및 순서 (0) | 2019.09.12 |
- Total
- Today
- Yesterday
- Event Sourcing
- SAGA
- 애자일
- 디토소비
- 호모프롬프트
- API Composition
- 마이크로서비스
- agile
- micro service
- 요즘남편 없던아빠
- 스핀프로젝트
- 마이크로서비스 패턴
- AXON
- 리퀴드폴리탄
- 도파밍
- 버라이어티가격
- CQRS
- spotify
- 육각형인간
- 분초사회
- 돌봄경제
- 스포티파이
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |