Additional service ports config for master service.

This commit is contained in:
Andrew Butcher
2015-10-07 11:06:05 -04:00
parent eeeb5e0cd6
commit efd8e3c9c7
4 changed files with 214 additions and 75 deletions

View File

@@ -59,6 +59,8 @@ type Controller struct {
ServiceIP net.IP
ServicePort int
ExtraServicePorts []api.ServicePort
ExtraEndpointPorts []api.EndpointPort
PublicServicePort int
KubernetesServiceNodePort int
@@ -111,10 +113,12 @@ func (c *Controller) UpdateKubernetesService() error {
return err
}
if c.ServiceIP != nil {
if err := c.CreateMasterServiceIfNeeded("kubernetes", c.ServiceIP, c.ServicePort, c.KubernetesServiceNodePort); err != nil {
servicePorts, serviceType := createPortAndServiceSpec(c.ServicePort, c.KubernetesServiceNodePort, "https", c.ExtraServicePorts)
if err := c.CreateMasterServiceIfNeeded("kubernetes", c.ServiceIP, servicePorts, serviceType); err != nil {
return err
}
if err := c.SetEndpoints("kubernetes", c.PublicIP, c.PublicServicePort); err != nil {
endpointPorts := createEndpointPortSpec(c.PublicServicePort, "https", c.ExtraEndpointPorts)
if err := c.SetEndpoints("kubernetes", c.PublicIP, endpointPorts); err != nil {
return err
}
}
@@ -143,31 +147,44 @@ func (c *Controller) CreateNamespaceIfNeeded(ns string) error {
// createPortAndServiceSpec creates an array of service ports.
// If the NodePort value is 0, just the servicePort is used, otherwise, a node port is exposed.
func createPortAndServiceSpec(servicePort int, nodePort int) ([]api.ServicePort, api.ServiceType) {
func createPortAndServiceSpec(servicePort int, nodePort int, servicePortName string, extraServicePorts []api.ServicePort) ([]api.ServicePort, api.ServiceType) {
//Use the Cluster IP type for the service port if NodePort isn't provided.
//Otherwise, we will be binding the master service to a NodePort.
if nodePort <= 0 {
return []api.ServicePort{{Protocol: api.ProtocolTCP,
Port: servicePort,
TargetPort: util.NewIntOrStringFromInt(servicePort)}}, api.ServiceTypeClusterIP
}
return []api.ServicePort{{Protocol: api.ProtocolTCP,
servicePorts := []api.ServicePort{{Protocol: api.ProtocolTCP,
Port: servicePort,
TargetPort: util.NewIntOrStringFromInt(servicePort),
NodePort: nodePort,
}}, api.ServiceTypeNodePort
Name: servicePortName,
TargetPort: util.NewIntOrStringFromInt(servicePort)}}
serviceType := api.ServiceTypeClusterIP
if nodePort > 0 {
servicePorts[0].NodePort = nodePort
serviceType = api.ServiceTypeNodePort
}
if extraServicePorts != nil {
servicePorts = append(servicePorts, extraServicePorts...)
}
return servicePorts, serviceType
}
// createEndpointPortSpec creates an array of endpoint ports
func createEndpointPortSpec(endpointPort int, endpointPortName string, extraEndpointPorts []api.EndpointPort) []api.EndpointPort {
endpointPorts := []api.EndpointPort{{Protocol: api.ProtocolTCP,
Port: endpointPort,
Name: endpointPortName,
}}
if extraEndpointPorts != nil {
endpointPorts = append(endpointPorts, extraEndpointPorts...)
}
return endpointPorts
}
// CreateMasterServiceIfNeeded will create the specified service if it
// doesn't already exist.
func (c *Controller) CreateMasterServiceIfNeeded(serviceName string, serviceIP net.IP, servicePort, nodePort int) error {
func (c *Controller) CreateMasterServiceIfNeeded(serviceName string, serviceIP net.IP, servicePorts []api.ServicePort, serviceType api.ServiceType) error {
ctx := api.NewDefaultContext()
if _, err := c.ServiceRegistry.GetService(ctx, serviceName); err == nil {
// The service already exists.
return nil
}
ports, serviceType := createPortAndServiceSpec(servicePort, nodePort)
svc := &api.Service{
ObjectMeta: api.ObjectMeta{
Name: serviceName,
@@ -175,7 +192,7 @@ func (c *Controller) CreateMasterServiceIfNeeded(serviceName string, serviceIP n
Labels: map[string]string{"provider": "kubernetes", "component": "apiserver"},
},
Spec: api.ServiceSpec{
Ports: ports,
Ports: servicePorts,
// maintained by this code, not by the pod selector
Selector: nil,
ClusterIP: serviceIP.String(),
@@ -207,7 +224,7 @@ func (c *Controller) CreateMasterServiceIfNeeded(serviceName string, serviceIP n
// to be running (c.masterCount).
// * SetEndpoints is called periodically from all apiservers.
//
func (c *Controller) SetEndpoints(serviceName string, ip net.IP, port int) error {
func (c *Controller) SetEndpoints(serviceName string, ip net.IP, endpointPorts []api.EndpointPort) error {
ctx := api.NewDefaultContext()
e, err := c.EndpointRegistry.GetEndpoints(ctx, serviceName)
if err != nil {
@@ -220,13 +237,13 @@ func (c *Controller) SetEndpoints(serviceName string, ip net.IP, port int) error
}
// First, determine if the endpoint is in the format we expect (one
// subset, one port, N IP addresses).
formatCorrect, ipCorrect := checkEndpointSubsetFormat(e, ip.String(), port, c.MasterCount)
// subset, ports matching endpointPorts, N IP addresses).
formatCorrect, ipCorrect := checkEndpointSubsetFormat(e, ip.String(), endpointPorts, c.MasterCount)
if !formatCorrect {
// Something is egregiously wrong, just re-make the endpoints record.
e.Subsets = []api.EndpointSubset{{
Addresses: []api.EndpointAddress{{IP: ip.String()}},
Ports: []api.EndpointPort{{Port: port, Protocol: api.ProtocolTCP}},
Ports: endpointPorts,
}}
glog.Warningf("Resetting endpoints for master service %q to %v", serviceName, e)
return c.EndpointRegistry.UpdateEndpoints(ctx, e)
@@ -259,17 +276,19 @@ func (c *Controller) SetEndpoints(serviceName string, ip net.IP, port int) error
// Determine if the endpoint is in the format SetEndpoints expect (one subset,
// one port, N IP addresses); and if the specified IP address is present and
// the correct number of ip addresses are found.
func checkEndpointSubsetFormat(e *api.Endpoints, ip string, port int, count int) (formatCorrect, ipCorrect bool) {
func checkEndpointSubsetFormat(e *api.Endpoints, ip string, ports []api.EndpointPort, count int) (formatCorrect, ipCorrect bool) {
if len(e.Subsets) != 1 {
return false, false
}
sub := &e.Subsets[0]
if len(sub.Ports) != 1 {
if len(sub.Ports) != len(ports) {
return false, false
}
p := &sub.Ports[0]
if p.Port != port || p.Protocol != api.ProtocolTCP {
return false, false
for i, p := range ports {
ep := &sub.Ports[i]
if p.Port != ep.Port || p.Protocol != ep.Protocol || p.Name != ep.Name {
return false, false
}
}
for _, addr := range sub.Addresses {
if addr.IP == ip {