1P by GN⁺ | ★ favorite | 댓글 1개
  • 서버 자동화 작업을 Python 코드로 작성하고 SSH로 병렬 실행해, 에이전트 없이 명령을 멱등적으로 수행함
  • pyinfra는 동일 워크로드에서 Ansible보다 6배 빠름을 내세우며, gevent와 SSH 기반 동시 실행을 사용함
  • --dry 옵션으로 적용 전 호스트별 변경 diff를 확인하고, 실제 실행 시 결과가 병렬 스트리밍으로 돌아옴
  • 대상 호스트에는 shell과 SSH만 필요하며, 데몬·상태 파일·컨트롤 플레인이 없음
  • YAML로 제어 흐름을 인코딩하지 않고 Python의 루프와 조건문을 그대로 쓰는 코드 중심 구성을 강조함

핵심 기능과 실행 흐름

  • 수천 대 서버 자동화

    • pyinfra는 Python-native, agentless 자동화 도구이며 SSH로 명령을 실행함
    • 명령 실행은 동시성, 멱등성, 속도를 강조하며, 동일 워크로드에서 Ansible보다 6배 빠름을 내세움
    • 설치 명령은 $ uv tool install pyinfra
    • 표기된 기본 조건은 MIT license, Python 3.10 이상, no agents, zero config임
  • 배포 코드 예시

    • apt, files, systemd 작업을 Python 코드로 불러와 패키지 설치, 템플릿 배치, 서비스 재로드를 수행함
    • 예시 코드는 nginxcertbot 패키지를 설치하고, templates/nginx.conf.j2/etc/nginx/sites-enabled/api로 배치함
    • 마지막 단계에서 systemd.service("nginx", reloaded=True)nginx 서비스를 재로드함
    from pyinfra.operations import apt, files, systemd
    
    apt.packages(
        packages=["nginx", "certbot"],
        update=True,
    )
    
    files.template(
        src="templates/nginx.conf.j2",
        dest="/etc/nginx/sites-enabled/api",
    )
    
    systemd.service("nginx", reloaded=True)
    
  • 인벤토리와 실행 결과

    • 인벤토리 예시는 web-01.prod부터 web-23.prod까지의 웹 호스트와 db-01.prod, db-02.prod 데이터베이스 호스트를 구성함
    • $ pyinfra inventory.py deploy.py --limit web 명령은 web 대상만 제한해 실행함
    • 실행 출력은 인벤토리 로딩, 동시 fact 수집, deploy.py 실행, 요약 순서로 진행됨
    • 예시 요약은 23개 호스트 성공, 18개 변경, 실패 0개, 총 2.1초를 기록함
  • 변경 전 확인

    • --dry는 pyinfra가 수행할 모든 작업의 호스트별 diff를 먼저 확인하게 함
    • 실제 실행에서는 결과가 병렬로 스트리밍되어 각 호스트의 변경 수와 실행 시간이 표시됨
    • 예시 실행은 24개 호스트 중 18개 변경, 6개 무변경, 실패 0개, 총 2.1초를 기록함

특징, Ansible 비교, 원칙

  • pyinfra를 선택하는 여섯 가지 이유

    • Just Python: YAML과 Jinja-in-YAML 없이 실제 제어 흐름을 Python으로 작성함
    • Concurrent SSH: gevent와 SSH 기반으로 동시 실행하며, 동일 워크로드에서 Ansible보다 6배 빠름
    • Diff before apply: --dry로 모든 변경을 미리 보고, 멱등 작업은 재실행 시 no-op이 됨
    • 0 agents: 호스트에는 shell과 SSH만 필요하며, 데몬·상태 파일·컨트롤 플레인이 없음
    • Scale-ready: 1개 호스트부터 10,000개 호스트까지 동작하고, 병렬 실행과 실시간 스트리밍 출력을 지원함
    • Hackable: 10줄로 커스텀 작업을 만들 수 있고, shell과 통신하는 docker, lxc, k8s에 연결할 수 있음
  • Ansible과 pyinfra 코드 비교

    • Ansible 예시는 playbook.yml 16줄로 nginx 설치, 템플릿 렌더링, 핸들러 기반 서비스 재로드를 구성함
    • pyinfra 예시는 deploy.py 8줄로 같은 흐름을 Python 코드로 작성함
    • pyinfra 예시는 files.template 결과의 cfg.will_change가 참일 때만 systemd.service("nginx", reloaded=True)를 실행함
    from pyinfra.operations import apt, files, systemd
    
    apt.packages(["nginx"], update=True)
    
    cfg = files.template(
        src="nginx.conf.j2",
        dest="/etc/nginx/sites-enabled/api",
    )
    if cfg.will_change:
        systemd.service("nginx", reloaded=True)
    
  • 선언문

    • Code > config: 루프는 루프 그대로이며, 제어 흐름을 YAML에 인코딩하지 않음
    • Show, then do: diff를 먼저 보고, 그다음 적용해 예기치 않은 변경을 피함
    • Stay out of the way: 에이전트, 상태 파일, 컨트롤 플레인 없이 SSH로 바로 실행함
    • Read like english: 작업은 apt.packages, files.template, systemd.service처럼 명사와 동사 형태로 읽힘
  • 시작 명령

    • 설치 명령은 $ uv tool install pyinfra
    • 5분 quickstart를 읽고 첫 호스트를 배포하라는 안내가 제공됨

