Merge pull request #1362 from gianrubio/customize-vts-filter-key
Customize VTS/Prometheus metrics
This commit is contained in:
commit
4d6b10a741
9 changed files with 96 additions and 26 deletions
3
.gitignore
vendored
3
.gitignore
vendored
|
@ -10,6 +10,9 @@
|
||||||
.project
|
.project
|
||||||
.settings/**
|
.settings/**
|
||||||
|
|
||||||
|
# visual studio code
|
||||||
|
.vscode/*
|
||||||
|
|
||||||
# Emacs save files
|
# Emacs save files
|
||||||
*~
|
*~
|
||||||
\#*\#
|
\#*\#
|
||||||
|
|
|
@ -537,6 +537,7 @@ The following table shows the options, the default value and a description.
|
||||||
|variables-hash-bucket-size|64|
|
|variables-hash-bucket-size|64|
|
||||||
|variables-hash-max-size|2048|
|
|variables-hash-max-size|2048|
|
||||||
|vts-status-zone-size|10m|
|
|vts-status-zone-size|10m|
|
||||||
|
|vts-default-filter-key|$geoip_country_code country::*|
|
||||||
|whitelist-source-range|permit all|
|
|whitelist-source-range|permit all|
|
||||||
|worker-processes|number of CPUs|
|
|worker-processes|number of CPUs|
|
||||||
|limit-conn-zone-variable|$binary_remote_addr|
|
|limit-conn-zone-variable|$binary_remote_addr|
|
||||||
|
|
|
@ -146,8 +146,21 @@ type Configuration struct {
|
||||||
// By default this is disabled
|
// By default this is disabled
|
||||||
EnableVtsStatus bool `json:"enable-vts-status,omitempty"`
|
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"`
|
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"`
|
||||||
|
|
||||||
// RetryNonIdempotent since 1.9.13 NGINX will not retry non-idempotent requests (POST, LOCK, PATCH)
|
// 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
|
// in case of an error. The previous behavior can be restored using the value true
|
||||||
RetryNonIdempotent bool `json:"retry-non-idempotent"`
|
RetryNonIdempotent bool `json:"retry-non-idempotent"`
|
||||||
|
@ -409,26 +422,27 @@ func NewDefault() Configuration {
|
||||||
WorkerShutdownTimeout: "10s",
|
WorkerShutdownTimeout: "10s",
|
||||||
LoadBalanceAlgorithm: defaultLoadBalancerAlgorithm,
|
LoadBalanceAlgorithm: defaultLoadBalancerAlgorithm,
|
||||||
VtsStatusZoneSize: "10m",
|
VtsStatusZoneSize: "10m",
|
||||||
|
VtsDefaultFilterKey: "$geoip_country_code country::*",
|
||||||
VariablesHashBucketSize: 64,
|
VariablesHashBucketSize: 64,
|
||||||
VariablesHashMaxSize: 2048,
|
VariablesHashMaxSize: 2048,
|
||||||
UseHTTP2: true,
|
UseHTTP2: true,
|
||||||
ProxyStreamTimeout: "600s",
|
ProxyStreamTimeout: "600s",
|
||||||
Backend: defaults.Backend{
|
Backend: defaults.Backend{
|
||||||
ProxyBodySize: bodySize,
|
ProxyBodySize: bodySize,
|
||||||
ProxyConnectTimeout: 5,
|
ProxyConnectTimeout: 5,
|
||||||
ProxyReadTimeout: 60,
|
ProxyReadTimeout: 60,
|
||||||
ProxySendTimeout: 60,
|
ProxySendTimeout: 60,
|
||||||
ProxyBufferSize: "4k",
|
ProxyBufferSize: "4k",
|
||||||
ProxyCookieDomain: "off",
|
ProxyCookieDomain: "off",
|
||||||
ProxyCookiePath: "off",
|
ProxyCookiePath: "off",
|
||||||
ProxyNextUpstream: "error timeout invalid_header http_502 http_503 http_504",
|
ProxyNextUpstream: "error timeout invalid_header http_502 http_503 http_504",
|
||||||
ProxyRequestBuffering: "on",
|
ProxyRequestBuffering: "on",
|
||||||
SSLRedirect: true,
|
SSLRedirect: true,
|
||||||
CustomHTTPErrors: []int{},
|
CustomHTTPErrors: []int{},
|
||||||
WhitelistSourceRange: []string{},
|
WhitelistSourceRange: []string{},
|
||||||
SkipAccessLogURLs: []string{},
|
SkipAccessLogURLs: []string{},
|
||||||
LimitRate: 0,
|
LimitRate: 0,
|
||||||
LimitRateAfter: 0,
|
LimitRateAfter: 0,
|
||||||
},
|
},
|
||||||
UpstreamKeepaliveConnections: 32,
|
UpstreamKeepaliveConnections: 32,
|
||||||
LimitConnZoneVariable: defaultLimitConnZoneVariable,
|
LimitConnZoneVariable: defaultLimitConnZoneVariable,
|
||||||
|
|
|
@ -96,17 +96,17 @@ func NewNGINXVTSCollector(watchNamespace, ingressClass string, port int, path st
|
||||||
filterZoneBytes: prometheus.NewDesc(
|
filterZoneBytes: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(ns, "", "filterzone_bytes_total"),
|
prometheus.BuildFQName(ns, "", "filterzone_bytes_total"),
|
||||||
"Nginx bytes count",
|
"Nginx bytes count",
|
||||||
[]string{"ingress_class", "namespace", "server_zone", "country", "direction"}, nil),
|
[]string{"ingress_class", "namespace", "server_zone", "key", "direction"}, nil),
|
||||||
|
|
||||||
filterZoneResponses: prometheus.NewDesc(
|
filterZoneResponses: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(ns, "", "filterzone_responses_total"),
|
prometheus.BuildFQName(ns, "", "filterzone_responses_total"),
|
||||||
"The number of responses with status codes 1xx, 2xx, 3xx, 4xx, and 5xx.",
|
"The number of responses with status codes 1xx, 2xx, 3xx, 4xx, and 5xx.",
|
||||||
[]string{"ingress_class", "namespace", "server_zone", "country", "status_code"}, nil),
|
[]string{"ingress_class", "namespace", "server_zone", "key", "status_code"}, nil),
|
||||||
|
|
||||||
filterZoneCache: prometheus.NewDesc(
|
filterZoneCache: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(ns, "", "filterzone_cache_total"),
|
prometheus.BuildFQName(ns, "", "filterzone_cache_total"),
|
||||||
"Nginx cache count",
|
"Nginx cache count",
|
||||||
[]string{"ingress_class", "namespace", "server_zone", "country", "type"}, nil),
|
[]string{"ingress_class", "namespace", "server_zone", "key", "type"}, nil),
|
||||||
|
|
||||||
upstreamBackup: prometheus.NewDesc(
|
upstreamBackup: prometheus.NewDesc(
|
||||||
prometheus.BuildFQName(ns, "", "upstream_backup"),
|
prometheus.BuildFQName(ns, "", "upstream_backup"),
|
||||||
|
@ -246,15 +246,15 @@ func (p vtsCollector) scrapeVts(ch chan<- prometheus.Metric) {
|
||||||
prometheus.CounterValue, zone.OutBytes, p.ingressClass, p.watchNamespace, name, "out")
|
prometheus.CounterValue, zone.OutBytes, p.ingressClass, p.watchNamespace, name, "out")
|
||||||
}
|
}
|
||||||
|
|
||||||
for serverZone, countries := range nginxMetrics.FilterZones {
|
for serverZone, keys := range nginxMetrics.FilterZones {
|
||||||
for country, zone := range countries {
|
for name, zone := range keys {
|
||||||
reflectMetrics(&zone.Responses, p.data.filterZoneResponses, ch, p.ingressClass, p.watchNamespace, serverZone, country)
|
reflectMetrics(&zone.Responses, p.data.filterZoneResponses, ch, p.ingressClass, p.watchNamespace, serverZone, name)
|
||||||
reflectMetrics(&zone.Cache, p.data.filterZoneCache, ch, p.ingressClass, p.watchNamespace, serverZone, country)
|
reflectMetrics(&zone.Cache, p.data.filterZoneCache, ch, p.ingressClass, p.watchNamespace, serverZone, name)
|
||||||
|
|
||||||
ch <- prometheus.MustNewConstMetric(p.data.filterZoneBytes,
|
ch <- prometheus.MustNewConstMetric(p.data.filterZoneBytes,
|
||||||
prometheus.CounterValue, zone.InBytes, p.ingressClass, p.watchNamespace, serverZone, country, "in")
|
prometheus.CounterValue, zone.InBytes, p.ingressClass, p.watchNamespace, serverZone, name, "in")
|
||||||
ch <- prometheus.MustNewConstMetric(p.data.filterZoneBytes,
|
ch <- prometheus.MustNewConstMetric(p.data.filterZoneBytes,
|
||||||
prometheus.CounterValue, zone.OutBytes, p.ingressClass, p.watchNamespace, serverZone, country, "out")
|
prometheus.CounterValue, zone.OutBytes, p.ingressClass, p.watchNamespace, serverZone, name, "out")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -46,7 +46,7 @@ http {
|
||||||
|
|
||||||
{{ if $cfg.EnableVtsStatus }}
|
{{ if $cfg.EnableVtsStatus }}
|
||||||
vhost_traffic_status_zone shared:vhost_traffic_status:{{ $cfg.VtsStatusZoneSize }};
|
vhost_traffic_status_zone shared:vhost_traffic_status:{{ $cfg.VtsStatusZoneSize }};
|
||||||
vhost_traffic_status_filter_by_set_key $geoip_country_code country::*;
|
vhost_traffic_status_filter_by_set_key {{ $cfg.VtsDefaultFilterKey }};
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
sendfile on;
|
sendfile on;
|
||||||
|
@ -578,7 +578,6 @@ stream {
|
||||||
more_set_headers "Strict-Transport-Security: max-age={{ $all.Cfg.HSTSMaxAge }}{{ if $all.Cfg.HSTSIncludeSubdomains }}; includeSubDomains{{ end }};{{ if $all.Cfg.HSTSPreload }} preload{{ end }}";
|
more_set_headers "Strict-Transport-Security: max-age={{ $all.Cfg.HSTSMaxAge }}{{ if $all.Cfg.HSTSIncludeSubdomains }}; includeSubDomains{{ end }};{{ if $all.Cfg.HSTSPreload }} preload{{ end }}";
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
{{ if $all.Cfg.EnableVtsStatus }}vhost_traffic_status_filter_by_set_key $geoip_country_code country::$server_name;{{ end }}
|
|
||||||
|
|
||||||
{{ if not (empty $server.CertificateAuth.CAFileName) }}
|
{{ if not (empty $server.CertificateAuth.CAFileName) }}
|
||||||
# PEM sha: {{ $server.CertificateAuth.PemSHA }}
|
# PEM sha: {{ $server.CertificateAuth.PemSHA }}
|
||||||
|
@ -630,6 +629,9 @@ stream {
|
||||||
{{ end }}
|
{{ end }}
|
||||||
|
|
||||||
location {{ $path }} {
|
location {{ $path }} {
|
||||||
|
|
||||||
|
{{ if $all.Cfg.EnableVtsStatus }}{{ if $location.VtsFilterKey }} vhost_traffic_status_filter_by_set_key {{ $location.VtsFilterKey }};{{ end }}{{ end }}
|
||||||
|
|
||||||
set $proxy_upstream_name "{{ buildUpstreamName $server.Hostname $all.Backends $location }}";
|
set $proxy_upstream_name "{{ buildUpstreamName $server.Hostname $all.Backends $location }}";
|
||||||
|
|
||||||
{{ $ing := (getIngressInformation $location.Ingress $path) }}
|
{{ $ing := (getIngressInformation $location.Ingress $path) }}
|
||||||
|
|
|
@ -110,7 +110,9 @@
|
||||||
"keyFilename": "",
|
"keyFilename": "",
|
||||||
"caFilename": "",
|
"caFilename": "",
|
||||||
"pemSha": ""
|
"pemSha": ""
|
||||||
}
|
},
|
||||||
|
"vtsDefaultFilterKey": "$uri $server_name"
|
||||||
|
|
||||||
}, {
|
}, {
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"isDefBackend": true,
|
"isDefBackend": true,
|
||||||
|
|
42
core/pkg/ingress/annotations/vtsfilterkey/main.go
Normal file
42
core/pkg/ingress/annotations/vtsfilterkey/main.go
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
/*
|
||||||
|
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/core/pkg/ingress/annotations/parser"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
annotation = "ingress.kubernetes.io/vts-filter-key"
|
||||||
|
)
|
||||||
|
|
||||||
|
type vtsFilterKey struct {
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewParser creates a new vts filter key annotation parser
|
||||||
|
func NewParser() parser.IngressAnnotation {
|
||||||
|
return vtsFilterKey{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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(annotation, ing)
|
||||||
|
}
|
|
@ -40,6 +40,7 @@ import (
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/snippet"
|
"k8s.io/ingress/core/pkg/ingress/annotations/snippet"
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/sslpassthrough"
|
"k8s.io/ingress/core/pkg/ingress/annotations/sslpassthrough"
|
||||||
"k8s.io/ingress/core/pkg/ingress/annotations/upstreamvhost"
|
"k8s.io/ingress/core/pkg/ingress/annotations/upstreamvhost"
|
||||||
|
"k8s.io/ingress/core/pkg/ingress/annotations/vtsfilterkey"
|
||||||
"k8s.io/ingress/core/pkg/ingress/errors"
|
"k8s.io/ingress/core/pkg/ingress/errors"
|
||||||
"k8s.io/ingress/core/pkg/ingress/resolver"
|
"k8s.io/ingress/core/pkg/ingress/resolver"
|
||||||
)
|
)
|
||||||
|
@ -80,6 +81,7 @@ func newAnnotationExtractor(cfg extractorConfig) annotationExtractor {
|
||||||
"ClientBodyBufferSize": clientbodybuffersize.NewParser(),
|
"ClientBodyBufferSize": clientbodybuffersize.NewParser(),
|
||||||
"DefaultBackend": defaultbackend.NewParser(cfg),
|
"DefaultBackend": defaultbackend.NewParser(cfg),
|
||||||
"UpstreamVhost": upstreamvhost.NewParser(),
|
"UpstreamVhost": upstreamvhost.NewParser(),
|
||||||
|
"VtsFilterKey": vtsfilterkey.NewParser(),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -313,6 +313,10 @@ type Location struct {
|
||||||
// UsePortInRedirects indicates if redirects must specify the port
|
// UsePortInRedirects indicates if redirects must specify the port
|
||||||
// +optional
|
// +optional
|
||||||
UsePortInRedirects bool `json:"usePortInRedirects"`
|
UsePortInRedirects bool `json:"usePortInRedirects"`
|
||||||
|
// VtsFilterKey contains the vts filter key on the location level
|
||||||
|
// https://github.com/vozlt/nginx-module-vts#vhost_traffic_status_filter_by_set_key
|
||||||
|
// +optional
|
||||||
|
VtsFilterKey string `json:"vtsFilterKey,omitempty"`
|
||||||
// ConfigurationSnippet contains additional configuration for the backend
|
// ConfigurationSnippet contains additional configuration for the backend
|
||||||
// to be considered in the configuration of the location
|
// to be considered in the configuration of the location
|
||||||
ConfigurationSnippet string `json:"configurationSnippet"`
|
ConfigurationSnippet string `json:"configurationSnippet"`
|
||||||
|
|
Loading…
Reference in a new issue