Browse Source

security context, node selections and resources limiting

tags/0.0.5
Vladimir Smagin 1 month ago
parent
commit
b0c9b80e2c
Signed by: Vladimir Smagin <21h@blindage.org> GPG Key ID: 13BCE12E5618F071

+ 1
- 1
VERSION View File

@@ -1 +1 @@
0.0.4
0.0.5

+ 41
- 3
deploy/test-cron.yaml View File

@@ -7,18 +7,56 @@ spec:

# global ENVs
envConfigmap: cron-global

# do not run same job again
concurrencyPolicy: Forbid

# do not restart job pods
restartPolicy: Never

# do not restart job
backoffLimit: 0
# history limits
failedJobsHistoryLimit: 2
successfulJobsHistoryLimit: 2

# used if you want to save intermediate data
# persistentVolumeName: my-pvc-name
# persistentVolumePath: /persistent
# persistentVolumeSubPath: data

# podSecurityContext:
# runAsUser: 1000

# standard kubernetes nodeSelector section
# nodeSelector:
# disktype: ssd

# standard kubernetes affinity section
# affinity:
# podAffinity:
# requiredDuringSchedulingIgnoredDuringExecution:
# - labelSelector:
# matchExpressions:
# - key: security
# operator: In
# values:
# - S1
# topologyKey: failure-domain.beta.kubernetes.io/zone

# standard kubernetes toleration section
# tolerations:
# - key: "key"
# operator: "Exists"
# effect: "NoSchedule"

# podRequests:
# memory: "64Mi"
# cpu: "250m"
# ephemeral-storage: "10Ki"

# podLimits:
# memory: "128Mi"
# cpu: "500m"
# ephemeral-storage: "10Ki"

tasks:
# special task with failed command
- name: var-local

+ 1
- 0
go.mod View File

@@ -1,6 +1,7 @@
module git.blindage.org/21h/cron-operator

