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

Annotate Pods for Prometheus Metrics Collection #1098

Merged
merged 6 commits into from
Oct 4, 2023

Conversation

teodor-yanev
Copy link
Contributor

@teodor-yanev teodor-yanev commented Oct 4, 2023

#1097

Overview:

Prometheus relies on annotations to discover which pods to scrape metrics from. This issue covers the addition of the necessary annotations to the relevant pods (for Mediator), enabling Prometheus to dynamically and accurately discover and scrape them.

Goals:

  1. Annotate the mediator pods to expose the metrics endpoint to Prometheus.
  2. Ensure that the annotations are correctly picked up by Prometheus for scraping.
  3. Maintain a standard scrape configuration that can be easily scaled and managed across different pods/services in the future.

Acceptance Criteria:

  1. After deployment, the mediator pods should have the appropriate prometheus.io annotations.
  2. Prometheus should start scraping metrics from the mediator pods based on the annotations.
  3. There should be visible metric data in Prometheus (and AMP, when integrated) related to the mediator pods.

@JAORMX
Copy link
Contributor

JAORMX commented Oct 4, 2023

Can you add more description to this PR and the commit itself? it's good to have this for historical purposes and context.

annotations:
prometheus.io/scrape: "true"
prometheus.io/port: "9090"
prometheus.io/path: '/metrics'
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's make these annotations configurable as follows:

      annotations:
        prometheus.io/scrape: "true"
        prometheus.io/port: "9090"
        prometheus.io/path: '/metrics'
        {{- with .Values.podAnnotations }}
        {{- toYaml . | nindent 8 }}
        {{- end }}

This way, operators may set extra annotations via podAnnotations in values.yaml

you should then set podAnnotations in values.yaml as {}

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was a great point, thanks. Done now.

@teodor-yanev
Copy link
Contributor Author

Can you add more description to this PR and the commit itself? it's good to have this for historical purposes and context.

Done (copied the issue description).

JAORMX
JAORMX previously requested changes Oct 4, 2023
@@ -28,6 +28,10 @@ spec:
metadata:
labels:
app: '{{ include "common.names.name" . }}'
annotations:
'{{- with .Values.podAnnotations }}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is the single quote needed? I wouldn't expect wrapping here and it seems to me like it would break the YAML.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The addition of the single quotes was a measure to ensure compatibility with 'ko', which tries to parse the raw Helm template as YAML before Helm processes it. Without the single quotes, 'ko' was throwing a parsing error.

The single quotes ensure that, from a YAML perspective, the Helm directives are treated as a simple string. When Helm processes this template, it replaces the single quotes and the inner directives with the intended values, resulting in valid, rendered YAML.
This serves as a safeguard against parsing issues with tools that try to read the raw Helm template. Once Helm processes the template, the resulting YAML is as expected without any single quotes.

I'm open to other suggestions 😄.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

make helm                                   
cd deployment/helm; rm -f templates/combined.yml && \
            ko resolve --platform=linux/amd64,linux/arm64 --base-import-paths --push=false -f templates/ > templates/combined.yml && \
                helm dependency update && \
                helm package --version="0.1.0" .
2023/10/04 15:25:25 Using base cgr.dev/chainguard/static:latest@sha256:ef5add7fd46cf1ce7d33d6de517833ac5c7e749db9b15249f9c472a772f3af27 for github.com/stacklok/mediator/cmd/server
2023/10/04 15:25:26 Building github.com/stacklok/mediator/cmd/server for linux/amd64
2023/10/04 15:25:26 Unexpected error running "go build": context canceled
2023/10/04 15:25:26 Building github.com/stacklok/mediator/cmd/server for linux/arm64
2023/10/04 15:25:26 Unexpected error running "go build": context canceled
Error: error processing import paths in "templates/deployment.yaml": yaml: line 31: did not find expected node content
make: *** [helm] Error 1

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

maaan! that's weird. @evankanderson is this expected? I would have thought that ko would use the rendered template instead.

Copy link
Member

@evankanderson evankanderson Oct 4, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ordering here is backwards -- we run ko before helm templating happens, because we want to do:

  1. Build container and replace package references in-line
  2. Package helm templates into an OCI image
  3. Replace helm parameters by ArgoCD on the cluster.

I'm surprised that helm is removing the single quotes (and not replacing them with the equivalent, like : | on the preceeding line). I'd expected:

....
    annotations:
      'prometheus.io/scrape: "true"
      prometheus.io/port: "9090"
      prometheus.io/path: "/metrics"'

What you want to do is the trick I did with labels above, and hide the template inside a comment on a single line.

I like having the resolved image associated with the helm chart so they are locked together, but I'm not thrilled with ko's insistence on valid YAML. I'd be open to another tool which did the build and substitution if there's an obvious one available.

BTW, for testing, what I've been doing is make helm build and then helm template mediator ./deployment/helm/mediator-*.tgz ...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note that helm template is entirely valid as a checking mechanism, because Argo is using that to get the set of objects to monitor in the cluster, and not actually running helm install or helm upgrade.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you both!

With the current setup, the yaml I get:

kind: Deployment
metadata:
  name: mediator
  labels:
    # This includes a newline, so ko sees this as valid yaml
    app.kubernetes.io/instance: mediator
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: mediator
    app.kubernetes.io/version: "2023-07-31"
    helm.sh/chart: mediator-0.1.0
spec:
  # We'll use autoscaling, sometimes clamped to one instance
  selector:
    matchLabels:
      app: 'mediator'
  template:
    metadata:
      labels:
        app: 'mediator'
      annotations:
        # This includes a newline, so ko sees this as valid yaml
        prometheus.io/scrape: "true"
        prometheus.io/port: "9090"
        prometheus.io/path: "/metrics"
    spec:
      serviceAccountName: mediator
      containers:
...

@evankanderson
Copy link
Member

Testing this with make helm && helm template mediator ./deployment/helm/mediator-0.1.0.tgz | grep -A 23 '^kind: Deployment', I get:

kind: Deployment
metadata:
  name: mediator
  labels:
  # This includes a newline, so ko sees this as valid yaml
  # 
    app.kubernetes.io/instance: mediator
    app.kubernetes.io/managed-by: Helm
    app.kubernetes.io/name: mediator
    app.kubernetes.io/version: "2023-07-31"
    helm.sh/chart: mediator-0.1.0
spec:
  # We'll use autoscaling, sometimes clamped to one instance
  selector:
    matchLabels:
      app: 'mediator'
  template:
    metadata:
      labels:
        app: 'mediator'
      annotations: '
        prometheus.io/path: /metrics
        prometheus.io/port: "9090"
        prometheus.io/scrape: "true"'

Try the comment trick and see if that helps.

evankanderson
evankanderson previously approved these changes Oct 4, 2023
Comment on lines 15 to 18
{{/*
Common annotations
*/}}
{{- define "common.annotations" -}}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit, but I'm not going to block submit: This is probably "pod annotations" or the like. We probably don't want these for other objects, like Services or Ingresses.

@evankanderson evankanderson dismissed JAORMX’s stale review October 4, 2023 19:53

Moved attributes to be configurable.

@teodor-yanev teodor-yanev merged commit f8a3532 into main Oct 4, 2023
12 checks passed
@teodor-yanev teodor-yanev deleted the 1097-annotate-pods-for-prometheus-metrics branch October 4, 2023 20:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants