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

Feature/tolerations #165

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
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ The config values to be set are:
| `NAMESPACE` | Namespace where daemonset is to be created | `kubernetes-image-puller` |
| `IMAGES` | List of images to be cached, in this format `<name>=<image>;...` | Contains a default list of images, but should be configured when deploying |
| `NODE_SELECTOR` | Node selector applied to pods created by the daemonset, provided in this format `'{"key":"value"}'` | `'{}'` |
| `TOLERATIONS` | Tolerations to be applied to pods to be scheduled on to tainted nodes. Format: `"key=value:Effect"` | `""` |
| `IMAGE_PULL_SECRETS` | List of image pull secrets, in this format `pullsecret1;...` to add to pods created by the DaemonSet. Those secrets need to be in the image puller's namespace and a cluster administrator must create them. | `""` |
| `AFFINITY` | Affinity applied to pods created by the daemonset, in this format `'{"nodeAffinity":{ ... }}'` | `'{}'` |
| `KIP_IMAGE` | The image puller image to copy the `sleep` binary from | `quay.io/eclipse/kubernetes-image-puller:next` |
Expand All @@ -46,7 +47,8 @@ The following values can be set:
| `configMap.cachingMemoryLimit` | The value of `CACHING_MEMORY_LIMIT` to be set in the ConfigMap | `"20Mi"` |
| `configMap.cachingCpuRequest` | The value of `CACHING_CPU_REQUEST` to be set in the ConfigMap | `.05` |
| `configMap.cachingCpuLimit` | The value of `CACHING_CPU_LIMIT` to be set in the ConfigMap | `.2` |
| `configMap.nodeSelector` | The value of `NODE_SELECTOR` to be set in the ConfigMap | `"{}"` |
| `configMap.nodeSelector` | The value of `NODE_SELECTOR` to be set in the ConfigMap | `"{}"` |
| `configMap.tolerations` | The value of `TOLERATIONS` to be set in the ConfigMap | `""` |
| `configMap.imagePullSecrets` | The value of `IMAGE_PULL_SECRETS` | `""` |
| `configMap.affinity` | The value of `AFFINITY` to be set in the ConfigMap | `"{}"` |

Expand All @@ -68,6 +70,7 @@ The following values can be set:
| `CACHING_CPU_LIMIT` | The value of `CACHING_CPU_LIMIT` to be set in the ConfigMap | `.2` |
| `NAMESPACE` | The value of `NAMESPACE` to be set in the ConfigMap | `k8s-image-puller` |
| `NODE_SELECTOR` | The value of `NODE_SELECTOR` to be set in the ConfigMap | `"{}"` |
| `TOLERATIONS` | The value of `TOLERATIONS` to be set in the ConfigMap | `""` |
| `IMAGE_PULL_SECRETS` | The value of `IMAGE_PULL_SECRETS` | `""` |
| `AFFINITY` | The value of `AFFINITY` to be set in the ConfigMap | `"{}"` |

