일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | |||||
3 | 4 | 5 | 6 | 7 | 8 | 9 |
10 | 11 | 12 | 13 | 14 | 15 | 16 |
17 | 18 | 19 | 20 | 21 | 22 | 23 |
24 | 25 | 26 | 27 | 28 | 29 | 30 |
- ip
- kubernetes
- jvm
- Spring
- helm
- EC2
- Packet
- OS
- tcp
- kubectl
- Vision
- Python
- PostgreSQL
- AWS
- JavaScript
- CVAT
- aws s3
- kubeadm
- grafana
- Operating System
- airflow
- CSV
- MAC address
- Kafka
- docker
- Trino
- log
- Network
- zookeeper
- java
- Today
- Total
JUST WRITE
Trino 한번 써보겠습니다(2) - Hive Metastore와 AWS S3 연결 본문
Trino 한번 써보겠습니다(2)
분산 Query Engine 중 가장 핫한 Trino를 설치해 보았습니다.
이제 Data Source에 연결해서 Trino를 통해 데이터를 조회해 보려고 합니다.
이번 시리즈에서 선택한 Data Source는 AWS S3입니다.
- Trino 설치
- Hive Metastore와 AWS S3 연결
- Trino로 CSV 데이터 조회
AWS S3에 CSV 파일을 업로드하고 파일의 데이터를 조회하려고 합니다.
Trino가 AWS S3와 연결하려면 Hive Metastore가 필요합니다.
이번 포스팅에서는 Hive Metastore 세팅과 Trino의 AWS S3 연결을 정리해 보겠습니다.
Hive Metastore 세팅
먼저 Hive Metastore 세팅을 진행하겠습니다.
Binary로 설치할 수도 있지만 Trino도 Kubernetes에 한 김에 Metastore도 Kubernetes에 세팅해 보겠습니다.
Hive Metastore 이미지 생성부터 진행하겠습니다.
Hive Metastore 이미지 생성
Hive Binary 파일로 세팅해도 되지만 Metastore standalone을 따로 Download 할 수 있습니다.
아래 사이트에서 Download 가능하며 이번 포스팅에서는 3.1.3 버전으로 진행하였습니다.
Hive Metastore를 실행하기 위해서는 Hadoop이 필요합니다.
Hadoop은 최소 2.6 이상 버전이 필요합니다.
이번 포스팅에서는 Hadoop 3.2.4 버전으로 진행하였습니다.
아래 내용은 $HIVE_METASTORE_HOME/bin/base 파일입니다.
HADOOP=$HADOOP_HOME/bin/hadoop
if [ ! -f ${HADOOP} ]; then
echo "Cannot find hadoop installation: \$HADOOP_HOME or \$HADOOP_PREFIX must be set or hadoop must be in the path";
exit 4;
fi
if [ "$SKIP_HADOOPVERSION" = false ]; then
# Make sure we're using a compatible version of Hadoop
if [ "x$HADOOP_VERSION" == "x" ]; then
HADOOP_VERSION=$($HADOOP version 2>&2 | awk -F"\t" '/Hadoop/ {print $0}' | cut -d' ' -f 2);
fi
# Save the regex to a var to workaround quoting incompatabilities
# between Bash 3.1 and 3.2
hadoop_version_re="^([[:digit:]]+)\.([[:digit:]]+)(\.([[:digit:]]+))?.*$"
if [[ "$HADOOP_VERSION" =~ $hadoop_version_re ]]; then
hadoop_major_ver=${BASH_REMATCH[1]}
hadoop_minor_ver=${BASH_REMATCH[2]}
hadoop_patch_ver=${BASH_REMATCH[4]}
else
echo "Unable to determine Hadoop version information."
echo "'hadoop version' returned:"
echo `$HADOOP version`
exit 5
fi
if [ "$hadoop_major_ver" -lt "2" ] || [ "$hadoop_major_ver" -eq "2" -a "$hadoop_minor_ver" -lt "6" ]; then
echo "Standalone metastore requires Hadoop 2.6 or later."
echo "'hadoop version' returned:"
echo `$HADOOP version`
exit 6
fi
fi
Hive Metastore 3.1.3과 Hadoop 3.2.4 Binary를 Download 합니다.
그리고 Metastore를 MySQL로 진행하기 위해서 MySQL JDBC를 Download 합니다.
$ wget https://repo1.maven.org/maven2/org/apache/hive/hive-standalone-metastore/3.1.3/hive-standalone-metastore-3.1.3-bin.tar.gz
$ wget https://dlcdn.apache.org/hadoop/common/hadoop-3.2.4/hadoop-3.2.4.tar.gz
$ wget https://repo1.maven.org/maven2/mysql/mysql-connector-java/8.0.27/mysql-connector-java-8.0.27.jar
Dockerfile를 작성합니다.
기본 이미지는 openjdk:11-slim으로 하였습니다.
Hive Metastore는 Java 8 이상 필요합니다.
FROM openjdk:11-slim
RUN apt-get update -y && apt-get install -y curl --no-install-recommends && rm -rf /var/lib/apt/lists/*
COPY hadoop-3.2.4.tar.gz hive-standalone-metastore-3.1.3-bin.tar.gz mysql-connector-java-8.0.27.jar /opt
WORKDIR /opt
RUN tar xzf hadoop-3.2.4.tar.gz && ln -s /opt/hadoop-3.2.4 /opt/hadoop && tar xzf hive-standalone-metastore-3.1.3-bin.tar.gz && ln -s /opt/apache-hive-metastore-3.1.3-bin /opt/hive-metastore && rm /opt/hadoop-3.2.4.tar.gz /opt/hive-standalone-metastore-3.1.3-bin.tar.gz
RUN rm -r /opt/hadoop/share/doc && ln -s /opt/hadoop/share/hadoop/tools/lib/aws-java-sdk-bundle-1.11.901.jar /opt/hadoop/share/hadoop/common/lib/ && ln -s /opt/hadoop/share/hadoop/tools/lib/hadoop-aws-3.2.4.jar /opt/hadoop/share/hadoop/common/lib/
RUN rm /opt/hive-metastore/lib/guava-19.0.jar && cp /opt/hadoop/share/hadoop/common/lib/guava-27.0-jre.jar /opt/hive-metastore/lib
RUN ln -s /opt/mysql-connector-java-8.0.27.jar /opt/hadoop/share/hadoop/common/lib/ && ln -s /opt/mysql-connector-java-8.0.27.jar /opt/hive-metastore/lib/
ENV HADOOP_VERSION=3.2.4 \
HIVE_METASTORE_VERSION=3.1.3 \
HADOOP_HOME="/opt/hadoop" \
PATH="/opt/hadoop/bin:${PATH}"
해당 Dockerfile로 이미지 생성 후 Dockerhub에 push 하였습니다.
$ docker build -t sang1759/hive-metastore:3.1.3 .
$ docker push sang1759/hive-metastore:3.1.3
Kubernetes에 MySQL 세팅
Hive Metastore를 세팅하기 전에 Metastore로 활용할 MySQL를 세팅합니다.
아래 Object들을 생성합니다.
- Secret -> MySQL Root Password를 저장
- PersistentVolumeClaim -> MySQL Data를 저장할 PV 생성
- Deployment -> MySQL Pod
- Service
secret에 들어가는 MySQL Root Password는 base64로 encoding 한 값을 넣습니다.
apiVersion: v1
kind: Secret
metadata:
name: mysql-secrets
namespace: trino
type: Opaque
data:
ROOT_PASSWORD: cm9vdA==
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: mysql-data-vol
namespace: trino
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 2Gi
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: mysql-deployment
namespace: trino
labels:
app: mysql
spec:
replicas: 1
selector:
matchLabels:
app: mysql
template:
metadata:
labels:
app: mysql
spec:
containers:
- name: mysql
image: mysql:8.0.27
ports:
- containerPort: 3306
volumeMounts:
- mountPath: "/var/lib/mysql"
subPath: "mysql"
name: mysql-data
env:
- name: MYSQL_ROOT_PASSWORD
valueFrom:
secretKeyRef:
name: mysql-secrets
key: ROOT_PASSWORD
volumes:
- name: mysql-data
persistentVolumeClaim:
claimName: mysql-data-vol
---
apiVersion: v1
kind: Service
metadata:
name: mysql-service
namespace: trino
spec:
selector:
app: mysql
ports:
- protocol: TCP
port: 3306
targetPort: 3306
해당 yaml로 작성해서 MySQL Object들을 생성합니다.
$ kubectl apply -f mysql.yaml
$ kubectl get all -n trino
NAME READY STATUS RESTARTS AGE
pod/mysql-deployment-6948465c44-xrjqc 1/1 Running 0 112s
pod/trino-coordinator-54bf94c5d5-n2ff2 1/1 Running 1 (177m ago) 3h19m
pod/trino-worker-df8c6b8c9-twwt9 1/1 Running 1 (177m ago) 3h20m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mysql-service ClusterIP 10.102.96.24 <none> 3306/TCP 112s
service/trino NodePort 10.110.205.240 <none> 8080:32157/TCP 23d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mysql-deployment 1/1 1 1 112s
deployment.apps/trino-coordinator 1/1 1 1 23d
deployment.apps/trino-worker 1/1 1 1 23d
NAME DESIRED CURRENT READY AGE
replicaset.apps/mysql-deployment-6948465c44 1 1 1 112s
replicaset.apps/trino-coordinator-54bf94c5d5 1 1 1 23d
replicaset.apps/trino-worker-df8c6b8c9 1 1 1 23d
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/trino-worker Deployment/trino-worker <unknown>/20% 1 3 1 23d
Hive Metastore initSchema
Metastore로 사용할 MySQL까지 세팅하였으면 MySQL에 Metastore에 관련된 schema를 생성해야 합니다.
위에서 생성한 Metastore 이미지와 Kubernetes Job를 통해서 schema를 생성합니다.
apiVersion: batch/v1
kind: Job
metadata:
name: hive-initschema
namespace: trino
spec:
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchExpressions:
- key: app
operator: In
values:
- mysql
topologyKey: kubernetes.io/hostname
containers:
- name: hivemeta
image: sang1759/hive-metastore:3.1.3
command: ["/opt/hive-metastore/bin/schematool"]
args: ["--verbose" ,"-initSchema" , "-dbType", "mysql" , "-userName", "root",
"-passWord", "root" , "-url", "jdbc:mysql://mysql-service.trino.svc.cluster.local:3306/metastore_db?createDatabaseIfNotExist=true&connectTimeout=1000"]
restartPolicy: Never
backoffLimit: 4
Metastore에서 schematool command가 있습니다.
실행 시 옵션에 방금 세팅한 MySQL 정보를 입력해 줍니다.
작성한 yaml로 Job을 생성합니다.
$ kubectl apply -f init-schema.yaml
$ kubectl get all -n trino
NAME READY STATUS RESTARTS AGE
pod/hive-initschema-fjqgn 0/1 Completed 0 114s
pod/mysql-deployment-6948465c44-xrjqc 1/1 Running 0 30m
pod/trino-coordinator-54bf94c5d5-n2ff2 1/1 Running 1 (3h25m ago) 3h48m
pod/trino-worker-df8c6b8c9-twwt9 1/1 Running 1 (3h25m ago) 3h48m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/mysql-service ClusterIP 10.102.96.24 <none> 3306/TCP 30m
service/trino NodePort 10.110.205.240 <none> 8080:32157/TCP 23d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/mysql-deployment 1/1 1 1 30m
deployment.apps/trino-coordinator 1/1 1 1 23d
deployment.apps/trino-worker 1/1 1 1 23d
NAME DESIRED CURRENT READY AGE
replicaset.apps/mysql-deployment-6948465c44 1 1 1 30m
replicaset.apps/trino-coordinator-54bf94c5d5 1 1 1 23d
replicaset.apps/trino-worker-df8c6b8c9 1 1 1 23d
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/trino-worker Deployment/trino-worker <unknown>/20% 1 3 1 23d
NAME COMPLETIONS DURATION AGE
job.batch/hive-initschema 1/1 76s 114s
Dbeaver로 MySQL에 접속해보면 Metastore관련 Table들이 생성된 것을 확인할 수 있습니다.
AWS S3 접근 유저 생성
Hive Metastore에서 AWS S3에 접근하려면 권한이 필요합니다.
AWS IAM에서 필요한 유저를 생성합니다.
실습이라 AmazonS3 FullAccess 권한을 가진 유저를 생성하였습니다.
유저를 생성한 후에는 액세스 키를 만듭니다.
access-key와 secret-key를 잘 저장해 둡니다.
Metastore Service 생성
이제 Metastore Service를 생성해 보겠습니다.
먼저 2가지 설정파일을 작성합니다.
- core-site.xml
- metastore-site.xml
# core-site.xml
<configuration>
<property>
<name>fs.defaultFS</name>
<value>s3a://******</value>
</property>
<property>
<name>fs.s3a.path.style.access</name>
<value>true</value>
</property>
<property>
<name>fs.s3a.access.key</name>
<value>******</value>
</property>
<property>
<name>fs.s3a.secret.key</name>
<value>******</value>
</property>
<property>
<name>fs.s3a.impl</name>
<value>org.apache.hadoop.fs.s3a.S3AFileSystem</value>
</property>
<property>
<name>fs.s3a.endpoint</name>
<value>s3.ap-northeast-2.amazonaws.com</value>
</property>
<property>
<name>fs.s3a.fast.upload</name>
<value>true</value>
</property>
</configuration>
# metastore-site.xml
<configuration>
<property>
<name>metastore.task.threads.always</name>
<value>org.apache.hadoop.hive.metastore.events.EventCleanerTask</value>
</property>
<property>
<name>metastore.expression.proxy</name>
<value>org.apache.hadoop.hive.metastore.DefaultPartitionExpressionProxy</value>
</property>
<property>
<name>javax.jdo.option.ConnectionDriverName</name>
<value>com.mysql.cj.jdbc.Driver</value>
</property>
<property>
<name>javax.jdo.option.ConnectionURL</name>
<value>jdbc:mysql://mysql-service.trino.svc.cluster.local:3306/metastore_db?useSSL=false&allowPublicKeyRetrieval=true</value>
</property>
<property>
<name>javax.jdo.option.ConnectionUserName</name>
<value>root</value>
</property>
<property>
<name>javax.jdo.option.ConnectionPassword</name>
<value>******</value>
</property>
<property>
<name>metastore.warehouse.dir</name>
<value>s3a://******/warehouse/</value>
</property>
</configuration>
작성한 2가지 설정파일로 ConfigMap을 생성합니다.
kubectl create configmap metastore-cfg --from-file=metastore-site.xml --from-file=core-site.xml -n trino
그리고 Metastore에 Enviorment로 S3 access-key와 secret-key를 secret으로 생성합니다.
kubectl create secret generic my-s3-keys --from-literal=access-key='******' --from-literal=secret-key='******' -n trino
마지막으로 Hive Metastore의 Deployment와 Service를 생성합니다.
apiVersion: v1
kind: Service
metadata:
name: metastore
namespace: trino
spec:
ports:
- port: 9083
selector:
app: metastore
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: metastore
namespace: trino
spec:
selector:
matchLabels:
app: metastore
strategy:
type: Recreate
template:
metadata:
labels:
app: metastore
spec:
containers:
- name: metastore
image: sang1759/hive-metastore:3.1.3
env:
- name: AWS_ACCESS_KEY_ID
valueFrom:
secretKeyRef:
name: my-s3-keys
key: access-key
- name: AWS_SECRET_ACCESS_KEY
valueFrom:
secretKeyRef:
name: my-s3-keys
key: secret-key
ports:
- containerPort: 9083
volumeMounts:
- name: metastore-cfg-vol
mountPath: /opt/hive-metastore/conf/metastore-site.xml
subPath: metastore-site.xml
- name: metastore-cfg-vol
mountPath: /opt/hadoop/etc/hadoop/core-site.xml
subPath: core-site.xml
command: ["/opt/hive-metastore/bin/start-metastore"]
args: ["-p", "9083"]
resources:
requests:
memory: "2G"
cpu: 2
imagePullPolicy: Always
volumes:
- name: metastore-cfg-vol
configMap:
name: metastore-cfg
생성 후 확인해 봅니다.
$ kubectl apply -f metastore.yaml
$ kubectl get all -n trino
NAME READY STATUS RESTARTS AGE
pod/hive-initschema-fjqgn 0/1 Completed 0 57m
pod/metastore-6c4976766f-lr948 1/1 Running 0 6s
pod/mysql-deployment-6948465c44-xrjqc 1/1 Running 0 86m
pod/trino-coordinator-54bf94c5d5-n2ff2 1/1 Running 1 (4h21m ago) 4h44m
pod/trino-worker-df8c6b8c9-twwt9 1/1 Running 1 (4h21m ago) 4h44m
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/metastore ClusterIP 10.99.186.13 <none> 9083/TCP 6s
service/mysql-service ClusterIP 10.102.96.24 <none> 3306/TCP 86m
service/trino NodePort 10.110.205.240 <none> 8080:32157/TCP 23d
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/metastore 1/1 1 1 6s
deployment.apps/mysql-deployment 1/1 1 1 86m
deployment.apps/trino-coordinator 1/1 1 1 23d
deployment.apps/trino-worker 1/1 1 1 23d
NAME DESIRED CURRENT READY AGE
replicaset.apps/metastore-6c4976766f 1 1 1 6s
replicaset.apps/mysql-deployment-6948465c44 1 1 1 86m
replicaset.apps/trino-coordinator-54bf94c5d5 1 1 1 23d
replicaset.apps/trino-worker-df8c6b8c9 1 1 1 23d
NAME REFERENCE TARGETS MINPODS MAXPODS REPLICAS AGE
horizontalpodautoscaler.autoscaling/trino-worker Deployment/trino-worker <unknown>/20% 1 3 1 23d
NAME COMPLETIONS DURATION AGE
job.batch/hive-initschema 1/1 76s 57m
$ kubectl logs -n trino pod/metastore-6c4976766f-lr948
2023-08-09 13:21:42: Starting Metastore Server
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/opt/apache-hive-metastore-3.1.3-bin/lib/log4j-slf4j-impl-2.17.1.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/opt/hadoop-3.2.4/share/hadoop/common/lib/slf4j-reload4j-1.7.35.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
2023-08-09 13:21:46,744 main INFO Log4j appears to be running in a Servlet environment, but there's no log4j-web module available. If you want better web container support, please add the log4j-web JAR to your web archive or server lib director
정리
이번 포스팅에서는 Metastore 이미지를 만들고 Kubernetes에 세팅해 보았습니다.
다음 포스팅에서는 Metastore를 통해 S3에 있는 CSV 파일을 Trino로 조회해 보겠습니다.
[참고사이트]
'Data' 카테고리의 다른 글
[Trino] 너의 흔적을 기록하고 싶어 - 히스토리 데이터 영구 저장 (0) | 2024.11.17 |
---|---|
Trino 한번 써보겠습니다(3) - AWS S3내 CSV 데이터 조회 (2) | 2023.08.14 |
Trino 한번 써보겠습니다(1) - Kubernetes에 Trino 설치 (0) | 2023.07.17 |
GlusterFS 설치 (0) | 2023.02.26 |
AWS EC2 Nifi 설치 (0) | 2022.11.23 |