Saturday, January 18, 2025

Triển khai Jenkins trên Kubernetes Cluster sử dụng manifest

-

Jenkins và Kubernetes là hai công nghệ khác nhau và có mục đích sử dụng khác nhau.

Jenkins là một công cụ tự động hóa được sử dụng cho việc triển khai liên tục (continuous deployment) và tích hợp liên tục (continuous integration) trong quá trình phát triển phần mềm. Jenkins cung cấp khả năng xây dựng, kiểm tra và phân phối phần mềm một cách tự động trên nhiều máy chủ khác nhau, giúp tăng tốc độ phát triển và giảm thiểu sai sót.

Kubernetes là một nền tảng mã nguồn mở được sử dụng để quản lý và triển khai các ứng dụng trong môi trường đám mây. Kubernetes cung cấp một cách tiếp cận đơn giản và tự động hóa cho việc quản lý các ứng dụng trên nhiều máy chủ, giúp tối ưu hóa tài nguyên và tăng tính sẵn sàng của hệ thống.

Khi kết hợp Jenkins và Kubernetes, các nhà phát triển có thể sử dụng Jenkins để tự động hóa các bước kiểm tra, xây dựng và phân phối ứng dụng, và triển khai chúng trên Kubernetes để quản lý và phân phối một cách hiệu quả. Điều này giúp tăng tốc độ phát triển, đồng thời đảm bảo tính sẵn sàng và tin cậy của hệ thống.

Nào, chúng ta hãy bắt đầu triển khai Jenkins trên cụm Kubernetes Cluster.

Bước 1: Tạo một Namespace riêng cho Jenkins.

Đầu tiên hãy tạo một thư mục lưu các manifest của Jenkins.

mkdir -p /home/kustomize

Để triển khai Jenkins trên Kubernetes, nên tạo một Namespace riêng cho Jenkins. Việc này giúp cho việc quản lý Jenkins trở nên dễ dàng hơn, đồng thời giúp giữ cho các đối tượng của Jenkins được phân biệt với các đối tượng của các ứng dụng khác trong cùng một cluster.

Các bước để tạo Namespace cho Jenkins như sau:

  • Sử dụng lệnh kubectl create namespace <namespace-name> để tạo một Namespace mới cho Jenkins. Ví dụ: kubectl create namespace devops-tools
  • Sử dụng lệnh kubectl get namespaces để xác nhận rằng Namespace đã được tạo thành công.
  • Các đối tượng của Jenkins, chẳng hạn như Pod và Service, sẽ được triển khai trong Namespace vừa tạo.

Ví dụ, để triển khai một Deployment cho Jenkins trong Namespace jenkins, có thể sử dụng lệnh như sau:

kubectl create namespace devops-tools

Hoặc bạn cũng có thể tạo namespace bằng manifest cũng được.

cat > /home/kustomize/namespace.yaml << 'OEF'
apiVersion: v1
kind: Namespace
metadata:
  name: devops-tools
OEF

Sau khi tạo xong manifest thì bạn hãy triển khai manifest này để tạo namespace bằng lệnhkubectl apply -f namespace.yaml

kubectl apply -f namespace.yaml

Việc tạo Namespace cho Jenkins giúp tăng tính cô lập và quản lý của các đối tượng của Jenkins, đồng thời giúp cho việc triển khai và quản lý các công cụ DevOps khác trong cùng một cluster trở nên dễ dàng hơn.

Hãy xác nhận việc tạo namespace thành công bằng lệnh kubectl get ns devops-tools.

$ kubectl get ns devops-tools
NAME           STATUS   AGE
devops-tools   Active   16s

Bước 2: Tạo Service Account

Trong Kubernetes, một Service Account là một tài khoản được sử dụng bởi các Pod để tương tác với các API server của Kubernetes. Service Account được sử dụng để xác thực và ủy quyền các Pod và các tác vụ khác trong Kubernetes.

Để triển khai Jenkins trên Kubernetes, ta cần tạo một Service Account riêng cho Jenkins. Với Service Account này, các Pod của Jenkins sẽ được xác thực và ủy quyền để tương tác với các API server của Kubernetes.

