Merge pull request #172 from aleksandra-malinowska/add-taints-to-node-templates
add taints to GCE node template
This commit is contained in:
commit
f17c67ef81
|
|
@ -26,7 +26,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"gopkg.in/gcfg.v1"
|
gcfg "gopkg.in/gcfg.v1"
|
||||||
|
|
||||||
"github.com/golang/glog"
|
"github.com/golang/glog"
|
||||||
"golang.org/x/oauth2"
|
"golang.org/x/oauth2"
|
||||||
|
|
@ -327,7 +327,7 @@ func (m *GceManager) buildNodeFromTemplate(mig *Mig, template *gce.InstanceTempl
|
||||||
// TODO: use proper allocatable!!
|
// TODO: use proper allocatable!!
|
||||||
node.Status.Allocatable = node.Status.Capacity
|
node.Status.Allocatable = node.Status.Capacity
|
||||||
|
|
||||||
// KubeEnvLabels
|
// KubeEnv labels & taints
|
||||||
if template.Properties.Metadata == nil {
|
if template.Properties.Metadata == nil {
|
||||||
return nil, fmt.Errorf("instance template %s has no metadata", template.Name)
|
return nil, fmt.Errorf("instance template %s has no metadata", template.Name)
|
||||||
}
|
}
|
||||||
|
|
@ -336,11 +336,18 @@ func (m *GceManager) buildNodeFromTemplate(mig *Mig, template *gce.InstanceTempl
|
||||||
if item.Value == nil {
|
if item.Value == nil {
|
||||||
return nil, fmt.Errorf("no kube-env content in metadata")
|
return nil, fmt.Errorf("no kube-env content in metadata")
|
||||||
}
|
}
|
||||||
|
// Extract labels
|
||||||
kubeEnvLabels, err := extractLabelsFromKubeEnv(*item.Value)
|
kubeEnvLabels, err := extractLabelsFromKubeEnv(*item.Value)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
node.Labels = cloudprovider.JoinStringMaps(node.Labels, kubeEnvLabels)
|
node.Labels = cloudprovider.JoinStringMaps(node.Labels, kubeEnvLabels)
|
||||||
|
// Extract taints
|
||||||
|
kubeEnvTaints, err := extractTaintsFromKubeEnv(*item.Value)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
node.Spec.Taints = append(node.Spec.Taints, kubeEnvTaints...)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// GenericLabels
|
// GenericLabels
|
||||||
|
|
@ -390,6 +397,18 @@ func parseCustomMachineType(machineType string) (cpu, mem int64, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func extractLabelsFromKubeEnv(kubeEnv string) (map[string]string, error) {
|
func extractLabelsFromKubeEnv(kubeEnv string) (map[string]string, error) {
|
||||||
|
return extractFromKubeEnv(kubeEnv, "NODE_LABELS")
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractTaintsFromKubeEnv(kubeEnv string) ([]apiv1.Taint, error) {
|
||||||
|
taintMap, err := extractFromKubeEnv(kubeEnv, "NODE_TAINTS")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return buildTaints(taintMap)
|
||||||
|
}
|
||||||
|
|
||||||
|
func extractFromKubeEnv(kubeEnv, resource string) (map[string]string, error) {
|
||||||
result := make(map[string]string)
|
result := make(map[string]string)
|
||||||
|
|
||||||
for line, env := range strings.Split(kubeEnv, "\n") {
|
for line, env := range strings.Split(kubeEnv, "\n") {
|
||||||
|
|
@ -403,15 +422,31 @@ func extractLabelsFromKubeEnv(kubeEnv string) (map[string]string, error) {
|
||||||
}
|
}
|
||||||
key := strings.Trim(items[0], " ")
|
key := strings.Trim(items[0], " ")
|
||||||
value := strings.Trim(items[1], " \"'")
|
value := strings.Trim(items[1], " \"'")
|
||||||
if key == "NODE_LABELS" {
|
if key == resource {
|
||||||
for _, label := range strings.Split(value, ",") {
|
for _, val := range strings.Split(value, ",") {
|
||||||
labelItems := strings.SplitN(label, "=", 2)
|
valItems := strings.SplitN(val, "=", 2)
|
||||||
if len(labelItems) != 2 {
|
if len(valItems) != 2 {
|
||||||
return nil, fmt.Errorf("error while parsing label: %s", label)
|
return nil, fmt.Errorf("error while parsing kube env value: %s", val)
|
||||||
}
|
}
|
||||||
result[labelItems[0]] = labelItems[1]
|
result[valItems[0]] = valItems[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result, nil
|
return result, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func buildTaints(kubeEnvTaints map[string]string) ([]apiv1.Taint, error) {
|
||||||
|
taints := make([]apiv1.Taint, 0)
|
||||||
|
for key, value := range kubeEnvTaints {
|
||||||
|
values := strings.SplitN(value, ":", 2)
|
||||||
|
if len(values) != 2 {
|
||||||
|
return nil, fmt.Errorf("error while parsing node taint value and effect: %s", value)
|
||||||
|
}
|
||||||
|
taints = append(taints, apiv1.Taint{
|
||||||
|
Key: key,
|
||||||
|
Value: values[0],
|
||||||
|
Effect: apiv1.TaintEffect(values[1]),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return taints, nil
|
||||||
|
}
|
||||||
|
|
|
||||||
|
|
@ -20,6 +20,7 @@ import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
"github.com/stretchr/testify/assert"
|
||||||
|
apiv1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
"k8s.io/autoscaler/cluster-autoscaler/cloudprovider"
|
||||||
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
kubeletapis "k8s.io/kubernetes/pkg/kubelet/apis"
|
||||||
)
|
)
|
||||||
|
|
@ -53,6 +54,45 @@ func TestExtractLabelsFromKubeEnv(t *testing.T) {
|
||||||
assert.Equal(t, "true", labels["cloud.google.com/gke-preemptible"])
|
assert.Equal(t, "true", labels["cloud.google.com/gke-preemptible"])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestExtractTaintsFromKubeEnv(t *testing.T) {
|
||||||
|
kubeenv := "ENABLE_NODE_PROBLEM_DETECTOR: 'daemonset'\n" +
|
||||||
|
"NODE_LABELS: a=b,c=d,cloud.google.com/gke-nodepool=pool-3,cloud.google.com/gke-preemptible=true\n" +
|
||||||
|
"DNS_SERVER_IP: '10.0.0.10'\n" +
|
||||||
|
"NODE_TAINTS: 'dedicated=ml:NoSchedule,test=dev:PreferNoSchedule,a=b:c'\n"
|
||||||
|
|
||||||
|
expectedTaints := []apiv1.Taint{
|
||||||
|
{
|
||||||
|
Key: "dedicated",
|
||||||
|
Value: "ml",
|
||||||
|
Effect: apiv1.TaintEffectNoSchedule,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "test",
|
||||||
|
Value: "dev",
|
||||||
|
Effect: apiv1.TaintEffectPreferNoSchedule,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Key: "a",
|
||||||
|
Value: "b",
|
||||||
|
Effect: apiv1.TaintEffect("c"),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
taints, err := extractTaintsFromKubeEnv(kubeenv)
|
||||||
|
assert.Nil(t, err)
|
||||||
|
assert.Equal(t, 3, len(taints))
|
||||||
|
assert.Equal(t, makeTaintSet(expectedTaints), makeTaintSet(taints))
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func makeTaintSet(taints []apiv1.Taint) map[apiv1.Taint]bool {
|
||||||
|
set := make(map[apiv1.Taint]bool)
|
||||||
|
for _, taint := range taints {
|
||||||
|
set[taint] = true
|
||||||
|
}
|
||||||
|
return set
|
||||||
|
}
|
||||||
|
|
||||||
func TestParseCustomMachineType(t *testing.T) {
|
func TestParseCustomMachineType(t *testing.T) {
|
||||||
cpu, mem, err := parseCustomMachineType("custom-2-2816")
|
cpu, mem, err := parseCustomMachineType("custom-2-2816")
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
|
|
|
||||||
|
|
@ -293,7 +293,7 @@ func sanitizeTemplateNode(node *apiv1.Node, nodeGroup string) (*apiv1.Node, erro
|
||||||
return newNode, nil
|
return newNode, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removes unregisterd nodes if needed. Returns true if anything was removed and error if such occurred.
|
// Removes unregistered nodes if needed. Returns true if anything was removed and error if such occurred.
|
||||||
func removeOldUnregisteredNodes(unregisteredNodes []clusterstate.UnregisteredNode, context *AutoscalingContext,
|
func removeOldUnregisteredNodes(unregisteredNodes []clusterstate.UnregisteredNode, context *AutoscalingContext,
|
||||||
currentTime time.Time) (bool, error) {
|
currentTime time.Time) (bool, error) {
|
||||||
removedAny := false
|
removedAny := false
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue