← 글 목록

Ansible로 라즈베리파이 클러스터 시스템 업데이트 자동화하기

/ 11분 분량

라즈베리파이 클러스터의 시스템 업데이트를 Ansible로 자동화하는 방법을 배웠습니다. SSH 키 설정부터 Playbook 작성, Cron을 이용한 자동 실행까지 구현해보았습니다.

Ansible로 라즈베리파이 클러스터 시스템 업데이트 자동화하기

라즈베리파이 클러스터의 시스템 업데이트를 Ansible로 자동화하는 방법을 배웠습니다. SSH 키 설정부터 Playbook 작성, Cron을 이용한 자동 실행까지 구현해보았습니다.

학습 주제

  • 공부 주제: Ansible을 이용한 라즈베리파이 클러스터 시스템 업데이트 자동화
  • 대화 제목: Ansible로 라즈베리파이 클러스터의 시스템 업데이트 자동화 초기 설정 완료
  • 학습 날짜: 2026년 2월 25일

질문과 탐구

처음으로 Ansible을 접하면서 다음과 같은 질문들을 던지고 답을 찾아나갔습니다.

  • Ansible은 정확히 어떤 역할을 하는 도구인가?
  • SSH 키 인증은 어떻게 동작하며, 왜 필요한가?
  • Playbook은 어떻게 작성해야 하는가?
  • Roles, Tasks, Handlers는 어떤 개념이며 어떻게 사용하는가?
  • 호스트네임 변경이나 서비스 시작 실패와 같은 예상치 못한 문제는 어떻게 해결하는가?
  • Cron을 사용하여 Ansible Playbook을 주기적으로 실행하려면 어떻게 설정해야 하는가?
  • 클러스터 환경에서 재부팅 순서와 서비스 복구는 어떻게 관리해야 무중단에 가까운 상태를 유지할 수 있는가?
  • 로그는 어떻게 관리해야 문제 발생 시 추적이 용이한가?

핵심 학습 내용

Ansible을 활용하여 라즈베리파이 클러스터의 시스템 업데이트를 자동화하는 전 과정을 단계별로 학습했습니다.

1. Ansible 기초 및 SSH 키 인증 구축

  • Ansible 개요: 여러 서버를 한 곳에서 관리하는 자동화 도구로, SSH와 Python을 기반으로 작동하여 에이전트 설치가 필요 없는 Agentless 아키텍처를 가집니다. Control Node (Ansible 실행 서버)와 Managed Nodes (관리 대상 서버)로 구성됩니다.
  • SSH 키 인증: Control Node에서 Managed Nodes로 암호 없이 접속하기 위해 SSH 키 쌍(개인키, 공개키)을 생성하고, 공개키를 모든 Managed Node의 ~/.ssh/authorized_keys에 등록하는 과정을 실습했습니다. hostnamectl 명령과 /etc/hostname, /etc/hosts 파일의 관계, 그리고 Cloud-init의 호스트명 자동 관리 기능까지 이해하게 되었습니다.

2. Ansible 구조 설계 및 Playbook 작성

  • 디렉토리 구조: Ansible 프로젝트의 표준적인 구조(inventory, playbooks, roles 등)를 학습하고, cluster-admin 프로젝트 내에 ansible 디렉토리를 구성했습니다.
  • Inventory: inventory.ini 파일에 관리 대상 호스트들을 그룹별로 정의하고, ansible_user, ansible_ssh_private_key_file과 같은 변수를 설정했습니다. [all:vars] 및 [all:children]의 의미를 파악하고, serial: 1 옵션을 사용하여 노드별 순차 처리를 설정했습니다.
  • Playbook: 시스템 업데이트(apt update, apt upgrade), 재부팅 필요 여부 확인(stat), 조건부 재부팅(reboot with when), 그리고 k3s/k3s-agent 서비스 상태 대기(systemd with until) 기능을 포함하는 Playbook을 작성했습니다.
    - name: System Update and Sequential Reboot
      hosts: all
      gather_facts: yes
      serial: 1
      tasks:
        - name: Update apt cache
          apt:
            update_cache: yes
          become: yes
    
        - name: Upgrade packages
          apt:
            upgrade: dist
          become: yes
    
        - name: Check if reboot is required
          stat:
            path: /var/run/reboot-required
          register: reboot_required
    
        - name: Reboot if required
          reboot:
            msg: "System reboot initiated by Ansible"
            connect_timeout: 5
            reboot_timeout: 300
            post_reboot_delay: 30
          become: yes
          when: reboot_required.stat.exists
    
        - name: Wait for k3s service to be ready (master)
          systemd:
            name: k3s
            state: started
          become: yes
          register: k3s_service
          until: k3s_service.status.ActiveState == 'active'
          retries: 60
          delay: 10
          when: inventory_hostname in groups['master']
    
        - name: Wait for k3s-agent service to be ready (workers)
          systemd:
            name: k3s-agent
            state: started
          become: yes
          register: k3s_agent_service
          until: k3s_agent_service.status.ActiveState == 'active'
          retries: 60
          delay: 10
          when: inventory_hostname in groups['workers']
    

