NodePort apiserver option for exposing KubernetesMasterService NodePort on startup.

pull/6/head
jayvyas 2015-10-01 22:59:00 -04:00
parent c095bbf8ca
commit be2a2ec3cd
5 changed files with 78 additions and 45 deletions

View File

@ -114,6 +114,7 @@ type APIServer struct {
SSHUser string
SSHKeyfile string
MaxConnectionBytesPerSec int64
KubernetesServiceNodePort int
}
// NewAPIServer creates a new APIServer object with default parameters
@ -242,6 +243,8 @@ func (s *APIServer) AddFlags(fs *pflag.FlagSet) {
fs.StringVar(&s.KubeletConfig.CertFile, "kubelet-client-certificate", s.KubeletConfig.CertFile, "Path to a client cert file for TLS.")
fs.StringVar(&s.KubeletConfig.KeyFile, "kubelet-client-key", s.KubeletConfig.KeyFile, "Path to a client key file for TLS.")
fs.StringVar(&s.KubeletConfig.CAFile, "kubelet-certificate-authority", s.KubeletConfig.CAFile, "Path to a cert. file for the certificate authority.")
//See #14282 for details on how to test/try this option out. TODO remove this comment once this option is tested in CI.
fs.IntVar(&s.KubernetesServiceNodePort, "kubernetes-service-node-port", 0, "If non-zero, the Kubernetes master service (which apiserver creates/maintains) will be of type NodePort, using this as the value of the port. If zero, the Kubernetes master service will be of type ClusterIP.")
}
// TODO: Longer term we should read this from some config store, rather than a flag.
@ -353,6 +356,10 @@ func (s *APIServer) Run(_ []string) error {
glog.Fatalf("specify either --etcd-servers or --etcd-config")
}
if s.KubernetesServiceNodePort > 0 && !s.ServiceNodePortRange.Contains(s.KubernetesServiceNodePort) {
glog.Fatalf("Kubernetes service port range %v doesn't contain %v", s.ServiceNodePortRange, (s.KubernetesServiceNodePort))
}
capabilities.Initialize(capabilities.Capabilities{
AllowPrivileged: s.AllowPrivileged,
// TODO(vmarmol): Implement support for HostNetworkSources.
@ -539,6 +546,7 @@ func (s *APIServer) Run(_ []string) error {
SSHKeyfile: s.SSHKeyfile,
InstallSSHKey: installSSH,
ServiceNodePortRange: s.ServiceNodePortRange,
KubernetesServiceNodePort: s.KubernetesServiceNodePort,
}
m := master.New(config)

View File

@ -17,6 +17,7 @@ api-servers
api-server-port
api-token
api-version
kubernetes-service-node-port
authorization-mode
authorization-policy-file
auth-path

View File

@ -60,6 +60,7 @@ type Controller struct {
ServiceIP net.IP
ServicePort int
PublicServicePort int
KubernetesServiceNodePort int
runner *util.Runner
}
@ -110,7 +111,7 @@ func (c *Controller) UpdateKubernetesService() error {
return err
}
if c.ServiceIP != nil {
if err := c.CreateMasterServiceIfNeeded("kubernetes", c.ServiceIP, c.ServicePort); err != nil {
if err := c.CreateMasterServiceIfNeeded("kubernetes", c.ServiceIP, c.ServicePort, c.KubernetesServiceNodePort); err != nil {
return err
}
if err := c.SetEndpoints("kubernetes", c.PublicIP, c.PublicServicePort); err != nil {
@ -140,14 +141,33 @@ func (c *Controller) CreateNamespaceIfNeeded(ns string) error {
return err
}
// 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) {
//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,
Port: servicePort,
TargetPort: util.NewIntOrStringFromInt(servicePort),
NodePort: nodePort,
}}, api.ServiceTypeNodePort
}
// CreateMasterServiceIfNeeded will create the specified service if it
// doesn't already exist.
func (c *Controller) CreateMasterServiceIfNeeded(serviceName string, serviceIP net.IP, servicePort int) error {
func (c *Controller) CreateMasterServiceIfNeeded(serviceName string, serviceIP net.IP, servicePort, nodePort int) 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,
@ -155,15 +175,14 @@ func (c *Controller) CreateMasterServiceIfNeeded(serviceName string, serviceIP n
Labels: map[string]string{"provider": "kubernetes", "component": "apiserver"},
},
Spec: api.ServiceSpec{
Ports: []api.ServicePort{{Port: servicePort, Protocol: api.ProtocolTCP, TargetPort: util.NewIntOrStringFromInt(servicePort)}},
Ports: ports,
// maintained by this code, not by the pod selector
Selector: nil,
ClusterIP: serviceIP.String(),
SessionAffinity: api.ServiceAffinityNone,
Type: api.ServiceTypeClusterIP,
Type: serviceType,
},
}
if err := rest.BeforeCreate(rest.Services, ctx, svc); err != nil {
return err
}

View File

@ -259,7 +259,7 @@ func TestSetEndpoints(t *testing.T) {
}
if test.expectUpdate != nil {
if len(registry.Updates) != 1 {
t.Errorf("case %q: unexpected updates: %v", test.testName, registry.Updates)
t.Errorf("case %q: unexpected updates: (%v). Expected exactly 1 change. ", test.testName, registry.Updates)
} else if e, a := test.expectUpdate, &registry.Updates[0]; !reflect.DeepEqual(e, a) {
t.Errorf("case %q: expected update:\n%#v\ngot:\n%#v\n", test.testName, e, a)
}

View File

@ -244,6 +244,8 @@ type Config struct {
SSHUser string
SSHKeyfile string
InstallSSHKey InstallSSHKey
KubernetesServiceNodePort int
}
type InstallSSHKey func(user string, data []byte) error
@ -318,6 +320,7 @@ type Master struct {
thirdPartyResources map[string]*thirdpartyresourcedataetcd.REST
// protects the map
thirdPartyResourcesLock sync.RWMutex
KubernetesServiceNodePort int
}
// NewEtcdStorage returns a storage.Interface for the provided arguments or an error if the version
@ -451,6 +454,7 @@ func New(c *Config) *Master {
serviceReadWritePort: 443,
installSSHKey: c.InstallSSHKey,
KubernetesServiceNodePort: c.KubernetesServiceNodePort,
}
var handlerContainer *restful.Container
@ -784,6 +788,7 @@ func (m *Master) NewBootstrapController() *Controller {
ServiceIP: m.serviceReadWriteIP,
ServicePort: m.serviceReadWritePort,
PublicServicePort: m.publicReadWritePort,
KubernetesServiceNodePort: m.KubernetesServiceNodePort,
}
}