Skip to main content

2 posts tagged with "build-queue"

View All Tags

· 8 min read

0. 준비

Jenkins에 있는 job을 remote trigger 할 일이 생겼다. 자동화를 해야 하기 때문에 적절히 trigger 될 수 있어야 한다. 여기에서 '적절히'는 trigger 되는 job이 후보군 중 일부에만 몰리는 일이 없어야 하며, 동시에 slot (Jenkins의 executor)이 비는 경우도 없어야 하고 가급적 빠르게 시작할 수 있어야 한다는 것을 의미한다.

1. 환경

현재 환경이 가지고 있는 조건들은 아래와 같다.

#1 : 거의 동일한 내용의 작업을 수행하는 job이 복수로 존재한다. (이름만 다른 job)

#2 : 각 job은 parameter를 받도록 되어있고, parameter의 조합은 항상 다르다.

#3 : 각 job은 master / slave 어디에서든 실행될 수 있어야 한다.

2. Executor / Build Queue 특징

2-1. Executor

Jenkins에서 job이 실제 실행될 때 위치하는 공간인 executor는 같은 이름의 job을 단 하나만 가질 수 있다. Executor의 내용을 json이나 xml로 뽑아보면 각 job이 가지고 있는 속성 중에 progress 라는게 있는 것을 확인할 수 있는데 job이 시작된지 얼마나 흘렀는지를 표시하는 값으로 보인다. (진행시간을 second 단위로 표시하는 것으로 추측됨)

2-2. Build Queue

Build Queue는 executor와는 조금 다르게 같은 이름의 job이라도 여러개 위치할 수 있다. 모든 job이 여러개 위치할 수 있는 것은 아니고 parameter가 다른 경우 같은 이름의 job이라도 다른 것으로 인식하는 것으로 보인다. Executor처럼 queue의 내용을 뽑아보면 executor의 progress 대신에 inQueueSince 라는 값으로 처음 queue에 들어온 시간을 저장해두고 있다.

3. 목표

내가 처한 환경에서는 job이 지속적으로 생성되는데(당연하지만), 한 개 job이 작업을 마치는데 시간이 몇분에서 길게는 한시간 이상 소요될 수 있기 때문에 필연적으로 job이 쌓일 것으로 예상된다. Executor는 동일한 이름의 job을 받아 들이지 않기 때문에 동일한 이름의 job을 trigger하게 되면 queue에 쌓이게 될 것이다. Executor가 비어있는데도 queue에 쌓이는 일을 막기 위해서 executor에 없는 job을 우선적으로 trigger 할 수 있어야 한다. Executor가 꽉 찬 경우에는 어쩔 수 없이 queue에 job이 등록될텐데 이 경우 가장 빨리 실행될 수 있을 것 같은 job을 고를 수 있어야 하고 그 job을 trigger 해야한다. 또 queue에는 동일한 이름의 job이 여러개 위치할 수 있기 때문에 복수의 job에 대해서도 고려되어야 한다.

4. Modeling

4-1. Sorting / Weight

전체 job list를 T라고 하자. Executor에 위치한 job list를 E, queue에 있는 list를 Q라고 했을 때 각각을 적당한 기준으로 sorting을 하면 우선순위를 매기기 편할 것이라고 생각했다. 그 기준이 애매할 수 있는데 감사하게도 Jenkins에는 위에 설명된 것처럼 적당한 값들을 저장하고 있다. E는 progress, Q는 inQueueSince를 기준으로 sorting 하기로 했다. Progress는 클수록 시간이 오래 흘렀음을 의미하므로 progress 값이 큰 job은 우선적으로 종료될 가능성이 높다. 그래서 E는 progress를 기준으로 내림차순 정렬하고 Q의 inQueueSince는 progress와 반대이기 때문에 오름차순으로 정렬한다. 이렇게 두 세트를 만들어 보면 정렬된 리스트 중 가장 앞에 위치한 job이 선택에 있어서 가장 높은 우선순위를 갖게 된다.

Executor에 없는 job이 항상 queue에 있는 job 보다는 우선순위가 높아야 하기 때문에 queue에서는 절대 넘을 수 없는 벽 같은 것을 만들어야 했다. 그래서 weight의 개념을 사용하기로 했는데, E와 W의 가중치를 각각 다르게 주되 그 차이를 각각 가질 수 있는 weight의 가용범위보다 크게 하면 벽처럼 사용가능할 것 같았다.

4-2. Model

위에서 정렬된 리스트 E, Q에서 순서대로 weight를 부여한다. 수식으로 만들어보면 아래처럼 되는데 Jw는 job의 가중치 총합계를 의미하고 아래첨자 i는 정렬된 리스트의 index 값 (낮을수록 우선순위 높음), executor와 queue를 분리하기 위한 기본 weight 값이다. Qc는 queue에 존재하는 동일한 job의 갯수이다.

