Skip to content

Commit

Permalink
replace BindAddress by Address and OnlyBindToAddress
Browse files Browse the repository at this point in the history
Signed-off-by: Phillip Schichtel <phillip@schich.tel>
  • Loading branch information
pschichtel committed Sep 1, 2024
1 parent 7ac920b commit 96fb12d
Show file tree
Hide file tree
Showing 8 changed files with 37 additions and 54 deletions.
4 changes: 3 additions & 1 deletion cmd/controller/certificates.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"net"
"os"
"path/filepath"
"strconv"

"github.com/k0sproject/k0s/internal/pkg/file"
"github.com/k0sproject/k0s/pkg/apis/k0s/v1beta1"
Expand Down Expand Up @@ -64,7 +65,8 @@ 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://%s:%d", c.ClusterSpec.API.APIServerAddress(), c.ClusterSpec.API.Port)
apiAddress := net.JoinHostPort(c.ClusterSpec.API.Address, strconv.Itoa(c.ClusterSpec.API.Port))
kubeConfigAPIUrl := fmt.Sprintf("https://%s", apiAddress)
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: 0 additions & 1 deletion cmd/controller/controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,6 @@ 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
19 changes: 9 additions & 10 deletions docs/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@ 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,15 +112,15 @@ 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. |
| `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) |
| `k0sApiPort`¹ | Custom port for k0s-api server to listen on (default: 9443) |
| Element | Description |
|---------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `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. |
| `onlyBindToAddress` | Whether to bind only to the IP address given by the `address` option, instead of binding to all addresses. |
| `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. |
| `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) |
| `k0sApiPort`¹ | Custom port for k0s-api server to listen on (default: 9443) |
¹ If `port` and `k0sApiPort` are used with the `externalAddress` element, the loadbalancer serving at `externalAddress` must listen on the same ports.
Expand Down
3 changes: 2 additions & 1 deletion inttest/bind-address/bind_address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ func (s *suite) TestCustomizedBindAddress() {
API: func() *v1beta1.APISpec {
apiSpec := v1beta1.DefaultAPISpec()
apiSpec.Address = s.GetIPAddress(s.ControllerNode(i))
apiSpec.OnlyToBindAddress = true
return apiSpec
}(),
WorkerProfiles: v1beta1.WorkerProfiles{
Expand Down Expand Up @@ -172,7 +173,7 @@ func TestCustomizedBindAddressSuite(t *testing.T) {
s := suite{
common.BootlooseSuite{
ControllerCount: 3,
WorkerCount: 2,
WorkerCount: 1,
},
}
testifysuite.Run(t, &s)
Expand Down
31 changes: 12 additions & 19 deletions pkg/apis/k0s/v1beta1/api.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ 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.
// Whether to only bind to the IP given by the address option.
// +optional
BindAddress string `json:"bindAddress,omitempty"`
OnlyToBindAddress bool `json:"onlyBindToAddress,omitempty"`

// The loadbalancer address (for k0s controllers running behind a loadbalancer)
ExternalAddress string `json:"externalAddress,omitempty"`
Expand Down Expand Up @@ -97,9 +97,6 @@ func (a *APISpec) K0sControlPlaneAPIAddress() string {

func (a *APISpec) getExternalURIForPort(port int) string {
addr := a.Address
if a.BindAddress != "" {
addr = a.BindAddress
}
if a.ExternalAddress != "" {
addr = a.ExternalAddress
}
Expand All @@ -109,21 +106,10 @@ 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 {
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 All @@ -132,6 +118,10 @@ func (a *APISpec) Sans() []string {
return stringslice.Unique(sans)
}

func isAnyAddress(address string) bool {
return address == "0.0.0.0" || address == "::"
}

// Validate validates APISpec struct
func (a *APISpec) Validate() []error {
if a == nil {
Expand All @@ -143,6 +133,9 @@ func (a *APISpec) Validate() []error {
if !govalidator.IsIP(a.Address) {
errors = append(errors, field.Invalid(field.NewPath("address"), a.Address, "invalid IP address"))
}
if isAnyAddress(a.Address) {
errors = append(errors, field.Invalid(field.NewPath("address"), a.Address, "invalid INADDR_ANY"))
}

validateIPAddressOrDNSName := func(path *field.Path, san string) {
if govalidator.IsIP(san) || govalidator.IsDNSName(san) {
Expand All @@ -153,6 +146,9 @@ func (a *APISpec) Validate() []error {

if a.ExternalAddress != "" {
validateIPAddressOrDNSName(field.NewPath("externalAddress"), a.ExternalAddress)
if isAnyAddress(a.ExternalAddress) {
errors = append(errors, field.Invalid(field.NewPath("externalAddress"), a.Address, "invalid INADDR_ANY"))
}
}

for _, msg := range validation.IsValidPortNum(a.K0sAPIPort) {
Expand All @@ -168,9 +164,6 @@ 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: 1 addition & 15 deletions pkg/apis/k0s/v1beta1/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,7 @@ func (s *APISuite) TestValidation() {

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

Expand All @@ -59,7 +58,6 @@ 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 @@ -72,18 +70,6 @@ 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
9 changes: 6 additions & 3 deletions pkg/component/controller/apiserver.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,13 @@ import (
"crypto/x509"
"fmt"
"io"
"net"
"net/http"
"net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"

"github.com/sirupsen/logrus"
Expand Down Expand Up @@ -125,8 +127,8 @@ 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
if a.ClusterConfig.Spec.API.OnlyToBindAddress {
args["bind-address"] = a.ClusterConfig.Spec.API.Address
}

apiAudiences := []string{"https://kubernetes.default.svc"}
Expand Down Expand Up @@ -234,7 +236,8 @@ func (a *APIServer) Ready() error {
TLSClientConfig: tlsConfig,
}
client := &http.Client{Transport: tr}
resp, err := client.Get(fmt.Sprintf("https://%s:%d/readyz?verbose", a.ClusterConfig.Spec.API.APIServerAddress(), a.ClusterConfig.Spec.API.Port))
apiAddress := net.JoinHostPort(a.ClusterConfig.Spec.API.Address, strconv.Itoa(a.ClusterConfig.Spec.API.Port))
resp, err := client.Get(fmt.Sprintf("https://%s/readyz?verbose", apiAddress))
if err != nil {
return err
}
Expand Down
8 changes: 4 additions & 4 deletions static/_crds/k0s/k0s.k0sproject.io_clusterconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -45,10 +45,6 @@ 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 All @@ -66,6 +62,10 @@ spec:
maximum: 65535
minimum: 1
type: integer
onlyBindToAddress:
description: Whether to only bind to the IP given by the address
option.
type: boolean
port:
default: 6443
description: 'Custom port for kube-api server to listen on (default:
Expand Down

0 comments on commit 96fb12d

Please sign in to comment.