Skip to content

Commit 8814022

Browse files
Merge pull request #4206 from QiWang19/4.13-anno
[release-4.13] OCPBUGS-29721: Add existing kubeletconfig/ctrcfg mc-name-suffix annotation
2 parents 77c5676 + 3f14776 commit 8814022

File tree

6 files changed

+277
-42
lines changed

6 files changed

+277
-42
lines changed

pkg/controller/container-runtime-config/container_runtime_config_controller.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -627,23 +627,23 @@ func (ctrl *Controller) syncContainerRuntimeConfig(key string) error {
627627
if err != nil {
628628
return ctrl.syncStatusOnly(cfg, err, "could not create MachineConfig from new Ignition config: %v", err)
629629
}
630-
_, ok := cfg.GetAnnotations()[ctrlcommon.MCNameSuffixAnnotationKey]
631-
arr := strings.Split(managedKey, "-")
632-
// the first managed key value 99-poolname-generated-containerruntime does not have a suffix
633-
// set "" as suffix annotation to the containerruntime config object
634-
if _, err := strconv.Atoi(arr[len(arr)-1]); err != nil && !ok {
635-
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, ""); err != nil {
636-
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for containerruntimeConfig")
637-
}
630+
}
631+
_, ok := cfg.GetAnnotations()[ctrlcommon.MCNameSuffixAnnotationKey]
632+
arr := strings.Split(managedKey, "-")
633+
// the first managed key value 99-poolname-generated-containerruntime does not have a suffix
634+
// set "" as suffix annotation to the containerruntime config object
635+
if _, err := strconv.Atoi(arr[len(arr)-1]); err != nil && !ok {
636+
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, ""); err != nil {
637+
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for containerruntimeConfig")
638638
}
639-
// If the MC name suffix annotation does not exist and the managed key value returned has a suffix, then add the MC name
640-
// suffix annotation and suffix value to the ctrcfg object
641-
if len(arr) > 4 && !ok {
642-
_, err := strconv.Atoi(arr[len(arr)-1])
643-
if err == nil {
644-
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, arr[len(arr)-1]); err != nil {
645-
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for containerRuntimeConfig")
646-
}
639+
}
640+
// If the MC name suffix annotation does not exist and the managed key value returned has a suffix, then add the MC name
641+
// suffix annotation and suffix value to the ctrcfg object
642+
if len(arr) > 4 && !ok {
643+
_, err := strconv.Atoi(arr[len(arr)-1])
644+
if err == nil {
645+
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, arr[len(arr)-1]); err != nil {
646+
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for containerRuntimeConfig")
647647
}
648648
}
649649
}

pkg/controller/container-runtime-config/container_runtime_config_controller_test.go