Để tạo một Service Account cho Jenkins, có thể tạo một file YAML với nội dung như sau:

cat > /home/kustomize/serviceAccount.yaml << 'OEF'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: jenkins-admin
rules:
  - apiGroups: [""]
    resources: ["*"]
    verbs: ["*"]

---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins-admin
  namespace: devops-tools

---
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: devops-tools
OEF

Trong đoạn mã YAML trên, chúng ta đang định nghĩa một Service Account jenkins-admin cùng với các ClusterRole và ClusterRoleBinding liên quan để cấp quyền cho Service Account này.

  • Đầu tiên, chúng ta định nghĩa một ClusterRole có tên jenkins-admin. ClusterRole này có quyền truy cập tất cả các tài nguyên trong tất cả các API group của Kubernetes (apiGroups: [""]), với tất cả các loại tài nguyên (resources: ["*"]), và có quyền thực hiện tất cả các thao tác (verbs: ["*"]).
  • Tiếp theo, chúng ta định nghĩa một Service Account có tên là jenkins-admin thuộc Namespace devops-tools.
  • Cuối cùng, chúng ta định nghĩa một ClusterRoleBinding có tên là jenkins-admin để liên kết Service Account jenkins-admin với ClusterRole jenkins-admin. Điều này sẽ cấp quyền cho Service Account này để truy cập tất cả các tài nguyên trong tất cả các API group của Kubernetes.

Với các định nghĩa này, Service Account jenkins-admin sẽ có quyền tương tác với tất cả các tài nguyên trong Kubernetes, cho phép Jenkins có thể triển khai các đối tượng trên Kubernetes một cách linh hoạt và tiện lợi. Tuy nhiên, trong môi trường sản phẩm, ta nên đưa ra các cấu hình cụ thể hơn để hạn chế quyền truy cập của Jenkins chỉ vào các tài nguyên cần thiết.

Chúng ta hãy triển khai Service Account này bằng lệnh kubectl apply -f serviceAccount.yaml.

# kubectl apply -f serviceAccount.yaml
clusterrole.rbac.authorization.k8s.io/jenkins-admin created
serviceaccount/jenkins-admin created
clusterrolebinding.rbac.authorization.k8s.io/jenkins-admin created

Bạn có thể sử dụng lệnh kubectl get serviceaccount jenkins-admin -n devops-tools để kiểm tra xem Service Account đã được tạo thành công hay chưa:

$ kubectl get serviceaccount jenkins-admin -n devops-tools
NAME            SECRETS   AGE
jenkins-admin   1         40s

Nếu Service Account đã được tạo thành công, kết quả trả về sẽ hiển thị thông tin của Service Account như tên và namespace. Nếu không tìm thấy Service Account, bạn cần kiểm tra lại các bước trước đó đã được thực hiện đúng cách hay chưa.

Bước 3:Tạo Persistent Volume và Persistent Volume Claim

Tuỳ chọn 1: Sử dụng mout trực tiếp trên các Node.

Trong tuỳ chọn 1 của bước này, chúng ta đang tạo một Persistent Volume (PV) thông qua đoạn code YAML sau:

cat > /home/kustomize/volume.yaml << 'OEF'
kind: StorageClass
apiVersion: storage.k8s.io/v1
metadata:
  name: local-storage
provisioner: kubernetes.io/no-provisioner
volumeBindingMode: WaitForFirstConsumer

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins-pv-volume
  labels:
    type: local
spec:
  storageClassName: local-storage
  claimRef:
    name: jenkins-pv-claim
    namespace: devops-tools
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  local:
    path: /mnt
  nodeAffinity:
    required:
      nodeSelectorTerms:
      - matchExpressions:
        - key: kubernetes.io/hostname
          operator: In
          values:
          - k8s-worker1

---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: jenkins-pv-claim
  namespace: devops-tools
spec:
  storageClassName: local-storage
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 3Gi
OEF

Đoạn code này sẽ tạo ra một StorageClass và các PersistentVolume (PV) và PersistentVolumeClaim (PVC) để lưu trữ dữ liệu của Jenkins.

Trước tiên, đoạn code định nghĩa một StorageClass với tên là local-storage, không có provisioner (do không sử dụng dynamic provisioning), và volumeBindingMode là WaitForFirstConsumer.

