容器化爬虫部署:基于K8s的任务调度与自动扩缩容设计

本文涉及的产品
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
Elasticsearch Serverless检索通用型,资源抵扣包 100CU*H
实时数仓Hologres,5000CU*H 100GB 3个月
简介: 随着业务复杂度提升,传统定时任务和手工扩缩容难以满足高并发与实时性需求。本文对比两种基于 Kubernetes 的爬虫调度与扩缩容方案:CronJob+HPA 和 KEDA。从调度灵活性、扩缩容粒度、实现难度等维度分析,并提供 YAML+Python 示例。方案 A(CronJob+HPA)适合固定定时任务,配置简单;方案 B(KEDA)支持事件驱动,适合高并发与异步触发场景。根据实际需求可混合使用,优化资源利用与效率。

爬虫代理.png

摘要
随着业务复杂度提升,单纯依靠定时任务和手工扩缩容已无法满足高并发、实时性和资源利用效率需求。本篇文章比较了两种基于 Kubernetes 的容器化爬虫调度与扩缩容方案:一种是利用 Kubernetes 原生的 CronJob 与 Horizontal Pod Autoscaler(HPA);另一种是基于 KEDA(Kubernetes Event‑Driven Autoscaling)的事件驱动扩缩容。文章从调度灵活性、扩缩容粒度、实现难度、成本效率和生态成熟度五个维度进行对比,并给出完整的 YAML+Python 对比示例及推荐场景,帮助读者在不同业务场景下做出最佳选型。


1. 选型背景

在分布式爬虫项目中,常见需求包括:

  • 定时触发:夜间全量抓取或定时增量更新
  • 动态扩缩容:根据任务队列积压或业务高峰动态调度更多爬虫容器
  • 资源管控:控制并发爬取速率,避免目标站点封禁
  • 监控告警:对失败率、时延、资源使用进行实时监控

传统做法常借助单机定时脚本 + Docker Compose,或自行编写调度器。但随着爬取量和业务复杂度增长,出现以下痛点:

  1. 扩缩容延迟高:无法根据实时负载灵活伸缩,资源浪费或爬取缓慢。
  2. 监控耦合度高:自研监控难与容器平台打通。
  3. 维护成本大:需要额外开发和运维管理。

因此,引入 Kubernetes 原生能力或 KEDA 事件驱动扩缩容成为可选方案。


2. 技术对比维度

维度 CronJob + HPA KEDA Event‑Driven
调度灵活性 基于 Cron 表达式,适合固定时段触发 支持多种事件源(队列长度、Kafka、Prometheus 指标等)
扩缩容粒度 HPA 支持基于 CPU/内存等指标 支持自定义指标(队列长度、HTTP 请求数)
实现难度 配置相对简单,Kubernetes 原生,无额外组件 需部署 KEDA 控制器,多一层依赖
成本效率 只付 Kubernetes 成本 多部署 KEDA 组件,成本略增
社区生态成熟度 Kubernetes 官方,生态完善 KEDA 社区活跃,官方背书

3. 代码对比示例

3.1 方案 A:Kubernetes CronJob+HorizontalPodAutoscaler

3.1.1 Kubernetes 资源定义

# cronjob-hpa.yaml
apiVersion: batch/v1
kind: CronJob
metadata:
  name: tianyancha-crawler
spec:
  schedule: "0 2 * * *"                  # 每天凌晨 2 点触发
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: crawler
            image: your-registry/tianyancha-crawler:latest
            env:
            - name: PROXY_HOST # 参考亿牛云代理 www.16yun.cn
              value: "proxy.16yun.cn" # 代理域名
            - name: PROXY_PORT
              value: "12345"              # 端口
            - name: PROXY_USER
              value: "16YUN"      # 用户名
            - name: PROXY_PASS
              value: "16IP"      # 密码
          restartPolicy: OnFailure
---
apiVersion: autoscaling/v2
kind: HorizontalPodAutoscaler
metadata:
  name: crawler-hpa
spec:
  scaleTargetRef:
    apiVersion: batch/v1
    kind: CronJob
    name: tianyancha-crawler
  minReplicas: 1
  maxReplicas: 5
  metrics:
  - type: Resource
    resource:
      name: cpu
      target:
        type: Utilization
        averageUtilization: 50        # CPU 利用率超过 50% 时扩容

3.1.2 Python 爬虫脚本(crawler.py)

# -*- coding: utf-8 -*-
import os
import requests
from bs4 import BeautifulSoup
import json

