Merge pull request #60852 from karan/kubeadm-cluster-name

Automatic merge from submit-queue (batch tested with PRs 58178, 62491, 60852). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

[kubeadm] Add support for clusterName in config file.

**What this PR does / why we need it**: Adds a `--cluster-name` arg to kubeadm init.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
See https://github.com/kubernetes/kube-deploy/issues/636
Code inspired by #52470

**Special notes for your reviewer**:

**Release note**:

```release-note
Adds --cluster-name to kubeadm init for specifying the cluster name in kubeconfig.
```
This commit is contained in:
Kubernetes Submit Queue 2018-04-12 15:40:10 -07:00 committed by GitHub
commit 38da981ab7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 60 additions and 36 deletions

View File

@ -55,6 +55,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
obj.CIImageRepository = ""
obj.UnifiedControlPlaneImage = "foo"
obj.FeatureGates = map[string]bool{"foo": true}
obj.ClusterName = "foo"
obj.APIServerExtraArgs = map[string]string{"foo": "foo"}
obj.APIServerExtraVolumes = []kubeadm.HostPathMount{{
Name: "foo",
@ -132,6 +133,7 @@ func Funcs(codecs runtimeserializer.CodecFactory) []interface{} {
obj.TLSBootstrapToken = "foo"
obj.Token = "foo"
obj.CRISocket = "foo"
obj.ClusterName = "foo"
},
}
}

View File

@ -124,6 +124,9 @@ type MasterConfiguration struct {
// FeatureGates enabled by the user.
FeatureGates map[string]bool
// The cluster name
ClusterName string
}
// API struct contains elements of API server address.
@ -236,6 +239,8 @@ type NodeConfiguration struct {
Token string
// CRISocket is used to retrieve container runtime info.
CRISocket string
// The cluster name
ClusterName string
// DiscoveryTokenCACertHashes specifies a set of public key pins to verify
// when token-based discovery is used. The root CA found during discovery

View File

@ -52,6 +52,8 @@ const (
DefaultManifestsDir = "/etc/kubernetes/manifests"
// DefaultCRISocket defines the default cri socket
DefaultCRISocket = "/var/run/dockershim.sock"
// DefaultClusterName defines the default cluster name
DefaultClusterName = "kubernetes"
// DefaultEtcdDataDir defines default location of etcd where static pods will save data to
DefaultEtcdDataDir = "/var/lib/etcd"
@ -136,6 +138,10 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
obj.Etcd.DataDir = DefaultEtcdDataDir
}
if obj.ClusterName == "" {
obj.ClusterName = DefaultClusterName
}
SetDefaultsEtcdSelfHosted(obj)
if features.Enabled(obj.FeatureGates, features.DynamicKubeletConfig) {
SetDefaults_KubeletConfiguration(obj)
@ -186,6 +192,9 @@ func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
Duration: DefaultDiscoveryTimeout,
}
}
if obj.ClusterName == "" {
obj.ClusterName = DefaultClusterName
}
}
// SetDefaultsEtcdSelfHosted sets defaults for self-hosted etcd if used

View File

