Add Generic interface
This commit is contained in:
parent
f2b627486d
commit
5a8e090736
36 changed files with 58014 additions and 675 deletions
|
|
@ -25,14 +25,16 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
|
||||
"k8s.io/ingress/core/pkg/ingress"
|
||||
"k8s.io/ingress/core/pkg/ingress/defaults"
|
||||
|
||||
"errors"
|
||||
|
||||
"k8s.io/ingress/controllers/nginx/pkg/config"
|
||||
ngx_template "k8s.io/ingress/controllers/nginx/pkg/template"
|
||||
"k8s.io/ingress/controllers/nginx/pkg/version"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -75,6 +77,8 @@ Error loading new template : %v
|
|||
}
|
||||
|
||||
n.t = ngxTpl
|
||||
go n.Start()
|
||||
|
||||
return n
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +89,7 @@ type NGINXController struct {
|
|||
binary string
|
||||
}
|
||||
|
||||
// Start ...
|
||||
// Start start a new NGINX master process running in foreground.
|
||||
func (n NGINXController) Start() {
|
||||
glog.Info("starting NGINX process...")
|
||||
cmd := exec.Command(n.binary, "-c", cfgPath)
|
||||
|
|
@ -99,14 +103,13 @@ func (n NGINXController) Start() {
|
|||
}
|
||||
}
|
||||
|
||||
// Stop ...
|
||||
func (n NGINXController) Stop() error {
|
||||
n.t.Close()
|
||||
return exec.Command(n.binary, "-s", "stop").Run()
|
||||
}
|
||||
// Reload checks if the running configuration file is different
|
||||
// to the specified and reload nginx if required
|
||||
func (n NGINXController) Reload(data []byte) ([]byte, error) {
|
||||
if !n.isReloadRequired(data) {
|
||||
return nil, fmt.Errorf("Reload not required")
|
||||
}
|
||||
|
||||
// Restart ...
|
||||
func (n NGINXController) Restart(data []byte) ([]byte, error) {
|
||||
err := ioutil.WriteFile(cfgPath, data, 0644)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
|
@ -120,15 +123,15 @@ func (n NGINXController) Test(file string) *exec.Cmd {
|
|||
return exec.Command(n.binary, "-t", "-c", file)
|
||||
}
|
||||
|
||||
// UpstreamDefaults returns the nginx defaults
|
||||
func (n NGINXController) UpstreamDefaults() defaults.Backend {
|
||||
// BackendDefaults returns the nginx defaults
|
||||
func (n NGINXController) BackendDefaults() defaults.Backend {
|
||||
d := config.NewDefault()
|
||||
return d.Backend
|
||||
}
|
||||
|
||||
// IsReloadRequired check if the new configuration file is different
|
||||
// from the current one.
|
||||
func (n NGINXController) IsReloadRequired(data []byte) bool {
|
||||
func (n NGINXController) isReloadRequired(data []byte) bool {
|
||||
in, err := os.Open(cfgPath)
|
||||
if err != nil {
|
||||
return false
|
||||
|
|
@ -167,8 +170,13 @@ func (n NGINXController) IsReloadRequired(data []byte) bool {
|
|||
}
|
||||
|
||||
// Info return build information
|
||||
func (n NGINXController) Info() string {
|
||||
return fmt.Sprintf("build version %v from repo %v commit %v", version.RELEASE, version.REPO, version.COMMIT)
|
||||
func (n NGINXController) Info() *ingress.BackendInfo {
|
||||
return &ingress.BackendInfo{
|
||||
Name: "NGINX",
|
||||
Release: version.RELEASE,
|
||||
Build: version.COMMIT,
|
||||
Repository: version.REPO,
|
||||
}
|
||||
}
|
||||
|
||||
// testTemplate checks if the NGINX configuration inside the byte array is valid
|
||||
|
|
@ -183,12 +191,13 @@ func (n NGINXController) testTemplate(cfg []byte) error {
|
|||
out, err := n.Test(tmpfile.Name()).CombinedOutput()
|
||||
if err != nil {
|
||||
// this error is different from the rest because it must be clear why nginx is not working
|
||||
return fmt.Errorf(`
|
||||
oe := fmt.Sprintf(`
|
||||
-------------------------------------------------------------------------------
|
||||
Error: %v
|
||||
%v
|
||||
-------------------------------------------------------------------------------
|
||||
`, err, string(out))
|
||||
return errors.New(oe)
|
||||
}
|
||||
|
||||
os.Remove(tmpfile.Name())
|
||||
|
|
@ -207,9 +216,9 @@ func (n NGINXController) OnUpdate(cmap *api.ConfigMap, ingressCfg ingress.Config
|
|||
var longestName int
|
||||
var serverNames int
|
||||
for _, srv := range ingressCfg.Servers {
|
||||
serverNames += len([]byte(srv.Name))
|
||||
if longestName < len(srv.Name) {
|
||||
longestName = len(srv.Name)
|
||||
serverNames += len([]byte(srv.Hostname))
|
||||
if longestName < len(srv.Hostname) {
|
||||
longestName = len(srv.Hostname)
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -234,21 +243,17 @@ func (n NGINXController) OnUpdate(cmap *api.ConfigMap, ingressCfg ingress.Config
|
|||
cfg.ServerNameHashMaxSize = serverNameHashMaxSize
|
||||
}
|
||||
|
||||
conf := make(map[string]interface{})
|
||||
// adjust the size of the backlog
|
||||
conf["backlogSize"] = sysctlSomaxconn()
|
||||
conf["upstreams"] = ingressCfg.Upstreams
|
||||
conf["passthroughUpstreams"] = ingressCfg.PassthroughUpstreams
|
||||
conf["servers"] = ingressCfg.Servers
|
||||
conf["tcpUpstreams"] = ingressCfg.TCPEndpoints
|
||||
conf["udpUpstreams"] = ingressCfg.UPDEndpoints
|
||||
conf["healthzURL"] = ingressCfg.HealthzURL
|
||||
conf["defResolver"] = cfg.Resolver
|
||||
conf["sslDHParam"] = ""
|
||||
conf["customErrors"] = len(cfg.CustomHTTPErrors) > 0
|
||||
conf["cfg"] = ngx_template.StandarizeKeyNames(cfg)
|
||||
|
||||
return n.t.Write(conf, n.testTemplate)
|
||||
return n.t.Write(config.TemplateConfig{
|
||||
BacklogSize: sysctlSomaxconn(),
|
||||
Backends: ingressCfg.Backends,
|
||||
PassthrougBackends: ingressCfg.PassthroughBackends,
|
||||
Servers: ingressCfg.Servers,
|
||||
TCPBackends: ingressCfg.TCPEndpoints,
|
||||
UDPBackends: ingressCfg.UPDEndpoints,
|
||||
HealthzURI: "/healthz",
|
||||
CustomErrors: len(cfg.CustomHTTPErrors) > 0,
|
||||
Cfg: cfg,
|
||||
}, n.testTemplate)
|
||||
}
|
||||
|
||||
// http://graphics.stanford.edu/~seander/bithacks.html#RoundUpPowerOf2
|
||||
|
|
|
|||
|
|
@ -19,9 +19,10 @@ package config
|
|||
import (
|
||||
"runtime"
|
||||
|
||||
"k8s.io/ingress/core/pkg/ingress/defaults"
|
||||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/ingress/core/pkg/ingress"
|
||||
"k8s.io/ingress/core/pkg/ingress/defaults"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -216,8 +217,7 @@ type Configuration struct {
|
|||
WorkerProcesses int `structs:"worker-processes,omitempty"`
|
||||
}
|
||||
|
||||
// NewDefault returns the default configuration contained
|
||||
// in the file default-conf.json
|
||||
// NewDefault returns the default nginx configuration
|
||||
func NewDefault() Configuration {
|
||||
cfg := Configuration{
|
||||
BodySize: bodySize,
|
||||
|
|
@ -264,3 +264,15 @@ func NewDefault() Configuration {
|
|||
|
||||
return cfg
|
||||
}
|
||||
|
||||
type TemplateConfig struct {
|
||||
BacklogSize int
|
||||
Backends []*ingress.Backend
|
||||
PassthrougBackends []*ingress.SSLPassthroughBackend
|
||||
Servers []*ingress.Server
|
||||
TCPBackends []*ingress.Location
|
||||
UDPBackends []*ingress.Location
|
||||
HealthzURI string
|
||||
CustomErrors bool
|
||||
Cfg Configuration
|
||||
}
|
||||
|
|
|
|||
|
|
@ -27,10 +27,10 @@ import (
|
|||
"github.com/mitchellh/mapstructure"
|
||||
go_camelcase "github.com/segmentio/go-camelcase"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
|
||||
"k8s.io/ingress/controllers/nginx/pkg/config"
|
||||
"k8s.io/ingress/core/pkg/ingress/defaults"
|
||||
|
||||
"k8s.io/kubernetes/pkg/api"
|
||||
)
|
||||
|
||||
const (
|
||||
|
|
@ -50,9 +50,9 @@ func ReadConfig(conf *api.ConfigMap) config.Configuration {
|
|||
return config.NewDefault()
|
||||
}
|
||||
|
||||
var errors []int
|
||||
var skipUrls []string
|
||||
var whitelist []string
|
||||
errors := make([]int, 0)
|
||||
skipUrls := make([]string, 0)
|
||||
whitelist := make([]string, 0)
|
||||
|
||||
if val, ok := conf.Data[customHTTPErrors]; ok {
|
||||
delete(conf.Data, customHTTPErrors)
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
|
||||
"github.com/golang/glog"
|
||||
|
||||
"k8s.io/ingress/controllers/nginx/pkg/config"
|
||||
"k8s.io/ingress/core/pkg/ingress"
|
||||
"k8s.io/ingress/core/pkg/watch"
|
||||
)
|
||||
|
|
@ -73,12 +74,19 @@ func (t *Template) Close() {
|
|||
|
||||
// Write populates a buffer using a template with NGINX configuration
|
||||
// and the servers and upstreams created by Ingress rules
|
||||
func (t *Template) Write(conf map[string]interface{},
|
||||
isValidTemplate func([]byte) error) ([]byte, error) {
|
||||
|
||||
func (t *Template) Write(conf config.TemplateConfig, isValidTemplate func([]byte) error) ([]byte, error) {
|
||||
defer t.tmplBuf.Reset()
|
||||
defer t.outCmdBuf.Reset()
|
||||
|
||||
defer func() {
|
||||
if t.s < t.tmplBuf.Cap() {
|
||||
glog.V(2).Infof("adjusting template buffer size from %v to %v", t.s, t.tmplBuf.Cap())
|
||||
t.s = t.tmplBuf.Cap()
|
||||
t.tmplBuf = bytes.NewBuffer(make([]byte, 0, t.tmplBuf.Cap()))
|
||||
t.outCmdBuf = bytes.NewBuffer(make([]byte, 0, t.outCmdBuf.Cap()))
|
||||
}
|
||||
}()
|
||||
|
||||
if glog.V(3) {
|
||||
b, err := json.Marshal(conf)
|
||||
if err != nil {
|
||||
|
|
@ -88,12 +96,8 @@ func (t *Template) Write(conf map[string]interface{},
|
|||
}
|
||||
|
||||
err := t.tmpl.Execute(t.tmplBuf, conf)
|
||||
|
||||
if t.s < t.tmplBuf.Cap() {
|
||||
glog.V(2).Infof("adjusting template buffer size from %v to %v", t.s, t.tmplBuf.Cap())
|
||||
t.s = t.tmplBuf.Cap()
|
||||
t.tmplBuf = bytes.NewBuffer(make([]byte, 0, t.tmplBuf.Cap()))
|
||||
t.outCmdBuf = bytes.NewBuffer(make([]byte, 0, t.outCmdBuf.Cap()))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// squeezes multiple adjacent empty lines to be single
|
||||
|
|
@ -124,12 +128,12 @@ var (
|
|||
}
|
||||
return true
|
||||
},
|
||||
"buildLocation": buildLocation,
|
||||
"buildAuthLocation": buildAuthLocation,
|
||||
"buildProxyPass": buildProxyPass,
|
||||
"buildRateLimitZones": buildRateLimitZones,
|
||||
"buildRateLimit": buildRateLimit,
|
||||
"getSSPassthroughUpstream": getSSPassthroughUpstream,
|
||||
"buildLocation": buildLocation,
|
||||
"buildAuthLocation": buildAuthLocation,
|
||||
"buildProxyPass": buildProxyPass,
|
||||
"buildRateLimitZones": buildRateLimitZones,
|
||||
"buildRateLimit": buildRateLimit,
|
||||
"buildSSPassthroughUpstreams": buildSSPassthroughUpstreams,
|
||||
|
||||
"contains": strings.Contains,
|
||||
"hasPrefix": strings.HasPrefix,
|
||||
|
|
@ -139,13 +143,32 @@ var (
|
|||
}
|
||||
)
|
||||
|
||||
func getSSPassthroughUpstream(input interface{}) string {
|
||||
s, ok := input.(*ingress.Server)
|
||||
if !ok {
|
||||
return ""
|
||||
func buildSSPassthroughUpstreams(b interface{}, sslb interface{}) string {
|
||||
backends := b.([]*ingress.Backend)
|
||||
sslBackends := sslb.([]*ingress.SSLPassthroughBackend)
|
||||
buf := bytes.NewBuffer(make([]byte, 0, 10))
|
||||
|
||||
// multiple services can use the same upstream.
|
||||
// avoid duplications using a map[name]=true
|
||||
u := make(map[string]bool)
|
||||
for _, passthrough := range sslBackends {
|
||||
if u[passthrough.Backend] {
|
||||
continue
|
||||
}
|
||||
u[passthrough.Backend] = true
|
||||
fmt.Fprintf(buf, "upstream %v {\n", passthrough.Backend)
|
||||
for _, backend := range backends {
|
||||
if backend.Name == passthrough.Backend {
|
||||
for _, server := range backend.Endpoints {
|
||||
fmt.Fprintf(buf, "\t\tserver %v:%v;\n", server.Address, server.Port)
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
fmt.Fprint(buf, "\t}\n\n")
|
||||
}
|
||||
|
||||
return s.Name
|
||||
return buf.String()
|
||||
}
|
||||
|
||||
// buildLocation produces the location string, if the ingress has redirects
|
||||
|
|
@ -184,20 +207,27 @@ func buildAuthLocation(input interface{}) string {
|
|||
// (specified through the ingress.kubernetes.io/rewrite-to annotation)
|
||||
// If the annotation ingress.kubernetes.io/add-base-url:"true" is specified it will
|
||||
// add a base tag in the head of the response from the service
|
||||
func buildProxyPass(input interface{}) string {
|
||||
location, ok := input.(*ingress.Location)
|
||||
func buildProxyPass(b interface{}, loc interface{}) string {
|
||||
backends := b.([]*ingress.Backend)
|
||||
location, ok := loc.(*ingress.Location)
|
||||
if !ok {
|
||||
return ""
|
||||
}
|
||||
|
||||
path := location.Path
|
||||
|
||||
proto := "http"
|
||||
if location.SecureUpstream {
|
||||
proto = "https"
|
||||
|
||||
for _, backend := range backends {
|
||||
if backend.Name == location.Backend {
|
||||
if backend.Secure {
|
||||
proto = "https"
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
// defProxyPass returns the default proxy_pass, just the name of the upstream
|
||||
defProxyPass := fmt.Sprintf("proxy_pass %s://%s;", proto, location.Backend.Name)
|
||||
defProxyPass := fmt.Sprintf("proxy_pass %s://%s;", proto, location.Backend)
|
||||
// if the path in the ingress rule is equals to the target: no special rewrite
|
||||
if path == location.Redirect.Target {
|
||||
return defProxyPass
|
||||
|
|
@ -227,13 +257,13 @@ func buildProxyPass(input interface{}) string {
|
|||
rewrite %s(.*) /$1 break;
|
||||
rewrite %s / break;
|
||||
proxy_pass %s://%s;
|
||||
%v`, path, location.Path, proto, location.Backend.Name, abu)
|
||||
%v`, path, location.Path, proto, location.Backend, abu)
|
||||
}
|
||||
|
||||
return fmt.Sprintf(`
|
||||
rewrite %s(.*) %s/$1 break;
|
||||
proxy_pass %s://%s;
|
||||
%v`, path, location.Redirect.Target, proto, location.Backend.Name, abu)
|
||||
%v`, path, location.Redirect.Target, proto, location.Backend, abu)
|
||||
}
|
||||
|
||||
// default proxy_pass
|
||||
|
|
|
|||
|
|
@ -17,14 +17,21 @@ limitations under the License.
|
|||
package template
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"testing"
|
||||
|
||||
"io/ioutil"
|
||||
|
||||
"k8s.io/ingress/controllers/nginx/pkg/config"
|
||||
"k8s.io/ingress/core/pkg/ingress"
|
||||
"k8s.io/ingress/core/pkg/ingress/annotations/rewrite"
|
||||
)
|
||||
|
||||
var (
|
||||
// TODO: add tests for secure endpoints
|
||||
tmplFuncTestcases = map[string]struct {
|
||||
Path string
|
||||
Target string
|
||||
|
|
@ -88,12 +95,77 @@ func TestBuildProxyPass(t *testing.T) {
|
|||
loc := &ingress.Location{
|
||||
Path: tc.Path,
|
||||
Redirect: rewrite.Redirect{Target: tc.Target, AddBaseURL: tc.AddBaseURL},
|
||||
Upstream: ingress.Backend{Name: "upstream-name"},
|
||||
Backend: "upstream-name",
|
||||
}
|
||||
|
||||
pp := buildProxyPass(loc)
|
||||
pp := buildProxyPass([]*ingress.Backend{}, loc)
|
||||
if !strings.EqualFold(tc.ProxyPass, pp) {
|
||||
t.Errorf("%s: expected \n'%v'\nbut returned \n'%v'", k, tc.ProxyPass, pp)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestTemplateWithData(t *testing.T) {
|
||||
pwd, _ := os.Getwd()
|
||||
f, err := os.Open(path.Join(pwd, "../../test/data/config.json"))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error reading json file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
data, err := ioutil.ReadFile(f.Name())
|
||||
if err != nil {
|
||||
t.Error("unexpected error reading json file: ", err)
|
||||
}
|
||||
var dat config.TemplateConfig
|
||||
if err := json.Unmarshal(data, &dat); err != nil {
|
||||
t.Errorf("unexpected error unmarshalling json: %v", err)
|
||||
}
|
||||
|
||||
tf, err := os.Open(path.Join(pwd, "../../rootfs/etc/nginx/template/nginx.tmpl"))
|
||||
if err != nil {
|
||||
t.Errorf("unexpected error reading json file: %v", err)
|
||||
}
|
||||
defer tf.Close()
|
||||
|
||||
ngxTpl, err := NewTemplate(tf.Name(), func() {})
|
||||
if err != nil {
|
||||
t.Errorf("invalid NGINX template: %v", err)
|
||||
}
|
||||
|
||||
_, err = ngxTpl.Write(dat, func(b []byte) error { return nil })
|
||||
if err != nil {
|
||||
t.Errorf("invalid NGINX template: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
func BenchmarkTemplateWithData(b *testing.B) {
|
||||
pwd, _ := os.Getwd()
|
||||
f, err := os.Open(path.Join(pwd, "../../test/data/config.json"))
|
||||
if err != nil {
|
||||
b.Errorf("unexpected error reading json file: %v", err)
|
||||
}
|
||||
defer f.Close()
|
||||
data, err := ioutil.ReadFile(f.Name())
|
||||
if err != nil {
|
||||
b.Error("unexpected error reading json file: ", err)
|
||||
}
|
||||
var dat config.TemplateConfig
|
||||
if err := json.Unmarshal(data, &dat); err != nil {
|
||||
b.Errorf("unexpected error unmarshalling json: %v", err)
|
||||
}
|
||||
|
||||
tf, err := os.Open(path.Join(pwd, "../../rootfs/etc/nginx/template/nginx.tmpl"))
|
||||
if err != nil {
|
||||
b.Errorf("unexpected error reading json file: %v", err)
|
||||
}
|
||||
defer tf.Close()
|
||||
|
||||
ngxTpl, err := NewTemplate(tf.Name(), func() {})
|
||||
if err != nil {
|
||||
b.Errorf("invalid NGINX template: %v", err)
|
||||
}
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
ngxTpl.Write(dat, func(b []byte) error { return nil })
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@
|
|||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
FROM gcr.io/google_containers/nginx-slim:0.10
|
||||
FROM gcr.io/google_containers/nginx-slim:0.11
|
||||
|
||||
RUN DEBIAN_FRONTEND=noninteractive apt-get update && apt-get install -y \
|
||||
diffutils \
|
||||
|
|
|
|||
|
|
@ -1,20 +1,20 @@
|
|||
{{ $cfg := .cfg }}{{ $healthzURL := .healthzURL }}
|
||||
{{ $cfg := .Cfg }}{{ $healthzURI := .HealthzURI }}{{ $backends := .Backends }}
|
||||
daemon off;
|
||||
|
||||
worker_processes {{ $cfg.workerProcesses }};
|
||||
worker_processes {{ $cfg.WorkerProcesses }};
|
||||
pid /run/nginx.pid;
|
||||
worker_rlimit_nofile 131072;
|
||||
|
||||
events {
|
||||
multi_accept on;
|
||||
worker_connections {{ $cfg.maxWorkerConnections }};
|
||||
worker_connections {{ $cfg.MaxWorkerConnections }};
|
||||
use epoll;
|
||||
}
|
||||
|
||||
http {
|
||||
{{/* we use the value of the header X-Forwarded-For to be able to use the geo_ip module */}}
|
||||
{{ if $cfg.useProxyProtocol }}
|
||||
set_real_ip_from {{ $cfg.proxyRealIpCidr }};
|
||||
{{ if $cfg.UseProxyProtocol }}
|
||||
set_real_ip_from {{ $cfg.ProxyRealIpCidr }};
|
||||
real_ip_header proxy_protocol;
|
||||
{{ else }}
|
||||
real_ip_header X-Forwarded-For;
|
||||
|
|
@ -30,8 +30,8 @@ http {
|
|||
geoip_city /etc/nginx/GeoLiteCity.dat;
|
||||
geoip_proxy_recursive on;
|
||||
|
||||
{{ if $cfg.enableVtsStatus }}
|
||||
vhost_traffic_status_zone shared:vhost_traffic_status:{{ $cfg.vtsStatusZoneSize }};
|
||||
{{ if $cfg.EnableVtsStatus }}
|
||||
vhost_traffic_status_zone shared:vhost_traffic_status:{{ $cfg.VtsStatusZoneSize }};
|
||||
vhost_traffic_status_filter_by_set_key $geoip_country_code country::*;
|
||||
{{ end }}
|
||||
|
||||
|
|
@ -50,43 +50,43 @@ http {
|
|||
|
||||
reset_timedout_connection on;
|
||||
|
||||
keepalive_timeout {{ $cfg.keepAlive }}s;
|
||||
keepalive_timeout {{ $cfg.KeepAlive }}s;
|
||||
|
||||
types_hash_max_size 2048;
|
||||
server_names_hash_max_size {{ $cfg.serverNameHashMaxSize }};
|
||||
server_names_hash_bucket_size {{ $cfg.serverNameHashBucketSize }};
|
||||
map_hash_bucket_size {{ $cfg.mapHashBucketSize }};
|
||||
server_names_hash_max_size {{ $cfg.ServerNameHashMaxSize }};
|
||||
server_names_hash_bucket_size {{ $cfg.ServerNameHashBucketSize }};
|
||||
map_hash_bucket_size {{ $cfg.MapHashBucketSize }};
|
||||
|
||||
include /etc/nginx/mime.types;
|
||||
default_type text/html;
|
||||
{{ if $cfg.useGzip }}
|
||||
{{ if $cfg.UseGzip }}
|
||||
gzip on;
|
||||
gzip_comp_level 5;
|
||||
gzip_http_version 1.1;
|
||||
gzip_min_length 256;
|
||||
gzip_types {{ $cfg.gzipTypes }};
|
||||
gzip_types {{ $cfg.GzipTypes }};
|
||||
gzip_proxied any;
|
||||
{{ end }}
|
||||
|
||||
client_max_body_size "{{ $cfg.bodySize }}";
|
||||
client_max_body_size "{{ $cfg.BodySize }}";
|
||||
|
||||
log_format upstreaminfo '{{ if $cfg.useProxyProtocol }}$proxy_protocol_addr{{ else }}$remote_addr{{ end }} - '
|
||||
log_format upstreaminfo '{{ if $cfg.UseProxyProtocol }}$proxy_protocol_addr{{ else }}$remote_addr{{ end }} - '
|
||||
'[$proxy_add_x_forwarded_for] - $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';
|
||||
|
||||
{{/* map urls that should not appear in access.log */}}
|
||||
{{/* http://nginx.org/en/docs/http/ngx_http_log_module.html#access_log */}}
|
||||
map $request $loggable {
|
||||
{{ range $reqUri := $cfg.skipAccessLogUrls }}
|
||||
{{ range $reqUri := $cfg.SkipAccessLogURLs }}
|
||||
{{ $reqUri }} 0;{{ end }}
|
||||
default 1;
|
||||
}
|
||||
|
||||
access_log /var/log/nginx/access.log upstreaminfo if=$loggable;
|
||||
error_log /var/log/nginx/error.log {{ $cfg.errorLogLevel }};
|
||||
error_log /var/log/nginx/error.log {{ $cfg.ErrorLogLevel }};
|
||||
|
||||
{{ if not (empty .defResolver) }}# Custom dns resolver.
|
||||
resolver {{ .defResolver }} valid=30s;
|
||||
{{ if not (empty $cfg.Resolver) }}# Custom dns resolver.
|
||||
resolver {{ $cfg.Resolver }} valid=30s;
|
||||
resolver_timeout 10s;
|
||||
{{ end }}
|
||||
|
||||
|
|
@ -98,14 +98,14 @@ http {
|
|||
{{/* normal nginx behavior we have to use this approach. */}}
|
||||
# Retain the default nginx handling of requests without a "Connection" header
|
||||
map $http_upgrade $connection_upgrade {
|
||||
default upgrade;
|
||||
'' close;
|
||||
default upgrade;
|
||||
'' close;
|
||||
}
|
||||
|
||||
# trust http_x_forwarded_proto headers correctly indicate ssl offloading
|
||||
map $http_x_forwarded_proto $pass_access_scheme {
|
||||
default $http_x_forwarded_proto;
|
||||
'' $scheme;
|
||||
default $http_x_forwarded_proto;
|
||||
'' $scheme;
|
||||
}
|
||||
|
||||
# Map a response error watching the header Content-Type
|
||||
|
|
@ -124,51 +124,51 @@ http {
|
|||
}
|
||||
|
||||
server_name_in_redirect off;
|
||||
port_in_redirect off;
|
||||
port_in_redirect off;
|
||||
|
||||
ssl_protocols {{ $cfg.sslProtocols }};
|
||||
ssl_protocols {{ $cfg.SSLProtocols }};
|
||||
|
||||
# turn on session caching to drastically improve performance
|
||||
{{ if $cfg.sslSessionCache }}
|
||||
ssl_session_cache builtin:1000 shared:SSL:{{ $cfg.sslSessionCacheSize }};
|
||||
ssl_session_timeout {{ $cfg.sslSessionTimeout }};
|
||||
{{ if $cfg.SSLSessionCache }}
|
||||
ssl_session_cache builtin:1000 shared:SSL:{{ $cfg.SSLSessionCacheSize }};
|
||||
ssl_session_timeout {{ $cfg.SSLSessionTimeout }};
|
||||
{{ end }}
|
||||
|
||||
# allow configuring ssl session tickets
|
||||
ssl_session_tickets {{ if $cfg.sslSessionTickets }}on{{ else }}off{{ end }};
|
||||
ssl_session_tickets {{ if $cfg.SSLSessionTickets }}on{{ else }}off{{ end }};
|
||||
|
||||
# slightly reduce the time-to-first-byte
|
||||
ssl_buffer_size {{ $cfg.sslBufferSize }};
|
||||
ssl_buffer_size {{ $cfg.SSLBufferSize }};
|
||||
|
||||
{{ if not (empty $cfg.sslCiphers) }}
|
||||
{{ if not (empty $cfg.SSLCiphers) }}
|
||||
# allow configuring custom ssl ciphers
|
||||
ssl_ciphers '{{ $cfg.sslCiphers }}';
|
||||
ssl_ciphers '{{ $cfg.SSLCiphers }}';
|
||||
ssl_prefer_server_ciphers on;
|
||||
{{ end }}
|
||||
|
||||
{{ if not (empty .sslDHParam) }}
|
||||
{{ if not (empty $cfg.SSLDHParam) }}
|
||||
# allow custom DH file http://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_dhparam
|
||||
ssl_dhparam {{ .sslDHParam }};
|
||||
ssl_dhparam {{ $cfg.SSLDHParam }};
|
||||
{{ end }}
|
||||
|
||||
{{ if not $cfg.enableDynamicTlsRecords }}
|
||||
{{ if not $cfg.EnableDynamicTLSRecords }}
|
||||
ssl_dyn_rec_size_lo 0;
|
||||
{{ end }}
|
||||
|
||||
{{ if .customErrors }}
|
||||
{{ if .CustomErrors }}
|
||||
# Custom error pages
|
||||
proxy_intercept_errors on;
|
||||
{{ end }}
|
||||
|
||||
{{ range $errCode := $cfg.customHttpErrors }}
|
||||
{{ range $errCode := $cfg.CustomHTTPErrors }}
|
||||
error_page {{ $errCode }} = @custom_{{ $errCode }};{{ end }}
|
||||
|
||||
# In case of errors try the next upstream server before returning an error
|
||||
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504{{ if $cfg.retryNonIdempotent }} non_idempotent{{ end }};
|
||||
proxy_next_upstream error timeout invalid_header http_502 http_503 http_504{{ if $cfg.RetryNonIdempotent }} non_idempotent{{ end }};
|
||||
|
||||
{{range $name, $upstream := .upstreams}}
|
||||
{{range $name, $upstream := $backends}}
|
||||
upstream {{$upstream.Name}} {
|
||||
{{ if $cfg.enableStickySessions }}
|
||||
{{ if $cfg.EnableStickySessions }}
|
||||
sticky hash=sha1 httponly;
|
||||
{{ else }}
|
||||
least_conn;
|
||||
|
|
@ -180,26 +180,26 @@ http {
|
|||
|
||||
{{/* build all the required rate limit zones. Each annotation requires a dedicated zone */}}
|
||||
{{/* 1MB -> 16 thousand 64-byte states or about 8 thousand 128-byte states */}}
|
||||
{{ range $zone := (buildRateLimitZones .servers) }}
|
||||
{{ range $zone := (buildRateLimitZones .Servers) }}
|
||||
{{ $zone }}
|
||||
{{ end }}
|
||||
|
||||
{{ range $server := .servers }}
|
||||
{{ range $server := .Servers }}
|
||||
server {
|
||||
server_name {{ $server.Name }};
|
||||
listen 80{{ if $cfg.useProxyProtocol }} proxy_protocol{{ end }};
|
||||
{{ if $server.SSL }}listen 442 {{ if $cfg.useProxyProtocol }}proxy_protocol{{ end }} ssl {{ if $cfg.useHttp2 }}http2{{ end }};
|
||||
server_name {{ $server.Hostname }};
|
||||
listen 80{{ if $cfg.UseProxyProtocol }} proxy_protocol{{ end }};
|
||||
{{ if not (empty $server.SSLCertificate) }}listen 442 {{ if $cfg.UseProxyProtocol }}proxy_protocol{{ end }} ssl {{ if $cfg.UseHttp2 }}http2{{ end }};
|
||||
{{/* comment PEM sha is required to detect changes in the generated configuration and force a reload */}}
|
||||
# PEM sha: {{ $server.SSLPemChecksum }}
|
||||
ssl_certificate {{ $server.SSLCertificate }};
|
||||
ssl_certificate_key {{ $server.SSLCertificate }};
|
||||
{{ end }}
|
||||
|
||||
{{ if (and $server.SSL $cfg.hsts) }}
|
||||
more_set_headers "Strict-Transport-Security: max-age={{ $cfg.hstsMaxAge }}{{ if $cfg.hstsIncludeSubdomains }}; includeSubDomains{{ end }}; preload";
|
||||
{{ if (and (not (empty $server.SSLCertificate)) $cfg.HSTS) }}
|
||||
more_set_headers "Strict-Transport-Security: max-age={{ $cfg.HSTSMaxAge }}{{ if $cfg.HSTSIncludeSubdomains }}; includeSubDomains{{ end }}; preload";
|
||||
{{ end }}
|
||||
|
||||
{{ if $cfg.enableVtsStatus }}vhost_traffic_status_filter_by_set_key $geoip_country_code country::$server_name;{{ end }}
|
||||
{{ if $cfg.EnableVtsStatus }}vhost_traffic_status_filter_by_set_key $geoip_country_code country::$server_name;{{ end }}
|
||||
|
||||
{{ range $location := $server.Locations }}
|
||||
{{ $path := buildLocation $location }}
|
||||
|
|
@ -240,7 +240,7 @@ http {
|
|||
auth_request {{ $authPath }};
|
||||
{{ end }}
|
||||
|
||||
{{ if (and $server.SSL $location.Redirect.SSLRedirect) }}
|
||||
{{ if (and (not (empty $server.SSLCertificate)) $location.Redirect.SSLRedirect) }}
|
||||
# enforce ssl on server side
|
||||
if ($scheme = http) {
|
||||
return 301 https://$host$request_uri;
|
||||
|
|
@ -256,7 +256,6 @@ http {
|
|||
auth_basic "{{ $location.BasicDigestAuth.Realm }}";
|
||||
auth_basic_user_file {{ $location.BasicDigestAuth.File }};
|
||||
{{ else }}
|
||||
#TODO: add nginx-http-auth-digest module
|
||||
auth_digest "{{ $location.BasicDigestAuth.Realm }}";
|
||||
auth_digest_user_file {{ $location.BasicDigestAuth.File }};
|
||||
{{ end }}
|
||||
|
|
@ -300,14 +299,14 @@ http {
|
|||
proxy_set_header Accept-Encoding "";
|
||||
{{ end }}
|
||||
|
||||
set $proxy_upstream_name "{{ $location.Backend.Name }}";
|
||||
{{ buildProxyPass $location }}
|
||||
set $proxy_upstream_name "{{ $location.Backend }}";
|
||||
{{ buildProxyPass $backends $location }}
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ if eq $server.Name "_" }}
|
||||
{{ if eq $server.Hostname "_" }}
|
||||
# health checks in cloud providers require the use of port 80
|
||||
location {{ $healthzURL }} {
|
||||
location {{ $healthzURI }} {
|
||||
access_log off;
|
||||
return 200;
|
||||
}
|
||||
|
|
@ -322,6 +321,7 @@ http {
|
|||
stub_status on;
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
{{ template "CUSTOM_ERRORS" $cfg }}
|
||||
}
|
||||
|
||||
|
|
@ -332,15 +332,15 @@ http {
|
|||
# Use the port 18080 (random value just to avoid known ports) as default port for nginx.
|
||||
# Changing this value requires a change in:
|
||||
# https://github.com/kubernetes/contrib/blob/master/ingress/controllers/nginx/nginx/command.go#L104
|
||||
listen 18080 default_server reuseport backlog={{ .backlogSize }};
|
||||
listen 18080 default_server reuseport backlog={{ .BacklogSize }};
|
||||
|
||||
location {{ $healthzURL }} {
|
||||
location {{ $healthzURI }} {
|
||||
access_log off;
|
||||
return 200;
|
||||
}
|
||||
|
||||
location /nginx_status {
|
||||
{{ if $cfg.enableVtsStatus }}
|
||||
{{ if $cfg.EnableVtsStatus }}
|
||||
vhost_traffic_status_display;
|
||||
vhost_traffic_status_display_format html;
|
||||
{{ else }}
|
||||
|
|
@ -362,7 +362,7 @@ http {
|
|||
set $proxy_upstream_name "-";
|
||||
|
||||
location / {
|
||||
{{ if .customErrors }}
|
||||
{{ if .CustomErrors }}
|
||||
content_by_lua_block {
|
||||
openURL(503)
|
||||
}
|
||||
|
|
@ -376,15 +376,14 @@ http {
|
|||
stream {
|
||||
# map FQDN that requires SSL passthrough
|
||||
map $ssl_preread_server_name $stream_upstream {
|
||||
{{ range $i, $passthrough := .passthroughUpstreams }}
|
||||
{{ $passthrough.Host }} {{ $passthrough.Upstream.Name }}-{{ $i }}-pt;
|
||||
{{ range $i, $passthrough := .PassthrougBackends }}
|
||||
{{ $passthrough.Hostname }} {{ $passthrough.Backend }};
|
||||
{{ end }}
|
||||
# send SSL traffic to this nginx in a different port
|
||||
default nginx-ssl-backend;
|
||||
}
|
||||
|
||||
log_format log_stream '$remote_addr [$time_local] $protocol [$ssl_preread_server_name] [$stream_upstream] '
|
||||
'$status $bytes_sent $bytes_received $session_time';
|
||||
log_format log_stream '$remote_addr [$time_local] $protocol [$ssl_preread_server_name] [$stream_upstream] $status $bytes_sent $bytes_received $session_time';
|
||||
|
||||
access_log /var/log/nginx/access.log log_stream;
|
||||
error_log /var/log/nginx/error.log;
|
||||
|
|
@ -394,56 +393,20 @@ stream {
|
|||
server 127.0.0.1:442;
|
||||
}
|
||||
|
||||
{{ range $i, $passthrough := .passthroughUpstreams }}
|
||||
upstream {{ $passthrough.Name }}-{{ $i }}-pt {
|
||||
{{ range $server := $passthrough.Endpoints }}server {{ $server.Address }}:{{ $server.Port }};
|
||||
{{ end }}
|
||||
}
|
||||
{{ end }}
|
||||
{{ buildSSPassthroughUpstreams $backends .PassthrougBackends }}
|
||||
|
||||
server {
|
||||
listen 443;
|
||||
|
||||
{{ if $cfg.useProxyProtocol }}proxy_protocol on;{{ end }}
|
||||
|
||||
{{ if $cfg.UseProxyProtocol }}proxy_protocol on;{{ end }}
|
||||
proxy_pass $stream_upstream;
|
||||
ssl_preread on;
|
||||
}
|
||||
|
||||
# TCP services
|
||||
{{ range $i, $tcpServer := .tcpUpstreams }}
|
||||
upstream tcp-{{ $tcpServer.Upstream.Name }} {
|
||||
{{ range $server := $tcpServer.Upstream.Endpoints }}server {{ $server.Address }}:{{ $server.Port }};
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
server {
|
||||
listen {{ $tcpServer.Path }};
|
||||
proxy_connect_timeout {{ $tcpServer.Proxy.ConnectTimeout }}s;
|
||||
proxy_timeout {{ $tcpServer.Proxy.ReadTimeout }}s;
|
||||
proxy_pass tcp-{{ $tcpServer.Upstream.Name }};
|
||||
}
|
||||
{{ end }}
|
||||
|
||||
# UDP services
|
||||
{{ range $i, $udpServer := .udpUpstreams }}
|
||||
upstream udp-{{ $udpServer.Upstream.Name }} {
|
||||
{{ range $server := $udpServer.Upstream.Endpoints }}server {{ $server.Address }}:{{ $server.Port }};
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
server {
|
||||
listen {{ $udpServer.Path }} udp;
|
||||
proxy_timeout 10s;
|
||||
proxy_responses 1;
|
||||
proxy_pass udp-{{ $udpServer.Upstream.Name }};
|
||||
}
|
||||
{{ end }}
|
||||
}
|
||||
|
||||
{{/* definition of templates to avoid repetitions */}}
|
||||
{{ define "CUSTOM_ERRORS" }}
|
||||
{{ range $errCode := .customHttpErrors }}
|
||||
{{ range $errCode := .CustomHTTPErrors }}
|
||||
location @custom_{{ $errCode }} {
|
||||
internal;
|
||||
content_by_lua_block {
|
||||
|
|
|
|||
57259
controllers/nginx/test/data/config.json
Normal file
57259
controllers/nginx/test/data/config.json
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue