[Netflix TechBlog] Data pipeline asset management with Dataflow by Sam Setegne, Jai Balani, Olek Gorajek Summa
해당 게시글은 비전공자이자 쌩초보 개발자 지망생이 작성한 글로 정확하지 않을 수 있으니 참고해주시길 바랍니다!
피드백과 정보 정정 댓글은 환영입니다 :)
https://netflixtechblog.com/data-pipeline-asset-management-with-dataflow-86525b3e21ca
Data pipeline asset management with Dataflow
by Sam Setegne, Jai Balani, Olek Gorajek
netflixtechblog.com
기본 용어 정리
What is Business Logic?
컴퓨터 프로그램에서 실세계의 규칙에 따라 데이터를 생성·표시·저장·변경하는 부분을 일컫는다. 이 용어는 특히 데이터베이스, 표시장치 등 프로그램의 다른 부분과 대조되는 개념으로 쓰인다.
https://ko.wikipedia.org/wiki/%EB%B9%84%EC%A6%88%EB%8B%88%EC%8A%A4_%EB%A1%9C%EC%A7%81
비즈니스 로직 - 위키백과, 우리 모두의 백과사전
ko.wikipedia.org
What is asset?
SQL이나 JAR 파일 형식으로 된 코드
What is data pipeline?
사전에 정의된 순서와 논리로 데이터를 변형시키는 행위들의 집합
What is Dataflow?
데이터 파이프라인 관리를 위한 넷플릭스 자체 제작 커맨드 인터페이스
What is job?
업무, 데이터 파이프라인에서의 데이터 변환 업무
What is namespace?
workflow asset에 할당된 식별자, Dataflow로부터 실행되는 다른 asset들과 구분짓기 위해 붙여지는 태그
Intro
외부 asset이라 함은 특정 업무를 실행시킬 수 있는 무언가를 의미한다. 이 asset이라는 것은 Scala에서 만들어진 JAR 파일일 수도, Python script or module일 수도, 혹은 단순한 SQL 파일일 수도 있다! 가장 중요한 것은 무엇이냐. 이러한 비즈니스 로직이 workflow 와 독립적으로, 별개로 존재해야 한다는 것이다. (조심스럽게 첨언하건대, 해당 asset이 workflow 내에 존재하게 되면 workflow 에 문제가 생겼을 때 asset을 새로 건설해야 하는 상황이 일어날 수도 있기 때문이지 않을까? 마치 건물 설계도 도면을 건물 안에 놓게 되면 건물이 무너졌을 때 설계도를 다시 그려야 하는 상황을 맞닥뜨리는 것처럼... 사실 어느 바보가 건물 설계도 도면을 건물 안에 넣어놓을까 싶긴 하다.)
이에 따라 workflow를 deploy(해당 단어를 대체할 적합한 한국어 단어를 생각하지 못해 해당 본문에서 deploy와 배치 내지 전개 라는 단어를 교차하여 사용할 예정이다.)할 때에는 다음과 같은 속성을 염두에 두어야 한다!
Properties for the whole workflow deployment
1. Versioning(소프트웨어 버전 작성): workflow 와 assets는 버전 작성이 되어져야 한다. (이 둘은 독립적으로 존재하기에 각각에 표기된 버전을 통해 이어져야 하기 때문이다. 버전이 이 둘을 이어주는 bridge 같은 ...? )
2. Transparency(투명성): 어떤 버전의 asset이 문제를 일으켰는지 쉽게 찾아내기 위해 workflow에 대하여 어떤 버전의 asset이 작동하고 있는지 살펴보아야 한다.
3. ACID deployment: workflow change가 발생하더라도 ACID를 모두 보장할 수 있게끔 하는 것. 이를 위해서는 어떤 버전의 workflow로 돌아갈 수 있는지(roll back)를 인지할 수 있어야 함.
* ACID(Atomicity, Consistency, Isolation, Durability): 데이터베이스 트랜잭션이 안전하게 수행된다는 것을 보장하기 위한 성질을 가리키는 약어.
Atomicity: 중간 단계에서 실패하는 일이 없게끔
Consistency: 일관성 있는 데이터베이스 유지하면서
Isolation: 다른 트랜잭션 연산이 끼어드는 것을 방지하고
Durability: 성공적으로 수행된 트랜잭션은 데이터베이스에 영원히 유지되게끔 한다.
https://ko.wikipedia.org/wiki/ACID
ACID - 위키백과, 우리 모두의 백과사전
ko.wikipedia.org
Previous Solutions
Figure 1에서 보여주고 있는 Previous solutions에서 workflow의 resources/assets를 임의로 바꾸게 되면 문제를 일으키게 된다.
Figure 1를 보게 되면, Workflow assets들이 고정된 S3 location에 저장이 된다. 이후 해당 workflow가 실행이 되면서 저장된 S3 경로에서 assets을 가져오게 된다. 해당 모델은 오랜 시간동안 사용되어져 왔으나, 다음과 같은 결점을 가지고 있다.
1. Does not consider branch/PR deployments
만약 Asset(ex: Scala code)를 S3 내의 대체 장소에 넣는 동시에 이 경로를 가리키는 테스트 버전 (sandbox version) 을 실행시키는 일은 굉장히 복잡할 것이다. (새로운 파일을 저장시키면서 workflow가 이 파일을 활용하는 동시작업이 복잡하다는 뜻으로 추정...)
2. Cannot rollback to previous workflow versions
현재 모델에서는 문제가 생기면 이전 workflow로 돌아가는 것에서 그치지 않고 아예 새로운 asset을 재건설해야 한다. (asset과 workflow가 독립적이지 못하기 때문이다.) 자동적인 roll back을 가능하게 하기 위해 현 모델에서는 새로운 asset을 만들어야 할 뿐더러, deployment를 가능하게 하는 scipt에 새로운 asset이 저장된 경로와 workflow가 이 asset을 활용하기 위해 가리키는 경로를 매번 지정해주어야 한다. 하지만 이는 너무 복잡하다! (파일 하나 만들때마다 새로 옮기고 다시 위치 지정해주는 건 정말 귀찮다... 이런 의미로 추정)
3. Runtime dependency on user-managed cloud storage locations
해당 workflow는 실행을 하며 사용자가 지정한 위치에서 asset을 가져오게 된다. 이 과정에서 workflow 개발자들이 임의적으로 지정한 위치로 인해 runtime dependency 를 야기시킨다. (해당 파일 위치가 잘못되면 에러가 뜰 수 있다..로 추정)
* A runtime dependency is an existing JAR file needed by your plug-in at execution. (C에서 header 같은 느낌)
Adding a Runtime Dependency
In the "Classpath Entries" section of the Runtime tab, click Add and navigate to the required JAR file. Only JARs that are added to the list of runtime dependencies will be included when you deploy the plug-in. © copyright 2005, 2006, 2007 Cisco Systems,
www.eclipse.org
Dataflow deployment with asset management
이를 위해 넷플릭스에서는 Dataflow라는 파이썬 기반 CLI+ 라이브러리 (command linde utility)를 제작하였는데, 이는 workflow의 asset의 테스트와 배치를 동시에 진행할 수 있다!
Figure 2에서 assets 는 UUID 에 저장이 된다. Workflow definiton은 UUID에 의해 정의가 되고, 이 workflow를 deploy 하는 과정에서 Deployment Bundle이 스케쥴링 시스템에 의해 생성된다. 해당 번들에는 workflow가 사용하는 asset이 모두 포함되어 있고, 역으로 해당 번들은 스케쥴링 시스템에 deploy 되어 있다. 번들이 스케쥴링 시스템에 내장되어 있기 때문에 runtime dependency와 같이 외부에서 파일을 가져올 필요가 없다. 즉,
1. Deploying the asset
2. Generating the UUID
3. Building the deployment bundle
이 세 가지 작업을 자동적으로 수행하는 것이 Dataflow (= Referencing system)이다.
Deployment of an asset
이제 실제 Dataflow에 입력되는 명령들을 통해 workflow asset build and deployment 과정에 대해 알아보자! starnger-data 라는, 다음과 같은 구조를 가진 저장소가 있다고 가정해보자!
다음과 같은 명령어를 이용해 프로젝트 내에 어떤 asset 파일이 있는지 확인할 수 있다.
Dataflow에서는 assets을 배치하기 전에 (특히 우리가 이에 대한 변경사항을 만들었다면) unit test를 실행할 수 있다! 물론 이 과정은 선택적인데, 이 이유는 Dataflow가 지속적으로 pull-request(검토 후 병합 요청)가 있을 때마다 테스트를 작동시키기 때문이다.
이제 모든 테스트들이 통과되었다고 가정한 후, DataFlow 명령을 통해 Scala와 Python assets의 새로운 버전을 Dataflow asset registry 에 새로 생성하고 배치해봅시다.
여기서 입력한 명령어는
1. workflow assets의 새로운 버전을 만들었으며
2. UUID에 새로운 asset들을 할당시켰고
3. S3 location에 이 asset들을 배치시키는 업무
들을 포함한다.
위 명령어는 eggs라고 배치된된 것들 중에서 name space가 hello_world 인 것들의 모든 이전 버전들을 보여준다. 이러면 이전 버전의 asset을 찾기가 용이해진다. 즉, 문제가 생겼을 때 roll back 할 수 있는 asset을 쉽게 찾을 수 있다.
Deployment of a workflow
위의 과정을 통해 asset을 배치시켰으니, 이제 이 asset들을 바탕으로 workflow를 deploy 하는 과정을 살펴보자! 해당 workflow는 DAG라는 이름을 가진 pipeline의 일부가 될 것이다.
* yaml file = 데이터 직렬화 양식 파일 (.py , .gradle 파일에 yaml file을 읽을 수 있는 형식이 들어있는 것 같다.)
해당 yaml 파일에서 script: ${dataflow.jar.scala-workflow} 라고 볼드처리 되어 있는 부분의 의미는 해당 경로에 있는 파일들 중 가장 최신 버전의 jar을 사용하여 렌더링(render) 하라는 의미이다. 해당 scipt처럼 가장 최신 버전의 파일에 접근하는 방법도 있지만, 또 다른 두가지 방법도 존재한다. 첫 번째는 asset의 속성을 종류, name space, repo owner, repo name 등의 식별자로 세분화하여 분류시키는 것. 그리고 또 다른 절충안도 존재하는데 총 세가지의 방법은 아래와 같다.
- 현재 branch에서 가장 최신 asset 에 접근 script: ${dataflow.jar|egg.<namespace>}
- 현재 branch에서 특정한 asset에 접근 script: ${dataflow.jar|egg.<namespace>.<build>}
- 특정 키를 활용하여 특정 asset에 접근 script: ${dataflow.jar|egg.<namespace>.<project>.<repo>.<branch>.<commit>.<build>}
이러한 세가지 방법들을 통해 any version of any asset in any workflow 에 접근 가능하게끔 한다.
Workflow Deploy 과정을 거치게 되면 .yaml 파일이 렌더링 된 것을 볼 수 있다. 이후 Scheduler Workflows에도 렌더링 된 yaml 파일이 배치된 것을 확인할 수 있다.
렌더링된 main.sch.yaml을 살펴보자! 본래 yaml 파일의 코드(Figure 9 참고)에는 ${dataflow.jar.scala-workflow}와 같이 작성되어 있는데, 렌더된 이후에는 s3://dataflow/jars/scala-workflow/user/stranger-data/master/39206ee8/1.jar 와 같이 가장 최신 버전의 asset 파일 위치를 가리키는 포인터로 이를 대체해준다! (자동으로 참조할 최신 파일의 위치를 반환해주는 것.)
이해를 위한 끄적끄적
아티클에서 제시된 Previous Solution의 경우, 작업을 실행시킬 때 필요한 asset을 사용자가 정의한 S3 경로에 저장하고 이를 직접 가져와서 쓰게 된다. 그렇기 때문에 새로운 파일을 추가하게 되면 이 위치를 새로 지정해주어야 한다. 이는 제법 번거로운데, Dataflow 툴을 사용하게 되면 이 작업이 수월해지고 safer 해진다. safer 한 이유는 렌더링 하기 이전에는 이전 파일로 계속 데이터 작업을 처리하고 있기 때문에 파일 바꿔치기를 하게 되는 경우보다는 훨씬 안전할 듯하다. 우리가 yaml file에 '최신 파일만 가져오겠다'라는 내용을 작성하고 Dataflow로 deploy 및 render를 하게 되면 자동으로 해당 위치에 지정된 최신파일을 가져오기 때문이다. 즉, S3 file에 asset을 추가하기만 하면 되기 때문이다. 또한 workflow와 asset이 UUID와 Deployment Bundle에 의해, workflow definition 이 Deployment Bundle에 의해 분리되어 있기 때문에 safer 하기도 하다. (runtime에서 망가져도 Deployment Bundle이랑 이어주면 되니까? 이건 무슨 말인지 잘 모르겠다.)
Conclusions
새로운 수단 Dataflow는 workflow 관리를 쉽게, 투명성 있게 그리고 더 신뢰성 있게 만들었다. 그리고 해당 코드를 workflow와 독립적인 것으로 만듦으로써 데이터 파이프라인을 보다 더 안전하게 구조화 시켰다!
느낀점
이해가 될 듯 말 듯~ 블로그에 게시된 코드들은 배운 언어가 아님에도 불구하고 터미널이랑 비슷해서 쉬운 이해..가 가능했다. 다만 이런 분야에 대해 물어볼 사람이 있어서 내가 이해한 내용이 맞는지가 제법 궁금하다. 방법과 대책을 강구해보자...