3. 문제 해결 과정

  • sudo 권한 문제: Worker 노드에서 sudo 명령을 사용할 때 암호 입력이 필요한 문제를 sudo visudo를 통해 NOPASSWD 설정을 추가하여 해결했습니다.
  • k3s-agent 시작 실패: Worker 노드에서 k3s-agent 서비스가 포트 충돌로 시작되지 않는 문제를 발견했습니다. 이는 해당 노드가 k3s server로 잘못 설정되었거나, 처음 설치 시 설정 오류가 있었던 것으로 추정됩니다. k3s-agent 서비스 재시작 및 Master 노드의 Kubernetes API에서 해당 노드 제거 후 재등록하여 문제를 해결했습니다.
  • 호스트네임 변경 문제: Master 노드의 호스트네임이 raspiMaster에서 raspiWorker1로 바뀌는 현상이 발생했습니다. 초기 k3s 설치 시 또는 Cloud-init 설정의 문제로 추정되었으나, hostnamectl 명령과 /etc/hostname, /etc/hosts 파일을 직접 수정하고 Cloud-init의 manage_etc_hosts 설정을 비활성화하는 과정을 통해 정상화했습니다.
  • 재부팅 순서: Master 노드가 먼저 재부팅되면 클러스터에 영향을 줄 수 있다는 점을 인지하고, Inventory 설정을 수정하여 Worker 노드들을 먼저 재부팅하고 Master 노드를 마지막에 재부팅하도록 순서를 변경했습니다. (이후 논의에서 Master 노드가 마지막에 재부팅되는 것이 더 안정적이라는 결론에 도달했습니다.)

4. Cron을 이용한 자동화

  • Shell Script 작성: Ansible Playbook 실행과 로그 저장을 자동화하는 run-update.sh 스크립트를 작성했습니다. nohup과 &를 사용하여 Master 재부팅 시에도 스크립트가 백그라운드에서 계속 실행되도록 했습니다.
  • Cron 설정: crontab -e를 통해 매일 오전 1시에 run-update.sh 스크립트가 실행되도록 설정했습니다. 로그는 logs/ 디렉토리에 타임스탬프별로 저장되도록 구성했습니다.

이해한 내용

Ansible을 통해 서버의 일상적인 관리 작업을 자동화하는 것이 얼마나 효율적인지 체감할 수 있었습니다. 복잡한 개념들도 단계별 실습과 문제 해결 과정을 통해 명확하게 이해할 수 있었습니다. 특히, SSH 키 인증의 작동 방식, Playbook의 구조와 각 요소의 역할, 그리고 Cloud-init과 같은 OS 레벨 자동화 기능까지 깊이 있게 배울 수 있었습니다.

실전 적용

  • 자동화: 이번 학습을 통해 구축된 Ansible Playbook과 Cron 작업은 라즈베리파이 클러스터의 정기적인 시스템 업데이트를 완벽하게 자동화합니다. 매일 오전 1시에 자동으로 실행되어 보안 패치 및 업데이트를 적용하고, 필요시 순차적으로 재부팅한 후 k3s 서비스를 안정화합니다.
  • 로그 관리: 모든 작업은 logs/ 디렉토리에 타임스탬프가 포함된 로그 파일로 저장되어, 문제 발생 시 원인 파악 및 추적이 용이합니다.
  • 실습 계획: 향후에는 Slack 알림 연동, 실패 시 더 구체적인 에러 처리 로직 추가, 그리고 Master 노드의 HA 구성 등을 추가적으로 학습하고 적용해 볼 계획입니다.

추가 학습 계획

  • Ansible Roles 심화: 이번에는 Task를 직접 작성했지만, 다음에는 Roles를 활용하여 Playbook을 더욱 모듈화하고 재사용 가능하게 만드는 방법을 학습하고 싶습니다.
  • Kubernetes HA 구성: Master 노드의 단일 실패 지점을 해결하기 위해 Kubernetes HA 구성을 학습하고, 3개의 Master 노드로 클러스터를 구성하는 방법을 익힐 예정입니다.
  • 알림 시스템 연동: Ansible Playbook 실행 중 오류 발생 시 Slack 또는 이메일로 즉시 알림을 받을 수 있도록 시스템을 구축하는 것을 목표로 합니다.

참고 자료

  • Ansible 공식 문서
  • k3s 공식 문서
  • Ubuntu/Debian 패키지 관리 (apt) 관련 자료
  • Cloud-init 공식 문서