Merge branch 'master' into xff

This commit is contained in:
Dario Nieuwenhuis 2018-08-16 18:15:14 +02:00 committed by GitHub
commit b5bcb93a4b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
1532 changed files with 65966 additions and 34963 deletions

6
.gitignore vendored
View file

@ -39,3 +39,9 @@ site
# temporal github pages
gh-pages
# Docker-based builds
/test/binaries
/.env
/.gocache/
/bin/

View file

@ -5,29 +5,27 @@ sudo: required
services:
- docker
language: go
# FIXME(#46924): these two commands are required to enable IPv6,
# they shouldn't exist, please revert once more official solutions appeared.
# see https://github.com/travis-ci/travis-ci/issues/8891#issuecomment-353403729
before_install:
- echo '{"ipv6":true,"fixed-cidr-v6":"2001:db8:1::/64"}' | sudo tee /etc/docker/daemon.json
- sudo service docker restart
addons:
apt:
packages:
- luarocks
language: generic
notifications:
email:
on_failure: always
on_success: never
go:
- 1.10.2
go_import_path: k8s.io/ingress-nginx
# New secure variables can be added using travis encrypt -r kubernetes/ingress-nginx --add K=V
env:
global:
- CHANGE_MINIKUBE_NONE_USER=true
- KUBERNETES_VERSION=v1.10.0
- DOCKER=docker
- SKIP_SNAPSHOT=true
- NODE_IP=10.192.0.3
- E2E_NODES=6
- GH_REF=github.com/kubernetes/ingress-nginx
- secure: LIS2XpZufWTcJ53jiRsSZy2Gi1EUJ1XmLg7z3f2ZHeMnyG2Jhk3GW4vod1FNru+PY4PWgddLdCdIl+jqOYXndFlbdAWF3/Oy5fEkYLXdYV7tdlHcPWDkqNFrfiyZ4guChN+b2Nk6FqU7o5fsZAIR7VAbgqNRF5XMo9Mhn/vhDCQRcnbXy7uq7JTrYUkqDbQoyYvT6b480GCY5gags1zp/xZfPDNZEe936o8i5IPTyiykRyNOXN/AH6kd3pR5e1xYgcvJ9KpSVPghcwFE7kJ4fOVMRhRG5ML+IyML+xD0jX43EMNoqRKZ/HS42kIMCInFbJEcxVde7DPNBZ7Y3GAqh7HO6qrE70Dn3ha6DID6zCoH2ArW39BxG4zempjn2VxYoMRGREyZszWQb++dwGoHmo5FHt6zvIrYBG0dA0H8ja9VkZkjFwtYTGHU1ooPzUfJK4O4VBayV8LqZibyZQR+GrmyQc0aagUY7J/fe4A2PJyI4DbkeZ7GX1ELj0ciDz4urQSzUc8l/T3aU3X+FuJItjgYtMLPmqcjA5uifDCtutE8Z9L2gSpanqUdvLSOozuxPho/KNl+2YlF7fXqPW3LnRf5mHD+NbOff306pvKlHJOb2Vmth+HBQ1XDzt/Cy5+sfwS3E0Vmh6UTq/NtkUXxwH10BDMF7FMVlQ4zdHQvyZ0=
- secure: rKDoy9IYYYy0fYBs4+9mwuBVq/TcxfFwMfE0ywYWhUUdgzrUYSJAwpoe/96EQ4YmESUefwC2nDNq4G3XzJKYOWf83PaIveb9Z//zmMrCQXjDuDBDLpwV3sXSh7evXiVDohJz4ogBCeMRUCMKYsyKBM9yWfa/iu+yI92dbphpK9peOKW6yBc0uspJlln4swN3GS2WT9LVuPY2Azv9U2UqrXufOPDKG/qEb/Vrn4yZ2lR/50r2k45e9nSvDoByvr10V8ubM5Zc0iP0vBuAUVRdByv6N53Q4gaBGapY6SxhIjIPC/h0rNnuT9EXp7MWaPT5FmBxLt9wnyleT9QhZJnFyaBYqFgcz/DKifYQkryY4M5dLMo/Rt3yATyAy8Y0df1TOoV2dKdqwOOwQ8bXB1wDfyrGxmQj9HY4Ffnphx3wPE1a+Sjuh+S5Epm7XJbPx5pZJqNO2hd4sTbk0Xp3gpPbihny2r/jtNwHl0wpFCfOM68RNrsVRlIwG3UhzbZvblbQ/M/mmWCdgzINjt07I2SGCJxfKG0e98Q49SKUoDoOgQTTRDqTC9IgOEDxyfAkT0Vr6BtlP88Nsgnf6kmboyigBrRAiaDQGTxn3SP6LnQI3CeopaRDYvFZe/rTwPXE9XlKoTn9FTWnAqF3MuWaLslDcDKYEh7OaYJjF01piu6g4Nc=
@ -38,29 +36,16 @@ jobs:
include:
- stage: Static Check
script:
- sudo luarocks install luacheck
- make luacheck
- mkdir --parents $GOPATH/src/golang.org/x
&& git clone --depth=1 https://go.googlesource.com/lint $GOPATH/src/golang.org/x/lint
&& go get golang.org/x/lint/golint
- go get github.com/vbatts/git-validation
- make verify-all
- make static-check
- stage: Lua Unit Test
before_script:
- rootfs/etc/nginx/lua/test/up.sh
script:
- make lua-test
- stage: Coverage
before_script:
# start minikube
- test/e2e/up.sh
script:
- make cover
- stage: e2e
before_script:
- go get github.com/onsi/ginkgo/ginkgo
- test/e2e/up.sh
- make dev-env
script:
- make e2e-test
# split builds to avoid job timeouts
@ -71,18 +56,22 @@ jobs:
- stage: publish arm
if: type = api AND branch = master AND repo = kubernetes/ingress-nginx
script:
- make register-qemu
- .travis/publish.sh arm
- stage: publish arm64
if: type = api AND branch = master AND repo = kubernetes/ingress-nginx
script:
- make register-qemu
- .travis/publish.sh arm64
- stage: publish ppc64le
if: type = api AND branch = master AND repo = kubernetes/ingress-nginx
script:
- make register-qemu
- .travis/publish.sh ppc64le
- stage: publish s390x
if: type = api AND branch = master AND repo = kubernetes/ingress-nginx
script:
- make register-qemu
- .travis/publish.sh s390x
- stage: Publish docs
if: type = api AND branch = master AND repo = kubernetes/ingress-nginx

View file

