Storage Configuration
This deployment uses NFS for persistent storage. Ensure a StorageClass named nfs-storage is already configured in your cluster.
Create Namespace
kubectl create namespace ops
Configure RBAC Permissions
Define a service account, cluster role, and binding to grant Jenkins necessary permissions:
# ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
name: jenkins-sa
namespace: ops
---
# ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: jenkins-role
rules:
- apiGroups: ["apps", "extensions"]
resources: ["deployments", "ingresses"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["services", "pods", "pods/exec"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
- apiGroups: [""]
resources: ["pods/log", "events"]
verbs: ["get", "list", "watch"]
- apiGroups: [""]
resources: ["secrets"]
verbs: ["get"]
---
# ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: jenkins-binding
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: jenkins-role
subjects:
- kind: ServiceAccount
name: jenkins-sa
namespace: ops
Create Headless Service
A headless service enables direct pod access with out load balancing:
apiVersion: v1
kind: Service
metadata:
name: jenkins-headless
namespace: ops
spec:
clusterIP: None
selector:
app.kubernetes.io/name: jenkins
ports:
- name: web
port: 8080
targetPort: 8080
- name: agent
port: 50000
targetPort: 50000
Deploy Jenkins as a StatefulSet
Use a StatefulSet to manage Jenkins with stable network identity and persistent storage:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: jenkins-app
namespace: ops
spec:
serviceName: jenkins-headless
replicas: 1
selector:
matchLabels:
app.kubernetes.io/name: jenkins
template:
metadata:
labels:
app.kubernetes.io/name: jenkins
spec:
serviceAccountName: jenkins-sa
containers:
- name: jenkins
image: jenkins/jenkins:2.473-jdk17
imagePullPolicy: IfNotPresent
securityContext:
runAsUser: 0
privileged: true
env:
- name: JAVA_OPTS
value: "-Duser.timezone=Asia/Shanghai"
ports:
- containerPort: 8080
name: web
- containerPort: 50000
name: agent
volumeMounts:
- name: jenkins-data
mountPath: /var/jenkins_home
volumeClaimTemplates:
- metadata:
name: jenkins-data
spec:
accessModes: ["ReadWriteOnce"]
storageClassName: nfs-storage
resources:
requests:
storage: 1Gi
Expose via Ingress
Route external traffic using an Ingress resource:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: jenkins-ingress
namespace: ops
spec:
ingressClassName: nginx
rules:
- host: jenkins.ops.net
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: jenkins-headless
port:
name: web
Apply Manifests
Deploy all resources from the current directory:
kubectl apply -f .