Commit 6ee191ab authored by Michael Taufen's avatar Michael Taufen

Refactor kubelet config controller bootstrap process

This makes the bootstrap feel much more linear and as a result it is easier to read. Also simplifies status reporting for local config.
parent d99fcd5e
...@@ -10,7 +10,6 @@ go_library( ...@@ -10,7 +10,6 @@ go_library(
srcs = [ srcs = [
"configsync.go", "configsync.go",
"controller.go", "controller.go",
"rollback.go",
"watch.go", "watch.go",
], ],
importpath = "k8s.io/kubernetes/pkg/kubelet/kubeletconfig", importpath = "k8s.io/kubernetes/pkg/kubelet/kubeletconfig",
......
...@@ -168,7 +168,7 @@ func (cc *Controller) setCurrentConfig(source checkpoint.RemoteConfigSource) (bo ...@@ -168,7 +168,7 @@ func (cc *Controller) setCurrentConfig(source checkpoint.RemoteConfigSource) (bo
updated, err := cc.checkpointStore.SetCurrentUpdated(source) updated, err := cc.checkpointStore.SetCurrentUpdated(source)
if err != nil { if err != nil {
if source == nil { if source == nil {
return false, status.FailSyncReasonSetCurrentDefault, err return false, status.FailSyncReasonSetCurrentLocal, err
} }
return false, fmt.Sprintf(status.FailSyncReasonSetCurrentUIDFmt, source.UID()), err return false, fmt.Sprintf(status.FailSyncReasonSetCurrentUIDFmt, source.UID()), err
} }
......
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package kubeletconfig
import (
"fmt"
apiv1 "k8s.io/api/core/v1"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig"
"k8s.io/kubernetes/pkg/kubelet/apis/kubeletconfig/validation"
"k8s.io/kubernetes/pkg/kubelet/kubeletconfig/status"
utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log"
)
// lkgRollback returns a valid last-known-good configuration, and updates the `cc.configOK` condition
// regarding the `reason` for the rollback, or returns an error if a valid last-known-good could not be produced
func (cc *Controller) lkgRollback(reason, detail string) (*kubeletconfig.KubeletConfiguration, error) {
utillog.Errorf(fmt.Sprintf("%s, %s", reason, detail))
lkgUID := ""
if lkgSource, err := cc.checkpointStore.LastKnownGood(); err != nil {
return nil, fmt.Errorf("unable to determine last-known-good config, error: %v", err)
} else if lkgSource != nil {
lkgUID = lkgSource.UID()
}
// if lkgUID indicates the default should be used, return initConfig or defaultConfig
if len(lkgUID) == 0 {
if cc.initConfig != nil {
cc.configOK.Set(status.LkgInitMessage, reason, apiv1.ConditionFalse)
return cc.initConfig, nil
}
cc.configOK.Set(status.LkgDefaultMessage, reason, apiv1.ConditionFalse)
return cc.defaultConfig, nil
}
// load
checkpoint, err := cc.checkpointStore.Load(lkgUID)
if err != nil {
return nil, fmt.Errorf("%s, error: %v", fmt.Sprintf(status.LkgFailLoadReasonFmt, lkgUID), err)
}
// parse
lkg, err := checkpoint.Parse()
if err != nil {
return nil, fmt.Errorf("%s, error: %v", fmt.Sprintf(status.LkgFailParseReasonFmt, lkgUID), err)
}
// validate
if err := validation.ValidateKubeletConfiguration(lkg); err != nil {
return nil, fmt.Errorf("%s, error: %v", fmt.Sprintf(status.LkgFailValidateReasonFmt, lkgUID), err)
}
cc.configOK.Set(fmt.Sprintf(status.LkgRemoteMessageFmt, lkgUID), reason, apiv1.ConditionFalse)
return lkg, nil
}
...@@ -32,28 +32,27 @@ import ( ...@@ -32,28 +32,27 @@ import (
utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log" utillog "k8s.io/kubernetes/pkg/kubelet/kubeletconfig/util/log"
) )
// TODO(mtaufen): s/current/assigned, as this is more accurate e.g. if you are using lkg, you aren't currently using "current" :)
const ( const (
// CurDefaultMessage indicates the Kubelet is using it's current config, which is the default // NotDynamicLocalMessage indicates that the Kubelet is using its local config - we send this when dynamic Kubelet config is disabled by omitting the --dynamic-config-dir flag
CurDefaultMessage = "using current (default)" NotDynamicLocalMessage = "using local config"
// LkgDefaultMessage indicates the Kubelet is using it's last-known-good config, which is the default // NotDynamicLocalReason indicates that the Kubelet is using its local config - we send this when dynamic Kubelet config is disabled by omitting the --dynamic-config-dir flag
LkgDefaultMessage = "using last-known-good (default)" NotDynamicLocalReason = "dynamic config is currently disabled by omission of --dynamic-config-dir Kubelet flag"
// CurInitMessage indicates the Kubelet is using it's current config, which is from the init config files // CurLocalMessage indicates that the Kubelet is using its local config, which consists of defaults, flags, and/or local files
CurInitMessage = "using current (init)" CurLocalMessage = "using current (local)"
// LkgInitMessage indicates the Kubelet is using it's last-known-good config, which is from the init config files // LkgLocalMessage indicates that the Kubelet is using its local config, which consists of defaults, flags, and/or local files
LkgInitMessage = "using last-known-good (init)" LkgLocalMessage = "using last-known-good (local)"
// CurRemoteMessageFmt indicates the Kubelet is usin it's current config, which is from an API source // CurRemoteMessageFmt indicates the Kubelet is using its current config, which is from an API source
CurRemoteMessageFmt = "using current (UID: %q)" CurRemoteMessageFmt = "using current (UID: %q)"
// LkgRemoteMessageFmt indicates the Kubelet is using it's last-known-good config, which is from an API source // LkgRemoteMessageFmt indicates the Kubelet is using its last-known-good config, which is from an API source
LkgRemoteMessageFmt = "using last-known-good (UID: %q)" LkgRemoteMessageFmt = "using last-known-good (UID: %q)"
// CurDefaultOKReason indicates that no init config files were provided // CurLocalOkayReason indicates that the Kubelet is using its local config
CurDefaultOKReason = "current is set to the local default, and no init config was provided" CurLocalOkayReason = "when the config source is nil, the Kubelet uses its local config"
// CurInitOKReason indicates that init config files were provided // CurRemoteOkayReason indicates that the config referenced by Node.ConfigSource is currently passing all checks
CurInitOKReason = "current is set to the local default, and an init config was provided" CurRemoteOkayReason = "passing all checks"
// CurRemoteOKReason indicates that the config referenced by Node.ConfigSource is currently passing all checks
CurRemoteOKReason = "passing all checks"
// CurFailLoadReasonFmt indicates that the Kubelet failed to load the current config checkpoint for an API source // CurFailLoadReasonFmt indicates that the Kubelet failed to load the current config checkpoint for an API source
CurFailLoadReasonFmt = "failed to load current (UID: %q)" CurFailLoadReasonFmt = "failed to load current (UID: %q)"
...@@ -61,8 +60,6 @@ const ( ...@@ -61,8 +60,6 @@ const (
CurFailParseReasonFmt = "failed to parse current (UID: %q)" CurFailParseReasonFmt = "failed to parse current (UID: %q)"
// CurFailValidateReasonFmt indicates that the Kubelet failed to validate the current config checkpoint for an API source // CurFailValidateReasonFmt indicates that the Kubelet failed to validate the current config checkpoint for an API source
CurFailValidateReasonFmt = "failed to validate current (UID: %q)" CurFailValidateReasonFmt = "failed to validate current (UID: %q)"
// CurFailCrashLoopReasonFmt indicates that the Kubelet experienced a crash loop while using the current config checkpoint for an API source
CurFailCrashLoopReasonFmt = "current failed trial period due to crash loop (UID: %q)"
// LkgFail*ReasonFmt reasons are currently used to print errors in the Kubelet log, but do not appear in Node.Status.Conditions // LkgFail*ReasonFmt reasons are currently used to print errors in the Kubelet log, but do not appear in Node.Status.Conditions
...@@ -87,13 +84,13 @@ const ( ...@@ -87,13 +84,13 @@ const (
// FailSyncReasonInformer is used when the informer fails to report the Node object // FailSyncReasonInformer is used when the informer fails to report the Node object
FailSyncReasonInformer = "failed to read Node from informer object cache" FailSyncReasonInformer = "failed to read Node from informer object cache"
// FailSyncReasonReset is used when we can't reset the local configuration references, e.g. due to filesystem issues // FailSyncReasonReset is used when we can't reset the local configuration references, e.g. due to filesystem issues
FailSyncReasonReset = "failed to reset to local (default or init) config" FailSyncReasonReset = "failed to reset to local config"
// FailSyncReasonCheckpointExistenceFmt is used when we can't determine if a checkpoint already exists, e.g. due to filesystem issues // FailSyncReasonCheckpointExistenceFmt is used when we can't determine if a checkpoint already exists, e.g. due to filesystem issues
FailSyncReasonCheckpointExistenceFmt = "failed to determine whether object with UID %q was already checkpointed" FailSyncReasonCheckpointExistenceFmt = "failed to determine whether object with UID %q was already checkpointed"
// FailSyncReasonSaveCheckpointFmt is used when we can't save a checkpoint, e.g. due to filesystem issues // FailSyncReasonSaveCheckpointFmt is used when we can't save a checkpoint, e.g. due to filesystem issues
FailSyncReasonSaveCheckpointFmt = "failed to save config checkpoint for object with UID %q" FailSyncReasonSaveCheckpointFmt = "failed to save config checkpoint for object with UID %q"
// FailSyncReasonSetCurrentDefault is used when we can't set the current config checkpoint to the local default, e.g. due to filesystem issues // FailSyncReasonSetCurrentDefault is used when we can't set the current config checkpoint to the local default, e.g. due to filesystem issues
FailSyncReasonSetCurrentDefault = "failed to set current config checkpoint to default" FailSyncReasonSetCurrentLocal = "failed to set current config checkpoint to local config"
// FailSyncReasonSetCurrentUIDFmt is used when we can't set the current config checkpoint to a checkpointed object, e.g. due to filesystem issues // FailSyncReasonSetCurrentUIDFmt is used when we can't set the current config checkpoint to a checkpointed object, e.g. due to filesystem issues
FailSyncReasonSetCurrentUIDFmt = "failed to set current config checkpoint to object with UID %q" FailSyncReasonSetCurrentUIDFmt = "failed to set current config checkpoint to object with UID %q"
......
...@@ -87,7 +87,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -87,7 +87,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
Name: originalConfigMap.Name}}, Name: originalConfigMap.Name}},
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue,
Message: fmt.Sprintf(status.CurRemoteMessageFmt, originalConfigMap.UID), Message: fmt.Sprintf(status.CurRemoteMessageFmt, originalConfigMap.UID),
Reason: status.CurRemoteOKReason}, Reason: status.CurRemoteOkayReason},
expectConfig: originalKC, expectConfig: originalKC,
}, false) }, false)
}) })
...@@ -126,8 +126,8 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -126,8 +126,8 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
{desc: "Node.Spec.ConfigSource is nil", {desc: "Node.Spec.ConfigSource is nil",
configSource: nil, configSource: nil,
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue,
Message: status.CurDefaultMessage, Message: status.CurLocalMessage,
Reason: status.CurDefaultOKReason}, Reason: status.CurLocalOkayReason},
expectConfig: nil, expectConfig: nil,
event: true, event: true,
}, },
...@@ -175,7 +175,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -175,7 +175,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
Name: correctConfigMap.Name}}, Name: correctConfigMap.Name}},
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue,
Message: fmt.Sprintf(status.CurRemoteMessageFmt, correctConfigMap.UID), Message: fmt.Sprintf(status.CurRemoteMessageFmt, correctConfigMap.UID),
Reason: status.CurRemoteOKReason}, Reason: status.CurRemoteOkayReason},
expectConfig: correctKC, expectConfig: correctKC,
event: true, event: true,
}, },
...@@ -187,7 +187,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -187,7 +187,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
Namespace: failParseConfigMap.Namespace, Namespace: failParseConfigMap.Namespace,
Name: failParseConfigMap.Name}}, Name: failParseConfigMap.Name}},
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionFalse, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionFalse,
Message: status.LkgDefaultMessage, Message: status.LkgLocalMessage,
Reason: fmt.Sprintf(status.CurFailParseReasonFmt, failParseConfigMap.UID)}, Reason: fmt.Sprintf(status.CurFailParseReasonFmt, failParseConfigMap.UID)},
expectConfig: nil, expectConfig: nil,
event: true, event: true,
...@@ -200,7 +200,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -200,7 +200,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
Namespace: failValidateConfigMap.Namespace, Namespace: failValidateConfigMap.Namespace,
Name: failValidateConfigMap.Name}}, Name: failValidateConfigMap.Name}},
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionFalse, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionFalse,
Message: status.LkgDefaultMessage, Message: status.LkgLocalMessage,
Reason: fmt.Sprintf(status.CurFailValidateReasonFmt, failValidateConfigMap.UID)}, Reason: fmt.Sprintf(status.CurFailValidateReasonFmt, failValidateConfigMap.UID)},
expectConfig: nil, expectConfig: nil,
event: true, event: true,
...@@ -245,7 +245,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -245,7 +245,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
Name: lkgConfigMap.Name}}, Name: lkgConfigMap.Name}},
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue,
Message: fmt.Sprintf(status.CurRemoteMessageFmt, lkgConfigMap.UID), Message: fmt.Sprintf(status.CurRemoteMessageFmt, lkgConfigMap.UID),
Reason: status.CurRemoteOKReason}, Reason: status.CurRemoteOkayReason},
expectConfig: lkgKC, expectConfig: lkgKC,
event: true, event: true,
}, },
...@@ -295,10 +295,11 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -295,10 +295,11 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
Name: cm1.Name}}, Name: cm1.Name}},
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue,
Message: fmt.Sprintf(status.CurRemoteMessageFmt, cm1.UID), Message: fmt.Sprintf(status.CurRemoteMessageFmt, cm1.UID),
Reason: status.CurRemoteOKReason}, Reason: status.CurRemoteOkayReason},
expectConfig: kc1, expectConfig: kc1,
event: true, event: true,
}, },
{desc: "cm2", {desc: "cm2",
configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{ configSource: &apiv1.NodeConfigSource{ConfigMapRef: &apiv1.ObjectReference{
UID: cm2.UID, UID: cm2.UID,
...@@ -306,7 +307,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube ...@@ -306,7 +307,7 @@ var _ = framework.KubeDescribe("DynamicKubeletConfiguration [Feature:DynamicKube
Name: cm2.Name}}, Name: cm2.Name}},
expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue, expectConfigOK: &apiv1.NodeCondition{Type: apiv1.NodeConfigOK, Status: apiv1.ConditionTrue,
Message: fmt.Sprintf(status.CurRemoteMessageFmt, cm2.UID), Message: fmt.Sprintf(status.CurRemoteMessageFmt, cm2.UID),
Reason: status.CurRemoteOKReason}, Reason: status.CurRemoteOkayReason},
expectConfig: kc2, expectConfig: kc2,
event: true, event: true,
}, },
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment