본문 바로가기

개발/SRE - 사이트 신뢰성 엔지니어링

SRE 18장 - SRE 조직의 소프트웨어 엔지니어링

  누군가에게 구글의 소프트웨어 엔지니어링 중 가장 많은 비중을 차지하는 제품이 무엇이냐고 묻는다면, 대부분 지메일이나 지도 같은 사용자 서비스라고 답할 것이다. 하지만, 사실 최종 사용자에게는 드러나지 않는 소프트웨어 엔지니어링의 비중도 엄청나다. 이들 중 상당 부분은 SRE 조직에서 개발한 것이다.

 

  SRE는 복잡한 프로덕션 환경을 직접 경험하고, 내부의 문제를 해결하기 위한 적절한 도구를 개발하며, 프로덕션 환경을 지속적이고 안정적으로 운영할 수 있는 다양한 활용 사례들을 만들어내고 있다. 

 바이너리 배포 메커니즘, 모니터링 또는 동적 서버 조합(dynamic server composition)을 기반으로 한 개발 환경의 구축 등

SRE 조직의 소프트웨어 엔지니어링 역량이 중요한 이유

SRE가 효율적으로 내부 소프트웨어를 개발할 수 있는 조직이라는 독특한 위치를 갖게 된 데는 다음과 같은 이유들이 작용했다.

  • SRE 조직의 폭넓고 깊은 지식 덕분에 소프트웨어를 디자인하고 개발할 수 있다.
  • SRE들은 중요한 사안에는 모두 참여하므로 개발할 도구의 목적과 요구사항을 손쉽게 이해한다.
  • 개발하는 도구의 사용자(다른 SRE들)와의 관계가 직접적이기 때문에 솔직하고 신속한 사용자 피드백을 기대할 수 있다. 문제 영역을 잘 이해하고 있는 내부 수요자들을 위한 도구를 릴리즈한다는 것은 개발팀의 릴리즈 주기가 더 짧아질 수 있다는 것을 의미한다. 내부 사용자들은 개발 초기의 여러 가지 문제들에 대해 대부분 잘 이해해주는 편이다.

SRE의 가이드 원리 중 하나는 "팀의 규모는 서비스의 성장률과 직접적으로 비례해서는 안 된다"는 것이다. 서비스가 폭발적으로 성장하더라도 SRE 조직의 규모를 선형적으로 유지하려면 지속적인 자동화 작업과 능률적인 도구, 절차에 대한 개선 노력이 필요하다. 또한 일상적인 운영 업무에 비효율성을 초래하는 부분을 전과는 다르게 바라보는 시각이 필요하다. 

 

SRE 조직에서 진행하는 완전히 자율적인 소프트웨어 개발 프로젝트는 SRE에게 있어 경력 개발의 기회인 동시에 자신의 코딩 스킬이 녹스는 것을 원치 않는 엔지니어에게는 고민의 탈출구가 되어준다. 소프트웨어 엔지니어링과 시스템 엔지니어링 사이의 균형을 원하는 엔지니어에게는 직업에 대한 만족도를 높여준다.

 

소프트웨어 개발 프로젝트는 SRE 조직에 또 다른 이점으로 작용한다. 엔지니어들이 지속적으로 다양한 종류의 기술들을 익힐 수 있도록 이끌어 준다. 다양한 배경지식과 문제 해결에 대한 접근법은 장애의 사각지대를 찾아내는 데 큰 도움이 된다. SRE에게 있어 팀의 다양성이란 남다르게 중요한 부분이다. 

 


Auxon 사례 연구: 프로젝트 배경 및 문제가 발생한 부분

Auxon은 SRE가 구글의 서비스 수용량 계획을 자동화하기 위해 만든 강력한 도구다.

전통적인 수용량 계획

