-
Notifications
You must be signed in to change notification settings - Fork 38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Issue 130: Ability to specify container resources #129
Changes from 13 commits
4abafe4
33ec9d1
44b7697
a50b533
50b8442
2818fd6
8be2cfe
213d449
faac0f1
2ea7277
dd3413a
4308f52
ad2c198
9878fac
64b8d06
6acf293
5a7e937
464f206
e466ec5
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -68,6 +68,10 @@ type BookkeeperSpec struct { | |
// ServiceAccountName configures the service account used on BookKeeper instances | ||
ServiceAccountName string `json:"serviceAccountName,omitempty"` | ||
|
||
// BookieResources specifies the request and limit of resources that bookie can have. | ||
// BookieResources includes CPU and memory resources | ||
Resources *v1.ResourceRequirements `json:"resources,omitempty"` | ||
|
||
// Options is the Bookkeeper configuration that is to override the bk_server.conf | ||
// in bookkeeper. Some examples can be found here | ||
// https://github.com/apache/bookkeeper/blob/master/docker/README.md | ||
|
@@ -102,9 +106,24 @@ func (s *BookkeeperSpec) withDefaults() (changed bool) { | |
s.AutoRecovery = &boolTrue | ||
} | ||
|
||
if s.Resources == nil { | ||
changed = true | ||
s.Resources = &v1.ResourceRequirements{ | ||
Requests: v1.ResourceList{ | ||
v1.ResourceCPU: resource.MustParse("500m"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why these values are lower than the ones in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The default values are meant to represent the bare minimum requirements for Pravega to run. These values are intended to be use in a first contact with Pravega, functional testing, or development work. Therefore, we want to keep them low so that Pravega can be deployed to small Kubernetes clusters. Whereas the values in |
||
v1.ResourceMemory: resource.MustParse("1Gi"), | ||
}, | ||
Limits: v1.ResourceList{ | ||
v1.ResourceCPU: resource.MustParse("1000m"), | ||
v1.ResourceMemory: resource.MustParse("2Gi"), | ||
}, | ||
} | ||
} | ||
|
||
if s.Options == nil { | ||
s.Options = map[string]string{} | ||
} | ||
|
||
return changed | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -87,6 +87,14 @@ type PravegaSpec struct { | |
// SegmentStoreServiceAccountName configures the service account used on segment store instances. | ||
// If not specified, Kubernetes will automatically assign the default service account in the namespace | ||
SegmentStoreServiceAccountName string `json:"segmentStoreServiceAccountName,omitempty"` | ||
|
||
// ControllerResources specifies the request and limit of resources that controller can have. | ||
// ControllerResources includes CPU and memory resources | ||
ControllerResources *v1.ResourceRequirements `json:"controllerResources,omitempty"` | ||
|
||
// SegmentStoreResources specifies the request and limit of resources that segmentStore can have. | ||
// SegmentStoreResources includes CPU and memory resources | ||
SegmentStoreResources *v1.ResourceRequirements `json:"segmentStoreResources,omitempty"` | ||
} | ||
|
||
func (s *PravegaSpec) withDefaults() (changed bool) { | ||
|
@@ -129,10 +137,39 @@ func (s *PravegaSpec) withDefaults() (changed bool) { | |
changed = true | ||
s.Tier2 = &Tier2Spec{} | ||
} | ||
|
||
if s.Tier2.withDefaults() { | ||
changed = true | ||
} | ||
|
||
if s.ControllerResources == nil { | ||
changed = true | ||
s.ControllerResources = &v1.ResourceRequirements{ | ||
Requests: v1.ResourceList{ | ||
v1.ResourceCPU: resource.MustParse("250m"), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same comment here with the defaults compared to There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Responded in #129 (comment) |
||
v1.ResourceMemory: resource.MustParse("512Mi"), | ||
}, | ||
Limits: v1.ResourceList{ | ||
v1.ResourceCPU: resource.MustParse("500m"), | ||
v1.ResourceMemory: resource.MustParse("1Gi"), | ||
}, | ||
} | ||
} | ||
|
||
if s.SegmentStoreResources == nil { | ||
changed = true | ||
s.SegmentStoreResources = &v1.ResourceRequirements{ | ||
Requests: v1.ResourceList{ | ||
v1.ResourceCPU: resource.MustParse("500m"), | ||
v1.ResourceMemory: resource.MustParse("1Gi"), | ||
}, | ||
Limits: v1.ResourceList{ | ||
v1.ResourceCPU: resource.MustParse("1000m"), | ||
v1.ResourceMemory: resource.MustParse("2Gi"), | ||
}, | ||
} | ||
} | ||
|
||
return changed | ||
} | ||
|
||
|
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -20,7 +20,6 @@ import ( | |
appsv1 "k8s.io/api/apps/v1" | ||
corev1 "k8s.io/api/core/v1" | ||
policyv1beta1 "k8s.io/api/policy/v1beta1" | ||
"k8s.io/apimachinery/pkg/api/resource" | ||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" | ||
"k8s.io/apimachinery/pkg/util/intstr" | ||
) | ||
|
@@ -99,16 +98,7 @@ func makeSegmentstorePodSpec(pravegaCluster *api.PravegaCluster) corev1.PodSpec | |
MountPath: cacheVolumeMountPoint, | ||
}, | ||
}, | ||
Resources: corev1.ResourceRequirements{ | ||
Requests: corev1.ResourceList{ | ||
corev1.ResourceCPU: resource.MustParse("1000m"), | ||
corev1.ResourceMemory: resource.MustParse("3Gi"), | ||
}, | ||
Limits: corev1.ResourceList{ | ||
corev1.ResourceCPU: resource.MustParse("2000m"), | ||
corev1.ResourceMemory: resource.MustParse("5Gi"), | ||
}, | ||
}, | ||
Resources: *pravegaSpec.SegmentStoreResources, | ||
ReadinessProbe: &corev1.Probe{ | ||
Handler: corev1.Handler{ | ||
Exec: &corev1.ExecAction{ | ||
|
@@ -151,44 +141,48 @@ func makeSegmentstorePodSpec(pravegaCluster *api.PravegaCluster) corev1.PodSpec | |
return podSpec | ||
} | ||
|
||
func MakeSegmentstoreConfigMap(pravegaCluster *api.PravegaCluster) *corev1.ConfigMap { | ||
func MakeSegmentstoreConfigMap(p *api.PravegaCluster) *corev1.ConfigMap { | ||
javaOpts := []string{ | ||
"-Xms1g -Xmx4g -XX:MaxDirectMemorySize=1g -Dpravegaservice.clusterName=" + pravegaCluster.Name, | ||
"-Xms1g", | ||
"-XX:+UnlockExperimentalVMOptions", | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are these options configurable as part of another PR, right? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, JVM options are not externally configurable. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ok, this may not be great, because we will rely on the default
So, we may end up providing 4GBs of memory to a pod, but 1GB at most will be devoted to the JVM (despite the main purpose of that pod is to run the JVM for the Pravega process at hand). What is your opinion about this? Have you used |
||
"-XX:+UseCGroupMemoryLimitForHeap", | ||
"-XX:MaxRAMFraction=1", | ||
"-Dpravegaservice.clusterName=" + p.Name, | ||
} | ||
|
||
for name, value := range pravegaCluster.Spec.Pravega.Options { | ||
for name, value := range p.Spec.Pravega.Options { | ||
javaOpts = append(javaOpts, fmt.Sprintf("-D%v=%v", name, value)) | ||
} | ||
|
||
configData := map[string]string{ | ||
"AUTHORIZATION_ENABLED": "false", | ||
"CLUSTER_NAME": pravegaCluster.Name, | ||
"ZK_URL": pravegaCluster.Spec.ZookeeperUri, | ||
"CLUSTER_NAME": p.Name, | ||
"ZK_URL": p.Spec.ZookeeperUri, | ||
"JAVA_OPTS": strings.Join(javaOpts, " "), | ||
"CONTROLLER_URL": util.PravegaControllerServiceURL(*pravegaCluster), | ||
"CONTROLLER_URL": util.PravegaControllerServiceURL(*p), | ||
} | ||
|
||
// Wait for at least 3 Bookies to come up | ||
var waitFor []string | ||
for i := int32(0); i < util.Min(3, pravegaCluster.Spec.Bookkeeper.Replicas); i++ { | ||
for i := int32(0); i < util.Min(3, p.Spec.Bookkeeper.Replicas); i++ { | ||
waitFor = append(waitFor, | ||
fmt.Sprintf("%s-%d.%s.%s:3181", | ||
util.StatefulSetNameForBookie(pravegaCluster.Name), | ||
util.StatefulSetNameForBookie(p.Name), | ||
i, | ||
util.HeadlessServiceNameForBookie(pravegaCluster.Name), | ||
pravegaCluster.Namespace)) | ||
util.HeadlessServiceNameForBookie(p.Name), | ||
p.Namespace)) | ||
} | ||
configData["WAIT_FOR"] = strings.Join(waitFor, ",") | ||
|
||
if pravegaCluster.Spec.ExternalAccess.Enabled { | ||
if p.Spec.ExternalAccess.Enabled { | ||
configData["K8_EXTERNAL_ACCESS"] = "true" | ||
} | ||
|
||
if pravegaCluster.Spec.Pravega.DebugLogging { | ||
if p.Spec.Pravega.DebugLogging { | ||
configData["log.level"] = "DEBUG" | ||
} | ||
|
||
for k, v := range getTier2StorageOptions(pravegaCluster.Spec.Pravega) { | ||
for k, v := range getTier2StorageOptions(p.Spec.Pravega) { | ||
configData[k] = v | ||
} | ||
|
||
|
@@ -198,9 +192,9 @@ func MakeSegmentstoreConfigMap(pravegaCluster *api.PravegaCluster) *corev1.Confi | |
APIVersion: "v1", | ||
}, | ||
ObjectMeta: metav1.ObjectMeta{ | ||
Name: util.ConfigMapNameForSegmentstore(pravegaCluster.Name), | ||
Namespace: pravegaCluster.Namespace, | ||
Labels: util.LabelsForSegmentStore(pravegaCluster), | ||
Name: util.ConfigMapNameForSegmentstore(p.Name), | ||
Namespace: p.Namespace, | ||
Labels: util.LabelsForSegmentStore(p), | ||
}, | ||
Data: configData, | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is there any test that validates that these values are properly passed to the process?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, we will work on adding a test to validate that resources are passed down to pod templates correctly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Test added. Could you please review it again? Thanks!