Skip to content

SOC4Kafka Installation Guide - OCI Streaming to Splunk

This guide walks you through installing and configuring the Splunk OpenTelemetry Collector for Kafka (SOC4Kafka) on an OCI Ubuntu VM so that records published to an OCI Streaming stream are forwarded to Splunk via HTTP Event Collector (HEC).

It covers two deployment forms - pick the one that fits your environment:

  • Option A - Bare metal / systemd: the collector binary runs directly on the VM. No container runtime required. Good for a simple single-host setup.
  • Option B - Kubernetes: the collector runs as a Kubernetes pod via the official Helm chart. Good if you want pod-level isolation and rolling updates.

Before you start - values to have ready

Collect the following before touching the VM. Everything in this document is a <PLACEHOLDER> - substitute your real values as you go.

From OCI Console

What you need Where to find it Placeholder
Kafka bootstrap endpoint Streaming → Stream Pools → select pool → Kafka Connection Settings → Bootstrap Servers <KAFKA_BOOTSTRAP>
Kafka SASL username Same page → Username (fully formed, ready to copy) <SASL_USERNAME>
OCI auth token (SASL password) Profile → User Settings → Auth Tokens → Generate Token - copy immediately, shown once <OCI_AUTH_TOKEN>
Stream / topic name Streaming → Streams <TOPIC>

Info

