Planning for Dynamic Programming (Model-Based)

  • Planning = Model-Based: MDP에 대한 모든 정보를 다 알때(Model이 있을 때) ex. environment, state, state transition, ...
  • Dynamic Programming: Planning 문제를 풀기 위한 방법론으로 DP가 되기 위한 조건이 2가지 있다.
    • Optimal Substructure: 전체 큰 문제에 대한 optimal solution이 작은 문제들로 쪼갤 수 있어야 한다. = Bellman Eq가 recursive하게 적용 가능
    • Overlapping Subproblems: subproblems들을 구하고 캐싱하여 계산적 이득 = value function(작은 문제들의 정답값)들이 저장되고 솔루션을 구할 때 재사용된다.

 

MDP가 만족되면 DP를 적용하여 "문제를 푼다"

DP는 MDP에 대한 모든 것을 알고 있다고 가정한다.(full-knowledge = Model-Based)

  • Prediction을 풀기: MDP & Policy가 주어졌을 때, MDP가 Policy를 따랐을 때 리턴을 얼마 받는지, 즉 value function이 어떻게 되는지 v_π를 찾는 문제 = Value Function을 학습 = Policy Evaluation
    • Bellman Expectation Equation을 iterative하게 적용한다.
      1. random하게 v1 초기화
      2. 모든 State에 대해 π를 이용하여 v2 구하기 (synchronous backup)
      3. 2 반복
      4. v_π에 수렴
  • Control을 풀기: MDP가 주어졌을 때, optimal policy π*를 찾는 문제 = Optimal Policy를 찾기
    • Policy Iteration: 결국 π는 policy iteration을 하면 optimal policy π*로 수렴한다
      1. Policy π를 평가: v_π(s) = E[R_{t+1} + rR_{t+2} + ... | S_t=s]
      2. v_π의 값이 가장 좋은 쪽으로 움직임: π' = greedy(v_π)
      3. 1-2 반복
        • Modified Policy Iteration: policy evaluation 단계에서 꼭 v_π가 수렴할 필요 없이 early-stopping도 가능하고, batch 단위로 업데이트도 가능함
    • Value Iteration: policy iteration과 달리 explicit한 policy가 없다
      1. v1 초기화
      2. Bellman Optimality backup(synchronous) 적용
      3. 2 반복
    • Principle of Optimality: Optimal Policy는 두가지 요소로 나뉠 수 있다
      • 첫 action A가 optimal하다 = A*
      • 그 action을 해서 어떤 State s'에 도달하면 거기서부터 또 optimal policy를 따라간다
      • 즉, Bellman Optimality Equation에 따르면 v*(s) = max_a(R_s^a + r\sum_{s' from State} P_{ss'}^a v*(s'))
        • 즉 상태 s의 optimal value를 알기 위해서는 다음 상태 s'까지 진행해봐야 상태 s의 value가 최적인지/아닌지 판단이 가능하다
        • S0 -> S1 -> ... ->St(terminate) 인 시퀀스가 있을 때, V(St)를 알아야 비로소 V0(S0)을 알 수 있다.

 

길찾기 문제

예를 들어 길찾기 문제에서 goal 근처의 value는 goal을 이용하여 계산하게 된다.

*하지만 DP에서 모든 상태에 대한 업데이트를 동시에 진행해야하므로, goal의 optimal value가 goal과 가까운 곳부터 퍼져나가면서 다른 위치의 칸들이 optimal vlaue를 계산할 수 있을 때 까지 여러번 반복된다. 이를 value iteration이라고 한다.

 

  • 알고리즘이 State value function에 의존하고 있으면 한 iteration마다 complexity는 O(mn^2)
  • 알고리즘이 State action value function에 의존하고 있으면 한 iteration마다 complexity는 O(m^2n^2)

 

위의 경우 모두 synchronous backup을 말하고 있는데, asynchronous backup을 하는 경우 computation을 줄일 수 있다.

(State 들이 비슷한 확률로 다양하게 뽑힌다면 수렴도 보장된다.)

asynchronous backup을 할 땐 state에 우선순위를 두고 하면 빠르게 수렴될 수 있는데, Bellman error가 클수록 우선순위를 높게 설정한다. asynchronous backup을 하는 경우에는 계산적 이득 뿐만 아니라 실제로 구현 시 v array를 하나만 사용해도 된다.

  • Bellman error = |max_a(R_s + r\sum_{s' from State} P_{ss'}^a v(s)) - v(s)|

 

State Space가 넓고 Agent가 도달하는 State가 한정적인 경우에는, Agent를 움직이게 해 놓고, Agent가 방문한 State를 먼저 업데이트하는 Real-Time Dynamic Programming 기법이 효과적이다.

 

사실 DP는 full-width backup으로, s에서 갈 수 있는 모든 s'를 이용하여 value를 업데이트 하게 되기 때문에 medium-sized problem에는 효과적이지만, 큰 문제에서는 비효율적이다. (state 수가 늘어날수록 계산량이 exponential하게 증가하므로)

따라서 큰 문제에서는 sample backup을 사용한다. 

  • state가 많아져도 고정된 비용(sample 갯수)로 backup (=dimension이 커질 때 발생하는 문제를 sampling을 통해 해결)
  • model-free 상황에서도 가능

 

Model-Free Prediction

 

 

 

https://www.youtube.com/watch?v=2pWv7GOvuf0&list=PLzuuYNsE1EZAXYR4FJ75jcJseBmo4KQ9-

스터디 시작 전 David Silver 교수님의 강의를 듣고 개념 정리를 했습니다.

 

 

 

Introduction to Reinforcement Learning

  • 문제 setting, 용어 등 기본적인 소개

강화학습에서는 오로지 보상에만 초점을 맞춘다. 미리 정해진 정답값을제공하는 기존 ML과 달리, 강화학습은 reward를 보고 가장 최적의 솔루션을 찾아내는 데 중점을 둔다.

즉, 강화학습의 목적은 최대 보상을 얻기 위해 특정 행동을 지시하는 것이 아니라, RL이 받고 있는 보상을 최적화 하는 방법을 알아내는 것이다. 이런 접근 방식은 인간은 결국 sub-optimal한 정답값에 도달하게된다는 생각에서 출발한다. 따라서 복잡한 시나리오에서 사람이 답을 알려주며 학습을 하게 되면 결국 sub-optimal한 정답값을 학습하게 되기 때문에 차선책에 만족하는 경우가 많다. 강화학습은 알고리즘이 보상을 기반으로 자유롭게 탐색하고 최적화 하도록 함으로써 복잡한 시나리오에서 자율적으로 global optimal을 찾아나갈 수 있다.

 

핵심적인 차이점은 강화학습은 순서가 중요한 sequential data를 사용한다는 점이다. 고정된 예시가 아니라 경험을 통해 학습함으로써, 시간이 지남에 따라 행동에 대한 보상이 누적되며 agent가 따르는 policy가 형성된다.

 

RangL: A Reinforcement Learning Competition Platform

 

강화학습의 목표는 누적된 총 Reward를 최대화하는 것이다.
  • Reward: 단일 스칼라 숫자값, 시간 t 동안 agent가 얼마나 잘 수행했는지 나타내는 지표
  • Agent: Reward의 축적된 합을 최대화하는 것이 목적인 것
    • 강화학습을 수행하기 위해 Reward를 단일 숫자 값으로 표현할 수 있어야 하며, reward가 스칼라 값 하나로 치환 불가능할 정도로 복잡한 경우는 강화학습이 적합하지 않을 수 있다.
Agent는 다음 Action을 결정하는 데 State를 기반으로 의사 결정을 내린다.
  • State: 다음에 무슨 행동을 할지 결정하기 위한 모든 정보들
    • Environment State: environment가 observation(행동에 따라 상황이 어떻게 바뀌었는지)과 reward를 계산할 때 쓴 모든 정보(Agent는 알 수 없는 정보) = Markov
    • Agent State: 다음 action을 하기 위해 필요한 모든 정보 (reward와 observation 값/가공값)
    • Markov State: 어떤 tate가 Markov한지/아닌지
      • Markov하다 = 미래는 전체 히스토리가 아닌 현재 상태에만 의존한다. t 시간에 대한 결정을 할 때 바로 이전 (t-1)에만 의존하여 결정하는 것, 즉 (t+1) 미래의 시간은 현재 t와 관련 있으며, 과거 (t-1)와 그 이전의 시간들과는 관련 없다. 문제를 단순화 하여 agent가 이전의 모든 상태를 기억하지 않고도 그 순간의 보상을 극대화하는 데 집중할 수 있다.

 

 

Agent의 구성 요소

 

Agent의 목표는 Value Function을 최대화 하는 것이다. 이를 위해서는 장기적으로 가장 높은 Reward를 가져오는 최선의 Action을 선택하도록 Policy를 최적화해야 한다. Value Function과 Policy는 상호 의존적이며 반복적으로 개선된다.

  • Policy: State를 Action에 매핑하는 Agent의 행동
    • Deterministic Policy: State가 주어지면 결정적으로 action이 리턴
    • Stochastic Policy: State가 주어지면 가능한 여러 action들이 일어날 확률이 리턴

  • Value Function: 현재 Policy에 따라 State가 얼마나 좋은지 나타내는 지표, 종료될 때까지 받을 수 있는 미래 리워드의 합산
    • v_π(s): State=s에서 시작했을 때, 정의된 policy에 따라 받게되는 총 기댓값 
    • r: discount factor = 미래의 리워드는 불확실하니까 등의 이유로

  • Model: Model을 활용하여 Environment가 어떻게 될지 예측할 수 있다
    • State s에서 Action a를 했을 때
      • State=s에서 Action=a를 취한 후 즉각적인 reward는 무엇을 받을지 예측
      • State=s에서 Action=a를 취함으로써 발생할 다음 State가 무엇이 될지 예측
    • 이러한 모델링 기법은 RL에서 사용될 수도(model-based) / 사용되지 않을수도(model-gree) 있다.

 

 

RL의 분류 (value-based/policy-based/actor critic) vs (model-free/model-based)

 

강화학습 방법은 두 가지로 분류할 수 있다.

  • value-based vs policy-based vs actor critic
    • value-based: policy(x), value function(o) -> 각 state에서 value를 학습하여, 이로부터 도출된 정책을 따르는 데 의존
      • value function만 있더라도 agent 역할을 할 수 있는 경우
    • policy-based: policy(o), value function(x) -> value function을 하용하지 않고 policy를 직접 최적화하는 데 중점
    • actor critic: policy(o), value function(o) -> policy와 value function을 동시에 학습
  • model-free vs model-based
    • model-free: policy and/or value function(o), model(x)
      • 모델을 내부적으로 만들지 않고
    • model-based: policy and/or value function(o), model(o)
      • agent가 내부적으로 environment 모델을 추측하여 만들어서, model에 근거한 action이 이루어짐

 

RL 문제의 종류

 

강화학습에서 Agent는 크게 두 가지 방법으로 Policy를 개선할 수 있다.

  • Learning: Agent가 environment를 알지 못할 때, environment와 상호작용하면서 policy를 개선해나가는 것
  • Planning: Agent가 environment(reward & state transition)를 알고 있을 때, 실제로 environment에서 동작하지 않고도 내부 계산만으로 다양한 시나리오를 시뮬레이션하고 평가함으로써 policy를 개선해나간다
    • ex. 알파고의 몬테카를로 Search

Agent의 주요 목표는 크게 두가지로 나눌 수 있다.

  • Prediction: 주어진 Policy 하에서, 미래를 평가하는 것 = value function 을 잘 학습시키는 것
  • Control: Policy를 최적화하는 것 = best policy를 찾는 것

 

  • 그 외 용어
  • Exploration: environment에 대한 새로운 정보를 발견하기 위해 이전에 해보지 않은 행동을 시도하는 것
  • Exploitation: 이미 가지고 있는 정보들을 활용하여 reward를 최대화하는 것
    • RL 학습이 잘 이루어지려면 Exploration과 Exploitation 두 개념에 대한 균형이 중요하다

 

 

Markov Decision Process(MDP)

  • 강화학습이 적용되는 문제 도메인은 모두 MDP(=완전히 관찰 가능한 환경)이다
  • 강화학습은 MDP으로 모델링할 수 있는 환경에서 최적의 순차적 의사결정을 하는 것이다.
  • MDP: RL에서의 environment를 표현 & environment가 모두 관측 가능한 상황을 말한다.
    • 모든 강화학습 문제는 MDP 형태로 만들 수 있다.

  • Markov Process: n개의 State가 있고, 과거 경로에 관계없이 확률에 따라 State를 옮겨다니는 프로세스
    • State Transition Matrix: action없이 state를 확률에 따라 옮겨다님(Environment를 설명하기 위한 개념)
      • State S -> S'로 옮겨갈 확률 P_{ss'} = P[S_{t+1}=s' | S_t=s]일때, 모든 state의 확률을 나타내는 matrix

  • Markov Reward Process: n개의 State가 있고, 과거 경로에 관계없이 확률에 따라 State를 옮겨다니는 프로세스로, State s일때의 reward는 R_s=E[R_{t+1} | S_t=s]이고 r(discount factor)는 0~1사이 값이다.
    • Return: 강화학습은 return을 maximize하는 것이다.
      • G_t = R_{t+1} + rR_{t+2} + ... = 미래의 리워드 합
    • Value Function: Return의 기대값 = State s에 왔을 때 G_t의 기대값
      • v(s) = E[G_t | S_t=s] = State s에서 시작한 여러 episode들의 평균
    • Bellman Equation: value function은 두가지 부분으로 나뉜다.
      • v(s) = E[G_t | S_t=s] = E[R_{t+1} + r(R_{t+2} + rR_{t+3} + ...) | S_t = s]
        • R_{t+1}: immediate reward
        • r(R_{t+2} + rR_{t+3} + ...): discounted value of successor state = r v(s_{t+1})
      • v(s) = R_s + r\sum_{s' from S} P_{ss'}v(s')
        • R_s: s일때의 reward
        • P_{ss'}: s->s'로 옮겨갈 확률
        • v(s'): s'일때 value function
      • 이를 행렬로 표현하면 V=(I-rP)^{-1}R이다. 즉, 주어져있는 값이므로 역행렬을 통해 한번에 계산이 가능하다.
        • computational complexity는 O(n^3)이므로 비싼 연산임
        • n이 작을 때는 한번에 계산 가능하지만, n이 클 때는 iterative(DP/Monte-Carlo Evaluation/Temporal Difference Learning)한 방법을 사용해야 한다.
  • Markov Decision Process: n개의 State와 Action이 있고, 과거 경로에 관계없이 확률에 따라 State를 옮겨다니는 프로세스로, Action a를 하고 State s일때의 reward는 R_s^a=E[R_{t+1} | S_t=s, A_t=a]이고 r(discount factor)는 0~1사이 값이다.
    • State s에서 Action a를 하면 확률적으로 다른 State들에 도달하게 된다.
      • P_{ss'}^a = P[S_{t+1}=s' | S_t=s, A_t=a]: State s에서 Action a를 했을 때 State s'로 갈 확률
    • Policy: State s일때 Action a를 할 확률 = agent의 행동을 완전히 결정해줌
      • π(a|s) = P[A_t=a | S_t=s]
    • Value Function: 만약 agent의 policy가 고정되면 Markov process와 동일하다고 볼 수 있으며, reward도 마찬가지로 MRP로 볼 수 있음
      • State Value Function: State s에서 Policy π를 따랐을 때, episode들의 평균
        • v_π(s) = E_π[G_t | S_t=s]
      • Action Value Function: State s에서 Action a를 했을 때, 그 이후에는 Policy π를 따랐을 때의 기댓값
        • q_π(s,a) = E_π[G_t | S_t=s, A_t=a]
      • Bellaman Expectation Equation (= Prediction 문제): Bellman Eq.와 마찬가지로
        • v_π(s) = E_π[G_t | S_t=s] = E_π[R_{t+1} + rv_π(S_{t+1})| S_t=s] 
        • q_π(s,a) = E_π[R_{t+1} + rq_π(S_{t+1}, A_{t+1}) | S_t=s, A_t=a]
        • 위 두 식을 결합하면 v<->q로 표현할 수 있다.
          • v_π(s) = \sum_{a from Action} π(a|s) q_π(s,a)
          • q_π(s,a) = R_s^a + r\sum_{s' from State} P_{ss'}^a v_π(s')
          • v_π(s) = \sum_{a from Action} π(a|s) {R_s^a + r\sum_{s' from State} P_{ss'}^a v_π(s')}
        • MRP에서의 Bellman Eq.에 의해 행렬식으로 바꾸면 V_π = (I-rP_π)^{-1}R_π 로 구할 수 있다.
          • 마찬가지로 n이 커지면 구하기 어려우므로, q는 optimal value function을 이용하여 구한다.
    • Optimal Value Function
      • Optimal State Value Function: State s에서 어떤 policy를 따르든 간에, 그 중 가장 큰 value
      • Optimal Action Value Function: q*(s,a) = max_π(q_π(s,a))
      • Optimal Policy: 두 policy 중 더 나은 policy를 비교하기 위해서는 모든 State s에 대해 v_π(s) >= v_π'(s)가 성립하면 Policy π 가 Policy π' 보다 낫다고 할 수 있다.
        • Optimal Policy π*를 따르면 Optimal State Value Function v*(s)와 Optimal Action Value Function q*(s,a)를 구할 수 있다. 그리고 Optimal Policy는 q*(s,a)를 아는 순간 찾을 수 있다.
      • Bellman Optimality Equation (= Control 문제)
        • v*(s) = max_a(q*(s,a)): q*값들이 각 action마다 있을텐데, 그 중 max인 a를 선택하면 v*와 같다
        • q*(s,a) = R_s^a + r\sum_{s' from State} P_{ss'}^a v*(s')
        • 따라서 v*(s) = max_a(R_s^a + r\sum_{s' from State} P_{ss'}^a v*(s')): 이 식은 max 때문에 linear equation이 성립하지 않아 역행렬을 구하여 풀 수 없는 문제가 된다. 즉, 다양한 iterative solution method로 풀이를 해야한다.(value equation/policy equation/q-learning/sarsa)

 

우연한 기회에 ML 소프트웨어 엔지니어 7년차분과 커피챗을 할 수 있는 기회가 생겼다.

현재 대학원에 재학중인 나는 시스템 수준의 트레이스를 분석하거나,

이를 통해 머신러닝 학습 프로세스를 최적화 하는 방법들에 관한 페이퍼들을 써왔다.

 

대학원 과정에서 혼자 연구 주제를 구체화하고 연구를 진행할 때면,

이게 진짜 학교 밖에서도 요구되는 주제인지

내가 하고 있는 일들이 기업이 원하는 역량들인지 고민됐다.

 

모든 것이 순조롭게 진행된다고 가정할 때, 졸업이 1년정도 남은 상황인데

나는 취업을 위해 구체적으로 어떤 역량을 키워야하는지에 우선 순위에 대한 불확실성에 대해 계속 고민중이었다.

이런 고민들에 보다 명확한 답을 찾기 위해서 커피챗을 신청하게 됐다.

 

 

커리어패스를 명확하게 하는 것이 좋다

1. 학계에 남거나, 2. 기업의 연구원이 되거나, 3. 기업에서 소프트웨어 엔지니어가 되는 등

컴공 대학원생의 진로는 다양할 수 있고, 나는 이들 중 회사에서 엔지니어 일을 하고 싶었다.

 

대학원에서 가르치는 역량은 논문 라이팅이 주가 되고 있는 상황이기 때문에,

기업의 엔지니어는 대학원 졸업생에게 어떤 역량을 기대할 것 같은지 다시 여쭤봤다.

 

 

회사가 나에게 요구하는 역량, 내가 준비해야할 것

  • 엔지니어링 팀에 지원하더라도 인터뷰에서는 박사 과정에서 주로 했던 분야에 관해 가장 많이 물어볼 것이다
  • 박사 과정 학생이 해야할 일에 집중할 것

대학원 이전에도 인턴십 경험이 조금 있는데, 여름학기에 인턴을 다시 지원하는 것도 괜찮을 것이며,

학부 과정에서 배웠던 CS 기초 내용에 대한 지식의 지속적인 관련성을 강조하시면서 기본기에 충실한 학습을 하라고 하셨다.

라이브 코딩이 이루어지면서 이에 관한 소프트스킬도 연습하면 좋다고 하셨다.

 

추가적으로 박사 과정의 경우 종종 시스템 디자인 설계에 대한 부분까지도 기대하기도 하는데,

이는 실제 경험이 없으면 사실 어려운 일이다. 이런 역량을 쌓기 위해서는 잘 쓰여진 책을 살펴보라는 조언을 들었다.

 

나는 작년 오픈 소스 프로젝트에 코드를 기여하지 못한 것에 대해 아쉬움이 들어 재지원을 고민하고 있었다.

멘토님께서는 그런 기여가 유익하긴 하지만, 박사 과정 학생으로서 해야 할 일에 대한 우선순위를 잘 세우라고 조언을 주셨다.

오픈 소스 작업을 학업과 연계하는 것은 좋다고 하셨다.

 

 

엔지니어링 분야의 업계 동향과 발전 사항

  • 개발자 컨퍼런스나 기술 블로그
  • Hidden Technical Debt in Machine Learning Systems .. etc

평소 최적화를 위해, 그리고 ML 모델 서비스의 최신 동향과 발전을 파악하기 위한 접근 방식에 대해 여쭤봤다.

 

학술 논문은 사실 실험실 환경에서 제안된 솔루션인 경우가 많아 실용적인 엔지니어링 인사이트를 얻는 것이 어려우며,

대신 모니터링 모범 사례 등과 같은 빅 테크에서 정리된 페이퍼는 도움이 될 수 있다고 하셨다.

 

주로 현업 개발자 컨퍼런스나 기술 블로그가 유용한 리소스이며,

특정 주제에 대해 깊게 파고들 때는 책/논문/컨퍼런스 가리지 않고 참고한다고 하셨다.

 

 

 

새해를 맞이하면서 계획을 세우고, 만다라트도 만들고(ㅋㅋ) 여러가지를 준비하느라 바빴다.

해야할 일이 너무 많은것 같아서 부담스럽기도 했다.

멘토님께서는 참고만 하라고 하셨지만, 할 일에 대한 우선순위를 확신을 가지고 정하는데 너무너무 도움이 되는 시간이었다!!

 

흥미롭게도, 과거에는 기업의 ML 시스템에 시스템 수준 최적화가 일반적인 초점이 아니었는데

이제 사용자 디바이스에서 직접 모델을 제공하면서 제한된 환경에서 모델 서빙에 최적화가 많이 이루어지고 있다고 하셨다.

귀중한 인사이트와 여러 조언을 들으며 시간을 내주신 멘토님께 감사했다~ :>

 

💡 요약
- abstract: 컨테이너화된 환경을 위해 설계된 IO 제어 솔루션에 관한 연구
- introduction: 블록 스토리지를 위한 기존의 IO 제어 메커니즘은 스토리지 디바이스의 하드웨어 이질성과 데이터센터에 배포된 워크로드의 특수성을 고려하면서 최신 SSD에 알맞게 낮은 오버헤드로 실행되지 못한다는 문제가 있다.
- related works:
  - IO 제어 및 공정성 분야의 다양한 관련 연구
  - 프로덕션 스토리지 디바이스 전반의 성능 변동성, SSD 성능 예측을 위한 모델링 접근법, 가상 머신 모니터를 위한 IO 솔루션에 대한 연구
  - IO 스택의 여러 계층에 걸친 정보를 고려해야 할 필요성
  - 컨테이너를 위한 리소스 관리 솔루션과 아키텍처 확장
- method: 디바이스별 모델을 사용하여 각 IO 요청의 디바이스 점유율을 추정하는 방식으로 작동한다. => 오프라인 프로파일링, 디바이스 모델링, 새로운 작업 절약형 예산 기부 알고리즘을 활용하여 데이터센터의 다양한 워크로드와 이기종 스토리지 디바이스에 대해 확장 가능하고 작업을 절약하며 오버헤드가 낮은 IO 제어 기능을 제공함
- experiment: Meta의 모든 컨테이너에 IOCost를 배포하여 평가한 결과, IOCost는 최소한의 오버헤드로 비례적이고 작업을 절약하며 메모리 관리를 인식하는 IO 제어 성능이 뛰어났다.
- conclusion & discussion: IOCost는 ZooKeeper 배포, AWS Elastic Block Store/Google Cloud Persistent Disk 등의 원격 스토리지에서도 사용 가능하다.

 

 

Introduction

최근 주요 클라우드 업체들에서 컨테이너 기반 솔루션을 제공하고 있으며,

  • https://aws.amazon.com/ko/containers/
  • https://cloud.google.com/containers?hl=ko
  • https://azure.microsoft.com/en-us/products/container-instances/

프라이빗 데이터센터에서도 컨테이너로 운영되는 추세이다. (Facebook도 전체 데이터센터가 컨테이너로만 운영되고 있다고 함)

 

기존에는 컴퓨팅, 메모리, 네트워크에 대한 리소스 격리에 대해 많은 연구가 이루어져왔는데, 블록 스토리지에 대한 기존 IO 제어 메커니즘도 개선이 필요하다.

  • IO 제어는 데이터센터의 하드웨어 이질성을 고려해야 한다. 디바이스 종류 뿐만 아니라 한 유형 내에서도 지연 시간 및 처리량 측면에서 크게 다른 성능 특성을 가지기도 함.
    • 특히 짧은 순간에 성능을 과도하게 발휘한 후 급격히 느려져 스택 환경에 악영향을 미칠 수 있는 SSD 특성을 고려해야
  • IO 제어는 다양한 애플리케이션의 이질성을 고려해야 한다.
    • 지연 시간에 민감 vs 처리량 vs 순차적 또는 무작위 액세스를 버스트 또는 연속적으로 수행

=> 하드웨어 + 애플리케이션 이질성으로 인해 지연 시간과 처리량 간의 균형점을 파악하는 것이 어렵다

  • IO 격리는 페이지 회수 및 스왑과 같은 메모리 관리 작업과 잘 상호 작용 할 수 있도록 고려되어야 한다.

 

 

Background

1) cgroup: 컨테이너별 리소스 할당을 구성하기 위한 기술

컨테이너 런타임은 리소스 제어 및 격리를 위해 cgroup을 사용한다.

  • cgroup: 컨테이너가 프로세스를 계층적으로 구성하고 계층을 따라 시스템 리소스를 제어 및 구성 가능한 방식으로 배포하기 위한 기본 메커니즘
    • 개별 cgroup이 계층 구조를 형성하고, 프로세스는 하나의 cgroup에 속한다.
    • cgroup 컨트롤러는 주로 가중치를 활용하여 CPU, 메모리 및 IO와 같은 특정 시스템 리소스를 트리를 따라 배포한다.
      • 모든 형제 cgroup의 가중치를 합산하고 각각에 합계에 대한 가중치의 비율을 부여하여 리소스를 배포

2) Linux 블록 레이어와 기존 IO 제어 솔루션

Linux Device Driver - Block Device Layer

애플리케이션과 파일시스템은 블록 계층을 사용하여 블록 디바이스에 접근한다.

그림과 같이 userspace에서 시스템 호출을 통해 커널과 상호 작용하며, 파일시스템에 대한 읽기 및 쓰기 작업은 파일시스템 IO(FS IO)로 블록 레이어로 전달된다.

블록 레이어는 bio 데이터 구조를 사용하여 아래와 같은 다양한 정보를 전달한다.

  • 요청 유형: read/write
  • 크기
  • 대상 장치
  • 장치의 섹터 오프셋
  • 요청한 cgroup
  • 데이터를 복사하거나 복사할 메모리 등의 정보

Linux 커널에는 활성화할 수 있는 여러 가지 IO 스케줄러가 있다.

  • cgroup 제어가 없는 IO 스케줄링: 컨테이너에 특정 IO 리소스를 보장하기보다는 일반적인 성능 속성을 유지하는 데 우선순위를 둔다. 전체 시스템 성능을 유지하기 위해 일반적으로 느린 비동기 read가 일반적으로 빠르고 즉각적인 응답이 필요한 동기 read보다 우선권을 갖지 못하도록 한다.
    • 스케줄러 없는 경우
    • mq-deadline
    • kyber 
  • blk-throttle: read/write IOPS 또는 초당 바이트의 형태로 IO 제한을 설정할 수 있으나, 유휴 상태이거나 사용하지 않는 리소스를 필요로 하는 컨테이너 또는 워크로드에 할당할 수 없다는 단점이 있다.
  • BFQ: IO 리소스를 비례적으로 제어할 수 있으나, 메모리 관리와의 상호 작용을 간과하여 잠재적으로 격리 문제를 일으킬 수 있다. 요청당 오버헤드가 높고 지연 시간 편차가 크며, 컨테이너당 read/write 섹터를 기반으로 하는 라운드 로빈 스케줄링은 내부 작업이 복잡한 최신 디바이스에는 효과적이지 않다는 단점이 있다.
  • IOLatency: 개별 cgroup에 대한 IO 레이턴시 목표를 설정할 수 있으며, 다른 cgroup의 IO가 레이턴시 목표를 초과하면 이전 cgroup이 호출된다. IOLatency는 주로 엄격한 우선순위를 가진 컨테이너 간에 스케줄링은 적합하지만, 동일한 우선순위를 가진 컨테이너에 대해 비례 제어가 부족하여 워크로드 간의 공평성을 보장하기 어렵다는 한계가 있다.

3) 이기종 블록 장치와 워크로드가 있는 최신 데이터센터의 컨텍스트

Meta의 데이터센터에는 다양한 SSD가 있고, SSD간에 하드웨어 디바이스적 성능 특성이 매우 이질적이다.

  • H: 낮은 레이턴시에서 높은 IOPS를 달성
  • G: 낮은 IOPS와 상대적으로 낮은 레이턴시를 제공
  • A: 높은 레이턴시와 함께 중간 정도의 IOPS를 제공

Meta의 애플리케이션을 분석해보면 IO 워크로드가 매우 다양함을 알 수 있다.

  • Web A /B: 가장 일반적인 Meta 워크로드로, 읽기 및 쓰기가 무작위 및 순차 작업 측면에서 거의 동일하게 혼합되어 있다.
  • serverless: 할당용량을 초과하는 경우가 많으며, 읽기 및 쓰기 양이 거의 동일하게 혼합되어 있다.
  • Cache A/B: 인메모리 캐시를 위한 백업 저장소로 고속 블록 장치를 사용하는 인메모리 캐싱 서비스로, 두 캐시 모두 많은 양의 순차적 IO로 이루어져있다. (주로 스토리지 관련 작업을 수행)

 

 

Related Work

  • 기존 연구는 대부분 하이퍼바이저를 개선하기 위함 + VM 기반 가상화 환경에 중점
    • 단일 공유 운영 체제, 메모리 하위 시스템과 IO의 상호 작용, 고도로 스택된 배포와 같은 컨테이너의 복잡성을 고려하지 않는다는 한계점이 존재한다.
  • Linux 커널의 IO 제어는 BFQ 또는 최대 대역폭 사용량(IOPS 또는 바이트) 기반의 제한에 의존
    • BFQ: 우선순위와 요청량에 따라 각 프로세스에 디스크 시간 예산을 할당하여 여러 프로세스 또는 애플리케이션 간에 디스크 대역폭을 공정하게 할당하는 것을 목표로 하는 알고리즘 => 특정 프로세스가 디스크 독점 방지/모든 프로세스가 공평하게 IO 리소스를 할당받을 수 있도록 함
    • 디바이스의 유휴 자원을 모두 활용하지 못하거나, 빠른 저장장치에 과도한 성능 오버헤드를 추가하는 한계점
  • 기존의 CPU 스케줄링은 가중 공정 큐잉과 같은 기술을 사용하여 CPU 사용 시간을 측정하여 CPU 점유율을 비례적으로 배분했는데, I/O 제어에 사용되는 IOPS나 바이트와 같은 지표는 특히 블록 디바이스의 다양성을 고려할 때 점유율을 측정하기 좋지 않다.
    • 최신 블록 디바이스는 내부 버퍼링과 가비지 컬렉션과 같은 복잡한 지연 작업에 크게 의존하므로, 디바이스 시간 공유에 의존하거나 주로 IOPS 또는 바이트를 기반의 공정성 보장 기술에 문제가 있다.

 

 

Method

IOCost는 디바이스의 복잡성과 무관하게 워크로드를 구성하기 위해 디바이스와 워크로드 구성을 분리한다.

  • 각 디바이스에 대해 IOCost는 비용 모델과 디바이스 동작을 정의하고 규제하는 일련의 서비스 품질(QoS) 파라미터를 설정
  • 각 워크로드에 대해 IOCost는 비례 구성을 위해 cgroup 가중치(hweight = 해당 cgroup이 받을 수 있는 IO 디바이스의 최종적인 비중)를 활용
  • 지연 시간이 짧은 issue path 와 주기적으로 동작하는 planning path 를 분리

1) IO 디바이스 점유율을 추정하는 모델링: 개별 bio 작업의 점유를 추정 => 이 점유 추정치를 사용하여 각 cgroup에 할당된 가중치에 따라 스케줄링 결정을 내린다.

  • 선형 모델을 사용하여 읽기/쓰기 초당 바이트 수, 초당 4kB 순차 및 랜덤 IO(IOPS) 등의 매개변수를 기반으로 IO 작업 비용을 계산한다.
    • fio 오픈소스 도구를 이용하여 다양한 블록 크기 및 액세스 패턴(순차 또는 임의), 읽기/쓰기과 같은 다양한 유형의 I/O 워크로드를 시뮬레이션하여 평가함
  • 단순한 선형 모델링만으로는 복잡한 캐싱 메커니즘, 요청 재정렬, 가비지 컬렉션이 있는 최신 SSD의 복잡성을 포착하기에 충분하지 않으므로, 모델의 부정확성을 보완하기 위해 IOCost는 cgroup 사용량과 IO 완료 대기 시간에 대한 실시간 통계를 기반으로 IO 제어를 런타임에 조정한다.
    • 요청 시 자원부족 및 지연 시간 목표 위반을 추적하여(디바이스 포화 상태를 파악) 디바이스로 전송되는 총 IO를 제한하고 QoS 매개변수를 사용하여 디바이스 동작을 규제함 => 일관된 지연 시간 제어
    • QoS 매개변수: 가상 워크로드(ResourceControlBench)를 사용하여 지연에 민감한 서비스의 동작을 관찰하고 그에 따라 QoS 매개변수를 조정하는 체계적인 접근 방식을 개발했다. 다양한 전송률 범위에서 성능을 분석하여 IO 제어를 위한 최적의 지점을 파악 => 일관된 지연 시간을 달성하기 위해 디바이스를 스로틀링하는 방법을 결정

2) 디바이스의 유휴자원을 모두 활용할 수 있는 작업 보존 알고리즘 => 컨테이너가 과도한 메모리를 사용할 때 다른 컨테이너가 불이익을 받는 리소스 격리 문제 해결 = 컨테이너에 대한 블록 IO 제어

  • 개별 cgroup에 할당된 IO 용량을 완전히 활용하지 못하는 경우에는 해당 cgroup의 가중치를 동적으로 낮춤으로써 다른 cgroup이 장치를 활용하고 사용하지 않은 리소스를을 공유할 수 있도록 하여 효율적인 리소스 활용을 보장한다.

3) 런타임 오버헤드를 최소화하기 위해 IO 제어를 빠른 IO별 이슈 경로와 느린 주기적 계획 경로로 분리

  • wall clock time: 작업을 수행하는 데 걸리는 실제 시간으로, 측정된 작업 완료 시간은 당시 시스템에서 수행 중인 다른 작업(CPU, I/O, Sub Program 등)의 영향을 받을 수 있다.
  • vtime(virtual time rate): Wall clock time과 함께 진행되는 글로벌 가상 시간으로, IOCost 시스템에서 각 cgroup 내의 IO 작업의 진행 상황을 추적하고 관리하기 위해 사용되는 개념이다.
    • 로컬 vtime: 특정 cgroup 내 IO 작업의 진행 상황을 나타낸다. 각 cgroup의 IO 작업에 따라 증가하며, 증가하는 속도는 해당 IO 작업의 상대적 비용(동일한 cgroup 내의 다른 작업과 비교하여 IO 작업이 얼마나 많은 리소스 또는 시간을 필요로 하는지)에 의해 결정됨
    • 글로벌 vtime: 모든 cgroup의 모든 IO 작업에 대한 전반적인 진행 상황을 나타낸다. 이는 가상 시간 속도(vrate)에 의해 결정된 Wall clock time과 함께 진행되는 가상 시간이다
    • 스로틀링 결정은 cgroup의 로컬 vtime과 글로벌 vtime 간의 차이(=cgroup의 현재 IO 예산)를 비교하여 이루어지며, 이를 통해 IO를 즉시 실행할 수 있는지 또는 할당된 예산 내에서 유지하기 위해 추가 진행 상황을 기다려야 하는지를 결정함
      • group의 현재 IO 예산이 IO의 상대적 비용을 충당하기에 충분하면 즉시 실행되고, 그렇지 않으면 글로벌 vtime이 더 진행될 때까지 IO가 대기한다.
  • issue path: 로컬 및 글로벌 vtime에 따라 IO 작업의 비용을 결정하고, features에 따라 비용모델을 이용하여 bio의 절대 비용을 계산하고, 스로틀링 결정을 내린다. 각 cgroup에는 가중치(형제 그룹에서의 IO 점유 비율)가 할당되며, 이러한 가중치는 hweight로 재계산되어 캐싱된다.
    • IOCost는 활성 cgroup과 비활성 cgroup을 구분하여, 유휴 cgroup의 남는 자원을 활성 cgroup에서 사용할 수 있도록 한다. 만약 활성/비활성 cgroup의 상태가 변경되면 hweight 가중치를 재계산한다.
      • 활성 cgroup: IO 요청이 있는 경우
      • 비활성 cgroup: IO 없이 전체 planning 기간(= IO 제어 결정이 내려지는 전체 기간)이 지나는 경우로, 가중치 계산 시 무시된다.
  • planning path: 글로벌 오케스트레이션을 담당하며, 데이터센터의 각 cgroup 운영을 조정하여 IO 리소스를 효율적이고 공정하게 분배할 수 있도록 한다. 주기적으로 각 cgroup의 IO 사용량을 평가하고, 그에 따라 가중치를 조정한다. 또한 서비스 품질(QoS) 매개변수를 통해 vrate를 수정하여 cgroup 당 발생하는 IO 요청량을 조정한다.

 

 

Evaluation

다양한 유형의 SSD가 장착된 단일 소켓 64GB 서버에서 테스트 수행

1) 데이터 센터의 고속 SSD에 대한 IO를 제어할 때는 오버헤드를 최소화하는 것이 중요하다.

=> 최대 초당 입출력 작업 수(IOPS)를 측정하는 실험

  • none = 소프트웨어 스케줄러나 컨트롤러가 실행되지 않은 상태로, 디바이스에서 블록 레이어의 달성 가능한 최대 처리량
  • IOCost: issue path/planning path로 분할하므로, 복잡한 스로틀링 로직을 가지고 있음에도 오버헤드가 발생하지 않는다.

2) 유휴 자원의 효율적 활용을 보장하는 것이 중요하다.

=> 서로 다른 우선순위를 가진 워크로드에 대해 요청 지연 시간의 특정 임계값을 초과하지 않고 원활하게 실행되는지 평가

  • cgroup 인식 IO 제어 메커니즘의 성능 => High:Low = 2:1 이 최적의 분배일때
  • IOCost: 예상되는 2:1 비율과 정확히 일치하여 비례 제어에 효과적임을 입증

=> 서로 다른 우선순위를 가진 워크로드에 대해 우선순위 및 지연 시간 요구 사항을 고려하면서, 얼마나 리소스를 비례적으로 잘 배분할 수 있는지 평가

** think time: 다음 연속적인 요청을 실행하기까지 대기/지연 시간 = 새로운 요청이 발생하지 않는 유휴시간

  • IOCost: 우선순위가 높은 워크로드의 레이턴시를 효과적으로 관리하면서, 우선순위가 낮은 워크로드가 유휴자원을 활용할 수 있도록 허용함을 입증

3) 다양한 워크로드 간의 공정성과 적절한 격리를 보장하는 것이 중요하다.

=> 각 메커니즘이 디바이스 점유 측면에서 얼마나 공정성을 제공하고 우선순위가 높은 워크로드와 낮은 워크로드 간에 원하는 비율을 유지하는지를 평가

  • IOCost: random/sequential IO의 비용을 모델링하고 디바이스 점유 측면에서 공정성을 보장함으로써 모든 시나리오에서 원하는 2:1의 비율을 유지한다. 

4) 최신 SSD의 경우, 단순한 모델링 접근 방식은 부정확하기 때문에 이를 효과적으로 보정하는 것이 중요하다.

=> SSD 워크로드에 대해 원하는 서비스 품질(QoS)을 유지하는 데 있어 IOCost의 동적 조정(vrate)의 효과를 평가

  • 처음에는 vrate가 약 100으로 유지
  • 0.5x of model(모델 매개변수 값을 감소 = 장치의 점유량이 이전보다 절반으로 줄어드는 경우): IOPs(읽기 속도)가 떨어지지만, QoS를 유지하며 발급 속도를 약 두 배로 상승시켜 IOPs를 유지한다.
  • 2x of model(모델 매개변수 값을 증가 = 디바이스의 점유량이 이전보다 두 배로 늘어나는 경우): 처음에는 디바이스를 과도하게 포화시켜 지연 시간이 급증하지만, QoS를 유지하기 위해 vrate가 초기 값의 약 절반으로 떨어지면서 지연 시간이 감소한다.

5) 효율적인 리소스 확보를 위해 메모리 관리 통합이 중요하다. (우선순위가 높은 워크로드에 리소스를 보장하면서 우선순위가 낮은 워크로드가 나머지 리소스를 활용할 수 있도록 리소스를 적절하게 회수하기 위해)

=> 여러 조건에서 웹 서버 처리량을 평가

  • IOCost: 메모리 누수 프로세스와 같은 까다로운 조건에서도 웹 서버 처리량을 일정하게 유지

=> 오버커밋 환경에서 IOCost의 성능을 평가

  • ramp up time: 본 실험에서 최대 부하의 40% -> 80%로 확장하는 데 걸리는 시간
  • IOCost: BFQ보다 약 5배 빠르게 스케일업을 완료할 수 있다

6) 여러 컨테이너 간에 IO 서비스의 공정한 할당 중요하다.

=>  Zookeeper와 유사한 워크로드에서 노이즈가 많은 이웃 앙상블과 스냅샷의 영향을 얼마나 잘 차단하는지, 그리고 읽기 및 쓰기 작업에 대한 레이턴시 서비스 수준 목표(SLO)를 충족할 수 있는지 평가

  • IOCost: 노이즈가 많은 이웃 앙상블과 스냅샷의 영향을 효과적으로 격리하여 서비스의 레이턴시 SLO 위반을 최소화한다.
    • SLO 위반이 1.5s, 1.04s 두번만 발생함

7) 퍼블릭 클라우드와 같은 원격 블록 스토리지 환경에도 적용 할 수 있어야한다.

=> 로컬 스토리지와 원격 연결 스토리지를 포함한 다양한 구성에서(AWS 및 Google Cloud와 같은 퍼블릭 클라우드) IOCost가 IO를 얼마나 잘 격리할 수 있는지 평가

  • 지연 시간에 민감한 워크로드(ResourceControlBench)를 AWS Elastic Block Store(gp3-3000iops, io2-64000iops) 및 Google Cloud persistent disk(balanced, SSD)를 사용하여 다양한 구성에서 메모리 누수 워크로드와 함께 배치
  • IOCost를 적용하지 않은 경우: 두 워크로드 간에 간섭이 발생하여 RPS(초당 요청)가 감소
  • IOCost가 적용된 경우: 메모리 누수 워크로드로 인한 간섭으로부터 ResourceControlBench를 효과적으로 격리하고 보호하여 RPS가 높은 값으로 나타난다.

