CLOUDWAVE

IaC : Ansible 소개 및 설치

갬짱 2025. 1. 31. 01:35

 

Cloud Native

: 클라우드 이점을 최대로 활용하여 현대적인 애플리케이션을 구축하고 실행하는 방식
동적 인프라 환경에서 유연성, 가용성, 확장성을 갖추어 효율적인 애플리케이션 개발, 배포, 운영을 지향함

  • DevOps : 개발(Dev)과 운영(Ops)을 통합하여 협업 및 자동화를 강화하는 문화와 방법론 → 빠르고 안정적인 배포 및 유지보수
    • IaC(Infrastructure as Code) 도구 사용 (예: Ansible, Terraform)
  • CI/CD : 코드 통합, 테스트, 빌드, 배포 프로세스를 자동화하여 배포 속도와 품질 극대화
    • GitHub Actions, Jenkins, ArgoCD
  • Container : 애플리케이션과 그 실행환경(운영체제와 라이브러리, 설정 파일 등)을 하나의 패키지로 묶어 확장성, 이식성을 극대화한 기술 ( 종속성 제거 )
    • Docker, Kubernetes
  • MSA : 애플리케이션을 구성하는 서비스들을 마이크로 한 단위인 서비스로 분리하여 독립적으로 개발, 배포, 운영하는 방식 결합도 낮춤으로써 확장성, 유지보수성, 장애 복구 능력 강화
    • Spring Boot, Kafka, Service Mesh (Istio)

기본으로 제공되는 보안서비스 : 보안그룹, WAF(웹방화벽), shield(DDoS방어 솔루션, AWS 리소스사용시 무료버전이 자동으로 동작)
CNAPP : 클라우드 네이티브 환경의 보안솔루션, 추가적으로 플랫폼을 이용하여 보안실행

 
 
Automation : 도구( ansible, terraform )를 통한 클라우드 서비스의 자동화
자동화란 = 작업내용을 미리 만들어 놓은 파일(스크립트)을 따라 특정시점에 동작하도록 함

  • 테라폼은 프로비저닝 자동화 도구 - 클라우드 리소스(서버, 네트워크, 스토리지 등)를 정의하고, 프로비저닝(생성, 삭제, 업데이트)하는 데 사용
  • 엔서블은 configuration 자동화 도구 - 이미 존재하는 서버(인프라)의 설정구성을 자동화하는 데 사용 ( playbook을 이용 )

 

Ansible 소개

: 오픈소스 자동화 플랫폼으로 IT 시스템 구성 및 관리를 자동화하는 도구 → 여러 서버에 동일한 설정을 반복적으로 적용, 새로운 서버를 빠르게 설정하는 등 반복작업을 자동화, 인적실수를 줄임
 
 
[ 전통적인 관리방식 vs 자동화 관리방식 ]
 
전통적인 관리방식 : 그래픽, 명령줄 인터페이스(CLI)를 통해 관리자가 수동적으로 시스템 및 인프라 관리 → humon error의 발생, 일률적이지 못함

  • 리눅스환경에서 시스템 관리 표준작업 방식
    • nmcli : 리눅스에서 네트워크 설정하는 도구
    • 디스크를 파티셔닝해서 파일시스템으로 mount
  • 눈송이 서버(Snowflake Server) : 여러 서버의 동작이 외부에서는 동일한 형상으로 보이지만( 정상동작 ) 내부 관리에서 문제와 차이가 발생 ( 내부의 configuration 설정이 모두 다름 ) → 유지보수 비용이 증가, 환경오류 및 불안정

자동화 방식 : 시스템 관리 작업에 자동화 도구들을 사용, 다량의 서버가 동일한 configuration을 가지도록 함 → 신속하고 올바른 배포와 구성

  • 자동화 언어를 사용하여 인프라상태를 정의하고 설명
    • 버전제어 시스템 관리가 용이함( 변경기록이 지속적으로 유지 )
    • DevOps패턴 유지 : 개발자의 언어로 구성정의
    • 인프라 관리의 일관성유지, 오류완화

 
 
[ Ansible과 Container의 유사성 ]

  • 이미지 내부에 실행환경(Runtime)이 구성됨 ( 라이브러리, 프레임워크, 바이너리 등.. ) → 컨테이너로 구체화, 실행 ( 모두 동일한 플랫폼을 보장, 이식성이 높음 )
  • IT 시스템 구성( 어플리케이션이 동작하는 환경 )을 스크립트로 자동화 → 동일한 시스템 환경을 보장
  • 도커의 컨테이너 이미지 = 스크립트 파일

 
 
[ Ansible의 주요특징 ]

(1) 확장성과 유연성
ansible은 모듈(python)을 이용하여 다양한 작업을 수행 ( hummon error risk 방지 ) → 전체 어플리케이션의 라이프사이클을 오케스트레이션

  • 모듈은 서버 뿐아니라 네트워크 장비까지 설정가능( 네트워크 자동화, 워크플로우 자동화, 애플리케이션 배포 자동화 … )
    **대부분의 automation도구들이 서버만 자동화하는 것에 비해 이는 네트워크 및 장치까지 자동화 관리가 가능
  • 모듈은 다양한 운영체제, 클라우드 플랫폼, 네트워크 장치를 지원

 
(2) 에이전트 불필요
OpenSSH를 사용하여 관리대상 호스트와 연결하고 모듈 프로그램을 내보내어 호스트에 작업을 수행( window에서는 winrm )

  • 많은 automation은 에이전트를 통한 동작하는 것과 차별성 → 버전호환성 문제 없음(효율적), 사용자지정 보안 인프라 필요없음
  • 모듈 프로그램은 호스트 시스템을 다양한 목적에 따라 제어하는데 사용되고 작업이 완료되면 제거됨

 
(3) 간단하게 작성가능
사람이 읽기쉬운 YAML 문법을 지원 ( JSON은 편집이 어려움 )
 
(4) 멱등성과 예측가능성

  • 멱등성 : 여러번 같은 작업을 하더라도 동일한 결과(상태)를 보장 ( ex. 쿠버네티스의 controller는 여러번 배포(apply)하더라도 replicas의 지정갯수만큼만 pod 개수를 유지, 작업횟수에 따라 추가되거나 감소하지 않음 )
    playbook(스크립트)을 반복적으로 수행해도 정해진 설정상태로 유지됨
  • 검증된 스크립트를 재사용

 

Ansible 아키텍처

Ansible 아키텍처 : 제어 노드 + 관리 호스트 ( OpenSSH로 연결 )

  • ansible node 구축( ansible 패키지 설치, 코드실행 ) : managed host로 명령을 전달하고 제어 ( 각 노드에서 자동화 작업이 실행됨 )
    • Inventory 파일 : 관리 대상 호스트를 목록화 ( 텍스트 파일에 정적 정의 + 스크립트 실행을 통해 외부 소스로부터 동적 정의 )
    • Playbook : 실제 수행해야하는 작업 목록
      • YAML형식 ( key와 value로 이루어지는 문법, dictionary datatype & list data type(-) )
      • 플레이 단위 ( 작업대상(network, DB, 서버 등 인벤토리중 하나) + 작업내용( 모듈 = 파이썬 라이브러리 ) ) 들의 모음
  • Multi host : 여러 호스트를 구성하여 요청을 주고 받도로 만듬

 

  • 환경에 따라 사용하는 인벤토리의 목록이 달라짐 ( 개발환경, prod환경… )
  • 모듈 : 다양한 자동화 작업을 수행
  • 플레이북의 멱등(Idempotence)설계 : 시스템의 특정요소가 특정상태(권한, 콘텐츠)에 있는지 확인 → 해당상태에 있지 않으면 작업을 통해 해당상태로 만들도록 동작, 해당상태에 도달해있다면 아무 작업도 수행하지 않음

 

Ansible 설치 실습

Ansible 엔진은 Python으로 작성되어 있기 때문에 버전에 맞는 Python 패키지를 사전에 설치해야함
 
[ 가상머신(Virtual Box) 설정 ]
rocky linux( 9.5ver ) 이미지로 가상머신 4개를 구성 ( controller →(복제) serverA, serverB, serverC )

초기상태에서 수동으로 호스트 네트워크 영역( 네트워크 어댑터 ) 설정( 172.16.0.1/24 )
호스트 네트워크(Host-only Network) : 가상머신(VM)과 호스트(로컬 머신) 간에 직접 통신이 가능한 독립적인 네트워크 설정 → 로컬 머신과 가상 머신이 안전하고 제한적인 환경에서 통신하도록 함( 격리와 보안 )
 

각 가상머신의 네트워크 세팅에서 어댑터2를 호스트 전용 어댑터로 설정 ( 어뎁터1은 인터넷 통신을 위해 NAT로 기본설정되어있음 )

