Skip to content

Commit 513b100

Browse files
authored
Merge pull request #6117 from apricote/tilt-prometheus
✨ Tilt: Add prometheus to observability deployment
2 parents 294917f + 34676f0 commit 513b100

File tree

7 files changed

+122
-16
lines changed

7 files changed

+122
-16
lines changed

Tiltfile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -336,6 +336,10 @@ def deploy_observability():
336336
k8s_yaml(read_file("./.tiltbuild/yaml/grafana.observability.yaml"), allow_duplicates = True)
337337
k8s_resource(workload = "grafana", port_forwards = "3001:3000", extra_pod_selectors = [{"app": "grafana"}], labels = ["observability"])
338338

339+
if "prometheus" in settings.get("deploy_observability", []):
340+
k8s_yaml(read_file("./.tiltbuild/yaml/prometheus.observability.yaml"), allow_duplicates = True)
341+
k8s_resource(workload = "prometheus-server", new_name = "prometheus", port_forwards = "9090", extra_pod_selectors = [{"app": "prometheus"}], labels = ["observability"])
342+
339343
def prepare_all():
340344
allow_k8s_arg = ""
341345
if settings.get("allowed_contexts"):

docs/book/src/developer/tilt.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ for more details.
7676
provider's yaml.
7777
7878
**deploy_observability** ([string], default=[]): If set, installs on the dev cluster one of more observability
79-
tools. Supported values are `grafana`, `loki` and/or `promtail` (Note: the UI for `grafana` will be accessible via a link in the tilt console).
79+
tools. Supported values are `grafana`, `loki`, `promtail` and/or `prometheus` (Note: the UI for `grafana` and `prometheus` will be accessible via a link in the tilt console).
8080
Important! This feature requires the `helm` command to be available in the user's path.
8181
8282
**debug** (Map{string: Map} default{}): A map of named configurations for the provider. The key is the name of the provider.

hack/observability/grafana/values.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,9 @@ datasources:
1818
- name: Loki
1919
type: loki
2020
url: http://loki:3100
21+
- name: Prometheus
22+
type: prometheus
23+
url: http://prometheus-server
2124

2225
# Disable grafana test framework
2326
testFramework:
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
resources:
2+
- ../namespace.yaml
3+
4+
helmCharts:
5+
- name: prometheus
6+
repo: https://prometheus-community.github.io/helm-charts
7+
releaseName: prometheus
8+
namespace: observability
9+
valuesFile: values.yaml
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Configuration for prometheus chart, see https://github.com/prometheus-community/helm-charts/tree/main/charts/prometheus
2+
3+
# These components do not make sense in a local dev environment
4+
# and can be disabled.
5+
alertmanager:
6+
enabled: false
7+
kubeStateMetrics:
8+
enabled: false
9+
nodeExporter:
10+
enabled: false
11+
pushgateway:
12+
enabled: false
13+
14+
# Scrape metrics from deployed providers
15+
extraScrapeConfigs: |
16+
- job_name: 'capi-providers'
17+
metrics_path: /metrics
18+
kubernetes_sd_configs:
19+
- role: pod
20+
21+
relabel_configs:
22+
- source_labels: [__meta_kubernetes_pod_labelpresent_cluster_x_k8s_io_provider]
23+
action: keep
24+
regex: true
25+
- source_labels: [__meta_kubernetes_pod_container_port_name]
26+
action: keep
27+
regex: metrics
28+
- source_labels: [__meta_kubernetes_pod_label_cluster_x_k8s_io_provider]
29+
action: replace
30+
target_label: provider
31+
- source_labels: [__meta_kubernetes_namespace]
32+
action: replace
33+
target_label: namespace
34+
- source_labels: [__meta_kubernetes_pod_name]
35+
action: replace
36+
target_label: pod

hack/observability/promtail/values.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# Configuration for grafana chart, see https://github.com/grafana/helm-charts/tree/main/charts/grafana
1+
# Configuration for promtail chart, see https://github.com/grafana/helm-charts/tree/main/charts/promtail
22

33
config:
44
# publish data to loki

hack/tools/tilt-prepare/main.go

Lines changed: 68 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ import (
3333
"github.com/spf13/pflag"
3434
"golang.org/x/net/context"
3535
appsv1 "k8s.io/api/apps/v1"
36+
corev1 "k8s.io/api/core/v1"
3637
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3738
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3839
kerrors "k8s.io/apimachinery/pkg/util/errors"
@@ -415,6 +416,11 @@ func providerTask(path, out string, debug bool) taskFunction {
415416
}
416417
}
417418

419+
if err := prepareDeploymentForObservability(prefix, objs); err != nil {
420+
errCh <- err
421+
return
422+
}
423+
418424
providerObj, err := getProviderObj(prefix, objs)
419425
if err != nil {
420426
errCh <- err
@@ -467,20 +473,12 @@ func writeIfChanged(prefix string, path string, yaml []byte) error {
467473
// prepareDeploymentForDebug alter controller deployments for working nicely with delve debugger;
468474
// most specifically, liveness and readiness probes are dropper and leader election turned off.
469475
func prepareDeploymentForDebug(prefix string, objs []unstructured.Unstructured) error {
470-
for i := range objs {
471-
obj := objs[i]
472-
if obj.GetKind() != "Deployment" {
473-
continue
474-
}
475-
476-
// Convert Unstructured into a typed object
477-
d := &appsv1.Deployment{}
478-
if err := scheme.Scheme.Convert(&obj, d, nil); err != nil {
479-
return errors.Wrapf(err, "[%s] failed to convert Deployment to typed object", prefix)
480-
}
481-
482-
for j := range d.Spec.Template.Spec.Containers {
483-
container := d.Spec.Template.Spec.Containers[j]
476+
return updateDeployment(prefix, objs, func(d *appsv1.Deployment) {
477+
for j, container := range d.Spec.Template.Spec.Containers {
478+
if container.Name != "manager" {
479+
// as defined in clusterctl Provider Contract "Controllers & Watching namespace"
480+
continue
481+
}
484482

485483
// Drop liveness and readiness probes.
486484
container.LivenessProbe = nil
@@ -498,7 +496,63 @@ func prepareDeploymentForDebug(prefix string, objs []unstructured.Unstructured)
498496

499497
d.Spec.Template.Spec.Containers[j] = container
500498
}
499+
})
500+
}
501+
502+
// prepareDeploymentForObservability alters controller deployments for working
503+
// nicely with prometheus metrics scraping. Specifically, the metrics endpoint is set to
504+
// listen on all interfaces instead of only localhost, and another port is added to the
505+
// container to expose the metrics endpoint.
506+
func prepareDeploymentForObservability(prefix string, objs []unstructured.Unstructured) error {
507+
return updateDeployment(prefix, objs, func(d *appsv1.Deployment) {
508+
for j, container := range d.Spec.Template.Spec.Containers {
509+
if container.Name != "manager" {
510+
// as defined in clusterctl Provider Contract "Controllers & Watching namespace"
511+
continue
512+
}
513+
514+
args := make([]string, 0, len(container.Args))
515+
for _, a := range container.Args {
516+
if strings.HasPrefix(a, "--metrics-bind-addr=") {
517+
args = append(args, "--metrics-bind-addr=0.0.0.0:8080")
518+
continue
519+
}
520+
args = append(args, a)
521+
}
522+
container.Args = args
523+
524+
container.Ports = append(container.Ports, corev1.ContainerPort{
525+
Name: "metrics",
526+
ContainerPort: 8080,
527+
Protocol: "TCP",
528+
})
529+
530+
d.Spec.Template.Spec.Containers[j] = container
531+
}
532+
})
533+
}
534+
535+
type updateDeploymentFunction func(deployment *appsv1.Deployment)
536+
537+
// updateDeployment passes all (typed) deployments to the updateDeploymentFunction
538+
// to modify as needed.
539+
func updateDeployment(prefix string, objs []unstructured.Unstructured, f updateDeploymentFunction) error {
540+
for i := range objs {
541+
obj := objs[i]
542+
if obj.GetKind() != "Deployment" {
543+
continue
544+
}
545+
546+
// Convert Unstructured into a typed object
547+
d := &appsv1.Deployment{}
548+
if err := scheme.Scheme.Convert(&obj, d, nil); err != nil {
549+
return errors.Wrapf(err, "[%s] failed to convert Deployment to typed object", prefix)
550+
}
551+
552+
// Call updater function
553+
f(d)
501554

555+
// Convert back to Unstructured
502556
if err := scheme.Scheme.Convert(d, &obj, nil); err != nil {
503557
return errors.Wrapf(err, "[%s] failed to convert Deployment to unstructured", prefix)
504558
}

0 commit comments

Comments
 (0)