Skip to content
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

Support resource annotations for jaeger agent sidecar #169

Closed
17 changes: 17 additions & 0 deletions README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -439,6 +439,23 @@ sampled.

Refer to the Jaeger documentation on link:https://www.jaegertracing.io/docs/latest/sampling/#collector-sampling-configuration[Collector Sampling Configuration] to see how service and endpoint sampling can be configured. The JSON representation described in that documentation can be used in the operator by converting to YAML.

== Defining resouce limits

By default, the Jaeger operator will create a container with limits of `500m` CPU and `128Mi` memory.
This behavior can be overwritten through annotations `jaeger-agent-max-cpu` and `jaeger-agent-max-memory` on the deployment object.

[source,yaml]
----
apiVersion: apps/v1
kind: Deployment
metadata:
name: mydepapp
annotations:
inject-jaeger-agent: "true"
jaeger-agent-max-cpu: "1000m" # Use units of choice. 1000m = 1 CPU.
jaeger-agent-max-memory: "256Mi" # = 256MiB.
----

== Schema migration

=== Cassandra
Expand Down
46 changes: 44 additions & 2 deletions pkg/inject/sidecar.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
log "github.com/sirupsen/logrus"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"

"github.com/jaegertracing/jaeger-operator/pkg/apis/jaegertracing/v1"
"github.com/jaegertracing/jaeger-operator/pkg/deployment"
Expand All @@ -21,6 +22,12 @@ var (

// AnnotationLegacy holds the annotation name we had in the past, which we keep for backwards compatibility
AnnotationLegacy = "inject-jaeger-agent"

// LimitCPU is the annotation name for cpu resource limits for a jaeger agent sidecar
LimitCPU = "jaeger-agent-max-cpu"

// LimitMem is the annotation name for memory resource limits for a jaeger agent sidecar
LimitMem = "jaeger-agent-max-memory"
)

const (
Expand All @@ -38,7 +45,7 @@ func Sidecar(jaeger *v1.Jaeger, dep *appsv1.Deployment) *appsv1.Deployment {
} else {
decorate(dep)
logFields.Debug("injecting sidecar")
dep.Spec.Template.Spec.Containers = append(dep.Spec.Template.Spec.Containers, container(jaeger))
dep.Spec.Template.Spec.Containers = append(dep.Spec.Template.Spec.Containers, container(jaeger, dep))
}

return dep
Expand Down Expand Up @@ -87,7 +94,7 @@ func Select(target *appsv1.Deployment, availableJaegerPods *v1.JaegerList) *v1.J
return nil
}

func container(jaeger *v1.Jaeger) corev1.Container {
func container(jaeger *v1.Jaeger, dep *appsv1.Deployment) corev1.Container {
args := append(jaeger.Spec.Agent.Options.ToArgs())

if len(util.FindItem("--reporter.type=", args)) == 0 {
Expand All @@ -103,6 +110,31 @@ func container(jaeger *v1.Jaeger) corev1.Container {
// see https://github.com/jaegertracing/jaeger-operator/issues/334
sort.Strings(args)

// Checking annotations for CPU/Memory limits
limitCPU := "500m"
limitMem := "128Mi"

CPULimitDefault, _ := resource.ParseQuantity(limitCPU)
MemLimitDefault, _ := resource.ParseQuantity(limitMem)

if dep.Annotations[LimitCPU] != "" {
limitCPU = dep.Annotations[LimitCPU]
}
if dep.Annotations[LimitMem] != "" {
limitMem = dep.Annotations[LimitMem]
}

CPULimit, err := resource.ParseQuantity(limitCPU)
if err != nil {
jaeger.Logger().Debugf("Could not parse quantity for CPU limits: %v, using defaults.", limitCPU)
CPULimit = CPULimitDefault
}
MemLimit, err := resource.ParseQuantity(limitMem)
if err != nil {
jaeger.Logger().Debugf("Could not parse quantity for Memory limits: %v, using defaults.", limitMem)
MemLimit = MemLimitDefault
}

return corev1.Container{
Image: jaeger.Spec.Agent.Image,
Name: "jaeger-agent",
Expand All @@ -125,6 +157,16 @@ func container(jaeger *v1.Jaeger) corev1.Container {
Name: "jg-binary-trft",
},
},
Resources: corev1.ResourceRequirements{
Limits: corev1.ResourceList{
corev1.ResourceLimitsCPU: CPULimit,
corev1.ResourceLimitsMemory: MemLimit,
},
Requests: corev1.ResourceList{
corev1.ResourceRequestsCPU: CPULimit,
corev1.ResourceRequestsMemory: MemLimit,
},
},
}
}

Expand Down
69 changes: 62 additions & 7 deletions pkg/inject/sidecar_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import (
"github.com/stretchr/testify/assert"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/resource"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

"github.com/jaegertracing/jaeger-operator/pkg/apis/jaegertracing/v1"
Expand Down Expand Up @@ -122,7 +123,7 @@ func TestSidecarNotNeeded(t *testing.T) {
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
corev1.Container{},
{},
},
},
},
Expand All @@ -149,7 +150,7 @@ func TestSelectSingleJaegerPod(t *testing.T) {
dep := dep(map[string]string{Annotation: "true"}, map[string]string{})
jaegerPods := &v1.JaegerList{
Items: []v1.Jaeger{
v1.Jaeger{
{
ObjectMeta: metav1.ObjectMeta{
Name: "the-only-jaeger-instance-available",
},
Expand All @@ -166,12 +167,12 @@ func TestCannotSelectFromMultipleJaegerPods(t *testing.T) {
dep := dep(map[string]string{Annotation: "true"}, map[string]string{})
jaegerPods := &v1.JaegerList{
Items: []v1.Jaeger{
v1.Jaeger{
{
ObjectMeta: metav1.ObjectMeta{
Name: "the-first-jaeger-instance-available",
},
},
v1.Jaeger{
{
ObjectMeta: metav1.ObjectMeta{
Name: "the-second-jaeger-instance-available",
},
Expand All @@ -194,12 +195,12 @@ func TestSelectBasedOnName(t *testing.T) {

jaegerPods := &v1.JaegerList{
Items: []v1.Jaeger{
v1.Jaeger{
{
ObjectMeta: metav1.ObjectMeta{
Name: "the-first-jaeger-instance-available",
},
},
v1.Jaeger{
{
ObjectMeta: metav1.ObjectMeta{
Name: "the-second-jaeger-instance-available",
},
Expand All @@ -212,6 +213,60 @@ func TestSelectBasedOnName(t *testing.T) {
assert.Equal(t, "the-second-jaeger-instance-available", jaeger.Name)
}

func TestAgentResouceDefs(t *testing.T) {
jaeger := v1.NewJaeger("TestAgentResouceDefs")
dep := dep(map[string]string{Annotation: jaeger.Name}, map[string]string{})

// Inject sidecar agent
Sidecar(jaeger, dep)

// Assert that the agent is injected.
assert.Len(t, dep.Spec.Template.Spec.Containers, 2)
assert.Contains(t, dep.Spec.Template.Spec.Containers[1].Image, "jaeger-agent")

// Check resource values for the injected sidecar.
CPULimit, _ := resource.ParseQuantity("500m")
MemLimit, _ := resource.ParseQuantity("128Mi")
assert.Equal(t, dep.Spec.Template.Spec.Containers[1].Resources.Limits[corev1.ResourceLimitsCPU], CPULimit)
assert.Equal(t, dep.Spec.Template.Spec.Containers[1].Resources.Limits[corev1.ResourceLimitsMemory], MemLimit)
}

func TestAgentResouceDefsOverride(t *testing.T) {
jaeger := v1.NewJaeger("TestAgentResouceDefsOverride")
dep := dep(map[string]string{Annotation: jaeger.Name, "jaeger-agent-max-cpu": "1024m", "jaeger-agent-max-memory": "100Mi"}, map[string]string{})

// Inject sidecar agent
Sidecar(jaeger, dep)

// Assert that the agent is injected.
assert.Len(t, dep.Spec.Template.Spec.Containers, 2)
assert.Contains(t, dep.Spec.Template.Spec.Containers[1].Image, "jaeger-agent")

// Check resource values for the injected sidecar.
CPULimit, _ := resource.ParseQuantity("1024m")
MemLimit, _ := resource.ParseQuantity("100Mi")
assert.Equal(t, dep.Spec.Template.Spec.Containers[1].Resources.Limits[corev1.ResourceLimitsCPU], CPULimit)
assert.Equal(t, dep.Spec.Template.Spec.Containers[1].Resources.Limits[corev1.ResourceLimitsMemory], MemLimit)
}

func TestAgentResouceDefsParseErr(t *testing.T) {
jaeger := v1.NewJaeger("TestAgentResouceDefsOverride")
dep := dep(map[string]string{Annotation: jaeger.Name, "jaeger-agent-max-cpu": "1024m0", "jaeger-agent-max-memory": "100MiB"}, map[string]string{})

// Inject sidecar agent
Sidecar(jaeger, dep)

// Assert that the agent is injected.
assert.Len(t, dep.Spec.Template.Spec.Containers, 2)
assert.Contains(t, dep.Spec.Template.Spec.Containers[1].Image, "jaeger-agent")

// Check resource values for the injected sidecar.
CPULimit, _ := resource.ParseQuantity("500m")
MemLimit, _ := resource.ParseQuantity("128Mi")
assert.Equal(t, dep.Spec.Template.Spec.Containers[1].Resources.Limits[corev1.ResourceLimitsCPU], CPULimit)
assert.Equal(t, dep.Spec.Template.Spec.Containers[1].Resources.Limits[corev1.ResourceLimitsMemory], MemLimit)
}

func TestSidecarOrderOfArguments(t *testing.T) {
jaeger := v1.NewJaeger("TestQueryOrderOfArguments")
jaeger.Spec.Agent.Options = v1.NewOptions(map[string]interface{}{
Expand Down Expand Up @@ -260,7 +315,7 @@ func dep(annotations map[string]string, labels map[string]string) *appsv1.Deploy
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{
corev1.Container{},
{},
},
},
},
Expand Down