수용량 계획을 수립하기 위한 방법은 수만 가지가 존재하지만, 대부분은 대략 다음과 같은 주기로 정리할 수 있다.

  1. 수요 예측의 수집 - 얼마나 많은 자원이 필요한가? 언제 그리고 어디서 이 자원들을 활용하는가?
    • 현재 가용한 최선의 데이터를 확보해야 미래를 위한 계획을 수립할 수 있다.
    • 주로 몇 개 분기에서 수년 정도의 데이터를 기반으로 자료를 수집한다.
  2. 빌드 및 할당 계획의 수립
    • 수집된 예상 수요를 바탕으로 요구를 만족시키기 위해 추가로 제공되어야 하는 자원이 있는가? 있다면 얼마나 많이, 그리고 어느 지역에 추가해야 하는가?
  3. 리뷰 및 계획의 승인
    • 예측된 수요는 적절한가? 예산 범위를 초과하지 않으며, 제품 및 기술적 요소들이 모두 고려되었는가?
  4. 배포 및 자원 설정
    • 자원이 도착하면(어느 정도 시간이 지난 다음에), 어느 서비스가 해당 자원을 사용해야 하는가? 저수준의 자원들(CPU, 디스크 등)을 서비스에 어떻게 적절하게 활용할 것인가?

전통적인 수용량 계획은 수요(demand)를 주요 지표로 사용하며, 매번 무언가 바뀔 때마다 그에 따라 수요를 맞추기 위한 수작업이 진행되곤 한다.

 

본질적으로 불안정하다

전통적인 수용량 계획 진행시 자원 할당 계획을 수립하게 되는데, 이 계획은 약간의 변화에도 쉽게 영향을 받는다. 아래의 예를 살펴보자.

  • 서비스의 효율성이 떨어져서 동일한 양의 수요를 감당하기 위해 더 많은 자원을 필요로 하게 되는 경우
  • 고객의 유입률이 증가하여 그에 따라 수요가 증가하는 경우
  • 컴퓨트 자원의 새 클러스터의 배송이 지연되는 경우
  • 제품의 성능 목표가 변경되어 서비스의 배포 형태와 필요한 자원의 양이 바뀌는 경우
이처럼 별것 아닌 변화에도 현재 계획의 실현 가능 여부를 판단하기 위하여 전체 할당 계획을 재점검해야 한다. 

더 큰 변화( 자원의 배송 지연, 제품 전략 변경)가 발생하면 처음부터 계획을 세워야 하는 경우도 있다.

 

노동집약적이며 모호하다

  • 수요 예측을 위해 필요한 데이터를 수집하는 과정은 느리고 오류를 범하기 쉬운 과정이다. 모든 예측은 제약이나 변수가 존재하기 마련이다. 
  • 현재 가용한 수용량으로부터 실제 자원을 할당하는 것 역시 느리게 수행된다. 복잡하고, 제한된 범위에서 해결책을 찾아야 하는 지루한 작업이다.
  • 이보다 더 한 사실은 이 과정에서 불안정하거나 거추장스러운 도구들을 사용해야 한다는 점이다. 
    • 그로 인해 데이터는 점점 더 망가져가고 변경 추적은 어려워진다.
문제를 조금이라도 더 쉽게 해결하기 위해 더 단순한 가정을 세우고 요구사항에 대한 복잡도를 줄이기 위해 노력해왔다

여기서는 이 문제를 "상자 채우기 문제(bin packing problem)"라는 NP-hard 문제로 정의하고 있다. 이는 인간이 직접 계산하기에는 어렵다. 결국 엄청난 노력이 필요하고, 이 과정은 변화 수용이 어렵고, 최적의 해결책에 대해서도 알려진 바가 없다.

 


구글의 해결책: 의도 기반 수용량 계획

구현이 아닌 요구사항을 명확히 하자

구글의 많은 팀들이 의도 기반 수용량 계획 접근법을 활용하고 있다. 

의존성과 서비스의 수요에 따른 매개변수(의도)를 프로그래밍적으로 인코딩하고 상세한 할당 계획을 자동으로 생성하는 것이다