# —— 参考亿牛云代理配置 www.16yun.cn ——
PROXY_HOST = os.getenv("proxy.16yun.cn")
PROXY_PORT = os.getenv("8100")
PROXY_USER = os.getenv("16YUN")
PROXY_PASS = os.getenv("16IP")
proxy_url = f"http://{PROXY_USER}:{PROXY_PASS}@{PROXY_HOST}:{PROXY_PORT}"
proxies = {
   "http": proxy_url, "https": proxy_url}

# —— HTTP 请求头 & Cookie ——
headers = {
   
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36",
}
cookies = {
   
    # 如果需要登录后 Cookie,可在此添加,如 {"_csrf_token": "xxx"}
}

def fetch_company_info(name):
    """根据公司名称抓取天眼查信息并返回 dict"""
    url = f"https://www.tianyancha.com/search?key={name}"
    resp = requests.get(url, headers=headers, cookies=cookies, proxies=proxies, timeout=15)
    soup = BeautifulSoup(resp.text, "lxml")

    # 示例解析逻辑(请根据真实页面结构调整)
    item = soup.select_one(".search-result-single")
    data = {
   
        "name": name,
        "credit_code": item.select_one(".credit-code").get_text(strip=True),
        "phone": item.select_one(".phone").get_text(strip=True),
        "legal_person": item.select_one(".legal-person").get_text(strip=True),
        "email": item.select_one(".email").get_text(strip=True),
        "registered_capital": item.select_one(".registered-capital").get_text(strip=True),
        "website": item.select_one(".website a")["href"],
        "established_date": item.select_one(".established-date").get_text(strip=True),
        "address": item.select_one(".address").get_text(strip=True),
        "description": item.select_one(".description").get_text(strip=True),
    }
    return data

def main():
    company_list = ["示例公司A", "示例公司B"]  # 可从文件、消息队列读取
    results = []
    for name in company_list:
        info = fetch_company_info(name)
        results.append(info)
    # 分类存储:根据注册资本大小分文件(示例)
    big = [r for r in results if float(r["registered_capital"].rstrip("万")) > 1000]
    small = [r for r in results if float(r["registered_capital"].rstrip("万")) <= 1000]
    with open("/data/big_company.json", "w", encoding="utf-8") as f:
        json.dump(big, f, ensure_ascii=False, indent=2)
    with open("/data/small_company.json", "w", encoding="utf-8") as f:
        json.dump(small, f, ensure_ascii=False, indent=2)

if __name__ == "__main__":
    main()

3.2 方案 B:KEDA 事件驱动扩缩容

3.2.1 Kubernetes 资源定义

# crawler-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: tianyancha-crawler
spec:
  replicas: 1
  selector:
    matchLabels:
      app: crawler
  template:
    metadata:
      labels:
        app: crawler
    spec:
      containers:
      - name: crawler
        image: your-registry/tianyancha-crawler:latest
        env:
        - name: PROXY_HOST
          value: "proxy.yiniuyun.com"
        - name: PROXY_PORT
          value: "12345"
        - name: PROXY_USER
          value: "your_username"
        - name: PROXY_PASS
          value: "your_password"
---
apiVersion: keda.sh/v1alpha1
kind: ScaledObject
metadata:
  name: crawler-scaledobject
spec:
  scaleTargetRef:
    apiVersion: apps/v1
    kind: Deployment
    name: tianyancha-crawler
  minReplicaCount: 1
  maxReplicaCount: 10
  triggers:
  - type: prometheus                   # 基于 Prometheus 自定义指标
    metadata:
      serverAddress: http://prometheus-operated.monitoring.svc:9090
      metricName: crawler_queue_length
      threshold: "50"
      query: sum(queue_length{
   job="tianyancha"})

说明:将爬虫任务推入消息队列(如 Kafka/RabbitMQ)或对 Prometheus 指标埋点,KEDA 根据队列深度或自定义指标自动扩缩容。

3.2.2 Python 爬虫脚本(同 3.1.2,可复用)

脚本可与方案 A 完全一致,部署方式和扩缩容策略不同,无需调整业务代码。


4. 场景推荐

  • 固定定时全量抓取,资源消耗可预估:选择 CronJob+HPA。配置简单、易于运维。
  • 异步消息队列触发或高峰期秒级拓展:选择 KEDA。支持多种事件源,扩缩容更灵活。
  • 对运维成本敏感,已有 Prometheus 监控体系:CronJob+HPA 即可满足多数需求。
  • 需支持复杂业务触发(如 Kafka 消息、数据库表行数等):KEDA 更能“一站式”接入。

5. 结论

  • 方案 A(CronJob+HPA):上手快、依赖少,适合业务固定且可预估资源的定时爬取场景。
  • 方案 B(KEDA):扩缩容粒度更灵活,事件驱动,适合高并发、异步触发或对接多种指标源的场景。

