From 7ebf224238cffadbe1bdea8eb82fce9310ac541b Mon Sep 17 00:00:00 2001 From: Craig Peterson <192540+captncraig@users.noreply.github.com> Date: Thu, 14 Sep 2023 17:55:59 -0400 Subject: [PATCH] New components remote.kubernetes.secret and remote.kubernetes.configmap (#4854) * initial work * move to subdir * cleanup * add docs * add all files * lint * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> * switch to correct package after river move * changelog * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Mischa Thompson * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Mischa Thompson * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Mischa Thompson * Update component/remote/kubernetes/kubernetes.go Co-authored-by: Mischa Thompson * Update docs/sources/flow/reference/components/remote.kubernetes.configmap.md Co-authored-by: Mischa Thompson * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Mischa Thompson * Update component/remote/kubernetes/kubernetes.go Co-authored-by: Mischa Thompson * Update docs/sources/flow/reference/components/remote.kubernetes.secret.md Co-authored-by: Mischa Thompson * add test, make timeout optional, and enforced * require positive timeout * newline --------- Co-authored-by: Clayton Cornell <131809008+clayton-cornell@users.noreply.github.com> Co-authored-by: Mischa Thompson --- CHANGELOG.md | 2 + component/all/all.go | 2 + .../remote/kubernetes/configmap/configmap.go | 17 ++ component/remote/kubernetes/kubernetes.go | 251 ++++++++++++++++++ .../remote/kubernetes/kubernetes_test.go | 43 +++ component/remote/kubernetes/secret/secret.go | 17 ++ .../components/remote.kubernetes.configmap.md | 155 +++++++++++ .../components/remote.kubernetes.secret.md | 166 ++++++++++++ 8 files changed, 653 insertions(+) create mode 100644 component/remote/kubernetes/configmap/configmap.go create mode 100644 component/remote/kubernetes/kubernetes.go create mode 100644 component/remote/kubernetes/kubernetes_test.go create mode 100644 component/remote/kubernetes/secret/secret.go create mode 100644 docs/sources/flow/reference/components/remote.kubernetes.configmap.md create mode 100644 docs/sources/flow/reference/components/remote.kubernetes.secret.md diff --git a/CHANGELOG.md b/CHANGELOG.md index eec3d8fb1b11..e89ac0f11174 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -32,6 +32,8 @@ Main (unreleased) - `discovery.serverset` discovers Serversets stored in Zookeeper. (@thampiotr) - `discovery.scaleway` discovers scrape targets from Scaleway virtual instances and bare-metal machines. (@rfratto) + - `remote.kubernetes.configmap` loads a configmap's data for use in other components (@captncraig) + - `remote.kubernetes.secret` loads a secret's data for use in other components (@captncraig) - Flow: allow the HTTP server to be configured with TLS in the config file using the new `http` config block. (@rfratto) diff --git a/component/all/all.go b/component/all/all.go index 0b1a68446a96..2f068f5ca938 100644 --- a/component/all/all.go +++ b/component/all/all.go @@ -119,6 +119,8 @@ import ( _ "github.com/grafana/agent/component/pyroscope/scrape" // Import pyroscope.scrape _ "github.com/grafana/agent/component/pyroscope/write" // Import pyroscope.write _ "github.com/grafana/agent/component/remote/http" // Import remote.http + _ "github.com/grafana/agent/component/remote/kubernetes/configmap" // Import remote.kubernetes.configmap + _ "github.com/grafana/agent/component/remote/kubernetes/secret" // Import remote.kubernetes.secret _ "github.com/grafana/agent/component/remote/s3" // Import remote.s3 _ "github.com/grafana/agent/component/remote/vault" // Import remote.vault ) diff --git a/component/remote/kubernetes/configmap/configmap.go b/component/remote/kubernetes/configmap/configmap.go new file mode 100644 index 000000000000..2cef93b65ffe --- /dev/null +++ b/component/remote/kubernetes/configmap/configmap.go @@ -0,0 +1,17 @@ +package configmap + +import ( + "github.com/grafana/agent/component" + "github.com/grafana/agent/component/remote/kubernetes" +) + +func init() { + component.Register(component.Registration{ + Name: "remote.kubernetes.configmap", + Args: kubernetes.Arguments{}, + Exports: kubernetes.Exports{}, + Build: func(opts component.Options, args component.Arguments) (component.Component, error) { + return kubernetes.New(opts, args.(kubernetes.Arguments), kubernetes.TypeConfigMap) + }, + }) +} diff --git a/component/remote/kubernetes/kubernetes.go b/component/remote/kubernetes/kubernetes.go new file mode 100644 index 000000000000..26a42b187d04 --- /dev/null +++ b/component/remote/kubernetes/kubernetes.go @@ -0,0 +1,251 @@ +// Package kubernetes implements the logic for remote.kubernetes.secret and remote.kubernetes.configmap component. +package kubernetes + +import ( + "context" + "fmt" + "reflect" + "sync" + "time" + + "github.com/go-kit/log" + + "github.com/grafana/agent/component" + "github.com/grafana/agent/component/common/kubernetes" + "github.com/grafana/river/rivertypes" + + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + client_go "k8s.io/client-go/kubernetes" +) + +type ResourceType string + +const ( + TypeSecret ResourceType = "secret" + TypeConfigMap ResourceType = "configmap" +) + +// Arguments control the component. +type Arguments struct { + Namespace string `river:"namespace,attr"` + Name string `river:"name,attr"` + PollFrequency time.Duration `river:"poll_frequency,attr,optional"` + PollTimeout time.Duration `river:"poll_timeout,attr,optional"` + + // Client settings to connect to Kubernetes. + Client kubernetes.ClientArguments `river:"client,block,optional"` +} + +// DefaultArguments holds default settings for Arguments. +var DefaultArguments = Arguments{ + PollFrequency: 1 * time.Minute, + PollTimeout: 15 * time.Second, +} + +// SetToDefault implements river.Defaulter. +func (args *Arguments) SetToDefault() { + *args = DefaultArguments +} + +// Validate implements river.Validator. +func (args *Arguments) Validate() error { + if args.PollFrequency <= 0 { + return fmt.Errorf("poll_frequency must be greater than 0") + } + if args.PollTimeout <= 0 { + return fmt.Errorf("poll_timeout must not be greater than 0") + } + return nil +} + +// Exports holds settings exported by this component. +type Exports struct { + Data map[string]rivertypes.OptionalSecret `river:"data,attr"` +} + +// Component implements the remote.kubernetes.* component. +type Component struct { + log log.Logger + opts component.Options + + mut sync.Mutex + args Arguments + + client *client_go.Clientset + kind ResourceType + + lastPoll time.Time + lastExports Exports // Used for determining whether exports should be updated + + healthMut sync.RWMutex + health component.Health +} + +var ( + _ component.Component = (*Component)(nil) + _ component.HealthComponent = (*Component)(nil) +) + +// New returns a new, unstarted remote.kubernetes.* component. +func New(opts component.Options, args Arguments, rType ResourceType) (*Component, error) { + c := &Component{ + log: opts.Logger, + opts: opts, + + kind: rType, + health: component.Health{ + Health: component.HealthTypeUnknown, + Message: "component started", + UpdateTime: time.Now(), + }, + } + + if err := c.Update(args); err != nil { + return nil, err + } + return c, nil +} + +// Run starts the remote.kubernetes.* component. +func (c *Component) Run(ctx context.Context) error { + for { + select { + case <-ctx.Done(): + return nil + case <-time.After(c.nextPoll()): + c.poll() + } + } +} + +// nextPoll returns how long to wait to poll given the last time a +// poll occurred. nextPoll returns 0 if a poll should occur immediately. +func (c *Component) nextPoll() time.Duration { + c.mut.Lock() + defer c.mut.Unlock() + + nextPoll := c.lastPoll.Add(c.args.PollFrequency) + now := time.Now() + + if now.After(nextPoll) { + // Poll immediately; next poll period was in the past. + return 0 + } + return nextPoll.Sub(now) +} + +// poll performs a HTTP GET for the component's configured URL. c.mut must +// not be held when calling. After polling, the component's health is updated +// with the success or failure status. +func (c *Component) poll() { + err := c.pollError() + c.updatePollHealth(err) +} + +func (c *Component) updatePollHealth(err error) { + c.healthMut.Lock() + defer c.healthMut.Unlock() + + if err == nil { + c.health = component.Health{ + Health: component.HealthTypeHealthy, + Message: "got " + string(c.kind), + UpdateTime: time.Now(), + } + } else { + c.health = component.Health{ + Health: component.HealthTypeUnhealthy, + Message: fmt.Sprintf("polling failed: %s", err), + UpdateTime: time.Now(), + } + } +} + +// pollError is like poll but returns an error if one occurred. +func (c *Component) pollError() error { + c.mut.Lock() + defer c.mut.Unlock() + + c.lastPoll = time.Now() + + ctx, cancel := context.WithTimeout(context.Background(), c.args.PollTimeout) + defer cancel() + + data := map[string]rivertypes.OptionalSecret{} + if c.kind == TypeSecret { + secret, err := c.client.CoreV1().Secrets(c.args.Namespace).Get(ctx, c.args.Name, v1.GetOptions{}) + if err != nil { + return err + } + for k, v := range secret.Data { + data[k] = rivertypes.OptionalSecret{ + Value: string(v), + IsSecret: true, + } + } + } else if c.kind == TypeConfigMap { + cmap, err := c.client.CoreV1().ConfigMaps(c.args.Namespace).Get(ctx, c.args.Name, v1.GetOptions{}) + if err != nil { + return err + } + for k, v := range cmap.Data { + data[k] = rivertypes.OptionalSecret{ + Value: v, + IsSecret: false, + } + } + } + + newExports := Exports{ + Data: data, + } + + // Only send a state change event if the exports have changed from the + // previous poll. + if !reflect.DeepEqual(newExports.Data, c.lastExports.Data) { + c.opts.OnStateChange(newExports) + } + + c.lastExports = newExports + return nil +} + +// Update updates the remote.kubernetes.* component. After the update completes, a +// poll is forced. +func (c *Component) Update(args component.Arguments) (err error) { + // defer initial poll so the lock is released first + defer func() { + if err != nil { + return + } + // Poll after updating and propagate the error if the poll fails. If an error + // occurred during Update, we don't bother to do anything. + // It is important to set err and the health so startup works correctly + err = c.pollError() + c.updatePollHealth(err) + }() + + c.mut.Lock() + defer c.mut.Unlock() + + newArgs := args.(Arguments) + c.args = newArgs + + restConfig, err := c.args.Client.BuildRESTConfig(c.log) + if err != nil { + return err + } + c.client, err = client_go.NewForConfig(restConfig) + if err != nil { + return fmt.Errorf("creating kubernetes client: %w", err) + } + + return err +} + +// CurrentHealth returns the current health of the component. +func (c *Component) CurrentHealth() component.Health { + c.healthMut.RLock() + defer c.healthMut.RUnlock() + return c.health +} diff --git a/component/remote/kubernetes/kubernetes_test.go b/component/remote/kubernetes/kubernetes_test.go new file mode 100644 index 000000000000..2cf564fe129f --- /dev/null +++ b/component/remote/kubernetes/kubernetes_test.go @@ -0,0 +1,43 @@ +package kubernetes + +import ( + "testing" + "time" + + "github.com/grafana/river" + "github.com/stretchr/testify/require" + "gotest.tools/assert" +) + +func TestRiverUnmarshal(t *testing.T) { + riverCfg := ` + name = "foo" + namespace = "bar" + poll_frequency = "10m" + poll_timeout = "1s"` + + var args Arguments + err := river.Unmarshal([]byte(riverCfg), &args) + require.NoError(t, err) + + assert.Equal(t, 10*time.Minute, args.PollFrequency) + assert.Equal(t, time.Second, args.PollTimeout) + assert.Equal(t, "foo", args.Name) + assert.Equal(t, "bar", args.Namespace) +} +func TestValidate(t *testing.T) { + t.Run("0 Poll Freq", func(t *testing.T) { + args := Arguments{} + args.SetToDefault() + args.PollFrequency = 0 + err := args.Validate() + require.ErrorContains(t, err, "poll_frequency must be greater than 0") + }) + t.Run("negative Poll timeout", func(t *testing.T) { + args := Arguments{} + args.SetToDefault() + args.PollTimeout = 0 + err := args.Validate() + require.ErrorContains(t, err, "poll_timeout must not be greater than 0") + }) +} diff --git a/component/remote/kubernetes/secret/secret.go b/component/remote/kubernetes/secret/secret.go new file mode 100644 index 000000000000..6c89c58383d6 --- /dev/null +++ b/component/remote/kubernetes/secret/secret.go @@ -0,0 +1,17 @@ +package secret + +import ( + "github.com/grafana/agent/component" + "github.com/grafana/agent/component/remote/kubernetes" +) + +func init() { + component.Register(component.Registration{ + Name: "remote.kubernetes.secret", + Args: kubernetes.Arguments{}, + Exports: kubernetes.Exports{}, + Build: func(opts component.Options, args component.Arguments) (component.Component, error) { + return kubernetes.New(opts, args.(kubernetes.Arguments), kubernetes.TypeSecret) + }, + }) +} diff --git a/docs/sources/flow/reference/components/remote.kubernetes.configmap.md b/docs/sources/flow/reference/components/remote.kubernetes.configmap.md new file mode 100644 index 000000000000..9120832b3984 --- /dev/null +++ b/docs/sources/flow/reference/components/remote.kubernetes.configmap.md @@ -0,0 +1,155 @@ +--- +canonical: https://grafana.com/docs/agent/latest/flow/reference/components/remote.kubernetes.configmap/ +title: remote.kubernetes.configmap +--- + +# remote.kubernetes.configmap + +`remote.kubernetes.configmap` reads a ConfigMap from the Kubernetes API server and exposes its data for other components to consume. + +This can be useful anytime the agent needs data from a ConfigMap that is not directly mounted to the Grafana Agent pod. + +## Usage + +```river +remote.kubernetes.configmap "LABEL" { + namespace = "NAMESPACE_OF_CONFIGMAP" + name = "NAME_OF_CONFIGMAP" +} +``` + +## Arguments + +The following arguments are supported: + +Name | Type | Description | Default | Required +---- | ---- | ----------- | ------- | -------- +`namespace` | `string` | Kubernetes namespace containing the desired ConfigMap. | | yes +`name` | `string` | Name of the Kubernetes ConfigMap | | yes +`poll_frequency` | `duration` | Frequency to poll the Kubernetes API. | `"1m"` | no +`poll_timeout` | `duration` | Timeout when polling the Kubernetes API. | `"15s"` | no + +When this component performs a poll operation, it requests the ConfigMap data from the Kubernetes API. +A poll is triggered by the following: + +* When the component first loads. +* Every time the component's arguments get re-evaluated. +* At the frequency specified by the `poll_frequency` argument. + +Any error while polling will mark the component as unhealthy. After +a successful poll, all data is exported with the same field names as the source ConfigMap. + +## Blocks + +The following blocks are supported inside the definition of `remote.kubernetes.configmap`: + +Hierarchy | Block | Description | Required +--------- | ----- | ----------- | -------- +client | [client][] | Configures Kubernetes client used to find Probes. | no +client > basic_auth | [basic_auth][] | Configure basic authentication to the Kubernetes API. | no +client > authorization | [authorization][] | Configure generic authorization to the Kubernetes API. | no +client > oauth2 | [oauth2][] | Configure OAuth2 for authenticating to the Kubernetes API. | no +client > oauth2 > tls_config | [tls_config][] | Configure TLS settings for connecting to the Kubernetes API. | no +client > tls_config | [tls_config][] | Configure TLS settings for connecting to the Kubernetes API. | no + +The `>` symbol indicates deeper levels of nesting. For example, `client > basic_auth` +refers to a `basic_auth` block defined inside a `client` block. + +[client]: #client-block +[basic_auth]: #basic_auth-block +[authorization]: #authorization-block +[oauth2]: #oauth2-block +[tls_config]: #tls_config-block + +### client block + +The `client` block configures the Kubernetes client used to discover Probes. If the `client` block isn't provided, the default in-cluster +configuration with the service account of the running Grafana Agent pod is +used. + +The following arguments are supported: + +Name | Type | Description | Default | Required +---- | ---- | ----------- | ------- | -------- +`api_server` | `string` | URL of the Kubernetes API server. | | no +`kubeconfig_file` | `string` | Path of the `kubeconfig` file to use for connecting to Kubernetes. | | no +`bearer_token_file` | `string` | File containing a bearer token to authenticate with. | | no +`proxy_url` | `string` | HTTP proxy to proxy requests through. | | no +`follow_redirects` | `bool` | Whether redirects returned by the server should be followed. | `true` | no +`enable_http2` | `bool` | Whether HTTP2 is supported for requests. | `true` | no + + At most, one of the following can be provided: + - [`bearer_token` argument][client]. + - [`bearer_token_file` argument][client]. + - [`basic_auth` block][basic_auth]. + - [`authorization` block][authorization]. + - [`oauth2` block][oauth2]. + +### basic_auth block + +{{< docs/shared lookup="flow/reference/components/basic-auth-block.md" source="agent" >}} + +### authorization block + +{{< docs/shared lookup="flow/reference/components/authorization-block.md" source="agent" >}} + +### oauth2 block + +{{< docs/shared lookup="flow/reference/components/oauth2-block.md" source="agent" >}} + +### tls_config block + +{{< docs/shared lookup="flow/reference/components/tls-config-block.md" source="agent" >}} + + +## Exported fields + +The following fields are exported and can be referenced by other components: + +Name | Type | Description +---- | ---- | ----------- +`data` | `map(string)` | Data from the ConfigMap obtained from kubernetes. + +The `data` field contains a mapping from field names to values. + +## Component health + +Instances of `remote.kubernetes.configmap` report as healthy if the most recent attempt to poll the kubernetes API succeeds. + +## Debug information + +`remote.kubernetes.configmap` does not expose any component-specific debug information. + +### Debug metrics + +`remote.kubernetes.configmap` does not expose any component-specific debug metrics. + +## Example + +This example reads a Secret and a ConfigMap from Kubernetes and uses them to supply remote-write credentials. + +```river +remote.kubernetes.secret "credentials" { + namespace = "monitoring" + name = "metrics-secret" +} + +remote.kubernetes.configmap "endpoint" { + namespace = "monitoring" + name = "metrics-endpoint" +} + +prometheus.remote_write "default" { + endpoint { + url = remote.kubernetes.configmap.endpoint.data["url"] + basic_auth { + username = remote.kubernetes.configmap.endpoint.data["username"] + password = remote.kubernetes.secret.credentials.data["password"] + } + } +} +``` + +This example assumes that the Secret and ConfigMap have already been created, and that the appropriate field names +exist in their data. + diff --git a/docs/sources/flow/reference/components/remote.kubernetes.secret.md b/docs/sources/flow/reference/components/remote.kubernetes.secret.md new file mode 100644 index 000000000000..09defa406c2f --- /dev/null +++ b/docs/sources/flow/reference/components/remote.kubernetes.secret.md @@ -0,0 +1,166 @@ +--- +canonical: https://grafana.com/docs/agent/latest/flow/reference/components/remote.kubernetes.secret/ +title: remote.kubernetes.secret +--- + +# remote.kubernetes.secret + +`remote.kubernetes.secret` reads a Secret from the Kubernetes API server and exposes its data for other components to consume. + +A common use case for this is loading credentials or other information from secrets that are not already mounted into the agent pod at deployment time. + +## Usage + +```river +remote.kubernetes.secret "LABEL" { + namespace = "NAMESPACE_OF_SECRET" + name = "NAME_OF_SECRET" +} +``` + +## Arguments + +The following arguments are supported: + +Name | Type | Description | Default | Required +---- | ---- | ----------- | ------- | -------- +`namespace` | `string` | Kubernetes namespace containing the desired Secret. | | yes +`name` | `string` | Name of the Kubernetes Secret | | yes +`poll_frequency` | `duration` | Frequency to poll the Kubernetes API. | `"1m"` | no +`poll_timeout` | `duration` | Timeout when polling the Kubernetes API. | `"15s"` | no + +When this component performs a poll operation, it requests the Secret data from the Kubernetes API. +A poll is triggered by the following: + +* When the component first loads. +* Every time the component's arguments get re-evaluated. +* At the frequency specified by the `poll_frequency` argument. + +Any error while polling will mark the component as unhealthy. After +a successful poll, all data is exported with the same field names as the source Secret. + +## Blocks + +The following blocks are supported inside the definition of `remote.kubernetes.secret`: + +Hierarchy | Block | Description | Required +--------- | ----- | ----------- | -------- +client | [client][] | Configures Kubernetes client used to find Probes. | no +client > basic_auth | [basic_auth][] | Configure basic authentication to the Kubernetes API. | no +client > authorization | [authorization][] | Configure generic authorization to the Kubernetes API. | no +client > oauth2 | [oauth2][] | Configure OAuth2 for authenticating to the Kubernetes API. | no +client > oauth2 > tls_config | [tls_config][] | Configure TLS settings for connecting to the Kubernetes API. | no +client > tls_config | [tls_config][] | Configure TLS settings for connecting to the Kubernetes API. | no + +The `>` symbol indicates deeper levels of nesting. For example, `client > basic_auth` +refers to a `basic_auth` block defined inside a `client` block. + +[client]: #client-block +[basic_auth]: #basic_auth-block +[authorization]: #authorization-block +[oauth2]: #oauth2-block +[tls_config]: #tls_config-block + +### client block + +The `client` block configures the Kubernetes client used to discover Probes. If the `client` block isn't provided, the default in-cluster +configuration with the service account of the running Grafana Agent pod is +used. + +The following arguments are supported: + +Name | Type | Description | Default | Required +---- | ---- | ----------- | ------- | -------- +`api_server` | `string` | URL of the Kubernetes API server. | | no +`kubeconfig_file` | `string` | Path of the `kubeconfig` file to use for connecting to Kubernetes. | | no +`bearer_token_file` | `string` | File containing a bearer token to authenticate with. | | no +`proxy_url` | `string` | HTTP proxy to proxy requests through. | | no +`follow_redirects` | `bool` | Whether redirects returned by the server should be followed. | `true` | no +`enable_http2` | `bool` | Whether HTTP2 is supported for requests. | `true` | no + + At most, one of the following can be provided: + - [`bearer_token` argument][client]. + - [`bearer_token_file` argument][client]. + - [`basic_auth` block][basic_auth]. + - [`authorization` block][authorization]. + - [`oauth2` block][oauth2]. + +### basic_auth block + +{{< docs/shared lookup="flow/reference/components/basic-auth-block.md" source="agent" >}} + +### authorization block + +{{< docs/shared lookup="flow/reference/components/authorization-block.md" source="agent" >}} + +### oauth2 block + +{{< docs/shared lookup="flow/reference/components/oauth2-block.md" source="agent" >}} + +### tls_config block + +{{< docs/shared lookup="flow/reference/components/tls-config-block.md" source="agent" >}} + + +## Exported fields + +The following fields are exported and can be referenced by other components: + +Name | Type | Description +---- | ---- | ----------- +`data` | `map(secret)` | Data from the secret obtained from kubernetes. + +The `data` field contains a mapping from field names to values. + +If an individual key stored in `data` does not hold sensitive data, it can be +converted into a string using [the `nonsensitive` function][nonsensitive]: + +```river +nonsensitive(remote.kubernetes.secret.LABEL.data.KEY_NAME) +``` + +Using `nonsensitive` allows for using the exports of `remote.kubernetes.secret` for +attributes in components that do not support secrets. + +[nonsensitive]: {{< relref "../stdlib/nonsensitive.md" >}} + +## Component health + +Instances of `remote.kubernetes.secret` report as healthy if the most recent attempt to poll the kubernetes API succeeds. + +## Debug information + +`remote.kubernetes.secret` does not expose any component-specific debug information. + +### Debug metrics + +`remote.kubernetes.secret` does not expose any component-specific debug metrics. + +## Example + +This example reads a Secret and a ConfigMap from Kubernetes and uses them to supply remote-write credentials. + +```river +remote.kubernetes.secret "credentials" { + namespace = "monitoring" + name = "metrics-secret" +} + +remote.kubernetes.configmap "endpoint" { + namespace = "monitoring" + name = "metrics-endpoint" +} + +prometheus.remote_write "default" { + endpoint { + url = remote.kubernetes.configmap.endpoint.data["url"] + basic_auth { + username = remote.kubernetes.configmap.endpoint.data["username"] + password = remote.kubernetes.secret.credentials.data["password"] + } + } +} +``` + +This example assumes that the Secret and ConfigMap have already been created, and that the appropriate field names +exist in their data. \ No newline at end of file