Path: blob/main/install/installer/pkg/cluster/affinity.go
2501 views
// Copyright (c) 2021 Gitpod GmbH. All rights reserved.1// Licensed under the GNU Affero General Public License (AGPL).2// See License.AGPL.txt in the project root for license information.34package cluster56import (7corev1 "k8s.io/api/core/v1"8metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"9)1011// Valid characters for affinities are alphanumeric, -, _, . and one / as a subdomain prefix12const (13AffinityLabelMeta = "gitpod.io/workload_meta"14AffinityLabelIDE = "gitpod.io/workload_ide"15AffinityLabelServices = "gitpod.io/workload_services"16AffinityLabelWorkspacesRegular = "gitpod.io/workload_workspace_regular"17AffinityLabelWorkspacesHeadless = "gitpod.io/workload_workspace_headless"1819HostnameTopologyKey = "kubernetes.io/hostname"20)2122var AffinityListMeta = []string{23AffinityLabelMeta,24AffinityLabelIDE,25AffinityLabelServices,26}2728var AffinityListWorkspace = []string{29AffinityLabelServices,30AffinityLabelWorkspacesRegular,31AffinityLabelWorkspacesHeadless,32}3334var AffinityList = func() []string {35list := []string{}3637list = append(list, AffinityListMeta...)38list = append(list, AffinityListWorkspace...)3940return list41}()4243func WithPodAntiAffinityHostname(component string) *corev1.PodAntiAffinity {44return &corev1.PodAntiAffinity{45PreferredDuringSchedulingIgnoredDuringExecution: []corev1.WeightedPodAffinityTerm{46{47Weight: 100,48PodAffinityTerm: corev1.PodAffinityTerm{49LabelSelector: &metav1.LabelSelector{50MatchExpressions: []metav1.LabelSelectorRequirement{{51Key: "component",52Operator: "In",53Values: []string{component},54}},55},56TopologyKey: HostnameTopologyKey,57},58},59},60}61}6263func defaultLabels(component string) map[string]string {64return map[string]string{65"app": "gitpod",66"component": component,67}68}6970func WithHostnameTopologySpread(component string) []corev1.TopologySpreadConstraint {71return []corev1.TopologySpreadConstraint{72{73LabelSelector: &metav1.LabelSelector{MatchLabels: defaultLabels(component)},74MaxSkew: 1,75TopologyKey: HostnameTopologyKey,76WhenUnsatisfiable: corev1.ScheduleAnyway,77},78}79}8081func WithNodeAffinityHostnameAntiAffinity(component string, orLabels ...string) *corev1.Affinity {82var terms []corev1.NodeSelectorTerm8384for _, lbl := range orLabels {85terms = append(terms, corev1.NodeSelectorTerm{86MatchExpressions: []corev1.NodeSelectorRequirement{87{88Key: lbl,89Operator: corev1.NodeSelectorOpExists,90},91},92})93}9495return &corev1.Affinity{96NodeAffinity: &corev1.NodeAffinity{97RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{98NodeSelectorTerms: terms,99},100},101PodAntiAffinity: WithPodAntiAffinityHostname(component),102}103}104105func WithNodeAffinity(orLabels ...string) *corev1.Affinity {106var terms []corev1.NodeSelectorTerm107108for _, lbl := range orLabels {109terms = append(terms, corev1.NodeSelectorTerm{110MatchExpressions: []corev1.NodeSelectorRequirement{111{112Key: lbl,113Operator: corev1.NodeSelectorOpExists,114},115},116})117}118119return &corev1.Affinity{120NodeAffinity: &corev1.NodeAffinity{121RequiredDuringSchedulingIgnoredDuringExecution: &corev1.NodeSelector{122NodeSelectorTerms: terms,123},124},125}126}127128129