Skip to content

Commit a57955c

Browse files
committed
Fix control-plane join failing with empty certificate key
The previous approach ran `kubeadm init phase upload-certs --upload-certs` and piped the output through `2>/dev/null | tail -1` to extract the certificate key. This broke because kubeadm prints informational `[upload-certs]` lines to stdout (not stderr), so `2>/dev/null` had no effect on them, and `tail -1` could grab a trailing empty line instead of the actual 64-char hex key. Fix by generating the key separately with `kubeadm certs certificate-key` which outputs only the key, then passing it explicitly to `kubeadm init phase upload-certs --upload-certs --certificate-key <key>`. Assisted-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent fdfdc86 commit a57955c

1 file changed

Lines changed: 6 additions & 5 deletions

File tree

internal/cluster/join.go

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -135,19 +135,20 @@ func (c *Cluster) Join(ctx context.Context, opts JoinOptions) error {
135135
// generateJoinCommand generates a fresh join command from the control plane
136136
func (c *Cluster) generateJoinCommand(ctx context.Context, cpSSHClient *ssh.Client, isControlPlane bool) (string, error) {
137137
if isControlPlane {
138-
// For control-plane nodes, we need to upload certificates and get the certificate key
138+
// Generate a certificate key, then upload certs encrypted with that key
139139
c.logger.Info("Uploading certificates for control-plane join...")
140-
certKeyOutput, err := cpSSHClient.Exec(ctx, "sudo kubeadm init phase upload-certs --upload-certs 2>/dev/null | tail -1")
140+
certKeyOutput, err := cpSSHClient.Exec(ctx, "sudo kubeadm certs certificate-key")
141141
if err != nil {
142-
return "", fmt.Errorf("failed to upload certificates: %w", err)
142+
return "", fmt.Errorf("failed to generate certificate key: %w", err)
143143
}
144-
145144
certificateKey := strings.TrimSpace(certKeyOutput)
146145
if certificateKey == "" {
147146
return "", fmt.Errorf("certificate key is empty")
148147
}
149148

150-
c.logger.Infof("Certificate key: %s", certificateKey)
149+
if _, err := cpSSHClient.Exec(ctx, fmt.Sprintf("sudo kubeadm init phase upload-certs --upload-certs --certificate-key %s", certificateKey)); err != nil {
150+
return "", fmt.Errorf("failed to upload certificates: %w", err)
151+
}
151152

152153
// Generate join command with control-plane flag
153154
output, err := cpSSHClient.Exec(ctx, "sudo kubeadm token create --print-join-command")

0 commit comments

Comments
 (0)