mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-07-25 20:53:33 +00:00
kubeadm: Add --cert-dir, --apiserver-cert-extra-sans, remove --api-external-dns-names and add the phase command for certs. Also use the CertificatesDir var everywhere instead of the HostPKIPath variable and fix some bugs in certs.go
This commit is contained in:
parent
f12db38d5c
commit
579a743482
@ -32,7 +32,6 @@ func SetEnvParams() *EnvParams {
|
|||||||
|
|
||||||
envParams := map[string]string{
|
envParams := map[string]string{
|
||||||
"kubernetes_dir": "/etc/kubernetes",
|
"kubernetes_dir": "/etc/kubernetes",
|
||||||
"host_pki_path": "/etc/kubernetes/pki",
|
|
||||||
"host_etcd_path": "/var/lib/etcd",
|
"host_etcd_path": "/var/lib/etcd",
|
||||||
"hyperkube_image": "",
|
"hyperkube_image": "",
|
||||||
"repo_prefix": "gcr.io/google_containers",
|
"repo_prefix": "gcr.io/google_containers",
|
||||||
@ -48,7 +47,6 @@ func SetEnvParams() *EnvParams {
|
|||||||
|
|
||||||
return &EnvParams{
|
return &EnvParams{
|
||||||
KubernetesDir: path.Clean(envParams["kubernetes_dir"]),
|
KubernetesDir: path.Clean(envParams["kubernetes_dir"]),
|
||||||
HostPKIPath: path.Clean(envParams["host_pki_path"]),
|
|
||||||
HostEtcdPath: path.Clean(envParams["host_etcd_path"]),
|
HostEtcdPath: path.Clean(envParams["host_etcd_path"]),
|
||||||
HyperkubeImage: envParams["hyperkube_image"],
|
HyperkubeImage: envParams["hyperkube_image"],
|
||||||
RepositoryPrefix: envParams["repo_prefix"],
|
RepositoryPrefix: envParams["repo_prefix"],
|
||||||
|
@ -34,6 +34,8 @@ func KubeadmFuzzerFuncs(t apitesting.TestingCommon) []interface{} {
|
|||||||
obj.Networking.DNSDomain = "foo"
|
obj.Networking.DNSDomain = "foo"
|
||||||
obj.AuthorizationMode = "foo"
|
obj.AuthorizationMode = "foo"
|
||||||
obj.Discovery.Token = &kubeadm.TokenDiscovery{}
|
obj.Discovery.Token = &kubeadm.TokenDiscovery{}
|
||||||
|
obj.CertificatesDir = "foo"
|
||||||
|
obj.APIServerCertSANs = []string{}
|
||||||
},
|
},
|
||||||
func(obj *kubeadm.NodeConfiguration, c fuzz.Continue) {
|
func(obj *kubeadm.NodeConfiguration, c fuzz.Continue) {
|
||||||
c.FuzzNoCustom(obj)
|
c.FuzzNoCustom(obj)
|
||||||
|
@ -22,7 +22,6 @@ import (
|
|||||||
|
|
||||||
type EnvParams struct {
|
type EnvParams struct {
|
||||||
KubernetesDir string
|
KubernetesDir string
|
||||||
HostPKIPath string
|
|
||||||
HostEtcdPath string
|
HostEtcdPath string
|
||||||
HyperkubeImage string
|
HyperkubeImage string
|
||||||
RepositoryPrefix string
|
RepositoryPrefix string
|
||||||
@ -40,6 +39,7 @@ type MasterConfiguration struct {
|
|||||||
KubernetesVersion string
|
KubernetesVersion string
|
||||||
CloudProvider string
|
CloudProvider string
|
||||||
AuthorizationMode string
|
AuthorizationMode string
|
||||||
|
|
||||||
// SelfHosted enables an alpha deployment type where the apiserver, scheduler, and
|
// SelfHosted enables an alpha deployment type where the apiserver, scheduler, and
|
||||||
// controller manager are managed by Kubernetes itself. This option is likely to
|
// controller manager are managed by Kubernetes itself. This option is likely to
|
||||||
// become the default in the future.
|
// become the default in the future.
|
||||||
@ -48,12 +48,18 @@ type MasterConfiguration struct {
|
|||||||
APIServerExtraArgs map[string]string
|
APIServerExtraArgs map[string]string
|
||||||
ControllerManagerExtraArgs map[string]string
|
ControllerManagerExtraArgs map[string]string
|
||||||
SchedulerExtraArgs map[string]string
|
SchedulerExtraArgs map[string]string
|
||||||
|
|
||||||
|
// APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert
|
||||||
|
APIServerCertSANs []string
|
||||||
|
// CertificatesDir specifies where to store or look for all required certificates
|
||||||
|
CertificatesDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
|
// AdvertiseAddress sets the address for the API server to advertise.
|
||||||
AdvertiseAddress string
|
AdvertiseAddress string
|
||||||
ExternalDNSNames []string
|
// BindPort sets the secure port for the API Server to bind to
|
||||||
BindPort int32
|
BindPort int32
|
||||||
}
|
}
|
||||||
|
|
||||||
type Discovery struct {
|
type Discovery struct {
|
||||||
|
@ -32,6 +32,7 @@ const (
|
|||||||
DefaultDiscoveryBindPort = 9898
|
DefaultDiscoveryBindPort = 9898
|
||||||
DefaultAuthorizationMode = "RBAC"
|
DefaultAuthorizationMode = "RBAC"
|
||||||
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
|
DefaultCACertPath = "/etc/kubernetes/pki/ca.crt"
|
||||||
|
DefaultCertificatesDir = "/etc/kubernetes/pki"
|
||||||
)
|
)
|
||||||
|
|
||||||
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
func addDefaultingFuncs(scheme *runtime.Scheme) error {
|
||||||
@ -66,6 +67,10 @@ func SetDefaults_MasterConfiguration(obj *MasterConfiguration) {
|
|||||||
if obj.AuthorizationMode == "" {
|
if obj.AuthorizationMode == "" {
|
||||||
obj.AuthorizationMode = DefaultAuthorizationMode
|
obj.AuthorizationMode = DefaultAuthorizationMode
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if obj.CertificatesDir == "" {
|
||||||
|
obj.CertificatesDir = DefaultCertificatesDir
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
|
func SetDefaults_NodeConfiguration(obj *NodeConfiguration) {
|
||||||
|
@ -30,6 +30,7 @@ type MasterConfiguration struct {
|
|||||||
KubernetesVersion string `json:"kubernetesVersion"`
|
KubernetesVersion string `json:"kubernetesVersion"`
|
||||||
CloudProvider string `json:"cloudProvider"`
|
CloudProvider string `json:"cloudProvider"`
|
||||||
AuthorizationMode string `json:"authorizationMode"`
|
AuthorizationMode string `json:"authorizationMode"`
|
||||||
|
|
||||||
// SelfHosted enables an alpha deployment type where the apiserver, scheduler, and
|
// SelfHosted enables an alpha deployment type where the apiserver, scheduler, and
|
||||||
// controller manager are managed by Kubernetes itself. This option is likely to
|
// controller manager are managed by Kubernetes itself. This option is likely to
|
||||||
// become the default in the future.
|
// become the default in the future.
|
||||||
@ -38,13 +39,18 @@ type MasterConfiguration struct {
|
|||||||
APIServerExtraArgs map[string]string `json:"apiServerExtraArgs"`
|
APIServerExtraArgs map[string]string `json:"apiServerExtraArgs"`
|
||||||
ControllerManagerExtraArgs map[string]string `json:"controllerManagerExtraArgs"`
|
ControllerManagerExtraArgs map[string]string `json:"controllerManagerExtraArgs"`
|
||||||
SchedulerExtraArgs map[string]string `json:"schedulerExtraArgs"`
|
SchedulerExtraArgs map[string]string `json:"schedulerExtraArgs"`
|
||||||
|
|
||||||
|
// APIServerCertSANs sets extra Subject Alternative Names for the API Server signing cert
|
||||||
|
APIServerCertSANs []string `json:"apiServerCertSANs"`
|
||||||
|
// CertificatesDir specifies where to store or look for all required certificates
|
||||||
|
CertificatesDir string `json:"certificatesDir"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
// The address for the API server to advertise.
|
// AdvertiseAddress sets the address for the API server to advertise.
|
||||||
AdvertiseAddress string `json:"advertiseAddress"`
|
AdvertiseAddress string `json:"advertiseAddress"`
|
||||||
ExternalDNSNames []string `json:"externalDNSNames"`
|
// BindPort sets the secure port for the API Server to bind to
|
||||||
BindPort int32 `json:"bindPort"`
|
BindPort int32 `json:"bindPort"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type Discovery struct {
|
type Discovery struct {
|
||||||
|
@ -27,8 +27,10 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/constants:go_default_library",
|
||||||
"//cmd/kubeadm/app/util/token:go_default_library",
|
"//cmd/kubeadm/app/util/token:go_default_library",
|
||||||
|
"//pkg/api/validation:go_default_library",
|
||||||
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
"//pkg/kubeapiserver/authorizer/modes:go_default_library",
|
||||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -21,13 +21,15 @@ import (
|
|||||||
"net"
|
"net"
|
||||||
"net/url"
|
"net/url"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/apimachinery/pkg/util/validation"
|
||||||
"k8s.io/apimachinery/pkg/util/validation/field"
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
"k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
tokenutil "k8s.io/kubernetes/cmd/kubeadm/app/util/token"
|
||||||
|
apivalidation "k8s.io/kubernetes/pkg/api/validation"
|
||||||
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
authzmodes "k8s.io/kubernetes/pkg/kubeapiserver/authorizer/modes"
|
||||||
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
"k8s.io/kubernetes/pkg/registry/core/service/ipallocator"
|
||||||
)
|
)
|
||||||
@ -49,9 +51,11 @@ var cloudproviders = []string{
|
|||||||
|
|
||||||
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
|
func ValidateMasterConfiguration(c *kubeadm.MasterConfiguration) field.ErrorList {
|
||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
allErrs = append(allErrs, ValidateServiceSubnet(c.Networking.ServiceSubnet, field.NewPath("service subnet"))...)
|
|
||||||
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...)
|
allErrs = append(allErrs, ValidateCloudProvider(c.CloudProvider, field.NewPath("cloudprovider"))...)
|
||||||
allErrs = append(allErrs, ValidateAuthorizationMode(c.AuthorizationMode, field.NewPath("authorization-mode"))...)
|
allErrs = append(allErrs, ValidateAuthorizationMode(c.AuthorizationMode, field.NewPath("authorization-mode"))...)
|
||||||
|
allErrs = append(allErrs, ValidateNetworking(&c.Networking, field.NewPath("networking"))...)
|
||||||
|
allErrs = append(allErrs, ValidateAPIServerCertSANs(c.APIServerCertSANs, field.NewPath("cert-altnames"))...)
|
||||||
|
allErrs = append(allErrs, ValidateAbsolutePath(c.CertificatesDir, field.NewPath("certificates-dir"))...)
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -59,7 +63,7 @@ func ValidateNodeConfiguration(c *kubeadm.NodeConfiguration) field.ErrorList {
|
|||||||
allErrs := field.ErrorList{}
|
allErrs := field.ErrorList{}
|
||||||
allErrs = append(allErrs, ValidateDiscovery(c, field.NewPath("discovery"))...)
|
allErrs = append(allErrs, ValidateDiscovery(c, field.NewPath("discovery"))...)
|
||||||
|
|
||||||
if !path.IsAbs(c.CACertPath) || !strings.HasSuffix(c.CACertPath, ".crt") {
|
if !filepath.IsAbs(c.CACertPath) || !strings.HasSuffix(c.CACertPath, ".crt") {
|
||||||
allErrs = append(allErrs, field.Invalid(field.NewPath("ca-cert-path"), c.CACertPath, "the ca certificate path must be an absolute path"))
|
allErrs = append(allErrs, field.Invalid(field.NewPath("ca-cert-path"), c.CACertPath, "the ca certificate path must be an absolute path"))
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
@ -142,35 +146,75 @@ func ValidateToken(t string, fldPath *field.Path) field.ErrorList {
|
|||||||
|
|
||||||
id, secret, err := tokenutil.ParseToken(t)
|
id, secret, err := tokenutil.ParseToken(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath, nil, err.Error()))
|
allErrs = append(allErrs, field.Invalid(fldPath, t, err.Error()))
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(id) == 0 || len(secret) == 0 {
|
if len(id) == 0 || len(secret) == 0 {
|
||||||
allErrs = append(allErrs, field.Invalid(fldPath, nil, "token must be of form '[a-z0-9]{6}.[a-z0-9]{16}'"))
|
allErrs = append(allErrs, field.Invalid(fldPath, t, "token must be of form '[a-z0-9]{6}.[a-z0-9]{16}'"))
|
||||||
}
|
}
|
||||||
return allErrs
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateServiceSubnet(subnet string, fldPath *field.Path) field.ErrorList {
|
func ValidateAPIServerCertSANs(altnames []string, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
for _, altname := range altnames {
|
||||||
|
if len(validation.IsDNS1123Subdomain(altname)) != 0 && net.ParseIP(altname) == nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath, altname, "altname is not a valid dns label or ip address"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateIPFromString(ipaddr string, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if net.ParseIP(ipaddr) == nil {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath, ipaddr, "ip address is not valid"))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateIPNetFromString(subnet string, minAddrs int64, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
_, svcSubnet, err := net.ParseCIDR(subnet)
|
_, svcSubnet, err := net.ParseCIDR(subnet)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return field.ErrorList{field.Invalid(fldPath, nil, "couldn't parse the service subnet")}
|
allErrs = append(allErrs, field.Invalid(fldPath, subnet, "couldn't parse subnet"))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
numAddresses := ipallocator.RangeSize(svcSubnet)
|
numAddresses := ipallocator.RangeSize(svcSubnet)
|
||||||
if numAddresses < constants.MinimumAddressesInServiceSubnet {
|
if numAddresses < minAddrs {
|
||||||
return field.ErrorList{field.Invalid(fldPath, nil, "service subnet is too small")}
|
allErrs = append(allErrs, field.Invalid(fldPath, subnet, "subnet is too small"))
|
||||||
}
|
}
|
||||||
return field.ErrorList{}
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateNetworking(c *kubeadm.Networking, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
allErrs = append(allErrs, apivalidation.ValidateDNS1123Subdomain(c.DNSDomain, field.NewPath("dns-domain"))...)
|
||||||
|
allErrs = append(allErrs, ValidateIPNetFromString(c.ServiceSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("service-subnet"))...)
|
||||||
|
if len(c.PodSubnet) != 0 {
|
||||||
|
allErrs = append(allErrs, ValidateIPNetFromString(c.PodSubnet, constants.MinimumAddressesInServiceSubnet, field.NewPath("pod-subnet"))...)
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
|
}
|
||||||
|
|
||||||
|
func ValidateAbsolutePath(path string, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
if !filepath.IsAbs(path) {
|
||||||
|
allErrs = append(allErrs, field.Invalid(fldPath, path, "path is not absolute"))
|
||||||
|
}
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
|
|
||||||
func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList {
|
func ValidateCloudProvider(provider string, fldPath *field.Path) field.ErrorList {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
if len(provider) == 0 {
|
if len(provider) == 0 {
|
||||||
return field.ErrorList{}
|
return allErrs
|
||||||
}
|
}
|
||||||
for _, supported := range cloudproviders {
|
for _, supported := range cloudproviders {
|
||||||
if provider == supported {
|
if provider == supported {
|
||||||
return field.ErrorList{}
|
return allErrs
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return field.ErrorList{field.Invalid(fldPath, nil, "cloudprovider not supported")}
|
allErrs = append(allErrs, field.Invalid(fldPath, provider, "cloudprovider not supported"))
|
||||||
|
return allErrs
|
||||||
}
|
}
|
||||||
|
@ -69,31 +69,6 @@ func TestValidateAuthorizationMode(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestValidateServiceSubnet(t *testing.T) {
|
|
||||||
var tests = []struct {
|
|
||||||
s string
|
|
||||||
f *field.Path
|
|
||||||
expected bool
|
|
||||||
}{
|
|
||||||
{"", nil, false},
|
|
||||||
{"this is not a cidr", nil, false}, // not a CIDR
|
|
||||||
{"10.0.0.1", nil, false}, // not a CIDR
|
|
||||||
{"10.96.0.1/29", nil, false}, // CIDR too small, only 8 addresses and we require at least 10
|
|
||||||
{"10.96.0.1/28", nil, true}, // a /28 subnet is ok because it can contain 16 addresses
|
|
||||||
{"10.96.0.1/12", nil, true}, // the default subnet should obviously pass as well
|
|
||||||
}
|
|
||||||
for _, rt := range tests {
|
|
||||||
actual := ValidateServiceSubnet(rt.s, rt.f)
|
|
||||||
if (len(actual) == 0) != rt.expected {
|
|
||||||
t.Errorf(
|
|
||||||
"failed ValidateServiceSubnet:\n\texpected: %t\n\t actual: %t",
|
|
||||||
rt.expected,
|
|
||||||
(len(actual) == 0),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateCloudProvider(t *testing.T) {
|
func TestValidateCloudProvider(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
s string
|
s string
|
||||||
@ -118,6 +93,78 @@ func TestValidateCloudProvider(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestValidateAPIServerCertSANs(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
sans []string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{[]string{}, true}, // ok if not provided
|
||||||
|
{[]string{"1,2,,3"}, false}, // not a DNS label or IP
|
||||||
|
{[]string{"my-hostname", "???&?.garbage"}, false}, // not valid
|
||||||
|
{[]string{"my-hostname", "my.subdomain", "1.2.3.4"}, true}, // supported
|
||||||
|
{[]string{"my-hostname2", "my.other.subdomain", "10.0.0.10"}, true}, // supported
|
||||||
|
}
|
||||||
|
for _, rt := range tests {
|
||||||
|
actual := ValidateAPIServerCertSANs(rt.sans, nil)
|
||||||
|
if (len(actual) == 0) != rt.expected {
|
||||||
|
t.Errorf(
|
||||||
|
"failed ValidateAPIServerCertSANs:\n\texpected: %t\n\t actual: %t",
|
||||||
|
rt.expected,
|
||||||
|
(len(actual) == 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateIPFromString(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
ip string
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{"", false}, // not valid
|
||||||
|
{"1234", false}, // not valid
|
||||||
|
{"1.2", false}, // not valid
|
||||||
|
{"1.2.3.4/16", false}, // not valid
|
||||||
|
{"1.2.3.4", true}, // valid
|
||||||
|
{"16.0.1.1", true}, // valid
|
||||||
|
}
|
||||||
|
for _, rt := range tests {
|
||||||
|
actual := ValidateIPFromString(rt.ip, nil)
|
||||||
|
if (len(actual) == 0) != rt.expected {
|
||||||
|
t.Errorf(
|
||||||
|
"failed ValidateIPFromString:\n\texpected: %t\n\t actual: %t",
|
||||||
|
rt.expected,
|
||||||
|
(len(actual) == 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestValidateIPNetFromString(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
subnet string
|
||||||
|
minaddrs int64
|
||||||
|
expected bool
|
||||||
|
}{
|
||||||
|
{"", 0, false}, // not valid
|
||||||
|
{"1234", 0, false}, // not valid
|
||||||
|
{"abc", 0, false}, // not valid
|
||||||
|
{"1.2.3.4", 0, false}, // ip not valid
|
||||||
|
{"10.0.0.16/29", 10, false}, // valid, but too small. At least 10 addrs needed
|
||||||
|
{"10.0.0.16/12", 10, true}, // valid
|
||||||
|
}
|
||||||
|
for _, rt := range tests {
|
||||||
|
actual := ValidateIPNetFromString(rt.subnet, rt.minaddrs, nil)
|
||||||
|
if (len(actual) == 0) != rt.expected {
|
||||||
|
t.Errorf(
|
||||||
|
"failed ValidateIPNetFromString:\n\texpected: %t\n\t actual: %t",
|
||||||
|
rt.expected,
|
||||||
|
(len(actual) == 0),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestValidateMasterConfiguration(t *testing.T) {
|
func TestValidateMasterConfiguration(t *testing.T) {
|
||||||
var tests = []struct {
|
var tests = []struct {
|
||||||
s *kubeadm.MasterConfiguration
|
s *kubeadm.MasterConfiguration
|
||||||
@ -131,7 +178,9 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
|||||||
AuthorizationMode: "RBAC",
|
AuthorizationMode: "RBAC",
|
||||||
Networking: kubeadm.Networking{
|
Networking: kubeadm.Networking{
|
||||||
ServiceSubnet: "10.96.0.1/12",
|
ServiceSubnet: "10.96.0.1/12",
|
||||||
|
DNSDomain: "cluster.local",
|
||||||
},
|
},
|
||||||
|
CertificatesDir: "/some/cert/dir",
|
||||||
}, true},
|
}, true},
|
||||||
{&kubeadm.MasterConfiguration{
|
{&kubeadm.MasterConfiguration{
|
||||||
Discovery: kubeadm.Discovery{
|
Discovery: kubeadm.Discovery{
|
||||||
@ -140,7 +189,9 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
|||||||
AuthorizationMode: "RBAC",
|
AuthorizationMode: "RBAC",
|
||||||
Networking: kubeadm.Networking{
|
Networking: kubeadm.Networking{
|
||||||
ServiceSubnet: "10.96.0.1/12",
|
ServiceSubnet: "10.96.0.1/12",
|
||||||
|
DNSDomain: "cluster.local",
|
||||||
},
|
},
|
||||||
|
CertificatesDir: "/some/other/cert/dir",
|
||||||
}, true},
|
}, true},
|
||||||
{&kubeadm.MasterConfiguration{
|
{&kubeadm.MasterConfiguration{
|
||||||
Discovery: kubeadm.Discovery{
|
Discovery: kubeadm.Discovery{
|
||||||
@ -153,7 +204,9 @@ func TestValidateMasterConfiguration(t *testing.T) {
|
|||||||
AuthorizationMode: "RBAC",
|
AuthorizationMode: "RBAC",
|
||||||
Networking: kubeadm.Networking{
|
Networking: kubeadm.Networking{
|
||||||
ServiceSubnet: "10.96.0.1/12",
|
ServiceSubnet: "10.96.0.1/12",
|
||||||
|
DNSDomain: "cluster.local",
|
||||||
},
|
},
|
||||||
|
CertificatesDir: "/yet/another/cert/dir",
|
||||||
}, true},
|
}, true},
|
||||||
}
|
}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
|
@ -88,10 +88,6 @@ func NewCmdInit(out io.Writer) *cobra.Command {
|
|||||||
&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort,
|
&cfg.API.BindPort, "apiserver-bind-port", cfg.API.BindPort,
|
||||||
"Port for the API Server to bind to",
|
"Port for the API Server to bind to",
|
||||||
)
|
)
|
||||||
cmd.PersistentFlags().StringSliceVar(
|
|
||||||
&cfg.API.ExternalDNSNames, "api-external-dns-names", cfg.API.ExternalDNSNames,
|
|
||||||
"The DNS names to advertise, in case you have configured them yourself",
|
|
||||||
)
|
|
||||||
cmd.PersistentFlags().StringVar(
|
cmd.PersistentFlags().StringVar(
|
||||||
&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet,
|
&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet,
|
||||||
"Use alternative range of IP address for service VIPs",
|
"Use alternative range of IP address for service VIPs",
|
||||||
@ -108,6 +104,14 @@ func NewCmdInit(out io.Writer) *cobra.Command {
|
|||||||
&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion,
|
&cfg.KubernetesVersion, "kubernetes-version", cfg.KubernetesVersion,
|
||||||
`Choose a specific Kubernetes version for the control plane`,
|
`Choose a specific Kubernetes version for the control plane`,
|
||||||
)
|
)
|
||||||
|
cmd.PersistentFlags().StringVar(
|
||||||
|
&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir,
|
||||||
|
`The path where to save and store the certificates`,
|
||||||
|
)
|
||||||
|
cmd.PersistentFlags().StringSliceVar(
|
||||||
|
&cfg.APIServerCertSANs, "apiserver-cert-extra-sans", cfg.APIServerCertSANs,
|
||||||
|
`Optional extra altnames to use for the API Server serving cert. Can be both IP addresses and dns names.`,
|
||||||
|
)
|
||||||
|
|
||||||
cmd.PersistentFlags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
cmd.PersistentFlags().StringVar(&cfgPath, "config", cfgPath, "Path to kubeadm config file")
|
||||||
|
|
||||||
@ -179,7 +183,7 @@ func (i *Init) Validate() error {
|
|||||||
func (i *Init) Run(out io.Writer) error {
|
func (i *Init) Run(out io.Writer) error {
|
||||||
|
|
||||||
// PHASE 1: Generate certificates
|
// PHASE 1: Generate certificates
|
||||||
err := certphase.CreatePKIAssets(i.cfg, kubeadmapi.GlobalEnvParams.HostPKIPath)
|
err := certphase.CreatePKIAssets(i.cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -190,7 +194,7 @@ func (i *Init) Run(out io.Writer) error {
|
|||||||
// so we'll pick the first one, there is much of chance to have an empty
|
// so we'll pick the first one, there is much of chance to have an empty
|
||||||
// slice by the time this gets called
|
// slice by the time this gets called
|
||||||
masterEndpoint := fmt.Sprintf("https://%s:%d", i.cfg.API.AdvertiseAddress, i.cfg.API.BindPort)
|
masterEndpoint := fmt.Sprintf("https://%s:%d", i.cfg.API.AdvertiseAddress, i.cfg.API.BindPort)
|
||||||
err = kubeconfigphase.CreateInitKubeConfigFiles(masterEndpoint, kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmapi.GlobalEnvParams.KubernetesDir)
|
err = kubeconfigphase.CreateInitKubeConfigFiles(masterEndpoint, i.cfg.CertificatesDir, kubeadmapi.GlobalEnvParams.KubernetesDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@ -198,7 +202,7 @@ func (i *Init) Run(out io.Writer) error {
|
|||||||
// TODO: It's not great to have an exception for token here, but necessary because the apiserver doesn't handle this properly in the API yet
|
// TODO: It's not great to have an exception for token here, but necessary because the apiserver doesn't handle this properly in the API yet
|
||||||
// but relies on files on disk for now, which is daunting.
|
// but relies on files on disk for now, which is daunting.
|
||||||
if i.cfg.Discovery.Token != nil {
|
if i.cfg.Discovery.Token != nil {
|
||||||
if err := tokenphase.CreateTokenAuthFile(tokenutil.BearerToken(i.cfg.Discovery.Token)); err != nil {
|
if err := tokenphase.CreateTokenAuthFile(i.cfg.CertificatesDir, tokenutil.BearerToken(i.cfg.Discovery.Token)); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -10,15 +10,22 @@ load(
|
|||||||
go_library(
|
go_library(
|
||||||
name = "go_default_library",
|
name = "go_default_library",
|
||||||
srcs = [
|
srcs = [
|
||||||
|
"certs.go",
|
||||||
"kubeconfig.go",
|
"kubeconfig.go",
|
||||||
"phase.go",
|
"phase.go",
|
||||||
],
|
],
|
||||||
tags = ["automanaged"],
|
tags = ["automanaged"],
|
||||||
deps = [
|
deps = [
|
||||||
"//cmd/kubeadm/app/constants:go_default_library",
|
"//cmd/kubeadm/app/apis/kubeadm:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/apis/kubeadm/v1alpha1:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/apis/kubeadm/validation:go_default_library",
|
||||||
|
"//cmd/kubeadm/app/phases/certs:go_default_library",
|
||||||
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
"//cmd/kubeadm/app/phases/kubeconfig:go_default_library",
|
||||||
"//cmd/kubeadm/app/util:go_default_library",
|
"//cmd/kubeadm/app/util:go_default_library",
|
||||||
"//vendor:github.com/spf13/cobra",
|
"//vendor:github.com/spf13/cobra",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/util/net",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/util/validation/field",
|
||||||
|
"//vendor:k8s.io/client-go/pkg/api",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
|
||||||
|
99
cmd/kubeadm/app/cmd/phases/certs.go
Normal file
99
cmd/kubeadm/app/cmd/phases/certs.go
Normal file
@ -0,0 +1,99 @@
|
|||||||
|
/*
|
||||||
|
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 phases
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
|
netutil "k8s.io/apimachinery/pkg/util/net"
|
||||||
|
"k8s.io/apimachinery/pkg/util/validation/field"
|
||||||
|
"k8s.io/client-go/pkg/api"
|
||||||
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||||
|
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/validation"
|
||||||
|
certphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/certs"
|
||||||
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
|
)
|
||||||
|
|
||||||
|
func NewCmdCerts() *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "certs",
|
||||||
|
Aliases: []string{"certificates"},
|
||||||
|
Short: "Generate certificates for a Kubernetes cluster.",
|
||||||
|
RunE: subCmdRunE("certs"),
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd.AddCommand(NewCmdSelfSign())
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewCmdSelfSign() *cobra.Command {
|
||||||
|
// TODO: Move this into a dedicated Certificates Phase API object
|
||||||
|
cfg := &kubeadmapiext.MasterConfiguration{}
|
||||||
|
// Default values for the cobra help text
|
||||||
|
api.Scheme.Default(cfg)
|
||||||
|
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "selfsign",
|
||||||
|
Short: "Generate the CA, APIServer signing/client cert, the ServiceAccount public/private keys and a CA and client cert for the front proxy",
|
||||||
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
|
|
||||||
|
// Run the defaulting once again to take passed flags into account
|
||||||
|
api.Scheme.Default(cfg)
|
||||||
|
internalcfg := &kubeadmapi.MasterConfiguration{}
|
||||||
|
api.Scheme.Convert(cfg, internalcfg, nil)
|
||||||
|
|
||||||
|
err := RunSelfSign(internalcfg)
|
||||||
|
kubeadmutil.CheckErr(err)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
cmd.Flags().StringVar(&cfg.Networking.DNSDomain, "dns-domain", cfg.Networking.DNSDomain, "The DNS Domain for the Kubernetes cluster.")
|
||||||
|
cmd.Flags().StringVar(&cfg.CertificatesDir, "cert-dir", cfg.CertificatesDir, "The path where to save and store the certificates")
|
||||||
|
cmd.Flags().StringVar(&cfg.Networking.ServiceSubnet, "service-cidr", cfg.Networking.ServiceSubnet, "The subnet for the Services in the cluster.")
|
||||||
|
cmd.Flags().StringSliceVar(&cfg.APIServerCertSANs, "cert-altnames", []string{}, "Optional extra altnames to use for the API Server serving cert. Can be both IP addresses and dns names.")
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|
||||||
|
// RunSelfSign generates certificate assets in the specified directory
|
||||||
|
func RunSelfSign(config *kubeadmapi.MasterConfiguration) error {
|
||||||
|
if err := validateArgs(config); err != nil {
|
||||||
|
return fmt.Errorf("The argument validation failed: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// If it's possible to detect the default IP, add it to the SANs as well. Otherwise, just go with the provided ones
|
||||||
|
ip, err := netutil.ChooseBindAddress(net.ParseIP(config.API.AdvertiseAddress))
|
||||||
|
if err == nil {
|
||||||
|
config.API.AdvertiseAddress = ip.String()
|
||||||
|
}
|
||||||
|
|
||||||
|
err = certphase.CreatePKIAssets(config)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func validateArgs(config *kubeadmapi.MasterConfiguration) error {
|
||||||
|
allErrs := field.ErrorList{}
|
||||||
|
allErrs = append(allErrs, validation.ValidateNetworking(&config.Networking, field.NewPath("networking"))...)
|
||||||
|
allErrs = append(allErrs, validation.ValidateAbsolutePath(config.CertificatesDir, field.NewPath("cert-dir"))...)
|
||||||
|
allErrs = append(allErrs, validation.ValidateAPIServerCertSANs(config.APIServerCertSANs, field.NewPath("cert-altnames"))...)
|
||||||
|
return allErrs.ToAggregate()
|
||||||
|
}
|
@ -22,7 +22,7 @@ import (
|
|||||||
|
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||||
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
kubeconfigphase "k8s.io/kubernetes/cmd/kubeadm/app/phases/kubeconfig"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
)
|
)
|
||||||
@ -74,7 +74,7 @@ func NewCmdClientCerts(out io.Writer) *cobra.Command {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func addCommonFlags(cmd *cobra.Command, config *kubeconfigphase.BuildConfigProperties) {
|
func addCommonFlags(cmd *cobra.Command, config *kubeconfigphase.BuildConfigProperties) {
|
||||||
cmd.Flags().StringVar(&config.CertDir, "cert-dir", kubeadmconstants.DefaultCertDir, "The path to the directory where the certificates are.")
|
cmd.Flags().StringVar(&config.CertDir, "cert-dir", kubeadmapiext.DefaultCertificatesDir, "The path to the directory where the certificates are.")
|
||||||
cmd.Flags().StringVar(&config.ClientName, "client-name", "", "The name of the client for which the KubeConfig file will be generated.")
|
cmd.Flags().StringVar(&config.ClientName, "client-name", "", "The name of the client for which the KubeConfig file will be generated.")
|
||||||
cmd.Flags().StringVar(&config.APIServer, "server", "", "The location of the api server.")
|
cmd.Flags().StringVar(&config.APIServer, "server", "", "The location of the api server.")
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ func NewCmdPhase(out io.Writer) *cobra.Command {
|
|||||||
RunE: subCmdRunE("phase"),
|
RunE: subCmdRunE("phase"),
|
||||||
}
|
}
|
||||||
cmd.AddCommand(NewCmdKubeConfig(out))
|
cmd.AddCommand(NewCmdKubeConfig(out))
|
||||||
|
cmd.AddCommand(NewCmdCerts())
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,7 @@ import (
|
|||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
|
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
|
kubeadmapiext "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1alpha1"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
"k8s.io/kubernetes/cmd/kubeadm/app/preflight"
|
||||||
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
kubeadmutil "k8s.io/kubernetes/cmd/kubeadm/app/util"
|
||||||
@ -36,11 +37,12 @@ import (
|
|||||||
// NewCmdReset returns the "kubeadm reset" command
|
// NewCmdReset returns the "kubeadm reset" command
|
||||||
func NewCmdReset(out io.Writer) *cobra.Command {
|
func NewCmdReset(out io.Writer) *cobra.Command {
|
||||||
var skipPreFlight, removeNode bool
|
var skipPreFlight, removeNode bool
|
||||||
|
var certsDir string
|
||||||
cmd := &cobra.Command{
|
cmd := &cobra.Command{
|
||||||
Use: "reset",
|
Use: "reset",
|
||||||
Short: "Run this to revert any changes made to this host by 'kubeadm init' or 'kubeadm join'.",
|
Short: "Run this to revert any changes made to this host by 'kubeadm init' or 'kubeadm join'.",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
r, err := NewReset(skipPreFlight, removeNode)
|
r, err := NewReset(skipPreFlight, removeNode, certsDir)
|
||||||
kubeadmutil.CheckErr(err)
|
kubeadmutil.CheckErr(err)
|
||||||
kubeadmutil.CheckErr(r.Run(out))
|
kubeadmutil.CheckErr(r.Run(out))
|
||||||
},
|
},
|
||||||
@ -56,14 +58,20 @@ func NewCmdReset(out io.Writer) *cobra.Command {
|
|||||||
"Remove this node from the pool of nodes in this cluster",
|
"Remove this node from the pool of nodes in this cluster",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
cmd.PersistentFlags().StringVar(
|
||||||
|
&certsDir, "cert-dir", kubeadmapiext.DefaultCertificatesDir,
|
||||||
|
"The path to the directory where the certificates are stored. If specified, clean this directory.",
|
||||||
|
)
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
type Reset struct {
|
type Reset struct {
|
||||||
removeNode bool
|
removeNode bool
|
||||||
|
certsDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewReset(skipPreFlight, removeNode bool) (*Reset, error) {
|
func NewReset(skipPreFlight, removeNode bool, certsDir string) (*Reset, error) {
|
||||||
if !skipPreFlight {
|
if !skipPreFlight {
|
||||||
fmt.Println("[preflight] Running pre-flight checks")
|
fmt.Println("[preflight] Running pre-flight checks")
|
||||||
|
|
||||||
@ -76,6 +84,7 @@ func NewReset(skipPreFlight, removeNode bool) (*Reset, error) {
|
|||||||
|
|
||||||
return &Reset{
|
return &Reset{
|
||||||
removeNode: removeNode,
|
removeNode: removeNode,
|
||||||
|
certsDir: certsDir,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -137,7 +146,7 @@ func (r *Reset) Run(out io.Writer) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Remove contents from the config and pki directories
|
// Remove contents from the config and pki directories
|
||||||
resetConfigDir(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmapi.GlobalEnvParams.HostPKIPath)
|
resetConfigDir(kubeadmapi.GlobalEnvParams.KubernetesDir, r.certsDir)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,6 @@ const (
|
|||||||
ControllerManagerKubeConfigFileName = "controller-manager.conf"
|
ControllerManagerKubeConfigFileName = "controller-manager.conf"
|
||||||
SchedulerKubeConfigFileName = "scheduler.conf"
|
SchedulerKubeConfigFileName = "scheduler.conf"
|
||||||
|
|
||||||
DefaultCertDir = "/etc/kubernetes/pki"
|
|
||||||
|
|
||||||
// Important: a "v"-prefix shouldn't exist here; semver doesn't allow that
|
// Important: a "v"-prefix shouldn't exist here; semver doesn't allow that
|
||||||
MinimumControlPlaneVersion = "1.6.0-alpha.2"
|
MinimumControlPlaneVersion = "1.6.0-alpha.2"
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ func encodeKubeDiscoverySecretData(dcfg *kubeadmapi.TokenDiscovery, apicfg kubea
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateDiscoveryDeploymentAndSecret(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
|
func CreateDiscoveryDeploymentAndSecret(cfg *kubeadmapi.MasterConfiguration, client *clientset.Clientset) error {
|
||||||
caCertificatePath := path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmconstants.CACertName)
|
caCertificatePath := path.Join(cfg.CertificatesDir, kubeadmconstants.CACertName)
|
||||||
caCerts, err := certutil.CertsFromFile(caCertificatePath)
|
caCerts, err := certutil.CertsFromFile(caCertificatePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't load the CA certificate file %s: %v", caCertificatePath, err)
|
return fmt.Errorf("couldn't load the CA certificate file %s: %v", caCertificatePath, err)
|
||||||
|
@ -292,10 +292,6 @@ func getComponentBaseCommand(component string) []string {
|
|||||||
return []string{"kube-" + component}
|
return []string{"kube-" + component}
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCertFilePath(certName string) string {
|
|
||||||
return path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, certName)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) []string {
|
func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) []string {
|
||||||
var command []string
|
var command []string
|
||||||
|
|
||||||
@ -308,13 +304,13 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) [
|
|||||||
"insecure-port": "0",
|
"insecure-port": "0",
|
||||||
"admission-control": kubeadmconstants.DefaultAdmissionControl,
|
"admission-control": kubeadmconstants.DefaultAdmissionControl,
|
||||||
"service-cluster-ip-range": cfg.Networking.ServiceSubnet,
|
"service-cluster-ip-range": cfg.Networking.ServiceSubnet,
|
||||||
"service-account-key-file": getCertFilePath(kubeadmconstants.ServiceAccountPublicKeyName),
|
"service-account-key-file": path.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPublicKeyName),
|
||||||
"client-ca-file": getCertFilePath(kubeadmconstants.CACertName),
|
"client-ca-file": path.Join(cfg.CertificatesDir, kubeadmconstants.CACertName),
|
||||||
"tls-cert-file": getCertFilePath(kubeadmconstants.APIServerCertName),
|
"tls-cert-file": path.Join(cfg.CertificatesDir, kubeadmconstants.APIServerCertName),
|
||||||
"tls-private-key-file": getCertFilePath(kubeadmconstants.APIServerKeyName),
|
"tls-private-key-file": path.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKeyName),
|
||||||
"kubelet-client-certificate": getCertFilePath(kubeadmconstants.APIServerKubeletClientCertName),
|
"kubelet-client-certificate": path.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKubeletClientCertName),
|
||||||
"kubelet-client-key": getCertFilePath(kubeadmconstants.APIServerKubeletClientKeyName),
|
"kubelet-client-key": path.Join(cfg.CertificatesDir, kubeadmconstants.APIServerKubeletClientKeyName),
|
||||||
"token-auth-file": path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmconstants.CSVTokenFileName),
|
"token-auth-file": path.Join(cfg.CertificatesDir, kubeadmconstants.CSVTokenFileName),
|
||||||
"secure-port": fmt.Sprintf("%d", cfg.API.BindPort),
|
"secure-port": fmt.Sprintf("%d", cfg.API.BindPort),
|
||||||
"allow-privileged": "true",
|
"allow-privileged": "true",
|
||||||
"storage-backend": "etcd3",
|
"storage-backend": "etcd3",
|
||||||
@ -324,7 +320,7 @@ func getAPIServerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted bool) [
|
|||||||
"requestheader-username-headers": "X-Remote-User",
|
"requestheader-username-headers": "X-Remote-User",
|
||||||
"requestheader-group-headers": "X-Remote-Group",
|
"requestheader-group-headers": "X-Remote-Group",
|
||||||
"requestheader-extra-headers-prefix": "X-Remote-Extra-",
|
"requestheader-extra-headers-prefix": "X-Remote-Extra-",
|
||||||
"requestheader-client-ca-file": getCertFilePath(kubeadmconstants.FrontProxyCACertName),
|
"requestheader-client-ca-file": path.Join(cfg.CertificatesDir, kubeadmconstants.FrontProxyCACertName),
|
||||||
"requestheader-allowed-names": "front-proxy-client",
|
"requestheader-allowed-names": "front-proxy-client",
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -379,10 +375,10 @@ func getControllerManagerCommand(cfg *kubeadmapi.MasterConfiguration, selfHosted
|
|||||||
"address": "127.0.0.1",
|
"address": "127.0.0.1",
|
||||||
"leader-elect": "true",
|
"leader-elect": "true",
|
||||||
"kubeconfig": path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName),
|
"kubeconfig": path.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.ControllerManagerKubeConfigFileName),
|
||||||
"root-ca-file": getCertFilePath(kubeadmconstants.CACertName),
|
"root-ca-file": path.Join(cfg.CertificatesDir, kubeadmconstants.CACertName),
|
||||||
"service-account-private-key-file": getCertFilePath(kubeadmconstants.ServiceAccountPrivateKeyName),
|
"service-account-private-key-file": path.Join(cfg.CertificatesDir, kubeadmconstants.ServiceAccountPrivateKeyName),
|
||||||
"cluster-signing-cert-file": getCertFilePath(kubeadmconstants.CACertName),
|
"cluster-signing-cert-file": path.Join(cfg.CertificatesDir, kubeadmconstants.CACertName),
|
||||||
"cluster-signing-key-file": getCertFilePath(kubeadmconstants.CAKeyName),
|
"cluster-signing-key-file": path.Join(cfg.CertificatesDir, kubeadmconstants.CAKeyName),
|
||||||
"insecure-experimental-approve-all-kubelet-csrs-for-group": kubeadmconstants.CSVTokenBootstrapGroup,
|
"insecure-experimental-approve-all-kubelet-csrs-for-group": kubeadmconstants.CSVTokenBootstrapGroup,
|
||||||
"use-service-account-credentials": "true",
|
"use-service-account-credentials": "true",
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,8 @@ import (
|
|||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const testCertsDir = "/var/lib/certs"
|
||||||
|
|
||||||
func TestWriteStaticPodManifests(t *testing.T) {
|
func TestWriteStaticPodManifests(t *testing.T) {
|
||||||
tmpdir, err := ioutil.TempDir("", "")
|
tmpdir, err := ioutil.TempDir("", "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -380,21 +382,22 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
API: kubeadm.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"},
|
API: kubeadm.API{BindPort: 123, AdvertiseAddress: "1.2.3.4"},
|
||||||
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
||||||
|
CertificatesDir: testCertsDir,
|
||||||
},
|
},
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"kube-apiserver",
|
"kube-apiserver",
|
||||||
"--insecure-port=0",
|
"--insecure-port=0",
|
||||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
|
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
|
||||||
"--service-cluster-ip-range=bar",
|
"--service-cluster-ip-range=bar",
|
||||||
"--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/sa.pub",
|
"--service-account-key-file=" + testCertsDir + "/sa.pub",
|
||||||
"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--client-ca-file=" + testCertsDir + "/ca.crt",
|
||||||
"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt",
|
"--tls-cert-file=" + testCertsDir + "/apiserver.crt",
|
||||||
"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key",
|
"--tls-private-key-file=" + testCertsDir + "/apiserver.key",
|
||||||
"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt",
|
"--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt",
|
||||||
"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key",
|
"--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key",
|
||||||
"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv",
|
"--token-auth-file=" + testCertsDir + "/tokens.csv",
|
||||||
fmt.Sprintf("--secure-port=%d", 123),
|
fmt.Sprintf("--secure-port=%d", 123),
|
||||||
"--allow-privileged=true",
|
"--allow-privileged=true",
|
||||||
"--storage-backend=etcd3",
|
"--storage-backend=etcd3",
|
||||||
@ -402,7 +405,7 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
"--requestheader-username-headers=X-Remote-User",
|
"--requestheader-username-headers=X-Remote-User",
|
||||||
"--requestheader-group-headers=X-Remote-Group",
|
"--requestheader-group-headers=X-Remote-Group",
|
||||||
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
||||||
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
"--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt",
|
||||||
"--requestheader-allowed-names=front-proxy-client",
|
"--requestheader-allowed-names=front-proxy-client",
|
||||||
"--authorization-mode=RBAC",
|
"--authorization-mode=RBAC",
|
||||||
"--advertise-address=1.2.3.4",
|
"--advertise-address=1.2.3.4",
|
||||||
@ -411,21 +414,22 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
API: kubeadm.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"},
|
API: kubeadm.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"},
|
||||||
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
||||||
|
CertificatesDir: testCertsDir,
|
||||||
},
|
},
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"kube-apiserver",
|
"kube-apiserver",
|
||||||
"--insecure-port=0",
|
"--insecure-port=0",
|
||||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
|
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
|
||||||
"--service-cluster-ip-range=bar",
|
"--service-cluster-ip-range=bar",
|
||||||
"--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/sa.pub",
|
"--service-account-key-file=" + testCertsDir + "/sa.pub",
|
||||||
"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--client-ca-file=" + testCertsDir + "/ca.crt",
|
||||||
"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt",
|
"--tls-cert-file=" + testCertsDir + "/apiserver.crt",
|
||||||
"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key",
|
"--tls-private-key-file=" + testCertsDir + "/apiserver.key",
|
||||||
"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt",
|
"--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt",
|
||||||
"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key",
|
"--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key",
|
||||||
"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv",
|
"--token-auth-file=" + testCertsDir + "/tokens.csv",
|
||||||
fmt.Sprintf("--secure-port=%d", 123),
|
fmt.Sprintf("--secure-port=%d", 123),
|
||||||
"--allow-privileged=true",
|
"--allow-privileged=true",
|
||||||
"--storage-backend=etcd3",
|
"--storage-backend=etcd3",
|
||||||
@ -433,7 +437,7 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
"--requestheader-username-headers=X-Remote-User",
|
"--requestheader-username-headers=X-Remote-User",
|
||||||
"--requestheader-group-headers=X-Remote-Group",
|
"--requestheader-group-headers=X-Remote-Group",
|
||||||
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
||||||
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
"--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt",
|
||||||
"--requestheader-allowed-names=front-proxy-client",
|
"--requestheader-allowed-names=front-proxy-client",
|
||||||
"--authorization-mode=RBAC",
|
"--authorization-mode=RBAC",
|
||||||
"--advertise-address=4.3.2.1",
|
"--advertise-address=4.3.2.1",
|
||||||
@ -442,22 +446,23 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
API: kubeadm.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"},
|
API: kubeadm.API{BindPort: 123, AdvertiseAddress: "4.3.2.1"},
|
||||||
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
Networking: kubeadm.Networking{ServiceSubnet: "bar"},
|
||||||
Etcd: kubeadm.Etcd{CertFile: "fiz", KeyFile: "faz"},
|
Etcd: kubeadm.Etcd{CertFile: "fiz", KeyFile: "faz"},
|
||||||
|
CertificatesDir: testCertsDir,
|
||||||
},
|
},
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"kube-apiserver",
|
"kube-apiserver",
|
||||||
"--insecure-port=0",
|
"--insecure-port=0",
|
||||||
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
|
"--admission-control=NamespaceLifecycle,LimitRanger,ServiceAccount,PersistentVolumeLabel,DefaultStorageClass,ResourceQuota,DefaultTolerationSeconds",
|
||||||
"--service-cluster-ip-range=bar",
|
"--service-cluster-ip-range=bar",
|
||||||
"--service-account-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/sa.pub",
|
"--service-account-key-file=" + testCertsDir + "/sa.pub",
|
||||||
"--client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--client-ca-file=" + testCertsDir + "/ca.crt",
|
||||||
"--tls-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.crt",
|
"--tls-cert-file=" + testCertsDir + "/apiserver.crt",
|
||||||
"--tls-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver.key",
|
"--tls-private-key-file=" + testCertsDir + "/apiserver.key",
|
||||||
"--kubelet-client-certificate=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.crt",
|
"--kubelet-client-certificate=" + testCertsDir + "/apiserver-kubelet-client.crt",
|
||||||
"--kubelet-client-key=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/apiserver-kubelet-client.key",
|
"--kubelet-client-key=" + testCertsDir + "/apiserver-kubelet-client.key",
|
||||||
"--token-auth-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/tokens.csv",
|
"--token-auth-file=" + testCertsDir + "/tokens.csv",
|
||||||
fmt.Sprintf("--secure-port=%d", 123),
|
fmt.Sprintf("--secure-port=%d", 123),
|
||||||
"--allow-privileged=true",
|
"--allow-privileged=true",
|
||||||
"--storage-backend=etcd3",
|
"--storage-backend=etcd3",
|
||||||
@ -465,7 +470,7 @@ func TestGetAPIServerCommand(t *testing.T) {
|
|||||||
"--requestheader-username-headers=X-Remote-User",
|
"--requestheader-username-headers=X-Remote-User",
|
||||||
"--requestheader-group-headers=X-Remote-Group",
|
"--requestheader-group-headers=X-Remote-Group",
|
||||||
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
"--requestheader-extra-headers-prefix=X-Remote-Extra-",
|
||||||
"--requestheader-client-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/front-proxy-ca.crt",
|
"--requestheader-client-ca-file=" + testCertsDir + "/front-proxy-ca.crt",
|
||||||
"--requestheader-allowed-names=front-proxy-client",
|
"--requestheader-allowed-names=front-proxy-client",
|
||||||
"--authorization-mode=RBAC",
|
"--authorization-mode=RBAC",
|
||||||
"--advertise-address=4.3.2.1",
|
"--advertise-address=4.3.2.1",
|
||||||
@ -492,47 +497,55 @@ func TestGetControllerManagerCommand(t *testing.T) {
|
|||||||
expected []string
|
expected []string
|
||||||
}{
|
}{
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{},
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
|
CertificatesDir: testCertsDir,
|
||||||
|
},
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"kube-controller-manager",
|
"kube-controller-manager",
|
||||||
"--address=127.0.0.1",
|
"--address=127.0.0.1",
|
||||||
"--leader-elect=true",
|
"--leader-elect=true",
|
||||||
"--kubeconfig=" + kubeadmapi.GlobalEnvParams.KubernetesDir + "/controller-manager.conf",
|
"--kubeconfig=" + kubeadmapi.GlobalEnvParams.KubernetesDir + "/controller-manager.conf",
|
||||||
"--root-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--root-ca-file=" + testCertsDir + "/ca.crt",
|
||||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/sa.key",
|
"--service-account-private-key-file=" + testCertsDir + "/sa.key",
|
||||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--cluster-signing-cert-file=" + testCertsDir + "/ca.crt",
|
||||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.key",
|
"--cluster-signing-key-file=" + testCertsDir + "/ca.key",
|
||||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
||||||
"--use-service-account-credentials=true",
|
"--use-service-account-credentials=true",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{CloudProvider: "foo"},
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
|
CloudProvider: "foo",
|
||||||
|
CertificatesDir: testCertsDir,
|
||||||
|
},
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"kube-controller-manager",
|
"kube-controller-manager",
|
||||||
"--address=127.0.0.1",
|
"--address=127.0.0.1",
|
||||||
"--leader-elect=true",
|
"--leader-elect=true",
|
||||||
"--kubeconfig=" + kubeadmapi.GlobalEnvParams.KubernetesDir + "/controller-manager.conf",
|
"--kubeconfig=" + kubeadmapi.GlobalEnvParams.KubernetesDir + "/controller-manager.conf",
|
||||||
"--root-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--root-ca-file=" + testCertsDir + "/ca.crt",
|
||||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/sa.key",
|
"--service-account-private-key-file=" + testCertsDir + "/sa.key",
|
||||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--cluster-signing-cert-file=" + testCertsDir + "/ca.crt",
|
||||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.key",
|
"--cluster-signing-key-file=" + testCertsDir + "/ca.key",
|
||||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
||||||
"--use-service-account-credentials=true",
|
"--use-service-account-credentials=true",
|
||||||
"--cloud-provider=foo",
|
"--cloud-provider=foo",
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{Networking: kubeadm.Networking{PodSubnet: "bar"}},
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
|
Networking: kubeadm.Networking{PodSubnet: "bar"},
|
||||||
|
CertificatesDir: testCertsDir,
|
||||||
|
},
|
||||||
expected: []string{
|
expected: []string{
|
||||||
"kube-controller-manager",
|
"kube-controller-manager",
|
||||||
"--address=127.0.0.1",
|
"--address=127.0.0.1",
|
||||||
"--leader-elect=true",
|
"--leader-elect=true",
|
||||||
"--kubeconfig=" + kubeadmapi.GlobalEnvParams.KubernetesDir + "/controller-manager.conf",
|
"--kubeconfig=" + kubeadmapi.GlobalEnvParams.KubernetesDir + "/controller-manager.conf",
|
||||||
"--root-ca-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--root-ca-file=" + testCertsDir + "/ca.crt",
|
||||||
"--service-account-private-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/sa.key",
|
"--service-account-private-key-file=" + testCertsDir + "/sa.key",
|
||||||
"--cluster-signing-cert-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.crt",
|
"--cluster-signing-cert-file=" + testCertsDir + "/ca.crt",
|
||||||
"--cluster-signing-key-file=" + kubeadmapi.GlobalEnvParams.HostPKIPath + "/ca.key",
|
"--cluster-signing-key-file=" + testCertsDir + "/ca.key",
|
||||||
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
"--insecure-experimental-approve-all-kubelet-csrs-for-group=kubeadm:kubelet-bootstrap",
|
||||||
"--use-service-account-credentials=true",
|
"--use-service-account-credentials=true",
|
||||||
"--allocate-node-cidrs=true",
|
"--allocate-node-cidrs=true",
|
||||||
|
@ -32,6 +32,7 @@ go_library(
|
|||||||
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
|
"//cmd/kubeadm/app/phases/certs/pkiutil:go_default_library",
|
||||||
"//pkg/registry/core/service/ipallocator:go_default_library",
|
"//pkg/registry/core/service/ipallocator:go_default_library",
|
||||||
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
"//vendor:k8s.io/apimachinery/pkg/util/sets",
|
||||||
|
"//vendor:k8s.io/apimachinery/pkg/util/validation",
|
||||||
"//vendor:k8s.io/client-go/util/cert",
|
"//vendor:k8s.io/client-go/util/cert",
|
||||||
],
|
],
|
||||||
)
|
)
|
||||||
|
@ -24,6 +24,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
|
|
||||||
setutil "k8s.io/apimachinery/pkg/util/sets"
|
setutil "k8s.io/apimachinery/pkg/util/sets"
|
||||||
|
"k8s.io/apimachinery/pkg/util/validation"
|
||||||
certutil "k8s.io/client-go/util/cert"
|
certutil "k8s.io/client-go/util/cert"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
@ -40,34 +41,22 @@ import (
|
|||||||
|
|
||||||
// CreatePKIAssets will create and write to disk all PKI assets necessary to establish the control plane.
|
// CreatePKIAssets will create and write to disk all PKI assets necessary to establish the control plane.
|
||||||
// It generates a self-signed CA certificate and a server certificate (signed by the CA)
|
// It generates a self-signed CA certificate and a server certificate (signed by the CA)
|
||||||
func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error {
|
func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration) error {
|
||||||
altNames := certutil.AltNames{}
|
pkiDir := cfg.CertificatesDir
|
||||||
|
|
||||||
// First, define all domains this cert should be signed for
|
|
||||||
internalAPIServerFQDN := []string{
|
|
||||||
"kubernetes",
|
|
||||||
"kubernetes.default",
|
|
||||||
"kubernetes.default.svc",
|
|
||||||
fmt.Sprintf("kubernetes.default.svc.%s", cfg.Networking.DNSDomain),
|
|
||||||
}
|
|
||||||
hostname, err := os.Hostname()
|
hostname, err := os.Hostname()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("couldn't get the hostname: %v", err)
|
return fmt.Errorf("couldn't get the hostname: %v", err)
|
||||||
}
|
}
|
||||||
altNames.DNSNames = append(cfg.API.ExternalDNSNames, hostname)
|
|
||||||
altNames.DNSNames = append(altNames.DNSNames, internalAPIServerFQDN...)
|
|
||||||
|
|
||||||
// and lastly, extract the internal IP address for the API server
|
_, svcSubnet, err := net.ParseCIDR(cfg.Networking.ServiceSubnet)
|
||||||
_, n, err := net.ParseCIDR(cfg.Networking.ServiceSubnet)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("error parsing CIDR %q: %v", cfg.Networking.ServiceSubnet, err)
|
return fmt.Errorf("error parsing CIDR %q: %v", cfg.Networking.ServiceSubnet, err)
|
||||||
}
|
}
|
||||||
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(n, 1)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("unable to allocate IP address for the API server from the given CIDR (%q) [%v]", &cfg.Networking.ServiceSubnet, err)
|
|
||||||
}
|
|
||||||
|
|
||||||
altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP, net.ParseIP(cfg.API.AdvertiseAddress))
|
// Build the list of SANs
|
||||||
|
altNames := getAltNames(cfg.APIServerCertSANs, hostname, cfg.Networking.DNSDomain, svcSubnet)
|
||||||
|
// Append the address the API Server is advertising
|
||||||
|
altNames.IPs = append(altNames.IPs, net.ParseIP(cfg.API.AdvertiseAddress))
|
||||||
|
|
||||||
var caCert *x509.Certificate
|
var caCert *x509.Certificate
|
||||||
var caKey *rsa.PrivateKey
|
var caKey *rsa.PrivateKey
|
||||||
@ -126,6 +115,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error {
|
|||||||
return fmt.Errorf("failure while saving API server certificate and key [%v]", err)
|
return fmt.Errorf("failure while saving API server certificate and key [%v]", err)
|
||||||
}
|
}
|
||||||
fmt.Println("[certificates] Generated API server certificate and key.")
|
fmt.Println("[certificates] Generated API server certificate and key.")
|
||||||
|
fmt.Printf("[certificates] API Server serving cert is signed for DNS names %v and IPs %v\n", altNames.DNSNames, altNames.IPs)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If at least one of them exists, we should try to load them
|
// If at least one of them exists, we should try to load them
|
||||||
@ -158,9 +148,9 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// If the key exists, we should try to load it
|
// If the key exists, we should try to load it
|
||||||
if pkiutil.CertOrKeyExist(pkiDir, kubeadmconstants.ServiceAccountPrivateKeyName) {
|
if pkiutil.CertOrKeyExist(pkiDir, kubeadmconstants.ServiceAccountKeyBaseName) {
|
||||||
// Try to load sa.key from the PKI directory
|
// Try to load sa.key from the PKI directory
|
||||||
_, err := pkiutil.TryLoadKeyFromDisk(pkiDir, kubeadmconstants.ServiceAccountPrivateKeyName)
|
_, err := pkiutil.TryLoadKeyFromDisk(pkiDir, kubeadmconstants.ServiceAccountKeyBaseName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("certificate and/or key existed but they could not be loaded properly [%v]", err)
|
return fmt.Errorf("certificate and/or key existed but they could not be loaded properly [%v]", err)
|
||||||
}
|
}
|
||||||
@ -176,12 +166,11 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error {
|
|||||||
if err = pkiutil.WriteKey(pkiDir, kubeadmconstants.ServiceAccountKeyBaseName, saTokenSigningKey); err != nil {
|
if err = pkiutil.WriteKey(pkiDir, kubeadmconstants.ServiceAccountKeyBaseName, saTokenSigningKey); err != nil {
|
||||||
return fmt.Errorf("failure while saving service account token signing key [%v]", err)
|
return fmt.Errorf("failure while saving service account token signing key [%v]", err)
|
||||||
}
|
}
|
||||||
fmt.Println("[certificates] Generated service account token signing key.")
|
|
||||||
|
|
||||||
if err = pkiutil.WritePublicKey(pkiDir, kubeadmconstants.ServiceAccountKeyBaseName, &saTokenSigningKey.PublicKey); err != nil {
|
if err = pkiutil.WritePublicKey(pkiDir, kubeadmconstants.ServiceAccountKeyBaseName, &saTokenSigningKey.PublicKey); err != nil {
|
||||||
return fmt.Errorf("failure while saving service account token signing public key [%v]", err)
|
return fmt.Errorf("failure while saving service account token signing public key [%v]", err)
|
||||||
}
|
}
|
||||||
fmt.Println("[certificates] Generated service account token signing public key.")
|
fmt.Println("[certificates] Generated service account token signing key and public key.")
|
||||||
}
|
}
|
||||||
|
|
||||||
// front proxy CA and client certs are used to secure a front proxy authenticator which is used to assert identity
|
// front proxy CA and client certs are used to secure a front proxy authenticator which is used to assert identity
|
||||||
@ -254,7 +243,7 @@ func CreatePKIAssets(cfg *kubeadmapi.MasterConfiguration, pkiDir string) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Verify that the cert is valid for all IPs and DNS names it should be valid for
|
// checkAltNamesExist verifies that the cert is valid for all IPs and DNS names it should be valid for
|
||||||
func checkAltNamesExist(IPs []net.IP, DNSNames []string, altNames certutil.AltNames) bool {
|
func checkAltNamesExist(IPs []net.IP, DNSNames []string, altNames certutil.AltNames) bool {
|
||||||
dnsset := setutil.NewString(DNSNames...)
|
dnsset := setutil.NewString(DNSNames...)
|
||||||
|
|
||||||
@ -279,3 +268,33 @@ func checkAltNamesExist(IPs []net.IP, DNSNames []string, altNames certutil.AltNa
|
|||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// getAltNames builds an AltNames object for the certutil to use when generating the certificates
|
||||||
|
func getAltNames(cfgAltNames []string, hostname, dnsdomain string, svcSubnet *net.IPNet) certutil.AltNames {
|
||||||
|
altNames := certutil.AltNames{
|
||||||
|
DNSNames: []string{
|
||||||
|
hostname,
|
||||||
|
"kubernetes",
|
||||||
|
"kubernetes.default",
|
||||||
|
"kubernetes.default.svc",
|
||||||
|
fmt.Sprintf("kubernetes.default.svc.%s", dnsdomain),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
// Populate IPs/DNSNames from AltNames
|
||||||
|
for _, altname := range cfgAltNames {
|
||||||
|
if ip := net.ParseIP(altname); ip != nil {
|
||||||
|
altNames.IPs = append(altNames.IPs, ip)
|
||||||
|
} else if len(validation.IsDNS1123Subdomain(altname)) == 0 {
|
||||||
|
altNames.DNSNames = append(altNames.DNSNames, altname)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// and lastly, extract the internal IP address for the API server
|
||||||
|
internalAPIServerVirtualIP, err := ipallocator.GetIndexedIP(svcSubnet, 1)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("[certs] WARNING: Unable to get first IP address from the given CIDR (%s): %v\n", svcSubnet.String(), err)
|
||||||
|
}
|
||||||
|
altNames.IPs = append(altNames.IPs, internalAPIServerVirtualIP)
|
||||||
|
return altNames
|
||||||
|
}
|
||||||
|
@ -45,29 +45,32 @@ func TestCreatePKIAssets(t *testing.T) {
|
|||||||
{
|
{
|
||||||
// CIDR too small
|
// CIDR too small
|
||||||
cfg: &kubeadmapi.MasterConfiguration{
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"},
|
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"},
|
||||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
|
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/1"},
|
||||||
|
CertificatesDir: fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir),
|
||||||
},
|
},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// CIDR invalid
|
// CIDR invalid
|
||||||
cfg: &kubeadmapi.MasterConfiguration{
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"},
|
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"},
|
||||||
Networking: kubeadmapi.Networking{ServiceSubnet: "invalid"},
|
Networking: kubeadmapi.Networking{ServiceSubnet: "invalid"},
|
||||||
|
CertificatesDir: fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir),
|
||||||
},
|
},
|
||||||
expected: false,
|
expected: false,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
cfg: &kubeadmapi.MasterConfiguration{
|
cfg: &kubeadmapi.MasterConfiguration{
|
||||||
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"},
|
API: kubeadmapi.API{AdvertiseAddress: "1.2.3.4"},
|
||||||
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/24"},
|
Networking: kubeadmapi.Networking{ServiceSubnet: "10.0.0.1/24"},
|
||||||
|
CertificatesDir: fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir),
|
||||||
},
|
},
|
||||||
expected: true,
|
expected: true,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
for _, rt := range tests {
|
for _, rt := range tests {
|
||||||
actual := CreatePKIAssets(rt.cfg, fmt.Sprintf("%s/etc/kubernetes/pki", tmpdir))
|
actual := CreatePKIAssets(rt.cfg)
|
||||||
if (actual == nil) != rt.expected {
|
if (actual == nil) != rt.expected {
|
||||||
t.Errorf(
|
t.Errorf(
|
||||||
"failed CreatePKIAssets with an error:\n\texpected: %t\n\t actual: %t",
|
"failed CreatePKIAssets with an error:\n\texpected: %t\n\t actual: %t",
|
||||||
@ -126,3 +129,46 @@ func TestCheckAltNamesExist(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGetAltNames(t *testing.T) {
|
||||||
|
var tests = []struct {
|
||||||
|
cfgaltnames []string
|
||||||
|
hostname string
|
||||||
|
dnsdomain string
|
||||||
|
servicecidr string
|
||||||
|
expectedIPs []string
|
||||||
|
expectedDNSNames []string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
cfgaltnames: []string{"foo", "192.168.200.1", "bar.baz"},
|
||||||
|
hostname: "my-node",
|
||||||
|
dnsdomain: "cluster.external",
|
||||||
|
servicecidr: "10.96.0.1/12",
|
||||||
|
expectedIPs: []string{"192.168.200.1", "10.96.0.1"},
|
||||||
|
expectedDNSNames: []string{"my-node", "kubernetes", "kubernetes.default", "kubernetes.default.svc", "kubernetes.default.svc.cluster.external", "foo", "bar.baz"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, rt := range tests {
|
||||||
|
_, svcSubnet, _ := net.ParseCIDR(rt.servicecidr)
|
||||||
|
actual := getAltNames(rt.cfgaltnames, rt.hostname, rt.dnsdomain, svcSubnet)
|
||||||
|
for i := range actual.IPs {
|
||||||
|
if rt.expectedIPs[i] != actual.IPs[i].String() {
|
||||||
|
t.Errorf(
|
||||||
|
"failed getAltNames:\n\texpected: %s\n\t actual: %s",
|
||||||
|
rt.expectedIPs[i],
|
||||||
|
actual.IPs[i].String(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for i := range actual.DNSNames {
|
||||||
|
if rt.expectedDNSNames[i] != actual.DNSNames[i] {
|
||||||
|
t.Errorf(
|
||||||
|
"failed getAltNames:\n\texpected: %s\n\t actual: %s",
|
||||||
|
rt.expectedDNSNames[i],
|
||||||
|
actual.DNSNames[i],
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -22,16 +22,25 @@ package certs
|
|||||||
|
|
||||||
INPUTS:
|
INPUTS:
|
||||||
From MasterConfiguration
|
From MasterConfiguration
|
||||||
.API.ExternalDNSNames is needed for knowing which DNS names the certs should be signed for
|
.API.AdvertiseAddress is an optional parameter that can be passed for an extra addition to the SAN IPs
|
||||||
|
.APIServerCertSANs is needed for knowing which DNS names and IPs the API Server serving cert should be valid for
|
||||||
.Networking.DNSDomain is needed for knowing which DNS name the internal kubernetes service has
|
.Networking.DNSDomain is needed for knowing which DNS name the internal kubernetes service has
|
||||||
.Networking.ServiceSubnet is needed for knowing which IP the internal kubernetes service is going to point to
|
.Networking.ServiceSubnet is needed for knowing which IP the internal kubernetes service is going to point to
|
||||||
The PKIPath is required for knowing where all certificates should be stored
|
.CertificatesDir is required for knowing where all certificates should be stored
|
||||||
|
|
||||||
OUTPUTS:
|
OUTPUTS:
|
||||||
Files to PKIPath (default /etc/kubernetes/pki):
|
Files to .CertificatesDir (default /etc/kubernetes/pki):
|
||||||
- ca.crt
|
- ca.crt
|
||||||
- ca.key
|
- ca.key
|
||||||
- apiserver.crt
|
- apiserver.crt
|
||||||
- apiserver.key
|
- apiserver.key
|
||||||
|
- apiserver-kubelet-client.crt
|
||||||
|
- apiserver-kubelet-client.key
|
||||||
|
- sa.pub
|
||||||
|
- sa.key
|
||||||
|
- front-proxy-ca.crt
|
||||||
|
- front-proxy-ca.key
|
||||||
|
- front-proxy-client.crt
|
||||||
|
- front-proxy-client.key
|
||||||
|
|
||||||
*/
|
*/
|
||||||
|
@ -23,16 +23,15 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
|
|
||||||
"k8s.io/apimachinery/pkg/util/uuid"
|
"k8s.io/apimachinery/pkg/util/uuid"
|
||||||
kubeadmapi "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm"
|
|
||||||
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
|
||||||
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
cmdutil "k8s.io/kubernetes/pkg/kubectl/cmd/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CreateTokenAuthFile creates the CSV file that can be used for allowing users with tokens access to the API Server
|
// CreateTokenAuthFile creates the CSV file that can be used for allowing users with tokens access to the API Server
|
||||||
func CreateTokenAuthFile(bt string) error {
|
func CreateTokenAuthFile(certsDir, bt string) error {
|
||||||
tokenAuthFilePath := path.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmconstants.CSVTokenFileName)
|
tokenAuthFilePath := path.Join(certsDir, kubeadmconstants.CSVTokenFileName)
|
||||||
if err := os.MkdirAll(kubeadmapi.GlobalEnvParams.HostPKIPath, 0700); err != nil {
|
if err := os.MkdirAll(certsDir, 0700); err != nil {
|
||||||
return fmt.Errorf("failed to create directory %q [%v]", kubeadmapi.GlobalEnvParams.HostPKIPath, err)
|
return fmt.Errorf("failed to create directory %q [%v]", certsDir, err)
|
||||||
}
|
}
|
||||||
serialized := []byte(fmt.Sprintf("%s,%s,%s,%s\n", bt, kubeadmconstants.CSVTokenBootstrapUser, uuid.NewUUID(), kubeadmconstants.CSVTokenBootstrapGroup))
|
serialized := []byte(fmt.Sprintf("%s,%s,%s,%s\n", bt, kubeadmconstants.CSVTokenBootstrapUser, uuid.NewUUID(), kubeadmconstants.CSVTokenBootstrapGroup))
|
||||||
// DumpReaderToFile create a file with mode 0600
|
// DumpReaderToFile create a file with mode 0600
|
||||||
|
@ -540,7 +540,7 @@ func RunJoinNodeChecks(cfg *kubeadmapi.NodeConfiguration) error {
|
|||||||
PortOpenCheck{port: 10250},
|
PortOpenCheck{port: 10250},
|
||||||
DirAvailableCheck{Path: filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
DirAvailableCheck{Path: filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, "manifests")},
|
||||||
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
DirAvailableCheck{Path: "/var/lib/kubelet"},
|
||||||
FileAvailableCheck{Path: filepath.Join(kubeadmapi.GlobalEnvParams.HostPKIPath, kubeadmconstants.CACertName)},
|
FileAvailableCheck{Path: cfg.CACertPath},
|
||||||
FileAvailableCheck{Path: filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)},
|
FileAvailableCheck{Path: filepath.Join(kubeadmapi.GlobalEnvParams.KubernetesDir, kubeadmconstants.KubeletKubeConfigFileName)},
|
||||||
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
FileContentCheck{Path: bridgenf, Content: []byte{'1'}},
|
||||||
InPathCheck{executable: "ip", mandatory: true},
|
InPathCheck{executable: "ip", mandatory: true},
|
||||||
|
@ -20,6 +20,7 @@ apiserver-advertise-address
|
|||||||
apiserver-arg-overrides
|
apiserver-arg-overrides
|
||||||
apiserver-arg-overrides
|
apiserver-arg-overrides
|
||||||
apiserver-bind-port
|
apiserver-bind-port
|
||||||
|
apiserver-cert-extra-sans
|
||||||
apiserver-count
|
apiserver-count
|
||||||
apiserver-count
|
apiserver-count
|
||||||
apiserver-count
|
apiserver-count
|
||||||
@ -67,6 +68,7 @@ build-only
|
|||||||
build-tag
|
build-tag
|
||||||
ca-cert-path
|
ca-cert-path
|
||||||
cadvisor-port
|
cadvisor-port
|
||||||
|
cert-altnames
|
||||||
cert-dir
|
cert-dir
|
||||||
certificate-authority
|
certificate-authority
|
||||||
cgroup-driver
|
cgroup-driver
|
||||||
@ -158,6 +160,7 @@ discovery-file
|
|||||||
discovery-port
|
discovery-port
|
||||||
discovery-token
|
discovery-token
|
||||||
dns-bind-address
|
dns-bind-address
|
||||||
|
dns-domain
|
||||||
dns-port
|
dns-port
|
||||||
dns-provider
|
dns-provider
|
||||||
dns-provider-config
|
dns-provider-config
|
||||||
|
Loading…
Reference in New Issue
Block a user