Merge pull request #1812 from robinpercy/ig-taints

Adding taints property to IG Spec.
This commit is contained in:
Justin Santa Barbara 2017-03-27 10:06:12 -04:00 committed by GitHub
commit 58db07050f
22 changed files with 297 additions and 53 deletions

View File

@ -354,6 +354,7 @@ func RunCreateCluster(f *util.Factory, out io.Writer, c *CreateClusterOptions) e
g := &api.InstanceGroup{} g := &api.InstanceGroup{}
g.Spec.Role = api.InstanceGroupRoleMaster g.Spec.Role = api.InstanceGroupRoleMaster
g.Spec.Taints = []string{api.TaintNoScheduleMaster}
g.Spec.Subnets = []string{subnet.Name} g.Spec.Subnets = []string{subnet.Name}
g.Spec.MinSize = fi.Int32(1) g.Spec.MinSize = fi.Int32(1)
g.Spec.MaxSize = fi.Int32(1) g.Spec.MaxSize = fi.Int32(1)

View File

@ -131,6 +131,27 @@ So the procedure is:
* Rolling-update, only if you want to apply changes immediately: `kops rolling-update cluster` * Rolling-update, only if you want to apply changes immediately: `kops rolling-update cluster`
## Adding Taints to an Instance Group
If you're running Kubernetes 1.6.0 or later, you can also control taints in the InstanceGroup.
The taints property takes a list of strings. The following example would add two taints to an IG,
using the same `edit` -> `update` -> `rolling-update` process as above.
```
metadata:
creationTimestamp: "2016-07-10T15:47:14Z"
name: nodes
spec:
machineType: m3.medium
maxSize: 3
minSize: 3
role: Node
taints:
- dedicated=gpu:NoSchedule
- team=search:PreferNoSchedule
```
## Resizing the master ## Resizing the master
(This procedure should be pretty familiar by now!) (This procedure should be pretty familiar by now!)

View File

