2020년 12월 31일 목요일

2020년 회고

2020년 올해는 기술적으로 이것 저것 많이 시도해봤다. 

데이터엔지니어로서 데이터를 다루는 것도 중요하지만 데이터를 수집하고 저장하고 처리하는 구조를 만드는 일이 더 중요하고 어려운 일이라고 생각하기 때문에 이 부분을 공략하는데 주력했던 것 같다. 또한 한번 만들어놓은 구조는 쉽게 바꾸지않기 때문에 다뤄볼 기회가 적은 것도 사실이다.

1분기 쯤에는 카산드라 클러스터에 ZING GC를 도입하기 위해 여러 테스트를 해봤다. G1GC, CMS GC 등 여러 GC를 비교해보고 결국 ZING을 선택했고 국내에서는 최초로 카산드라+ZING 조합의 레퍼런스가 되었다.

2분기 쯤에는 Spark+Cassandra조합으로 memtable을 헤비하게 사용하다가 결국 장애를 발생했고 sstable로 전환하는 작업을 진행했다. 한번에 성공한 것은 아니고 하나를 고칠 때 마다 네트워크장애, 디스크 장애가 순차적으로 발생하여 하나하나 들여다보는 계기가 되었다. 결국 수 많은 시행착오 끝에 꽤 괜찮게 최적화를 했고 분산환경에서 배치시간이나 성능이슈를 해결하는 노하우가 생겼다.

3분기 쯤에는 추천시스템의 A/B Test를 자동화할 수 있는 궁극기(?)인 MAB(Multi Armed Bandit)을 적용하고 싶었다. 여러 자료를 찾아보고 결국에는 도메인으로 풀어야한다는 생각을 개인적으로 했다. 먼저 데이터 수집이 안되고 있었기 때문에 kafka, logstash로 먼저 데이터를 수집했고 이후 Spark Batch로 필요한 데이터를 연산까지는 했지만 결국은 적용하지는 못했다.

4분기 쯤에 가장 기억나는 일은 2020 Data Conference에서 발표를 했던 일이다. 많은 분들이 도움을 주셨고 팀원분들과 Azul Systems 대표님께 감사하게 생각하고 있다.

그리고 아직 진행 중이기는 하지만 거의 마무리가 된 일 중에 하둡2에서 하둡3으로 업그레이드하면서 하둡, 메소스, 스파크 클러스터를 새로 구축하고 아즈카반을 활용한 배치를 모두 옮기면서 전체적인 구조를 다시 한번 생각해보게 되었다. 시스템 분들의 도움을 많이 받아서 중구난방인 디스크 배치도 다시 잡고 Raid 구성도 서버의 역할마다 다르게 세팅하고 재밌었다.

2020년은 빅데이터 플랫폼을 구성하는 각각의 프레임워크를 조금 더 깊게 다뤄보고 안쓰는 기능도 도입하기 위한 테스트 해보고, 설계도 해보면서 꽤 재밌었다.

블로그도 2019년에 비하면 꽤 올랐다.


하둡 3.1.2는 그냥 집에서 개인적으로 설치한 건데 생각보다 조회수가 많다. 내년에는 프로덕션 환경에서 적용할 수 있는 HA 구성까지 한 3.1.4 버전으로 많이 유입이 되었으면 좋겠다.



아무튼 2021년에는 더 재밌는 일이 찾아오기를 바란다.

2020년 12월 30일 수요일

hadoop 3.x ec policy(erasure coding) vs replication 3

하둡3에서 ec policy라는 기능이 생겼다. 말로만 들었던 기능인데 이참에 테스트할 겸 적용해보기로 한다.

하둡2에서 하둡3으로 데이터 마이그레이션을 할 때 공간이슈 때문에 3복제 대신에 ec policy 적용을 고려해보았다.


적용 자체는 path별로 구분해서 적용할 수 있게 되어있었고 적용하면 replication이 아닌 ec policy에 의해 1 replication + @로 저장&관리되는 형태이다.


