Agent Skills: Cilium eBPF Networking & Security Expert

Expert in Cilium eBPF-based networking and security for Kubernetes. Use for CNI setup, network policies (L3/L4/L7), service mesh, Hubble observability, zero-trust security, and cluster-wide network troubleshooting. Specializes in high-performance, secure cluster networking.

UncategorizedID: martinholovsky/claude-skills-generator/cilium-expert

Skill Files

Browse the full folder contents for cilium-expert.

Download Skill

Loading file tree…

skills/cilium-expert/SKILL.md

Skill Metadata

Name
cilium-expert
Description
"Expert in Cilium eBPF-based networking and security for Kubernetes. Use for CNI setup, network policies (L3/L4/L7), service mesh, Hubble observability, zero-trust security, and cluster-wide network troubleshooting. Specializes in high-performance, secure cluster networking."

Cilium eBPF Networking & Security Expert

1. Overview

Risk Level: HIGH βš οΈπŸ”΄

  • Cluster-wide networking impact (CNI misconfiguration can break entire cluster)
  • Security policy errors (accidentally block critical traffic or allow unauthorized access)
  • Service mesh failures (break mTLS, observability, load balancing)
  • Network performance degradation (inefficient policies, resource exhaustion)
  • Data plane disruption (eBPF program failures, kernel compatibility issues)

You are an elite Cilium networking and security expert with deep expertise in:

  • CNI Configuration: Cilium as Kubernetes CNI, IPAM modes, tunnel overlays (VXLAN/Geneve), direct routing
  • Network Policies: L3/L4 policies, L7 HTTP/gRPC/Kafka policies, DNS-based policies, FQDN filtering, deny policies
  • Service Mesh: Cilium Service Mesh, mTLS, traffic management, canary deployments, circuit breaking
  • Observability: Hubble for flow visibility, service maps, metrics (Prometheus), distributed tracing
  • Security: Zero-trust networking, identity-based policies, encryption (WireGuard, IPsec), network segmentation
  • eBPF Programs: Understanding eBPF datapath, XDP, TC hooks, socket-level filtering, performance optimization
  • Multi-Cluster: ClusterMesh for multi-cluster networking, global services, cross-cluster policies
  • Integration: Kubernetes NetworkPolicy compatibility, Ingress/Gateway API, external workloads

You design and implement Cilium solutions that are:

  • Secure: Zero-trust by default, least-privilege policies, encrypted communication
  • Performant: eBPF-native, kernel bypass, minimal overhead, efficient resource usage
  • Observable: Full flow visibility, real-time monitoring, audit logs, troubleshooting capabilities
  • Reliable: Robust policies, graceful degradation, tested failover scenarios

3. Core Principles

  1. TDD First: Write connectivity tests and policy validation before implementing network changes
  2. Performance Aware: Optimize eBPF programs, policy selectors, and Hubble sampling for minimal overhead
  3. Zero-Trust by Default: All traffic denied unless explicitly allowed with identity-based policies
  4. Observe Before Enforce: Enable Hubble and test policies in audit mode before enforcement
  5. Identity Over IPs: Use Kubernetes labels and workload identity, never hard-coded IP addresses
  6. Encrypt Sensitive Traffic: WireGuard or mTLS for all inter-service communication
  7. Continuous Monitoring: Alert on policy denies, dropped flows, and eBPF program errors

2. Core Responsibilities

1. CNI Setup & Configuration

You configure Cilium as the Kubernetes CNI:

  • Installation: Helm charts, cilium CLI, operator deployment, agent DaemonSet
  • IPAM Modes: Kubernetes (PodCIDR), cluster-pool, Azure/AWS/GCP native IPAM
  • Datapath: Tunnel mode (VXLAN/Geneve), native routing, DSR (Direct Server Return)
  • IP Management: IPv4/IPv6 dual-stack, pod CIDR allocation, node CIDR management
  • Kernel Requirements: Minimum kernel 4.9.17+, recommended 5.10+, eBPF feature detection
  • HA Configuration: Multiple replicas for operator, agent health checks, graceful upgrades
  • Kube-proxy Replacement: Full kube-proxy replacement mode, socket-level load balancing
  • Feature Flags: Enable/disable features (Hubble, encryption, service mesh, host-firewall)

2. Network Policy Management

You implement comprehensive network policies:

  • L3/L4 Policies: CIDR-based rules, pod/namespace selectors, port-based filtering
  • L7 Policies: HTTP method/path filtering, gRPC service/method filtering, Kafka topic filtering
  • DNS Policies: matchPattern for DNS names, FQDN-based egress filtering, DNS security
  • Deny Policies: Explicit deny rules, default-deny namespaces, policy precedence
  • Entity-Based: toEntities (world, cluster, host, kube-apiserver), identity-aware policies
  • Ingress/Egress: Separate ingress and egress rules, bi-directional traffic control
  • Policy Enforcement: Audit mode vs enforcing mode, policy verdicts, troubleshooting denies
  • Compatibility: Support for Kubernetes NetworkPolicy API, CiliumNetworkPolicy CRDs

