Skip to content

Commit 2e8f30c

Browse files
authored
feat(hatchery:k8s): set memory and CPU limits for workers and services (#6187)
1 parent 767e9f6 commit 2e8f30c

File tree

3 files changed

+66
-12
lines changed

3 files changed

+66
-12
lines changed

engine/hatchery/kubernetes/kubernetes.go

+55-11
Original file line numberDiff line numberDiff line change
@@ -183,7 +183,15 @@ func (h *HatcheryKubernetes) SpawnWorker(ctx context.Context, spawnArgs hatchery
183183
logJob = fmt.Sprintf("for workflow job %d,", spawnArgs.JobID)
184184
}
185185

186+
cpu := h.Config.DefaultCPU
187+
if cpu == "" {
188+
cpu = "500m"
189+
}
190+
186191
memory := int64(h.Config.DefaultMemory)
192+
if memory == 0 {
193+
memory = 1024
194+
}
187195
for _, r := range spawnArgs.Requirements {
188196
if r.Type == sdk.MemoryRequirement {
189197
var err error
@@ -192,9 +200,15 @@ func (h *HatcheryKubernetes) SpawnWorker(ctx context.Context, spawnArgs hatchery
192200
log.Warn(ctx, "spawnKubernetesDockerWorker> %s unable to parse memory requirement %d: %v", logJob, memory, err)
193201
return err
194202
}
203+
break
195204
}
196205
}
197206

207+
ephemeralStorage := h.Config.DefaultEphemeralStorage
208+
if ephemeralStorage == "" {
209+
ephemeralStorage = "1Gi"
210+
}
211+
198212
workerConfig := h.GenerateWorkerConfig(ctx, h, spawnArgs)
199213
udataParam := struct {
200214
API string
@@ -283,7 +297,14 @@ func (h *HatcheryKubernetes) SpawnWorker(ctx context.Context, spawnArgs hatchery
283297
Args: []string{cmd},
284298
Resources: apiv1.ResourceRequirements{
285299
Requests: apiv1.ResourceList{
286-
apiv1.ResourceMemory: resource.MustParse(fmt.Sprintf("%d", memory)),
300+
apiv1.ResourceCPU: resource.MustParse(cpu),
301+
apiv1.ResourceMemory: *resource.NewScaledQuantity(memory, resource.Mega),
302+
apiv1.ResourceEphemeralStorage: resource.MustParse(ephemeralStorage),
303+
},
304+
Limits: apiv1.ResourceList{
305+
apiv1.ResourceCPU: resource.MustParse(cpu),
306+
apiv1.ResourceMemory: *resource.NewScaledQuantity(memory, resource.Mega),
307+
apiv1.ResourceEphemeralStorage: resource.MustParse(ephemeralStorage),
287308
},
288309
},
289310
},
@@ -313,28 +334,51 @@ func (h *HatcheryKubernetes) SpawnWorker(ctx context.Context, spawnArgs hatchery
313334
podSchema.Spec.HostAliases[0].Hostnames[0] = "worker"
314335
}
315336

337+
serviceCPU := h.Config.DefaultServiceCPU
338+
if serviceCPU == "" {
339+
serviceCPU = "256m"
340+
}
341+
342+
serviceMemory := int64(h.Config.DefaultServiceMemory)
343+
if serviceMemory == 0 {
344+
serviceMemory = 512
345+
}
346+
347+
serviceEphemeralStorage := h.Config.DefaultServiceEphemeralStorage
348+
if serviceEphemeralStorage == "" {
349+
serviceEphemeralStorage = "512Mi"
350+
}
351+
316352
for i, serv := range services {
317353
//name= <alias> => the name of the host put in /etc/hosts of the worker
318354
//value= "postgres:latest env_1=blabla env_2=blabla"" => we can add env variables in requirement name
319355
img, envm := hatchery.ParseRequirementModel(serv.Value)
320356

321-
servContainer := apiv1.Container{
322-
Name: fmt.Sprintf("service-%d-%s", serv.ID, strings.ToLower(serv.Name)),
323-
Image: img,
324-
}
325-
326357
if sm, ok := envm["CDS_SERVICE_MEMORY"]; ok {
327-
mq, err := resource.ParseQuantity(sm)
358+
var err error
359+
serviceMemory, err = strconv.ParseInt(sm, 10, 64)
328360
if err != nil {
329361
log.Warn(ctx, "hatchery> kubernetes> SpawnWorker> Unable to parse CDS_SERVICE_MEMORY value '%s': %s", sm, err)
330362
continue
331363
}
332-
servContainer.Resources = apiv1.ResourceRequirements{
364+
delete(envm, "CDS_SERVICE_MEMORY")
365+
}
366+
367+
servContainer := apiv1.Container{
368+
Name: fmt.Sprintf("service-%d-%s", serv.ID, strings.ToLower(serv.Name)),
369+
Image: img,
370+
Resources: apiv1.ResourceRequirements{
333371
Requests: apiv1.ResourceList{
334-
apiv1.ResourceMemory: mq,
372+
apiv1.ResourceCPU: resource.MustParse(serviceCPU),
373+
apiv1.ResourceMemory: *resource.NewScaledQuantity(serviceMemory, resource.Mega),
374+
apiv1.ResourceEphemeralStorage: resource.MustParse(serviceEphemeralStorage),
335375
},
336-
}
337-
delete(envm, "CDS_SERVICE_MEMORY")
376+
Limits: apiv1.ResourceList{
377+
apiv1.ResourceCPU: resource.MustParse(serviceCPU),
378+
apiv1.ResourceMemory: *resource.NewScaledQuantity(serviceMemory, resource.Mega),
379+
apiv1.ResourceEphemeralStorage: resource.MustParse(serviceEphemeralStorage),
380+
},
381+
},
338382
}
339383

340384
if sa, ok := envm["CDS_SERVICE_ARGS"]; ok {

engine/hatchery/kubernetes/kubernetes_test.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func TestHatcheryKubernetes_Status(t *testing.T) {
100100

101101
require.Equal(t, 2, len(podRequest.Spec.Containers))
102102
require.Equal(t, "my-worker", podRequest.Spec.Containers[0].Name)
103-
require.Equal(t, int64(4096), podRequest.Spec.Containers[0].Resources.Requests.Memory().Value())
103+
require.Equal(t, int64(4096000000), podRequest.Spec.Containers[0].Resources.Requests.Memory().Value())
104104
var foundEnv, foundSecret bool
105105
for _, env := range podRequest.Spec.Containers[0].Env {
106106
if env.Name == "PROVISION_ENV" && env.Value == "MYVALUE" {

engine/hatchery/kubernetes/types.go

+10
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,18 @@ var containerServiceNameRegexp = regexp.MustCompile(`service-([0-9]+)-(.*)`)
1919
// HatcheryConfiguration is the configuration for local hatchery
2020
type HatcheryConfiguration struct {
2121
service.HatcheryCommonConfiguration `mapstructure:"commonConfiguration" toml:"commonConfiguration" json:"commonConfiguration"`
22+
// DefaultCPU Worker default CPU
23+
DefaultCPU string `mapstructure:"defaultCPU" toml:"defaultCPU" default:"500m" commented:"false" comment:"Worker default CPU" json:"defaultCPU"`
2224
// DefaultMemory Worker default memory
2325
DefaultMemory int `mapstructure:"defaultMemory" toml:"defaultMemory" default:"1024" commented:"false" comment:"Worker default memory in Mo" json:"defaultMemory"`
26+
// DefaultEphemeralStorage Worker default ephemeral storage size
27+
DefaultEphemeralStorage string `mapstructure:"defaultEphemeralStorage" toml:"defaultEphemeralStorage" default:"1Gi" commented:"false" comment:"Worker default ephemeral storage size" json:"defaultEphemeralStorage"`
28+
// DefaultServiceCPU Service default CPU
29+
DefaultServiceCPU string `mapstructure:"defaultServiceCPU" toml:"defaultServiceCPU" default:"256m" commented:"false" comment:"Service default CPU" json:"defaultServiceCPU"`
30+
// DefaultServiceMemory Service default memory
31+
DefaultServiceMemory int `mapstructure:"defaultServiceMemory" toml:"defaultServiceMemory" default:"512" commented:"false" comment:"Service default memory in Mo" json:"defaultServiceMemory"`
32+
// DefaultServiceEphemeralStorage Service default ephemeral storage size
33+
DefaultServiceEphemeralStorage string `mapstructure:"defaultServiceEphemeralStorage" toml:"defaultServiceEphemeralStorage" default:"512Mi" commented:"false" comment:"Service default ephemeral storage size" json:"defaultServiceEphemeralStorage"`
2434
// Namespace is the kubernetes namespace in which workers are spawned"
2535
Namespace string `mapstructure:"namespace" toml:"namespace" default:"cds" commented:"false" comment:"Kubernetes namespace in which workers are spawned" json:"namespace"`
2636
// KubernetesMasterURL Address of kubernetes master

0 commit comments

Comments
 (0)