improve kube-vip cp lb auto-enable
parent
3614a9fd0e
commit
d6c612fcba
|
@ -947,8 +947,9 @@ func (k *Bootstrapper) UpdateNode(cfg config.ClusterConfig, n config.Node, r cru
|
||||||
if n.ControlPlane {
|
if n.ControlPlane {
|
||||||
// for primary control-plane node only, generate kubeadm config based on current params
|
// for primary control-plane node only, generate kubeadm config based on current params
|
||||||
// on node restart, it will be checked against later if anything needs changing
|
// on node restart, it will be checked against later if anything needs changing
|
||||||
|
var kubeadmCfg []byte
|
||||||
if config.IsPrimaryControlPlane(cfg, n) {
|
if config.IsPrimaryControlPlane(cfg, n) {
|
||||||
kubeadmCfg, err := bsutil.GenerateKubeadmYAML(cfg, n, r)
|
kubeadmCfg, err = bsutil.GenerateKubeadmYAML(cfg, n, r)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return errors.Wrap(err, "generating kubeadm cfg")
|
return errors.Wrap(err, "generating kubeadm cfg")
|
||||||
}
|
}
|
||||||
|
@ -964,7 +965,7 @@ func (k *Bootstrapper) UpdateNode(cfg config.ClusterConfig, n config.Node, r cru
|
||||||
return errors.Wrapf(err, "parsing kubernetes version %q", cfg.KubernetesConfig.KubernetesVersion)
|
return errors.Wrapf(err, "parsing kubernetes version %q", cfg.KubernetesConfig.KubernetesVersion)
|
||||||
}
|
}
|
||||||
workaround := kv.GTE(semver.Version{Major: 1, Minor: 29}) && config.IsPrimaryControlPlane(cfg, n) && len(config.ControlPlanes(cfg)) == 1
|
workaround := kv.GTE(semver.Version{Major: 1, Minor: 29}) && config.IsPrimaryControlPlane(cfg, n) && len(config.ControlPlanes(cfg)) == 1
|
||||||
kubevipCfg, err := kubevip.Configure(cfg, workaround)
|
kubevipCfg, err := kubevip.Configure(cfg, k.c, kubeadmCfg, workaround)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
klog.Errorf("couldn't generate kube-vip config, this might cause issues (will continue): %v", err)
|
klog.Errorf("couldn't generate kube-vip config, this might cause issues (will continue): %v", err)
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -19,10 +19,14 @@ package kubevip
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"html/template"
|
"html/template"
|
||||||
|
"os/exec"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"k8s.io/klog/v2"
|
"k8s.io/klog/v2"
|
||||||
|
"k8s.io/minikube/pkg/minikube/command"
|
||||||
"k8s.io/minikube/pkg/minikube/config"
|
"k8s.io/minikube/pkg/minikube/config"
|
||||||
|
"k8s.io/minikube/pkg/minikube/driver"
|
||||||
)
|
)
|
||||||
|
|
||||||
const Manifest = "kube-vip.yaml"
|
const Manifest = "kube-vip.yaml"
|
||||||
|
@ -72,10 +76,12 @@ spec:
|
||||||
value: {{ .VIP }}
|
value: {{ .VIP }}
|
||||||
- name: prometheus_server
|
- name: prometheus_server
|
||||||
value: :2112
|
value: :2112
|
||||||
|
{{- if .EnableLB }}
|
||||||
- name : lb_enable
|
- name : lb_enable
|
||||||
value: "true"
|
value: "true"
|
||||||
- name: lb_port
|
- name: lb_port
|
||||||
value: "{{ .Port }}"
|
value: "{{ .Port }}"
|
||||||
|
{{- end}}
|
||||||
image: ghcr.io/kube-vip/kube-vip:v0.7.1
|
image: ghcr.io/kube-vip/kube-vip:v0.7.1
|
||||||
imagePullPolicy: IfNotPresent
|
imagePullPolicy: IfNotPresent
|
||||||
name: kube-vip
|
name: kube-vip
|
||||||
|
@ -101,17 +107,19 @@ status: {}
|
||||||
`))
|
`))
|
||||||
|
|
||||||
// Configure takes last client ip address in cluster nodes network subnet as vip address and generates kube-vip.yaml file.
|
// Configure takes last client ip address in cluster nodes network subnet as vip address and generates kube-vip.yaml file.
|
||||||
func Configure(cc config.ClusterConfig, workaround bool) ([]byte, error) {
|
func Configure(cc config.ClusterConfig, r command.Runner, kubeadmCfg []byte, workaround bool) ([]byte, error) {
|
||||||
klog.Info("generating kube-vip config ...")
|
klog.Info("generating kube-vip config ...")
|
||||||
|
|
||||||
params := struct {
|
params := struct {
|
||||||
VIP string
|
VIP string
|
||||||
Port int
|
Port int
|
||||||
AdminConf string
|
AdminConf string
|
||||||
|
EnableLB bool
|
||||||
}{
|
}{
|
||||||
VIP: cc.KubernetesConfig.APIServerHAVIP,
|
VIP: cc.KubernetesConfig.APIServerHAVIP,
|
||||||
Port: cc.APIServerPort,
|
Port: cc.APIServerPort,
|
||||||
AdminConf: "/etc/kubernetes/admin.conf",
|
AdminConf: "/etc/kubernetes/admin.conf",
|
||||||
|
EnableLB: enableCPLB(cc, r, kubeadmCfg),
|
||||||
}
|
}
|
||||||
if workaround {
|
if workaround {
|
||||||
params.AdminConf = "/etc/kubernetes/super-admin.conf"
|
params.AdminConf = "/etc/kubernetes/super-admin.conf"
|
||||||
|
@ -126,3 +134,25 @@ func Configure(cc config.ClusterConfig, workaround bool) ([]byte, error) {
|
||||||
|
|
||||||
return b.Bytes(), nil
|
return b.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// enableCPLB auto-enables control-plane load-balancing, if possible - currently only possible with ipvs.
|
||||||
|
// ref: https://kube-vip.io/docs/about/architecture/?query=ipvs#control-plane-load-balancing
|
||||||
|
func enableCPLB(cc config.ClusterConfig, r command.Runner, kubeadmCfg []byte) bool {
|
||||||
|
// note known issue: "service lb with ipvs mode won't work with kubeproxy that is configured with ipvs mode"
|
||||||
|
// ref: https://kube-vip.io/docs/about/architecture/?query=ipvs#known-issues
|
||||||
|
// so we only want to enable control-plane load-balancing if kube-proxy mode is not set to ipvs
|
||||||
|
// ref: https://kubernetes.io/docs/reference/networking/virtual-ips/#proxy-mode-ipvs
|
||||||
|
if ipvs := strings.EqualFold(string(kubeadmCfg), "mode: ipvs"); ipvs {
|
||||||
|
klog.Info("giving up enabling control-plane load-balancing as kube-proxy mode appears to be set to ipvs")
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
klog.Info("enabling control-plane load-balancing as kube-proxy mode appears not be set to ipvs")
|
||||||
|
// for vm driver, also ensure required ipvs kernel modules are loaded to enable kube-vip's control-plane load-balancing feature
|
||||||
|
// ref: https://github.com/kubernetes/kubernetes/blob/f90461c43e881d320b78d48793db10c110d488d1/pkg/proxy/ipvs/README.md?plain=1#L257-L269
|
||||||
|
if driver.IsVM(cc.Driver) {
|
||||||
|
if _, err := r.RunCmd(exec.Command("sudo", "sh", "-c", "modprobe --all ip_vs ip_vs_rr ip_vs_wrr ip_vs_sh nf_conntrack")); err != nil {
|
||||||
|
klog.Errorf("unable to load ipvs kernel modules: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
|
@ -35,8 +35,8 @@ import (
|
||||||
"k8s.io/minikube/pkg/util/retry"
|
"k8s.io/minikube/pkg/util/retry"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TestMutliControlPlane tests all ha (multi-control plane) cluster functionality
|
// TestMultiControlPlane tests all ha (multi-control plane) cluster functionality
|
||||||
func TestMutliControlPlane(t *testing.T) {
|
func TestMultiControlPlane(t *testing.T) {
|
||||||
if NoneDriver() {
|
if NoneDriver() {
|
||||||
t.Skip("none driver does not support multinode/ha(multi-control plane) cluster")
|
t.Skip("none driver does not support multinode/ha(multi-control plane) cluster")
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue