Skip to content

Controller: Correctly identify other pods on shutdown. #13444

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

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
4 changes: 2 additions & 2 deletions charts/ingress-nginx/Chart.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
annotations:
artifacthub.io/changes: |
- Update Ingress-Nginx version controller-v1.12.2
- Add electionID label to controller pods when leader election is enabled
artifacthub.io/prerelease: "false"
apiVersion: v2
appVersion: 1.12.2
Expand All @@ -20,4 +20,4 @@ maintainers:
name: ingress-nginx
sources:
- https://github.com/kubernetes/ingress-nginx
version: 4.12.2
version: 4.12.3
9 changes: 9 additions & 0 deletions charts/ingress-nginx/changelog/helm-chart-4.12.3.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Changelog

This file documents all notable changes to [ingress-nginx](https://github.com/kubernetes/ingress-nginx) Helm Chart. The release numbering uses [semantic versioning](http://semver.org).

### 4.12.3

* Add electionID label to controller pods when leader election is enabled

**Full Changelog**: https://github.com/kubernetes/ingress-nginx/compare/helm-chart-4.12.2...helm-chart-4.12.3
3 changes: 3 additions & 0 deletions charts/ingress-nginx/templates/controller-daemonset.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ spec:
labels:
{{- include "ingress-nginx.labels" . | nindent 8 }}
app.kubernetes.io/component: controller
{{- if not .Values.controller.disableLeaderElection }}
nginx.ingress.kubernetes.io/electionID: {{ include "ingress-nginx.controller.electionID" . }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure if camel case is the way to go here...

Suggested change
nginx.ingress.kubernetes.io/electionID: {{ include "ingress-nginx.controller.electionID" . }}
nginx.ingress.kubernetes.io/election-id: {{ include "ingress-nginx.controller.electionID" . }}

{{- end }}
{{- with .Values.controller.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
Expand Down
3 changes: 3 additions & 0 deletions charts/ingress-nginx/templates/controller-deployment.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@ spec:
labels:
{{- include "ingress-nginx.labels" . | nindent 8 }}
app.kubernetes.io/component: controller
{{- if not .Values.controller.disableLeaderElection }}
nginx.ingress.kubernetes.io/electionID: {{ include "ingress-nginx.controller.electionID" . }}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here:

Suggested change
nginx.ingress.kubernetes.io/electionID: {{ include "ingress-nginx.controller.electionID" . }}
nginx.ingress.kubernetes.io/election-id: {{ include "ingress-nginx.controller.electionID" . }}

{{- end }}
{{- with .Values.controller.labels }}
{{- toYaml . | nindent 8 }}
{{- end }}
Expand Down
27 changes: 27 additions & 0 deletions charts/ingress-nginx/tests/controller-daemonset_test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -208,3 +208,30 @@ tests:
- equal:
path: spec.template.spec.runtimeClassName
value: myClass

- it: should create a DaemonSet with the electionID label on the pod template when leader election is enabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- it: should create a DaemonSet with the electionID label on the pod template when leader election is enabled
- it: should create a DaemonSet with election ID label

set:
controller.kind: DaemonSet
controller.disableLeaderElection: false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd actually omit explicitly setting this, so the test fails as soon as someone changes the default.

asserts:
- equal:
path: spec.template.metadata.labels.[nginx.ingress.kubernetes.io/electionID]
value: RELEASE-NAME-ingress-nginx-leader

- it: should create a DaemonSet with the custom electionID label on the pod template when controller.electionID is set and leader election is enabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- it: should create a DaemonSet with the custom electionID label on the pod template when controller.electionID is set and leader election is enabled
- it: should create a DaemonSet with custom election ID label if `controller.electionID` is set

set:
controller.kind: DaemonSet
controller.disableLeaderElection: false
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here: I'd actually omit explicitly setting this, so the test fails as soon as someone changes the default.

controller.electionID: custom-election-id
asserts:
- equal:
path: spec.template.metadata.labels.[nginx.ingress.kubernetes.io/electionID]
value: custom-election-id

- it: should create a DaemonSet without the electionID label on the pod template when leader election is disabled
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
- it: should create a DaemonSet without the electionID label on the pod template when leader election is disabled
- it: should create a DaemonSet without election ID label if `controller.disableLeaderElection` is true

set:
controller.kind: DaemonSet
controller.disableLeaderElection: true
asserts:
- notExists:
path: spec.template.metadata.labels.[nginx.ingress.kubernetes.io/electionID]
24 changes: 24 additions & 0 deletions charts/ingress-nginx/tests/controller-deployment_test.yaml
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here as for the DaemonSet tests.

Original file line number Diff line number Diff line change
Expand Up @@ -231,3 +231,27 @@ tests:
- equal:
path: spec.template.spec.runtimeClassName
value: myClass

- it: should create a Deployment with the electionID label on the pod template when leader election is enabled
set:
controller.disableLeaderElection: false
asserts:
- equal:
path: spec.template.metadata.labels.[nginx.ingress.kubernetes.io/electionID]
value: RELEASE-NAME-ingress-nginx-leader

- it: should create a Deployment with the custom electionID label on the pod template when controller.electionID is set and leader election is enabled
set:
controller.disableLeaderElection: false
controller.electionID: custom-election-id
asserts:
- equal:
path: spec.template.metadata.labels.[nginx.ingress.kubernetes.io/electionID]
value: custom-election-id

- it: should create a Deployment without the electionID label on the pod template when leader election is disabled
set:
controller.disableLeaderElection: true
asserts:
- notExists:
path: spec.template.metadata.labels.[nginx.ingress.kubernetes.io/electionID]
2 changes: 2 additions & 0 deletions internal/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,8 @@ type Configuration struct {

DisableSyncEvents bool

UseElectionIDSelectorOnShutdown bool

EnableTopologyAwareRouting bool
}

Expand Down
2 changes: 2 additions & 0 deletions internal/ingress/controller/nginx.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,8 @@
IngressLister: n.store,
UpdateStatusOnShutdown: config.UpdateStatusOnShutdown,
UseNodeInternalIP: config.UseNodeInternalIP,
UseElectionIDSelectorOnShutdown: config.UseElectionIDSelectorOnShutdown,
ElectionID: config.ElectionID,

Check failure on line 156 in internal/ingress/controller/nginx.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (gofmt)
})
} else {
klog.Warning("Update of Ingress status is disabled (flag --update-status)")
Expand Down
59 changes: 41 additions & 18 deletions internal/ingress/status/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,11 @@
"k8s.io/ingress-nginx/pkg/apis/ingress"
)

const (
// ElectionIDLabelKey is the label key used to identify controller pods by election ID
ElectionIDLabelKey = "nginx.ingress.kubernetes.io/electionID"
)

// UpdateInterval defines the time interval, in seconds, in
// which the status should check if an update is required.
var UpdateInterval = 60
Expand Down Expand Up @@ -68,6 +73,10 @@

UseNodeInternalIP bool

UseElectionIDSelectorOnShutdown bool

ElectionID string

IngressLister ingressLister
}

