-
Notifications
You must be signed in to change notification settings - Fork 1
feat: optionally distribute replicas across architectures #153
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -68,6 +68,29 @@ type SecretConfig struct { | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Type product.SiteSecretType `json:"type,omitempty"` | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // componentSelector is the label-identity selector for a component's own pods — | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // shared by anti-affinity and topology spread so both target the same pod set. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func componentSelector(p product.KubernetesLabelser) *metav1.LabelSelector { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return &metav1.LabelSelector{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatchExpressions: []metav1.LabelSelectorRequirement{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Key: KubernetesInstanceLabelKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operator: metav1.LabelSelectorOpIn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Values: []string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| p.KubernetesLabels()[KubernetesInstanceLabelKey], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Key: SiteLabelKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operator: metav1.LabelSelectorOpIn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Values: []string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| p.KubernetesLabels()[SiteLabelKey], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ComponentSpecPodAntiAffinity generates a *corev1.PodAntiAffinity suitable for use in a | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // given component's deployment template spec to inform kubernetes to place pod replicas | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // on separate nodes when possible. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
@@ -77,28 +100,31 @@ func ComponentSpecPodAntiAffinity(p product.KubernetesLabelser, namespace string | |||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Weight: 1, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| PodAffinityTerm: corev1.PodAffinityTerm{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TopologyKey: "kubernetes.io/hostname", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Namespaces: []string{namespace}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LabelSelector: &metav1.LabelSelector{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| MatchExpressions: []metav1.LabelSelectorRequirement{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Key: KubernetesInstanceLabelKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operator: metav1.LabelSelectorOpIn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Values: []string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| p.KubernetesLabels()[KubernetesInstanceLabelKey], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Key: SiteLabelKey, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Operator: metav1.LabelSelectorOpIn, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Values: []string{ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| p.KubernetesLabels()[SiteLabelKey], | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| TopologyKey: "kubernetes.io/hostname", | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Namespaces: []string{namespace}, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| LabelSelector: componentSelector(p), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| }, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // ComponentSpecTopologySpreadConstraints defaults any constraint's LabelSelector to | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // componentSelector when the caller left it nil. A nil LabelSelector matches zero pods | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // (Kubernetes semantics: metav1.LabelSelectorAsSelector(nil) returns labels.Nothing()), | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // silently turning maxSkew/whenUnsatisfiable into a no-op. This exists so the common case | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // (spread this component's own replicas) works without the caller re-deriving labels the | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // operator already owns; an explicit caller-supplied LabelSelector is always left untouched. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func ComponentSpecTopologySpreadConstraints( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| constraints []corev1.TopologySpreadConstraint, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| p product.KubernetesLabelser, | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) []corev1.TopologySpreadConstraint { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out := make([]corev1.TopologySpreadConstraint, len(constraints)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i, c := range constraints { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if c.LabelSelector == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| c.LabelSelector = componentSelector(p) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| out[i] = c | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return out | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Suggestion: When
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Important: When Consider returning
Suggested change
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -217,6 +217,11 @@ type InternalPackageManagerSpec struct { | |
| // If unset, product defaults are applied. Setting this replaces the defaults entirely. | ||
| Resources *corev1.ResourceRequirements `json:"resources,omitempty"` | ||
|
|
||
| // TopologySpreadConstraints controls how server pod replicas are spread across topology | ||
| // domains (e.g. node architecture, zone, hostname). Composes with the operator's built-in | ||
| // hostname-keyed soft anti-affinity. | ||
| TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` | ||
|
|
||
| // Deprecated: use envVars instead. If the same variable name is set in both | ||
| // addEnv and envVars, envVars takes precedence: it is rendered after addEnv, | ||
| // and Kubernetes resolves a duplicate env var name to the last occurrence. | ||
|
|
@@ -288,6 +293,11 @@ type InternalConnectSpec struct { | |
| // If unset, product defaults are applied. Setting this replaces the defaults entirely. | ||
| Resources *corev1.ResourceRequirements `json:"resources,omitempty"` | ||
|
|
||
| // TopologySpreadConstraints controls how server pod replicas are spread across topology | ||
| // domains (e.g. node architecture, zone, hostname). Composes with the operator's built-in | ||
| // hostname-keyed soft anti-affinity. | ||
| TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The Same applies to the |
||
|
|
||
| Auth AuthSpec `json:"auth,omitempty"` | ||
|
|
||
| // RegisterOnFirstLogin controls whether new users are automatically registered | ||
|
|
@@ -418,6 +428,11 @@ type InternalWorkbenchSpec struct { | |
| // If unset, product defaults are applied. Setting this replaces the defaults entirely. | ||
| Resources *corev1.ResourceRequirements `json:"resources,omitempty"` | ||
|
|
||
| // TopologySpreadConstraints controls how server pod replicas are spread across topology | ||
| // domains (e.g. node architecture, zone, hostname). Composes with the operator's built-in | ||
| // hostname-keyed soft anti-affinity. Applies only to the server Deployment, not sessions. | ||
| TopologySpreadConstraints []corev1.TopologySpreadConstraint `json:"topologySpreadConstraints,omitempty"` | ||
|
|
||
| // Tolerations that are applied universally to server and sessions | ||
| Tolerations []corev1.Toleration `json:"tolerations,omitempty"` | ||
|
|
||
|
|
||
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
componentSelectorusesMatchExpressions(specificallyIn) rather thanMatchLabels. Both produce equivalent Kubernetes behavior, but the anti-affinity helper directly above usesMatchExpressionsfor the same reason — so this is consistent.One thing to note: the selector is built from
KubernetesLabels()keysapp.kubernetes.io/instanceandposit.team/site. These are the selector labels, so they're stable and correct for pod matching. Looks good.