Handling special characters: the OCI auth token may contain characters like &, |, >, `, or ! - no need to regenerate the token if it does. Just make sure to keep the single quotes shown around KAFKA_SASL_PASS and --from-literal=... below when you set it: without them, the shell interprets those characters itself and can silently truncate or empty out the value before it ever reaches the collector.

From Splunk

What you need Where to find it Placeholder
HEC endpoint URL Settings → Data inputs → HTTP Event Collector → host + port 8088, path /services/collector <SPLUNK_HEC_ENDPOINT>
HEC token Settings → Data inputs → HTTP Event Collector → token’s Token Value <SPLUNK_HEC_TOKEN>
Target index Settings → Indexes <SPLUNK_INDEX>

Info

HEC prerequisites: before installing the collector, make sure HEC is globally enabled (Global Settings → Enabled) and that Indexer Acknowledgement is OFF - SOC4Kafka does not implement HEC ACK and the connection will stall if it is on.

Choose a consumer group name

Pick a short, unique string for <CONSUMER_GROUP> (e.g. soc4kafka-v1). This name identifies your collector instance to the Kafka broker. Use a fresh name - reusing a group ID from a previous failed install can cause the collector to loop indefinitely on startup.


Option A - Bare metal / systemd

All commands run on the OCI VM over SSH.

A.1 Install dependencies

These packages are used for connectivity testing and producing test messages. They are not required for the collector itself to run.

sudo apt-get update
sudo apt-get install -y kafkacat curl netcat-openbsd

A.2 Download the collector binary

SOC4Kafka releases are published on GitHub. Download the binary for your target version, make it executable, and place it in a working directory.

mkdir -p ~/soc4kafka && cd ~/soc4kafka
wget https://github.com/signalfx/splunk-otel-collector/releases/download/v0.158.0/otelcol_linux_amd64
chmod +x otelcol_linux_amd64

Note

Check the releases page for newer versions and substitute v0.158.0 accordingly.

A.3 Create the secrets file

Create ~/soc4kafka/collector.env and restrict its permissions. This file holds all secrets so they never appear in the config file or in process arguments.

cat > ~/soc4kafka/collector.env <<'EOF'
KAFKA_BOOTSTRAP=<KAFKA_BOOTSTRAP>
KAFKA_SASL_USER=<SASL_USERNAME>
KAFKA_SASL_PASS='<OCI_AUTH_TOKEN>'
SPLUNK_HEC_URL=<SPLUNK_HEC_ENDPOINT>
SPLUNK_HEC_TOKEN=<SPLUNK_HEC_TOKEN>
SPLUNK_INDEX=<SPLUNK_INDEX>
EOF
chmod 600 ~/soc4kafka/collector.env

Note

Wrap KAFKA_SASL_PASS in single quotes so the shell does not expand special characters in the token value.

A.4 Create the collector config

Create ~/soc4kafka/config.yaml with the content below. Substitute <CONSUMER_GROUP> and <TOPIC> directly in the file - these are not secrets and do not need to be in the env file.

receivers:
  kafka:
    brokers:
      - ${env:KAFKA_BOOTSTRAP}
    group_id: <CONSUMER_GROUP>
    client_id: <CONSUMER_GROUP>
    group_rebalance_strategy: range
    initial_offset: earliest
    tls:
      insecure_skip_verify: false
    auth:
      sasl:
        username: ${env:KAFKA_SASL_USER}
        password: ${env:KAFKA_SASL_PASS}
        mechanism: PLAIN
    logs:
      topics:
        - <TOPIC>
      encoding: text

processors:
  resourcedetection:
    detectors: [system]
    system:
      hostname_sources: ["os"]

exporters:
  splunk_hec:
    token: ${env:SPLUNK_HEC_TOKEN}
    endpoint: ${env:SPLUNK_HEC_URL}
    source: oci-streaming
    sourcetype: oci:streaming:text
    index: ${env:SPLUNK_INDEX}
    tls:
      insecure_skip_verify: true
    splunk_app_name: soc4kafka

service:
  pipelines:
    logs:
      receivers: [kafka]
      processors: [resourcedetection]
      exporters: [splunk_hec]

A.5 Verify connectivity before starting the collector

Check that the VM can reach Splunk HEC:

nc -vz <SPLUNK_HEC_HOST> 8088

Check that the VM can reach the Kafka broker and authenticate (this is the single best end-to-end connectivity test - success means DNS, routing, TLS, and SASL all work):

set -a; source ~/soc4kafka/collector.env; set +a
kafkacat -L \
  -b "$KAFKA_BOOTSTRAP" \
  -X security.protocol=SASL_SSL \
  -X sasl.mechanisms=PLAIN \
  -X sasl.username="$KAFKA_SASL_USER" \
  -X sasl.password="$KAFKA_SASL_PASS" | head -20

You should see <TOPIC> listed in the output. If it times out or returns an auth error, resolve that before proceeding - the collector will exhibit the same failure.

A.6 Start the collector

Run in the foreground first to watch the startup logs:

cd ~/soc4kafka
set -a; source ./collector.env; set +a
./otelcol_linux_amd64 --config config.yaml

A healthy startup looks like:

Everything is ready. Begin running and processing data.
...joined, balancing group   group: <CONSUMER_GROUP>
...synced                    assigned: <TOPIC>[0]
...beginning heartbeat loop

If you see NOT_COORDINATOR repeating, stop the collector, change group_id and client_id to a new name in config.yaml, and restart.

A.7 Install as a systemd service

Once the collector starts cleanly, promote it to a managed service so it restarts automatically and its logs are captured by journald.

Copy files into place:

sudo mkdir -p /opt/soc4kafka /etc/soc4kafka
sudo cp ~/soc4kafka/otelcol_linux_amd64 /opt/soc4kafka/
sudo cp ~/soc4kafka/config.yaml /opt/soc4kafka/
sudo cp ~/soc4kafka/collector.env /etc/soc4kafka/collector.env
sudo chmod 600 /etc/soc4kafka/collector.env

Create the service user and set ownership:

sudo useradd --system --no-create-home --shell /usr/sbin/nologin otel
sudo chown otel:otel /opt/soc4kafka/otelcol_linux_amd64
sudo chown otel:otel /opt/soc4kafka/config.yaml
sudo chown otel:otel /etc/soc4kafka/collector.env

Create the unit file:

sudo tee /etc/systemd/system/soc4kafka.service > /dev/null <<'EOF'
[Unit]
Description=SOC4Kafka collector (OCI Streaming -> Splunk)
After=network-online.target
Wants=network-online.target

[Service]
User=otel
Group=otel
EnvironmentFile=/etc/soc4kafka/collector.env
ExecStart=/opt/soc4kafka/otelcol_linux_amd64 --config /opt/soc4kafka/config.yaml
Restart=on-failure
RestartSec=5s

[Install]
WantedBy=multi-user.target
EOF

Enable and start:

sudo systemctl daemon-reload
sudo systemctl enable --now soc4kafka
sudo journalctl -u soc4kafka -f

A.8 Send a test message and confirm in Splunk

set -a; source ~/soc4kafka/collector.env; set +a
printf '{"hello":"splunk","ts":"%s"}\n' "$(date -u +%FT%TZ)" | \
  kafkacat -P \
    -b "$KAFKA_BOOTSTRAP" \
    -t <TOPIC> \
    -X security.protocol=SASL_SSL \
    -X sasl.mechanisms=PLAIN \
    -X sasl.username="$KAFKA_SASL_USER" \
    -X sasl.password="$KAFKA_SASL_PASS"

In Splunk search:

index=<SPLUNK_INDEX> sourcetype=oci:streaming:text

You can also monitor collector throughput from the VM:

curl -s http://127.0.0.1:8888/metrics | grep -E 'otelcol_(receiver_accepted|exporter_sent)'

receiver_accepted_log_records_total should increment when you produce; exporter_sent_log_records_total should follow shortly after as the batch flushes.


Option B - Kubernetes

All commands run on the OCI VM over SSH.

Info

Kubernetes distribution note: this guide uses MicroK8s as a representative example of a single-node Kubernetes setup. The SOC4Kafka Helm chart is distribution-agnostic and will run on any conformant Kubernetes cluster (EKS, GKE, AKS, K3s, vanilla kubeadm, etc.). If you are using a different distribution, substitute your cluster’s kubectl and helm commands for the microk8s kubectl and microk8s helm3 equivalents used below. The DNS configuration (step B.1), firewall fix (step B.2), and the OCI-specific CIDRs in the step B.2 callout are specific to MicroK8s on an OCI Ubuntu VM and will differ on other distributions or cloud providers.

MicroK8s ships its own bundled helm3 and kubectl. The commands below use microk8s helm3 and microk8s kubectl - not the system-level tools.

B.1 Install MicroK8s

sudo snap install microk8s --classic --channel=1.33/stable
sudo usermod -a -G microk8s "$USER"
sudo chown -f -R "$USER" ~/.kube
newgrp microk8s

Enable the addons the chart needs:

microk8s enable hostpath-storage
microk8s enable rbac
microk8s enable metrics-server

Enable DNS pinned to the OCI VCN resolver. This resolver handles both private OCI names (your broker’s private endpoint) and public names (your Splunk HEC host) - using it as the single upstream is important:

microk8s enable dns:169.254.169.254

Warning

Do not add a public resolver like 8.8.8.8 alongside it. The OCI Streaming broker resolves to a private VCN IP, and a public resolver will return NXDOMAIN for it, causing intermittent connection failures.

B.2 Fix the OCI host firewall

The OCI Ubuntu image ships a firewall rule that blocks forwarded traffic. This prevents pods from reaching the Kubernetes API server, causing CoreDNS and Calico to crash-loop. Remove the rule:

sudo iptables -L FORWARD -n --line-numbers | head
sudo iptables -D FORWARD 1    # removes the REJECT rule (usually at position 1)

Pods recover within about 60 seconds. Make the fix permanent - the rule returns on reboot otherwise:

# Edit the persisted ruleset and remove the REJECT line, then reload:
sudo grep -nE 'REJECT|icmp-host-prohibited' /etc/iptables/rules.v4
# Delete the matching line from the file, then:
sudo netfilter-persistent reload

On a test VM you can instead disable the OS firewall entirely - the OCI VCN security list still controls ingress at the cloud layer:

sudo systemctl disable --now netfilter-persistent

Warning

If Calico still crash-loops after removing the FORWARD rule, your image also has an INPUT-chain REJECT that blocks pod traffic to the Kubernetes API server VIP (10.152.183.1) and pod CIDR (10.1.0.0/16). These are standard MicroK8s defaults. Allow them:

sudo iptables -I INPUT 4 -s 10.152.183.0/24 -j ACCEPT

sudo iptables -I INPUT 4 -d 10.152.183.0/24 -j ACCEPT

sudo iptables -I INPUT 4 -s 10.1.0.0/16 -j ACCEPT

sudo iptables -I INPUT 4 -d 10.1.0.0/16 -j ACCEPT

The -I INPUT 4 inserts before the catch-all REJECT. Confirm position with sudo iptables -L INPUT -n --line-numbers first. If you customised MicroK8s CIDRs, replace the ranges with your actual service CIDR (grep service-cluster-ip-range /var/snap/microk8s/current/args/*) and pod CIDR (grep cluster-cidr /var/snap/microk8s/current/args/*).

B.3 Create the namespace

microk8s kubectl create namespace soc4kafka

B.4 Create the Kubernetes secrets

The collector reads credentials from Kubernetes Secrets injected as environment variables - they never appear in the Helm values file.

# Kafka SASL password - the key name "password" is required by the chart
microk8s kubectl -n soc4kafka create secret generic kafka-sasl \
  --from-literal=password='<OCI_AUTH_TOKEN>'

# Splunk HEC token - the key name "splunk-hec-token" is required by the chart
microk8s kubectl -n soc4kafka create secret generic splunk-hec \
  --from-literal=splunk-hec-token='<SPLUNK_HEC_TOKEN>'

Warning

Wrap values in single quotes to prevent the shell from interpreting special characters.

B.5 Create values.yaml

Create this file on the VM (e.g. at ~/soc4kafka_microk8s/values.yaml) before running the Helm install. Substitute all <PLACEHOLDERS> with your real values.

replicaCount: 1

kafkaReceivers:
  - name: main
    brokers:
      - <KAFKA_BOOTSTRAP>
    client_id: <CONSUMER_GROUP>       # e.g. soc4kafka-m8k-v1 - must be fresh
    group_id: <CONSUMER_GROUP>
    group_rebalance_strategy: range
    initial_offset: earliest
    logs:
      topics:
        - <TOPIC>
      encoding: text
    auth:
      sasl:
        username: <SASL_USERNAME>
        mechanism: PLAIN
        secret: kafka-sasl            # references the Secret created in step B.4
    tls:
      insecure_skip_verify: false     # OCI broker cert is publicly trusted (DigiCert)

splunkExporters:
  - name: primary
    endpoint: <SPLUNK_HEC_ENDPOINT>
    secret: splunk-hec                # references the Secret created in step B.4
    source: oci-streaming
    sourcetype: oci:streaming:text
    index: <SPLUNK_INDEX>
    splunk_app_name: soc4kafka
    tls:
      insecure_skip_verify: true      # Splunk default self-signed cert has no SAN

pipelines:
  - name: oci-to-splunk
    type: logs
    receivers: [main]
    exporters: [primary]
    processors: [resourcedetection]

extraEnv:
  - name: KAFKA_KAFKA_MAIN_SASL_PASSWORD
    valueFrom:
      secretKeyRef:
        name: kafka-sasl
        key: password

resources:
  limits:
    cpu: 500m
    memory: 512Mi
  requests:
    cpu: 100m
    memory: 256Mi

collectorLogs:
  enabled: false
collectorMetrics:
  enabled: false

B.6 Install the chart

microk8s helm3 repo add splunk-opentelemetry-collector-for-kafka \
  https://splunk.github.io/splunk-opentelemetry-collector-for-kafka
microk8s helm3 repo update

microk8s helm3 upgrade --install soc4kafka \
  splunk-opentelemetry-collector-for-kafka/splunk-opentelemetry-collector-for-kafka \
  -n soc4kafka \
  -f ~/soc4kafka_microk8s/values.yaml

Warning

Always include -n soc4kafka. Without it the release lands in the default namespace and will be difficult to find.

B.7 Verify the deployment

Check that all pods are running:

microk8s kubectl get pods -A

Tail the collector logs and look for the healthy startup sequence:

microk8s kubectl -n soc4kafka logs -f \
  deploy/soc4kafka-splunk-opentelemetry-collector-for-kafka

Expected output:

Everything is ready. Begin running and processing data.
franz   joined, balancing group   group: <CONSUMER_GROUP>
franz   synced                    assigned: <TOPIC>[0]
franz   assigning partitions      ...

Note

If you see NOT_COORDINATOR repeating, change client_id and group_id to a new name in values.yaml and re-run the helm3 upgrade command from step B.6.

B.8 Send a test message and confirm in Splunk

Produce a message from the VM (install kafkacat first if needed: sudo apt-get install -y kafkacat):

echo "hello-from-microk8s-$(date -Is)" | kafkacat -P \
  -b <KAFKA_BOOTSTRAP> \
  -t <TOPIC> \
  -X security.protocol=SASL_SSL \
  -X sasl.mechanisms=PLAIN \
  -X sasl.username='<SASL_USERNAME>' \
  -X sasl.password='<OCI_AUTH_TOKEN>' \
  -X ssl.ca.location=/etc/ssl/certs/ca-certificates.crt

Alternatively use the OCI Console: Streaming → Streams → select stream → Produce Test Message.

In Splunk search:

index=<SPLUNK_INDEX> sourcetype="oci:streaming:text" earliest=-5m