From e6e13ca73e74a982d892ca75be8051596fb37906 Mon Sep 17 00:00:00 2001 From: Tomasz Mielech Date: Wed, 6 Oct 2021 21:02:51 +0200 Subject: [PATCH 1/2] add feature with random pod names --- CHANGELOG.md | 1 + pkg/deployment/features/names.go | 19 +++++-- pkg/deployment/images.go | 2 +- pkg/deployment/resources/pod_creator.go | 73 +++++++++++++++---------- pkg/util/k8sutil/pods.go | 10 ++-- 5 files changed, 65 insertions(+), 40 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 35532e5c3..a48244668 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,7 @@ - Fix PVC Resize for Single servers - Add Topology support - Add ARANGODB_ZONE env to Topology Managed pods +- Add "Random pod names" feature ## [1.2.3](https://github.com/arangodb/kube-arangodb/tree/1.2.3) (2021-09-24) - Update UBI Image to 8.4 diff --git a/pkg/deployment/features/names.go b/pkg/deployment/features/names.go index de527d999..c782d5e1f 100644 --- a/pkg/deployment/features/names.go +++ b/pkg/deployment/features/names.go @@ -17,16 +17,16 @@ // // Copyright holder is ArangoDB GmbH, Cologne, Germany // -// Author Adam Janikowski // package features func init() { - registerFeature(podNames) + registerFeature(shortPodNames) + registerFeature(randomPodNames) } -var podNames = &feature{ +var shortPodNames = &feature{ name: "short-pod-names", description: "Enable Short Pod Names", version: "3.5.0", @@ -34,6 +34,15 @@ var podNames = &feature{ enabledByDefault: false, } -func PodNames() Feature { - return podNames +func ShortPodNames() Feature { + return shortPodNames +} + +var randomPodNames = &feature{ + name: "random-pod-names", + description: "Enables generating random pod names", +} + +func RandomPodNames() Feature { + return randomPodNames } diff --git a/pkg/deployment/images.go b/pkg/deployment/images.go index 0d4a798cb..e80780c8e 100644 --- a/pkg/deployment/images.go +++ b/pkg/deployment/images.go @@ -233,7 +233,7 @@ func (ib *imagesBuilder) fetchArangoDBImageIDAndVersion(ctx context.Context, cac } err = k8sutil.RunWithTimeout(ctx, func(ctxChild context.Context) error { - _, err := resources.CreateArangoPod(ctxChild, ib.KubeCli, ib.APIObject, ib.Spec, api.ServerGroupImageDiscovery, pod) + _, _, err := resources.CreateArangoPod(ctxChild, ib.KubeCli, ib.APIObject, ib.Spec, api.ServerGroupImageDiscovery, pod) return err }) if err != nil { diff --git a/pkg/deployment/resources/pod_creator.go b/pkg/deployment/resources/pod_creator.go index d60600813..462152695 100644 --- a/pkg/deployment/resources/pod_creator.go +++ b/pkg/deployment/resources/pod_creator.go @@ -17,8 +17,6 @@ // // Copyright holder is ArangoDB GmbH, Cologne, Germany // -// Author Ewout Prangsma -// Author Tomasz Mielech // package resources @@ -35,27 +33,22 @@ import ( "sync" "time" - "github.com/arangodb/kube-arangodb/pkg/util" - - "github.com/arangodb/kube-arangodb/pkg/util/errors" - - "github.com/arangodb/kube-arangodb/pkg/deployment/features" - - inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector" - "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/interfaces" - + core "k8s.io/api/core/v1" + meta "k8s.io/apimachinery/pkg/apis/meta/v1" "k8s.io/apimachinery/pkg/types" + "k8s.io/client-go/kubernetes" - "github.com/arangodb/kube-arangodb/pkg/deployment/pod" + "github.com/arangodb/go-driver" - driver "github.com/arangodb/go-driver" api "github.com/arangodb/kube-arangodb/pkg/apis/deployment/v1" + "github.com/arangodb/kube-arangodb/pkg/deployment/features" + "github.com/arangodb/kube-arangodb/pkg/deployment/pod" + "github.com/arangodb/kube-arangodb/pkg/util" "github.com/arangodb/kube-arangodb/pkg/util/constants" + "github.com/arangodb/kube-arangodb/pkg/util/errors" "github.com/arangodb/kube-arangodb/pkg/util/k8sutil" - - core "k8s.io/api/core/v1" - meta "k8s.io/apimachinery/pkg/apis/meta/v1" - "k8s.io/client-go/kubernetes" + inspectorInterface "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/inspector" + "github.com/arangodb/kube-arangodb/pkg/util/k8sutil/interfaces" ) func versionHasAdvertisedEndpoint(v driver.Version) bool { @@ -369,7 +362,8 @@ func (r *Resources) RenderPodForMember(ctx context.Context, cachedStatus inspect newMember.PodName = k8sutil.CreatePodName(apiObject.GetName(), roleAbbr, newMember.ID, CreatePodSuffix(spec)) - // Render pod + var podCreator interfaces.PodCreator + var args []string if group.IsArangod() { // Prepare arguments autoUpgrade := newMember.Conditions.IsTrue(api.ConditionTypeAutoUpgrade) || spec.Upgrade.Get().AutoUpgrade @@ -390,7 +384,8 @@ func (r *Resources) RenderPodForMember(ctx context.Context, cachedStatus inspect input := memberPod.AsInput() - args, err := createArangodArgs(cachedStatus, input) + var err error + args, err = createArangodArgs(cachedStatus, input) if err != nil { return nil, errors.WithStack(err) } @@ -398,8 +393,7 @@ func (r *Resources) RenderPodForMember(ctx context.Context, cachedStatus inspect if err := memberPod.Validate(cachedStatus); err != nil { return nil, errors.WithStack(errors.Wrapf(err, "Validation of pods resources failed")) } - - return RenderArangoPod(cachedStatus, apiObject, role, newMember.ID, newMember.PodName, args, &memberPod) + podCreator = &memberPod } else if group.IsArangosync() { // Check image if !imageInfo.Enterprise { @@ -455,7 +449,7 @@ func (r *Resources) RenderPodForMember(ctx context.Context, cachedStatus inspect } // Prepare arguments - args := createArangoSyncArgs(apiObject, spec, group, groupSpec, *newMember) + args = createArangoSyncArgs(apiObject, spec, group, groupSpec, *newMember) memberSyncPod := MemberSyncPod{ tlsKeyfileSecretName: tlsKeyfileSecretName, @@ -470,10 +464,23 @@ func (r *Resources) RenderPodForMember(ctx context.Context, cachedStatus inspect arangoMember: *member, } - return RenderArangoPod(cachedStatus, apiObject, role, newMember.ID, newMember.PodName, args, &memberSyncPod) + podCreator = &memberSyncPod } else { return nil, errors.Newf("unable to render Pod") } + + pod, err := RenderArangoPod(cachedStatus, apiObject, role, newMember.ID, newMember.PodName, args, podCreator) + if err != nil { + return nil, err + } + + if features.RandomPodNames().Enabled() { + // The server will generate the name with some additional suffix after `-`. + pod.GenerateName = pod.Name + "-" + pod.Name = "" + } + + return pod, nil } func (r *Resources) SelectImage(spec api.DeploymentSpec, status api.DeploymentStatus) (api.ImageInfo, bool) { @@ -563,11 +570,12 @@ func (r *Resources) createPodForMember(ctx context.Context, spec api.DeploymentS ctxChild, cancel := context.WithTimeout(ctx, k8sutil.GetRequestTimeout()) defer cancel() - uid, err := CreateArangoPod(ctxChild, kubecli, apiObject, spec, group, CreatePodFromTemplate(template.PodSpec)) + podName, uid, err := CreateArangoPod(ctxChild, kubecli, apiObject, spec, group, CreatePodFromTemplate(template.PodSpec)) if err != nil { return errors.WithStack(err) } + m.PodName = podName m.PodUID = uid m.PodSpecVersion = template.PodSpecChecksum m.ArangoVersion = m.Image.ArangoDBVersion @@ -610,12 +618,13 @@ func (r *Resources) createPodForMember(ctx context.Context, spec api.DeploymentS ctxChild, cancel := context.WithTimeout(ctx, k8sutil.GetRequestTimeout()) defer cancel() - uid, err := CreateArangoPod(ctxChild, kubecli, apiObject, spec, group, CreatePodFromTemplate(template.PodSpec)) + podName, uid, err := CreateArangoPod(ctxChild, kubecli, apiObject, spec, group, CreatePodFromTemplate(template.PodSpec)) if err != nil { return errors.WithStack(err) } log.Debug().Str("pod-name", m.PodName).Msg("Created pod") + m.PodName = podName m.PodUID = uid m.PodSpecVersion = template.PodSpecChecksum } @@ -704,13 +713,14 @@ func RenderArangoPod(cachedStatus inspectorInterface.Inspector, deployment k8sut // CreateArangoPod creates a new Pod with container provided by parameter 'containerCreator' // If the pod already exists, nil is returned. // If another error occurs, that error is returned. -func CreateArangoPod(ctx context.Context, kubecli kubernetes.Interface, deployment k8sutil.APIObject, deploymentSpec api.DeploymentSpec, group api.ServerGroup, pod *core.Pod) (types.UID, error) { - uid, err := k8sutil.CreatePod(ctx, kubecli, pod, deployment.GetNamespace(), deployment.AsOwner()) +func CreateArangoPod(ctx context.Context, kubecli kubernetes.Interface, deployment k8sutil.APIObject, + deploymentSpec api.DeploymentSpec, group api.ServerGroup, pod *core.Pod) (string, types.UID, error) { + podName, uid, err := k8sutil.CreatePod(ctx, kubecli, pod, deployment.GetNamespace(), deployment.AsOwner()) if err != nil { - return "", errors.WithStack(err) + return "", "", errors.WithStack(err) } - return uid, nil + return podName, uid, nil } func CreatePodFromTemplate(p *core.PodTemplateSpec) *core.Pod { @@ -777,8 +787,11 @@ func (r *Resources) EnsurePods(ctx context.Context, cachedStatus inspectorInterf return nil } +// CreatePodSuffix creates additional string to glue it to the POD name. +// The suffix is calculated according to the given spec, so it is easily to recognize by name if the pods have the same spec. +// The additional `postSuffix` can be provided. It can be used to distinguish restarts of POD. func CreatePodSuffix(spec api.DeploymentSpec) string { - if features.PodNames().Enabled() { + if features.ShortPodNames().Enabled() || features.RandomPodNames().Enabled() { return "" } diff --git a/pkg/util/k8sutil/pods.go b/pkg/util/k8sutil/pods.go index bb3dc14c5..f5483867e 100644 --- a/pkg/util/k8sutil/pods.go +++ b/pkg/util/k8sutil/pods.go @@ -465,16 +465,18 @@ func GetPodSpecChecksum(podSpec core.PodSpec) (string, error) { // CreatePod adds an owner to the given pod and calls the k8s api-server to created it. // If the pod already exists, nil is returned. // If another error occurs, that error is returned. -func CreatePod(ctx context.Context, kubecli kubernetes.Interface, pod *core.Pod, ns string, owner metav1.OwnerReference) (types.UID, error) { +func CreatePod(ctx context.Context, kubecli kubernetes.Interface, pod *core.Pod, ns string, + owner metav1.OwnerReference) (string, types.UID, error) { AddOwnerRefToObject(pod.GetObjectMeta(), &owner) if pod, err := kubecli.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{}); err != nil { if IsAlreadyExists(err) { - return "", nil // If pod exists do not return any error but do not record UID (enforced rotation) + return "", "", nil // If pod exists do not return any error but do not record UID (enforced rotation) } - return "", errors.WithStack(err) + + return "", "", errors.WithStack(err) } else { - return pod.UID, nil + return pod.GetName(), pod.UID, nil } } From e5c155938a7f7c7780af4360f70b4ad08c47105f Mon Sep 17 00:00:00 2001 From: Tomasz Mielech Date: Thu, 7 Oct 2021 14:23:49 +0200 Subject: [PATCH 2/2] return pod name when it exists already --- pkg/util/k8sutil/pods.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/util/k8sutil/pods.go b/pkg/util/k8sutil/pods.go index f5483867e..8868777ab 100644 --- a/pkg/util/k8sutil/pods.go +++ b/pkg/util/k8sutil/pods.go @@ -469,14 +469,14 @@ func CreatePod(ctx context.Context, kubecli kubernetes.Interface, pod *core.Pod, owner metav1.OwnerReference) (string, types.UID, error) { AddOwnerRefToObject(pod.GetObjectMeta(), &owner) - if pod, err := kubecli.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{}); err != nil { + if createdPod, err := kubecli.CoreV1().Pods(ns).Create(ctx, pod, metav1.CreateOptions{}); err != nil { if IsAlreadyExists(err) { - return "", "", nil // If pod exists do not return any error but do not record UID (enforced rotation) + return pod.GetName(), "", nil // If pod exists do not return any error but do not record UID (enforced rotation) } return "", "", errors.WithStack(err) } else { - return pod.GetName(), pod.UID, nil + return createdPod.GetName(), pod.UID, nil } }