8) 경합이 심한 조건에서도 시스템 서비스 및 워크로드 간에 IO 리소스를 공정하게 분배(비례 제어 기능)할 수 있어야한다.

** IO 고갈로 인한 통신 장애 및 성능 저하가 발생할 수 있는 데이터센터의 패키지 가져오기 장애/컨테이너 정리 장애에 유용

=> 비례 제어 기능을 갖춘 IOCost가 이러한 장애 발생을 크게 줄이고 시스템 안정성과 리소스 관리를 개선할 수 있음을 입증

- package fetching: 컨테이너화된 애플리케이션에 필요한 소프트웨어 패키지 또는 종속성을 검색하는 프로세스 => IO 고갈(충분한 입출력 리소스 부족)이 발생하면 패키지 검색에 실패하고 후속 컨테이너 업데이트에 실패할 수 있다.

  • IOCost가 활성화되면 해당 리전에서 package fetching 오류의 비율이 감소하여 IOLatency와 비교했을 때 오류가 10배 감소

- container cleanup: 데이터센터 환경에서 오래된 컨테이너를 제거하거나 삭제하는 프로세스 => 리소스 경합이나 기타 요인으로 인해 이 작업 중에 IO 고갈이 발생하면 오래된 컨테이너 정리가 지연되어 성능이 저하되거나 충분한 디스크 공간을 확보할 수 없을 수 있다.

  • IOCost가 활성화되면 container cleanup 실패 발생이 IOLatency에 비해 3배 감소

 

 

Discussion

요즘 연구해보고 싶은 분야와 비슷해서 정말 많이 도움됐다.

컨테이너 기술 동향에 대해서도 살펴볼 수 있었다.

** 컨테이너를 위한 아키텍처 및 OS 확장에 관한 연구

  • D. Skarlatos, Q. Chen, J. Chen, T. Xu and J. Torrellas, "Draco: Architectural and Operating System Support for System Call Security," 2020 53rd Annual IEEE/ACM International Symposium on Microarchitecture (MICRO), Athens, Greece, 2020, pp. 42-57, doi: 10.1109/MICRO50266.2020.00017.
  • D. Skarlatos, U. Darbaz, B. Gopireddy, N. Sung Kim and J. Torrellas, "BabelFish: Fusing Address Translations for Containers," in IEEE Micro, vol. 41, no. 3, pp. 57-62, 1 May-June 2021, doi: 10.1109/MM.2021.3073194.

 

 

💡 요약
- abstract: 컨테이너 라이브 마이그레이션의 사전 복사 알고리즘에 더티 페이지가 반복적으로 전송되는 문제를 해결하기 위한 연구
- introduction: 라이브 마이그레이션에서 가장 널리 사용되는 기술인 사전 복사 알고리즘은 메모리 집약적인 시나리오에서 메모리 페이지의 복사를 반복하기 때문에 전송되는 데이터의 양과 총 마이그레이션 시간이 늘어날 뿐만 아니라 반복 프로세스가 수렴되지 않아 마이그레이션이 실패할 수 있다는 문제가 있다.
- related works: 
- method: 프로그램 운영체제의 locality 원칙을 활용하고, 더티 페이지 예측을 위해 랜덤 포레스트 모델을 사용하여 반복되는 더티 페이지 전송을 건너뛴다. 페이지 압축과 함께 incremental page만 전송하여 기존의 사전 복사 방식에 비해 데이터 전송 및 마이그레이션 시간을 크게 단축했다. => 메모리 페이지와 인접한 페이지의 더티 레코드를 수집하고 머신러닝 모델을 사용하여 향후 페이지가 더티화될지 여부를 예측함
- experiment: 더티 페이지가 적게/많이 발생하는 환경에서 제안하는 알고리즘은 가장 최적의 결과를 보여주었다. 
- conclusion & discussion: ML 접근법을 사용하여 컨테이너 라이브 마이그레이션을 최적화하기 위한 알고리즘을 설계했으며, 전송 데이터를 줄이기 위해 압축 알고리즘을 함께 사용했다.

 

 

 

Introduction

  • 가상화
    • 가상 머신
    • 컨테이너 가상화:
      • 경량, 휴대성, 빠른 시작 속도
      • Docker, LXC, Podman 
  • 서비스 마이그레이션: 가상시스템을 다른 곳으로 이동
    • 콜드 마이그레이션: 전원이 꺼져 있거나 일시 중단된 가상 시스템을 새 호스트로 이동
    • 라이브 마이그레이션 (=핫 마이그레이션): 전원이 켜진 가상 시스템을 새 호스트로 이동
      • 마이그레이션 과정에서 서비스가 영향을 받지 않도록 하는 것을 목표로 한다.
  • 사전 복사(pre-copy) 알고리즘: 라이브 마이그레이션에서 가장 널리 사용되는 기술로, 컨테이너가 실행되는 동안 메모리 페이지가 소스에서 대상으로 전송된다.
    • 사전 복사는 일반적으로 남아 있는 더티 페이지 수가 충분히 낮을 때 종료된다. => 메모리 집약적인 시나리오에서 사전 복사 알고리즘은 반복 단계에서 메모리 페이지의 복사를 반복하기 때문에 전송되는 데이터의 양과 총 마이그레이션 시간이 늘어날 뿐만 아니라 반복 프로세스가 수렴되지 않아 마이그레이션이 실패할 수 있다.
    • c.f. Post-copy는 네트워크를 통해 각 페이지를 한 번만 전송하는 반면, Pre-copy는 마이그레이션 중에 페이지가 소스에서 반복적으로 write가 발생하는 경우 동일한 페이지를 여러 번 전송할 수 있다.
      • Pre-copy: 마이그레이션 중에 source에서 VM 상태를 최신 상태로 유지
      • Post-copy: source와 destination 간에 VM 상태를 분할
      • 실시간 마이그레이션 중에 대상이 실패하면 사전 복사는 VM을 복구할 수 있지만 사후 복사는 복구할 수 없다

 

Related Work

  • pre-copy: 더티 메모리 페이지를 반복적으로 복사하여 가상 머신 다운타임을 단축, 부하가 높고 메모리 쓰기 집약적인 시나리오에서는 반복 단계에서 일부 메모리 페이지가 자주 수정되어 매우 더티한 일부 메모리 페이지가 반복적으로 전송될 수 있어서 전송되는 데이터의 양을 증가시킬 뿐만 아니라 반복 프로세스가 수렴하지 못하는 원인이 될 수 있다
    • 페이지 중복 전송 문제를 피하기 위해, 자주 더럽혀지는 페이지를 추적하여 전송 종료 단계에 저장하는 재사용 거리 개념 제안
    • 마르코프 예측 모델을 사용하여 메모리 페이지의 기록된 과거 동작을 사용하여 상태 전이 행렬을 통해 페이지가 다시 수정될 확률을 계산하고 예측 확률이 낮은 페이지만 전송하는 방법을 제안
    • related dirty rate에 기반한 예측 방법을 제안했다. 페이지의 수정 확률 P를 실제 수정 시간 R과 결합하여 관련 더티 페이지 비율 PR을 얻은 후, R과 PR이 모두 설정된 임계값보다 큰 경우에만 페이지 전송을 건너뛴다.
    • => 페이지의 시간적 상관관계만 고려할 뿐 공간적 상관관계는 고려하지 않음
    • 마이그레이션 과정에서 메모리 더티 페이지의 생성 속도를 줄이기 위해 CPU 스케줄링을 사용하여 마이그레이션의 원활한 진행을 보장함 => 필연적으로 애플리케이션 성능 저하로 이어질 수 있으며 여러 번의 반복이 완전히 해결되지 않음
    • 대역폭 인식 기반의 데이터 압축 방법을 제안하여, 마이그레이션 대역폭에 따라 적절한 압축 알고리즘을 동적으로 선택하여 전송할 페이지를 압축한 후 목적지로 전송함으로써 전송 데이터의 양을 줄이고 전체 마이그레이션 시간을 단축함
  • post-copy
  • hybrid copy
  • 로그 기반 추적
  • 복제 마이그레이션

 

가상 머신에 비해 컨테이너 라이브 마이그레이션에 대한 연구는 상대적으로 적다.

  • Virtuozzo: 컨테이너에서 라이브 마이그레이션을 지원한다. 마이그레이션을 수행하는 데 필요한 주요 프로세스와 기능을 커널에 통합하여 구현하기 때문에 Virtuozzo 커널은 고도로 커스터마이징된 커널로, 메인스트림 Linux 커널에서 동일한 기능을 구현하기 위해 Virtuozzo는 CRIU 프로젝트를 설립했다.
    • CRIU: Linux에서 실행되는 오픈 소스 소프트웨어 도구로, 사용자 공간에서 프로세스를 체크포인트 및 복원할 수 있다. 즉, 체크포인트 메커니즘을 사용하여 실행 중인 애플리케이션을 동결하고 해당 상태 정보를 디스크에 이미지 파일로 덤프한 다음, 이 이미지 파일을 사용하여 복원 작업을 수행하여 동결된 지점에서 복구하고 프로그램을 다시 실행할 수 있다.
    • => 현재 Docker에는 컨테이너 마이그레이션 작업을 지원하는 통합 CRIU 도구가 있지만, 이 접근 방식은 상태 저장 컨테이너 마이그레이션을 지원할 수 없으며 과도한 다운타임을 초래한다.
  • P.Haul: Docker 컨테이너의 외부 마이그레이션을 가능하게 하는 OpenVZ에서 시작한 프로젝트로, 외부 마이그레이션은 P.Haul이 CRIU를 통해 Docker 컨테이너 내 프로세스의 실시간 마이그레이션만 구현하기 때문에, 이 방식은 destination 단의 Docker 엔진이 컨테이너를 관리할 수 있는 기능을 상실하게 된다.
  • 중첩 가상화와 컨테이너 마이그레이션을 통해 메모리 공간을 리매핑하여 동일한 호스트에서 컨테이너 메모리 마이그레이션을 최적화 => 호스트 간 컨테이너 마이그레이션을 지원하지 않는다.
  • NFS를 사용하여 데이터 전송을 용이하게 하는 방법도 있는데, 이는 메모리 집약적인 워크로드를 마이그레이션할 때 긴 다운타임을 유발한다.
  • 파일 시스템 공유 방식을 사용하여 포스트카피와 파일 시스템 유니온을 기반으로 실시간 마이그레이션을 하는 방법도 있다.

 

Method

  • original pre-copy algorithm: 
    • 반복 마이그레이션 단계: 첫 번째 라운드에서 모든 메모리 페이지를 대상 호스트로 전송하고, 이후 각 라운드에서는 이전 라운드 반복 후 수정된 메모리 페이지(더티 페이지)만 전송한다. 셧다운 마이그레이션 조건이 충족될 때까지 이 반복 프로세스를 반복한다.
    • 셧다운 마이그레이션 단계: source 호스트는 컨테이너를 잠시 중지하고, 더티 메모리 페이지의 마지막 라운드와 CPU 등의 기타 상태 정보를 대상 호스트에 전송한 후, 이러한 정보에 따라 destination 호스트에서 컨테이너를 재시작한다.
    • => 메모리 집약적인 쓰기 부하에서는 반복적인 마이그레이션 단계에서 일부 메모리 페이지가 자주 쓰기 되어 페이지 전송이 반복됨

 

  1. 일정 기간 동안 컨테이너 메모리의 변경 사항을 수집
  2. 수집한 메모리 더티 데이터를 사용하여 생성된 더티 페이지를 예측 => 더티 페이지가 많은 페이지의 전송을 생략하고 페이지 압축을 사용하여 데이터 전송을 줄인다.
  3. (반복적인 복사본 마이그레이션 단계) 페이지 예측과 페이지 압축을 사용하여 더티 페이지의 전송을 최적화한다. 최대 반복 횟수에 도달하거나 더티 페이지 데이터 크기가 수렴하는 등 셧다운 마이그레이션 조건이 충족되면 셧다운 마이그레이션 단계로 진입
  4. 셧다운 마이그레이션 단계로, source 호스트는 컨테이너 실행을 중지하고 컨테이너의 남은 더티 페이지를 압축한 후 CPU 및 기타 상태 정보와 함께 대상 호스트에 전송
  5. 컨테이너 복구 단계로, destination 호스트는 수신한 메모리 데이터 정보에 따라 컨테이너의 동작을 재개

 

더티 페이지의 반복 전송 문제를 해결하기 위해

  • 더티 페이지 예측: 일정 기간 동안 컨테이너 메모리의 변경 사항을 수집하여 더티 페이지가 향후에도 계속 더티 페이지가 될 확률을 예측하여 더티 비율이 낮은 페이지를 전송할 페이지 세트에 추가하고 더티 비율이 높은 페이지의 전송을 건너 뛴다.
    • 기존의 더티 페이지 예측 방법은 대부분 시계열 예측 방법을 사용하는데, 본 논문에서는 기존 방식과 달리 머신러닝 방식을 사용한다.
      • 특징 추출 방법: 지역성 원리에 기반한 특징 선택
        • 시간적 지역성: 현재 더럽혀진 페이지가 가까운 미래에 다시 더럽혀질 가능성이 높다는 것을 의미
        • 공간적 지역성: 현재 더럽혀진 페이지에 인접한 주소 페이지가 가까운 미래에 더럽혀질 가능성이 높다는 것을 의미
      • 오프라인에서 모델을 학습하는 데 사용하여 컨테이너의 온라인 마이그레이션에 적용한다. 
        • 랜덤 포레스트: 과적합이 쉽지 않고 일반화 능력이 높기 때문에 예측 모델로 선택했으며, 특징 윈도우 m*n이 증가함에 따라 모델 예측 정확도가 증가하는 것을 확인함
        • 실제 컨테이너 마이그레이션에서는 피처 윈도우가 커질수록 예측 시간 오버헤드가 발생하게 되므로, 본 논문에서는 예측 효과와 예측 시간의 균형을 맞추기 위해 피처 윈도우 m=5, n=5로 고정

더티 페이지 예측 방법을 기반으로 설계한 전송 페이지 선택 알고리즘

  • PageList: 컨테이너 메모리에 있는 모든 페이지의 집합 => 각 반복 후 관련 페이지 정보를 업데이트해야 한다.
  • Dirty: 이번 라운드의 더티 페이지 집합
  • ToTransmit: 이번 반복에서 최종적으로 전송할 페이지의 집합
  • ToSkip: 반복 중에 전송을 건너뛰는 페이지의 집합
  • RFModel: 랜덤 포레스트 예측 모델로, 예측이 1이면 향후에도 페이지가 dirty 할 것을 의미한다. 

각 반복 라운드에서 랜덤 포레스트 모델을 사용하여 현재 더티 페이지가 1로 예측되면 현재 라운드에서 해당 페이지의 전송을 건너뛰고 ToSkip에 추가하고, 예측이 0이면 이번 라운드에서 페이지가 destination에 전송된다.

이번 라운드의 클린 페이지의 경우 이전 반복에서 전송을 건너뛰고 ToSkip에 저장한 경우 이번 라운드에서 제 시간에 대상에 전송해야 한다.

 

 

  • 전송되는 메모리 페이지 압축: 전송할 페이지를 압축하여 네트워크에서 전송되는 데이터의 양을 더욱 줄인다.
    • 페이지를 전송할 때 페이지 단위가 아닌 바이트 단위로 전송한다. 한 반복 내에서 전송할 더티 메모리 페이지가 처음 전송되는지 여부를 확인하고, 처음 전송되는 페이지가 아니면 지난번에 destination으로 전송한 페이지 데이터와 XOR하여 페이지 증분값을 구한 뒤 페이지 증분값을 압축하여 전송한다.
      • 증분 압축의 장점은 페이지 증분에는 반복되는 0이 많이 포함되어 페이지의 압축률을 향상시키는 데 도움이 된다는 것이다.
      • 압축 알고리즘은 LZ4 압축 알고리즘을 선택했으며, 이는 무손실 압축 알고리즘으로 압축 속도가 빨라 메모리 데이터 압축 장면에 적합하고 압축 비율과 압축 속도를 넓은 범위에서 조정할 수 있다.
    • 데이터를 수신한 destination에서는 압축을 풀고 다시 XOR하여 이번 라운드의 실제 메모리 페이지 데이터를 얻는다.

 

 

Experiment

실험 환경: 두 개의 가상 머신에서 Docker 컨테이너의 라이브 마이그레이션을 테스트

  • Ubuntu 18.04 LTS, CPU 코어 2개, 8GB RAM 및 50GB 디스크
  • 두 가상 머신 간의 네트워크 대역폭은 100Mbps

 

컨테이너가 실행 중일 때 다양한 메모리 쓰기 부하를 시뮬레이션하기 위해 모든 크기의 연속 메모리를 신청하고 연속 쓰기 작업을 수행할 수 있는 MemChange 프로그램을 작성하고 이를 컨테이너화했다. 

사전 복사 알고리즘은 메모리 더티율이 전송 대역폭을 초과할 수 없어야 하며, 그렇지 않으면 반복 프로세스가 수렴하지 않거나 심지어 중지되므로 실험 환경의 네트워크 대역폭 100Mbps에 따라 두 가지 메모리 더티 레이트 부하를 설계했다. 
- 메모리 저속 부하: 메모리 더티율 1-2M/s 
- 메모리 고속 부하: 메모리 더티율 11~12M/s 

본 논문에서 제안한 마이그레이션 방법 = MBDPC

예측 알고리즘의 성능을 객관적으로 비교하기 위해 MBDPC에서 압축 알고리즘을 제거한 알고리즘 = MBDP

 

1. 더티 페이지 예측 비교

마르코프, PR 예측 알고리즘과 비교했을 때, 본 논문에서 제안하는 더티페이지 예측 알고리즘의 AUC 값이 약 17% 증가하여 더티 페이지 예측 효과가 더 우수하다는 것을 알 수 있다.

  • x축: FPR(오탐률)
  • y축: TPR(진탐률)
  • AUC: 곡선 아래 영역으로, 모델의 전반적인 랭킹 능력을 반영한다. 넓을수록 좋음

 

2. 다운 타임: 컨테이너가 중지된 후 서비스 복구까지 걸리는 시간 = T stop + T restore

그림은 다양한 메모리 크기일 때, 저속부하에서의 다운 타임을 보여주는데, 기존 사전 복사 알고리즘과 비교했을 때, 마르코프와 PR은 평균 1.1%, 1.3% 감소한 반면, MBDP와 MBDPC는 평균 2.1%, 2.8% 감소했다.

즉, 컨테이너 메모리가 작을 경우 마르코프, PR, MBDP, MBDPC는 최적화 효과가 거의 없는데, = 저속 시나리오에서는 컨테이너 메모리의 수정 속도가 낮기 때문에 1~2회 반복하면 더티 페이지 수가 즉시 종료 조건을 충족하고 종료 마이그레이션 단계로 들어감 (메모리 크기와 메모리 더티율이 낮은 경우 예측 알고리즘에는 일정한 한계가 있다)

 


다양한 메모리 크기에서 메모리 고속 부하의 다운타임을 살펴보면, 메모리 더티율이 높을 때 마르코프와 PR은 원본 사전 복사본에 비해 평균 3.3%와 4.1% 감소한 반면, MBDP와 MBDPC는 평균 3.7%와 34.9% 감소했다.

페이지 예측은 반복 프로세스의 속도를 높이고 셧다운 마이그레이션 단계에서 더티 페이지의 수를 줄일 수 있음을 알 수 있으며, MBDPC는 반복 프로세스의 속도를 더 빠르게 할 뿐만 아니라 페이지 압축을 통해 종료 단계에서 전송 시간 Tstop을 크게 단축할 수 있었다.

 

3. Total Migration Time: 첫 번째 iteration 부터 대상 컨테이너가 컨테이너를 재시작할 때까지의 시간 = ∑T iterative(i) + T stop + T restore

  • 저속 부하에서는 페이지 더티율이 낮음
    • 마코프와 PR이 원본 프리카피에 비해 총 마이그레이션 시간을 단축하는 효과가 적다
    • MBDP와 MBDPC는 평균 3%, 16.5% 단축하여 최적화 효과가 더 높다
  • 고속 로드에서는 페이지 더티율이 높다
    • 원래의 사전 복사 알고리즘은 높은 더티 페이지를 반복적으로 전송하여 라운드당 더티 페이지 수가 종료 임계값보다 낮아질 수 없다. 따라서 반복 시간 n i=1 Titerative(i)가 길어지고 총 마이그레이션 시간이 증가한다.
    • 원본 사전 복사본과 비교하여 예측 알고리즘은 매우 더티한 페이지의 반복 전송을 피함으로써 반복 시간을 줄일 수 있다.

=> 메모리 더티율이 높을 경우 MBDPC가 총 마이그레이션 시간을 더 잘 줄일 수 있다.

 

 

4. 총 전송 데이터: 전체 마이그레이션 과정에서 전송된 데이터의 총량 = TD iterative(i) + TD stop

  • 앞선 내용들과 마찬가지로 메모리 더티율이 낮으면 iteration 프로세스가 빠르게 멈추기 때문에 마르코프, PR, MBDP 알고리즘의 최적화 효과는 상대적으로 적다.
  • 고속 워크로드에서(메모리 더티율이 높으면) 예측 알고리즘은 원본 사전 복사본과 비교하여 반복 과정에서 매우 더티한 메모리 페이지의 반복 전송을 피함으로써 전송되는 데이터의 양을 줄일 수 있다. MBDPC는 페이지 압축을 사용하기 때문에 전송되는 데이터의 총량을 더 줄일 수 있다.

 

 

5. iteration 당 전송되는 데이터의 양:

제안한 MBDPC 방식은 각 라운드의 데이터 양과 마지막에 전송되는 총 데이터 양이 다른 알고리즘에 비해 낮다.

메모리 데이터를 미리 수집하고 첫 번째 라운드에서 예측을 하기 때문에 첫 번째 라운드에서 불필요한 페이지 전송을 피할 수 있다.

 

 

Discussion

본 논문에서는 머신러닝 기법의 더티 페이지 예측을 기반으로 하는 컨테이너 사전 복사 마이그레이션 방법인 MBDPC를 제안했다.

MBDPC는 프로그램 로컬리티 원리를 이용해 메모리 더티 페이지를 예측하여 페이지가 반복 전송되는 것을 방지했다.

본 논문은 단일 컨테이너의 마이그레이션에 대한 연구이며, 향후 쿠버네티스와 같이 널리 사용되는 컨테이너 오케스트레이션 도구와 결합하여 여러 컨테이너 간의 마이그레이션 문제를 해결하는 방법을 고려하면 좋을 것 같다.

 

메모리 접근 특성을 분석하여 시스템 내에서 메모리 관리에 사용하는 쪽만 생각했었는데, 이렇게 라이브 마이그레이션에도 사용할 수 있다는 것을 알 수 있었다. 라이브 마이그레이션에서는 아무래도 전송량이 중요하기 때문에 더티페이지 예측 뿐만 아니라 메모리 압축 기술을 사용했나보다