require (
github.com/NYTimes/gziphandler v1.0.1 // indirect
github.com/certifi/gocertifi v0.0.0-20190506164543-d2eda7129713 // indirect
github.com/getsentry/raven-go v0.2.0
github.com/go-logr/logr v0.1.0

+ 34
- 13
pkg/apis/blindage/v1alpha1/cronop_types.go View File

@@ -10,27 +10,48 @@ import (
// +k8s:openapi-gen=true

type CronTask struct {
Name string `json:"name"`
Schedule string `json:"schedule,omitempty"` // default "0 * * * *", hourly
Workdir string `json:"workdir,omitempty"` // default empty
Commands []string `json:"commands"`
RestartPolicy *corev1.RestartPolicy `json:"restartPolicy,omitempty"` // default OnFailure, overrides global policy
ConcurrencyPolicy *batchv1beta1.ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"` // default Allow, overrides global policy
EnvConfigmap string `json:"envConfigmap,omitempty"` // default empty, overrides global configmap
BackoffLimit *int32 `json:"backoffLimit,omitempty"` // default 0, overrides global limit
Name string `json:"name"`
Schedule string `json:"schedule,omitempty"` // default "0 * * * *", hourly
Workdir string `json:"workdir,omitempty"` // default empty
Commands []string `json:"commands"`
RestartPolicy *corev1.RestartPolicy `json:"restartPolicy,omitempty"` // default OnFailure, overrides global policy
ConcurrencyPolicy *batchv1beta1.ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"` // default Allow, overrides global policy
EnvConfigmap string `json:"envConfigmap,omitempty"` // default empty, overrides global configmap
BackoffLimit *int32 `json:"backoffLimit,omitempty"` // default 0, overrides global limit
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"` // default empty, overrides global context
}

type CronOpSpec struct {
Image string `json:"image,omitempty"` // default busybox

RestartPolicy *corev1.RestartPolicy `json:"restartPolicy,omitempty"` // default OnFailure, global
ConcurrencyPolicy *batchv1beta1.ConcurrencyPolicy `json:"concurrencyPolicy,omitempty"` // default Allow, global
SuccessfulJobsHistoryLimit *int32 `json:"successfulJobsHistoryLimit,omitempty"` // default 3
FailedJobsHistoryLimit *int32 `json:"failedJobsHistoryLimit,omitempty"` // default 3
BackoffLimit *int32 `json:"backoffLimit,omitempty"` // default 0, global
Image string `json:"image,omitempty"` // default busybox
PersistentVolumeName string `json:"persistentVolumeName,omitempty"` // default emtpy, must be created before use
PersistentVolumePath string `json:"persistentVolumePath,omitempty"` // default emtpy
EnvConfigmap string `json:"envConfigmap,omitempty"` // default empty, global
Tasks []CronTask `json:"tasks,omitempty"` // default empty

EnvConfigmap string `json:"envConfigmap,omitempty"` // default empty, global
PodSecurityContext *corev1.PodSecurityContext `json:"podSecurityContext,omitempty"`

PersistentVolumeName string `json:"persistentVolumeName,omitempty"` // default emtpy, must be created before use
PersistentVolumePath string `json:"persistentVolumePath,omitempty"` // default emtpy
PersistentVolumeSubPath string `json:"persistentVolumeSubPath,omitempty"` // default emtpy

Tasks []CronTask `json:"tasks,omitempty"` // default empty

// standart kubernetes resource limits for pods, default empty
// https://kubernetes.io/docs/concepts/configuration/manage-compute-resources-container/
PodRequests corev1.ResourceList `json:"podRequests,omitempty"`
PodLimits corev1.ResourceList `json:"podLimits,omitempty"`

// node selection
// https://kubernetes.io/docs/concepts/configuration/assign-pod-node/
NodeSelector map[string]string `json:"nodeSelector,omitempty"`
Affinity *corev1.Affinity `json:"affinity,omitempty"`

// tolerations
// https://kubernetes.io/docs/concepts/configuration/taint-and-toleration/
Tolerations *[]corev1.Toleration `json:"tolerations,omitempty"`
}

// CronOpStatus defines the observed state of CronOp

+ 47
- 0
pkg/apis/blindage/v1alpha1/zz_generated.deepcopy.go View File

@@ -99,6 +99,11 @@ func (in *CronOpSpec) DeepCopyInto(out *CronOpSpec) {
*out = new(int32)
**out = **in
}
if in.PodSecurityContext != nil {
in, out := &in.PodSecurityContext, &out.PodSecurityContext
*out = new(v1.PodSecurityContext)
(*in).DeepCopyInto(*out)
}
if in.Tasks != nil {
in, out := &in.Tasks, &out.Tasks
*out = make([]CronTask, len(*in))
@@ -106,6 +111,43 @@ func (in *CronOpSpec) DeepCopyInto(out *CronOpSpec) {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
if in.PodRequests != nil {
in, out := &in.PodRequests, &out.PodRequests
*out = make(v1.ResourceList, len(*in))
for key, val := range *in {
(*out)[key] = val.DeepCopy()
}
}
if in.PodLimits != nil {
in, out := &in.PodLimits, &out.PodLimits
*out = make(v1.ResourceList, len(*in))
for key, val := range *in {
(*out)[key] = val.DeepCopy()
}
}
if in.NodeSelector != nil {
in, out := &in.NodeSelector, &out.NodeSelector
*out = make(map[string]string, len(*in))
for key, val := range *in {
(*out)[key] = val
}
}
if in.Affinity != nil {
in, out := &in.Affinity, &out.Affinity
*out = new(v1.Affinity)
(*in).DeepCopyInto(*out)
}
if in.Tolerations != nil {
in, out := &in.Tolerations, &out.Tolerations
*out = new([]v1.Toleration)
if **in != nil {
in, out := *in, *out
*out = make([]v1.Toleration, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
return
}

@@ -158,6 +200,11 @@ func (in *CronTask) DeepCopyInto(out *CronTask) {
*out = new(int32)
**out = **in
}
if in.PodSecurityContext != nil {
in, out := &in.PodSecurityContext, &out.PodSecurityContext
*out = new(v1.PodSecurityContext)
(*in).DeepCopyInto(*out)
}
return
}


+ 40
- 5
pkg/controller/cronop/cronjob.go View File

@@ -94,6 +94,32 @@ func generateCronjob(reqLogger logr.Logger, cr *blindagev1alpha1.CronOp, jobSpec
cronjob.Spec.ConcurrencyPolicy = *jobSpec.ConcurrencyPolicy
}

//
// Node selection, affinity
//

cronjob.Spec.JobTemplate.Spec.Template.Spec.NodeSelector = cr.Spec.NodeSelector

if cr.Spec.Affinity != nil {
cronjob.Spec.JobTemplate.Spec.Template.Spec.Affinity = cr.Spec.Affinity
}

if cr.Spec.Tolerations != nil {
cronjob.Spec.JobTemplate.Spec.Template.Spec.Tolerations = *cr.Spec.Tolerations
}

//
// Security for Pods
//

if cr.Spec.PodSecurityContext != nil {
cronjob.Spec.JobTemplate.Spec.Template.Spec.SecurityContext = cr.Spec.PodSecurityContext
}

if jobSpec.PodSecurityContext != nil {
cronjob.Spec.JobTemplate.Spec.Template.Spec.SecurityContext = jobSpec.PodSecurityContext
}

//
// ENV variables
//
@@ -141,6 +167,11 @@ func generateCronjob(reqLogger logr.Logger, cr *blindagev1alpha1.CronOp, jobSpec
Image: imageName,
Command: jobSpec.Commands,
WorkingDir: workdir,
// resource limiting, default empty
Resources: corev1.ResourceRequirements{
Requests: cr.Spec.PodRequests,
Limits: cr.Spec.PodLimits,
},
}

jobContainer.EnvFrom = envs
@@ -160,12 +191,16 @@ func generateCronjob(reqLogger logr.Logger, cr *blindagev1alpha1.CronOp, jobSpec
}

// Set mount point
jobContainer.VolumeMounts = []corev1.VolumeMount{
{
Name: "persistent-volume",
MountPath: cr.Spec.PersistentVolumePath,
},
volumeMount := corev1.VolumeMount{
Name: "persistent-volume",
MountPath: cr.Spec.PersistentVolumePath,
}
// Set SubPath for some pod security reasons
if cr.Spec.PersistentVolumeSubPath != "" {
volumeMount.SubPath = cr.Spec.PersistentVolumeSubPath
}
jobContainer.VolumeMounts = []corev1.VolumeMount{volumeMount}

}

cronjob.Spec.JobTemplate.Spec.Template.Spec.Containers = []corev1.Container{jobContainer}

+ 1
- 1
version/version.go View File

@@ -1,5 +1,5 @@
package version

var (
Version = "0.0.4"
Version = "0.0.5"
)

Loading…
Cancel
Save