2017-11-05 21:35:46 +00:00
|
|
|
/*
|
|
|
|
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.
|
|
|
|
*/
|
|
|
|
|
2017-11-05 01:18:28 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"flag"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
2018-04-05 20:37:21 +00:00
|
|
|
"runtime"
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
"github.com/golang/glog"
|
|
|
|
"github.com/spf13/pflag"
|
|
|
|
|
|
|
|
apiv1 "k8s.io/api/core/v1"
|
|
|
|
|
2017-11-22 13:35:47 +00:00
|
|
|
"k8s.io/ingress-nginx/internal/ingress/annotations/class"
|
2017-11-23 16:46:23 +00:00
|
|
|
"k8s.io/ingress-nginx/internal/ingress/annotations/parser"
|
2017-11-07 22:02:12 +00:00
|
|
|
"k8s.io/ingress-nginx/internal/ingress/controller"
|
|
|
|
ngx_config "k8s.io/ingress-nginx/internal/ingress/controller/config"
|
|
|
|
ing_net "k8s.io/ingress-nginx/internal/net"
|
2017-11-05 01:18:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
func parseFlags() (bool, *controller.Configuration, error) {
|
|
|
|
var (
|
|
|
|
flags = pflag.NewFlagSet("", pflag.ExitOnError)
|
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
defaultSvc = flags.String("default-backend-service", "",
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
ingressClass = flags.String("ingress-class", "",
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
configMap = flags.String("configmap", "",
|
2018-06-11 09:17:50 +00:00
|
|
|
`Name of the ConfigMap containing custom global configurations for the controller.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
publishSvc = flags.String("publish-service", "",
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
tcpConfigMapName = flags.String("tcp-services-configmap", "",
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
udpConfigMapName = flags.String("udp-services-configmap", "",
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-13 12:47:09 +00:00
|
|
|
resyncPeriod = flags.Duration("sync-period", 0,
|
|
|
|
`Period at which the controller forces the repopulation of its local object stores. Disabled by default.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
watchNamespace = flags.String("watch-namespace", apiv1.NamespaceAll,
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
profiling = flags.Bool("profiling", true,
|
|
|
|
`Enable profiling via web interface host:port/debug/pprof/`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
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".`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
electionID = flags.String("election-id", "ingress-controller-leader",
|
|
|
|
`Election id to use for Ingress status updates.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
forceIsolation = flags.Bool("force-namespace-isolation", false,
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
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.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
sortBackends = flags.Bool("sort-backends", false,
|
|
|
|
`Sort servers inside NGINX upstreams.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
useNodeInternalIP = flags.Bool("report-node-internal-ip-address", false,
|
2018-06-11 09:17:50 +00:00
|
|
|
`Set the load-balancer status of Ingress objects to internal Node addresses instead of external.
|
|
|
|
Requires the update-status parameter.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
|
|
|
showVersion = flags.Bool("version", false,
|
2018-06-11 09:17:50 +00:00
|
|
|
`Show release information about the NGINX Ingress controller and exit.`)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
enableSSLPassthrough = flags.Bool("enable-ssl-passthrough", false,
|
|
|
|
`Enable SSL Passthrough.`)
|
2017-11-08 20:58:57 +00:00
|
|
|
|
2018-06-11 09:17:50 +00:00
|
|
|
annotationsPrefix = flags.String("annotations-prefix", "nginx.ingress.kubernetes.io",
|
|
|
|
`Prefix of the Ingress annotations specific to the NGINX controller.`)
|
2017-11-13 01:43:28 +00:00
|
|
|
|
|
|
|
enableSSLChainCompletion = flags.Bool("enable-ssl-chain-completion", true,
|
2018-06-11 09:17:50 +00:00
|
|
|
`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.`)
|
2017-12-05 19:07:34 +00:00
|
|
|
|
|
|
|
syncRateLimit = flags.Float32("sync-rate-limit", 0.3,
|
|
|
|
`Define the sync frequency upper limit`)
|
2018-02-27 03:02:19 +00:00
|
|
|
|
|
|
|
publishStatusAddress = flags.String("publish-status-address", "",
|
2018-06-11 09:17:50 +00:00
|
|
|
`Customized address to set as the load-balancer status of Ingress objects this controller satisfies.
|
|
|
|
Requires the update-status parameter.`)
|
2018-03-18 13:13:41 +00:00
|
|
|
|
|
|
|
dynamicConfigurationEnabled = flags.Bool("enable-dynamic-configuration", false,
|
2018-06-11 09:17:50 +00:00
|
|
|
`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-passtrough-proxy-port", 442, `Port to use internally for SSL Passthgough.`)
|
|
|
|
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.")
|
2017-11-05 01:18:28 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
flag.Set("logtostderr", "true")
|
|
|
|
|
|
|
|
flags.AddGoFlagSet(flag.CommandLine)
|
|
|
|
flags.Parse(os.Args)
|
|
|
|
|
|
|
|
// Workaround for this issue:
|
|
|
|
// https://github.com/kubernetes/kubernetes/issues/17162
|
|
|
|
flag.CommandLine.Parse([]string{})
|
|
|
|
|
2017-12-27 03:13:16 +00:00
|
|
|
pflag.VisitAll(func(flag *pflag.Flag) {
|
|
|
|
glog.V(2).Infof("FLAG: --%s=%q", flag.Name, flag.Value)
|
|
|
|
})
|
|
|
|
|
2017-11-05 01:18:28 +00:00
|
|
|
if *showVersion {
|
|
|
|
return true, nil, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
if *defaultSvc == "" {
|
|
|
|
return false, nil, fmt.Errorf("Please specify --default-backend-service")
|
|
|
|
}
|
|
|
|
|
|
|
|
if *ingressClass != "" {
|
2018-06-11 09:17:50 +00:00
|
|
|
glog.Infof("Watching for Ingress class: %s", *ingressClass)
|
2017-11-05 01:18:28 +00:00
|
|
|
|
2017-11-22 13:35:47 +00:00
|
|
|
if *ingressClass != class.DefaultClass {
|
2018-06-11 09:17:50 +00:00
|
|
|
glog.Warningf("Only Ingresses with class %q will be processed by this ingress controller", *ingressClass)
|
2017-11-05 01:18:28 +00:00
|
|
|
}
|
2017-11-22 13:35:47 +00:00
|
|
|
|
|
|
|
class.IngressClass = *ingressClass
|
2017-11-05 01:18:28 +00:00
|
|
|
}
|
|
|
|
|
2017-11-23 16:46:23 +00:00
|
|
|
parser.AnnotationsPrefix = *annotationsPrefix
|
|
|
|
|
2017-11-05 01:18:28 +00:00
|
|
|
// check port collisions
|
|
|
|
if !ing_net.IsPortAvailable(*httpPort) {
|
|
|
|
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --http-port", *httpPort)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !ing_net.IsPortAvailable(*httpsPort) {
|
|
|
|
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --https-port", *httpsPort)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !ing_net.IsPortAvailable(*statusPort) {
|
|
|
|
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --status-port", *statusPort)
|
|
|
|
}
|
|
|
|
|
|
|
|
if !ing_net.IsPortAvailable(*defServerPort) {
|
|
|
|
return false, nil, fmt.Errorf("Port %v is already in use. Please check the flag --default-server-port", *defServerPort)
|
|
|
|
}
|
|
|
|
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
|
2017-11-13 01:43:28 +00:00
|
|
|
if !*enableSSLChainCompletion {
|
2018-06-11 09:17:50 +00:00
|
|
|
glog.Warningf("SSL certificate chain completion is disabled (--enable-ssl-chain-completion=false)")
|
2017-11-13 01:43:28 +00:00
|
|
|
}
|
|
|
|
|
2018-04-11 14:52:42 +00:00
|
|
|
// LuaJIT is not available on arch s390x and ppc64le
|
|
|
|
disableLua := false
|
|
|
|
if runtime.GOARCH == "s390x" || runtime.GOARCH == "ppc64le" {
|
|
|
|
disableLua = true
|
|
|
|
if *dynamicConfigurationEnabled {
|
|
|
|
*dynamicConfigurationEnabled = false
|
2018-06-11 09:17:50 +00:00
|
|
|
glog.Warningf("LuaJIT is not available on s390x and ppc64le architectures: disabling dynamic configuration feature.")
|
2018-04-11 14:52:42 +00:00
|
|
|
}
|
2018-04-05 20:37:21 +00:00
|
|
|
}
|
|
|
|
|
2017-11-05 01:18:28 +00:00
|
|
|
config := &controller.Configuration{
|
2018-03-18 13:13:41 +00:00
|
|
|
APIServerHost: *apiserverHost,
|
|
|
|
KubeConfigFile: *kubeConfigFile,
|
|
|
|
UpdateStatus: *updateStatus,
|
|
|
|
ElectionID: *electionID,
|
|
|
|
EnableProfiling: *profiling,
|
|
|
|
EnableSSLPassthrough: *enableSSLPassthrough,
|
|
|
|
EnableSSLChainCompletion: *enableSSLChainCompletion,
|
|
|
|
ResyncPeriod: *resyncPeriod,
|
|
|
|
DefaultService: *defaultSvc,
|
|
|
|
Namespace: *watchNamespace,
|
|
|
|
ConfigMapName: *configMap,
|
|
|
|
TCPConfigMapName: *tcpConfigMapName,
|
|
|
|
UDPConfigMapName: *udpConfigMapName,
|
|
|
|
DefaultSSLCertificate: *defSSLCertificate,
|
|
|
|
DefaultHealthzURL: *defHealthzURL,
|
|
|
|
PublishService: *publishSvc,
|
|
|
|
PublishStatusAddress: *publishStatusAddress,
|
|
|
|
ForceNamespaceIsolation: *forceIsolation,
|
|
|
|
UpdateStatusOnShutdown: *updateStatusOnShutdown,
|
|
|
|
SortBackends: *sortBackends,
|
|
|
|
UseNodeInternalIP: *useNodeInternalIP,
|
|
|
|
SyncRateLimit: *syncRateLimit,
|
|
|
|
DynamicConfigurationEnabled: *dynamicConfigurationEnabled,
|
2018-04-11 14:52:42 +00:00
|
|
|
DisableLua: disableLua,
|
2017-11-05 01:18:28 +00:00
|
|
|
ListenPorts: &ngx_config.ListenPorts{
|
|
|
|
Default: *defServerPort,
|
|
|
|
Health: *healthzPort,
|
|
|
|
HTTP: *httpPort,
|
|
|
|
HTTPS: *httpsPort,
|
|
|
|
SSLProxy: *sslProxyPort,
|
|
|
|
Status: *statusPort,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
return false, config, nil
|
|
|
|
}
|