Skip to content

Kubernetes Deployment

This guide covers deploying the ByteFreezer Proxy in Kubernetes with different networking configurations.

Networking Modes

The proxy needs to receive data on specific ports (syslog:514, sFlow:6343, IPFIX:4739, etc.). Kubernetes offers several ways to expose these ports:

Mode Port Declaration Dynamic Ports Use Case
HostNetwork Not required Yes Recommended for dynamic configs
LoadBalancer (MetalLB) Required in Service No Static port allocation
NodePort Required in Service No Cloud/bare metal without LB
ClusterIP Required in Service No Internal cluster only

With hostNetwork: true, the pod uses the host's network stack directly. No Service port declaration needed - the proxy binds directly to host ports based on its configuration.

Advantages

  • Dynamic port allocation from Control
  • No Kubernetes manifest changes when adding datasets
  • Proxy configuration drives which ports are open
  • Simplest for control-only mode

Deployment

apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: bytefreezer-proxy
  namespace: bytefreezer
spec:
  selector:
    matchLabels:
      app: bytefreezer-proxy
  template:
    metadata:
      labels:
        app: bytefreezer-proxy
    spec:
      hostNetwork: true        # Use host network - no Service needed for data ports
      dnsPolicy: ClusterFirstWithHostNet
      containers:
        - name: proxy
          image: bytefreezer/proxy:latest
          securityContext:
            capabilities:
              add:
                - NET_BIND_SERVICE   # Allow binding to ports < 1024
          volumeMounts:
            - name: config
              mountPath: /etc/bytefreezer
            - name: spool
              mountPath: /var/spool/bytefreezer-proxy
            - name: cache
              mountPath: /var/cache/bytefreezer-proxy
          resources:
            requests:
              memory: "128Mi"
              cpu: "100m"
            limits:
              memory: "512Mi"
              cpu: "1000m"
      volumes:
        - name: config
          configMap:
            name: bytefreezer-proxy-config
        - name: spool
          hostPath:
            path: /var/spool/bytefreezer-proxy
            type: DirectoryOrCreate
        - name: cache
          hostPath:
            path: /var/cache/bytefreezer-proxy
            type: DirectoryOrCreate

ConfigMap

apiVersion: v1
kind: ConfigMap
metadata:
  name: bytefreezer-proxy-config
  namespace: bytefreezer
data:
  config.yml: |
    app:
      name: bytefreezer-proxy

    # Control-only mode - proxy receives port configs from Control
    config_mode: "control-only"
    account_id: "your-account-id"
    bearer_token: "your-api-key"
    control_url: "https://api.bytefreezer.com"

    config_polling:
      enabled: true
      interval_seconds: 60

    receiver:
      base_url: "http://your-receiver:8080"    # Your Receiver webhook endpoint

    batching:
      enabled: true
      max_bytes: 10485760
      timeout_seconds: 60
      compression_enabled: true

    spooling:
      enabled: true
      directory: "/var/spool/bytefreezer-proxy"

    health_reporting:
      enabled: true
      report_interval: 30

How It Works

  1. Proxy starts and polls Control: GET /api/v1/proxy/config?account_id=X&proxy_instance_id=<hostname>
  2. Control returns datasets assigned to this proxy
  3. Proxy starts listeners on configured ports (e.g., syslog:514, ipfix:4739)
  4. Ports are immediately available on the host
  5. No Kubernetes Service or manifest update required

Firewall Configuration

Ensure host firewall allows the port range you plan to use:

# Example: Allow common data ports
sudo firewall-cmd --permanent --add-port=514/udp    # Syslog
sudo firewall-cmd --permanent --add-port=514/tcp    # Syslog TCP
sudo firewall-cmd --permanent --add-port=6343/udp   # sFlow
sudo firewall-cmd --permanent --add-port=4739/udp   # IPFIX
sudo firewall-cmd --permanent --add-port=2055/udp   # NetFlow
sudo firewall-cmd --permanent --add-port=2056/udp   # eBPF
sudo firewall-cmd --reload

Or with iptables:

sudo iptables -A INPUT -p udp --dport 514 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 6343 -j ACCEPT
sudo iptables -A INPUT -p udp --dport 4739 -j ACCEPT

LoadBalancer Mode (MetalLB)

With LoadBalancer Services, ports must be declared in the Service manifest before deployment. Use this when you need a stable external IP or cannot use hostNetwork.

Limitations

  • Ports must be pre-declared in Service manifest
  • Adding new ports requires Service update and reapply
  • Not suitable for dynamic port allocation

Service Definition

apiVersion: v1
kind: Service
metadata:
  name: bytefreezer-proxy
  namespace: bytefreezer
  annotations:
    metallb.universe.tf/loadBalancerIPs: 192.168.1.100   # Optional: specific IP
spec:
  type: LoadBalancer
  selector:
    app: bytefreezer-proxy
  ports:
    # Declare ALL ports you need BEFORE deployment
    - name: syslog-udp
      protocol: UDP
      port: 514
      targetPort: 514
    - name: syslog-tcp
      protocol: TCP
      port: 514
      targetPort: 514
    - name: sflow
      protocol: UDP
      port: 6343
      targetPort: 6343
    - name: ipfix
      protocol: UDP
      port: 4739
      targetPort: 4739
    - name: netflow
      protocol: UDP
      port: 2055
      targetPort: 2055
    - name: api
      protocol: TCP
      port: 8008
      targetPort: 8008

Deployment (without hostNetwork)

apiVersion: apps/v1
kind: Deployment
metadata:
  name: bytefreezer-proxy
  namespace: bytefreezer
