Deploy Jenkins On K8S

Image from Jenkins.io

พอดีได้อ่านบทความของพี่ Phayao Boonon ในหัวข้อ สร้าง CI/CD ด้วย Jenkins บน Kubernetes แบบง่ายๆ เลยแอบอยากลองเอา Image ที่เคยทำเอาไว้ในบทความก่อนหน้า Jenkins with .net core มาลองทำดูบ้างครับ ว่าจะทำได้หรือเปล่า (แอบขี้เกียจ ดองบทความ Microservice แหะๆ )

โดยตัว K8S ที่ผมจะใช้งานจะเอามาจากบทความ K8S กึ่งสำเร็จรูป ที่เคยเขียนไปก่อนหน้านี้แล้วมาใช้งานกันครับ

และไฟล์ Image ของเราเข้ามาใช้งานบน K8S จะมี 3 วิธีด้วยกันคือ

  • ฝาก Image เอาไว้บน Docker Hub หรือ Store
  • จาก Local Registry จะเหมือนกับ Docker Hub ทุกอย่าง คือเรียกง่ายๆ ว่าเป็น Private Docker Hub ก็ได้ครับ
  • จาก Local ก็จากที่เรา Build Image กันนั่นละครับ ดึงมาใช้งานตรงๆ เลย

สำหรับวิธีที่ 1 และ 2 จะใช้งานเหมือนกัน เพียงแต่ จะมีการระบุ server ที่ต้องการดึงไฟล์ Image มาใช้งาน

ส่วนวิธีที่ 3 จะแตกต่างจาก ข้อ 1 แค่ต้องไปกำหนดให้ K8S ไม่ต้อง Pull Image ลงมาใหม่เท่านั้นครับ เดี๋ยวผมจะทำไฟล์ประกอบทั้ง 3 วิธีให้นะครับ แต่สุดท้ายแล้วในส่วนของการเขียนคำสั่ง deployment ส่วนใหญ่จะเหมือนกันครับ เรามาเตรียม image ของเราที่จะใช้งานในวิธีที่ 1 และ 2 กันก่อนเลยครับ

สำหรับวิธีแรก ก่อนอื่นเลยเราก็จะต้องมา push image ของเราขึ้นไปไว้บน hub กันก่อนด้วย คำสั่ง

$> docker push jenkins:dotnetcore-2.1
Push image to Docker hub

วิธีที่ 2 Local Registry เราจะใช้ add-on ของ microk8s ที่มีมาให้อยู่แล้ว โดยให้เราไป เปิดใช้งานกันก่อน ด้วยคำสั่ง

$> microk8s.enable registry

หลังจากนั้น เราก็จะมาเตรียม image เพื่อ push เข้า private registry กันครับ โดยที่เราสามารถทำได้ 2 วิธี คือ

  • ใช้ Image เดิมที่มีอยู่ โดยการ กำหนด Tag ใหม่ ซึ่งคำสั่งก็จะมีลักษณะ ดังนี้
$> docker tag {current tag} {registry url}:{port}/{target tag}
  • Build image ใหม่ โดยกำหนด registry ใน tag เลย
$> docker build -t {registry url}:{port}/tag
Docker build images

หลังจากนั้นเราก็จะ push image เข้า private registry ของเรา ด้วยคำสั่ง

$> docker push localhost:32000/jenkins

ขั้นตอนต่อไป เราก็จะมาเริ่มขั้นตอนต่อไป คือสร้าง namespace บน k8s เพื่อให้จัดการได้ง่าย โดยจะใช้คำสั่ง

$> kubectl create ns jenkins-space
Kubectl create jenkins-space
K8S Namespace on Ingress Dash board

เมื่อสร้าง namespace เสร็จแล้ว ก็จะมาสร้างไฟล์ jenkins-deployment.yml กัน ซึ่งคำสั่งในไฟล์ ผมจะทำเป็น 3 ไฟล์ แล้วแต่จะใช้วิธีจากที่กล่าวข้างต้นเอาไว้ ว่าจะใช้วิธีไหนกันนะครับ

Pull image from Docker hub
Pull image from private registry
Use local image

จะสังเกตุได้ว่า 2 ไฟล์ข้างบน จะแตกจากกันที่ image tag ซึ่งจะเป็นตัวระบุว่าเราจะใช้ image จากที่ไหน และในไฟล์ที่ 3 จะแตกต่างตรงที่ imagePullPolicy ซึ่งจะกำหนดให้ K8S ไม่ต้องทำการ ตรวจสอบ Image จาก DockerHub