Sau đó, nó định nghĩa một PersistentVolume với tên là jenkins-pv-volume, sử dụng StorageClass local-storage, và có capacity là 10Gi. PV này được mount tới thư mục /mnt trên một worker node có hostname là k8s-worker1.

Tiếp theo, nó định nghĩa một PersistentVolumeClaim với tên jenkins-pv-claim, và yêu cầu 3Gi dung lượng lưu trữ. PVC này sử dụng StorageClass local-storage và access mode là ReadWriteOnce.

Lưu ý rằng PVC jenkins-pv-claim có một field claimRef trỏ đến PV jenkins-pv-volume, để PV có thể được bind với PVC.

Lưu ý quan trọng: Thay thế k8s-worker1 bằng bất kỳ tên máy chủ nút worker nào trong cụm của bạn.

Dùng lệnh kubectl get nodes | grep <tên worker> để lấy tên worker trên cụm Kubernetes Cluster của bạn.

$ kubectl get nodes | grep worker
k8s-worker1   Ready    <none>                 6d20h   v1.23.8
k8s-worker2   Ready    <none>                 6d20h   v1.23.8
k8s-worker3   Ready    <none>                 6d20h   v1.23.8

Sau khi định nghĩa xong manifest bạn hãy triển khai nó bằng lệnh kubectl create -f volume.yaml.

$ kubectl create -f volume.yaml
storageclass.storage.k8s.io/local-storage created
persistentvolume/jenkins-pv-volume created
persistentvolumeclaim/jenkins-pv-claim created

Bạn có thể sử dụng các lệnh kubectl sau để xác minh rằng các PersistentVolume và PersistentVolumeClaim đã được tạo thành công:

  • Xem danh sách các PersistentVolume:
$ kubectl get pv
NAME                CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                           STORAGECLASS    REASON   AGE
jenkins-pv-volume   10Gi       RWO            Retain           Bound    devops-tools/jenkins-pv-claim   local-storage            4m31s

Xem danh sách các PersistentVolumeClaim trong namespace devops-tools:

$ kubectl get pvc -n devops-tools
NAME               STATUS   VOLUME              CAPACITY   ACCESS MODES   STORAGECLASS    AGE
jenkins-pv-claim   Bound    jenkins-pv-volume   10Gi       RWO            local-storage   5m52s

Nếu cả hai lệnh trên đều trả về kết quả không có lỗi, thì các PV và PVC đã được tạo thành công và sẵn sàng để được sử dụng cho Jenkins.

Tuỳ chọn 2: Bạn có storage ngoài, ví dụ mình sử dụng Longhorn

Truy cập vào giao diện Longhorn của bạn, bấm vào Create Volume.

Mình đặt tên cho Persistent Volume này là jenkins-pv-volume, dung lượng là 20G, số bản Replicas là 2 và Access Mode mình chọn ReadWriteMany.

Bạn sẽ có Persistent Volume mới sau khi tạo xong như dưới. Bấm vào (1) và chọn Create PV/PVC (2) để tạo Persistent Volume Claim.

Bạn giữ nguyên tên Persistent Volume và đặt tên cho Persistent Volume Claim tại PVC Name, hãy điền namespace và bấm Ok.

Tai PV/PVC thông báo Bound tức là bạn đã tạo Persistent Volume Claim thành công.

Lúc này trong CLI bạn cũng có thể thấy thông tin Persistent Volume và Persistent Volume Claim đã được tạo và đang ở trạng thái Bound.

$ kubectl get pv,pvc -n devops-tools
NAME                                 CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                           STORAGECLASS      REASON   AGE
persistentvolume/jenkins-pv-volume   20Gi       RWX            Retain           Bound    devops-tools/jenkins-pv-claim   longhorn-static            80s

NAME                                     STATUS   VOLUME              CAPACITY   ACCESS MODES   STORAGECLASS      AGE
persistentvolumeclaim/jenkins-pv-claim   Bound    jenkins-pv-volume   20Gi       RWX            longhorn-static   79s

Như vậy các PV và PVC đã được tạo thành công và sẵn sàng để được sử dụng cho Jenkins.

