Cybersecurity

Crowdsec IPS Pod Scheduling

crowdsec ips pod scheduling
Crowdsec IPS Pod Scheduling | SiamCafe Blog
2026-03-17· อ. บอม — SiamCafe.net· 1,227 คำ

CrowdSec IPS Pod Scheduling คืออะไร

CrowdSec เป็น open source Intrusion Prevention System (IPS) ที่ใช้ crowdsourced threat intelligence ในการตรวจจับและบล็อกการโจมตี ทำงานคล้าย Fail2Ban แต่มี community-driven blocklists และรองรับ distributed architecture Pod Scheduling คือกระบวนการจัดสรร pods ไปยัง nodes ใน Kubernetes cluster การรวม CrowdSec กับ Kubernetes pod scheduling ช่วยให้ deploy security agents อย่างมีประสิทธิภาพ กระจาย IPS ไปทุก node และจัดการ resources อย่างเหมาะสม

CrowdSec Architecture บน Kubernetes

# crowdsec_arch.py — CrowdSec on Kubernetes
import json

class CrowdSecK8sArch:
    COMPONENTS = {
        "agent": {
            "name": "CrowdSec Agent (Log Processor)",
            "role": "อ่าน logs, ตรวจจับ attacks, ส่ง decisions",
            "deployment": "DaemonSet (ทุก node)",
            "resources": "CPU: 100m-500m, RAM: 128Mi-512Mi",
        },
        "lapi": {
            "name": "LAPI (Local API)",
            "role": "Central API สำหรับ decisions, alerts, blocklists",
            "deployment": "Deployment (1-3 replicas)",
            "resources": "CPU: 200m-1000m, RAM: 256Mi-1Gi",
        },
        "bouncer": {
            "name": "Bouncer (Enforcement)",
            "role": "บล็อก traffic ตาม decisions จาก LAPI",
            "deployment": "DaemonSet หรือ Sidecar",
            "types": "Nginx bouncer, Traefik bouncer, Firewall bouncer",
        },
        "cscli": {
            "name": "cscli (CLI Tool)",
            "role": "จัดการ CrowdSec: ดู decisions, alerts, metrics",
            "deployment": "ใช้ผ่าน kubectl exec",
        },
    }

    ARCHITECTURE = """
    [Internet Traffic]
          ↓
    [Ingress (Nginx/Traefik)]
          ↓
    [CrowdSec Bouncer] ←── block/allow ──→ [LAPI]
          ↓                                    ↑
    [Application Pods]                    [CrowdSec Agents]
                                              ↑
                                         [Node Logs]
                                              ↑
                                    [Community Blocklists]
    """

    def show_components(self):
        print("=== CrowdSec K8s Components ===\n")
        for key, comp in self.COMPONENTS.items():
            print(f"[{comp['name']}]")
            print(f"  Role: {comp['role']}")
            print(f"  Deploy: {comp['deployment']}")
            print()

    def show_architecture(self):
        print("=== Architecture ===")
        print(self.ARCHITECTURE)

arch = CrowdSecK8sArch()
arch.show_components()
arch.show_architecture()

Pod Scheduling Strategies

# scheduling.py — Pod scheduling for CrowdSec
import json