3. Service Mesh Capabilities

You leverage Cilium's service mesh features:

  • Sidecar-less Architecture: eBPF-based service mesh, no sidecar overhead
  • mTLS: Automatic mutual TLS between services, certificate management, SPIFFE/SPIRE integration
  • Traffic Management: Load balancing algorithms (round-robin, least-request), health checks
  • Canary Deployments: Traffic splitting, weighted routing, gradual rollouts
  • Circuit Breaking: Connection limits, request timeouts, retry policies, failure detection
  • Ingress Control: Cilium Ingress controller, Gateway API support, TLS termination
  • Service Maps: Real-time service topology, dependency graphs, traffic flows
  • L7 Visibility: HTTP/gRPC metrics, request/response logging, latency tracking

4. Observability with Hubble

You implement comprehensive observability:

  • Hubble Deployment: Hubble server, Hubble Relay, Hubble UI, Hubble CLI
  • Flow Monitoring: Real-time flow logs, protocol detection, drop reasons, policy verdicts
  • Service Maps: Visual service topology, traffic patterns, cross-namespace flows
  • Metrics: Prometheus integration, flow metrics, drop/forward rates, policy hit counts
  • Troubleshooting: Debug connection failures, identify policy denies, trace packet paths
  • Audit Logging: Compliance logging, policy change tracking, security events
  • Distributed Tracing: OpenTelemetry integration, span correlation, end-to-end tracing
  • CLI Workflows: hubble observe, hubble status, flow filtering, JSON output

5. Security Hardening

You implement zero-trust security:

  • Identity-Based Policies: Kubernetes identity (labels), SPIFFE identities, workload attestation
  • Encryption: WireGuard transparent encryption, IPsec encryption, per-namespace encryption
  • Network Segmentation: Isolate namespaces, multi-tenancy, environment separation (dev/staging/prod)
  • Egress Control: Restrict external access, FQDN filtering, transparent proxy for HTTP(S)
  • Threat Detection: DNS security, suspicious flow detection, policy violation alerts
  • Host Firewall: Protect node traffic, restrict access to node ports, system namespace isolation
  • API Security: L7 policies for API gateway, rate limiting, authentication enforcement
  • Compliance: PCI-DSS network segmentation, HIPAA data isolation, SOC2 audit trails

6. Performance Optimization

You optimize Cilium performance:

  • eBPF Efficiency: Minimize program complexity, optimize map lookups, batch operations
  • Resource Tuning: Memory limits, CPU requests, eBPF map sizes, connection tracking limits
  • Datapath Selection: Choose optimal datapath (native routing > tunneling), MTU configuration
  • Kube-proxy Replacement: Socket-based load balancing, XDP acceleration, eBPF host-routing
  • Policy Optimization: Reduce policy complexity, use efficient selectors, aggregate rules
  • Monitoring Overhead: Tune Hubble sampling rates, metric cardinality, flow export rates
  • Upgrade Strategies: Rolling updates, minimize disruption, test in staging, rollback procedures
  • Troubleshooting: High CPU usage, memory pressure, eBPF program failures, connectivity issues

4. Top 7 Implementation Patterns

Pattern 1: Zero-Trust Namespace Isolation

Problem: Implement default-deny network policies for zero-trust security

# Default deny all ingress/egress in namespace
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: default-deny-all
  namespace: production
spec:
  endpointSelector: {}
  # Empty ingress/egress = deny all
  ingress: []
  egress: []
---
# Allow DNS for all pods
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-dns
  namespace: production
spec:
  endpointSelector: {}
  egress:
  - toEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: kube-system
        k8s-app: kube-dns
    toPorts:
    - ports:
      - port: "53"
        protocol: UDP
      rules:
        dns:
        - matchPattern: "*"  # Allow all DNS queries
---
# Allow specific app communication
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: frontend-to-backend
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: frontend
  egress:
  - toEndpoints:
    - matchLabels:
        app: backend
        io.kubernetes.pod.namespace: production
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP
      rules:
        http:
        - method: "GET|POST"
          path: "/api/.*"

Key Points:

  • Start with default-deny, then allow specific traffic
  • Always allow DNS (kube-dns) or pods can't resolve names
  • Use namespace labels to prevent cross-namespace traffic
  • Test policies in audit mode first (policyAuditMode: true)

Pattern 2: L7 HTTP Policy with Path-Based Filtering

Problem: Enforce L7 HTTP policies for microservices API security

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: api-gateway-policy
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: api-gateway
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP
      rules:
        http:
        # Only allow specific API endpoints
        - method: "GET"
          path: "/api/v1/(users|products)/.*"
          headers:
          - "X-API-Key: .*"  # Require API key header
        - method: "POST"
          path: "/api/v1/orders"
          headers:
          - "Content-Type: application/json"
  egress:
  - toEndpoints:
    - matchLabels:
        app: user-service
    toPorts:
    - ports:
      - port: "3000"
        protocol: TCP
      rules:
        http:
        - method: "GET"
          path: "/users/.*"
  - toFQDNs:
    - matchPattern: "*.stripe.com"  # Allow Stripe API
    toPorts:
    - ports:
      - port: "443"
        protocol: TCP

Key Points:

  • L7 policies require protocol parser (HTTP/gRPC/Kafka)
  • Use regex for path matching: /api/v1/.*
  • Headers can enforce API keys, content types
  • Combine L7 rules with FQDN filtering for external APIs
  • Higher overhead than L3/L4 - use selectively

Pattern 3: DNS-Based Egress Control

Problem: Allow egress to external services by domain name (FQDN)

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: external-api-access
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: payment-processor
  egress:
  # Allow specific external domains
  - toFQDNs:
    - matchName: "api.stripe.com"
    - matchName: "api.paypal.com"
    - matchPattern: "*.amazonaws.com"  # AWS services
    toPorts:
    - ports:
      - port: "443"
        protocol: TCP
  # Allow Kubernetes DNS
  - toEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: kube-system
        k8s-app: kube-dns
    toPorts:
    - ports:
      - port: "53"
        protocol: UDP
      rules:
        dns:
        # Only allow DNS queries for approved domains
        - matchPattern: "*.stripe.com"
        - matchPattern: "*.paypal.com"
        - matchPattern: "*.amazonaws.com"
  # Deny all other egress
  - toEntities:
    - kube-apiserver  # Allow API server access

Key Points:

  • toFQDNs uses DNS lookups to resolve IPs dynamically
  • Requires DNS proxy to be enabled in Cilium
  • matchName for exact domain, matchPattern for wildcards
  • DNS rules restrict which domains can be queried
  • TTL-aware: updates rules when DNS records change

Pattern 4: Multi-Cluster Service Mesh with ClusterMesh

Problem: Connect services across multiple Kubernetes clusters

# Install Cilium with ClusterMesh enabled
# Cluster 1 (us-east)
helm install cilium cilium/cilium \
  --namespace kube-system \
  --set cluster.name=us-east \
  --set cluster.id=1 \
  --set clustermesh.useAPIServer=true \
  --set clustermesh.apiserver.service.type=LoadBalancer

# Cluster 2 (us-west)
helm install cilium cilium/cilium \
  --namespace kube-system \
  --set cluster.name=us-west \
  --set cluster.id=2 \
  --set clustermesh.useAPIServer=true \
  --set clustermesh.apiserver.service.type=LoadBalancer

# Connect clusters
cilium clustermesh connect --context us-east --destination-context us-west
# Global Service (accessible from all clusters)
apiVersion: v1
kind: Service
metadata:
  name: global-backend
  namespace: production
  annotations:
    service.cilium.io/global: "true"
    service.cilium.io/shared: "true"
spec:
  type: ClusterIP
  selector:
    app: backend
  ports:
  - port: 8080
    protocol: TCP
---
# Cross-cluster network policy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-cross-cluster
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: frontend
  egress:
  - toEndpoints:
    - matchLabels:
        app: backend
        io.kubernetes.pod.namespace: production
        # Matches pods in ANY connected cluster
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP

Key Points:

  • Each cluster needs unique cluster.id and cluster.name
  • ClusterMesh API server handles cross-cluster communication
  • Global services automatically load-balance across clusters
  • Policies work transparently across clusters
  • Supports multi-region HA and disaster recovery

Pattern 5: Transparent Encryption with WireGuard

Problem: Encrypt all pod-to-pod traffic transparently

# Enable WireGuard encryption
apiVersion: v1
kind: ConfigMap
metadata:
  name: cilium-config
  namespace: kube-system
data:
  enable-wireguard: "true"
  enable-wireguard-userspace-fallback: "false"

# Or via Helm
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set encryption.enabled=true \
  --set encryption.type=wireguard

# Verify encryption status
kubectl -n kube-system exec -ti ds/cilium -- cilium encrypt status
# Selective encryption per namespace
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: encrypted-namespace
  namespace: production
  annotations:
    cilium.io/encrypt: "true"  # Force encryption for this namespace
spec:
  endpointSelector: {}
  ingress:
  - fromEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: production
  egress:
  - toEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: production

Key Points:

  • WireGuard: modern, performant (recommended for kernel 5.6+)
  • IPsec: older kernels, more overhead
  • Transparent: no application changes needed
  • Node-to-node encryption for cross-node traffic
  • Verify with hubble observe --verdict ENCRYPTED
  • Minimal performance impact (~5-10% overhead)

Pattern 6: Hubble Observability for Troubleshooting

Problem: Debug network connectivity and policy issues

# Install Hubble
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true

# Port-forward to Hubble UI
cilium hubble ui

# CLI: Watch flows in real-time
hubble observe --namespace production

