mirror of
https://github.com/rancher/rke.git
synced 2025-08-13 20:46:51 +00:00
Add per node kubelet server certificate
This commit is contained in:
parent
e811e18fb3
commit
adc5941fd9
@ -44,7 +44,7 @@ func GetClusterCertsFromKubernetes(ctx context.Context, kubeCluster *Cluster) (m
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, etcdHost := range kubeCluster.EtcdHosts {
|
for _, etcdHost := range kubeCluster.EtcdHosts {
|
||||||
etcdName := pki.GetEtcdCrtName(etcdHost.InternalAddress)
|
etcdName := pki.GetCrtNameForHost(etcdHost, pki.EtcdCertName)
|
||||||
certificatesNames = append(certificatesNames, etcdName)
|
certificatesNames = append(certificatesNames, etcdName)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -121,13 +121,16 @@ func RotateRKECertificates(ctx context.Context, c *Cluster, flags ExternalFlags,
|
|||||||
var (
|
var (
|
||||||
serviceAccountTokenKey string
|
serviceAccountTokenKey string
|
||||||
)
|
)
|
||||||
componentsCertsFuncMap := map[string]pki.GenFunc{
|
componentsCertsFuncMap := map[string][]pki.GenFunc{
|
||||||
services.KubeAPIContainerName: pki.GenerateKubeAPICertificate,
|
services.KubeAPIContainerName: []pki.GenFunc{pki.GenerateKubeAPICertificate},
|
||||||
services.KubeControllerContainerName: pki.GenerateKubeControllerCertificate,
|
services.KubeControllerContainerName: []pki.GenFunc{pki.GenerateKubeControllerCertificate},
|
||||||
services.SchedulerContainerName: pki.GenerateKubeSchedulerCertificate,
|
services.SchedulerContainerName: []pki.GenFunc{pki.GenerateKubeSchedulerCertificate},
|
||||||
services.KubeproxyContainerName: pki.GenerateKubeProxyCertificate,
|
services.KubeproxyContainerName: []pki.GenFunc{pki.GenerateKubeProxyCertificate},
|
||||||
services.KubeletContainerName: pki.GenerateKubeNodeCertificate,
|
services.KubeletContainerName: []pki.GenFunc{pki.GenerateKubeNodeCertificate},
|
||||||
services.EtcdContainerName: pki.GenerateEtcdCertificates,
|
services.EtcdContainerName: []pki.GenFunc{pki.GenerateEtcdCertificates},
|
||||||
|
}
|
||||||
|
if c.IsKubeletGenerateServingCertificateEnabled() {
|
||||||
|
componentsCertsFuncMap[services.KubeletContainerName] = append(componentsCertsFuncMap[services.KubeletContainerName], pki.GenerateKubeletCertificate)
|
||||||
}
|
}
|
||||||
rotateFlags := c.RancherKubernetesEngineConfig.RotateCertificates
|
rotateFlags := c.RancherKubernetesEngineConfig.RotateCertificates
|
||||||
if rotateFlags.CACertificates {
|
if rotateFlags.CACertificates {
|
||||||
@ -138,13 +141,15 @@ func RotateRKECertificates(ctx context.Context, c *Cluster, flags ExternalFlags,
|
|||||||
rotateFlags.Services = nil
|
rotateFlags.Services = nil
|
||||||
}
|
}
|
||||||
for _, k8sComponent := range rotateFlags.Services {
|
for _, k8sComponent := range rotateFlags.Services {
|
||||||
genFunc := componentsCertsFuncMap[k8sComponent]
|
genFunctions := componentsCertsFuncMap[k8sComponent]
|
||||||
if genFunc != nil {
|
if genFunctions != nil {
|
||||||
|
for _, genFunc := range genFunctions {
|
||||||
if err := genFunc(ctx, c.Certificates, c.RancherKubernetesEngineConfig, flags.ClusterFilePath, flags.ConfigDir, true); err != nil {
|
if err := genFunc(ctx, c.Certificates, c.RancherKubernetesEngineConfig, flags.ClusterFilePath, flags.ConfigDir, true); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// to handle kontainer engine sending empty string for services
|
// to handle kontainer engine sending empty string for services
|
||||||
if len(rotateFlags.Services) == 0 || (len(rotateFlags.Services) == 1 && rotateFlags.Services[0] == "") {
|
if len(rotateFlags.Services) == 0 || (len(rotateFlags.Services) == 1 && rotateFlags.Services[0] == "") {
|
||||||
// do not rotate service account token
|
// do not rotate service account token
|
||||||
@ -216,3 +221,13 @@ func compareCerts(ctx context.Context, kubeCluster, currentCluster *Cluster) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Cluster) IsKubeletGenerateServingCertificateEnabled() bool {
|
||||||
|
if c == nil {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
if c.Services.Kubelet.GenerateServingCertificate {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -222,6 +222,10 @@ func (c *Cluster) BuildKubeAPIProcess(host *hosts.Host, prefixPath string, svcOp
|
|||||||
CommandArgs["experimental-encryption-provider-config"] = EncryptionProviderFilePath
|
CommandArgs["experimental-encryption-provider-config"] = EncryptionProviderFilePath
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if c.IsKubeletGenerateServingCertificateEnabled() {
|
||||||
|
CommandArgs["kubelet-certificate-authority"] = pki.GetCertPath(pki.CACertName)
|
||||||
|
}
|
||||||
|
|
||||||
serviceOptions := c.GetKubernetesServicesOptions(host.DockerInfo.OSType, svcOptionData)
|
serviceOptions := c.GetKubernetesServicesOptions(host.DockerInfo.OSType, svcOptionData)
|
||||||
if serviceOptions.KubeAPI != nil {
|
if serviceOptions.KubeAPI != nil {
|
||||||
for k, v := range serviceOptions.KubeAPI {
|
for k, v := range serviceOptions.KubeAPI {
|
||||||
@ -451,6 +455,11 @@ func (c *Cluster) BuildKubeletProcess(host *hosts.Host, prefixPath string, svcOp
|
|||||||
CommandArgs["cloud-config"] = path.Join(prefixPath, cloudConfigFileName)
|
CommandArgs["cloud-config"] = path.Join(prefixPath, cloudConfigFileName)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if c.IsKubeletGenerateServingCertificateEnabled() {
|
||||||
|
CommandArgs["tls-cert-file"] = pki.GetCertPath(pki.GetCrtNameForHost(host, pki.KubeletCertName))
|
||||||
|
CommandArgs["tls-private-key-file"] = pki.GetCertPath(fmt.Sprintf("%s-key", pki.GetCrtNameForHost(host, pki.KubeletCertName)))
|
||||||
|
}
|
||||||
|
|
||||||
if len(c.CloudProvider.Name) > 0 {
|
if len(c.CloudProvider.Name) > 0 {
|
||||||
c.Services.Kubelet.ExtraEnv = append(
|
c.Services.Kubelet.ExtraEnv = append(
|
||||||
c.Services.Kubelet.ExtraEnv,
|
c.Services.Kubelet.ExtraEnv,
|
||||||
@ -891,7 +900,7 @@ func (c *Cluster) BuildSidecarProcess(host *hosts.Host, prefixPath string) v3.Pr
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) BuildEtcdProcess(host *hosts.Host, etcdHosts []*hosts.Host, prefixPath string) v3.Process {
|
func (c *Cluster) BuildEtcdProcess(host *hosts.Host, etcdHosts []*hosts.Host, prefixPath string) v3.Process {
|
||||||
nodeName := pki.GetEtcdCrtName(host.InternalAddress)
|
nodeName := pki.GetCrtNameForHost(host, pki.EtcdCertName)
|
||||||
initCluster := ""
|
initCluster := ""
|
||||||
architecture := "amd64"
|
architecture := "amd64"
|
||||||
if len(etcdHosts) == 0 {
|
if len(etcdHosts) == 0 {
|
||||||
|
@ -351,7 +351,7 @@ func restartComponentsWhenCertChanges(ctx context.Context, currentCluster, kubeC
|
|||||||
}
|
}
|
||||||
|
|
||||||
for _, host := range kubeCluster.EtcdHosts {
|
for _, host := range kubeCluster.EtcdHosts {
|
||||||
etcdCertName := pki.GetEtcdCrtName(host.Address)
|
etcdCertName := pki.GetCrtNameForHost(host, pki.EtcdCertName)
|
||||||
certMap := map[string]bool{
|
certMap := map[string]bool{
|
||||||
etcdCertName: false,
|
etcdCertName: false,
|
||||||
}
|
}
|
||||||
|
@ -274,6 +274,16 @@ func buildCleanerConfig(host *Host, toCleanDirs []string, cleanerImage string) (
|
|||||||
|
|
||||||
func NodesToHosts(rkeNodes []v3.RKEConfigNode, nodeRole string) []*Host {
|
func NodesToHosts(rkeNodes []v3.RKEConfigNode, nodeRole string) []*Host {
|
||||||
hostList := make([]*Host, 0)
|
hostList := make([]*Host, 0)
|
||||||
|
// Return all nodes if there is no noderole passed to the function
|
||||||
|
if nodeRole == "" {
|
||||||
|
for _, node := range rkeNodes {
|
||||||
|
newHost := Host{
|
||||||
|
RKEConfigNode: node,
|
||||||
|
}
|
||||||
|
hostList = append(hostList, &newHost)
|
||||||
|
}
|
||||||
|
return hostList
|
||||||
|
}
|
||||||
for _, node := range rkeNodes {
|
for _, node := range rkeNodes {
|
||||||
for _, role := range node.Role {
|
for _, role := range node.Role {
|
||||||
if role == nodeRole {
|
if role == nodeRole {
|
||||||
|
@ -21,6 +21,7 @@ const (
|
|||||||
KubeSchedulerCertName = "kube-scheduler"
|
KubeSchedulerCertName = "kube-scheduler"
|
||||||
KubeProxyCertName = "kube-proxy"
|
KubeProxyCertName = "kube-proxy"
|
||||||
KubeNodeCertName = "kube-node"
|
KubeNodeCertName = "kube-node"
|
||||||
|
KubeletCertName = "kube-kubelet"
|
||||||
EtcdCertName = "kube-etcd"
|
EtcdCertName = "kube-etcd"
|
||||||
EtcdClientCACertName = "kube-etcd-client-ca"
|
EtcdClientCACertName = "kube-etcd-client-ca"
|
||||||
EtcdClientCertName = "kube-etcd-client"
|
EtcdClientCertName = "kube-etcd-client"
|
||||||
|
@ -26,6 +26,16 @@ const (
|
|||||||
func DeployCertificatesOnPlaneHost(ctx context.Context, host *hosts.Host, rkeConfig v3.RancherKubernetesEngineConfig, crtMap map[string]CertificatePKI, certDownloaderImage string, prsMap map[string]v3.PrivateRegistry, forceDeploy bool) error {
|
func DeployCertificatesOnPlaneHost(ctx context.Context, host *hosts.Host, rkeConfig v3.RancherKubernetesEngineConfig, crtMap map[string]CertificatePKI, certDownloaderImage string, prsMap map[string]v3.PrivateRegistry, forceDeploy bool) error {
|
||||||
crtBundle := GenerateRKENodeCerts(ctx, rkeConfig, host.Address, crtMap)
|
crtBundle := GenerateRKENodeCerts(ctx, rkeConfig, host.Address, crtMap)
|
||||||
env := []string{}
|
env := []string{}
|
||||||
|
|
||||||
|
// Strip CA key as its sensitive and unneeded on nodes without controlplane role
|
||||||
|
if !host.IsControl {
|
||||||
|
caCert := crtBundle[CACertName]
|
||||||
|
caCert.Key = nil
|
||||||
|
caCert.KeyEnvName = ""
|
||||||
|
caCert.KeyPath = ""
|
||||||
|
crtBundle[CACertName] = caCert
|
||||||
|
}
|
||||||
|
|
||||||
for _, crt := range crtBundle {
|
for _, crt := range crtBundle {
|
||||||
env = append(env, crt.ToEnv()...)
|
env = append(env, crt.ToEnv()...)
|
||||||
}
|
}
|
||||||
@ -192,7 +202,7 @@ func FetchCertificatesFromHost(ctx context.Context, extraHosts []*hosts.Host, ho
|
|||||||
|
|
||||||
for _, etcdHost := range extraHosts {
|
for _, etcdHost := range extraHosts {
|
||||||
// Fetch etcd certificates
|
// Fetch etcd certificates
|
||||||
crtList[GetEtcdCrtName(etcdHost.InternalAddress)] = false
|
crtList[GetCrtNameForHost(etcdHost, EtcdCertName)] = false
|
||||||
}
|
}
|
||||||
|
|
||||||
for certName, config := range crtList {
|
for certName, config := range crtList {
|
||||||
|
26
pki/pki.go
26
pki/pki.go
@ -62,22 +62,11 @@ func GenerateRKECerts(ctx context.Context, rkeConfig v3.RancherKubernetesEngineC
|
|||||||
func GenerateRKENodeCerts(ctx context.Context, rkeConfig v3.RancherKubernetesEngineConfig, nodeAddress string, certBundle map[string]CertificatePKI) map[string]CertificatePKI {
|
func GenerateRKENodeCerts(ctx context.Context, rkeConfig v3.RancherKubernetesEngineConfig, nodeAddress string, certBundle map[string]CertificatePKI) map[string]CertificatePKI {
|
||||||
crtMap := make(map[string]CertificatePKI)
|
crtMap := make(map[string]CertificatePKI)
|
||||||
crtKeys := []string{}
|
crtKeys := []string{}
|
||||||
removeCAKey := true
|
|
||||||
for _, node := range rkeConfig.Nodes {
|
for _, node := range rkeConfig.Nodes {
|
||||||
if node.Address == nodeAddress {
|
if node.Address == nodeAddress {
|
||||||
for _, role := range node.Role {
|
for _, role := range node.Role {
|
||||||
switch role {
|
keys := getCertKeys(rkeConfig.Nodes, role, &rkeConfig)
|
||||||
case controlRole:
|
|
||||||
keys := getControlCertKeys()
|
|
||||||
crtKeys = append(crtKeys, keys...)
|
crtKeys = append(crtKeys, keys...)
|
||||||
removeCAKey = false
|
|
||||||
case workerRole:
|
|
||||||
keys := getWorkerCertKeys()
|
|
||||||
crtKeys = append(crtKeys, keys...)
|
|
||||||
case etcdRole:
|
|
||||||
keys := getEtcdCertKeys(rkeConfig.Nodes, etcdRole)
|
|
||||||
crtKeys = append(crtKeys, keys...)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
@ -85,13 +74,6 @@ func GenerateRKENodeCerts(ctx context.Context, rkeConfig v3.RancherKubernetesEng
|
|||||||
for _, key := range crtKeys {
|
for _, key := range crtKeys {
|
||||||
crtMap[key] = certBundle[key]
|
crtMap[key] = certBundle[key]
|
||||||
}
|
}
|
||||||
if removeCAKey {
|
|
||||||
caCert := crtMap[CACertName]
|
|
||||||
caCert.Key = nil
|
|
||||||
caCert.KeyEnvName = ""
|
|
||||||
caCert.KeyPath = ""
|
|
||||||
crtMap[CACertName] = caCert
|
|
||||||
}
|
|
||||||
return crtMap
|
return crtMap
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -103,7 +85,8 @@ func RegenerateEtcdCertificate(
|
|||||||
clusterDomain string,
|
clusterDomain string,
|
||||||
KubernetesServiceIP net.IP) (map[string]CertificatePKI, error) {
|
KubernetesServiceIP net.IP) (map[string]CertificatePKI, error) {
|
||||||
|
|
||||||
log.Infof(ctx, "[certificates] Regenerating new etcd-%s certificate and key", etcdHost.InternalAddress)
|
etcdName := GetCrtNameForHost(etcdHost, EtcdCertName)
|
||||||
|
log.Infof(ctx, "[certificates] Regenerating new %s certificate and key", etcdName)
|
||||||
caCrt := crtMap[CACertName].Certificate
|
caCrt := crtMap[CACertName].Certificate
|
||||||
caKey := crtMap[CACertName].Key
|
caKey := crtMap[CACertName].Key
|
||||||
etcdAltNames := GetAltNames(etcdHosts, clusterDomain, KubernetesServiceIP, []string{})
|
etcdAltNames := GetAltNames(etcdHosts, clusterDomain, KubernetesServiceIP, []string{})
|
||||||
@ -112,9 +95,8 @@ func RegenerateEtcdCertificate(
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
etcdName := GetEtcdCrtName(etcdHost.InternalAddress)
|
|
||||||
crtMap[etcdName] = ToCertObject(etcdName, "", "", etcdCrt, etcdKey, nil)
|
crtMap[etcdName] = ToCertObject(etcdName, "", "", etcdCrt, etcdKey, nil)
|
||||||
log.Infof(ctx, "[certificates] Successfully generated new etcd-%s certificate and key", etcdHost.InternalAddress)
|
log.Infof(ctx, "[certificates] Successfully generated new %s certificate and key", etcdName)
|
||||||
return crtMap, nil
|
return crtMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ func GenerateKubeAPICertificate(ctx context.Context, certs map[string]Certificat
|
|||||||
kubeAPICert := certs[KubeAPICertName].Certificate
|
kubeAPICert := certs[KubeAPICertName].Certificate
|
||||||
if kubeAPICert != nil &&
|
if kubeAPICert != nil &&
|
||||||
reflect.DeepEqual(kubeAPIAltNames.DNSNames, kubeAPICert.DNSNames) &&
|
reflect.DeepEqual(kubeAPIAltNames.DNSNames, kubeAPICert.DNSNames) &&
|
||||||
deepEqualIPsAltNames(kubeAPIAltNames.IPs, kubeAPICert.IPAddresses) && !rotate {
|
DeepEqualIPsAltNames(kubeAPIAltNames.IPs, kubeAPICert.IPAddresses) && !rotate {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Infof(ctx, "[certificates] Generating Kubernetes API server certificates")
|
log.Infof(ctx, "[certificates] Generating Kubernetes API server certificates")
|
||||||
@ -65,7 +65,7 @@ func GenerateKubeAPICSR(ctx context.Context, certs map[string]CertificatePKI, rk
|
|||||||
oldKubeAPICSR := certs[KubeAPICertName].CSR
|
oldKubeAPICSR := certs[KubeAPICertName].CSR
|
||||||
if oldKubeAPICSR != nil &&
|
if oldKubeAPICSR != nil &&
|
||||||
reflect.DeepEqual(kubeAPIAltNames.DNSNames, oldKubeAPICSR.DNSNames) &&
|
reflect.DeepEqual(kubeAPIAltNames.DNSNames, oldKubeAPICSR.DNSNames) &&
|
||||||
deepEqualIPsAltNames(kubeAPIAltNames.IPs, oldKubeAPICSR.IPAddresses) {
|
DeepEqualIPsAltNames(kubeAPIAltNames.IPs, oldKubeAPICSR.IPAddresses) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Infof(ctx, "[certificates] Generating Kubernetes API server csr")
|
log.Infof(ctx, "[certificates] Generating Kubernetes API server csr")
|
||||||
@ -372,7 +372,7 @@ func GenerateEtcdCertificates(ctx context.Context, certs map[string]CertificateP
|
|||||||
sort.Strings(ips)
|
sort.Strings(ips)
|
||||||
|
|
||||||
for _, host := range etcdHosts {
|
for _, host := range etcdHosts {
|
||||||
etcdName := GetEtcdCrtName(host.InternalAddress)
|
etcdName := GetCrtNameForHost(host, EtcdCertName)
|
||||||
if _, ok := certs[etcdName]; ok && certs[etcdName].CertificatePEM != "" && !rotate {
|
if _, ok := certs[etcdName]; ok && certs[etcdName].CertificatePEM != "" && !rotate {
|
||||||
cert := certs[etcdName].Certificate
|
cert := certs[etcdName].Certificate
|
||||||
if cert != nil && len(dnsNames) == len(cert.DNSNames) && len(ips) == len(cert.IPAddresses) {
|
if cert != nil && len(dnsNames) == len(cert.DNSNames) && len(ips) == len(cert.IPAddresses) {
|
||||||
@ -396,7 +396,7 @@ func GenerateEtcdCertificates(ctx context.Context, certs map[string]CertificateP
|
|||||||
if !rotate {
|
if !rotate {
|
||||||
serviceKey = certs[etcdName].Key
|
serviceKey = certs[etcdName].Key
|
||||||
}
|
}
|
||||||
log.Infof(ctx, "[certificates] Generating etcd-%s certificate and key", host.InternalAddress)
|
log.Infof(ctx, "[certificates] Generating %s certificate and key", etcdName)
|
||||||
etcdCrt, etcdKey, err := GenerateSignedCertAndKey(caCrt, caKey, true, EtcdCertName, etcdAltNames, serviceKey, nil)
|
etcdCrt, etcdKey, err := GenerateSignedCertAndKey(caCrt, caKey, true, EtcdCertName, etcdAltNames, serviceKey, nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -415,7 +415,7 @@ func GenerateEtcdCSRs(ctx context.Context, certs map[string]CertificatePKI, rkeC
|
|||||||
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
||||||
etcdAltNames := GetAltNames(etcdHosts, clusterDomain, kubernetesServiceIP, []string{})
|
etcdAltNames := GetAltNames(etcdHosts, clusterDomain, kubernetesServiceIP, []string{})
|
||||||
for _, host := range etcdHosts {
|
for _, host := range etcdHosts {
|
||||||
etcdName := GetEtcdCrtName(host.InternalAddress)
|
etcdName := GetCrtNameForHost(host, EtcdCertName)
|
||||||
etcdCrt := certs[etcdName].Certificate
|
etcdCrt := certs[etcdName].Certificate
|
||||||
etcdCSRPEM := certs[etcdName].CSRPEM
|
etcdCSRPEM := certs[etcdName].CSRPEM
|
||||||
if etcdCSRPEM != "" {
|
if etcdCSRPEM != "" {
|
||||||
@ -484,6 +484,63 @@ func GenerateRKERequestHeaderCACert(ctx context.Context, certs map[string]Certif
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GenerateKubeletCertificate(ctx context.Context, certs map[string]CertificatePKI, rkeConfig v3.RancherKubernetesEngineConfig, configPath, configDir string, rotate bool) error {
|
||||||
|
// generate kubelet certificate and key
|
||||||
|
caCrt := certs[CACertName].Certificate
|
||||||
|
caKey := certs[CACertName].Key
|
||||||
|
if caCrt == nil || caKey == nil {
|
||||||
|
return fmt.Errorf("CA Certificate or Key is empty")
|
||||||
|
}
|
||||||
|
log.Infof(ctx, "[certificates] Generating Kubernetes Kubelet certificates")
|
||||||
|
allHosts := hosts.NodesToHosts(rkeConfig.Nodes, "")
|
||||||
|
for _, host := range allHosts {
|
||||||
|
kubeletName := GetCrtNameForHost(host, KubeletCertName)
|
||||||
|
kubeletCert := certs[kubeletName].Certificate
|
||||||
|
if kubeletCert != nil && !rotate {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
kubeletAltNames := GetIPHostAltnamesForHost(host)
|
||||||
|
if kubeletCert != nil &&
|
||||||
|
reflect.DeepEqual(kubeletAltNames.DNSNames, kubeletCert.DNSNames) &&
|
||||||
|
DeepEqualIPsAltNames(kubeletAltNames.IPs, kubeletCert.IPAddresses) && !rotate {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
var serviceKey *rsa.PrivateKey
|
||||||
|
if !rotate {
|
||||||
|
serviceKey = certs[kubeletName].Key
|
||||||
|
}
|
||||||
|
log.Infof(ctx, "[certificates] Generating %s certificate and key", kubeletName)
|
||||||
|
kubeletCrt, kubeletKey, err := GenerateSignedCertAndKey(caCrt, caKey, true, kubeletName, kubeletAltNames, serviceKey, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
certs[kubeletName] = ToCertObject(kubeletName, "", "", kubeletCrt, kubeletKey, nil)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GenerateKubeletCSR(ctx context.Context, certs map[string]CertificatePKI, rkeConfig v3.RancherKubernetesEngineConfig) error {
|
||||||
|
allHosts := hosts.NodesToHosts(rkeConfig.Nodes, "")
|
||||||
|
for _, host := range allHosts {
|
||||||
|
kubeletName := GetCrtNameForHost(host, KubeletCertName)
|
||||||
|
kubeletCert := certs[kubeletName].Certificate
|
||||||
|
oldKubeletCSR := certs[kubeletName].CSR
|
||||||
|
kubeletAltNames := GetIPHostAltnamesForHost(host)
|
||||||
|
if oldKubeletCSR != nil &&
|
||||||
|
reflect.DeepEqual(kubeletAltNames.DNSNames, oldKubeletCSR.DNSNames) &&
|
||||||
|
DeepEqualIPsAltNames(kubeletAltNames.IPs, oldKubeletCSR.IPAddresses) {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
log.Infof(ctx, "[certificates] Generating %s Kubernetes Kubelet csr", kubeletName)
|
||||||
|
kubeletCSR, kubeletKey, err := GenerateCertSigningRequestAndKey(true, kubeletName, kubeletAltNames, certs[kubeletName].Key, nil)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
certs[kubeletName] = ToCertObject(kubeletName, "", "", kubeletCert, kubeletKey, kubeletCSR)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func GenerateRKEServicesCerts(ctx context.Context, certs map[string]CertificatePKI, rkeConfig v3.RancherKubernetesEngineConfig, configPath, configDir string, rotate bool) error {
|
func GenerateRKEServicesCerts(ctx context.Context, certs map[string]CertificatePKI, rkeConfig v3.RancherKubernetesEngineConfig, configPath, configDir string, rotate bool) error {
|
||||||
RKECerts := []GenFunc{
|
RKECerts := []GenFunc{
|
||||||
GenerateKubeAPICertificate,
|
GenerateKubeAPICertificate,
|
||||||
@ -496,6 +553,9 @@ func GenerateRKEServicesCerts(ctx context.Context, certs map[string]CertificateP
|
|||||||
GenerateAPIProxyClientCertificate,
|
GenerateAPIProxyClientCertificate,
|
||||||
GenerateEtcdCertificates,
|
GenerateEtcdCertificates,
|
||||||
}
|
}
|
||||||
|
if IsKubeletGenerateServingCertificateEnabledinConfig(&rkeConfig) {
|
||||||
|
RKECerts = append(RKECerts, GenerateKubeletCertificate)
|
||||||
|
}
|
||||||
for _, gen := range RKECerts {
|
for _, gen := range RKECerts {
|
||||||
if err := gen(ctx, certs, rkeConfig, configPath, configDir, rotate); err != nil {
|
if err := gen(ctx, certs, rkeConfig, configPath, configDir, rotate); err != nil {
|
||||||
return err
|
return err
|
||||||
@ -518,6 +578,9 @@ func GenerateRKEServicesCSRs(ctx context.Context, certs map[string]CertificatePK
|
|||||||
GenerateAPIProxyClientCSR,
|
GenerateAPIProxyClientCSR,
|
||||||
GenerateEtcdCSRs,
|
GenerateEtcdCSRs,
|
||||||
}
|
}
|
||||||
|
if IsKubeletGenerateServingCertificateEnabledinConfig(&rkeConfig) {
|
||||||
|
RKECerts = append(RKECerts, GenerateKubeletCSR)
|
||||||
|
}
|
||||||
for _, csr := range RKECerts {
|
for _, csr := range RKECerts {
|
||||||
if err := csr(ctx, certs, rkeConfig); err != nil {
|
if err := csr(ctx, certs, rkeConfig); err != nil {
|
||||||
return err
|
return err
|
||||||
|
107
pki/util.go
107
pki/util.go
@ -135,6 +135,34 @@ func GenerateCACertAndKey(commonName string, privateKey *rsa.PrivateKey) (*x509.
|
|||||||
return kubeCACert, rootKey, nil
|
return kubeCACert, rootKey, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetIPHostAltnamesForHost(host *hosts.Host) *cert.AltNames {
|
||||||
|
var ips []net.IP
|
||||||
|
dnsNames := []string{}
|
||||||
|
// Check if node address is a valid IP
|
||||||
|
if nodeIP := net.ParseIP(host.Address); nodeIP != nil {
|
||||||
|
ips = append(ips, nodeIP)
|
||||||
|
} else {
|
||||||
|
dnsNames = append(dnsNames, host.Address)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if node internal address is a valid IP
|
||||||
|
if len(host.InternalAddress) != 0 && host.InternalAddress != host.Address {
|
||||||
|
if internalIP := net.ParseIP(host.InternalAddress); internalIP != nil {
|
||||||
|
ips = append(ips, internalIP)
|
||||||
|
} else {
|
||||||
|
dnsNames = append(dnsNames, host.InternalAddress)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Add hostname to the ALT dns names
|
||||||
|
if len(host.HostnameOverride) != 0 && host.HostnameOverride != host.Address {
|
||||||
|
dnsNames = append(dnsNames, host.HostnameOverride)
|
||||||
|
}
|
||||||
|
return &cert.AltNames{
|
||||||
|
IPs: ips,
|
||||||
|
DNSNames: dnsNames,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func GetAltNames(cpHosts []*hosts.Host, clusterDomain string, KubernetesServiceIP net.IP, SANs []string) *cert.AltNames {
|
func GetAltNames(cpHosts []*hosts.Host, clusterDomain string, KubernetesServiceIP net.IP, SANs []string) *cert.AltNames {
|
||||||
ips := []net.IP{}
|
ips := []net.IP{}
|
||||||
dnsNames := []string{}
|
dnsNames := []string{}
|
||||||
@ -224,9 +252,14 @@ func getConfigEnvFromEnv(env string) string {
|
|||||||
return fmt.Sprintf("KUBECFG_%s", env)
|
return fmt.Sprintf("KUBECFG_%s", env)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetEtcdCrtName(address string) string {
|
func GetCrtNameForHost(host *hosts.Host, prefix string) string {
|
||||||
newAddress := strings.Replace(address, ".", "-", -1)
|
var newAddress string
|
||||||
return fmt.Sprintf("%s-%s", EtcdCertName, newAddress)
|
if len(host.InternalAddress) != 0 && host.InternalAddress != host.Address {
|
||||||
|
newAddress = strings.Replace(host.InternalAddress, ".", "-", -1)
|
||||||
|
} else {
|
||||||
|
newAddress = strings.Replace(host.Address, ".", "-", -1)
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("%s-%s", prefix, newAddress)
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetCertPath(name string) string {
|
func GetCertPath(name string) string {
|
||||||
@ -279,7 +312,7 @@ func ToCertObject(componentName, commonName, ouName string, certificate *x509.Ce
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if componentName != CACertName && componentName != KubeAPICertName && !strings.Contains(componentName, EtcdCertName) && componentName != ServiceAccountTokenKeyName {
|
if componentName != CACertName && componentName != KubeAPICertName && !strings.Contains(componentName, EtcdCertName) && !strings.Contains(componentName, KubeletCertName) && componentName != ServiceAccountTokenKeyName {
|
||||||
config = getKubeConfigX509("https://127.0.0.1:6443", "local", componentName, caCertPath, path, keyPath)
|
config = getKubeConfigX509("https://127.0.0.1:6443", "local", componentName, caCertPath, path, keyPath)
|
||||||
configPath = GetConfigPath(componentName)
|
configPath = GetConfigPath(componentName)
|
||||||
configEnvName = getConfigEnvFromEnv(envName)
|
configEnvName = getConfigEnvFromEnv(envName)
|
||||||
@ -309,42 +342,41 @@ func getDefaultCN(name string) string {
|
|||||||
return fmt.Sprintf("system:%s", name)
|
return fmt.Sprintf("system:%s", name)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getControlCertKeys() []string {
|
func getCertKeys(rkeNodes []v3.RKEConfigNode, nodeRole string, rkeConfig *v3.RancherKubernetesEngineConfig) []string {
|
||||||
return []string{
|
// static certificates each node needs
|
||||||
CACertName,
|
certList := []string{CACertName, KubeProxyCertName, KubeNodeCertName}
|
||||||
|
allHosts := hosts.NodesToHosts(rkeNodes, "")
|
||||||
|
if IsKubeletGenerateServingCertificateEnabledinConfig(rkeConfig) {
|
||||||
|
for _, host := range allHosts {
|
||||||
|
// Add per node kubelet certificates (used for kube-api -> kubelet connection)
|
||||||
|
certList = append(certList, GetCrtNameForHost(host, KubeletCertName))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// etcd
|
||||||
|
if nodeRole == etcdRole {
|
||||||
|
etcdHosts := hosts.NodesToHosts(rkeNodes, nodeRole)
|
||||||
|
for _, host := range etcdHosts {
|
||||||
|
certList = append(certList, GetCrtNameForHost(host, EtcdCertName))
|
||||||
|
}
|
||||||
|
return certList
|
||||||
|
}
|
||||||
|
// control
|
||||||
|
if nodeRole == controlRole {
|
||||||
|
controlCertList := []string{
|
||||||
KubeAPICertName,
|
KubeAPICertName,
|
||||||
ServiceAccountTokenKeyName,
|
ServiceAccountTokenKeyName,
|
||||||
KubeControllerCertName,
|
KubeControllerCertName,
|
||||||
KubeSchedulerCertName,
|
KubeSchedulerCertName,
|
||||||
KubeProxyCertName,
|
|
||||||
KubeNodeCertName,
|
|
||||||
EtcdClientCertName,
|
EtcdClientCertName,
|
||||||
EtcdClientCACertName,
|
EtcdClientCACertName,
|
||||||
RequestHeaderCACertName,
|
RequestHeaderCACertName,
|
||||||
APIProxyClientCertName,
|
APIProxyClientCertName,
|
||||||
}
|
}
|
||||||
}
|
certList = append(certList, controlCertList...)
|
||||||
|
return certList
|
||||||
func getWorkerCertKeys() []string {
|
}
|
||||||
return []string{
|
// worker
|
||||||
CACertName,
|
|
||||||
KubeProxyCertName,
|
|
||||||
KubeNodeCertName,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func getEtcdCertKeys(rkeNodes []v3.RKEConfigNode, etcdRole string) []string {
|
|
||||||
certList := []string{
|
|
||||||
CACertName,
|
|
||||||
KubeProxyCertName,
|
|
||||||
KubeNodeCertName,
|
|
||||||
}
|
|
||||||
etcdHosts := hosts.NodesToHosts(rkeNodes, etcdRole)
|
|
||||||
for _, host := range etcdHosts {
|
|
||||||
certList = append(certList, GetEtcdCrtName(host.InternalAddress))
|
|
||||||
}
|
|
||||||
return certList
|
return certList
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetKubernetesServiceIP(serviceClusterRange string) (net.IP, error) {
|
func GetKubernetesServiceIP(serviceClusterRange string) (net.IP, error) {
|
||||||
@ -393,7 +425,7 @@ func populateCertMap(tmpCerts map[string]CertificatePKI, localConfigPath string,
|
|||||||
certs[KubeAdminCertName] = kubeAdminCertObj
|
certs[KubeAdminCertName] = kubeAdminCertObj
|
||||||
// etcd
|
// etcd
|
||||||
for _, host := range extraHosts {
|
for _, host := range extraHosts {
|
||||||
etcdName := GetEtcdCrtName(host.InternalAddress)
|
etcdName := GetCrtNameForHost(host, EtcdCertName)
|
||||||
etcdCrt, etcdKey := tmpCerts[etcdName].Certificate, tmpCerts[etcdName].Key
|
etcdCrt, etcdKey := tmpCerts[etcdName].Certificate, tmpCerts[etcdName].Key
|
||||||
certs[etcdName] = ToCertObject(etcdName, "", "", etcdCrt, etcdKey, nil)
|
certs[etcdName] = ToCertObject(etcdName, "", "", etcdCrt, etcdKey, nil)
|
||||||
}
|
}
|
||||||
@ -466,7 +498,7 @@ func isFileNotFoundErr(e error) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func deepEqualIPsAltNames(oldIPs, newIPs []net.IP) bool {
|
func DeepEqualIPsAltNames(oldIPs, newIPs []net.IP) bool {
|
||||||
if len(oldIPs) != len(newIPs) {
|
if len(oldIPs) != len(newIPs) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@ -696,7 +728,7 @@ func ValidateBundleContent(rkeConfig *v3.RancherKubernetesEngineConfig, certBund
|
|||||||
}
|
}
|
||||||
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
||||||
for _, host := range etcdHosts {
|
for _, host := range etcdHosts {
|
||||||
etcdName := GetEtcdCrtName(host.InternalAddress)
|
etcdName := GetCrtNameForHost(host, EtcdCertName)
|
||||||
if certBundle[etcdName].Certificate == nil || certBundle[etcdName].Key == nil {
|
if certBundle[etcdName].Certificate == nil || certBundle[etcdName].Key == nil {
|
||||||
return fmt.Errorf("Failed to find etcd [%s] Certificate or Key", etcdName)
|
return fmt.Errorf("Failed to find etcd [%s] Certificate or Key", etcdName)
|
||||||
}
|
}
|
||||||
@ -733,7 +765,7 @@ func validateCAIssuer(rkeConfig *v3.RancherKubernetesEngineConfig, certBundle ma
|
|||||||
}
|
}
|
||||||
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
||||||
for _, host := range etcdHosts {
|
for _, host := range etcdHosts {
|
||||||
etcdName := GetEtcdCrtName(host.InternalAddress)
|
etcdName := GetCrtNameForHost(host, EtcdCertName)
|
||||||
ComponentsCerts = append(ComponentsCerts, etcdName)
|
ComponentsCerts = append(ComponentsCerts, etcdName)
|
||||||
}
|
}
|
||||||
for _, componentCert := range ComponentsCerts {
|
for _, componentCert := range ComponentsCerts {
|
||||||
@ -763,3 +795,10 @@ func IsValidCertStr(c string) (bool, error) {
|
|||||||
}
|
}
|
||||||
return true, nil
|
return true, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func IsKubeletGenerateServingCertificateEnabledinConfig(rkeConfig *v3.RancherKubernetesEngineConfig) bool {
|
||||||
|
if rkeConfig.Services.Kubelet.GenerateServingCertificate {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
@ -428,7 +428,7 @@ func DownloadEtcdSnapshotFromS3(ctx context.Context, etcdHost *hosts.Host, prsMa
|
|||||||
|
|
||||||
func RestoreEtcdSnapshot(ctx context.Context, etcdHost *hosts.Host, prsMap map[string]v3.PrivateRegistry, etcdRestoreImage, snapshotName, initCluster string, es v3.ETCDService) error {
|
func RestoreEtcdSnapshot(ctx context.Context, etcdHost *hosts.Host, prsMap map[string]v3.PrivateRegistry, etcdRestoreImage, snapshotName, initCluster string, es v3.ETCDService) error {
|
||||||
log.Infof(ctx, "[etcd] Restoring [%s] snapshot on etcd host [%s]", snapshotName, etcdHost.Address)
|
log.Infof(ctx, "[etcd] Restoring [%s] snapshot on etcd host [%s]", snapshotName, etcdHost.Address)
|
||||||
nodeName := pki.GetEtcdCrtName(etcdHost.InternalAddress)
|
nodeName := pki.GetCrtNameForHost(etcdHost, pki.EtcdCertName)
|
||||||
snapshotPath := fmt.Sprintf("%s%s", EtcdSnapshotPath, snapshotName)
|
snapshotPath := fmt.Sprintf("%s%s", EtcdSnapshotPath, snapshotName)
|
||||||
|
|
||||||
// make sure that restore path is empty otherwise etcd restore will fail
|
// make sure that restore path is empty otherwise etcd restore will fail
|
||||||
|
Loading…
Reference in New Issue
Block a user