Skip to content

Commit 90114ed

Browse files
akuitybotkrancour
andauthored
chore(backport release-1.4): feat: allow specifying a token for job metric logs access + docs (#3779)
Co-authored-by: Kent Rancourt <[email protected]>
1 parent ad14485 commit 90114ed

File tree

6 files changed

+77
-1
lines changed

6 files changed

+77
-1
lines changed

charts/kargo/README.md

+2
Original file line numberDiff line numberDiff line change
@@ -137,6 +137,8 @@ the Kargo controller is running.
137137
| `api.rollouts.integrationEnabled` | Specifies whether Argo Rollouts integration is enabled. When not enabled, the API server will not be capable of creating/updating/applying AnalysesTemplate resources in the Kargo control plane. When enabled, the API server will perform a sanity check at startup. If Argo Rollouts CRDs are not found, the API server will proceed as if this integration had been explicitly disabled. Explicitly disabling is still preferable if this integration is not desired, as it will grant fewer permissions to the API server. | `true` |
138138
| `api.rollouts.logs.enabled` | Specifies whether support for streaming logs from AnalysisRuns using a JobMetric provider is enabled. This feature requires you to have forwarded and stored the logs yourself in a place where they can be retrieved with an HTTP GET. | `false` |
139139
| `api.rollouts.logs.urlTemplate` | Instructs Kargo on how to construct a URL for the retrieval of relevant logs via HTTP GET. Expressions offset by ${{ }} are supported with the following variables pre-defined and injected with values: project, namespace (the Project namespace), stage, analysisRun (its name), metricName (name of the JobMetric), jobNamespace (namespace of the Job; may be different that the Project namespace as the Job may actually execute in a different cluster), jobName, container (since a Pod associated with a Job could have more than one). Example: "https://logs.kargo.example.com/${{project}}/${{analysisRun}}/${{job}}/${{container}}". | `""` |
140+
| `api.rollouts.logs.tokenSecret.name` | specifies the name of a Kubernetes Secret managed "out of band" that contains a token usable for accessing job metric logs. | `nil` |
141+
| `api.rollouts.logs.tokenSecret.key` | specifies the key in a Kubernetes Secret (named by name) that is managed "out of band" and contains a token usable for accessing job metric logs. | `nil` |
140142
| `api.rollouts.logs.httpHeaders` | Specifies HTTP headers to include in the HTTP GET request for log retrieval. These are typically used for authentication. The header values support expressions offset by ${{ }}, with the same variables documented for urlTemplate pre-defined and injected with values. | `{}` |
141143

142144
### Controller

charts/kargo/templates/api/deployment.yaml

+7
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,13 @@ spec:
7575
{{- with (concat .Values.global.env .Values.api.env) }}
7676
{{- toYaml . | nindent 10 }}
7777
{{- end }}
78+
{{- if and .Values.api.rollouts.integrationEnabled .Values.api.rollouts.logs.enabled .Values.api.rollouts.logs.tokenSecret.name .Values.api.rollouts.logs.tokenSecret.key }}
79+
- name: ANALYSIS_RUN_LOG_TOKEN
80+
valueFrom:
81+
secretKeyRef:
82+
name: {{ .Values.api.rollouts.logs.tokenSecret.name }}
83+
key: {{ .Values.api.rollouts.logs.tokenSecret.key }}
84+
{{- end }}
7885
envFrom:
7986
- configMapRef:
8087
name: kargo-api

charts/kargo/values.yaml

+5
Original file line numberDiff line numberDiff line change
@@ -357,6 +357,11 @@ api:
357357
enabled: false
358358
## @param api.rollouts.logs.urlTemplate Instructs Kargo on how to construct a URL for the retrieval of relevant logs via HTTP GET. Expressions offset by ${{ }} are supported with the following variables pre-defined and injected with values: project, namespace (the Project namespace), stage, analysisRun (its name), metricName (name of the JobMetric), jobNamespace (namespace of the Job; may be different that the Project namespace as the Job may actually execute in a different cluster), jobName, container (since a Pod associated with a Job could have more than one). Example: "https://logs.kargo.example.com/${{project}}/${{analysisRun}}/${{job}}/${{container}}".
359359
urlTemplate: ""
360+
tokenSecret:
361+
## @param api.rollouts.logs.tokenSecret.name specifies the name of a Kubernetes Secret managed "out of band" that contains a token usable for accessing job metric logs.
362+
name:
363+
## @param api.rollouts.logs.tokenSecret.key specifies the key in a Kubernetes Secret (named by name) that is managed "out of band" and contains a token usable for accessing job metric logs.
364+
key:
360365
## @param api.rollouts.logs.httpHeaders Specifies HTTP headers to include in the HTTP GET request for log retrieval. These are typically used for authentication. The header values support expressions offset by ${{ }}, with the same variables documented for urlTemplate pre-defined and injected with values.
361366
httpHeaders: {}
362367

docs/docs/40-operator-guide/20-advanced-installation/30-common-configurations.md

+58
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,64 @@ is preferred if this integration is not desired, as it will grant fewer
349349
permissions to the controller.
350350
:::
351351

352+
### Logs from Job Metrics
353+
354+
For those utilizing Argo Rollouts integration for verifications,
355+
[job metrics](https://argoproj.github.io/argo-rollouts/analysis/job/) stand out
356+
as an especially useful feature because they are implemented as Kubernetes
357+
[`Job`s](https://kubernetes.io/docs/concepts/workloads/controllers/job/), which
358+
give users the flexibility to define any arbitrary post-promotion tests they'd
359+
like to run against a `Stage` by simply providing appropriate `Job` specs
360+
[as described here](../../50-user-guide/20-how-to-guides/60-verification.md#configuring-analysistemplates).
361+
In cases such as these, access to logs produced by the `Job`'s underlying `Pod`
362+
is helpful for debugging purposes and for understanding results.
363+
364+
Since it's common for multiple Kargo controllers to be deployed to many
365+
different clusters, such logs need to be aggregated in a centralized location
366+
for the API server to access them and, in-turn, stream them to the Kargo UI or
367+
CLI. Rather than build support for many different logging stacks, Kargo has
368+
settled on a "lowest common denominator" approach: The API server can stream
369+
any logs that it can access via an HTTP GET request.
370+
371+
To facilitate this, operators may, at the time of installation, provide a URL
372+
template that the API server can use to construct the URL for any job metric logs
373+
as a function of attributes such as `Project` name, `Stage` name, `AnalysisRun`
374+
name, and more.
375+
376+
A token can be specified by referencing a Kubernetes `Secret` that is managed
377+
"out of band." HTTP headers may also be specified, and may reference the token
378+
if one is provided.
379+
380+
Example:
381+
382+
```yaml
383+
api:
384+
rollouts:
385+
integrationEnabled: true
386+
logs:
387+
enabled: true
388+
urlTemplate: https://logs.kargo.example.com/${{project}}/${{analysisRun}}/${{job}}/${{container}}
389+
tokenSecret:
390+
name: kargo-logs-token
391+
key: token
392+
httpHeaders:
393+
Authentication: "Bearer ${{ token }}"
394+
```
395+
396+
:::note
397+
This "lowest common denominator" approach to streaming job metric logs does
398+
leave it as an exercise for the Kargo administrator to arrange for the
399+
forwarding and storage of applicable logs.
400+
401+
Users of Kargo via the [Akuity Platform](https://akuity.io/akuity-platform),
402+
however, will have this seamlessly handled for them.
403+
:::
404+
405+
:::note
406+
For more information, refer to the
407+
[chart documentation](https://github.com/akuity/kargo/blob/main/charts/kargo/README.md).
408+
:::
409+
352410
## Resource Management
353411

354412
### Tuning Concurrent Reconciliation Limits

internal/server/config/config.go

+2
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ type ServerConfig struct {
2929
PermissiveCORSPolicyEnabled bool
3030
RolloutsIntegrationEnabled bool
3131
AnalysisRunLogURLTemplate string
32+
AnalysisRunLogToken string
3233
AnalysisRunLogHTTPHeaders map[string]string
3334
}
3435

@@ -59,6 +60,7 @@ func ServerConfigFromEnv() ServerConfig {
5960
types.MustParseBool(os.GetEnv("ROLLOUTS_INTEGRATION_ENABLED", "true"))
6061
if cfg.RolloutsIntegrationEnabled {
6162
cfg.AnalysisRunLogURLTemplate = os.GetEnv("ANALYSIS_RUN_LOG_URL_TEMPLATE", "")
63+
cfg.AnalysisRunLogToken = os.GetEnv("ANALYSIS_RUN_LOG_TOKEN", "")
6264
if headersStr := os.GetEnv("ANALYSIS_RUN_LOG_HTTP_HEADERS", ""); headersStr != "" {
6365
kvPairs := strings.Split(headersStr, ",")
6466
cfg.AnalysisRunLogHTTPHeaders = make(map[string]string, len(kvPairs))

internal/server/get_analysisrun_logs_v1alpha1.go

+3-1
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,9 @@ func (s *server) buildRequest(
413413
if err != nil {
414414
return nil, fmt.Errorf("error creating GET request for log url %s: %w", url, err)
415415
}
416-
if userInfo, ok := user.InfoFromContext(ctx); ok {
416+
if s.cfg.AnalysisRunLogToken != "" {
417+
env["token"] = s.cfg.AnalysisRunLogToken
418+
} else if userInfo, ok := user.InfoFromContext(ctx); ok {
417419
env["token"] = userInfo.BearerToken
418420
}
419421
for key, valTemplate := range s.cfg.AnalysisRunLogHTTPHeaders {

0 commit comments

Comments
 (0)