@ -116,6 +116,9 @@ type MasterConfiguration struct {
// FeatureGates enabled by the user.
FeatureGates map[string]bool `json:"featureGates,omitempty"`
// The cluster name
ClusterName string `json:"clusterName,omitempty"`
}
// API struct contains elements of API server address.
@ -226,6 +229,8 @@ type NodeConfiguration struct {
Token string `json:"token"`
// CRISocket is used to retrieve container runtime info.
CRISocket string `json:"criSocket,omitempty"`
// ClusterName is the name for the cluster in kubeconfig.
ClusterName string `json:"clusterName,omitempty"`
// DiscoveryTokenCACertHashes specifies a set of public key pins to verify
// when token-based discovery is used. The root CA found during discovery

View File

@ -259,6 +259,7 @@ func autoConvert_v1alpha1_MasterConfiguration_To_kubeadm_MasterConfiguration(in
return err
}
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
@ -310,6 +311,7 @@ func autoConvert_kubeadm_MasterConfiguration_To_v1alpha1_MasterConfiguration(in
return err
}
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
out.ClusterName = in.ClusterName
return nil
}
@ -352,6 +354,7 @@ func autoConvert_v1alpha1_NodeConfiguration_To_kubeadm_NodeConfiguration(in *Nod
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Token = in.Token
out.CRISocket = in.CRISocket
out.ClusterName = in.ClusterName
out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes))
out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))
@ -373,6 +376,7 @@ func autoConvert_kubeadm_NodeConfiguration_To_v1alpha1_NodeConfiguration(in *kub
out.TLSBootstrapToken = in.TLSBootstrapToken
out.Token = in.Token
out.CRISocket = in.CRISocket
out.ClusterName = in.ClusterName
out.DiscoveryTokenCACertHashes = *(*[]string)(unsafe.Pointer(&in.DiscoveryTokenCACertHashes))
out.DiscoveryTokenUnsafeSkipCAVerification = in.DiscoveryTokenUnsafeSkipCAVerification
out.FeatureGates = *(*map[string]bool)(unsafe.Pointer(&in.FeatureGates))

View File

@ -51,9 +51,9 @@ var (
`+cmdutil.AlphaDisclaimer), kubeadmconstants.AdminKubeConfigFileName)
kubeletKubeconfigLongDesc = fmt.Sprintf(normalizer.LongDesc(`
Generates the kubeconfig file for the kubelet to use and saves it to %s file.
Generates the kubeconfig file for the kubelet to use and saves it to %s file.
Please note that this should *only* be used for bootstrapping purposes. After your control plane is up,
Please note that this should *only* be used for bootstrapping purposes. After your control plane is up,
you should request all kubelet credentials from the CSR API.
`+cmdutil.AlphaDisclaimer), filepath.Join(kubeadmconstants.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName))

View File

@ -43,7 +43,7 @@ func For(cfg *kubeadmapi.NodeConfiguration) (*clientcmdapi.Config, error) {
return kubeconfigutil.CreateWithToken(
clusterinfo.Server,
"kubernetes",
cfg.ClusterName,
TokenUser,
clusterinfo.CertificateAuthorityData,
cfg.TLSBootstrapToken,
@ -55,9 +55,9 @@ func GetValidatedClusterInfoObject(cfg *kubeadmapi.NodeConfiguration) (*clientcm
switch {
case len(cfg.DiscoveryFile) != 0:
if isHTTPSURL(cfg.DiscoveryFile) {
return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
return https.RetrieveValidatedClusterInfo(cfg.DiscoveryFile, cfg.ClusterName)
}
return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile)
return file.RetrieveValidatedClusterInfo(cfg.DiscoveryFile, cfg.ClusterName)
case len(cfg.DiscoveryToken) != 0:
return token.RetrieveValidatedClusterInfo(cfg)
default:

View File

@ -33,18 +33,18 @@ import (
// RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk
// securely to the API Server using the provided CA cert and
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
func RetrieveValidatedClusterInfo(filepath string) (*clientcmdapi.Cluster, error) {
func RetrieveValidatedClusterInfo(filepath, clustername string) (*clientcmdapi.Cluster, error) {
clusterinfo, err := clientcmd.LoadFromFile(filepath)
if err != nil {
return nil, err
}
return ValidateClusterInfo(clusterinfo)
return ValidateClusterInfo(clusterinfo, clustername)
}
// ValidateClusterInfo connects to the API Server and makes sure it can talk
// securely to the API Server using the provided CA cert and
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
func ValidateClusterInfo(clusterinfo *clientcmdapi.Config) (*clientcmdapi.Cluster, error) {
func ValidateClusterInfo(clusterinfo *clientcmdapi.Config, clustername string) (*clientcmdapi.Cluster, error) {
err := validateClusterInfoKubeConfig(clusterinfo)
if err != nil {
return nil, err
@ -57,7 +57,7 @@ func ValidateClusterInfo(clusterinfo *clientcmdapi.Config) (*clientcmdapi.Cluste
// We do this in order to not pick up other possible misconfigurations in the clusterinfo file
configFromClusterInfo := kubeconfigutil.CreateBasic(
defaultCluster.Server,
"kubernetes",
clustername,
"", // no user provided
defaultCluster.CertificateAuthorityData,
)

View File

@ -29,7 +29,7 @@ import (
// RetrieveValidatedClusterInfo connects to the API Server and makes sure it can talk
// securely to the API Server using the provided CA cert and
// optionally refreshes the cluster-info information from the cluster-info ConfigMap
func RetrieveValidatedClusterInfo(httpsURL string) (*clientcmdapi.Cluster, error) {
func RetrieveValidatedClusterInfo(httpsURL, clustername string) (*clientcmdapi.Cluster, error) {
client := &http.Client{Transport: netutil.SetOldTransportDefaults(&http.Transport{})}
response, err := client.Get(httpsURL)
if err != nil {
@ -46,5 +46,5 @@ func RetrieveValidatedClusterInfo(httpsURL string) (*clientcmdapi.Cluster, error
if err != nil {
return nil, err
}
return file.ValidateClusterInfo(clusterinfo)
return file.ValidateClusterInfo(clusterinfo, clustername)
}

View File

@ -61,7 +61,7 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
// The endpoint that wins the race and completes the task first gets its kubeconfig returned below
baseKubeConfig, err := runForEndpointsAndReturnFirst(cfg.DiscoveryTokenAPIServers, cfg.DiscoveryTimeout.Duration, func(endpoint string) (*clientcmdapi.Config, error) {
insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint)
insecureBootstrapConfig := buildInsecureBootstrapKubeConfig(endpoint, cfg.ClusterName)
clusterName := insecureBootstrapConfig.Contexts[insecureBootstrapConfig.CurrentContext].Cluster
insecureClient, err := kubeconfigutil.ToClientSet(insecureBootstrapConfig)
@ -128,7 +128,7 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
}
// Now that we know the proported cluster CA, connect back a second time validating with that CA
secureBootstrapConfig := buildSecureBootstrapKubeConfig(endpoint, clusterCABytes)
secureBootstrapConfig := buildSecureBootstrapKubeConfig(endpoint, clusterCABytes, clusterName)
secureClient, err := kubeconfigutil.ToClientSet(secureBootstrapConfig)
if err != nil {
return nil, err
@ -168,18 +168,17 @@ func RetrieveValidatedClusterInfo(cfg *kubeadmapi.NodeConfiguration) (*clientcmd
}
// buildInsecureBootstrapKubeConfig makes a KubeConfig object that connects insecurely to the API Server for bootstrapping purposes
func buildInsecureBootstrapKubeConfig(endpoint string) *clientcmdapi.Config {
func buildInsecureBootstrapKubeConfig(endpoint, clustername string) *clientcmdapi.Config {
masterEndpoint := fmt.Sprintf("https://%s", endpoint)
clusterName := "kubernetes"
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clusterName, BootstrapUser, []byte{})
bootstrapConfig.Clusters[clusterName].InsecureSkipTLSVerify = true
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clustername, BootstrapUser, []byte{})
bootstrapConfig.Clusters[clustername].InsecureSkipTLSVerify = true
return bootstrapConfig
}
// buildSecureBootstrapKubeConfig makes a KubeConfig object that connects securely to the API Server for bootstrapping purposes (validating with the specified CA)
func buildSecureBootstrapKubeConfig(endpoint string, caCert []byte) *clientcmdapi.Config {
func buildSecureBootstrapKubeConfig(endpoint string, caCert []byte, clustername string) *clientcmdapi.Config {
masterEndpoint := fmt.Sprintf("https://%s", endpoint)
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, "kubernetes", BootstrapUser, caCert)
bootstrapConfig := kubeconfigutil.CreateBasic(masterEndpoint, clustername, BootstrapUser, caCert)
return bootstrapConfig
}

View File

@ -119,7 +119,7 @@ func createKubeConfigFiles(outDir string, cfg *kubeadmapi.MasterConfiguration, k
}
// builds the KubeConfig object
config, err := buildKubeConfigFromSpec(spec)
config, err := buildKubeConfigFromSpec(spec, cfg.ClusterName)
if err != nil {
return err
}
@ -188,14 +188,14 @@ func getKubeConfigSpecs(cfg *kubeadmapi.MasterConfiguration) (map[string]*kubeCo
}
// buildKubeConfigFromSpec creates a kubeconfig object for the given kubeConfigSpec
func buildKubeConfigFromSpec(spec *kubeConfigSpec) (*clientcmdapi.Config, error) {
func buildKubeConfigFromSpec(spec *kubeConfigSpec, clustername string) (*clientcmdapi.Config, error) {
// If this kubeconfig should use token
if spec.TokenAuth != nil {
// create a kubeconfig with a token
return kubeconfigutil.CreateWithToken(
spec.APIServer,
"kubernetes",
clustername,
spec.ClientName,
certutil.EncodeCertPEM(spec.CACert),
spec.TokenAuth.Token,
@ -216,7 +216,7 @@ func buildKubeConfigFromSpec(spec *kubeConfigSpec) (*clientcmdapi.Config, error)
// create a kubeconfig with the client certs
return kubeconfigutil.CreateWithCerts(
spec.APIServer,
"kubernetes",
clustername,
spec.ClientName,
certutil.EncodeCertPEM(spec.CACert),
certutil.EncodePrivateKeyPEM(clientKey),
@ -293,7 +293,7 @@ func WriteKubeConfigWithClientCert(out io.Writer, cfg *kubeadmapi.MasterConfigur
},
}
return writeKubeConfigFromSpec(out, spec)
return writeKubeConfigFromSpec(out, spec, cfg.ClusterName)
}
// WriteKubeConfigWithToken writes a kubeconfig file - with a token as client authentication info - to the given writer.
@ -319,14 +319,14 @@ func WriteKubeConfigWithToken(out io.Writer, cfg *kubeadmapi.MasterConfiguration
},
}
return writeKubeConfigFromSpec(out, spec)
return writeKubeConfigFromSpec(out, spec, cfg.ClusterName)
}
// writeKubeConfigFromSpec creates a kubeconfig object from a kubeConfigSpec and writes it to the given writer.
func writeKubeConfigFromSpec(out io.Writer, spec *kubeConfigSpec) error {
func writeKubeConfigFromSpec(out io.Writer, spec *kubeConfigSpec, clustername string) error {
// builds the KubeConfig object
config, err := buildKubeConfigFromSpec(spec)
config, err := buildKubeConfigFromSpec(spec, clustername)
if err != nil {
return err
}

View File

@ -190,7 +190,7 @@ func TestBuildKubeConfigFromSpecWithClientAuth(t *testing.T) {
caCert, caKey := certstestutil.SetupCertificateAuthorithy(t)
// Executes buildKubeConfigFromSpec passing a KubeConfigSpec with a ClientAuth
config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "myClientName", "myOrg1", "myOrg2")
config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "myClientName", "test-cluster", "myOrg1", "myOrg2")
// Asserts spec data are propagated to the kubeconfig
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
@ -202,7 +202,7 @@ func TestBuildKubeConfigFromSpecWithTokenAuth(t *testing.T) {
caCert, _ := certstestutil.SetupCertificateAuthorithy(t)
// Executes buildKubeConfigFromSpec passing a KubeConfigSpec with a Token
config := setupdKubeConfigWithTokenAuth(t, caCert, "https://1.2.3.4:1234", "myClientName", "123456")
config := setupdKubeConfigWithTokenAuth(t, caCert, "https://1.2.3.4:1234", "myClientName", "123456", "test-cluster")
// Asserts spec data are propagated to the kubeconfig
kubeconfigtestutil.AssertKubeConfigCurrentCluster(t, config, "https://1.2.3.4:1234", caCert)
@ -216,9 +216,9 @@ func TestCreateKubeConfigFileIfNotExists(t *testing.T) {
anotherCaCert, anotherCaKey := certstestutil.SetupCertificateAuthorithy(t)
// build kubeconfigs (to be used to test kubeconfigs equality/not equality)
config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "myOrg1", "myOrg2")
configWithAnotherClusterCa := setupdKubeConfigWithClientAuth(t, anotherCaCert, anotherCaKey, "https://1.2.3.4:1234", "myOrg1", "myOrg2")
configWithAnotherClusterAddress := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://3.4.5.6:3456", "myOrg1", "myOrg2")
config := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1", "myOrg2")
configWithAnotherClusterCa := setupdKubeConfigWithClientAuth(t, anotherCaCert, anotherCaKey, "https://1.2.3.4:1234", "test-cluster", "myOrg1", "myOrg2")
configWithAnotherClusterAddress := setupdKubeConfigWithClientAuth(t, caCert, caKey, "https://3.4.5.6:3456", "myOrg1", "test-cluster", "myOrg2")
var tests = []struct {
existingKubeConfig *clientcmdapi.Config
@ -447,7 +447,7 @@ func TestWriteKubeConfig(t *testing.T) {
}
// setupdKubeConfigWithClientAuth is a test utility function that wraps buildKubeConfigFromSpec for building a KubeConfig object With ClientAuth
func setupdKubeConfigWithClientAuth(t *testing.T, caCert *x509.Certificate, caKey *rsa.PrivateKey, APIServer, clientName string, organizations ...string) *clientcmdapi.Config {
func setupdKubeConfigWithClientAuth(t *testing.T, caCert *x509.Certificate, caKey *rsa.PrivateKey, APIServer, clientName, clustername string, organizations ...string) *clientcmdapi.Config {
spec := &kubeConfigSpec{
CACert: caCert,
APIServer: APIServer,
@ -458,7 +458,7 @@ func setupdKubeConfigWithClientAuth(t *testing.T, caCert *x509.Certificate, caKe
},
}
config, err := buildKubeConfigFromSpec(spec)
config, err := buildKubeConfigFromSpec(spec, clustername)
if err != nil {
t.Fatal("buildKubeConfigFromSpec failed!")
}
@ -467,7 +467,7 @@ func setupdKubeConfigWithClientAuth(t *testing.T, caCert *x509.Certificate, caKe
}
// setupdKubeConfigWithClientAuth is a test utility function that wraps buildKubeConfigFromSpec for building a KubeConfig object With Token
func setupdKubeConfigWithTokenAuth(t *testing.T, caCert *x509.Certificate, APIServer, clientName, token string) *clientcmdapi.Config {
func setupdKubeConfigWithTokenAuth(t *testing.T, caCert *x509.Certificate, APIServer, clientName, token, clustername string) *clientcmdapi.Config {
spec := &kubeConfigSpec{
CACert: caCert,
APIServer: APIServer,
@ -477,7 +477,7 @@ func setupdKubeConfigWithTokenAuth(t *testing.T, caCert *x509.Certificate, APISe
},
}
config, err := buildKubeConfigFromSpec(spec)
config, err := buildKubeConfigFromSpec(spec, clustername)
if err != nil {
t.Fatal("buildKubeConfigFromSpec failed!")
}