Remove ConditionSchedulable

This commit is contained in:
gmarek 2015-04-03 15:43:51 +02:00
parent d6851729d2
commit ef56dca6b6
11 changed files with 34 additions and 130 deletions

View File

@ -38,24 +38,17 @@ must have appropriate conditions, see below.
### Node Condition ### Node Condition
Node Condition describes the conditions of `Running` nodes. Current valid Node Condition describes the conditions of `Running` nodes. Current valid
conditions are `NodeReady` and `NodeSchedulable`. In the future, we plan to condition is `NodeReady`. In the future, we plan to add more.
add more. `NodeReady` means kubelet is healthy and ready to accept pods `NodeReady` means kubelet is healthy and ready to accept pods. Different
`NodeSchedulable` means node is allowed to schedule any new pods and is condition provides different level of understanding for node health.
controlled by 'unschedulable' field in node spec. Different condition provides Node condition is represented as a json object. For example,
different level of understanding for node health. Kubernetes will make a the following conditions mean the node is in sane state:
comprehensive scheduling decision based on the information. Node condition
is represented as a json object. For example, the following conditions mean
the node is in sane state but not allowed to accept new pods:
```json ```json
"conditions": [ "conditions": [
{ {
"kind": "Ready", "kind": "Ready",
"status": "True", "status": "True",
}, },
{
"kind": "Schedulable",
"status": "False",
},
] ]
``` ```

View File

@ -1087,12 +1087,10 @@ type NodeConditionType string
// These are valid conditions of node. Currently, we don't have enough information to decide // These are valid conditions of node. Currently, we don't have enough information to decide
// node condition. In the future, we will add more. The proposed set of conditions are: // node condition. In the future, we will add more. The proposed set of conditions are:
// NodeReachable, NodeLive, NodeReady, NodeSchedulable, NodeRunnable. // NodeReady, NodeReachable
const ( const (
// NodeReady means kubelet is healthy and ready to accept pods. // NodeReady means kubelet is healthy and ready to accept pods.
NodeReady NodeConditionType = "Ready" NodeReady NodeConditionType = "Ready"
// NodeSchedulable means the node is ready to accept new pods.
NodeSchedulable NodeConditionType = "Schedulable"
) )
type NodeCondition struct { type NodeCondition struct {

View File

@ -945,6 +945,7 @@ const (
// NodeReady means kubelet is healthy and ready to accept pods. // NodeReady means kubelet is healthy and ready to accept pods.
NodeReady NodeConditionKind = "Ready" NodeReady NodeConditionKind = "Ready"
// NodeSchedulable means the node is ready to accept new pods. // NodeSchedulable means the node is ready to accept new pods.
// DEPRECATED: this kind of condition is unused and has no effect even if present.
NodeSchedulable NodeConditionKind = "Schedulable" NodeSchedulable NodeConditionKind = "Schedulable"
) )

View File

@ -954,6 +954,7 @@ const (
// NodeReady means kubelet is healthy and ready to accept pods. // NodeReady means kubelet is healthy and ready to accept pods.
NodeReady NodeConditionKind = "Ready" NodeReady NodeConditionKind = "Ready"
// NodeSchedulable means the node is ready to accept new pods. // NodeSchedulable means the node is ready to accept new pods.
// DEPRECATED: this kind of condition is unused and has no effect even if present.
NodeSchedulable NodeConditionKind = "Schedulable" NodeSchedulable NodeConditionKind = "Schedulable"
) )

View File

@ -1088,8 +1088,6 @@ type NodeConditionType string
const ( const (
// NodeReady means kubelet is healthy and ready to accept pods. // NodeReady means kubelet is healthy and ready to accept pods.
NodeReady NodeConditionType = "Ready" NodeReady NodeConditionType = "Ready"
// NodeSchedulable means the node is ready to accept new pods.
NodeSchedulable NodeConditionType = "Schedulable"
) )
type NodeCondition struct { type NodeCondition struct {

View File

@ -339,12 +339,6 @@ func (nc *NodeController) DoCheck(node *api.Node) []api.NodeCondition {
} }
conditions = append(conditions, *newReadyCondition) conditions = append(conditions, *newReadyCondition)
// Check Condition: NodeSchedulable
oldSchedulableCondition := nc.getCondition(&node.Status, api.NodeSchedulable)
newSchedulableCondition := nc.checkNodeSchedulable(node)
nc.updateLastTransitionTime(oldSchedulableCondition, newSchedulableCondition)
conditions = append(conditions, *newSchedulableCondition)
return conditions return conditions
} }
@ -360,25 +354,6 @@ func (nc *NodeController) updateLastTransitionTime(oldCondition, newCondition *a
} }
} }
// checkNodeSchedulable checks node schedulable condition, without transition timestamp set.
func (nc *NodeController) checkNodeSchedulable(node *api.Node) *api.NodeCondition {
if node.Spec.Unschedulable {
return &api.NodeCondition{
Type: api.NodeSchedulable,
Status: api.ConditionFalse,
Reason: "User marked unschedulable during node create/update",
LastProbeTime: nc.now(),
}
} else {
return &api.NodeCondition{
Type: api.NodeSchedulable,
Status: api.ConditionTrue,
Reason: "Node is schedulable by default",
LastProbeTime: nc.now(),
}
}
}
// checkNodeReady checks raw node ready condition, without transition timestamp set. // checkNodeReady checks raw node ready condition, without transition timestamp set.
func (nc *NodeController) checkNodeReady(node *api.Node) *api.NodeCondition { func (nc *NodeController) checkNodeReady(node *api.Node) *api.NodeCondition {
switch status, err := nc.kubeletClient.HealthCheck(node.Name); { switch status, err := nc.kubeletClient.HealthCheck(node.Name); {

View File

@ -625,13 +625,6 @@ func TestNodeConditionsCheck(t *testing.T) {
LastProbeTime: fakeNow, LastProbeTime: fakeNow,
LastTransitionTime: fakeNow, LastTransitionTime: fakeNow,
}, },
{
Type: api.NodeSchedulable,
Status: api.ConditionTrue,
Reason: "Node is schedulable by default",
LastProbeTime: fakeNow,
LastTransitionTime: fakeNow,
},
}, },
}, },
{ {
@ -650,18 +643,10 @@ func TestNodeConditionsCheck(t *testing.T) {
LastProbeTime: fakeNow, LastProbeTime: fakeNow,
LastTransitionTime: fakeNow, LastTransitionTime: fakeNow,
}, },
{
Type: api.NodeSchedulable,
Status: api.ConditionTrue,
Reason: "Node is schedulable by default",
LastProbeTime: fakeNow,
LastTransitionTime: fakeNow,
},
}, },
}, },
{ {
// User specified node as unschedulable and kubelet /healthz probe returns failure with some error. // Expected node condition to be not ready as marking Node Unschedulable does not impact Readiness.
// Expected node condition to be not ready and marked unschedulable.
node: &api.Node{ObjectMeta: api.ObjectMeta{Name: "node0"}, Spec: api.NodeSpec{Unschedulable: true}}, node: &api.Node{ObjectMeta: api.ObjectMeta{Name: "node0"}, Spec: api.NodeSpec{Unschedulable: true}},
fakeKubeletClient: &FakeKubeletClient{ fakeKubeletClient: &FakeKubeletClient{
Status: probe.Failure, Status: probe.Failure,
@ -675,13 +660,6 @@ func TestNodeConditionsCheck(t *testing.T) {
LastProbeTime: fakeNow, LastProbeTime: fakeNow,
LastTransitionTime: fakeNow, LastTransitionTime: fakeNow,
}, },
{
Type: api.NodeSchedulable,
Status: api.ConditionFalse,
Reason: "User marked unschedulable during node create/update",
LastProbeTime: fakeNow,
LastTransitionTime: fakeNow,
},
}, },
}, },
} }
@ -764,13 +742,6 @@ func TestSyncProbedNodeStatus(t *testing.T) {
LastProbeTime: fakeNow, LastProbeTime: fakeNow,
LastTransitionTime: fakeNow, LastTransitionTime: fakeNow,
}, },
{
Type: api.NodeSchedulable,
Status: api.ConditionTrue,
Reason: "Node is schedulable by default",
LastProbeTime: fakeNow,
LastTransitionTime: fakeNow,
},
}, },
Addresses: []api.NodeAddress{ Addresses: []api.NodeAddress{
{Type: api.NodeLegacyHostIP, Address: "1.2.3.4"}, {Type: api.NodeLegacyHostIP, Address: "1.2.3.4"},
@ -795,13 +766,6 @@ func TestSyncProbedNodeStatus(t *testing.T) {
LastProbeTime: fakeNow, LastProbeTime: fakeNow,
LastTransitionTime: fakeNow, LastTransitionTime: fakeNow,
}, },
{
Type: api.NodeSchedulable,
Status: api.ConditionTrue,
Reason: "Node is schedulable by default",
LastProbeTime: fakeNow,
LastTransitionTime: fakeNow,
},
}, },
Addresses: []api.NodeAddress{ Addresses: []api.NodeAddress{
{Type: api.NodeLegacyHostIP, Address: "1.2.3.4"}, {Type: api.NodeLegacyHostIP, Address: "1.2.3.4"},
@ -868,12 +832,6 @@ func TestSyncProbedNodeStatusTransitionTime(t *testing.T) {
Reason: "Node health check succeeded: kubelet /healthz endpoint returns ok", Reason: "Node health check succeeded: kubelet /healthz endpoint returns ok",
LastTransitionTime: util.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), LastTransitionTime: util.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
}, },
{
Type: api.NodeSchedulable,
Status: api.ConditionTrue,
Reason: "Node is schedulable by default",
LastTransitionTime: util.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
},
}, },
}, },
}, },
@ -903,12 +861,6 @@ func TestSyncProbedNodeStatusTransitionTime(t *testing.T) {
Reason: "Node health check succeeded: kubelet /healthz endpoint returns ok", Reason: "Node health check succeeded: kubelet /healthz endpoint returns ok",
LastTransitionTime: util.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC), LastTransitionTime: util.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
}, },
{
Type: api.NodeSchedulable,
Status: api.ConditionTrue,
Reason: "Node is schedulable by default",
LastTransitionTime: util.Date(2012, 1, 1, 0, 0, 0, 0, time.UTC),
},
}, },
}, },
}, },

