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 Namespacedevops-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 Accountjenkins-admin
với ClusterRolejenkins-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:
apiVersion
vàkind
: 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ưname
vànamespace
.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.
path
và pathType
đượ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: /
và 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