Merge pull request #52188 from luxas/kubeadm_fix_join_v17

Automatic merge from submit-queue (batch tested with PRs 50949, 52155, 52175, 52112, 52188)

kubeadm: Perform TLS Bootstrapping in kubeadm join for v1.7 kubelets

**What this PR does / why we need it**:

Partially reverts 9dc3a661d7
Performs the TLS Bootstrap if `kubeadm join` v1.8 is executed on a node with a kubelet v1.7.
Since the kubelet arguments for v1.7 (from the kubeadm dropin) expects a TLS bootstrapped kubeconfig, we still have to provide this functionality in kubeadm CLI v1.8 (as we support one minor version down)

**Which issue this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close that issue when PR gets merged)*: fixes #

fixes: https://github.com/kubernetes/kubeadm/issues/429

**Special notes for your reviewer**:

This is a required bug fix for v1.8

**Release note**:

```release-note
NONE
```
@kubernetes/sig-cluster-lifecycle-pr-reviews
pull/6/head
Kubernetes Submit Queue 2017-09-08 15:11:33 -07:00 committed by GitHub
commit 46c7ec209a
4 changed files with 99 additions and 1 deletions

View File

@ -29,6 +29,7 @@ go_library(
"//cmd/kubeadm/app/discovery:go_default_library",
"//cmd/kubeadm/app/features:go_default_library",
"//cmd/kubeadm/app/images:go_default_library",
"//cmd/kubeadm/app/node:go_default_library",
"//cmd/kubeadm/app/phases/addons/dns:go_default_library",
"//cmd/kubeadm/app/phases/addons/proxy:go_default_library",
"//cmd/kubeadm/app/phases/apiconfig:go_default_library",

View File

@ -20,7 +20,9 @@ import (
"fmt"
"io"
"io/ioutil"
"os/exec"
"path/filepath"
"strings"
"github.com/renstrom/dedent"
"github.com/spf13/cobra"
@ -32,6 +34,7 @@ import (
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
"k8s.io/kubernetes/cmd/kubeadm/app/discovery"
kubeadmnode "k8s.io/kubernetes/cmd/kubeadm/app/node"
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
@ -203,7 +206,31 @@ func (j *Join) Run(out io.Writer) error {
return err
}
client, err := kubeconfigutil.KubeConfigToClientSet(cfg)
if err != nil {
return err
}
if err := kubeadmnode.ValidateAPIServer(client); err != nil {
return err
}
kubeconfigFile := filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletBootstrapKubeConfigFileName)
// Depending on the kubelet version, we might perform the TLS bootstrap or not
kubeletVersionBytes, err := exec.Command("sh", "-c", "kubelet --version").Output()
// In case the command executed successfully and returned v1.7-something, we'll perform TLS Bootstrapping
// Otherwise, just assume v1.8
// TODO: In the beginning of the v1.9 cycle, we can remove the logic as we then don't support v1.7 anymore
if err == nil && strings.HasPrefix(string(kubeletVersionBytes), "Kubernetes v1.7") {
hostname := nodeutil.GetHostname(j.cfg.NodeName)
if err := kubeadmnode.PerformTLSBootstrap(cfg, hostname); err != nil {
return err
}
// As we now performed the TLS Bootstrap, change the filepath to be kubelet.conf instead of bootstrap-kubelet.conf
kubeconfigFile = filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)
}
// Write the bootstrap kubelet config file or the TLS-Boostrapped kubelet config file down to disk
if err := kubeconfigutil.WriteToDisk(kubeconfigFile, cfg); err != nil {
return err
}

View File

@ -8,10 +8,18 @@ load(
go_library(
name = "go_default_library",
srcs = ["validate.go"],
srcs = [
"csr.go",
"validate.go",
],
deps = [
"//cmd/kubeadm/app/util/kubeconfig:go_default_library",
"//pkg/kubelet/util/csr:go_default_library",
"//vendor/k8s.io/api/certificates/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/types:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
"//vendor/k8s.io/client-go/tools/clientcmd/api:go_default_library",
"//vendor/k8s.io/client-go/util/cert:go_default_library",
],
)

View File

@ -0,0 +1,62 @@
/*
Copyright 2016 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 node
import (
"fmt"
"k8s.io/apimachinery/pkg/types"
clientcmdapi "k8s.io/client-go/tools/clientcmd/api"
certutil "k8s.io/client-go/util/cert"
kubeconfigutil "k8s.io/kubernetes/cmd/kubeadm/app/util/kubeconfig"
"k8s.io/kubernetes/pkg/kubelet/util/csr"
)
// CSRContextAndUser defines the context to use for the client certs in the kubelet kubeconfig file
const CSRContextAndUser = "kubelet-csr"
// PerformTLSBootstrap executes a node certificate signing request.
func PerformTLSBootstrap(cfg *clientcmdapi.Config, hostName string) error {
client, err := kubeconfigutil.KubeConfigToClientSet(cfg)
if err != nil {
return err
}
fmt.Println("[csr] Created API client to obtain unique certificate for this node, generating keys and certificate signing request")
key, err := certutil.MakeEllipticPrivateKeyPEM()
if err != nil {
return fmt.Errorf("failed to generate private key [%v]", err)
}
cert, err := csr.RequestNodeCertificate(client.CertificatesV1beta1().CertificateSigningRequests(), key, types.NodeName(hostName))
if err != nil {
return fmt.Errorf("failed to request signed certificate from the API server [%v]", err)
}
fmt.Println("[csr] Received signed certificate from the API server, generating KubeConfig...")
cfg.AuthInfos[CSRContextAndUser] = &clientcmdapi.AuthInfo{
ClientKeyData: key,
ClientCertificateData: cert,
}
cfg.Contexts[CSRContextAndUser] = &clientcmdapi.Context{
AuthInfo: CSRContextAndUser,
Cluster: cfg.Contexts[cfg.CurrentContext].Cluster,
}
cfg.CurrentContext = CSRContextAndUser
return nil
}