코알못

[AWS] EMR(hadoop) - 배치를 만들어보자! 본문

BIG DATA

[AWS] EMR(hadoop) - 배치를 만들어보자!

코린이s 2022. 1. 30. 02:18
728x90

hue 라는 도구를 이용하면 하둡 데이터에 쉽게 접근 할 수 있고 여러 하둡 에코 시스템과 연동 되어 쉽게 서비스를 이용할 수 있다.

만약 hue 없이 서비스를 이용한다고 하면 화면이 없는 콘솔창에서 명령어를 직접 날려서 관리 해야 하여 UI에 익숙한 관리자의 경우에는 불편 할 수 있다. 그리고 hue 라는 하나의 도구에서 관리한다는거는 시스템 관리 측면에서 좋은 부분이다.

추가로 oozie 라는 서비스를 이용하면 스케쥴링를 쉽게 등록 할 수 있으며 실습을 하면서 알아가보자!

 

실습할 내용은 총 세가지이다!

1. csv 파일 데이터를 읽어 데이터를 hive(하둡용 DB)에 누적하는 잡 생성 및 실행

2. 다른 서버(하둡 클러스터 이외 서버)의 스크립트를 실행시키는 잡 생성 및 실행

3. 두개의 잡이 특정 시간에 실행 되도록 배치를 등록 해보자

 

자 그럼 hue(http://master_pubulic_dns:8888/)에 접속하여 저번 시간에 만든 계정으로 접속하고 실습을 진행한다.

1. csv 파일 데이터를 읽어 데이터를 hive(하둡용 DB)에 누적하는 잡 생성 및 실행

우선 실습을 진행할 csv 파일과 데이터를 읽기 위한 hive 테이블을 만든다.

// 파일명은 자유.csv

1,ParkHyunJun
2,LeeHoSeong
3,thewayhj
4,LeeNow
5,hongYooLee

해당 데이터는 s3, hdfs 중에 원하는 저장소에 저장하면 되며 각각 특성은 아래와 같으니 맞게 사용하면 된다. 저자의 경우 계속적으로 사용할 예정으로 s3에 업로드 한다.

- hdfs : 클러스터가 종료되면 데이터도 삭제됨 (클러스터는 중단 기능이 없어 사용 안하는 경우 종료하는 경우가 많으나 삭제되어도 상관 없는 데이터 또는 클러스터 종료하는 시점 부터 배치를 더이상 돌리지 않는다면 hdfs에 올려도 된다.)

- s3 : 직접 삭제 전까지 영구적

s3 에 업로드 하면 되고 저번시간에는 S3 에서 바로 업로드 하였으나 hue를 통해서도 업로드 가능하여 그 방법은 아래와 같다.

업로드 하였으면 데이터를 읽을 수 있는 hive 테이블을 생성한다.

우선 하이브에 접속하여 데이터베이스를 만든다. (datahub 라고 만들었으나 다른 명칭으로 하셔도 됩니다.) 

$ hive
Hive Session ID = e8bd183f-7dce-4329-bf26-59402828eae7

Logging initialized using configuration in file:/etc/hive/conf.dist/hive-log4j2.properties Async: false
Hive Session ID = 7c3ff09f-8220-44f7-9988-af759c5568ee
hive> create database datahub;
hive> show databases;
OK
datahub
hive> use datahub;
hive>

그리고 테이블을 만드는데 location 을 지정하여 데이터 위치를 지정해줍니다. 지정 해주면 해당 디렉토리 하위 파일 모두 읽어 옵니다. 

CREATE EXTERNAL TABLE tb_user(
    id int,
    name string
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
LOCATION 's3a://emr-hong/data/datahub/tb_user'

데이터를 조회 하면 정상적으로 조회되는것을 확인 할 수 있습니다!

hive> select * from tb_user;
OK
1	ParkHyunJun
2	LeeHoSeong
3	thewayhj
4	LeeNow
5	hongYooLee

그럼 이제 누적 테이블을 생성합니다.

참고로 partitioned by 는 하이브 기능인 파티션 기능인데 RDB 의 인덱스 개념으로 빠르게 조회 가능하도록 하는 기능이며, stored as orc 는 저장 방식인데 orc 는 압축 방식중 하나로 저장될때 텍스트 형식 보다 공간을 적게 차지하도록 한다.

CREATE TABLE tb_user_history(
    id int,
    name string
)
PARTITIONED BY (
  `yyyy` int,
  `mm` int,
  `dd` int)
  STORED AS ORC
  LOCATION 's3a://emr-hong/data/datahub/tb_user_history';

이제 누적 데이터를 만드는 쿼리를 배치 돌릴시 읽어 오도록 하기위해 S3에 파일로 저장합니다.

hue 에서 s3 에 저장할 경로로 가서 new > 파일을 눌러 

적당한 명칭을 넣고 create 를 통해 파일을 만듭니다.

생성된 파일을 클릭한뒤 Edit file 을 클릭하여 수정 할 준비를 한뒤

아래와 같이 누적 배치 쿼리를 적어줍니다.

set 하고 나오는 옵션은 지정 안할시 파티션 저장이 되지 않고 오류 발생하니 꼭 적어주고 저장 버튼을 눌러 저장합니다.

set hive.exec.dynamic.partition.mode=true;
use datahub;
INSERT OVERWRITE TABLE tb_user_history PARTITION (yyyy,mm,dd)
SELECT id, name, year(current_date()), month(current_date()), day(current_date()) FROM tb_user;

그럼 준비는 완료!

자 이제 잡을 만들어 봅니다.

위와 같이 눌러서 적절한 잡 명을 넣고 hive2 script 아이콘을 끌어 넣습니다.

생성한 하이브 쿼리를 S3 에서 선택을 하고 

s3a 는 s3로 변경을 한다. (s3a 로 돌릴시 우지에서 ' ClassNotFoundException: Class org.apache.hadoop.fs.s3a.S3AFileSystem not found' 에러 발생)

그리고 저장한뒤 재생 버튼을 눌러 재출하면 주황생 바가 되었다가 완료시 초록색으로 된다.

 

데이터를 확인해보면 정상적으로 데이터가 들어 간 것을 확인할 수 있다.

hive> use datahub;
hive> select * from tb_user_history where yyyy=2022 and mm=01 and dd=29;
OK
1	ParkHyunJun	2022	1	29
2	LeeHoSeong	2022	1	29
3	thewayhj	2022	1	29
4	LeeNow	2022	1	29
5	hongYooLee	2022	1	29

 

2. 다른 서버(하둡 클러스터 이외 서버)의 스크립트를 실행시키는 잡 생성 및 실행

다른 서버에 우선 스크립트 파일을 생성해두고 다른 외부 접속자가 실행할 수 있도록 권한을 부여한다.

$ vi test.sh
echo "hello data now : $(date +%Y/%m/%d/%H:%M:%S) " >> service.log
:wq!
$ chmod 777 test.sh
$ ./test.sh
$ cat service.log
hello data now : 2022/01/27/05:52:01
hello data now : 2022/01/27/05:52:06
hello data now : 2022/01/27/05:52:14

그리고 우지에서 해당 서버에 ssh 접속을 비밀번호 없이 접속할 수 있어야 잡이 실행되는데 마스터 서버에서 아래와 같이 입력시 비밀 번호 입력하는 창이뜨거나 permission denied 에러가 발생한다면 아래 참고사항의 'Oozie 에서 ssh 실행시 permission denied 에러 발생' 을 먼저 진행 한다.

// 마스터 서버 접속 한뒤 우지 계정 접속
$ sudo -su oozie
$ ssh hadoop@원격서버IP test.sh

// 정상 경우
: 스크립트 실행 로그 발생

// 비정상 경우
Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

설정이 완료 되면 이제 잡을 등록한다.

IP는 원격 서버 Private ip 로 지정하고 실행할 스크립트도 맞게 적는다.

저장하고 실행해보면 초록색으로 완료 표기가 되며

실제 로그 확인해보면 정상적으로 돈것을 확인 할 수 있다.

$ cat service.log
hello data now : 2022/01/29/17:01:31
hello data now : 2022/01/29/17:06:51

3. 두개의 잡이 특정 시간에 실행 되도록 배치를 등록 해보자

이제 두개의 잡을 배치에 등록해보자!

두개의 잡은 서브워크플로우라는 액션으로 선택이 가능하다.

 

두개의 잡을 실행하는 워크 플로우를 저장 한다. (워크 플로우 단위로 배치 등록이 가능하여 묶어준다.)

이제 배치를 등록해보자!

배치등록을 위해서는 스케쥴을 클릭하여 스케쥴을 생성해준다.

 

최종적으로 만든 잡을 선택하고 매일 19:58분에 돌고, 01/22 00:00 ~ 01/23 00:00 까지 스케쥴이 실행 되도록 저장하고 실행한다.

테스트 해보았을시 from, to 에 들어가는 time 은 00:00으로 해야 정상적으로 실행되므로 이점도 참고 바란다.

스케쥴 등록된 부분 확인하면 정상적으로 등록되어 running 상태인것을 볼수 있다. from 시간 보다 현재 시간이 이전이면 prep 상태이다.

그리고 스케쥴 시간이 되어 도는 잡을 확인할 수 있으며

잡이 완료된후 스케쥴을 클릭해보면 완료 된것을 확인 할수 있다. 만약 스케쥴을 5일치 잡아두었으면 5개의 리스트가 뜨나 현재 1번만 실행 되도록 일자를 잡아두어 1개만 표기된다.

끝!

 

# 참고 사항 

1. Oozie S3AFileSystem 에러

- 에러 : ClassNotFoundException: Class org.apache.hadoop.fs.s3a.S3AFileSystem not found

- 해결 방안 : https://hadoop.apache.org/docs/r3.1.2/hadoop-aws/tools/hadoop-aws/troubleshooting_s3a.html#ClassNotFoundException:_org.apache.hadoop.fs.s3a.S3AFileSystem
hadoop-aws JAR를 oozie share lib 디렉토리에 넣으면 해결됨
- oozie-site.xml 의 'oozie.service.WorkflowAppService.system.libpath' 설정값 '/user/${user.name}/share/lib' 경로에 hadoop-aws.jar 를 넣는다.

- 만약 'hadoop-aws.jar' 라이브러리가 없다면 아래 사이트에서 하둡 버전에 맞는 라이브러리를 받는다. (https://mvnrepository.com/artifact/org.apache.hadoop/hadoop-aws)

// 하둡 관련 라이브러리 위치 확인후 해당 경로에 'hadoop-aws.jar' 가 있는지 확인했더니 있다.
$ hadoop version
Hadoop 3.2.1-amzn-3.1
Source code repository Unknown -r Unknown
Compiled by release on 2021-06-30T04:40Z
Compiled with protoc 2.5.0
From source with checksum 47c8381c39387deae12aa9a33f101b
This command was run using /usr/lib/hadoop/hadoop-common-3.2.1-amzn-3.1.jar
// 하둡 우지 라이브러리 경로에 넣는다.
$ hadoop fs -mkdir /user/oozie/share/lib/lib_20220118032216/aws/
$ hadoop fs -put /usr/lib/hadoop/hadoop-aws.jar /user/oozie/share/lib/lib_20220118032216/aws/
$ hadoop fs -ls /user/oozie/share/lib/lib_20220118032216/aws
Found 1 items
-rw-r--r--   3 root oozie     501707 2022-01-19 05:05 /user/oozie/share/lib/lib_20220118032216/aws/hadoop-aws.jar

2. Oozie 스케쥴 안도는 이슈

- 원인 : 타임존이 UTC 여서 한국 시간과 안맞음

// 해당 설정 파일이 oozie-default.xml 에도 있으나 해당 파일에 설정시 적용이 안되어 oozie-site.xml 에 추가하였더니 동작함

$ vi /etc/oozie/conf/oozie-site.xml
<property>
  <name>oozie.processing.timezone</name>
  <value>GMT+0900</value>
</property>
:wq!

// 우지 재기동

$ systemctl status oozie
$ systemctl stop oozie
$ systemctl status oozie
$ systemctl start oozie
$ systemctl status oozie

3. TOK_TMP_FILE 에러

Error creating temporary folder on: hdfs://x.x.x.x/user/hive/warehouse/datahub.db Error encountered near token 'TOK_TMP_FILE' (state=42000,code=40000)

-  원인

hive warehouse 디렉토리의 쓰기 권한이 없어 임시 폴더 생성 실패 (hue에서 실했으므로 로그인 한 유저인 root 가 해당 디렉토리 권한이 필요)

- 해결 방안

% 실행한 유저가 해당 디렉토리에 쓸수 있는 권한을 부여 

- 가이드  : https://co-de.tistory.com/51 

% warehouse 의 경로를 하둡이 아닌 s3 에 저장되도록 수정

- EMR 의 경우 클러스터를 종료하는 경우도 있어 재구성 시 EC2 서버는 계속적으로 변경 된다. 그러므로 하둡에 저장시 날라가므로 이전에 하둡에 만든 데이터 베이스에 쓰거나 읽을 수 없다.

- hive 웨어 하우스 경로를 s3 로 변경하여 운영 이슈가 발생하지 않도록 한다.

우선 s3 에 warehouse directory 생성 한 뒤

설정을 진행 하며 아래 클러스터 생성 전후로 설정 방법 참고하여 설정한다. 

// 클러스터 생성 시점에 설정시

      "Configurations" : [
                {
                    "Classification" : "hive-site",
                    "ConfigurationProperties" : {
                        "hive.metastore.warehouse.dir" : "s3a://your_s3_bucket/hive_warehouse/",
                    }
                }
            ],

// 클러스터 생성후 설정시

$ vi /etc/hive/conf/hive-site.xml
<property>
    <name>hive.metastore.warehouse.dir</name>
    <value>s3a://emr-hong/data/warehouse</value>
</property>
:wq!

// hive service name find
$ systemctl --type=service  | grep -i hive
$ systemctl status hive-server2
● hive-server2.service - Hive Server2
   Loaded: loaded (/etc/systemd/system/hive-server2.service; enabled; vendor preset: disabled)
   Active: active (running) since 일 2022-01-23 01:33:28 UTC; 1h 42min ago

// hive service restart
$ systemctl stop hive-server2
$ systemctl start hive-server2
$ systemctl status hive-server2
● hive-server2.service - Hive Server2
   Loaded: loaded (/etc/systemd/system/hive-server2.service; enabled; vendor preset: disabled)
   Active: active (running) since 일 2022-01-23 03:16:51 UTC; 2s ago

정상적으로 생성되는지 데이터베이스를 생성해본다.

hive> create database genie_tmp;
OK
Time taken: 0.912 seconds

정상적으로 S3에 만들어 진다.

4. hiveql 에 한글 포함시 우지에서 ??? 으로 읽어 들임

워크 플로우에 하이브 파일을 선택하고 저장해서 돌리면

아래와 같이 선택한 파일이 하둡에 저장된다.

로그를 보면 beeline 의 -f 옵션을 통해 해당 파일을 읽어들여 실행하는데 해당 파일을 읽어 들일때 한글을 못읽어 온다.

서버에서 직접 읽어서 하면 정상적으로 되니.. 어디서 문제인지 모르겠다.

그래서 대처 방안은 아래와 같이 파라미터를 받아서 처리하면 정상적으로 된다.

하이브 파일을 아래와 같이 만들었다면 파라미터에는 'test=한글' 이렇게 하면 정상적으로 된다.

select * from tb_test where test=${test}

5. Oozie 에서 ssh 실행시 permission denied 에러 발생

- 해결 방안 : 마스터 서버에서 oozie 로 접속해서 원격 서버에 공개키 복사 (hue 로 우지 접속시)

// [원격 서버에서 실행]
// pem key 없이 접속 가능하도록 설정
$ sudo vi /etc/ssh/sshd_config
PasswordAuthentication yes
#PermitEmptyPasswords no
#PasswordAuthentication no
:wq!
// 재기동
$ sudo service sshd restart
Redirecting to /bin/systemctl restart sshd.service
// 비밀번호 설정 
$ sudo passwd hadoop

// [우지가 설치 되어있는 마스터 서버 접속]
// 우지 유저로 접속하여 공개키 복사 
$ sudo -su oozie
$ ssh-keygen -t rsa
$ chmod 700 ~/.ssh
$ chmod 600 ~/.ssh/id_rsa
$ chmod 644 ~/.ssh/id_rsa.pub
$ chmod 644 ~/.ssh/authorized_keys
$ chmod 644 ~/.ssh/known_hosts
// 우지 공개키를 원격 접속하고자 하는 원격 서버에 복사하여 비밀번호 없이 접속 가능하도록 허용
$ ssh-copy-id -i ~/.ssh/id_rsa.pub hadoop@원격서버privateIp
: 원격 서버 설정한 비밀번호 입력

// [원격 서버에서 확인]
// 공개키 복사됐는지 확인
$ cat ~/.ssh/authorized_keys

// [우지가 설치 되어있는 마스터 서버 접속]
// 테스트
$ sudo -su oozie
$ ssh hadoop@원격서버privateIp /home/hadoop/test.sh
: 비밀번호 물어보지 않아야함

// [원격 서버에서 확인]
// 실행 됐는지 로그 확인 
$ cat service.log
hello data now : 2022/01/29/17:01:31

 

728x90
Comments