각종 정보(ex 패리티비트)로 인해 블록수를 더 많이 자치할 수 있어 namenode 입장에서 약간의 overhead가 있다고는 하지만 case by case인것 같고 내 기준에서는 크게 무리될 정도는 아니었기에 바로 적용을 해보았다. 

3 replica가 1 replica로 즉시 바뀌지는 않고 신규로 write되는 것부터 바뀌는 것 같다. 

즉 해당 옵션은 hdfs path별로 on/off 시켜서 동작할 수 있다.


기존 3 replica의 경우 3배의 용량을 차지하는데 ec policy를 사용하면 1.3배 정도로도 데이터를 저장할 수 있다고 한다. 


아무튼 적용하고 장애 테스트를 해보기 위해 해당 block을 저장하고 있는 datanode들을 down시켰더니 그 즉시 해당 data를 읽을 수 없는 문제가 존재했다.

3 replica의 경우 데이터노드가 몇 대 내려가더라도 1대만 살아있으면 즉시 제대로 동작하는데 ec policy는 그러지 못하는 것 같다. 

(또한 -replication 옵션과 -policy옵션을 동시에 사용이 불가능하다.)


현재까지 테스트한 결론으로는 일회성으로 read하는 단순 저장용이나 또는 복구가능한 집계성 데이터는 ec policy를 적용하고 원천 데이터처럼 자주 read하는 데이터들은 그냥 3 replication이 좋을 것 같다.

어쨌든 배치를 돌려야하는데 즉시 read하지 못하기 때문에 적용이 불가능해보인다.


시간관계상 제대로 알아보지 못했지만 분명한 것은 일괄적용하기에는 무리가 있다.

참조 : https://hadoop.apache.org/docs/r3.1.1/hadoop-project-dist/hadoop-hdfs/HDFSErasureCoding.html

2020년 12월 15일 화요일

hadoop name node heap size

hadoop cluster에서 특히 spark cluster를 hadoop data node에 구성을 하기 때문에 name node heap size는 신경 안써도 된다고 생각할 수도 있는데 hdfs가 많아질 수록 신경을 써야한다.

하둡 네임노드의 경우 memory는 data node의 file system에 영향을 받는다. 따라서 하둡 과거버전처럼 block size를 64MB로 할 때보다 128MB로 하면 네임노드의 heap이 확 줄어드는 것을 관찰 할 수 있을 것이다.

아무래도 데이터를 큰 바구니에 담으면 기억해야하는 바구니 갯수가 줄어들테니 당연한 일이다.


아래는 기록용으로 남기려고 한다.

hadoop v2.7.5

하둡 2.7.5버전에서의 block size 256MB이고 모든 데이터가 3 replica를 갖는다. 

file과 directories 갯수에 따른 메모리 사용량이다.


27270751 files and directories, 22352862 blocks = 49623613 total filesystem object(s).

Heap Memory used 27.18 GB of 39.51 GB Heap Memory. Max Heap Memory is 56.89 GB.

Non Heap Memory used 104.05 MB of 106.5 MB Commited Non Heap Memory. Max Non Heap Memory is -1 B.



hadoop v3.1.4

현재 하둡 3.1.4에서 block size도 동일하게 256MB를 잡았고 동일하게 3 replica이다. 100% 마이그레이션을 하지는 않았는데 replica 쪽에 개선이 있어서 메모리를 덜 사용할 것이다.


7,743 files and directories, 11,767 blocks (11,767 replicated blocks, 0 erasure coded block groups) = 19,510 total filesystem object(s).

Heap Memory used 1.99 GB of 5.08 GB Heap Memory. Max Heap Memory is 56.89 GB.

Non Heap Memory used 80.31 MB of 83.31 MB Commited Non Heap Memory. Max Non Heap Memory is <unbounded>.


데이터, 배치 마이그레이션 끝내고 꾸준히 모니터링을 하면서 얼마나 사용하는지 봐야겠다.



2020년 12월 4일 금요일

apache mesos를 세팅하면서

resource manager 중에 yarn vs mesos 뭐가 더 좋은지는 모르겠지만 mesos가 ui 부분에서는 확실히 이쁜 것 같다. 자원도 이쁘게 할당하고 현재 connect된 agent(slave)와 task 각각의 상태를 보는 것이 편리하다. 


물론 사용할 기능적인 측면에서 yarn과 mesos는 100% 같다고 볼 수 있기는 하지만 가장 큰 차이점은 ui의 깔끔함 정도라고 생각을 한다. 찾아봐도 딱히 어떤 것이 좋다 할 수는 없고 대부분의 배치를 mesos로 돌리기 때문에 그런 것 일테지만 어쨌든 개인적으로는 mesos가 더 마음에 든다.

포스팅 시점으로 1.11.0 버전이 최신이다. 설치는 가이드 문서를 참고다. 



완전히 새로 세팅된 OS에서 깔끔하게 offline으로 설치를 하려고 빌드를 하고 실행을 해보면 결국 libaprutil-1.so.0 등의 수 많은 dependency가 없다는 에러때문에 실행이 되지않는다. 따라서 결국에는 가이드 문서에서 요구하는 dependency를 만족시키기 위해서는 초반에 OS를 설치하고 /usr/lib64에 설치될 dependency를 마구마구 설치해도록하자. 


mesos의 경우 zookeeper를 활용하여 HA를 구성하고 마스터는 2대 이상으로 구성을 한다.
master 3대, 나머지는 agent로 생각을하고 그냥 올리면 된다.

빌드를 한 곳에 실행 스크립트가 생기고 각 마스터 3대에서 아래처럼 마스터를 실행한다.
./mesos-master.sh --work_dir=/data01/sw/mesos --logging_level=ERROR --log_dir=/appData01/mesos/log --zk=zk://master1:2181,master2:2181,master3:2181/mesos --quorum=2 --cluster=test-mesos-cluster &
마스터가 3대이기 때문에 quorum은 2로 한다. 만약 2대일 경우 1로 주면 된다.

나머지 서버에서는 agent를 실행한다.
./mesos-slave.sh --master=zk://master1:2181,master2:2181,master3:2181/mesos --work_dir=/data01/mesos --resources='cpus:40;mem:112640' --logging_level=ERROR --no-systemd_enable_support &

resources 옵션을 통해서 해당 서버에서 cpu, gpu, memory, disk 등을 얼마나 포함할건지를 줄 수 있다. 위처럼 하면 --resources='cpus:40;mem:112640' 옵션을 주면 각 agent에서 cpu가 40개, memory가 110G씩 올라온다.
위 링크 문서에서 보면 --resources='cpus:24;gpus:2;mem:24576;disk:409600;ports:[21000-24000,30000-34000];bugs(debug_role):{a,b,c}' 옵션을 줄 수 있는데 port range와 role을 줄 수 있는데 이를 잘 사용한다면 설계할 때 최적으로 설계를 할 수 있을 것이다. 하지만 mesos cluster를 분리해서 운영하는게 더 관리하기는 편해보인다.

마지막으로 spark job을 수행할 때 --master 옵션을 다음처럼 주면 된다. 
--master mesos://zk://master1:2181,master2:2181,master3:2181/mesos

즉 전체를 예로 들면 다음과 같다.

bin/spark-submit \
--master mesos://zk://master1:2181,master2:2181,master3:2181/mesos \
--executor-memory 32G \
--driver-memory 32G \
--class "aaa" \
--total-executor-cores 300 \
/jar_path/test-assembly-1.0.jar

그리고 코드 상에서는 예를 들어 spark.executor.cores 같은 옵션을 통해 각 익스큐터당 자원을 잘 할당할 수 있고 이는 task가 한쪽 서버에 안몰리고 이쁘게 잘 펼쳐져서 배치가 돌 것 이다. 이 부분은 추후에 포스팅을 이어서 해보려고 한다.




2022년 회고

 올해는 블로그 포스팅을 열심히 못했다. 개인적으로 지금까지 경험했던 내용들을 리마인드하자는 마인드로 한해를 보낸 것 같다.  대부분의 시간을 MLOps pipeline 구축하고 대부분을 최적화 하는데 시간을 많이 할애했다. 결국에는 MLops도 데이...