Lines changed: 58 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -137,7 +137,7 @@ func newControllerConfig(name string, platform apicfgv1.PlatformType) *mcfgv1.Co
137137
func newContainerRuntimeConfig(name string, ctrconf *mcfgv1.ContainerRuntimeConfiguration, selector *metav1.LabelSelector) *mcfgv1.ContainerRuntimeConfig {
138138
return &mcfgv1.ContainerRuntimeConfig{
139139
TypeMeta: metav1.TypeMeta{APIVersion: mcfgv1.SchemeGroupVersion.String()},
140-
ObjectMeta: metav1.ObjectMeta{Name: name, UID: types.UID(utilrand.String(5)), Generation: 1},
140+
ObjectMeta: metav1.ObjectMeta{Name: name, UID: types.UID(utilrand.String(5)), Generation: 1, CreationTimestamp: metav1.Now()},
141141
Spec: mcfgv1.ContainerRuntimeConfigSpec{
142142
ContainerRuntimeConfig: ctrconf,
143143
MachineConfigPoolSelector: selector,
@@ -1512,6 +1512,63 @@ func TestContainerruntimeConfigResync(t *testing.T) {
15121512
}
15131513
}
15141514

1515+
func TestAddAnnotationExistingContainerRuntimeConfig(t *testing.T) {
1516+
for _, platform := range []apicfgv1.PlatformType{apicfgv1.AWSPlatformType, apicfgv1.NonePlatformType, "unrecognized"} {
1517+
t.Run(string(platform), func(t *testing.T) {
1518+
f := newFixture(t)
1519+
f.newController()
1520+
1521+
cc := newControllerConfig(ctrlcommon.ControllerConfigName, platform)
1522+
mcp := helpers.NewMachineConfigPool("master", nil, helpers.MasterSelector, "v0")
1523+
mcp2 := helpers.NewMachineConfigPool("worker", nil, helpers.WorkerSelector, "v0")
1524+
1525+
ctrMCKey := "99-master-generated-containerruntime"
1526+
ctr1MCKey := "99-master-generated-containerruntime-1"
1527+
ctrc := newContainerRuntimeConfig("log-level", &mcfgv1.ContainerRuntimeConfiguration{LogLevel: "debug"}, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/master", ""))
1528+
ctrc.Finalizers = []string{ctrMCKey}
1529+
ctrc1 := newContainerRuntimeConfig("log-level-1", &mcfgv1.ContainerRuntimeConfiguration{LogLevel: "debug"}, metav1.AddLabelToSelector(&metav1.LabelSelector{}, "pools.operator.machineconfiguration.openshift.io/master", ""))
1530+
ctrc1.SetAnnotations(map[string]string{ctrlcommon.MCNameSuffixAnnotationKey: "1"})
1531+
ctrc1.Finalizers = []string{ctr1MCKey}
1532+
ctrcfgMC := helpers.NewMachineConfig(ctrMCKey, map[string]string{"node-role/master": ""}, "dummy://", []ign3types.File{{}})
1533+
1534+
f.ccLister = append(f.ccLister, cc)
1535+
f.mcpLister = append(f.mcpLister, mcp)
1536+
f.mcpLister = append(f.mcpLister, mcp2)
1537+
f.mccrLister = append(f.mccrLister, ctrc, ctrc1)
1538+
f.objects = append(f.objects, ctrc, ctrc1, ctrcfgMC)
1539+
1540+
// ctrc created before ctrc1,
1541+
// make sure ccr does not have annotation machineconfiguration.openshift.io/mc-name-suffix before sync, ccr1 has annotation machineconfiguration.openshift.io/mc-name-suffix
1542+
_, ok := ctrc.GetAnnotations()[ctrlcommon.MCNameSuffixAnnotationKey]
1543+
require.False(t, ok)
1544+
val := ctrc1.GetAnnotations()[ctrlcommon.MCNameSuffixAnnotationKey]
1545+
require.Equal(t, "1", val)
1546+
1547+
// no new machine config will be created
1548+
f.expectGetMachineConfigAction(ctrcfgMC)
1549+
f.expectGetMachineConfigAction(ctrcfgMC)
1550+
f.expectUpdateContainerRuntimeConfigRoot(ctrc)
1551+
f.expectUpdateMachineConfigAction(ctrcfgMC)
1552+
f.expectPatchContainerRuntimeConfig(ctrc, ctrcfgPatchBytes)
1553+
f.expectUpdateContainerRuntimeConfig(ctrc)
1554+
1555+
c := f.newController()
1556+
err := c.syncHandler(getKey(ctrc, t))
1557+
if err != nil {
1558+
t.Errorf("syncHandler returned: %v", err)
1559+
}
1560+
f.validateActions()
1561+
1562+
// ctrc annotation machineconfiguration.openshift.io/mc-name-suffix after sync
1563+
val = ctrc.GetAnnotations()[ctrlcommon.MCNameSuffixAnnotationKey]
1564+
require.Equal(t, "", val)
1565+
ctrcFinalizers := ctrc.GetFinalizers()
1566+
require.Equal(t, 1, len(ctrcFinalizers))
1567+
require.Equal(t, ctrMCKey, ctrcFinalizers[0])
1568+
})
1569+
}
1570+
}
1571+
15151572
// TestCleanUpDuplicatedMC test the function removes the MC from the MC list
15161573
// if the MC is of old GeneratedByControllerVersionAnnotationKey.
15171574
func TestCleanUpDuplicatedMC(t *testing.T) {

pkg/controller/container-runtime-config/helpers.go

Lines changed: 66 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,13 @@ import (
3333
)
3434

3535
const (
36-
minLogSize = 8192
37-
minPidsLimit = 20
38-
storageConfigPath = "/etc/containers/storage.conf"
39-
registriesConfigPath = "/etc/containers/registries.conf"
40-
searchRegDropInFilePath = "/etc/containers/registries.conf.d/01-image-searchRegistries.conf"
41-
policyConfigPath = "/etc/containers/policy.json"
36+
minLogSize = 8192
37+
minPidsLimit = 20
38+
managedContainerRuntimeConfigKeyPrefix = "99"
39+
storageConfigPath = "/etc/containers/storage.conf"
40+
registriesConfigPath = "/etc/containers/registries.conf"
41+
searchRegDropInFilePath = "/etc/containers/registries.conf.d/01-image-searchRegistries.conf"
42+
policyConfigPath = "/etc/containers/policy.json"
4243
// CRIODropInFilePathLogLevel is the path at which changes to the crio config for log-level
4344
// will be dropped in this is exported so that we can use it in the e2e-tests
4445
CRIODropInFilePathLogLevel = "/etc/crio/crio.conf.d/01-ctrcfg-logLevel"
@@ -221,11 +222,60 @@ func getManagedKeyCtrCfg(pool *mcfgv1.MachineConfigPool, client mcfgclientset.In
221222
return ctrlcommon.GetManagedKey(pool, client, "99", "containerruntime", getManagedKeyCtrCfgDeprecated(pool))
222223
}
223224

224-
// If we are here, this means that a new containerruntime config was created, so we have to calculate the suffix value for its MC name
225+
// If we are here, this means that
226+
// 1. a new containerruntime config was created, so we have to calculate the suffix value for its MC name
227+
// 2. or this is an existing containerruntime config did not get ctrlcommon.MCNameSuffixAnnotationKey set, so we have to set the MCNameSuffixAnnotationKey to the machineconfig suffix it was rendered to, assume for existing containerruntime config, cfg.Finalizers with the largest suffix is the machine config the ctrcfg was rendered to
225228
// if the containerruntime config is the only one in the list, mc name should not suffixed since cfg is the first containerruntime config to be created
226229
if len(ctrcfgList) == 1 {
227230
return ctrlcommon.GetManagedKey(pool, client, "99", "containerruntime", getManagedKeyCtrCfgDeprecated(pool))
228231
}
232+
// if cfg is not a newly created containerruntime config and did not get ctrlcommon.MCNameSuffixAnnotationKey
233+
// but has been rendered to a machineconfig, its len(cfg.Finalizers) > 0
234+
if notLatestContainerRuntimeConfigInPool(ctrcfgList, cfg) {
235+
finalizers := cfg.GetFinalizers()
236+
containerRuntimeMCPrefix := fmt.Sprintf("99-%s-generated-containerruntime", pool.Name)
237+
latestFinalizerIdx := -1
238+
maxFinalizerSuffix := -1
239+
for i, f := range finalizers {
240+
// skip the finalizer:
241+
// the finalizer is not a machineconfig
242+
// the finalizer is not generated by containerruntimeconfig controller of this pool
243+
if _, err := client.MachineconfigurationV1().MachineConfigs().Get(context.TODO(), f, metav1.GetOptions{}); err != nil {
244+
glog.Infof("skipping error: %v", fmt.Errorf("containerruntimeconfig %s has invalid finalizer: %s", cfg.Name, f))
245+
continue
246+
}
247+
if !strings.HasPrefix(f, containerRuntimeMCPrefix) {
248+
continue
249+
}
250+
arr := strings.Split(f, "-")
251+
suffix, err := strconv.Atoi(arr[len(arr)-1])
252+
// if the finalizer does not end with a number, make sure it is in the format 99-<poolname>-generated-containerruntime
253+
// otherwise, the ctrcfg contains invalid finalizer, do not generate managedKey from finalizers
254+
if err != nil {
255+
key, err := ctrlcommon.GetManagedKey(pool, nil, managedContainerRuntimeConfigKeyPrefix, "containerruntime", getManagedKeyCtrCfgDeprecated(pool))
256+
if err != nil {
257+
glog.Infof("skipping error: %v", fmt.Errorf("error generating managedKey for suffix %s: %v", key, err))
258+
continue
259+
}
260+
if f != key {
261+
glog.Infof("skipping error: %v", fmt.Errorf("finalizer format does not match the managedKubeletConfigKey: %s, want: %s", f, key))
262+
continue
263+
}
264+
// if the suffix is not a number, f is 99-<poolname>-generated-containerruntime
265+
suffix = 0
266+
}
267+
if suffix > maxFinalizerSuffix {
268+
maxFinalizerSuffix = suffix
269+
latestFinalizerIdx = i
270+
}
271+
}
272+
273+
if latestFinalizerIdx != -1 {
274+
glog.Infof("return containerruntimeconfig managedKey from finalizers %s", finalizers[latestFinalizerIdx])
275+
return finalizers[latestFinalizerIdx], nil
276+
}
277+
glog.Infof("skipping error generating managedKey for existing containerruntimeconfig %s from finalizers", cfg.Name)
278+
}
229279
suffixNum := 0
230280
// Go through the list of ctrcfg objects created and get the max suffix value currently created
231281
for _, item := range ctrcfgList {
@@ -253,6 +303,15 @@ func getManagedKeyCtrCfg(pool *mcfgv1.MachineConfigPool, client mcfgclientset.In
253303
return fmt.Sprintf("99-%s-generated-containerruntime-%s", pool.Name, strconv.Itoa(suffixNum+1)), nil
254304
}
255305

306+
func notLatestContainerRuntimeConfigInPool(ctrcfgList []mcfgv1.ContainerRuntimeConfig, cfg *mcfgv1.ContainerRuntimeConfig) bool {
307+
for _, crc := range ctrcfgList {
308+
if cfg.CreationTimestamp.Time.Before(crc.CreationTimestamp.Time) {
309+
return true
310+
}
311+
}
312+
return false
313+
}
314+
256315
// Deprecated: use getManagedKeyReg
257316
func getManagedKeyRegDeprecated(pool *mcfgv1.MachineConfigPool) string {
258317
return fmt.Sprintf("99-%s-%s-registries", pool.Name, pool.ObjectMeta.UID)

pkg/controller/kubelet-config/helpers.go

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import (
2020
"k8s.io/apimachinery/pkg/runtime/schema"
2121
"k8s.io/apimachinery/pkg/runtime/serializer"
2222
"k8s.io/apimachinery/pkg/util/yaml"
23+
"k8s.io/klog/v2"
2324
kubeletconfigv1beta1 "k8s.io/kubelet/config/v1beta1"
2425

2526
mcfgv1 "github.com/openshift/machine-config-operator/pkg/apis/machineconfiguration.openshift.io/v1"
@@ -258,11 +259,61 @@ func getManagedKubeletConfigKey(pool *mcfgv1.MachineConfigPool, client mcfgclien
258259
return ctrlcommon.GetManagedKey(pool, client, managedKubeletConfigKeyPrefix, "kubelet", getManagedKubeletConfigKeyDeprecated(pool))
259260
}
260261

261-
// If we are here, this means that a new kubelet config was created, so we have to calculate the suffix value for its MC name
262+
// If we are here, this means that
263+
// 1. a new kubelet config was created, so we have to calculate the suffix value for its MC name
264+
// 2. or this is an existing kubeletconfig did not get ctrlcommon.MCNameSuffixAnnotationKey set, so we have to set the MCNameSuffixAnnotationKey to the machineconfig suffix it was rendered to, assume for existing kubeletconfig, cfg.Finalizers with the largest suffix is the machine config the kcfg was rendered to
262265
// if the kubelet config is the only one in the list, mc name should not suffixed since cfg is the first kubelet config to be created
263266
if len(kcList) == 1 {
264267
return ctrlcommon.GetManagedKey(pool, client, managedKubeletConfigKeyPrefix, "kubelet", getManagedKubeletConfigKeyDeprecated(pool))
265268
}
269+
// if cfg is not a newly created kubeletconfig and did not get ctrlcommon.MCNameSuffixAnnotationKey
270+
// but has been rendered to a machineconfig, its len(cfg.Finalizers) > 0
271+
if notLatestKubeletConfigInPool(kcList, cfg) {
272+
finalizers := cfg.GetFinalizers()
273+
kubeletMCPrefix := fmt.Sprintf("99-%s-generated-kubelet", pool.Name)
274+
latestFinalizerIdx := -1
275+
maxFinalizerSuffix := -1
276+
for i, f := range finalizers {
277+
// skip the finalizer:
278+
// the finalizer is not a machineconfig
279+
// the finalizer is not generated by kubeletconfig controller of this pool
280+
if _, err := client.MachineconfigurationV1().MachineConfigs().Get(context.TODO(), f, metav1.GetOptions{}); err != nil {
281+
klog.Infof("skipping error: %v", fmt.Errorf("kubeletconfig %s has invalid finalizer: %s", cfg.Name, f))
282+
continue
283+
}
284+
if !strings.HasPrefix(f, kubeletMCPrefix) {
285+
continue
286+
}
287+
arr := strings.Split(f, "-")
288+
suffix, err := strconv.Atoi(arr[len(arr)-1])
289+
// if the finalizer does not end with a number, make sure it is in the format 99-<poolname>-generated-kubelet
290+
// otherwise, the kcfg contains invalid finalizer, do not generate managedKey from finalizers
291+
if err != nil {
292+
key, err := ctrlcommon.GetManagedKey(pool, nil, managedKubeletConfigKeyPrefix, "kubelet", getManagedKubeletConfigKeyDeprecated(pool))
293+
if err != nil {
294+
klog.Infof("skipping error: %v", fmt.Errorf("error generating managedKey for suffix %s: %v", key, err))
295+
continue
296+
}
297+
if f != key {
298+
klog.Infof("skipping error: %v", fmt.Errorf("finalizer format does not match the managedKubeletConfigKey: %s, want: %s", f, key))
299+
continue
300+
}
301+
// if the suffix is not a number, f is 99-<poolname>-generated-kubelet
302+
suffix = 0
303+
}
304+
if suffix > maxFinalizerSuffix {
305+
maxFinalizerSuffix = suffix
306+
latestFinalizerIdx = i
307+
}
308+
}
309+
310+
if latestFinalizerIdx != -1 {
311+
klog.Infof("return kubeletconfig managedKey from finalizers %s", finalizers[latestFinalizerIdx])
312+
return finalizers[latestFinalizerIdx], nil
313+
}
314+
klog.Infof("skipping error generating managedKey for existing kubeletconfig %s from finalizers", cfg.Name)
315+
}
316+
266317
suffixNum := 0
267318
// Go through the list of kubelet config objects created and get the max suffix value currently created
268319
for _, item := range kcList {
@@ -278,6 +329,7 @@ func getManagedKubeletConfigKey(pool *mcfgv1.MachineConfigPool, client mcfgclien
278329
}
279330
}
280331
}
332+
281333
// The max suffix value that we can go till with this logic is 9 - this means that a user can create up to 10 different kubelet config CRs.
282334
// However, if there is a kc-1 mapping to mc-1 and kc-2 mapping to mc-2 and the user deletes kc-1, it will delete mc-1 but
283335
// then if the user creates a kc-new it will map to mc-3. This is what we want as the latest kubelet config created should be higher in priority
@@ -290,6 +342,15 @@ func getManagedKubeletConfigKey(pool *mcfgv1.MachineConfigPool, client mcfgclien
290342
return fmt.Sprintf("%s-%s-generated-kubelet-%s", managedKubeletConfigKeyPrefix, pool.Name, strconv.Itoa(suffixNum+1)), nil
291343
}
292344

345+
func notLatestKubeletConfigInPool(kcList []mcfgv1.KubeletConfig, cfg *mcfgv1.KubeletConfig) bool {
346+
for _, kc := range kcList {
347+
if cfg.CreationTimestamp.Time.Before(kc.CreationTimestamp.Time) {
348+
return true
349+
}
350+
}
351+
return false
352+
}
353+
293354
func getManagedFeaturesKey(pool *mcfgv1.MachineConfigPool, client mcfgclientset.Interface) (string, error) {
294355
return ctrlcommon.GetManagedKey(pool, client, managedFeaturesKeyPrefix, "kubelet", getManagedFeaturesKeyDeprecated(pool))
295356
}

pkg/controller/kubelet-config/kubelet_config_controller.go

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -603,23 +603,23 @@ func (ctrl *Controller) syncKubeletConfig(key string) error {
603603
return ctrl.syncStatusOnly(cfg, err, "could not create MachineConfig from new Ignition config: %v", err)
604604
}
605605
mc.ObjectMeta.UID = uuid.NewUUID()
606-
_, ok := cfg.GetAnnotations()[ctrlcommon.MCNameSuffixAnnotationKey]
607-
arr := strings.Split(managedKey, "-")
608-
// the first managed key value 99-poolname-generated-kubelet does not have a suffix
609-
// set "" as suffix annotation to the kubelet config object
610-
if _, err := strconv.Atoi(arr[len(arr)-1]); err != nil && !ok {
611-
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, ""); err != nil {
612-
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for kubeletConfig")
613-
}
606+
}
607+
_, ok := cfg.GetAnnotations()[ctrlcommon.MCNameSuffixAnnotationKey]
608+
arr := strings.Split(managedKey, "-")
609+
// the first managed key value 99-poolname-generated-kubelet does not have a suffix
610+
// set "" as suffix annotation to the kubelet config object
611+
if _, err := strconv.Atoi(arr[len(arr)-1]); err != nil && !ok {
612+
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, ""); err != nil {
613+
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for kubeletConfig")
614614
}
615-
// If the MC name suffix annotation does not exist and the managed key value returned has a suffix, then add the MC name
616-
// suffix annotation and suffix value to the kubelet config object
617-
if len(arr) > 4 && !ok {
618-
_, err := strconv.Atoi(arr[len(arr)-1])
619-
if err == nil {
620-
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, arr[len(arr)-1]); err != nil {
621-
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for kubeletConfig")
622-
}
615+
}
616+
// If the MC name suffix annotation does not exist and the managed key value returned has a suffix, then add the MC name
617+
// suffix annotation and suffix value to the kubelet config object
618+
if len(arr) > 4 && !ok {
619+
_, err := strconv.Atoi(arr[len(arr)-1])
620+
if err == nil {
621+
if err := ctrl.addAnnotation(cfg, ctrlcommon.MCNameSuffixAnnotationKey, arr[len(arr)-1]); err != nil {
622+
return ctrl.syncStatusOnly(cfg, err, "could not update annotation for kubeletConfig")
623623
}
624624
}
625625
}

0 commit comments

Comments
 (0)