# APM Agent Setup with Kubernetes

## Visual Guide

## Prerequisites

- Kubernetes 1.18 or later
- Helm 3.x installed and configured against your cluster
- A Kloudfuse API key with trace ingestion scope (see **Administration → API Keys**)
- Outbound HTTPS access from the cluster to the Kloudfuse platform
- At least one application instrumented with an OpenTelemetry SDK (see [Java](https://docs.kloudfuse.com/platform/4.1.0/data-collection/apm/instrument-java/), [Python](https://docs.kloudfuse.com/platform/4.1.0/data-collection/apm/instrument-python/), or [Go](https://docs.kloudfuse.com/platform/4.1.0/data-collection/apm/instrument-go/))

## Supported Environments

`kf-agent` runs on any conformant Kubernetes distribution:

| Platform | Notes |
| --- | --- |
| Amazon EKS | Supported; enable AWS resource detection with `resourceDetection.aws.enabled=true` |
| Google GKE | Supported; enable GCP resource detection with `resourceDetection.gcp.enabled=true` |
| Azure AKS | Supported; enable Azure resource detection with `resourceDetection.azure.enabled=true` |
| OpenShift | Supported; set `securityContext.runAsNonRoot=true` and configure an appropriate SCC |
| Self-managed (kubeadm, k3s, RKE) | Supported without additional configuration |

## Step 1: Install kf-agent

### Add the Helm Repository

```bash
helm repo add kloudfuse https://helm.kloudfuse.com
helm repo update
```

### Deploy the Agent

Install `kf-agent` into a dedicated namespace. Replace `<your-kloudfuse-api-key>` with your API key and `<my-cluster>` with a name that identifies this cluster in the Kloudfuse UI:

```bash
helm install kf-agent kloudfuse/kf-agent \
  --namespace kloudfuse \
  --create-namespace \
  --set clusterName=my-cluster \
  --set apiKey=<your-kloudfuse-api-key>
```

To avoid embedding the API key in shell history or CI logs, pass it from a Kubernetes Secret:

```bash
kubectl create secret generic kloudfuse-api-key \
  --namespace kloudfuse \
  --from-literal=value=<your-kloudfuse-api-key>

helm install kf-agent kloudfuse/kf-agent \
  --namespace kloudfuse \
  --create-namespace \
  --set clusterName=my-cluster \
  --set apiKeySecretName=kloudfuse-api-key
```

### Verify the Agent is Running

```bash
kubectl get pods -n kloudfuse -l app=kf-agent
kubectl logs -n kloudfuse -l app=kf-agent --tail=50
```

The agent is ready when the pod is in `Running` state and logs show `Listening on :4317 (gRPC)` and `Listening on :4318 (HTTP)`.

### Key Helm Values

| Value | Description | Default |
| --- | --- | --- |
| `clusterName` | Cluster identifier shown in Kloudfuse UI service maps and resource attributes. | `""` |
| `apiKey` | Kloudfuse API key for trace ingestion. Use `apiKeySecretName` instead in production. | `""` |
| `apiKeySecretName` | Name of a Kubernetes Secret containing the API key under the `value` key. | `""` |
| `replicaCount` | Number of agent replicas. Increase for high-throughput clusters. | `1` |
| `resources.requests.memory` | Minimum memory for the agent pod. | `256Mi` |
| `resources.limits.memory` | Maximum memory for the agent pod. | `512Mi` |
| `service.grpcPort` | Port for OTLP/gRPC receiver. | `4317` |
| `service.httpPort` | Port for OTLP/HTTP receiver. | `4318` |
| `resourceDetection.aws.enabled` | Auto-detect EC2, ECS, EKS resource attributes. | `false` |
| `resourceDetection.gcp.enabled` | Auto-detect GCE, GKE, Cloud Run resource attributes. | `false` |
| `resourceDetection.azure.enabled` | Auto-detect Azure VM and AKS resource attributes. | `false` |

## Network Requirements

Application pods must be able to reach `kf-agent` on two ports:

| Port | Protocol | Used by |
| --- | --- | --- |
| `4317` | OTLP/gRPC | Java agent, Go `otlptracegrpc`, Python gRPC exporter (default) |
| `4318` | OTLP/HTTP (protobuf or JSON) | Any SDK configured with `OTEL_EXPORTER_OTLP_PROTOCOL=http/protobuf` |

If your cluster enforces `NetworkPolicy`, add an egress rule allowing application pods to reach `kf-agent` on both ports:

```yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-kf-agent-egress
  namespace: <app-namespace>
spec:
  podSelector: {}
  policyTypes:
    - Egress
  egress:
    - to:
        - namespaceSelector:
            matchLabels:
              kubernetes.io/metadata.name: kloudfuse
      ports:
        - port: 4317
          protocol: TCP
        - port: 4318
          protocol: TCP
```

## Step 2: Instrument Your Applications

Set these two environment variables on every application pod to point it at `kf-agent`:

```bash
OTEL_SERVICE_NAME=my-service
OTEL_EXPORTER_OTLP_ENDPOINT=http://kf-agent:4317
```

The examples below show the minimal changes needed per language. See the linked setup guides for full configuration options.

### Java

Use `JAVA_TOOL_OPTIONS` to attach the OpenTelemetry Java agent without modifying the container entrypoint:

```yaml
env:
  - name: JAVA_TOOL_OPTIONS
    value: "-javaagent:/agent/opentelemetry-javaagent.jar"
  - name: OTEL_SERVICE_NAME
    value: my-java-service
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: http://kf-agent:4317
  - name: OTEL_RESOURCE_ATTRIBUTES
    value: service.namespace=payments,deployment.environment.name=production
```

### Python

Run your application through the `opentelemetry-instrument` wrapper and set the endpoint via environment variable:

```bash
opentelemetry-instrument \
  --traces_exporter otlp \
  --exporter_otlp_endpoint http://kf-agent:4317 \
  --service_name my-python-service \
  python app.py
```

Or configure entirely via environment variables in the pod spec:

```yaml
env:
  - name: OTEL_SERVICE_NAME
    value: my-python-service
  - name: OTEL_EXPORTER_OTLP_ENDPOINT
    value: http://kf-agent:4317
  - name: OTEL_TRACES_EXPORTER
    value: otlp
```

### Go

Configure the `otlptracegrpc` exporter to point at `kf-agent` on port `4317`:

```go
import "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"

exporter, err := otlptracegrpc.New(ctx,
    otlptracegrpc.WithEndpoint("kf-agent:4317"),
    otlptracegrpc.WithInsecure(),
)
```

Or read the endpoint from an environment variable so it can be set in the pod spec without changing code:

```bash
# Pod spec env
OTEL_SERVICE_NAME=my-go-service
OTEL_EXPORTER_OTLP_ENDPOINT=http://kf-agent:4317
```

```go
// Use otlptracegrpc.WithEndpointURL to read OTEL_EXPORTER_OTLP_ENDPOINT automatically
exporter, err := otlptracegrpc.New(ctx)
```

## Step 3: Verify Trace Collection

1. Open **Kloudfuse UI → APM → Trace Explorer**
2. In the search bar, filter by `service.name = <your-service-name>`
3. Send a test request to your application — a trace should appear within a few seconds
4. Click the trace to verify span names, attributes, and parent-child relationships
5. Open **APM → Service Map** to confirm inter-service dependencies are visible

If traces do not appear, see [Common Setup Issues](https://docs.kloudfuse.com/platform/4.1.0/data-collection/apm/instrument-common-issues/) for diagnostic steps.
