refactor: adaption for kine

This commit is contained in:
mendrugory
2022-06-23 12:14:23 +02:00
committed by Dario Tranchitella
parent 3be6cf1c4f
commit 8f59de6e13
17 changed files with 192 additions and 95 deletions

View File

@@ -14,6 +14,7 @@ import (
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
"github.com/clastix/kamaji/internal/resources" "github.com/clastix/kamaji/internal/resources"
"github.com/clastix/kamaji/internal/resources/konnectivity" "github.com/clastix/kamaji/internal/resources/konnectivity"
"github.com/clastix/kamaji/internal/types"
) )
const ( const (
@@ -179,27 +180,32 @@ func getKubeconfigResources(c client.Client, log logr.Logger, tcpReconcilerConfi
} }
func getKubernetesStorageResources(c client.Client, log logr.Logger, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource { func getKubernetesStorageResources(c client.Client, log logr.Logger, tcpReconcilerConfig TenantControlPlaneReconcilerConfig, tenantControlPlane kamajiv1alpha1.TenantControlPlane) []resources.Resource {
return []resources.Resource{ switch tcpReconcilerConfig.ETCDStorageType {
&resources.ETCDCACertificatesResource{ case types.ETCD:
Name: "etcd-ca-certificates", return []resources.Resource{
Client: c, &resources.ETCDCACertificatesResource{
Log: log, Name: "etcd-ca-certificates",
ETCDCASecretName: tcpReconcilerConfig.ETCDCASecretName, Client: c,
ETCDCASecretNamespace: tcpReconcilerConfig.ETCDCASecretNamespace, Log: log,
}, ETCDCASecretName: tcpReconcilerConfig.ETCDCASecretName,
&resources.ETCDCertificatesResource{ ETCDCASecretNamespace: tcpReconcilerConfig.ETCDCASecretNamespace,
Name: "etcd-certificates", },
Client: c, &resources.ETCDCertificatesResource{
Log: log, Name: "etcd-certificates",
}, Client: c,
&resources.ETCDSetupResource{ Log: log,
Name: "etcd-setup", },
Client: c, &resources.ETCDSetupResource{
Log: log, Name: "etcd-setup",
ETCDClientCertsSecret: getNamespacedName(tcpReconcilerConfig.ETCDClientSecretNamespace, tcpReconcilerConfig.ETCDClientSecretName), Client: c,
ETCDCACertsSecret: getNamespacedName(tcpReconcilerConfig.ETCDCASecretNamespace, tcpReconcilerConfig.ETCDCASecretName), Log: log,
Endpoints: getArrayFromString(tcpReconcilerConfig.ETCDEndpoints), ETCDClientCertsSecret: getNamespacedName(tcpReconcilerConfig.ETCDClientSecretNamespace, tcpReconcilerConfig.ETCDClientSecretName),
}, ETCDCACertsSecret: getNamespacedName(tcpReconcilerConfig.ETCDCASecretNamespace, tcpReconcilerConfig.ETCDCASecretName),
Endpoints: getArrayFromString(tcpReconcilerConfig.ETCDEndpoints),
},
}
default:
return []resources.Resource{}
} }
} }

View File

@@ -21,6 +21,7 @@ import (
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
kamajierrors "github.com/clastix/kamaji/internal/errors" kamajierrors "github.com/clastix/kamaji/internal/errors"
"github.com/clastix/kamaji/internal/resources" "github.com/clastix/kamaji/internal/resources"
"github.com/clastix/kamaji/internal/types"
) )
const ( const (
@@ -36,6 +37,7 @@ type TenantControlPlaneReconciler struct {
// TenantControlPlaneReconcilerConfig gives the necessary configuration for TenantControlPlaneReconciler. // TenantControlPlaneReconcilerConfig gives the necessary configuration for TenantControlPlaneReconciler.
type TenantControlPlaneReconcilerConfig struct { type TenantControlPlaneReconcilerConfig struct {
ETCDStorageType types.ETCDStorageType
ETCDCASecretName string ETCDCASecretName string
ETCDCASecretNamespace string ETCDCASecretNamespace string
ETCDClientSecretName string ETCDClientSecretName string
@@ -83,14 +85,13 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
registeredDeleteableResources := GetDeleteableResources(groupDeleteableResourceBuilderConfiguration) registeredDeleteableResources := GetDeleteableResources(groupDeleteableResourceBuilderConfiguration)
for _, resource := range registeredDeleteableResources { for _, resource := range registeredDeleteableResources {
if err := resource.Delete(ctx, tenantControlPlane); err != nil { if err := resources.HandleDeletion(ctx, resource, tenantControlPlane); err != nil {
return ctrl.Result{}, err return ctrl.Result{}, err
} }
} }
if hasFinalizer { if hasFinalizer {
controllerutil.RemoveFinalizer(tenantControlPlane, finalizer) if err := r.RemoveFinalizer(ctx, tenantControlPlane); err != nil {
if err := r.Update(ctx, tenantControlPlane); err != nil {
return ctrl.Result{}, err return ctrl.Result{}, err
} }
} }
@@ -99,12 +100,7 @@ func (r *TenantControlPlaneReconciler) Reconcile(ctx context.Context, req ctrl.R
} }
if !hasFinalizer { if !hasFinalizer {
controllerutil.AddFinalizer(tenantControlPlane, finalizer) return ctrl.Result{}, r.AddFinalizer(ctx, tenantControlPlane)
if err := r.Update(ctx, tenantControlPlane); err != nil {
return ctrl.Result{}, err
}
return ctrl.Result{}, nil
} }
groupResourceBuilderConfiguration := GroupResourceBuilderConfiguration{ groupResourceBuilderConfiguration := GroupResourceBuilderConfiguration{
@@ -200,3 +196,15 @@ func hasFinalizer(tenantControlPlane kamajiv1alpha1.TenantControlPlane) bool {
return false return false
} }
func (r *TenantControlPlaneReconciler) AddFinalizer(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
controllerutil.AddFinalizer(tenantControlPlane, finalizer)
return r.Update(ctx, tenantControlPlane)
}
func (r *TenantControlPlaneReconciler) RemoveFinalizer(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
controllerutil.RemoveFinalizer(tenantControlPlane, finalizer)
return r.Update(ctx, tenantControlPlane)
}

View File

@@ -21,7 +21,7 @@ Available flags are the following:
--etcd-client-secret-name Name of the secret which contains ETCD client certificates. (default: "root-client-certs") --etcd-client-secret-name Name of the secret which contains ETCD client certificates. (default: "root-client-certs")
--etcd-client-secret-namespace Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji") --etcd-client-secret-namespace Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji")
--etcd-compaction-interval ETCD Compaction interval (i.e. "5m0s"). (default: "0" (disabled)) --etcd-compaction-interval ETCD Compaction interval (i.e. "5m0s"). (default: "0" (disabled))
--etcd-endpoints Comma-separated list with ETCD endpoints (i.e. etcd-0.etcd.kamaji.svc.cluster.local,etcd-1.etcd.kamaji.svc.cluster.local,etcd-2.etcd.kamaji.svc.cluster.local) --etcd-endpoints Comma-separated list with ETCD endpoints (i.e. https://etcd-0.etcd.kamaji.svc.cluster.local,https://etcd-1.etcd.kamaji.svc.cluster.local,https://etcd-2.etcd.kamaji.svc.cluster.local)
--health-probe-bind-address string The address the probe endpoint binds to. (default ":8081") --health-probe-bind-address string The address the probe endpoint binds to. (default ":8081")
--kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster. --kubeconfig string Paths to a kubeconfig. Only required if out-of-cluster.
--leader-elect Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager. --leader-elect Enable leader election for controller manager. Enabling this will ensure there is only one active controller manager.

View File

@@ -23,9 +23,11 @@ import (
// These tests use Ginkgo (BDD-style Go testing framework). Refer to // These tests use Ginkgo (BDD-style Go testing framework). Refer to
// http://onsi.github.io/ginkgo/ to learn more about Ginkgo. // http://onsi.github.io/ginkgo/ to learn more about Ginkgo.
var cfg *rest.Config // nolint var (
var k8sClient client.Client cfg *rest.Config // nolint
var testEnv *envtest.Environment k8sClient client.Client
testEnv *envtest.Environment
)
func TestAPIs(t *testing.T) { func TestAPIs(t *testing.T) {
RegisterFailHandler(Fail) RegisterFailHandler(Fail)

View File

@@ -76,7 +76,7 @@ var _ = Describe("Deploy a TenantControlPlane resource", func() {
} }
// Check if Status field has been created on TenantControlPlane struct // Check if Status field has been created on TenantControlPlane struct
if *&tcp.Status.Kubernetes.Version.Status == nil { if tcp.Status.Kubernetes.Version.Status == nil {
return "" return ""
} }

View File

@@ -109,6 +109,10 @@ var _ = Describe("starting a kind worker with kubeadm", func() {
return "" return ""
} }
if tcp.Status.Kubernetes.Version.Status == nil {
return ""
}
return *tcp.Status.Kubernetes.Version.Status return *tcp.Status.Kubernetes.Version.Status
}, 5*time.Minute, time.Second).Should(Equal(kamajiv1alpha1.VersionReady)) }, 5*time.Minute, time.Second).Should(Equal(kamajiv1alpha1.VersionReady))
}) })