💡 요약
- abstract: 다양한 워크로드에 대처할 수 있는 유연성을 높이기 위해 컨테이너 기반 애플리케이션의 수평 및 수직 탄력성을 제어하기 위한 강화 학습(RL) 솔루션을 제안한 연구
- introduction: 컨테이너 기반 애플리케이션을 확장할 때 효율성을 최적화하기 위해 확장 정책이 유연하고 적응적으로 동작해야 한다는 과제가 있다.
- related works: 기존에는 수직적 탄력성과 수평적 탄력성을 결합한 연구가 소수만 이루어졌다. 또한 기존에는 탄력성을 구동하기 위해 임계값을 사용했다.
- method: 컨테이너 기반 애플리케이션의 탄력성을 제어하기 위해 모델 없는 솔루션과 모델 기반 솔루션을 포함한 다양한 RL 정책을 사용할 것을 제안했다.
- experiment: 시뮬레이션과 프로토타입 기반 실험을 통해 다양한 RL 접근 방식을 평가했다. 결과적으로 결과는 모델 기반 접근 방식이 사용자 정의 배포 목표에 따라 최상의 적응 정책을 성공적으로 학습할 수 있음을 보여주었다.
- conclusion & discussion: 모델 기반 RL 접근법을 사용하여 컨테이너 기반 애플리케이션의 탄력성을 제어하기 위한 RL 알고리즘을 설계했으며, 제안된 정책을 컨테이너 오케스트레이션 도구인 Docker Swarm에 자체 적응 기능을 도입하는 확장 기능인 Elastic Docker Swarm을 적용했다.

 

 

 

Introduction

컨테이너를 사용하면 수평 및 수직 확장을 통해 애플리케이션 배포를 쉽게 조정할 수 있다.

  • 수평적 탄력성: 애플리케이션 인스턴스(컨테이너) 수를 늘린다. => 컨테이너 구성을 변경하므로 새 구성을 적용하는 데 필요한 시간 동안 전체 애플리케이션을 사용할 수 없게 됨(다운타임 발생)
  • 수직적 탄력성: 애플리케이션 인스턴스에 할당된 컴퓨팅 리소스의 양을 늘리거나 줄인다 => 일반적으로 추가적인 다운타임이 발생하지는 않지만, Docker Swarm에서 스케일 아웃을 수행하면 적응 비용이 발생
    • Docker Swarm에서 스케일 아웃을 수행하면 적응 비용이 발생하는 이유?
    • Docker Swarm의 트래픽 라우팅 전략 때문이다. 새로운 인스턴스가 실행되기 전에도 Docker Swarm은 애플리케이션 요청을 새로 추가된 인스턴스로 보내려고 시도하는데, 이때 해당 인스턴스가 아직 실행 중이지 않으면 응답하지 못할 가능성이 있다. 따라서 이전 버전의 컨테이너를 사용하여 요청을 처리하기 위해 일시적으로 다운 타임이 발생할 수 있다.

이러한 컨테이너의 특성을 사용하여 런타임에 애플리케이션 배포를 적절히 조정하여 성능을 유지할 수 있다

 

 

Related Work

(1) 탄력성 조치를 적용하는 범위에 따른 연구

  • 인프라 수준: 인프라 수준에서 탄력성 컨트롤러는 일반적으로 VM을 획득하고 해제하여 컴퓨팅 리소스의 수를 변경한다.
  • 애플리케이션 수준: 애플리케이션 수준에서 컨트롤러는 애플리케이션에 직접 할당된 컴퓨팅 리소스를 조정한다(ex. 병렬 처리 수준 변경) 또는, 탄력성 컨트롤러를 애플리케이션 코드 내에 통합하는 임베디드 탄력성을 사용하는데, 이 경우 애플리케이션 자체에서 적응을 조정하는 메커니즘과 정책도 구현해야 한다. 

외부 컨트롤러를 사용하여 컴퓨팅 리소스를 조정하는 방식은 소프트웨어 모듈성과 유연성을 향상시키기 때문에, 본 논문에서는 분산 컨테이너화된 애플리케이션의 수평 및 수직 탄력성을 관리하기 위한 외부 컨트롤러를 제안하고 있다.

 

(2) 탄력성 조치 적용의 목표에 따른 연구

  • 애플리케이션 성능 개선: 로드 밸런싱 및 리소스 활용
  • 에너지 효율성
  • 배포 비용 절감

대부분의 연구는 단일 수준의 배포 목표를 고려하기 때문에, 본 연구 또한 단일 수준의 배포에 초점을 맞추고 컨테이너 수준에서 탄력성을 활용한다.

 

(3) 배포를 조정하는 데 사용되는 작업 및 방법론에 따른 연구

  • 수학적 프로그래밍 접근법: 컨테이너의 초기 배치와 런타임 배포 적응 비용(배포 재구성으로 인한 성능 저하) 을 고려하여 배포를 조정함
  • 휴리스틱: 임계값 기반 및 RL 기반 솔루션
    • 임계값 기반: 클라우드 인프라 레이어뿐만 아니라 런타임에 컨테이너를 확장하는 데 가장 많이 사용되는 접근 방식으로, 기존의 오케스트레이션 프레임워크(Kubernetes, Docker Swarm, Amazon ECS 등)는 일반적으로 일부 로드 메트릭(ex. CPU 사용률)에 기반한 최선의 임계값 기반 정책에 의존하고 있다. => 효과적인 임계값 기반 정책을 사용하려면 임계값 매개변수를 올바르게 설정해야 하며, 이를 위해서는 애플리케이션 리소스 소비에 대한 어느 정도 지식이 필요하며, 수직 확장에 대한 연구는 별로 이루어지지 못했다. = 매우 번거롭다
    • RL 기반 솔루션: Q-Learning 을 이용하여 가상 머신 할당 및 프로비저닝을 위한 정책 수립 등에 적용되어왔다. => 모델이 없는 솔루션이기 때문에 수렴이 느리다는 문제가 있다.

본 논문에서는 빠르게 학습시키기 위해 시스템 지식을 활용하는 새로운 모델 기반 RL 정책을 제안하며, 애플리케이션 배포를 런타임에 적응하기 위해 특히 수직 및 수평 탄력성을 공동으로 활용할 때의 이점을 조사한다.

 

 

Background

A. Docker Swarm

Docker는 컨테이너화된 애플리케이션을 생성하고 관리하기 위한 플랫폼으로, Docker를 사용하여 특정 리소스 할당량을 가진 컨테이너를 구성할 수 있고, 런타임에 업데이트하여 수직적 탄력성을 활성화할 수 있다.

Docker Swarm은 master-worker 패턴에 따라 여러 노드에서 컨테이너 실행을 단순화하는 클러스터링 시스템이다.

 

Method

  • 강화학습(Reinforcement Learning): 런타임에 컨테이너 기반 애플리케이션에 대한 최적의 적응 전략을 학습한다.
    • 에이전트(agent): 개별적인 시간 단위로 애플리케이션과 상호 작용하고, 애플리케이션 상태(state)를 관찰하며 예상되는 장기 비용을 최소화하기 위한 작업을 수행한다.
    • 상태(state): 컨테이너 수(=인스턴스 수), CPU 사용률, 각 컨테이너에 할당된 CPU 점유율의 튜플로 정의한다.
    • cost function: 애플리케이션 상태가 s에서 s'로 전환될 때 작업 a를 수행하는 데 드는 비용을 나타낸다. => 비용 최소화는 일반적으로 RL 에이전트의 제약 조건 또는 부차적인 목표이다.
      • 본 논문에서는 적응 비용(컨테이너 추가 또는 제거와 같은 작업에 대한 비용), 성능 비용(애플리케이션 응답 시간 제한을 초과할 때마다), 리소스 비용(애플리케이션 인스턴스 수 및 할당된 CPU 점유율에 비례) 을 단일 가중치 비용 함수로 결합하여 사용한다.
  • solution1) Q-learning: 강화 학습에서 샘플링 평균을 통해 최적의 Q-function을 추정하는 데 사용되는 모델 없는 알고리즘이다. 본 논문에서는 greedy 정책으로 기반으로 작업을 선택하지만, 낮은 확률로 차선의 작업도 탐색한다. 각 시간 슬롯이 끝날 때마다 학습 속도 매개변수와 향후 보상의 중요성을 결정하는 discount factor 를 사용하여 관찰된 state-action 쌍에 대한 Q값이 업데이트됨
    • Q-function=Q(s,a): 상태 s에서 액션 a를 실행 시 예상되는 장기 비용을 나타낸다. 컨테이너 확장에 대한 결정을 내리는 데 사용되며, 실제 발생한 비용을 관찰하여 시간이 지남에 따라 업데이트된다. => 높은 보상을 받을 가능성이 가장 높은 행동을 결정할 때 사용
    • Dyna-Q: 애플리케이션과 환경 간의 상호 작용을 시뮬레이션하여 학습 프로세스의 속도를 높이는 강화 학습 알고리즘이다. 런타임에 Dyna-Q는 애플리케이션 상태를 관찰하고 Q-러닝과 유사하게 Q(s, a)의 추정치를 사용하여 적응 action을 선택한 뒤, 탐색된 (s, a)에 대한 다음 상태 s'와 비용 c를 저장하여 런타임에 시스템 모델인 모델(s, a)을 업데이트한다. 모델은 Q-함수를 업데이트하는 데 사용된다.
  • solution2) 모델 기반 강화 학습: 본 논문에서는 경험적 데이터를 사용하여 시스템 모델의 전이 확률과 비용 함수를 추정하는 전체 백업 모델 기반 강화학습 접근 방식을 적용했다.
    • 전체 백업 접근법: 추정 가능한 시스템 모델에 의존하며, 벨만 방정식을 사용하여 Q 함수 계산한다. 
    • 샘플 값을 사용하여 비용 추정치를 업데이트하는 동안, 특정 속성을 적용하여 컨테이너 수가 감소하거나 CPU 사용률이 증가하거나 CPU 점유율이 감소할 때 Rmax 위반으로 인한 예상 비용이 낮아지지 않도록 한다

 

본 논문에서는 Docker Swarm에 모니터링/분석/계획/실행 제어 루프를 적용함으로써 Elastic Docker Swarm(EDS) 아키텍쳐로 확장했다. EDS는 RL 정책을 사용하여 애플리케이션 배포 및 재구성 시기/방법을 결정하며, Docker Swarm API를 활용한다.

  • Docker Monitor: 각 노드에서 실행되며, 노드에서 실행 중인 컨테이너의 CPU 사용률에 대한 정보를 메시지 브로커(Apache Kafka)에 주기적으로 게시
  • Container Manager: 메시지 브로커를 통해 모니터링 정보를 수신하고, RL 에이전트를 사용하여 분석 및 계획 단계를 수행
    1. RL 에이전트가 애플리케이션 상태를 판단하고 Q-function 을 업데이트한다.
    2. RL 에이전트를 사용하여 수행해야 할 확장 작업을 식별한다.
    3. 애플리케이션 배포를 조정하기 위해 EDS는 Docker Swarm API를 활용한다.

 

 

Experiment

  • 시뮬레이션 실험: 애플리케이션이 무작위적이고 독립적인 요청(M)을 수신하고, 서버가 요청을 처리하는 데 걸리는 시간(D)은 고정되어 있으며 변하지 않으며, 서버 수는 시간 단계 i에서 사용된 컨테이너 수(ki)와 같다고 가정한다.

시뮬레이션 실험에서 사용되는 변화하는 워크로드

  • 최대 응답 시간(Rmax) 위반을 방지하는 데 중점을 둔 경우, 모델 기반 솔루션은 응답 시간 위반이 2.85%에 불과하여 모델 없는 접근 방식보다 성능이 더 우수했다. 또한, 리소스 중점 시나리오에서는 모델 기반 솔루션이 애플리케이션 응답 시간이 길어지는 대신 리소스 활용도를 성공적으로 개선했다.
  • 5-액션 모델은 학습 작업을 간소화하고 모든 RL 정책에 대한 Rmax 위반을 줄이는 반면, 9-액션 모델은 학습 프로세스를 느리게 했다.

=> 모델 기반 접근 방식이 더 우수하다 = 시스템에 대한 사전 지식이 매우 중요하다

*모델 기반 접근 방식: 시스템의 동적인 특성을 사전에 알고 있는 경우, 이를 활용하여 강화학습 모델이 더욱 효과적으로 학습할 수 있도록 하는 방법

 

  • 프로토타입 기반 실험: Amazon EC2 인스턴스로 구성된 클러스터에서 EDS로 제안된 정책을 사용하여 실제 환경에서 강화 학습(RL) 알고리즘을 평가함

프로토타입 실험에서 사용되는 변화하는 워크로드

  • 목표 응답 시간 위반을 줄이고 워크로드 변동에 적응하는 측면에서 모델 기반 정책이 Q-러닝보다 우수한 것으로 나타났다.
    •  Q러닝은 모델 기반 솔루션과 유사한 솔루션을 찾지만 애플리케이션 배포를 더 자주 변경했다.
    • 모델 기반 솔루션은 Q-러닝보다 Rmax 위반 횟수를 줄이고 애플리케이션 배포를 덜 변경하여 애플리케이션 가용성을 높이는 것으로 나타났다.
  • 모델 기반 접근 방식은 수직 확장보다 수평 확장을 선호하는 것으로 관찰되었다.
    • Elastic 배포 시스템(EDS)의 적응 비용 정의에 따라 컨테이너 구성 변경(수직 확장)이 새 컨테이너 추가(수평 확장)보다 비용이 더 많이 들기 때문

=> RL 기반 접근 방식이 갑작스러운 워크로드 변화에 적응할 수 있어서 더 좋지만, 모델 기반 솔루션은 모든 상태, 동작, 다음 상태를 반복해야 하므로 계산이 많이 필요하며, 사용 가능한 동작과 전환 확률이 제한되어 있기 때문에 복잡성이 크다