@ -314,6 +314,9 @@ type KubeletConfigSpec struct {
// The full path of the directory in which to search for additional third party volume plugins // The full path of the directory in which to search for additional third party volume plugins
VolumePluginDirectory string `json:"volumePluginDirectory,omitempty" flag:"volume-plugin-dir"` VolumePluginDirectory string `json:"volumePluginDirectory,omitempty" flag:"volume-plugin-dir"`
// Taints to add when registering a node in the cluster
Taints []string `json:"taints,omitempty" flag:"register-with-taints"`
} }
type KubeProxyConfig struct { type KubeProxyConfig struct {

View File

@ -22,9 +22,11 @@ import (
"github.com/golang/glog" "github.com/golang/glog"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/util/validation/field" "k8s.io/apimachinery/pkg/util/validation/field"
"k8s.io/kops/pkg/apis/kops/util"
) )
const LabelClusterName = "kops.k8s.io/cluster" const LabelClusterName = "kops.k8s.io/cluster"
const TaintNoScheduleMaster = "dedicated=master:NoSchedule"
// InstanceGroup represents a group of instances (either nodes or masters) with the same configuration // InstanceGroup represents a group of instances (either nodes or masters) with the same configuration
type InstanceGroup struct { type InstanceGroup struct {
@ -92,6 +94,9 @@ type InstanceGroupSpec struct {
// Kubelet overrides kubelet config from the ClusterSpec // Kubelet overrides kubelet config from the ClusterSpec
Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"` Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"`
// Taints indicates the kubernetes taints for nodes in this group
Taints []string `json:"taints,omitempty"`
} }
// PerformAssignmentsInstanceGroups populates InstanceGroups with default values // PerformAssignmentsInstanceGroups populates InstanceGroups with default values
@ -171,6 +176,11 @@ func (g *InstanceGroup) CrossValidate(cluster *Cluster, strict bool) error {
return err return err
} }
err = g.ValidateTaintsForKubeVersion(cluster)
if err != nil {
return err
}
// Check that instance groups are defined in valid zones // Check that instance groups are defined in valid zones
{ {
clusterSubnets := make(map[string]*ClusterSubnetSpec) clusterSubnets := make(map[string]*ClusterSubnetSpec)
@ -191,3 +201,19 @@ func (g *InstanceGroup) CrossValidate(cluster *Cluster, strict bool) error {
return nil return nil
} }
// Ensures that users don't try to specify custom taints on pre-1.6.0 IGs
func (g *InstanceGroup) ValidateTaintsForKubeVersion(cluster *Cluster) error {
kv, err := util.ParseKubernetesVersion(cluster.Spec.KubernetesVersion)
if err != nil {
return fmt.Errorf("Unable to determine kubernetes version from %q", cluster.Spec.KubernetesVersion)
}
if kv.Major == 1 && kv.Minor <= 5 && len(g.Spec.Taints) > 0 {
if !(g.IsMaster() && g.Spec.Taints[0] == TaintNoScheduleMaster && len(g.Spec.Taints) == 1) {
return fmt.Errorf("User-specified taints are not supported before kubernetes version 1.6.0")
}
}
return nil
}

View File

@ -16,7 +16,12 @@ limitations under the License.
package kops package kops
import "k8s.io/kops/upup/pkg/fi/utils" import (
"fmt"
"github.com/blang/semver"
"k8s.io/kops/pkg/apis/kops/util"
"k8s.io/kops/upup/pkg/fi/utils"
)
const RoleLabelName = "kubernetes.io/role" const RoleLabelName = "kubernetes.io/role"
const RoleMasterLabelValue = "master" const RoleMasterLabelValue = "master"
@ -60,5 +65,33 @@ func BuildKubeletConfigSpec(cluster *Cluster, instanceGroup *InstanceGroup) (*Ku
utils.JsonMergeStruct(c, instanceGroup.Spec.Kubelet) utils.JsonMergeStruct(c, instanceGroup.Spec.Kubelet)
} }
sv, err := util.ParseKubernetesVersion(cluster.Spec.KubernetesVersion)
if err != nil {
return c, fmt.Errorf("Failed to lookup kubernetes version: %v", err)
}
// --register-with-taints was available in the first 1.6.0 alpha, no need to rely on semver's pre/build ordering
sv.Pre = nil
sv.Build = nil
if sv.GTE(semver.Version{Major: 1, Minor: 6, Patch: 0, Pre: nil, Build: nil}) {
for i, t := range instanceGroup.Spec.Taints {
if c.Taints == nil {
c.Taints = make([]string, len(instanceGroup.Spec.Taints))
}
c.Taints[i] = t
}
// Enable scheduling since it can be controlled via taints.
// For pre-1.6.0 clusters, this is handled by tainter.go
registerSchedulable := true
c.RegisterSchedulable = &registerSchedulable
} else {
err = instanceGroup.ValidateTaintsForKubeVersion(cluster)
if err != nil {
return nil, err
}
}
return c, nil return c, nil
} }

View File

@ -20,14 +20,18 @@ import (
"testing" "testing"
) )
var taintValidationError = "User-specified taints are not supported before kubernetes version 1.6.0"
func Test_InstanceGroupKubeletMerge(t *testing.T) { func Test_InstanceGroupKubeletMerge(t *testing.T) {
var cluster = &Cluster{} var cluster = &Cluster{}
cluster.Spec.Kubelet = &KubeletConfigSpec{} cluster.Spec.Kubelet = &KubeletConfigSpec{}
cluster.Spec.Kubelet.NvidiaGPUs = 0 cluster.Spec.Kubelet.NvidiaGPUs = 0
cluster.Spec.KubernetesVersion = "1.6.0"
var instanceGroup = &InstanceGroup{} var instanceGroup = &InstanceGroup{}
instanceGroup.Spec.Kubelet = &KubeletConfigSpec{} instanceGroup.Spec.Kubelet = &KubeletConfigSpec{}
instanceGroup.Spec.Kubelet.NvidiaGPUs = 1 instanceGroup.Spec.Kubelet.NvidiaGPUs = 1
instanceGroup.Spec.Role = InstanceGroupRoleNode
var mergedKubeletSpec, err = BuildKubeletConfigSpec(cluster, instanceGroup) var mergedKubeletSpec, err = BuildKubeletConfigSpec(cluster, instanceGroup)
if err != nil { if err != nil {
@ -41,3 +45,99 @@ func Test_InstanceGroupKubeletMerge(t *testing.T) {
t.Errorf("InstanceGroup kubelet value (%d) should be reflected in merged output", instanceGroup.Spec.Kubelet.NvidiaGPUs) t.Errorf("InstanceGroup kubelet value (%d) should be reflected in merged output", instanceGroup.Spec.Kubelet.NvidiaGPUs)
} }
} }
func TestTaintsAppliedAfter160(t *testing.T) {
exp := map[string]bool{
"1.4.9": false,
"1.5.2": false,
"1.6.0-alpha.1": true,
"1.6.0": true,
"1.6.5": true,
"1.7.0": true,
}
for ver, e := range exp {
helpTestTaintsForV(t, ver, e)
}
}
func TestDefaultTaintsEnforcedBefore160(t *testing.T) {
type param struct {
ver string
role InstanceGroupRole
taints []string
shouldErr bool
}
params := []param{
{"1.5.0", InstanceGroupRoleNode, []string{TaintNoScheduleMaster}, true},
{"1.5.1", InstanceGroupRoleNode, nil, false},
{"1.5.2", InstanceGroupRoleNode, []string{}, false},
{"1.6.0", InstanceGroupRoleNode, []string{TaintNoScheduleMaster}, false},
{"1.6.1", InstanceGroupRoleNode, []string{"Foo"}, false},
}
for _, p := range params {
cluster := &Cluster{Spec: ClusterSpec{KubernetesVersion: p.ver}}
ig := &InstanceGroup{Spec: InstanceGroupSpec{
Taints: p.taints,
Role: p.role,
}}
_, err := BuildKubeletConfigSpec(cluster, ig)
if p.shouldErr {
if err == nil {
t.Fatal("Expected error building kubelet config, received nil.")
} else if err.Error() != taintValidationError {
t.Fatalf("Received an unexpected error validating taints: '%s'", err.Error())
}
} else {
if err != nil {
t.Fatalf("Received an unexpected error validating taints: '%s', params: '%v'", err.Error(), p)
}
}
}
}
func helpTestTaintsForV(t *testing.T, version string, shouldApply bool) {
cluster := &Cluster{Spec: ClusterSpec{KubernetesVersion: version}}
ig := &InstanceGroup{Spec: InstanceGroupSpec{Role: InstanceGroupRoleMaster, Taints: []string{"foo", "bar", "baz"}}}
c, err := BuildKubeletConfigSpec(cluster, ig)
var expTaints []string
if shouldApply {
expTaints = []string{"foo", "bar", "baz"}
if c.RegisterSchedulable == nil || !*c.RegisterSchedulable {
t.Fatalf("Expected RegisterSchedulable == &true, got %v", c.RegisterSchedulable)
}
if !aEqual(expTaints, c.Taints) {
t.Fatalf("Expected taints %v, got %v", expTaints, c.Taints)
}
} else if err == nil || err.Error() != taintValidationError {
t.Fatalf("Received an unexpected error: '%s'", err.Error())
}
}
func aEqual(exp, other []string) bool {
if exp == nil && other != nil {
return false
}
if exp != nil && other == nil {
return false
}
if len(exp) != len(other) {
return false
}
for i, e := range exp {
if other[i] != e {
return false
}
}
return true
}

View File

@ -313,6 +313,9 @@ type KubeletConfigSpec struct {
// The full path of the directory in which to search for additional third party volume plugins // The full path of the directory in which to search for additional third party volume plugins
VolumePluginDirectory string `json:"volumePluginDirectory,omitempty" flag:"volume-plugin-dir"` VolumePluginDirectory string `json:"volumePluginDirectory,omitempty" flag:"volume-plugin-dir"`
// Taints to add when registering a node in the cluster
Taints []string `json:"taints,omitempty" flag:"register-with-taints"`
} }
type KubeProxyConfig struct { type KubeProxyConfig struct {

View File

@ -76,4 +76,10 @@ type InstanceGroupSpec struct {
// NodeLabels indicates the kubernetes labels for nodes in this group // NodeLabels indicates the kubernetes labels for nodes in this group
NodeLabels map[string]string `json:"nodeLabels,omitempty"` NodeLabels map[string]string `json:"nodeLabels,omitempty"`
// Kubelet overrides kubelet config from the ClusterSpec
Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"`
// Taints indicates the kubernetes taints for nodes in this group
Taints []string `json:"taints,omitempty"`
} }

View File

@ -244,10 +244,7 @@ func Convert_kops_CloudConfiguration_To_v1alpha1_CloudConfiguration(in *kops.Clo
} }
func autoConvert_v1alpha1_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s conversion.Scope) error { func autoConvert_v1alpha1_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_v1alpha1_ClusterSpec_To_kops_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -259,10 +256,7 @@ func Convert_v1alpha1_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s
} }
func autoConvert_kops_Cluster_To_v1alpha1_Cluster(in *kops.Cluster, out *Cluster, s conversion.Scope) error { func autoConvert_kops_Cluster_To_v1alpha1_Cluster(in *kops.Cluster, out *Cluster, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_kops_ClusterSpec_To_v1alpha1_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -754,10 +748,7 @@ func Convert_kops_ExternalNetworkingSpec_To_v1alpha1_ExternalNetworkingSpec(in *
} }
func autoConvert_v1alpha1_Federation_To_kops_Federation(in *Federation, out *kops.Federation, s conversion.Scope) error { func autoConvert_v1alpha1_Federation_To_kops_Federation(in *Federation, out *kops.Federation, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_v1alpha1_FederationSpec_To_kops_FederationSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_v1alpha1_FederationSpec_To_kops_FederationSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -769,10 +760,7 @@ func Convert_v1alpha1_Federation_To_kops_Federation(in *Federation, out *kops.Fe
} }
func autoConvert_kops_Federation_To_v1alpha1_Federation(in *kops.Federation, out *Federation, s conversion.Scope) error { func autoConvert_kops_Federation_To_v1alpha1_Federation(in *kops.Federation, out *Federation, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_kops_FederationSpec_To_v1alpha1_FederationSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_kops_FederationSpec_To_v1alpha1_FederationSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -862,10 +850,7 @@ func Convert_kops_FlannelNetworkingSpec_To_v1alpha1_FlannelNetworkingSpec(in *ko
} }
func autoConvert_v1alpha1_InstanceGroup_To_kops_InstanceGroup(in *InstanceGroup, out *kops.InstanceGroup, s conversion.Scope) error { func autoConvert_v1alpha1_InstanceGroup_To_kops_InstanceGroup(in *InstanceGroup, out *kops.InstanceGroup, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_v1alpha1_InstanceGroupSpec_To_kops_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_v1alpha1_InstanceGroupSpec_To_kops_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -877,10 +862,7 @@ func Convert_v1alpha1_InstanceGroup_To_kops_InstanceGroup(in *InstanceGroup, out
} }
func autoConvert_kops_InstanceGroup_To_v1alpha1_InstanceGroup(in *kops.InstanceGroup, out *InstanceGroup, s conversion.Scope) error { func autoConvert_kops_InstanceGroup_To_v1alpha1_InstanceGroup(in *kops.InstanceGroup, out *InstanceGroup, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_kops_InstanceGroupSpec_To_v1alpha1_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_kops_InstanceGroupSpec_To_v1alpha1_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -945,6 +927,16 @@ func autoConvert_v1alpha1_InstanceGroupSpec_To_kops_InstanceGroupSpec(in *Instan
out.AdditionalSecurityGroups = in.AdditionalSecurityGroups out.AdditionalSecurityGroups = in.AdditionalSecurityGroups
out.CloudLabels = in.CloudLabels out.CloudLabels = in.CloudLabels
out.NodeLabels = in.NodeLabels out.NodeLabels = in.NodeLabels
if in.Kubelet != nil {
in, out := &in.Kubelet, &out.Kubelet
*out = new(kops.KubeletConfigSpec)
if err := Convert_v1alpha1_KubeletConfigSpec_To_kops_KubeletConfigSpec(*in, *out, s); err != nil {
return err
}
} else {
out.Kubelet = nil
}
out.Taints = in.Taints
return nil return nil
} }
@ -962,6 +954,16 @@ func autoConvert_kops_InstanceGroupSpec_To_v1alpha1_InstanceGroupSpec(in *kops.I
out.AdditionalSecurityGroups = in.AdditionalSecurityGroups out.AdditionalSecurityGroups = in.AdditionalSecurityGroups
out.CloudLabels = in.CloudLabels out.CloudLabels = in.CloudLabels
out.NodeLabels = in.NodeLabels out.NodeLabels = in.NodeLabels
if in.Kubelet != nil {
in, out := &in.Kubelet, &out.Kubelet
*out = new(KubeletConfigSpec)
if err := Convert_kops_KubeletConfigSpec_To_v1alpha1_KubeletConfigSpec(*in, *out, s); err != nil {
return err
}
} else {
out.Kubelet = nil
}
out.Taints = in.Taints
return nil return nil
} }
@ -1253,6 +1255,7 @@ func autoConvert_v1alpha1_KubeletConfigSpec_To_kops_KubeletConfigSpec(in *Kubele
out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
return nil return nil
} }
@ -1298,6 +1301,7 @@ func autoConvert_kops_KubeletConfigSpec_To_v1alpha1_KubeletConfigSpec(in *kops.K
out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
return nil return nil
} }

View File

@ -135,6 +135,9 @@ type KubeletConfigSpec struct {
// The full path of the directory in which to search for additional third party volume plugins // The full path of the directory in which to search for additional third party volume plugins
VolumePluginDirectory string `json:"volumePluginDirectory,omitempty" flag:"volume-plugin-dir"` VolumePluginDirectory string `json:"volumePluginDirectory,omitempty" flag:"volume-plugin-dir"`
// Taints to add when registering a node in the cluster
Taints []string `json:"taints,omitempty" flag:"register-with-taints"`
} }
type KubeProxyConfig struct { type KubeProxyConfig struct {

View File

@ -83,4 +83,10 @@ type InstanceGroupSpec struct {
// NodeLabels indicates the kubernetes labels for nodes in this group // NodeLabels indicates the kubernetes labels for nodes in this group
NodeLabels map[string]string `json:"nodeLabels,omitempty"` NodeLabels map[string]string `json:"nodeLabels,omitempty"`
// Kubelet overrides kubelet config from the ClusterSpec
Kubelet *KubeletConfigSpec `json:"kubelet,omitempty"`
// Taints indicates the kubernetes taints for nodes in this group
Taints []string `json:"taints,omitempty"`
} }

View File

@ -270,10 +270,7 @@ func Convert_kops_CloudConfiguration_To_v1alpha2_CloudConfiguration(in *kops.Clo
} }
func autoConvert_v1alpha2_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s conversion.Scope) error { func autoConvert_v1alpha2_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_v1alpha2_ClusterSpec_To_kops_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -285,10 +282,7 @@ func Convert_v1alpha2_Cluster_To_kops_Cluster(in *Cluster, out *kops.Cluster, s
} }
func autoConvert_kops_Cluster_To_v1alpha2_Cluster(in *kops.Cluster, out *Cluster, s conversion.Scope) error { func autoConvert_kops_Cluster_To_v1alpha2_Cluster(in *kops.Cluster, out *Cluster, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_kops_ClusterSpec_To_v1alpha2_ClusterSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -844,10 +838,7 @@ func Convert_kops_ExternalNetworkingSpec_To_v1alpha2_ExternalNetworkingSpec(in *
} }
func autoConvert_v1alpha2_Federation_To_kops_Federation(in *Federation, out *kops.Federation, s conversion.Scope) error { func autoConvert_v1alpha2_Federation_To_kops_Federation(in *Federation, out *kops.Federation, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_v1alpha2_FederationSpec_To_kops_FederationSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_v1alpha2_FederationSpec_To_kops_FederationSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -859,10 +850,7 @@ func Convert_v1alpha2_Federation_To_kops_Federation(in *Federation, out *kops.Fe
} }
func autoConvert_kops_Federation_To_v1alpha2_Federation(in *kops.Federation, out *Federation, s conversion.Scope) error { func autoConvert_kops_Federation_To_v1alpha2_Federation(in *kops.Federation, out *Federation, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_kops_FederationSpec_To_v1alpha2_FederationSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_kops_FederationSpec_To_v1alpha2_FederationSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -952,10 +940,7 @@ func Convert_kops_FlannelNetworkingSpec_To_v1alpha2_FlannelNetworkingSpec(in *ko
} }
func autoConvert_v1alpha2_InstanceGroup_To_kops_InstanceGroup(in *InstanceGroup, out *kops.InstanceGroup, s conversion.Scope) error { func autoConvert_v1alpha2_InstanceGroup_To_kops_InstanceGroup(in *InstanceGroup, out *kops.InstanceGroup, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_v1alpha2_InstanceGroupSpec_To_kops_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_v1alpha2_InstanceGroupSpec_To_kops_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -967,10 +952,7 @@ func Convert_v1alpha2_InstanceGroup_To_kops_InstanceGroup(in *InstanceGroup, out
} }
func autoConvert_kops_InstanceGroup_To_v1alpha2_InstanceGroup(in *kops.InstanceGroup, out *InstanceGroup, s conversion.Scope) error { func autoConvert_kops_InstanceGroup_To_v1alpha2_InstanceGroup(in *kops.InstanceGroup, out *InstanceGroup, s conversion.Scope) error {
// TODO: Inefficient conversion - can we improve it? out.ObjectMeta = in.ObjectMeta
if err := s.Convert(&in.ObjectMeta, &out.ObjectMeta, 0); err != nil {
return err
}
if err := Convert_kops_InstanceGroupSpec_To_v1alpha2_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil { if err := Convert_kops_InstanceGroupSpec_To_v1alpha2_InstanceGroupSpec(&in.Spec, &out.Spec, s); err != nil {
return err return err
} }
@ -1035,6 +1017,16 @@ func autoConvert_v1alpha2_InstanceGroupSpec_To_kops_InstanceGroupSpec(in *Instan
out.AdditionalSecurityGroups = in.AdditionalSecurityGroups out.AdditionalSecurityGroups = in.AdditionalSecurityGroups
out.CloudLabels = in.CloudLabels out.CloudLabels = in.CloudLabels
out.NodeLabels = in.NodeLabels out.NodeLabels = in.NodeLabels
if in.Kubelet != nil {
in, out := &in.Kubelet, &out.Kubelet
*out = new(kops.KubeletConfigSpec)
if err := Convert_v1alpha2_KubeletConfigSpec_To_kops_KubeletConfigSpec(*in, *out, s); err != nil {
return err
}
} else {
out.Kubelet = nil
}
out.Taints = in.Taints
return nil return nil
} }
@ -1056,6 +1048,16 @@ func autoConvert_kops_InstanceGroupSpec_To_v1alpha2_InstanceGroupSpec(in *kops.I
out.AdditionalSecurityGroups = in.AdditionalSecurityGroups out.AdditionalSecurityGroups = in.AdditionalSecurityGroups
out.CloudLabels = in.CloudLabels out.CloudLabels = in.CloudLabels
out.NodeLabels = in.NodeLabels out.NodeLabels = in.NodeLabels
if in.Kubelet != nil {
in, out := &in.Kubelet, &out.Kubelet
*out = new(KubeletConfigSpec)
if err := Convert_kops_KubeletConfigSpec_To_v1alpha2_KubeletConfigSpec(*in, *out, s); err != nil {
return err
}
} else {
out.Kubelet = nil
}
out.Taints = in.Taints
return nil return nil
} }
@ -1351,6 +1353,7 @@ func autoConvert_v1alpha2_KubeletConfigSpec_To_kops_KubeletConfigSpec(in *Kubele
out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
return nil return nil
} }
@ -1396,6 +1399,7 @@ func autoConvert_kops_KubeletConfigSpec_To_v1alpha2_KubeletConfigSpec(in *kops.K
out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod out.EvictionMaxPodGracePeriod = in.EvictionMaxPodGracePeriod
out.EvictionMinimumReclaim = in.EvictionMinimumReclaim out.EvictionMinimumReclaim = in.EvictionMinimumReclaim
out.VolumePluginDirectory = in.VolumePluginDirectory out.VolumePluginDirectory = in.VolumePluginDirectory
out.Taints = in.Taints
return nil return nil
} }

View File

@ -44,9 +44,9 @@ type nodePatchSpec struct {
// Note that this is for k8s <= 1.5 only // Note that this is for k8s <= 1.5 only
const TaintsAnnotationKey string = "scheduler.alpha.kubernetes.io/taints" const TaintsAnnotationKey string = "scheduler.alpha.kubernetes.io/taints"
// ApplyMasterTaints finds masters that have not yet been tainted, and applies the master taint // ApplyMasterTaints finds masters that have not yet been tainted, and applies the master taint.
// Once the kubelet support --taints (like --labels) this can probably go away entirely. // Once all supported kubelet versions accept the --register-with-taints flag introduced in 1.6.0, this can probably
// It also sets the unschedulable flag to false, so pods (with a toleration) can target the node // go away entirely. It also sets the unschedulable flag to false, so pods (with a toleration) can target the node
func ApplyMasterTaints(kubeContext *KubernetesContext) error { func ApplyMasterTaints(kubeContext *KubernetesContext) error {
client, err := kubeContext.KubernetesClient() client, err := kubeContext.KubernetesClient()
if err != nil { if err != nil {
@ -74,7 +74,7 @@ func ApplyMasterTaints(kubeContext *KubernetesContext) error {
nodeTaintJSON := node.Annotations[TaintsAnnotationKey] nodeTaintJSON := node.Annotations[TaintsAnnotationKey]
if nodeTaintJSON != "" { if nodeTaintJSON != "" {
if nodeTaintJSON != string(taintJSON) { if nodeTaintJSON != string(taintJSON) {
glog.Infof("Node %q had unexpected taint: %v", node.Name, nodeTaintJSON) glog.Infof("Node %q is registered with taint: %v", node.Name, nodeTaintJSON)
} }
continue continue
} }

View File

@ -62,6 +62,8 @@ spec:
maxSize: 1 maxSize: 1
minSize: 1 minSize: 1
role: Master role: Master
taints:
- dedicated=master:NoSchedule
zones: zones:
- us-test-1a - us-test-1a
@ -80,6 +82,8 @@ spec:
maxSize: 1 maxSize: 1
minSize: 1 minSize: 1
role: Master role: Master
taints:
- dedicated=master:NoSchedule
zones: zones:
- us-test-1b - us-test-1b
@ -98,6 +102,8 @@ spec:
maxSize: 1 maxSize: 1
minSize: 1 minSize: 1
role: Master role: Master
taints:
- dedicated=master:NoSchedule
zones: zones:
- us-test-1c - us-test-1c

View File

@ -72,6 +72,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1a - us-test-1a
taints:
- dedicated=master:NoSchedule
--- ---
@ -90,6 +92,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1b - us-test-1b
taints:
- dedicated=master:NoSchedule
--- ---
@ -108,6 +112,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1c - us-test-1c
taints:
- dedicated=master:NoSchedule
--- ---

View File

@ -76,6 +76,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1a - us-test-1a
taints:
- dedicated=master:NoSchedule
--- ---
@ -94,6 +96,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1a - us-test-1a
taints:
- dedicated=master:NoSchedule
--- ---
@ -112,6 +116,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1a - us-test-1a
taints:
- dedicated=master:NoSchedule
--- ---
@ -130,6 +136,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1b - us-test-1b
taints:
- dedicated=master:NoSchedule
--- ---
@ -148,6 +156,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1b - us-test-1b
taints:
- dedicated=master:NoSchedule
--- ---

View File

@ -50,6 +50,8 @@ spec:
maxSize: 1 maxSize: 1
minSize: 1 minSize: 1
role: Master role: Master
taints:
- dedicated=master:NoSchedule
zones: zones:
- us-test-1a - us-test-1a

View File

@ -56,6 +56,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1a - us-test-1a
taints:
- dedicated=master:NoSchedule
--- ---

View File

@ -74,6 +74,8 @@ spec:
maxSize: 1 maxSize: 1
minSize: 1 minSize: 1
role: Master role: Master
taints:
- dedicated=master:NoSchedule
zones: zones:
- us-test-1a - us-test-1a

View File

@ -82,6 +82,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1a - us-test-1a
taints:
- dedicated=master:NoSchedule
--- ---

View File

@ -80,6 +80,8 @@ spec:
maxSize: 1 maxSize: 1
minSize: 1 minSize: 1
role: Master role: Master
taints:
- dedicated=master:NoSchedule
zones: zones:
- us-test-1a - us-test-1a

View File

@ -88,6 +88,8 @@ spec:
role: Master role: Master
subnets: subnets:
- us-test-1a - us-test-1a
taints:
- dedicated=master:NoSchedule
--- ---