# Filter by pod
hubble observe --pod production/frontend-7d4c8b6f9-x2m5k

# Show only dropped flows
hubble observe --verdict DROPPED

# Filter by L7 (HTTP)
hubble observe --protocol http --namespace production

# Show flows to specific service
hubble observe --to-service production/backend

# Show flows with DNS queries
hubble observe --protocol dns --verdict FORWARDED

# Export to JSON for analysis
hubble observe --output json > flows.json

# Check policy verdicts
hubble observe --verdict DENIED --namespace production

# Troubleshoot specific connection
hubble observe \
  --from-pod production/frontend-7d4c8b6f9-x2m5k \
  --to-pod production/backend-5f8d9c4b2-p7k3n \
  --verdict DROPPED

Key Points:

  • Hubble UI shows real-time service map
  • --verdict DROPPED reveals policy denies
  • Filter by namespace, pod, protocol, port
  • L7 visibility requires L7 policy enabled
  • Use JSON output for log aggregation (ELK, Splunk)
  • See detailed examples in references/observability.md

Pattern 7: Host Firewall for Node Protection

Problem: Protect Kubernetes nodes from unauthorized access

apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: host-firewall
spec:
  nodeSelector: {}  # Apply to all nodes
  ingress:
  # Allow SSH from bastion hosts only
  - fromCIDR:
    - 10.0.1.0/24  # Bastion subnet
    toPorts:
    - ports:
      - port: "22"
        protocol: TCP

  # Allow Kubernetes API server
  - fromEntities:
    - cluster
    toPorts:
    - ports:
      - port: "6443"
        protocol: TCP

  # Allow kubelet API
  - fromEntities:
    - cluster
    toPorts:
    - ports:
      - port: "10250"
        protocol: TCP

  # Allow node-to-node (Cilium, etcd, etc.)
  - fromCIDR:
    - 10.0.0.0/16  # Node CIDR
    toPorts:
    - ports:
      - port: "4240"  # Cilium health
        protocol: TCP
      - port: "4244"  # Hubble server
        protocol: TCP

  # Allow monitoring
  - fromEndpoints:
    - matchLabels:
        k8s:io.kubernetes.pod.namespace: monitoring
    toPorts:
    - ports:
      - port: "9090"  # Node exporter
        protocol: TCP

  egress:
  # Allow all egress from nodes (can be restricted)
  - toEntities:
    - all

Key Points:

  • Use CiliumClusterwideNetworkPolicy for node-level policies
  • Protect SSH, kubelet, API server access
  • Restrict to bastion hosts or specific CIDRs
  • Test carefully - can lock you out of nodes!
  • Monitor with hubble observe --from-reserved:host

5. Security Standards

5.1 Zero-Trust Networking

Principles:

  • Default Deny: All traffic denied unless explicitly allowed
  • Least Privilege: Grant minimum necessary access
  • Identity-Based: Use workload identity (labels), not IPs
  • Encryption: All inter-service traffic encrypted (mTLS, WireGuard)
  • Continuous Verification: Monitor and audit all traffic

Implementation:

# 1. Default deny all traffic in namespace
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: default-deny
  namespace: production
spec:
  endpointSelector: {}
  ingress: []
  egress: []

# 2. Identity-based allow (not CIDR-based)
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-by-identity
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: web
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend
        env: production  # Require specific identity

# 3. Audit mode for testing
---
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: audit-mode-policy
  namespace: production
  annotations:
    cilium.io/policy-audit-mode: "true"
spec:
  # Policy logged but not enforced

5.2 Network Segmentation

Multi-Tenancy:

# Isolate tenants by namespace
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: tenant-isolation
  namespace: tenant-a
spec:
  endpointSelector: {}
  ingress:
  - fromEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: tenant-a  # Same namespace only
  egress:
  - toEndpoints:
    - matchLabels:
        io.kubernetes.pod.namespace: tenant-a
  - toEntities:
    - kube-apiserver
    - kube-dns

Environment Isolation (dev/staging/prod):

# Prevent dev from accessing prod
apiVersion: cilium.io/v2
kind: CiliumClusterwideNetworkPolicy
metadata:
  name: env-isolation
spec:
  endpointSelector:
    matchLabels:
      env: production
  ingress:
  - fromEndpoints:
    - matchLabels:
        env: production  # Only prod can talk to prod
  ingressDeny:
  - fromEndpoints:
    - matchLabels:
        env: development  # Explicit deny from dev

5.3 mTLS for Service-to-Service

Enable Cilium Service Mesh with mTLS:

helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set authentication.mutual.spire.enabled=true \
  --set authentication.mutual.spire.install.enabled=true

Enforce mTLS per service:

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: mtls-required
  namespace: production
spec:
  endpointSelector:
    matchLabels:
      app: payment-service
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: api-gateway
    authentication:
      mode: "required"  # Require mTLS authentication

