一. 概述
因為學習了 docker
和 k8s
,不管什麼專案都想使用容器化部署?,一個最主要的原因是,使用容器化部署是真的方便?。上一篇文章 【爬蟲】從零開始使用 Scrapy 介紹瞭如何使用 scrapy
,如果需要啟動或者定時執行 scrapy
專案可以部署如下兩個元件:
scrapyd
:它本質上就是幫我們執行了scrapy crawl spidername
這個命令來啟動scrapy
專案。spiderkeeper
:它是scrapy
專案的視覺化管理工具。
scrapyd
原始碼地址:https://github.com/scrapy/scrapyd
spiderkeeper
原始碼地址:https://github.com/DormyMo/SpiderKeeper
如果我們要將 scrapy
專案部署到 k8s
,那麼就需要將 scrapyd
和 spiderkeeper
部署到 k8s
上面,這篇文章將通過如下內容進行介紹:
- 自定義
scrapyd
的映象並上傳到docker hub
- 自定義
spiderkeeper
的映象並上傳到docker hub
- 部署
scrapyd
到k8s
- 部署
spiderkeeper
到k8s
- 專案驗證是否部署成功
- 總結
環境說明
作業系統:Windows 10
安裝的元件:
- Docker Desktop :在
windows
系統中執行docker
,便於在本地構建和推送映象 - minikube :在
windows
系統中執行本地k8s
環境,和其他k8s
叢集使用方式是一樣的,這裡為了方便測試驗證
二. 自定義 scrapyd
的映象
如果要自定義 scrapyd
的映象,我們需要知道 scrapyd
在伺服器上面是怎樣安裝的,查閱官方文件
scrapyd
官方文件:https://scrapyd.readthedocs.io/en/stable/install.html
這裡我們構建 scrapyd
的映象需要定義三個檔案:
Dockerfile
:構建映象的檔案scrapyd.conf
:scrapyd 的配置檔案requirements.txt
:python 的依賴包管理檔案
Dockerfile
檔案內容如下:
FROM python:3.7
COPY scrapyd.conf /etc/scrapyd/scrapyd.conf
COPY requirements.txt requirements.txt
RUN pip install --upgrade pip && pip install -i https://mirrors.aliyun.com/pypi/simple -r requirements.txt
EXPOSE 6800
CMD scrapyd
scrapyd.conf
檔案是 scrapyd
的配置檔案,在 Unix
系統中會在 /etc/scrapyd/scrapyd.conf
檔案中讀取配置,官方文件的說明如下圖:
因為 scrapyd.conf
檔案中的 bind_address 的值預設為 127.0.0.1
,它只能在本機訪問,如果部署到 docker 容器中,則只能在容器內部訪問,所以我們需要修改 scrapyd.conf
檔案中的 bind_address 的值為 0.0.0.0
,以便外部服務能夠訪問 scrapyd
,修改後的 scrapyd.conf
檔案內容如下:
[scrapyd]
eggs_dir = eggs
logs_dir = logs
items_dir =
jobs_to_keep = 5
dbs_dir = dbs
max_proc = 0
max_proc_per_cpu = 4
finished_to_keep = 100
poll_interval = 5.0
bind_address = 0.0.0.0
http_port = 6800
debug = off
runner = scrapyd.runner
application = scrapyd.app.application
launcher = scrapyd.launcher.Launcher
webroot = scrapyd.website.Root
[services]
schedule.json = scrapyd.webservice.Schedule
cancel.json = scrapyd.webservice.Cancel
addversion.json = scrapyd.webservice.AddVersion
listprojects.json = scrapyd.webservice.ListProjects
listversions.json = scrapyd.webservice.ListVersions
listspiders.json = scrapyd.webservice.ListSpiders
delproject.json = scrapyd.webservice.DeleteProject
delversion.json = scrapyd.webservice.DeleteVersion
listjobs.json = scrapyd.webservice.ListJobs
daemonstatus.json = scrapyd.webservice.DaemonStatus
由於我們的 scrapy
專案是在 scrapyd
容器中執行,而我們上傳到 scrapyd
中的是 scrapy
專案的原始碼,如果要正確的執行 scrapy
專案,需要在 scrapyd
的容器中安裝相關的依賴,這裡將相關的依賴定義在 requirements.txt
檔案中, requirements.txt
檔案中的內容如下:
scrapyd~=1.2.1
beautifulsoup4~=4.10.0
requests~=2.26.0
chardet~=3.0.4
lxml~=4.7.1
pymongo==3.5.1
如果你的 scrapy
專案有其他依賴,那麼需要在 requirements.txt
檔案中新增相關依賴,並重新構建 scrapyd
的映象。
定義好上面的三個檔案之後,在 Dockerfile
檔案所在的位置執行下面的命令構建 scrapyd
的映象:
docker build -t scrapyd .
構建完成映象後,可以通過下面的命令檢視映象:
docker images |grep scrapyd
如果需要推送映象到遠端倉庫需要給映象打上標籤,使用如下命令 Usage: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
:
docker tag scrapyd wangedison98/scrapyd
使用如下命令推送映象到遠端倉庫,這裡根據需要推送到你自己的 docker hub
倉庫:
docker push wangedison98/scrapyd
三. 自定義 spiderkeeper 的映象
自定義 spiderkeeper 的映象和構建 scrapyd 的 映象一樣,首先需要知道 spiderkeeper 在伺服器上面是怎樣安裝的,查閱官方文件:
spiderkeeper 的安裝地址:https://github.com/DormyMo/SpiderKeeper
根據官方文件可以知道 spiderkeeper 的安裝方式為 pip install spiderkeeper
,所以 Dockerfile 檔案內容如下:
FROM python:3.7
WORKDIR /home/spiderkeeper
RUN pip install spiderkeeper
EXPOSE 5000
ENV SERVER http://localhost:6800
ENV USERNAME admin
ENV PASSWORD admin
CMD ["sh", "-c", "spiderkeeper --username=$USERNAME --password=$PASSWORD --server=$SERVER"]
使用如下命令構建 spiderkeeper 的映象:
docker build -t spiderkeeper .
發現構建過程中報出如下錯誤:
ERROR: Could not find a version that satisfies the requirement MarkupSafe==1.0 (from spiderkeeper)
ERROR: No matching distribution found for MarkupSafe==1.0
從報錯的內容可以知道無法下載 MarkupSafe==1.0
的依賴包,去到 pypi 官網搜尋 MarkupSafe 發現有相關的版本,如下圖所示:
所以如果要解決這個問題,我們需要修改 spiderkeeper
依賴包的版本,給專案的作者提交了升級依賴的 PR
,但是作者並沒有合併,這種情況下我打算自己將升級依賴後的 spiderkeeper
推送到 pypi
官網,查閱了一些資料實現了這個方法,後面會寫一篇文章介紹如何推送自己的 python
包到 pypi
官網,下面就是我自己推送的 spiderkeeper-new
:
下面就是使用自己定義的 spiderkeeper-new
來構建映象,Dockerfile
的內容如下:
FROM python:3.7
WORKDIR /home/db
RUN pip install -i https://pypi.org/simple/ SpiderKeeper-new
EXPOSE 5000
ENV SERVER http://localhost:6800
ENV USERNAME admin
ENV PASSWORD admin
CMD ["sh", "-c", "spiderkeeper --username=$USERNAME --password=$PASSWORD --server=$SERVER"]
在 Dockerfile
檔案所在位置,再次使用如下命令構建 spiderkeeper
映象:
docker build -t spiderkeeper .
構建完成後可以使用如下命令檢視 spiderkeeper 映象:
docker images |grep spiderkeeper
如果需要推送映象到遠端倉庫需要給映象打上標籤,使用如下命令 Usage: docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
:
docker tag spiderkeeper wangedison98/spiderkeeper
使用如下命令推送映象到遠端倉庫,這裡根據需要推送到你自己的 docker hub
倉庫:
docker push wangedison98/spiderkeeper
四. 部署 scrapyd 到 k8s
要部署 scrapyd
到 k8s
只需要定義一個 deployment.yaml
檔案,檔案的內容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: scrapyd
namespace: default
labels:
app: scrapyd
spec:
replicas: 1
selector:
matchLabels:
app: scrapyd
template:
metadata:
labels:
app: scrapyd
spec:
containers:
- name: scrapyd
image: wangedison98/scrapyd:latest
imagePullPolicy: Always
env:
- name: TZ
value: Asia/Shanghai
- name: NAMESPACE
value: default
ports:
- containerPort: 6800
name: http-port
---
apiVersion: v1
kind: Service
metadata:
name: scrapyd
namespace: default
labels:
app: scrapyd
spec:
ports:
- name: port
port: 80
protocol: TCP
targetPort: 6800
- name: port2
port: 6800
protocol: TCP
targetPort: 6800
selector:
app: scrapyd
type: ClusterIP
在 k8s 中執行下面的命令即可部署 scrapyd:
kubectl apply -f deployment.yaml
五. 部署 spiderkeeper 到 k8s
要部署 spiderkeeper
到 k8s
只需要建立一個 deployment.yaml
檔案,檔案內容如下:
apiVersion: apps/v1
kind: Deployment
metadata:
name: spiderkeeper
namespace: default
labels:
app: spiderkeeper
spec:
replicas: 1
selector:
matchLabels:
app: spiderkeeper
template:
metadata:
labels:
app: spiderkeeper
spec:
containers:
- name: spiderkeeper
image: wangedison98/spiderkeeper:latest
imagePullPolicy: Always
env:
- name: TZ
value: Asia/Shanghai
- name: NAMESPACE
value: default
- name: SERVER
value: http://scrapyd:6800
- name: USERNAME
value: admin
- name: PASSWORD
value: admin
ports:
- containerPort: 5000
name: http-port
---
apiVersion: v1
kind: Service
metadata:
name: spiderkeeper
namespace: default
labels:
app: spiderkeeper
spec:
ports:
- name: port
port: 80
protocol: TCP
targetPort: 5000
- name: port2
port: 5000
protocol: TCP
targetPort: 5000
selector:
app: spiderkeeper
type: ClusterIP
在 k8s
中執行下面的命令即可部署 spiderkeeper
:
kubectl apply -f deployment.yaml
六. 專案驗證
通過前面的步驟已經將 scrapyd
和 spiderkeeper
部署到 k8s
叢集了,我們可以通過如下方式暴露服務:
ingress
(推薦)- 設定
service
的type
為NodePort
- 使用
kubectl port-forward TYPE/NAME
臨時暴露服務
因為我這裡使用的是 minikube
所以,可以使用 minikube service [flags] SERVICE [options]
臨時暴露服務,使用如下命令:
minikube service spiderkeeper
之後就可以根據返回的地址和埠訪問 spiderkeeper
服務,預設的使用者名稱和密碼為:admin
,登入成功後如下圖所示:
點選 Create Project
,建立一個 test 專案:
在 scrapy 專案中使用 scrapyd-deploy --build-egg output.egg
生成部署檔案並上傳:
七. 總結
本文詳細描述瞭如何將 scrapy
專案部署到 k8s
叢集,其中遇到的難點就是官方給出的 spiderkeeper
無法成功構建映象,所以通過自己下載原始碼,升級相關依賴,推送了一個新的 spiderkeeper
用來構建映象,這裡沒有介紹相關流程,下一篇檔案將會講解如何實現推送 python
包到 pypi
官網。如果你對 docker
和 k8s
比較瞭解,其他的就沒有什麼難點了,其中有一點值得說明一下,這裡是將 scrapyd
和 spiderkeeper
分開部署的,通過它們之間通過 servicename
進行通訊,k8s
的 service
提供了負載均衡的能力,所以當有大量 scrapy
專案需要部署的時候,你可能認為通過增加 scrapyd
的副本數就可以了,但是預設情況下 spiderkeeper
使用的資料庫是 sqlite
,儲存的資料儲存在容器內部無法共享,就會導致一個問題,在 spiderkeeper
中無法看到所有的 scrapy
專案,只能看到它連線的那個 scrapyd
中的專案,為了解決這個問題,你可以使用 mysql
作為 spiderkeeper
的外部資料庫,這樣應該可以實現資料共享,具體實現就不在這裡介紹了。
還有一個管理 scrapy
專案的工具,叫做 Gerapy
,也可以瞭解一下,如果有空可以寫一篇檔案介紹一下在 k8s
中的使用流程。
Gerapy 原始碼地址:https://github.com/Gerapy/Gerapy