From 504eff2956bc8fe47f04b3fcb0c0248643dca3a5 Mon Sep 17 00:00:00 2001 From: ArielLahiany Date: Tue, 21 Jan 2025 22:29:43 +0200 Subject: [PATCH] Kubernetes Driver: switch to 'StatefulSet' from 'Deployment'. Signed-off-by: ArielLahiany --- driver/kubernetes/driver.go | 46 +++++++------- driver/kubernetes/factory.go | 70 +++++++++++----------- driver/kubernetes/manifest/manifest.go | 59 ++++++++++-------- driver/kubernetes/podchooser/podchooser.go | 24 ++++---- 4 files changed, 103 insertions(+), 96 deletions(-) diff --git a/driver/kubernetes/driver.go b/driver/kubernetes/driver.go index 6629cfcca202..b907b604ce9f 100644 --- a/driver/kubernetes/driver.go +++ b/driver/kubernetes/driver.go @@ -43,16 +43,16 @@ type Driver struct { // if you add fields, remember to update docs: // https://github.com/docker/docs/blob/main/content/build/drivers/kubernetes.md - minReplicas int - deployment *appsv1.Deployment - configMaps []*corev1.ConfigMap - clientset *kubernetes.Clientset - deploymentClient clientappsv1.DeploymentInterface - podClient clientcorev1.PodInterface - configMapClient clientcorev1.ConfigMapInterface - podChooser podchooser.PodChooser - defaultLoad bool - timeout time.Duration + minReplicas int + statefulSet *appsv1.StatefulSet + configMaps []*corev1.ConfigMap + clientset *kubernetes.Clientset + statefulSetClient clientappsv1.StatefulSetInterface + podClient clientcorev1.PodInterface + configMapClient clientcorev1.ConfigMapInterface + podChooser podchooser.PodChooser + defaultLoad bool + timeout time.Duration } func (d *Driver) IsMobyDriver() bool { @@ -65,10 +65,10 @@ func (d *Driver) Config() driver.InitConfig { func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { return progress.Wrap("[internal] booting buildkit", l, func(sub progress.SubLogger) error { - _, err := d.deploymentClient.Get(ctx, d.deployment.Name, metav1.GetOptions{}) + _, err := d.statefulSetClient.Get(ctx, d.statefulSet.Name, metav1.GetOptions{}) if err != nil { if !apierrors.IsNotFound(err) { - return errors.Wrapf(err, "error for bootstrap %q", d.deployment.Name) + return errors.Wrapf(err, "error for bootstrap %q", d.statefulSet.Name) } for _, cfg := range d.configMaps { @@ -85,9 +85,9 @@ func (d *Driver) Bootstrap(ctx context.Context, l progress.Logger) error { } } - _, err = d.deploymentClient.Create(ctx, d.deployment, metav1.CreateOptions{}) + _, err = d.statefulSetClient.Create(ctx, d.statefulSet, metav1.CreateOptions{}) if err != nil { - return errors.Wrapf(err, "error while calling deploymentClient.Create for %q", d.deployment.Name) + return errors.Wrapf(err, "error while calling statefulSetClient.Create for %q", d.statefulSet.Name) } } return sub.Wrap( @@ -102,7 +102,7 @@ func (d *Driver) wait(ctx context.Context) error { // TODO: use watch API var ( err error - depl *appsv1.Deployment + stat *appsv1.StatefulSet ) timeoutChan := time.After(d.timeout) @@ -116,31 +116,31 @@ func (d *Driver) wait(ctx context.Context) error { case <-timeoutChan: return err case <-ticker.C: - depl, err = d.deploymentClient.Get(ctx, d.deployment.Name, metav1.GetOptions{}) + stat, err = d.statefulSetClient.Get(ctx, d.statefulSet.Name, metav1.GetOptions{}) if err == nil { - if depl.Status.ReadyReplicas >= int32(d.minReplicas) { + if stat.Status.ReadyReplicas >= int32(d.minReplicas) { return nil } - err = errors.Errorf("expected %d replicas to be ready, got %d", d.minReplicas, depl.Status.ReadyReplicas) + err = errors.Errorf("expected %d replicas to be ready, got %d", d.minReplicas, stat.Status.ReadyReplicas) } } } } func (d *Driver) Info(ctx context.Context) (*driver.Info, error) { - depl, err := d.deploymentClient.Get(ctx, d.deployment.Name, metav1.GetOptions{}) + stat, err := d.statefulSetClient.Get(ctx, d.statefulSet.Name, metav1.GetOptions{}) if err != nil { // TODO: return err if err != ErrNotFound return &driver.Info{ Status: driver.Inactive, }, nil } - if depl.Status.ReadyReplicas <= 0 { + if stat.Status.ReadyReplicas <= 0 { return &driver.Info{ Status: driver.Stopped, }, nil } - pods, err := podchooser.ListRunningPods(ctx, d.podClient, depl) + pods, err := podchooser.ListRunningPods(ctx, d.podClient, stat) if err != nil { return nil, err } @@ -182,9 +182,9 @@ func (d *Driver) Rm(ctx context.Context, force, rmVolume, rmDaemon bool) error { return nil } - if err := d.deploymentClient.Delete(ctx, d.deployment.Name, metav1.DeleteOptions{}); err != nil { + if err := d.statefulSetClient.Delete(ctx, d.statefulSet.Name, metav1.DeleteOptions{}); err != nil { if !apierrors.IsNotFound(err) { - return errors.Wrapf(err, "error while calling deploymentClient.Delete for %q", d.deployment.Name) + return errors.Wrapf(err, "error while calling statefulSetClient.Delete for %q", d.statefulSet.Name) } } for _, cfg := range d.configMaps { diff --git a/driver/kubernetes/factory.go b/driver/kubernetes/factory.go index b25abb899b68..32a9dea4d3e0 100644 --- a/driver/kubernetes/factory.go +++ b/driver/kubernetes/factory.go @@ -104,7 +104,7 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver } } - deploymentName, err := buildxNameToDeploymentName(cfg.Name) + statefulSetName, err := buildxNameToStatefulSetName(cfg.Name) if err != nil { return nil, err } @@ -128,7 +128,7 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver clientset: clientset, } - deploymentOpt, loadbalance, namespace, defaultLoad, timeout, err := f.processDriverOpts(deploymentName, namespace, cfg) + statefulSetOpt, loadbalance, namespace, defaultLoad, timeout, err := f.processDriverOpts(statefulSetName, namespace, cfg) if nil != err { return nil, err } @@ -136,36 +136,36 @@ func (f *factory) New(ctx context.Context, cfg driver.InitConfig) (driver.Driver d.defaultLoad = defaultLoad d.timeout = timeout - d.deployment, d.configMaps, err = manifest.NewDeployment(deploymentOpt) + d.statefulSet, d.configMaps, err = manifest.NewStatefulSet(statefulSetOpt) if err != nil { return nil, err } - d.minReplicas = deploymentOpt.Replicas + d.minReplicas = statefulSetOpt.Replicas - d.deploymentClient = clientset.AppsV1().Deployments(namespace) + d.statefulSetClient = clientset.AppsV1().StatefulSets(namespace) d.podClient = clientset.CoreV1().Pods(namespace) d.configMapClient = clientset.CoreV1().ConfigMaps(namespace) switch loadbalance { case LoadbalanceSticky: d.podChooser = &podchooser.StickyPodChooser{ - Key: cfg.ContextPathHash, - PodClient: d.podClient, - Deployment: d.deployment, + Key: cfg.ContextPathHash, + PodClient: d.podClient, + StatefulSet: d.statefulSet, } case LoadbalanceRandom: d.podChooser = &podchooser.RandomPodChooser{ - PodClient: d.podClient, - Deployment: d.deployment, + PodClient: d.podClient, + StatefulSet: d.statefulSet, } } return d, nil } -func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg driver.InitConfig) (*manifest.DeploymentOpt, string, string, bool, time.Duration, error) { - deploymentOpt := &manifest.DeploymentOpt{ - Name: deploymentName, +func (f *factory) processDriverOpts(statefulSetName string, namespace string, cfg driver.InitConfig) (*manifest.StatefulSetOpt, string, string, bool, time.Duration, error) { + statefulSetOpt := &manifest.StatefulSetOpt{ + Name: statefulSetName, Image: bkimage.DefaultImage, Replicas: 1, BuildkitFlags: cfg.BuildkitdFlags, @@ -177,7 +177,7 @@ func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg defaultLoad := false timeout := defaultTimeout - deploymentOpt.Qemu.Image = bkimage.QemuImage + statefulSetOpt.Qemu.Image = bkimage.QemuImage loadbalance := LoadbalanceSticky var err error @@ -186,57 +186,57 @@ func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg switch k { case "image": if v != "" { - deploymentOpt.Image = v + statefulSetOpt.Image = v } case "namespace": namespace = v case "replicas": - deploymentOpt.Replicas, err = strconv.Atoi(v) + statefulSetOpt.Replicas, err = strconv.Atoi(v) if err != nil { return nil, "", "", false, 0, err } case "requests.cpu": - deploymentOpt.RequestsCPU = v + statefulSetOpt.RequestsCPU = v case "requests.memory": - deploymentOpt.RequestsMemory = v + statefulSetOpt.RequestsMemory = v case "requests.ephemeral-storage": - deploymentOpt.RequestsEphemeralStorage = v + statefulSetOpt.RequestsEphemeralStorage = v case "limits.cpu": - deploymentOpt.LimitsCPU = v + statefulSetOpt.LimitsCPU = v case "limits.memory": - deploymentOpt.LimitsMemory = v + statefulSetOpt.LimitsMemory = v case "limits.ephemeral-storage": - deploymentOpt.LimitsEphemeralStorage = v + statefulSetOpt.LimitsEphemeralStorage = v case "rootless": - deploymentOpt.Rootless, err = strconv.ParseBool(v) + statefulSetOpt.Rootless, err = strconv.ParseBool(v) if err != nil { return nil, "", "", false, 0, err } if _, isImage := cfg.DriverOpts["image"]; !isImage { - deploymentOpt.Image = bkimage.DefaultRootlessImage + statefulSetOpt.Image = bkimage.DefaultRootlessImage } case "schedulername": - deploymentOpt.SchedulerName = v + statefulSetOpt.SchedulerName = v case "serviceaccount": - deploymentOpt.ServiceAccountName = v + statefulSetOpt.ServiceAccountName = v case "nodeselector": - deploymentOpt.NodeSelector, err = splitMultiValues(v, ",", "=") + statefulSetOpt.NodeSelector, err = splitMultiValues(v, ",", "=") if err != nil { return nil, "", "", false, 0, errors.Wrap(err, "cannot parse node selector") } case "annotations": - deploymentOpt.CustomAnnotations, err = splitMultiValues(v, ",", "=") + statefulSetOpt.CustomAnnotations, err = splitMultiValues(v, ",", "=") if err != nil { return nil, "", "", false, 0, errors.Wrap(err, "cannot parse annotations") } case "labels": - deploymentOpt.CustomLabels, err = splitMultiValues(v, ",", "=") + statefulSetOpt.CustomLabels, err = splitMultiValues(v, ",", "=") if err != nil { return nil, "", "", false, 0, errors.Wrap(err, "cannot parse labels") } case "tolerations": ts := strings.Split(v, ";") - deploymentOpt.Tolerations = []corev1.Toleration{} + statefulSetOpt.Tolerations = []corev1.Toleration{} for i := range ts { kvs := strings.Split(ts[i], ",") @@ -267,7 +267,7 @@ func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg } } - deploymentOpt.Tolerations = append(deploymentOpt.Tolerations, t) + statefulSetOpt.Tolerations = append(statefulSetOpt.Tolerations, t) } case "loadbalance": switch v { @@ -278,13 +278,13 @@ func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg } loadbalance = v case "qemu.install": - deploymentOpt.Qemu.Install, err = strconv.ParseBool(v) + statefulSetOpt.Qemu.Install, err = strconv.ParseBool(v) if err != nil { return nil, "", "", false, 0, err } case "qemu.image": if v != "" { - deploymentOpt.Qemu.Image = v + statefulSetOpt.Qemu.Image = v } case "default-load": defaultLoad, err = strconv.ParseBool(v) @@ -301,7 +301,7 @@ func (f *factory) processDriverOpts(deploymentName string, namespace string, cfg } } - return deploymentOpt, loadbalance, namespace, defaultLoad, timeout, nil + return statefulSetOpt, loadbalance, namespace, defaultLoad, timeout, nil } func splitMultiValues(in string, itemsep string, kvsep string) (map[string]string, error) { @@ -324,7 +324,7 @@ func (f *factory) AllowsInstances() bool { // buildxNameToDeploymentName converts buildx name to Kubernetes Deployment name. // // eg. "buildx_buildkit_loving_mendeleev0" -> "loving-mendeleev0" -func buildxNameToDeploymentName(bx string) (string, error) { +func buildxNameToStatefulSetName(bx string) (string, error) { // TODO: commands.util.go should not pass "buildx_buildkit_" prefix to drivers s, err := driver.ParseBuilderName(bx) if err != nil { diff --git a/driver/kubernetes/manifest/manifest.go b/driver/kubernetes/manifest/manifest.go index 1137badb7f2b..4bc0df73cbb1 100644 --- a/driver/kubernetes/manifest/manifest.go +++ b/driver/kubernetes/manifest/manifest.go @@ -13,7 +13,7 @@ import ( metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" ) -type DeploymentOpt struct { +type StatefulSetOpt struct { Namespace string Name string Image string @@ -64,7 +64,7 @@ func (ErrReservedLabelApp) Error() string { return fmt.Sprintf("the label %q is reserved and cannot be customized", LabelApp) } -func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.ConfigMap, err error) { +func NewStatefulSet(opt *StatefulSetOpt) (s *appsv1.StatefulSet, c []*corev1.ConfigMap, err error) { labels := map[string]string{ LabelApp: opt.Name, } @@ -91,10 +91,10 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config labels[k] = v } - d = &appsv1.Deployment{ + s = &appsv1.StatefulSet{ TypeMeta: metav1.TypeMeta{ APIVersion: appsv1.SchemeGroupVersion.String(), - Kind: "Deployment", + Kind: "StatefulSet", }, ObjectMeta: metav1.ObjectMeta{ Namespace: opt.Namespace, @@ -102,7 +102,7 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config Labels: labels, Annotations: annotations, }, - Spec: appsv1.DeploymentSpec{ + Spec: appsv1.StatefulSetSpec{ Replicas: &replicas, Selector: &metav1.LabelSelector{ MatchLabels: labels, @@ -130,6 +130,13 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config }, }, }, + LivenessProbe: &corev1.Probe{ + ProbeHandler: corev1.ProbeHandler{ + Exec: &corev1.ExecAction{ + Command: []string{"buildctl", "debug", "workers"}, + }, + }, + }, Resources: corev1.ResourceRequirements{ Requests: corev1.ResourceList{}, Limits: corev1.ResourceList{}, @@ -154,12 +161,12 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config Data: cfg.files, } - d.Spec.Template.Spec.Containers[0].VolumeMounts = append(d.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ + s.Spec.Template.Spec.Containers[0].VolumeMounts = append(s.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ Name: cfg.name, MountPath: path.Join("/etc/buildkit", cfg.path), }) - d.Spec.Template.Spec.Volumes = append(d.Spec.Template.Spec.Volumes, corev1.Volume{ + s.Spec.Template.Spec.Volumes = append(s.Spec.Template.Spec.Volumes, corev1.Volume{ Name: cfg.name, VolumeSource: corev1.VolumeSource{ ConfigMap: &corev1.ConfigMapVolumeSource{ @@ -173,7 +180,7 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config } if opt.Qemu.Install { - d.Spec.Template.Spec.InitContainers = []corev1.Container{ + s.Spec.Template.Spec.InitContainers = []corev1.Container{ { Name: "qemu", Image: opt.Qemu.Image, @@ -186,17 +193,17 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config } if opt.Rootless { - if err := toRootless(d); err != nil { + if err := toRootless(s); err != nil { return nil, nil, err } } if len(opt.NodeSelector) > 0 { - d.Spec.Template.Spec.NodeSelector = opt.NodeSelector + s.Spec.Template.Spec.NodeSelector = opt.NodeSelector } if len(opt.Tolerations) > 0 { - d.Spec.Template.Spec.Tolerations = opt.Tolerations + s.Spec.Template.Spec.Tolerations = opt.Tolerations } if opt.RequestsCPU != "" { @@ -204,7 +211,7 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config if err != nil { return nil, nil, err } - d.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceCPU] = reqCPU + s.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceCPU] = reqCPU } if opt.RequestsMemory != "" { @@ -212,7 +219,7 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config if err != nil { return nil, nil, err } - d.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceMemory] = reqMemory + s.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceMemory] = reqMemory } if opt.RequestsEphemeralStorage != "" { @@ -220,7 +227,7 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config if err != nil { return nil, nil, err } - d.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceEphemeralStorage] = reqEphemeralStorage + s.Spec.Template.Spec.Containers[0].Resources.Requests[corev1.ResourceEphemeralStorage] = reqEphemeralStorage } if opt.LimitsCPU != "" { @@ -228,7 +235,7 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config if err != nil { return nil, nil, err } - d.Spec.Template.Spec.Containers[0].Resources.Limits[corev1.ResourceCPU] = limCPU + s.Spec.Template.Spec.Containers[0].Resources.Limits[corev1.ResourceCPU] = limCPU } if opt.LimitsMemory != "" { @@ -236,7 +243,7 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config if err != nil { return nil, nil, err } - d.Spec.Template.Spec.Containers[0].Resources.Limits[corev1.ResourceMemory] = limMemory + s.Spec.Template.Spec.Containers[0].Resources.Limits[corev1.ResourceMemory] = limMemory } if opt.LimitsEphemeralStorage != "" { @@ -244,26 +251,26 @@ func NewDeployment(opt *DeploymentOpt) (d *appsv1.Deployment, c []*corev1.Config if err != nil { return nil, nil, err } - d.Spec.Template.Spec.Containers[0].Resources.Limits[corev1.ResourceEphemeralStorage] = limEphemeralStorage + s.Spec.Template.Spec.Containers[0].Resources.Limits[corev1.ResourceEphemeralStorage] = limEphemeralStorage } return } -func toRootless(d *appsv1.Deployment) error { - d.Spec.Template.Spec.Containers[0].Args = append( - d.Spec.Template.Spec.Containers[0].Args, +func toRootless(s *appsv1.StatefulSet) error { + s.Spec.Template.Spec.Containers[0].Args = append( + s.Spec.Template.Spec.Containers[0].Args, "--oci-worker-no-process-sandbox", ) - d.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{ + s.Spec.Template.Spec.Containers[0].SecurityContext = &corev1.SecurityContext{ SeccompProfile: &corev1.SeccompProfile{ Type: corev1.SeccompProfileTypeUnconfined, }, } - if d.Spec.Template.ObjectMeta.Annotations == nil { - d.Spec.Template.ObjectMeta.Annotations = make(map[string]string, 1) + if s.Spec.Template.ObjectMeta.Annotations == nil { + s.Spec.Template.ObjectMeta.Annotations = make(map[string]string, 1) } - d.Spec.Template.ObjectMeta.Annotations["container.apparmor.security.beta.kubernetes.io/"+containerName] = "unconfined" + s.Spec.Template.ObjectMeta.Annotations["container.apparmor.security.beta.kubernetes.io/"+containerName] = "unconfined" // Dockerfile has `VOLUME /home/user/.local/share/buildkit` by default too, // but the default VOLUME does not work with rootless on Google's Container-Optimized OS @@ -271,11 +278,11 @@ func toRootless(d *appsv1.Deployment) error { // https://github.com/moby/buildkit/issues/879#issuecomment-1240347038 // https://github.com/moby/buildkit/pull/3097 const emptyDirVolName = "buildkitd" - d.Spec.Template.Spec.Containers[0].VolumeMounts = append(d.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ + s.Spec.Template.Spec.Containers[0].VolumeMounts = append(s.Spec.Template.Spec.Containers[0].VolumeMounts, corev1.VolumeMount{ Name: emptyDirVolName, MountPath: "/home/user/.local/share/buildkit", }) - d.Spec.Template.Spec.Volumes = append(d.Spec.Template.Spec.Volumes, corev1.Volume{ + s.Spec.Template.Spec.Volumes = append(s.Spec.Template.Spec.Volumes, corev1.Volume{ Name: emptyDirVolName, VolumeSource: corev1.VolumeSource{ EmptyDir: &corev1.EmptyDirVolumeSource{}, diff --git a/driver/kubernetes/podchooser/podchooser.go b/driver/kubernetes/podchooser/podchooser.go index 06a294417abf..fe9d3c23f602 100644 --- a/driver/kubernetes/podchooser/podchooser.go +++ b/driver/kubernetes/podchooser/podchooser.go @@ -20,13 +20,13 @@ type PodChooser interface { } type RandomPodChooser struct { - RandSource rand.Source - PodClient clientcorev1.PodInterface - Deployment *appsv1.Deployment + RandSource rand.Source + PodClient clientcorev1.PodInterface + StatefulSet *appsv1.StatefulSet } func (pc *RandomPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error) { - pods, err := ListRunningPods(ctx, pc.PodClient, pc.Deployment) + pods, err := ListRunningPods(ctx, pc.PodClient, pc.StatefulSet) if err != nil { return nil, err } @@ -44,13 +44,13 @@ func (pc *RandomPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error) } type StickyPodChooser struct { - Key string - PodClient clientcorev1.PodInterface - Deployment *appsv1.Deployment + Key string + PodClient clientcorev1.PodInterface + StatefulSet *appsv1.StatefulSet } func (pc *StickyPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error) { - pods, err := ListRunningPods(ctx, pc.PodClient, pc.Deployment) + pods, err := ListRunningPods(ctx, pc.PodClient, pc.StatefulSet) if err != nil { return nil, err } @@ -66,16 +66,16 @@ func (pc *StickyPodChooser) ChoosePod(ctx context.Context) (*corev1.Pod, error) // NOTREACHED logrus.Errorf("no pod found for key %q", pc.Key) rpc := &RandomPodChooser{ - PodClient: pc.PodClient, - Deployment: pc.Deployment, + PodClient: pc.PodClient, + StatefulSet: pc.StatefulSet, } return rpc.ChoosePod(ctx) } return podMap[chosen], nil } -func ListRunningPods(ctx context.Context, client clientcorev1.PodInterface, depl *appsv1.Deployment) ([]*corev1.Pod, error) { - selector, err := metav1.LabelSelectorAsSelector(depl.Spec.Selector) +func ListRunningPods(ctx context.Context, client clientcorev1.PodInterface, stat *appsv1.StatefulSet) ([]*corev1.Pod, error) { + selector, err := metav1.LabelSelectorAsSelector(stat.Spec.Selector) if err != nil { return nil, err }