네트워크 어뎁터(NIC)는 특정 네트워크 대역 연결될 수 있도록 물리적 포트( 가상포트 )를 제공 네트워크 인터페이스는 NIC위에서 동작하는 소프트웨어 레이어로 특정 네트워크 대역에서 하나의 IP주소를 할당받아 통신역할을 수행

 

  • rocky linux 운영체제 초기 설정
    • 디스크 파티셔닝 자동으로 설정, root사용자 pass설정( SSH접속허용 ), 일반사용자 하나정도 생성
    • 가상머신 복제시( controller →(복제) serverA, serverB, serverC ) 모든 네트워크 어뎁터&MAC주소 새로 생성하도록 설정 : 쿠버네티스 활용을 위함( 쿠버네티스에서는 MAC주소 검증 )

 

  • 가상머신을 편리한 터미널 환경( mobaXterm, putty … )에서 접근하기 위해 IP세팅 ( controllerVM )기존네트워크 대역에서 가상머신의 enp0s8 네트워크 인터페이스에 대해 수동적으로 설정한 IP로 통신하도록 설정
    nmcli con mod enp0s8 ipv4.address 172.16.0.200/24 ipv4.method manual
    1. IPv4 주소를 172.16.0.200으로 설정. ( 처음에 생성한 네트워크 대역의 주소중 하나 ) ( controller VM : 172.16.0.200 , servera : 172.16.0.201 , serverb : 172.16.0.202 , serverc : 172.16.0.203 으로 설정 )
    2. 서브넷 마스크를 /24 (즉, 255.255.255.0)로 설정. ( 처음에 생성한 네트워크 대역 )
    3. IP 설정 방식을 수동(manual)으로 지정 (DHCP가 아닌 직접 설정)

 

  • ncmli con show enp0s8 로 확인

 

  • ip a → 3개의 ip가 할당되어있다.
  • lo : 로컬머신 자신을 가리키는 Loopback IP = 127.0.0.1 ( 고정적 )
  • enp0s3 : NAT 어댑터에서 자동으로 할당한 IP → 외부통신 담당 기본적으로 VirtualBox는 10.0.2.15/24부터 IP를 할당하는 방식을 사용하는 것이 관례
  • enp0s8 : 직접할당한 IP가 할당

 
[ SSH 연결 ]

  • 인증 : 인가된 사용자인지 검증 → SSH에서 지원하는 2가지 인증방식
    • 사용자 password를 이용한 인증 : 유저의 ID/PASSWORD
    • keypair를 이용한 인증 : 공개키(public key)와 개인키(private key) 쌍을 이용
      • 공개키는 공개하여 다른 시스템에 배포할 수 있는 키, 서버의 ~/.ssh/authorized_keys 파일에 저장
      • 개인키(비공개키)는 비밀로 유지하며 본인만 소유하는 키, 접속을 시도하는 클라이언트의 ~/.ssh/id_rsa 파일에 저장
      서버는 클라이언트의 공개키를 이용해 challenge를 생성하여 전달 → 클라이언트는 개인키(비공개키)로 이를 암호화(서명)하여 전달 → 서버는 공개키로 이를 복호화하여 검증
  • ansible( controller node )에서 키를 생성 → managed host에 public key를 등록 & private key를 소유하여 추후에 접속 ( managed host를 서버로 취급 )
    • controller VM에서 key를 생성하고 server A, B, C에 배분
    • 유사) AWS에서 키인증 : public key를 AWS 서버에서 가지고( 공개키 경로에 등록 ) private key를 사용자에게 부여하여(다운로드) 접속하게 해줌

(1) 키 생성

ssh-keygen
  • ssh-keygen : 키를 만드는 명령 → 암호화 프로토콜로 기본적으로 RSA을 사용 ( 비대칭방식 )
  • -f : 생성된 키가 저장되는 위치 디폴트 위치 : ~/.ssh/id_rsa 로 설정 ⇒ SSH 명령어에서 -i 옵션( 키 위치 )을 생략할 수 있음
  • -N : 키를 사용할때 키에 대한 패스워드를 지정가능
    -N ‘’ : 앤서블에서는 다음과 같이 키에 암호를 지정하지 않음 → 자동화를 위함

기본 암호화 방식( RSA )로 해당위치(~/.ssh/id_rsa)에 키 페어가 만들어짐
 
