mirror of
https://github.com/clastix/kamaji.git
synced 2026-02-14 10:00:02 +00:00
* feat: supporting k8s v1.35 Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * feat: upgrading deployment also in sleeping mode Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * feat(deps): bumping ko to v0.18.1 Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * feat(deps): bumping controller-gen to v0.20.0 Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * chore(crds): aligning to k8s v1.35 Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * docs: alinging to k8s v1.35 Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * test: upgrading to k8s 1.35 Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> * feat(helm): updating artifact hub changes Signed-off-by: Dario Tranchitella <dario@tranchitella.eu> --------- Signed-off-by: Dario Tranchitella <dario@tranchitella.eu>
148 lines
5.0 KiB
Go
148 lines
5.0 KiB
Go
// Copyright 2022 Clastix Labs
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
|
|
package resources
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
|
|
"github.com/pkg/errors"
|
|
"github.com/prometheus/client_golang/prometheus"
|
|
"k8s.io/apimachinery/pkg/util/version"
|
|
"k8s.io/kubernetes/cmd/kubeadm/app/phases/upgrade"
|
|
"k8s.io/utils/ptr"
|
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
|
"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
|
|
|
|
kamajiv1alpha1 "github.com/clastix/kamaji/api/v1alpha1"
|
|
"github.com/clastix/kamaji/internal/kubeadm/printers"
|
|
kamajiupgrade "github.com/clastix/kamaji/internal/upgrade"
|
|
"github.com/clastix/kamaji/internal/utilities"
|
|
)
|
|
|
|
type KubernetesUpgrade struct {
|
|
Client client.Client
|
|
upgrade upgrade.Upgrade
|
|
|
|
inProgress bool
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) GetHistogram() prometheus.Histogram {
|
|
kubeadmupgradeCollector = LazyLoadHistogramFromResource(kubeadmupgradeCollector, k)
|
|
|
|
return kubeadmupgradeCollector
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) Define(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
k.upgrade = upgrade.Upgrade{
|
|
Before: upgrade.ClusterState{
|
|
KubeVersion: tenantControlPlane.Status.Kubernetes.Version.Version,
|
|
},
|
|
After: upgrade.ClusterState{
|
|
KubeVersion: tenantControlPlane.Spec.Kubernetes.Version,
|
|
},
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) ShouldCleanup(*kamajiv1alpha1.TenantControlPlane) bool {
|
|
return false
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) CleanUp(context.Context, *kamajiv1alpha1.TenantControlPlane) (bool, error) {
|
|
return false, nil
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) CreateOrUpdate(ctx context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) (controllerutil.OperationResult, error) {
|
|
// A new installation, no need to upgrade
|
|
if len(tenantControlPlane.Status.Kubernetes.Version.Version) == 0 {
|
|
k.inProgress = false
|
|
|
|
return controllerutil.OperationResultNone, nil
|
|
}
|
|
// No version change, no need to upgrade
|
|
if tenantControlPlane.Status.Kubernetes.Version.Version == tenantControlPlane.Spec.Kubernetes.Version {
|
|
k.inProgress = false
|
|
|
|
return controllerutil.OperationResultNone, nil
|
|
}
|
|
// An upgrade is in progress, let it go
|
|
if status := tenantControlPlane.Status.Kubernetes.Version.Status; status != nil && *status == kamajiv1alpha1.VersionUpgrading {
|
|
return controllerutil.OperationResultNone, nil
|
|
}
|
|
// Checking if the upgrade is allowed, or not
|
|
clientSet, err := utilities.GetTenantClientSet(ctx, k.Client, tenantControlPlane)
|
|
if err != nil {
|
|
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot create REST client required for Kubernetes upgrade plan")
|
|
}
|
|
|
|
var coreDNSVersion string
|
|
if tenantControlPlane.Spec.Addons.CoreDNS != nil {
|
|
coreDNSVersion = tenantControlPlane.Spec.Addons.CoreDNS.ImageTag
|
|
}
|
|
|
|
versionGetter := kamajiupgrade.NewKamajiKubeVersionGetter(clientSet, tenantControlPlane.Status.Kubernetes.Version.Version, coreDNSVersion, tenantControlPlane.Status.Kubernetes.Version.Status)
|
|
|
|
if _, err = upgrade.GetAvailableUpgrades(versionGetter, false, false, &printers.Discard{}); err != nil {
|
|
return controllerutil.OperationResultNone, errors.Wrap(err, "cannot retrieve available Upgrades for Kubernetes upgrade plan")
|
|
}
|
|
|
|
if err = k.isUpgradable(); err != nil {
|
|
return controllerutil.OperationResultNone, fmt.Errorf("the required upgrade plan is not available")
|
|
}
|
|
|
|
if ptr.Deref(tenantControlPlane.Spec.ControlPlane.Deployment.Replicas, 0) > 0 {
|
|
k.inProgress = true
|
|
}
|
|
|
|
return controllerutil.OperationResultNone, nil
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) GetName() string {
|
|
return "upgrade"
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) ShouldStatusBeUpdated(context.Context, *kamajiv1alpha1.TenantControlPlane) bool {
|
|
return k.inProgress
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) UpdateTenantControlPlaneStatus(_ context.Context, tenantControlPlane *kamajiv1alpha1.TenantControlPlane) error {
|
|
if k.inProgress {
|
|
tenantControlPlane.Status.Kubernetes.Version.Status = &kamajiv1alpha1.VersionUpgrading
|
|
}
|
|
|
|
if tenantControlPlane.Spec.Kubernetes.Version == tenantControlPlane.Status.Kubernetes.Version.Version {
|
|
tenantControlPlane.Status.Kubernetes.Version.Status = &kamajiv1alpha1.VersionReady
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (k *KubernetesUpgrade) isUpgradable() error {
|
|
newK8sVersion, err := version.ParseSemantic(k.upgrade.After.KubeVersion)
|
|
if err != nil {
|
|
return errors.Wrap(err, fmt.Sprintf("unable to parse normalized version %q as a semantic version", k.upgrade.After.KubeVersion))
|
|
}
|
|
|
|
oldK8sVersion, err := version.ParseSemantic(k.upgrade.Before.KubeVersion)
|
|
if err != nil {
|
|
return errors.Wrap(err, fmt.Sprintf("unable to parse normalized version %q as a semantic version", k.upgrade.After.KubeVersion))
|
|
}
|
|
|
|
if newK8sVersion.Minor() < oldK8sVersion.Minor() {
|
|
return fmt.Errorf("cannot downgrade to a previous minor version of Kubernetes")
|
|
}
|
|
// Patch upgrades are allowed
|
|
if newK8sVersion.Minor() == oldK8sVersion.Minor() {
|
|
return nil
|
|
}
|
|
// Following minor release upgrades are allowed
|
|
if newK8sVersion.Minor() == oldK8sVersion.Minor()+1 {
|
|
return nil
|
|
}
|
|
|
|
return fmt.Errorf("an upgrade to a non consecutive Kubernetes minor release is forbidden")
|
|
}
|