💡 요약
- abstract: 라이브 VM 마이그레이션을 사용하여 마이크로 아키텍처 리소스의 충돌을 완화하고, 클러스터 수준 가상 머신 스케줄링 기법을 제안한 연구
- introduction: 모바일 디바이스에서 연산 오프로드를 위해 컴퓨팅 리소스를 요구 방식과 클라우드 제공업체의 리소스 제공 방식이 일치하지 않고, 모바일 디바이스가 오프로딩을 사용할 경우 무선네트워크를 사용하는데 이러한 경우 오프로딩 성능의 저하, 높은 비용이 발생한다는 문제점이 있다.
- related works: 시스템 내 스케줄링이나 스레드 스케줄링 위주의 연구가 이루어짐으로써 NUMA 선호도나 공유 캐시는 고려되지 않아 경합의 영향을 완화하기 어렵다.
- method: 캐시 인식 스케줄러 & NUMA 인식 스케줄러
- experiment: 가장 최악의 경우(클라우드 시스템에서 소켓당 LLC 누락의 최대치와 최소치 간의 차이가 가장 큰 매핑 & 모든 VM의 메모리 페이지가 원격 소켓에 할당)보다 성능 향상 관찰
- conclusion & discussion: 본 논문에서는 VM의 동작에 대한 사전 지식이 필요하지 않은 메모리 인식 클라우드 스케줄링 기법을 제안하고 평가했으며, 추후 핫 페이지 마이그레이션을 통해 보다 효율적인 NUMA 인식 스케줄링의 확장 가능성을 제시했다.

 

 

Introduction

  • 가상화 기반 클라우드 시스템에서 가상머신(VM)은 물리적 리소스를 공유 => 리소스 경합이 발생하는 경우 성능 저하
  • 이후 멀티코어의 등장으로 공유 캐시 및 메모리 컨트롤러와 같은 마이크로 아키텍쳐 리소스를 공유 =>  마이크로 아키텍쳐 리소스에 대한 경합은 CPU, 메모리, I/O를 동일하게 공유하더라도 공동 실행중인 애플리케이션에 의해 영향 (성능 편차의 주요 원인)

본 논문에서는 라이브 VM 마이그레이션을 사용하여 공유 캐시 및 메모리 컨트롤러의 경합을 최소화하기 위해 VM을 동적으로 스케줄링하며, 클라우드 서버에서 일반적으로 사용되는 멀티 소켓 시스템에서 NUMA의 영향을 고려함으로써 캐시 공유 및 NUMA 선호도를 위한 경합 인식 클라우드 스케줄링 기법을 제안한다.

  • 온라인에서 VM의 캐시 동작을 식별
  • 현재 VM의 배치가 과도한 공유 캐시 충돌이나 잘못된 NUMA 선호도를 유발하는 경우 VM을 동적으로 마이그레이션

 

  • 장점: VM 동작을 동적으로 식별하고 실시간 마이그레이션을 통해 충돌 해결 => VM 동작에 대한 사전 지식이 필요X
  • 캐시를 고려한 스케줄링은 클라우드 시스템에서 전체 Last Level Cache(LLC) 누락을 최소화
  • NUMA 인식 클라우드 스케줄링은 NUMA 선호도를 고려함으로써 캐시를 고려한 스케줄링을 확장

 

 

Related Works

리소스 공유로 인힌 리소스 경합을 완화하기 위해

  • 기존의 클라우드 시스템: 라이브 마이그레이션 기술을 사용하여 실행중인 VM의 배치를 변경하는 동적 VM 스케줄링을 사용
  • 단일 시스템일 때: 스레드를 신중하게 스케줄링하여 공유 캐시 및 메모리 컨트롤러에 대한 경합의 영향을 완화하기 위해 애플리케이션을 그룹화하여 캐시를 공유함으로써 시스템의 전체 캐시 누락을 최소화
    • 메모리 동작의 이질성에 의존하며, 단일 시스템에서 유사한 캐시 동작을 하는 애플리케이션을 실행하는 경우 이러한 시스템 내 스케줄링으로는 경합을 완화할 수 없다
  • 스레드 스케줄링: 스레드를 그룹화하고, 서로 다른 소켓에 매핑하여 모든 공유 LLC에서 캐시 누락의 합을 최소화
    • NUMA 선호도는 캐시를 고려한 스케줄링을 복잡하게 만든다.
    • 가상화 시스템에서 일부 상용 하이퍼바이저는 VM의 메모리 액세스 지연 시간을 줄이기 위해 동적 페이지 마이그레이션을 제공하지만 캐시 공유 효과는 고려하지 않았다.

 

단일 시스템에서의 스케줄링은 코어 수가 적고 LLC를 공유하는 최적의 스레드 그룹을 찾는데 제한이 있다. 하지만 클라우드와 같이 많은 수의 노드로 구성된 가상화된 시스템에서는 VM이 물리적 시스템 경계를 넘어 마이그레이션 할 수 있으므로, 공유 LLC를 위한 더 나은 VM 그룹을 찾고 NUMA 친화성을 지원할 수 있을 가능성이 높다.

 

 

Backgrounds

1. 라이브 마이그레이션: 

Live Migration

CPU, 메모리, I/O 하위 시스템과 같은 기존의 할당 가능한 시스템 리소스에서 충돌을 해결하거나 부하를 분산하는데 사용된 기술로, 클라우드 시스템에서 VM에 대한 리소스 사용량을 모니터링하여 트리거한다. CPU, 메모리, I/O 하위 시스템과 같은 기존의 할당 가능한 시스템 리소스에서 충돌을 해결하거나 부하를 분산하는데 사용된 기술로, 클라우드 시스템에서 VM에 대한 리소스 사용량을 모니터링하여 트리거한다. 가장 중요한 점은 행 중인 가상 머신을 서비스 중단 없이 물리적 호스트 간에 이동시킨다는 점이다. 

 

구글 사례 를 살펴보면 아래와 같다.

마이그레이션의 대략적인 단계

  • VM을 현재 호스트 시스템에서 제거해야 한다는 알림 발생
    • 알림은 파일 변경(예: 새 BIOS를 사용할 수 있음을 나타내는 릴리스 엔지니어), 하드웨어 작업 일정 유지 관리, 임박한 하드웨어 오류의 자동 신호 등으로 시작될 수 있다.
  • 클러스터 관리 소프트웨어는 이러한 이벤트를 지속적으로 감시하고, 이를 기반으로 데이터 센터(예: 용량 활용률) 및 작업(예: 한 번에 마이그레이션할 수 있는 단일 고객의 VM 수)을 제어하는 ​​정책을 스케줄링
  • 마이그레이션을 위해 VM이 선택되면 게스트에게 알림 제공
  • 대기 기간 후 대상 호스트가 선택되고 호스트는 마이그레이션 중인 "소스" VM을 수신하기 위해 비어 있는 새 "대상" VM을 설정하라는 요청을 받는다.
    • 소스와 대상 간의 연결을 설정할 때 인증 사용
    • 브라운 아웃 기간: 새로운 VM이 가동된 상태로, 메모리 상의 데이터 등의 VM 내용을 새로운 VM에 복사
    • 블랙 아웃 기간: 이전 VM의 모든 동작을 일순간만 정지시켜 브라운 대기 중에 받은 네트워크 패킷을 새로운 VM에 전송
    • 마이그레이션 이후 브라운 아웃 기간: 이전 VM은 이후에도 남겨, 블랙 아웃 기간 중 받은 네트워크 패킷을 새로운 VM에 전송
  • 마이그레이션이 완료되면 시스템이 소스 VM을 삭제 (고객은 로그에서 마이그레이션 수행 여부를 알 수 있다)

 

2. NUMA(Non-uniform Memory Access)

위 그림과 같이 NUMA 구조에서는 여러 개의 CPU 모듈이 있고 각 CPU 모듈에는 여러 개의 CPU가 포함되며 독립적인 로컬 메모리, I/O 슬롯 등이 있다. 그 결과 메모리 접근 시간이 프로세서와 관련된 메모리 위치에 따라 달라진다

  • NUMA Affinity: NUMA 영역 간의 메모리 접근은 메모리 버스를 통과해야 할 뿐만 아니라 데이터에 액세스하기 위해 영역 간 버스를 통과해야하기 때문에 지연시간이 증가하고, 버스에서 충돌이 발생할 수도 있다.
    • CPU에 NUMA Affinity를 설정함으로써, NUMA 토폴로지를 선택하여 VM에 할당된 CPU가 있는 NUMA 지역을 제한

 

 

Motivation

2.1 Cache Sharing and NUMA Affinity

공유 캐시: 코어 간 동적 용량 공유를 통해 잠재적으로 캐시의 효율성을 향상시킬 수 있지만, 코어 중 하나가 과도한 캐시 미스를 생성하여 다른 코어에서 캐시된 데이터를 제거할 때 경합 문제가 발생할 수도 있다.

공유 캐시에서 이러한 부정적인 간섭을 완화하기 위해:

  • 캐시 분할
  • 신중한 스레드 스케줄링: 스레드를 그룹화하고, 서로 다른 소켓에 매핑하여 모든 공유 LLC에서 캐시 누락의 합을 최소화

 

2.2 Performance Implication in Clouds

아래 그림은 NUMA 인식 VM 스케줄링 정책의 조합을 보여준다. 각 조합에서 첫 번째 문자는 캐시 정책을 나타내고 두 번째 문자는 NUMA 정책을 나타내는데, W-W 정책에 비해 성능 향상이 일어났음을 확인할 수 있다.

클러스터에 4개의 애플리케이션 유형이 혼합된 워크로드의 성능과 각 애플리케이션 유형에 대해 8개의 VM 인스턴스

캐시 공유 측면에서는 두 가지 매핑 정책을 제시한다:

  • 가장 좋은 경우(B): 클라우드 시스템의 모든 소켓에서 LLC 누락의 합이 최소화되도록 VM을 코어에 매핑
  • 최악의 경우(W): 클라우드 시스템에서 소켓당 LLC 누락의 최대치와 최소치 간의 차이가 가장 큰 매핑

NUMA 선호도에 대해 세 가지 매핑정책을 제시한다:

  • 최악의 경우 = 모든 VM의 메모리 페이지가 원격 소켓에 할당되는 경우
  • 최상의 경우 = 모든 VM 메모리 페이지가 로컬 소켓에 할당되는 경우
  • 인터리브 할당(I) = VM의 메모리 페이지를 항상 두 소켓에 인터리브 방식으로 할당

워크로드 특성

  • milc, GemsFDTD: 메모리 사용량이 적은 다른 워크로드와 캐시를 공유함으로써 성능 향상의 가능성
    • 공유 캐시의 최상의 경우에도 좋은 NUMA 정책은 특히 메모리 집약적인 워크로드의 성능을 향상시킬 수 있다.
  • hmmer, namd: LLC에 고용량을 요구하지 않기 때문에 개선 효과X
  • NUMA 선호도를 최적화할 수 없는 경우, 인터리브 메모리 할당은 NUMA에 대한 최악의 경우를 피하기 위한 대안이 될 수 있음

결과적으로, 소규모 클러스터에서도 VM 스케줄링으로 인한 성능 편차가 클 수 있다.

퍼블릭 클라우드에서는 일관된 성능을 지원하는 것이 중요한데, 대규모 클라우드 시스템에서는 다양한 사용자가 클라우드 시스템을 공유하게 되므로 노드 간 VM 캐시 동작의 이질성이 크다. 따라서 메모리 인식 클라우드 수준 스케줄링은 이러한 캐시 동작의 이질성을 활용하여 최악의 스케줄링을 피하고 공유 캐시 및 NUMA 선호도의 효율성을 잠재적으로 개선할 수 있다.

 

 

Method

메모리 인식 클라우드 스케줄러 구조

  • 각 컴퓨팅 노드: 모니터는 하드웨어 성능 모니터링 카운터로 LLC 미스를 확인하고, 주기적으로 VM별 LLC 미스 및 NUMA 선호도 정보를 클라우드 스케줄러로 전송한다. = 각 VM의 캐시 동작 수집
  • 클라우드 스케줄러: 모든 노드의 VM 상태 정보를 기반으로 글로벌 스케줄링 결정을 내린다. 만약 마이그레이션을 통해 클라우드 시스템에서 전체 캐시 미스와 평균 메모리 접근 레이턴시를 줄일 수 있는 경우, VM을 마이그레이션한다.
    • 캐시 인식 스케줄러: 공유 캐시에 대한 경합만 고려하고 NUMA 효과는 무시 => 그룹화가 NUMA 선호도를 위반할 수 있더라도 전체 클라우드 시스템에서 전체 LLC 누락을 최소화하기 위해 VM을 그룹화한다.
      • 로컬 단계: 각 컴퓨팅 노드의 VM을 그룹화하여 노드의 공유 캐시 도메인(일반적으로 소켓)으로 스케줄링한다. (물리적 노드 간 VM 마이그레이션은 네트워크 대역폭과 컴퓨팅 성능을 소모하므로 먼저 노드 내에서 VM 스케줄링을 최적화하여 이러한 VM 마이그레이션을 최소화하려고 시도) => 로컬 단계에서는 각 노드의 VM을 LLC 미스별로 정렬한 다음 각 LLC가 균일한 미스를 갖도록 그룹화한다. 모든 과정은 과정은 모든 VM이 공유 캐시 도메인 그룹에 할당될 때까지 계속된다. 
      • 글로벌 단계: 클라우드 스케줄러가 클라우드 시스템의 모든 노드에서 LLC 누락이 발생하지 않도록 VM을 재분배하려고 시도 => 클라우드 시스템에서 LLC 미스 수가 가장 많은 노드와 가장 적은 노드 두 개를 찾고, 두 노드에서 LLC 미스 차이가 임계값보다 큰 경우 두 VM은 실시간 마이그레이션을 통해 교체한다.
    • NUMA 인식 스케줄러: 캐시 인식 스케줄러를 확장하여 NUMA 선호도를 고려한다. (로컬 스케줄링이 VM의 NUMA 선호도를 잠재적으로 깨뜨릴 수 있으므로 글로벌 스케줄링만 제공) 
      • 글로벌 단계: 클라우드 시스템에서 LLC 미스 수가 가장 많은 소켓과 가장 적은 소켓 두 개를 선택 후, 두 개의 소켓 중에서 LLC 미스 횟수가 가장 많고 가장 적은 두 개의 VM이 각각 선택하여 두 개의 VM을 교체한다. 이때, 소켓 교환을 통해 메모리 페이지를 포함한 VM이 이동하더라도 NUMA 선호도는 계속 유지한다.
        • 성능 상 오버헤드를 줄이기 위해, 물리적 노드 내에서 VM에 속한 전체 페이지를 마이그레이션하는 대신, VM이 자주 액세스하는 핫 페이지만 다른 소켓으로 마이그레이션하는 방법을 생각해 볼 수 있다.

