이번 글에서는 저번에 구현한 Daum News Crawler 를 Kubernetes Cluster 상에 띄우는 작업을 진행하겠습니다. 크롤러를 쉬지 않고 작동되도록 할 수 있으나, 해당 사이트에 부담을 줄이기 위해 일정 시간간격마다 작동되도록 하려고 합니다. 이를 위해서는 Deployment 보다 CronJob 으로 배포하는 것이 효율적입니다. 리눅스의 CronTab 에 등록하는 작업만큼 간단합니다. 이 작업을 진행해보도록 하겠습니다.

  • DockerFile 작성

DockerFile 은 기존에 작업한 daum_news_crawler 의 github 최상위 경로에 두도록 하겠습니다.

FROM ubuntu:20.04

ARG DEBIAN_FRONTEND=noninteractive
RUN apt-get update && apt-get install -y \
git \
python3 \
python3-dev \
python3-pip \
libxml2-dev \
libxslt1-dev \
zlib1g-dev \
libffi-dev \
libssl-dev \
vim \
default-libmysqlclient-dev \
build-essential \
&& rm -rf /var/lib/apt/lists/*

RUN pip install scrapy SQLAlchemy mysqlclient

RUN mkdir -p /workspace/daum_news_crawler
RUN git clone -b release --single-branch https://github.com/truelifer/daum_news_crawler.git /workspace/daum_news_crawler
WORKDIR /workspace/daum_news_crawler/daum_news_crawler

CMD ["scrapy", "crawl", "daum_news_crawler"]

ubuntu 20.04 베이스로 생성합니다. apt-get 과정중에 tzdata 라는 패키지를 설치하게 되는데 지역정보를 interactive 하게 넣어주는 과정이 있습니다. 이를 생략하기 위해 DEBIAN_FRONTEND 를 ARG 로 넣어줍니다. apt-get 과 pip 로 필요한 패키지를 설치한 후 작업디렉터리로 /workspace/daum_news_crawler 를 지정해 줍니다. 그리고 git clone 으로 소스를 받아온 후 scrapy 명령을 통해 daum_news_crawler 를 실행시키는 간단한 작업입니다.

  • Image Build

위에서 작성한 Dockerfile 을 가지고 Image 를 빌드합니다.

$ sudo docker build -t truelifer-registry.com:8090/daum_news_crawler:$(git log -1 --format=%h) .$ sudo docker build -t truelifer-registry.com:8090/daum_news_crawler:latest .

이전 글에서 구축한 Docker Private Registry 에 push 하기 위해 Registry 의 주소와 적당한 이름, 그리고 버전을 입력합니다. 일반적으로 버전은 git 의 최신 commit 의 shortened hash 값을 사용합니다. latest 버전도 추가로 tagging 해줍니다.

  • Private Repository 에 Image Push
$ sudo docker push truelifer-registry.com:8090/daum_news_crawler:$(git log -1 --format=%h)$ sudo docker push truelifer-registry.com:8090/daum_news_crawler:latest

위에서 build 한 최신버전의 image 를 Registry 에 push해줍니다.

  • ConfigMap, Secret 생성

daum_news_crawler 의 소스코드에서는 db connection 정보를 환경변수에서 읽어오도록 코딩했습니다. 이 환경변수를 kubernetes 의 Configmap 과 Secret 를 통해서 주입해주도록 하겠습니다.

$ kubectl create configmap configmap-daum-news-crawler --from-literal DAUM_NEWS_CRAWLER_DB_USER=truelifer --from-literal DAUM_NEWS_CRAWLER_DB=daum_news --from-literal DAUM_NEWS_CRAWLER_DB_HOST=truelifer.iptime.org --from-literal DAUM_NEWS_CRAWLER_DB_PORT=3306

먼저 DB Connection 정보를 Configmap 으로생성합니다.

$ kubectl create secret generic secret-daum-news-crawler --from-literal DAUM_NEWS_CRAWLER_DB_PW={비밀번호}

그리고 나서 DB Password 를 Secret 으로 생성합니다.

  • 작업폴더 설정
$ sudo mkdir -p /workspace/kubernetes/daum-news-crawler
$ sudo chown -R truelifer:truelifer /workspace/kubernetes
$ cd /workspace/kubernetes/daum-news-crawler

먼저 daum-news-crawler 배포를 위한 폴더를 생성 후 적절한 권한을 설정해줍니다.

  • CronJob 생성

이제 CronJob 을 생성해보도록 하겠습니다.

$ vi cronjob-daum-news-crawler.yaml

vi 편집기로 Cronjob 생성을 위한 yaml 파일을 생성합니다.

apiVersion: batch/v1
kind: CronJob
metadata:
name: daum-news-crawler
spec:
schedule: "* */1 * * *"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: daum-news-crawler
image: truelifer-registry.com:8090/daum_news_crawler:latest
env:
- name: DAUM_NEWS_CRAWLER_DB_USER
valueFrom:
configMapKeyRef:
name: configmap-daum-news-crawler
key: DAUM_NEWS_CRAWLER_DB_USER
- name: DAUM_NEWS_CRAWLER_DB
valueFrom:
configMapKeyRef:
name: configmap-daum-news-crawler
key: DAUM_NEWS_CRAWLER_DB
- name: DAUM_NEWS_CRAWLER_DB_HOST
valueFrom:
configMapKeyRef:
name: configmap-daum-news-crawler
key: DAUM_NEWS_CRAWLER_DB_HOST
- name: DAUM_NEWS_CRAWLER_DB_PORT
valueFrom:
configMapKeyRef:
name: configmap-daum-news-crawler
key: DAUM_NEWS_CRAWLER_DB_PORT
- name: DAUM_NEWS_CRAWLER_DB_PW
valueFrom:
secretKeyRef:
name: secret-daum-news-crawler
key: DAUM_NEWS_CRAWLER_DB_PW

