AWS 上に構築されたシステム間で、データ変換と連携処理を行う開発を行いました。
連携データは S3 上に csv と json 形式で、何種類かのデータを使います。
取り込んだデータは、最終的には、 Athena で検索することに使われるんですが、元データの量が大きいため、効率よく短時間で取り込むために Spark が使いたいなぁという状況でした。
ただ、24時間常時実行される仕組みではないので Spark のためだけに複数台の EC2 を使うのはモッタイないです。
夜間バッチの1~2時間くらい使えればよいので Spark そのものが、サービス化されたものってないのかしら・・・と、AWSを探したところ AWS Glue がズバリそのものでした。
AWS Glue のお試し
さっそく、 Glue をシステムに組み込めそうか、お試しすることにしました。
CSV を Parquet 形式に変換するところに Glue を使ってみます。そして、おぉ、やっぱり速い!
ついでに Parquet 形式になったデータを Athena で検索してみても、おぉ、これも速い!
・・・ということを体感して、イケそうな感触が得られたので、本格的な開発の準備に取り掛かかることにしました。
料金を気にせず開発したい
Spark の開発をやったことのある方ならわかると思うのですが Spark は 大量のメモリを使うので、そのクラスター構成を動かすサービスとなると、利用料も安いハズがないです。
バグで暴走して、ものすごい請求が来た!なんてことになると困ります。ジョブを停止する手順をあらかじめ調べておいて、いざというときには、強制停止できるように準備しておく必要があります。
でも、それでも、”ジョブを実行”する段階では、ビビります。特に開発チームに参加したばかりの人は、実行ボタンを推すときの躊躇いの時間が、初期の立ちあがりの時間を遅くします。
プログラム作りは、ちょっと実装して動かしてみて軌道修正して・・・という作業を繰り返すので、”ためらう”ことなく実行できるローカルの環境があると、安心して試行に取り組めます。
AWS Glue をローカルで動かす
そんなわけで、dockerで実行できるようにしました。
参考にしたのは、この2つの記事です。
https://dev.classmethod.jp/articles/aws-glue-local/
https://future-architect.github.io/articles/20191101/
作成した dockerイメージは、Docker Hub で公開してあります。
Dockerfile は以下のようになりました。
- Glue 1.0 は Python 3.6
- PySparkを使うために、python:3.6 のイメージを元にしている
- Spark は JDK8 じゃないとダメ(デフォルトのJDK10ではエラーが出る)
- gluepyspark を1回動かしてmavenの依存モジュールをイメージに入れておく
- jarの参照先をglueのものではなくsparkのものに入れ替える
FROM python:3.6
# Avoid warnings by switching to noninteractive
ENV DEBIAN_FRONTEND=noninteractive
ENV PYTHONUNBUFFERED 1
# Configure apt and install packages
RUN echo 'deb http://ftp.jp.debian.org/debian sid main' >> /etc/apt/sources.list \
&& apt-get update \
&& apt-get -y install --no-install-recommends apt-utils dialog 2>&1 \
#
# Verify git, process tools, lsb-release (common in install instructions for CLIs) installed
&& apt-get -y install git iproute2 procps lsb-release \
#
# Install pylint/awscli
&& pip --disable-pip-version-check --no-cache-dir install pylint awscli \
#
# for glue (spark=jdk8)
&& apt-get install -y openjdk-8-jdk zip unzip less \
#
# Clean up
&& apt-get autoremove -y \
&& apt-get clean -y \
&& rm -rf /var/lib/apt/lists/*
# awscli
RUN curl -sSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
RUN unzip awscliv2.zip
RUN ./aws/install
# maven (for glue)
RUN curl -sSOL https://aws-glue-etl-artifacts.s3.amazonaws.com/glue-common/apache-maven-3.6.0-bin.tar.gz
RUN tar -xzvf apache-maven-3.6.0-bin.tar.gz
RUN mv apache-maven-3.6.0 /opt/
RUN ln -s /opt/apache-maven-3.6.0 /opt/apache-maven
ENV PATH $PATH:/opt/apache-maven/bin
# glue 1.0
RUN git clone -b glue-1.0 --depth 1 https://github.com/awslabs/aws-glue-libs
RUN mv aws-glue-libs /opt/
ENV chmod -R ao+wr /opt/aws-glue-libs
ENV PATH $PATH:/opt/aws-glue-libs/bin
# spark
RUN curl -OL https://aws-glue-etl-artifacts.s3.amazonaws.com/glue-1.0/spark-2.4.3-bin-hadoop2.8.tgz
RUN tar -xzvf spark-2.4.3-bin-hadoop2.8.tgz
RUN mv spark-2.4.3-bin-spark-2.4.3-bin-hadoop2.8 /opt/
RUN ln -s /opt/spark-2.4.3-bin-spark-2.4.3-bin-hadoop2.8 /opt/spark
ENV SPARK_HOME /opt/spark
# glue setup
RUN gluepyspark
# 2020/6/30にbuildし直してみたら、jarのバージョン違いが解消されて、
# 以下のオマジナイをしなくても大丈夫になったようです。
# RUN mv /opt/aws-glue-libs/jarsv1 /opt/aws-glue-libs/jarsv1.bk
# RUN ln -s ${SPARK_HOME}/jars /opt/aws-glue-libs/jarsv
# AWSのGlueの実行環境には、以下の外部ライブラリがインストール済のようで、
# 外部ライブラリとして、zip化しなくても、使えるようです。
# https://docs.aws.amazon.com/ja_jp/glue/latest/dg/add-job-python.html#python-shell-supported-library
# 少なくとも、boto3 は使えたので、コンテナにも、インストール済にしておく。
# 他、ユニットテストに必要なライブラリも追加
RUN pip install -U boto3 pytest pandas
docker-compose.yml も作成します。 のちのち、LocalStackも入れたくなるでしょう。
version: '3'
services:
glue:
image: altus5/devcontainer-glue:latest
volumes:
- '.:/workspace'
working_dir: '/workspace'
environment:
TZ: 'Asia/Tokyo'
command: 'sleep infinity'
docker-compose up -d
で起動させたら glue のコンテナ内に入ります。
docker-compose exec glue bash
実行するには、それぞれのアカウントを設定して、テストデータを配置して、 glue にスクリプトを送信します。
export AWS_ACCESS_KEY_ID=XXXXXXXXXXXXXX
export AWS_SECRET_ACCESS_KEY=YYYYYYYYYYY
export AWS_REGION=ap-northeast-1
# S3にテストデータ配置(コピーするデータは適宜自分で用意する)
aws s3 cp testdata.gz s3://glue-test/
# 実行
gluesparksubmit ./src/sample.py --JOB_NAME='dummy'
関連記事
- 2020/05/17 私たちの AWS Glue を使った開発のやり方 弊社での AWS Glue (Spark) を使ったシステムの開発のやり方についてご紹介します。ポイントはできるだけローカルの環境を使うことです。
- 2020/11/02 ChatOpsのススメ SlackのChatbotをMS製のBot Frameworkで作成してみました。簡単に作り方を説明します。
- 2020/09/07 AWSのエラーログ監視の設定 AWSにサーバーレスなシステムを構築したときのログ監視のやり方を説明します。簡単に再利用できるようにできるだけCLIで設定します。
- 2020/06/15 PySparkの分散される処理単位であるクロージャと共有変数の仕組み Spark では、処理が分散されて、複数のノードやスレッドで実行されますが、分散される処理の塊を、どう配信しているのか?加えて、複数のタスク間でのデータの共有とか、集約するための仕組みがどうなっているのか?少しだけ説明します。