mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-23 11:50:44 +00:00
Add configuration item to allow kubeadm join to use a dns name pointing to control plane
This commit is contained in:
parent
6535c955bf
commit
2fd29a0406
@ -121,8 +121,10 @@ type MasterConfiguration struct {
|
||||
|
||||
// API struct contains elements of API server address.
|
||||
type API struct {
|
||||
// AdvertiseAddress sets the address for the API server to advertise.
|
||||
// AdvertiseAddress sets the IP address for the API server to advertise.
|
||||
AdvertiseAddress string
|
||||
// ControlPlaneEndpoint sets the DNS address for the API server
|
||||
ControlPlaneEndpoint string
|
||||
// BindPort sets the secure port for the API Server to bind to.
|
||||
// Defaults to 6443.
|
||||
BindPort int32
|
||||
|
@ -113,8 +113,10 @@ type MasterConfiguration struct {
|
||||
|
||||
// API struct contains elements of API server address.
|
||||
type API struct {
|
||||
// AdvertiseAddress sets the address for the API server to advertise.
|
||||
// AdvertiseAddress sets the IP address for the API server to advertise.
|
||||
AdvertiseAddress string `json:"advertiseAddress"`
|
||||
// ControlPlaneEndpoint sets the DNS address for the API server
|
||||
ControlPlaneEndpoint string `json:"controlPlaneEndpoint"`
|
||||
// BindPort sets the secure port for the API Server to bind to.
|
||||
// Defaults to 6443.
|
||||
BindPort int32 `json:"bindPort"`
|
||||
|
@ -351,7 +351,7 @@ func ValidateAPIEndpoint(c *kubeadm.MasterConfiguration, fldPath *field.Path) fi
|
||||
|
||||
endpoint, err := kubeadmutil.GetMasterEndpoint(c)
|
||||
if err != nil {
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, endpoint, "Invalid API Endpoint"))
|
||||
allErrs = append(allErrs, field.Invalid(fldPath, endpoint, err.Error()))
|
||||
}
|
||||
return allErrs
|
||||
}
|
||||
|
@ -143,7 +143,7 @@ func getControlPlaneSubCommands(outDir, defaultKubernetesVersion string) []*cobr
|
||||
cmd.Flags().StringVar(&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion, `Choose a specific Kubernetes version for the control plane`)
|
||||
|
||||
if properties.use == "all" || properties.use == "apiserver" {
|
||||
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address or DNS name the API server is accessible on")
|
||||
cmd.Flags().StringVar(&cfg.API.AdvertiseAddress, "apiserver-advertise-address", cfg.API.AdvertiseAddress, "The IP address of the API server is accessible on")
|
||||
cmd.Flags().Int32Var(&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort, "The port the API server is accessible on")
|
||||
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "The range of IP address used for service VIPs")
|
||||
cmd.Flags().StringVar(&featureGatesString, "feature-gates", featureGatesString, "A set of key=value pairs that describe feature gates for various features. "+
|
||||
|
@ -41,6 +41,7 @@ func TestPrintConfiguration(t *testing.T) {
|
||||
api:
|
||||
advertiseAddress: ""
|
||||
bindPort: 0
|
||||
controlPlaneEndpoint: ""
|
||||
auditPolicy:
|
||||
logDir: ""
|
||||
path: ""
|
||||
@ -78,6 +79,7 @@ func TestPrintConfiguration(t *testing.T) {
|
||||
api:
|
||||
advertiseAddress: ""
|
||||
bindPort: 0
|
||||
controlPlaneEndpoint: ""
|
||||
auditPolicy:
|
||||
logDir: ""
|
||||
path: ""
|
||||
@ -120,6 +122,7 @@ func TestPrintConfiguration(t *testing.T) {
|
||||
api:
|
||||
advertiseAddress: ""
|
||||
bindPort: 0
|
||||
controlPlaneEndpoint: ""
|
||||
auditPolicy:
|
||||
logDir: ""
|
||||
path: ""
|
||||
|
@ -548,5 +548,10 @@ func getAltNames(cfg *kubeadmapi.MasterConfiguration) (*certutil.AltNames, error
|
||||
}
|
||||
}
|
||||
|
||||
// add api server dns advertise address
|
||||
if len(cfg.API.ControlPlaneEndpoint) > 0 {
|
||||
altNames.DNSNames = append(altNames.DNSNames, cfg.API.ControlPlaneEndpoint)
|
||||
}
|
||||
|
||||
return altNames, nil
|
||||
}
|
||||
|
@ -261,8 +261,9 @@ func TestWriteKeyFilesIfNotExist(t *testing.T) {
|
||||
func TestGetAltNames(t *testing.T) {
|
||||
hostname := "valid-hostname"
|
||||
advertiseIP := "1.2.3.4"
|
||||
controlPlaneEndpoint := "api.k8s.io"
|
||||
cfg := &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{AdvertiseAddress: advertiseIP},
|
||||
API: kubeadmapi.API{AdvertiseAddress: advertiseIP, ControlPlaneEndpoint: controlPlaneEndpoint},
|
||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.96.0.0/12", DNSDomain: "cluster.local"},
|
||||
NodeName: hostname,
|
||||
APIServerCertSANs: []string{"10.1.245.94", "10.1.245.95"},
|
||||
@ -273,7 +274,7 @@ func TestGetAltNames(t *testing.T) {
|
||||
t.Fatalf("failed calling getAltNames: %v", err)
|
||||
}
|
||||
|
||||
expectedDNSNames := []string{hostname, "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local"}
|
||||
expectedDNSNames := []string{hostname, "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.local", controlPlaneEndpoint}
|
||||
for _, DNSName := range expectedDNSNames {
|
||||
found := false
|
||||
for _, val := range altNames.DNSNames {
|
||||
|
@ -71,12 +71,25 @@ func TestGetKubeConfigSpecs(t *testing.T) {
|
||||
NodeName: "valid-node-name",
|
||||
}
|
||||
|
||||
// Creates a Master Configuration pointing to the pkidir folder
|
||||
cfgDNS := &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{ControlPlaneEndpoint: "api.k8s.io", BindPort: 1234},
|
||||
CertificatesDir: pkidir,
|
||||
NodeName: "valid-node-name",
|
||||
}
|
||||
|
||||
// Executes getKubeConfigSpecs
|
||||
specs, err := getKubeConfigSpecs(cfg)
|
||||
if err != nil {
|
||||
t.Fatal("getKubeConfigSpecs failed!")
|
||||
}
|
||||
|
||||
// Executes getKubeConfigSpecs
|
||||
specsDNS, err := getKubeConfigSpecs(cfgDNS)
|
||||
if err != nil {
|
||||
t.Fatal("getKubeConfigSpecs failed!")
|
||||
}
|
||||
|
||||
var assertions = []struct {
|
||||
kubeConfigFile string
|
||||
clientName string
|
||||
@ -136,6 +149,39 @@ func TestGetKubeConfigSpecs(t *testing.T) {
|
||||
} else {
|
||||
t.Errorf("getKubeConfigSpecs didn't create spec for %s ", assertion.kubeConfigFile)
|
||||
}
|
||||
|
||||
// assert the spec for the kubeConfigFile exists
|
||||
if spec, ok := specsDNS[assertion.kubeConfigFile]; ok {
|
||||
|
||||
// Assert clientName
|
||||
if spec.ClientName != assertion.clientName {
|
||||
t.Errorf("getKubeConfigSpecs for %s clientName is %s, expected %s", assertion.kubeConfigFile, spec.ClientName, assertion.clientName)
|
||||
}
|
||||
|
||||
// Assert Organizations
|
||||
if spec.ClientCertAuth == nil || !reflect.DeepEqual(spec.ClientCertAuth.Organizations, assertion.organizations) {
|
||||
t.Errorf("getKubeConfigSpecs for %s Organizations is %v, expected %v", assertion.kubeConfigFile, spec.ClientCertAuth.Organizations, assertion.organizations)
|
||||
}
|
||||
|
||||
// Asserts MasterConfiguration values injected into spec
|
||||
masterEndpoint, err := kubeadmutil.GetMasterEndpoint(cfgDNS)
|
||||
if err != nil {
|
||||
t.Error(err)
|
||||
}
|
||||
if spec.APIServer != masterEndpoint {
|
||||
t.Errorf("getKubeConfigSpecs didn't injected cfg.APIServer endpoint into spec for %s", assertion.kubeConfigFile)
|
||||
}
|
||||
|
||||
// Asserts CA certs and CA keys loaded into specs
|
||||
if spec.CACert == nil {
|
||||
t.Errorf("getKubeConfigSpecs didn't loaded CACert into spec for %s!", assertion.kubeConfigFile)
|
||||
}
|
||||
if spec.ClientCertAuth == nil || spec.ClientCertAuth.CAKey == nil {
|
||||
t.Errorf("getKubeConfigSpecs didn't loaded CAKey into spec for %s!", assertion.kubeConfigFile)
|
||||
}
|
||||
} else {
|
||||
t.Errorf("getKubeConfigSpecs didn't create spec for %s ", assertion.kubeConfigFile)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -34,7 +34,7 @@ import (
|
||||
"k8s.io/kubernetes/pkg/util/version"
|
||||
)
|
||||
|
||||
// SetInitDynamicDefaults checks and sets conifugration values for Master node
|
||||
// SetInitDynamicDefaults checks and sets configuration values for Master node
|
||||
func SetInitDynamicDefaults(cfg *kubeadmapi.MasterConfiguration) error {
|
||||
|
||||
// Choose the right address for the API Server to advertise. If the advertise address is localhost or 0.0.0.0, the default interface's IP address is used
|
||||
|
@ -21,12 +21,14 @@ import (
|
||||
"net"
|
||||
"strconv"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/validation"
|
||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||
)
|
||||
|
||||
// GetMasterEndpoint returns a properly formatted Master Endpoint
|
||||
// or passes the error from GetMasterHostPort.
|
||||
func GetMasterEndpoint(cfg *kubeadmapi.MasterConfiguration) (string, error) {
|
||||
|
||||
hostPort, err := GetMasterHostPort(cfg)
|
||||
if err != nil {
|
||||
return "", err
|
||||
@ -37,15 +39,25 @@ func GetMasterEndpoint(cfg *kubeadmapi.MasterConfiguration) (string, error) {
|
||||
// GetMasterHostPort returns a properly formatted Master IP/port pair or error
|
||||
// if the IP address can not be parsed or port is outside the valid TCP range.
|
||||
func GetMasterHostPort(cfg *kubeadmapi.MasterConfiguration) (string, error) {
|
||||
masterIP := net.ParseIP(cfg.API.AdvertiseAddress)
|
||||
if masterIP == nil {
|
||||
return "", fmt.Errorf("error parsing address %s", cfg.API.AdvertiseAddress)
|
||||
var masterIP string
|
||||
if len(cfg.API.ControlPlaneEndpoint) > 0 {
|
||||
errs := validation.IsDNS1123Subdomain(cfg.API.ControlPlaneEndpoint)
|
||||
if len(errs) > 0 {
|
||||
return "", fmt.Errorf("error parsing `ControlPlaneEndpoint` to valid dns subdomain with errors: %s", errs)
|
||||
}
|
||||
masterIP = cfg.API.ControlPlaneEndpoint
|
||||
} else {
|
||||
ip := net.ParseIP(cfg.API.AdvertiseAddress)
|
||||
if ip == nil {
|
||||
return "", fmt.Errorf("error parsing address %s", cfg.API.AdvertiseAddress)
|
||||
}
|
||||
masterIP = ip.String()
|
||||
}
|
||||
|
||||
if cfg.API.BindPort < 0 || cfg.API.BindPort > 65535 {
|
||||
return "", fmt.Errorf("api server port must be between 0 and 65535")
|
||||
}
|
||||
|
||||
hostPort := net.JoinHostPort(masterIP.String(), strconv.Itoa(int(cfg.API.BindPort)))
|
||||
hostPort := net.JoinHostPort(masterIP, strconv.Itoa(int(cfg.API.BindPort)))
|
||||
return hostPort, nil
|
||||
}
|
||||
|
@ -29,6 +29,40 @@ func TestGetMasterEndpoint(t *testing.T) {
|
||||
endpoint string
|
||||
expected bool
|
||||
}{
|
||||
{
|
||||
name: "bad controlplane endpooint dns",
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{
|
||||
ControlPlaneEndpoint: "bad!!cp.k8s.io",
|
||||
BindPort: 1234,
|
||||
},
|
||||
},
|
||||
endpoint: "https://cp.k8s.io:1234",
|
||||
expected: false,
|
||||
},
|
||||
{
|
||||
name: "both DNS and IP passed",
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{
|
||||
AdvertiseAddress: "1.2.3.4",
|
||||
ControlPlaneEndpoint: "cp.k8s.io",
|
||||
BindPort: 1234,
|
||||
},
|
||||
},
|
||||
endpoint: "https://cp.k8s.io:1234",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "valid DNS endpoint",
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
API: kubeadmapi.API{
|
||||
ControlPlaneEndpoint: "cp.k8s.io",
|
||||
BindPort: 1234,
|
||||
},
|
||||
},
|
||||
endpoint: "https://cp.k8s.io:1234",
|
||||
expected: true,
|
||||
},
|
||||
{
|
||||
name: "valid IPv4 endpoint",
|
||||
cfg: &kubeadmapi.MasterConfiguration{
|
||||
|
Loading…
Reference in New Issue
Block a user