Bước 3: Triển khai Jenkins.

Hãy tạo file deployment.yaml với nội dung sau.

cat > /home/kustomize/deployment.yaml << 'OEF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: devops-tools
spec:
  replicas: 1
  selector:
    matchLabels:
      app: jenkins-server
  template:
    metadata:
      labels:
        app: jenkins-server
    spec:
      securityContext:
            fsGroup: 1000 
            runAsUser: 1000
      serviceAccountName: jenkins-admin
      containers:
        - name: jenkins
          image: jenkins/jenkins:lts
          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-pv-claim
OEF


Đây là file YAML để tạo một deployment trong Kubernetes, với các thông tin sau:

  • apiVersionkind: Chỉ định loại tài nguyên được sử dụng trong file YAML, ở đây là Deployment.
  • metadata: Chứa các thông tin meta của deployment như namenamespace.
  • spec: Bao gồm các thông tin cấu hình của deployment.
    • replicas: Số lượng bản sao (pod) được triển khai.
    • selector: Các labels để phân loại các pod thuộc deployment.
    • template: Mẫu pod sẽ được triển khai trong deployment, bao gồm:
      • securityContext: Cấu hình bảo mật cho container.
      • serviceAccountName: Sử dụng service account có tên là jenkins-admin cho container.
      • containers: Danh sách các container trong pod.
        • name: Tên container.
        • image: Image sẽ được sử dụng cho container.
        • resources: Cấu hình tài nguyên sử dụng bởi container.
        • ports: Danh sách các port mà container sẽ lắng nghe.
        • livenessProbe: Cấu hình kiểm tra tính khả dụng của container thông qua HTTP GET request đến đường dẫn /login trên port 8080.
        • readinessProbe: Cấu hình kiểm tra tính sẵn sàng của container thông qua HTTP GET request đến đường dẫn /login trên port 8080.
        • volumeMounts: Mount một volume tên là jenkins-data vào container tại đường dẫn /var/jenkins_home.
      • volumes: Danh sách các volume được sử dụng bởi pod, bao gồm:
        • name: Tên của volume.
        • persistentVolumeClaim: Sử dụng một PersistentVolumeClaim (PVC) có tên là jenkins-pv-claim cho volume.
$ kubectl get deployments -n devops-tools
NAME      READY   UP-TO-DATE   AVAILABLE   AGE
jenkins   1/1     1            1           110s

Hoặc sử dụng lệnh liệt kê danh sách các pods của Jenkins.

$ kubectl get po -n devops-tools
NAME                      READY   STATUS    RESTARTS   AGE
jenkins-b96f7764f-ws5sz   1/1     Running   0          2m4s

Bước 4: Truy cập Jenkins sử dụng Kubernetes Service

Sau khi chúng ta đã tạo ra deployment của Jenkins, để truy cập nó từ bên ngoài, chúng ta cần tạo ra một Kubernetes Service và liên kết nó với deployment. Service sẽ cho phép các yêu cầu từ bên ngoài được điều hướng đến các Pod của Jenkins deployment.

Service được tạo bằng cách định nghĩa một tập hợp các Pod theo các cách khác nhau. Service định tuyến các yêu cầu đến các Pod phù hợp dựa trên các thuộc tính của chúng, chẳng hạn như label. Với Jenkins, chúng ta cần tạo một Service để định tuyến các yêu cầu HTTP tới Jenkins UI và các yêu cầu JNLP tới các Pod Jenkins Agent. Ở hướng dẫn này mình sẽ làm hai tuỳ chọn truy cập dịch vụ đó là sử dụng NodePort và Ingress.

Tuỳ chọn 1: Sử dụng NodePort.

Trong Kubernetes, có hai loại Service: ClusterIP và NodePort. ClusterIP chỉ cung cấp truy cập nội bộ trong cluster Kubernetes, trong khi NodePort cho phép truy cập từ bên ngoài cluster thông qua IP của các node worker.

Trong hướng dẫn này, chúng ta sẽ sử dụng loại Service là NodePort để cho phép truy cập Jenkins deployment từ bên ngoài cluster Kubernetes.