ซึ่งตรงนี้ เราจะสามารถกำหนด param ได้ 3 ค่า คือ

  • Always ตรวจสอบจาก Docker Hub หรือ Registry ทุกครั้ง
  • IfNotPresent หากไม่พบ Image ใน Local ให้ โหลดจาก Docker Hub หรือ Registry
  • Never ไม่ต้องตรวจสอบ

สำหรับของผมจะใช้จาก Local image ครับ จากนั้น เราก็จะใช้คำสั่งนี้ เพื่อสั่งให้ K8S สร้าง Pod และ Deployment จากไฟล์ jenkins-deployment.yml ที่เราสร้างขึ้นมา

$> kubectl create -f jenkins-deployment.yml --namespace jenkins-space
Create Pods and Deployment

เราสามารถตรวจสอบรายละเอียดของ deployment และ Pod ขึ้นมา โดยใช้คำสั่ง

$> kubectl  describe deployments --namespace=jenkins-space
Jenkins Deployment & Pod Detail
Jenkins Deployment

ขั้นตอนสุดท้าย ก่อนจะไปทำการ Config ตัว Jenkins ได้ เราต้องมาสร้าง Service เพื่อ Forward port จากข้างนอกเพื่อเข้าใช้งาน Jenkins Container ที่อยู่ใน Deployment ของ K8S กันครับ โดยคำสั่งของไฟล์ jenkins-service.yml จะมีดังนี้

Jenkins service file

เมื่อสร้างไฟล์ jenkins-service.yml เสร็จแล้ว เราก็จะใช้คำสั่งนี้ เพื่อสร้าง service ใน K8S กันครับ

$> kubectl create -f jenkins-service.yml --namespace jenkins-space
Create Jenkins service
Jenkins Service

ขั้นตอนสุดท้าย ก็จะเป็นการ Config ตัว Jenkins ที่เราสร้างขึ้นมา โดยเราต้อง Copy ตัว Initial Password ที่อยู่ใน pod กันก่อนครับ จะใช้ Command line หรือจะเข้าไปดูใน log ของ Ingress Dashboard ก็ได้ครับ

สำหรับ Command Line จะใช้คำสั่งนี้ เพื่อแสดงรายชื่อ pods

$> kubectl get pods --namespace=jenkins-space
Jenkins Pod List

แล้วจะใช้คำสั่ง logs เพื่อ ดู Initial Password จาก logs ของ Pods

$> kubectl logs {deployment name} --namespace={namespace}
Jenkins Initial Password

สำหรับ Ingress Dashboard สามารถเข้าไปดูได้ตาม Path ในภาพครับ

Jenkins Pod detail on Ingress Board
Jenkins Pod Log

เมื่อได้ Initial Password มาแล้ว เราก็จะเข้า Jenkins ของเราผ่าน Port ที่เราระบุ NodePort เอาไว้ใน Service ซึ่งเรากำหนดเอาไว้ที่ 30000 อย่างเช่น

http://{K8S IP}:{Node Pod}

แล้วเราก็จะเข้าสู่หน้า Jenkins Config และใช้ Initial Password ที่เราได้มาจาก Log เพื่อ Config ขั้นตอนต่อไป

Jenkins Enter Initial Password
Plug-In install

เพิ่มเติมครับ หากใครไม่สามารถโหลด Plug-In ของ Jenkins ได้ เนื่องจาก Pod ไม่สามารถเชื่อมต่อ Internet ได ้ให้ใช้คำสั่งนี้ เพื่อ Allow การทำ Forward Port ครับ

$> sudo iptables -P FORWARD ACCEPT

หากใช้ UFW จะใช้คำสั่งนี้ครับ

$> sudo ufw default allow routed

สำหรับบทความนี้ก็ขอจบเพียงแค่นี้ครับ หากขาดตกบกพร่องใดๆ
ต้องขออภัยมา ณ ที่นี้ด้วยครับ ขอบคุณที่ติดตามครับ

References: MicroK8S, MicroK8S Github, How to setup Jenkins On Kubernetes, สร้าง CI/CD ด้วย Jenkins บน Kubernetes แบบง่ายๆ

Love podcasts or audiobooks? Learn on the go with our new app.