Expand Down
2 changes: 2 additions & 0 deletions cfg/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ type Config struct {
CachingInterval int
NodeSelector map[string]string
ImagePullSecrets []string
Tolerations []corev1.Toleration
Affinity *corev1.Affinity
ImagePullerImage string
}
Expand All @@ -41,6 +42,7 @@ func GetConfig() Config {
CachingCpuLimit: getEnvVarOrDefault(cachingCpuLimitEnvVar, defaultCachingCpuLimit),
NodeSelector: processNodeSelectorEnvVar(),
ImagePullSecrets: processImagePullSecretsEnvVar(),
Tolerations: processTolerationsEnvVar(),
Affinity: processAffinityEnvVar(),
ImagePullerImage: getEnvVarOrDefault(kipImageEnvVar, defaultImage),
}
Expand Down
16 changes: 16 additions & 0 deletions cfg/config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func TestEnvVars(t *testing.T) {
CachingCpuLimit: ".2",
CachingInterval: 5,
NodeSelector: map[string]string{},
Tolerations: []v1.Toleration{},
ImagePullSecrets: []string{},
Affinity: &v1.Affinity{},
ImagePullerImage: "quay.io/eclipse/kubernetes-image-puller:next",
Expand All @@ -48,6 +49,7 @@ func TestEnvVars(t *testing.T) {
"DAEMONSET_NAME": "custom-daemonset-name",
"NAMESPACE": "my-namespace",
"NODE_SELECTOR": "{\"type\": \"compute\"}",
"TOLERATIONS": "key=value:NoSchedule;key1=value1:NoExecute",
"CACHING_CPU_REQUEST": ".055",
"IMAGE_PULL_SECRETS": "secret1; secret2",
"AFFINITY": `{"nodeAffinity":{"requiredDuringSchedulingIgnoredDuringExecution":{"nodeSelectorTerms":[{"matchExpressions":[{"key":"kubernetes.io/e2e-az-name","operator":"In","values":["e2e-az1","e2e-az2"]}]}]}}}`,
Expand All @@ -67,6 +69,20 @@ func TestEnvVars(t *testing.T) {
NodeSelector: map[string]string{
"type": "compute",
},
Tolerations: []v1.Toleration{
v1.Toleration{
Key: "key",
Value: "value",
Operator: "Equal",
Effect: v1.TaintEffectNoSchedule,
},
v1.Toleration{
Key: "key1",
Value: "value1",
Operator: "Equal",
Effect: v1.TaintEffectNoExecute,
},
},
ImagePullSecrets: []string{"secret1", "secret2"},
Affinity: &v1.Affinity{
NodeAffinity: &v1.NodeAffinity{
Expand Down
60 changes: 60 additions & 0 deletions cfg/envvars.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ package cfg

import (
"encoding/json"
"fmt"
"log"
"os"
"strconv"
Expand All @@ -33,6 +34,7 @@ const (
cachingCpuRequestEnvVar = "CACHING_CPU_REQUEST"
cachingCpuLimitEnvVar = "CACHING_CPU_LIMIT"
nodeSelectorEnvVar = "NODE_SELECTOR"
tolerationsEnvVar = "TOLERATIONS"
imagePullSecretsEnvVar = "IMAGE_PULL_SECRETS"
affinityEnvVar = "AFFINITY"
kipImageEnvVar = "KIP_IMAGE"
Expand All @@ -49,6 +51,7 @@ const (
defaultCachingCpuRequest = ".05"
defaultCachingCpuLimit = ".2"
defaultNodeSelector = "{}"
defaultTolerations = ""
defaultImagePullSecret = ""
defaultAffinity = "{}"
defaultImage = "quay.io/eclipse/kubernetes-image-puller:next"
Expand Down Expand Up @@ -104,6 +107,63 @@ func processNodeSelectorEnvVar() map[string]string {
return nodeSelector
}

func convertToTaintEffect(effectString string) (corev1.TaintEffect, error) {
switch strings.ToLower(effectString) {
case "noschedule":
return corev1.TaintEffectNoSchedule, nil
case "prefernoschedule":
return corev1.TaintEffectPreferNoSchedule, nil
case "noexecute":
return corev1.TaintEffectNoExecute, nil
default:
return "", fmt.Errorf("invalid taint effect: %s", effectString)
}
}

func processTolerationsEnvVar() []corev1.Toleration {
rawTolerations := getEnvVarOrDefault(tolerationsEnvVar, defaultTolerations)
rawTolerations = strings.TrimSpace(rawTolerations)

if rawTolerations == "" {
return []corev1.Toleration{}
}

tolerationList := strings.Split(rawTolerations, ";")
var tolerations []corev1.Toleration

for _, toleration := range tolerationList {
parts := strings.Split(strings.TrimSpace(toleration), ":")
if len(parts) != 2 {
log.Fatalf("invalid toleration format")
}

keyValue := parts[0]
effect, err := convertToTaintEffect(parts[1])
if err != nil {
log.Fatalf("invalid toleration effect")
}

keyValueParts := strings.Split(keyValue, "=")
if len(keyValueParts) != 2 {
log.Fatalf("invalid toleration format")
}

key := keyValueParts[0]
value := keyValueParts[1]

result := corev1.Toleration{
Key: key,
Operator: "Equal",
Value: value,
Effect: effect,
}

tolerations = append(tolerations, result)
}

return tolerations
}

func processImagePullSecretsEnvVar() []string {
rawImagePullSecrets := getEnvVarOrDefault(imagePullSecretsEnvVar, defaultImagePullSecret)
rawImagePullSecrets = strings.TrimSpace(rawImagePullSecrets)
Expand Down
57 changes: 57 additions & 0 deletions cfg/envvars_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,63 @@ func TestProcessNodeSElectorEnvVar(t *testing.T) {
}
}

func TestTolerationsEnvVar(t *testing.T) {
type testcase struct {
name string
tolerations string
isTolerationSet bool
want []v1.Toleration
}

testcases := []testcase{
{
name: "default tolerations, TOLERATIONS set",
tolerations: "",
isTolerationSet: true,
want: []v1.Toleration{},
},
{
name: "multiple tolerations, TOLERATIONS set",
tolerations: "key=value:NoSchedule; test=hello:NoExecute",
isTolerationSet: true,
want: []v1.Toleration{
v1.Toleration{
Key: "key",
Value: "value",
Operator: "Equal",
Effect: v1.TaintEffectNoSchedule,
},
v1.Toleration{
Key: "test",
Value: "hello",
Operator: "Equal",
Effect: v1.TaintEffectNoExecute,
},
},
},
{
name: "default env var, TOLERATIONS not set",
tolerations: "key=value:NoSchedule",
isTolerationSet: false,
want: []v1.Toleration{},
},
}

for _, c := range testcases {
t.Run(c.name, func(t *testing.T) {
defer os.Clearenv()
if c.isTolerationSet {
os.Setenv("TOLERATIONS", c.tolerations)
}
got := processTolerationsEnvVar()

if d := cmp.Diff(c.want, got); d != "" {
t.Errorf("(-want, +got): %s", d)
}
})
}
}

func TestGetEnvVarOrDefaultBool(t *testing.T) {
defer os.Clearenv()
os.Setenv("DEFINED_ENV_VAR", "true")
Expand Down
2 changes: 1 addition & 1 deletion deploy/helm/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
apiVersion: v1
name: kubernetes-image-puller
version: 1.0.0
version: 1.1.0
description: The kubernetes image puller downloads che images ahead of time for faster workspace startup
1 change: 1 addition & 0 deletions deploy/helm/templates/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ data:
CACHING_CPU_REQUEST: "{{ .Values.configMap.cachingCpuRequest }}"
CACHING_CPU_LIMIT: "{{ .Values.configMap.cachingCpuLimit }}"
NODE_SELECTOR: "{{ .Values.configMap.nodeSelector }}"
TOLERATIONS: "{{ .Values.configMap.tolerations }}"
IMAGE_PULL_SECRETS: "{{ .Values.configMap.imagePullSecrets }}"
AFFINITY: "{{ .Values.configMap.affinity }}"
1 change: 1 addition & 0 deletions deploy/helm/values.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ configMap:
cachingCpuRequest: ".05"
cachingCpuLimit: ".2"
nodeSelector: "{}"
tolerations: ""
imagePullSecrets: ""
affinity: "{}"
3 changes: 3 additions & 0 deletions deploy/openshift/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ objects:
CACHING_CPU_REQUEST: ${CACHING_CPU_REQUEST}
CACHING_CPU_LIMIT: ${CACHING_CPU_LIMIT}
NODE_SELECTOR: ${NODE_SELECTOR}
TOLERATIONS: ${TOLERATIONS}
IMAGE_PULL_SECRETS: ${IMAGE_PULL_SECRETS}
AFFINITY: ${AFFINITY}
parameters:
Expand All @@ -44,6 +45,8 @@ parameters:
value: ".2"
- name: NODE_SELECTOR
value: "{}"
- name: TOLERATIONS
value: ""
- name: IMAGE_PULL_SECRETS
value: ""
- name: AFFINITY
Expand Down
1 change: 1 addition & 0 deletions utils/clusterutils.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ func getDaemonset(deployment *appsv1.Deployment) *appsv1.DaemonSet {
},
Spec: corev1.PodSpec{
NodeSelector: cfg.NodeSelector,
Tolerations: cfg.Tolerations,
TerminationGracePeriodSeconds: &terminationGracePeriodSeconds,
InitContainers: []corev1.Container{{
Name: "copy-sleep",
Expand Down