Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[wip] feat: add ephemeral pvc option to jenkins home #833

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions api/v1alpha2/jenkins_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,11 @@ type JenkinsMaster struct {
// +optional
Volumes []corev1.Volume `json:"volumes,omitempty"`

// Storage settings for the jenkins home directory
// Can be tempDir or ephemeral
// +optional
StorageSettings StorageSettings `json:"storageSettings,omitempty"`

// If specified, the pod's tolerations.
// +optional
Tolerations []corev1.Toleration `json:"tolerations,omitempty"`
Expand Down Expand Up @@ -387,6 +392,19 @@ type JenkinsMaster struct {
HostAliases []corev1.HostAlias `json:"hostAliases,omitempty"`
}

// StorageSettings defines Jenkins master pod persistence attributes.
// +optional
type StorageSettings struct {
// UseEmptyDir allows you to create an emptydir as jenkins-home, also this is the default
UseEmptyDir bool `json:"useEmptyDir"`
// UseEphemeralStorage allows you to create kubernetes ephemeral pvc, see "https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes"
UseEphemeralStorage bool `json:"useEphemeralStorage"`
// StorageClassName in case of ephemeral pvc, can be empty
StorageClassName string `json:"storageClassName"`
// StorageRequest allows you to specify the storage request, required in case of ephemeral pvc
StorageRequest string `json:"storageRequest"`
}

// Service defines Kubernetes service attributes
type Service struct {
// Annotations is an unstructured key value map stored with a resource that may be
Expand Down
21 changes: 18 additions & 3 deletions api/v1alpha2/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

50 changes: 39 additions & 11 deletions chart/jenkins-operator/crds/jenkins-crd.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ spec:
type: object
basePlugins:
description: 'BasePlugins contains plugins required by operator
Defaults to : - name: kubernetes version: "1.31.3" - name:
workflow-job version: "1145.v7f2433caa07f" - name: workflow-aggregator version:
"2.6" - name: git version: "4.11.3" - name: job-dsl version:
"1.78.1" - name: configuration-as-code version: "1346.ve8cfa_3473c94" - name:
kubernetes-credentials-provider version: "0.20"'
Defaults to : - name: configuration-as-code version: "1625.v27444588cc3d"
- name: git version: "5.0.0" - name: job-dsl version: "1.83"
- name: kubernetes version: "3909.v1f2c633e8590" - name: kubernetes-credentials-provider
version: "1.211.vc236a_f5a_2f3c" - name: workflow-aggregator
version: "596.v8c21c963d92d" - name: workflow-job version: "1289.vd1c337fd5354"'
items:
description: Plugin defines Jenkins plugin.
properties:
Expand Down Expand Up @@ -1100,11 +1100,6 @@ spec:
- resources
type: object
type: array
latestPlugins:
description: 'Allow to override jenkins-plugin-cli default behavior
while downloading the plugin and dependencies, see:
https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options'
type: boolean
disableCSRFProtection:
description: DisableCSRFProtection allows you to toggle CSRF Protection
on Jenkins
Expand Down Expand Up @@ -1150,6 +1145,10 @@ spec:
selectors of replication controllers and services. More info:
http://kubernetes.io/docs/user-guide/labels'
type: object
latestPlugins:
description: 'Allow to override jenkins-plugin-cli default behavior
while downloading the plugin and dependencies see: https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options'
type: boolean
nodeSelector:
additionalProperties:
type: string
Expand Down Expand Up @@ -1331,6 +1330,32 @@ spec:
type: string
type: object
type: object
storageSettings:
description: Storage settings for the jenkins home directory Can
be tempDir or ephemeral
properties:
storageClassName:
description: StorageClassName in case of ephemeral pvc, can
be empty
type: string
storageRequest:
description: StorageRequest allows you to specify the storage
request, required in case of ephemeral pvc
type: string
useEmptyDir:
description: UseEmptyDir allows you to create an emptydir
as jenkins-home, also this is the default
type: boolean
useEphemeralStorage:
description: UseEphemeralStorage allows you to create kubernetes
ephemeral pvc, see "https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes"
type: boolean
required:
- storageClassName
- storageRequest
- useEmptyDir
- useEphemeralStorage
type: object
tolerations:
description: If specified, the pod's tolerations.
items:
Expand Down Expand Up @@ -2864,6 +2889,7 @@ spec:
type: array
required:
- disableCSRFProtection
- latestPlugins
type: object
notifications:
description: Notifications defines list of a services which are used
Expand Down Expand Up @@ -3124,8 +3150,10 @@ spec:
type: object
type: array
seedJobAgentImage:
description: SeedJobAgentImage defines the image that will be used
by the seed job agent. If not defined jenkins/inbound-agent:4.9-1
will be used.
type: string
description: 'SeedJobAgentImage defines the image that will be used by the seed job agent. If not defined jenkins/inbound-agent:4.10-3 will be used.'
seedJobs:
description: 'SeedJobs defines list of Jenkins Seed Job configurations
More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuration#configure-seed-jobs-and-pipelines'
Expand Down
3 changes: 3 additions & 0 deletions chart/jenkins-operator/templates/jenkins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ spec:
{{- end }}
{{- end }}
{{- with .Values.jenkins.volumes }}
storageSettings: {{- toYaml . | nindent 6 }}
{{- end }}
{{- with .Values.jenkins.storageSettings }}
volumes: {{- toYaml . | nindent 4 }}
{{- end }}
{{- with .Values.jenkins.imagePullSecrets }}
Expand Down
12 changes: 12 additions & 0 deletions chart/jenkins-operator/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,18 @@ jenkins:
# See https://jenkinsci.github.io/kubernetes-operator/docs/installation/#note-on-restricted-jenkins-controller-pod-volumemounts for details
volumeMounts: []

# Storage for Jenkins
# By default emptyDir
# See https://kubernetes.io/docs/concepts/storage/volumes/#emptydir for details
storageSettings:
useEmptyDir: true
# Alternative storage settings
# An ephemeral pvc can be used see https://kubernetes.io/docs/concepts/storage/volumes/#ephemeral-volume
# In case is true we also need to pass the storageRequest and optionally the storageClassName
ephemeralStorage: false
storageClassName: ""
storageRequest: ""

# defines authorization strategy of the operator for the Jenkins API
authorizationStrategy: createUser

Expand Down
50 changes: 39 additions & 11 deletions config/crd/bases/jenkins.io_jenkins.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -157,11 +157,11 @@ spec:
type: object
basePlugins:
description: 'BasePlugins contains plugins required by operator
Defaults to : - name: kubernetes version: "1.31.3" - name:
workflow-job version: "1145.v7f2433caa07f" - name: workflow-aggregator version:
"2.6" - name: git version: "4.11.3" - name: job-dsl version:
"1.78.1" - name: configuration-as-code version: "1346.ve8cfa_3473c94" - name:
kubernetes-credentials-provider version: "0.20"'
Defaults to : - name: configuration-as-code version: "1625.v27444588cc3d"
- name: git version: "5.0.0" - name: job-dsl version: "1.83"
- name: kubernetes version: "3909.v1f2c633e8590" - name: kubernetes-credentials-provider
version: "1.211.vc236a_f5a_2f3c" - name: workflow-aggregator
version: "596.v8c21c963d92d" - name: workflow-job version: "1289.vd1c337fd5354"'
items:
description: Plugin defines Jenkins plugin.
properties:
Expand Down Expand Up @@ -1100,11 +1100,6 @@ spec:
- resources
type: object
type: array
latestPlugins:
description: 'Allow to override jenkins-plugin-cli default behavior
while downloading the plugin and dependencies, see:
https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options'
type: boolean
disableCSRFProtection:
description: DisableCSRFProtection allows you to toggle CSRF Protection
on Jenkins
Expand Down Expand Up @@ -1150,6 +1145,10 @@ spec:
selectors of replication controllers and services. More info:
http://kubernetes.io/docs/user-guide/labels'
type: object
latestPlugins:
description: 'Allow to override jenkins-plugin-cli default behavior
while downloading the plugin and dependencies see: https://github.com/jenkinsci/plugin-installation-manager-tool#cli-options'
type: boolean
nodeSelector:
additionalProperties:
type: string
Expand Down Expand Up @@ -1331,6 +1330,32 @@ spec:
type: string
type: object
type: object
storageSettings:
description: Storage settings for the jenkins home directory Can
be tempDir or ephemeral
properties:
storageClassName:
description: StorageClassName in case of ephemeral pvc, can
be empty
type: string
storageRequest:
description: StorageRequest allows you to specify the storage
request, required in case of ephemeral pvc
type: string
useEmptyDir:
description: UseEmptyDir allows you to create an emptydir
as jenkins-home, also this is the default
type: boolean
useEphemeralStorage:
description: UseEphemeralStorage allows you to create kubernetes
ephemeral pvc, see "https://kubernetes.io/docs/concepts/storage/ephemeral-volumes/#generic-ephemeral-volumes"
type: boolean
required:
- storageClassName
- storageRequest
- useEmptyDir
- useEphemeralStorage
type: object
tolerations:
description: If specified, the pod's tolerations.
items:
Expand Down Expand Up @@ -2864,6 +2889,7 @@ spec:
type: array
required:
- disableCSRFProtection
- latestPlugins
type: object
notifications:
description: Notifications defines list of a services which are used
Expand Down Expand Up @@ -3124,8 +3150,10 @@ spec:
type: object
type: array
seedJobAgentImage:
description: SeedJobAgentImage defines the image that will be used
by the seed job agent. If not defined jenkins/inbound-agent:4.9-1
will be used.
type: string
description: 'SeedJobAgentImage defines the image that will be used by the seed job agent. If not defined jenkins/inbound-agent:4.10-3 will be used.'
seedJobs:
description: 'SeedJobs defines list of Jenkins Seed Job configurations
More info: https://jenkinsci.github.io/kubernetes-operator/docs/getting-started/latest/configuration#configure-seed-jobs-and-pipelines'
Expand Down
57 changes: 51 additions & 6 deletions pkg/configuration/base/resources/pod.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/jenkinsci/kubernetes-operator/pkg/constants"

corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)

Expand Down Expand Up @@ -88,18 +89,62 @@ func getJenkinsHomePath(jenkins *v1alpha2.Jenkins) string {
return defaultJenkinsHomePath
}

func validateStorageSize(storageSize string) bool {
if strings.TrimSpace(storageSize) == "" {
return false
}
_, err := resource.ParseQuantity(storageSize)
return err == nil
}

// get Jenkins home storage settings from the CRD
func getJenkinsHomeStorageSettings(jenkins *v1alpha2.Jenkins) corev1.Volume {
emptyDirVol := corev1.Volume{
Name: JenkinsHomeVolumeName,
VolumeSource: corev1.VolumeSource{
// Create empty dir for Jenkins home
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
}
var JenkinsHomeVolume corev1.Volume
if jenkins.Spec.Master.StorageSettings.UseEphemeralStorage {
if !validateStorageSize(jenkins.Spec.Master.StorageSettings.StorageRequest) {
fmt.Println("Invalid storage size %s, falling back to empty dir" + jenkins.Spec.Master.StorageSettings.StorageRequest)
JenkinsHomeVolume = emptyDirVol
return JenkinsHomeVolume
}
JenkinsHomeVolume = corev1.Volume{
Name: JenkinsHomeVolumeName,
VolumeSource: corev1.VolumeSource{
// Create ephemeral storage for Jenkins home
Ephemeral: &corev1.EphemeralVolumeSource{
VolumeClaimTemplate: &corev1.PersistentVolumeClaimTemplate{
Spec: corev1.PersistentVolumeClaimSpec{
StorageClassName: &jenkins.Spec.Master.StorageSettings.StorageClassName,
AccessModes: []corev1.PersistentVolumeAccessMode{corev1.ReadWriteOnce},
Resources: corev1.ResourceRequirements{
Requests: corev1.ResourceList{
corev1.ResourceStorage: resource.MustParse(jenkins.Spec.Master.StorageSettings.StorageRequest),
},
},
},
},
},
},
}
} else {
JenkinsHomeVolume = emptyDirVol
}
return JenkinsHomeVolume
}

// GetJenkinsMasterPodBaseVolumes returns Jenkins master pod volumes required by operator
func GetJenkinsMasterPodBaseVolumes(jenkins *v1alpha2.Jenkins) []corev1.Volume {
configMapVolumeSourceDefaultMode := corev1.ConfigMapVolumeSourceDefaultMode
secretVolumeSourceDefaultMode := corev1.SecretVolumeSourceDefaultMode
var scriptsVolumeDefaultMode int32 = 0777
volumes := []corev1.Volume{
{
Name: JenkinsHomeVolumeName,
VolumeSource: corev1.VolumeSource{
EmptyDir: &corev1.EmptyDirVolumeSource{},
},
},
getJenkinsHomeStorageSettings(jenkins),
{
Name: jenkinsScriptsVolumeName,
VolumeSource: corev1.VolumeSource{
Expand Down
Loading