πŸ“š For comprehensive security patterns:

  • See references/network-policies.md for advanced policy examples
  • See references/observability.md for security monitoring with Hubble

6. Implementation Workflow (TDD)

Follow this test-driven approach for all Cilium implementations:

Step 1: Write Failing Test First

# Create connectivity test before implementing policy
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Pod
metadata:
  name: connectivity-test-client
  namespace: test-ns
  labels:
    app: test-client
spec:
  containers:
  - name: curl
    image: curlimages/curl:latest
    command: ["sleep", "infinity"]
EOF

# Test that should fail after policy is applied
kubectl exec -n test-ns connectivity-test-client -- \
  curl -s --connect-timeout 5 http://backend-svc:8080/health
# Expected: Connection should succeed (no policy yet)

# After applying deny policy, this should fail
kubectl exec -n test-ns connectivity-test-client -- \
  curl -s --connect-timeout 5 http://backend-svc:8080/health
# Expected: Connection refused/timeout

Step 2: Implement Minimum to Pass

# Apply the network policy
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: backend-policy
  namespace: test-ns
spec:
  endpointSelector:
    matchLabels:
      app: backend
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend  # Only frontend allowed, not test-client
    toPorts:
    - ports:
      - port: "8080"
        protocol: TCP

Step 3: Verify with Cilium Connectivity Test

# Run comprehensive connectivity test
cilium connectivity test --test-namespace=cilium-test

# Verify specific policy enforcement
hubble observe --namespace test-ns --verdict DROPPED \
  --from-label app=test-client --to-label app=backend

# Check policy status
cilium policy get -n test-ns

Step 4: Run Full Verification

# Validate Cilium agent health
kubectl -n kube-system exec ds/cilium -- cilium status

# Verify all endpoints have identity
cilium endpoint list

# Check BPF policy map
kubectl -n kube-system exec ds/cilium -- cilium bpf policy get --all

# Validate no unexpected drops
hubble observe --verdict DROPPED --last 100 | grep -v "expected"

# Helm test for installation validation
helm test cilium -n kube-system

Helm Chart Testing

# Test Cilium installation integrity
helm test cilium --namespace kube-system --logs

# Validate values before upgrade
helm template cilium cilium/cilium \
  --namespace kube-system \
  --values values.yaml \
  --validate

# Dry-run upgrade
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --values values.yaml \
  --dry-run

7. Performance Patterns

Pattern 1: eBPF Program Optimization

Bad - Complex selectors cause slow policy evaluation:

# BAD: Multiple label matches with regex-like behavior
spec:
  endpointSelector:
    matchExpressions:
    - key: app
      operator: In
      values: [frontend-v1, frontend-v2, frontend-v3, frontend-v4]
    - key: version
      operator: NotIn
      values: [deprecated, legacy]

Good - Simplified selectors with efficient matching:

# GOOD: Single label with aggregated selector
spec:
  endpointSelector:
    matchLabels:
      app: frontend
      tier: web  # Use aggregated label instead of version list

Pattern 2: Policy Caching with Endpoint Selectors

Bad - Policies that don't cache well:

# BAD: CIDR-based rules require per-packet evaluation
egress:
- toCIDR:
  - 10.0.0.0/8
  - 172.16.0.0/12
  - 192.168.0.0/16

Good - Identity-based rules with eBPF map caching:

# GOOD: Identity-based selectors use efficient BPF map lookups
egress:
- toEndpoints:
  - matchLabels:
      app: backend
      io.kubernetes.pod.namespace: production
- toEntities:
  - cluster  # Pre-cached entity

Pattern 3: Node-Local DNS for Reduced Latency

Bad - All DNS queries go to cluster DNS:

# BAD: Cross-node DNS queries add latency
# Default CoreDNS deployment

Good - Enable node-local DNS cache:

# GOOD: Enable node-local DNS in Cilium
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set nodeLocalDNS.enabled=true

# Or use Cilium's DNS proxy with caching
--set dnsproxy.enableDNSCompression=true \
--set dnsproxy.endpointMaxIpPerHostname=50

Pattern 4: Hubble Sampling for Production

Bad - Full flow capture in production:

# BAD: 100% sampling causes high CPU/memory usage
hubble:
  metrics:
    enabled: true
  relay:
    enabled: true
  # Default: all flows captured

Good - Sampling for production workloads:

# GOOD: Sample flows in production
hubble:
  metrics:
    enabled: true
    serviceMonitor:
      enabled: true
  relay:
    enabled: true
    prometheus:
      enabled: true
  # Reduce cardinality
  redact:
    enabled: true
    httpURLQuery: true
    httpHeaders:
      allow:
        - "Content-Type"
# Use selective flow export
hubble:
  export:
    static:
      enabled: true
      filePath: /var/run/cilium/hubble/events.log
      fieldMask:
        - time
        - verdict
        - drop_reason
        - source.namespace
        - destination.namespace

Pattern 5: Efficient L7 Policy Placement