View File

@ -482,11 +482,17 @@ func printSecretList(list *api.SecretList, w io.Writer) error {
func printNode(node *api.Node, w io.Writer) error { func printNode(node *api.Node, w io.Writer) error {
conditionMap := make(map[api.NodeConditionType]*api.NodeCondition) conditionMap := make(map[api.NodeConditionType]*api.NodeCondition)
NodeAllConditions := []api.NodeConditionType{api.NodeSchedulable, api.NodeReady} NodeAllConditions := []api.NodeConditionType{api.NodeReady}
for i := range node.Status.Conditions { for i := range node.Status.Conditions {
cond := node.Status.Conditions[i] cond := node.Status.Conditions[i]
conditionMap[cond.Type] = &cond conditionMap[cond.Type] = &cond
} }
var schedulable string
if node.Spec.Unschedulable {
schedulable = "Unschedulable"
} else {
schedulable = "Schedulable"
}
var status []string var status []string
for _, validCondition := range NodeAllConditions { for _, validCondition := range NodeAllConditions {
if condition, ok := conditionMap[validCondition]; ok { if condition, ok := conditionMap[validCondition]; ok {
@ -500,7 +506,7 @@ func printNode(node *api.Node, w io.Writer) error {
if len(status) == 0 { if len(status) == 0 {
status = append(status, "Unknown") status = append(status, "Unknown")
} }
_, err := fmt.Fprintf(w, "%s\t%s\t%s\n", node.Name, formatLabels(node.Labels), strings.Join(status, ",")) _, err := fmt.Fprintf(w, "%s\t%s\t%s\t%s\n", node.Name, schedulable, formatLabels(node.Labels), strings.Join(status, ","))
return err return err
} }

View File

@ -579,24 +579,6 @@ func TestPrintMinionStatus(t *testing.T) {
}, },
status: "Unknown", status: "Unknown",
}, },
{
minion: api.Node{
ObjectMeta: api.ObjectMeta{Name: "foo7"},
Status: api.NodeStatus{Conditions: []api.NodeCondition{
{Type: api.NodeSchedulable, Status: api.ConditionTrue},
{Type: api.NodeReady, Status: api.ConditionTrue}}},
},
status: "Schedulable,Ready",
},
{
minion: api.Node{
ObjectMeta: api.ObjectMeta{Name: "foo8"},
Status: api.NodeStatus{Conditions: []api.NodeCondition{
{Type: api.NodeSchedulable, Status: api.ConditionFalse},
{Type: api.NodeReady, Status: api.ConditionFalse}}},
},
status: "NotSchedulable,NotReady",
},
} }
for _, test := range table { for _, test := range table {

View File

@ -249,10 +249,8 @@ func (factory *ConfigFactory) pollMinions() (cache.Enumerator, error) {
cond := node.Status.Conditions[i] cond := node.Status.Conditions[i]
conditionMap[cond.Type] = &cond conditionMap[cond.Type] = &cond
} }
if condition, ok := conditionMap[api.NodeSchedulable]; ok { if node.Spec.Unschedulable {
if condition.Status != api.ConditionTrue { continue
continue
}
} }
if condition, ok := conditionMap[api.NodeReady]; ok { if condition, ok := conditionMap[api.NodeReady]; ok {
if condition.Status == api.ConditionTrue { if condition.Status == api.ConditionTrue {

View File

@ -148,10 +148,8 @@ func TestPollMinions(t *testing.T) {
}, },
{ {
ObjectMeta: api.ObjectMeta{Name: "fiz"}, ObjectMeta: api.ObjectMeta{Name: "fiz"},
Status: api.NodeStatus{ Spec: api.NodeSpec{
Conditions: []api.NodeCondition{ Unschedulable: false,
{Type: api.NodeSchedulable, Status: api.ConditionTrue},
},
}, },
}, },
{ {
@ -167,28 +165,34 @@ func TestPollMinions(t *testing.T) {
ObjectMeta: api.ObjectMeta{Name: "fuz"}, ObjectMeta: api.ObjectMeta{Name: "fuz"},
Status: api.NodeStatus{ Status: api.NodeStatus{
Conditions: []api.NodeCondition{ Conditions: []api.NodeCondition{
{Type: api.NodeSchedulable, Status: api.ConditionTrue},
{Type: api.NodeReady, Status: api.ConditionTrue}, {Type: api.NodeReady, Status: api.ConditionTrue},
}, },
}, },
Spec: api.NodeSpec{
Unschedulable: false,
},
}, },
{ {
ObjectMeta: api.ObjectMeta{Name: "buz"}, ObjectMeta: api.ObjectMeta{Name: "buz"},
Status: api.NodeStatus{ Status: api.NodeStatus{
Conditions: []api.NodeCondition{ Conditions: []api.NodeCondition{
{Type: api.NodeSchedulable, Status: api.ConditionFalse},
{Type: api.NodeReady, Status: api.ConditionTrue}, {Type: api.NodeReady, Status: api.ConditionTrue},
}, },
}, },
Spec: api.NodeSpec{
Unschedulable: true,
},
}, },
{ {
ObjectMeta: api.ObjectMeta{Name: "foobar"}, ObjectMeta: api.ObjectMeta{Name: "foobar"},
Status: api.NodeStatus{ Status: api.NodeStatus{
Conditions: []api.NodeCondition{ Conditions: []api.NodeCondition{
{Type: api.NodeSchedulable, Status: api.ConditionTrue},
{Type: api.NodeReady, Status: api.ConditionFalse}, {Type: api.NodeReady, Status: api.ConditionFalse},
}, },
}, },
Spec: api.NodeSpec{
Unschedulable: false,
},
}, },
}, },
expectedCount: 3, expectedCount: 3,
@ -218,18 +222,14 @@ func TestPollMinions(t *testing.T) {
minions: []api.Node{ minions: []api.Node{
{ {
ObjectMeta: api.ObjectMeta{Name: "foo"}, ObjectMeta: api.ObjectMeta{Name: "foo"},
Status: api.NodeStatus{ Spec: api.NodeSpec{
Conditions: []api.NodeCondition{ Unschedulable: false,
{Type: api.NodeSchedulable, Status: api.ConditionTrue},
},
}, },
}, },
{ {
ObjectMeta: api.ObjectMeta{Name: "bar"}, ObjectMeta: api.ObjectMeta{Name: "bar"},
Status: api.NodeStatus{ Spec: api.NodeSpec{
Conditions: []api.NodeCondition{ Unschedulable: true,
{Type: api.NodeSchedulable, Status: api.ConditionFalse},
},
}, },
}, },
}, },