수요나 공급 또는 서비스의 요구사항이 변경되면, 변경된 매개변수를 바탕으로 다시 최적의 자원 분산을 위한 계획을 새로 생성하면 그만이다. 

서비스의 실제 요구사항과 유연성을 확보하면 변화에 훨씬 빠르게 대응할 수 있는 수용량 계획을 수립할 수 있으며, 최대한 많은 매개변수를 만족시킬 수 있는 최적의 해결책을 마련할 수 있게 된다. 상자 채우기 문제를 컴퓨터에 위임함으로써, 인력의 낭비가 눈에 띄게 줄었다. 다른 우선순위가 더 높은 부분들에 집중할 수 있게 된다.

 

또한 컴퓨터를 통한 최적화를 통해 의도를 실제 구현과 연결함으로써 정확도가 훨씬 높아졌고, 조직 운영에 드는 비용 절감이 가능했다. 일부 타입들은 여전히 NP-hard의 문제를 가지고 있으므로 상자 채우기 문제가 완전히 해결되었다고 보기는 어렵다. 그렇지만 현재의 알고리즘으로도 충분히 이를 해결해서 최적의 방법을 도출할 수 있다. 

내가 바라는 방향의 개발이지 않을까 싶다. 실제 백엔드 개발의 문제점을, Object function으로 정의하고, 이를 Optimization으로 풀어서 이를 구현하는 과정

 


의도 기반 수용량 계획

의도란 서비스 담당자가 자신들의 서비스를 운영하고자 하는 의도를 의미한다.  실제 수용량 계획 의도를 이끌어내기 위해서는 여러 단계의 추상화가 필요하다. 

  1. Foo 서비스를 위해 X, Y, 그리고 Z 클러스터에 50개의 코어가 필요합니다.
    • 대체 왜 특정한 클러스터와 이 많은 자원들이 필요한가?
  2. Foo 서비스를 위해 YYY 지역의 클러스터 중 세 개에서 50개의 코어가 필요합니다.
    • 대체 왜 이만큼의 자원이 필요하며, 왜 세 개의 클러스터 공간이 필요한가?
  3. Foo 서비스에 대한 각 지역별 수요를 충당하기를 원하며 N+2의 다중화를 원합니다.
    • 자유도가 훨씬 높아졌다. 그리고 "인간으로써" 이해하기가 쉬워졌다. 하지만, 왜 N+2 개의 Foo 서비스가 필요할까?
  4. Foo 서비스에 99.999%의 가용성을 지원하고 싶습니다
    • 가장 추상화된 요구사항이며, 맞추지 못했을 때의 결과가 명확하다. 그리고 유연하다. 

구글의 경험상으로는 3단계의 추상화를 제공할 때 가장 좋은 성과를 내는 것으로 드러났다. 유연성도 뛰어나고, 요구 결과가 더 높은 수준의 이해하기 쉬운 용어로 제공되기 때문이다.

 

의도를 파악하기 위한 선행 작업

서비스의 의도를 파악하려면 필요한 정보는 의존성과, 성능 지표, 그리고 우선순위 결정이다.

의존성

서비스 Foo가 인프라스트럭처 저장소 서비스인 Bar에 의존하고 있을 경우, 요구사항에 의존성이 명시되어야하고, 의도 기반 수용량 계획은 반드시 이 제약 사항들을 고려해야한다. 

 

성능 지표

한 서비스에 대한 수요는 하나 혹은 그 이상의 다른 서비스들에 대한 수요에 조금씩 영향을 미친다. 이때 의존성 간의 연결 관계를 이해하면 상자 채우기 문제의 일반적인 범위를 공식화할 수 있다. 그렇지만 좀 더 자세한 정보가 필요하다. 

Foo 서비스가 N개의 요청을 처리하려면 얼마나 많은 컴퓨트 자원이 필요할까? N개의 요청이 전달되면 Bar 서비스는 몇 Mbps의 데이터를 서비스 해야할까?

 

