mirror of https://github.com/k3s-io/k3s
kubeadm: add configuration option to not taint master
Although tainting the master is normally a good and proper thing to do in some
situations (docker for mac in our case, but I suppose minikube and such as
well) having a single host configuration is desirable.
In linuxkit we have a [workaround](443e47c408/projects/kubernetes/kubernetes/kubeadm-init.sh (L19...L22)
)
to remove the taint after initialisation. With the change here we could simply
populate /etc/kubeadm/kubeadm.yaml` with `noTaintMaster: true` instead and have
it never be tainted in the first place.
I have only added this to the config file and not to the CLI since AIUI the
latter is somewhat deprecated.
The code also arranges to _remove_ an existing taint if it is unwanted. I'm
unsure if this behaviour is correct or desirable, I think a reasonable argument
could be made for leaving an existing taint in place too.
Signed-off-by: Ian Campbell <ijc@docker.com>
pull/6/head
parent
117780b908
commit
a4e00ff3d8
|
@ -50,6 +50,10 @@ type MasterConfiguration struct {
|
|||
// If not specified, defaults to Node and RBAC, meaning both the node
|
||||
// authorizer and RBAC are enabled.
|
||||
AuthorizationModes []string
|
||||
// NoTaintMaster will, if set, suppress the tainting of the
|
||||
// master node allowing workloads to be run on it (e.g. in
|
||||
// single node configurations).
|
||||
NoTaintMaster bool
|
||||
|
||||
// Mark the controller and api server pods as privileged as some cloud
|
||||
// controllers like openstack need escalated privileges under some conditions
|
||||
|
|
|
@ -50,6 +50,10 @@ type MasterConfiguration struct {
|
|||
// If not specified, defaults to Node and RBAC, meaning both the node
|
||||
// authorizer and RBAC are enabled.
|
||||
AuthorizationModes []string `json:"authorizationModes,omitempty"`
|
||||
// NoTaintMaster will, if set, suppress the tainting of the
|
||||
// master node allowing workloads to be run on it (e.g. in
|
||||
// single node configurations).
|
||||
NoTaintMaster bool `json:"noTaintMaster,omitempty"`
|
||||
|
||||
// Mark the controller and api server pods as privileged as some cloud
|
||||
// controllers like openstack need escalated privileges under some conditions
|
||||
|
|
|
@ -202,6 +202,7 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in
|
|||
out.CloudProvider = in.CloudProvider
|
||||
out.NodeName = in.NodeName
|
||||
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
|
||||
out.NoTaintMaster = in.NoTaintMaster
|
||||
out.PrivilegedPods = in.PrivilegedPods
|
||||
out.Token = in.Token
|
||||
out.TokenTTL = (*v1.Duration)(unsafe.Pointer(in.TokenTTL))
|
||||
|
@ -244,6 +245,7 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in
|
|||
out.CloudProvider = in.CloudProvider
|
||||
out.NodeName = in.NodeName
|
||||
out.AuthorizationModes = *(*[]string)(unsafe.Pointer(&in.AuthorizationModes))
|
||||
out.NoTaintMaster = in.NoTaintMaster
|
||||
out.PrivilegedPods = in.PrivilegedPods
|
||||
out.Token = in.Token
|
||||
out.TokenTTL = (*v1.Duration)(unsafe.Pointer(in.TokenTTL))
|
||||
|
|
|
@ -388,7 +388,7 @@ func (i *Init) Run(out io.Writer) error {
|
|||
}
|
||||
|
||||
// PHASE 4: Mark the master with the right label/taint
|
||||
if err := markmasterphase.MarkMaster(client, i.cfg.NodeName); err != nil {
|
||||
if err := markmasterphase.MarkMaster(client, i.cfg.NodeName, !i.cfg.NoTaintMaster); err != nil {
|
||||
return fmt.Errorf("error marking master: %v", err)
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ func NewCmdMarkMaster() *cobra.Command {
|
|||
client, err := kubeconfigutil.ClientSetFromFile(kubeConfigFile)
|
||||
kubeadmutil.CheckErr(err)
|
||||
|
||||
err = markmasterphase.MarkMaster(client, internalcfg.NodeName)
|
||||
err = markmasterphase.MarkMaster(client, internalcfg.NodeName, !internalcfg.NoTaintMaster)
|
||||
kubeadmutil.CheckErr(err)
|
||||
},
|
||||
}
|
||||
|
|
|
@ -32,9 +32,13 @@ import (
|
|||
)
|
||||
|
||||
// MarkMaster taints the master and sets the master label
|
||||
func MarkMaster(client clientset.Interface, masterName string) error {
|
||||
func MarkMaster(client clientset.Interface, masterName string, taint bool) error {
|
||||
|
||||
fmt.Printf("[markmaster] Will mark node %s as master by adding a label and a taint\n", masterName)
|
||||
if taint {
|
||||
fmt.Printf("[markmaster] Will mark node %s as master by adding a label and a taint\n", masterName)
|
||||
} else {
|
||||
fmt.Printf("[markmaster] Will mark node %s as master by adding a label\n", masterName)
|
||||
}
|
||||
|
||||
// Loop on every falsy return. Return with an error if raised. Exit successfully if true is returned.
|
||||
return wait.Poll(kubeadmconstants.APICallRetryInterval, kubeadmconstants.MarkMasterTimeout, func() (bool, error) {
|
||||
|
@ -56,7 +60,7 @@ func MarkMaster(client clientset.Interface, masterName string) error {
|
|||
}
|
||||
|
||||
// The master node should be tainted and labelled accordingly
|
||||
markMasterNode(n)
|
||||
markMasterNode(n, taint)
|
||||
|
||||
newData, err := json.Marshal(n)
|
||||
if err != nil {
|
||||
|
@ -76,15 +80,23 @@ func MarkMaster(client clientset.Interface, masterName string) error {
|
|||
return false, err
|
||||
}
|
||||
|
||||
fmt.Printf("[markmaster] Master %s tainted and labelled with key/value: %s=%q\n", masterName, kubeadmconstants.LabelNodeRoleMaster, "")
|
||||
if taint {
|
||||
fmt.Printf("[markmaster] Master %s tainted and labelled with key/value: %s=%q\n", masterName, kubeadmconstants.LabelNodeRoleMaster, "")
|
||||
} else {
|
||||
fmt.Printf("[markmaster] Master %s labelled with key/value: %s=%q\n", masterName, kubeadmconstants.LabelNodeRoleMaster, "")
|
||||
}
|
||||
|
||||
return true, nil
|
||||
})
|
||||
}
|
||||
|
||||
func markMasterNode(n *v1.Node) {
|
||||
func markMasterNode(n *v1.Node, taint bool) {
|
||||
n.ObjectMeta.Labels[kubeadmconstants.LabelNodeRoleMaster] = ""
|
||||
addTaintIfNotExists(n, kubeadmconstants.MasterTaint)
|
||||
if taint {
|
||||
addTaintIfNotExists(n, kubeadmconstants.MasterTaint)
|
||||
} else {
|
||||
delTaintIfExists(n, kubeadmconstants.MasterTaint)
|
||||
}
|
||||
}
|
||||
|
||||
func addTaintIfNotExists(n *v1.Node, t v1.Taint) {
|
||||
|
@ -96,3 +108,14 @@ func addTaintIfNotExists(n *v1.Node, t v1.Taint) {
|
|||
|
||||
n.Spec.Taints = append(n.Spec.Taints, t)
|
||||
}
|
||||
|
||||
func delTaintIfExists(n *v1.Node, t v1.Taint) {
|
||||
var taints []v1.Taint
|
||||
for _, taint := range n.Spec.Taints {
|
||||
if taint == t {
|
||||
continue
|
||||
}
|
||||
taints = append(taints, t)
|
||||
}
|
||||
n.Spec.Taints = taints
|
||||
}
|
||||
|
|
|
@ -43,32 +43,51 @@ func TestMarkMaster(t *testing.T) {
|
|||
name string
|
||||
existingLabel string
|
||||
existingTaint *v1.Taint
|
||||
wantTaint bool
|
||||
expectedPatch string
|
||||
}{
|
||||
{
|
||||
"master label and taint missing",
|
||||
"",
|
||||
nil,
|
||||
true,
|
||||
"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}},\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}",
|
||||
},
|
||||
{
|
||||
"master label and taint missing but taint not wanted",
|
||||
"",
|
||||
nil,
|
||||
false,
|
||||
"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}",
|
||||
},
|
||||
{
|
||||
"master label missing",
|
||||
"",
|
||||
&kubeadmconstants.MasterTaint,
|
||||
true,
|
||||
"{\"metadata\":{\"labels\":{\"node-role.kubernetes.io/master\":\"\"}}}",
|
||||
},
|
||||
{
|
||||
"master taint missing",
|
||||
kubeadmconstants.LabelNodeRoleMaster,
|
||||
nil,
|
||||
true,
|
||||
"{\"spec\":{\"taints\":[{\"effect\":\"NoSchedule\",\"key\":\"node-role.kubernetes.io/master\"}]}}",
|
||||
},
|
||||
{
|
||||
"nothing missing",
|
||||
kubeadmconstants.LabelNodeRoleMaster,
|
||||
&kubeadmconstants.MasterTaint,
|
||||
true,
|
||||
"{}",
|
||||
},
|
||||
{
|
||||
"nothing missing but taint unwanted",
|
||||
kubeadmconstants.LabelNodeRoleMaster,
|
||||
&kubeadmconstants.MasterTaint,
|
||||
false,
|
||||
"{\"spec\":{\"taints\":null}}",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
|
@ -125,7 +144,7 @@ func TestMarkMaster(t *testing.T) {
|
|||
t.Fatalf("MarkMaster(%s): unexpected error building clientset: %v", tc.name, err)
|
||||
}
|
||||
|
||||
err = MarkMaster(cs, hostname)
|
||||
err = MarkMaster(cs, hostname, tc.wantTaint)
|
||||
if err != nil {
|
||||
t.Errorf("MarkMaster(%s) returned unexpected error: %v", tc.name, err)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue