Skip to content

Commit

Permalink
Add spec.api.bindAddress configuration
Browse files Browse the repository at this point in the history
Signed-off-by: Alex Hutchins <gakio12@gmail.com>
Signed-off-by: gakio12 <gakio12@gmail.com>
Signed-off-by: Phillip Schichtel <phillip@schich.tel>
  • Loading branch information
gakio12 authored and pschichtel committed Sep 1, 2024
1 parent 38c9110 commit 4161823
Show file tree
Hide file tree
Showing 7 changed files with 49 additions and 6 deletions.
2 changes: 1 addition & 1 deletion cmd/controller/certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func (c *Certificates) Init(ctx context.Context) error {
}
c.CACert = string(cert)
// Changing the URL here also requires changes in the "k0s kubeconfig admin" subcommand.
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 {
Expand Down
1 change: 1 addition & 0 deletions cmd/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,7 @@ func (c *command) start(ctx context.Context) error {
}

logrus.Infof("using api address: %s", nodeConfig.Spec.API.Address)
logrus.Infof("using api bind-address: %s", nodeConfig.Spec.API.BindAddress)
logrus.Infof("using listen port: %d", nodeConfig.Spec.API.Port)
logrus.Infof("using sans: %s", nodeConfig.Spec.API.SANs)

Expand Down
6 changes: 4 additions & 2 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ spec:
address: 192.168.68.104
k0sApiPort: 9443
port: 6443
bindAddress: 192.0.2.1
sans:
- 192.168.68.104
controllerManager: {}
Expand Down Expand Up @@ -113,9 +114,10 @@ spec:
### `spec.api`
| Element | Description |
| ------------------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|--------------------------| --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `externalAddress` | The loadbalancer address (for k0s controllers running behind a loadbalancer). Configures all cluster components to connect to this address and also configures this address for use when joining new nodes to the cluster. |
| `address` | Local address on which to bind an API. Also serves as one of the addresses pushed on the k0s create service certificate on the API. Defaults to first non-local address found on the node. |
| `address` | Local address on which to bind an API. Also serves as one of the addresses pushed on the k0s create service certificate on the API. Defaults to first non-local address found on the node. |
| `bindAddress` | The IP address for the Kubernetes API server to to listen on. The associated interface(s) must be reachable by the rest of the cluster. Will be added as an additional subject alternative name to the API server's TLS certificate. If blank or an unspecified address (`0.0.0.0` or `::`), all interfaces and IP address families will be used. This is effectively the value for the API server's `--bind-address` CLI flag. |
| `sans` | List of additional addresses to push to API servers serving the certificate. |
| `extraArgs` | Map of key-values (strings) for any extra arguments to pass down to Kubernetes api-server process. |
| `port`¹ | Custom port for kube-api server to listen on (default: 6443) |
Expand Down
20 changes: 19 additions & 1 deletion pkg/apis/k0s/v1beta1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,10 @@ type APISpec struct {
// Address on which to connect to the API server.
Address string `json:"address,omitempty"`

// The IP address for the Kubernetes API server to listen on.
// +optional
BindAddress string `json:"bindAddress,omitempty"`

// The loadbalancer address (for k0s controllers running behind a loadbalancer)
ExternalAddress string `json:"externalAddress,omitempty"`

Expand Down Expand Up @@ -102,10 +106,21 @@ func (a *APISpec) getExternalURIForPort(port int) string {
return fmt.Sprintf("https://%s:%d", addr, port)
}

// Sans return the given SANS plus all local adresses and externalAddress if given
// APIServerAddress returns the address the API is listening on
func (a *APISpec) APIServerAddress() string {
if a.BindAddress == "" {
return "localhost"
}
return a.BindAddress
}

// Sans return the given SANS plus all local addresses and externalAddress if given
func (a *APISpec) Sans() []string {
sans, _ := iface.AllAddresses()
sans = append(sans, a.Address)
if a.BindAddress != "" {
sans = append(sans, a.BindAddress)
}
sans = append(sans, a.SANs...)
if a.ExternalAddress != "" {
sans = append(sans, a.ExternalAddress)
Expand Down Expand Up @@ -150,6 +165,9 @@ func (a *APISpec) Validate() []error {
validateIPAddressOrDNSName(sansPath.Index(idx), san)
}

if a.BindAddress != "" && !govalidator.IsIP(a.BindAddress) {
errors = append(errors, field.Invalid(field.NewPath("bindAddress"), a.BindAddress, "invalid IP address"))
}
return errors
}

Expand Down
16 changes: 15 additions & 1 deletion pkg/apis/k0s/v1beta1/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ func (s *APISuite) TestValidation() {

s.Run("invalid_api_address", func() {
a := APISpec{
Address: "something.that.is.not.valid//(())",
Address: "something.that.is.not.valid//(())",
BindAddress: "0.0.0.0",
}
a.setDefaults()

Expand All @@ -58,6 +59,7 @@ func (s *APISuite) TestValidation() {

s.Run("invalid_sans_address", func() {
a := APISpec{
BindAddress: "0.0.0.0",
SANs: []string{
"something.that.is.not.valid//(())",
},
Expand All @@ -70,6 +72,18 @@ func (s *APISuite) TestValidation() {
s.ErrorContains(errors[0], `sans[0]: Invalid value: "something.that.is.not.valid//(())": invalid IP address / DNS name`)
}
})

s.T().Run("invalid_api_bind_address", func(t *testing.T) {
a := APISpec{
Address: "1.2.3.4",
BindAddress: "something.that.is.not.valid//(())",
}

errors := a.Validate()
s.NotNil(errors)
s.Len(errors, 1)
s.Contains(errors[0].Error(), "invalid IP address")
})
}

func TestApiSuite(t *testing.T) {
Expand Down
6 changes: 5 additions & 1 deletion pkg/component/controller/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ func (a *APIServer) Start(_ context.Context) error {
"enable-admission-plugins": "NodeRestriction",
}

if a.ClusterConfig.Spec.API.BindAddress != "" {
args["bind-address"] = a.ClusterConfig.Spec.API.BindAddress
}

apiAudiences := []string{"https://kubernetes.default.svc"}

if a.EnableKonnectivity {
Expand Down Expand Up @@ -230,7 +234,7 @@ func (a *APIServer) Ready() 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
}
Expand Down
4 changes: 4 additions & 0 deletions static/_crds/k0s/k0s.k0sproject.io_clusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,10 @@ spec:
address:
description: Address on which to connect to the API server.
type: string
bindAddress:
description: The IP address for the Kubernetes API server to listen
on.
type: string
externalAddress:
description: The loadbalancer address (for k0s controllers running
behind a loadbalancer)
Expand Down

0 comments on commit 4161823

Please sign in to comment.