성능 지표는 의존성 간의 연결 고리다. 고수준의 자원 타입을 그보다 낮은 수준의 자원 타입으로 변환한다. 적절한 성능 지표를 확보하려면 부하 테스트와 자원 활용에 대한 모니터링이 필요하다.

우선순위 결정

자원에 대한 제약은 필연적으로 절충과 쉽지 않은 결정으로 결론이 나게 된다. 충분한 수용량을 확보하지 못했을 때 어떤 요구사항을 포기해야 할까? 

의도 기반 계획은 이러한 결정을 투명하고 공개적이며 일관성 있게 내리는 것에 초점을 맞춘다. 우선순위에 대한 결정은 서비스 담당자 입장에서는 너무 즉흥적이고 불투명하게 느껴지는 경우가 종종 있다. 하지만 의도 기반 계획을 통해 우선순위의 결정을 필요에 따라 세밀하게 또는 굵직하게 조정할 수 있다. 

 

 

Auxon 소개

SRE가 디자인하고 개발한 소프트웨어 엔지니어링 제품으로서는 가장 중요한 사례다. 머신들을 사용하기 위한 계획을 수립하는 데 적극적으로 활용되고 있다.

 

서비스의 자원 요구사항과 의존성에 대한 의도 기반 명세를 수집한다. Auxon은 사용자의 설정 언어 혹은 프로그래밍 API를 통해 수집한 후, 사람의 의도를 기계가 이해할 수 있는 제약으로 변환한다. 요구 사항의 우선순위를 조정하는 기능을 사용 가능한 자원이 모든 요구사항을 충족시킬 수 없을 때 유용하다.

이 요구사항(의도)은 결국 내부적으로는 mixed-integer, 혹은 Linear Programming으로 표현된다. ( 모든 실행활의 문제는 opt 표현이 가능하다는 것은 명백하다. 그런데, mixed integer는 그렇다쳐도, LP로 표현되는 게 맞을까? Non Linear Programming의 요구사항 문제들도 많을 것 같은데. )
결국 Auxon의 핵심은 문제를 Object function으로 정의하고, 이렇게 정의된 NP-hard(대부분) 문제를 heuristic 하게 풀어낸다는 것이다.

 


요구사항과 실제 구현: 성공 사례와 그로부터 배운 것들

Auxon의 개발과정 동안, 제품의 개발에는 직접 참여하지 않던 SRE팀이 프로덕션 환경에 계속해서 깊이 관여하게 되었다. 처음의 Auxon은 SRE와 기술 프로그램 관리자가 스프레드 시트에 수작업으로 수용량 계획을 진행하다가, 자동화에 따른 비효율성과 개선의 기회를 기반으로 고안한 것이다.

즉, 제품의 사용자이자 개발자 역할을 동시에 하고 있었다. 문제를 직접 체험했던 경험은 제품 성공에 대한 큰 성과를 얻었고, SRE 내에서 제품의 신뢰성과 정당성을 확보하는 데도 도움이 되었다.

 

미완성된 제품

문제의 범위가 잘 알려져 있지 않다면, 완벽하면서도 깔끔한 해결책에 집착해서는 안 된다. 뭔가를 해보고 계속해서 반복하는 것이 좋다. 

 

복잡한 소프트웨어 개발을 위한 엔지니어링은 컴포넌트의 디자인이나 해결해야 하는 문제의 불확실성과 맞닥뜨리게 된다. Auxon 또한, 선형 프로그래밍이라는 생소한 개념으로 인해 이와 같은 불확실성을 마주했다. 그래서 제품 동작의 핵심 같았던 선형 프로그래밍의 한계들을 제대로 이해하지 못했다. 

그래서 간소화된 해법 엔진을 개발하였다. 개발의 속도를 높이기 위해 미완성된 제품을 배포했고, 나중에 언제든지 내부 해법 엔진을 바꿀 수 있도록 하였다. 결국 충분히 선형 프로그래밍 모델에 자신이 생길 때 교체할 수 있었다.

 