Expand Down Expand Up @@ -175,6 +184,36 @@

// runningAddresses returns a list of IP addresses and/or FQDN where the
// ingress controller is currently running
// listControllerPods returns a list of running pods with controller labels
func (s *statusSync) listControllerPods(useElectionID bool) (*apiv1.PodList, error) {
podLabel := make(map[string]string)

Check failure on line 190 in internal/ingress/status/status.go

View workflow job for this annotation

GitHub Actions / lint

File is not properly formatted (gofmt)
if useElectionID {
// When using electionID, only look for pods with the electionID label
// This is more specific and will correctly identify pods belonging to the same controller group
// Note: This requires the electionID label to be set on the pods (done by helm chart)
podLabel[ElectionIDLabelKey] = s.Config.ElectionID

Check failure on line 195 in internal/ingress/status/status.go

View workflow job for this annotation

GitHub Actions / lint

QF1008: could remove embedded field "Config" from selector (staticcheck)
} else {
// As a standard, app.kubernetes.io are "reserved well-known" labels.
// In our case, we add those labels as identifiers of the Ingress
// deployment in this namespace, so we can select it as a set of Ingress instances.
// As those labels are also generated as part of a HELM deployment, we can be "safe" they
// cover 95% of the cases
for k, v := range k8s.IngressPodDetails.Labels {
// Skip labels that are frequently modified by deployment controllers
if k != "pod-template-hash" && k != "controller-revision-hash" && k != "pod-template-generation" {
podLabel[k] = v
}
}
}

return s.Client.CoreV1().Pods(k8s.IngressPodDetails.Namespace).List(
context.TODO(),
metav1.ListOptions{
LabelSelector: labels.SelectorFromSet(podLabel).String(),
})
}

func (s *statusSync) runningAddresses() ([]v1.IngressLoadBalancerIngress, error) {
if s.PublishStatusAddress != "" {
re := regexp.MustCompile(`,\s*`)
Expand All @@ -191,9 +230,7 @@
}

// get information about all the pods running the ingress controller
pods, err := s.Client.CoreV1().Pods(k8s.IngressPodDetails.Namespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labels.SelectorFromSet(k8s.IngressPodDetails.Labels).String(),
})
pods, err := s.listControllerPods(false)
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -230,21 +267,7 @@
}

func (s *statusSync) isRunningMultiplePods() bool {
// As a standard, app.kubernetes.io are "reserved well-known" labels.
// In our case, we add those labels as identifiers of the Ingress
// deployment in this namespace, so we can select it as a set of Ingress instances.
// As those labels are also generated as part of a HELM deployment, we can be "safe" they
// cover 95% of the cases
podLabel := make(map[string]string)
for k, v := range k8s.IngressPodDetails.Labels {
if k != "pod-template-hash" && k != "controller-revision-hash" && k != "pod-template-generation" {
podLabel[k] = v
}
}

pods, err := s.Client.CoreV1().Pods(k8s.IngressPodDetails.Namespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labels.SelectorFromSet(podLabel).String(),
})
pods, err := s.listControllerPods(s.UseElectionIDSelectorOnShutdown) // Use election ID-compatible labels if configured
if err != nil {
return false
}
Expand Down
Loading
Loading