ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Ansible] 시스템 구축 및 환경 설정 자동화(스터디 3주차)
    Infra/Cloud 2024. 1. 31. 12:00

    3주차는 지금까지 배운 Ansible의 anisble-galaxy, playbook, role, module 등을 이용해 직접 환경구축 및 테스트를 진행했다.

    따라서 이번 포스팅에서는 별도로 개념이 추가된 것이 아니므로 활용에 관련된 도전과제만 작성해보았다.

     


     

    # 도전과제1

    * ansible-vault 사용시, AWS SecretManager를 활용해보기

     

    - 우선 ansible-vault  create를 통해 암호화할 파일(user_secrert.yml)을 생성한다.

    - 나의 경우 파일 암호화에 쓰일 패스워드를 'Password123'으로 했다.

    # user_secret.yml
    ---
    
    user_info:
      - userid: "ansible"
        userpw: "ansiblePw1"
      - userid: "stack"
        userpw: "stackPw1"

    => 해당 파일이 ansible-vault에 의해 암호화 된 것을 확인할 수 있었다.

     

     

     

    - Playbook 생성

    ---
    
    - hosts: all
    
      # vault로 사용자 계정 관련 변수가 정의된 파일을 임포트하여 사용
      vars_files:
        - user_secret.yml
    
      tasks:
      # loop 문을 사용하여 user_info의 userid와 userpw 사용
      - name: Create user
        ansible.builtin.user:
          name: "{{ item.userid }}"
          password: "{{ item.userpw | password_hash('sha512', 'mysecret') }}"
          state: present
          shell: /bin/bash
        loop: "{{ user_info }}"

    => 위에서 암호화한 파일의 user id,pw 정보로 계정을 생성하는 Playbook이다.

     

     

     

    - ansible-vault encrypt 파일 사용 시, playbook 실행방법

    ansible-playbook create-user.yaml --ask-vault-pass

    => 해당 방법은 파일암호화에 사용된 패스워드를 입력하는 옵션인 '--ask-vault-pass'를 사용한 것이다. 하지만 이 방법은 파이프라인 구성이나 자동화 스트립트 등에 사용 시에는 제약이 따라온다. 이를 해결하는 방법은 '--vault-password-file' 옵션을 통해 파일 암호화에 사용된 패스워드를 파일에 작성하여 사용하는 것이다. 

     

     

    AWS Secret Manager

    - 하지만  '--vault-password-file' 을 사용하는 방법 역시, 해당 복호화 키 파일의 유출 가능성이 존재하므로 안전한 저장소에서 관리하는 것이 더욱 좋다. 그래서 사용할 수 있는 방법중 하나가 바로 AWS Secret Manager이다.

     

     

    - aws secretmanager를 통한 secret 생성

    cat  << EOF > secret.json
    {
        "password": "Password123"
    }
    EOF
    aws secretsmanager create-secret --name  secret-file --secret-string file://secret.json --region ap-northeast-2

    => secret.json에 암호화에 사용될 Key-value 값을 작성한 뒤 해당파일을 인자로 create-secret을 진행하였다.

     

     

     

    - 존재하는 Secret name 확인

    aws secretsmanager list-secrets --region ap-northeast-2 | jq -r .SecretList[].Name

    => aws-cli나 GUI를 통해 내가 저장한 Secret value를 확인할 수 있었다. 이제 해당 secret을 암호화키로 사용해보자.

     

     

     

    - aws secretmanager value 사용

    aws secretsmanager get-secret-value --secret-id secret-file --region ap-northeast-2 | jq -r '.SecretString | fromjson | .password'
    cat > get-secret.sh << EOF
    #!/bin/bash
    aws secretsmanager get-secret-value --secret-id secret-file --region ap-northeast-2 | jq -r '.SecretString | fromjson | .password'
    EOF
    
    chmod +x get-secrets.sh
    ansible-playbook  create-user.yaml --vault-password-file ./get-secret.sh

    => shellscript를 파일로 작성해서 --vault-password-file 인자로 넣어주는 방법 외에 다른 여러 방법으로 시도해보았지만 내가 못하는건지 안되는 것 같다(아시는분 댓글 부탁드립니다)

     

     

     

    - 계정 생성 확인

    for i in {1..3}; do ssh ubuntu@tnode$i tail -n 2 /etc/passwd; echo;done

    => 정상적으로 생성된 것을 확인할 수 있었다.

     

     


     

    # 도전과제2

    * Lookups 플러그인을 활용한 playbook를 직접 작성

     

    Lookups — Ansible Documentation

    Lookups Lookup plugins retrieve data from outside sources such as files, databases, key/value stores, APIs, and other services. Like all templating, lookups execute and are evaluated on the Ansible control machine. Ansible makes the data returned by a look

    docs.ansible.com

    => lookup 플러그인은 playbook 내에서 외부 소스(file, db, key/value stores, APIs 등)에 접근하여 그 내용을 playbook내로 가져와서 사용할 수 있게 해주는 역할을 한다(Jinja2 템플릿 언어에 대한 Ansible 전용 확장 기능)

     

     

     

    -  랜덤패스워드(문자,숫자,특수문자 3가지조합 + 10자리)를 가진 계정을 생성하는 playbook

    ---
    - hosts: all
      tasks:
        - name: Generate and encrypt password
          set_fact:
            encrypted_password: "{{ lookup('ansible.builtin.password', '/home/ubuntu/my-ansible/pw.txt', chars=['ascii_letters', 'digits', 'punctuation'], length=10) | password_hash('sha512') }}"
    
        - name: Create user with encrypted password
          ansible.builtin.user:
            name: tmp_user
            comment: temp user
            shell: /bin/bash
            state: present # 삭제시 absent 사용
            password: "{{ encrypted_password }}"
          register: user_creation_result
    
        - name: Show generated password
          debug:
            var: user_creation_result.ansible_facts.user_password

    => playbook 내에 작성한 것과 같이 10자리의 랜덤패스워드가로 tmp_user가 생성되었고 해당 패스워드는 pw.txt 파일에서 확인할 수 있었다.

     


     

    # 도전과제 3

    * Ubuntu 와 CentOS에 apache http를 설치하는 playbook을 작성(롤/템플릿 사용은 편한대로)

    => centos에도 제대로 동작되는지 확인하기 위해 tnode4를 centos를 생성해주고 /etc/hosts와 inventory 파일에 내용을 추가해주었다. 해당 AMI의 경우 AWS marketplace를 통해 생성했다(실습 후 marketplace 구독취소를 해주었다)

     

     

    # Roles(apache.http) 생성 및 정보

    ansible-galaxy init --init-path ./roles apache.http

     

     

    - handlers/main.yml

    ---
    # handlers file for apache.http
    
    - name: Start httpd 
      ansible.builtin.service:
        name: httpd
        state: started

     

     

    - tasks/main.yml

    ---
    # tasks file for apache.http
    
    - name: Import playbook
      ansible.builtin.include_tasks:
        file: "{{ ansible_facts.distribution }}.yml"
    
    - name: Copy index file when Ubuntu
      ansible.builtin.template:
        src: modify.html
        dest: /var/www/html/index.html
      when: ansible_facts.distribution == "Ubuntu"
    
    - name: Copy index file when CentOS
      ansible.builtin.template:
        src: modify.html
        dest: /var/www/html/index.html
      when: ansible_facts.distribution == "CentOS"

     

     

    - tasks/CentOS.yml

    ---
    
    - name: Install the latest version of Apache in CentOS
      ansible.builtin.yum:
        name: httpd
        state: present
      notify: Start httpd  
      #when: ansible_facts.distribution == "CentOS"

     

     

     

    - tasks/Ubuntu.yml

    ---
    
    - name: Install the latest version of Apache in Ubuntu
      ansible.builtin.apt:
        name: apache2
        state: present
      #when: ansible_facts.distribution == "Ubuntu"

     

     

    - templetes/modify.html

    <h1> This is Apache server!! </h1>

     

     

    - playbook.yml

    ---
    
    - hosts: tnode
      roles:
        - role: apache.http

    => playbook 실행결과 ubuntu, centos에 따라 상이하게 apt, yum으로 apache, httpd package가 설치되었다(해당되지 않는 경우 skip됨을 알 수 있음). 상이하게 적용한 점은 ubuntu의 경우 자동으로 apache service가 실행되었으나 centos의 경우 service를 직접 실행해주어야했으므로 handler를 통해 serivce를 start 시켜주었다.

     

     

    - 서비스 정상 실행 확인

    for i in {1..4}; do ssh tnode$i 'hostname;curl -s 127.0.0.1';echo; done

    => 모든 관리노드에서 설정한 templates/modify.html 내용으로 service가 실행중임을 확인할 수 있었다.

     

     


     

    # 도전과제4

    * Jinja2 템플릿을 활용한 예시 playbook를 구글링하여 실습 환경에 맞게 구성(내용 추가 및 수정 중)

    ansible-galaxy role init --init-path ./roles myrole.nginx

     

     

    - handlers/main.yml

    ---
    # handlers file for myrole.nginx
    
    - name: Reload daemon
      systemd:
        daemon_reload: yes
    - name: Restart nginx
      service:
        name: nginx
        state: restarted

     

     

    - template/nginx.conf.j2

    user www-data;
    worker_processes auto;
    pid /run/nginx.pid;
    include /etc/nginx/modules-enabled/*.conf;
    
    events {
        worker_connections 1024;  
    }
    
    http {
        sendfile on;
        #tcp_nopush on;
        #tcp_nodelay on;
        keepalive_timeout 65;
    
        include /etc/nginx/mime.types;
        default_type application/octet-stream;
    
        access_log /var/log/nginx/access.log;
        error_log /var/log/nginx/error.log;
    
        #gzip on;
    
        server {
            listen 80 default_server;
            listen [::]:80 default_server;
            
            root /var/www/html;
            index index.html index.htm;
            
            server_name _;
            
            location / {
                try_files $uri $uri/ =404;
            }
        }
    }

     

     

    - var/main.yml

    ---
    # vars file for myrole.nginx
    user: imyoungho

     

     

    - tasks/main.yml

    ---
    # tasks file for myrole.nginx
    
    - name: apt update
      apt:
        update_cache: yes
    
    - name: Add User for Nginx
      user:
        name: "{{ user }}"
        shell: /bin/bash
        home: /home/{{ user }}
        createhome: yes
    
    - name: Install Nginx
      apt:
        name: nginx
        state: present
    
    - name: Copy Nginx Configuration
      template:
        src: nginx.conf.j2
        dest: /etc/nginx/nginx.conf
      notify:
        - Reload daemon
        - Restart nginx

     

     

    - playbook file(install_nginx.yml)

    ---
          
    - hosts: tnode3
      vars_files:
        - vars/main.yml
      roles:
        - role: myrole.nginx
          become: yes

     

     


     

    # 도전과제5

    * file과 lineinfile 모듈을 활용하여 /tmp/test.txt 파일을 생성하고 hello 문자열을 추가하는 playbook 작성

     

     

    - work.yml

    ---
    
    - hosts: all
      vars_files: var.yml
    
      tasks: 
      - name: Create file
        ansible.builtin.file:
          path: "{{ item.filepath }}"
          owner: "{{ item.own }}"
          group: "{{ item.own }}"
          mode: "{{ item.permit }}"
          state: touch
        loop: "{{ fileinfo }}"
    
      - name: Write String in file
        ansible.builtin.lineinfile:
          path: "{{ item.filepath }}"
          line: "{{ item.string }}"
        loop: "{{ fileinfo }}"

     

     

    - var.yml

    fileinfo:
      - string: hello
        own: ubuntu
        filepath: /tmp/test.txt
        permit: 644
        
      - string: byebye
        own: ubuntu
        filepath: /tmp/test2.txt
        permit: 644

     

     

    - 결과

    for i in {1..3}; do ssh tnode1 ls /tmp/*.txt;echo; done
    for i in {1..3}; do ssh tnode1 cat /tmp/*.txt;echo; done

     


    # 도전과제6

    * 앤서블 갤럭시에서 PostgreSQL 설치하는 롤을 검색하여, 해당 롤을 통해 tnode3에 설치

     

    Ansible Galaxy

     

    galaxy.ansible.com

     

    * postgreSQL role install

    - ansible.cfg file

    [defaults]
    inventory = ./inventory
    remote_user = ubuntu
    ask_pass = false
    roles_path = ./roles
    
    [privilege_escalation]
    become = true
    become_method = sudo
    become_user = root
    become_ask_pass = false

     

     

    - inventory file

    [db]
    tnode3
    
    [tnode]
    tnode1
    tnode2
    tnode3

     

     

    - ansible-galaxy를 통한 role install

     

    Ansible Galaxy

     

    galaxy.ansible.com

    ansible-galaxy role install geerlingguy.postgresql

     

     

     

    - playbook file (install_postgresql.yml)

    - hosts: tnode3
      vars_files:
        - vars/main.yml
      roles:
        - role: geerlingguy.postgresql
          become: yes

     

     

    - var/main.yml

    postgresql_databases:
      - name: imyoungho_db
    postgresql_users:
      - name: imyoungho
        password: qwe123

     

     

    * playbook 실행

    ansible-playbook install_postgresql.yml

     

     

    - postgreSQL 접속

    psql -U imyoungho -d imyoungho_db -h localhost -p 5432

    => tnode3에 위에서 설정한 var/main.yml 설정으로 postgresql이 구축되었으며 정상적으로 접속까지 가능한 것을 확인할 수 있었다.

    반응형

    댓글

Designed by Tistory.