diff --git a/Makefile b/Makefile index e593a0a82..7c65b4251 100644 --- a/Makefile +++ b/Makefile @@ -232,11 +232,15 @@ dep-ensure: check-go-version ## Update and vendo go dependencies. .PHONY: dev-env dev-env: check-go-version ## Starts a local Kubernetes cluster using minikube, building and deploying the ingress controller. - @DIND_TASKS=0 USE_DOCKER=false build/dev-env.sh + @build/dev-env.sh .PHONY: live-docs live-docs: ## Build and launch a local copy of the documentation website in http://localhost:3000 - @docker build --pull -t ingress-nginx/mkdocs images/mkdocs + @docker buildx build \ + --pull \ + --load \ + --progress plain \ + -t ingress-nginx/mkdocs images/mkdocs @docker run --rm -it -p 3000:3000 -v ${PWD}:/docs ingress-nginx/mkdocs .PHONY: build-docs diff --git a/build/dev-env.sh b/build/dev-env.sh index e535af5c4..c4ee3fbe2 100755 --- a/build/dev-env.sh +++ b/build/dev-env.sh @@ -22,10 +22,7 @@ set -o errexit set -o nounset set -o pipefail -NAMESPACE="${NAMESPACE:-ingress-nginx}" -echo "NAMESPACE is set to ${NAMESPACE}" - -kubectl config use-context minikube +DIR=$(cd $(dirname "${BASH_SOURCE}") && pwd -P) export TAG=dev export ARCH=amd64 @@ -33,46 +30,77 @@ export REGISTRY=${REGISTRY:-ingress-controller} DEV_IMAGE=${REGISTRY}/nginx-ingress-controller:${TAG} -{ [ "$(minikube status | grep -c Running)" -ge 2 ] && minikube status | grep -qE ': Configured$|Correctly Configured'; } \ - || minikube start \ - --extra-config=kubelet.sync-frequency=1s \ - --extra-config=apiserver.authorization-mode=RBAC +if ! command -v kind &> /dev/null; then + echo "kind is not installed" + echo "Use a package manager or visit the official site https://kind.sigs.k8s.io" + exit 1 +fi -# shellcheck disable=SC2046 -eval $(minikube docker-env --shell bash) +if ! command -v kubectl &> /dev/null; then + echo "Please install kubectl 1.15 or higher" + exit 1 +fi + +KUBE_CLIENT_VERSION=$(kubectl version --client --short | awk '{print $3}' | cut -d. -f2) || true +if [[ ${KUBE_CLIENT_VERSION} -lt 14 ]]; then + echo "Please update kubectl to 1.15 or higher" + exit 1 +fi echo "[dev-env] building container" make build container docker tag "${REGISTRY}/nginx-ingress-controller-${ARCH}:${TAG}" "${DEV_IMAGE}" -# kubectl >= 1.14 includes Kustomize via "apply -k". Makes it easier to use on Linux as well, assuming kubectl installed -KUBE_CLIENT_VERSION=$(kubectl version --client --short | awk '{print $3}' | cut -d. -f2) || true -if [[ ${KUBE_CLIENT_VERSION} -lt 14 ]]; then - for tool in kubectl kustomize; do - echo "[dev-env] installing $tool" - $tool version || brew install $tool - done -fi +export K8S_VERSION=${K8S_VERSION:-v1.17.2@sha256:59df31fc61d1da5f46e8a61ef612fa53d3f9140f82419d1ef1a6b9656c6b737c} -if ! kubectl get namespace "${NAMESPACE}"; then - kubectl create namespace "${NAMESPACE}" -fi +export DOCKER_CLI_EXPERIMENTAL=enabled -kubectl get deploy nginx-ingress-controller -n "${NAMESPACE}" && kubectl delete deploy nginx-ingress-controller -n "${NAMESPACE}" +KIND_CLUSTER_NAME="ingress-nginx-dev" -ROOT=./deploy/minikube - -if [[ ${KUBE_CLIENT_VERSION} -lt 14 ]]; then - pushd $ROOT - kustomize edit set namespace "${NAMESPACE}" - kustomize edit set image "quay.io/kubernetes-ingress-controller/nginx-ingress-controller=${DEV_IMAGE}" - popd - - echo "[dev-env] deploying NGINX Ingress controller in namespace $NAMESPACE" - kustomize build $ROOT | kubectl apply -f - +if ! kind get clusters -q | grep -q ${KIND_CLUSTER_NAME}; then +echo "[dev-env] creating Kubernetes cluster with kind" +cat <:port". If not provided, no admission controller is starte streamPort = flags.Int("stream-port", 10247, "Port to use for the lua TCP/UDP endpoint configuration.") profilerPort = flags.Int("profiler-port", 10245, "Port to use for expose the ingress controller Go profiler when it is enabled.") + + statusUpdateInterval = flags.Int("status-update-interval", status.UpdateInterval, "Time interval in seconds in which the status should check if an update is required. Default is 60 seconds") ) flags.MarkDeprecated("force-namespace-isolation", `This flag doesn't do anything.`) @@ -201,6 +204,13 @@ https://blog.maxmind.com/2019/12/18/significant-changes-to-accessing-and-using-g return true, nil, nil } + if *statusUpdateInterval < 5 { + klog.Warningf("The defined time to update the Ingress status too low (%v seconds). Adjusting to 5 seconds", *statusUpdateInterval) + status.UpdateInterval = 5 + } else { + status.UpdateInterval = *statusUpdateInterval + } + if *ingressClass != "" { klog.Infof("Watching for Ingress class: %s", *ingressClass) diff --git a/deploy/grafana/dashboards/screenshot.png b/deploy/grafana/dashboards/screenshot.png index bc5ad3b19..e0f52b21b 100644 Binary files a/deploy/grafana/dashboards/screenshot.png and b/deploy/grafana/dashboards/screenshot.png differ diff --git a/deploy/minikube/kustomization.yaml b/deploy/kind/kustomization.yaml similarity index 82% rename from deploy/minikube/kustomization.yaml rename to deploy/kind/kustomization.yaml index 5f857e6e1..8230fce40 100644 --- a/deploy/minikube/kustomization.yaml +++ b/deploy/kind/kustomization.yaml @@ -7,3 +7,5 @@ bases: images: - name: quay.io/kubernetes-ingress-controller/nginx-ingress-controller newTag: dev +patchesStrategicMerge: +- service-hostport.yaml diff --git a/deploy/kind/service-hostport.yaml b/deploy/kind/service-hostport.yaml new file mode 100644 index 000000000..ff0601cc1 --- /dev/null +++ b/deploy/kind/service-hostport.yaml @@ -0,0 +1,25 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + name: nginx-ingress-controller +spec: + replicas: 1 + template: + metadata: + annotations: + prometheus.io/port: "10254" + prometheus.io/scrape: "true" + spec: + containers: + - name: nginx-ingress-controller + ports: + - containerPort: 80 + hostPort: 80 + - containerPort: 443 + hostPort: 443 + nodeSelector: + ingress-ready: "true" + tolerations: + - key: node-role.kubernetes.io/master + operator: Equal + effect: NoSchedule diff --git a/docs/deploy/index.md b/docs/deploy/index.md index fc99c39e5..78f7506cf 100644 --- a/docs/deploy/index.md +++ b/docs/deploy/index.md @@ -78,7 +78,6 @@ minikube addons disable ingress ```console $ kubectl get pods -n ingress-nginx NAME READY STATUS RESTARTS AGE -default-http-backend-66b447d9cf-rrlf9 1/1 Running 0 12s nginx-ingress-controller-fdcdcd6dd-vvpgs 1/1 Running 0 11s ``` diff --git a/docs/development.md b/docs/development.md index 9a032ebbd..34ed3f777 100644 --- a/docs/development.md +++ b/docs/development.md @@ -19,11 +19,6 @@ cd ingress-nginx ### Initial developer environment build ->**Prequisites**: Minikube must be installed. -See [releases](https://github.com/kubernetes/minikube/releases) for installation instructions. - -If you are using **MacOS** and deploying to **minikube**, the following command will build the local nginx controller container image and deploy the ingress controller onto a minikube cluster with RBAC enabled in the namespace `ingress-nginx`: - ``` $ make dev-env ``` diff --git a/docs/examples/customization/custom-errors/README.md b/docs/examples/customization/custom-errors/README.md index 49393f658..a6a1d5aca 100644 --- a/docs/examples/customization/custom-errors/README.md +++ b/docs/examples/customization/custom-errors/README.md @@ -40,7 +40,7 @@ If you do not already have an instance of the NGINX Ingress controller running, ingress-nginx ClusterIP 10.0.0.13 80/TCP,443/TCP 10m ``` -!!! Note +!!! note The `ingress-nginx` Service is of type `ClusterIP` in this example. This may vary depending on your environment. Make sure you can use the Service to reach NGINX before proceeding with the rest of this example. diff --git a/docs/examples/docker-registry/README.md b/docs/examples/docker-registry/README.md index 7dbd20cbd..495297a84 100644 --- a/docs/examples/docker-registry/README.md +++ b/docs/examples/docker-registry/README.md @@ -26,9 +26,9 @@ wget https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/docs/exam ``` !!! Important - Running a docker registry without TLS requires we configure our local docker daemon with the insecure registry flag. + Running a docker registry without TLS requires we configure our local docker daemon with the insecure registry flag. - Please check [deploy a plain http registry](https://docs.docker.com/registry/insecure/#deploy-a-plain-http-registry) +Please check [deploy a plain http registry](https://docs.docker.com/registry/insecure/#deploy-a-plain-http-registry) ### With TLS diff --git a/docs/examples/grpc/app.yaml b/docs/examples/grpc/app.yaml index 3c04033e0..acc4060d0 100644 --- a/docs/examples/grpc/app.yaml +++ b/docs/examples/grpc/app.yaml @@ -7,6 +7,9 @@ metadata: namespace: default spec: replicas: 1 + selector: + matchLabels: + k8s-app: fortune-teller-app template: metadata: labels: diff --git a/docs/images/baremetal/baremetal_overview.jpg b/docs/images/baremetal/baremetal_overview.jpg index ecf19d551..322a88246 100644 Binary files a/docs/images/baremetal/baremetal_overview.jpg and b/docs/images/baremetal/baremetal_overview.jpg differ diff --git a/docs/images/baremetal/cloud_overview.jpg b/docs/images/baremetal/cloud_overview.jpg index ec8830e88..3af770785 100644 Binary files a/docs/images/baremetal/cloud_overview.jpg and b/docs/images/baremetal/cloud_overview.jpg differ diff --git a/docs/images/baremetal/hostnetwork.jpg b/docs/images/baremetal/hostnetwork.jpg index f86dc4a62..455cb2038 100644 Binary files a/docs/images/baremetal/hostnetwork.jpg and b/docs/images/baremetal/hostnetwork.jpg differ diff --git a/docs/images/baremetal/metallb.jpg b/docs/images/baremetal/metallb.jpg index 28dad6dea..9ea03dc29 100644 Binary files a/docs/images/baremetal/metallb.jpg and b/docs/images/baremetal/metallb.jpg differ diff --git a/docs/images/baremetal/nodeport.jpg b/docs/images/baremetal/nodeport.jpg index 012f53383..504d052a2 100644 Binary files a/docs/images/baremetal/nodeport.jpg and b/docs/images/baremetal/nodeport.jpg differ diff --git a/docs/images/baremetal/user_edge.jpg b/docs/images/baremetal/user_edge.jpg index f1165f5cc..ac18241d9 100644 Binary files a/docs/images/baremetal/user_edge.jpg and b/docs/images/baremetal/user_edge.jpg differ diff --git a/docs/images/elb-l7-listener.png b/docs/images/elb-l7-listener.png index 006c69871..472b96ae1 100644 Binary files a/docs/images/elb-l7-listener.png and b/docs/images/elb-l7-listener.png differ diff --git a/docs/images/grafana.png b/docs/images/grafana.png index 662a9878a..a11ea40aa 100644 Binary files a/docs/images/grafana.png and b/docs/images/grafana.png differ diff --git a/docs/images/jaeger-demo.png b/docs/images/jaeger-demo.png index 3a3e31536..4b1cbea2a 100644 Binary files a/docs/images/jaeger-demo.png and b/docs/images/jaeger-demo.png differ diff --git a/docs/images/prometheus-dashboard.png b/docs/images/prometheus-dashboard.png index 5de60fafd..3c8fa4fa2 100644 Binary files a/docs/images/prometheus-dashboard.png and b/docs/images/prometheus-dashboard.png differ diff --git a/docs/images/zipkin-demo.png b/docs/images/zipkin-demo.png index 8b5970b72..767767869 100644 Binary files a/docs/images/zipkin-demo.png and b/docs/images/zipkin-demo.png differ diff --git a/docs/user-guide/cli-arguments.md b/docs/user-guide/cli-arguments.md index 7489cd6b2..4dfa612f1 100644 --- a/docs/user-guide/cli-arguments.md +++ b/docs/user-guide/cli-arguments.md @@ -44,6 +44,7 @@ They are set in the container spec of the `nginx-ingress-controller` Deployment | `--udp-services-configmap string` | Name of the ConfigMap containing the definition of the UDP services to expose. The key in the map indicates the external port to be used. The value is a reference to a Service in the form "namespace/name:port", where "port" can either be a port name or number. | | `--update-status` | Update the load-balancer status of Ingress objects this controller satisfies. Requires setting the publish-service parameter to a valid Service reference. (default true) | | `--update-status-on-shutdown` | Update the load-balancer status of Ingress objects when the controller shuts down. Requires the update-status parameter. (default true) | +| `--status-update-interval` | Time interval in seconds in which the status should check if an update is required. (default 60 seconds) | | `-v`, `--v Level` | log level for V logs | | `--version` | Show release information about the NGINX Ingress controller and exit. | | `--vmodule moduleSpec` | comma-separated list of pattern=N settings for file-filtered logging | diff --git a/docs/user-guide/fcgi-services.md b/docs/user-guide/fcgi-services.md index 5d2140813..7c9dd6138 100644 --- a/docs/user-guide/fcgi-services.md +++ b/docs/user-guide/fcgi-services.md @@ -79,15 +79,13 @@ spec: servicePort: fastcgi ``` -## The FastCGI Ingress Annotations +## FastCGI Ingress Annotations -### The `nginx.ingress.kubernetes.io/backend-protocol` Annotation - -To enable FastCGI, the `backend-protocol` annotation needs to be set to `FCGI`, which overrides the default `HTTP` value. +To enable FastCGI, the `nginx.ingress.kubernetes.io/backend-protocol` annotation needs to be set to `FCGI`, which overrides the default `HTTP` value. > `nginx.ingress.kubernetes.io/backend-protocol: "FCGI"` -This enables the _FastCGI_ mode for the whole _Ingress_ object. +**This enables the _FastCGI_ mode for all paths defined in the _Ingress_ object** ### The `nginx.ingress.kubernetes.io/fastcgi-index` Annotation diff --git a/docs/user-guide/ingress-path-matching.md b/docs/user-guide/ingress-path-matching.md index 0c6d3aea3..9fc9c2a3a 100644 --- a/docs/user-guide/ingress-path-matching.md +++ b/docs/user-guide/ingress-path-matching.md @@ -9,8 +9,8 @@ The ingress controller supports **case insensitive** regular expressions in the This can be enabled by setting the `nginx.ingress.kubernetes.io/use-regex` annotation to `true` (the default is false). !!! hint -Kubernetes only accept expressions that comply with the RE2 engine syntax. It is possible that valid expressions accepted by NGINX cannot be used with ingress-nginx, because the PCRE library (used in NGINX) supports a wider syntax than RE2. -See the [RE2 Syntax](https://github.com/google/re2/wiki/Syntax) documentation for differences. + Kubernetes only accept expressions that comply with the RE2 engine syntax. It is possible that valid expressions accepted by NGINX cannot be used with ingress-nginx, because the PCRE library (used in NGINX) supports a wider syntax than RE2. + See the [RE2 Syntax](https://github.com/google/re2/wiki/Syntax) documentation for differences. See the [description](./nginx-configuration/annotations.md#use-regex) of the `use-regex` annotation for more details. diff --git a/docs/user-guide/nginx-configuration/annotations.md b/docs/user-guide/nginx-configuration/annotations.md index 109a5cc3f..727cc5f65 100755 --- a/docs/user-guide/nginx-configuration/annotations.md +++ b/docs/user-guide/nginx-configuration/annotations.md @@ -171,7 +171,7 @@ If you use the ``cookie`` affinity type you can also specify the name of the coo The NGINX annotation `nginx.ingress.kubernetes.io/session-cookie-path` defines the path that will be set on the cookie. This is optional unless the annotation `nginx.ingress.kubernetes.io/use-regex` is set to true; Session cookie paths do not support regex. -Use `nginx.ingress.kubernetes.io/session-cookie-samesite` to apply a `SameSite` attribute to the sticky cookie. Browser accepted values are `None`, `Lax`, and `Strict`. Some older browsers reject cookies with the more-recently-defined `SameSite=None`. To omit `SameSite=None` from these older browsers, add the annotation `nginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none: "true"`. +Use `nginx.ingress.kubernetes.io/session-cookie-samesite` to apply a `SameSite` attribute to the sticky cookie. Browser accepted values are `None`, `Lax`, and `Strict`. Some browsers reject cookies with `SameSite=None`, including those created before the `SameSite=None` specification (e.g. Chrome 5X). Other browsers mistakenly treat `SameSite=None` cookies as `SameSite=Strict` (e.g. Safari running on OSX 14). To omit `SameSite=None` from browsers with these incompatibilities, add the annotation `nginx.ingress.kubernetes.io/session-cookie-conditional-samesite-none: "true"`. ### Authentication @@ -352,7 +352,7 @@ Enables automatic conversion of preload links specified in the “Link” respon Allows the definition of one or more aliases in the server definition of the NGINX configuration using the annotation `nginx.ingress.kubernetes.io/server-alias: ","`. This will create a server with the same configuration, but adding new values to the `server_name` directive. -!!! Note +!!! note A server-alias name cannot conflict with the hostname of an existing server. If it does, the server-alias annotation will be ignored. If a server-alias is created and later a new server with the same hostname is created, the new server configuration will take place over the alias configuration. @@ -446,7 +446,8 @@ By default the controller redirects all requests to an existing service that pro `nginx.ingress.kubernetes.io/enable-global-auth`: indicates if GlobalExternalAuth configuration should be applied or not to this Ingress rule. Default values is set to `"true"`. -!!! note For more information please see [global-auth-url](./configmap.md#global-auth-url). +!!! note + For more information please see [global-auth-url](./configmap.md#global-auth-url). ### Rate limiting @@ -837,7 +838,7 @@ nginx.ingress.kubernetes.io/backend-protocol: "HTTPS" ### Use Regex !!! attention -When using this annotation with the NGINX annotation `nginx.ingress.kubernetes.io/affinity` of type `cookie`, `nginx.ingress.kubernetes.io/session-cookie-path` must be also set; Session cookie paths do not support regex. + When using this annotation with the NGINX annotation `nginx.ingress.kubernetes.io/affinity` of type `cookie`, `nginx.ingress.kubernetes.io/session-cookie-path` must be also set; Session cookie paths do not support regex. Using the `nginx.ingress.kubernetes.io/use-regex` annotation will indicate whether or not the paths defined on an Ingress use regular expressions. The default value is `false`. @@ -885,4 +886,4 @@ nginx.ingress.kubernetes.io/mirror-request-body: "off" The request sent to the mirror is linked to the orignial request. If you have a slow mirror backend, then the orignial request will throttle. -For more information on the mirror module see https://nginx.org/en/docs/http/ngx_http_mirror_module.html +For more information on the mirror module see [ngx_http_mirror_module](https://nginx.org/en/docs/http/ngx_http_mirror_module.html) diff --git a/docs/user-guide/nginx-configuration/configmap.md b/docs/user-guide/nginx-configuration/configmap.md index e374a7f69..e4d30529a 100755 --- a/docs/user-guide/nginx-configuration/configmap.md +++ b/docs/user-guide/nginx-configuration/configmap.md @@ -14,7 +14,7 @@ data: ssl-protocols: SSLv2 ``` -!!! Important +!!! important The key and values in a ConfigMap can only be strings. This means that we want a value with boolean values we need to quote the values, like "true" or "false". Same for numbers, like "100". @@ -567,7 +567,7 @@ Since `0.27.0` and due to a [change in the MaxMind databases](https://blog.maxmi For this reason, it is required to define a new flag `--maxmind-license-key` in the ingress controller deployment to download the databases needed during the initialization of the ingress controller. Alternatively, it is possible to use a volume to mount the files `/etc/nginx/geoip/GeoLite2-City.mmdb` and `/etc/nginx/geoip/GeoLite2-ASN.mmdb`, avoiding the overhead of the download. -!!! Important +!!! important If the feature is enabled but the files are missing, GeoIP2 will not be enabled. _**default:**_ false diff --git a/docs/user-guide/third-party-addons/opentracing.md b/docs/user-guide/third-party-addons/opentracing.md index ca7dc9890..0ced23000 100644 --- a/docs/user-guide/third-party-addons/opentracing.md +++ b/docs/user-guide/third-party-addons/opentracing.md @@ -100,8 +100,7 @@ All these options (including host) allow environment variables, such as `$HOSTNA ## Examples -The following examples show how to deploy and test different distributed tracing systems. These example can be performed -using Minikube. +The following examples show how to deploy and test different distributed tracing systems. These example can be performed using Minikube. ### Zipkin diff --git a/docs/user-guide/tls.md b/docs/user-guide/tls.md index d28dcc6c4..e4764de67 100644 --- a/docs/user-guide/tls.md +++ b/docs/user-guide/tls.md @@ -78,7 +78,6 @@ or per-Ingress with the `nginx.ingress.kubernetes.io/ssl-redirect: "false"` annotation in the particular resource. !!! tip - When using SSL offloading outside of cluster (e.g. AWS ELB) it may be useful to enforce a redirect to HTTPS even when there is no TLS certificate available. This can be achieved by using the `nginx.ingress.kubernetes.io/force-ssl-redirect: "true"` diff --git a/internal/ingress/annotations/authreq/main.go b/internal/ingress/annotations/authreq/main.go index 12d232b27..48f3a81e9 100644 --- a/internal/ingress/annotations/authreq/main.go +++ b/internal/ingress/annotations/authreq/main.go @@ -218,8 +218,8 @@ func (a authReq) Parse(ing *networking.Ingress) (interface{}, error) { return nil, ing_errors.NewLocationDenied(fmt.Sprintf("unable to find configMap %q", proxySetHeaderMap)) } - for header, value := range proxySetHeadersMapContents.Data { - if !ValidHeader(header) || !ValidHeader(value) { + for header := range proxySetHeadersMapContents.Data { + if !ValidHeader(header) { return nil, ing_errors.NewLocationDenied("invalid proxy-set-headers in configmap") } } diff --git a/internal/ingress/annotations/authreq/main_test.go b/internal/ingress/annotations/authreq/main_test.go index c57344e19..914b6882a 100644 --- a/internal/ingress/annotations/authreq/main_test.go +++ b/internal/ingress/annotations/authreq/main_test.go @@ -276,8 +276,8 @@ func TestProxySetHeaders(t *testing.T) { }{ {"single header", "http://goog.url", map[string]string{"header": "h1"}, false}, {"no header map", "http://goog.url", nil, true}, - {"header with spaces", "http://goog.url", map[string]string{"header": "bad value"}, true}, - {"header with other bad symbols", "http://goog.url", map[string]string{"header": "bad+value"}, true}, + {"header with spaces", "http://goog.url", map[string]string{"header": "bad value"}, false}, + {"header with other bad symbols", "http://goog.url", map[string]string{"header": "bad+value"}, false}, } for _, test := range tests { diff --git a/internal/ingress/annotations/mirror/main.go b/internal/ingress/annotations/mirror/main.go index dcd6244be..b2591347e 100644 --- a/internal/ingress/annotations/mirror/main.go +++ b/internal/ingress/annotations/mirror/main.go @@ -82,6 +82,7 @@ func (a mirror) Parse(ing *networking.Ingress) (interface{}, error) { config.Target, err = parser.GetStringAnnotation("mirror-target", ing) if err != nil { config.Target = "" + config.Source = "" } return config, nil diff --git a/internal/ingress/annotations/mirror/main_test.go b/internal/ingress/annotations/mirror/main_test.go index 3712a0a11..1ecaef3b9 100644 --- a/internal/ingress/annotations/mirror/main_test.go +++ b/internal/ingress/annotations/mirror/main_test.go @@ -47,7 +47,7 @@ func TestParse(t *testing.T) { Target: "https://test.env.com/$request_uri", }}, {map[string]string{requestBody: "off"}, &Config{ - Source: ngxURI, + Source: "", RequestBody: "off", Target: "", }}, diff --git a/internal/ingress/controller/store/store.go b/internal/ingress/controller/store/store.go index f2a944cbf..c7b6eba8e 100644 --- a/internal/ingress/controller/store/store.go +++ b/internal/ingress/controller/store/store.go @@ -535,18 +535,39 @@ func New( AddFunc: func(obj interface{}) { cm := obj.(*corev1.ConfigMap) key := k8s.MetaNamespaceKey(cm) + + triggerUpdate := false + // updates to configuration configmaps can trigger an update if changeTriggerUpdate(key) { recorder.Eventf(cm, corev1.EventTypeNormal, "CREATE", fmt.Sprintf("ConfigMap %v", key)) - + triggerUpdate = true if key == configmap { store.setConfig(cm) } } - updateCh.In() <- Event{ - Type: ConfigurationEvent, - Obj: obj, + ings := store.listers.IngressWithAnnotation.List() + for _, ingKey := range ings { + key := k8s.MetaNamespaceKey(ingKey) + ing, err := store.getIngress(key) + if err != nil { + klog.Errorf("could not find Ingress %v in local store: %v", key, err) + continue + } + + if parser.AnnotationsReferencesConfigmap(ing) { + recorder.Eventf(cm, corev1.EventTypeNormal, "CREATE", fmt.Sprintf("ConfigMap %v", key)) + store.syncIngress(ing) + triggerUpdate = true + } + } + + if triggerUpdate { + updateCh.In() <- Event{ + Type: ConfigurationEvent, + Obj: obj, + } } }, UpdateFunc: func(old, cur interface{}) { diff --git a/internal/ingress/controller/template/template.go b/internal/ingress/controller/template/template.go index 3ffe91cb1..7939565c3 100644 --- a/internal/ingress/controller/template/template.go +++ b/internal/ingress/controller/template/template.go @@ -275,6 +275,7 @@ func configForLua(input interface{}) string { return fmt.Sprintf(`{ use_forwarded_headers = %t, + use_proxy_protocol = %t, is_ssl_passthrough_enabled = %t, http_redirect_code = %v, listen_ports = { ssl_proxy = "%v", https = "%v" }, @@ -285,6 +286,7 @@ func configForLua(input interface{}) string { hsts_preload = %t, }`, all.Cfg.UseForwardedHeaders, + all.Cfg.UseProxyProtocol, all.IsSSLPassthroughEnabled, all.Cfg.HTTPRedirectCode, all.ListenPorts.SSLProxy, diff --git a/internal/ingress/status/status.go b/internal/ingress/status/status.go index 2c23c9912..60c5fdaf3 100644 --- a/internal/ingress/status/status.go +++ b/internal/ingress/status/status.go @@ -40,9 +40,9 @@ import ( "k8s.io/ingress-nginx/internal/task" ) -const ( - updateInterval = 60 * time.Second -) +// UpdateInterval defines the time interval, in seconds, in +// which the status should check if an update is required. +var UpdateInterval = 60 // Syncer ... type Syncer interface { @@ -98,7 +98,7 @@ func (s statusSync) Run(stopCh chan struct{}) { // when this instance is the leader we need to enqueue // an item to trigger the update of the Ingress status. - wait.PollUntil(updateInterval, func() (bool, error) { + wait.PollUntil(time.Duration(UpdateInterval)*time.Second, func() (bool, error) { s.syncQueue.EnqueueTask(task.GetDummyObject("sync status")) return false, nil }, stopCh) diff --git a/labels.yaml b/labels.yaml deleted file mode 100644 index cc5968c87..000000000 --- a/labels.yaml +++ /dev/null @@ -1,34 +0,0 @@ -repo: kubernetes/ingress -labels: -- name: area/api - color: ededed -- name: area/docs - color: 1d76db -- name: area/infra - color: bfdadc -- name: backend/gce - color: "5319e7" -- name: backend/generic - color: c2e0c6 -- name: backend/nginx - color: c5def5 -- name: bug - color: ee0701 -- name: 'cncf-cla: no' - color: ededed -- name: 'cncf-cla: yes' - color: ededed -- name: duplicate - color: cccccc -- name: enhancement - color: 84b6eb -- name: help wanted - color: 128A0C -- name: invalid - color: e6e6e6 -- name: lgtm - color: 15dd18 -- name: question - color: cc317c -- name: wontfix - color: ffffff diff --git a/requirements-docs.txt b/requirements-docs.txt index 14700a61d..5bed1b15a 100644 --- a/requirements-docs.txt +++ b/requirements-docs.txt @@ -1,4 +1,4 @@ -mkdocs-material~=4.4.0 +mkdocs-material~=4.6.2 mkdocs~=1.0.4 -pymdown-extensions~=6.0 -pygments~=2.3.1 +pymdown-extensions~=6.3 +pygments~=2.5.2 diff --git a/rootfs/etc/nginx/lua/balancer/sticky.lua b/rootfs/etc/nginx/lua/balancer/sticky.lua index 3527f1f73..e97b0a8dc 100644 --- a/rootfs/etc/nginx/lua/balancer/sticky.lua +++ b/rootfs/etc/nginx/lua/balancer/sticky.lua @@ -54,15 +54,12 @@ function _M.set_cookie(self, value) end end - if cookie_samesite then - cookie_path = cookie_path .. "; SameSite=" .. cookie_samesite - end - local cookie_data = { key = self:cookie_name(), value = value, path = cookie_path, httponly = true, + samesite = cookie_samesite, secure = ngx.var.https == "on", } diff --git a/rootfs/etc/nginx/lua/lua_ingress.lua b/rootfs/etc/nginx/lua/lua_ingress.lua index 83106425a..2d84ce141 100644 --- a/rootfs/etc/nginx/lua/lua_ingress.lua +++ b/rootfs/etc/nginx/lua/lua_ingress.lua @@ -123,6 +123,12 @@ function _M.rewrite(location_config) end end + if config.use_proxy_protocol then + if ngx.var.proxy_protocol_server_port == "443" then + ngx.var.pass_access_scheme = "https" + end + end + ngx.var.pass_port = ngx.var.pass_server_port if config.is_ssl_passthrough_enabled then if ngx.var.pass_server_port == config.listen_ports.ssl_proxy then diff --git a/rootfs/etc/nginx/lua/test/balancer/sticky_test.lua b/rootfs/etc/nginx/lua/test/balancer/sticky_test.lua index d967769e1..c1bee4ac0 100644 --- a/rootfs/etc/nginx/lua/test/balancer/sticky_test.lua +++ b/rootfs/etc/nginx/lua/test/balancer/sticky_test.lua @@ -114,6 +114,7 @@ describe("Sticky", function() set = function(self, payload) assert.equal(payload.key, test_backend.sessionAffinityConfig.cookieSessionAffinity.name) assert.equal(payload.path, ngx.var.location_path) + assert.equal(payload.samesite, nil) assert.equal(payload.domain, nil) assert.equal(payload.httponly, true) assert.equal(payload.secure, false) @@ -143,6 +144,7 @@ describe("Sticky", function() set = function(self, payload) assert.equal(payload.key, test_backend.sessionAffinityConfig.cookieSessionAffinity.name) assert.equal(payload.path, ngx.var.location_path) + assert.equal(payload.samesite, nil) assert.equal(payload.domain, nil) assert.equal(payload.httponly, true) assert.equal(payload.secure, true) @@ -185,6 +187,7 @@ describe("Sticky", function() set = function(self, payload) assert.equal(payload.key, test_backend.sessionAffinityConfig.cookieSessionAffinity.name) assert.equal(payload.path, ngx.var.location_path) + assert.equal(payload.samesite, nil) assert.equal(payload.domain, nil) assert.equal(payload.httponly, true) assert.equal(payload.secure, false) @@ -228,6 +231,7 @@ describe("Sticky", function() assert.equal(payload.path, ngx.var.location_path) assert.equal(payload.domain, ngx.var.host) assert.equal(payload.httponly, true) + assert.equal(payload.samesite, nil) return true, nil end, get = function(k) return false end, @@ -368,6 +372,7 @@ describe("Sticky", function() set = function(self, payload) assert.equal(payload.key, test_backend.sessionAffinityConfig.cookieSessionAffinity.name) assert.equal(payload.path, ngx.var.location_path) + assert.equal(payload.samesite, nil) assert.equal(payload.domain, nil) assert.equal(payload.httponly, true) assert.equal(payload.secure, false) @@ -405,13 +410,14 @@ describe("Sticky", function() cookie.new = mocked_cookie_new end) - local function test_set_cookie(sticky, samesite, conditional_samesite_none, expected_path) + local function test_set_cookie(sticky, samesite, conditional_samesite_none, expected_path, expected_samesite) local s = {} cookie.new = function(self) local cookie_instance = { set = function(self, payload) assert.equal(payload.key, test_backend.sessionAffinityConfig.cookieSessionAffinity.name) assert.equal(payload.path, expected_path) + assert.equal(payload.samesite, expected_samesite) assert.equal(payload.domain, nil) assert.equal(payload.httponly, true) assert.equal(payload.secure, false) @@ -433,27 +439,27 @@ describe("Sticky", function() end it("returns a cookie with SameSite=Strict when user specifies samesite strict", function() - test_set_cookie(sticky_balanced, "Strict", false, "/; SameSite=Strict") + test_set_cookie(sticky_balanced, "Strict", false, "/", "Strict") end) it("returns a cookie with SameSite=Strict when user specifies samesite strict and conditional samesite none", function() - test_set_cookie(sticky_balanced, "Strict", true, "/; SameSite=Strict") + test_set_cookie(sticky_balanced, "Strict", true, "/", "Strict") end) it("returns a cookie with SameSite=Lax when user specifies samesite lax", function() - test_set_cookie(sticky_balanced, "Lax", false, "/; SameSite=Lax") + test_set_cookie(sticky_balanced, "Lax", false, "/", "Lax") end) it("returns a cookie with SameSite=Lax when user specifies samesite lax and conditional samesite none", function() - test_set_cookie(sticky_balanced, "Lax", true, "/; SameSite=Lax") + test_set_cookie(sticky_balanced, "Lax", true, "/", "Lax") end) it("returns a cookie with SameSite=None when user specifies samesite None", function() - test_set_cookie(sticky_balanced, "None", false, "/; SameSite=None") + test_set_cookie(sticky_balanced, "None", false, "/", "None") end) it("returns a cookie with SameSite=None when user specifies samesite None and conditional samesite none with supported user agent", function() mock_ngx({ var = { location_path = "/", host = "test.com" , http_user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.2704.103 Safari/537.36"} }) - test_set_cookie(sticky_balanced, "None", true, "/; SameSite=None") + test_set_cookie(sticky_balanced, "None", true, "/", "None") end) it("returns a cookie without SameSite=None when user specifies samesite None and conditional samesite none with unsupported user agent", function() mock_ngx({ var = { location_path = "/", host = "test.com" , http_user_agent = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36"} }) - test_set_cookie(sticky_balanced, "None", true, "/") + test_set_cookie(sticky_balanced, "None", true, "/", nil) end) end) end) diff --git a/test/e2e/annotations/mirror.go b/test/e2e/annotations/mirror.go index 9ada90974..d2d809d6c 100644 --- a/test/e2e/annotations/mirror.go +++ b/test/e2e/annotations/mirror.go @@ -69,7 +69,7 @@ var _ = framework.IngressNginxDescribe("Annotations - Mirror", func() { It("should disable mirror-request-body", func() { annotations := map[string]string{ - "nginx.ingress.kubernetes.io/mirror-uri": "http://localhost/mirror", + "nginx.ingress.kubernetes.io/mirror-target": "http://localhost/mirror", "nginx.ingress.kubernetes.io/mirror-request-body": "off", } diff --git a/test/e2e/run.sh b/test/e2e/run.sh index 209bceb04..369dd9c8a 100755 --- a/test/e2e/run.sh +++ b/test/e2e/run.sh @@ -47,6 +47,11 @@ if ! command -v parallel &> /dev/null; then exit 1 fi +if ! command -v kind --version &> /dev/null; then + echo "kind is not installed. Use the package manager or visit the official site https://kind.sigs.k8s.io/" + exit 1 +fi + DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" export TAG=dev @@ -59,8 +64,6 @@ export DOCKER_CLI_EXPERIMENTAL=enabled KIND_CLUSTER_NAME="ingress-nginx-dev" -kind --version || $(echo "Please install kind before running e2e tests";exit 1) - echo "[dev-env] creating Kubernetes cluster with kind" export KUBECONFIG="${HOME}/.kube/kind-config-${KIND_CLUSTER_NAME}" diff --git a/test/e2e/settings/proxy_protocol.go b/test/e2e/settings/proxy_protocol.go index fc696313d..e0348c4ed 100644 --- a/test/e2e/settings/proxy_protocol.go +++ b/test/e2e/settings/proxy_protocol.go @@ -69,6 +69,39 @@ var _ = framework.IngressNginxDescribe("Proxy Protocol", func() { body := string(data) Expect(body).Should(ContainSubstring(fmt.Sprintf("host=%v", "proxy-protocol"))) Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-port=1234"))) + Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-proto=http"))) + Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-for=192.168.0.1"))) + }) + + It("should respect proto passed by the PROXY Protocol server port", func() { + host := "proxy-protocol" + + f.UpdateNginxConfigMapData(setting, "true") + + f.EnsureIngress(framework.NewSingleIngress(host, "/", host, f.Namespace, framework.EchoService, 80, nil)) + + f.WaitForNginxServer(host, + func(server string) bool { + return strings.Contains(server, "server_name proxy-protocol") && + strings.Contains(server, "listen 80 proxy_protocol") + }) + + ip := f.GetNginxIP() + + conn, err := net.Dial("tcp", net.JoinHostPort(ip, "80")) + Expect(err).NotTo(HaveOccurred(), "unexpected error creating connection to %s:80", ip) + defer conn.Close() + + header := "PROXY TCP4 192.168.0.1 192.168.0.11 56324 443\r\n" + conn.Write([]byte(header)) + conn.Write([]byte("GET / HTTP/1.1\r\nHost: proxy-protocol\r\n\r\n")) + + data, err := ioutil.ReadAll(conn) + Expect(err).NotTo(HaveOccurred(), "unexpected error reading connection data") + body := string(data) + Expect(body).Should(ContainSubstring(fmt.Sprintf("host=%v", "proxy-protocol"))) + Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-port=443"))) + Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-proto=https"))) Expect(body).Should(ContainSubstring(fmt.Sprintf("x-forwarded-for=192.168.0.1"))) }) })