spec:
  replicas: 1
  selector:
    matchLabels:
      app: bytefreezer-proxy
  template:
    metadata:
      labels:
        app: bytefreezer-proxy
    spec:
      containers:
        - name: proxy
          image: bytefreezer/proxy:latest
          ports:
            - containerPort: 514
              protocol: UDP
            - containerPort: 514
              protocol: TCP
            - containerPort: 6343
              protocol: UDP
            - containerPort: 4739
              protocol: UDP
            - containerPort: 2055
              protocol: UDP
            - containerPort: 8008
              protocol: TCP
          volumeMounts:
            - name: config
              mountPath: /etc/bytefreezer
      volumes:
        - name: config
          configMap:
            name: bytefreezer-proxy-config

Adding New Ports

When you need to add a new data source:

  1. Update Service manifest with new port
  2. Update Deployment with new containerPort
  3. Apply changes: kubectl apply -f proxy-service.yaml -f proxy-deployment.yaml
  4. Create dataset in Control and assign to proxy

NodePort Mode

Similar to LoadBalancer but uses high ports (30000-32767) on every node.

apiVersion: v1
kind: Service
metadata:
  name: bytefreezer-proxy
  namespace: bytefreezer
spec:
  type: NodePort
  selector:
    app: bytefreezer-proxy
  ports:
    - name: syslog-udp
      protocol: UDP
      port: 514
      targetPort: 514
      nodePort: 30514      # Access via <any-node-ip>:30514
    - name: sflow
      protocol: UDP
      port: 6343
      targetPort: 6343
      nodePort: 30343

Comparison Summary

Use HostNetwork When:

  • Configuration comes from Control (control-only mode)
  • Datasets/ports change frequently
  • You want automatic port management
  • Running as DaemonSet on dedicated nodes

Use LoadBalancer/NodePort When:

  • Ports are static and known in advance
  • You need a stable external IP (MetalLB)
  • Network policies require Service abstraction
  • Running multiple replicas behind load balancer

UDP Buffer Tuning

For high-throughput UDP sources, tune kernel buffers on the host:

# Increase UDP buffer sizes
sudo sysctl -w net.core.rmem_max=16777216
sudo sysctl -w net.core.rmem_default=8388608
sudo sysctl -w net.core.netdev_max_backlog=50000

# Persist across reboots
cat <<EOF | sudo tee /etc/sysctl.d/99-bytefreezer.conf
net.core.rmem_max=16777216
net.core.rmem_default=8388608
net.core.netdev_max_backlog=50000
EOF

For Kubernetes nodes, apply these settings via DaemonSet init container or node configuration management.


Troubleshooting

Port Not Accessible

  1. HostNetwork: Check host firewall, verify proxy is listening (ss -ulnp | grep <port>)
  2. LoadBalancer: Verify Service has external IP, check port is declared
  3. Both: Verify dataset is assigned to this proxy in Control

Proxy Not Receiving Data

# Check if proxy is listening
kubectl exec -it <proxy-pod> -- ss -ulnp

# Check proxy logs
kubectl logs <proxy-pod> -f

# Verify config from Control
kubectl exec -it <proxy-pod> -- cat /var/cache/bytefreezer-proxy/*.json

UDP Drops

If you see "UDP socket drops" in the UI:

  1. Apply kernel buffer tuning (see above)
  2. Increase read_buffer_size in dataset config
  3. Increase worker_count for the plugin
  4. Restart proxy to reset counters

Helm Chart Installation

The ByteFreezer Proxy Helm chart simplifies Kubernetes deployment with configurable networking options.

Quick Start with Values File

Create proxy-values.yaml:

# Required settings
receiver:
  url: "http://your-receiver:8080"

controlService:
  url: "https://api.bytefreezer.com"
  accountId: "your-account-id"
  bearerToken: "your-api-key"

# Network mode: hostNetwork for direct node access
hostNetwork: true

# Pin to specific node (optional)
nodeName: "worker-1"

# UDP configuration
udp:
  enabled: true
  ports:
    - port: 514
      name: syslog
    - port: 5514
      name: syslog-alt

Install:

helm install proxy ./helm/proxy -n bytefreezer -f proxy-values.yaml

Network Mode Examples

Option 1: HostNetwork (Direct Node Access)

# proxy-hostnetwork.yaml
receiver:
  url: "http://your-receiver:8080"

controlService:
  url: "https://api.bytefreezer.com"
  accountId: "your-account-id"
  bearerToken: "your-api-key"

hostNetwork: true
nodeName: "worker-1"   # Pin to specific node

udp:
  enabled: true
  ports:
    - port: 514
      name: syslog

Option 2: LoadBalancer (MetalLB)

# proxy-loadbalancer.yaml
receiver:
  url: "http://your-receiver:8080"

controlService:
  url: "https://api.bytefreezer.com"
  accountId: "your-account-id"
  bearerToken: "your-api-key"

hostNetwork: false

udp:
  enabled: true
  ports:
    - port: 514
      name: syslog
  service:
    type: LoadBalancer
    annotations:
      metallb.universe.tf/loadBalancerIPs: "192.168.1.100"

Option 3: ClusterIP (Internal Only)

# proxy-internal.yaml
receiver:
  url: "http://your-receiver:8080"

controlService:
  url: "https://api.bytefreezer.com"
  accountId: "your-account-id"
  bearerToken: "your-api-key"

hostNetwork: false

udp:
  enabled: true
  service:
    type: ClusterIP

Node Selection

When using hostNetwork: true, control which node the proxy runs on:

By node name:

nodeName: "tp4"

By node label:

# First label the node
kubectl label node tp4 bytefreezer-proxy=true
nodeSelector:
  bytefreezer-proxy: "true"

Upgrade and Uninstall

# Upgrade with new values
helm upgrade proxy ./helm/proxy -n bytefreezer -f proxy-values.yaml

# Uninstall
helm uninstall proxy -n bytefreezer