@ -1,5 +1,298 @@
# Changelog
### 0.18.0
**Image:** `quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.18.0`
*New Features:*
- NGINX 1.15.2
- Dynamic configuration is enabled by default
- Support for AJP protocol
- Use of authbind to bind privileged ports
- Replace minikube with [kubeadm-dind-cluster](https://github.com/kubernetes-sigs/kubeadm-dind-cluster) to run e2e tests
*Changes:*
- [X] [#2789](https://github.com/kubernetes/ingress-nginx/pull/2789) Remove KubeConfig Dependency for Store Tests
- [X] [#2794](https://github.com/kubernetes/ingress-nginx/pull/2794) enable dynamic backend configuration by default
- [X] [#2795](https://github.com/kubernetes/ingress-nginx/pull/2795) start minikube before trying to build the image
- [X] [#2804](https://github.com/kubernetes/ingress-nginx/pull/2804) add support for ExternalName service type in dynamic mode
- [X] [#2808](https://github.com/kubernetes/ingress-nginx/pull/2808) fix the bug #2799, add prefix (?i) in rewrite statement.
- [X] [#2811](https://github.com/kubernetes/ingress-nginx/pull/2811) Escape $request_uri for external auth
- [X] [#2812](https://github.com/kubernetes/ingress-nginx/pull/2812) modified annotation name "rewrite-to" to "rewrite-target" in comments
- [X] [#2819](https://github.com/kubernetes/ingress-nginx/pull/2819) Catch errors waiting for controller deployment
- [X] [#2823](https://github.com/kubernetes/ingress-nginx/pull/2823) Multiple optimizations to build targets
- [X] [#2825](https://github.com/kubernetes/ingress-nginx/pull/2825) Refactoring of how we run as user
- [X] [#2826](https://github.com/kubernetes/ingress-nginx/pull/2826) Remove setcap from image and update nginx to 0.15.1
- [X] [#2827](https://github.com/kubernetes/ingress-nginx/pull/2827) Use nginx image as base and install go on top
- [X] [#2829](https://github.com/kubernetes/ingress-nginx/pull/2829) use resty-cli for running lua unit tests
- [X] [#2830](https://github.com/kubernetes/ingress-nginx/pull/2830) Remove lua mocks
- [X] [#2834](https://github.com/kubernetes/ingress-nginx/pull/2834) Added permanent-redirect-code
- [X] [#2844](https://github.com/kubernetes/ingress-nginx/pull/2844) Do not allow invalid latency values in metrics
- [X] [#2852](https://github.com/kubernetes/ingress-nginx/pull/2852) fix custom-error-pages functionality in dynamic mode
- [X] [#2853](https://github.com/kubernetes/ingress-nginx/pull/2853) improve annotations/default_backend e2e test
- [X] [#2858](https://github.com/kubernetes/ingress-nginx/pull/2858) Update build image
- [X] [#2859](https://github.com/kubernetes/ingress-nginx/pull/2859) Fix inconsistent metric labels
- [X] [#2863](https://github.com/kubernetes/ingress-nginx/pull/2863) Replace minikube for e2e tests
- [X] [#2867](https://github.com/kubernetes/ingress-nginx/pull/2867) fix bug with lua e2e test suite
- [X] [#2868](https://github.com/kubernetes/ingress-nginx/pull/2868) Use an existing e2e image
- [X] [#2869](https://github.com/kubernetes/ingress-nginx/pull/2869) describe under what circumstances and how we avoid Nginx reload
- [X] [#2871](https://github.com/kubernetes/ingress-nginx/pull/2871) Add support for AJP protocol
- [X] [#2872](https://github.com/kubernetes/ingress-nginx/pull/2872) Update nginx to 1.15.2
- [X] [#2874](https://github.com/kubernetes/ingress-nginx/pull/2874) Delay initial prometheus status metric
- [X] [#2876](https://github.com/kubernetes/ingress-nginx/pull/2876) Remove dashboard an tune sync-frequency
- [X] [#2877](https://github.com/kubernetes/ingress-nginx/pull/2877) Refactor entrypoint to avoid issues with volumes
- [X] [#2885](https://github.com/kubernetes/ingress-nginx/pull/2885) fix: Sort TCP/UDP upstream order
- [X] [#2888](https://github.com/kubernetes/ingress-nginx/pull/2888) Fix grafana datasources
- [X] [#2890](https://github.com/kubernetes/ingress-nginx/pull/2890) Usability improvements to build steps
- [X] [#2893](https://github.com/kubernetes/ingress-nginx/pull/2893) Update nginx image
- [X] [#2894](https://github.com/kubernetes/ingress-nginx/pull/2894) Use authbind to bind privileged ports
- [X] [#2895](https://github.com/kubernetes/ingress-nginx/pull/2895) support custom configuration to main context of nginx config
- [X] [#2896](https://github.com/kubernetes/ingress-nginx/pull/2896) support configuring multi_accept directive via configmap
- [X] [#2897](https://github.com/kubernetes/ingress-nginx/pull/2897) Enable reuse-port by default
- [X] [#2905](https://github.com/kubernetes/ingress-nginx/pull/2905) Fix IPV6 detection
*Documentation:*
- [X] [#2816](https://github.com/kubernetes/ingress-nginx/pull/2816) doc log-format: add variables about ingress
- [X] [#2866](https://github.com/kubernetes/ingress-nginx/pull/2866) Update index.md
- [X] [#2898](https://github.com/kubernetes/ingress-nginx/pull/2898) Fix default sync-period doc
- [X] [#2903](https://github.com/kubernetes/ingress-nginx/pull/2903) Very minor grammar fix
### 0.17.1
**Image:** `quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.17.1`
*Changes:*
- [X] [#2782](https://github.com/kubernetes/ingress-nginx/pull/2782) Add Better Error Handling for SSLSessionTicketKey
- [X] [#2790](https://github.com/kubernetes/ingress-nginx/pull/2790) Update prometheus labels
*Documentation:*
- [X] [#2770](https://github.com/kubernetes/ingress-nginx/pull/2770) Basic-Auth doc misleading: fix double quotes leading to nginx config error
### 0.17.0
**Image:** `quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.17.0`
*New Features:*
- [Grafana dashboards](https://github.com/kubernetes/ingress-nginx/tree/master/deploy/grafana/dashboards)
*Changes:*
- [X] [#2705](https://github.com/kubernetes/ingress-nginx/pull/2705) Remove duplicated securityContext
- [X] [#2719](https://github.com/kubernetes/ingress-nginx/pull/2719) Sample rate configmap option for zipkin in nginx-opentracing
- [X] [#2726](https://github.com/kubernetes/ingress-nginx/pull/2726) Cleanup prometheus metrics after a reload
- [X] [#2727](https://github.com/kubernetes/ingress-nginx/pull/2727) Add e2e tests for Client-Body-Buffer-Size
- [X] [#2732](https://github.com/kubernetes/ingress-nginx/pull/2732) Improve logging
- [X] [#2741](https://github.com/kubernetes/ingress-nginx/pull/2741) Add redirect uri for oauth2 login
- [X] [#2744](https://github.com/kubernetes/ingress-nginx/pull/2744) fix: Use the correct opentracing plugin for Jaeger
- [X] [#2747](https://github.com/kubernetes/ingress-nginx/pull/2747) Update opentracing-cpp and modsecurity
- [X] [#2748](https://github.com/kubernetes/ingress-nginx/pull/2748) Update nginx image to 0.54
- [X] [#2749](https://github.com/kubernetes/ingress-nginx/pull/2749) Use docker to build go binaries
- [X] [#2754](https://github.com/kubernetes/ingress-nginx/pull/2754) Allow gzip compression level to be controlled via ConfigMap
- [X] [#2760](https://github.com/kubernetes/ingress-nginx/pull/2760) Fix ingress rule parsing error
- [X] [#2767](https://github.com/kubernetes/ingress-nginx/pull/2767) Fix regression introduced in #2732
- [X] [#2771](https://github.com/kubernetes/ingress-nginx/pull/2771) Grafana Dashboard
- [X] [#2775](https://github.com/kubernetes/ingress-nginx/pull/2775) Simplify handler registration and updates prometheus
- [X] [#2776](https://github.com/kubernetes/ingress-nginx/pull/2776) Fix configuration hash calculation
*Documentation:*
- [X] [#2717](https://github.com/kubernetes/ingress-nginx/pull/2717) GCE/GKE proxy mentioned for Azure
- [X] [#2743](https://github.com/kubernetes/ingress-nginx/pull/2743) Clarify Installation Document by Separating Helm Steps
- [X] [#2761](https://github.com/kubernetes/ingress-nginx/pull/2761) Fix spelling mistake
- [X] [#2764](https://github.com/kubernetes/ingress-nginx/pull/2764) Use language neutral links to MDN
- [X] [#2765](https://github.com/kubernetes/ingress-nginx/pull/2765) Add FOSSA status badge
- [X] [#2777](https://github.com/kubernetes/ingress-nginx/pull/2777) Build docs using local docker image [ci skip]
### 0.16.2
**Image:** `quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.2`
*Breaking changes:*
Running as user requires an update in the deployment manifest.
```yaml
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
```
Note: the deploy [guide](https://kubernetes.github.io/ingress-nginx/deploy/#mandatory-command) contains this change
*Changes:*
- [X] [#2678](https://github.com/kubernetes/ingress-nginx/pull/2678) Refactor server type to include SSLCert
- [X] [#2685](https://github.com/kubernetes/ingress-nginx/pull/2685) Fix qemu docker build
- [X] [#2696](https://github.com/kubernetes/ingress-nginx/pull/2696) If server_tokens is disabled completely remove the Server header
- [X] [#2698](https://github.com/kubernetes/ingress-nginx/pull/2698) Improve best-cert guessing with empty tls.hosts
- [X] [#2701](https://github.com/kubernetes/ingress-nginx/pull/2701) Remove prometheus labels with high cardinality
*Documentation:*
- [X] [#2368](https://github.com/kubernetes/ingress-nginx/pull/2368) [aggregate] Fix typos across codebase
- [X] [#2681](https://github.com/kubernetes/ingress-nginx/pull/2681) Typo fix in error message: encounted->encountered
- [X] [#2697](https://github.com/kubernetes/ingress-nginx/pull/2697) Enhance Distributed Tracing Documentation
### 0.16.1
**Image:** `quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.1`
*Breaking changes:*
Running as user requires an update in the deployment manifest.
```yaml
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
```
Note: the deploy [guide](https://kubernetes.github.io/ingress-nginx/deploy/#mandatory-command) contains this change
*New Features:*
- Run as user dropping root privileges
- New prometheus metric implementation (VTS module was removed)
- [InfluxDB integration](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#influxdb)
- [Module GeoIP2](https://github.com/leev/ngx_http_geoip2_module)
*Changes:*
- [X] [#2692](https://github.com/kubernetes/ingress-nginx/pull/2692) Fix initial read of configuration configmap
- [X] [#2693](https://github.com/kubernetes/ingress-nginx/pull/2693) Revert #2669
- [X] [#2694](https://github.com/kubernetes/ingress-nginx/pull/2694) Add note about status update
### 0.16.0
**Image:** `quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.16.1`
*Breaking changes:*
Running as user requires an update in the deployment manifest.
```yaml
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
```
Note: the deploy [guide](https://kubernetes.github.io/ingress-nginx/deploy/#mandatory-command) contains this change
*New Features:*
- Run as user dropping root privileges
- New prometheus metric implementation (VTS module was removed)
- [InfluxDB integration](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#influxdb)
- [Module GeoIP2](https://github.com/leev/ngx_http_geoip2_module)
*Changes:*
- [X] [#2423](https://github.com/kubernetes/ingress-nginx/pull/2423) Resolves issue with proxy-redirect nginx configuration
- [X] [#2451](https://github.com/kubernetes/ingress-nginx/pull/2451) fix for #1930, make sessions sticky, for ingress with multiple rules …
- [X] [#2484](https://github.com/kubernetes/ingress-nginx/pull/2484) Fix bugs in Lua implementation of sticky sessions
- [X] [#2486](https://github.com/kubernetes/ingress-nginx/pull/2486) Extend kubernetes interrelation variables in nginx.tmpl
- [X] [#2504](https://github.com/kubernetes/ingress-nginx/pull/2504) Add Timeout For TLS Passthrough
- [X] [#2505](https://github.com/kubernetes/ingress-nginx/pull/2505) Annotations for the InfluxDB module
- [X] [#2517](https://github.com/kubernetes/ingress-nginx/pull/2517) Fix typo about the kind of request
- [X] [#2523](https://github.com/kubernetes/ingress-nginx/pull/2523) Add tests for bind-address
- [X] [#2524](https://github.com/kubernetes/ingress-nginx/pull/2524) Add support for grpc_set_header
- [X] [#2526](https://github.com/kubernetes/ingress-nginx/pull/2526) Fix upstream hash lua test
- [X] [#2528](https://github.com/kubernetes/ingress-nginx/pull/2528) Remove go-bindata
- [X] [#2533](https://github.com/kubernetes/ingress-nginx/pull/2533) NGINX image update: add the influxdb module
- [X] [#2534](https://github.com/kubernetes/ingress-nginx/pull/2534) Set Focus for E2E Tests
- [X] [#2537](https://github.com/kubernetes/ingress-nginx/pull/2537) Update nginx modules
- [X] [#2542](https://github.com/kubernetes/ingress-nginx/pull/2542) Instrument controller to show configReload metrics
- [X] [#2543](https://github.com/kubernetes/ingress-nginx/pull/2543) introduce a balancer interface
- [X] [#2548](https://github.com/kubernetes/ingress-nginx/pull/2548) Implement generate-request-id
- [X] [#2554](https://github.com/kubernetes/ingress-nginx/pull/2554) use better defaults for proxy-next-upstream(-tries)
- [X] [#2558](https://github.com/kubernetes/ingress-nginx/pull/2558) Update qemu to 2.12.0 [ci skip]
- [X] [#2559](https://github.com/kubernetes/ingress-nginx/pull/2559) Add geoip2 module and DB to nginx build
- [X] [#2564](https://github.com/kubernetes/ingress-nginx/pull/2564) Add security contacts file [ci skip]
- [X] [#2569](https://github.com/kubernetes/ingress-nginx/pull/2569) Update nginx modules to fix core dump [ci skip]
- [X] [#2570](https://github.com/kubernetes/ingress-nginx/pull/2570) Enable core dumps during tests
- [X] [#2573](https://github.com/kubernetes/ingress-nginx/pull/2573) Refactor e2e tests and update go dependencies
- [X] [#2574](https://github.com/kubernetes/ingress-nginx/pull/2574) Fix default-backend annotation
- [X] [#2575](https://github.com/kubernetes/ingress-nginx/pull/2575) Print information about NGINX version
- [X] [#2577](https://github.com/kubernetes/ingress-nginx/pull/2577) make sure ingress-nginx instances are watching their namespace only during test runs
- [X] [#2588](https://github.com/kubernetes/ingress-nginx/pull/2588) Update nginx dependencies
- [X] [#2590](https://github.com/kubernetes/ingress-nginx/pull/2590) Typo fix: muthual autentication -> mutual authentication
- [X] [#2591](https://github.com/kubernetes/ingress-nginx/pull/2591) Access log improvements
- [X] [#2597](https://github.com/kubernetes/ingress-nginx/pull/2597) Fix arm paths for liblua.so and lua_package_cpath
- [X] [#2598](https://github.com/kubernetes/ingress-nginx/pull/2598) Always sort upstream list to provide stable iteration order
- [X] [#2600](https://github.com/kubernetes/ingress-nginx/pull/2600) typo fix futher to further && preformance to performance
- [X] [#2602](https://github.com/kubernetes/ingress-nginx/pull/2602) Crossplat fixes
- [X] [#2603](https://github.com/kubernetes/ingress-nginx/pull/2603) Bump nginx influxdb module to f8732268d44aea706ecf8d9c6036e9b6dacc99b2
- [X] [#2608](https://github.com/kubernetes/ingress-nginx/pull/2608) Expose UDP message on /metrics endpoint
- [X] [#2611](https://github.com/kubernetes/ingress-nginx/pull/2611) Add metric emitter lua module
- [X] [#2614](https://github.com/kubernetes/ingress-nginx/pull/2614) fix nginx conf test error when not found active service endpoints
- [X] [#2617](https://github.com/kubernetes/ingress-nginx/pull/2617) Update go to 1.10.3
- [X] [#2618](https://github.com/kubernetes/ingress-nginx/pull/2618) Update nginx to 1.15.0 and remove VTS module
- [X] [#2619](https://github.com/kubernetes/ingress-nginx/pull/2619) Run as user dropping privileges
- [X] [#2623](https://github.com/kubernetes/ingress-nginx/pull/2623) Proofread cmd package and update flags description
- [X] [#2634](https://github.com/kubernetes/ingress-nginx/pull/2634) Disable resync period
- [X] [#2636](https://github.com/kubernetes/ingress-nginx/pull/2636) Add missing equality comparisons for ingress.Server
- [X] [#2638](https://github.com/kubernetes/ingress-nginx/pull/2638) Wait the result of the controller deployment before running any test
- [X] [#2639](https://github.com/kubernetes/ingress-nginx/pull/2639) Clarify log messages in controller package
- [X] [#2643](https://github.com/kubernetes/ingress-nginx/pull/2643) Remove VTS from the ingress controller
- [X] [#2644](https://github.com/kubernetes/ingress-nginx/pull/2644) Update nginx image version
- [X] [#2646](https://github.com/kubernetes/ingress-nginx/pull/2646) Rollback nginx 1.15.0 to 1.13.12
- [X] [#2649](https://github.com/kubernetes/ingress-nginx/pull/2649) Add support for IPV6 in stream upstream servers
- [X] [#2652](https://github.com/kubernetes/ingress-nginx/pull/2652) Use a unix socket instead udp for reception of metrics
- [X] [#2653](https://github.com/kubernetes/ingress-nginx/pull/2653) Remove dummy file watcher
- [X] [#2654](https://github.com/kubernetes/ingress-nginx/pull/2654) Hotfix: influxdb module enable disable toggle
- [X] [#2656](https://github.com/kubernetes/ingress-nginx/pull/2656) Improve configuration change detection
- [X] [#2658](https://github.com/kubernetes/ingress-nginx/pull/2658) Do not wait informer initialization to read configuration
- [X] [#2659](https://github.com/kubernetes/ingress-nginx/pull/2659) Update nginx image
- [X] [#2660](https://github.com/kubernetes/ingress-nginx/pull/2660) Change modsecurity directories
- [X] [#2661](https://github.com/kubernetes/ingress-nginx/pull/2661) Add additional header when debug is enabled
- [X] [#2664](https://github.com/kubernetes/ingress-nginx/pull/2664) refactor some lua code
- [X] [#2669](https://github.com/kubernetes/ingress-nginx/pull/2669) Remove unnecessary sync when the leader change
- [X] [#2672](https://github.com/kubernetes/ingress-nginx/pull/2672) After a configmap change parse ingress annotations (again)
- [X] [#2673](https://github.com/kubernetes/ingress-nginx/pull/2673) Add new approvers to the project
- [X] [#2674](https://github.com/kubernetes/ingress-nginx/pull/2674) Add e2e test for configmap change and reload
- [X] [#2675](https://github.com/kubernetes/ingress-nginx/pull/2675) Update opentracing nginx module
- [X] [#2676](https://github.com/kubernetes/ingress-nginx/pull/2676) Update opentracing configuration
*Documentation:*
- [X] [#2479](https://github.com/kubernetes/ingress-nginx/pull/2479) Document how the NGINX Ingress controller build nginx.conf
- [X] [#2515](https://github.com/kubernetes/ingress-nginx/pull/2515) Simplify installation and e2e manifests
- [X] [#2531](https://github.com/kubernetes/ingress-nginx/pull/2531) Mention the #ingress-nginx Slack channel
- [X] [#2540](https://github.com/kubernetes/ingress-nginx/pull/2540) DOCS: Correct ssl-passthrough annotation description.
- [X] [#2544](https://github.com/kubernetes/ingress-nginx/pull/2544) [docs] Fix manifest URL for GKE + Azure
- [X] [#2566](https://github.com/kubernetes/ingress-nginx/pull/2566) Fix wrong default value for `enable-brotli`
- [X] [#2581](https://github.com/kubernetes/ingress-nginx/pull/2581) Improved link in modsecurity.md
- [X] [#2583](https://github.com/kubernetes/ingress-nginx/pull/2583) docs: add secret scheme details to the example
- [X] [#2592](https://github.com/kubernetes/ingress-nginx/pull/2592) Typo fix: are be->are/to on->to
- [X] [#2595](https://github.com/kubernetes/ingress-nginx/pull/2595) Typo fix: successfull->successful
- [X] [#2601](https://github.com/kubernetes/ingress-nginx/pull/2601) fix changelog link in README.md
- [X] [#2624](https://github.com/kubernetes/ingress-nginx/pull/2624) Fix minor documentation example
- [X] [#2625](https://github.com/kubernetes/ingress-nginx/pull/2625) Add annotation doc on proxy buffer size
- [X] [#2630](https://github.com/kubernetes/ingress-nginx/pull/2630) Update documentation for custom error pages
- [X] [#2666](https://github.com/kubernetes/ingress-nginx/pull/2666) Add documentation for proxy-cookie-domain annotation (#2034)
### 0.15.0
**Image:** `quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0`

142
Gopkg.lock generated
View file

@ -4,8 +4,8 @@
[[projects]]
name = "cloud.google.com/go"
packages = ["compute/metadata"]
revision = "0fd7230b2a7505833d5f69b75cbd6c9582401479"
version = "v0.23.0"
revision = "aad3f485ee528456e0768f20397b4d9dd941e755"
version = "v0.25.0"
[[projects]]
name = "github.com/Azure/go-autorest"
@ -15,7 +15,8 @@
"autorest/azure",
"autorest/date"
]
revision = "d4e6b95c12a08b4de2d48b45d5b4d594e5d32fab"
revision = "1f7cd6cfe0adea687ad44a512dfe76140f804318"
version = "v10.12.0"
[[projects]]
branch = "master"
@ -80,7 +81,7 @@
branch = "master"
name = "github.com/fullsailor/pkcs7"
packages = ["."]
revision = "ae226422660e5ca10db350d33f81c6608f3fbcdd"
revision = "8306686428a5fe132eac8cb7c4848af725098bd4"
[[projects]]
name = "github.com/ghodss/yaml"
@ -123,6 +124,12 @@
revision = "b4deda0973fb4c70b50d226b1af49f3da59f5265"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "github.com/google/btree"
packages = ["."]
revision = "e89373fe6b4a7413d7acd6da1725b83ef713e6e4"
[[projects]]
branch = "master"
name = "github.com/google/gofuzz"
@ -151,7 +158,16 @@
"openstack/utils",
"pagination"
]
revision = "282f25e4025de0a42015d2e2b5faef1d920aad3c"
revision = "45c2d035713fa44f366921035a44610ac5d45beb"
[[projects]]
branch = "master"
name = "github.com/gregjones/httpcache"
packages = [
".",
"diskcache"
]
revision = "9cad4c3443a7200dd6400aef47183728de563a38"
[[projects]]
branch = "master"
@ -162,12 +178,6 @@
]
revision = "0fb14efe8c47ae851c0034ed7a448854d3d34cf3"
[[projects]]
branch = "master"
name = "github.com/howeyc/gopass"
packages = ["."]
revision = "bf9dde6d0d2c004a008c27aaee91170c786f6db8"
[[projects]]
name = "github.com/imdario/mergo"
packages = ["."]
@ -177,14 +187,8 @@
[[projects]]
name = "github.com/json-iterator/go"
packages = ["."]
revision = "ca39e5af3ece67bbcda3d0f4f56a8e24d9f2dad4"
version = "1.1.3"
[[projects]]
name = "github.com/kr/pty"
packages = ["."]
revision = "282ce0e5322c82529687d609ee670fac7c7d917c"
version = "v1.1.1"
revision = "ab8a2e0c74be9d3be70b3184d9acc634935ded82"
version = "1.1.4"
[[projects]]
branch = "master"
@ -198,8 +202,8 @@
[[projects]]
name = "github.com/matttproud/golang_protobuf_extensions"
packages = ["pbutil"]
revision = "3247c84500bff8d9fb6d579d800f20b3e091582c"
version = "v1.0.0"
revision = "c12348ce28de40eed0136aa2b644d0ee0650e56c"
version = "v1.0.1"
[[projects]]
branch = "master"
@ -207,6 +211,12 @@
packages = ["."]
revision = "4fdf99ab29366514c69ccccddab5dc58b8d84062"
[[projects]]
branch = "master"
name = "github.com/mitchellh/hashstructure"
packages = ["."]
revision = "2bca23e0e452137f789efbc8610126fd8b94f73b"
[[projects]]
branch = "master"
name = "github.com/mitchellh/mapstructure"
@ -222,8 +232,8 @@
[[projects]]
name = "github.com/modern-go/reflect2"
packages = ["."]
revision = "1df9eeb2bb81f327b96228865c5687bc2194af3f"
version = "1.0.0"
revision = "4b7aa43c6742a2c18fdef89dd197aaae7dac7ccd"
version = "1.0.1"
[[projects]]
branch = "master"
@ -309,6 +319,18 @@
revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53"
version = "v1.1"
[[projects]]
branch = "master"
name = "github.com/petar/GoLLRB"
packages = ["llrb"]
revision = "53be0d36a84c2a886ca057d34b6aa4468df9ccb4"
[[projects]]
name = "github.com/peterbourgon/diskv"
packages = ["."]
revision = "5f041e8faa004a95c88a202771f4cc3e991971e6"
version = "v2.0.1"
[[projects]]
name = "github.com/pkg/errors"
packages = ["."]
@ -316,19 +338,19 @@
version = "v0.8.0"
[[projects]]
branch = "master"
name = "github.com/prometheus/client_golang"
packages = [
"prometheus",
"prometheus/promhttp"
]
revision = "c5b7fccd204277076155f10851dad72b76a49317"
version = "v0.8.0"
revision = "ee1c9d7e23df7f011bdf6f12a5c9e7f0ae10a1fe"
[[projects]]
branch = "master"
name = "github.com/prometheus/client_model"
packages = ["go"]
revision = "99fa1f4be8e564e8a6b613da7fa6f46c9edafc6c"
revision = "5c3871d89910bfb32f5fcab2aa4b9ec68e65a99f"
[[projects]]
branch = "master"
@ -349,7 +371,7 @@
"nfs",
"xfs"
]
revision = "8b1c2da0d56deffdbb9e48d4414b4e674bd8083e"
revision = "ae68e2d4c00fed4943b5f6698d504a5fe083da8a"
[[projects]]
name = "github.com/spf13/afero"
@ -357,8 +379,8 @@
".",
"mem"
]
revision = "63644898a8da0bc22138abf860edaf5277b6102e"
version = "v1.1.0"
revision = "787d034dfe70e44075ccc060d346146ef53270ad"
version = "v1.1.1"
[[projects]]
name = "github.com/spf13/pflag"
@ -369,8 +391,8 @@
[[projects]]
name = "github.com/zakjan/cert-chain-resolver"
packages = ["certUtil"]
revision = "c222fb53d84f5c835aab8027b5d422d4089f9d29"
version = "1.0.1"
revision = "6076e1ded27284d6df12668dba6bee76fc17f84e"
version = "1.0.2"
[[projects]]
branch = "master"
@ -380,7 +402,7 @@
"ed25519/internal/edwards25519",
"ssh/terminal"
]
revision = "a3beeb748656e13e54256fd2cde19e058f41f60f"
revision = "a49355c7e3f8fe157a85be2f77e6e269a0f89602"
[[projects]]
branch = "master"
@ -399,7 +421,7 @@
"publicsuffix",
"trace"
]
revision = "dfa909b99c79129e1100513e5cd36307665e5723"
revision = "cffdcf672aee934982473246bc7e9a8ba446aa9b"
[[projects]]
branch = "master"
@ -411,7 +433,7 @@
"jws",
"jwt"
]
revision = "770e5ebd4ab27c4d70b0983674d138217f5e2c72"
revision = "ef147856a6ddbb60760db74283d2424e98c87bff"
[[projects]]
branch = "master"
@ -420,7 +442,7 @@
"unix",
"windows"
]
revision = "c11f84a56e43e20a78cee75a7c034031ecf57d1f"
revision = "1b2967e3c290b7c545b3db0deeda16e9be4f98a2"
[[projects]]
name = "golang.org/x/text"
@ -475,14 +497,14 @@
"internal/urlfetch",
"urlfetch"
]
revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a"
version = "v1.0.0"
revision = "b1f26356af11148e710935ed1ac8a7f5702c7612"
version = "v1.1.0"
[[projects]]
branch = "master"
name = "google.golang.org/genproto"
packages = ["googleapis/rpc/status"]
revision = "694d95ba50e67b2e363f3483057db5d4910c18f9"
revision = "e92b116572682a5b432ddd840aeaba2a559eeff1"
[[projects]]
name = "google.golang.org/grpc"
@ -491,15 +513,16 @@
"balancer",
"balancer/base",
"balancer/roundrobin",
"channelz",
"codes",
"connectivity",
"credentials",
"encoding",
"encoding/proto",
"grpclb/grpc_lb_v1/messages",
"grpclog",
"internal",
"internal/backoff",
"internal/channelz",
"internal/grpcrand",
"keepalive",
"metadata",
"naming",
@ -512,8 +535,8 @@
"tap",
"transport"
]
revision = "41344da2231b913fa3d983840a57a6b1b7b631a1"
version = "v1.12.0"
revision = "168a6198bcb0ef175f7dacec0b8691fc141dc9b8"
version = "v1.13.0"
[[projects]]
name = "gopkg.in/fsnotify/fsnotify.v1"
@ -577,12 +600,13 @@
"rbac/v1alpha1",
"rbac/v1beta1",
"scheduling/v1alpha1",
"scheduling/v1beta1",
"settings/v1alpha1",
"storage/v1",
"storage/v1alpha1",
"storage/v1beta1"
]
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[projects]]
name = "k8s.io/apiextensions-apiserver"
@ -594,7 +618,7 @@
"pkg/client/clientset/clientset/typed/apiextensions/v1beta1",
"pkg/features"
]
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[projects]]
name = "k8s.io/apimachinery"
@ -604,9 +628,6 @@
"pkg/api/meta",
"pkg/api/resource",
"pkg/api/validation",
"pkg/apimachinery",
"pkg/apimachinery/announced",
"pkg/apimachinery/registered",
"pkg/apis/meta/internalversion",
"pkg/apis/meta/v1",
"pkg/apis/meta/v1/unstructured",
@ -652,7 +673,7 @@
"third_party/forked/golang/netutil",
"third_party/forked/golang/reflect"
]
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[projects]]
name = "k8s.io/apiserver"
@ -665,7 +686,7 @@
"pkg/util/feature",
"pkg/util/logs"
]
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[projects]]
name = "k8s.io/client-go"
@ -706,6 +727,7 @@
"informers/rbac/v1beta1",
"informers/scheduling",
"informers/scheduling/v1alpha1",
"informers/scheduling/v1beta1",
"informers/settings",
"informers/settings/v1alpha1",
"informers/storage",
@ -763,6 +785,8 @@
"kubernetes/typed/rbac/v1beta1/fake",
"kubernetes/typed/scheduling/v1alpha1",
"kubernetes/typed/scheduling/v1alpha1/fake",
"kubernetes/typed/scheduling/v1beta1",
"kubernetes/typed/scheduling/v1beta1/fake",
"kubernetes/typed/settings/v1alpha1",
"kubernetes/typed/settings/v1alpha1/fake",
"kubernetes/typed/storage/v1",
@ -791,12 +815,14 @@
"listers/rbac/v1alpha1",
"listers/rbac/v1beta1",
"listers/scheduling/v1alpha1",
"listers/scheduling/v1beta1",
"listers/settings/v1alpha1",
"listers/storage/v1",
"listers/storage/v1alpha1",
"listers/storage/v1beta1",
"pkg/apis/clientauthentication",
"pkg/apis/clientauthentication/v1alpha1",
"pkg/apis/clientauthentication/v1beta1",
"pkg/version",
"plugin/pkg/client/auth",
"plugin/pkg/client/auth/azure",
@ -826,6 +852,7 @@
"util/buffer",
"util/cert",
"util/cert/triple",
"util/connrotation",
"util/exec",
"util/flowcontrol",
"util/homedir",
@ -834,13 +861,13 @@
"util/retry",
"util/workqueue"
]
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[projects]]
branch = "master"
name = "k8s.io/kube-openapi"
packages = ["pkg/util/proto"]
revision = "41e43949ca69d04b66104069ed3ffd619b289b3d"
revision = "0cf8f7e6ed1d2e3d47d02e3b6e559369af24d803"
[[projects]]
name = "k8s.io/kubernetes"
@ -858,6 +885,8 @@
"pkg/apis/core/validation",
"pkg/apis/extensions",
"pkg/apis/networking",
"pkg/apis/policy",
"pkg/apis/scheduling",
"pkg/capabilities",
"pkg/cloudprovider",
"pkg/controller",
@ -867,10 +896,13 @@
"pkg/kubelet/container",
"pkg/kubelet/types",
"pkg/kubelet/util/format",
"pkg/kubelet/util/ioutils",
"pkg/kubelet/util/sliceutils",
"pkg/master/ports",
"pkg/scheduler/algorithm",
"pkg/scheduler/algorithm/priorities/util",
"pkg/scheduler/api",
"pkg/scheduler/cache",
"pkg/scheduler/util",
"pkg/security/apparmor",
"pkg/serviceaccount",
"pkg/util/file",
@ -889,17 +921,17 @@
"pkg/volume/util/recyclerclient",
"third_party/forked/golang/expansion"
]
revision = "v1.10.3"
revision = "v1.11.0"
[[projects]]
branch = "master"
name = "k8s.io/utils"
packages = ["exec"]
revision = "258e2a2fa64568210fbd6267cf1d8fd87c3cb86e"
revision = "ab9069044f32ba0c6da081bb46bb0b12e3862c21"
[solve-meta]
analyzer-name = "dep"
analyzer-version = 1
inputs-digest = "5feeef324f0cbac72e0234d5f649fc7c4233f4e2bb4477e454e047b5461d7569"
inputs-digest = "a9315cc322f719f566fce26b3f0de8594ab9d4a074febfc1f0de3c99371c37c4"
solver-name = "gps-cdcl"
solver-version = 1

View file

@ -78,7 +78,7 @@
[[constraint]]
name = "github.com/prometheus/client_golang"
version = "0.8.0"
branch = "master"
[[constraint]]
name = "github.com/spf13/pflag"
@ -98,24 +98,24 @@
[[constraint]]
name = "k8s.io/kubernetes"
revision = "v1.10.3"
revision = "v1.11.0"
[[constraint]]
name = "k8s.io/api"
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[constraint]]
name = "k8s.io/apimachinery"
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[constraint]]
name = "k8s.io/client-go"
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[constraint]]
name = "k8s.io/apiextensions-apiserver"
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"
[[constraint]]
name = "k8s.io/apiserver"
revision = "kubernetes-1.10.3"
revision = "kubernetes-1.11.0"

154
Makefile
View file

@ -15,22 +15,22 @@
.PHONY: all
all: all-container
BUILDTAGS=
# Use the 0.0 tag for testing, it shouldn't clobber any release builds
TAG?=0.15.0
REGISTRY?=quay.io/kubernetes-ingress-controller
GOOS?=linux
DOCKER?=docker
SED_I?=sed -i
TAG ?= 0.18.0
REGISTRY ?= quay.io/kubernetes-ingress-controller
DOCKER ?= docker
SED_I ?= sed -i
GOHOSTOS ?= $(shell go env GOHOSTOS)
# e2e settings
# Allow limiting the scope of the e2e tests. By default run everything
FOCUS?=.*
FOCUS ?= .*
# number of parallel test
E2E_NODES?=3
E2E_NODES ?= 4
# slow test only if takes > 40s
SLOW_E2E_THRESHOLD ?= 40
NODE_IP ?= $(shell minikube ip)
ifeq ($(GOHOSTOS),darwin)
SED_I=sed -i ''
@ -38,28 +38,30 @@ endif
REPO_INFO=$(shell git config --get remote.origin.url)
ifndef COMMIT
COMMIT := git-$(shell git rev-parse --short HEAD)
ifndef GIT_COMMIT
GIT_COMMIT := git-$(shell git rev-parse --short HEAD)
endif
PKG=k8s.io/ingress-nginx
PKG = k8s.io/ingress-nginx
ARCH ?= $(shell go env GOARCH)
GOARCH = ${ARCH}
DUMB_ARCH = ${ARCH}
GOBUILD_FLAGS :=
ALL_ARCH = amd64 arm arm64 ppc64le s390x
QEMUVERSION=v2.12.0
QEMUVERSION = v2.12.0-1
BUSTED_ARGS=-v --pattern=_test
BUSTED_ARGS =-v --pattern=_test
IMGNAME = nginx-ingress-controller
IMAGE = $(REGISTRY)/$(IMGNAME)
MULTI_ARCH_IMG = $(IMAGE)-$(ARCH)
# Set default base image dynamically for each arch
BASEIMAGE?=quay.io/kubernetes-ingress-controller/nginx-$(ARCH):0.49
BASEIMAGE?=quay.io/kubernetes-ingress-controller/nginx-$(ARCH):0.58
ifeq ($(ARCH),arm)
QEMUARCH=arm
@ -67,7 +69,7 @@ ifeq ($(ARCH),arm)
DUMB_ARCH=armhf
endif
ifeq ($(ARCH),arm64)
QEMUARCH=aarch64
QEMUARCH=aarch64
endif
ifeq ($(ARCH),ppc64le)
QEMUARCH=ppc64le
@ -75,11 +77,19 @@ ifeq ($(ARCH),ppc64le)
DUMB_ARCH=ppc64el
endif
ifeq ($(ARCH),s390x)
QEMUARCH=s390x
QEMUARCH=s390x
endif
TEMP_DIR := $(shell mktemp -d)
DEF_VARS:=ARCH=$(ARCH) \
TAG=$(TAG) \
PKG=$(PKG) \
GOARCH=$(GOARCH) \
GIT_COMMIT=$(GIT_COMMIT) \
REPO_INFO=$(REPO_INFO) \
PWD=$(PWD)
DOCKERFILE := $(TEMP_DIR)/rootfs/Dockerfile
.PHONY: image-info
@ -101,10 +111,15 @@ all-container: $(addprefix sub-container-,$(ALL_ARCH))
all-push: $(addprefix sub-push-,$(ALL_ARCH))
.PHONY: container
container: .container-$(ARCH)
container: clean-container .container-$(ARCH)
.PHONY: .container-$(ARCH)
.container-$(ARCH):
@echo "+ Copying artifact to temporary directory"
mkdir -p $(TEMP_DIR)/rootfs
cp bin/$(ARCH)/nginx-ingress-controller $(TEMP_DIR)/rootfs/nginx-ingress-controller
@echo "+ Building container image $(MULTI_ARCH_IMG):$(TAG)"
cp -RP ./* $(TEMP_DIR)
$(SED_I) "s|BASEIMAGE|$(BASEIMAGE)|g" $(DOCKERFILE)
$(SED_I) "s|QEMUARCH|$(QEMUARCH)|g" $(DOCKERFILE)
@ -119,13 +134,18 @@ else
$(SED_I) "s/CROSS_BUILD_//g" $(DOCKERFILE)
endif
$(DOCKER) build -t $(MULTI_ARCH_IMG):$(TAG) $(TEMP_DIR)/rootfs
$(DOCKER) build --no-cache --pull -t $(MULTI_ARCH_IMG):$(TAG) $(TEMP_DIR)/rootfs
ifeq ($(ARCH), amd64)
# This is for maintaining backward compatibility
$(DOCKER) tag $(MULTI_ARCH_IMG):$(TAG) $(IMAGE):$(TAG)
endif
.PHONY: clean-container
clean-container:
@echo "+ Deleting container image $(MULTI_ARCH_IMG):$(TAG)"
$(DOCKER) rmi -f $(MULTI_ARCH_IMG):$(TAG) || true
.PHONY: register-qemu
register-qemu:
# Register /usr/bin/qemu-ARCH-static as the handler for binaries in multiple platforms
@ -141,78 +161,68 @@ ifeq ($(ARCH), amd64)
$(DOCKER) push $(IMAGE):$(TAG)
endif
.PHONY: build
build:
@echo "+ Building bin/$(ARCH)/nginx-ingress-controller"
@$(DEF_VARS) \
GOBUILD_FLAGS="$(GOBUILD_FLAGS)" \
build/go-in-docker.sh build/build.sh
.PHONY: clean
clean:
$(DOCKER) rmi -f $(MULTI_ARCH_IMG):$(TAG) || true
rm -rf bin/ .gocache/ .env
.PHONY: build
build: clean
CGO_ENABLED=0 GOOS=${GOOS} GOARCH=${GOARCH} go build -a -installsuffix cgo \
-ldflags "-s -w -X ${PKG}/version.RELEASE=${TAG} -X ${PKG}/version.COMMIT=${COMMIT} -X ${PKG}/version.REPO=${REPO_INFO}" \
-o ${TEMP_DIR}/rootfs/nginx-ingress-controller ${PKG}/cmd/nginx
.PHONY: verify-all
verify-all:
@./hack/verify-all.sh
.PHONY: static-check
static-check:
@$(DEF_VARS) \
build/go-in-docker.sh build/static-check.sh
.PHONY: test
test:
@go test -v -race -tags "$(BUILDTAGS) cgo" $(shell go list ${PKG}/... | grep -v vendor | grep -v '/test/e2e')
@$(DEF_VARS) \
NODE_IP=$(NODE_IP) \
DOCKER_OPTS="-i --net=host" \
build/go-in-docker.sh build/test.sh
.PHONY: lua-test
lua-test:
@busted $(BUSTED_ARGS) ./rootfs/etc/nginx/lua/test;
@$(DEF_VARS) \
BUSTED_ARGS="$(BUSTED_ARGS)" \
build/go-in-docker.sh build/test-lua.sh
.PHONY: e2e-test
e2e-test:
@ginkgo version || go get -u github.com/onsi/ginkgo/ginkgo
@ginkgo build ./test/e2e
@KUBECONFIG=${HOME}/.kube/config ginkgo \
-randomizeSuites \
-randomizeAllSpecs \
-flakeAttempts=2 \
--focus=$(FOCUS) \
-p \
-trace \
-nodes=$(E2E_NODES) \
./test/e2e/e2e.test
@$(DEF_VARS) \
FOCUS=$(FOCUS) \
E2E_NODES=$(E2E_NODES) \
DOCKER_OPTS="-i --net=host" \
NODE_IP=$(NODE_IP) \
SLOW_E2E_THRESHOLD=$(SLOW_E2E_THRESHOLD) \
build/go-in-docker.sh build/e2e-tests.sh
.PHONY: cover
cover:
@rm -rf coverage.txt
@for d in `go list ./... | grep -v vendor | grep -v '/test/e2e' | grep -v 'images/grpc-fortune-teller'`; do \
t=$$(date +%s); \
go test -coverprofile=cover.out -covermode=atomic $$d || exit 1; \
echo "Coverage test $$d took $$(($$(date +%s)-t)) seconds"; \
if [ -f cover.out ]; then \
cat cover.out >> coverage.txt; \
rm cover.out; \
fi; \
done
@echo "Uploading coverage results..."
@$(DEF_VARS) \
DOCKER_OPTS="-i --net=host" \
build/go-in-docker.sh build/cover.sh
echo "Uploading coverage results..."
@curl -s https://codecov.io/bash | bash
.PHONY: vet
vet:
@go vet $(shell go list ${PKG}/... | grep -v vendor)
.PHONY: luacheck
luacheck:
luacheck -q ./rootfs/etc/nginx/lua/
.PHONY: release
release: all-container all-push
echo "done"
.PHONY: docker-build
docker-build: all-container
.PHONY: docker-push
docker-push: all-push
.PHONY: check_dead_links
check_dead_links:
docker run -t -v $$PWD:/tmp aledbf/awesome_bot:0.1 --allow-dupe --allow-redirect $(shell find $$PWD -mindepth 1 -name "*.md" -printf '%P\n' | grep -v vendor | grep -v Changelog.md)
docker run -t \
-v $$PWD:/tmp aledbf/awesome_bot:0.1 \
--allow-dupe \
--allow-redirect $(shell find $$PWD -mindepth 1 -name "*.md" -printf '%P\n' | grep -v vendor | grep -v Changelog.md)
.PHONY: dep-ensure
dep-ensure:
@ -223,12 +233,22 @@ dep-ensure:
.PHONY: dev-env
dev-env:
@./hack/build-dev-env.sh
@build/dev-env.sh
.PHONY: live-docs
live-docs:
@docker run --rm -it -p 3000:3000 -v ${PWD}:/docs aledbf/mkdocs:0.1
@docker build --pull -t ingress-nginx/mkdocs build/mkdocs
@docker run --rm -it -p 3000:3000 -v ${PWD}:/docs ingress-nginx/mkdocs
.PHONY: build-docs
build-docs:
@docker run --rm -it -v ${PWD}:/docs aledbf/mkdocs:0.1 build
@docker build --pull -t ingress-nginx/mkdocs build/mkdocs
@docker run --rm -it -v ${PWD}:/docs ingress-nginx/mkdocs build
.PHONY: misspell
misspell:
@go get github.com/client9/misspell/cmd/misspell
misspell \
-locale US \
-error \
cmd/* internal/* deploy/* docs/* design/* test/* README.md

2
OWNERS
View file

@ -4,6 +4,8 @@ approvers:
- sig-network-leads
- ingress-nginx-admins
- ingress-nginx-maintainers
- ElvinEfendi
- antoineco
reviewers:
- aledbf

View file

@ -10,18 +10,16 @@
[![GitHub license](https://img.shields.io/github/license/kubernetes/ingress-nginx.svg)](https://github.com/kubernetes/ingress-nginx/blob/master/LICENSE)
[![GitHub stars](https://img.shields.io/github/stars/kubernetes/ingress-nginx.svg)](https://github.com/kubernetes/ingress-nginx/stargazers)
[![GitHub stars](https://img.shields.io/badge/contributions-welcome-orange.svg)](https://github.com/kubernetes/ingress-nginx/blob/master/CONTRIBUTING.md)
[![FOSSA Status](https://app.fossa.io/api/projects/git%2Bgithub.com%2Fkubernetes%2Fingress-nginx.svg?type=shield)](https://app.fossa.io/projects/git%2Bgithub.com%2Fkubernetes%2Fingress-nginx?ref=badge_shield)
# Get Involved
* **Contributing**: Pull requests are welcome!
* Read [`CONTRIBUTING.md`](CONTRIBUTING.md) and check out [help-wanted](https://github.com/kubernetes/ingress-nginx/labels/help%20wanted) issues
* Submit github issues for any feature enhancements, bugs or documentation problems
* **Support**: Join to [Kubernetes Slack](http://slack.kubernetes.io/) to ask questions to get support from the maintainers and other developers
* Questions/comments can also be posted as [github issues](https://github.com/kubernetes/ingress-nginx/issues)
* **Discuss**: Tweet using the `#IngressNginx` hashtag
- **Contributing**: Pull requests are welcome!
- Read [`CONTRIBUTING.md`](CONTRIBUTING.md) and check out [help-wanted](https://github.com/kubernetes/ingress-nginx/labels/help%20wanted) issues
- Submit github issues for any feature enhancements, bugs or documentation problems
- **Support**: Join to [Kubernetes Slack](http://slack.kubernetes.io/) to ask questions to get support from the maintainers and other developers
- Questions/comments can also be posted as [github issues](https://github.com/kubernetes/ingress-nginx/issues)
- **Discuss**: Tweet using the `#IngressNginx` hashtag
## Description
@ -37,41 +35,33 @@ The Ingress resource embodies this idea, and an Ingress controller is meant to h
An Ingress Controller is a daemon, deployed as a Kubernetes Pod, that watches the apiserver's `/ingresses` endpoint for updates to the [Ingress resource](https://kubernetes.io/docs/concepts/services-networking/ingress/). Its job is to satisfy requests for Ingresses.
## Documentation
To check out [Live Docs](https://kubernetes.github.io/ingress-nginx/)
## Questions
For questions and support please use the [#ingress-nginx](https://kubernetes.slack.com/messages/CANQGM8BA/) channel in the [Kubernetes Slack](http://slack.kubernetes.io/) or [kubernetes-users](https://groups.google.com/forum/#!forum/kubernetes-users) mailing list. The issue list of this repo is **exclusively** for bug reports and feature requests.
## Issues
Please make sure to read the [Issue Reporting Checklist](https://github.com/kubernetes/ingress-nginx/blob/master/CONTRIBUTING.md#issue-reporting-guidelines) before opening an issue. Issues not conforming to the guidelines may be closed immediately.
## Changelog
Detailed changes for each release are documented in the [Changelog.md](Changelog.md)
## Contribution
Please make sure to read the [Contributing Guide](CONTRIBUTING.md) before making a pull request.
Thank you to all the people who already contributed to NGINX Ingress Controller!
## Code of Conduct
This project adheres to the [Kubernetes Community Code of Conduct](https://git.k8s.io/community/code-of-conduct.md).
By participating in this project you agree to abide by its terms.
## License
[Apache License 2.0](https://github.com/kubernetes/ingress-nginx/blob/master/LICENSE)

50
build/build.sh Executable file
View file

@ -0,0 +1,50 @@
#!/bin/bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
declare -a mandatory
mandatory=(
PKG
ARCH
GIT_COMMIT
REPO_INFO
TAG
)
missing=false
for var in "${mandatory[@]}"; do
if [[ -z "${!var:-}" ]]; then
echo "Environment variable $var must be set"
missing=true
fi
done
if [ "$missing" = true ]; then
exit 1
fi
export CGO_ENABLED=0
go build \
${GOBUILD_FLAGS} \
-ldflags "-s -w \
-X ${PKG}/version.RELEASE=${TAG} \
-X ${PKG}/version.COMMIT=${GIT_COMMIT} \
-X ${PKG}/version.REPO=${REPO_INFO}" \
-o bin/${ARCH}/nginx-ingress-controller ${PKG}/cmd/nginx

35
build/cover.sh Executable file
View file

@ -0,0 +1,35 @@
#!/bin/bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
if [ -z "${PKG}" ]; then
echo "PKG must be set"
exit 1
fi
rm -rf coverage.txt
for d in `go list ${PKG}/... | grep -v vendor | grep -v '/test/e2e' | grep -v images`; do
t=$(date +%s);
go test -coverprofile=cover.out -covermode=atomic $d || exit 1;
echo "Coverage test $d took $(($(date +%s)-$t)) seconds";
if [ -f cover.out ]; then
cat cover.out >> coverage.txt;
rm cover.out;
fi;
done

View file

@ -14,17 +14,32 @@
# See the License for the specific language governing permissions and
# limitations under the License.
: "${NAMESPACE:=ingress-nginx}"
set -o errexit
set -o nounset
set -o pipefail
SKIP_MINIKUBE_START=${SKIP_MINIKUBE_START:-}
NAMESPACE="${NAMESPACE:-ingress-nginx}"
echo "NAMESPACE is set to ${NAMESPACE}"
test $(minikube status | grep Running | wc -l) -eq 2 && $(minikube status | grep -q 'Correctly Configured') || minikube start
eval $(minikube docker-env)
export TAG=dev
export REGISTRY=ingress-controller
export ARCH=amd64
export REGISTRY=${REGISTRY:-ingress-controller}
DEV_IMAGE=${REGISTRY}/nginx-ingress-controller:${TAG}
if [ -z "${SKIP_MINIKUBE_START}" ]; then
test $(minikube status | grep Running | wc -l) -eq 2 && $(minikube status | grep -q 'Correctly Configured') || minikube start \
--extra-config=kubelet.sync-frequency=1s \
--extra-config=apiserver.authorization-mode=RBAC
eval $(minikube docker-env)
fi
echo "[dev-env] building container"
ARCH=amd64 make build container
make build container
docker save "${DEV_IMAGE}" | (eval $(minikube docker-env) && docker load) || true
echo "[dev-env] installing kubectl"
kubectl version || brew install kubectl
@ -38,4 +53,4 @@ kubectl set image \
deployments \
--namespace ingress-nginx \
--selector app=ingress-nginx \
nginx-ingress-controller=${REGISTRY}/nginx-ingress-controller:${TAG}
nginx-ingress-controller=${DEV_IMAGE}

69
build/e2e-tests.sh Executable file
View file

@ -0,0 +1,69 @@
#!/bin/bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
declare -a mandatory
mandatory=(
NODE_IP
SLOW_E2E_THRESHOLD
PKG
FOCUS
E2E_NODES
)
missing=false
for var in ${mandatory[@]}; do
if [[ -z "${!var+x}" ]]; then
echo "Environment variable $var must be set"
missing=true
fi
done
if [ "$missing" = true ];then
exit 1
fi
SCRIPT_ROOT=$(dirname ${BASH_SOURCE})/..
mkdir -p ${SCRIPT_ROOT}/test/binaries
TEST_BINARIES=$( cd "${SCRIPT_ROOT}/test/binaries" ; pwd -P )
export PATH=${TEST_BINARIES}:$PATH
if ! [ -x "$(command -v kubectl)" ]; then
echo "downloading kubectl..."
curl -sSLo ${TEST_BINARIES}/kubectl \
https://storage.googleapis.com/kubernetes-release/release/v1.11.0/bin/linux/amd64/kubectl
chmod +x ${TEST_BINARIES}/kubectl
fi
ginkgo build ./test/e2e
exec -- \
ginkgo \
-randomizeSuites \
-randomizeAllSpecs \
-flakeAttempts=2 \
--focus=${FOCUS} \
-p \
-trace \
-nodes=${E2E_NODES} \
-slowSpecThreshold=${SLOW_E2E_THRESHOLD} \
test/e2e/e2e.test

81
build/go-in-docker.sh Executable file
View file

@ -0,0 +1,81 @@
#!/bin/bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
declare -a mandatory
mandatory=(
PKG
ARCH
GIT_COMMIT
REPO_INFO
TAG
HOME
)
missing=false
for var in ${mandatory[@]}; do
if [[ -z "${!var+x}" ]]; then
echo "Environment variable $var must be set"
missing=true
fi
done
if [ "$missing" = true ];then
exit 1
fi
E2E_IMAGE=quay.io/kubernetes-ingress-controller/e2e:v08152018-56ed290
DOCKER_OPTS=${DOCKER_OPTS:-""}
FLAGS=$@
tee .env << EOF
PKG=${PKG:-""}
ARCH=${ARCH:-""}
GIT_COMMIT=${GIT_COMMIT:-""}
E2E_NODES=${E2E_NODES:-4}
FOCUS=${FOCUS:-.*}
TAG=${TAG:-"0.0"}
HOME=${HOME:-/root}
KUBECONFIG=${HOME}/.kube/config
GOARCH=${GOARCH}
GOBUILD_FLAGS=${GOBUILD_FLAGS:-"-v"}
PWD=${PWD}
BUSTED_ARGS=${BUSTED_ARGS:-""}
REPO_INFO=${REPO_INFO:-local}
NODE_IP=${NODE_IP:-127.0.0.1}
SLOW_E2E_THRESHOLD=${SLOW_E2E_THRESHOLD:-40}
EOF
docker run \
--tty \
--rm \
${DOCKER_OPTS} \
-v ${HOME}/.kube:/${HOME}/.kube \
-v ${HOME}/.minikube:${HOME}/.minikube \
-v ${PWD}:/go/src/${PKG} \
-v ${PWD}/.gocache:${HOME}/.cache/go-build \
-v ${PWD}/bin/${ARCH}:/go/bin/linux_${ARCH} \
-w /go/src/${PKG} \
--env-file .env \
--entrypoint ${FLAGS} \
${E2E_IMAGE}
rm .env

39
build/mkdocs/Dockerfile Normal file
View file

@ -0,0 +1,39 @@
# Copyright 2018 The Kubernetes Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM alpine:3.7
RUN apk update && apk add --no-cache \
git \
git-fast-import \
openssh \
python3 \
python3-dev \
curl \
&& python3 -m ensurepip \
&& rm -r /usr/lib/python*/ensurepip \
&& pip3 install --upgrade pip setuptools \
&& rm -r /root/.cache \
&& rm -rf /var/cache/apk/*
RUN curl -sSL https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/requirements-docs.txt -o requirements.txt \
&& pip install -U -r requirements.txt
WORKDIR /docs
EXPOSE 3000
ENTRYPOINT ["mkdocs"]
CMD ["serve", "--dev-addr=0.0.0.0:3000", "--livereload"]

View file

@ -1,4 +1,4 @@
#!/usr/bin/env bash
#!/bin/bash
# Copyright 2018 The Kubernetes Authors.
#
@ -14,17 +14,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
install()
{
package="$1"
version="$2"
set -o errexit
set -o nounset
set -o pipefail
if luarocks list --porcelain $package $version | grep -q "installed"; then
echo $package already installed, skipping ;
else
sudo luarocks install $package $version;
fi
}
if [ -z "${PKG}" ]; then
echo "PKG must be set"
exit 1
fi
install busted 2.0.rc12
install lua-cjson 2.1.0-1
hack/verify-all.sh
luacheck -q rootfs/etc/nginx/lua/

29
build/test-lua.sh Executable file
View file

@ -0,0 +1,29 @@
#!/bin/bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
set -o errexit
set -o nounset
set -o pipefail
resty \
-I ./rootfs/etc/nginx/lua \
-I /usr/local/lib/lua \
-I /usr/lib/lua-platform-path/lua/5.1 \
--shdict "configuration_data 5M" \
--shdict "certificate_data 16M" \
--shdict "balancer_ewma 1M" \
--shdict "balancer_ewma_last_touched_at 1M" \
./rootfs/etc/nginx/lua/test/run.lua ${BUSTED_ARGS} ./rootfs/etc/nginx/lua/test/

18
images/echoheaders/run.sh → build/test.sh Normal file → Executable file
View file

@ -14,12 +14,14 @@
# See the License for the specific language governing permissions and
# limitations under the License.
echo "Generating self-signed cert"
mkdir -p /certs
openssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 \
-keyout /certs/privateKey.key \
-out /certs/certificate.crt \
-subj "/C=UK/ST=Warwickshire/L=Leamington/O=OrgName/OU=IT Department/CN=example.com"
set -o errexit
set -o nounset
set -o pipefail
echo "Starting nginx"
nginx -g "daemon off;"
if [ -z "${PKG}" ]; then
echo "PKG must be set"
exit 1
fi
go test -v -race -tags "cgo" \
$(go list ${PKG}/... | grep -v vendor | grep -v '/test/e2e' | grep -v images | grep -v "docs/examples")

View file

@ -34,12 +34,12 @@ func resetForTesting(usage func()) {
func TestMandatoryFlag(t *testing.T) {
_, _, err := parseFlags()
if err == nil {
t.Fatalf("expected and error about default backend service")
t.Fatalf("Expected an error about default backend service")
}
}
func TestDefaults(t *testing.T) {
resetForTesting(func() { t.Fatal("bad parse") })
resetForTesting(func() { t.Fatal("Parsing failed") })
oldArgs := os.Args
defer func() { os.Args = oldArgs }()
@ -47,15 +47,15 @@ func TestDefaults(t *testing.T) {
showVersion, conf, err := parseFlags()
if err != nil {
t.Fatalf("unexpected error parsing default flags: %v", err)
t.Fatalf("Unexpected error parsing default flags: %v", err)
}
if showVersion {
t.Fatal("expected false but true was returned for flag show-version")
t.Fatal("Expected flag \"show-version\" to be false")
}
if conf == nil {
t.Fatal("expected a configuration but nil returned")
t.Fatal("Expected a controller Configuration")
}
}

View file

@ -21,7 +21,6 @@ import (
"fmt"
"os"
"runtime"
"time"
"github.com/golang/glog"
"github.com/spf13/pflag"
@ -39,101 +38,121 @@ func parseFlags() (bool, *controller.Configuration, error) {
var (
flags = pflag.NewFlagSet("", pflag.ExitOnError)
apiserverHost = flags.String("apiserver-host", "", "The address of the Kubernetes Apiserver "+
"to connect to in the format of protocol://address:port, e.g., "+
"http://localhost:8080. If not specified, the assumption is that the binary runs inside a "+
"Kubernetes cluster and local discovery is attempted.")
kubeConfigFile = flags.String("kubeconfig", "", "Path to kubeconfig file with authorization and master location information.")
apiserverHost = flags.String("apiserver-host", "",
`Address of the Kubernetes API server.
Takes the form "protocol://address:port". If not specified, it is assumed the
program runs inside a Kubernetes cluster and local discovery is attempted.`)
kubeConfigFile = flags.String("kubeconfig", "",
`Path to a kubeconfig file containing authorization and API server information.`)
defaultSvc = flags.String("default-backend-service", "",
`Service used to serve a 404 page for the default backend. Takes the form
namespace/name. The controller uses the first node port of this Service for
the default backend.`)
`Service used to serve HTTP requests not matching any known server name (catch-all).
Takes the form "namespace/name". The controller configures NGINX to forward
requests to the first port of this Service.`)
ingressClass = flags.String("ingress-class", "",
`Name of the ingress class to route through this controller.`)
`Name of the ingress class this controller satisfies.
The class of an Ingress object is set using the annotation "kubernetes.io/ingress.class".
All ingress classes are satisfied if this parameter is left empty.`)
configMap = flags.String("configmap", "",
`Name of the ConfigMap that contains the custom configuration to use`)
`Name of the ConfigMap containing custom global configurations for the controller.`)
publishSvc = flags.String("publish-service", "",
`Service fronting the ingress controllers. Takes the form namespace/name.
The controller will set the endpoint records on the ingress objects to reflect those on the service.`)
`Service fronting the Ingress controller.
Takes the form "namespace/name". When used together with update-status, the
controller mirrors the address of this service's endpoints to the load-balancer
status of all Ingress objects it satisfies.`)
tcpConfigMapName = flags.String("tcp-services-configmap", "",
`Name of the ConfigMap that contains the definition of the TCP services to expose.
The key in the map indicates the external port to be used. The value is the name of the
service with the format namespace/serviceName and the port of the service could be a
number of the name of the port.
The ports 80 and 443 are not allowed as external ports. This ports are reserved for the backend`)
`Name of the ConfigMap containing the definition of the TCP 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 number or name. TCP ports 80 and 443 are reserved by the
controller for servicing HTTP traffic.`)
udpConfigMapName = flags.String("udp-services-configmap", "",
`Name of the ConfigMap that contains the definition of the UDP services to expose.
The key in the map indicates the external port to be used. The value is the name of the
service with the format namespace/serviceName and the port of the service could be a
number of the name of the port.`)
`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.`)
resyncPeriod = flags.Duration("sync-period", 600*time.Second,
`Relist and confirm cloud resources this often. Default is 10 minutes`)
resyncPeriod = flags.Duration("sync-period", 0,
`Period at which the controller forces the repopulation of its local object stores. Disabled by default.`)
watchNamespace = flags.String("watch-namespace", apiv1.NamespaceAll,
`Namespace to watch for Ingress. Default is to watch all namespaces`)
`Namespace the controller watches for updates to Kubernetes objects.
This includes Ingresses, Services and all configuration resources. All
namespaces are watched if this parameter is left empty.`)
profiling = flags.Bool("profiling", true, `Enable profiling via web interface host:port/debug/pprof/`)
profiling = flags.Bool("profiling", true,
`Enable profiling via web interface host:port/debug/pprof/`)
defSSLCertificate = flags.String("default-ssl-certificate", "", `Name of the secret
that contains a SSL certificate to be used as default for a HTTPS catch-all server.
Takes the form <namespace>/<secret name>.`)
defSSLCertificate = flags.String("default-ssl-certificate", "",
`Secret containing a SSL certificate to be used by the default HTTPS server (catch-all).
Takes the form "namespace/name".`)
defHealthzURL = flags.String("health-check-path", "/healthz", `Defines
the URL to be used as health check inside in the default server in NGINX.`)
defHealthzURL = flags.String("health-check-path", "/healthz",
`URL path of the health check endpoint.
Configured inside the NGINX status server. All requests received on the port
defined by the healthz-port parameter are forwarded internally to this path.`)
updateStatus = flags.Bool("update-status", true, `Indicates if the
ingress controller should update the Ingress status IP/hostname. Default is true`)
updateStatus = flags.Bool("update-status", true,
`Update the load-balancer status of Ingress objects this controller satisfies.
Requires setting the publish-service parameter to a valid Service reference.`)
electionID = flags.String("election-id", "ingress-controller-leader", `Election id to use for status update.`)
electionID = flags.String("election-id", "ingress-controller-leader",
`Election id to use for Ingress status updates.`)
forceIsolation = flags.Bool("force-namespace-isolation", false,
`Force namespace isolation. This flag is required to avoid the reference of secrets or
configmaps located in a different namespace than the specified in the flag --watch-namespace.`)
`Force namespace isolation.
Prevents Ingress objects from referencing Secrets and ConfigMaps located in a
different namespace than their own. May be used together with watch-namespace.`)
updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true, `Indicates if the
ingress controller should update the Ingress status IP/hostname when the controller
is being stopped. Default is true`)
updateStatusOnShutdown = flags.Bool("update-status-on-shutdown", true,
`Update the load-balancer status of Ingress objects when the controller shuts down.
Requires the update-status parameter.`)
sortBackends = flags.Bool("sort-backends", false, `Defines if servers inside NGINX upstream should be sorted`)
sortBackends = flags.Bool("sort-backends", false,
`Sort servers inside NGINX upstreams.`)
useNodeInternalIP = flags.Bool("report-node-internal-ip-address", false,
`Defines if the nodes IP address to be returned in the ingress status should be the internal instead of the external IP address`)
`Set the load-balancer status of Ingress objects to internal Node addresses instead of external.
Requires the update-status parameter.`)
showVersion = flags.Bool("version", false,
`Shows release information about the NGINX Ingress controller`)
`Show release information about the NGINX Ingress controller and exit.`)
enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)
enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false,
`Enable SSL Passthrough.`)
httpPort = flags.Int("http-port", 80, `Indicates the port to use for HTTP traffic`)
httpsPort = flags.Int("https-port", 443, `Indicates the port to use for HTTPS traffic`)
statusPort = flags.Int("status-port", 18080, `Indicates the TCP port to use for exposing the nginx status page`)
sslProxyPort = flags.Int("ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
defServerPort = flags.Int("default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
healthzPort = flags.Int("healthz-port", 10254, "port for healthz endpoint.")
annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io", `Prefix of the ingress annotations.`)
annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io",
`Prefix of the Ingress annotations specific to the NGINX controller.`)
enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", true,
`Defines if the nginx ingress controller should check the secrets for missing intermediate CA certificates.
If the certificate contain issues chain issues is not possible to enable OCSP.
Default is true.`)
`Autocomplete SSL certificate chains with missing intermediate CA certificates.
A valid certificate chain is required to enable OCSP stapling. Certificates
uploaded to Kubernetes must have the "Authority Information Access" X.509 v3
extension for this to succeed.`)
syncRateLimit = flags.Float32("sync-rate-limit", 0.3,
`Define the sync frequency upper limit`)
publishStatusAddress = flags.String("publish-status-address", "",
`User customized address to be set in the status of ingress resources. The controller will set the
endpoint records on the ingress using this address.`)
`Customized address to set as the load-balancer status of Ingress objects this controller satisfies.
Requires the update-status parameter.`)
dynamicConfigurationEnabled = flags.Bool("enable-dynamic-configuration", false,
`When enabled controller will try to avoid Nginx reloads as much as possible by using Lua. Disabled by default.`)
dynamicConfigurationEnabled = flags.Bool("enable-dynamic-configuration", true,
`Dynamically refresh backends on topology changes instead of reloading NGINX.
Feature backed by OpenResty Lua libraries.`)
httpPort = flags.Int("http-port", 80, `Port to use for servicing HTTP traffic.`)
httpsPort = flags.Int("https-port", 443, `Port to use for servicing HTTPS traffic.`)
statusPort = flags.Int("status-port", 18080, `Port to use for exposing NGINX status pages.`)
sslProxyPort = flags.Int("ssl-passthrough-proxy-port", 442, `Port to use internally for SSL Passthrough.`)
defServerPort = flags.Int("default-server-port", 8181, `Port to use for exposing the default server (catch-all).`)
healthzPort = flags.Int("healthz-port", 10254, "Port to use for the healthz endpoint.")
)
flag.Set("logtostderr", "true")
@ -158,10 +177,10 @@ func parseFlags() (bool, *controller.Configuration, error) {
}
if *ingressClass != "" {
glog.Infof("Watching for ingress class: %s", *ingressClass)
glog.Infof("Watching for Ingress class: %s", *ingressClass)
if *ingressClass != class.DefaultClass {
glog.Warningf("only Ingress with class \"%v\" will be processed by this ingress controller", *ingressClass)
glog.Warningf("Only Ingresses with class %q will be processed by this Ingress controller", *ingressClass)
}
class.IngressClass = *ingressClass
@ -187,11 +206,11 @@ func parseFlags() (bool, *controller.Configuration, error) {
}
if *enableSSLPassthrough && !ing_net.IsPortAvailable(*sslProxyPort) {
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --ssl-passtrough-proxy-port", *sslProxyPort)
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --ssl-passthrough-proxy-port", *sslProxyPort)
}
if !*enableSSLChainCompletion {
glog.Warningf("Check of SSL certificate chain is disabled (--enable-ssl-chain-completion=false)")
glog.Warningf("SSL certificate chain completion is disabled (--enable-ssl-chain-completion=false)")
}
// LuaJIT is not available on arch s390x and ppc64le
@ -200,7 +219,7 @@ func parseFlags() (bool, *controller.Configuration, error) {
disableLua = true
if *dynamicConfigurationEnabled {
*dynamicConfigurationEnabled = false
glog.Warningf("Disabling dynamic configuration feature (LuaJIT is not available in s390x and ppc64le)")
glog.Warningf("LuaJIT is not available on s390x and ppc64le architectures: disabling dynamic configuration feature.")
}
}

View file

@ -29,6 +29,7 @@ import (
"time"
"github.com/golang/glog"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -40,11 +41,23 @@ import (
"k8s.io/ingress-nginx/internal/file"
"k8s.io/ingress-nginx/internal/ingress/controller"
"k8s.io/ingress-nginx/internal/ingress/metric"
"k8s.io/ingress-nginx/internal/k8s"
"k8s.io/ingress-nginx/internal/net/ssl"
"k8s.io/ingress-nginx/version"
)
const (
// High enough QPS to fit all expected use cases. QPS=0 is not set here, because
// client code is overriding it.
defaultQPS = 1e6
// High enough Burst to fit all expected use cases. Burst=0 is not set here, because
// client code is overriding it.
defaultBurst = 1e6
fakeCertificate = "default-fake-certificate"
)
func main() {
rand.Seed(time.Now().UnixNano())
@ -71,36 +84,33 @@ func main() {
handleFatalInitError(err)
}
ns, name, err := k8s.ParseNameNS(conf.DefaultService)
defSvcNs, defSvcName, err := k8s.ParseNameNS(conf.DefaultService)
if err != nil {
glog.Fatal(err)
}
_, err = kubeClient.CoreV1().Services(ns).Get(name, metav1.GetOptions{})
_, err = kubeClient.CoreV1().Services(defSvcNs).Get(defSvcName, metav1.GetOptions{})
if err != nil {
// TODO (antoineco): compare with error types from k8s.io/apimachinery/pkg/api/errors
if strings.Contains(err.Error(), "cannot get services in the namespace") {
glog.Fatalf("✖ It seems the cluster it is running with Authorization enabled (like RBAC) and there is no permissions for the ingress controller. Please check the configuration")
glog.Fatalf("✖ The cluster seems to be running with a restrictive Authorization mode and the Ingress controller does not have the required permissions to operate normally.")
}
glog.Fatalf("no service with name %v found: %v", conf.DefaultService, err)
glog.Fatalf("No service with name %v found: %v", conf.DefaultService, err)
}
glog.Infof("validated %v as the default backend", conf.DefaultService)
glog.Infof("Validated %v as the default backend.", conf.DefaultService)
if conf.Namespace != "" {
_, err = kubeClient.CoreV1().Namespaces().Get(conf.Namespace, metav1.GetOptions{})
if err != nil {
glog.Fatalf("no namespace with name %v found: %v", conf.Namespace, err)
glog.Fatalf("No namespace with name %v found: %v", conf.Namespace, err)
}
}
if conf.ResyncPeriod.Seconds() < 10 {
glog.Fatalf("resync period (%vs) is too low", conf.ResyncPeriod.Seconds())
}
// create the default SSL certificate (dummy)
defCert, defKey := ssl.GetFakeSSLCert()
c, err := ssl.AddOrUpdateCertAndKey(fakeCertificate, defCert, defKey, []byte{}, fs)
if err != nil {
glog.Fatalf("Error generating self signed certificate: %v", err)
glog.Fatalf("Error generating self-signed certificate: %v", err)
}
conf.FakeCertificatePath = c.PemFileName
@ -108,14 +118,33 @@ func main() {
conf.Client = kubeClient
ngx := controller.NewNGINXController(conf, fs)
reg := prometheus.NewRegistry()
reg.MustRegister(prometheus.NewGoCollector())
reg.MustRegister(prometheus.NewProcessCollector(os.Getpid(), ""))
mc, err := metric.NewCollector(conf.ListenPorts.Status, reg)
if err != nil {
glog.Fatalf("Error creating prometheus collector: %v", err)
}
mc.Start()
ngx := controller.NewNGINXController(conf, mc, fs)
go handleSigterm(ngx, func(code int) {
os.Exit(code)
})
mux := http.NewServeMux()
go registerHandlers(conf.EnableProfiling, conf.ListenPorts.Health, ngx, mux)
if conf.EnableProfiling {
registerProfiler(mux)
}
registerHealthz(ngx, mux)
registerMetrics(reg, mux)
registerHandlers(mux)
go startHTTPServer(conf.ListenPorts.Health, mux)
ngx.Start()
}
@ -130,24 +159,26 @@ func handleSigterm(ngx *controller.NGINXController, exit exiter) {
exitCode := 0
if err := ngx.Stop(); err != nil {
glog.Infof("Error during shutdown %v", err)
glog.Infof("Error during shutdown: %v", err)
exitCode = 1
}
glog.Infof("Handled quit, awaiting pod deletion")
glog.Infof("Handled quit, awaiting Pod deletion")
time.Sleep(10 * time.Second)
glog.Infof("Exiting with %v", exitCode)
exit(exitCode)
}
// createApiserverClient creates new Kubernetes Apiserver client. When kubeconfig or apiserverHost param is empty
// the function assumes that it is running inside a Kubernetes cluster and attempts to
// discover the Apiserver. Otherwise, it connects to the Apiserver specified.
//
// apiserverHost param is in the format of protocol://address:port/pathPrefix, e.g.http://localhost:8001.
// kubeConfig location of kubeconfig file
func createApiserverClient(apiserverHost string, kubeConfig string) (*kubernetes.Clientset, error) {
// createApiserverClient creates a new Kubernetes REST client. apiserverHost is
// the URL of the API server in the format protocol://address:port/pathPrefix,
// kubeConfig is the location of a kubeconfig file. If defined, the kubeconfig
// file is loaded first, the URL of the API server read from the file is then
// optionally overridden by the value of apiserverHost.
// If neither apiserverHost nor kubeConfig are passed in, we assume the
// controller runs inside Kubernetes and fallback to the in-cluster config. If
// the in-cluster config is missing or fails, we fallback to the default config.
func createApiserverClient(apiserverHost, kubeConfig string) (*kubernetes.Clientset, error) {
cfg, err := clientcmd.BuildConfigFromFlags(apiserverHost, kubeConfig)
if err != nil {
return nil, err
@ -166,7 +197,7 @@ func createApiserverClient(apiserverHost string, kubeConfig string) (*kubernetes
var v *discovery.Info
// In some environments is possible the client cannot connect the API server in the first request
// The client may fail to connect to the API server in the first request.
// https://github.com/kubernetes/ingress-nginx/issues/1968
defaultRetry := wait.Backoff{
Steps: 10,
@ -177,7 +208,7 @@ func createApiserverClient(apiserverHost string, kubeConfig string) (*kubernetes
var lastErr error
retries := 0
glog.V(2).Info("trying to discover Kubernetes version")
glog.V(2).Info("Trying to discover Kubernetes version")
err = wait.ExponentialBackoff(defaultRetry, func() (bool, error) {
v, err = client.Discovery().ServerVersion()
@ -186,59 +217,38 @@ func createApiserverClient(apiserverHost string, kubeConfig string) (*kubernetes
}
lastErr = err
glog.V(2).Infof("unexpected error discovering Kubernetes version (attempt %v): %v", err, retries)
glog.V(2).Infof("Unexpected error discovering Kubernetes version (attempt %v): %v", err, retries)
retries++
return false, nil
})
// err is not null only if there was a timeout in the exponential backoff (ErrWaitTimeout)
// err is returned in case of timeout in the exponential backoff (ErrWaitTimeout)
if err != nil {
return nil, lastErr
}
// this should not happen, warn the user
if retries > 0 {
glog.Warningf("it was required to retry %v times before reaching the API server", retries)
glog.Warningf("Initial connection to the Kubernetes API server was retried %d times.", retries)
}
glog.Infof("Running in Kubernetes Cluster version v%v.%v (%v) - git (%v) commit %v - platform %v",
glog.Infof("Running in Kubernetes cluster version v%v.%v (%v) - git (%v) commit %v - platform %v",
v.Major, v.Minor, v.GitVersion, v.GitTreeState, v.GitCommit, v.Platform)
return client, nil
}
const (
// High enough QPS to fit all expected use cases. QPS=0 is not set here, because
// client code is overriding it.
defaultQPS = 1e6
// High enough Burst to fit all expected use cases. Burst=0 is not set here, because
// client code is overriding it.
defaultBurst = 1e6
fakeCertificate = "default-fake-certificate"
)
/**
* Handles fatal init error that prevents server from doing any work. Prints verbose error
* messages and quits the server.
*/
// Handler for fatal init errors. Prints a verbose error message and exits.
func handleFatalInitError(err error) {
glog.Fatalf("Error while initializing connection to Kubernetes apiserver. "+
"This most likely means that the cluster is misconfigured (e.g., it has "+
"invalid apiserver certificates or service accounts configuration). Reason: %s\n"+
glog.Fatalf("Error while initiating a connection to the Kubernetes API server. "+
"This could mean the cluster is misconfigured (e.g. it has invalid API server certificates "+
"or Service Accounts configuration). Reason: %s\n"+
"Refer to the troubleshooting guide for more information: "+
"https://github.com/kubernetes/ingress-nginx/blob/master/docs/troubleshooting.md", err)
"https://kubernetes.github.io/ingress-nginx/troubleshooting/",
err)
}
func registerHandlers(enableProfiling bool, port int, ic *controller.NGINXController, mux *http.ServeMux) {
// expose health check endpoint (/healthz)
healthz.InstallHandler(mux,
healthz.PingHealthz,
ic,
)
mux.Handle("/metrics", promhttp.Handler())
func registerHandlers(mux *http.ServeMux) {
mux.HandleFunc("/build", func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
b, _ := json.Marshal(version.String())
@ -248,23 +258,44 @@ func registerHandlers(enableProfiling bool, port int, ic *controller.NGINXContro
mux.HandleFunc("/stop", func(w http.ResponseWriter, r *http.Request) {
err := syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
if err != nil {
glog.Errorf("unexpected error: %v", err)
glog.Errorf("Unexpected error: %v", err)
}
})
}
if enableProfiling {
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/heap", pprof.Index)
mux.HandleFunc("/debug/pprof/mutex", pprof.Index)
mux.HandleFunc("/debug/pprof/goroutine", pprof.Index)
mux.HandleFunc("/debug/pprof/threadcreate", pprof.Index)
mux.HandleFunc("/debug/pprof/block", pprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
}
func registerHealthz(ic *controller.NGINXController, mux *http.ServeMux) {
// expose health check endpoint (/healthz)
healthz.InstallHandler(mux,
healthz.PingHealthz,
ic,
)
}
func registerMetrics(reg *prometheus.Registry, mux *http.ServeMux) {
mux.Handle(
"/metrics",
promhttp.InstrumentMetricHandler(
reg,
promhttp.HandlerFor(reg, promhttp.HandlerOpts{}),
),
)
}
func registerProfiler(mux *http.ServeMux) {
mux.HandleFunc("/debug/pprof/", pprof.Index)
mux.HandleFunc("/debug/pprof/heap", pprof.Index)
mux.HandleFunc("/debug/pprof/mutex", pprof.Index)
mux.HandleFunc("/debug/pprof/goroutine", pprof.Index)
mux.HandleFunc("/debug/pprof/threadcreate", pprof.Index)
mux.HandleFunc("/debug/pprof/block", pprof.Index)
mux.HandleFunc("/debug/pprof/cmdline", pprof.Cmdline)
mux.HandleFunc("/debug/pprof/profile", pprof.Profile)
mux.HandleFunc("/debug/pprof/symbol", pprof.Symbol)
mux.HandleFunc("/debug/pprof/trace", pprof.Trace)
}
func startHTTPServer(port int, mux *http.ServeMux) {
server := &http.Server{
Addr: fmt.Sprintf(":%v", port),
Handler: mux,

View file

@ -18,46 +18,51 @@ package main
import (
"fmt"
"k8s.io/api/core/v1"
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
"k8s.io/ingress-nginx/internal/file"
"k8s.io/ingress-nginx/internal/ingress/controller"
"os"
"syscall"
"testing"
"time"
"k8s.io/ingress-nginx/internal/file"
"k8s.io/ingress-nginx/internal/ingress/controller"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func TestCreateApiserverClient(t *testing.T) {
home := os.Getenv("HOME")
kubeConfigFile := fmt.Sprintf("%v/.kube/config", home)
cli, err := createApiserverClient("", kubeConfigFile)
if err != nil {
t.Fatalf("unexpected error creating api server client: %v", err)
}
if cli == nil {
t.Fatalf("expected a kubernetes client but none returned")
}
_, err = createApiserverClient("", "")
_, err := createApiserverClient("", "")
if err == nil {
t.Fatalf("expected an error creating api server client without an api server URL or kubeconfig file")
t.Fatal("Expected an error creating REST client without an API server URL or kubeconfig file.")
}
}
func TestHandleSigterm(t *testing.T) {
home := os.Getenv("HOME")
kubeConfigFile := fmt.Sprintf("%v/.kube/config", home)
clientSet := fake.NewSimpleClientset()
cli, err := createApiserverClient("", kubeConfigFile)
ns := "test"
cm := createConfigMap(clientSet, ns, t)
defer deleteConfigMap(cm, ns, clientSet, t)
name := "test"
pod := v1.Pod{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: ns,
},
}
_, err := clientSet.CoreV1().Pods(ns).Create(&pod)
if err != nil {
t.Fatalf("unexpected error creating api server client: %v", err)
t.Fatalf("error creating pod %v: %v", pod, err)
}
resetForTesting(func() { t.Fatal("bad parse") })
os.Setenv("POD_NAME", "test")
os.Setenv("POD_NAMESPACE", "test")
os.Setenv("POD_NAME", name)
os.Setenv("POD_NAMESPACE", ns)
defer os.Setenv("POD_NAME", "")
defer os.Setenv("POD_NAMESPACE", "")
@ -67,20 +72,20 @@ func TestHandleSigterm(t *testing.T) {
_, conf, err := parseFlags()
if err != nil {
t.Errorf("unexpected error creating NGINX controller: %v", err)
t.Errorf("Unexpected error creating NGINX controller: %v", err)
}
conf.Client = cli
conf.Client = clientSet
fs, err := file.NewFakeFS()
if err != nil {
t.Fatalf("unexpected error: %v", err)
t.Fatalf("Unexpected error: %v", err)
}
ngx := controller.NewNGINXController(conf, fs)
ngx := controller.NewNGINXController(conf, nil, fs)
go handleSigterm(ngx, func(code int) {
if code != 1 {
t.Errorf("expected exit code 1 but %v received", code)
t.Errorf("Expected exit code 1 but %d received", code)
}
return
@ -88,12 +93,45 @@ func TestHandleSigterm(t *testing.T) {
time.Sleep(1 * time.Second)
t.Logf("sending SIGTERM to process PID %v", syscall.Getpid())
t.Logf("Sending SIGTERM to PID %d", syscall.Getpid())
err = syscall.Kill(syscall.Getpid(), syscall.SIGTERM)
if err != nil {
t.Errorf("unexpected error sending SIGTERM signal")
t.Error("Unexpected error sending SIGTERM signal.")
}
err = clientSet.CoreV1().Pods(ns).Delete(name, &metav1.DeleteOptions{})
if err != nil {
t.Fatalf("error deleting pod %v: %v", pod, err)
}
}
func TestRegisterHandlers(t *testing.T) {
func createConfigMap(clientSet kubernetes.Interface, ns string, t *testing.T) string {
t.Helper()
t.Log("Creating temporal config map")
configMap := &v1.ConfigMap{
ObjectMeta: metav1.ObjectMeta{
Name: "config",
SelfLink: fmt.Sprintf("/api/v1/namespaces/%s/configmaps/config", ns),
},
}
cm, err := clientSet.CoreV1().ConfigMaps(ns).Create(configMap)
if err != nil {
t.Errorf("error creating the configuration map: %v", err)
}
t.Logf("Temporal configmap %v created", cm)
return cm.Name
}
func deleteConfigMap(cm, ns string, clientSet kubernetes.Interface, t *testing.T) {
t.Helper()
t.Logf("Deleting temporal configmap %v", cm)
err := clientSet.CoreV1().ConfigMaps(ns).Delete(cm, &metav1.DeleteOptions{})
if err != nil {
t.Errorf("error deleting the configmap: %v", err)
}
t.Logf("Temporal configmap %v deleted", cm)
}

View file

@ -0,0 +1,19 @@
# Grafana Dashboards
Ingress-nginx supports a rich collection of prometheus metrics. If you have prometheus and grafana installed on your cluster then prometheus will already be scraping this data due to the `scrape` annotation on the deployment.
This folder contains a dashboard that you can import:
![Dashboard](screenshot.png)
## Features
- Ability to filter by Namespace, Controller Class and Controller
- Visbility of Request Volume, connections, success rates, config reloads and configs out of sync.
- Network IO pressure, memory and CPU use
- Ingress P50, P95 and P99 percentile response times with IN/OUT throughput
- SSL certificate expiry
- Annotational overlays to show when config reloads happened
## Requirements
- **Grafana v5.2.0** (or newer)

File diff suppressed because it is too large Load diff

Binary file not shown.

After

Width:  |  Height:  |  Size: 606 KiB

View file

@ -242,7 +242,7 @@ spec:
serviceAccountName: nginx-ingress-serviceaccount
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.18.0
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
@ -251,6 +251,14 @@ spec:
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
env:
- name: POD_NAME
valueFrom:
@ -284,5 +292,3 @@ spec:
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
securityContext:
runAsNonRoot: false

View file

@ -0,0 +1,41 @@
apiVersion: v1
kind: ConfigMap
metadata:
name: prometheus-configuration
labels:
name: prometheus-configuration
namespace: ingress-nginx
data:
prometheus.yml: |-
global:
scrape_interval: 10s
scrape_configs:
- job_name: 'ingress-nginx-endpoints'
kubernetes_sd_configs:
- role: pod
namespaces:
names:
- ingress-nginx
relabel_configs:
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scrape]
action: keep
regex: true
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_scheme]
action: replace
target_label: __scheme__
regex: (https?)
- source_labels: [__meta_kubernetes_pod_annotation_prometheus_io_path]
action: replace
target_label: __metrics_path__
regex: (.+)
- source_labels: [__address__, __meta_kubernetes_pod_annotation_prometheus_io_port]
action: replace
target_label: __address__
regex: ([^:]+)(?::\d+)?;(\d+)
replacement: $1:$2
- source_labels: [__meta_kubernetes_service_name]
regex: prometheus-service
action: drop

View file

@ -0,0 +1,57 @@
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
labels:
name: grafana
name: grafana
namespace: ingress-nginx
spec:
selector:
matchLabels:
app: grafana
strategy:
rollingUpdate:
maxSurge: 1
maxUnavailable: 1
type: RollingUpdate
template:
metadata:
labels:
app: grafana
spec:
containers:
- image: grafana/grafana
name: grafana
ports:
- containerPort: 3000
protocol: TCP
resources:
limits:
cpu: 500m
memory: 2500Mi
requests:
cpu: 100m
memory: 100Mi
volumeMounts:
- mountPath: /var/lib/grafana
name: data
restartPolicy: Always
volumes:
- emptyDir: {}
name: data
---
apiVersion: v1
kind: Service
metadata:
name: grafana
namespace: ingress-nginx
spec:
ports:
- port: 3000
protocol: TCP
targetPort: 3000
selector:
app: grafana
type: NodePort

View file

@ -0,0 +1,89 @@
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: prometheus-server
namespace: ingress-nginx
rules:
- apiGroups: [""]
resources:
- services
- endpoints
- pods
verbs: ["get", "list", "watch"]
---
apiVersion: v1
kind: ServiceAccount
metadata:
name: prometheus-server
namespace: ingress-nginx
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: prometheus-server
namespace: ingress-nginx
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: prometheus-server
subjects:
- kind: ServiceAccount
name: prometheus-server
namespace: ingress-nginx
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: prometheus-server
namespace: ingress-nginx
spec:
replicas: 1
selector:
matchLabels:
app: prometheus-server
template:
metadata:
labels:
app: prometheus-server
spec:
serviceAccountName: prometheus-server
containers:
- name: prometheus
image: prom/prometheus:v2.3.2
args:
- "--config.file=/etc/prometheus/prometheus.yml"
- "--storage.tsdb.path=/prometheus/"
ports:
- containerPort: 9090
volumeMounts:
- name: prometheus-config-volume
mountPath: /etc/prometheus/
- name: prometheus-storage-volume
mountPath: /prometheus/
volumes:
- name: prometheus-config-volume
configMap:
name: prometheus-configuration
- name: prometheus-storage-volume
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: prometheus-service
namespace: ingress-nginx
spec:
selector:
app: prometheus-server
type: NodePort
ports:
- port: 9090
targetPort: 9090

View file

@ -21,7 +21,7 @@ spec:
serviceAccountName: nginx-ingress-serviceaccount
containers:
- name: nginx-ingress-controller
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0
image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.18.0
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
@ -30,6 +30,14 @@ spec:
- --udp-services-configmap=$(POD_NAMESPACE)/udp-services
- --publish-service=$(POD_NAMESPACE)/ingress-nginx
- --annotations-prefix=nginx.ingress.kubernetes.io
securityContext:
capabilities:
drop:
- ALL
add:
- NET_BIND_SERVICE
# www-data -> 33
runAsUser: 33
env:
- name: POD_NAME
valueFrom:
@ -63,5 +71,3 @@ spec:
periodSeconds: 10
successThreshold: 1
timeoutSeconds: 1
securityContext:
runAsNonRoot: false

View file

@ -2,17 +2,18 @@
## Contents
- [Mandatory command](#mandatory-command)
- [Custom Provider](#custom-provider)
- [Docker for Mac](#docker-for-mac)
- [minikube](#minikube)
- [AWS](#aws)
- [GCE - GKE](#gce---gke)
- [Azure](#azure)
- [Baremetal](#baremetal)
- [Generic Deployment](#generic-deployment)
- [Mandatory command](#mandatory-command)
- [Provider Specific Steps](#provider-specific-steps)
- [Docker for Mac](#docker-for-mac)
- [minikube](#minikube)
- [AWS](#aws)
- [GCE - GKE](#gce---gke)
- [Azure](#azure)
- [Baremetal](#baremetal)
- [Verify installation](#verify-installation)
- [Detect installed version](#detect-installed-version)
- [Using Helm](#using-helm)
- [Verify installation](#verify-installation)
- [Detect installed version](#detect-installed-version)
## Generic Deployment
@ -24,16 +25,14 @@ The following resources are required for a generic deployment.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/mandatory.yaml
```
## Custom Service Provider Deployment
### Provider Specific Steps
There are cloud provider specific yaml files.
### Docker for Mac
#### Docker for Mac
Kubernetes is available for Docker for Mac's Edge channel. Switch to the [Edge
channel][edge] and [enable Kubernetes][enable].
Kubernetes is available in Docker for Mac (from [version 18.06.0-ce](https://docs.docker.com/docker-for-mac/release-notes/#stable-releases-of-2018))
[edge]: https://docs.docker.com/docker-for-mac/install/
[enable]: https://docs.docker.com/docker-for-mac/#kubernetes
Create a service
@ -42,7 +41,7 @@ Create a service
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/cloud-generic.yaml
```
### minikube
#### minikube
For standard usage:
@ -68,13 +67,13 @@ default-http-backend-66b447d9cf-rrlf9 1/1 Running 0 12s
nginx-ingress-controller-fdcdcd6dd-vvpgs 1/1 Running 0 11s
```
### AWS
#### AWS
In AWS we use an Elastic Load Balancer (ELB) to expose the NGINX Ingress controller behind a Service of `Type=LoadBalancer`.
Since Kubernetes v1.9.0 it is possible to use a classic load balancer (ELB) or network load balancer (NLB)
Please check the [elastic load balancing AWS details page](https://aws.amazon.com/es/elasticloadbalancing/details/)
#### Elastic Load Balancer - ELB
##### Elastic Load Balancer - ELB
This setup requires to choose in which layer (L4 or L7) we want to configure the ELB:
@ -102,7 +101,7 @@ This example creates an ELB with just two listeners, one in port 80 and another
![Listeners](../images/elb-l7-listener.png)
#### Network Load Balancer (NLB)
##### Network Load Balancer (NLB)
This type of load balancer is supported since v1.10.0 as an ALPHA feature.
@ -110,7 +109,7 @@ This type of load balancer is supported since v1.10.0 as an ALPHA feature.
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/aws/service-nlb.yaml
```
### GCE - GKE
#### GCE - GKE
```console
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/cloud-generic.yaml
@ -118,16 +117,15 @@ kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/mast
**Important Note:** proxy protocol is not supported in GCE/GKE
### Azure
#### Azure
```console
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/cloud-generic.yaml
```
**Important Note:** proxy protocol is not supported in GCE/GKE
### Baremetal
#### Baremetal
Using [NodePort](https://kubernetes.io/docs/concepts/services-networking/service/#type-nodeport):
@ -135,9 +133,30 @@ Using [NodePort](https://kubernetes.io/docs/concepts/services-networking/service
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/provider/baremetal/service-nodeport.yaml
```
### Verify installation
To check if the ingress controller pods have started, run the following command:
```console
kubectl get pods --all-namespaces -l app=ingress-nginx --watch
```
Once the operator pods are running, you can cancel the above command by typing `Ctrl+C`.
Now, you are ready to create your first ingress.
### Detect installed version
To detect which version of the ingress controller is running, exec into the pod and run `nginx-ingress-controller version` command.
```console
POD_NAMESPACE=ingress-nginx
POD_NAME=$(kubectl get pods -n $POD_NAMESPACE -l app=ingress-nginx -o jsonpath={.items[0].metadata.name})
kubectl exec -it $POD_NAME -n $POD_NAMESPACE -- /nginx-ingress-controller --version
```
## Using Helm
NGINX Ingress controller can be installed via [Helm](https://helm.sh/) using the chart [stable/nginx](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress) from the official charts repository.
NGINX Ingress controller can be installed via [Helm](https://helm.sh/) using the chart [stable/nginx-ingress](https://github.com/kubernetes/charts/tree/master/stable/nginx-ingress) from the official charts repository.
To install the chart with the release name `my-nginx`:
```console
@ -150,23 +169,10 @@ If the kubernetes cluster has RBAC enabled, then run:
helm install stable/nginx-ingress --name my-nginx --set rbac.create=true
```
## Verify installation
To check if the ingress controller pods have started, run the following command:
Detect installed version:
```console
kubectl get pods --all-namespaces -l app=ingress-nginx --watch
POD_NAME=$(kubectl get pods -l app=nginx-ingress -o jsonpath={.items[0].metadata.name})
kubectl exec -it $POD_NAME -- /nginx-ingress-controller --version
```
Once the operator pods are running, you can cancel the above command by typing `Ctrl+C`.
Now, you are ready to create your first ingress.
## Detect installed version
To detect which version of the ingress controller is running, exec into the pod and run `nginx-ingress-controller version` command.
```console
POD_NAMESPACE=ingress-nginx
POD_NAME=$(kubectl get pods -n $POD_NAMESPACE -l app=ingress-nginx -o jsonpath={.items[0].metadata.name})
kubectl exec -it $POD_NAME -n $POD_NAMESPACE -- /nginx-ingress-controller --version
```

View file

@ -1,8 +1,8 @@
# Upgrading
!!! important
No matter the method you use for upgrading, *if you use template overrides,
make sure your templates are compatible with the new version of ingress-nginx*.
No matter the method you use for upgrading, _if you use template overrides,
make sure your templates are compatible with the new version of ingress-nginx_.
## Without Helm
@ -33,12 +33,11 @@ The easiest way to do this is e.g. (do note you may need to change the name para
```
kubectl set image deployment/nginx-ingress-controller \
nginx-ingress-controller=nginx:quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0
nginx-ingress-controller=nginx:quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.18.0
```
For interactive editing, use `kubectl edit deployment nginx-ingress-controller`.
## With Helm
If you installed ingress-nginx using the Helm command in the deployment docs so its name is `ngx-ingress`,
@ -47,4 +46,3 @@ you should be able to upgrade using
```shell
helm upgrade --reuse-values ngx-ingress stable/nginx-ingress
```

View file

@ -40,7 +40,7 @@ metadata:
# name of the secret that contains the user/password definitions
nginx.ingress.kubernetes.io/auth-secret: basic-auth
# message to display with an appropriate context why the authentication is required
nginx.ingress.kubernetes.io/auth-realm: "Authentication Required - foo"
nginx.ingress.kubernetes.io/auth-realm: 'Authentication Required - foo'
spec:
rules:
- host: foo.bar.com

View file

@ -24,8 +24,8 @@ Sample:
metadata:
name: application
annotations:
"nginx.ingress.kubernetes.io/auth-url": "https://$host/oauth2/auth"
"nginx.ingress.kubernetes.io/auth-signin": "https://$host/oauth2/sign_in"
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
...
```

View file

@ -2,8 +2,8 @@ apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/auth-signin: https://$host/oauth2/start
nginx.ingress.kubernetes.io/auth-url: https://$host/oauth2/auth
nginx.ingress.kubernetes.io/auth-url: "https://$host/oauth2/auth"
nginx.ingress.kubernetes.io/auth-signin: "https://$host/oauth2/start?rd=$escaped_request_uri"
name: external-auth-oauth2
namespace: kube-system
spec:

View file

@ -28,7 +28,7 @@ spec:
value: <Client ID>
- name: OAUTH2_PROXY_CLIENT_SECRET
value: <Client Secret>
# python -c 'import os,base64; print base64.b64encode(os.urandom(16))'
# docker run -ti --rm python:3-alpine python -c 'import secrets,base64; print(base64.b64encode(base64.b64encode(secrets.token_bytes(16))));'
- name: OAUTH2_PROXY_COOKIE_SECRET
value: SECRET
image: docker.io/colemickens/oauth2_proxy:latest

View file

@ -2,7 +2,7 @@
## Ingress
The Ingress in this example adds a custom header to Nginx configuration that only applies to that specific Ingress. If you want to add headers that apply globally to all Ingresses, please have a look at [this example](/docs/examples/customization/custom-headers).
The Ingress in this example adds a custom header to Nginx configuration that only applies to that specific Ingress. If you want to add headers that apply globally to all Ingresses, please have a look at [this example](/examples/customization/custom-headers/README).
```console
$ kubectl apply -f ingress.yaml

View file

@ -5,7 +5,6 @@ metadata:
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
more_set_headers "Request-Id: $req_id";
spec:
rules:
- host: custom.configuration.com

View file

@ -1,82 +1,83 @@
# Custom Errors
This example shows how is possible to use a custom backend to render custom error pages. The code of this example is located here [custom-error-pages](https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/customization/custom-errors)
This example demonstrates how to use a custom backend to render custom error pages.
## Customized default backend
The idea is to use the headers `X-Code` and `X-Format` that NGINX pass to the backend in case of an error to find out the best existent representation of the response to be returned. i.e. if the request contains an `Accept` header of type `json` the error should be in that format and not in `html` (the default in NGINX).
First create the custom backend to use in the Ingress controller
First, create the custom `default-backend`. It will be used by the Ingress controller later on.
```
$ kubectl create -f custom-default-backend.yaml
service "nginx-errors" created
replicationcontroller "nginx-errors" created
deployment.apps "nginx-errors" created
```
```
$ kubectl get svc
NAME CLUSTER-IP EXTERNAL-IP PORT(S) AGE
echoheaders 10.3.0.7 nodes 80/TCP 23d
kubernetes 10.3.0.1 <none> 443/TCP 34d
nginx-errors 10.3.0.102 <none> 80/TCP 11s
```
This should have created a Deployment and a Service with the name `nginx-errors`.
```
$ kubectl get rc
CONTROLLER REPLICAS AGE
echoheaders 1 19d
nginx-errors 1 19s
$ kubectl get deploy,svc
NAME DESIRED CURRENT READY AGE
deployment.apps/nginx-errors 1 1 1 10s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/nginx-errors ClusterIP 10.0.0.12 <none> 80/TCP 10s
```
Next create the Ingress controller executing
```
$ kubectl create -f rc-custom-errors.yaml
```
## Ingress controller configuration
Now to check if this is working we use curl:
If you do not already have an instance of the the NGINX Ingress controller running, deploy it according to the
[deployment guide][deploy], then follow these steps:
1. Edit the `nginx-ingress-controller` Deployment and set the value of the `--default-backend` flag to the name of the
newly created error backend.
2. Edit the `nginx-configuration` ConfigMap and create the key `custom-http-errors` with a value of `404,503`.
3. Take note of the IP address assigned to the NGINX Ingress controller Service.
```
$ kubectl get svc ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
ingress-nginx ClusterIP 10.0.0.13 <none> 80/TCP,443/TCP 10m
```
!!! 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.
[deploy]: ../../../deploy/
## Testing error pages
Let us send a couple of HTTP requests using cURL and validate everything is working as expected.
A request to the default backend returns a 404 error with a custom message:
```
$ curl -v http://172.17.4.99/
* Trying 172.17.4.99...
* Connected to 172.17.4.99 (172.17.4.99) port 80 (#0)
> GET / HTTP/1.1
> Host: 172.17.4.99
> User-Agent: curl/7.43.0
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Server: nginx/1.10.0
< Date: Wed, 04 May 2016 02:53:45 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept-Encoding
<
$ curl -D- http://10.0.0.13/
HTTP/1.1 404 Not Found
Server: nginx/1.13.12
Date: Tue, 12 Jun 2018 19:11:24 GMT
Content-Type: */*
Transfer-Encoding: chunked
Connection: keep-alive
<span>The page you're looking for could not be found.</span>
* Connection #0 to host 172.17.4.99 left intact
```
Specifying json as expected format:
A request with a custom `Accept` header returns the corresponding document type (JSON):
```
$ curl -v http://172.17.4.99/ -H 'Accept: application/json'
* Trying 172.17.4.99...
* Connected to 172.17.4.99 (172.17.4.99) port 80 (#0)
> GET / HTTP/1.1
> Host: 172.17.4.99
> User-Agent: curl/7.43.0
> Accept: application/json
>
< HTTP/1.1 404 Not Found
< Server: nginx/1.10.0
< Date: Wed, 04 May 2016 02:54:00 GMT
< Content-Type: text/html
< Transfer-Encoding: chunked
< Connection: keep-alive
< Vary: Accept-Encoding
<
$ curl -D- -H 'Accept: application/json' http://10.0.0.13/
HTTP/1.1 404 Not Found
Server: nginx/1.13.12
Date: Tue, 12 Jun 2018 19:12:36 GMT
Content-Type: application/json
Transfer-Encoding: chunked
Connection: keep-alive
Vary: Accept-Encoding
{ "message": "The page you're looking for could not be found" }
* Connection #0 to host 172.17.4.99 left intact
```
To go further with this example, feel free to deploy your own applications and Ingress objects, and validate that the
responses are still in the correct format when a backend returns 503 (eg. if you scale a Deployment down to 0 replica).

View file

@ -1,3 +1,4 @@
---
apiVersion: v1
kind: Service
metadata:
@ -5,27 +6,35 @@ metadata:
labels:
app: nginx-errors
spec:
ports:
- port: 80
targetPort: 80
protocol: TCP
name: http
selector:
app: nginx-errors
ports:
- port: 80
targetPort: 8080
name: http
---
apiVersion: v1
kind: ReplicationController
apiVersion: apps/v1beta2
kind: Deployment
apiVersion: apps/v1beta2
metadata:
name: nginx-errors
spec:
replicas: 1
selector:
matchLabels:
app: nginx-errors
template:
metadata:
labels:
app: nginx-errors
spec:
containers:
- name: nginx-errors
image: aledbf/nginx-error-server:0.1
- name: nginx-error-server
image: quay.io/kubernetes-ingress-controller/custom-error-pages-amd64:0.3
ports:
- containerPort: 80
- containerPort: 8080
# Setting the environment variable DEBUG we can see the headers sent
# by the ingress controller to the backend in the client response.
# env:
# - name: DEBUG
# value: "true"

View file

@ -1,53 +0,0 @@
apiVersion: v1
kind: ReplicationController
metadata:
name: nginx-ingress-controller
labels:
k8s-app: nginx-ingress-lb
spec:
replicas: 1
selector:
k8s-app: nginx-ingress-lb
template:
metadata:
labels:
k8s-app: nginx-ingress-lb
name: nginx-ingress-lb
spec:
terminationGracePeriodSeconds: 60
containers:
- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0
name: nginx-ingress-lb
imagePullPolicy: Always
readinessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
livenessProbe:
httpGet:
path: /healthz
port: 10254
scheme: HTTP
initialDelaySeconds: 10
timeoutSeconds: 1
# use downward API
env:
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
ports:
- containerPort: 80
hostPort: 80
- containerPort: 443
hostPort: 443
args:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/nginx-errors
securityContext:
runAsNonRoot: false

View file

@ -42,6 +42,3 @@ $ kubectl exec nginx-ingress-controller-v1ppm cat /etc/nginx/nginx.conf
}
....
```
![nginx-module-vts](custom-upstream.png "screenshot with custom configuration")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 59 KiB

View file

@ -1,103 +0,0 @@
# Custom VTS metrics with Prometheus
This example aims to demonstrate the deployment of an nginx ingress controller and use a ConfigMap to enable [nginx vts module](https://github.com/vozlt/nginx-module-vts
) to export metrics in prometheus format.
## vts-metrics
Vts-metrics export NGINX metrics. To deploy all the files simply run `kubectl apply -f nginx`. A deployment and service will be
created which already has a `prometheus.io/scrape: 'true'` annotation and if you added
the recommended Prometheus service-endpoint scraping [configuration](https://raw.githubusercontent.com/prometheus/prometheus/master/documentation/examples/prometheus-kubernetes.yml),
Prometheus will scrape it automatically and you start using the generated metrics right away.
## Custom configuration
```console
apiVersion: v1
data:
enable-vts-status: "true"
kind: ConfigMap
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app: ingress-nginx
```
```console
$ kubectl apply -f nginx-vts-metrics-conf.yaml
```
## Result
Check whether the ingress controller successfully generated the NGINX vts status:
```console
$ kubectl exec nginx-ingress-controller-873061567-4n3k2 -n ingress-nginx cat /etc/nginx/nginx.conf|grep vhost_traffic_status_display
vhost_traffic_status_display;
vhost_traffic_status_display_format html;
```
### NGINX vts dashboard
The vts dashboard provides real time metrics.
![vts dashboard](imgs/vts-dashboard.png)
Because the vts port it's not yet exposed, you should forward the controller port to see it.
```console
$ kubectl port-forward $(kubectl get pods --selector=k8s-app=nginx-ingress-controller -n ingress-nginx --output=jsonpath={.items..metadata.name}) -n ingress-nginx 18080
```
Now open the url [http://localhost:18080/nginx_status](http://localhost:18080/nginx_status) in your browser.
### Prometheus metrics output
NGINX Ingress controller already has a parser to convert vts metrics to Prometheus format. It exports prometheus metrics to the address `:10254/metrics`.
```console
$ kubectl exec -ti -n ingress-nginx $(kubectl get pods --selector=k8s-app=nginx-ingress-controller -n kube-system --output=jsonpath={.items..metadata.name}) curl localhost:10254/metrics
ingress_controller_ssl_expire_time_seconds{host="foo.bar.com"} -6.21355968e+10
# HELP ingress_controller_success Cumulative number of Ingress controller reload operations
# TYPE ingress_controller_success counter
ingress_controller_success{count="reloads"} 3
# HELP nginx_bytes_total Nginx bytes count
# TYPE nginx_bytes_total counter
nginx_bytes_total{direction="in",ingress_class="nginx",namespace="",server_zone="*"} 3708
nginx_bytes_total{direction="in",ingress_class="nginx",namespace="",server_zone="_"} 3708
nginx_bytes_total{direction="out",ingress_class="nginx",namespace="",server_zone="*"} 5256
nginx_bytes_total{direction="out",ingress_class="nginx",namespace="",server_zone="_"} 5256
```
### Customize metrics
The default [vts vhost key](https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_filter_by_set_key) is `$geoip_country_code country::*` that expose metrics grouped by server and country code. The example below show how to have metrics grouped by server and server path.
![vts dashboard](imgs/vts-dashboard-filter-key-path.png)
## NGINX custom configuration ( http level )
```
apiVersion: v1
kind: ConfigMap
data:
enable-vts-status: "true"
vts-default-filter-key: "$server_name"
...
```
## Customize ingress
```
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
annotations:
nginx.ingress.kubernetes.io/vts-filter-key: $uri $server_name
name: ingress
```
## Result
![prometheus filter key path](imgs/prometheus-filter-key-path.png)

Binary file not shown.

Before

Width:  |  Height:  |  Size: 969 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 451 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 244 KiB

View file

@ -1,9 +0,0 @@
apiVersion: v1
data:
enable-vts-status: "true"
kind: ConfigMap
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app: ingress-nginx

View file

@ -14,7 +14,7 @@ spec:
spec:
containers:
- name: http-svc
image: gcr.io/google_containers/echoserver:1.8
image: gcr.io/kubernetes-e2e-test-images/echoserver:2.1
ports:
- containerPort: 8080
env:

View file

@ -13,10 +13,9 @@ Auth | [OAuth external auth](auth/oauth-external-auth/README.md) | TODO | TODO
Customization | [Configuration snippets](customization/configuration-snippets/README.md) | customize nginx location configuration using annotations | Advanced
Customization | [Custom configuration](customization/custom-configuration/README.md) | TODO | TODO
Customization | [Custom DH parameters for perfect forward secrecy](customization/ssl-dh-param/README.md) | TODO | TODO
Customization | [Custom errors](customization/custom-errors/README.md) | TODO | TODO
Customization | [Custom errors](customization/custom-errors/README.md) | serve custom error pages from the default backend | Intermediate
Customization | [Custom headers](customization/custom-headers/README.md) | set custom headers before sending traffic to backends | Advanced
Customization | [Custom upstream check](customization/custom-upstream-check/README.md) | TODO | TODO
Customization | [Custom VTS metrics with Prometheus](customization/custom-vts-metrics-prometheus/README.md) | TODO | TODO
Customization | [External authentication with response header propagation](customization/external-auth-headers/README.md) | TODO | TODO
Customization | [Sysctl tuning](customization/sysctl/README.md) | TODO | TODO
Features | [Rewrite](rewrite/README.md) | TODO | TODO

View file

@ -58,7 +58,7 @@ spec:
spec:
containers:
- name: http-svc
image: gcr.io/google_containers/echoserver:1.8
image: gcr.io/kubernetes-e2e-test-images/echoserver:2.1
ports:
- containerPort: 8080
env:

View file

@ -21,7 +21,7 @@ spec:
# hostNetwork: true
terminationGracePeriodSeconds: 60
containers:
- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.15.0
- image: quay.io/kubernetes-ingress-controller/nginx-ingress-controller:0.18.0
name: nginx-ingress-controller
readinessProbe:
httpGet:
@ -53,5 +53,3 @@ spec:
- /nginx-ingress-controller
- --default-backend-service=$(POD_NAMESPACE)/default-http-backend
- --publish-service=$(POD_NAMESPACE)/nginx-ingress-lb
securityContext:
runAsNonRoot: false

View file

@ -1,16 +1,16 @@
# How it works
The objective of this document explains how the NGINX Ingress controller works, in particular how the NGINX model is built and why we need a one.
The objective of this document is to explain how the NGINX Ingress controller works, in particular how the NGINX model is built and why we need one.
## NGINX configuration
The goal of this Ingress controller is the assembly of a configuration file (nginx.conf). The main implication of this requirement is the need to reload NGINX after any change in the configuration file.
The goal of this Ingress controller is the assembly of a configuration file (nginx.conf). The main implication of this requirement is the need to reload NGINX after any change in the configuration file. _Though it is important to note that we don't reload Nginx on changes that impact only an `upstream` configuration (i.e Endpoints change when you deploy your app)_. We use https://github.com/openresty/lua-nginx-module to achieve this. Check [below](#avoiding-reloads-on-endpoints-changes) to learn more about how it's done.
## NGINX model
Usually, a Kubernetes Controller utilizes the [synchronization loop pattern](1) to check if the desired state in the controller is updated or a change is required. To this purpose, we need to build a model using different objects from the cluster, in particular (in no special order) Ingresses, Services, Endpoints, Secrets, and Configmaps to generate a point in time configuration file that reflects the state of the cluster.
To get this object from the cluster, we use [Kubernetes Informers](2), in particular, `FilteredSharedInformer`. This informers allows reacting to changes in using [callbacks](3) to individual changes when a new object is added, modified or removed. Unfortunately, there is no way to know if a particular change is going to affect the final configuration file. Therefore on every change, we have to rebuild a new model from scratch based on the state of cluster and compare it to the current model. If the new model equals to the current one, then we avoid generating a new NGINX configuration and [trigger a reload](7). Otherwise, we create a new NGINX configuration based on the new model, replace the current model and [trigger a reload](7).
To get this object from the cluster, we use [Kubernetes Informers](2), in particular, `FilteredSharedInformer`. This informers allows reacting to changes in using [callbacks](3) to individual changes when a new object is added, modified or removed. Unfortunately, there is no way to know if a particular change is going to affect the final configuration file. Therefore on every change, we have to rebuild a new model from scratch based on the state of cluster and compare it to the current model. If the new model equals to the current one, then we avoid generating a new NGINX configuration and triggering a reload. Otherwise, we check if the difference is only about Endpoints. If so we then send the new list of Endpoints to a Lua handler running inside Nginx using HTTP POST request and again avoid generating a new NGINX configuration and triggering a reload. If the difference between running and new model is about more than just Endpoints we create a new NGINX configuration based on the new model, replace the current model and trigger a reload.
One of the uses of the model is to avoid unnecessary reloads when there's no change in the state and to detect conflicts in definitions.
@ -39,16 +39,21 @@ The next list describes the scenarios when a reload is required:
- New Ingress Resource Created.
- TLS section is added to existing Ingress.
- Change in Ingress annotations.
- Change in Ingress annotations that impacts more than just upstream configuration. For instance `load-balance` annotation does not require a reload.
- A path is added/removed from an Ingress.
- An Ingress, Service, Secret is removed.
- Some missing referenced object from the Ingress is available, like a Service, Secret or Endpoint.
- Some missing referenced object from the Ingress is available, like a Service or Secret.
- A Secret is updated.
## Avoiding reloads
In some cases, it is possible to avoid reloads, in particular when there is a change in the endpoints, i.e., a pod is started or replaced. It is out of the scope of this Ingress controller to remove reloads completely. This would require an incredible amount of work and at some point makes no sense. This can change only if NGINX changes the way new configurations are read, basically, new changes do not replace worker processes.
### Avoiding reloads on Endpoints changes
On every endpoint change the controller fetches endpoints from all the services it sees and generates corresponding Backend objects. It then sends these objects to a Lua handler running inside Nginx. The Lua code in turn stores those backends in a shared memory zone. Then for every request Lua code running in [`balancer_by_lua`](https://github.com/openresty/lua-resty-core/blob/master/lib/ngx/balancer.md) context detects what endpoints it should choose upstream peer from and applies the configured load balancing algorithm to choose the peer. Then Nginx takes care of the rest. This way we avoid reloading Nginx on endpoint changes. _Note_ that this includes annotation changes that affects only `upstream` configuration in Nginx as well.
In a relatively big clusters with frequently deploying apps this feature saves significant number of Nginx reloads which can otherwise affect response latency, load balancing quality (after every reload Nginx resets the state of load balancing) and so on.
[0]: https://github.com/openresty/lua-nginx-module/pull/1259
[1]: https://coreos.com/kubernetes/docs/latest/replication-controller.html#the-reconciliation-loop-in-detail
[2]: https://godoc.org/k8s.io/client-go/informers#NewFilteredSharedInformerFactory
@ -56,4 +61,4 @@ In some cases, it is possible to avoid reloads, in particular when there is a ch
[4]: https://github.com/kubernetes/ingress-nginx/blob/master/internal/task/queue.go#L38
[5]: https://golang.org/pkg/sync/#Mutex
[6]: https://github.com/kubernetes/ingress-nginx/blob/master/rootfs/etc/nginx/template/nginx.tmpl
[7]: http://nginx.org/en/docs/beginners_guide.html#control
[7]: http://nginx.org/en/docs/beginners_guide.html#control

BIN
docs/images/grafana.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 84 KiB

BIN
docs/images/jaeger-demo.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 112 KiB

View file

@ -1,14 +0,0 @@
# Ingress Controller Catalog
This is a non-comprehensive list of existing ingress controllers.
* [Dummy controller backend](/examples/custom-controller)
* [HAProxy Ingress controller](https://github.com/jcmoraisjr/haproxy-ingress)
* [Linkerd](https://linkerd.io/config/0.9.1/linkerd/index.html#ingress-identifier)
* [traefik](https://docs.traefik.io/configuration/backends/kubernetes/)
* [AWS Application Load Balancer Ingress Controller](https://github.com/coreos/alb-ingress-controller)
* [kube-ingress-aws-controller](https://github.com/zalando-incubator/kube-ingress-aws-controller)
* [Voyager: HAProxy Ingress Controller](https://github.com/appscode/voyager)
* [External Nginx Ingress Controller](https://github.com/unibet/ext_nginx)
* [Heptio Contour controller](https://github.com/heptio/contour)
* [LemonLDAP::NG kubernetes controller](https://github.com/lemonldap-ng-controller/lemonldap-ng-controller) adds WebSSO, Access Management and Identity Federation to NGINX Ingress Controller

View file

@ -1,48 +1,48 @@
# Command line arguments
The following command line arguments are accepted by the main controller executable.
The following command line arguments are accepted by the Ingress controller executable.
They are set in the container spec of the `nginx-ingress-controller` Deployment object (see `deploy/with-rbac.yaml` or `deploy/without-rbac.yaml`).
They are set in the container spec of the `nginx-ingress-controller` Deployment manifest (see `deploy/with-rbac.yaml` or `deploy/without-rbac.yaml`).
| Argument | Description |
|----------|-------------|
| `--alsologtostderr` | log to standard error as well as files |
| `--annotations-prefix string` | Prefix of the ingress annotations. (default "nginx.ingress.kubernetes.io") |
| `--apiserver-host string` | The address of the Kubernetes Apiserver to connect to in the format of protocol://address:port, e.g., http://localhost:8080. If not specified, the assumption is that the binary runs inside a Kubernetes cluster and local discovery is attempted. |
| `--configmap string` | Name of the ConfigMap that contains the custom configuration to use |
| `--default-backend-service string` | Service used to serve a 404 page for the default backend. Takes the form namespace/name. The controller uses the first node port of this Service for the default backend. |
| `--default-server-port int` | Default port to use for exposing the default server (catch all) (default 8181) |
| `--default-ssl-certificate string` | Name of the secret that contains a SSL certificate to be used as default for a HTTPS catch-all server. Takes the form <namespace>/<secret name>. |
| `--election-id string` | Election id to use for status update. (default "ingress-controller-leader") |
| `--enable-dynamic-configuration` | When enabled controller will try to avoid Nginx reloads as much as possible by using Lua. Disabled by default. |
| `--enable-ssl-chain-completion` | Defines if the nginx ingress controller should check the secrets for missing intermediate CA certificates. If the certificate contain issues chain issues is not possible to enable OCSP. Default is true. (default true) |
| `--enable-ssl-passthrough` | Enable SSL passthrough feature. Default is disabled |
| `--force-namespace-isolation` | Force namespace isolation. This flag is required to avoid the reference of secrets or configmaps located in a different namespace than the specified in the flag --watch-namespace. |
| `--health-check-path string` | Defines the URL to be used as health check inside in the default server in NGINX. (default "/healthz") |
| `--healthz-port int` | port for healthz endpoint. (default 10254) |
| `--http-port int` | Indicates the port to use for HTTP traffic (default 80) |
| `--https-port int` | Indicates the port to use for HTTPS traffic (default 443) |
| `--ingress-class string` | Name of the ingress class to route through this controller. |
| `--kubeconfig string` | Path to kubeconfig file with authorization and master location information. |
| `--log_backtrace_at traceLocation` | when logging hits line file:N, emit a stack trace (default :0) |
| `--log_dir string` | If non-empty, write log files in this directory |
| `--logtostderr` | log to standard error instead of files (default true) |
| `--profiling` | Enable profiling via web interface host:port/debug/pprof/ (default true) |
| `--publish-service string` | Service fronting the ingress controllers. Takes the form namespace/name. The controller will set the endpoint records on the ingress objects to reflect those on the service. |
| `--publish-status-address string` | User customized address to be set in the status of ingress resources. The controller will set the endpoint records on the ingress using this address. |
| `--report-node-internal-ip-address` | Defines if the nodes IP address to be returned in the ingress status should be the internal instead of the external IP address |
| `--sort-backends` | Defines if backends and its endpoints should be sorted |
| `--ssl-passtrough-proxy-port int` | Default port to use internally for SSL when SSL Passthgough is enabled (default 442) |
| `--status-port int` | Indicates the TCP port to use for exposing the nginx status page (default 18080) |
| `--stderrthreshold severity` | logs at or above this threshold go to stderr (default 2) |
| `--sync-period duration` | Relist and confirm cloud resources this often. Default is 10 minutes (default 10m0s) |
| `--sync-rate-limit float32` | Define the sync frequency upper limit (default 0.3) |
| `--tcp-services-configmap string` | Name of the ConfigMap that contains the definition of the TCP services to expose. The key in the map indicates the external port to be used. The value is the name of the service with the format namespace/serviceName and the port of the service could be a number of the name of the port. The ports 80 and 443 are not allowed as external ports. This ports are reserved for the backend |
| `--udp-services-configmap string` | Name of the ConfigMap that contains the definition of the UDP services to expose. The key in the map indicates the external port to be used. The value is the name of the service with the format namespace/serviceName and the port of the service could be a number of the name of the port. |
| `--update-status` | Indicates if the ingress controller should update the Ingress status IP/hostname. Default is true (default true) |
| `--update-status-on-shutdown` | Indicates if the ingress controller should update the Ingress status IP/hostname when the controller is being stopped. Default is true (default true) |
| `-v`, `--v Level` | log level for V logs |
| `--version` | Shows release information about the NGINX Ingress controller |
| `--vmodule moduleSpec` | comma-separated list of pattern=N settings for file-filtered logging |
| `--watch-namespace string` | Namespace to watch for Ingress. Default is to watch all namespaces |
| --alsologtostderr | log to standard error as well as files |
| --annotations-prefix string | Prefix of the Ingress annotations specific to the NGINX controller. (default "nginx.ingress.kubernetes.io") |
| --apiserver-host string | Address of the Kubernetes API server. Takes the form "protocol://address:port". If not specified, it is assumed the program runs inside a Kubernetes cluster and local discovery is attempted. |
| --configmap string | Name of the ConfigMap containing custom global configurations for the controller. |
| --default-backend-service string | Service used to serve HTTP requests not matching any known server name (catch-all). Takes the form "namespace/name". The controller configures NGINX to forward requests to the first port of this Service. |
| --default-server-port int | Port to use for exposing the default server (catch-all). (default 8181) |
| --default-ssl-certificate string | Secret containing a SSL certificate to be used by the default HTTPS server (catch-all). Takes the form "namespace/name". |
| --election-id string | Election id to use for Ingress status updates. (default "ingress-controller-leader") |
| --enable-dynamic-configuration | Dynamically refresh backends on topology changes instead of reloading NGINX. Feature backed by OpenResty Lua libraries. (enabled by default) |
| --enable-ssl-chain-completion | Autocomplete SSL certificate chains with missing intermediate CA certificates. A valid certificate chain is required to enable OCSP stapling. Certificates uploaded to Kubernetes must have the "Authority Information Access" X.509 v3 extension for this to succeed. (default true) |
| --enable-ssl-passthrough | Enable SSL Passthrough. |
| --force-namespace-isolation | Force namespace isolation. Prevents Ingress objects from referencing Secrets and ConfigMaps located in a different namespace than their own. May be used together with watch-namespace. |
| --health-check-path string | URL path of the health check endpoint. Configured inside the NGINX status server. All requests received on the port defined by the healthz-port parameter are forwarded internally to this path. (default "/healthz") |
| --healthz-port int | Port to use for the healthz endpoint. (default 10254) |
| --http-port int | Port to use for servicing HTTP traffic. (default 80) |
| --https-port int | Port to use for servicing HTTPS traffic. (default 443) |
| --ingress-class string | Name of the ingress class this controller satisfies. The class of an Ingress object is set using the annotation "kubernetes.io/ingress.class". All ingress classes are satisfied if this parameter is left empty. |
| --kubeconfig string | Path to a kubeconfig file containing authorization and API server information. |
| --log_backtrace_at traceLocation | when logging hits line file:N, emit a stack trace (default :0) |
| --log_dir string | If non-empty, write log files in this directory |
| --logtostderr | log to standard error instead of files (default true) |
| --profiling | Enable profiling via web interface host:port/debug/pprof/ (default true) |
| --publish-service string | Service fronting the Ingress controller. Takes the form "namespace/name". When used together with update-status, the controller mirrors the address of this service's endpoints to the load-balancer status of all Ingress objects it satisfies. |
| --publish-status-address string | Customized address to set as the load-balancer status of Ingress objects this controller satisfies. Requires the update-status parameter. |
| --report-node-internal-ip-address | Set the load-balancer status of Ingress objects to internal Node addresses instead of external. Requires the update-status parameter. |
| --sort-backends | Sort servers inside NGINX upstreams. |
| --ssl-passthrough-proxy-port int | Port to use internally for SSL Passthrough. (default 442) |
| --status-port int | Port to use for exposing NGINX status pages. (default 18080) |
| --stderrthreshold severity | logs at or above this threshold go to stderr (default 2) |
| --sync-period duration | Period at which the controller forces the repopulation of its local object stores. (default is 0) |
| --sync-rate-limit float32 | Define the sync frequency upper limit (default 0.3) |
| --tcp-services-configmap string | Name of the ConfigMap containing the definition of the TCP 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 number or name. TCP ports 80 and 443 are reserved by the controller for servicing HTTP traffic. |
| --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) |
| --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 |
| --watch-namespace string | Namespace the controller watches for updates to Kubernetes objects. This includes Ingresses, Services and all configuration resources. All namespaces are watched if this parameter is left empty. |

View file

@ -1,19 +1,30 @@
# Custom errors
In case of an error in a request the body of the response is obtained from the `default backend`.
Each request to the default backend includes two headers:
When the [`custom-http-errors`][cm-custom-http-errors] option is enabled, the Ingress controller configures NGINX so
that it passes several HTTP headers down to its `default-backend` in case of error:
- `X-Code` indicates the HTTP code to be returned to the client.
- `X-Format` the value of the `Accept` header.
| Header | Value |
| ---------------- | ------------------------------------------------ |
| `X-Code` | HTTP status code retuned by the request |
| `X-Format` | Value of the `Accept` header sent by the client |
| `X-Original-URI` | URI that caused the error |
| `X-Namespace` | Namespace where the backend Service is located |
| `X-Ingress-Name` | Name of the Ingress where the backend is defined |
| `X-Service-Name` | Name of the Service backing the backend |
| `X-Service-Port` | Port number of the Service backing the backend |
A custom error backend can use this information to return the best possible representation of an error page. For
example, if the value of the `Accept` header send by the client was `application/json`, a carefully crafted backend
could decide to return the error payload as a JSON document instead of HTML.
!!! Important
The custom backend must return the correct HTTP status code to be returned. NGINX does not change the response from the custom default backend.
The custom backend is expected to return the correct HTTP status code instead of `200`. NGINX does not change
the response from the custom default backend.
Using these two headers it's possible to use a custom backend service like [this one](https://github.com/kubernetes/ingress-nginx/tree/master/images/custom-error-pages) that inspects each request and returns a custom error page with the format expected by the client. Please check the example [custom-errors](https://github.com/kubernetes/ingress-nginx/tree/master/docs/examples/customization/custom-errors).
An example of such custom backend is available inside the source repository at [images/custom-error-pages][img-custom-error-pages].
NGINX sends additional headers that can be used to build custom response:
See also the [Custom errors][example-custom-errors] example.
- X-Original-URI
- X-Namespace
- X-Ingress-Name
- X-Service-Name
[cm-custom-http-errors]: ./nginx-configuration/configmap.md#custom-http-errors
[img-custom-error-pages]: https://github.com/kubernetes/ingress-nginx/tree/master/images/custom-error-pages
[example-custom-errors]: ../examples/customization/custom-errors

View file

@ -12,7 +12,8 @@ The next example shows how to expose the service `example-go` running in the nam
apiVersion: v1
kind: ConfigMap
metadata:
name: tcp-configmap-example
name: tcp-services
namespace: ingress-nginx
data:
9000: "default/example-go:8080"
```
@ -24,7 +25,8 @@ The next example shows how to expose the service `kube-dns` running in the names
apiVersion: v1
kind: ConfigMap
metadata:
name: udp-configmap-example
name: udp-services
namespace: ingress-nginx
data:
 53: "kube-system/kube-dns:53"
```

View file

@ -0,0 +1,90 @@
# Prometheus and Grafana installation
This tutorial will show you how to install [Prometheus](https://prometheus.io/) and [Grafana](https://grafana.com/) for scraping the metrics of the NGINX Ingress controller.
!!! Important: this example uses `emptyDir` volumes for Prometheus and Grafana. This means once the pod gets terminated you will lose all the data.
## Before You Begin
The NGINX Ingress controller should already be deployed according to the deployment instructions [here](../deploy/index.md).
Note that the yaml files used in this tutorial are stored in the [deploy/monitoring](https://github.com/kubernetes/ingress-nginx/tree/master/deploy/monitoring) folder of the GitHub repository [kubernetes/ingress-nginx](https://github.com/kubernetes/ingress-nginx).
## Deploy and configure Prometheus Server
The Prometheus server must be configured so that it can discover endpoints of services. If a Prometheus server is already running in the cluster and if it is configured in a way that it can find the ingress controller pods, no extra configuration is needed.
If there is no existing Prometheus server running, the rest of this tutorial will guide you through the steps needed to deploy a properly configured Prometheus server.
Running the following command deploys the prometheus configuration in Kubernetes:
```console
kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/monitoring/configuration.yaml
configmap "prometheus-configuration" created
```
Running the following command deploys prometheus in Kubernetes:
```console
kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/monitoring/prometheus.yaml
clusterrole "prometheus-server" created
serviceaccount "prometheus-server" created
clusterrolebinding "prometheus-server" created
deployment "prometheus-server" created
service "prometheus-service" created
```
### Prometheus Dashboard
Open Prometheus dashboard in a web browser:
```console
kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default-http-backend ClusterIP 10.103.59.201 <none> 80/TCP 3d
ingress-nginx NodePort 10.97.44.72 <none> 80:30100/TCP,443:30154/TCP,10254:32049/TCP 5h
prometheus NodePort 10.98.233.86 <none> 9090:32630/TCP 1m
```
Obtain the IP address of the nodes in the running cluster:
```console
kubectl get nodes -o wide
```
In some cases where the node only have internal IP adresses we need to execute:
```console
kubectl get nodes --selector=kubernetes.io/role!=master -o jsonpath={.items[*].status.addresses[?\(@.type==\"InternalIP\"\)].address}
10.192.0.2 10.192.0.3 10.192.0.4
```
Open your browser and visit the following URL: _http://{node IP address}:{prometheus-svc-nodeport}_ to load the Prometheus Dashboard.
According to the above example, this URL will be http://10.192.0.3:32630
![Dashboard](../images/prometheus-dashboard.png)
### Grafana
```console
kubectl create -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/master/deploy/monitoring/grafana.yaml
```
```console
kubectl get svc -n ingress-nginx
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
default-http-backend ClusterIP 10.103.59.201 <none> 80/TCP 3d
ingress-nginx NodePort 10.97.44.72 <none> 80:30100/TCP,443:30154/TCP,10254:32049/TCP 5h
prometheus NodePort 10.98.233.86 <none> 9090:32630/TCP 10m
grafana NodePort 10.98.233.86 <none> 9090:31086/TCP 10m
```
Open your browser and visit the following URL: _http://{node IP address}:{grafana-svc-nodeport}_ to load the Grafana Dashboard.
According to the above example, this URL will be http://10.192.0.3:31086
The username and password is `admin`
After the login you can import the Grafana dashboard from _https://github.com/kubernetes/ingress-nginx/tree/master/deploy/grafana/dashboards_
![Dashboard](../images/grafana.png)

View file

@ -27,6 +27,7 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|[nginx.ingress.kubernetes.io/auth-tls-error-page](#client-certificate-authentication)|string|
|[nginx.ingress.kubernetes.io/auth-tls-pass-certificate-to-upstream](#client-certificate-authentication)|"true" or "false"|
|[nginx.ingress.kubernetes.io/auth-url](#external-authentication)|string|
|[nginx.ingress.kubernetes.io/backend-protocol](#backend-protocol)|string|HTTP,HTTPS,GRPC,GRPCS,AJP|
|[nginx.ingress.kubernetes.io/base-url-scheme](#rewrite)|string|
|[nginx.ingress.kubernetes.io/client-body-buffer-size](#client-body-buffer-size)|string|
|[nginx.ingress.kubernetes.io/configuration-snippet](#configuration-snippet)|string|
@ -43,7 +44,9 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|[nginx.ingress.kubernetes.io/limit-connections](#rate-limiting)|number|
|[nginx.ingress.kubernetes.io/limit-rps](#rate-limiting)|number|
|[nginx.ingress.kubernetes.io/permanent-redirect](#permanent-redirect)|string|
|[nginx.ingress.kubernetes.io/permanent-redirect-code](#permanent-redirect-code)|number|
|[nginx.ingress.kubernetes.io/proxy-body-size](#custom-max-body-size)|string|
|[nginx.ingress.kubernetes.io/proxy-cookie-domain](#proxy-cookie-domain)|string|
|[nginx.ingress.kubernetes.io/proxy-connect-timeout](#custom-timeouts)|number|
|[nginx.ingress.kubernetes.io/proxy-send-timeout](#custom-timeouts)|number|
|[nginx.ingress.kubernetes.io/proxy-read-timeout](#custom-timeouts)|number|
@ -70,6 +73,7 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|[nginx.ingress.kubernetes.io/upstream-vhost](#custom-nginx-upstream-vhost)|string|
|[nginx.ingress.kubernetes.io/whitelist-source-range](#whitelist-source-range)|CIDR|
|[nginx.ingress.kubernetes.io/proxy-buffering](#proxy-buffering)|string|
|[nginx.ingress.kubernetes.io/proxy-buffer-size](#proxy-buffer-size)|string|
|[nginx.ingress.kubernetes.io/ssl-ciphers](#ssl-ciphers)|string|
|[nginx.ingress.kubernetes.io/connection-proxy-header](#connection-proxy-header)|string|
|[nginx.ingress.kubernetes.io/enable-access-log](#enable-access-log)|"true" or "false"|
@ -150,7 +154,7 @@ nginx.ingress.kubernetes.io/auth-realm: "realm string"
NGINX exposes some flags in the [upstream configuration](http://nginx.org/en/docs/http/ngx_http_upstream_module.html#upstream) that enable the configuration of each server in the upstream. The Ingress controller allows custom `max_fails` and `fail_timeout` parameters in a global context using `upstream-max-fails` and `upstream-fail-timeout` in the NGINX ConfigMap or in a particular Ingress rule. `upstream-max-fails` defaults to 0. This means NGINX will respect the container's `readinessProbe` if it is defined. If there is no probe and no values for `upstream-max-fails` NGINX will continue to send traffic to the container.
!!! tip
!!! tip
With the default configuration NGINX will not health check your backends. Whenever the endpoints controller notices a readiness probe failure, that pod's IP will be removed from the list of endpoints. This will trigger the NGINX controller to also remove it from the upstreams.**
To use custom values in an Ingress rule define these annotations:
@ -208,9 +212,9 @@ The annotations are:
!!! attention
TLS with Client Authentication is **not** possible in Cloudflare and might result in unexpected behavior.
Cloudflare only allows Authenticated Origin Pulls and is required to use their own certificate: [https://blog.cloudflare.com/protecting-the-origin-with-tls-authenticated-origin-pulls/](https://blog.cloudflare.com/protecting-the-origin-with-tls-authenticated-origin-pulls/)
Only Authenticated Origin Pulls are allowed and can be configured by following their tutorial: [https://support.cloudflare.com/hc/en-us/articles/204494148-Setting-up-NGINX-to-use-TLS-Authenticated-Origin-Pulls](https://support.cloudflare.com/hc/en-us/articles/204494148-Setting-up-NGINX-to-use-TLS-Authenticated-Origin-Pulls)
@ -364,6 +368,10 @@ To configure this setting globally for all Ingress rules, the `limit-rate-after`
This annotation allows to return a permanent redirect instead of sending data to the upstream. For example `nginx.ingress.kubernetes.io/permanent-redirect: https://www.google.com` would redirect everything to Google.
### Permanent Redirect Code
This annotation allows you to modify the status code used for permanent redirects. For example `nginx.ingress.kubernetes.io/permanent-redirect-code: '308'` would return your permanent-redirect with a 308.
### SSL Passthrough
The annotation `nginx.ingress.kubernetes.io/ssl-passthrough` allows to configure TLS termination in the pod and not in NGINX.
@ -375,7 +383,9 @@ The annotation `nginx.ingress.kubernetes.io/ssl-passthrough` allows to configure
!!! attention
The use of this annotation requires the flag `--enable-ssl-passthrough` (By default it is disabled).
### Secure backends
### Secure backends DEPRECATED (since 0.18.0)
Please use `nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"`
By default NGINX uses plain HTTP to reach the services.
Adding the annotation `nginx.ingress.kubernetes.io/secure-backends: "true"` in the Ingress rule changes the protocol to HTTPS.
@ -464,6 +474,12 @@ To use custom values in an Ingress rule define these annotation:
nginx.ingress.kubernetes.io/proxy-body-size: 8m
```
### Proxy cookie domain
Sets a text that [should be changed in the domain attribute](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_cookie_domain) of the "Set-Cookie" header fields of a proxied server response.
To configure this setting globally for all Ingress rules, the `proxy-cookie-domain` value may be set in the [NGINX ConfigMap][configmap].
### Proxy buffering
Enable or disable proxy buffering [`proxy_buffering`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering).
@ -476,6 +492,16 @@ To use custom values in an Ingress rule define these annotation:
nginx.ingress.kubernetes.io/proxy-buffering: "on"
```
### Proxy buffer size
Sets the size of the buffer [`proxy_buffer_size`](http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffer_size) used for reading the first part of the response received from the proxied server.
By default proxy buffer size is set as "4k"
To configure this setting globally, set `proxy-buffer-size` in [NGINX ConfigMap][configmap]. To use custom values in an Ingress rule, define this annotation:
```yaml
nginx.ingress.kubernetes.io/proxy-buffer-size: "8k"
```
### SSL ciphers
Specifies the [enabled ciphers](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_ciphers).
@ -546,7 +572,9 @@ nginx.ingress.kubernetes.io/lua-resty-waf-extra-rules: '[=[ { "access": [ { "act
For details on how to write WAF rules, please refer to [https://github.com/p0pr0ck5/lua-resty-waf](https://github.com/p0pr0ck5/lua-resty-waf).
### gRPC backend
### gRPC backend DEPRECATED (since 0.18.0)
Please use `nginx.ingress.kubernetes.io/backend-protocol: "GRPC"` or `nginx.ingress.kubernetes.io/backend-protocol: "GRPCS"`
Since NGINX 1.13.10 it is possible to expose [gRPC services natively](http://nginx.org/en/docs/http/ngx_http_grpc_module.html)
@ -568,15 +596,29 @@ using the [nginx-influxdb-module](https://github.com/influxdata/nginx-influxdb-m
nginx.ingress.kubernetes.io/enable-influxdb: "true"
nginx.ingress.kubernetes.io/influxdb-measurement: "nginx-reqs"
nginx.ingress.kubernetes.io/influxdb-port: "8089"
nginx.ingress.kubernetes.io/influxdb-host: "influxdb"
nginx.ingress.kubernetes.io/influxdb-host: "127.0.0.1"
nginx.ingress.kubernetes.io/influxdb-server-name: "nginx-ingress"
```
For the `influxdb-host` parameter you have two options:
To use the module in the Kubernetes Nginx ingress controller, you have two options:
- Use an InfluxDB server configured to enable the [UDP protocol](https://docs.influxdata.com/influxdb/v1.5/supported_protocols/udp/).
- Use an InfluxDB server configured with the [UDP protocol](https://docs.influxdata.com/influxdb/v1.5/supported_protocols/udp/) enabled.
- Deploy Telegraf as a sidecar proxy to the Ingress controller configured to listen UDP with the [socket listener input](https://github.com/influxdata/telegraf/tree/release-1.6/plugins/inputs/socket_listener) and to write using
anyone of the [outputs plugins](https://github.com/influxdata/telegraf/tree/release-1.6/plugins/outputs)
anyone of the [outputs plugins](https://github.com/influxdata/telegraf/tree/release-1.7/plugins/outputs) like InfluxDB, Apache Kafka,
Prometheus, etc.. (recommended)
It's important to remember that there's no DNS resolver at this stage so you will have to configure
an ip address to `nginx.ingress.kubernetes.io/influxdb-host`. If you deploy Influx or Telegraf as sidecar (another container in the same pod) this becomes straightforward since you can directly use `127.0.0.1`.
### Backend Protocol
Using `backend-protocol` annotations is possible to indicate how NGINX should communicate with the backend service.
Valid Values: HTTP, HTTPS, GRPC, GRPCS and AJP
By default NGINX uses `HTTP`.
Example:
```yaml
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
```

View file

@ -44,10 +44,6 @@ The following table shows a configuration option's name, type, and the default v
|[disable-ipv6-dns](#disable-ipv6-dns)|bool|false|
|[enable-underscores-in-headers](#enable-underscores-in-headers)|bool|false|
|[ignore-invalid-headers](#ignore-invalid-headers)|bool|true|
|[enable-vts-status](#enable-vts-status)|bool|false|
|[vts-status-zone-size](#vts-status-zone-size)|string|"10m"|
|[vts-sum-key](#vts-sum-key)|string|"*"|
|[vts-default-filter-key](#vts-default-filter-key)|string|"$geoip_country_code country::*"|
|[retry-non-idempotent](#retry-non-idempotent)|bool|"false"|
|[error-log-level](#error-log-level)|string|"notice"|
|[http2-max-field-size](#http2-max-field-size)|string|"4k"|
@ -62,6 +58,7 @@ The following table shows a configuration option's name, type, and the default v
|[log-format-escape-json](#log-format-escape-json)|bool|"false"|
|[log-format-upstream](#log-format-upstream)|string|`%v - [$the_real_ip] - $remote_user [$time_local] "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent" $request_length $request_time [$proxy_upstream_name] $upstream_addr $upstream_response_length $upstream_response_time $upstream_status`|
|[log-format-stream](#log-format-stream)|string|`[$time_local] $protocol $status $bytes_sent $bytes_received $session_time`|
|[enable-multi-accept](#enable-multi-accept)|bool|"true"|
|[max-worker-connections](#max-worker-connections)|int|16384|
|[map-hash-bucket-size](#max-worker-connections)|int|64|
|[nginx-status-ipv4-whitelist](#nginx-status-ipv4-whitelist)|[]string|"127.0.0.1"|
@ -72,6 +69,7 @@ The following table shows a configuration option's name, type, and the default v
|[server-name-hash-bucket-size](#server-name-hash-bucket-size)|int|`<size of the processors cache line>`
|[proxy-headers-hash-max-size](#proxy-headers-hash-max-size)|int|512|
|[proxy-headers-hash-bucket-size](#proxy-headers-hash-bucket-size)|int|64|
|[reuse-port](#reuse-port)|bool|"true"|
|[server-tokens](#server-tokens)|bool|"true"|
|[ssl-ciphers](#ssl-ciphers)|string|"ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA256"|
|[ssl-ecdh-curve](#ssl-ecdh-curve)|string|"auto"|
@ -91,11 +89,12 @@ The following table shows a configuration option's name, type, and the default v
|[brotli-level](#brotli-level)|int|4|
|[brotli-types](#brotli-types)|string|"application/xml+rss application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component"|
|[use-http2](#use-http2)|bool|"true"|
|[gzip-level](#gzip-level)|int|5|
|[gzip-types](#gzip-types)|string|"application/atom+xml application/javascript application/x-javascript application/json application/rss+xml application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/svg+xml image/x-icon text/css text/plain text/x-component"|
|[worker-processes](#worker-processes)|string|`<Number of CPUs>`|
|[worker-cpu-affinity](#worker-cpu-affinity)|string|""|
|[worker-shutdown-timeout](#worker-shutdown-timeout)|string|"10s"|
|[load-balance](#load-balance)|string|"least_conn"|
|[load-balance](#load-balance)|string|"round_robin"|
|[variables-hash-bucket-size](#variables-hash-bucket-size)|int|128|
|[variables-hash-max-size](#variables-hash-max-size)|int|2048|
|[upstream-keepalive-connections](#upstream-keepalive-connections)|int|32|
@ -112,15 +111,17 @@ The following table shows a configuration option's name, type, and the default v
|[zipkin-collector-host](#zipkin-collector-host)|string|""|
|[zipkin-collector-port](#zipkin-collector-port)|int|9411|
|[zipkin-service-name](#zipkin-service-name)|string|"nginx"|
|[zipkin-sample-rate](#zipkin-sample-rate)|float|1.0|
|[jaeger-collector-host](#jaeger-collector-host)|string|""|
|[jaeger-collector-port](#jaeger-collector-port)|int|6831|
|[jaeger-service-name](#jaeger-service-name)|string|"nginx"|
|[jaeger-sampler-type](#jaeger-sampler-type)|string|"const"|
|[jaeger-sampler-param](#jaeger-sampler-param)|string|"1"|
|[main-snippet](#main-snippet)|string|""|
|[http-snippet](#http-snippet)|string|""|
|[server-snippet](#server-snippet)|string|""|
|[location-snippet](#location-snippet)|string|""|
|[custom-http-errors](#custom-http-errors)|[]int]|[]int{}|
|[custom-http-errors](#custom-http-errors)|[]int|[]int{}|
|[proxy-body-size](#proxy-body-size)|string|"1m"|
|[proxy-connect-timeout](#proxy-connect-timeout)|int|5|
|[proxy-read-timeout](#proxy-read-timeout)|int|60|
@ -241,32 +242,6 @@ Enables underscores in header names. _**default:**_ is disabled
Set if header fields with invalid names should be ignored.
_**default:**_ is enabled
## enable-vts-status
Allows the replacement of the default status page with a third party module named [nginx-module-vts](https://github.com/vozlt/nginx-module-vts).
_**default:**_ is disabled
## vts-status-zone-size
Vts config on http level sets parameters for a shared memory zone that will keep states for various keys. The cache is shared between all worker processes. _**default:**_ 10m
_References:_
[https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_zone](https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_zone)
## vts-default-filter-key
Vts config on http level enables the keys by user defined variable. The key is a key string to calculate traffic. The name is a group string to calculate traffic. The key and name can contain variables such as $host, $server_name. The name's group belongs to filterZones if specified. The key's group belongs to serverZones if not specified second argument name. _**default:**_ $geoip_country_code country::*
_References:_
[https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_filter_by_set_key](https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_filter_by_set_key)
## vts-sum-key
For metrics keyed (or when using Prometheus, labeled) by server zone, this value is used to indicate metrics for all server zones combined. _**default:**_ *
_References:_
[https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_display_sum_key](https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_display_sum_key)
## retry-non-idempotent
Since 1.9.13 NGINX will not retry non-idempotent requests (POST, LOCK, PATCH) in case of an error in the upstream server. The previous behavior can be restored using the value "true".
@ -360,6 +335,14 @@ Please check the [log-format](log-format.md) for definition of each field.
Sets the nginx [stream format](https://nginx.org/en/docs/stream/ngx_stream_log_module.html#log_format).
## enable-multi-accept
If disabled, a worker process will accept one new connection at a time. Otherwise, a worker process will accept all new connections at a time.
_**default:**_ true
_References:_
[http://nginx.org/en/docs/ngx_core_module.html#multi_accept](http://nginx.org/en/docs/ngx_core_module.html#multi_accept)
## max-worker-connections
Sets the maximum number of simultaneous connections that can be opened by each [worker process](http://nginx.org/en/docs/ngx_core_module.html#worker_connections)
@ -401,7 +384,12 @@ _References:_
- [http://nginx.org/en/docs/hash.html](http://nginx.org/en/docs/hash.html)
- [https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_headers_hash_max_size](https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_headers_hash_max_size)
## proxy-headers-hash-bucket-size
## reuse-port
Instructs NGINX to create an individual listening socket for each worker process (using the SO_REUSEPORT socket option), allowing a kernel to distribute incoming connections between worker processes
_**default:**_ true
## proxy-headers-hash-bucket-size
Sets the size of the bucket for the proxy headers hash tables.
@ -463,8 +451,9 @@ Enables or disables session resumption through [TLS session tickets](http://ngin
## ssl-session-ticket-key
Sets the secret key used to encrypt and decrypt TLS session tickets. The value must be a valid base64 string.
To create a ticket: `openssl rand 80 | openssl enc -A -base64`
[TLS session ticket-key](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets), by default, a randomly generated key is used. To create a ticket: `openssl rand 80 | base64 -w0`
[TLS session ticket-key](http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets), by default, a randomly generated key is used.
## ssl-session-timeout
@ -483,7 +472,7 @@ Enables or disables the [PROXY protocol](https://www.nginx.com/resources/admin-g
## proxy-protocol-header-timeout
Sets the timeout value for receiving the proxy-protocol headers. The default of 5 seconds prevents the TLS passthrough handler from waiting indefinetly on a dropped connection.
Sets the timeout value for receiving the proxy-protocol headers. The default of 5 seconds prevents the TLS passthrough handler from waiting indefinitely on a dropped connection.
_**default:**_ 5s
## use-gzip
@ -516,6 +505,10 @@ _**default:**_ `application/xml+rss application/atom+xml application/javascript
Enables or disables [HTTP/2](http://nginx.org/en/docs/http/ngx_http_v2_module.html) support in secure connections.
## gzip-level
Sets the gzip Compression Level that will be used. _**default:**_ 5
## gzip-types
Sets the MIME types in addition to "text/html" to compress. The special value "\*" matches any MIME type. Responses with the "text/html" type are always compressed if `use-gzip` is enabled.
@ -544,11 +537,11 @@ Sets the algorithm to use for load balancing.
The value can either be:
- round_robin: to use the default round robin loadbalancer
- least_conn: to use the least connected method
- ip_hash: to use a hash of the server for routing.
- ewma: to use the peak ewma method for routing (only available with `enable-dynamic-configuration` flag)
- least_conn: to use the least connected method (_note_ that this is available only in non-dynamic mode: `--enable-dynamic-configuration=false`)
- ip_hash: to use a hash of the server for routing (_note_ that this is available only in non-dynamic mode: `--enable-dynamic-configuration=false`, but alternatively you can consider using `nginx.ingress.kubernetes.io/upstream-hash-by`)
- ewma: to use the Peak EWMA method for routing ([implementation](https://github.com/kubernetes/ingress-nginx/blob/master/rootfs/etc/nginx/lua/balancer/ewma.lua))
The default is least_conn.
The default is `round_robin`.
_References:_
[http://nginx.org/en/docs/http/load_balancing.html](http://nginx.org/en/docs/http/load_balancing.html)
@ -638,6 +631,10 @@ Specifies the port to use when uploading traces. _**default:**_ 9411
Specifies the service name to use for any traces created. _**default:**_ nginx
## zipkin-sample-rate
Specifies sample rate for any traces created. _**default:**_ 1.0
## jaeger-collector-host
Specifies the host to use when uploading traces. It must be a valid URL.
@ -659,20 +656,21 @@ Specifies the sampler to be used when sampling traces. The available samplers ar
Specifies the argument to be passed to the sampler constructor. Must be a number.
For const this should be 0 to never sample and 1 to always sample. _**default:**_ 1
## main-snippet
Adds custom configuration to the main section of the nginx configuration.
## http-snippet
Adds custom configuration to the http section of the nginx configuration.
_**default:**_ ""
## server-snippet
Adds custom configuration to all the servers in the nginx configuration.
_**default:**_ ""
## location-snippet
Adds custom configuration to all the locations in the nginx configuration.
_**default:**_ ""
## custom-http-errors
@ -761,7 +759,7 @@ _References:_
## http-redirect-code
Sets the HTTP status code to be used in redirects.
Supported codes are [301](https://developer.mozilla.org/es/docs/Web/HTTP/Status/301),[302](https://developer.mozilla.org/es/docs/Web/HTTP/Status/302),[307](https://developer.mozilla.org/es/docs/Web/HTTP/Status/307) and [308](https://developer.mozilla.org/es/docs/Web/HTTP/Status/308)
Supported codes are [301](https://developer.mozilla.org/docs/Web/HTTP/Status/301),[302](https://developer.mozilla.org/docs/Web/HTTP/Status/302),[307](https://developer.mozilla.org/docs/Web/HTTP/Status/307) and [308](https://developer.mozilla.org/docs/Web/HTTP/Status/308)
_**default:**_ 308
> __Why the default code is 308?__

View file

@ -31,6 +31,15 @@ log_format upstreaminfo
| `$upstream_response_time` | time spent on receiving the response from the upstream server as seconds with millisecond resolution |
| `$upstream_status` | status code of the response obtained from the upstream server |
Additional available variables:
| Placeholder | Description |
|-------------|-------------|
| `$namespace` | namespace of the ingress |
| `$ingress_name` | name of the ingress |
| `$service_name` | name of the service |
| `$service_port` | port of the service |
Sources:

View file

@ -1,11 +0,0 @@
# NGINX status page
The [ngx_http_stub_status_module](http://nginx.org/en/docs/http/ngx_http_stub_status_module.html) module provides access to basic status information.
This is the default module active in the url `/nginx_status` in the status port (default is 18080).
This controller provides an alternative to this module using the [nginx-module-vts](https://github.com/vozlt/nginx-module-vts) module.
To use this module just set in the configuration configmap `enable-vts-status: "true"`.
![nginx-module-vts screenshot](https://cloud.githubusercontent.com/assets/3648408/10876811/77a67b70-8183-11e5-9924-6a6d0c5dc73a.png "screenshot with filter")
To extract the information in JSON format the module provides a custom URL: `/nginx_status/format/json`

View file

@ -7,7 +7,7 @@ The [ModSecurity-nginx](https://github.com/SpiderLabs/ModSecurity-nginx) connect
The default ModSecurity configuration file is located in `/etc/nginx/modsecurity/modsecurity.conf`. This is the only file located in this directory and contains the default recommended configuration. Using a volume we can replace this file with the desired configuration.
To enable the ModSecurity feature we need to specify `enable-modsecurity: "true"` in the configuration configmap.
>__Note:__ the default configuration use detection only, because that minimises the chances of post-installation disruption.
>__Note:__ the default configuration use detection only, because that minimizes the chances of post-installation disruption.
The file `/var/log/modsec_audit.log` contains the log of ModSecurity.

View file

@ -1,9 +1,59 @@
# OpenTracing
Enables requests served by nginx for distributed tracing via The OpenTracing Project.
Using the third party module [opentracing-contrib/nginx-opentracing](https://github.com/opentracing-contrib/nginx-opentracing) the NGINX ingress controller can configure NGINX to enable [OpenTracing](http://opentracing.io) instrumentation.
By default this feature is disabled.
To enable the instrumentation we just need to enable the instrumentation in the configuration configmap and set the host where we should send the traces.
## Usage
To enable the instrumentation we must enable opentracing in the configuration configmap:
```
data:
enable-opentracing: "true"
```
We must also set the host to use when uploading traces:
```
zipkin-collector-host: zipkin.default.svc.cluster.local
jaeger-collector-host: jaeger-collector.default.svc.cluster.local
```
Next you will need to deploy a distributed tracing system which uses OpenTracing. Both [Zipkin](https://github.com/openzipkin/zipkin) and
[Jaeger](https://github.com/jaegertracing/jaeger) have been tested.
Other optional configuration options:
```
# specifies the port to use when uploading traces
zipkin-collector-port
# specifies the service name to use for any traces created, Default: nginx
zipkin-service-name
# specifies sample rate for any traces created. Default: 1.0
zipkin-sample-rate
# specifies the port to use when uploading traces
jaeger-collector-port
# specifies the service name to use for any traces created, Default: nginx
jaeger-service-name
# specifies the sampler to be used when sampling traces.
# The available samplers are: const, probabilistic, ratelimiting, remote, Default: const
jaeger-sampler-type
# specifies the argument to be passed to the sampler constructor, Default: 1
jaeger-sampler-param
```
## Examples
The following examples show how to deploy and test different distributed tracing systems. These example can be performed
using Minikube.
### Zipkin
In the [rnburn/zipkin-date-server](https://github.com/rnburn/zipkin-date-server)
github repository is an example of a dockerized date service. To install the example and zipkin collector run:
@ -23,20 +73,111 @@ data:
enable-opentracing: "true"
zipkin-collector-host: zipkin.default.svc.cluster.local
metadata:
name: nginx-configuration
namespace: ingress-nginx
labels:
app: ingress-nginx
name: nginx-load-balancer-conf
namespace: kube-system
' | kubectl replace -f -
```
Using curl we can generate some traces:
```console
$ curl -v http://$(minikube ip)
$ curl -v http://$(minikube ip)
```
In the zipkin interface we can see the details:
![zipkin screenshot](../../images/zipkin-demo.png "zipkin collector screenshot")
### Jaeger
1. Enable Ingress addon in minikube:
```
$ minikube addons enable ingress
```
2. Add minikube IP to /etc/hosts:
```
$ echo "$(minikube ip) example.com" | sudo tee -a /etc/hosts
```
3. Apply a Basic Service and Ingress Resource:
```
# Create Echoheaders Deployment
$ kubectl run echoheaders --image=k8s.gcr.io/echoserver:1.4 --replicas=1 --port=8080
# Expose as a Cluster-IP
$ kubectl expose deployment echoheaders --port=80 --target-port=8080 --name=echoheaders-x
# Apply the Ingress Resource
$ echo '
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: echo-ingress
spec:
rules:
- host: example.com
http:
paths:
- backend:
serviceName: echoheaders-x
servicePort: 80
path: /echo
' | kubectl apply -f -
```
4. Enable OpenTracing and set the zipkin-collector-host:
```
$ echo '
apiVersion: v1
kind: ConfigMap
data:
enable-opentracing: "true"
zipkin-collector-host: zipkin.default.svc.cluster.local
jaeger-collector-host: jaeger-collector.default.svc.cluster.local
metadata:
name: nginx-load-balancer-conf
namespace: kube-system
' | kubectl replace -f -
```
5. Apply the Jaeger All-In-One Template:
```
$ kubectl apply -f https://raw.githubusercontent.com/jaegertracing/jaeger-kubernetes/master/all-in-one/jaeger-all-in-one-template.yml
```
6. Make a few requests to the Service:
```
$ curl example.com/echo -d "meow"
CLIENT VALUES:
client_address=172.17.0.5
command=POST
real path=/echo
query=nil
request_version=1.1
request_uri=http://example.com:8080/echo
SERVER VALUES:
server_version=nginx: 1.10.0 - lua: 10001
HEADERS RECEIVED:
accept=*/*
connection=close
content-length=4
content-type=application/x-www-form-urlencoded
host=example.com
user-agent=curl/7.54.0
x-forwarded-for=192.168.99.1
x-forwarded-host=example.com
x-forwarded-port=80
x-forwarded-proto=http
x-original-uri=/echo
x-real-ip=192.168.99.1
x-scheme=http
BODY:
meow
```
7. View the Jaeger UI:
```
$ minikube service jaeger-query --url
http://192.168.99.100:30183
```
In the jaeger interface we can see the details:
![jaeger screenshot](../../images/jaeger-demo.png "jaeger collector screenshot")

View file

@ -50,6 +50,7 @@ args = parser.parse_args()
verbose_out = sys.stderr if args.verbose else open("/dev/null", "w")
def get_refs():
refs = {}
@ -63,6 +64,7 @@ def get_refs():
return refs
def file_passes(filename, refs, regexs):
try:
f = open(filename, 'r')
@ -127,10 +129,19 @@ def file_passes(filename, refs, regexs):
return True
def file_extension(filename):
return os.path.splitext(filename)[1].split(".")[-1].lower()
skipped_dirs = ['.git', "vendor", "test/e2e/framework/framework.go", "test/e2e/generated/bindata.go", "hack/boilerplate/test", "internal/file/bindata.go"]
skipped_dirs = [
'.git',
"vendor",
"test/e2e/framework/framework.go",
"hack/boilerplate/test",
"test/e2e/dind-cluster-v1.11.sh"
]
def normalize_files(files):
newfiles = []
@ -143,6 +154,7 @@ def normalize_files(files):
newfiles[i] = os.path.join(args.rootdir, pathname)
return newfiles
def get_files(extensions):
files = []
if len(args.filenames) > 0:
@ -170,19 +182,23 @@ def get_files(extensions):
outfiles.append(pathname)
return outfiles
def get_regexs():
regexs = {}
# Search for "YEAR" which exists in the boilerplate, but shouldn't in the real thing
regexs["year"] = re.compile( 'YEAR' )
regexs["year"] = re.compile('YEAR')
# dates can be 2014, 2015, 2016, ..., CURRENT_YEAR, company holder names can be anything
years = range(2014, date.today().year + 1)
regexs["date"] = re.compile( '(%s)' % "|".join(map(lambda l: str(l), years)) )
regexs["date"] = re.compile(
'(%s)' % "|".join(map(lambda l: str(l), years)))
# strip // +build \n\n build constraints
regexs["go_build_constraints"] = re.compile(r"^(// \+build.*\n)+\n", re.MULTILINE)
regexs["go_build_constraints"] = re.compile(
r"^(// \+build.*\n)+\n", re.MULTILINE)
# strip #!.* from shell scripts
regexs["shebang"] = re.compile(r"^(#!.*\n)\n*", re.MULTILINE)
return regexs
def main():
regexs = get_regexs()
refs = get_refs()
@ -194,5 +210,6 @@ def main():
return 0
if __name__ == "__main__":
sys.exit(main())
sys.exit(main())

View file

@ -3,7 +3,7 @@ all: all-container
BUILDTAGS=
# Use the 0.0 tag for testing, it shouldn't clobber any release builds
TAG?=0.1
TAG?=0.3
REGISTRY?=quay.io/kubernetes-ingress-controller
GOOS?=linux
DOCKER?=docker
@ -26,11 +26,11 @@ ARCH ?= $(shell go env GOARCH)
GOARCH = ${ARCH}
DUMB_ARCH = ${ARCH}
BASEIMAGE?=alpine:3.6
BASEIMAGE?=alpine:3.7
ALL_ARCH = amd64 arm arm64 ppc64le
QEMUVERSION=v2.9.1
QEMUVERSION=v2.12.0-1
IMGNAME = custom-error-pages
IMAGE = $(REGISTRY)/$(IMGNAME)
@ -74,7 +74,7 @@ ifeq ($(ARCH),amd64)
else
# When cross-building, only the placeholder "CROSS_BUILD_" should be removed
# Register /usr/bin/qemu-ARCH-static as the handler for ARM binaries in the kernel
$(DOCKER) run --rm --privileged multiarch/qemu-user-static:register --reset
# $(DOCKER) run --rm --privileged multiarch/qemu-user-static:register --reset
curl -sSL https://github.com/multiarch/qemu-user-static/releases/download/$(QEMUVERSION)/x86_64_qemu-$(QEMUARCH)-static.tar.gz | tar -xz -C $(TEMP_DIR)/rootfs
$(SED_I) "s/CROSS_BUILD_//g" $(DOCKERFILE)
endif
@ -103,3 +103,8 @@ build: clean
release: all-container all-push
echo "done"
.PHONY: register-qemu
register-qemu:
# Register /usr/bin/qemu-ARCH-static as the handler for binaries in multiple platforms
$(DOCKER) run --rm --privileged multiarch/qemu-user-static:register --reset

View file

@ -1,2 +1,3 @@
# custom-error-pages
Example of Custom error pages for the NGINX Ingress controller

View file

@ -39,15 +39,34 @@ const (
// ContentType name of the header that defines the format of the reply
ContentType = "Content-Type"
// OriginalURI name of the header with the original URL from NGINX
OriginalURI = "X-Original-URI"
// Namespace name of the header that contains information about the Ingress namespace
Namespace = "X-Namespace"
// IngressName name of the header that contains the matched Ingress
IngressName = "X-Ingress-Name"
// ServiceName name of the header that contains the matched Service in the Ingress
ServiceName = "X-Service-Name"
// ServicePort name of the header that contains the matched Service port in the Ingress
ServicePort = "X-Service-Port"
// ErrFilesPathVar is the name of the environment variable indicating
// the location on disk of files served by the handler.
ErrFilesPathVar = "ERROR_FILES_PATH"
)
func main() {
path := "/www"
if os.Getenv("PATH") != "" {
path = os.Getenv("PATH")
errFilesPath := "/www"
if os.Getenv(ErrFilesPathVar) != "" {
errFilesPath = os.Getenv(ErrFilesPathVar)
}
http.HandleFunc("/", errorHandler(path))
http.HandleFunc("/", errorHandler(errFilesPath))
http.Handle("/metrics", promhttp.Handler())
@ -63,18 +82,28 @@ func errorHandler(path string) func(http.ResponseWriter, *http.Request) {
start := time.Now()
ext := "html"
if os.Getenv("DEBUG") != "" {
w.Header().Set(FormatHeader, r.Header.Get(FormatHeader))
w.Header().Set(CodeHeader, r.Header.Get(CodeHeader))
w.Header().Set(ContentType, r.Header.Get(ContentType))
w.Header().Set(OriginalURI, r.Header.Get(OriginalURI))
w.Header().Set(Namespace, r.Header.Get(Namespace))
w.Header().Set(IngressName, r.Header.Get(IngressName))
w.Header().Set(ServiceName, r.Header.Get(ServiceName))
w.Header().Set(ServicePort, r.Header.Get(ServicePort))
}
format := r.Header.Get(FormatHeader)
if format == "" {
format = "text/html"
log.Printf("forma not specified. Using %v\n", format)
log.Printf("format not specified. Using %v", format)
}
mediaType, _, _ := mime.ParseMediaType(format)
cext, err := mime.ExtensionsByType(mediaType)
cext, err := mime.ExtensionsByType(format)
if err != nil {
log.Printf("unexpected error reading media type extension: %v. Using %v\n", err, ext)
log.Printf("unexpected error reading media type extension: %v. Using %v", err, ext)
} else if len(cext) == 0 {
log.Printf("couldn't get media type extension. Using %v\n", ext)
log.Printf("couldn't get media type extension. Using %v", ext)
} else {
ext = cext[0]
}
@ -84,7 +113,7 @@ func errorHandler(path string) func(http.ResponseWriter, *http.Request) {
code, err := strconv.Atoi(errCode)
if err != nil {
code = 404
log.Printf("unexpected error reading return code: %v. Using %v\n", err, code)
log.Printf("unexpected error reading return code: %v. Using %v", err, code)
}
w.WriteHeader(code)
@ -94,22 +123,22 @@ func errorHandler(path string) func(http.ResponseWriter, *http.Request) {
file := fmt.Sprintf("%v/%v%v", path, code, ext)
f, err := os.Open(file)
if err != nil {
log.Printf("unexpected error opening file: %v\n", err)
log.Printf("unexpected error opening file: %v", err)
scode := strconv.Itoa(code)
file := fmt.Sprintf("%v/%cxx%v", path, scode[0], ext)
f, err := os.Open(file)
if err != nil {
log.Printf("unexpected error opening file: %v\n", err)
log.Printf("unexpected error opening file: %v", err)
http.NotFound(w, r)
return
}
defer f.Close()
log.Printf("serving custom error response for code %v and format %v from file %v\n", code, format, file)
log.Printf("serving custom error response for code %v and format %v from file %v", code, format, file)
io.Copy(w, f)
return
}
defer f.Close()
log.Printf("serving custom error response for code %v and format %v from file %v\n", code, format, file)
log.Printf("serving custom error response for code %v and format %v from file %v", code, format, file)
io.Copy(w, f)
duration := time.Now().Sub(start).Seconds()

File diff suppressed because it is too large Load diff

62
images/e2e/Dockerfile Normal file
View file

@ -0,0 +1,62 @@
# Copyright 2018 The Kubernetes Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
FROM quay.io/kubernetes-ingress-controller/nginx-amd64:0.57
RUN clean-install \
g++ \
gcc \
git \
libc6-dev \
make \
wget \
luarocks \
pkg-config
ENV GOLANG_VERSION 1.10.3
ENV GO_ARCH linux-amd64
ENV GOLANG_SHA fa1b0e45d3b647c252f51f5e1204aba049cde4af177ef9f2181f43004f901035
RUN set -eux; \
url="https://golang.org/dl/go${GOLANG_VERSION}.${GO_ARCH}.tar.gz"; \
wget -O go.tgz "$url"; \
echo "${GOLANG_SHA} *go.tgz" | sha256sum -c -; \
tar -C /usr/local -xzf go.tgz; \
rm go.tgz; \
export PATH="/usr/local/go/bin:$PATH"; \
go version
ENV GOPATH /go
ENV PATH $GOPATH/bin:/usr/local/go/bin:$PATH
RUN mkdir -p "$GOPATH/src" "$GOPATH/bin" && chmod -R 777 "$GOPATH"
WORKDIR $GOPATH
ENV RESTY_CLI_VERSION 0.22rc2
ENV RESTY_CLI_SHA 1ec64d204469a04da553c95eaafb2e5601a03acb8f26cc10ae16b15525228c12
RUN set -eux; \
url="https://github.com/openresty/resty-cli/archive/v${RESTY_CLI_VERSION}.tar.gz"; \
wget -O resty_cli.tgz "$url"; \
echo "${RESTY_CLI_SHA} *resty_cli.tgz" | sha256sum -c -; \
tar -C /tmp -xzf resty_cli.tgz; \
rm resty_cli.tgz; \
mv /tmp/resty-cli-${RESTY_CLI_VERSION}/bin/* /usr/local/bin/; \
resty -V
RUN luarocks install luacheck \
&& luarocks install busted 2.0.rc12
RUN go get github.com/onsi/ginkgo/ginkgo \
&& go get golang.org/x/lint/golint

27
images/e2e/Makefile Normal file
View file

@ -0,0 +1,27 @@
# Copyright 2018 The Kubernetes Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
TAG ?=v$(shell date +%m%d%Y)-$(shell git rev-parse --short HEAD)
REGISTRY ?= quay.io/kubernetes-ingress-controller
DOCKER ?= docker
IMAGE = $(REGISTRY)/e2e
all: docker-build docker-push
docker-build:
$(DOCKER) build -t $(IMAGE):$(TAG) .
docker-push:
$(DOCKER) push $(IMAGE):$(TAG)

View file

@ -1,64 +0,0 @@
# Copyright 2017 The Kubernetes Authors. All rights reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
TAG ?= 1.10
REGISTRY ?= gcr.io/google_containers
ARCH ?= $(shell go env GOARCH)
ALL_ARCH = amd64 arm ppc64le
QEMUVERSION=v2.7.0
IMGNAME = echoserver
IMAGE = $(REGISTRY)/$(IMGNAME)
MULTI_ARCH_IMG = $(IMAGE)-$(ARCH)
# Set default base image dynamically for each arch
BASEIMAGE?=gcr.io/google_containers/nginx-slim-$(ARCH):0.21
TEMP_DIR := $(shell mktemp -d)
all: all-container
sub-container-%:
$(MAKE) ARCH=$* container
sub-push-%:
$(MAKE) ARCH=$* push
all-container: $(addprefix sub-container-,$(ALL_ARCH))
all-push: $(addprefix sub-push-,$(ALL_ARCH))
container: .container-$(ARCH)
.container-$(ARCH):
cp ./* $(TEMP_DIR)
cd $(TEMP_DIR) && sed -i 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile
docker build -t $(MULTI_ARCH_IMG):$(TAG) $(TEMP_DIR)
ifeq ($(ARCH), amd64)
# This is for to maintain the backward compatibility
docker tag $(MULTI_ARCH_IMG):$(TAG) $(IMAGE):$(TAG)
endif
push: .push-$(ARCH)
.push-$(ARCH): .container-$(ARCH)
gcloud docker -- push $(MULTI_ARCH_IMG):$(TAG)
ifeq ($(ARCH), amd64)
gcloud docker -- push $(IMAGE):$(TAG)
endif
clean: $(addprefix sub-clean-,$(ALL_ARCH))
sub-clean-%:
docker rmi -f $(IMAGE)-$*:$(TAG) || true

View file

@ -1,10 +0,0 @@
# Echoserver
This is a simple server that responds with the http headers it received.
Image Versions >= 1.10 support HTTP2 on :8443.
Image Versions >= 1.9 expose HTTPS endpoint on :8443.
Image versions >= 1.4 removes the redirect introduced in 1.3.
Image versions >= 1.3 redirect requests on :80 with `X-Forwarded-Proto: http` to :443.
Image versions > 1.0 run an nginx server, and implement the echoserver using lua in the nginx config.
Image versions <= 1.0 run a python http server instead of nginx, and don't redirect any requests.

View file

@ -1,59 +0,0 @@
apiVersion: v1
kind: Service
metadata:
name: echoheaders
labels:
app: echoheaders
spec:
type: NodePort
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
- port: 443
targetPort: 8443
protocol: TCP
name: https
selector:
app: echoheaders
---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: echoheaders
labels:
app: echoheaders
spec:
replicas: 1
selector:
matchLabels:
app: echoheaders
template:
metadata:
labels:
app: echoheaders
spec:
containers:
- name: echoheaders
image: gcr.io/google_containers/echoserver:1.10
ports:
- containerPort: 8080
- containerPort: 8443
env:
- name: NODE_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
- name: POD_NAME
valueFrom:
fieldRef:
fieldPath: metadata.name
- name: POD_NAMESPACE
valueFrom:
fieldRef:
fieldPath: metadata.namespace
- name: POD_IP
valueFrom:
fieldRef:
fieldPath: status.podIP

View file

@ -1,92 +0,0 @@
events {
worker_connections 1024;
}
env HOSTNAME;
env NODE_NAME;
env POD_NAME;
env POD_NAMESPACE;
env POD_IP;
http {
default_type 'text/plain';
# maximum allowed size of the client request body. By default this is 1m.
# Request with bigger bodies nginx will return error code 413.
# http://nginx.org/en/docs/http/ngx_http_core_module.html#client_max_body_size
client_max_body_size 10m;
init_by_lua_block {
local template = require("template")
-- template syntax documented here:
-- https://github.com/bungle/lua-resty-template/blob/master/README.md
tmpl = template.compile([[
Hostname: {{os.getenv("HOSTNAME") or "N/A"}}
Pod Information:
{% if os.getenv("POD_NAME") then %}
node name: {{os.getenv("NODE_NAME") or "N/A"}}
pod name: {{os.getenv("POD_NAME") or "N/A"}}
pod namespace: {{os.getenv("POD_NAMESPACE") or "N/A"}}
pod IP: {{os.getenv("POD_IP") or "N/A"}}
{% else %}
-no pod information available-
{% end %}
Server values:
server_version=nginx: {{ngx.var.nginx_version}} - lua: {{ngx.config.ngx_lua_version}}
Request Information:
client_address={{ngx.var.remote_addr}}
method={{ngx.req.get_method()}}
real path={{ngx.var.request_uri}}
query={{ngx.var.query_string or ""}}
request_version={{ngx.req.http_version()}}
request_scheme={{ngx.var.scheme}}
request_uri={{ngx.var.scheme.."://"..ngx.var.host..":"..ngx.var.server_port..ngx.var.request_uri}}
Request Headers:
{% for i, key in ipairs(keys) do %}
{{key}}={{headers[key]}}
{% end %}
Request Body:
{{ngx.var.request_body or " -no body in request-"}}
]])
}
server {
# please check the benefits of reuseport https://www.nginx.com/blog/socket-sharding-nginx-release-1-9-1
# basically instructs to create an individual listening socket for each worker process (using the SO_REUSEPORT
# socket option), allowing a kernel to distribute incoming connections between worker processes.
listen 8080 default_server reuseport;
listen 8443 default_server ssl http2 reuseport;
ssl_certificate /certs/certificate.crt;
ssl_certificate_key /certs/privateKey.key;
# Replace '_' with your hostname.
server_name _;
# set long keepalive_timeout because some loadbalancer proxies expect the connection
# to remain open for at least ten minutes.
keepalive_timeout 620s;
location / {
lua_need_request_body on;
content_by_lua_block {
ngx.header["Server"] = "echoserver"
local headers = ngx.req.get_headers()
local keys = {}
for key, val in pairs(headers) do
table.insert(keys, key)
end
table.sort(keys)
ngx.say(tmpl({os=os, ngx=ngx, keys=keys, headers=headers}))
}
}
}
}

View file

@ -1,509 +0,0 @@
-- vendored from https://raw.githubusercontent.com/bungle/lua-resty-template/1f9a5c24fc7572dbf5be0b9f8168cc3984b03d24/lib/resty/template.lua
-- only modification: remove / from HTML_ENTITIES to not escape it, and fix the appropriate regex.
--[[
Copyright (c) 2014 - 2017 Aapo Talvensaari
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or
other materials provided with the distribution.
* Neither the name of the {organization} nor the names of its
contributors may be used to endorse or promote products derived from
this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--]]
local setmetatable = setmetatable
local loadstring = loadstring
local loadchunk
local tostring = tostring
local setfenv = setfenv
local require = require
local capture
local concat = table.concat
local assert = assert
local prefix
local write = io.write
local pcall = pcall
local phase
local open = io.open
local load = load
local type = type
local dump = string.dump
local find = string.find
local gsub = string.gsub
local byte = string.byte
local null
local sub = string.sub
local ngx = ngx
local jit = jit
local var
local _VERSION = _VERSION
local _ENV = _ENV
local _G = _G
local HTML_ENTITIES = {
["&"] = "&amp;",
["<"] = "&lt;",
[">"] = "&gt;",
['"'] = "&quot;",
["'"] = "&#39;",
}
local CODE_ENTITIES = {
["{"] = "&#123;",
["}"] = "&#125;",
["&"] = "&amp;",
["<"] = "&lt;",
[">"] = "&gt;",
['"'] = "&quot;",
["'"] = "&#39;",
["/"] = "&#47;"
}
local VAR_PHASES
local ok, newtab = pcall(require, "table.new")
if not ok then newtab = function() return {} end end
local caching = true
local template = newtab(0, 12)
template._VERSION = "1.9"
template.cache = {}
local function enabled(val)
if val == nil then return true end
return val == true or (val == "1" or val == "true" or val == "on")
end
local function trim(s)
return gsub(gsub(s, "^%s+", ""), "%s+$", "")
end
local function rpos(view, s)
while s > 0 do
local c = sub(view, s, s)
if c == " " or c == "\t" or c == "\0" or c == "\x0B" then
s = s - 1
else
break
end
end
return s
end
local function escaped(view, s)
if s > 1 and sub(view, s - 1, s - 1) == "\\" then
if s > 2 and sub(view, s - 2, s - 2) == "\\" then
return false, 1
else
return true, 1
end
end
return false, 0
end
local function readfile(path)
local file = open(path, "rb")
if not file then return nil end
local content = file:read "*a"
file:close()
return content
end
local function loadlua(path)
return readfile(path) or path
end
local function loadngx(path)
local vars = VAR_PHASES[phase()]
local file, location = path, vars and var.template_location
if sub(file, 1) == "/" then file = sub(file, 2) end
if location and location ~= "" then
if sub(location, -1) == "/" then location = sub(location, 1, -2) end
local res = capture(concat{ location, '/', file})
if res.status == 200 then return res.body end
end
local root = vars and (var.template_root or var.document_root) or prefix
if sub(root, -1) == "/" then root = sub(root, 1, -2) end
return readfile(concat{ root, "/", file }) or path
end
do
if ngx then
VAR_PHASES = {
set = true,
rewrite = true,
access = true,
content = true,
header_filter = true,
body_filter = true,
log = true
}
template.print = ngx.print or write
template.load = loadngx
prefix, var, capture, null, phase = ngx.config.prefix(), ngx.var, ngx.location.capture, ngx.null, ngx.get_phase
if VAR_PHASES[phase()] then
caching = enabled(var.template_cache)
end
else
template.print = write
template.load = loadlua
end
if _VERSION == "Lua 5.1" then
local context = { __index = function(t, k)
return t.context[k] or t.template[k] or _G[k]
end }
if jit then
loadchunk = function(view)
return assert(load(view, nil, nil, setmetatable({ template = template }, context)))
end
else
loadchunk = function(view)
local func = assert(loadstring(view))
setfenv(func, setmetatable({ template = template }, context))
return func
end
end
else
local context = { __index = function(t, k)
return t.context[k] or t.template[k] or _ENV[k]
end }
loadchunk = function(view)
return assert(load(view, nil, nil, setmetatable({ template = template }, context)))
end
end
end
function template.caching(enable)
if enable ~= nil then caching = enable == true end
return caching
end
function template.output(s)
if s == nil or s == null then return "" end
if type(s) == "function" then return template.output(s()) end
return tostring(s)
end
function template.escape(s, c)
if type(s) == "string" then
if c then return gsub(s, "[}{\">/<'&]", CODE_ENTITIES) end
return gsub(s, "[\"><'&]", HTML_ENTITIES)
end
return template.output(s)
end
function template.new(view, layout)
assert(view, "view was not provided for template.new(view, layout).")
local render, compile = template.render, template.compile
if layout then
if type(layout) == "table" then
return setmetatable({ render = function(self, context)
local context = context or self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
layout.blocks = context.blocks or {}
layout.view = context.view or ""
return layout:render()
end }, { __tostring = function(self)
local context = self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
layout.blocks = context.blocks or {}
layout.view = context.view
return tostring(layout)
end })
else
return setmetatable({ render = function(self, context)
local context = context or self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
return render(layout, context)
end }, { __tostring = function(self)
local context = self
context.blocks = context.blocks or {}
context.view = compile(view)(context)
return compile(layout)(context)
end })
end
end
return setmetatable({ render = function(self, context)
return render(view, context or self)
end }, { __tostring = function(self)
return compile(view)(self)
end })
end
function template.precompile(view, path, strip)
local chunk = dump(template.compile(view), strip ~= false)
if path then
local file = open(path, "wb")
file:write(chunk)
file:close()
end
return chunk
end
function template.compile(view, key, plain)
assert(view, "view was not provided for template.compile(view, key, plain).")
if key == "no-cache" then
return loadchunk(template.parse(view, plain)), false
end
key = key or view
local cache = template.cache
if cache[key] then return cache[key], true end
local func = loadchunk(template.parse(view, plain))
if caching then cache[key] = func end
return func, false
end
function template.parse(view, plain)
assert(view, "view was not provided for template.parse(view, plain).")
if not plain then
view = template.load(view)
if byte(view, 1, 1) == 27 then return view end
end
local j = 2
local c = {[[
context=... or {}
local function include(v, c) return template.compile(v)(c or context) end
local ___,blocks,layout={},blocks or {}
]] }
local i, s = 1, find(view, "{", 1, true)
while s do
local t, p = sub(view, s + 1, s + 1), s + 2
if t == "{" then
local e = find(view, "}}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
c[j] = "___[#___+1]=template.escape("
c[j+1] = trim(sub(view, p, e - 1))
c[j+2] = ")\n"
j=j+3
s, i = e + 1, e + 2
end
end
elseif t == "*" then
local e = find(view, "*}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
c[j] = "___[#___+1]=template.output("
c[j+1] = trim(sub(view, p, e - 1))
c[j+2] = ")\n"
j=j+3
s, i = e + 1, e + 2
end
end
elseif t == "%" then
local e = find(view, "%}", p, true)
if e then
local z, w = escaped(view, s)
if z then
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
i = s
else
local n = e + 2
if sub(view, n, n) == "\n" then
n = n + 1
end
local r = rpos(view, s - 1)
if i <= r then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, r)
c[j+2] = "]=]\n"
j=j+3
end
c[j] = trim(sub(view, p, e - 1))
c[j+1] = "\n"
j=j+2
s, i = n - 1, n
end
end
elseif t == "(" then
local e = find(view, ")}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
local f = sub(view, p, e - 1)
local x = find(f, ",", 2, true)
if x then
c[j] = "___[#___+1]=include([=["
c[j+1] = trim(sub(f, 1, x - 1))
c[j+2] = "]=],"
c[j+3] = trim(sub(f, x + 1))
c[j+4] = ")\n"
j=j+5
else
c[j] = "___[#___+1]=include([=["
c[j+1] = trim(f)
c[j+2] = "]=])\n"
j=j+3
end
s, i = e + 1, e + 2
end
end
elseif t == "[" then
local e = find(view, "]}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
c[j] = "___[#___+1]=include("
c[j+1] = trim(sub(view, p, e - 1))
c[j+2] = ")\n"
j=j+3
s, i = e + 1, e + 2
end
end
elseif t == "-" then
local e = find(view, "-}", p, true)
if e then
local x, y = find(view, sub(view, s, e + 1), e + 2, true)
if x then
local z, w = escaped(view, s)
if z then
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
i = s
else
y = y + 1
x = x - 1
if sub(view, y, y) == "\n" then
y = y + 1
end
local b = trim(sub(view, p, e - 1))
if b == "verbatim" or b == "raw" then
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
c[j] = "___[#___+1]=[=["
c[j+1] = sub(view, e + 2, x)
c[j+2] = "]=]\n"
j=j+3
else
if sub(view, x, x) == "\n" then
x = x - 1
end
local r = rpos(view, s - 1)
if i <= r then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, r)
c[j+2] = "]=]\n"
j=j+3
end
c[j] = 'blocks["'
c[j+1] = b
c[j+2] = '"]=include[=['
c[j+3] = sub(view, e + 2, x)
c[j+4] = "]=]\n"
j=j+5
end
s, i = y - 1, y
end
end
end
elseif t == "#" then
local e = find(view, "#}", p, true)
if e then
local z, w = escaped(view, s)
if i < s - w then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = sub(view, i, s - 1 - w)
c[j+2] = "]=]\n"
j=j+3
end
if z then
i = s
else
e = e + 2
if sub(view, e, e) == "\n" then
e = e + 1
end
s, i = e - 1, e
end
end
end
s = find(view, "{", s + 1, true)
end
s = sub(view, i)
if s and s ~= "" then
c[j] = "___[#___+1]=[=[\n"
c[j+1] = s
c[j+2] = "]=]\n"
j=j+3
end
c[j] = "return layout and include(layout,setmetatable({view=table.concat(___),blocks=blocks},{__index=context})) or table.concat(___)"
return concat(c)
end
function template.render(view, context, key, plain)
assert(view, "view was not provided for template.render(view, context, key, plain).")
return template.print(template.compile(view, key, plain)(context))
end
return template

View file

@ -13,7 +13,7 @@
# limitations under the License.
# 0.0.0 shouldn't clobber any released builds
TAG ?= 0.50
TAG ?= 0.58
REGISTRY ?= quay.io/kubernetes-ingress-controller
ARCH ?= $(shell go env GOARCH)
DOCKER ?= docker
@ -26,14 +26,14 @@ ifeq ($(GOHOSTOS),darwin)
SED_I=sed -i ''
endif
QEMUVERSION=v2.12.0
QEMUVERSION=v2.12.0-1
IMGNAME = nginx
IMAGE = $(REGISTRY)/$(IMGNAME)
MULTI_ARCH_IMG = $(IMAGE)-$(ARCH)
# Set default base image dynamically for each arch
BASEIMAGE?=gcr.io/google-containers/debian-base-$(ARCH):0.3
BASEIMAGE?=quay.io/kubernetes-ingress-controller/debian-base-$(ARCH):0.1
ifeq ($(ARCH),arm)
QEMUARCH=arm
@ -67,7 +67,7 @@ all-push: $(addprefix sub-push-,$(ALL_ARCH))
container: .container-$(ARCH)
.container-$(ARCH):
cp ./* $(TEMP_DIR)
cp -r ./rootfs/* $(TEMP_DIR)
cd $(TEMP_DIR) && $(SED_I) 's|BASEIMAGE|$(BASEIMAGE)|g' Dockerfile
cd $(TEMP_DIR) && $(SED_I) "s|ARCH|$(QEMUARCH)|g" Dockerfile

View file

@ -1,12 +1,11 @@
nginx 1.13.x base image using [debian-base](https://github.com/kubernetes/kubernetes/tree/master/build/debian-base)
nginx 1.15.x base image using [debian-base](https://github.com/kubernetes/kubernetes/tree/master/build/debian-base)
nginx [engine x] is an HTTP and reverse proxy server, a mail proxy server, and a generic TCP proxy server.
This custom nginx image contains:
- [stream](http://nginx.org/en/docs/stream/ngx_stream_core_module.html) tcp support for upstreams
- nginx stats [nginx-module-vts](https://github.com/vozlt/nginx-module-vts)
- [Dynamic TLS record sizing](https://blog.cloudflare.com/optimizing-tls-over-tcp-to-reduce-latency/)
- [ngx_devel_kit](https://github.com/simpl/ngx_devel_kit)
- [set-misc-nginx-module](https://github.com/openresty/set-misc-nginx-module)
@ -26,7 +25,7 @@ This image provides a default configuration file with no backend servers.
*Using docker*
```console
docker run -v /some/nginx.con:/etc/nginx/nginx.conf:ro quay.io/kubernetes-ingress-controller/nginx:0.30
docker run -v /some/nginx.con:/etc/nginx/nginx.conf:ro quay.io/kubernetes-ingress-controller/nginx:0.56
```
*Creating a replication controller*

View file

@ -28,10 +28,10 @@ spec:
metadata:
labels:
app: nginx
name: frontend
spec:
containers:
- name: nginx
image: quay.io/kubernetes-ingress-controller/nginx:0.30
image: quay.io/kubernetes-ingress-controller/nginx:0.56
ports:
- containerPort: 80
- containerPort: 443

View file

@ -17,7 +17,7 @@ FROM BASEIMAGE
CROSS_BUILD_COPY qemu-ARCH-static /usr/bin/
COPY build.sh install_lua_resty_waf.sh /
COPY . /
RUN clean-install bash
@ -30,4 +30,6 @@ RUN ln -sf /dev/stderr /var/log/nginx/error.log
EXPOSE 80 443
ENTRYPOINT [ "/entrypoint.sh" ]
CMD ["nginx", "-g", "daemon off;"]

View file

@ -19,23 +19,24 @@ set -o errexit
set -o nounset
set -o pipefail
export NGINX_VERSION=1.13.12
export NDK_VERSION=0.3.0
export VTS_VERSION=0.1.16
export SETMISC_VERSION=0.31
export NGINX_VERSION=1.15.2
export NDK_VERSION=0.3.1rc1
export SETMISC_VERSION=0.32
export STICKY_SESSIONS_VERSION=08a395c66e42
export MORE_HEADERS_VERSION=0.33
export NGINX_DIGEST_AUTH=274490cec649e7300fea97fed13d84e596bbc0ce
export NGINX_SUBSTITUTIONS=bc58cb11844bc42735bbaef7085ea86ace46d05b
export NGINX_OPENTRACING_VERSION=0.3.0
export OPENTRACING_CPP_VERSION=1.4.0
export ZIPKIN_CPP_VERSION=0.3.1
export JAEGER_VERSION=0.4.1
export MODSECURITY_VERSION=1.0.0
export LUA_NGX_VERSION=0.10.13
export NGINX_OPENTRACING_VERSION=0.6.0
export OPENTRACING_CPP_VERSION=1.5.0
export ZIPKIN_CPP_VERSION=0.5.1
export JAEGER_VERSION=ba0fa3fa6dbb01995d996f988a897e272100bf95
export MODSECURITY_VERSION=37b76e88df4bce8a9846345c27271d7e6ce1acfb
export LUA_NGX_VERSION=e94f2e5d64daa45ff396e262d8dab8e56f5f10e0
export LUA_UPSTREAM_VERSION=0.07
export COOKIE_FLAG_VERSION=1.1.0
export NGINX_INFLUXDB_VERSION=f8732268d44aea706ecf8d9c6036e9b6dacc99b2
export NGINX_INFLUXDB_VERSION=f20cfb2458c338f162132f5a21eb021e2cbe6383
export GEOIP2_VERSION=2.0
export NGINX_AJP_VERSION=bf6cd93f2098b59260de8d494f0f4b1f11a84627
export BUILD_PATH=/tmp/build
@ -80,29 +81,34 @@ clean-install \
util-linux \
lua5.1 liblua5.1-0 liblua5.1-dev \
lmdb-utils \
libjemalloc1 libjemalloc-dev \
wget \
libcurl4-openssl-dev \
libprotobuf-dev protobuf-compiler \
libz-dev \
procps \
git g++ pkgconf flex bison doxygen libyajl-dev liblmdb-dev libtool dh-autoreconf libxml2 libpcre++-dev libxml2-dev \
lua-cjson \
python \
luarocks \
libmaxminddb-dev \
authbind \
dumb-init \
gdb \
|| exit 1
if [[ ${ARCH} == "x86_64" ]]; then
ln -s /usr/lib/x86_64-linux-gnu/liblua5.1.so /usr/lib/liblua.so
ln -s /usr/lib/x86_64-linux-gnu /usr/lib/lua-platform-path
ln -s /usr/lib/x86_64-linux-gnu /usr/lib/lua-platform-path
fi
if [[ ${ARCH} == "armv7l" ]]; then
ln -s /usr/lib/arm-linux-gnueabihf/liblua5.1.so /usr/lib/liblua.so
ln -s /usr/lib/arm-linux-gnueabihf /usr/lib/lua-platform-path
ln -s /usr/lib/arm-linux-gnueabihf /usr/lib/lua-platform-path
fi
if [[ ${ARCH} == "aarch64" ]]; then
ln -s /usr/lib/aarch64-linux-gnu/liblua5.1.so /usr/lib/liblua.so
ln -s /usr/lib/aarch64-linux-gnu /usr/lib/lua-platform-path
ln -s /usr/lib/aarch64-linux-gnu /usr/lib/lua-platform-path
fi
if [[ ${ARCH} == "ppc64le" ]]; then
@ -127,26 +133,26 @@ function geoip_get {
wget -O $GEOIP_FOLDER/$1 $2 || { echo "Could not download $1, exiting." ; exit 1; }
gunzip $GEOIP_FOLDER/$1
}
geoip_get "GeoIP.dat.gz" "https://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"
geoip_get "GeoLiteCity.dat.gz" "https://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
geoip_get "GeoIPASNum.dat.gz" "http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz"
geoip_get "GeoIPASNum.dat.gz" "http://download.maxmind.com/download/geoip/database/asnum/GeoIPASNum.dat.gz"
geoip_get "GeoIP.dat.gz" "https://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz"
geoip_get "GeoLite2-City.mmdb.gz" "http://geolite.maxmind.com/download/geoip/database/GeoLite2-City.tar.gz"
geoip_get "GeoLite2-ASN.mmdb.gz" "http://geolite.maxmind.com/download/geoip/database/GeoLite2-ASN.tar.gz"
geoip_get "GeoLiteCity.dat.gz" "https://geolite.maxmind.com/download/geoip/database/GeoLiteCity.dat.gz"
mkdir --verbose -p "$BUILD_PATH"
cd "$BUILD_PATH"
# download, verify and extract the source files
get_src fb92f5602cdb8d3ab1ad47dbeca151b185d62eedb67d347bbe9d79c1438c85de \
get_src eeba09aecfbe8277ac33a5a2486ec2d6731739f3c1c701b42a0c3784af67ad90 \
"http://nginx.org/download/nginx-$NGINX_VERSION.tar.gz"
get_src 88e05a99a8a7419066f5ae75966fb1efc409bad4522d14986da074554ae61619 \
get_src 49f50d4cd62b166bc1aaf712febec5e028d9f187cedbc27a610dfd01bdde2d36 \
"https://github.com/simpl/ngx_devel_kit/archive/v$NDK_VERSION.tar.gz"
get_src 97946a68937b50ab8637e1a90a13198fe376d801dc3e7447052e43c28e9ee7de \
get_src f1ad2459c4ee6a61771aa84f77871f4bfe42943a4aa4c30c62ba3f981f52c201 \
"https://github.com/openresty/set-misc-nginx-module/archive/v$SETMISC_VERSION.tar.gz"
get_src c668d0ed38afbba12f0224cb8cf5d70dcb9388723766dfb40d00539f887186fa \
"https://github.com/vozlt/nginx-module-vts/archive/v$VTS_VERSION.tar.gz"
get_src a3dcbab117a9c103bc1ea5200fc00a7b7d2af97ff7fd525f16f8ac2632e30fbf \
"https://github.com/openresty/headers-more-nginx-module/archive/v$MORE_HEADERS_VERSION.tar.gz"
@ -159,26 +165,26 @@ get_src ede0ad490cb9dd69da348bdea2a60a4c45284c9777b2f13fa48394b6b8e7671c \
get_src 618551948ab14cac51d6e4ad00452312c7b09938f59ebff4f93875013be31f2d \
"https://github.com/yaoweibin/ngx_http_substitutions_filter_module/archive/$NGINX_SUBSTITUTIONS.tar.gz"
get_src 2d2b8784a09c7bb4ae7f8a76ab679c54a683b8dda26db2f948982de0ad44c7a5 \
get_src b6a6eecb0b18b15398b7d6ed0a2db4cfd7a9015c1e26f9da4160acc588b82b6f \
"https://github.com/opentracing-contrib/nginx-opentracing/archive/v$NGINX_OPENTRACING_VERSION.tar.gz"
get_src 2eb0a4a7dc62bc8cbf12872080197b41d53b4c04966c860774a6b11fd59fad55 \
get_src 4455ca507936bc4b658ded10a90d8ebbbd61c58f06207be565a4ffdc885687b5 \
"https://github.com/opentracing/opentracing-cpp/archive/v$OPENTRACING_CPP_VERSION.tar.gz"
get_src f16a6f1eed494ca3c2607d7ad671cb134bd7eb320c5969c8281c10922a146589 \
get_src f65cbb1de638f5b7bb4a7a3e0b4a6ecef7870e119f85652e3bd5fe4ea2f15d3f \
"https://github.com/rnburn/zipkin-cpp-opentracing/archive/v$ZIPKIN_CPP_VERSION.tar.gz"
get_src 8deee6d6f7128f58bd6ba2893bd69c1fdbc8a3ad2797ba45ef94b977255d181c \
"https://github.com/SpiderLabs/ModSecurity-nginx/archive/v$MODSECURITY_VERSION.tar.gz"
get_src fe7d3188e097d68f1942d46c4adba262d9ddcf433409ebc15bb5355bfb001a4a \
"https://github.com/SpiderLabs/ModSecurity-nginx/archive/$MODSECURITY_VERSION.tar.gz"
get_src 35b5a96ceb0aec68abdf25cdb9fe43cce09b2ab7bf52fb32d77038f21fef75ac \
"https://github.com/jaegertracing/jaeger-client-cpp/archive/v$JAEGER_VERSION.tar.gz"
get_src b68286966f292fb552511b71bd8bc11af8f12c8aa760372d1437ac8760cb2f25 \
"https://github.com/jaegertracing/jaeger-client-cpp/archive/$JAEGER_VERSION.tar.gz"
get_src 9915ad1cf0734cc5b357b0d9ea92fec94764b4bf22f4dce185cbd65feda30ec1 \
"https://github.com/AirisX/nginx_cookie_flag_module/archive/v$COOKIE_FLAG_VERSION.tar.gz"
get_src ecea8c3d7f69dd48c6132498ddefb5d83ba9f387fa3d4da14e2abeacdfc8a3ee \
"https://github.com/openresty/lua-nginx-module/archive/v$LUA_NGX_VERSION.tar.gz"
get_src 027a1f1ddb35164c720451869fc5ea9095abaf70af02a1b17f59e0772c0cfec0 \
"https://github.com/openresty/lua-nginx-module/archive/$LUA_NGX_VERSION.tar.gz"
get_src 2a69815e4ae01aa8b170941a8e1a10b6f6a9aab699dee485d58f021dd933829a \
"https://github.com/openresty/lua-upstream-nginx-module/archive/v$LUA_UPSTREAM_VERSION.tar.gz"
@ -213,9 +219,14 @@ get_src d81b33129c6fb5203b571fa4d8394823bf473d8872c0357a1d0f14420b1483bd \
get_src 76d8638a350a0484b3d6658e329ba38bb831d407eaa6dce2a084a27a22063133 \
"https://github.com/openresty/luajit2/archive/v2.1-20180420.tar.gz"
get_src e41589bd88953276c16c4817ab9b4faba1aca21d9bb70a8c1714505176c16ae4 \
get_src 1897d7677d99c1cedeb95b2eb00652a4a7e8e604304c3053a93bd3ba7dd82884 \
"https://github.com/influxdata/nginx-influxdb-module/archive/$NGINX_INFLUXDB_VERSION.tar.gz"
get_src ebb4652c4f9a2e1ee31fddefc4c93ff78e651a4b2727d3453d026bccbd708d99 \
"https://github.com/leev/ngx_http_geoip2_module/archive/$GEOIP2_VERSION.tar.gz"
get_src 5f629a50ba22347c441421091da70fdc2ac14586619934534e5a0f8a1390a950 \
"https://github.com/yaoweibin/nginx_ajp_module/archive/$NGINX_AJP_VERSION.tar.gz"
# improve compilation times
CORES=$(($(grep -c ^processor /proc/cpuinfo) - 0))
@ -275,29 +286,66 @@ fi
cd "$BUILD_PATH/opentracing-cpp-$OPENTRACING_CPP_VERSION"
mkdir .build
cd .build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF ..
cmake -DCMAKE_BUILD_TYPE=Release \
-DCMAKE_CXX_FLAGS="-fPIC" \
-DBUILD_TESTING=OFF \
-DBUILD_MOCKTRACER=OFF \
..
make
make install
# build zipkin lib
# build jaeger lib
cd "$BUILD_PATH/jaeger-client-cpp-$JAEGER_VERSION"
sed -i 's/-Werror//' CMakeLists.txt
sed -i 's/-Werror/-Wno-psabi/' CMakeLists.txt
cat <<EOF > export.map
{
global:
OpenTracingMakeTracerFactory;
local: *;
};
EOF
mkdir .build
cd .build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DBUILD_TESTING=OFF -DJAEGERTRACING_WITH_YAML_CPP=OFF -DJAEGERTRACING_BUILD_EXAMPLES=OFF ..
cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_TESTING=OFF \
-DJAEGERTRACING_BUILD_EXAMPLES=OFF \
-DJAEGERTRACING_BUILD_CROSSDOCK=OFF \
-DJAEGERTRACING_COVERAGE=OFF \
-DJAEGERTRACING_PLUGIN=ON \
-DHUNTER_CONFIGURATION_TYPES=Release \
-DJAEGERTRACING_WITH_YAML_CPP=ON ..
make
make install
export HUNTER_INSTALL_DIR=$(cat _3rdParty/Hunter/install-root-dir)
echo "HUNTER_INSTALL_DIR: ${HUNTER_INSTALL_DIR}"
cp $HUNTER_INSTALL_DIR/lib/libthrift* /usr/local/lib
rm /usr/local/lib/libthrift*.a
export HUNTER_INSTALL_DIR=$(cat _3rdParty/Hunter/install-root-dir) \
mv libjaegertracing_plugin.so /usr/local/lib/libjaegertracing_plugin.so
# build zipkin lib
cd "$BUILD_PATH/zipkin-cpp-opentracing-$ZIPKIN_CPP_VERSION"
cat <<EOF > export.map
{
global:
OpenTracingMakeTracerFactory;
local: *;
};
EOF
mkdir .build
cd .build
cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS=1 -DBUILD_TESTING=OFF ..
cmake -DCMAKE_BUILD_TYPE=Release \
-DBUILD_SHARED_LIBS=ON \
-DBUILD_PLUGIN=ON \
-DBUILD_TESTING=OFF ..
make
make install
@ -312,8 +360,9 @@ git submodule update
cd "$BUILD_PATH"
git clone -b v3/master --single-branch https://github.com/SpiderLabs/ModSecurity
cd ModSecurity/
# checkout v3.0.2
git checkout 8d0f51beda5c031e38741c27f29b67f0266352bb
# TODO: use a tag once 3.0.3 is released
# checkout v3.0.3
# git checkout
git submodule init
git submodule update
sh build.sh
@ -373,6 +422,7 @@ Include /etc/nginx/owasp-modsecurity-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTE
cd "$BUILD_PATH/nginx-$NGINX_VERSION"
WITH_FLAGS="--with-debug \
--with-compat \
--with-pcre-jit \
--with-http_ssl_module \
--with-http_stub_status_module \
@ -396,8 +446,19 @@ fi
# "Combining -flto with -g is currently experimental and expected to produce unexpected results."
# https://gcc.gnu.org/onlinedocs/gcc/Optimize-Options.html
CC_OPT="-g -Og -fPIE -fstack-protector-strong -Wformat -Werror=format-security -Wdate-time -D_FORTIFY_SOURCE=2 -Wno-deprecated-declarations --param=ssp-buffer-size=4 -DTCP_FASTOPEN=23 -Wno-error=strict-aliasing -fPIC -I$HUNTER_INSTALL_DIR/include"
LD_OPT="-ljemalloc -fPIE -fPIC -pie -Wl,-z,relro -Wl,-z,now -L$HUNTER_INSTALL_DIR/lib"
CC_OPT="-g -Og -fPIE -fstack-protector-strong \
-Wformat \
-Werror=format-security \
-Wno-deprecated-declarations \
-fno-strict-aliasing \
-D_FORTIFY_SOURCE=2 \
--param=ssp-buffer-size=4 \
-DTCP_FASTOPEN=23 \
-fPIC \
-I$HUNTER_INSTALL_DIR/include \
-Wno-cast-function-type"
LD_OPT="-fPIE -fPIC -pie -Wl,-z,relro -Wl,-z,now -L$HUNTER_INSTALL_DIR/lib"
if [[ ${ARCH} == "x86_64" ]]; then
CC_OPT+=' -m64 -mtune=native'
@ -405,7 +466,6 @@ fi
WITH_MODULES="--add-module=$BUILD_PATH/ngx_devel_kit-$NDK_VERSION \
--add-module=$BUILD_PATH/set-misc-nginx-module-$SETMISC_VERSION \
--add-module=$BUILD_PATH/nginx-module-vts-$VTS_VERSION \
--add-module=$BUILD_PATH/headers-more-nginx-module-$MORE_HEADERS_VERSION \
--add-module=$BUILD_PATH/nginx-goodies-nginx-sticky-module-ng-$STICKY_SESSIONS_VERSION \
--add-module=$BUILD_PATH/nginx-http-auth-digest-$NGINX_DIGEST_AUTH \
@ -415,9 +475,9 @@ WITH_MODULES="--add-module=$BUILD_PATH/ngx_devel_kit-$NDK_VERSION \
--add-module=$BUILD_PATH/nginx_cookie_flag_module-$COOKIE_FLAG_VERSION \
--add-module=$BUILD_PATH/nginx-influxdb-module-$NGINX_INFLUXDB_VERSION \
--add-dynamic-module=$BUILD_PATH/nginx-opentracing-$NGINX_OPENTRACING_VERSION/opentracing \
--add-dynamic-module=$BUILD_PATH/nginx-opentracing-$NGINX_OPENTRACING_VERSION/jaeger \
--add-dynamic-module=$BUILD_PATH/nginx-opentracing-$NGINX_OPENTRACING_VERSION/zipkin \
--add-dynamic-module=$BUILD_PATH/ModSecurity-nginx-$MODSECURITY_VERSION \
--add-dynamic-module=$BUILD_PATH/ngx_http_geoip2_module-${GEOIP2_VERSION} \
--add-module=$BUILD_PATH/nginx_ajp_module-${NGINX_AJP_VERSION} \
--add-module=$BUILD_PATH/ngx_brotli"
./configure \
@ -441,14 +501,19 @@ WITH_MODULES="--add-module=$BUILD_PATH/ngx_devel_kit-$NDK_VERSION \
--without-http_scgi_module \
--with-cc-opt="${CC_OPT}" \
--with-ld-opt="${LD_OPT}" \
${WITH_MODULES} \
&& make || exit 1 \
&& make install || exit 1
--user=www-data \
--group=www-data \
${WITH_MODULES}
make || exit 1
make install || exit 1
echo "Cleaning..."
cd /
mv /usr/share/nginx/sbin/nginx /usr/sbin
apt-mark unmarkauto \
bash \
curl ca-certificates \
@ -456,7 +521,7 @@ apt-mark unmarkauto \
libpcre3 \
zlib1g \
libaio1 \
xz-utils \
gdb \
geoip-bin \
libyajl2 liblmdb0 libxml2 libpcre++ \
gzip \
@ -464,8 +529,6 @@ apt-mark unmarkauto \
apt-get remove -y --purge \
build-essential \
gcc-6 \
cpp-6 \
libgeoip-dev \
libpcre3-dev \
libssl-dev \
@ -474,14 +537,14 @@ apt-get remove -y --purge \
linux-libc-dev \
cmake \
wget \
patch \
protobuf-compiler \
python \
xz-utils \
git g++ pkgconf flex bison doxygen libyajl-dev liblmdb-dev libgeoip-dev libtool dh-autoreconf libpcre++-dev libxml2-dev
apt-get autoremove -y
mkdir -p /var/lib/nginx/body /usr/share/nginx/html
mv /usr/share/nginx/sbin/nginx /usr/sbin
rm -rf "$BUILD_PATH"
rm -Rf /usr/share/man /usr/share/doc
rm -rf /tmp/* /var/tmp/*
@ -491,7 +554,29 @@ rm -rf /usr/local/modsecurity/bin
rm -rf /usr/local/modsecurity/include
rm -rf /usr/local/modsecurity/lib/libmodsecurity.a
rm -rf /root/.cache
rm -rf /etc/nginx/owasp-modsecurity-crs/.git
rm -rf /etc/nginx/owasp-modsecurity-crs/util/regression-tests
rm -rf $HOME/.hunter
# update image permissions
writeDirs=( \
/etc/nginx \
/var/lib/nginx \
/var/log/nginx \
/opt/modsecurity/var/log \
/opt/modsecurity/var/upload \
/opt/modsecurity/var/audit \
);
for dir in "${writeDirs[@]}"; do
mkdir -p ${dir};
chown -R www-data.www-data ${dir};
done
chmod 755 /etc/authbind/byuid/33
chown www-data /etc/authbind/byuid/33
chmod 755 /etc/authbind/byport/*
chown www-data /etc/authbind/byport/*

View file

@ -1,4 +1,6 @@
# Copyright 2017 The Kubernetes Authors. All rights reserved.
#!/usr/bin/dumb-init /bin/bash
# Copyright 2018 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@ -12,12 +14,6 @@
# See the License for the specific language governing permissions and
# limitations under the License.
FROM BASEIMAGE
ADD nginx.conf /etc/nginx/nginx.conf
ADD template.lua /usr/local/share/lua/5.1/
ADD README.md README.md
ADD run.sh /usr/local/bin/run.sh
RUN chmod +x /usr/local/bin/run.sh
ENTRYPOINT ["/usr/local/bin/run.sh"]
set -e
authbind --deep $@

View file

@ -0,0 +1,4 @@
0.0.0.0:1-1023
0.0.0.0:1-1023
::0:1-1023
::0:1-1023

View file

@ -33,6 +33,9 @@ if [[ ${ARCH} != "x86_64" ]]; then
luarocks install lrexlib-pcre 2.7.2-1 PCRE_LIBDIR=${PCRE_LIBDIR}
fi
curl -o 96b0a04ce62dd01b6c6c8a8c97df7ce9916d173e.patch -sSL https://github.com/p0pr0ck5/lua-resty-waf/commit/96b0a04ce62dd01b6c6c8a8c97df7ce9916d173e.patch
patch -p1 < 96b0a04ce62dd01b6c6c8a8c97df7ce9916d173e.patch
make
make install-check

View file

@ -25,6 +25,12 @@ import (
"k8s.io/kubernetes/pkg/util/filesystem"
)
// ReadWriteByUser defines linux permission to read and write files for the owner user
const ReadWriteByUser = 0660
// ReadByUserGroup defines linux permission to read files by the user and group owner/s
const ReadByUserGroup = 0640
// Filesystem is an interface that we can use to mock various filesystem operations
type Filesystem interface {
filesystem.Filesystem
@ -35,7 +41,7 @@ func NewLocalFS() (Filesystem, error) {
fs := filesystem.DefaultFs{}
for _, directory := range directories {
err := fs.MkdirAll(directory, 0655)
err := fs.MkdirAll(directory, ReadWriteByUser)
if err != nil {
return nil, err
}
@ -97,12 +103,5 @@ func NewFakeFS() (Filesystem, error) {
}
}
fakeFs.MkdirAll("/run", 0655)
fakeFs.MkdirAll("/proc", 0655)
fakeFs.MkdirAll("/etc/nginx/template", 0655)
fakeFs.MkdirAll(DefaultSSLDirectory, 0655)
fakeFs.MkdirAll(AuthDirectory, 0655)
return fakeFs, nil
}

View file

@ -29,6 +29,7 @@ import (
"k8s.io/ingress-nginx/internal/ingress/annotations/auth"
"k8s.io/ingress-nginx/internal/ingress/annotations/authreq"
"k8s.io/ingress-nginx/internal/ingress/annotations/authtls"
"k8s.io/ingress-nginx/internal/ingress/annotations/backendprotocol"
"k8s.io/ingress-nginx/internal/ingress/annotations/clientbodybuffersize"
"k8s.io/ingress-nginx/internal/ingress/annotations/connection"
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
@ -54,7 +55,6 @@ import (
"k8s.io/ingress-nginx/internal/ingress/annotations/sslpassthrough"
"k8s.io/ingress-nginx/internal/ingress/annotations/upstreamhashby"
"k8s.io/ingress-nginx/internal/ingress/annotations/upstreamvhost"
"k8s.io/ingress-nginx/internal/ingress/annotations/vtsfilterkey"
"k8s.io/ingress-nginx/internal/ingress/annotations/xforwardedprefix"
"k8s.io/ingress-nginx/internal/ingress/errors"
"k8s.io/ingress-nginx/internal/ingress/resolver"
@ -66,6 +66,7 @@ const DeniedKeyName = "Denied"
// Ingress defines the valid annotations present in one NGINX Ingress rule
type Ingress struct {
metav1.ObjectMeta
BackendProtocol string
Alias string
BasicDigestAuth auth.Config
CertificateAuth authtls.Config
@ -90,7 +91,6 @@ type Ingress struct {
UpstreamHashBy string
LoadBalancing string
UpstreamVhost string
VtsFilterKey string
Whitelist ipwhitelist.SourceRange
XForwardedPrefix bool
SSLCiphers string
@ -132,7 +132,6 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
"UpstreamHashBy": upstreamhashby.NewParser(cfg),
"LoadBalancing": loadbalancing.NewParser(cfg),
"UpstreamVhost": upstreamvhost.NewParser(cfg),
"VtsFilterKey": vtsfilterkey.NewParser(cfg),
"Whitelist": ipwhitelist.NewParser(cfg),
"XForwardedPrefix": xforwardedprefix.NewParser(cfg),
"SSLCiphers": sslcipher.NewParser(cfg),
@ -140,6 +139,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
"GRPC": grpc.NewParser(cfg),
"LuaRestyWAF": luarestywaf.NewParser(cfg),
"InfluxDB": influxdb.NewParser(cfg),
"BackendProtocol": backendprotocol.NewParser(cfg),
},
}
}

View file

@ -19,8 +19,6 @@ package auth
import (
"fmt"
"io/ioutil"
"os"
"path"
"regexp"
"github.com/pkg/errors"
@ -86,17 +84,6 @@ type auth struct {
// NewParser creates a new authentication annotation parser
func NewParser(authDirectory string, r resolver.Resolver) parser.IngressAnnotation {
os.MkdirAll(authDirectory, 0755)
currPath := authDirectory
for currPath != "/" {
currPath = path.Dir(currPath)
err := os.Chmod(currPath, 0755)
if err != nil {
break
}
}
return auth{r, authDirectory}
}
@ -157,8 +144,7 @@ func dumpSecret(filename string, secret *api.Secret) error {
}
}
// TODO: check permissions required
err := ioutil.WriteFile(filename, val, 0777)
err := ioutil.WriteFile(filename, val, file.ReadWriteByUser)
if err != nil {
return ing_errors.LocationDenied{
Reason: errors.Wrap(err, "unexpected error creating password file"),

View file

@ -0,0 +1,62 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package backendprotocol
import (
"regexp"
"strings"
"github.com/golang/glog"
extensions "k8s.io/api/extensions/v1beta1"
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
"k8s.io/ingress-nginx/internal/ingress/resolver"
)
var (
validProtocols = regexp.MustCompile(`^(HTTP|HTTPS|AJP|GRPC|GRPCS)$`)
)
type backendProtocol struct {
r resolver.Resolver
}
// NewParser creates a new backend protocol annotation parser
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
return backendProtocol{r}
}
// ParseAnnotations parses the annotations contained in the ingress
// rule used to indicate the backend protocol.
func (a backendProtocol) Parse(ing *extensions.Ingress) (interface{}, error) {
if ing.GetAnnotations() == nil {
return "HTTP", nil
}
proto, err := parser.GetStringAnnotation("backend-protocol", ing)
if err != nil {
return "HTTP", nil
}
proto = strings.TrimSpace(strings.ToUpper(proto))
if !validProtocols.MatchString(proto) {
glog.Warningf("Protocol %v is not a valid value for the backend-protocol annotation. Using HTTP as protocol", proto)
return "HTTP", nil
}
return proto, nil
}

View file

@ -0,0 +1,68 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package backendprotocol
import (
"testing"
api "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
"k8s.io/ingress-nginx/internal/ingress/resolver"
"k8s.io/apimachinery/pkg/util/intstr"
)
func buildIngress() *extensions.Ingress {
return &extensions.Ingress{
ObjectMeta: meta_v1.ObjectMeta{
Name: "foo",
Namespace: api.NamespaceDefault,
},
Spec: extensions.IngressSpec{
Backend: &extensions.IngressBackend{
ServiceName: "default-backend",
ServicePort: intstr.FromInt(80),
},
},
}
}
func TestParseAnnotations(t *testing.T) {
ing := buildIngress()
_, err := NewParser(&resolver.Mock{}).Parse(ing)
if err != nil {
t.Errorf("unexpected error: %v", err)
}
data := map[string]string{}
data[parser.GetAnnotationWithPrefix("backend-protocol")] = "HTTPS"
ing.SetAnnotations(data)
i, err := NewParser(&resolver.Mock{}).Parse(ing)
if err != nil {
t.Errorf("unexpected error parsing ingress with backend-protocol")
}
val, ok := i.(string)
if !ok {
t.Errorf("expected a string type")
}
if val != "HTTPS" {
t.Errorf("expected HTTPS but %v returned", val)
}
}

View file

@ -28,6 +28,8 @@ import (
"k8s.io/ingress-nginx/internal/ingress/resolver"
)
const defaultPermanentRedirectCode = http.StatusMovedPermanently
// Config returns the redirect configuration for an Ingress rule
type Config struct {
URL string `json:"url"`
@ -48,7 +50,7 @@ func NewParser(r resolver.Resolver) parser.IngressAnnotation {
// rule used to create a redirect in the paths defined in the rule.
// If the Ingress contains both annotations the execution order is
// temporal and then permanent
func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
func (r redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
r3w, _ := parser.GetBoolAnnotation("from-to-www-redirect", ing)
tr, err := parser.GetStringAnnotation("temporal-redirect", ing)
@ -73,20 +75,19 @@ func (a redirect) Parse(ing *extensions.Ingress) (interface{}, error) {
return nil, err
}
if pr != "" {
if err := isValidURL(pr); err != nil {
return nil, err
}
return &Config{
URL: pr,
Code: http.StatusMovedPermanently,
FromToWWW: r3w,
}, nil
prc, err := parser.GetIntAnnotation("permanent-redirect-code", ing)
if err != nil && !errors.IsMissingAnnotations(err) {
return nil, err
}
if r3w {
if prc < http.StatusMultipleChoices || prc > http.StatusPermanentRedirect {
prc = defaultPermanentRedirectCode
}
if pr != "" || r3w {
return &Config{
URL: pr,
Code: prc,
FromToWWW: r3w,
}, nil
}

View file

@ -0,0 +1,101 @@
/*
Copyright 2018 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package redirect
import (
"net/http"
"strconv"
"testing"
extensions "k8s.io/api/extensions/v1beta1"
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
"k8s.io/ingress-nginx/internal/ingress/resolver"
)
const (
defRedirectURL = "http://some-site.com"
)
func TestPermanentRedirectWithDefaultCode(t *testing.T) {
rp := NewParser(resolver.Mock{})
if rp == nil {
t.Fatalf("Expected a parser.IngressAnnotation but returned nil")
}
ing := new(extensions.Ingress)
data := make(map[string]string, 1)
data[parser.GetAnnotationWithPrefix("permanent-redirect")] = defRedirectURL
ing.SetAnnotations(data)
i, err := rp.Parse(ing)
if err != nil {
t.Errorf("Unexpected error with ingress: %v", err)
}
redirect, ok := i.(*Config)
if !ok {
t.Errorf("Expected a Redirect type")
}
if redirect.URL != defRedirectURL {
t.Errorf("Expected %v as redirect but returned %s", defRedirectURL, redirect.URL)
}
if redirect.Code != defaultPermanentRedirectCode {
t.Errorf("Expected %v as redirect to have a code %d but had %d", defRedirectURL, defaultPermanentRedirectCode, redirect.Code)
}
}
func TestPermanentRedirectWithCustomCode(t *testing.T) {
rp := NewParser(resolver.Mock{})
if rp == nil {
t.Fatalf("Expected a parser.IngressAnnotation but returned nil")
}
testCases := map[string]struct {
input int
expectOutput int
}{
"valid code": {http.StatusPermanentRedirect, http.StatusPermanentRedirect},
"invalid code": {http.StatusTeapot, defaultPermanentRedirectCode},
}
for n, tc := range testCases {
t.Run(n, func(t *testing.T) {
ing := new(extensions.Ingress)
data := make(map[string]string, 2)
data[parser.GetAnnotationWithPrefix("permanent-redirect")] = defRedirectURL
data[parser.GetAnnotationWithPrefix("permanent-redirect-code")] = strconv.Itoa(tc.input)
ing.SetAnnotations(data)
i, err := rp.Parse(ing)
if err != nil {
t.Errorf("Unexpected error with ingress: %v", err)
}
redirect, ok := i.(*Config)
if !ok {
t.Errorf("Expected a redirect Config type")
}
if redirect.URL != defRedirectURL {
t.Errorf("Expected %v as redirect but returned %s", defRedirectURL, redirect.URL)
}
if redirect.Code != tc.expectOutput {
t.Errorf("Expected %v as redirect to have a code %d but had %d", defRedirectURL, tc.expectOutput, redirect.Code)
}
})
}
}

View file

@ -1,40 +0,0 @@
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package vtsfilterkey
import (
extensions "k8s.io/api/extensions/v1beta1"
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
"k8s.io/ingress-nginx/internal/ingress/resolver"
)
type vtsFilterKey struct {
r resolver.Resolver
}
// NewParser creates a new vts filter key annotation parser
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
return vtsFilterKey{r}
}
// Parse parses the annotations contained in the ingress rule
// used to indicate if the location/s contains a fragment of
// configuration to be included inside the paths of the rules
func (a vtsFilterKey) Parse(ing *extensions.Ingress) (interface{}, error) {
return parser.GetStringAnnotation("vts-filter-key", ing)
}

View file

@ -26,6 +26,8 @@ import (
"github.com/pkg/errors"
)
const nginxPID = "/tmp/nginx.pid"
// Name returns the healthcheck name
func (n NGINXController) Name() string {
return "nginx-ingress-controller"
@ -33,7 +35,7 @@ func (n NGINXController) Name() string {
// Check returns if the nginx healthz endpoint is returning ok (status code 200)
func (n *NGINXController) Check(_ *http.Request) error {
res, err := http.Get(fmt.Sprintf("http://0.0.0.0:%v%v", n.cfg.ListenPorts.Status, ngxHealthPath))
res, err := http.Get(fmt.Sprintf("http://127.0.0.1:%v%v", n.cfg.ListenPorts.Status, ngxHealthPath))
if err != nil {
return err
}
@ -43,7 +45,7 @@ func (n *NGINXController) Check(_ *http.Request) error {
}
if n.cfg.DynamicConfigurationEnabled {
res, err := http.Get(fmt.Sprintf("http://0.0.0.0:%v/is-dynamic-lb-initialized", n.cfg.ListenPorts.Status))
res, err := http.Get(fmt.Sprintf("http://127.0.0.1:%v/is-dynamic-lb-initialized", n.cfg.ListenPorts.Status))
if err != nil {
return err
}
@ -58,13 +60,13 @@ func (n *NGINXController) Check(_ *http.Request) error {
if err != nil {
return errors.Wrap(err, "unexpected error reading /proc directory")
}
f, err := n.fileSystem.ReadFile("/run/nginx.pid")
f, err := n.fileSystem.ReadFile(nginxPID)
if err != nil {
return errors.Wrap(err, "unexpected error reading /run/nginx.pid")
return errors.Wrapf(err, "unexpected error reading %v", nginxPID)
}
pid, err := strconv.Atoi(strings.TrimRight(string(f), "\r\n"))
if err != nil {
return errors.Wrap(err, "unexpected error reading the PID from /run/nginx.pid")
return errors.Wrapf(err, "unexpected error reading the nginx PID from %v", nginxPID)
}
_, err = fs.NewProc(pid)

View file

@ -27,6 +27,7 @@ import (
"k8s.io/apiserver/pkg/server/healthz"
"k8s.io/kubernetes/pkg/util/filesystem"
"k8s.io/ingress-nginx/internal/file"
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
)
@ -60,8 +61,8 @@ func TestNginxCheck(t *testing.T) {
})
// create pid file
fs.MkdirAll("/run", 0655)
pidFile, err := fs.Create("/run/nginx.pid")
fs.MkdirAll("/tmp", file.ReadWriteByUser)
pidFile, err := fs.Create(nginxPID)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

View file

@ -77,7 +77,7 @@ const (
sslSessionCacheSize = "10m"
// Default setting for load balancer algorithm
defaultLoadBalancerAlgorithm = "least_conn"
defaultLoadBalancerAlgorithm = ""
// Parameters for a shared memory zone that will keep states for various keys.
// http://nginx.org/en/docs/http/ngx_http_limit_conn_module.html#limit_conn_zone
@ -161,31 +161,6 @@ type Configuration struct {
// By default this is enabled
IgnoreInvalidHeaders bool `json:"ignore-invalid-headers"`
// EnableVtsStatus allows the replacement of the default status page with a third party module named
// nginx-module-vts - https://github.com/vozlt/nginx-module-vts
// By default this is disabled
EnableVtsStatus bool `json:"enable-vts-status,omitempty"`
// Vts config on http level
// Description: Sets parameters for a shared memory zone that will keep states for various keys. The cache is shared between all worker processe
// https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_zone
// Default value is 10m
VtsStatusZoneSize string `json:"vts-status-zone-size,omitempty"`
// Vts config on http level
// Description: Enables the keys by user defined variable. The key is a key string to calculate traffic.
// The name is a group string to calculate traffic. The key and name can contain variables such as $host,
// $server_name. The name's group belongs to filterZones if specified. The key's group belongs to serverZones
// if not specified second argument name. The example with geoip module is as follows:
// https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_filter_by_set_key
// Default value is $geoip_country_code country::*
VtsDefaultFilterKey string `json:"vts-default-filter-key,omitempty"`
// Description: Sets sum key used by vts json output, and the sum label in prometheus output.
// These indicate metrics values for all server zones combined, rather than for a specific one.
// Default value is *
VtsSumKey string `json:"vts-sum-key,omitempty"`
// RetryNonIdempotent since 1.9.13 NGINX will not retry non-idempotent requests (POST, LOCK, PATCH)
// in case of an error. The previous behavior can be restored using the value true
RetryNonIdempotent bool `json:"retry-non-idempotent"`
@ -247,6 +222,12 @@ type Configuration struct {
// http://nginx.org/en/docs/http/ngx_http_log_module.html#log_format
LogFormatStream string `json:"log-format-stream,omitempty"`
// If disabled, a worker process will accept one new connection at a time.
// Otherwise, a worker process will accept all new connections at a time.
// http://nginx.org/en/docs/ngx_core_module.html#multi_accept
// Default: true
EnableMultiAccept bool `json:"enable-multi-accept,omitempty"`
// Maximum number of simultaneous connections that can be opened by each worker process
// http://nginx.org/en/docs/ngx_core_module.html#worker_connections
MaxWorkerConnections int `json:"max-worker-connections,omitempty"`
@ -328,7 +309,7 @@ type Configuration struct {
// Sets the secret key used to encrypt and decrypt TLS session tickets.
// http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_session_tickets
// By default, a randomly generated key is used.
// Example: openssl rand 80 | base64 -w0
// Example: openssl rand 80 | openssl enc -A -base64
SSLSessionTicketKey string `json:"ssl-session-ticket-key,omitempty"`
// Time during which a client may reuse the session parameters stored in a cache.
@ -375,6 +356,9 @@ type Configuration struct {
// Default: true
UseHTTP2 bool `json:"use-http2,omitempty"`
// gzip Compression Level that will be used
GzipLevel int `json:"gzip-level,omitempty"`
// MIME types in addition to "text/html" to compress. The special value “*” matches any MIME type.
// Responses with the “text/html” type are always compressed if UseGzip is enabled
GzipTypes string `json:"gzip-types,omitempty"`
@ -461,6 +445,10 @@ type Configuration struct {
// Default: nginx
ZipkinServiceName string `json:"zipkin-service-name"`
// ZipkinSampleRate specifies sampling rate for traces
// Default: 1.0
ZipkinSampleRate float32 `json:"zipkin-sample-rate"`
// JaegerCollectorHost specifies the host to use when uploading traces
JaegerCollectorHost string `json:"jaeger-collector-host"`
@ -480,6 +468,9 @@ type Configuration struct {
// Default: 1
JaegerSamplerParam string `json:"jaeger-sampler-param"`
// MainSnippet adds custom configuration to the main section of the nginx configuration
MainSnippet string `json:"main-snippet"`
// HTTPSnippet adds custom configuration to the http section of the nginx configuration
HTTPSnippet string `json:"http-snippet"`
@ -497,8 +488,7 @@ type Configuration struct {
// ReusePort instructs NGINX to create an individual listening socket for
// each worker process (using the SO_REUSEPORT socket option), allowing a
// kernel to distribute incoming connections between worker processes
// Default: false
// Reason for the default: https://trac.nginx.org/nginx/ticket/1300
// Default: true
ReusePort bool `json:"reuse-port"`
// HideHeaders sets additional header that will not be passed from the upstream
@ -534,6 +524,9 @@ type Configuration struct {
// http://github.com/influxdata/nginx-influxdb-module/
// By default this is disabled
EnableInfluxDB bool `json:"enable-influxdb"`
// Checksum contains a checksum of the configmap configuration
Checksum string `json:"-"`
}
// NewDefault returns the default nginx configuration
@ -575,6 +568,7 @@ func NewDefault() Configuration {
HSTSMaxAge: hstsMaxAge,
HSTSPreload: false,
IgnoreInvalidHeaders: true,
GzipLevel: 5,
GzipTypes: gzipTypes,
KeepAlive: 75,
KeepAliveRequests: 100,
@ -582,6 +576,7 @@ func NewDefault() Configuration {
LogFormatEscapeJSON: false,
LogFormatStream: logFormatStream,
LogFormatUpstream: logFormatUpstream,
EnableMultiAccept: true,
MaxWorkerConnections: 16384,
MapHashBucketSize: 64,
NginxStatusIpv4Whitelist: defNginxStatusIpv4Whitelist,
@ -592,6 +587,7 @@ func NewDefault() Configuration {
ProxyHeadersHashMaxSize: 512,
ProxyHeadersHashBucketSize: 64,
ProxyStreamResponses: 1,
ReusePort: true,
ShowServerTokens: true,
SSLBufferSize: sslBufferSize,
SSLCiphers: sslCiphers,
@ -607,9 +603,6 @@ func NewDefault() Configuration {
WorkerProcesses: strconv.Itoa(runtime.NumCPU()),
WorkerShutdownTimeout: "10s",
LoadBalanceAlgorithm: defaultLoadBalancerAlgorithm,
VtsStatusZoneSize: "10m",
VtsDefaultFilterKey: "$geoip_country_code country::*",
VtsSumKey: "*",
VariablesHashBucketSize: 128,
VariablesHashMaxSize: 2048,
UseHTTP2: true,
@ -641,6 +634,7 @@ func NewDefault() Configuration {
BindAddressIpv6: defBindAddress,
ZipkinCollectorPort: 9411,
ZipkinServiceName: "nginx",
ZipkinSampleRate: 1.0,
JaegerCollectorPort: 6831,
JaegerServiceName: "nginx",
JaegerSamplerType: "const",

File diff suppressed because it is too large Load diff

Some files were not shown because too many files have changed in this diff Show more