View File

@@ -64,7 +64,7 @@ Kubernetes: `>=1.18`
| etcd.clientSecret.name | string | `"root-client-certs"` | Name of the secret which contains ETCD client certificates. (default: "root-client-certs") | | etcd.clientSecret.name | string | `"root-client-certs"` | Name of the secret which contains ETCD client certificates. (default: "root-client-certs") |
| etcd.clientSecret.namespace | string | `"kamaji-system"` | Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji") | | etcd.clientSecret.namespace | string | `"kamaji-system"` | Name of the namespace where the secret which contains ETCD client certificates is. (default: "kamaji") |
| etcd.compactionInterval | int | `0` | ETCD Compaction interval (e.g. "5m0s"). (default: "0" (disabled)) | | etcd.compactionInterval | int | `0` | ETCD Compaction interval (e.g. "5m0s"). (default: "0" (disabled)) |
| etcd.endpoints | string | `"etcd-0.etcd.kamaji-system.svc.cluster.local:2379,etcd-1.etcd.kamaji-system.svc.cluster.local:2379,etcd-2.etcd.kamaji-system.svc.cluster.local:2379"` | (string) Comma-separated list of the endpoints of the etcd cluster's members. | | etcd.endpoints | string | `"https://etcd-0.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-1.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-2.etcd.kamaji-system.svc.cluster.local:2379"` | (string) Comma-separated list of the endpoints of the etcd cluster's members. |
| extraArgs | list | `[]` | A list of extra arguments to add to the kamaji controller default ones | | extraArgs | list | `[]` | A list of extra arguments to add to the kamaji controller default ones |
| fullnameOverride | string | `""` | | | fullnameOverride | string | `""` | |
| healthProbeBindAddress | string | `":8081"` | The address the probe endpoint binds to. (default ":8081") | | healthProbeBindAddress | string | `":8081"` | The address the probe endpoint binds to. (default ":8081") |

