mirror of
https://github.com/rancher/rke.git
synced 2025-08-31 22:46:25 +00:00
External etcd
This commit is contained in:
26
README.md
26
README.md
@@ -222,6 +222,32 @@ ingress:
|
|||||||
|
|
||||||
RKE will deploy Nginx Ingress controller as a DaemonSet with `hostnetwork: true`, so ports `80`, and `443` will be opened on each node where the controller is deployed.
|
RKE will deploy Nginx Ingress controller as a DaemonSet with `hostnetwork: true`, so ports `80`, and `443` will be opened on each node where the controller is deployed.
|
||||||
|
|
||||||
|
## External etcd
|
||||||
|
|
||||||
|
RKE supports using external etcd instead of deploying etcd servers, to enable external etcd the following parameters should be populated:
|
||||||
|
|
||||||
|
```
|
||||||
|
services:
|
||||||
|
etcd:
|
||||||
|
path: /etcdcluster
|
||||||
|
external_urls:
|
||||||
|
- https://etcd-example.com:2379
|
||||||
|
ca_cert: |-
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
xxxxxxxxxx
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
cert: |-
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
xxxxxxxxxx
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
key: |-
|
||||||
|
-----BEGIN PRIVATE KEY-----
|
||||||
|
xxxxxxxxxx
|
||||||
|
-----END PRIVATE KEY-----
|
||||||
|
```
|
||||||
|
|
||||||
|
Note that RKE only supports connecting to TLS enabled etcd setup, user can enable multiple endpoints in the `external_urls` field. RKE will not accept having external urls and nodes with `etcd` role at the same time, user should only specify either etcd role for servers or external etcd but not both.
|
||||||
|
|
||||||
## Operating Systems Notes
|
## Operating Systems Notes
|
||||||
|
|
||||||
### Atomic OS
|
### Atomic OS
|
||||||
|
17
cluster.yml
17
cluster.yml
@@ -68,9 +68,24 @@ nodes:
|
|||||||
|
|
||||||
services:
|
services:
|
||||||
etcd:
|
etcd:
|
||||||
|
# if external etcd is used
|
||||||
|
# path: /etcdcluster
|
||||||
|
# external_urls:
|
||||||
|
# - https://etcd-example.com:2379
|
||||||
|
# ca_cert: |-
|
||||||
|
# -----BEGIN CERTIFICATE-----
|
||||||
|
# xxxxxxxxxx
|
||||||
|
# -----END CERTIFICATE-----
|
||||||
|
# cert: |-
|
||||||
|
# -----BEGIN CERTIFICATE-----
|
||||||
|
# xxxxxxxxxx
|
||||||
|
# -----END CERTIFICATE-----
|
||||||
|
# key: |-
|
||||||
|
# -----BEGIN PRIVATE KEY-----
|
||||||
|
# xxxxxxxxxx
|
||||||
|
# -----END PRIVATE KEY-----
|
||||||
|
|
||||||
kube-api:
|
kube-api:
|
||||||
|
|
||||||
service_cluster_ip_range: 10.233.0.0/18
|
service_cluster_ip_range: 10.233.0.0/18
|
||||||
pod_security_policy: false
|
pod_security_policy: false
|
||||||
extra_args:
|
extra_args:
|
||||||
|
@@ -22,26 +22,26 @@ func SetUpAuthentication(ctx context.Context, kubeCluster, currentCluster *Clust
|
|||||||
if currentCluster != nil {
|
if currentCluster != nil {
|
||||||
kubeCluster.Certificates = currentCluster.Certificates
|
kubeCluster.Certificates = currentCluster.Certificates
|
||||||
} else {
|
} else {
|
||||||
log.Infof(ctx, "[certificates] Attempting to recover certificates from backup on host [%s]", kubeCluster.EtcdHosts[0].Address)
|
log.Infof(ctx, "[certificates] Attempting to recover certificates from backup on host [%s]", kubeCluster.ControlPlaneHosts[0].Address)
|
||||||
kubeCluster.Certificates, err = pki.FetchCertificatesFromHost(ctx, kubeCluster.EtcdHosts, kubeCluster.EtcdHosts[0], kubeCluster.SystemImages.Alpine, kubeCluster.LocalKubeConfigPath, kubeCluster.PrivateRegistriesMap)
|
kubeCluster.Certificates, err = pki.FetchCertificatesFromHost(ctx, kubeCluster.EtcdHosts, kubeCluster.ControlPlaneHosts[0], kubeCluster.SystemImages.Alpine, kubeCluster.LocalKubeConfigPath, kubeCluster.PrivateRegistriesMap)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if kubeCluster.Certificates != nil {
|
if kubeCluster.Certificates != nil {
|
||||||
log.Infof(ctx, "[certificates] Certificate backup found on host [%s]", kubeCluster.EtcdHosts[0].Address)
|
log.Infof(ctx, "[certificates] Certificate backup found on host [%s]", kubeCluster.ControlPlaneHosts[0].Address)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
log.Infof(ctx, "[certificates] No Certificate backup found on host [%s]", kubeCluster.EtcdHosts[0].Address)
|
log.Infof(ctx, "[certificates] No Certificate backup found on host [%s]", kubeCluster.ControlPlaneHosts[0].Address)
|
||||||
|
|
||||||
kubeCluster.Certificates, err = pki.GenerateRKECerts(ctx, kubeCluster.RancherKubernetesEngineConfig, kubeCluster.LocalKubeConfigPath, "")
|
kubeCluster.Certificates, err = pki.GenerateRKECerts(ctx, kubeCluster.RancherKubernetesEngineConfig, kubeCluster.LocalKubeConfigPath, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Failed to generate Kubernetes certificates: %v", err)
|
return fmt.Errorf("Failed to generate Kubernetes certificates: %v", err)
|
||||||
}
|
}
|
||||||
log.Infof(ctx, "[certificates] Temporarily saving certs to etcd host [%s]", kubeCluster.EtcdHosts[0].Address)
|
log.Infof(ctx, "[certificates] Temporarily saving certs to control host [%s]", kubeCluster.ControlPlaneHosts[0].Address)
|
||||||
if err := pki.DeployCertificatesOnHost(ctx, kubeCluster.EtcdHosts[0], kubeCluster.Certificates, kubeCluster.SystemImages.CertDownloader, pki.TempCertPath, kubeCluster.PrivateRegistriesMap); err != nil {
|
if err := pki.DeployCertificatesOnHost(ctx, kubeCluster.ControlPlaneHosts[0], kubeCluster.Certificates, kubeCluster.SystemImages.CertDownloader, pki.TempCertPath, kubeCluster.PrivateRegistriesMap); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
log.Infof(ctx, "[certificates] Saved certs to etcd host [%s]", kubeCluster.EtcdHosts[0].Address)
|
log.Infof(ctx, "[certificates] Saved certs to control host [%s]", kubeCluster.ControlPlaneHosts[0].Address)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
@@ -123,11 +123,14 @@ func saveCertToKubernetes(kubeClient *kubernetes.Clientset, crtName string, crt
|
|||||||
timeout := make(chan bool, 1)
|
timeout := make(chan bool, 1)
|
||||||
|
|
||||||
// build secret Data
|
// build secret Data
|
||||||
secretData := map[string][]byte{
|
secretData := make(map[string][]byte)
|
||||||
"Certificate": cert.EncodeCertPEM(crt.Certificate),
|
if crt.Certificate != nil {
|
||||||
"Key": cert.EncodePrivateKeyPEM(crt.Key),
|
secretData["Certificate"] = cert.EncodeCertPEM(crt.Certificate)
|
||||||
"EnvName": []byte(crt.EnvName),
|
secretData["EnvName"] = []byte(crt.EnvName)
|
||||||
"KeyEnvName": []byte(crt.KeyEnvName),
|
}
|
||||||
|
if crt.Key != nil {
|
||||||
|
secretData["Key"] = cert.EncodePrivateKeyPEM(crt.Key)
|
||||||
|
secretData["KeyEnvName"] = []byte(crt.KeyEnvName)
|
||||||
}
|
}
|
||||||
if len(crt.Config) > 0 {
|
if len(crt.Config) > 0 {
|
||||||
secretData["ConfigEnvName"] = []byte(crt.ConfigEnvName)
|
secretData["ConfigEnvName"] = []byte(crt.ConfigEnvName)
|
||||||
|
@@ -55,10 +55,14 @@ const (
|
|||||||
func (c *Cluster) DeployControlPlane(ctx context.Context) error {
|
func (c *Cluster) DeployControlPlane(ctx context.Context) error {
|
||||||
// Deploy Etcd Plane
|
// Deploy Etcd Plane
|
||||||
etcdProcessHostMap := c.getEtcdProcessHostMap(nil)
|
etcdProcessHostMap := c.getEtcdProcessHostMap(nil)
|
||||||
|
if len(c.Services.Etcd.ExternalURLs) > 0 {
|
||||||
if err := services.RunEtcdPlane(ctx, c.EtcdHosts, etcdProcessHostMap, c.LocalConnDialerFactory, c.PrivateRegistriesMap); err != nil {
|
log.Infof(ctx, "[etcd] External etcd connection string has been specified, skipping etcd plane")
|
||||||
return fmt.Errorf("[etcd] Failed to bring up Etcd Plane: %v", err)
|
} else {
|
||||||
|
if err := services.RunEtcdPlane(ctx, c.EtcdHosts, etcdProcessHostMap, c.LocalConnDialerFactory, c.PrivateRegistriesMap); err != nil {
|
||||||
|
return fmt.Errorf("[etcd] Failed to bring up Etcd Plane: %v", err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Deploy Control plane
|
// Deploy Control plane
|
||||||
processMap := map[string]v3.Process{
|
processMap := map[string]v3.Process{
|
||||||
services.SidekickContainerName: c.BuildSidecarProcess(),
|
services.SidekickContainerName: c.BuildSidecarProcess(),
|
||||||
|
@@ -21,7 +21,7 @@ const (
|
|||||||
|
|
||||||
func (c *Cluster) TunnelHosts(ctx context.Context, local bool) error {
|
func (c *Cluster) TunnelHosts(ctx context.Context, local bool) error {
|
||||||
if local {
|
if local {
|
||||||
if err := c.EtcdHosts[0].TunnelUpLocal(ctx); err != nil {
|
if err := c.ControlPlaneHosts[0].TunnelUpLocal(ctx); err != nil {
|
||||||
return fmt.Errorf("Failed to connect to docker for local host [%s]: %v", c.EtcdHosts[0].Address, err)
|
return fmt.Errorf("Failed to connect to docker for local host [%s]: %v", c.EtcdHosts[0].Address, err)
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
@@ -73,11 +73,15 @@ const (
|
|||||||
APIRoot = "APIRoot"
|
APIRoot = "APIRoot"
|
||||||
// kubernetes client certificates and kubeconfig paths
|
// kubernetes client certificates and kubeconfig paths
|
||||||
|
|
||||||
ClientCert = "ClientCert"
|
EtcdClientCert = "EtcdClientCert"
|
||||||
|
EtcdClientKey = "EtcdClientKey"
|
||||||
|
EtcdClientCA = "EtcdClientCA"
|
||||||
|
EtcdClientCertPath = "EtcdClientCertPath"
|
||||||
|
EtcdClientKeyPath = "EtcdClientKeyPath"
|
||||||
|
EtcdClientCAPath = "EtcdClientCAPath"
|
||||||
|
|
||||||
ClientCertPath = "ClientCertPath"
|
ClientCertPath = "ClientCertPath"
|
||||||
ClientKey = "ClientKey"
|
|
||||||
ClientKeyPath = "ClientKeyPath"
|
ClientKeyPath = "ClientKeyPath"
|
||||||
ClientCA = "ClientCA"
|
|
||||||
ClientCAPath = "ClientCAPath"
|
ClientCAPath = "ClientCAPath"
|
||||||
|
|
||||||
KubeCfg = "KubeCfg"
|
KubeCfg = "KubeCfg"
|
||||||
@@ -144,27 +148,36 @@ func (c *Cluster) doFlannelDeploy(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) doCalicoDeploy(ctx context.Context) error {
|
func (c *Cluster) doCalicoDeploy(ctx context.Context) error {
|
||||||
clientCert := b64.StdEncoding.EncodeToString(cert.EncodeCertPEM(c.Certificates[pki.KubeNodeCertName].Certificate))
|
|
||||||
clientkey := b64.StdEncoding.EncodeToString(cert.EncodePrivateKeyPEM(c.Certificates[pki.KubeNodeCertName].Key))
|
etcdEndpoints := services.GetEtcdConnString(c.EtcdHosts)
|
||||||
|
etcdClientCert := b64.StdEncoding.EncodeToString(cert.EncodeCertPEM(c.Certificates[pki.KubeNodeCertName].Certificate))
|
||||||
|
etcdClientkey := b64.StdEncoding.EncodeToString(cert.EncodePrivateKeyPEM(c.Certificates[pki.KubeNodeCertName].Key))
|
||||||
|
etcdCaCert := b64.StdEncoding.EncodeToString(cert.EncodeCertPEM(c.Certificates[pki.CACertName].Certificate))
|
||||||
clientConfig := pki.GetConfigPath(pki.KubeNodeCertName)
|
clientConfig := pki.GetConfigPath(pki.KubeNodeCertName)
|
||||||
caCert := b64.StdEncoding.EncodeToString(cert.EncodeCertPEM(c.Certificates[pki.CACertName].Certificate))
|
// handling external etcd
|
||||||
|
if len(c.Services.Etcd.ExternalURLs) > 0 {
|
||||||
|
etcdClientCert = b64.StdEncoding.EncodeToString([]byte(c.Services.Etcd.Cert))
|
||||||
|
etcdClientkey = b64.StdEncoding.EncodeToString([]byte(c.Services.Etcd.Key))
|
||||||
|
etcdCaCert = b64.StdEncoding.EncodeToString([]byte(c.Services.Etcd.CACert))
|
||||||
|
etcdEndpoints = strings.Join(c.Services.Etcd.ExternalURLs, ",")
|
||||||
|
}
|
||||||
calicoConfig := map[string]string{
|
calicoConfig := map[string]string{
|
||||||
EtcdEndpoints: services.GetEtcdConnString(c.EtcdHosts),
|
EtcdEndpoints: etcdEndpoints,
|
||||||
APIRoot: "https://127.0.0.1:6443",
|
APIRoot: "https://127.0.0.1:6443",
|
||||||
ClientCert: clientCert,
|
EtcdClientCA: etcdCaCert,
|
||||||
ClientCertPath: pki.GetCertPath(pki.KubeNodeCertName),
|
EtcdClientCert: etcdClientCert,
|
||||||
ClientKey: clientkey,
|
EtcdClientKey: etcdClientkey,
|
||||||
ClientKeyPath: pki.GetKeyPath(pki.KubeNodeCertName),
|
EtcdClientKeyPath: pki.GetKeyPath(pki.EtcdClientCertName),
|
||||||
ClientCA: caCert,
|
EtcdClientCertPath: pki.GetCertPath(pki.EtcdClientCertName),
|
||||||
ClientCAPath: pki.GetCertPath(pki.CACertName),
|
EtcdClientCAPath: pki.GetCertPath(pki.EtcdClientCACertName),
|
||||||
KubeCfg: clientConfig,
|
KubeCfg: clientConfig,
|
||||||
ClusterCIDR: c.ClusterCIDR,
|
ClusterCIDR: c.ClusterCIDR,
|
||||||
CNIImage: c.SystemImages.CalicoCNI,
|
CNIImage: c.SystemImages.CalicoCNI,
|
||||||
NodeImage: c.SystemImages.CalicoNode,
|
NodeImage: c.SystemImages.CalicoNode,
|
||||||
ControllersImage: c.SystemImages.CalicoControllers,
|
ControllersImage: c.SystemImages.CalicoControllers,
|
||||||
Calicoctl: c.SystemImages.CalicoCtl,
|
Calicoctl: c.SystemImages.CalicoCtl,
|
||||||
CloudProvider: c.Network.Options[CalicoCloudProvider],
|
CloudProvider: c.Network.Options[CalicoCloudProvider],
|
||||||
RBACConfig: c.Authorization.Mode,
|
RBACConfig: c.Authorization.Mode,
|
||||||
}
|
}
|
||||||
pluginYaml, err := c.getNetworkPluginManifest(calicoConfig)
|
pluginYaml, err := c.getNetworkPluginManifest(calicoConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@@ -4,6 +4,7 @@ import (
|
|||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
"github.com/rancher/rke/hosts"
|
"github.com/rancher/rke/hosts"
|
||||||
"github.com/rancher/rke/pki"
|
"github.com/rancher/rke/pki"
|
||||||
@@ -11,6 +12,10 @@ import (
|
|||||||
"github.com/rancher/types/apis/management.cattle.io/v3"
|
"github.com/rancher/types/apis/management.cattle.io/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
EtcdPathPrefix = "/registry"
|
||||||
|
)
|
||||||
|
|
||||||
func GeneratePlan(ctx context.Context, rkeConfig *v3.RancherKubernetesEngineConfig) (v3.RKEPlan, error) {
|
func GeneratePlan(ctx context.Context, rkeConfig *v3.RancherKubernetesEngineConfig) (v3.RKEPlan, error) {
|
||||||
clusterPlan := v3.RKEPlan{}
|
clusterPlan := v3.RKEPlan{}
|
||||||
myCluster, _ := ParseCluster(ctx, rkeConfig, "", "", nil, nil)
|
myCluster, _ := ParseCluster(ctx, rkeConfig, "", "", nil, nil)
|
||||||
@@ -55,8 +60,20 @@ func BuildRKEConfigNodePlan(ctx context.Context, myCluster *Cluster, host *hosts
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *Cluster) BuildKubeAPIProcess() v3.Process {
|
func (c *Cluster) BuildKubeAPIProcess() v3.Process {
|
||||||
etcdConnString := services.GetEtcdConnString(c.EtcdHosts)
|
// check if external etcd is used
|
||||||
args := []string{}
|
etcdConnectionString := services.GetEtcdConnString(c.EtcdHosts)
|
||||||
|
etcdPathPrefix := EtcdPathPrefix
|
||||||
|
etcdClientCert := pki.GetCertPath(pki.KubeNodeCertName)
|
||||||
|
etcdClientKey := pki.GetKeyPath(pki.KubeNodeCertName)
|
||||||
|
etcdCAClientCert := pki.GetCertPath(pki.CACertName)
|
||||||
|
if len(c.Services.Etcd.ExternalURLs) > 0 {
|
||||||
|
etcdConnectionString = strings.Join(c.Services.Etcd.ExternalURLs, ",")
|
||||||
|
etcdPathPrefix = c.Services.Etcd.Path
|
||||||
|
etcdClientCert = pki.GetCertPath(pki.EtcdClientCertName)
|
||||||
|
etcdClientKey = pki.GetKeyPath(pki.EtcdClientCertName)
|
||||||
|
etcdCAClientCert = pki.GetCertPath(pki.EtcdClientCACertName)
|
||||||
|
}
|
||||||
|
|
||||||
Command := []string{
|
Command := []string{
|
||||||
"/opt/rke/entrypoint.sh",
|
"/opt/rke/entrypoint.sh",
|
||||||
"kube-apiserver",
|
"kube-apiserver",
|
||||||
@@ -76,11 +93,14 @@ func (c *Cluster) BuildKubeAPIProcess() v3.Process {
|
|||||||
"--tls-cert-file=" + pki.GetCertPath(pki.KubeAPICertName),
|
"--tls-cert-file=" + pki.GetCertPath(pki.KubeAPICertName),
|
||||||
"--tls-private-key-file=" + pki.GetKeyPath(pki.KubeAPICertName),
|
"--tls-private-key-file=" + pki.GetKeyPath(pki.KubeAPICertName),
|
||||||
"--service-account-key-file=" + pki.GetKeyPath(pki.KubeAPICertName),
|
"--service-account-key-file=" + pki.GetKeyPath(pki.KubeAPICertName),
|
||||||
"--etcd-cafile=" + pki.GetCertPath(pki.CACertName),
|
|
||||||
"--etcd-certfile=" + pki.GetCertPath(pki.KubeAPICertName),
|
|
||||||
"--etcd-keyfile=" + pki.GetKeyPath(pki.KubeAPICertName),
|
|
||||||
}
|
}
|
||||||
args = append(args, "--etcd-servers="+etcdConnString)
|
args := []string{
|
||||||
|
"--etcd-cafile=" + etcdCAClientCert,
|
||||||
|
"--etcd-certfile=" + etcdClientCert,
|
||||||
|
"--etcd-keyfile=" + etcdClientKey,
|
||||||
|
"--etcd-servers=" + etcdConnectionString,
|
||||||
|
"--etcd-prefix=" + etcdPathPrefix,
|
||||||
|
}
|
||||||
|
|
||||||
if c.Authorization.Mode == services.RBACAuthorizationMode {
|
if c.Authorization.Mode == services.RBACAuthorizationMode {
|
||||||
args = append(args, "--authorization-mode=RBAC")
|
args = append(args, "--authorization-mode=RBAC")
|
||||||
|
@@ -10,6 +10,10 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func (c *Cluster) ClusterRemove(ctx context.Context) error {
|
func (c *Cluster) ClusterRemove(ctx context.Context) error {
|
||||||
|
externalEtcd := false
|
||||||
|
if len(c.Services.Etcd.ExternalURLs) > 0 {
|
||||||
|
externalEtcd = true
|
||||||
|
}
|
||||||
// Remove Worker Plane
|
// Remove Worker Plane
|
||||||
if err := services.RemoveWorkerPlane(ctx, c.WorkerHosts, true); err != nil {
|
if err := services.RemoveWorkerPlane(ctx, c.WorkerHosts, true); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -26,7 +30,7 @@ func (c *Cluster) ClusterRemove(ctx context.Context) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Clean up all hosts
|
// Clean up all hosts
|
||||||
if err := cleanUpHosts(ctx, c.ControlPlaneHosts, c.WorkerHosts, c.EtcdHosts, c.SystemImages.Alpine, c.PrivateRegistriesMap); err != nil {
|
if err := cleanUpHosts(ctx, c.ControlPlaneHosts, c.WorkerHosts, c.EtcdHosts, c.SystemImages.Alpine, c.PrivateRegistriesMap, externalEtcd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -34,14 +38,14 @@ func (c *Cluster) ClusterRemove(ctx context.Context) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func cleanUpHosts(ctx context.Context, cpHosts, workerHosts, etcdHosts []*hosts.Host, cleanerImage string, prsMap map[string]v3.PrivateRegistry) error {
|
func cleanUpHosts(ctx context.Context, cpHosts, workerHosts, etcdHosts []*hosts.Host, cleanerImage string, prsMap map[string]v3.PrivateRegistry, externalEtcd bool) error {
|
||||||
allHosts := []*hosts.Host{}
|
allHosts := []*hosts.Host{}
|
||||||
allHosts = append(allHosts, cpHosts...)
|
allHosts = append(allHosts, cpHosts...)
|
||||||
allHosts = append(allHosts, workerHosts...)
|
allHosts = append(allHosts, workerHosts...)
|
||||||
allHosts = append(allHosts, etcdHosts...)
|
allHosts = append(allHosts, etcdHosts...)
|
||||||
|
|
||||||
for _, host := range allHosts {
|
for _, host := range allHosts {
|
||||||
if err := host.CleanUpAll(ctx, cleanerImage, prsMap); err != nil {
|
if err := host.CleanUpAll(ctx, cleanerImage, prsMap, externalEtcd); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -12,9 +12,12 @@ func (c *Cluster) ValidateCluster() error {
|
|||||||
if len(c.ControlPlaneHosts) == 0 {
|
if len(c.ControlPlaneHosts) == 0 {
|
||||||
return fmt.Errorf("Cluster must have at least one control plane host")
|
return fmt.Errorf("Cluster must have at least one control plane host")
|
||||||
}
|
}
|
||||||
if len(c.EtcdHosts) == 0 {
|
if len(c.EtcdHosts) == 0 && len(c.Services.Etcd.ExternalURLs) == 0 {
|
||||||
return fmt.Errorf("Cluster must have at least one etcd plane host")
|
return fmt.Errorf("Cluster must have at least one etcd plane host")
|
||||||
}
|
}
|
||||||
|
if len(c.EtcdHosts) > 0 && len(c.Services.Etcd.ExternalURLs) > 0 {
|
||||||
|
return fmt.Errorf("Cluster can't have both internal and external etcd")
|
||||||
|
}
|
||||||
|
|
||||||
// validate hosts options
|
// validate hosts options
|
||||||
if err := validateHostsOptions(c); err != nil {
|
if err := validateHostsOptions(c); err != nil {
|
||||||
@@ -94,6 +97,21 @@ func validateServicesOptions(c *Cluster) error {
|
|||||||
return fmt.Errorf("%s can't be empty", strings.Join(strings.Split(optionName, "_"), " "))
|
return fmt.Errorf("%s can't be empty", strings.Join(strings.Split(optionName, "_"), " "))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// Validate external etcd information
|
||||||
|
if len(c.Services.Etcd.ExternalURLs) > 0 {
|
||||||
|
if len(c.Services.Etcd.CACert) == 0 {
|
||||||
|
return fmt.Errorf("External CA Certificate for etcd can't be empty")
|
||||||
|
}
|
||||||
|
if len(c.Services.Etcd.Cert) == 0 {
|
||||||
|
return fmt.Errorf("External Client Certificate for etcd can't be empty")
|
||||||
|
}
|
||||||
|
if len(c.Services.Etcd.Key) == 0 {
|
||||||
|
return fmt.Errorf("External Client Key for etcd can't be empty")
|
||||||
|
}
|
||||||
|
if len(c.Services.Etcd.Path) == 0 {
|
||||||
|
return fmt.Errorf("External etcd path can't be empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -41,16 +41,18 @@ const (
|
|||||||
CleanerContainerName = "kube-cleaner"
|
CleanerContainerName = "kube-cleaner"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h *Host) CleanUpAll(ctx context.Context, cleanerImage string, prsMap map[string]v3.PrivateRegistry) error {
|
func (h *Host) CleanUpAll(ctx context.Context, cleanerImage string, prsMap map[string]v3.PrivateRegistry, externalEtcd bool) error {
|
||||||
log.Infof(ctx, "[hosts] Cleaning up host [%s]", h.Address)
|
log.Infof(ctx, "[hosts] Cleaning up host [%s]", h.Address)
|
||||||
toCleanPaths := []string{
|
toCleanPaths := []string{
|
||||||
ToCleanEtcdDir,
|
|
||||||
ToCleanSSLDir,
|
ToCleanSSLDir,
|
||||||
ToCleanCNIConf,
|
ToCleanCNIConf,
|
||||||
ToCleanCNIBin,
|
ToCleanCNIBin,
|
||||||
ToCleanCalicoRun,
|
ToCleanCalicoRun,
|
||||||
ToCleanTempCertPath,
|
ToCleanTempCertPath,
|
||||||
}
|
}
|
||||||
|
if externalEtcd {
|
||||||
|
toCleanPaths = append(toCleanPaths, ToCleanEtcdDir)
|
||||||
|
}
|
||||||
return h.CleanUp(ctx, toCleanPaths, cleanerImage, prsMap)
|
return h.CleanUp(ctx, toCleanPaths, cleanerImage, prsMap)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -16,6 +16,8 @@ const (
|
|||||||
KubeProxyCertName = "kube-proxy"
|
KubeProxyCertName = "kube-proxy"
|
||||||
KubeNodeCertName = "kube-node"
|
KubeNodeCertName = "kube-node"
|
||||||
EtcdCertName = "kube-etcd"
|
EtcdCertName = "kube-etcd"
|
||||||
|
EtcdClientCACertName = "kube-etcd-client-ca"
|
||||||
|
EtcdClientCertName = "kube-etcd-client"
|
||||||
|
|
||||||
KubeNodeCommonName = "system:node"
|
KubeNodeCommonName = "system:node"
|
||||||
KubeNodeOrganizationName = "system:nodes"
|
KubeNodeOrganizationName = "system:nodes"
|
||||||
|
18
pki/pki.go
18
pki/pki.go
@@ -111,9 +111,27 @@ func GenerateRKECerts(ctx context.Context, rkeConfig v3.RancherKubernetesEngineC
|
|||||||
kubeAdminCertObj := ToCertObject(KubeAdminCertName, KubeAdminCertName, KubeAdminOrganizationName, kubeAdminCrt, kubeAdminKey)
|
kubeAdminCertObj := ToCertObject(KubeAdminCertName, KubeAdminCertName, KubeAdminOrganizationName, kubeAdminCrt, kubeAdminKey)
|
||||||
kubeAdminCertObj.Config = kubeAdminConfig
|
kubeAdminCertObj.Config = kubeAdminConfig
|
||||||
kubeAdminCertObj.ConfigPath = localKubeConfigPath
|
kubeAdminCertObj.ConfigPath = localKubeConfigPath
|
||||||
|
kubeAdminCertObj.ConfigEnvName = ""
|
||||||
certs[KubeAdminCertName] = kubeAdminCertObj
|
certs[KubeAdminCertName] = kubeAdminCertObj
|
||||||
|
|
||||||
// generate etcd certificate and key
|
// generate etcd certificate and key
|
||||||
|
if len(rkeConfig.Services.Etcd.ExternalURLs) > 0 {
|
||||||
|
clientCert, err := cert.ParseCertsPEM([]byte(rkeConfig.Services.Etcd.Cert))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
clientKey, err := cert.ParsePrivateKeyPEM([]byte(rkeConfig.Services.Etcd.Key))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
certs[EtcdClientCertName] = ToCertObject(EtcdClientCertName, "", "", clientCert[0], clientKey.(*rsa.PrivateKey))
|
||||||
|
|
||||||
|
caCert, err := cert.ParseCertsPEM([]byte(rkeConfig.Services.Etcd.CACert))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
certs[EtcdClientCACertName] = ToCertObject(EtcdClientCACertName, "", "", caCert[0], nil)
|
||||||
|
}
|
||||||
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
etcdHosts := hosts.NodesToHosts(rkeConfig.Nodes, etcdRole)
|
||||||
etcdAltNames := GetAltNames(etcdHosts, clusterDomain, kubernetesServiceIP)
|
etcdAltNames := GetAltNames(etcdHosts, clusterDomain, kubernetesServiceIP)
|
||||||
for _, host := range etcdHosts {
|
for _, host := range etcdHosts {
|
||||||
|
24
pki/util.go
24
pki/util.go
@@ -107,11 +107,14 @@ func GetAltNames(cpHosts []*hosts.Host, clusterDomain string, KubernetesServiceI
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (c *CertificatePKI) ToEnv() []string {
|
func (c *CertificatePKI) ToEnv() []string {
|
||||||
env := []string{
|
env := []string{}
|
||||||
c.CertToEnv(),
|
if c.Key != nil {
|
||||||
c.KeyToEnv(),
|
env = append(env, c.KeyToEnv())
|
||||||
}
|
}
|
||||||
if c.Config != "" {
|
if c.Certificate != nil {
|
||||||
|
env = append(env, c.CertToEnv())
|
||||||
|
}
|
||||||
|
if c.Config != "" && c.ConfigEnvName != "" {
|
||||||
env = append(env, c.ConfigToEnv())
|
env = append(env, c.ConfigToEnv())
|
||||||
}
|
}
|
||||||
return env
|
return env
|
||||||
@@ -218,6 +221,8 @@ func getControlCertKeys() []string {
|
|||||||
KubeSchedulerCertName,
|
KubeSchedulerCertName,
|
||||||
KubeProxyCertName,
|
KubeProxyCertName,
|
||||||
KubeNodeCertName,
|
KubeNodeCertName,
|
||||||
|
EtcdClientCertName,
|
||||||
|
EtcdClientCACertName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -226,6 +231,8 @@ func getWorkerCertKeys() []string {
|
|||||||
CACertName,
|
CACertName,
|
||||||
KubeProxyCertName,
|
KubeProxyCertName,
|
||||||
KubeNodeCertName,
|
KubeNodeCertName,
|
||||||
|
EtcdClientCertName,
|
||||||
|
EtcdClientCACertName,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -267,3 +274,12 @@ func GetLocalKubeConfig(configPath, configDir string) string {
|
|||||||
baseDir += "/"
|
baseDir += "/"
|
||||||
return fmt.Sprintf("%s%s%s", baseDir, KubeAdminConfigPrefix, fileName)
|
return fmt.Sprintf("%s%s%s", baseDir, KubeAdminConfigPrefix, fileName)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func strCrtToEnv(crtName, crt string) string {
|
||||||
|
return fmt.Sprintf("%s=%s", getEnvFromName(crtName), crt)
|
||||||
|
}
|
||||||
|
|
||||||
|
func strKeyToEnv(crtName, key string) string {
|
||||||
|
envName := getEnvFromName(crtName)
|
||||||
|
return fmt.Sprintf("%s=%s", getKeyEnvFromEnv(envName), key)
|
||||||
|
}
|
||||||
|
@@ -9,6 +9,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func runKubeAPI(ctx context.Context, host *hosts.Host, df hosts.DialerFactory, prsMap map[string]v3.PrivateRegistry, kubeAPIProcess v3.Process) error {
|
func runKubeAPI(ctx context.Context, host *hosts.Host, df hosts.DialerFactory, prsMap map[string]v3.PrivateRegistry, kubeAPIProcess v3.Process) error {
|
||||||
|
|
||||||
imageCfg, hostCfg, healthCheckURL := getProcessConfig(kubeAPIProcess)
|
imageCfg, hostCfg, healthCheckURL := getProcessConfig(kubeAPIProcess)
|
||||||
if err := docker.DoRunContainer(ctx, host.DClient, imageCfg, hostCfg, KubeAPIContainerName, host.Address, ControlRole, prsMap); err != nil {
|
if err := docker.DoRunContainer(ctx, host.DClient, imageCfg, hostCfg, KubeAPIContainerName, host.Address, ControlRole, prsMap); err != nil {
|
||||||
return err
|
return err
|
||||||
|
@@ -104,9 +104,9 @@ data:
|
|||||||
{
|
{
|
||||||
"type": "calico",
|
"type": "calico",
|
||||||
"etcd_endpoints": "{{.EtcdEndpoints}}",
|
"etcd_endpoints": "{{.EtcdEndpoints}}",
|
||||||
"etcd_key_file": "{{.ClientKeyPath}}",
|
"etcd_key_file": "{{.EtcdClientKeyPath}}",
|
||||||
"etcd_cert_file": "{{.ClientCertPath}}",
|
"etcd_cert_file": "{{.EtcdClientCertPath}}",
|
||||||
"etcd_ca_cert_file": "{{.ClientCAPath}}",
|
"etcd_ca_cert_file": "{{.EtcdClientCAPath}}",
|
||||||
"log_level": "info",
|
"log_level": "info",
|
||||||
"mtu": 1500,
|
"mtu": 1500,
|
||||||
"ipam": {
|
"ipam": {
|
||||||
@@ -114,10 +114,8 @@ data:
|
|||||||
},
|
},
|
||||||
"policy": {
|
"policy": {
|
||||||
"type": "k8s",
|
"type": "k8s",
|
||||||
"k8s_api_root": "{{.APIRoot}}",
|
"k8s_api_root": "https://__KUBERNETES_SERVICE_HOST__:__KUBERNETES_SERVICE_PORT__",
|
||||||
"k8s_client_certificate": "{{.ClientCertPath}}",
|
"k8s_auth_token": "__SERVICEACCOUNT_TOKEN__"
|
||||||
"k8s_client_key": "{{.ClientKeyPath}}",
|
|
||||||
"k8s_certificate_authority": "{{.ClientCAPath}}"
|
|
||||||
},
|
},
|
||||||
"kubernetes": {
|
"kubernetes": {
|
||||||
"kubeconfig": "{{.KubeCfg}}"
|
"kubeconfig": "{{.KubeCfg}}"
|
||||||
@@ -144,9 +142,9 @@ metadata:
|
|||||||
name: calico-etcd-secrets
|
name: calico-etcd-secrets
|
||||||
namespace: kube-system
|
namespace: kube-system
|
||||||
data:
|
data:
|
||||||
etcd-key: {{.ClientKey}}
|
etcd-key: {{.EtcdClientKey}}
|
||||||
etcd-cert: {{.ClientCert}}
|
etcd-cert: {{.EtcdClientCert}}
|
||||||
etcd-ca: {{.ClientCA}}
|
etcd-ca: {{.EtcdClientCA}}
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user