제안된 메모리 인식 스케줄러의 장점은 VM에 대한 사전 지식 없이 온라인으로 측정된 VM의 정보만 사용한다는 것이다.

처음에는 각 노드의 CPU 및 메모리 가용성만 고려하여 컴퓨팅 노드에 VM을 배치하지만, VM의 캐시 동작을 동적으로 식별하고 메모리 동작을 개선하기 위해 위치를 재조정한다.

 

 

Experiment

제안된 스케줄러를 별도의 클라우드 관리자 노드에서 실행하도록 구현했고, 각 컴퓨팅 노드는 Xen 하이퍼바이저로 가상화되었다.

SPECcpu 2006 애플리케이션을 사용하여 제안한 스케줄러를 평가했다.

 

최악의 경우(W-W)에 비해 개선된 성능

  • VM 마이그레이션의 오버헤드에도 불구하고, 2개의 메모리와 2개의 CPU 바운드 애플리케이션으로 구성된 WL1에서는 전체 성능이 17% 향상
  • 캐시 인식 스케줄링: 많은 수의 LLC 미스를 발생시키는 메모리 바운드 애플리케이션(milc, GemsFDTD)의 성능을 크게 개선하는 반면, 다른 두 애플리케이션(hmmer, namd)의 성능은 약간 저하시킨다.
    • hmmer와 namd는 캐시 용량에 크게 민감하지 않지만 메모리 집약적인 애플리케이션과 LLC를 공유해서 성능이 저하됨
  • NUMA 인식 스케줄러: 캐시 인식 스케줄러에 비해 전체 성능이 약간 향상되었다. 초기 설계에서 로컬 스케줄링을 제거하고 글로벌 스케줄링에만 의존하여 NUMA 친화성을 유지하므로 클라우드 시스템은 VM 배치를 천천히 조정하게 되며, VM 메모리를 다른 물리적 노드로 복사하는 데 CPU 리소스를 소비한다. VM의 핫 페이지만 단일 노드 내의 다른 소켓으로 마이그레이션하는 로컬 NUMA 인식 스케줄링의 경우에는 NUMA 선호도를 유지하기 위해 불필요한 글로벌 VM 마이그레이션을 줄일 수 있다.

워크로드에 대한 성능 개선 사항

  • WL6를 제외하고는 비슷한 추세를 보여준다 => WL6는 모두 CPU 바운드 애플리케이션으로 구성되므로 메모리 인식 스케줄링의 이점을 누릴 수 없기 때문

 

 

Discussion

본 논문에서는 VM의 동작에 대한 사전 지식이 필요하지 않은 메모리 인식 클라우드 스케줄링 기법을 제안하고 평가했다.

  • VM 라이브 마이그레이션이 마이크로 아키텍처 리소스 경합을 완화하는 데에도 사용될 수 있을 것이다.

 

 

Strace

리눅스에서는 시스템 콜 이벤트를 추적하고 기록하기 위해 strace 라는 툴을 제공한다.

strace [-ACdffhikqqrtttTvVwxxyyzZ] [-I n] [-b execve] [-e expr]... [-O overhead] [-S sortby] [-U columns] [-a column] [-o file] [-s strsize] [-X format] [-P path]... [-p pid]... [--seccomp-bpf] [--secontext[=format]] { -p pid | [-DDD] [-E var[=val]]... [-u username] command [args] }

strace -c [-dfwzZ] [-I n] [-b execve] [-e expr]... [-O overhead] [-S sortby] [-U columns] [-P path]... [-p pid]... [--seccomp-bpf] { -p pid | [-DDD] [-E var[=val]]... [-u username] command [args] }

 

strace는 지정된 명령어가 종료될 때까지 실행되며, 

프로세스가 호출하는 system call 과 프로세스가 수신하는 signal을 가로채서 기록한다.

 

  • 트레이스의 각 줄에는 시스템 호출 이름(함수명)과 괄호 안의 argument 및 시스템 콜 실행 후의 반환값이 포함된다
open("/dev/null", O_RDONLY) = 3
  • 오류가 발생하는 경우(일반적으로 반환값 -1)에는 errno symbol오류문자열이 기록된다
open("/foo/bar", O_RDONLY) = -1 ENOENT (No such file or directory)
  • signal은 signal symbol 과 디코딩 된 siginfo 구조로 기록된다
sigsuspend([] <unfinished ...>
           --- SIGINT {si_signo=SIGINT, si_code=SI_USER, si_pid=...} ---
           +++ killed by SIGINT +++
  • 만약 시스템 호출이 실행되는 동안 다른 스레드/프로세스에서 다른 호출이 실행되는 경우 이벤트 순서는 유지하되, 진행 중인 시스템 호출을 완료되지 않은 것으로 표시하고 호출이 반환되면 재개된 것으로 표시한다.
[pid 28772] select(4, [3], NULL, NULL, NULL <unfinished ...>
[pid 28779] clock_gettime(CLOCK_REALTIME, {tv_sec=1130322148, tv_nsec=3977000}) = 0
[pid 28772] <... select resumed> )      = 1 (in [3])
  • 단, signal 전달에 의한 restartable 시스템 호출의 중단은 다르게 처리된다
    • 이 경우에는 커널이 시스템 호출을 종료하고, signal handler가 완료된 후 즉시 재실행되도록 준비된다
read(0, 0x7ffff72cf5cf, 1)              = ? ERESTARTSYS (To be restarted)
--- SIGALRM {si_signo=SIGALRM, si_code=SI_KERNEL} ---
rt_sigreturn({mask=[]})                 = 0
read(0, "", 1)                          = 0
  • 알 수 없는 시스템 호출은 raw 상태로 기록되며, 알 수 없는 시스템 호출 번호는 16진수 형식으로 출력되며 앞에 syscall_ 접두사가 붙는다.
syscall_0xbad(0x1, 0x2, 0x3, 0x4, 0x5, 0x6) = -1 ENOSYS (Function not implemented)

 

options
-ttt:
절대 시간 기록, 마이크로 초 단위
-T: 시스템 호출에 소요된 시간, 각 시스템 호출의 시작과 끝 사이의 시간차를 기록, 디폴트는 마이크로 초 단위
-f: fork, vfork, clone 등의 시스템 콜의 결과로 현재 트레이싱 중인 프로세스에 의해 생성되는 자식 프로세스를 트레이싱한다. (만약 프로세스가 멀티스레드인 경우, 모든 스레드를 트레이싱)
-Z: 오류코드와 함께 반환된 시스템 콜만 기록
-z: 오류코드 없이 반환된 시스템 콜만 기록
-o: 트레이스 출력을 지정된 파일에 쓴다. 인수가 | 또는 !로 시작하면 나머지 인수는 커맨드로 취급되어, 모든 기록이 파이프로 전달된다. 이 옵션은 실행중인 프로그램의 리디렉션에 영향을 주지 않고, 디버깅 출력을 프로그램으로 파이프할 때 편하다.

 

 

Strace는 왜 컨테이너와 일반 프로세스에서 다르게 동작할까?

A containerized process uses system calls and needs permissions and privileges in just the same way that a regular process does. But containers give us some new ways to control how these permissions are assigned at runtime or during the container image build process, which will have a significant impact on security.

커널관점에서는 컨테이너 내에서 실행되는 프로세스 vs 호스트에서 실행되는 프로세스가 크게 다르지 않다.

결국 둘 다 단순히 생각하면 프로세스이고, 커널 영역을 공유한다. 따라서 syscall, kprobe, tracepoint 등의 커널 관련 이벤트로 프로세스를 트레이싱 하는 것은 동일 할 것이다.

https://devopscube.com/what-is-a-container-and-how-does-it-work/

따라서 strace로 컨테이너를 분석 할 때, 일반적으로 프로세스를 분석하는 것과 똑같이 하면 될 줄 알았다.

-rw-rw-r--  1 soyeon soyeon 1.8M  4월 27 16:13 squeezenet_docker.txt # 22091 lines
-rw-rw-r--  1 soyeon soyeon  19G  4월 27 10:51 squeezenet_real.txt # 223172114 lines

그런데 트레이스 사이즈가 너무 다르다;;

 


 

컨테이너와 호스트에서 실행되는 프로세스는 거의 비슷하지만,

사실은 컨테이너 워크로드에 자체 네임스페이스가 있어서 프로세스를 격리하게 된다.

즉, 컨테이너는 자체 루트 파일 시스템이 있고, binary/library는 서로 다른 mount namespace에 의해 격리된다

= 이벤트 추적 도구로부터 격리된다

 

그래서 트레이싱 툴이 작동할수도, 작동하지 않을수도 있다.

예를 들어 syncsnoop.bt는 잘 동작한다.

syncsnoop.bt
Attaching 7 probes...
Tracing sync syscalls... Hit Ctrl-C to end.
TIME      PID    COMM             EVENT
10:27:04  1229   auditd          tracepoint:syscalls:sys_enter_fsync
10:27:04  1229   auditd          tracepoint:syscalls:sys_enter_fsync
10:27:05  11459  fluent-bit       tracepoint:syscalls:sys_enter_fsync
10:27:05  11459  fluent-bit       tracepoint:syscalls:sys_enter_fsync
10:27:05  11459  fluent-bit       tracepoint:syscalls:sys_enter_fsync
10:27:05  11459  fluent-bit       tracepoint:syscalls:sys_enter_fsync
10:27:05  11459  fluent-bit       tracepoint:syscalls:sys_enter_fsync
.....

##################

cat /proc/1229/status | grep nspid -i
NSpid: 1229
cat /proc/11459/status | grep nspid -i
NSpid: 11459 1 # 기본 PID 네임스페이스: 11459, 자체 네임스페이스: 1

 

그런데 bpftrace 같은 경우에는 컨테이너 내부 바이너리 또는 .so 파일에 접근하여 uprobe를 주입할 수 없으므로 컨테이너 내부 애플리케이션은 제대로 된 트레이싱이 불가능하다.

  • uprobe: 프로세스가 probe를 만났을 때 수행할 작업을 커널에 알려준다. probe는 파일과 연결되어 있으므로 해당 파일에서 코드를 실행하는 모든 프로세스에 영향을 미친다. 
// uprobe의 핵심 기능
#include <linux/uprobes.h>

int uprobe_register(struct inode *inode, loff_t offset, struct uprobe_consumer *uc);

//////////////////////////
    struct uprobe_consumer {
	int (*handler) (struct uprobe_consumer *self, struct pt_regs *regs);
	bool (*filter) (struct uprobe_consumer *self, struct task_struct *task);
	struct uprobe_consumer *next;
    };

 

strace도 비슷하다. 거기다가 도커는 seccomp-bpf을 사용하여 컨테이너 프로세스가 특정한 시스템 콜을 실행하지 못하도록 막는다. 

(기본 seccomp profile에서 허용되는 호출을 지정하는 허용 목록 작성)https://docs.docker.com/engine/security/seccomp/

 

Seccomp security profiles for Docker

 

docs.docker.com

그래서 만약 seccomp profile 옵션을 사용하지 않고 도커를 실행하고 싶다면 --security-opt seccomp=unconfined 을 도커를 실행할 때 추가해야한다.

 

근데 이렇게 하더라도 큰 변화는 없어서 더 찾아보니,,,

결론적으로 strace는 docker container의 동작을 빠짐없이 추적하기에는 적합하지 않은 도구였다.

strace는 프로그램이 실행하는 동안 호스트 운영 체제에 액세스하는 데 사용되는 시스템 콜을 추적할 수 있지만,

컨테이너가 호스트 운영 체제와 상호 작용하기 위해 사용하는 API 호출은 추적할 수 없다는 걸 알았다...

 

예를 들어,

- 컨테이너가 파일 시스템에 액세스하려면 open() 시스템 콜을 호출 -> strace 시스템 콜 추적 O

- 컨테이너가 Docker 네트워크를 통해 네트워크에 액세스할 때 docker_network_connect() API 호출 -> strace 시스템 콜 추적 X

 

strace는 API 호출을 추적할 수는 없다. (이러한 API 호출이 컨테이너의 네트워크 및 파일 시스템 드라이버에서 처리되기 때문)

네트워크 및 파일 시스템 드라이버는 컨테이너가 호스트 운영 체제와 상호 작용할 수 있도록 하는 소프트웨어인데,

strace는 드라이버가 호스트 운영 체제에 액세스하는 데 사용하는 시스템 콜을 추적할 수 있지만 드라이버 자체가 호스트 운영 체제에 액세스하는 방법은 추적할 수 없다.

 

 

 

 

 

 

+ Recent posts