View File

@@ -1,2 +1,2 @@
etcd: etcd:
endpoints: "etcd-0.etcd.kamaji-system.svc.cluster.local:2379,etcd-1.etcd.kamaji-system.svc.cluster.local:2379,etcd-2.etcd.kamaji-system.svc.cluster.local:2379" endpoints: "https://etcd-0.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-1.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-2.etcd.kamaji-system.svc.cluster.local:2379"

View File

@@ -35,7 +35,7 @@ etcd:
compactionInterval: 0 compactionInterval: 0
# -- (string) Comma-separated list of the endpoints of the etcd cluster's members. # -- (string) Comma-separated list of the endpoints of the etcd cluster's members.
endpoints: "etcd-0.etcd.kamaji-system.svc.cluster.local:2379,etcd-1.etcd.kamaji-system.svc.cluster.local:2379,etcd-2.etcd.kamaji-system.svc.cluster.local:2379" endpoints: "https://etcd-0.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-1.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-2.etcd.kamaji-system.svc.cluster.local:2379"
# -- The address the probe endpoint binds to. (default ":8081") # -- The address the probe endpoint binds to. (default ":8081")
healthProbeBindAddress: ":8081" healthProbeBindAddress: ":8081"

View File

@@ -22,6 +22,7 @@ var (
const ( const (
envPrefix = "KAMAJI" envPrefix = "KAMAJI"
defaultETCDStorageType = "etcd"
defaultETCDCASecretName = "etcd-certs" defaultETCDCASecretName = "etcd-certs"
defaultETCDCASecretNamespace = "kamaji-system" defaultETCDCASecretNamespace = "kamaji-system"
defaultETCDEndpoints = "etcd-server:2379" defaultETCDEndpoints = "etcd-server:2379"
@@ -40,11 +41,12 @@ func InitConfig() (*viper.Viper, error) {
flag.String("health-probe-bind-address", ":8081", "The address the probe endpoint binds to.") flag.String("health-probe-bind-address", ":8081", "The address the probe endpoint binds to.")
flag.Bool("leader-elect", false, "Enable leader election for controller manager. "+ flag.Bool("leader-elect", false, "Enable leader election for controller manager. "+
"Enabling this will ensure there is only one active controller manager.") "Enabling this will ensure there is only one active controller manager.")
flag.String("etcd-storage-type", defaultETCDStorageType, "Type of storage for ETCD (i.e etcd, kine-mysql, kine-postgres)")
flag.String("etcd-ca-secret-name", defaultETCDCASecretName, "Name of the secret which contains CA's certificate and private key.") flag.String("etcd-ca-secret-name", defaultETCDCASecretName, "Name of the secret which contains CA's certificate and private key.")
flag.String("etcd-ca-secret-namespace", defaultETCDCASecretNamespace, "Namespace of the secret which contains CA's certificate and private key.") flag.String("etcd-ca-secret-namespace", defaultETCDCASecretNamespace, "Namespace of the secret which contains CA's certificate and private key.")
flag.String("etcd-client-secret-name", defaultETCDClientSecretName, "Name of the secret which contains ETCD client certificates") flag.String("etcd-client-secret-name", defaultETCDClientSecretName, "Name of the secret which contains ETCD client certificates")
flag.String("etcd-client-secret-namespace", defaultETCDClientSecretNamespace, "Name of the namespace where the secret which contains ETCD client certificates is") flag.String("etcd-client-secret-namespace", defaultETCDClientSecretNamespace, "Name of the namespace where the secret which contains ETCD client certificates is")
flag.String("etcd-endpoints", defaultETCDEndpoints, "Comma-separated list with ETCD endpoints (i.e. etcd-0.etcd.kamaji-system.svc.cluster.local,etcd-1.etcd.kamaji-system.svc.cluster.local,etcd-2.etcd.kamaji-system.svc.cluster.local)") flag.String("etcd-endpoints", defaultETCDEndpoints, "Comma-separated list with ETCD endpoints (i.e. https://etcd-0.etcd.kamaji-system.svc.cluster.local,https://etcd-1.etcd.kamaji-system.svc.cluster.local,https://etcd-2.etcd.kamaji-system.svc.cluster.local)")
flag.String("etcd-compaction-interval", defaultETCDCompactionInterval, "ETCD Compaction interval (i.e. \"5m0s\"). (default: \"0\" (disabled))") flag.String("etcd-compaction-interval", defaultETCDCompactionInterval, "ETCD Compaction interval (i.e. \"5m0s\"). (default: \"0\" (disabled))")
flag.String("tmp-directory", defaultTmpDirectory, "Directory which will be used to work with temporary files.") flag.String("tmp-directory", defaultTmpDirectory, "Directory which will be used to work with temporary files.")
@@ -74,6 +76,9 @@ func InitConfig() (*viper.Viper, error) {
if err := config.BindEnv("leader-elect", fmt.Sprintf("%s_LEADER_ELECTION", envPrefix)); err != nil { if err := config.BindEnv("leader-elect", fmt.Sprintf("%s_LEADER_ELECTION", envPrefix)); err != nil {
return nil, err return nil, err
} }
if err := config.BindEnv("etcd-storage-type", fmt.Sprintf("%s_ETCD_STORAGE_TYPE", envPrefix)); err != nil {
return nil, err
}
if err := config.BindEnv("etcd-ca-secret-name", fmt.Sprintf("%s_ETCD_CA_SECRET_NAME", envPrefix)); err != nil { if err := config.BindEnv("etcd-ca-secret-name", fmt.Sprintf("%s_ETCD_CA_SECRET_NAME", envPrefix)); err != nil {
return nil, err return nil, err
} }

View File

@@ -6,6 +6,7 @@ package kubeadm
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"strings"
"time" "time"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -14,6 +15,12 @@ import (
kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants" kubeadmconstants "k8s.io/kubernetes/cmd/kubeadm/app/constants"
) )
const (
defaultCAFile = "/etc/kubernetes/pki/etcd/ca.crt"
defaultCertFile = "/etc/kubernetes/pki/apiserver-etcd-client.crt"
defaultKeyFile = "/etc/kubernetes/pki/apiserver-etcd-client.key"
)
func CreateKubeadmInitConfiguration(params Parameters) Configuration { func CreateKubeadmInitConfiguration(params Parameters) Configuration {
config := kubeadmapi.InitConfiguration{ config := kubeadmapi.InitConfiguration{
ClusterConfiguration: getKubeadmClusterConfiguration(params), ClusterConfiguration: getKubeadmClusterConfiguration(params),
@@ -40,7 +47,16 @@ func CreateKubeadmInitConfiguration(params Parameters) Configuration {
return Configuration{InitConfiguration: config} return Configuration{InitConfiguration: config}
} }
func isHTTPS(url string) bool {
return strings.HasPrefix(url, "https")
}
func getKubeadmClusterConfiguration(params Parameters) kubeadmapi.ClusterConfiguration { func getKubeadmClusterConfiguration(params Parameters) kubeadmapi.ClusterConfiguration {
caFile, certFile, keyFile := "", "", ""
if isHTTPS(params.ETCDs[0]) {
caFile, certFile, keyFile = defaultCAFile, defaultCertFile, defaultKeyFile
}
return kubeadmapi.ClusterConfiguration{ return kubeadmapi.ClusterConfiguration{
KubernetesVersion: params.TenantControlPlaneVersion, KubernetesVersion: params.TenantControlPlaneVersion,
ClusterName: params.TenantControlPlaneName, ClusterName: params.TenantControlPlaneName,
@@ -57,10 +73,10 @@ func getKubeadmClusterConfiguration(params Parameters) kubeadmapi.ClusterConfigu
ControlPlaneEndpoint: params.TenantControlPlaneEndpoint, ControlPlaneEndpoint: params.TenantControlPlaneEndpoint,
Etcd: kubeadmapi.Etcd{ Etcd: kubeadmapi.Etcd{
External: &kubeadmapi.ExternalEtcd{ External: &kubeadmapi.ExternalEtcd{
Endpoints: formatETCDEndpoints(params.ETCDs), Endpoints: params.ETCDs,
CAFile: "/etc/kubernetes/pki/etcd/ca.crt", CAFile: caFile,
CertFile: "/etc/kubernetes/pki/apiserver-etcd-client.crt", CertFile: certFile,
KeyFile: "/etc/kubernetes/pki/apiserver-etcd-client.key", KeyFile: keyFile,
}, },
}, },
APIServer: kubeadmapi.APIServer{ APIServer: kubeadmapi.APIServer{
@@ -131,12 +147,3 @@ func getJSONStringFromStruct(i interface{}) (string, error) {
return string(b), nil return string(b), nil
} }
func formatETCDEndpoints(etcds []string) []string {
formatedETCDs := make([]string, 0, len(etcds))
for _, etcd := range etcds {
formatedETCDs = append(formatedETCDs, fmt.Sprintf("https://%s/", etcd))
}
return formatedETCDs
}

View File

@@ -22,13 +22,13 @@ const (
caKeyName = kubeadmconstants.CACertName caKeyName = kubeadmconstants.CACertName
) )
type resource struct { type etcdSetupResource struct {
role etcd.Role role etcd.Role
user etcd.User user etcd.User
} }
type ETCDSetupResource struct { type ETCDSetupResource struct {
resource *resource resource *etcdSetupResource
Client client.Client Client client.Client
Log logr.Logger Log logr.Logger
Name string Name string
@@ -55,7 +55,7 @@ func (r *ETCDSetupResource) CleanUp(ctx context.Context, tenantControlPlane *kam
} }
func (r *ETCDSetupResource) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error { func (r *ETCDSetupResource) Define(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
r.resource = &resource{ r.resource = &etcdSetupResource{
role: etcd.Role{Name: tenantControlPlane.Name, Exists: false}, role: etcd.Role{Name: tenantControlPlane.Name, Exists: false},
user: etcd.User{Name: tenantControlPlane.Name, Exists: false}, user: etcd.User{Name: tenantControlPlane.Name, Exists: false},
} }

View File

@@ -16,7 +16,7 @@ import (
corev1 "k8s.io/api/core/v1" corev1 "k8s.io/api/core/v1"
quantity "k8s.io/apimachinery/pkg/api/resource" quantity "k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types" apimachinerytypes "k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/util/intstr" "k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3" "k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta3"
"k8s.io/kubernetes/cmd/kubeadm/app/constants" "k8s.io/kubernetes/cmd/kubeadm/app/constants"
@@ -26,6 +26,7 @@ import (
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1" kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
"github.com/clastix/kamaji/internal/resources/konnectivity" "github.com/clastix/kamaji/internal/resources/konnectivity"
"github.com/clastix/kamaji/internal/types"
"github.com/clastix/kamaji/internal/utilities" "github.com/clastix/kamaji/internal/utilities"
) )
@@ -39,6 +40,7 @@ const (
type KubernetesDeploymentResource struct { type KubernetesDeploymentResource struct {
resource *appsv1.Deployment resource *appsv1.Deployment
Client client.Client Client client.Client
ETCDStorageType types.ETCDStorageType
ETCDEndpoints []string ETCDEndpoints []string
ETCDCompactionInterval string ETCDCompactionInterval string
Name string Name string
@@ -79,7 +81,7 @@ func (r *KubernetesDeploymentResource) Define(ctx context.Context, tenantControl
func (r *KubernetesDeploymentResource) secretHashValue(ctx context.Context, namespace, name string) (string, error) { func (r *KubernetesDeploymentResource) secretHashValue(ctx context.Context, namespace, name string) (string, error) {
secret := &corev1.Secret{} secret := &corev1.Secret{}
if err := r.Client.Get(ctx, types.NamespacedName{Namespace: namespace, Name: name}, secret); err != nil { if err := r.Client.Get(ctx, apimachinerytypes.NamespacedName{Namespace: namespace, Name: name}, secret); err != nil {
return "", errors.Wrap(err, "cannot retrieve *corev1.Secret for resource version retrieval") return "", errors.Wrap(err, "cannot retrieve *corev1.Secret for resource version retrieval")
} }
// Go access map values in random way, it means we have to sort them // Go access map values in random way, it means we have to sort them
@@ -105,11 +107,6 @@ func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenan
maxUnavailable := intstr.FromInt(0) maxUnavailable := intstr.FromInt(0)
etcdEndpoints := make([]string, len(r.ETCDEndpoints))
for i, v := range r.ETCDEndpoints {
etcdEndpoints[i] = fmt.Sprintf("https://%s", v)
}
address, err := tenantControlPlane.GetControlPlaneAddress(ctx, r.Client) address, err := tenantControlPlane.GetControlPlaneAddress(ctx, r.Client)
if err != nil { if err != nil {
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot create TenantControlPlane Deployment") return controllerutil.OperationResultNone, errors.Wrap(err, "cannot create TenantControlPlane Deployment")
@@ -151,16 +148,6 @@ func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenan
return return
}(), }(),
"component.kamaji.clastix.io/etcd-ca-certificates": func() (hash string) {
hash, _ = r.secretHashValue(ctx, tenantControlPlane.GetNamespace(), tenantControlPlane.Status.Certificates.ETCD.CA.SecretName)
return
}(),
"component.kamaji.clastix.io/etcd-certificates": func() (hash string) {
hash, _ = r.secretHashValue(ctx, tenantControlPlane.GetNamespace(), tenantControlPlane.Status.Certificates.ETCD.APIServer.SecretName)
return
}(),
"component.kamaji.clastix.io/front-proxy-ca-certificate": func() (hash string) { "component.kamaji.clastix.io/front-proxy-ca-certificate": func() (hash string) {
hash, _ = r.secretHashValue(ctx, tenantControlPlane.GetNamespace(), tenantControlPlane.Status.Certificates.FrontProxyCA.SecretName) hash, _ = r.secretHashValue(ctx, tenantControlPlane.GetNamespace(), tenantControlPlane.Status.Certificates.FrontProxyCA.SecretName)
@@ -207,22 +194,6 @@ func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenan
{ {
Secret: secretProjection(tenantControlPlane.Status.Certificates.SA.SecretName, constants.ServiceAccountPublicKeyName, constants.ServiceAccountPrivateKeyName), Secret: secretProjection(tenantControlPlane.Status.Certificates.SA.SecretName, constants.ServiceAccountPublicKeyName, constants.ServiceAccountPrivateKeyName),
}, },
{
Secret: secretProjection(tenantControlPlane.Status.Certificates.ETCD.APIServer.SecretName, constants.APIServerEtcdClientCertName, constants.APIServerEtcdClientKeyName),
},
{
Secret: &corev1.SecretProjection{
LocalObjectReference: corev1.LocalObjectReference{
Name: tenantControlPlane.Status.Certificates.ETCD.CA.SecretName,
},
Items: []corev1.KeyToPath{
{
Key: constants.CACertName,
Path: constants.EtcdCACertName,
},
},
},
},
}, },
DefaultMode: pointer.Int32Ptr(420), DefaultMode: pointer.Int32Ptr(420),
}, },
@@ -296,12 +267,6 @@ func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenan
fmt.Sprintf("--client-ca-file=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.CACertName)), fmt.Sprintf("--client-ca-file=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.CACertName)),
fmt.Sprintf("--enable-admission-plugins=%s", strings.Join(tenantControlPlane.Spec.Kubernetes.AdmissionControllers.ToSlice(), ",")), fmt.Sprintf("--enable-admission-plugins=%s", strings.Join(tenantControlPlane.Spec.Kubernetes.AdmissionControllers.ToSlice(), ",")),
"--enable-bootstrap-token-auth=true", "--enable-bootstrap-token-auth=true",
fmt.Sprintf("--etcd-compaction-interval=%s", r.ETCDCompactionInterval),
fmt.Sprintf("--etcd-cafile=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.EtcdCACertName)),
fmt.Sprintf("--etcd-certfile=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerEtcdClientCertName)),
fmt.Sprintf("--etcd-keyfile=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerEtcdClientKeyName)),
fmt.Sprintf("--etcd-servers=%s", strings.Join(etcdEndpoints, ",")),
fmt.Sprintf("--etcd-prefix=/%s", tenantControlPlane.GetName()),
fmt.Sprintf("--service-cluster-ip-range=%s", tenantControlPlane.Spec.NetworkProfile.ServiceCIDR), fmt.Sprintf("--service-cluster-ip-range=%s", tenantControlPlane.Spec.NetworkProfile.ServiceCIDR),
fmt.Sprintf("--kubelet-client-certificate=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerKubeletClientCertName)), fmt.Sprintf("--kubelet-client-certificate=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerKubeletClientCertName)),
fmt.Sprintf("--kubelet-client-key=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerKubeletClientKeyName)), fmt.Sprintf("--kubelet-client-key=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerKubeletClientKeyName)),
@@ -556,6 +521,8 @@ func (r *KubernetesDeploymentResource) CreateOrUpdate(ctx context.Context, tenan
}, },
} }
r.customizeStorage(ctx, &r.resource.Spec.Template, *tenantControlPlane)
if err := r.reconcileKonnectivity(&r.resource.Spec.Template.Spec, *tenantControlPlane); err != nil { if err := r.reconcileKonnectivity(&r.resource.Spec.Template.Spec, *tenantControlPlane); err != nil {
return err return err
} }
@@ -776,3 +743,62 @@ func (r *KubernetesDeploymentResource) buildKonnectivityServerContainer(tenantCo
ImagePullPolicy: corev1.PullIfNotPresent, ImagePullPolicy: corev1.PullIfNotPresent,
} }
} }
func (r *KubernetesDeploymentResource) customizeStorage(ctx context.Context, podTemplate *corev1.PodTemplateSpec, tenantControlPlane kamajiv1alpha1.TenantControlPlane) {
switch r.ETCDStorageType {
case types.ETCD:
r.customizeETCDStorage(ctx, podTemplate, tenantControlPlane)
default:
return
}
}
func (r *KubernetesDeploymentResource) customizeETCDStorage(ctx context.Context, podTemplate *corev1.PodTemplateSpec, tenantControlPlane kamajiv1alpha1.TenantControlPlane) {
labels := map[string]string{
"component.kamaji.clastix.io/etcd-ca-certificates": func() (hash string) {
hash, _ = r.secretHashValue(ctx, tenantControlPlane.GetNamespace(), tenantControlPlane.Status.Certificates.ETCD.CA.SecretName)
return
}(),
"component.kamaji.clastix.io/etcd-certificates": func() (hash string) {
hash, _ = r.secretHashValue(ctx, tenantControlPlane.GetNamespace(), tenantControlPlane.Status.Certificates.ETCD.APIServer.SecretName)
return
}(),
}
podTemplate.SetLabels(
utilities.MergeMaps(labels, podTemplate.Labels),
)
commands := []string{fmt.Sprintf("--etcd-compaction-interval=%s", r.ETCDCompactionInterval),
fmt.Sprintf("--etcd-cafile=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.EtcdCACertName)),
fmt.Sprintf("--etcd-certfile=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerEtcdClientCertName)),
fmt.Sprintf("--etcd-keyfile=%s", path.Join(v1beta3.DefaultCertificatesDir, constants.APIServerEtcdClientKeyName)),
fmt.Sprintf("--etcd-servers=%s", strings.Join(r.ETCDEndpoints, ",")),
fmt.Sprintf("--etcd-prefix=/%s", tenantControlPlane.GetName()),
}
podTemplate.Spec.Containers[0].Command = append(podTemplate.Spec.Containers[0].Command, commands...)
volumeProjections := []corev1.VolumeProjection{
{
Secret: secretProjection(tenantControlPlane.Status.Certificates.ETCD.APIServer.SecretName, constants.APIServerEtcdClientCertName, constants.APIServerEtcdClientKeyName),
},
{
Secret: &corev1.SecretProjection{
LocalObjectReference: corev1.LocalObjectReference{
Name: tenantControlPlane.Status.Certificates.ETCD.CA.SecretName,
},
Items: []corev1.KeyToPath{
{
Key: constants.CACertName,
Path: constants.EtcdCACertName,
},
},
},
},
}
podTemplate.Spec.Volumes[0].VolumeSource.Projected.Sources = append(podTemplate.Spec.Volumes[0].VolumeSource.Projected.Sources, volumeProjections...)
}

View File

@@ -28,6 +28,7 @@ type Resource interface {
} }
type DeleteableResource interface { type DeleteableResource interface {
Define(context.Context, *kamajiv1alpha1.TenantControlPlane) error
Delete(context.Context, *kamajiv1alpha1.TenantControlPlane) error Delete(context.Context, *kamajiv1alpha1.TenantControlPlane) error
} }
@@ -72,6 +73,15 @@ func Handle(ctx context.Context, resource Resource, tenantControlPlane *kamajiv1
return controllerutil.OperationResultNone, err return controllerutil.OperationResultNone, err
} }
// HandleDeletion handles the deletion of the given resource
func HandleDeletion(ctx context.Context, resource DeleteableResource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
if err := resource.Define(ctx, tenantControlPlane); err != nil {
return err
}
return resource.Delete(ctx, tenantControlPlane)
}
func createOrUpdate(ctx context.Context, resource Resource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) { func createOrUpdate(ctx context.Context, resource Resource, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
result, err := resource.CreateOrUpdate(ctx, tenantControlPlane) result, err := resource.CreateOrUpdate(ctx, tenantControlPlane)
if err != nil { if err != nil {

View File

@@ -0,0 +1,27 @@
package types
type ETCDStorageType int
const (
ETCD ETCDStorageType = iota
)
const (
defaultETCDStorageType = ETCD
)
var (
etcdStorageTypeString = map[string]ETCDStorageType{
"etcd": ETCD,
}
)
// ParseETCDStorageType returns the ETCDStorageType given a string representation of the type
func ParseETCDStorageType(s string) ETCDStorageType {
if storageType, ok := etcdStorageTypeString[s]; ok {
return storageType
}
// TODO: we have to decide what to do in this situation
return defaultETCDStorageType
}

View File

@@ -1,6 +1,6 @@
etcd-ca-secret-name: "etcd-certs" etcd-ca-secret-name: "etcd-certs"
etcd-ca-secret-namespace: kamaji-system etcd-ca-secret-namespace: kamaji-system
etcd-endpoints: etcd-0.etcd.kamaji-system.svc.cluster.local:2379,etcd-1.etcd.kamaji-system.svc.cluster.local:2379,etcd-2.etcd.kamaji-system.svc.cluster.local:2379 etcd-endpoints: https://etcd-0.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-1.etcd.kamaji-system.svc.cluster.local:2379,https://etcd-2.etcd.kamaji-system.svc.cluster.local:2379
etcd-client-secret-name: root-client-certs etcd-client-secret-name: root-client-certs
etcd-client-secret-namespaced: kamaji-system etcd-client-secret-namespaced: kamaji-system
etcd-compaction: "0" etcd-compaction: "0"

View File

@@ -33,6 +33,7 @@ import (
"github.com/clastix/kamaji/controllers" "github.com/clastix/kamaji/controllers"
"github.com/clastix/kamaji/internal" "github.com/clastix/kamaji/internal"
"github.com/clastix/kamaji/internal/config" "github.com/clastix/kamaji/internal/config"
"github.com/clastix/kamaji/internal/types"
) )
var ( var (
@@ -76,6 +77,7 @@ func main() {
Client: mgr.GetClient(), Client: mgr.GetClient(),
Scheme: mgr.GetScheme(), Scheme: mgr.GetScheme(),
Config: controllers.TenantControlPlaneReconcilerConfig{ Config: controllers.TenantControlPlaneReconcilerConfig{
ETCDStorageType: types.ParseETCDStorageType(conf.GetString("etcd-storage-type")),
ETCDCASecretName: conf.GetString("etcd-ca-secret-name"), ETCDCASecretName: conf.GetString("etcd-ca-secret-name"),
ETCDCASecretNamespace: conf.GetString("etcd-ca-secret-namespace"), ETCDCASecretNamespace: conf.GetString("etcd-ca-secret-namespace"),
ETCDClientSecretName: conf.GetString("etcd-client-secret-name"), ETCDClientSecretName: conf.GetString("etcd-client-secret-name"),