diff --git a/cmd/controller/controller.go b/cmd/controller/controller.go index 49f3765a06f5..4c3d25686ccb 100644 --- a/cmd/controller/controller.go +++ b/cmd/controller/controller.go @@ -184,6 +184,7 @@ func (c *CmdOpts) startController() error { }) logrus.Infof("using api address: %s", c.ClusterConfig.Spec.API.Address) + logrus.Infof("using api bind-address: %s", c.ClusterConfig.Spec.API.BindAddress) logrus.Infof("using listen port: %d", c.ClusterConfig.Spec.API.Port) logrus.Infof("using sans: %s", c.ClusterConfig.Spec.API.SANs) dnsAddress, err := c.ClusterConfig.Spec.Network.DNSAddress() diff --git a/pkg/apis/v1beta1/api.go b/pkg/apis/v1beta1/api.go index de954435074f..2cf0e7504e26 100644 --- a/pkg/apis/v1beta1/api.go +++ b/pkg/apis/v1beta1/api.go @@ -29,6 +29,7 @@ var _ Validateable = (*APISpec)(nil) type APISpec struct { Address string `yaml:"address"` Port int `yaml:"port"` + BindAddress string `yaml:"bindAddress,omitempty"` K0sAPIPort int `yaml:"k0sApiPort,omitempty"` ExternalAddress string `yaml:"externalAddress,omitempty"` SANs []string `yaml:"sans"` @@ -41,11 +42,12 @@ func DefaultAPISpec() *APISpec { addresses, _ := util.AllAddresses() publicAddress, _ := util.FirstPublicAddress() return &APISpec{ - Port: 6443, - K0sAPIPort: 9443, - SANs: addresses, - Address: publicAddress, - ExtraArgs: make(map[string]string), + Port: 6443, + K0sAPIPort: 9443, + BindAddress: "0.0.0.0", + SANs: addresses, + Address: publicAddress, + ExtraArgs: make(map[string]string), } } @@ -84,6 +86,20 @@ func (a *APISpec) getExternalURIForPort(port int) string { return fmt.Sprintf("https://%s:%d", addr, port) } +// APIServerAddress returns the address the API is listening on +func (a *APISpec) APIServerAddress() string { + return a.getAPIServerAddress(a.BindAddress) +} + +func (a *APISpec) getAPIServerAddress(address string) string { + switch address { + case "0.0.0.0": + return "localhost" + default: + return address + } +} + // Sans return the given SANS plus all local adresses and externalAddress if given func (a *APISpec) Sans() []string { sans, _ := util.AllAddresses() @@ -114,5 +130,9 @@ func (a *APISpec) Validate() []error { errors = append(errors, fmt.Errorf("spec.api.address: %q is not IP address", a.Address)) } + if !govalidator.IsIP(a.BindAddress) { + errors = append(errors, fmt.Errorf("spec.api.bindAddress: %q is not IP address", a.BindAddress)) + } + return errors } diff --git a/pkg/component/controller/apiserver.go b/pkg/component/controller/apiserver.go index e82f88fd1e35..2078c7410c72 100644 --- a/pkg/component/controller/apiserver.go +++ b/pkg/component/controller/apiserver.go @@ -87,6 +87,7 @@ func (a *APIServer) Run() error { logrus.Info("Starting kube-apiserver") args := map[string]string{ "advertise-address": a.ClusterConfig.Spec.API.Address, + "bind-address": a.ClusterConfig.Spec.API.BindAddress, "secure-port": fmt.Sprintf("%d", a.ClusterConfig.Spec.API.Port), "authorization-mode": "Node,RBAC", "client-ca-file": path.Join(a.K0sVars.CertRootDir, "ca.crt"), @@ -218,7 +219,7 @@ func (a *APIServer) Healthy() error { TLSClientConfig: tlsConfig, } client := &http.Client{Transport: tr} - resp, err := client.Get(fmt.Sprintf("https://localhost:%d/readyz?verbose", a.ClusterConfig.Spec.API.Port)) + resp, err := client.Get(fmt.Sprintf("https://%s:%d/readyz?verbose", a.ClusterConfig.Spec.API.APIServerAddress(), a.ClusterConfig.Spec.API.Port)) if err != nil { return err } diff --git a/pkg/component/controller/certificates.go b/pkg/component/controller/certificates.go index 1ed6ca383e71..cc0fc33a0c82 100644 --- a/pkg/component/controller/certificates.go +++ b/pkg/component/controller/certificates.go @@ -86,7 +86,7 @@ func (c *Certificates) Init() error { return fmt.Errorf("failed to read ca cert: %w", err) } c.CACert = string(cert) - kubeConfigAPIUrl := fmt.Sprintf("https://localhost:%d", c.ClusterSpec.API.Port) + kubeConfigAPIUrl := fmt.Sprintf("https://%s:%d", c.ClusterSpec.API.APIServerAddress(), c.ClusterSpec.API.Port) eg.Go(func() error { // Front proxy CA if err := c.CertManager.EnsureCA("front-proxy-ca", "kubernetes-front-proxy-ca"); err != nil {