Skip to content

Commit

Permalink
kubeadm: use actual addresses/ports for WaitForAllControlPlaneComponents
Browse files Browse the repository at this point in the history
By default check the KCM and scheduler on 127.0.0.1:<port> as that is the
defaall --bind-address kubeamd uses for these components.

For kube-apiserver take the value from APIEndpoint.AdvertiseAddress which is
dynamically detected from the host. Unless the user has passed explicitly --advertise-address
as an extra arg.

Read the <port> values for all components from the --secure-port flag
value if needed. Otherwise use defaults.

Use /livez for apiserver and scheduler. Add TODO for KCM to
switch to /livez as well.
  • Loading branch information
neolit123 committed Nov 2, 2024
1 parent 16f9fdc commit b2741f7
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 21 deletions.
54 changes: 41 additions & 13 deletions cmd/kubeadm/app/util/apiclient/wait.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import (

// Waiter is an interface for waiting for criteria in Kubernetes to happen
type Waiter interface {
// WaitForControlPlaneComponents waits for all control plane components to report "ok" on /healthz
// WaitForControlPlaneComponents waits for all control plane components to be ready.
WaitForControlPlaneComponents(cfg *kubeadmapi.ClusterConfiguration) error
// WaitForAPI waits for the API Server's /healthz endpoint to become "ok"
// TODO: remove WaitForAPI once WaitForAllControlPlaneComponents goes GA:
Expand Down Expand Up @@ -84,31 +84,58 @@ type controlPlaneComponent struct {
url string
}

const (
// TODO: switch to /livez once all components support it
// and delete the endpointHealthz constant.
// https://github.com/kubernetes/kubernetes/issues/118158
endpointHealthz = "healthz"
endpointLivez = "livez"
)

// getControlPlaneComponents takes a ClusterConfiguration and returns a slice of
// control plane components and their secure ports.
// control plane components and their health check URLs.
func getControlPlaneComponents(cfg *kubeadmapi.ClusterConfiguration) []controlPlaneComponent {
portArg := "secure-port"
const (
portArg = "secure-port"
addressArg = "bind-address"
defaultAddress = "127.0.0.1"
)

portAPIServer, idx := kubeadmapi.GetArgValue(cfg.APIServer.ExtraArgs, portArg, -1)
if idx == -1 {
portAPIServer = "6443"
portAPIServer = fmt.Sprintf("%d", constants.KubeAPIServerPort)
}
portKCM, idx := kubeadmapi.GetArgValue(cfg.ControllerManager.ExtraArgs, portArg, -1)
if idx == -1 {
portKCM = "10257"
portKCM = fmt.Sprintf("%d", constants.KubeControllerManagerPort)
}
portScheduler, idx := kubeadmapi.GetArgValue(cfg.Scheduler.ExtraArgs, portArg, -1)
if idx == -1 {
portScheduler = "10259"
portScheduler = fmt.Sprintf("%d", constants.KubeSchedulerPort)
}

addressAPIServer, idx := kubeadmapi.GetArgValue(cfg.APIServer.ExtraArgs, addressArg, -1)
if idx == -1 {
addressAPIServer = defaultAddress
}
addressKCM, idx := kubeadmapi.GetArgValue(cfg.ControllerManager.ExtraArgs, addressArg, -1)
if idx == -1 {
addressKCM = defaultAddress
}
urlFormat := "https://127.0.0.1:%s/healthz"
addressScheduler, idx := kubeadmapi.GetArgValue(cfg.Scheduler.ExtraArgs, addressArg, -1)
if idx == -1 {
addressScheduler = defaultAddress
}

urlFormat := "https://%s:%s/%s"
return []controlPlaneComponent{
{name: "kube-apiserver", url: fmt.Sprintf(urlFormat, portAPIServer)},
{name: "kube-controller-manager", url: fmt.Sprintf(urlFormat, portKCM)},
{name: "kube-scheduler", url: fmt.Sprintf(urlFormat, portScheduler)},
{name: "kube-apiserver", url: fmt.Sprintf(urlFormat, addressAPIServer, portAPIServer, endpointLivez)},
{name: "kube-controller-manager", url: fmt.Sprintf(urlFormat, addressKCM, portKCM, endpointHealthz)},
{name: "kube-scheduler", url: fmt.Sprintf(urlFormat, addressScheduler, portScheduler, endpointLivez)},
}
}

// WaitForControlPlaneComponents waits for all control plane components to report "ok" on /healthz
// WaitForControlPlaneComponents waits for all control plane components to report "ok".
func (w *KubeWaiter) WaitForControlPlaneComponents(cfg *kubeadmapi.ClusterConfiguration) error {
fmt.Printf("[control-plane-check] Waiting for healthy control plane components."+
" This can take up to %v\n", w.timeout)
Expand Down Expand Up @@ -136,15 +163,16 @@ func (w *KubeWaiter) WaitForControlPlaneComponents(cfg *kubeadmapi.ClusterConfig
true, func(ctx context.Context) (bool, error) {
resp, err := client.Get(comp.url)
if err != nil {
lastError = errors.WithMessagef(err, "%s /healthz check failed", comp.name)
lastError = errors.WithMessagef(err, "%s check failed at %s", comp.name, comp.url)
return false, nil
}

defer func() {
_ = resp.Body.Close()
}()
if resp.StatusCode != http.StatusOK {
lastError = errors.Errorf("%s /healthz check failed with status: %d", comp.name, resp.StatusCode)
lastError = errors.Errorf("%s check failed at %s with status: %d",
comp.name, comp.url, resp.StatusCode)
return false, nil
}

Expand Down
20 changes: 12 additions & 8 deletions cmd/kubeadm/app/util/apiclient/wait_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ limitations under the License.
package apiclient

import (
"fmt"
"reflect"
"testing"

Expand All @@ -30,39 +31,42 @@ func TestGetControlPlaneComponents(t *testing.T) {
expected []controlPlaneComponent
}{
{
name: "port values from config",
name: "port and addresses from config",
cfg: &kubeadmapi.ClusterConfiguration{
APIServer: kubeadmapi.APIServer{
ControlPlaneComponent: kubeadmapi.ControlPlaneComponent{
ExtraArgs: []kubeadmapi.Arg{
{Name: "secure-port", Value: "1111"},
{Name: "bind-address", Value: "0.0.0.0"},
},
},
},
ControllerManager: kubeadmapi.ControlPlaneComponent{
ExtraArgs: []kubeadmapi.Arg{
{Name: "secure-port", Value: "2222"},
{Name: "bind-address", Value: "0.0.0.0"},
},
},
Scheduler: kubeadmapi.ControlPlaneComponent{
ExtraArgs: []kubeadmapi.Arg{
{Name: "secure-port", Value: "3333"},
{Name: "bind-address", Value: "0.0.0.0"},
},
},
},
expected: []controlPlaneComponent{
{name: "kube-apiserver", url: "https://127.0.0.1:1111/healthz"},
{name: "kube-controller-manager", url: "https://127.0.0.1:2222/healthz"},
{name: "kube-scheduler", url: "https://127.0.0.1:3333/healthz"},
{name: "kube-apiserver", url: fmt.Sprintf("https://0.0.0.0:1111/%s", endpointLivez)},
{name: "kube-controller-manager", url: fmt.Sprintf("https://0.0.0.0:2222/%s", endpointHealthz)},
{name: "kube-scheduler", url: fmt.Sprintf("https://0.0.0.0:3333/%s", endpointLivez)},
},
},
{
name: "default ports",
name: "default ports and addresses",
cfg: &kubeadmapi.ClusterConfiguration{},
expected: []controlPlaneComponent{
{name: "kube-apiserver", url: "https://127.0.0.1:6443/healthz"},
{name: "kube-controller-manager", url: "https://127.0.0.1:10257/healthz"},
{name: "kube-scheduler", url: "https://127.0.0.1:10259/healthz"},
{name: "kube-apiserver", url: fmt.Sprintf("https://127.0.0.1:6443/%s", endpointLivez)},
{name: "kube-controller-manager", url: fmt.Sprintf("https://127.0.0.1:10257/%s", endpointHealthz)},
{name: "kube-scheduler", url: fmt.Sprintf("https://127.0.0.1:10259/%s", endpointLivez)},
},
},
}
Expand Down

0 comments on commit b2741f7

Please sign in to comment.