diff --git a/cmd/nginx-ingress/main.go b/cmd/nginx-ingress/main.go index 544ba5028f..5a9ea2b645 100644 --- a/cmd/nginx-ingress/main.go +++ b/cmd/nginx-ingress/main.go @@ -84,6 +84,9 @@ The external address of the service is used when reporting the status of Ingress leaderElectionEnabled = flag.Bool("enable-leader-election", false, "Enable Leader election to avoid multiple replicas of the controller reporting the status of Ingress resources -- only one replica will report status. See -report-ingress-status flag.") + leaderElectionLockName = flag.String("leader-election-lock-name", "nginx-ingress-leader-election", + `Specifies the name of the ConfigMap, within the same namespace as the controller, used as the lock for leader election. Requires -enable-leader-election.`) + nginxStatusAllowCIDRs = flag.String("nginx-status-allow-cidrs", "127.0.0.1", `Whitelist IPv4 IP/CIDR blocks to allow access to NGINX stub_status or the NGINX Plus API. Separate multiple IP/CIDR by commas.`) nginxStatusPort = flag.Int("nginx-status-port", 8080, @@ -297,6 +300,7 @@ func main() { ControllerNamespace: controllerNamespace, ReportIngressStatus: *reportIngressStatus, IsLeaderElectionEnabled: *leaderElectionEnabled, + LeaderElectionLockName: *leaderElectionLockName, WildcardTLSSecret: *wildcardTLSSecret, ConfigMaps: *nginxConfigMaps, } diff --git a/deployments/helm-chart/Chart.yaml b/deployments/helm-chart/Chart.yaml index 2730f067c0..d0c6e2a235 100644 --- a/deployments/helm-chart/Chart.yaml +++ b/deployments/helm-chart/Chart.yaml @@ -1,5 +1,5 @@ name: nginx-ingress -version: 0.3.5 +version: 0.3.6 appVersion: edge description: NGINX Ingress Controller icon: https://raw.githubusercontent.com/nginxinc/kubernetes-ingress/master/deployments/helm-chart/chart-icon.png diff --git a/deployments/helm-chart/README.md b/deployments/helm-chart/README.md index 15867f282a..0ef56a2534 100644 --- a/deployments/helm-chart/README.md +++ b/deployments/helm-chart/README.md @@ -65,6 +65,7 @@ Parameter | Description | Default `controller.image.repository` | The image repository of the Ingress controller. | nginx/nginx-ingress `controller.image.tag` | The tag of the Ingress controller image. | edge `controller.image.pullPolicy` | The pull policy for the Ingress controller image. | IfNotPresent +`controller.config.name` | The name of the ConfigMap used by the Ingress controller. | nginx-config `controller.config.entries` | The entries of the ConfigMap for customizing NGINX configuration. | {} `controller.defaultTLS.cert` | The base64-encoded TLS certificate for the default HTTPS server. If not specified, a pre-generated self-signed certificate is used. **Note:** It is recommended that you specify your own certificate. | A pre-generated self-signed certificate. `controller.defaultTLS.key` | The base64-encoded TLS key for the default HTTPS server. **Note:** If not specified, a pre-generated key is used. It is recommended that you specify your own key. | A pre-generated key. @@ -102,6 +103,7 @@ Parameter | Description | Default `controller.reportIngressStatus.enable` | Update the address field in the status of Ingresses resources with an external address of the Ingress controller. You must also specify the source of the external address either through an external service via `controller.reportIngressStatus.externalService` or the `external-status-address` entry in the ConfigMap via `controller.config.entries`. **Note:** `controller.config.entries.external-status-address` takes precedence if both are set. | true `controller.reportIngressStatus.externalService` | Specifies the name of the service with the type LoadBalancer through which the Ingress controller is exposed externally. The external address of the service is used when reporting the status of Ingress resources. `controller.reportIngressStatus.enable` must be set to `true`. | nginx-ingress `controller.reportIngressStatus.enableLeaderElection` | Enable Leader election to avoid multiple replicas of the controller reporting the status of Ingress resources. `controller.reportIngressStatus.enable` must be set to `true`. | true +`controller.reportIngressStatus.leaderElectionLockName` | Specifies the name of the ConfigMap, within the same namespace as the controller, used as the lock for leader election. controller.reportIngressStatus.enableLeaderElection must be set to true. | nginx-ingress-leader-election `rbac.create` | Configures RBAC. | true `prometheus.create` | Expose NGINX or NGINX Plus metrics in the Prometheus format. | false `prometheus.port` | Configures the port to scrape the metrics. | 9113 diff --git a/deployments/helm-chart/templates/controller-configmap.yaml b/deployments/helm-chart/templates/controller-configmap.yaml index bbcc1f1228..bbf8495d8d 100644 --- a/deployments/helm-chart/templates/controller-configmap.yaml +++ b/deployments/helm-chart/templates/controller-configmap.yaml @@ -1,7 +1,7 @@ apiVersion: v1 kind: ConfigMap metadata: - name: nginx-config + name: {{ .Values.controller.config.name }} labels: {{- include "nginx-ingress.labels" . | nindent 4 }} data: diff --git a/deployments/helm-chart/templates/controller-deployment.yaml b/deployments/helm-chart/templates/controller-deployment.yaml index 674ce92f1a..b3ece9fdf4 100644 --- a/deployments/helm-chart/templates/controller-deployment.yaml +++ b/deployments/helm-chart/templates/controller-deployment.yaml @@ -58,7 +58,7 @@ spec: fieldPath: metadata.name args: - -nginx-plus={{ .Values.controller.nginxplus }} - - -nginx-configmaps=$(POD_NAMESPACE)/nginx-config + - -nginx-configmaps=$(POD_NAMESPACE)/{{ .Values.controller.config.name }} {{- if .Values.controller.defaultTLS.secret }} - -default-server-tls-secret={{ .Values.controller.defaultTLS.secret }} {{ else }} @@ -80,6 +80,7 @@ spec: - -report-ingress-status - -external-service={{ .Values.controller.reportIngressStatus.externalService }} - -enable-leader-election={{ .Values.controller.reportIngressStatus.enableLeaderElection }} + - -leader-election-lock-name={{ .Values.controller.reportIngressStatus.leaderElectionLockName }} {{- end }} {{- if .Values.controller.wildcardTLS.secret }} - -wildcard-tls-secret={{ .Values.controller.wildcardTLS.secret }} @@ -88,4 +89,4 @@ spec: {{- end }} - -enable-prometheus-metrics={{ .Values.prometheus.create }} - -prometheus-metrics-listen-port={{ .Values.prometheus.port }} -{{- end }} \ No newline at end of file +{{- end }} diff --git a/deployments/helm-chart/values.yaml b/deployments/helm-chart/values.yaml index 432fcbcf13..25d43bf1ed 100644 --- a/deployments/helm-chart/values.yaml +++ b/deployments/helm-chart/values.yaml @@ -25,6 +25,9 @@ controller: pullPolicy: IfNotPresent config: + ## The name of the ConfigMap used by the Ingress controller. + name: nginx-config + ## The entries of the ConfigMap for customizing NGINX configuration. entries: {} @@ -155,6 +158,9 @@ controller: ## Enable Leader election to avoid multiple replicas of the controller reporting the status of Ingress resources. controller.reportIngressStatus.enable must be set to true. enableLeaderElection: true + ## Specifies the name of the ConfigMap, within the same namespace as the controller, used as the lock for leader election. controller.reportIngressStatus.enableLeaderElection must be set to true. + leaderElectionLockName: "nginx-ingress-leader-election" + rbac: ## Configures RBAC. create: true @@ -164,4 +170,4 @@ prometheus: create: true ## Configures the port to scrape the metrics. - port: 9113 \ No newline at end of file + port: 9113 diff --git a/docs/cli-arguments.md b/docs/cli-arguments.md index 8303af3e6f..ea2626fd1c 100644 --- a/docs/cli-arguments.md +++ b/docs/cli-arguments.md @@ -29,6 +29,8 @@ Usage of ./nginx-ingress: -ingress-template-path string Path to the ingress NGINX configuration template for an ingress resource. (default for NGINX "nginx.ingress.tmpl"; default for NGINX Plus "nginx-plus.ingress.tmpl") + -leader-election-lock-name + Specifies the name of the ConfigMap, within the same namespace as the controller, used as the lock for leader election. Requires -enable-leader-election. -log_backtrace_at value when logging hits line file:N, emit a stack trace -log_dir string diff --git a/docs/report-ingress-status.md b/docs/report-ingress-status.md index 88b2b64509..240efe68a6 100644 --- a/docs/report-ingress-status.md +++ b/docs/report-ingress-status.md @@ -17,5 +17,6 @@ The Ingress controller must be configured to report an Ingress status: 2. A Service of the type LoadBalancer configured with an external IP or address and specified by the `-external-service` command-line flag. 3. If you're running multiple replicas of the Ingress controller, enable leader election with the `-enable-leader-election` flag to ensure that only one replica updates an Ingress status. +4. By default, the Ingress controller will use a ConfigMap with the name `nginx-ingress-leader-election` as the lock. This can be customised via the `-leader-election-lock-name` flag. Notes: The Ingress controller does not clear the status of Ingress resources when it is being shut down. diff --git a/internal/k8s/controller.go b/internal/k8s/controller.go index f3ccfd910d..cac9ce8198 100644 --- a/internal/k8s/controller.go +++ b/internal/k8s/controller.go @@ -74,6 +74,7 @@ type LoadBalancerController struct { leaderElector *leaderelection.LeaderElector reportIngressStatus bool isLeaderElectionEnabled bool + leaderElectionLockName string resync time.Duration namespace string controllerNamespace string @@ -96,6 +97,7 @@ type NewLoadBalancerControllerInput struct { ControllerNamespace string ReportIngressStatus bool IsLeaderElectionEnabled bool + LeaderElectionLockName string WildcardTLSSecret string ConfigMaps string } @@ -111,6 +113,7 @@ func NewLoadBalancerController(input NewLoadBalancerControllerInput) *LoadBalanc useIngressClassOnly: input.UseIngressClassOnly, reportIngressStatus: input.ReportIngressStatus, isLeaderElectionEnabled: input.IsLeaderElectionEnabled, + leaderElectionLockName: input.LeaderElectionLockName, resync: input.ResyncPeriod, namespace: input.Namespace, controllerNamespace: input.ControllerNamespace, @@ -168,7 +171,7 @@ func (lbc *LoadBalancerController) UpdateManagedAndMergeableIngresses(ingresses // addLeaderHandler adds the handler for leader election to the controller func (lbc *LoadBalancerController) addLeaderHandler(leaderHandler leaderelection.LeaderCallbacks) { var err error - lbc.leaderElector, err = newLeaderElector(lbc.client, leaderHandler, lbc.controllerNamespace) + lbc.leaderElector, err = newLeaderElector(lbc.client, leaderHandler, lbc.controllerNamespace, lbc.leaderElectionLockName) if err != nil { glog.V(3).Infof("Error starting LeaderElection: %v", err) } diff --git a/internal/k8s/leader.go b/internal/k8s/leader.go index 3b5e300e65..6ac75cb4ec 100644 --- a/internal/k8s/leader.go +++ b/internal/k8s/leader.go @@ -17,7 +17,7 @@ import ( ) // newLeaderElector creates a new LeaderElection and returns the Elector. -func newLeaderElector(client kubernetes.Interface, callbacks leaderelection.LeaderCallbacks, namespace string) (*leaderelection.LeaderElector, error) { +func newLeaderElector(client kubernetes.Interface, callbacks leaderelection.LeaderCallbacks, namespace string, lockName string) (*leaderelection.LeaderElector, error) { podName := os.Getenv("POD_NAME") broadcaster := record.NewBroadcaster() @@ -27,7 +27,7 @@ func newLeaderElector(client kubernetes.Interface, callbacks leaderelection.Lead recorder := broadcaster.NewRecorder(scheme.Scheme, source) lock := resourcelock.ConfigMapLock{ - ConfigMapMeta: metav1.ObjectMeta{Namespace: namespace, Name: "leader-election"}, + ConfigMapMeta: metav1.ObjectMeta{Namespace: namespace, Name: lockName}, Client: client.CoreV1(), LockConfig: resourcelock.ResourceLockConfig{ Identity: podName,