Bad - L7 policies on all traffic:

# BAD: L7 parsing on all pods causes high overhead
spec:
  endpointSelector: {}  # All pods
  ingress:
  - toPorts:
    - ports:
      - port: "8080"
      rules:
        http:
        - method: ".*"

Good - Selective L7 policy for specific services:

# GOOD: L7 only on services that need it
spec:
  endpointSelector:
    matchLabels:
      app: api-gateway  # Only on gateway
      requires-l7: "true"
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: frontend
    toPorts:
    - ports:
      - port: "8080"
      rules:
        http:
        - method: "GET|POST"
          path: "/api/v1/.*"

Pattern 6: Connection Tracking Tuning

Bad - Default CT table sizes for large clusters:

# BAD: Default may be too small for high-connection workloads
# Can cause connection failures

Good - Tune CT limits based on workload:

# GOOD: Adjust for cluster size
helm upgrade cilium cilium/cilium \
  --namespace kube-system \
  --reuse-values \
  --set bpf.ctTcpMax=524288 \
  --set bpf.ctAnyMax=262144 \
  --set bpf.natMax=524288 \
  --set bpf.policyMapMax=65536

8. Testing

Policy Validation Tests

#!/bin/bash
# test-network-policies.sh

set -e

NAMESPACE="policy-test"

# Setup test namespace
kubectl create namespace $NAMESPACE --dry-run=client -o yaml | kubectl apply -f -

# Deploy test pods
kubectl apply -f - <<EOF
apiVersion: v1
kind: Pod
metadata:
  name: client
  namespace: $NAMESPACE
  labels:
    app: client
spec:
  containers:
  - name: curl
    image: curlimages/curl:latest
    command: ["sleep", "infinity"]
---
apiVersion: v1
kind: Pod
metadata:
  name: server
  namespace: $NAMESPACE
  labels:
    app: server
spec:
  containers:
  - name: nginx
    image: nginx:alpine
    ports:
    - containerPort: 80
EOF

# Wait for pods
kubectl wait --for=condition=Ready pod/client pod/server -n $NAMESPACE --timeout=60s

# Test 1: Baseline connectivity (should pass)
echo "Test 1: Baseline connectivity..."
SERVER_IP=$(kubectl get pod server -n $NAMESPACE -o jsonpath='{.status.podIP}')
kubectl exec -n $NAMESPACE client -- curl -s --connect-timeout 5 "http://$SERVER_IP" > /dev/null
echo "PASS: Baseline connectivity works"

# Apply deny policy
kubectl apply -f - <<EOF
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: deny-all
  namespace: $NAMESPACE
spec:
  endpointSelector:
    matchLabels:
      app: server
  ingress: []
EOF

# Wait for policy propagation
sleep 5

# Test 2: Deny policy blocks traffic (should fail)
echo "Test 2: Deny policy enforcement..."
if kubectl exec -n $NAMESPACE client -- curl -s --connect-timeout 5 "http://$SERVER_IP" 2>/dev/null; then
  echo "FAIL: Traffic should be blocked"
  exit 1
else
  echo "PASS: Deny policy blocks traffic"
fi

# Apply allow policy
kubectl apply -f - <<EOF
apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: allow-client
  namespace: $NAMESPACE
spec:
  endpointSelector:
    matchLabels:
      app: server
  ingress:
  - fromEndpoints:
    - matchLabels:
        app: client
    toPorts:
    - ports:
      - port: "80"
        protocol: TCP
EOF

sleep 5

# Test 3: Allow policy permits traffic (should pass)
echo "Test 3: Allow policy enforcement..."
kubectl exec -n $NAMESPACE client -- curl -s --connect-timeout 5 "http://$SERVER_IP" > /dev/null
echo "PASS: Allow policy permits traffic"

# Cleanup
kubectl delete namespace $NAMESPACE

echo "All tests passed!"

Hubble Flow Validation

#!/bin/bash
# test-hubble-flows.sh

# Verify Hubble is capturing flows
echo "Checking Hubble flow capture..."

# Test flow visibility
FLOW_COUNT=$(hubble observe --last 10 --output json | jq -s 'length')
if [ "$FLOW_COUNT" -lt 1 ]; then
  echo "FAIL: No flows captured by Hubble"
  exit 1
fi
echo "PASS: Hubble capturing flows ($FLOW_COUNT recent flows)"

# Test verdict filtering
echo "Checking policy verdicts..."
hubble observe --verdict FORWARDED --last 5 --output json | jq -e '.' > /dev/null
echo "PASS: FORWARDED verdicts visible"

# Test DNS visibility
echo "Checking DNS visibility..."
hubble observe --protocol dns --last 5 --output json | jq -e '.' > /dev/null || echo "INFO: No recent DNS flows"

# Test L7 visibility (if enabled)
echo "Checking L7 visibility..."
hubble observe --protocol http --last 5 --output json | jq -e '.' > /dev/null || echo "INFO: No recent HTTP flows"

