renew expired kubeadm certs

pull/16249/head
Steven Powell 2023-04-10 10:26:58 -07:00
parent 795b706adf
commit 9f9358931a
13 changed files with 77 additions and 9 deletions

View File

@ -19,17 +19,12 @@ package bsutil
import (
"os/exec"
"path"
"github.com/pkg/errors"
"k8s.io/minikube/pkg/minikube/assets"
"k8s.io/minikube/pkg/minikube/command"
"k8s.io/minikube/pkg/minikube/vmpath"
)
// KubeadmYamlPath is the path to the kubeadm configuration
var KubeadmYamlPath = path.Join(vmpath.GuestEphemeralDir, "kubeadm.yaml")
const (
// KubeletServiceFile is the file for the systemd kubelet.service
KubeletServiceFile = "/lib/systemd/system/kubelet.service"

View File

@ -140,6 +140,10 @@ func SetupCerts(cmd command.Runner, k8s config.ClusterConfig, n config.Node) err
if err := installCertSymlinks(cmd, caCerts); err != nil {
return errors.Wrapf(err, "certificate symlinks")
}
if err := generateKubeadmCerts(cmd, k8s); err != nil {
return fmt.Errorf("failed to renew kubeadm certs: %v", err)
}
return nil
}
@ -344,6 +348,33 @@ func generateProfileCerts(cfg config.ClusterConfig, n config.Node, ccs CACerts,
return xfer, nil
}
func generateKubeadmCerts(cmd command.Runner, cc config.ClusterConfig) error {
needsRefresh := false
certs := []string{"apiserver-etcd-client", "apiserver-kubelet-client", "etcd-server", "etcd-healthcheck-client", "etcd-peer", "front-proxy-client"}
for _, cert := range certs {
certPath := []string{vmpath.GuestPersistentDir, "certs"}
// certs starting with "etcd-" are in the "etcd" dir
// ex: etcd-server => etcd/server
if strings.HasPrefix(cert, "etcd-") {
certPath = append(certPath, "etcd")
}
certPath = append(certPath, strings.TrimPrefix(cert, "etcd-")+".crt")
if !isKubeadmCertValid(cmd, path.Join(certPath...)) {
needsRefresh = true
}
}
if !needsRefresh {
return nil
}
out.WarningT("kubeadm certificates have expired. Generating new ones...")
kubeadmPath := path.Join(vmpath.GuestPersistentDir, "binaries", cc.KubernetesConfig.KubernetesVersion)
bashCmd := fmt.Sprintf("sudo env PATH=\"%s:$PATH\" kubeadm certs renew all --config %s", kubeadmPath, constants.KubeadmYamlPath)
if _, err := cmd.RunCmd(exec.Command("/bin/bash", "-c", bashCmd)); err != nil {
return fmt.Errorf("failed to renew kubeadm certs: %v", err)
}
return nil
}
// isValidPEMCertificate checks whether the input file is a valid PEM certificate (with at least one CERTIFICATE block)
func isValidPEMCertificate(filePath string) (bool, error) {
fileBytes, err := os.ReadFile(filePath)
@ -545,3 +576,31 @@ func isValid(certPath, keyPath string) bool {
return true
}
func isKubeadmCertValid(cmd command.Runner, certPath string) bool {
rr, err := cmd.RunCmd(exec.Command("cat", certPath))
if err != nil {
klog.Infof("failed to read cert file %s: %v", certPath, err)
// if reading the cert failed it's likely first start and it doesn't exist yet so mark as valid
return true
}
certData, _ := pem.Decode(rr.Stdout.Bytes())
if certData == nil {
klog.Infof("failed to decode cert file %s", certPath)
return false
}
cert, err := x509.ParseCertificate(certData.Bytes)
if err != nil {
klog.Infof("failed to parse cert file %s: %v\n", certPath, err)
return false
}
if cert.NotAfter.Before(time.Now()) {
klog.Infof("cert expired %s: expiration: %s, now: %s", certPath, cert.NotAfter, time.Now())
return false
}
return true
}

View File

@ -238,7 +238,7 @@ func (k *Bootstrapper) init(cfg config.ClusterConfig) error {
return errors.Wrap(err, "clearing stale configs")
}
conf := bsutil.KubeadmYamlPath
conf := constants.KubeadmYamlPath
ctx, cancel := context.WithTimeout(context.Background(), initTimeoutMinutes*time.Minute)
defer cancel()
kr, kw := io.Pipe()
@ -429,7 +429,7 @@ func (k *Bootstrapper) StartCluster(cfg config.ClusterConfig) error {
// Fall-through to init
}
conf := bsutil.KubeadmYamlPath
conf := constants.KubeadmYamlPath
if _, err := k.c.RunCmd(exec.Command("sudo", "cp", conf+".new", conf)); err != nil {
return errors.Wrap(err, "cp")
}
@ -678,7 +678,7 @@ func (k *Bootstrapper) restartControlPlane(cfg config.ClusterConfig) error {
}
// If the cluster is running, check if we have any work to do.
conf := bsutil.KubeadmYamlPath
conf := constants.KubeadmYamlPath
if !k.needsReconfigure(conf, hostname, port, client, cfg.KubernetesConfig.KubernetesVersion) {
klog.Infof("Taking a shortcut, as the cluster seems to be properly configured")
@ -982,7 +982,7 @@ func (k *Bootstrapper) UpdateNode(cfg config.ClusterConfig, n config.Node, r cru
}
if n.ControlPlane {
files = append(files, assets.NewMemoryAssetTarget(kubeadmCfg, bsutil.KubeadmYamlPath+".new", "0640"))
files = append(files, assets.NewMemoryAssetTarget(kubeadmCfg, constants.KubeadmYamlPath+".new", "0640"))
}
// Installs compatibility shims for non-systemd environments

View File

@ -18,11 +18,13 @@ package constants
import (
"errors"
"path"
"path/filepath"
"time"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
"k8s.io/minikube/pkg/minikube/vmpath"
)
var (
@ -203,4 +205,7 @@ var (
// ErrMachineMissing is returned when virtual machine does not exist due to user interrupt cancel(i.e. Ctrl + C)
ErrMachineMissing = errors.New("machine does not exist")
// KubeadmYamlPath is the path to the kubeadm configuration
KubeadmYamlPath = path.Join(vmpath.GuestEphemeralDir, "kubeadm.yaml")
)

View File

@ -980,6 +980,7 @@
"invalid kubernetes version": "Invalide Kubernetes Version",
"json encoding failure": "",
"keep the kube-context active after cluster is stopped. Defaults to false.": "Halte den kube-context aktiv, wenn der Cluster gestoppt ist. Default: false",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "kubeadm erkannte einen TCP Port Konflikt mit anderen Prozessen: wahrscheinlich eine andere lokale Kubernetes Installation. Führe lsof -p\u003cport\u003e aus um den Prozess zu finden und zu töten",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "Konfiguration von Kubectl und minikube wird in {{.home_folder}} gespeichert",
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "kubectl nicht gefunden. Falls Sie es benötigen, versuchen Sie 'minikube kubectl -- get pods -A' aufzurufen",

View File

@ -976,6 +976,7 @@
"invalid kubernetes version": "",
"json encoding failure": "",
"keep the kube-context active after cluster is stopped. Defaults to false.": "",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "La configuración de kubectl y de minikube se almacenará en {{.home_folder}}",
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "",

View File

@ -961,6 +961,7 @@
"invalid kubernetes version": "version kubernetes invalide",
"json encoding failure": "échec de l'encodage json",
"keep the kube-context active after cluster is stopped. Defaults to false.": "garder le kube-context actif après l'arrêt du cluster. La valeur par défaut est false.",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "kubeadm a détecté un conflit de port TCP avec un autre processus : probablement une autre installation locale de Kubernetes. Exécutez lsof -p\u003cport\u003e pour trouver le processus et le tuer",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "Les configurations kubectl et minikube seront stockées dans le dossier {{.home_folder}}.",
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "kubectl introuvable. Si vous en avez besoin, essayez : 'minikube kubectl -- get pods -A'",

View File

@ -918,6 +918,7 @@
"invalid kubernetes version": "無効な Kubernetes バージョン",
"json encoding failure": "json エンコード失敗",
"keep the kube-context active after cluster is stopped. Defaults to false.": "クラスター停止後に kube-context をアクティブのままにします。デフォルトは false です。",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "kubeadm が他のプロセス (おそらくローカルにインストールされた他の Kubernetes) との TCP ポート衝突を検出しました。 lsof -p\u003cport\u003e を実行してそのプロセスを特定し、停止してください",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "kubectl と minikube の構成は {{.home_folder}} に保存されます",
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "kubectl が見つかりません。kubectl が必要な場合、'minikube kubectl -- get pods -A' を試してください",

View File

@ -980,6 +980,7 @@
"invalid kubernetes version": "",
"json encoding failure": "",
"keep the kube-context active after cluster is stopped. Defaults to false.": "",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "kubectl 과 minikube 환경 정보는 {{.home_folder}} 에 저장될 것입니다",
"kubectl not found in PATH, but is required for the dashboard. Installation guide: https://kubernetes.io/docs/tasks/tools/install-kubectl/": "kubectl 이 PATH 에 없습니다, 하지만 이는 대시보드에서 필요로 합니다. 설치 가이드:https://kubernetes.io/docs/tasks/tools/install-kubectl/",

View File

@ -988,6 +988,7 @@
"invalid kubernetes version": "Nieprawidłowa wersja Kubernetesa",
"json encoding failure": "",
"keep the kube-context active after cluster is stopped. Defaults to false.": "",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "konfiguracja minikube i kubectl będzie przechowywana w katalogu {{.home_folder}}",
"kubectl not found in PATH, but is required for the dashboard. Installation guide: https://kubernetes.io/docs/tasks/tools/install-kubectl/": "kubectl nie zostało odnalezione w zmiennej środowiskowej ${PATH}. Instrukcja instalacji: https://kubernetes.io/docs/tasks/tools/install-kubectl/",

View File

@ -908,6 +908,7 @@
"invalid kubernetes version": "",
"json encoding failure": "",
"keep the kube-context active after cluster is stopped. Defaults to false.": "",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "",
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "",

View File

@ -908,6 +908,7 @@
"invalid kubernetes version": "",
"json encoding failure": "",
"keep the kube-context active after cluster is stopped. Defaults to false.": "",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "",
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "",

View File

@ -1096,6 +1096,7 @@
"invalid kubernetes version": "",
"json encoding failure": "",
"keep the kube-context active after cluster is stopped. Defaults to false.": "",
"kubeadm certificates have expired. Generating new ones...": "",
"kubeadm detected a TCP port conflict with another process: probably another local Kubernetes installation. Run lsof -p\u003cport\u003e to find the process and kill it": "kubeadm 检测一个到与其他进程的 TCP 端口冲突:或许是另外的本地安装的 Kubernetes 导致。执行 lsof -p\u003cport\u003e 查找并杀死这些进程",
"kubectl and minikube configuration will be stored in {{.home_folder}}": "kubectl 和 minikube 配置将存储在 {{.home_folder}} 中",
"kubectl not found. If you need it, try: 'minikube kubectl -- get pods -A'": "",