diff --git a/cmd/kube-apiserver/app/server.go b/cmd/kube-apiserver/app/server.go index 84ec8c2dab0..15921ce4bbf 100644 --- a/cmd/kube-apiserver/app/server.go +++ b/cmd/kube-apiserver/app/server.go @@ -449,7 +449,7 @@ func (s *APIServer) Run(_ []string) error { s.TLSCertFile = path.Join(s.CertDirectory, "apiserver.crt") s.TLSPrivateKeyFile = path.Join(s.CertDirectory, "apiserver.key") // TODO (cjcullen): Is PublicAddress the right address to sign a cert with? - if err := util.GenerateSelfSignedCert(config.PublicAddress.String(), s.TLSCertFile, s.TLSPrivateKeyFile); err != nil { + if err := util.GenerateSelfSignedCert(config.PublicAddress.String(), s.TLSCertFile, s.TLSPrivateKeyFile, config.ServiceReadWriteIP); err != nil { glog.Errorf("Unable to generate self signed cert: %v", err) } else { glog.Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile) diff --git a/cmd/kubelet/app/server.go b/cmd/kubelet/app/server.go index 1cd1362da1f..f4b97a07bb3 100644 --- a/cmd/kubelet/app/server.go +++ b/cmd/kubelet/app/server.go @@ -395,7 +395,7 @@ func (s *KubeletServer) InitializeTLS() (*kubelet.TLSOptions, error) { if s.TLSCertFile == "" && s.TLSPrivateKeyFile == "" { s.TLSCertFile = path.Join(s.CertDirectory, "kubelet.crt") s.TLSPrivateKeyFile = path.Join(s.CertDirectory, "kubelet.key") - if err := util.GenerateSelfSignedCert(nodeutil.GetHostname(s.HostnameOverride), s.TLSCertFile, s.TLSPrivateKeyFile); err != nil { + if err := util.GenerateSelfSignedCert(nodeutil.GetHostname(s.HostnameOverride), s.TLSCertFile, s.TLSPrivateKeyFile, nil); err != nil { return nil, fmt.Errorf("unable to generate self signed cert: %v", err) } glog.V(4).Infof("Using self-signed cert (%s, %s)", s.TLSCertFile, s.TLSPrivateKeyFile) diff --git a/pkg/master/master.go b/pkg/master/master.go index ebc11888869..f07a7103618 100644 --- a/pkg/master/master.go +++ b/pkg/master/master.go @@ -147,6 +147,9 @@ type Config struct { // The range of IPs to be assigned to services with type=ClusterIP or greater ServiceClusterIPRange *net.IPNet + // The IP address for the master service (must be inside ServiceClusterIPRange + ServiceReadWriteIP net.IP + // The range of ports to be assigned to services with type=NodePort or greater ServiceNodePortRange util.PortRange @@ -245,6 +248,15 @@ func setDefaults(c *Config) { } c.ServiceClusterIPRange = serviceClusterIPRange } + if c.ServiceReadWriteIP == nil { + // Select the first valid IP from ServiceClusterIPRange to use as the master service IP. + serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) + if err != nil { + glog.Fatalf("Failed to generate service read-write IP for master service: %v", err) + } + glog.V(4).Infof("Setting master service IP to %q (read-write).", serviceReadWriteIP) + c.ServiceReadWriteIP = serviceReadWriteIP + } if c.ServiceNodePortRange.Size == 0 { // TODO: Currently no way to specify an empty range (do we need to allow this?) // We should probably allow this for clouds that don't require NodePort to do load-balancing (GCE) @@ -311,13 +323,6 @@ func New(c *Config) *Master { glog.Fatalf("master.New() called with config.KubeletClient == nil") } - // Select the first valid IP from serviceClusterIPRange to use as the master service IP. - serviceReadWriteIP, err := ipallocator.GetIndexedIP(c.ServiceClusterIPRange, 1) - if err != nil { - glog.Fatalf("Failed to generate service read-write IP for master service: %v", err) - } - glog.V(4).Infof("Setting master service IP to %q (read-write).", serviceReadWriteIP) - m := &Master{ serviceClusterIPRange: c.ServiceClusterIPRange, serviceNodePortRange: c.ServiceNodePortRange, @@ -343,7 +348,7 @@ func New(c *Config) *Master { externalHost: c.ExternalHost, clusterIP: c.PublicAddress, publicReadWritePort: c.ReadWritePort, - serviceReadWriteIP: serviceReadWriteIP, + serviceReadWriteIP: c.ServiceReadWriteIP, // TODO: serviceReadWritePort should be passed in as an argument, it may not always be 443 serviceReadWritePort: 443, diff --git a/pkg/util/crypto.go b/pkg/util/crypto.go index f312246bb57..eadb0424b18 100644 --- a/pkg/util/crypto.go +++ b/pkg/util/crypto.go @@ -38,7 +38,7 @@ import ( // The certificate will be created with file mode 0644. The key will be created with file mode 0600. // If the certificate or key files already exist, they will be overwritten. // Any parent directories of the certPath or keyPath will be created as needed with file mode 0755. -func GenerateSelfSignedCert(host, certPath, keyPath string) error { +func GenerateSelfSignedCert(host, certPath, keyPath string, ServiceReadWriteIP net.IP) error { priv, err := rsa.GenerateKey(rand.Reader, 2048) if err != nil { return err @@ -63,6 +63,15 @@ func GenerateSelfSignedCert(host, certPath, keyPath string) error { template.DNSNames = append(template.DNSNames, host) } + if ServiceReadWriteIP != nil { + template.IPAddresses = append(template.IPAddresses, ServiceReadWriteIP) + } + // It would be nice to have the next line, but only the kubelets know the fqdn, the apiserver is clueless + // template.DNSNames = append(template.DNSNames, "kubernetes.default.svc.CLUSTER.DNS.NAME") + template.DNSNames = append(template.DNSNames, "kubernetes.default.svc") + template.DNSNames = append(template.DNSNames, "kubernetes.default") + template.DNSNames = append(template.DNSNames, "kubernetes") + derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return err