Check if the dns add-on is working properly and skip invalid TCP services

This commit is contained in:
Manuel de Brito Fontes 2016-02-25 14:54:12 -03:00
parent a87efce5c2
commit 98f03b789a
3 changed files with 58 additions and 27 deletions

View file

@ -63,14 +63,24 @@ func main() {
glog.Fatalf("Please specify --default-backend") 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() kubeClient, err := unversioned.NewInCluster()
if err != nil { if err != nil {
glog.Fatalf("failed to create client: %v", err) glog.Fatalf("failed to create client: %v", err)
} }
lbInfo, _ := getLBDetails(kubeClient) lbInfo, _ := getLBDetails(kubeClient)
defSvc := getService(kubeClient, *defaultSvc) defSvc, err := getService(kubeClient, *defaultSvc)
defError := getService(kubeClient, *customErrorSvc) if err != nil {
glog.Fatalf("no default backend service found: %v", err)
}
defError, _ := getService(kubeClient, *customErrorSvc)
// Start loadbalancer controller // Start loadbalancer controller
lbc, err := NewLoadBalancerController(kubeClient, *resyncPeriod, defSvc, defError, *watchNamespace, lbInfo) lbc, err := NewLoadBalancerController(kubeClient, *resyncPeriod, defSvc, defError, *watchNamespace, lbInfo)

View file

@ -30,6 +30,7 @@ const (
// Start starts a nginx (master process) and waits. If the process ends // Start starts a nginx (master process) and waits. If the process ends
// we need to kill the controller process and return the reason. // we need to kill the controller process and return the reason.
func (ngx *NginxManager) Start() { func (ngx *NginxManager) Start() {
glog.Info("Starting nginx...")
cmd := exec.Command("nginx") cmd := exec.Command("nginx")
cmd.Stdout = os.Stdout cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr cmd.Stderr = os.Stderr

View file

@ -19,6 +19,7 @@ package main
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"net"
"os" "os"
"strconv" "strconv"
"strings" "strings"
@ -36,6 +37,11 @@ import (
"k8s.io/kubernetes/pkg/util/workqueue" "k8s.io/kubernetes/pkg/util/workqueue"
) )
const (
httpPort = "80"
httpsPort = "443"
)
var ( var (
errMissingPodInfo = fmt.Errorf("Unable to get POD information") 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 == "" { 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, "/") parts := strings.Split(name, "/")
if len(parts) != 2 { 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]) defaultPort, err := getServicePorts(kubeClient, parts[0], parts[1])
if err != nil { 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{ return nginx.Service{
ServiceName: parts[1], ServiceName: parts[1],
ServicePort: defaultPort[0], //TODO: which port? ServicePort: defaultPort[0], //TODO: which port?
Namespace: parts[0], 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) { func getServicePorts(kubeClient *unversioned.Client, ns, name string) (ports []string, err error) {
var svc *api.Service var svc *api.Service
glog.Infof("Waiting for %v/%v", ns, name) glog.Infof("Checking service %v/%v", ns, name)
wait.Poll(1*time.Second, 5*time.Minute, func() (bool, error) { svc, err = kubeClient.Services(ns).Get(name)
svc, err = kubeClient.Services(ns).Get(name) if err != nil {
if err != nil { return
if glog.V(2) { }
glog.Errorf("%v", err)
}
return false, nil
}
for _, p := range svc.Spec.Ports { for _, p := range svc.Spec.Ports {
if p.Port != 0 { if p.Port != 0 {
ports = append(ports, strconv.Itoa(p.Port)) ports = append(ports, strconv.Itoa(p.Port))
break break
}
} }
}
glog.Infof("Ports for %v/%v : %v", ns, name, ports) glog.Infof("Ports for %v/%v : %v", ns, name, ports)
return true, nil
})
return return
} }
@ -219,7 +218,18 @@ func getTcpServices(kubeClient *unversioned.Client, tcpServices string) []nginx.
namePort := strings.Split(svc, ":") namePort := strings.Split(svc, ":")
if len(namePort) == 2 { 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] tcpSvc.ExposedPort = namePort[1]
svcs = append(svcs, tcpSvc) svcs = append(svcs, tcpSvc)
} else { } else {
@ -229,3 +239,13 @@ func getTcpServices(kubeClient *unversioned.Client, tcpServices string) []nginx.
return svcs 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)
}