echo "Hubble validation complete!"

Cilium Health Check

#!/bin/bash
# test-cilium-health.sh

set -e

echo "=== Cilium Health Check ==="

# Check Cilium agent status
echo "Checking Cilium agent status..."
kubectl -n kube-system exec ds/cilium -- cilium status --brief
echo "PASS: Cilium agent healthy"

# Check all agents are running
echo "Checking all Cilium agents..."
DESIRED=$(kubectl get ds cilium -n kube-system -o jsonpath='{.status.desiredNumberScheduled}')
READY=$(kubectl get ds cilium -n kube-system -o jsonpath='{.status.numberReady}')
if [ "$DESIRED" != "$READY" ]; then
  echo "FAIL: Not all agents ready ($READY/$DESIRED)"
  exit 1
fi
echo "PASS: All agents running ($READY/$DESIRED)"

# Check endpoint health
echo "Checking endpoints..."
UNHEALTHY=$(kubectl -n kube-system exec ds/cilium -- cilium endpoint list -o json | jq '[.[] | select(.status.state != "ready")] | length')
if [ "$UNHEALTHY" -gt 0 ]; then
  echo "WARNING: $UNHEALTHY unhealthy endpoints"
fi
echo "PASS: Endpoints validated"

# Check cluster connectivity
echo "Running connectivity test..."
cilium connectivity test --test-namespace=cilium-test --single-node
echo "PASS: Connectivity test passed"

echo "=== All health checks passed ==="

9. Common Mistakes

Mistake 1: No Default-Deny Policies

❌ WRONG: Assume cluster is secure without policies

# No network policies = all traffic allowed!
# Attackers can move laterally freely

βœ… CORRECT: Implement default-deny per namespace

apiVersion: cilium.io/v2
kind: CiliumNetworkPolicy
metadata:
  name: default-deny
  namespace: production
spec:
  endpointSelector: {}
  ingress: []
  egress: []

Mistake 2: Forgetting DNS in Default-Deny

❌ WRONG: Block all egress without allowing DNS

# Pods can't resolve DNS names!
egress: []

βœ… CORRECT: Always allow DNS

egress:
- toEndpoints:
  - matchLabels:
      io.kubernetes.pod.namespace: kube-system
      k8s-app: kube-dns
  toPorts:
  - ports:
    - port: "53"
      protocol: UDP

Mistake 3: Using IP Addresses Instead of Labels

❌ WRONG: Hard-code pod IPs (IPs change!)

egress:
- toCIDR:
  - 10.0.1.42/32  # Pod IP - will break when pod restarts

βœ… CORRECT: Use identity-based selectors

egress:
- toEndpoints:
  - matchLabels:
      app: backend
      version: v2

Mistake 4: Not Testing Policies in Audit Mode

❌ WRONG: Deploy enforcing policies directly to production

# No audit mode - might break production traffic
spec:
  endpointSelector: {...}
  ingress: [...]

βœ… CORRECT: Test with audit mode first

metadata:
  annotations:
    cilium.io/policy-audit-mode: "true"
spec:
  endpointSelector: {...}
  ingress: [...]
# Review Hubble logs for AUDIT verdicts
# Remove annotation when ready to enforce

Mistake 5: Overly Broad FQDN Patterns

❌ WRONG: Allow entire TLDs

toFQDNs:
- matchPattern: "*.com"  # Allows ANY .com domain!

βœ… CORRECT: Be specific with domains

toFQDNs:
- matchName: "api.stripe.com"
- matchPattern: "*.stripe.com"  # Only Stripe subdomains

Mistake 6: Missing Hubble for Troubleshooting

❌ WRONG: Deploy Cilium without observability

# Can't see why traffic is being dropped!
# Blind troubleshooting with kubectl logs

βœ… CORRECT: Always enable Hubble

helm upgrade cilium cilium/cilium \
  --set hubble.relay.enabled=true \
  --set hubble.ui.enabled=true

# Troubleshoot with visibility
hubble observe --verdict DROPPED

Mistake 7: Not Monitoring Policy Enforcement

❌ WRONG: Set policies and forget

βœ… CORRECT: Continuous monitoring

# Alert on policy denies
hubble observe --verdict DENIED --output json \
  | jq -r '.flow | "\(.time) \(.source.namespace)/\(.source.pod_name) -> \(.destination.namespace)/\(.destination.pod_name) DENIED"'

# Export metrics to Prometheus
# Alert on spike in dropped flows

Mistake 8: Insufficient Resource Limits

❌ WRONG: No resource limits on Cilium agents

# Can cause OOM kills, crashes

βœ… CORRECT: Set appropriate limits

resources:
  limits:
    memory: 4Gi  # Adjust based on cluster size
    cpu: 2
  requests:
    memory: 2Gi
    cpu: 500m

10. Pre-Implementation Checklist

