Skip to content

Commit 9d48eae

Browse files
authored
fix!(kubeadm): cluster-info configmap reconciliation (#715)
This commit introduces a breaking change such as the removal of the default bootstrap token created by kubeadm on an idempotent basis. Signed-off-by: Dario Tranchitella <[email protected]>
1 parent f7eb53c commit 9d48eae

File tree

2 files changed

+97
-26
lines changed

2 files changed

+97
-26
lines changed

internal/resources/kubeadm_phases.go

+9-26
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ import (
1515
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
1616
"k8s.io/apimachinery/pkg/types"
1717
clientset "k8s.io/client-go/kubernetes"
18-
bootstraptokenv1 "k8s.io/kubernetes/cmd/kubeadm/app/apis/bootstraptoken/v1"
18+
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
1919
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
2020
"k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
2121
"sigs.k8s.io/controller-runtime/pkg/client"
@@ -24,7 +24,6 @@ import (
2424

2525
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
2626
"github.com/clastix/kamaji/internal/kubeadm"
27-
"github.com/clastix/kamaji/internal/resources/utils"
2827
)
2928

3029
type kubeadmPhase int
@@ -53,7 +52,7 @@ func (r *KubeadmPhase) GetWatchedObject() client.Object {
5352
case PhaseUploadConfigKubelet:
5453
return &corev1.ConfigMap{}
5554
case PhaseBootstrapToken:
56-
return &corev1.Secret{}
55+
return &corev1.ConfigMap{}
5756
case PhaseClusterAdminRBAC:
5857
return &rbacv1.ClusterRoleBinding{}
5958
default:
@@ -73,9 +72,9 @@ func (r *KubeadmPhase) GetPredicateFunc() func(obj client.Object) bool {
7372
}
7473
case PhaseBootstrapToken:
7574
return func(obj client.Object) bool {
76-
secret := obj.(*corev1.Secret) //nolint:forcetypeassert
75+
cm := obj.(*corev1.ConfigMap) //nolint:forcetypeassert
7776

78-
return secret.Type == "bootstrap.kubernetes.io/token" && secret.GetNamespace() == metav1.NamespaceSystem
77+
return cm.Name == bootstrapapi.ConfigMapClusterInfo && cm.GetNamespace() == metav1.NamespacePublic
7978
}
8079
case PhaseClusterAdminRBAC:
8180
return func(obj client.Object) bool {
@@ -130,7 +129,7 @@ func (r *KubeadmPhase) GetKubeadmFunction(ctx context.Context, tcp *kamajiv1alph
130129
return kubeadm.UploadKubeletConfig, nil
131130
case PhaseBootstrapToken:
132131
return func(client clientset.Interface, config *kubeadm.Configuration) ([]byte, error) {
133-
bootstrapTokensEnrichment(config.InitConfiguration.BootstrapTokens)
132+
config.InitConfiguration.BootstrapTokens = nil
134133

135134
return nil, kubeadm.BootstrapToken(client, config)
136135
}, nil
@@ -177,26 +176,6 @@ func (r *KubeadmPhase) GetKubeadmFunction(ctx context.Context, tcp *kamajiv1alph
177176
}
178177
}
179178

180-
func bootstrapTokensEnrichment(bootstrapTokens []bootstraptokenv1.BootstrapToken) {
181-
var bootstrapToken bootstraptokenv1.BootstrapToken
182-
if len(bootstrapTokens) > 0 {
183-
bootstrapToken = bootstrapTokens[0]
184-
}
185-
186-
enrichBootstrapToken(&bootstrapToken)
187-
bootstrapTokens[0] = bootstrapToken
188-
}
189-
190-
func enrichBootstrapToken(bootstrapToken *bootstraptokenv1.BootstrapToken) {
191-
if bootstrapToken.Token == nil {
192-
bootstrapToken.Token = &bootstraptokenv1.BootstrapTokenString{}
193-
}
194-
195-
if bootstrapToken.Token.ID == "" {
196-
bootstrapToken.Token.ID = fmt.Sprintf("%s.%s", utils.RandomString(6), utils.RandomString(16))
197-
}
198-
}
199-
200179
func (r *KubeadmPhase) GetClient() client.Client {
201180
return r.Client
202181
}
@@ -240,5 +219,9 @@ func (r *KubeadmPhase) GetStatus(tenantControlPlane *kamajiv1alpha1.TenantContro
240219
func (r *KubeadmPhase) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
241220
logger := log.FromContext(ctx, "resource", r.GetName(), "phase", r.Phase.String())
242221

222+
if r.Phase == PhaseBootstrapToken {
223+
return KubeadmBootstrap(ctx, r, logger, tenantControlPlane)
224+
}
225+
243226
return KubeadmPhaseCreate(ctx, r, logger, tenantControlPlane)
244227
}

internal/resources/kubeadm_utils.go

+88
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,12 @@ import (
88

99
"github.com/go-logr/logr"
1010
"github.com/pkg/errors"
11+
corev1 "k8s.io/api/core/v1"
12+
k8serrors "k8s.io/apimachinery/pkg/api/errors"
13+
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
14+
"k8s.io/apimachinery/pkg/types"
1115
clientset "k8s.io/client-go/kubernetes"
16+
bootstrapapi "k8s.io/cluster-bootstrap/token/api"
1217
"sigs.k8s.io/controller-runtime/pkg/client"
1318
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
1419

@@ -81,6 +86,89 @@ func GetKubeadmManifestDeps(ctx context.Context, client client.Client, tenantCon
8186
return tenantClient, config, nil
8287
}
8388

89+
func KubeadmBootstrap(ctx context.Context, r KubeadmPhaseResource, logger logr.Logger, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
90+
var checksum string
91+
92+
tntClient, err := utilities.GetTenantClient(ctx, r.GetClient(), tenantControlPlane)
93+
if err != nil {
94+
logger.Error(err, "cannot generate tenant client")
95+
96+
return controllerutil.OperationResultNone, err
97+
}
98+
99+
var clusterInfo corev1.ConfigMap
100+
if cmErr := tntClient.Get(ctx, types.NamespacedName{Name: bootstrapapi.ConfigMapClusterInfo, Namespace: metav1.NamespacePublic}, &clusterInfo); cmErr != nil {
101+
if !k8serrors.IsNotFound(cmErr) {
102+
logger.Error(cmErr, "cannot retrieve cluster-info ConfigMap")
103+
}
104+
}
105+
106+
status, err := r.GetStatus(tenantControlPlane)
107+
if err != nil {
108+
logger.Error(err, "cannot retrieve status")
109+
110+
return controllerutil.OperationResultNone, err
111+
}
112+
113+
if status != nil {
114+
checksum = utilities.CalculateMapChecksum(clusterInfo.Data)
115+
116+
if checksum == status.GetChecksum() {
117+
r.SetKubeadmConfigChecksum(checksum)
118+
119+
return controllerutil.OperationResultNone, nil
120+
}
121+
}
122+
123+
kubeconfig, err := utilities.GetTenantKubeconfig(ctx, r.GetClient(), tenantControlPlane)
124+
if err != nil {
125+
logger.Error(err, "cannot retrieve kubeconfig configuration")
126+
127+
return controllerutil.OperationResultNone, err
128+
}
129+
130+
config, err := getStoredKubeadmConfiguration(ctx, r.GetClient(), r.GetTmpDirectory(), tenantControlPlane)
131+
if err != nil {
132+
logger.Error(err, "cannot retrieve kubeadm configuration")
133+
134+
return controllerutil.OperationResultNone, err
135+
}
136+
137+
config.Kubeconfig = *kubeconfig
138+
139+
fun, err := r.GetKubeadmFunction(ctx, tenantControlPlane)
140+
if err != nil {
141+
logger.Error(err, "cannot retrieve kubeadm function")
142+
143+
return controllerutil.OperationResultNone, err
144+
}
145+
146+
client, err := utilities.GetTenantClientSet(ctx, r.GetClient(), tenantControlPlane)
147+
if err != nil {
148+
logger.Error(err, "cannot generate tenant client")
149+
150+
return controllerutil.OperationResultNone, err
151+
}
152+
153+
if _, err = fun(client, config); err != nil {
154+
logger.Error(err, "kubeadm function failed")
155+
156+
return controllerutil.OperationResultNone, err
157+
}
158+
159+
if status == nil {
160+
return controllerutil.OperationResultNone, nil
161+
}
162+
163+
r.SetKubeadmConfigChecksum(checksum)
164+
165+
if checksum == "" {
166+
return controllerutil.OperationResultCreated, nil
167+
}
168+
169+
return controllerutil.OperationResultUpdated, nil
170+
}
171+
84172
func KubeadmPhaseCreate(ctx context.Context, r KubeadmPhaseResource, logger logr.Logger, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
85173
config, err := getStoredKubeadmConfiguration(ctx, r.GetClient(), r.GetTmpDirectory(), tenantControlPlane)
86174
if err != nil {

0 commit comments

Comments
 (0)