cat > /home/kustomize/service.yaml << 'OEF'
apiVersion: v1
kind: Service
metadata:
  name: jenkins-service
  namespace: devops-tools
  annotations:
      prometheus.io/scrape: 'true'
      prometheus.io/path:   /
      prometheus.io/port:   '8080'
spec:
  selector: 
    app: jenkins-server
  type: NodePort  
  ports:
    - port: 8080
      targetPort: 8080
      nodePort: 32000
OEF

Hãy triển khai manifest này bằng lệnh kubectl apply -f service.yaml

$ kubectl apply -f service.yaml
service/jenkins-service created

Hãy xác minh lại service đã tạo thành công bằng lệnh kubectl get service -n <namespace>.

$ kubectl get service -n devops-tools
NAME              TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)          AGE
jenkins-service   NodePort   10.96.185.156   <none>        8080:32000/TCP   49s

Bây giờ nếu bạn duyệt đến bất kỳ một trong các IP Node trên cổng 32000, bạn sẽ có thể truy cập bảng điều khiển Jenkins. Vậy bây giờ hãy kiểm tra danh sách các Node trong cluster của bạn.

$ kubectl get node -A -owide
NAME          STATUS   ROLES                  AGE     VERSION   INTERNAL-IP      EXTERNAL-IP   OS-IMAGE             KERNEL-VERSION       CONTAINER-RUNTIME
k8s-master1   Ready    control-plane,master   6d22h   v1.23.8   192.168.13.211   <none>        Ubuntu 18.04.6 LTS   4.15.0-200-generic   containerd://1.6.14
k8s-master2   Ready    control-plane,master   6d22h   v1.23.8   192.168.13.212   <none>        Ubuntu 18.04.6 LTS   4.15.0-200-generic   containerd://1.6.14
k8s-worker1   Ready    <none>                 6d22h   v1.23.8   192.168.13.213   <none>        Ubuntu 18.04.6 LTS   4.15.0-200-generic   containerd://1.6.14
k8s-worker2   Ready    <none>                 6d22h   v1.23.8   192.168.13.214   <none>        Ubuntu 18.04.6 LTS   4.15.0-200-generic   containerd://1.6.14
k8s-worker3   Ready    <none>                 6d22h   v1.23.8   192.168.13.215   <none>        Ubuntu 18.04.6 LTS   4.15.0-200-generic   containerd://1.6.14

Mình lựa chọn IP của một Node bất kỳ để truy cập với url như dưới.

http://<node-ip>:32000

Kết quả.

Tuỳ chọn 2: Sử dụng Ingress.

Ingress là một đối tượng trong Kubernetes được sử dụng để quản lý việc phân phối các yêu cầu truy cập vào các dịch vụ trong cluster. Nó giúp cho việc truy cập các dịch vụ trong cluster dễ dàng hơn bằng cách sử dụng các quy tắc định tuyến dựa trên URL, tên miền và nhiều hơn nữa.

Để sử dụng Ingress để truy cập Jenkins, chúng ta cần định nghĩa một Ingress resource để định tuyến các yêu cầu đến Jenkins Service. Ta có thể sử dụng Ingress Controller như Nginx hoặc Traefik để quản lý và điều phối các yêu cầu truy cập đến các service khác nhau trong Kubernetes cluster.

Sau khi định nghĩa Ingress, chúng ta có thể truy cập Jenkins từ bất kỳ địa chỉ IP hoặc tên miền nào được cấu hình để định tuyến đến Ingress Controller.

cat > /home/kustomize/ingress.yaml << 'OEF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: jenkins-ingress
  namespace: devops-tools
spec:
  ingressClassName: nginx
  rules:
    - host: jenkins.hoanghd.com
      http:
        paths:
          - backend:
              service:
                name: jenkins-service
                port:
                  number: 8080
            path: /
            pathType: Prefix
OEF

Đoạn code trên là một file Kubernetes manifest để tạo một Ingress Resource trong Kubernetes cluster. Ingress Resource sẽ định tuyến các yêu cầu HTTP/HTTPS đến các Service trong Kubernetes.

