Commit 66095128 authored by xiangpengzhao's avatar xiangpengzhao

Regenerate API server serving certificates when upgrading.

parent 6b97376a
...@@ -162,7 +162,7 @@ func RunApply(flags *applyFlags) error { ...@@ -162,7 +162,7 @@ func RunApply(flags *applyFlags) error {
} }
// Upgrade RBAC rules and addons. // Upgrade RBAC rules and addons.
if err := upgrade.PerformPostUpgradeTasks(upgradeVars.client, internalcfg); err != nil { if err := upgrade.PerformPostUpgradeTasks(upgradeVars.client, internalcfg, flags.newK8sVersion); err != nil {
return fmt.Errorf("[upgrade/postupgrade] FATAL post-upgrade error: %v", err) return fmt.Errorf("[upgrade/postupgrade] FATAL post-upgrade error: %v", err)
} }
......
...@@ -17,6 +17,8 @@ limitations under the License. ...@@ -17,6 +17,8 @@ limitations under the License.
package upgrade package upgrade
import ( import (
"fmt"
"k8s.io/apimachinery/pkg/util/errors" "k8s.io/apimachinery/pkg/util/errors"
clientset "k8s.io/client-go/kubernetes" clientset "k8s.io/client-go/kubernetes"
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm" kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
...@@ -24,12 +26,14 @@ import ( ...@@ -24,12 +26,14 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy" "k8s.io/kubernetes/cmd/kubeadm/app/phases/addons/proxy"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo" "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/clusterinfo"
nodebootstraptoken "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node" nodebootstraptoken "k8s.io/kubernetes/cmd/kubeadm/app/phases/bootstraptoken/node"
certsphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
"k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig" "k8s.io/kubernetes/cmd/kubeadm/app/phases/uploadconfig"
"k8s.io/kubernetes/pkg/util/version"
) )
// PerformPostUpgradeTasks runs nearly the same functions as 'kubeadm init' would do // PerformPostUpgradeTasks runs nearly the same functions as 'kubeadm init' would do
// Note that the markmaster phase is left out, not needed, and no token is created as that doesn't belong to the upgrade // Note that the markmaster phase is left out, not needed, and no token is created as that doesn't belong to the upgrade
func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterConfiguration) error { func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterConfiguration, newK8sVer *version.Version) error {
errs := []error{} errs := []error{}
// Upload currently used configuration to the cluster // Upload currently used configuration to the cluster
...@@ -64,6 +68,19 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC ...@@ -64,6 +68,19 @@ func PerformPostUpgradeTasks(client clientset.Interface, cfg *kubeadmapi.MasterC
errs = append(errs, err) errs = append(errs, err)
} }
// Don't fail the upgrade phase if failing to determine to backup kube-apiserver cert and key.
if shouldBackup, err := shouldBackupAPIServerCertAndKey(newK8sVer); err != nil {
fmt.Printf("[postupgrade] WARNING: failed to determine to backup kube-apiserver cert and key: %v", err)
} else if shouldBackup {
// Don't fail the upgrade phase if failing to backup kube-apiserver cert and key.
if err := backupAPIServerCertAndKey(); err != nil {
fmt.Printf("[postupgrade] WARNING: failed to backup kube-apiserver cert and key: %v", err)
}
if err := certsphase.CreateAPIServerCertAndKeyFiles(cfg); err != nil {
errs = append(errs, err)
}
}
// Upgrade kube-dns and kube-proxy // Upgrade kube-dns and kube-proxy
if err := dns.EnsureDNSAddon(cfg, client); err != nil { if err := dns.EnsureDNSAddon(cfg, client); err != nil {
errs = append(errs, err) errs = append(errs, err)
......
/*
Copyright 2017 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package upgrade
import (
"crypto/x509"
"encoding/pem"
"fmt"
"io/ioutil"
"os"
"path/filepath"
"time"
"k8s.io/apimachinery/pkg/util/errors"
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/pkg/util/version"
)
var v190 = version.MustParseSemantic("v1.9.0")
// backupAPIServerCertAndKey backups the old cert and key of kube-apiserver to a specified directory.
func backupAPIServerCertAndKey() error {
subDir := "expired"
filesToMove := map[string]string{
filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerCertName): filepath.Join(kubeadmapiext.DefaultCertificatesDir, subDir, constants.APIServerCertName),
filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerKeyName): filepath.Join(kubeadmapiext.DefaultCertificatesDir, subDir, constants.APIServerKeyName),
}
return moveFiles(filesToMove)
}
// moveFiles moves files from one directory to another.
func moveFiles(files map[string]string) error {
filesToRecover := map[string]string{}
for from, to := range files {
if err := os.Rename(from, to); err != nil {
return rollbackFiles(filesToRecover, err)
}
filesToRecover[to] = from
}
return nil
}
// rollbackFiles moves the files back to the original directory.
func rollbackFiles(files map[string]string, originalErr error) error {
errs := []error{originalErr}
for from, to := range files {
if err := os.Rename(from, to); err != nil {
errs = append(errs, err)
}
}
return fmt.Errorf("couldn't roll back kube-apiserver cert and key! Got errors: %v", errors.NewAggregate(errs))
}
// shouldBackupAPIServerCertAndKey check if the new k8s version is at least 1.9.0
// and kube-apiserver will be expired in 60 days.
func shouldBackupAPIServerCertAndKey(newK8sVer *version.Version) (bool, error) {
if !newK8sVer.AtLeast(v190) {
return false, nil
}
data, err := ioutil.ReadFile(filepath.Join(kubeadmapiext.DefaultCertificatesDir, constants.APIServerCertName))
if err != nil {
return false, fmt.Errorf("failed to read kube-apiserver certificate from disk: %v", err)
}
block, _ := pem.Decode(data)
if block == nil {
return false, fmt.Errorf("expected the kube-apiserver certificate to be PEM encoded")
}
certs, err := x509.ParseCertificates(block.Bytes)
if err != nil {
return false, fmt.Errorf("unable to parse certificate data: %v", err)
}
if certs[0].NotAfter.Sub(time.Now()) < 60*24*time.Hour {
return true, nil
}
return false, nil
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment