Add flags to customize listen ports and detect port collisions

This commit is contained in:
Manuel de Brito Fontes 2017-08-24 10:33:26 -03:00
parent 02e20eb81a
commit 0459674931
12 changed files with 127 additions and 47 deletions

View file

@ -45,6 +45,8 @@ type statsCollector struct {
namespace string
watchClass string
healthPort int
}
func (s *statsCollector) stop(sm statusModule) {
@ -61,17 +63,17 @@ func (s *statsCollector) stop(sm statusModule) {
func (s *statsCollector) start(sm statusModule) {
switch sm {
case defaultStatusModule:
s.basic = collector.NewNginxStatus(s.namespace, s.watchClass, ngxHealthPort, ngxStatusPath)
s.basic = collector.NewNginxStatus(s.namespace, s.watchClass, s.healthPort, ngxStatusPath)
prometheus.Register(s.basic)
break
case vtsStatusModule:
s.vts = collector.NewNGINXVTSCollector(s.namespace, s.watchClass, ngxHealthPort, ngxVtsPath)
s.vts = collector.NewNGINXVTSCollector(s.namespace, s.watchClass, s.healthPort, ngxVtsPath)
prometheus.Register(s.vts)
break
}
}
func newStatsCollector(ns, class, binary string) *statsCollector {
func newStatsCollector(ns, class, binary string, hz int) *statsCollector {
glog.Infof("starting new nginx stats collector for Ingress controller running in namespace %v (class %v)", ns, class)
pc, err := collector.NewNamedProcess(true, collector.BinaryNameMatcher{
Name: "nginx",
@ -89,5 +91,6 @@ func newStatsCollector(ns, class, binary string) *statsCollector {
namespace: ns,
watchClass: class,
process: pc,
healthPort: hz,
}
}

View file

@ -34,6 +34,7 @@ import (
"github.com/spf13/pflag"
proxyproto "github.com/armon/go-proxyproto"
api "k8s.io/api/core/v1"
api_v1 "k8s.io/api/core/v1"
extensions "k8s.io/api/extensions/v1beta1"
@ -50,7 +51,6 @@ import (
type statusModule string
const (
ngxHealthPort = 18080
ngxHealthPath = "/healthz"
defaultStatusModule statusModule = "default"
@ -87,6 +87,7 @@ func newNGINXController() ingress.Controller {
configmap: &api_v1.ConfigMap{},
isIPV6Enabled: isIPv6Enabled(),
resolver: h,
ports: &config.ListenPorts{},
}
fcgiListener, err := net.Listen("unix", fastCGISocket)
@ -161,6 +162,8 @@ type NGINXController struct {
isSSLPassthroughEnabled bool
proxy *proxy
ports *config.ListenPorts
}
// Start start a new NGINX master process running in foreground.
@ -280,14 +283,42 @@ func (n NGINXController) Info() *ingress.BackendInfo {
}
}
// DefaultEndpoint returns the default endpoint to be use as default server that returns 404.
func (n NGINXController) DefaultEndpoint() ingress.Endpoint {
return ingress.Endpoint{
Address: "127.0.0.1",
Port: fmt.Sprintf("%v", n.ports.Default),
Target: &api.ObjectReference{},
}
}
// ConfigureFlags allow to configure more flags before the parsing of
// command line arguments
func (n *NGINXController) ConfigureFlags(flags *pflag.FlagSet) {
flags.BoolVar(&n.isSSLPassthroughEnabled, "enable-ssl-passthrough", false, `Enable SSL passthrough feature. Default is disabled`)
flags.IntVar(&n.ports.HTTP, "http-port", 80, `Indicates the port to use for HTTP traffic`)
flags.IntVar(&n.ports.HTTPS, "https-port", 443, `Indicates the port to use for HTTPS traffic`)
flags.IntVar(&n.ports.Status, "status-port", 18080, `Indicates the TCP port to use for exposing the nginx status page`)
flags.IntVar(&n.ports.SSLProxy, "ssl-passtrough-proxy-port", 442, `Default port to use internally for SSL when SSL Passthgough is enabled`)
flags.IntVar(&n.ports.Default, "default-server-port", 8181, `Default port to use for exposing the default server (catch all)`)
}
// OverrideFlags customize NGINX controller flags
func (n *NGINXController) OverrideFlags(flags *pflag.FlagSet) {
// we check port collisions
if !isPortAvailable(n.ports.HTTP) {
glog.Fatalf("Port %v is already in use. Please check the flag --http-port", n.ports.HTTP)
}
if !isPortAvailable(n.ports.HTTPS) {
glog.Fatalf("Port %v is already in use. Please check the flag --https-port", n.ports.HTTPS)
}
if !isPortAvailable(n.ports.Status) {
glog.Fatalf("Port %v is already in use. Please check the flag --status-port", n.ports.Status)
}
if !isPortAvailable(n.ports.Default) {
glog.Fatalf("Port %v is already in use. Please check the flag --default-server-port", n.ports.Default)
}
ic, _ := flags.GetString("ingress-class")
wc, _ := flags.GetString("watch-namespace")
@ -300,20 +331,24 @@ func (n *NGINXController) OverrideFlags(flags *pflag.FlagSet) {
}
flags.Set("ingress-class", ic)
n.stats = newStatsCollector(wc, ic, n.binary)
n.stats = newStatsCollector(wc, ic, n.binary, n.ports.Health)
if n.isSSLPassthroughEnabled {
if !isPortAvailable(n.ports.SSLProxy) {
glog.Fatalf("Port %v is already in use. Please check the flag --ssl-passtrough-proxy-port", n.ports.SSLProxy)
}
glog.Info("starting TLS proxy for SSL passthrough")
n.proxy = &proxy{
Default: &server{
Hostname: "localhost",
IP: "127.0.0.1",
Port: 442,
Port: n.ports.SSLProxy,
ProxyProtocol: true,
},
}
listener, err := net.Listen("tcp", ":443")
listener, err := net.Listen("tcp", fmt.Sprintf(":%v", n.ports.HTTPS))
if err != nil {
glog.Fatalf("%v", err)
}
@ -594,6 +629,7 @@ func (n *NGINXController) OnUpdate(ingressCfg ingress.Configuration) error {
IsIPV6Enabled: n.isIPV6Enabled && !cfg.DisableIpv6,
RedirectServers: redirectServers,
IsSSLPassthroughEnabled: n.isSSLPassthroughEnabled,
ListenPorts: n.ports,
}
// We need to extract the endpoints to be used in the fastcgi error handler
@ -651,7 +687,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://localhost:%v%v", ngxHealthPort, ngxHealthPath))
res, err := http.Get(fmt.Sprintf("http://localhost:%v%v", n.ports.Status, ngxHealthPath))
if err != nil {
return err
}

View file

@ -17,7 +17,9 @@ limitations under the License.
package main
import (
"fmt"
"io/ioutil"
"net"
"os"
"os/exec"
"syscall"
@ -74,3 +76,12 @@ func diff(b1, b2 []byte) ([]byte, error) {
out, _ := exec.Command("diff", "-u", f1.Name(), f2.Name()).CombinedOutput()
return out, nil
}
func isPortAvailable(p int) bool {
ln, err := net.Listen("tcp", fmt.Sprintf(":%v", p))
if err != nil {
return false
}
ln.Close()
return true
}