Cụ thể, đoạn code trên sẽ tạo một Ingress Resource với tên jenkins-ingress trong namespace devops-tools. Nó chỉ định rằng tất cả các yêu cầu HTTP được gửi đến jenkins.hoanghd.com sẽ được định tuyến đến Service jenkins-service với port là 8080.

Điều này có nghĩa là khi truy cập vào jenkins.hoanghd.com, yêu cầu sẽ được định tuyến đến Service jenkins-service, và sau đó đến Pod chứa ứng dụng Jenkins. Trong ví dụ này, cổng của Jenkins là 8080, vì vậy Ingress sẽ chuyển hướng các yêu cầu tới Service jenkins-service với cổng 8080.

pathpathType được sử dụng để chỉ định đường dẫn URL được yêu cầu để định tuyến đến Service jenkins-service. Cụ thể, path: /pathType: Prefix được sử dụng để chỉ định rằng bất kỳ yêu cầu nào với đường dẫn URL bắt đầu bằng / đều được định tuyến đến jenkins-service.

Triển khai manifest này bằng lệnh kubectl apply -f ingress.yaml.Và sau đó bạn có thể sử dụng lệnh kubectl get ing -n devops-tools để xác minh Ingress đã được tạo thành công hay chưa. Nếu Ingress đã được tạo, thông tin của nó sẽ được hiển thị trong bảng kết quả.

$ kubectl get ing -n devops-tools
NAME              CLASS   HOSTS                 ADDRESS          PORTS   AGE
jenkins-ingress   nginx   jenkins.hoanghd.com   192.168.13.218   80      3s

Để xem chi tiết ingress này bạn hãy sử dụng lệnh kubectl describe ingress <ingress_name>.

$ kubectl describe ingress jenkins-ingress
Name:             jenkins-ingress
Labels:           <none>
Namespace:        default
Address:          
Default backend:  default-http-backend:80 (<error: endpoints "default-http-backend" not found>)
Rules:
  Host                 Path  Backends
  ----                 ----  --------
  jenkins.hoanghd.com  
                       /jenkins   jenkins:httpport (<error: endpoints "jenkins" not found>)
Annotations:           nginx.ingress.kubernetes.io/rewrite-target: /
Events:                <none>

Giờ đây bạn có thể sử dụng url đã định nghĩa trong ingress để truy cập Jenkins.

Bước 5: Lấy mật khẩu administrator đầu tiên.

Xác định tên pod của Jenkins bằng lệnh kubectl get pods --namespace=<ingress_name>.

$ kubectl get pods --namespace=devops-tools
NAME                      READY   STATUS    RESTARTS   AGE
jenkins-b96f7764f-ws5sz   1/1     Running   0          94m

Theo thông tin ở trên thì tên pod của Jenkins hiện tại là jenkins-b96f7764f-ws5sz. Như vậy bạn hãy thực hiện lệnh kubectl logs <tên pod của Jenkins> -n <namespace> để lấy mật khẩu.

Theo như kết quả ở dưới, mật khẩu đăng nhập của Jenkins sẽ là 081f3ce36b7e4f9a93cb91f45fb3c5ec.

