Skip to content
Merged
Show file tree
Hide file tree
Changes from 4 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
############# builder #############
FROM golang:1.23.3 AS builder
FROM golang:1.24.1 AS builder

WORKDIR /go/src/github.com/gardener/machine-controller-manager
COPY . .
Expand Down
3 changes: 1 addition & 2 deletions pkg/controller/machine.go
Original file line number Diff line number Diff line change
Expand Up @@ -465,8 +465,7 @@ func (c *controller) machineCreate(machine *v1alpha1.Machine, driver driver.Driv
c.updateMachineStatus(machine, lastOperation, currentStatus)

var actualProviderID, nodeName string

err := c.addBootstrapTokenToUserData(machine.Name, driver)
err := c.addBootstrapTokenToUserData(machine.Spec.NodeTemplateSpec.Labels, machine.Name, driver)
if err != nil {
klog.Errorf("Error while creating bootstrap token for machine %s: %s", machine.Name, err.Error())
lastOperation := v1alpha1.LastOperation{
Expand Down
114 changes: 83 additions & 31 deletions pkg/controller/machine_bootstrap_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ package controller
import (
"crypto/rand"
"encoding/hex"
"fmt"
"math/big"
"sort"
"strings"
"time"

Expand All @@ -36,12 +38,27 @@ import (
)

const placeholder = "<<BOOTSTRAP_TOKEN>>"
const maxRetriesGetBootstrapToken = 5
const retryIntervalBootstrapToken = 3 * time.Second

func (c *controller) addBootstrapTokenToUserData(machineName string, driver driver.Driver) error {
func (c *controller) addBootstrapTokenToUserData(machineLabels map[string]string, machineName string, driver driver.Driver) error {
userData := driver.GetUserData()
klog.V(4).Infof("Creating bootstrap token!")
bootstrapTokenSecret, err := c.getBootstrapTokenOrCreateIfNotExist(machineName)
var bootstrapTokenSecret *v1.Secret
var err error
for attempt := 1; attempt <= maxRetriesGetBootstrapToken; attempt++ {
bootstrapTokenSecret, err = c.getBootstrapTokenOrCreateIfNotExist(machineLabels, machineName)
if err == nil {
break
}

klog.Warningf("attempt %d/%d: failed to get or create bootstrap token: %v", attempt, maxRetriesGetBootstrapToken, err)
if attempt < maxRetriesGetBootstrapToken {
time.Sleep(retryIntervalBootstrapToken)
}
}
if err != nil {
klog.Errorf("all %d attempts failed to get or create bootstrap token: %v", maxRetriesGetBootstrapToken, err)
return err
}

Expand All @@ -56,41 +73,76 @@ func (c *controller) addBootstrapTokenToUserData(machineName string, driver driv
return nil
}

func (c *controller) getBootstrapTokenOrCreateIfNotExist(machineName string) (secret *v1.Secret, err error) {
tokenID, secretName := getTokenIDAndSecretName(machineName)

secret, err = c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).Get(secretName, metav1.GetOptions{})
func (c *controller) getBootstrapTokenOrCreateIfNotExist(machineLabels map[string]string, machineName string) (secret *v1.Secret, err error) {
value, ok := machineLabels["node.deckhouse.io/group"]
if !ok || value == "" {
klog.Warningf("failed to get nodegroup name from spec node.deckhouse.io/group of machine: '%s'\nCreating bootstrap token by MCM!", machineName)
mcmToken, err := c.createBootstrapToken(machineName)
if err != nil {
return nil, err
}
return mcmToken, nil
}
labelSelector := fmt.Sprintf("node-manager.deckhouse.io/node-group=%s", value)
secretListNodeManager, err := c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).List(metav1.ListOptions{
LabelSelector: labelSelector,
})
if err != nil {
if apierrors.IsNotFound(err) {
bootstrapTokenSecretKey, err := generateRandomStringFromCharset(16, "0123456789abcdefghijklmnopqrstuvwxyz")
if err != nil {
return nil, err
}
data := map[string][]byte{
bootstraptokenapi.BootstrapTokenDescriptionKey: []byte("A bootstrap token generated by MachineControllManager."),
bootstraptokenapi.BootstrapTokenIDKey: []byte(tokenID),
bootstraptokenapi.BootstrapTokenSecretKey: []byte(bootstrapTokenSecretKey),
bootstraptokenapi.BootstrapTokenExpirationKey: []byte(metav1.Now().Add(c.safetyOptions.MachineCreationTimeout.Duration).Format(time.RFC3339)),
bootstraptokenapi.BootstrapTokenUsageAuthentication: []byte("true"),
bootstraptokenapi.BootstrapTokenUsageSigningKey: []byte("true"),
bootstraptokenapi.BootstrapTokenExtraGroupsKey: []byte(c.bootstrapTokenAuthExtraGroups),
}

secret = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: metav1.NamespaceSystem,
},
Type: bootstraptokenapi.SecretTypeBootstrapToken,
Data: data,
klog.Warningf("failed to list secrets in namespace kube-system created by node-manager: '%v'\nCreating bootstrap token by MCM!", err)
mcmToken, err := c.createBootstrapToken(machineName)
if err != nil {
return nil, err
}
return mcmToken, nil
}
if len(secretListNodeManager.Items) != 0 {
var filteredSecrets []*v1.Secret
for i := range secretListNodeManager.Items {
if strings.HasPrefix(secretListNodeManager.Items[i].Name, bootstraptokenapi.BootstrapTokenSecretPrefix) {
filteredSecrets = append(filteredSecrets, &secretListNodeManager.Items[i])
}

return c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret)
}
sort.Slice(filteredSecrets, func(i, j int) bool {
timeI := filteredSecrets[i].CreationTimestamp.Time
timeJ := filteredSecrets[j].CreationTimestamp.Time
return timeI.After(timeJ)
})
return filteredSecrets[0], nil
}
klog.Warningf("failed to get bootstrap token created by node-manager\nCreating bootstrap token from MCM!")
mcmToken, err := c.createBootstrapToken(machineName)
if err != nil {
return nil, err
}
return mcmToken, nil
}

func (c *controller) createBootstrapToken(machineName string) (secret *v1.Secret, err error) {
tokenID, secretName := getTokenIDAndSecretName(machineName)
bootstrapTokenSecretKey, err := generateRandomStringFromCharset(16, "0123456789abcdefghijklmnopqrstuvwxyz")
if err != nil {
return nil, err
}
data := map[string][]byte{
bootstraptokenapi.BootstrapTokenDescriptionKey: []byte("A bootstrap token generated by MachineControllManager."),
bootstraptokenapi.BootstrapTokenIDKey: []byte(tokenID),
bootstraptokenapi.BootstrapTokenSecretKey: []byte(bootstrapTokenSecretKey),
bootstraptokenapi.BootstrapTokenExpirationKey: []byte(metav1.Now().Add(c.safetyOptions.MachineCreationTimeout.Duration).Format(time.RFC3339)),
bootstraptokenapi.BootstrapTokenUsageAuthentication: []byte("true"),
bootstraptokenapi.BootstrapTokenUsageSigningKey: []byte("true"),
bootstraptokenapi.BootstrapTokenExtraGroupsKey: []byte(c.bootstrapTokenAuthExtraGroups),
}

secret = &v1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: secretName,
Namespace: metav1.NamespaceSystem,
},
Type: bootstraptokenapi.SecretTypeBootstrapToken,
Data: data,
}

return secret, nil
return c.targetCoreClient.CoreV1().Secrets(metav1.NamespaceSystem).Create(secret)
}

func (c *controller) deleteBootstrapToken(machineName string) error {
Expand Down
Loading