Skip to content
This repository has been archived by the owner on Jul 18, 2022. It is now read-only.

Commit

Permalink
Add a flag to make per-host metrics optional
Browse files Browse the repository at this point in the history
When serving many hosts from one nginx, the metrics may become too
numerous for Prometheus.  Add a flag to disable the host label, so
that metrics are totalled across all hosts.

Adds support for HTTP2 Push Preload annotation

update test for backendprotocols

Adds support for HTTP2 Push Preload annotation

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@serpro.gov.br>

Adds support for HTTP2 Push Preload annotation

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@serpro.gov.br>

Adds support for HTTP2 Push Preload annotation

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@serpro.gov.br>

Adds support for HTTP2 Push Preload annotation

Signed-off-by: Ricardo Pchevuzinske Katz <ricardo.katz@serpro.gov.br>

Adds support for HTTP2 Push Preload annotation

Adds support for HTTP2 Push Preload annotation

Update nginx to 1.15.8 (kubernetes#3601)

Fix CLA URLs
  • Loading branch information
bboreham authored and minherz committed Jan 5, 2019
1 parent 63b0137 commit caa79a7
Show file tree
Hide file tree
Showing 17 changed files with 204 additions and 16 deletions.
4 changes: 2 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ We'd love to accept your patches! Before we can take them, we have to jump a cou

Please fill out either the individual or corporate Contributor License Agreement (CLA).

* If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](http://code.google.com/legal/individual-cla-v1.0.html).
* If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](http://code.google.com/legal/corporate-cla-v1.0.html).
* If you are an individual writing original source code and you're sure you own the intellectual property, then you'll need to sign an [individual CLA](https://identity.linuxfoundation.org/projects/cncf).
* If you work for a company that wants to allow you to contribute your work, then you'll need to sign a [corporate CLA](https://identity.linuxfoundation.org/node/285/organization-signup).

Follow either of the two links above to access the appropriate CLA and instructions for how to sign and return it. Once we receive it, we'll be able to accept your pull requests.

Expand Down
3 changes: 3 additions & 0 deletions cmd/nginx/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,8 @@ Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not en

enableMetrics = flags.Bool("enable-metrics", true,
`Enables the collection of NGINX metrics`)
metricsPerHost = flags.Bool("metrics-per-host", true,
`Export metrics per-host`)

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.`)
Expand Down Expand Up @@ -227,6 +229,7 @@ Feature backed by OpenResty Lua libraries. Requires that OCSP stapling is not en
ElectionID: *electionID,
EnableProfiling: *profiling,
EnableMetrics: *enableMetrics,
MetricsPerHost: *metricsPerHost,
EnableSSLPassthrough: *enableSSLPassthrough,
EnableSSLChainCompletion: *enableSSLChainCompletion,
ResyncPeriod: *resyncPeriod,
Expand Down
2 changes: 1 addition & 1 deletion cmd/nginx/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,7 +131,7 @@ func main() {

mc := metric.NewDummyCollector()
if conf.EnableMetrics {
mc, err = metric.NewCollector(conf.ListenPorts.Status, reg)
mc, err = metric.NewCollector(conf.ListenPorts.Status, conf.MetricsPerHost, reg)
if err != nil {
klog.Fatalf("Error creating prometheus collector: %v", err)
}
Expand Down
9 changes: 9 additions & 0 deletions docs/user-guide/nginx-configuration/annotations.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ You can add these Kubernetes annotations to specific Ingress objects to customiz
|[nginx.ingress.kubernetes.io/cors-max-age](#enable-cors)|number|
|[nginx.ingress.kubernetes.io/force-ssl-redirect](#server-side-https-enforcement-through-redirect)|"true" or "false"|
|[nginx.ingress.kubernetes.io/from-to-www-redirect](#redirect-from-to-www)|"true" or "false"|
|[nginx.ingress.kubernetes.io/http2-push-preload](#http2-push-preload)|"true" or "false"|
|[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|
Expand Down Expand Up @@ -298,6 +299,14 @@ CORS can be controlled with the following annotations:
!!! note
For more information please see [https://enable-cors.org](https://enable-cors.org/server_nginx.html)

### HTTP2 Push Preload.

Enables automatic conversion of preload links specified in the “Link” response header fields into push requests.

!!! example

* `nginx.ingress.kubernetes.io/http2-push-preload: "true"`

### Server Alias

To add Server Aliases to an Ingress rule add the annotation `nginx.ingress.kubernetes.io/server-alias: "<alias>"`.
Expand Down
2 changes: 1 addition & 1 deletion images/nginx/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
# limitations under the License.

# 0.0.0 shouldn't clobber any released builds
TAG ?= 0.72
TAG ?= 0.73
REGISTRY ?= quay.io/kubernetes-ingress-controller
ARCH ?= $(shell go env GOARCH)
DOCKER ?= docker
Expand Down
8 changes: 4 additions & 4 deletions images/nginx/rootfs/build.sh
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ set -o errexit
set -o nounset
set -o pipefail

export NGINX_VERSION=1.15.7
export NGINX_VERSION=1.15.8
export NDK_VERSION=0.3.1rc1
export SETMISC_VERSION=0.32
export MORE_HEADERS_VERSION=0.33
Expand All @@ -36,7 +36,7 @@ export LUA_UPSTREAM_VERSION=0.07
export NGINX_INFLUXDB_VERSION=0e2cb6cbf850a29c81e44be9e33d9a15d45c50e8
export GEOIP2_VERSION=3.2
export NGINX_AJP_VERSION=bf6cd93f2098b59260de8d494f0f4b1f11a84627
export LUAJIT_VERSION=c58fe79b870f1934479bf14fe8035fc3d9fdfde2
export LUAJIT_VERSION=520d53a87dd44c637dddb6de313204211c2b212b

export BUILD_PATH=/tmp/build

Expand Down Expand Up @@ -128,7 +128,7 @@ mkdir --verbose -p "$BUILD_PATH"
cd "$BUILD_PATH"

# download, verify and extract the source files
get_src 8f22ea2f6c0e0a221b6ddc02b6428a3ff708e2ad55f9361102b1c9f4142bdf93 \
get_src a8bdafbca87eb99813ae4fcac1ad0875bf725ce19eb265d28268c309b2b40787 \
"https://nginx.org/download/nginx-$NGINX_VERSION.tar.gz"

get_src 49f50d4cd62b166bc1aaf712febec5e028d9f187cedbc27a610dfd01bdde2d36 \
Expand Down Expand Up @@ -197,7 +197,7 @@ get_src a77bf0d7cf6a9ba017d0dc973b1a58f13e48242dd3849c5e99c07d250667c44c \
get_src d81b33129c6fb5203b571fa4d8394823bf473d8872c0357a1d0f14420b1483bd \
"https://github.com/cloudflare/lua-resty-cookie/archive/v0.1.0.tar.gz"

get_src 21dab7625a028d4560d0215c4bc3b82f6153344f933abb99dc9fd5f0d19519ab \
get_src d04df883adb86c96a8e0fe6c404851b9c776840dbb524419c06ae3fac42c4e64 \
"https://github.com/openresty/luajit2/archive/$LUAJIT_VERSION.tar.gz"

get_src c673fcee37c1c4794f921b6710b09e8a0e1e58117aa788f798507d033f737192 \
Expand Down
3 changes: 3 additions & 0 deletions internal/ingress/annotations/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
"k8s.io/ingress-nginx/internal/ingress/annotations/cors"
"k8s.io/ingress-nginx/internal/ingress/annotations/customhttperrors"
"k8s.io/ingress-nginx/internal/ingress/annotations/defaultbackend"
"k8s.io/ingress-nginx/internal/ingress/annotations/http2pushpreload"
"k8s.io/ingress-nginx/internal/ingress/annotations/influxdb"
"k8s.io/ingress-nginx/internal/ingress/annotations/ipwhitelist"
"k8s.io/ingress-nginx/internal/ingress/annotations/loadbalancing"
Expand Down Expand Up @@ -80,6 +81,7 @@ type Ingress struct {
DefaultBackend *apiv1.Service
Denied error
ExternalAuth authreq.Config
HTTP2PushPreload bool
Proxy proxy.Config
RateLimit ratelimit.Config
Redirect redirect.Config
Expand Down Expand Up @@ -122,6 +124,7 @@ func NewAnnotationExtractor(cfg resolver.Resolver) Extractor {
"CustomHTTPErrors": customhttperrors.NewParser(cfg),
"DefaultBackend": defaultbackend.NewParser(cfg),
"ExternalAuth": authreq.NewParser(cfg),
"HTTP2PushPreload": http2pushpreload.NewParser(cfg),
"Proxy": proxy.NewParser(cfg),
"RateLimit": ratelimit.NewParser(cfg),
"Redirect": redirect.NewParser(cfg),
Expand Down
39 changes: 39 additions & 0 deletions internal/ingress/annotations/http2pushpreload/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
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 http2pushpreload

import (
extensions "k8s.io/api/extensions/v1beta1"

"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
"k8s.io/ingress-nginx/internal/ingress/resolver"
)

type http2PushPreload struct {
r resolver.Resolver
}

// NewParser creates a new http2PushPreload annotation parser
func NewParser(r resolver.Resolver) parser.IngressAnnotation {
return http2PushPreload{r}
}

// Parse parses the annotations contained in the ingress rule
// used to add http2 push preload to the server
func (h2pp http2PushPreload) Parse(ing *extensions.Ingress) (interface{}, error) {
return parser.GetBoolAnnotation("http2-push-preload", ing)
}
62 changes: 62 additions & 0 deletions internal/ingress/annotations/http2pushpreload/main_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
/*
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 http2pushpreload

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"
)

func TestParse(t *testing.T) {
annotation := parser.GetAnnotationWithPrefix("http2-push-preload")
ap := NewParser(&resolver.Mock{})
if ap == nil {
t.Fatalf("expected a parser.IngressAnnotation but returned nil")
}

testCases := []struct {
annotations map[string]string
expected bool
}{
{map[string]string{annotation: "true"}, true},
{map[string]string{annotation: "1"}, true},
{map[string]string{annotation: ""}, false},
{map[string]string{}, false},
{nil, false},
}

ing := &extensions.Ingress{
ObjectMeta: meta_v1.ObjectMeta{
Name: "foo",
Namespace: api.NamespaceDefault,
},
Spec: extensions.IngressSpec{},
}

for _, testCase := range testCases {
ing.SetAnnotations(testCase.annotations)
result, _ := ap.Parse(ing)
if result != testCase.expected {
t.Errorf("expected %v but returned %v, annotations: %s", testCase.expected, result, testCase.annotations)
}
}
}
4 changes: 3 additions & 1 deletion internal/ingress/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,8 @@ type Configuration struct {

EnableProfiling bool

EnableMetrics bool
EnableMetrics bool
MetricsPerHost bool

EnableSSLChainCompletion bool

Expand Down Expand Up @@ -472,6 +473,7 @@ func (n *NGINXController) getBackendServers(ingresses []*ingress.Ingress) ([]*in
loc.ConfigurationSnippet = anns.ConfigurationSnippet
loc.CorsConfig = anns.CorsConfig
loc.ExternalAuth = anns.ExternalAuth
loc.HTTP2PushPreload = anns.HTTP2PushPreload
loc.Proxy = anns.Proxy
loc.RateLimit = anns.RateLimit
loc.Redirect = anns.Redirect
Expand Down
18 changes: 14 additions & 4 deletions internal/ingress/metric/collectors/socket.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,12 @@ type SocketCollector struct {
metricMapping map[string]interface{}

hosts sets.String

metricsPerHost bool
}

var (
requestTags = []string{
"host",

"status",

"method",
Expand All @@ -95,7 +95,7 @@ var (

// NewSocketCollector creates a new SocketCollector instance using
// the ingress watch namespace and class used by the controller
func NewSocketCollector(pod, namespace, class string) (*SocketCollector, error) {
func NewSocketCollector(pod, namespace, class string, metricsPerHost bool) (*SocketCollector, error) {
socket := "/tmp/prometheus-nginx.socket"
listener, err := net.Listen("unix", socket)
if err != nil {
Expand All @@ -113,9 +113,16 @@ func NewSocketCollector(pod, namespace, class string) (*SocketCollector, error)
"controller_pod": pod,
}

requestTags := requestTags
if metricsPerHost {
requestTags = append(requestTags, "host")
}

sc := &SocketCollector{
listener: listener,

metricsPerHost: metricsPerHost,

responseTime: prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "response_duration_seconds",
Expand Down Expand Up @@ -219,15 +226,18 @@ func (sc *SocketCollector) handleMessage(msg []byte) {
continue
}

// Note these must match the order in requestTags at the top
requestLabels := prometheus.Labels{
"host": stats.Host,
"status": stats.Status,
"method": stats.Method,
"path": stats.Path,
"namespace": stats.Namespace,
"ingress": stats.Ingress,
"service": stats.Service,
}
if sc.metricsPerHost {
requestLabels["host"] = stats.Host
}

collectorLabels := prometheus.Labels{
"namespace": stats.Namespace,
Expand Down
2 changes: 1 addition & 1 deletion internal/ingress/metric/collectors/socket_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,7 +288,7 @@ func TestCollector(t *testing.T) {
t.Run(c.name, func(t *testing.T) {
registry := prometheus.NewPedanticRegistry()

sc, err := NewSocketCollector("pod", "default", "ingress")
sc, err := NewSocketCollector("pod", "default", "ingress", true)
if err != nil {
t.Errorf("%v: unexpected error creating new SocketCollector: %v", c.name, err)
}
Expand Down
4 changes: 2 additions & 2 deletions internal/ingress/metric/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ type collector struct {
}

// NewCollector creates a new metric collector the for ingress controller
func NewCollector(statusPort int, registry *prometheus.Registry) (Collector, error) {
func NewCollector(statusPort int, metricsPerHost bool, registry *prometheus.Registry) (Collector, error) {
podNamespace := os.Getenv("POD_NAMESPACE")
if podNamespace == "" {
podNamespace = "default"
Expand All @@ -77,7 +77,7 @@ func NewCollector(statusPort int, registry *prometheus.Registry) (Collector, err
return nil, err
}

s, err := collectors.NewSocketCollector(podName, podNamespace, class.IngressClass)
s, err := collectors.NewSocketCollector(podName, podNamespace, class.IngressClass, metricsPerHost)
if err != nil {
return nil, err
}
Expand Down
4 changes: 4 additions & 0 deletions internal/ingress/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -238,6 +238,10 @@ type Location struct {
// authentication using an external provider
// +optional
ExternalAuth authreq.Config `json:"externalAuth,omitempty"`
// HTTP2PushPreload allows to configure the HTTP2 Push Preload from backend
// original location.
// +optional
HTTP2PushPreload bool `json:"http2PushPreload,omitempty"`
// RateLimit describes a limit in the number of connections per IP
// address or connections per second.
// The Redirect annotation precedes RateLimit
Expand Down
3 changes: 3 additions & 0 deletions internal/ingress/types_equals.go
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,9 @@ func (l1 *Location) Equal(l2 *Location) bool {
if !(&l1.ExternalAuth).Equal(&l2.ExternalAuth) {
return false
}
if l1.HTTP2PushPreload != l2.HTTP2PushPreload {
return false
}
if !(&l1.RateLimit).Equal(&l2.RateLimit) {
return false
}
Expand Down
4 changes: 4 additions & 0 deletions rootfs/etc/nginx/template/nginx.tmpl
Original file line number Diff line number Diff line change
Expand Up @@ -1122,6 +1122,10 @@ stream {
rewrite_log on;
{{ end }}

{{ if $location.HTTP2PushPreload }}
http2_push_preload on;
{{ end }}

port_in_redirect {{ if $location.UsePortInRedirects }}on{{ else }}off{{ end }};

set $proxy_upstream_name "{{ buildUpstreamName $location }}";
Expand Down
Loading

0 comments on commit caa79a7

Please sign in to comment.