在Kubernetes的数据传输基础上添加了Web数据抓取功能的故事
Selenium/Appium Advent Calendar 201916号已经发布了!(很抱歉遥迟,请多多包涵!)
背景 – 背景资料
我们的产品在k8s(EKS)上构建了数据传输的基础设施。
数据传输是通过k8s的job进行的,并且数据传输的处理使用了Embulk。
我想给大家讲一下这次为数据传输添加爬虫功能的经历。
侧边车模式
出于心理上的原因,我认为不想通过在数据传输的主容器上放置Selenium的Driver来增加其大小。因此,我考虑使用Selenium构建一个基于侧边栏模式的网页抓取基础架构。
如果您想了解更多有关Sidecar的信息,可以阅读Brendan Burns、David Oppenheimer等人撰写的论文《基于容器的分布式系统的设计模式》,或者阅读相关的图书。简单来说,Sidecar是指在Pod中使用辅助容器来支持主要容器的一种架构配置。
在下面的例子中,我们将Web服务器放在主容器上,并将日志保存留给侧边车进行配置。
我們在本次的設計中,將爬取和數據傳輸處理的功能放在主容器中,而將Selenium的執行環境放在另一個容器中,創建了一個類似側載的結構。
关于从网络爬取数据到数据传输的方针
我们公司在数据传输方面使用Embulk。Embulk有一个用于传输本地文件的插件,因此我们决定按照以下策略传输抓取到的数据。
-
- 执行爬虫并将获取的数据转换为JSON数据
- 使用Embulk传输生成的JSON数据
我们将Selenium Grid配置为在Pod上作为执行环境。具体来说,我们在一个Pod上启动了Selenium Hub容器和Node容器。
实际启动
以下是当前正在运行的Pod的描述。
可以看出,在一个Pod中,Selenium Hub和Node作为Sidecar共存。
Name: sample-job-215127-m26g7
Namespace: default
Priority: 0
PriorityClassName: <none>
Node: ip-10-80-88-198.***/10.80.88.198
Start Time: Wed, 18 Dec 2019 01:49:03 +0000
Labels: controller-uid=9187b356-2138-11ea-a061-0e36cb33bc04
job-name=sample-job-215127
prometheus.io/path=metrics
prometheus.io/port=9010
prometheus.io/scrape=true
Annotations: cluster-autoscaler.kubernetes.io/safe-to-evict: false
Status: Running
IP: 10.80.92.39
Controlled By: Job/sample-job-215127
Containers:
worker:
Container ID: docker://4547f0a3b43fbf14c4850e26d71e9db89799f263125d679724e5c1a09289e4d6
Image: ***/worker.beta.sample.io:5c0f855874849b1d29ee5f1fe7c720ca835d60c3
Image ID: docker-pullable://***/worker.beta.sample.io@sha256:9a1771dff18778d1995359dd1eb056d13a2c0f1b7b23a3c03198771ee978024c
Port: 9010/TCP
Host Port: 0/TCP
Args:
sample:run[215127,false]
State: Running
Started: Wed, 18 Dec 2019 01:49:04 +0000
Ready: True
Restart Count: 0
Limits:
cpu: 2
memory: 2Gi
Requests:
cpu: 2
memory: 2Gi
Environment Variables from:
sample-config ConfigMap Optional: false
sample-secret Secret Optional: false
Environment: <none>
Mounts:
/tmp from tmp-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-4nw9k (ro)
selenium:
Container ID: docker://44c1d93596ff64ba63d783801ec4200d6f6fc6445305473904f5ce1e96fd686e
Image: selenium/hub:3.141.59
Image ID: docker-pullable://selenium/hub@sha256:6f6bdd8d5ce5cd8d7be42ded88bc3dbbdf7a60ec32c908eb26dd31b37f69589a
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 18 Dec 2019 01:49:04 +0000
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 2000Mi
Requests:
cpu: 500m
memory: 2000Mi
Environment Variables from:
sample-config ConfigMap Optional: false
sample-secret Secret Optional: false
Environment: <none>
Mounts:
/tmp from tmp-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-4nw9k (ro)
chrome:
Container ID: docker://cd880ec332d2af37efd91535ebdbad0e128295aa58f6255d6c093668306438cf
Image: selenium/node-chrome:3.141.59
Image ID: docker-pullable://selenium/node-chrome@sha256:5e37ffdeae0864dd7f0df63adafcc9428766d79976a645853bc1e20d7487ff4f
Port: <none>
Host Port: <none>
State: Running
Started: Wed, 18 Dec 2019 01:49:04 +0000
Ready: True
Restart Count: 0
Limits:
cpu: 500m
memory: 2000Mi
Requests:
cpu: 500m
memory: 2000Mi
Environment Variables from:
sample-config ConfigMap Optional: false
sample-secret Secret Optional: false
Environment: <none>
Mounts:
/tmp from tmp-volume (rw)
/var/run/secrets/kubernetes.io/serviceaccount from default-token-4nw9k (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
tmp-volume:
Type: EmptyDir (a temporary directory that shares a pod's lifetime)
Medium:
default-token-4nw9k:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-4nw9k
Optional: false
QoS Class: Guaranteed
Node-Selectors: <none>
Tolerations: node.kubernetes.io/not-ready:NoExecute for 300s
node.kubernetes.io/unreachable:NoExecute for 300s
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal Scheduled 18s default-scheduler Successfully assigned default/sample-job-215127-m26g7 to ip-10-80-88-198.***
Normal Pulled 17s kubelet, ip-10-80-88-198.a*** Container image "***/worker.beta.sample.io:5c0f855874849b1d29ee5f1fe7c720ca835d60c3" already present on machine
Normal Created 17s kubelet, ip-10-80-88-198.a*** Created container
Normal Started 17s kubelet, ip-10-80-88-198.a*** Started container
Normal Pulled 17s kubelet, ip-10-80-88-198.a*** Container image "selenium/hub:3.141.59" already present on machine
Normal Created 17s kubelet, ip-10-80-88-198.a*** Created container
Normal Started 17s kubelet, ip-10-80-88-198.a*** Started container
Normal Pulled 17s kubelet, ip-10-80-88-198.a*** Container image "selenium/node-chrome:3.141.59" already present on machine
Normal Created 17s kubelet, ip-10-80-88-198.a*** Created container
Normal Started 17s kubelet, ip-10-80-88-198.a*** Started container
通过这样的配置,我们能够构建出Selenium的执行环境,而不会使主要容器变得庞大。一旦传输完成,我们只需删除Pod,就可以轻松管理且不会残留Selenium环境。
然而,目前在使用侧车配置的Pod中,当主容器结束时,Pod的停止处理并不会同时停止侧车。
在此进行讨论的副手功能直到发布之前需要实施停止处理。
总结
我們談了一個在k8s上的數據傳輸基礎設施中結合Selenium的網絡爬蟲功能的話題。由於相對簡單且易於管理,我們希望能夠在未來以各種方式充分利用這個爬蟲基礎設施。