メインコンテンツまでスキップ

Glue + Athenaのローカル開発環境をOSSで構築(MinIO + Trino + HIVE)

· 約8分
moritalous

Glueの開発環境として、Dockerイメージが提供されています。(参考:Docker Hub

このイメージを使ってGlueのワークショップを試してみたのですが、Glue以外のリソースについてはところどころAWSへのアクセスが必要でした。

どうにかこうにか、AWSにアクセスしない環境にできなかいと思い、チャレンジしてみました。

ヒント

今回作成したコードはGitHubにあげてあります。
https://github.com/moritalous/glue-minio-trino

概要
  • AWSがGlueの開発用Dockerイメージを公開しています。
  • S3やAthenaの代替としてOSSを利用します。
  • ところどころ異なりますが、学習用途には使える環境が整いました。

構築イメージ

それぞれのサービスの置き換えは以下のイメージです。

image.png

AWSサービス代替サービス参考URL
GlueジョブGlue開発用Dockerイメージhttps://docs.aws.amazon.com/ja_jp/glue/latest/dg/aws-glue-programming-etl-libraries.html#develop-local-docker-image
GlueデータカタログHIVEメタストアhttps://hive.apache.org/
AthenaTrinohttps://trino.io/
S3MinIOhttps://min.io/

この環境をDocker Composeを使い構築します。

環境構築

MinIO

まずはS3を置き換えるMinIOからです。

ポイントは

  • path-styleではなくvirtual-hosted styleを使用するため、MINIO_DOMAIN環境変数をセット
  • 他のコンテナから[バケット名].minioで名前解決できるようにhostnameを指定

path-stylevirtual-hosted styleの違いはこちらを参照ください。

version: '3'

services:
minio:
image: quay.io/minio/minio
hostname: bucket001.minio
restart: always
volumes:
- ./minio/data:/data
environment:
- MINIO_DOMAIN=minio
command: ["server", "/data", "--console-address", ":9001"]
ports:
- "9000:9000"
- "9001:9001"

MinIOにアクセスする際のAWS認証情報は他のコンテナからも共通で使用する形で作成しました。

  • .aws/credentials
[default]
aws_access_key_id = minioadmin
aws_secret_access_key = minioadmin
注意

MinIOの管理者アカウントなので、適宜修正ください。

HIVEメタストア

Docker Hubには公式イメージがなさそうでしたので、こちらのサイトを参考にDockerfileを作成しました。

FROM ubuntu:22.04

RUN apt-get update && apt-get install -y openjdk-11-jre-headless wget && \
useradd -m -s /bin/bash hive

WORKDIR /tmp

RUN wget "https://repo1.maven.org/maven2/org/apache/hive/hive-standalone-metastore/3.1.2/hive-standalone-metastore-3.1.2-bin.tar.gz" && \
tar -zxvf hive-standalone-metastore-3.1.2-bin.tar.gz && \
mv apache-hive-metastore-3.1.2-bin /opt/ && \
rm hive-standalone-metastore-3.1.2-bin.tar.gz && \
ln -s /opt/apache-hive-metastore-3.1.2-bin /opt/apache-hive-metastore

RUN wget "https://dlcdn.apache.org/hadoop/common/hadoop-3.3.4/hadoop-3.3.4.tar.gz" && \
tar xvf hadoop-3.3.4.tar.gz && \
mv hadoop-3.3.4 /opt/ && \
rm hadoop-3.3.4.tar.gz && \
ln -s /opt/hadoop-3.3.4 /opt/hadoop

USER hive
WORKDIR /home/hive

ENV JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
ENV HADOOP_HOME=/opt/hadoop
ENV HADOOP_CLASSPATH=${HADOOP_HOME}/share/hadoop/tools/lib/aws-java-sdk-bundle-1.12.262.jar:${HADOOP_HOME}/share/hadoop/tools/lib/hadoop-aws-3.3.4.jar

RUN /opt/apache-hive-metastore/bin/schematool -initSchema -dbType derby

ENTRYPOINT [ "/opt/apache-hive-metastore/bin/start-metastore" ]

HIVEメタストアからMinIOにアクセスする必要があるため、設定ファイルにMinIOへの接続情報を追記します。

  • metastore-site.xml(追加部分のみ)
  <property>
<name>fs.s3.impl</name>
<value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
</property>
<property>
<name>fs.s3a.impl</name>
<value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
</property>

<property>
<name>fs.s3a.aws.credentials.provider</name>
<value>com.amazonaws.auth.DefaultAWSCredentialsProviderChain</value>
</property>
<property>
<name>fs.s3.aws.credentials.provider</name>
<value>com.amazonaws.auth.DefaultAWSCredentialsProviderChain</value>
</property>

<property>
<name>fs.s3a.connection.ssl.enabled</name>
<value>false</value>
</property>

<property>
<name>fs.s3a.endpoint</name>
<value>http://minio:9000</value>
</property>

docker-compose.yamlservicesに以下を追加します。

  hive-metastore:
build:
context: hive-metastore/
dockerfile: Dockerfile
volumes:
- ./.aws:/home/hive/.aws:ro
- ./hive-metastore/work:/work
- ./hive-metastore/metastore-site.xml:/opt/apache-hive-metastore/conf/metastore-site.xml
working_dir: /work
environment:
- AWS_PROFILE=default
ports:
- "9083:9083"

docker-compose.yamlができたら、スキーマの初期化が必要なので以下のコマンドを実行します。

docker compose run --entrypoint bash \
hive-metastore /opt/apache-hive-metastore/bin/schematool -initSchema -dbType derby

Trino

Trinoは公式イメージが用意されています。準備が必要なのはMinIOをカタログとして使用するための設定ファイルです。

  • minio.properties
connector.name=hive
hive.metastore.uri=thrift://hive-metastore:9083
hive.s3.endpoint=http://minio:9000
hive.s3.ssl.enabled=false
hive.allow-drop-table=true

docker-compose.yamlservicesに以下を追加します。

  trino:
image: trinodb/trino
volumes:
- ./.aws:/home/trino/.aws:ro
- ./trino/catalog/minio.properties:/etc/trino/catalog/minio.properties
environment:
- AWS_PROFILE=default
ports:
- 8080:8080
depends_on:
- hive-metastore

Glue開発用Dockerイメージ

DockerイメージはAWSへの接続ができる状態で提供されているので、以下の2点を修正することでローカル環境を参照させます。

  • S3の代わりにMinIOを使用する
  • Glueデータカタログの代わりにHIVEメタストアを使用する

それぞれ解説します。

  • S3の代わりにMinIOを使用する

    core-site.xmlで設定を行います。(設定の内容はHIVEメタストアにセットしたものと同等です)

    <configuration>
    <property>
    <name>fs.s3.impl</name>
    <value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
    </property>
    <property>
    <name>fs.s3a.impl</name>
    <value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
    </property>
    <property>
    <name>fs.s3a.aws.credentials.provider</name>
    <value>com.amazonaws.auth.DefaultAWSCredentialsProviderChain</value>
    </property>
    <property>
    <name>fs.s3.aws.credentials.provider</name>
    <value>com.amazonaws.auth.DefaultAWSCredentialsProviderChain</value>
    </property>

    <property>
    <name>fs.s3a.connection.ssl.enabled</name>
    <value>false</value>
    </property>

    <property>
    <name>fs.s3a.endpoint</name>
    <value>http://minio:9000</value>
    </property>
    </configuration>
  • Glueデータカタログの代わりにHIVEメタストアを使用する

    hive-site.xmlで設定します。

    <configuration>
    <property>
    <name>hive.metastore.connect.retries</name>
    <value>15</value>
    </property>
    <!-- <property>
    <name>hive.metastore.client.factory.class</name>
    <value>com.amazonaws.glue.catalog.metastore.AWSGlueDataCatalogHiveClientFactory</value>
    </property> -->

    <property>
    <name>hive.metastore.uris</name>
    <value>thrift://hive-metastore:9083</value>
    <description>Thrift URI for the remote metastore. Used by metastore client to connect to remote metastore.</description>
    </property>

    </configuration>
注意

試行錯誤してうまく行っただけですので、本来あるべき設定ではないかもしれません。

docker-compose.yamlのservicesに以下を追加します。

  glue:
image: amazon/aws-glue-libs:glue_libs_3.0.0_image_01
restart: always
volumes:
- ./.aws:/home/glue_user/.aws:ro
- ./jupyter_workspace:/home/glue_user/workspace/jupyter_workspace/
- ./glue/spark/core-site.xml:/home/glue_user/spark/conf/core-site.xml
- ./glue/spark/hive-site.xml:/home/glue_user/spark/conf/hive-site.xml
environment:
- AWS_PROFILE=default
- DISABLE_SSL=true
ports:
- 4040:4040
- 18080:18080
- 8998:8998
- 8888:8888
command: ["/home/glue_user/jupyter/jupyter_start.sh"]
depends_on:
- minio

Glue開発用Dockerイメージ内部ではglue_userというユーザーが使用されています。

  • glue_userユーザーのユーザーIDとグループIDの情報
[glue_user@a9b0e76a7b02 ~]$ id
uid=10000(glue_user) gid=0(root) groups=0(root)
[glue_user@a9b0e76a7b02 ~]$

永続化するディレクトリーの所有者をこのユーザーに合わせます。

mkdir jupyter_workspace
sudo chown -R 10000.root jupyter_workspace
ヒント

以上で準備は完了です。

使い方

準備が整いましたので、起動します。

docker compose up -d

Notebookへのアクセス

NotebookはGlue開発用Dockerコンテナに含まれており、8888ポートを使用しています。http://localhost:8888でアクセス可能です。

image.png

バケットを作成

Notebook内のTerminalで実行します。

aws s3 mb s3://bucket001 --endpoint-url http://minio:9000

PySpark

PySpark Notebookで実行します。

spark.sql("show databases").show()

Spark SQL

PySpark Notebookで%%sqlをつけるとSpark SQLを実行できます。

%%sql

show databases
  • DATABASE作成
%%sql

CREATE DATABASE IF NOT EXISTS spark_glueworkshop
LOCATION 's3a://bucket001/'
  • TABLE作成
%%sql

CREATE EXTERNAL TABLE IF NOT EXISTS spark_glueworkshop.spark_csv
(
uuid bigint,
Country string,
item_type string,
sales_channel string,
order_priority string,
order_date string,
region string,
ship_date string,
units_sold bigint,
unit_price double,
unit_cost double,
total_revenue double,
total_cost double,
total_profit double
)
STORED AS TEXTFILE
LOCATION 's3://bucket001/input/lab1/csv/'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
TBLPROPERTIES (
"skip.header.line.count"="1")
ヒント

PySparkやSpark SQLがローカルのみで動作する環境が整いました。

Trinoへのアクセス

Notebook内でTerminalを立ち上げ、以下のコマンドを実行します。

  • Trino CLIのインストール
mkdir bin

wget https://repo1.maven.org/maven2/io/trino/trino-cli/400/trino-cli-400-executable.jar
mv trino-cli-400-executable.jar bin/trino
chmod +x bin/trino
  • Trino CLIの実行
sh-4.2$ bin/trino --server http://trino:8080 --user trino
trino> 
  • SCHEMA作成
CREATE SCHEMA IF NOT EXISTS minio.athena_glueworkshop WITH(location = 's3a://bucket001/');
  • TABLE作成
CREATE TABLE minio.athena_glueworkshop.athena_csv
(
uuid varchar,
Country varchar,
item_type varchar,
sales_channel varchar,
order_priority varchar,
order_date varchar,
region varchar,
ship_date varchar,
units_sold varchar,
unit_price varchar,
unit_cost varchar,
total_revenue varchar,
total_cost varchar,
total_profit varchar
)
WITH (
format = 'csv',
csv_separator = ',',
csv_quote = '"',
csv_escape = '"',
skip_header_line_count = 1,
external_location = 's3a://bucket001/input/lab1/csv/'
);
ヒント

Trinoがローカルのみで動作する環境が整いました。

まとめ

今回作成したコードはGitHubに公開しています。 https://github.com/moritalous/glue-minio-trino

Glueワークショップの一部を実施したノートブックも含めていますので、どうぞご利用ください。