Auxon 제품에 대한 요구사항도 미정인 부분이 많았다. 하지만 불확실성이 존재한다고 해서 일 자체를 포기할 수는 없다. 이러한 모호함은 오히려 제품을 더욱 일반적이고 모듈 단위로 구현할 수 있는 기반으로 삼아야 한다.

 

오래된 모토인 '실행하고 반복하기'가 연관이 깊다. 완벽한 디자인을 기다리는 것보다는 전체적인 비전을 염두에 두고 디자인과 개발을 계속해서 발전시켜 나가는 것이 낫다. 불명확하다면 충분히 유연하게 디자인하자. 

 

인식의 제고 및 도입의 촉진

소프트웨어의 도입을 유도하기 위해서는 활용성, 성능, 신뢰성 목표와 SRE 삶의 질 향상을 모두 만족시킬 수 있는 능력을 보여주어야 한다. 홍보하는 과정과 조직이 이를 받아들이도록 유도하는 과정이야말로 프로젝트 성공의 열쇠라 할 수 있다. 

 

내부 소프트웨어 도구를 널리 알리기 위해서는

  • 일관적이고 긴밀한 접근법
  • 사용자에 대한 지원
  • 제품의 활용성을 알리기 위한 선임 개발자와 관리자의 전폭적인 지원

이 필요하다. 사용자의 관점에서 제품이 유용한 것인지에 대해 고려하자. 내부의 고객이더라도 문서도 제공하자.

 

기대치 설정하기

제품의 원대한 목표와 성공을 위한 최소한의 조건(혹은 최소 기능 제품)을 구분하는 것은 매우 중요하다. 너무 많은 것들을 추구하면서 동시에 너무 빨리 이를 달성하려고 하면 신뢰성을 잃게 될 수도 있다. 

 

적절한 사용자층을 정의하기

Auxon이 한 가지 해결책으로는 모든 시나리오를 감당할 수 없다는 점을 깨달았다. 그래서 초기 버전은 아직 수용량 계획 절차를 수립하지 못한 팀들을 대상으로 한 제품이었다. Auxon이 성공할 수 있었던 비결은 이런 팀들이 유용함을 증명해주고, 제품을 지지해주었기 때문이다. 

 

고객 서비스

어느정도 혁신이 가미된 소프트웨어들은 여전히 새로운 사용자들이 학습해야 할 부분들이 존재한다. 고객들이 적절하게 제품을 사용할 수 있도록 지원을 아끼지 말아야 한다. 

 

적절한 수준의 디자인

고객들이 Auxon 프레임워크를 사용하기 위해 어느 한 도구에 얽매일 필요가 없게 하는 것이 Auxon의 디자인 원칙의 핵심이었다. 한두 명의 대형 고객만을 위한 과도한 커스터마이징에 얽매이지 않았기 때문에 조직 전체에 걸쳐 폭넓은 사용자층을 확보할 수 있었고, 장벽을 낮출 수 있었다.

 


팀의 원동력

엔지니어의 선택에는 폭넓은 지식과 경험을 지닌 엔지니어와 새로운 주제에 신속하게 대응할 수 있는 다양한 기술을 가진 엔지니어들을 섞어서 시드 팀을 만드는 것이 큰 도움이 된다는 사실을 깨달았다. 

 

팀이 필요한 전문가와 긴밀한 업무 관계를 맺고 엔지니어들이 새로운 문제에 당면하더라도 마음 편히 이를 해결할 수 있는 환경을 조성하는 것이 기본이다. Auxon의 컨셉트를 정의하고 디자인하던 초기 단계에서 구글 내부의 운영 연구 및 수치 분석 전문가로 구성된 팀의 전문 지식을 활용하여 수용량 계획에 대한 충분한 지식을 확보할 수 있었다.

 


 

