From 98f03b789acd312b5b77b00c0b30ec8111a27d1a Mon Sep 17 00:00:00 2001 From: Manuel de Brito Fontes Date: Thu, 25 Feb 2016 14:54:12 -0300 Subject: [PATCH] Check if the dns add-on is working properly and skip invalid TCP services --- controllers/nginx-third-party/main.go | 14 +++- .../nginx-third-party/nginx/command.go | 1 + controllers/nginx-third-party/utils.go | 70 ++++++++++++------- 3 files changed, 58 insertions(+), 27 deletions(-) diff --git a/controllers/nginx-third-party/main.go b/controllers/nginx-third-party/main.go index a5cec4001..0ec320327 100644 --- a/controllers/nginx-third-party/main.go +++ b/controllers/nginx-third-party/main.go @@ -63,14 +63,24 @@ func main() { glog.Fatalf("Please specify --default-backend") } + glog.Info("Checking if DNS is working") + ip, err := checkDNS(*defaultSvc) + if err != nil { + glog.Fatalf("Please check if the DNS addon is working properly.\n%v", err) + } + glog.Infof("IP address of '%v' service: %s", *defaultSvc, ip) + kubeClient, err := unversioned.NewInCluster() if err != nil { glog.Fatalf("failed to create client: %v", err) } lbInfo, _ := getLBDetails(kubeClient) - defSvc := getService(kubeClient, *defaultSvc) - defError := getService(kubeClient, *customErrorSvc) + defSvc, err := getService(kubeClient, *defaultSvc) + if err != nil { + glog.Fatalf("no default backend service found: %v", err) + } + defError, _ := getService(kubeClient, *customErrorSvc) // Start loadbalancer controller lbc, err := NewLoadBalancerController(kubeClient, *resyncPeriod, defSvc, defError, *watchNamespace, lbInfo) diff --git a/controllers/nginx-third-party/nginx/command.go b/controllers/nginx-third-party/nginx/command.go index e1e02becd..8bd0a24c0 100644 --- a/controllers/nginx-third-party/nginx/command.go +++ b/controllers/nginx-third-party/nginx/command.go @@ -30,6 +30,7 @@ const ( // Start starts a nginx (master process) and waits. If the process ends // we need to kill the controller process and return the reason. func (ngx *NginxManager) Start() { + glog.Info("Starting nginx...") cmd := exec.Command("nginx") cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr diff --git a/controllers/nginx-third-party/utils.go b/controllers/nginx-third-party/utils.go index 13ae1955a..4a4b29527 100644 --- a/controllers/nginx-third-party/utils.go +++ b/controllers/nginx-third-party/utils.go @@ -19,6 +19,7 @@ package main import ( "encoding/json" "fmt" + "net" "os" "strconv" "strings" @@ -36,6 +37,11 @@ import ( "k8s.io/kubernetes/pkg/util/workqueue" ) +const ( + httpPort = "80" + httpsPort = "443" +) + var ( errMissingPodInfo = fmt.Errorf("Unable to get POD information") @@ -160,52 +166,45 @@ func getLBDetails(kubeClient *unversioned.Client) (rc *lbInfo, err error) { } } -func getService(kubeClient *unversioned.Client, name string) nginx.Service { +func getService(kubeClient *unversioned.Client, name string) (nginx.Service, error) { if name == "" { - return nginx.Service{} + return nginx.Service{}, fmt.Errorf("Empty string is not a valid service name") } - // Wait for the default backend Service. There's no pretty way to do this. parts := strings.Split(name, "/") if len(parts) != 2 { - glog.Fatalf("Default backend should take the form namespace/name: %v", name) + glog.Fatalf("Please check the service format (namespace/name) in service %v", name) } defaultPort, err := getServicePorts(kubeClient, parts[0], parts[1]) if err != nil { - glog.Fatalf("Could not configure default backend %v: %v", name, err) + return nginx.Service{}, fmt.Errorf("Error obtaining service %v: %v", name, err) } return nginx.Service{ ServiceName: parts[1], ServicePort: defaultPort[0], //TODO: which port? Namespace: parts[0], - } + }, nil } -// getServicePorts returns the po +// getServicePorts returns the ports defined in a service spec func getServicePorts(kubeClient *unversioned.Client, ns, name string) (ports []string, err error) { var svc *api.Service - glog.Infof("Waiting for %v/%v", ns, name) - wait.Poll(1*time.Second, 5*time.Minute, func() (bool, error) { - svc, err = kubeClient.Services(ns).Get(name) - if err != nil { - if glog.V(2) { - glog.Errorf("%v", err) - } - return false, nil - } + glog.Infof("Checking service %v/%v", ns, name) + svc, err = kubeClient.Services(ns).Get(name) + if err != nil { + return + } - for _, p := range svc.Spec.Ports { - if p.Port != 0 { - ports = append(ports, strconv.Itoa(p.Port)) - break - } + for _, p := range svc.Spec.Ports { + if p.Port != 0 { + ports = append(ports, strconv.Itoa(p.Port)) + break } + } - glog.Infof("Ports for %v/%v : %v", ns, name, ports) - return true, nil - }) + glog.Infof("Ports for %v/%v : %v", ns, name, ports) return } @@ -219,7 +218,18 @@ func getTcpServices(kubeClient *unversioned.Client, tcpServices string) []nginx. namePort := strings.Split(svc, ":") if len(namePort) == 2 { - tcpSvc := getService(kubeClient, namePort[0]) + tcpSvc, err := getService(kubeClient, namePort[0]) + if err != nil { + glog.Errorf("%s", err) + continue + } + + // the exposed TCP service cannot use 80 or 443 as ports + if namePort[1] == httpPort || namePort[1] == httpsPort { + glog.Errorf("The TCP service %v cannot use ports 80 or 443 (it creates a conflict with nginx)", svc) + continue + } + tcpSvc.ExposedPort = namePort[1] svcs = append(svcs, tcpSvc) } else { @@ -229,3 +239,13 @@ func getTcpServices(kubeClient *unversioned.Client, tcpServices string) []nginx. return svcs } + +func checkDNS(name string) (*net.IPAddr, error) { + parts := strings.Split(name, "/") + if len(parts) != 2 { + glog.Fatalf("Please check the service format (namespace/name) in service %v", name) + } + + host := fmt.Sprintf("%v.%v", parts[1], parts[0]) + return net.ResolveIPAddr("ip4", host) +}