1.Create an ingest key and store it as a Secret
Create a key of type “Log ingest” under API Keys, then put it into the namespace the agent runs in.
kubectl create namespace logging
kubectl -n logging create secret generic uptimeeye-logs \
--from-literal=key=ue_ingest_XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX2.Install Vector as a DaemonSet
The Helm chart ships a kubernetes_logs source that already knows how to read container logs and join pod metadata. The remap step picks the fields you want to filter on; the sink talks the Elasticsearch bulk protocol, which UptimeEye accepts.
role: Agent
# Mount the Secret as files; Vector reads the key via its secret backend
# (it does not expand ${ENV} placeholders in the config).
extraVolumes:
- name: uptimeeye-logs
secret: { secretName: uptimeeye-logs }
extraVolumeMounts:
- name: uptimeeye-logs
mountPath: /etc/vector/secrets
readOnly: true
customConfig:
data_dir: /vector-data-dir
secret:
k8s:
type: directory
path: /etc/vector/secrets
sources:
k8s_logs:
type: kubernetes_logs
transforms:
enrich:
type: remap
inputs: [k8s_logs]
source: |
.service = .kubernetes.container_name
.namespace = .kubernetes.pod_namespace
.pod = .kubernetes.pod_name
.host = .kubernetes.pod_node_name
.env = "prod"
# Applications that log JSON: lift their fields to the top level.
parsed, err = parse_json(string!(.message))
if err == null { . = merge(., parsed) }
del(.kubernetes); del(.file); del(.source_type)
sinks:
uptimeeye:
type: elasticsearch
inputs: [enrich]
endpoints: ["https://logs.uptimeeye.com/v1/ingest/elasticsearch/"]
api_version: v8
compression: gzip
healthcheck: { enabled: false }
request:
headers:
Authorization: "Bearer SECRET[k8s.key]"
query:
_msg_field: message
_time_field: timestamp
_stream_fields: namespace,service,env
buffer: { type: disk, max_size: 268435488 }3.Deploy
helm repo add vector https://helm.vector.dev
helm upgrade --install vector vector/vector -n logging -f values.yaml
kubectl -n logging logs ds/vector --tail=20 # look for "Healthcheck disabled" and no 4xx4.Search
Within a few seconds every pod appears under its container name. Try namespace:=payments level:error or open the fields panel and click a value.
Fields you get
These show up in the fields panel and can be used in every filter:
service(container name)namespacepodhost(node)env- any JSON field your application logs
Tips
- Keep stream fields to a handful of low-cardinality values (
namespace,service,env).podchanges on every rollout — keep it as a normal field. - Exclude noisy namespaces with
extra_namespace_label_selectoror afiltertransform (.namespace != "kube-system"). - Fluent Bit alternative: use the
kubernetesfilter and thehttpoutput from the Fluent Bit guide withURI /v1/ingest/jsonline?_msg_field=log&_stream_fields=kubernetes.namespace_name,kubernetes.container_name. - OpenTelemetry alternative: the Collector's
filelogreceiver +k8sattributesprocessor, exporting withotlphttpto/v1/ingest/otlp/v1/logs.
FAQ
- Do I need to change my applications?
- No. The agent reads stdout/stderr. If your apps already log JSON, the
parse_jsonstep turns their keys into searchable fields; plain-text lines stay as the message. - How much does the agent cost in resources?
- Vector as a DaemonSet typically needs 30–80 MB memory and a few percent of one core per node. The disk buffer (256 MB in the example) keeps logs while UptimeEye is unreachable.
- Where do I get the ingest key?
- In the app under API Keys → New API Key → type “Log ingest”. The key starts with
ue_ingest_and is shown once. Management keys (ue_live_) are refused by the ingest endpoint. - How do I check that logs arrive?
- Open Logs in the app, pick the 15m range and search for
service:=<your service>. New lines are searchable within about a second; Live tail shows them with a ~6 s delay.