class PodScheduling:
    DAEMONSET = """
# crowdsec-agent-daemonset.yaml
apiVersion: apps/v1
kind: DaemonSet
metadata:
  name: crowdsec-agent
  namespace: crowdsec
spec:
  selector:
    matchLabels:
      app: crowdsec-agent
  template:
    metadata:
      labels:
        app: crowdsec-agent
    spec:
      tolerations:
        - key: node-role.kubernetes.io/control-plane
          effect: NoSchedule
        - key: node-role.kubernetes.io/master
          effect: NoSchedule
      nodeSelector:
        kubernetes.io/os: linux
      containers:
        - name: crowdsec
          image: crowdsecurity/crowdsec:latest
          env:
            - name: COLLECTIONS
              value: "crowdsecurity/linux crowdsecurity/nginx crowdsecurity/k8s-audit"
            - name: CROWDSEC_LAPI_URL
              value: "http://crowdsec-lapi:8080"
          resources:
            requests:
              cpu: 100m
              memory: 128Mi
            limits:
              cpu: 500m
              memory: 512Mi
          volumeMounts:
            - name: varlog
              mountPath: /var/log
              readOnly: true
            - name: containers
              mountPath: /var/lib/docker/containers
              readOnly: true
      volumes:
        - name: varlog
          hostPath:
            path: /var/log
        - name: containers
          hostPath:
            path: /var/lib/docker/containers
"""

    AFFINITY = """
# LAPI with anti-affinity (spread across nodes)
apiVersion: apps/v1
kind: Deployment
metadata:
  name: crowdsec-lapi
  namespace: crowdsec
spec:
  replicas: 3
  template:
    spec:
      affinity:
        podAntiAffinity:
          preferredDuringSchedulingIgnoredDuringExecution:
            - weight: 100
              podAffinityTerm:
                labelSelector:
                  matchLabels:
                    app: crowdsec-lapi
                topologyKey: kubernetes.io/hostname
      topologySpreadConstraints:
        - maxSkew: 1
          topologyKey: topology.kubernetes.io/zone
          whenUnsatisfiable: DoNotSchedule
          labelSelector:
            matchLabels:
              app: crowdsec-lapi
"""

    SCHEDULING_TYPES = {
        "daemonset": {"name": "DaemonSet", "use": "Agent ทุก node", "guarantee": "1 pod/node"},
        "nodeSelector": {"name": "NodeSelector", "use": "เลือก nodes เฉพาะ", "guarantee": "Label match"},
        "affinity": {"name": "Node/Pod Affinity", "use": "กระจาย LAPI, co-locate bouncer", "guarantee": "Preferred/Required"},
        "tolerations": {"name": "Tolerations", "use": "Agent บน control-plane nodes", "guarantee": "Override taints"},
        "topology_spread": {"name": "TopologySpreadConstraints", "use": "กระจายข้าม zones", "guarantee": "Max skew"},
    }

    def show_daemonset(self):
        print("=== DaemonSet Config ===")
        print(self.DAEMONSET[:500])

    def show_scheduling(self):
        print(f"\n=== Scheduling Strategies ===")
        for key, s in self.SCHEDULING_TYPES.items():
            print(f"  [{s['name']}] {s['use']} → {s['guarantee']}")

sched = PodScheduling()
sched.show_daemonset()
sched.show_scheduling()

Helm Installation

# helm_install.py — CrowdSec Helm chart
import json

class HelmInstall:
    COMMANDS = """
# Add CrowdSec Helm repo
helm repo add crowdsec https://crowdsecurity.github.io/helm-charts
helm repo update

# Install CrowdSec
helm install crowdsec crowdsec/crowdsec \\
  --namespace crowdsec --create-namespace \\
  --set agent.acquisition[0].namespace=ingress-nginx \\
  --set agent.acquisition[0].podName=ingress-nginx-* \\
  --set lapi.replicas=2 \\
  --set lapi.persistentVolume.enabled=true \\
  --set agent.tolerations[0].key=node-role.kubernetes.io/control-plane \\
  --set agent.tolerations[0].effect=NoSchedule

# Verify
kubectl get pods -n crowdsec
kubectl logs -n crowdsec daemonset/crowdsec-agent
"""

    VALUES = """
# values.yaml — Custom Helm values
lapi:
  replicas: 2
  resources:
    requests:
      cpu: 200m
      memory: 256Mi
    limits:
      cpu: 1000m
      memory: 1Gi
  persistentVolume:
    enabled: true
    size: 5Gi

agent:
  tolerations:
    - key: node-role.kubernetes.io/control-plane
      effect: NoSchedule
  resources:
    requests:
      cpu: 100m
      memory: 128Mi
  env:
    - name: COLLECTIONS
      value: "crowdsecurity/linux crowdsecurity/nginx crowdsecurity/k8s-audit"

  acquisition:
    - namespace: ingress-nginx
      podName: "ingress-nginx-controller-*"
      program: nginx
    - namespace: default
      podName: "*"
      program: syslog
"""

    def show_commands(self):
        print("=== Helm Installation ===")
        print(self.COMMANDS[:400])

    def show_values(self):
        print(f"\n=== Custom Values ===")
        print(self.VALUES[:500])

helm = HelmInstall()
helm.show_commands()
helm.show_values()

Monitoring & Alerts

# monitoring.py — CrowdSec monitoring
import json
import random