SRE 조직에서 소프트웨어 엔지니어링을 육성하는 방법

어떤 프로젝트가 일회성의 도구를 위한 프로젝트의 수준에서 벗어나 완전한 기능의 소프트웨어 엔지니어링 프로젝트가 되기 위한 조건은 무엇일까? 

프로젝트는 SRE의 노고를 덜어준다거나, 기존의 인프라스트럭처의 일부를 개선한다거나 혹은 복잡한 프로세스를 능륙적으로 수행하는 등의 충분한 혜택을 제공해야 한다.

 

프로젝트들이 일부 조직의 서비스에만 혜택을 제공할 수 있는 것으로 치우치지 않도록 주의해야하고, 한편으로는 너무 지나치게 포괄적인 프레임워크도 문제가 될 수 있다는 것을 명심하자. 

SRE 조직에 소프트웨어 엔지니어링 문화를 성공적으로 정착시키기: 인력 수급과 개발 시간

SRE들은 제품 기획팀에 합류할 정도나 고객의 기능 요구에 대해 고려해야 하는 전통적인 SWE 경험이 없는 경우가 많다. 고객을 위한 소프트웨어 개발에 익숙한 엔지니어, TPM 혹은 PM들과의 협력을 통해 소프트웨어 제품 개발과 프로덕션 환경 운영 경험을 모두 포괄하는 소프트웨어 개발 문화를 팀에 정착시킬 수 있다.

 

집중할 수 있고, 방해 받지 않는 프로젝트 작업 시간은 모든 소프트웨어 개발에 있어 필수적인 요소다. 이런 시간은 반드시 보장되어야 한다. 하지만, 개발 노력에 참여한 모든 SRE는 SRE 조직에 속한 풀타임 개발자가 아니라 계속해서 SRE로써 남아야 한다. 

제품 생산의 세계에 참여함으로써 소중한 시각을 얻을 수 있는 기회가 된다. 생산자인 동시에 소비자가 되기 때문이다. 

 

목표 이루기

SRE 조직에서 소프트웨어를 개발함으로써 얻고자 하는 것이 무엇인지에 대해 생각 해보자.  단지 팀에 더 나은 소프트웨어 개발 문화를 도입하기를 원하는 것인가, 아니면 조직의 표준이 될 소프트웨어의 개발에 관심이 있는 것인가? 

 

이 책에서는 후자를 위한 경험 바탕의 가이드라인을 제시하고자 한다.

 

명확한 메시지로 소통하라

SRE에게 어떤 장점이 있는지를 명확하게 정의하고 소통하는 것이 중요하다. 

 

조직의 역량을 평가하라

SRE들은 사용자에게 제품을 개발해서 전달해본 경험이 부족하다. 그동안 요구되지 않았던 역할과 기술을 필요로 할 수도 있다. 

조직이 이미 확보한 기술을 이용해서 이런 차이점을 채워나가야 한다. 조언을 구하고, 코치를 제품 개발팀에 부탁해야 한다. 

 

출시하고 반복하라

적절한 시간 내에 어느 정도 가치가 있는 제품을 출시해서 신뢰성을 확보하는 것이 중요하다. 첫 번째 릴리즈는 상대적으로 직관적이며, 달성 가능한 목표를 추구해야 한다. 

지속적으로 새로운 기능들을 추가하면 성공 가능성이 크다.

 

자신의 표준을 낮추지 마라

지름길로 가고 싶은 충동을 느낄 때가 있지만, 표준을 계속해서 지켜나가는 것이 좋다.

 


결론

SRE들이 보유하고 있는 프로덕션 환경에 대한 경험은 오래된 문제들을 혁신적으로 해결할 수 있는 도구의 개발로 이어졌다. Auxon이 그 좋은 예다.  궁극적으로 SRE가 시간의 일부를 소프트웨어 개발에 투자하는 것은 SRE 조직, 그리고 SRE 본인들에게도 큰 수확이었다.