1시간마다 작동되도록 Schedule 을 작성하고 실패시 재시작되도록 restartPolicy 를 설정합니다. 만약 새로운 job 이 스케줄될 시간인데 이전 job 이 완료되지 않았다면 새로운 job 은 스킵하도록 concurrencyPolicy 를 Forbid 로 설정합니다. 컨테이너 스펙에 이미지 이름을 넣고 configmap, secret 으로 생성했던 값들을 환경변수로 주입합니다.

$ kubectl apply -f ./cronjob-daum-news-crawler.yaml

kubectl 명령을 통해 Cronjob 를 생성해 줍니다.

cronjob.batch/daum-news-crawler created

정상적으로 생성이 되었다면 위와 같은 메세지가 출력됩니다.

  • 테스트

위에서 cronjob 을 생성했다면 정해진 시간마다 job 이 생성되고 pod 이 생성됩니다.

$ kubectl get cronjobs

생성된 cronjob 을 확인합니다.

NAME SCHEDULE SUSPEND ACTIVE LAST SCHEDULE AGE
daum-news-crawler * */1 * * * False 1 5m28s 5m56s
$ kubectl get jobs

생성된 job 을 확인합니다.

NAME                         COMPLETIONS   DURATION   AGE
daum-news-crawler-27122554 0/1 5m33s 5m33s
$ kubectl get pods

생성된 pod 을 확인합니다.

NAME                               READY   STATUS    RESTARTS   AGE
daum-news-crawler-27122554-ggfsn 1/1 Running 0 5m36s
$ kubectl logs -f daum-news-crawler-27122554-ggfsn

pod 의 로그를 확인합니다.

2021-07-27 02:42:45 [daum_news_crawler] INFO: [parse_news] : https://news.v.daum.net/v/20210727071846573
2021-07-27 02:42:46 [daum_news_crawler] INFO: [parse_news] : https://news.v.daum.net/v/20210727062946997
2021-07-27 02:42:46 [daum_news_crawler] INFO: [parse_news] : https://news.v.daum.net/v/20210727071610548
2021-07-27 02:42:46 [daum_news_crawler] INFO: [parse_news] : https://news.v.daum.net/v/20210727070823456
2021-07-27 02:42:46 [daum_news_crawler] INFO: [parse_news] : https://news.v.daum.net/v/20210727072352625
.
.
.
.

정상적으로 뉴스가 스크랩되는 로그를 확인할 수 있습니다.

gui 툴을 통해 database 에 저장된 data 도 정상적으로 확인됩니다.

  • 마무리

이로써 한 시간에 한번씩 daum 의 뉴스를 스크랩하는 크롤러가 Kubernetes Cluster 상에 배포되었습니다. 다음 글에서는 배포 자동화를 위한 첫 작업으로 Jenkins 를 설치해보도록 하겠습니다.

--

--