Merge remote-tracking branch 'upstream/master'
8
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
|
||||
|
|
100
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 <<EOF | kind create cluster --name ${KIND_CLUSTER_NAME} --config=-
|
||||
kind: Cluster
|
||||
apiVersion: kind.x-k8s.io/v1alpha4
|
||||
nodes:
|
||||
- role: control-plane
|
||||
kubeadmConfigPatches:
|
||||
- |
|
||||
kind: InitConfiguration
|
||||
nodeRegistration:
|
||||
kubeletExtraArgs:
|
||||
node-labels: "ingress-ready=true"
|
||||
authorization-mode: "AlwaysAllow"
|
||||
extraPortMappings:
|
||||
- containerPort: 80
|
||||
hostPort: 80
|
||||
protocol: TCP
|
||||
- containerPort: 443
|
||||
hostPort: 443
|
||||
protocol: TCP
|
||||
EOF
|
||||
else
|
||||
sed -i -e "s|^namespace: .*|namespace: ${NAMESPACE}|g" "${ROOT}/kustomization.yaml"
|
||||
|
||||
echo "[dev-env] deploying NGINX Ingress controller in namespace $NAMESPACE"
|
||||
kubectl apply -k "${ROOT}"
|
||||
echo "[dev-env] using existing Kubernetes kind cluster"
|
||||
fi
|
||||
|
||||
echo "[dev-env] copying docker images to cluster..."
|
||||
kind load docker-image --name="${KIND_CLUSTER_NAME}" "${DEV_IMAGE}"
|
||||
|
||||
echo "[dev-env] deploying NGINX Ingress controller..."
|
||||
kubectl create namespace ingress-nginx || true
|
||||
kubectl apply -k ${DIR}/../deploy/kind
|
||||
|
||||
echo "[dev-env] deleting old ingress-nginx pods..."
|
||||
MINUTE_AGO=$(python -c "from datetime import datetime,timedelta; print((datetime.utcnow()-timedelta(seconds=60)).strftime('%Y-%m-%dT%H:%M:%SZ'))")
|
||||
kubectl get pods --namespace ingress-nginx -o go-template \
|
||||
--template '{{range .items}}{{.metadata.name}} {{.metadata.creationTimestamp}}{{"\n"}}{{end}}' | \
|
||||
awk -v MINUTE_AGO=$MINUTE_AGO '$2 <= MINUTE_AGO { print $1 }' | \
|
||||
xargs kubectl delete pod --namespace ingress-nginx
|
||||
|
||||
cat <<EOF
|
||||
|
||||
Kubernetes cluster ready and ingress-nginx listening in localhost using ports 80 and 443
|
||||
|
||||
To delete the dev cluster execute: 'kind delete cluster --name ingress-nginx-dev'
|
||||
|
||||
EOF
|
||||
|
|
|
@ -45,13 +45,6 @@ FLAGS=$@
|
|||
PKG=k8s.io/ingress-nginx
|
||||
ARCH=$(go env GOARCH)
|
||||
|
||||
MINIKUBE_PATH=${HOME}/.minikube
|
||||
MINIKUBE_VOLUME="-v ${MINIKUBE_PATH}:${MINIKUBE_PATH}"
|
||||
if [ ! -d "${MINIKUBE_PATH}" ]; then
|
||||
echo "Minikube directory not found! Volume will be excluded from docker build."
|
||||
MINIKUBE_VOLUME=""
|
||||
fi
|
||||
|
||||
# create output directory as current user to avoid problem with docker.
|
||||
mkdir -p "${KUBE_ROOT}/bin" "${KUBE_ROOT}/bin/${ARCH}"
|
||||
|
||||
|
@ -67,7 +60,6 @@ docker run \
|
|||
-v "${KUBE_ROOT}/bin/${ARCH}:/go/bin/linux_${ARCH}" \
|
||||
-v "/var/run/docker.sock:/var/run/docker.sock" \
|
||||
-v "${INGRESS_VOLUME}:/etc/ingress-controller/" \
|
||||
${MINIKUBE_VOLUME} \
|
||||
-w "/go/src/${PKG}" \
|
||||
-u $(id -u ${USER}):$(id -g ${USER}) \
|
||||
${E2E_IMAGE} /bin/bash -c "${FLAGS}"
|
||||
|
|
|
@ -94,11 +94,6 @@ until curl --output /dev/null -fsSL http://localhost:8001/; do
|
|||
sleep 5
|
||||
done
|
||||
|
||||
MINIKUBE_VOLUME=
|
||||
if [[ -d "${HOME}/.minikube" ]]; then
|
||||
MINIKUBE_VOLUME=" -v ${HOME}/.minikube:${HOME}/.minikube "
|
||||
fi
|
||||
|
||||
# if we run as user we cannot bind to port 80 and 443
|
||||
docker run \
|
||||
--rm \
|
||||
|
@ -109,7 +104,6 @@ docker run \
|
|||
-e POD_NAME="${POD_NAME}" \
|
||||
-v "${SSL_VOLUME}:/etc/ingress-controller/ssl/" \
|
||||
-v "${HOME}/.kube:${HOME}/.kube:ro" \
|
||||
${MINIKUBE_VOLUME} \
|
||||
"${IMAGE}-${ARCH}:${TAG}" /nginx-ingress-controller \
|
||||
--update-status=false \
|
||||
--v=2 \
|
||||
|
|
|
@ -31,6 +31,7 @@ import (
|
|||
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
||||
"k8s.io/ingress-nginx/internal/ingress/controller"
|
||||
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
||||
"k8s.io/ingress-nginx/internal/ingress/status"
|
||||
ing_net "k8s.io/ingress-nginx/internal/net"
|
||||
"k8s.io/ingress-nginx/internal/nginx"
|
||||
)
|
||||
|
@ -175,6 +176,8 @@ Takes the form "<host>: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)
|
||||
|
||||
|
|
Before Width: | Height: | Size: 606 KiB After Width: | Height: | Size: 329 KiB |
|
@ -7,3 +7,5 @@ bases:
|
|||
images:
|
||||
- name: quay.io/kubernetes-ingress-controller/nginx-ingress-controller
|
||||
newTag: dev
|
||||
patchesStrategicMerge:
|
||||
- service-hostport.yaml
|
25
deploy/kind/service-hostport.yaml
Normal file
|
@ -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
|
|
@ -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
|
||||
```
|
||||
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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 <none> 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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -7,6 +7,9 @@ metadata:
|
|||
namespace: default
|
||||
spec:
|
||||
replicas: 1
|
||||
selector:
|
||||
matchLabels:
|
||||
k8s-app: fortune-teller-app
|
||||
template:
|
||||
metadata:
|
||||
labels:
|
||||
|
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 30 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 38 KiB |
Before Width: | Height: | Size: 40 KiB After Width: | Height: | Size: 34 KiB |
Before Width: | Height: | Size: 49 KiB After Width: | Height: | Size: 41 KiB |
Before Width: | Height: | Size: 47 KiB After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 62 KiB After Width: | Height: | Size: 52 KiB |
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 28 KiB |
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 141 KiB After Width: | Height: | Size: 70 KiB |
Before Width: | Height: | Size: 112 KiB After Width: | Height: | Size: 81 KiB |
Before Width: | Height: | Size: 120 KiB After Width: | Height: | Size: 60 KiB |
|
@ -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 |
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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: "<alias 1>,<alias 2>"`.
|
||||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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"`
|
||||
|
|
|
@ -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")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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: "",
|
||||
}},
|
||||
|
|
|
@ -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{}) {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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)
|
||||
|
|
34
labels.yaml
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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",
|
||||
}
|
||||
|
||||
|
|
|
@ -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}"
|
||||
|
|
|
@ -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")))
|
||||
})
|
||||
})
|
||||
|
|