在实际生产中,可根据任务触发方式、并发峰值、监控体系成熟度及运维成本综合评估,亦可混合使用:核心夜间全量跑 CronJob,增量或高峰实时跑 KEDA。

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
人工智能 Kubernetes jenkins
容器化AI模型的持续集成与持续交付(CI/CD):自动化模型更新与部署
在前几篇文章中,我们探讨了容器化AI模型的部署、监控、弹性伸缩及安全防护。为加速模型迭代以适应新数据和业务需求,需实现容器化AI模型的持续集成与持续交付(CI/CD)。CI/CD通过自动化构建、测试和部署流程,提高模型更新速度和质量,降低部署风险,增强团队协作。使用Jenkins和Kubernetes可构建高效CI/CD流水线,自动化模型开发和部署,确保环境一致性并提升整体效率。
|
17天前
|
存储 Kubernetes 异构计算
Qwen3 大模型在阿里云容器服务上的极简部署教程
通义千问 Qwen3 是 Qwen 系列最新推出的首个混合推理模型,其在代码、数学、通用能力等基准测试中,与 DeepSeek-R1、o1、o3-mini、Grok-3 和 Gemini-2.5-Pro 等顶级模型相比,表现出极具竞争力的结果。
|
1月前
|
Kubernetes 调度 异构计算
生产环境 K8S + Deepseek 实现大模型部署 和 容器调度(图解+史上最全)
生产环境 K8S + Deepseek 实现大模型部署 和 容器调度(图解+史上最全)
生产环境 K8S + Deepseek 实现大模型部署 和 容器调度(图解+史上最全)
|
28天前
|
存储 数据安全/隐私保护 开发者
领取永久免费的ClawCloud云服务容器部署Alist网盘
领取永久免费的ClawCloud云服务容器部署Alist网盘,这是一款类似于 Vercel 和 Netlify 的在线开发平台,专为开发者和个人用户设计。如 Alist、Dify、frp 等,无需复杂的配置或高昂的成本。目前,平台提供永久免费的 5 刀/月额度,只需绑定一个注册超过 180 天的 GitHub 账号即可享受。
903 10
|
2月前
|
存储 测试技术 对象存储
使用容器服务ACK快速部署QwQ-32B模型并实现推理智能路由
阿里云最新发布的QwQ-32B模型,通过强化学习大幅度提升了模型推理能力。QwQ-32B模型拥有320亿参数,其性能可以与DeepSeek-R1 671B媲美。
|
2月前
|
存储 运维 Kubernetes
容器数据保护:基于容器服务 Kubernetes 版(ACK)备份中心实现K8s存储卷一键备份与恢复
阿里云ACK备份中心提供一站式容器化业务灾备及迁移方案,减少数据丢失风险,确保业务稳定运行。
|
3月前
|
机器学习/深度学习 人工智能 Kubernetes
容器化AI模型部署实战:从训练到推理
在上一篇中,我们探讨了AI技术如何赋能容器化生态。本篇聚焦于AI模型的容器化部署,通过图像分类任务实例,详细介绍了从模型训练到推理服务的完整流程。使用PyTorch训练CNN模型,Docker打包镜像,并借助Kubernetes进行编排和部署,最终通过FastAPI提供推理服务。容器化技术极大提升了AI模型部署的便利性和管理效率,未来将成为主流趋势。
|
15天前
|
关系型数据库 MySQL Docker
|
2月前
|
Ubuntu 关系型数据库 MySQL
容器技术实践:在Ubuntu上使用Docker安装MySQL的步骤。
通过以上的操作,你已经步入了Docker和MySQL的世界,享受了容器技术给你带来的便利。这个旅程中你可能会遇到各种挑战,但是只要你沿着我们划定的路线行进,你就一定可以达到目的地。这就是Ubuntu、Docker和MySQL的灵魂所在,它们为你开辟了一条通往新探索的道路,带你亲身感受到了技术的力量。欢迎在Ubuntu的广阔大海中探索,用Docker技术引领你的航行,随时准备感受新技术带来的震撼和乐趣。
124 16
|
2月前
|
监控 关系型数据库 MySQL
zabbix7.0.9安装-以宝塔安装形式-非docker容器安装方法-系统采用AlmaLinux9系统-最佳匹配操作系统提供稳定运行环境-安装教程完整版本-优雅草卓伊凡
zabbix7.0.9安装-以宝塔安装形式-非docker容器安装方法-系统采用AlmaLinux9系统-最佳匹配操作系统提供稳定运行环境-安装教程完整版本-优雅草卓伊凡
151 30