(2) 키 배포

ssh-copy-id USER@remote-server

ssh-copy-id : 생성된 공개 키(.pub)를 원격 시스템에 복사 → 원격 시스템의 ~/.ssh/authorized_keys 파일에 공개 키가 추가됨 ( 사용자 이름 생략시 기본적으로 현재 사용자와 동일한 이름의 유저에게 전달됨 )

개인 키는 로컬 시스템에만 존재하고, 공개 키는 원격 시스템에 전달 및 등록 ⇒ 로컬에서 원격에 접속가능하게 함
첫 원격접근시에 접속이력이 없어서 안내가 뜸 → yes를 누르면 finger print가 찍힘
 

이후 -i옵션 없이( 키 지정없이 ) 원격 접근가능
 
이러한 키 배포 및 인증은 유저별로 진행 ( root가 아닌 ansible 유저를 통해 인증할 수 있도록 설정한다. )
ssh의 기본 방식은 ssh USER@HOST → 이때 USER 생략시 현재 클라이언트에서 요청을 보내는 사용자의 정보가 자동으로 재사용됨

 
ansible 유저로 접속하여 호스트 서버에 키를 생성후 키를 전달( 이는 ansible-ssh 용도라는 공통적 목적을 가지고 있기에 모두 동일한 키로 복사 ⇒ 기간단위로 키를 순환, 키 순환에도 자동화도구가 이용됨 )

 ssh 서버IP hostname

hostname옵션 : SSH연결에서 interactive한 방식으로 연결을 유지하는 것이 아니라 한번의 응답만 받고 종료시킴
 
(3) sudo 권한등록
일반사용자에게는 설치, 모듈 작업을 위해서 자유로운 root 권한상승이 필요함
sudo : 일반 사용자가 루트 사용자의 권한으로 명령어를 실행할 수 있도록 하는 명령어 ( /etc/sudoers 파일에 권한상승 대상 사용자를 등록 )
바람직한 방식은 sudoers.d 디렉토리를 새롭게 생성하여 상속받도록 함( /etc/sudoers.d/ 디렉토리에 유저별로 파일을 추가하여 유저별로 sudo 권한을 설정 → 이 파일들은 최종적으로 /etc/sudoers 파일과 합쳐져서 동작, 시스템에서 해당 유저에게 sudo 권한을 부여 )
 

cat /etc/sudoers

%wheel ALL=(ALL) NOPASSWD: ALL : 패스워드 사용없이 root 권한으로 상승가능
 

ansible 유저가 모든 권한을 비번 없이 사용가능하도록 등록
 

ansible 유저는 sudo 권한을 가지고 패키지 설치가 가능하다
 
EPEL = extra package for enterprise linux : Red Hat 계열 배포판(RHEL, CentOS, Rocky Linux 등)에서 사용할 수 있는 추가 패키지 저장소(Repository)

이를 읽어서 레포지토리를 연결, 다양한 추가 패키지 설치 가능
 
(4) ansible 설치

sudo dnf install -y ansible

epel 레포지토리에 있는 ansible을 설치
* 요약 : controller에서 server node(managed host)에 SSH로 접근하여(키 인증기반) 작업을 수행 → 이때 노드의 ansible-user로 접근하며, 이 유저는 sudo권한을 가질 수 있음
 
(5) 호스트 이름 등록
static한 IP를 기반으로 명령을 보내는 것은 권장하지 않음 → 이름을 붙여서 요청을 보냄
 
/etc/hosts파일 : 로컬 시스템에서 IP주소와 호스트이름간의 매핑정보를 정의하여 DNS 요청없이 직접 참조 ( 로컬 해석이 우선적으로 이루어짐 ) ↔ DNS는 외부 네트워크상의 외부 네임서버에서 호스트 이름을 IP주소로 변환하는 방식
controller에서 /etc/hosts에 각 서버의 IP와 네이밍을 등록

이후에는 IP가 아닌 호스트명으로 접근가능 → 핑거프린트를 한번더 찍는다
agent방식이 아니라서 daemon으로 올릴 별도의 프로세스가 존재하지 않음, SSH로 단순접속
 

Ansible 제품

ansible core : 무료버전
ansible awx : 그래픽 기반, 무료버전 ⇒ docker compose로 실행
ansilbe ap( aap ) : 유료버전( redhat에서 제공하는 솔루션 ), awx를 고도화( subscription을 받아서 repo연결하여 설치 )