class CrowdSecMonitoring:
    def dashboard(self):
        print("=== CrowdSec Dashboard ===\n")
        metrics = {
            "Total decisions (blocks)": random.randint(500, 5000),
            "Active ban IPs": random.randint(50, 500),
            "Alerts today": random.randint(10, 100),
            "Top scenario": "crowdsecurity/http-bad-user-agent",
            "Community blocklist IPs": f"{random.randint(50, 200)}K",
            "Agents connected": random.randint(3, 10),
        }
        for m, v in metrics.items():
            print(f"  {m}: {v}")

    def top_attacks(self):
        print(f"\n=== Top Attack Scenarios ===")
        scenarios = [
            {"name": "http-bad-user-agent", "count": random.randint(100, 500), "action": "ban 4h"},
            {"name": "http-probing", "count": random.randint(50, 300), "action": "ban 4h"},
            {"name": "ssh-bf", "count": random.randint(20, 100), "action": "ban 24h"},
            {"name": "http-crawl-non-statics", "count": random.randint(30, 200), "action": "ban 1h"},
            {"name": "http-sqli-probing", "count": random.randint(10, 80), "action": "ban 24h"},
        ]
        for s in scenarios:
            print(f"  [{s['count']:>4}] {s['name']} → {s['action']}")

    def cscli_commands(self):
        print(f"\n=== cscli Commands ===")
        cmds = [
            "cscli decisions list          # ดู active decisions",
            "cscli alerts list             # ดู alerts",
            "cscli metrics                 # ดู metrics",
            "cscli bouncers list           # ดู connected bouncers",
            "cscli hub list                # ดู installed collections",
            "cscli decisions add --ip 1.2.3.4 --duration 24h  # Manual ban",
        ]
        for cmd in cmds:
            print(f"  $ {cmd}")

mon = CrowdSecMonitoring()
mon.dashboard()
mon.top_attacks()
mon.cscli_commands()

Bouncer Configuration

# bouncer.py — CrowdSec bouncer setup
import json

class BouncerSetup:
    NGINX_BOUNCER = """
# Nginx Ingress Bouncer
# Install via Helm
helm install crowdsec-bouncer crowdsec/crowdsec-bouncer-nginx \\
  --namespace crowdsec \\
  --set config.crowdsecLapiUrl=http://crowdsec-lapi:8080 \\
  --set config.crowdsecLapiKey=

# Or as annotation on Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  annotations:
    nginx.ingress.kubernetes.io/lua-resty-waf: "active"
"""

    TRAEFIK_BOUNCER = """
# Traefik Bouncer (Middleware)
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
  name: crowdsec-bouncer
  namespace: crowdsec
spec:
  plugin:
    crowdsec-bouncer:
      crowdsecLapiUrl: http://crowdsec-lapi:8080
      crowdsecLapiKey: ""
      updateIntervalSeconds: 15
"""

    def show_nginx(self):
        print("=== Nginx Bouncer ===")
        print(self.NGINX_BOUNCER[:400])

    def show_traefik(self):
        print(f"\n=== Traefik Bouncer ===")
        print(self.TRAEFIK_BOUNCER[:300])

bouncer = BouncerSetup()
bouncer.show_nginx()
bouncer.show_traefik()

FAQ - คำถามที่พบบ่อย

Q: CrowdSec กับ Fail2Ban อันไหนดีกว่า?

A: CrowdSec: community blocklists, multi-server, API-driven, Kubernetes-native Fail2Ban: simpler, single server, ไม่มี community sharing ใช้ CrowdSec: production, multi-server, Kubernetes ใช้ Fail2Ban: single VPS, simple setup CrowdSec มี Fail2Ban-compatible scenarios ใช้ migrate ได้ง่าย

Q: ทำไมต้องใช้ DaemonSet สำหรับ agent?

A: DaemonSet รับประกันว่า agent รันบนทุก node ทุก node มี logs ที่ต้อง monitor ถ้าใช้ Deployment อาจมี nodes ที่ไม่มี agent → blind spot ใช้ tolerations เพื่อรันบน control-plane nodes ด้วย

Q: CrowdSec ใช้ resources มากไหม?

A: Agent: 100-500m CPU, 128-512Mi RAM ต่อ node LAPI: 200m-1G CPU, 256Mi-1Gi RAM (ขึ้นอยู่กับ decisions) Bouncer: minimal (แค่ query LAPI) รวม: น้อยกว่า commercial IPS/WAF มาก

Q: Community blocklist ปลอดภัยไหม?

A: ปลอดภัย CrowdSec ใช้ consensus mechanism: IP ต้องถูก report จากหลาย sources False positive rate ต่ำ (< 0.1%) สามารถ whitelist IPs ที่ต้องการได้ ใช้ร่วมกับ local decisions สำหรับ defense-in-depth

📖 บทความที่เกี่ยวข้อง

Crowdsec IPS Agile Scrum Kanbanอ่านบทความ → Crowdsec IPS Backup Recovery Strategyอ่านบทความ → Fivetran Connector Pod Schedulingอ่านบทความ → GraphQL Federation Pod Schedulingอ่านบทความ → ClickHouse Analytics Pod Schedulingอ่านบทความ →

📚 ดูบทความทั้งหมด →