$ kubectl logs jenkins-b96f7764f-ws5sz -n devops-tools
Running from: /usr/share/jenkins/jenkins.war
webroot: /var/jenkins_home/war
2023-05-11 05:01:52.360+0000 [id=1]     INFO    winstone.Logger#logInternal: Beginning extraction from war file
2023-05-11 05:01:52.647+0000 [id=1]     WARNING o.e.j.s.handler.ContextHandler#setContextPath: Empty contextPath
2023-05-11 05:01:52.862+0000 [id=1]     INFO    org.eclipse.jetty.server.Server#doStart: jetty-10.0.13; built: 2022-12-07T20:13:20.134Z; git: 1c2636ea05c0ca8de1ffd6ca7f3a98ac084c766d; jvm 11.0.19+7
2023-05-11 05:01:54.356+0000 [id=1]     INFO    o.e.j.w.StandardDescriptorProcessor#visitServlet: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
2023-05-11 05:01:54.653+0000 [id=1]     INFO    o.e.j.s.s.DefaultSessionIdManager#doStart: Session workerName=node0
2023-05-11 05:01:56.534+0000 [id=1]     INFO    hudson.WebAppMain#contextInitialized: Jenkins home directory: /var/jenkins_home found at: EnvVars.masterEnvVars.get("JENKINS_HOME")
2023-05-11 05:01:57.054+0000 [id=1]     INFO    o.e.j.s.handler.ContextHandler#doStart: Started w.@591fd34d{Jenkins v2.387.3,/,file:///var/jenkins_home/war/,AVAILABLE}{/var/jenkins_home/war}
2023-05-11 05:01:57.143+0000 [id=1]     INFO    o.e.j.server.AbstractConnector#doStart: Started ServerConnector@7ee8290b{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2023-05-11 05:01:57.252+0000 [id=1]     INFO    org.eclipse.jetty.server.Server#doStart: Started Server@28975c28{STARTING}[10.0.13,sto=0] @6926ms
2023-05-11 05:01:57.258+0000 [id=23]    INFO    winstone.Logger#logInternal: Winstone Servlet Engine running: controlPort=disabled
2023-05-11 05:01:58.151+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: Started initialization
2023-05-11 05:01:58.364+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: Listed all plugins
2023-05-11 05:02:01.632+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: Prepared all plugins
2023-05-11 05:02:01.639+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: Started all plugins
2023-05-11 05:02:01.756+0000 [id=29]    INFO    jenkins.InitReactorRunner$1#onAttained: Augmented all extensions
2023-05-11 05:02:02.969+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: System config loaded
2023-05-11 05:02:02.970+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: System config adapted
2023-05-11 05:02:02.970+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: Loaded all jobs
2023-05-11 05:02:02.972+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: Configuration for all jobs updated
2023-05-11 05:02:03.431+0000 [id=29]    INFO    jenkins.install.SetupWizard#init: 

*************************************************************
*************************************************************
*************************************************************

Jenkins initial setup is required. An admin user has been created and a password generated.
Please use the following password to proceed to installation:

081f3ce36b7e4f9a93cb91f45fb3c5ec

This may also be found at: /var/jenkins_home/secrets/initialAdminPassword

*************************************************************
*************************************************************
*************************************************************

WARNING: An illegal reflective access operation has occurred
WARNING: Illegal reflective access by org.codehaus.groovy.vmplugin.v7.Java7$1 (file:/var/jenkins_home/war/WEB-INF/lib/groovy-all-2.4.21.jar) to constructor java.lang.invoke.MethodHandles$Lookup(java.lang.Class,int)
WARNING: Please consider reporting this to the maintainers of org.codehaus.groovy.vmplugin.v7.Java7$1
WARNING: Use --illegal-access=warn to enable warnings of further illegal reflective access operations
WARNING: All illegal access operations will be denied in a future release
2023-05-11 05:02:31.135+0000 [id=28]    INFO    jenkins.InitReactorRunner$1#onAttained: Completed initialization
2023-05-11 05:02:31.341+0000 [id=22]    INFO    hudson.lifecycle.Lifecycle#onReady: Jenkins is fully up and running

Hoặc bạn cũng có thể sử dụng lệnh kubectl exec -it <tên pod của Jenkins> cat /var/jenkins_home/secrets/initialAdminPassword -n <namespace> để lấy mật khẩu trực tiếp.

$ kubectl exec -it jenkins-b96f7764f-ws5sz cat /var/jenkins_home/secrets/initialAdminPassword -n devops-tools
081f3ce36b7e4f9a93cb91f45fb3c5ec

Login thành công, bây giờ bạn hãy cài đặt các plushin của Jenkins và sử dụng nó thôi.

Nếu muốn xoá nhanh project Jenkins này, bạn có thể xoá namespace devops-tools của project này, hệ thống sẽ tự xoá hết toàn bộ các thành phần liên quan.

kubectl delete namespace devops-tools

Do Persistent Volume mình không đưa vào namespace nên nó tự động tạo ra ở namespace default, như vậy bạn phải thực hiện thêm lệnh xoá Persistent Volume kubectl delete pv <tên Persistent Volume>.

kubectl delete pv jenkins-pv-volume

LEAVE A REPLY

Please enter your comment!
Please enter your name here

4,956FansLike
256FollowersFollow
223SubscribersSubscribe
spot_img

Related Stories