Jw = Ei + (Qi + Wb) * Qc

여기에서 Wb를 결정하기 위해서는 Ei가 가질 수 있는 최대값을 알면 되는데 Ei의 최대값보다 Wb를 크게만 만들면 executor에 없는 job의 우선순위를 queue 보다 높일 수 있다. 고민 끝에 Wb를 적절한 값으로 선택할 수 있었는데 바로 executor의 Total Executor 값이다. Ei 값은 index이기 때문에 job의 갯수에 맞춰서 설정할 executor의 총합보다 클 수가 없기 때문이다. Queue에 복수로 존재하는 job의 경우에는 queue에 하나만 존재하는 job 들보다 우선순위가 확연이 떨어지는데 이것 역시도 절대 넘을 수 없는 경계를 만들 수 있어야 한다.

5. Case

위의 내용을 바탕으로 일단 간단한 경우만 그려보면 아래처럼 된다. 덕분에 복잡할 수 있는 구현을 비교적 단순하게 할 수 있었다. 여러 경우를 고려했을 때 아직은 문제가 없어보이지만 혹시 발견되면 수정할 예정이다.

· 4 min read

Jenkins의 build queue를 살펴볼 일이 생겼다.

 

1. Build Queue

우선 Jenkins에서의 build queue는 수행될 job이 수행되기 전에 쌓이는 공간으로 여기서 대기하다가 job이 executor (slot)에 들어갈 수 있는 상태(executable)가 되면 executor로 이동된다.

Executor에 빈 slot이 없어서 실행되지 못하는 상황에 build queue에 job이 쌓이기도 하지만 동일한 이름의 job이 실행중인 경우 같은 job이 build trigger 된다면 이전에 실행중인 job이 종료될 때 까지 build queue에서 대기한다.

 

2. Build Queue를 사용하려는 이유

자동화에 Jenkins를 사용하고 있는데 remote로 build trigger를 하려다보니 무작정 job을 trigger 할 수 없다. 현재 build queue에 어떤 job이 있는지 executor에는 어떤 job 이 있어서 build 중인지를 확인하고 나서 적합한 job을 trigger 하는게 올바른 접근일 것이다.

 

3. Build Queue 접근

Jenkins에 authentication 설정이 걸려 있다고 해도 build queue api 접근은 가능하다. 이 페이지가 공식적으로 제공되고는 있는데 API에 대한 설명 같은게 없어서 일단은 구현하면서 대략의 구조를 살펴보게 되었는데, 제공되는 API는REST 방식으로 제공된다고 하는데  HTTP / get으로 간단히 접근할 수 있다.

 

4. Build Queue 구조

id

buildableStartMilliseconds

task (color, name, url)

inQueueSince

stuck

blocked

params

why

actions

┣━━━━ parameters (name, value)

┗━━━━ causes (shortDescription, userId, userName)

buildable

 

문서가 없어서 각 요소의 정확한 내용은 아직 알 수가 없지만 Jenkins developer group에 문의를 한 상태다. 이름과 얻어낸 값으로 예상한 내용은 아래와 같다.

[table nl='||']

Key, Type, Description, Note

id, Integer, Trigger된 job의 ID, 계속 변경되는 값으로 보임

buildableStartMilliseconds, Long, ?, 알 수 없음

task > color, String, 상태에 대한 이미지, 이전 상태 나타내는 이미지로 보임

task > name, String, Job의 이름, -

task > url, String, Job의 url, -

inQueueSince, Long, Build Queue에 쌓인 시간, -

stuck, Boolean, 막혔는지 여부, Build Queue에 쌓인 시간이 오래되면 true로 변경됨

blocked, Boolean, ?, stuck과의 차이를 알 수 없음

params, String, Trigger 될 때의 parameter, 줄바꿈된 문자열로 나열되어 활용 어려움

why, String, Build Queue에 쌓인 이유, 동일한 job이 실행중인지 등의 이유에 대한 설명

actions > parameters > name, String, Parameter의 name, -

actions > parameters > value, String, Parameter의 value, -

actions > causes > shortDescription, String, Job 실행에 대한 간단한 설명, -

actions > causes > userId, String, Job을 실행한 사용자의 ID, -

actions > causes > userName, String, Job을 실행한 사용자의 이름, -

buildable, Boolean, Build 가능 여부, -

[/table]

 

참고

actions의 parameters 항목의 경우 job에 parameter를 받는게 아니라면 값이 비어있는게 아니라 아예 생성되지 않는다.

이것은 parameter가 Jenkins 기본 기능이 아니라 parameterized plugin을 이용하는 거라 그런 것으로 생각된다.