재형이의 성장통 일지
  • 리눅스 운영의 기초 : 스크립트 및 설정 자동화
    2024년 01월 29일 06시 23분 02초에 업로드 된 글입니다.
    작성자: 재형이
    반응형
    • 리눅스 쉘 스크립트 및 IaC 도구 중 하나인 Ansible 기초 정리

    리눅스 운영의 기초 포스팅

     

    리눅스 운영의 기초 : 시스템 및 프로세스 관리

    운영을 잘하기 위해서는 운영체제의 기본 정도는 알고 있어야 할 것 같다는 생각이 들어서 리눅스를 공부하게 되었다 너무 딥하게 들어가지는 않을 것이고 기초 위주로 정리를 해볼 생각이다.

    jaehyeong.tistory.com

     

    리눅스 운영의 기초 : 파일시스템, 소프트웨어 및 사용자 관리

    지난번에 이어서 리눅스 기초 정리 리눅스 운영의 기초 포스팅 😎 리눅스 운영의 기초 : 시스템 및 프로세스 관리 리눅스 운영의 기초 : 시스템 및 프로세스 관리 운영을 잘하기 위해서는 운영

    jaehyeong.tistory.com

     

    리눅스 운영의 기초 : 스크립트 및 설정 자동화

    리눅스 쉘 스크립트 및 IaC 도구 중 하나인 Ansible 기초 정리 리눅스 운영의 기초 포스팅 😎 리눅스 운영의 기초 : 시스템 및 프로세스 관리 리눅스 운영의 기초 : 시스템 및 프로세스 관리 운영을

    jaehyeong.tistory.com

     


     

    1. 스크립트 및 쉘 프로그래밍 (스크립트 작성 기준, 기본 쉘 명령어 등)

    1-1. 쉘 스크립트의 일반적인 사용 방법

    • 개인적으로 사용하는 짧고 간편한 스크립트를 ~/bin 디렉토리에 모아 보관
    • 극히 짧은 버전의 스크립트는 ~/.bashrc에 alias로 정의하기도 함
      • alias l = ‘ls -alh’
      • alias reload = ‘source ~/.bashrc’
      • alias editbash = ‘vi ~/.bashrc’

    1-2. 쉘 스크립트 언어

    1. 쉘 스크립트
    2. Perl
    3. 파이썬
    4. 루비
    • 방대한 외부 패키지가 존재하는 파이썬을 많이 사용 → 단, 운영에 사용하기 전에 검토가 필요

    1-3. 쉘 스크립트 작성 기본 가이드

    • 부적절한 인수를 써서 실행했을 때는 사용법 메시지 출력
    • 입력 데이터의 유효성을 검증하고 도출된 값들이 정상인지 확인
      (입력 데이터의 유효성 검증을 통해 rm -rf를 통해 루트 디렉토리가 삭제된다거나 하는 경우 방지)
    • 의미 있는 종료 코드 사용
      → 성공 시 0, 실패시에는 0이 아닌 값
    • 변수, 스크립트, 루틴에 적합한 네이밍 규칙 사용
    • 스타일 가이드 사용
      → 예) 파이썬 PEP8

    https://ultrakain.gitbooks.io/python/content/chapter1/coding-style-pep8.html

     

    코딩 스타일 : PEP8 · Python

     

    ultrakain.gitbooks.io

    • 주석 사용
      → 예) 스크립트가 무슨 일을 수행하는지, 어떤 매개 변수를 사용하는지에 대한 정보 포함
      선택한 알고리즘, 참조한 웹사이트, 구현 이유 등도 유용
      단, 과도한 주석은 가독성을 해칠 수 있음
    • 기존 코드 재활용은 좋지만, 이해하지 못한 코드를 복사&붙여넣기는 지양

    1-4. Shell의 종류

    • 기원인 Borne Shell은 기본 유닉스 . AT&T 라이센스 이슈로 제한
      → 대부분 Almquist Shell(ash, dash, sh), Borne-Again Shell(bash) 형태로 사용
    • Almquist Shell
      • 오리지널 Borne Shell을 재 구현. 기본 기능만 제공.
    • Bash Shell
      • 대화형 사용성.
      • 당시 사용되던 유용한 기능들 대부분 흡수 (예, 자동완성)
    • Z Shell
      • Korn Shell(ksh), ksh의 고성능 버전 Z Shell(zsh)
      • 고유의 기능(예, 오타 교정, 색상 지정 등) + sh, ksh, bash와 두루 호환
      • Oy My ZSH로 에 다양한 기능 추가
        Z Shell 예시

    → 쉘 스크립트 실행 (/bin/sh), 로그인  (/bin/bash, /bin/zsh)

    1-5. 리다이렉션

    • 모든 프로세스는 3개의 기본 파일 디스크립터를 가지고 있음
    • 표준 입력(STDIN) : 0, 표준 출력(STDOUT) : 1, 표준 오류(STDERR) : 2
    • <,>,>> 기호는 한 명령의 입력이나 출력을 파일로 전환하라는 지시어 → 리다이렉션 기호
      • < : 해당 명령의 표준 입력을 기존 파일의 내용물에 연결
        예) sort < list.txt 
        cf) sort list.txt 는 파일을 인자로 넘겨준 것이고 sort < list.txt 는 표준입력으로 전달이 된 것
      • >, >> : STDOUT을 파일로 리다이렉트.
        > 는 파일의 내용을 대체, >> 는 기존 파일의 내용에 추가
        예) grep bash /etc/passwd > /tmp/bash-users # bash 쉘을 사용자 목록을 저장
        예) sort < list.txt > new_list.txt # 연결해서 사용 가능
    • 표준 입력과 리다이렉션 응용
      • 예) 2> : STDERR를 파일로 리다이렉트
    echo “dummy file” > /tmp/dummy
    cat /tmp/dummy
    # dummy file
    cat /tmp/dummy > /dev/null
    # /dev/null로 보내면 출력을 안함
    cat /tmp/dumm
    # /tmp/dumm: No such file or directory
    cat /tmp/dumm 2> /dev/null
    # 에러를 /dev/null로 보내서 아무것도 출력 안됨
    find / -name core > /tmp/corefiles 2> /dev/null 
    # permission denied 에러 출력을 안보고 싶을 때 이런 식으로 활용 가능, 결과는 파일로 저장
    • 예) 2>&1
    nohup run.sh &
    nohup run.sh > /dev/null &
    # 표준출력 /dev/null로 보내서 출력 안함
    nohup run.sh > /dev/null 2>&1 &
    # 2(표준오류)를 1(표준출력)으로 보내고 표준출력이 /dev/null로 감
    nohup run.sh > /tmp/run.log 2>&1 &
    nohup run.sh > /tmp/run.out 2> /tmp/run.err &

    1-6. 파이프 

    • 한 명령의 STDOUT을 다른 명령의 STDIN에 연결하려면 파이프(|)를 사용
      find / -name core 2> /dev/null | less # 검색 결과를 less 명령 입력에 전달
      ps -ef | grep nginx # ps 를 실행해 프로세스 목록을 만들어 파이프를 통해 grep 명령에 전달
    • 앞 명령이 성공했을 경우에만 두번째 명령 실행
      mkdir test && cd test # 종료 코드가 0인 경우에만 뒤에 명령 실행
    • 앞 명령이 실패했을 경우에만 두번째 명령 실행
      cd test || echo "No such directory"
    • 한 명령을 여러 줄에 걸쳐 쓰려면 \ 기호를 사용
    • 여러 명령을 결합해서 한 줄로 만드는 경우, 명령문들을 서로 구분하기 위해 ; 기호 사용
      mkdir test; cd test; touch hello

    1-7. 변수와 인용

    • 변수명에 값을 지정할 때는 이름만 사용, 값을 참조할 때는 변수명 앞에 $ 기호를 사용
      etcdir='/etc' # = 기호 주변에는 빈칸이 없어야 함. 빈칸이 있으면 ‘명령 인수1 인수2’로 인식
      echo $etcdir
    • 변수를 참조할 때는 변수명 주변을 중괄호({})로 묶어서 어디 까지가 변수이고 텍스트인지를 구분
      echo ${etcdir}
      echo "My etc directory is ${etcdir}."
    • 변수 네이밍에는 표준 관례가 있지는 않지만,
      • 환경변수, 글로벌 환경설정에서 읽은 변수: 모든 글자가 대문자
      • 로컬 변수: 소문자로 표시, _ 부호로 구성요소들을 구분
        * 대/소문자 구분함
    • 작은 따옴표, 큰 따옴표, 역 따옴표(백쿼터``)
      리눅스 명령의 결과를 변수로 사용할 때 백쿼터(``) 사용
      mylang="Korean"
      echo "I speak ${mylang}"
      echo 'I speak ${mylang}'
      echo " There are `wc -l < /etc/passwd` lines in the passwd file. "

    1-8. 환경 변수

    • 실행 프로그램들은 환경변수를 참조해 구동 조건을 변화 
      예) export BASE_URL=""
      export DATABASE_URL=""
    • 환경 변수 조회
      printenv
    • 로그인 시 설정하는 환경 변수는 ~/.profile이나 ~/.bash_profile에 포함
    • PWD, HOME 과 같은 환경변수들은 쉘에 의해 자동으로 관리 → 예약어가 존재함

    1-9. 유용한 명령어

    • wc : 줄, 단어, 문자의 수를 셈
      wc /etc/passwd
      wc -l /etc/passwd
    • head와 tail : 파일의 시작이나 끝을 읽어냄
      head /etc/passwd 
      head -n 20 /etc/passwd
      tail /etc/passwd
      tail -f /var/log/syslog
      tail -f /var/log/syslog /var/log/nginx/access.log
      → f 옵션 : 종료되지 않고 새 줄을 계속 출력
    • grep : 입력 텍스트를 검색해서 주어진 패턴과 일치하는 줄들을 출력
      grep ssh /var/log/syslog
      grep -l ssh /var/log/*
      → l 옵션 : 일치하는 텍스트를 가진 파일 목록만 표시

    1-10. 쉘 스크립트 작성법, 쉬뱅

    • 쉘 스크립트란 쉘이나 명령 줄 인터프리터에서 돌아가도록 작성된 스크립트
    • 문법이 특이하고 제한적
      → 긴 내용이나 셸에 없는 기능은 파이썬 사용을 권장
    • .sh라는 파일 확장자를 사용하기도 하지만, 대부분 쉘 스크립트는 파일 확장자를 사용하지 않음
    • 오리지널 Borne Shell의 문법으로 제한하는 것을 권장
      → 스크립트가 다른 시스템에서 동작하지 않는 경우를 방지
    • 작성
      • 첫 줄은 shebang
        → 현재 파일의 실행 방법을 커널에 안내 (호출된 쉘 입장에서는 주석)
        → 의 경우, 대부분 /bin/sh (링크 형태)
      • 주석은 #
      • 하나의 논리적인 줄을 여러 줄로 분리할 때는 끝에 \ 사용
      • 여러 실행문을 하나의 줄에서 실행할 때는 ; 으로 구분
      • 실행
        #!/bin/sh
        MY_KERNEL="`uname -r`"
        echo "My Kernel is ${MY_KERNEL}"
        chmod +x myscript
        ./myscript
        sh myscript # 새로운 쉘에서 명령 실행
        sh myscript
        echo $MY_KERNEL
        # 아무것도 안나옴

        source myscript 또는 . myscript # 현재 쉘에서 명령 실행
        sh myscript
        echo $MY_KERNEL
        # 5.13.0-1031-aws처럼 쉘스크립트에서 선언한 환경변수가 그대로 적용
      • 각 명령을 실행하기 전에 명령 내용을 출력
        sh -x myscript
        + uname -r
        + MY_KERNEL=5.13.0-1031-aws
        + echo My Kernel is 5.13.0-1031-aws
        My Kernel is 5.13.0-1031-aws

    1-11. AWS EC2 인스턴스 ID로 SSH 접속할 수 있게 세팅하기

    • 우분투 20.04 사용해야 함
    • ssh -i private_key ubuntu@10.0.0.23 → ssh_by_id i-12345678로 접속할 수 있게 됨
    #!/bin/bash
    #
    # Usage
    # $ ./ssh_by_id i-12345
    
    if [ $# -ne 1 ]; then
      echo "Usage"
      echo "$ ./ssh_by_id i-12345"
      exit 1
    fi
    
    instance_id=$1
    
    # get EC2 data
    availability_zone=$(aws ec2 describe-instances --instance-ids $instance_id | jq -r .Reservations[0].Instances[0].Placement.AvailabilityZone)
    ip_address=$(aws ec2 describe-instances --instance-ids $instance_id | jq -r .Reservations[0].Instances[0].PrivateIpAddress)
    
    # generate RSA key pair
    tmpfile="/tmp/ssh.`echo $RANDOM | base64 | head -c 6`"
    ssh-keygen -C "temp ssh key" -q -f $tmpfile -t rsa -b 2048 -N ""
    public_key=${tmpfile}.pub
    private_key=$tmpfile
    chmod 400 $private_key
    
    # register public key
    aws ec2-instance-connect send-ssh-public-key \
      --instance-id  $instance_id \
      --instance-os-user ubuntu \
      --ssh-public-key file://$public_key \
      --availability-zone $availability_zone > /dev/null
    
    # ssh into ec2 instance with private key
    ssh -i $private_key ubuntu@$ip_address
    # ssh_by_id 파일에 실행 권한 부여 및 복사
    chmod +x ssh_by_id
    sudo cp ssh_by_id /usr/local/bin
    # ssh_by_id 테스트
    ssh_by_id i-12345678

    부록 : 파이썬 쉘 스크립트 작성 및 가상환경 구성

    부록-1. Python

    • 범용적으로 널리 사용 (웹 앱 개발, 데이터 분석, 시스템 관리 등)
    • 장점
      • 방대한 외부 라이브러리가 존재
      • 단순한 구문으로 실행가능한 수도 코드라 불리기도 함 → 빠르게 배울 수 있음
    • 시스템 관리자에게 이젠 필수 언어
    • Python2 vs. Python3
      하위 호환성이 유지되지 않음 → 오랫동안 Python2가 유지. 현재도 여전히 Python2도 사용됨

    부록-2. Python 기반 스크립트 작성

    • 스크립트 작성
      • #!/usr/bin/python3
      • print(“Hello World”)
    • 스크립트 실행
      • chmod +x helloworld
      • ./helloworld

    부록-3. Python 가상환경을 통해 프로젝트별 환경 구성하기

    • virtualenv : Python용 가상 환경
    • 가상 환경 디렉토리 내부에 파이썬 가상 환경을 생성
      → 프로젝트별 패키지 및 환경 관리
    • virtualenv 설치
      sudo apt install python3-virtualenv
    • 가상환경 생성
      virtualenv myenv
    • 기본 사용 원리
      • 가상 환경에 있는 bin/ 디렉토리 내용을 실행하는 경우, 가상환경을 사용하게 됨
        • ~/myenv/bin/python
          >>> import requests
          → requests 패키지가 없다고 오류 나옴
        • ~/myenv/bin/pip install requests
        • ~/myenv/bin/python
          >>> import requests
          가상환경에만 requests 패키지가 설치됨
    • 쉘에서 대화형으로 작업할 때, 기본값으로 설정하려면
      • source ~/myenv/bin/activate 
        # 셸의 PATH변수를 재배치
      • pip freeze
        # 가상환경에 설치된 패키지 목록
      • deactivate
        # 가상환경에서 빠져나올 때

    부록-4. 프로젝트별 사용하는 Python 버전이 다를 경우 관리툴

    부록-5. pyenv + virtualenv : python 버전에 맞는 가상 환경 생성

    • 명령
      • pyenv virtualenv 3.8.0 myenv
        # 3.6.0 버전의 myenv 가상 환경 생성
      • pyenv activate myenv
        # myenv 가상환경 실행
      • pyenv deactivate
        # 가상환경 비활성화
        → /home/ubuntu/.pyenv/versions/3.8.0/envs/myenv

    부록-6. Python으로 리눅스 명령어 구현해보기

    1. tail -f 구현해보기
      #!/usr/bin/python3
      import sys
      import time
      
      def tail(filename):
          with open(filename) as f:
              f.seek(0,2)
              while True:
                  line = f.readline()
                  if not line:
                      time.sleep(0.1)
                      continue
                  yield line
      
      filename = sys.argv[1]
      for line in tail(filename):
          print(line)
      # 실행 권한 부여
      chmod +x py_tail
      
      # /usr/local/bin 디렉토리로 이동
      sudo cp py_tail /usr/local/bin
      
      # 테스트
      py_tail /var/log/auth.log
    2. wc 구현해보기
      #!/usr/bin/python3
      import sys
      import time
      
      def wc(filename):
          chars = words = lines = 0
          with open(filename) as f:
              for line in f:
                  lines += 1
                  words += len(line.split())
                  chars += len(line)
                  
          print("{} {} {} {}".format(lines, words, chars, filename))
      
      filename = sys.argv[1]
      wc(filename)
      # 실행 권한 부여
      chmod +x py_wc
      
      # /usr/local/bin 디렉토리로 이동
      sudo cp py_wc /usr/local/bin
      
      # 테스트
      py_wc py_tail

    2. 설정 자동화 도구 (Configuration Management 이해, Ansible 살펴보기 등)

    • 전통적인 시스템 관리 방법
      • 장애가 발생할 때마다 자체 개발한 셸 스크립트로 처리
         → 급한 장애는 처리하지만, 시간이 지나면서 재현할 수 없는 패키지 버전과 환경설정으로 변경
      • 그 외에도 업그레이드 / 패치 작업등으로 서버들의 형상은 시간이 지날 수록 다른 모습이 됨
      • 눈꽃송이처럼 서로 다른 모습을 갖게 됨
        → SnowFlake Server (https://martinfowler.com/bliki/SnowflakeServer.html)
    • 좀 더 나은 설정 방법 → 코드형 인프라(Infrastructure as Code, IaC)
      • 코드 형태로 원하는 상태를 관리
        → 수동으로 시스템 수정하지 않아야 함
      • 코드는 버전 관리 시스템으로 관리
      • 대부분의 환경 설정 관리 도구는 절차적이 아닌, 선언적 방식을 사용
        → 시스템 변경을 위한 개별 단계를 알려주는 방식이 아닌, 달성하려는 상태를 선언
      • 대표적인 도구 : Ansible, Saltstack, Puppet, Chef
    • IaC 비교

    • Ansible은 손쉽게 사용 및 운영 가능
    • agentless, 나머지는 master-agent
      → 장단점 존재
    • ansible 코어는 무료
    • 프로젝트 활성화 상태도 Ansible이 우세
    • GitHub Starts, Google Trend, Debian 패키지 랭킹

    • master-agent 모델은 더 빠르고, 다양한 기능을 제공

    • Ansible의 경우, 모든 inbound 규칙을 추가해야 한다는 단점도 있음
    • Chef는 강력한 기능 제공
      • 전문 인력, 수백/수천 서버, 규정 준수 요건
    • Puppet은 가장 오래됨
      • 많은 사용자, 많은 기여 모듈, 무료 웹 관리콘솔
      • 대규모 호스트 관리에는 병목현상, 소규모에 적용하기엔 진입장벽 → 점유율이 낮아지고 있음
    • Salt는 다양한 범위의 사용 사례를 커버
      • Ansible과 사용 방식 유사하지만 Ansible 대비 빠름
        → 환경설정 YAML, 템플릿 Jinja, 내부 구현은 Python
        → Agent요청을 비동기로 처리하여 호스트가 늘어나도 빠른 처리가 가능
      • Push / Pull 방식 모드 지원

    2-1. Ansible

    • RedHat에서 개발한 환경 설정 관리, 소프트웨어 설치, 어플리케이션 배포를 관리하는 도구
    • 리눅스 및 Windows 호스트를 지원
      → SSH, remote PowerShell execution
    • 서버에 동작하는 데몬 X, 클라이언트에 별도의 에이전트를 설치하지 않음
      → 클라이언트를 관리하려는 시스템(=서버)에 Ansible 실행에 필요한 명령어만 설치
      (ansible, ansible-playbook, ansible-vault)
    • 설치
      • OS 별 패키지 매니저 → 이전 버전 설치
      • PIP 사용 → 최신 버전 설치
        sudo pip install ansible
      • 가상환경에 설치
         python -m virtualenv ansible
        source ansible/bin/activate
        python -m pip install ansible

    2-2. Ansible 기본 구성

    1. Control node
      • Ansible CLI를 실행할 머신
    2. Managed node
      • Ansible로 관리를 진행할 타겟 호스트
    3. Inventory
      • 관리할 호스트 목록 (개별, 그룹, 중첩된 그룹)
        • INI, YAML 형식 사용
          # INI 형식의 인벤토리
          mail.example.com
          
          [webservers]
          foo.example.com
          bar.example.com
          
          [dbservers]
          one.example.com
          two.example.com
          three.example.com
          
          # YAML 형식의 인벤토리
          all:
            hosts:
              mail.example.com:
            children:
              webservers:
                hosts:
                  foo.example.com:
                  bar.example.com:
              dbservers:
                hosts:
                  one.example.com:
                  two.example.com:
                  three.example.com:
        • 개별, 그룹, 중첩된 그룹
          # 중첩된 그룹 : prod, test
          all:
            hosts:
              mail.example.com:
            children:
              webservers:
                hosts:
                  foo.example.com:
                  bar.example.com:
              dbservers:
                hosts:
                  one.example.com:
                  two.example.com:
                  three.example.com:
              east:
                hosts:
                  foo.example.com:
                  one.example.com:
                  two.example.com:
              west:
                hosts:
                  bar.example.com:
                  three.example.com:
              prod:
                children:
                  east:
              test:
                children:
                  west:
        • 이름 범위 사용
          # www01, www02, www03, …, www50
          ...
            webservers:
              hosts:
                www[01:50].example.com:
          
          
          # www01, www03, www05, …, www49 match, but not www00, www02, www50
          ...
            webservers:
              hosts:
                www[01:50:2].example.com:
      • 인벤토리 관리
        • 기본 인벤토리 목록: /etc/ansible/hosts
        • 실행 시 인자로 인벤토리 전달 가능
          (예, ansible webservers -m ping -i dev-hosts)
      • 동적 인벤토리
        • 동적으로 인벤토리 목록을 구성
          → 클라우드 가상머신의 메타데이터에 따라 인벤토리 구성
          예) AWS EC2에 임의의 태그 할당
          - NGINX용 인스턴스에 webserver 태그
          - PostgreSQL용 인스턴스에 dbserver 태그
    4. Playbooks
      • 실행할 작업 목록을 관리
        → 실행할 작업은 ‘플레이’로 구성
      • Play
        • Ansible 실행의 기본 단위
        • 변수, 롤, 태스크 목록
        • 예) 웹 서버 업데이트, DB 서버 업데이트
      • Task
          • 호스트에 적용할 동작을 정의
          • 예) 최신버전 DB 확인, DB 서비스 시작
        ---
        - name: Update web servers     → Play 부분
          hosts: webservers
          remote_user: root
        
          tasks:
          - name: Ensure apache is at the latest version     → Task 부분
            ansible.builtin.yum:
              name: httpd
              state: latest
        
          - name: Write the apache config file     → Task 부분
            ansible.builtin.template:
              src: /srv/httpd.j2
              dest: /etc/httpd.conf
        
        - name: Update db servers     → Play 부분
          hosts: databases
          remote_user: root
        
          tasks:
          - name: Ensure postgresql is at the latest version     → Task 부분
            ansible.builtin.yum:
              name: postgresql
              state: latest
        
          - name: Ensure that postgresql is started     → Task 부분
            ansible.builtin.service:
              name: postgresql
              state: started
    5. Modules
      • 모듈화된 작업 내용 → Ansible에서 사용하는 명령어 집합
        예) 파일 모듈, 소프트웨어 패키지 모듈, 시스템 모듈 등
      • 모듈에 없는 경우, 커스텀 스크립트를 사용하거나 커스텀 모듈을 만들어 사용
      • https://docs.ansible.com/ansible/2.9/modules/modules_by_category.html
         

        Module Index — Ansible Documentation

        Docs » User Guide » Working With Modules » Module Index © Copyright 2019 Red Hat, Inc. Last updated on May 27, 2022.

        docs.ansible.com

        # systemd 서비스를 제어하는 모듈 https://docs.ansible.com/ansible/2.9/modules/systemd_module.html#examples
        - name: Make sure a service is running
          systemd:
            state: started
            name: httpd
        
        - name: stop service cron on debian, if running
          systemd:
            name: cron
            state: stopped
        
        - name: restart service cron on centos, in all cases, also issue daemon-reload to pick up config changes
          systemd:
            state: restarted
            daemon_reload: yes
            name: crond
        # 리모트 서버에 파일을 카피하는 모듈 https://docs.ansible.com/ansible/2.9/modules/copy_module.html#examples
        - name: Copy file with owner and permissions
          copy:
            src: /srv/myfiles/foo.conf
            dest: /etc/foo.conf
            owner: foo
            group: foo
            mode: '0644'
        
        - name: Copy file with owner and permission, using symbolic representation
          copy:
            src: /srv/myfiles/foo.conf
            dest: /etc/foo.conf
            owner: foo
            group: foo
            mode: u=rw,g=r,o=r
        
        - name: Another symbolic mode example, adding some permissions and removing others
          copy:
            src: /srv/myfiles/foo.conf
            dest: /etc/foo.conf
            owner: foo
            group: foo
            mode: u+rw,g-wx,o-rwx
    6. Roles
      • 재사용 가능한 형태의 Ansible 자원
        (태스크, 핸들러, 변수, 플러그인, 템플릿, 파일)
        예) nginx 롤 : 설치, 설정, 상태 확인 등
        webserver playbook에서 nginx롤을 사용해서 nginx롤을 사용해 설정을 관리
      • 프로젝트 크기가 커질 경우 필수 사용
        Ansible 구성을 체계화 및 모듈화 가능
      • 디렉토리 용도
        • tasks : 실행할 태스크 목록을 관리
        • templates : Jinja2 템플릿 파일 관리
        • defaults : 변수의 기본값을 관리. (재정의 가능)
        • vars : 롤에 사용되는 변수. defaults 변수를 재정의.
        • files : 리모트 서버에 배포할 데이터 파일
      • Role은 Playbook을 통해 호출됨
        → 각 롤의 하위 디렉토리에 있는 main.yml을 실행
    # playbooks
    site.yml
    webservers.yml
    fooservers.yml
    
    # Role 디렉토리 구조 예시
    roles/
        common/               # this hierarchy represents a "role"
            tasks/            #
                main.yml      #  <-- tasks file can include smaller files if warranted
            handlers/         #
                main.yml      #  <-- handlers file
            templates/        #  <-- files for use with the template resource
                ntp.conf.j2   #  <------- templates end in .j2
            files/            #
                bar.txt       #  <-- files for use with the copy resource
                foo.sh        #  <-- script files for use with the script resource
            vars/             #
                main.yml      #  <-- variables associated with this role
            defaults/         #
                main.yml      #  <-- default lower priority variables for this role
            meta/             #
                main.yml      #  <-- role dependencies
            library/          # roles can also include custom modules
            module_utils/     # roles can also include custom module_utils
            lookup_plugins/   # or other types of plugins, like lookup in this case
    
        webtier/              # same kind of structure as "common" was above, done for the webtier role
        monitoring/           # ""
        fooapp/               # ""

    2-3. AWS EC2 서버에 사용자 생성하고 비밀번호로 접속하게 구성하기

    • 기존에는 우분투 이미지일 경우, ubuntu 사용자로 키파일을 이용해 접속해야만 했음
    • test라는 새로운 사용자를 생성하고 비밀번호로 접속하게 구성해보자
    1. 컨트롤 노드 구성 → ansible 명령어 및 AWS 플러그인 설치
    2. 관리할 노드 구성 → 동일한 서버 3대 생성
    3. 동적 인벤토리 구성 → 태그 기반으로 호스트 그룹 구성
    4. 플레이북 구성 → 로그인 유저 생성, sshd 설정 수정, sshd 서비스 재시작
    5. 테스트 → 관리 노드에 신규 유저 및 비밀번호로 접속

    구성도

    • 운영환경에서는 반드시, 형상 관리 도구를 사용해서 SnowFlake 서버가 만들어지지 않도록 주의
    # Ansible cli 도구 설치
    python3 -m pip install --user ansible
    ansible-galaxy collection install amazon.aws
    
    # ansible 실습을 위한 디렉토리 생성
    mkdir ansible_demo
    cd ansible_demo
    
    # ansible 사용자용 키페어 생성
    ssh-keygen -C "ansible ssh key" -q -f ./ansible_key -t rsa -b 2048 -N ""
    
    # AWS 신규 인스턴스 생성 - User Data 사용
    # PublicKeypair 부분은 ansible_key.pub 파일의 전체 내용으로 교체
    Content-Type: multipart/mixed; boundary="//"
    MIME-Version: 1.0
    
    --//
    Content-Type: text/cloud-config; charset="us-ascii"
    MIME-Version: 1.0
    Content-Transfer-Encoding: 7bit
    Content-Disposition: attachment; filename="cloud-config.txt"
    
    #cloud-config
    cloud_final_modules:
    - [users-groups, once]
    users:
      - name: ansible
        groups: [ sudo, adm ]
        sudo: [ "ALL=(ALL) NOPASSWD:ALL" ]
        shell: /bin/bash
        ssh_authorized_keys: 
        - PublicKeypair
        
    # 호스트 파일 생성 및 타겟 호스트 IP 추가
    # vim target_aws_ec2.yaml
    plugin: aws_ec2
    filters:
      instance-state-name: running
    keyed_groups:
      # tag_Name_Value 형식의 그룹을 생성
      - prefix: tag
        key: tags
    
    # ansible 설정 파일 생성
    # vim ansible.cfg
    [defaults]
    inventory = /home/ubuntu/ansible_demo/target_aws_ec2.yaml
    remote_user = ansible
    private_key_file = /home/ubuntu/ansible_demo/ansible_key
    host_key_checking = False
    
    # 타겟 호스트 목록 및 접속 상태 확인
    ansible-inventory --graph
    ansible all -m ping
    
    # 플레이북 작성
    # 새로운 사용자 생성
    # id: test / pwd: 1234qwer
    # 비밀번호 기반 ssh 접속위한 sshd config 수정
    # vim user_mgmt.yaml
    ---
    - name: user module demo
      hosts: tag_Name_ansible_demo
      become: true
      tasks:
        - name: Create a new user 
          ansible.builtin.user:
            name: test
            password: "{{ '1234qwer' | password_hash('sha512') }}"
            groups:
              - adm
              - sudo
            state: "present"
            shell: "/bin/bash"
            system: false
            create_home: true
            home: "/home/test"
            comment: "Ansible demo user"
    
        - name: Enable SSH password authentication
          ansible.builtin.lineinfile:
            path: /etc/ssh/sshd_config
            regexp: '^PasswordAuthentication'
            line: PasswordAuthentication yes
    
        - name: Restart sshd service
          ansible.builtin.service:
            name: sshd
            state: restarted
    
    # 플레이북 실행
    ansible-playbook user_mgmt.yaml
    
    # 비밀번호 기반으로 ec2 호스트 접속
    ssh test@ec2-3-38-165-185.ap-northeast-2.compute.amazonaws.com
    반응형
    댓글