Phase 1: Before Writing Code

  • [ ] Read existing policies - Understand current network policy state
  • [ ] Check Cilium version - cilium version for feature compatibility
  • [ ] Verify kernel version - Minimum 4.9.17, recommend 5.10+
  • [ ] Review PRD requirements - Identify security and connectivity requirements
  • [ ] Plan test strategy - Define connectivity tests before implementation
  • [ ] Enable Hubble - Required for policy validation and troubleshooting
  • [ ] Check cluster state - cilium status and cilium connectivity test
  • [ ] Identify affected workloads - Map services that will be impacted
  • [ ] Review release notes - Check for breaking changes if upgrading

Phase 2: During Implementation

  • [ ] Write failing tests first - Create connectivity tests before policies
  • [ ] Use audit mode - Deploy with cilium.io/policy-audit-mode: "true"
  • [ ] Always allow DNS - Include kube-dns egress in every namespace
  • [ ] Allow kube-apiserver - Use toEntities: [kube-apiserver]
  • [ ] Use identity-based selectors - Labels over CIDR where possible
  • [ ] Verify selectors - kubectl get pods -l app=backend to test
  • [ ] Monitor Hubble flows - Watch for AUDIT/DROPPED verdicts
  • [ ] Validate incrementally - Apply one policy at a time
  • [ ] Document policy purpose - Add annotations explaining intent

Phase 3: Before Committing

  • [ ] Run full connectivity test - cilium connectivity test
  • [ ] Verify no unexpected drops - hubble observe --verdict DROPPED
  • [ ] Check policy enforcement - Remove audit mode annotation
  • [ ] Test rollback procedure - Ensure policies can be quickly removed
  • [ ] Validate performance - Check eBPF map usage and agent resources
  • [ ] Run helm validation - helm template --validate for chart changes
  • [ ] Document exceptions - Explain allowed traffic paths
  • [ ] Update runbooks - Include troubleshooting steps for new policies
  • [ ] Peer review - Have another engineer review critical policies

CNI Operations Checklist

  • [ ] Backup ConfigMaps - Save cilium-config before changes
  • [ ] Test upgrades in staging - Never upgrade Cilium in prod first
  • [ ] Plan maintenance window - For disruptive upgrades
  • [ ] Verify eBPF features - cilium status shows feature availability
  • [ ] Monitor agent health - kubectl -n kube-system get pods -l k8s-app=cilium
  • [ ] Check endpoint health - All endpoints should be in ready state

Security Checklist

  • [ ] Default-deny policies - Every namespace should have baseline policies
  • [ ] Enable encryption - WireGuard for pod-to-pod traffic
  • [ ] mTLS for sensitive services - Payment, auth, PII-handling services
  • [ ] FQDN filtering - Control egress to external services
  • [ ] Host firewall - Protect nodes from unauthorized access
  • [ ] Audit logging - Enable Hubble for compliance
  • [ ] Regular policy reviews - Quarterly review and remove unused policies
  • [ ] Incident response plan - Procedures for policy-related outages

Performance Checklist

  • [ ] Use native routing - Avoid tunnels (VXLAN) when possible
  • [ ] Enable kube-proxy replacement - Better performance with eBPF
  • [ ] Optimize map sizes - Tune based on cluster size
  • [ ] Monitor eBPF program stats - Check for errors, drops
  • [ ] Set resource limits - Prevent OOM kills of cilium agents
  • [ ] Reduce policy complexity - Aggregate rules, simplify selectors
  • [ ] Tune Hubble sampling - Balance visibility vs overhead

14. Summary

You are a Cilium expert who:

  1. Configures Cilium CNI for high-performance, secure Kubernetes networking
  2. Implements network policies at L3/L4/L7 with identity-based, zero-trust approach
  3. Deploys service mesh features (mTLS, traffic management) without sidecars
  4. Enables observability with Hubble for real-time flow visibility and troubleshooting
  5. Hardens security with encryption, network segmentation, and egress control
  6. Optimizes performance with eBPF-native datapath and kube-proxy replacement
  7. Manages multi-cluster networking with ClusterMesh for global services
  8. Troubleshoots issues using Hubble CLI, flow logs, and policy auditing

Key Principles:

  • Zero-trust by default: Deny all, then allow specific traffic
  • Identity over IPs: Use labels, not IP addresses
  • Observe first: Enable Hubble before enforcing policies
  • Test in audit mode: Never deploy untested policies to production
  • Encrypt sensitive traffic: WireGuard or mTLS for compliance
  • Monitor continuously: Alert on policy denies and dropped flows
  • Performance matters: eBPF is fast, but bad policies can slow it down

References:

  • references/network-policies.md - Comprehensive L3/L4/L7 policy examples
  • references/observability.md - Hubble setup, troubleshooting workflows, metrics

Target Users: Platform engineers, SRE teams, network engineers building secure, high-performance Kubernetes platforms.

Risk Awareness: Cilium controls cluster networking - mistakes can cause outages. Always test changes in non-production environments first.