Published on

Deploy Jenkins trên Kubernetes

Trong bài viết này, mình sẽ hướng dẫn cách deploy Jenkins trên Kubernetes. Với cách deploy này mỗi agent thông thường sẽ được khởi tạo là 1 pod, khi job build kết thúc thì pod sẽ tự động bị thu hồi.

storage.yaml

Chúng ta cần tạo Persistent Volume để cho Jenkins có thể lưu trữ lại thông tin như job build, các config tranh bị mất đi nếu Pod bị restart.

Trong ví dụ mình dùng NFS Persistent Volume, nếu bạn dùng cấu hình khách thì phải tự cập nhật lại file storage.yaml

kind: PersistentVolume
apiVersion: v1
metadata:
  name: jenkins-pv
  labels:
    app: jenkins
  namespace: jenkins
spec:
  capacity:
    storage: 5Gi
  accessModes:
    - ReadWriteOnce
  persistentVolumeReclaimPolicy: Retain
  nfs:
    server: 192.168.1.10
    path: '/mnt/kubernetes/data/jenkins'
---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: jenkins-pvc
  labels:
    app: jenkins
  namespace: jenkins
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 5Gi
  volumeName: jenkins-pv

serviceAccount.yaml

Chúng ta cần Service account để cho jenkins có thể sử dụng các resources của K8s

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-admin
  namespace: jenkins
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins-admin
  labels:
    'app.kubernetes.io/name': 'jenkins'
rules:
  - apiGroups: ['']
    resources: ['pods']
    verbs: ['create', 'delete', 'get', 'list', 'patch', 'update', 'watch']
  - apiGroups: ['']
    resources: ['pods/exec']
    verbs: ['create', 'delete', 'get', 'list', 'patch', 'update', 'watch']
  - apiGroups: ['']
    resources: ['pods/log']
    verbs: ['get', 'list', 'watch']
  - apiGroups: ['']
    resources: ['secrets']
    verbs: ['get']
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins-admin
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins-admin
subjects:
  - kind: ServiceAccount
    name: jenkins-admin
    namespace: jenkins

deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: jenkins
spec:
  selector:
    matchLabels:
      app: jenkins
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      securityContext:
        fsGroup: 0
        runAsUser: 0
      serviceAccountName: jenkins-admin
      containers:
        - name: jenkins
          image: jenkins/jenkins:alpine
          resources:
            {}
            # limits:
            #   memory: "2Gi"
            #   cpu: "1000m"
            # requests:
            #   memory: "500Mi"
            #   cpu: "500m"
          ports:
            - name: httpport
              containerPort: 8080
            - name: jnlpport
              containerPort: 50000
          livenessProbe:
            httpGet:
              path: '/login'
              port: 8080
            initialDelaySeconds: 90
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 5
          readinessProbe:
            httpGet:
              path: '/login'
              port: 8080
            initialDelaySeconds: 60
            periodSeconds: 10
            timeoutSeconds: 5
            failureThreshold: 3
          volumeMounts:
            - name: jenkins-data
              mountPath: /var/jenkins_home
      volumes:
        - name: jenkins-data
          persistentVolumeClaim:
            claimName: jenkins-pvc

service.yaml

apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: jenkins
  annotations:
    prometheus.io/scrape: 'true'
    prometheus.io/path: /
    prometheus.io/port: '8080'
spec:
  selector:
    app: jenkins
  type: ClusterIP
  ports:
    - name: http
      port: 80
      targetPort: 8080
      protocol: TCP
    - name: jnlp
      port: 50000
      targetPort: 50000
      protocol: TCP

ingress.yaml

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins
  namespace: jenkins
  labels:
    app: jenkins
  annotations:
    cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
  ingressClassName: nginx
  rules:
    - host: jenkins.your-domain
      http:
        paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: jenkins
                port:
                  number: 80
  tls:
    - hosts:
        - jenkins.your-domain
      secretName: ssl-jenkins.your-domain

Sau khi hoàn tất cài đặt, bạn có thể truy cập vào: https://jenkins.your-domain để tiến hành các bước tiếp theo

Video hướng dẫn