댓글과 토론

Lobste.rs 의견들
  • pyinfra는 Ansible이 원래 이렇게 됐어야 한다는 느낌임. 템플릿 섞인 YAML에 제어 흐름을 덧붙이는 대신, 자동화를 Python으로 직접 작성할 수 있음
    Ansible을 오래 다뤄온 뒤라 신선했고, 딱히 Ansible을 싫어하던 입장도 아니었음

    • 정확히는 Python으로 된 Ansible이라기보다는 Python에서 셸로 변환하는 인터프리터에 가까워 보이고, 그 나름의 문제가 있음
      대상 서버에서도 Python을 쓰는 하이브리드가 더 나을 듯함. 파일 갱신 때 따옴표 지옥이 줄고, sed의 정규식 한계 같은 것도 피할 수 있기 때문임
  • pyinfra를 좋아하고 더 널리 쓰였으면 좋겠음
    지금까지 일한 회사들은 모두 Terraform 병행 여부와 관계없이 Ansible을 썼고, 직원들이 경험 없는 도구로 기존 자동화를 전부 다시 작성할 준비가 된 곳은 없었음
    pyinfra는 SysOps가 Python을 알아야 하는데, 개인적으로는 SysOps가 스크립트 언어 하나쯤은 알아야 한다고 봄. 특히 Ansible에서도 Python으로 모듈을 작성하면 YAML 난장판을 줄일 수 있지만, 적어도 프랑스에서는 흔한 생각은 아닌 듯함

    • Ansible을 많이 써봤는데, 사실상 스크립트 언어를 가장한 것이라고 봄
      그렇게까지 뜨거운 논쟁거리는 아닐 수도 있음
  • 홈랩에서 Ansible을 쓰다가 점점 답답해졌음. YAML 설정은 끔찍하고, 모든 게 해킹처럼 느껴졌고, 속도도 슬펐음. 셸 명령 몇 개 실행하려고 서버에 python3가 필요한 것도 납득이 안 됐음
    Google AI Mode 덕분에 pyinfra를 알게 됐고, 거의 한 달 써본 범위에서는 훨씬 상쾌했음. 장점은 Ansible보다 훨씬 빠르고, 반복과 조건을 Python으로 짤 수 있으며, 역할과 중첩 디렉터리 없이 서버에는 셸만 있으면 된다는 점임. 실행 전에 현재 상태 기반으로 계획을 만들고 -y를 안 주면 확인도 받음
    단점은 기본 작업들이 Ansible 모듈에 비해 작은 부분집합이고, 코드가 금방 스파게티가 될 수 있으며, if 'web_server' in hosts.groups 같은 방식도 썩 좋지는 않다는 것임. operation(..., filter_group='web_server')가 더 나은지도 모르겠음
    가장 나쁜 점은 커스텀 커넥터 작성이 너무 괴롭다는 것임. pyinfra 전용 entry point가 들어간 pyproject.toml이 필요해 보이고, uv를 써도 사내 커넥터 개발이 악몽 같음. 그냥 프로젝트 안의 일반 Python 파일로 만들 수 있어야 함

  • 며칠 동안 pyinfra를 홈랩 배포 도구에 시험 중인데, Ansible과 비교해 지금까지 가장 마음에 든 건 Python 문법보다 속도
    Ansible은 항상 참을 수 없을 만큼 느리게 느껴졌음

    • 이 영역이 흥미로움. 나도 배포 도구를 만들고 있고, 본업에서 실제 배포에 쓰고 있음
      대부분의 곳에서 Ansible과 Salt 사용을 대체하고 싶음
  • 코드형 인프라가 한 바퀴 돈 게 재미있음. 스크립트에서 YAML로 갔다가 다시 더 정교한 스크립트로 돌아왔음
    접근마다 적당한 지점이 있고, Ansible 사용자 관점에서 pyinfra는 꽤 좋아 보임

  • Ansible을 채택하게 된 핵심 이유는 드라이런과 차이 보기 모드였음. 예상 밖의 작업을 하지 않을 거라고 확신할 수 있었기 때문임
    그런데 pyinfra CLI에는 그런 옵션이 없어 보임. 모든 옵션을 알파벳순으로 정리한 참조 문서를 못 찾아서 놓쳤을 수도 있음

    • —dry 플래그가 있고, pyinfra 첫 화면에 바로 나와 있음
  • 관심 있는 사람에게는 비슷한 14년 된 내 프로젝트도 있음: https://github.com/sebastien/cuisine/tree/main
    에이전트 없이 SSH만 쓰고, 핵심 관리 기능 위에 Python다운 API를 얹었지만 드라이 모드는 지원하지 않음

  • 우리는 OpenStack에서 리소스를 프로비저닝할 때 Ansible을 쓰고, 나머지는 pyinfra로 처리하는데 지난 몇 년간 꽤 잘 동작했음
    가장 큰 단점은 커뮤니티가 작아서 직접 해결책을 작성하게 된다는 점임. 예를 들어 배포에 필요한 공유 비밀은 keyring + privy로 디스크에 보관하고, OpenStack 컴퓨트 인벤터리를 hosts 데이터로 바꾸는 몇 줄의 코드를 직접 씀