Ansible&Vagrant - 10.13

양승현·2022년 10월 14일
0

Ansible

  • IaC (infrastructure as code)는 수동적으로 인프라를 구성하는 것이 아닌 시스템이 읽을 수 있은 인프라 정의 파일을 통해 인프라의 구성 관리 및 배포를 자동화하는 것이다.
  • 가상화 테스트 환경을 위해 베이그런트를 주로 사용

멱등성

  • 연산을 여러번 적용해도 결과는 변경되지 않는다.
  • 변경된 부분이 있다면 그 그부분만 반영한다.

Iac (선언적 & 절차적)

  • DevOps 도구는 작업을 정의하는 선언적 및 절차적이라는 두 가지 범주로 제공
  • Terraform은 선언적이며, Ansible은 하이브리드
  • 절차적
    • 순서가 있다
  • 선언적
    • 순서가 없다
    • 최종적인 결과가 중요하다 -> depends_on 상태를 보장해준다

inventory file

  • 인벤토리(Inventory)는 관리 노드의 목록으로, 관리 노드에 대한 호스트 이름이나 IP 주소와 같은 정보를 지정
  • 기본 파일은 /etc/ansible/hosts이나, 따로 inventory 파일을 사용할 수 있는 옵션 -i를 줄 수 있다.
  • remote host를 Grouping 할 수 있다.
  • 여러 관리 노드를 그룹으로 조직화 할 수 있고, 중첩 그룹을 사용할 수 있다.

playbook

  • playbook은 ansible의 환경 설정 및 배포를 가능하게 한다.
  • yaml 문법을 사용
  • linux 기반 권한 관리 (user, group)지원
  • 하나의 playbook은 하나 혹은 하나 이상의 play를 가지고 있으며, play의 목적은 여러 호스트들에 잘 정의된 role과 task를 매핑하는 역할을 맡는다.

실습 환경

  • network
    • default 211.183.3.160 nat
    • 외부 연결용 bridge
    • ansible 관리용 사설 네트워크 10.x.x.x

프로비저닝

  • bridge 확인
[root@hypervisor ~]# brctl show

bridge name     bridge id               STP enabled     interfaces
br0             8000.000c294bc79d       no              ens32
virbr0          8000.5254003da230       yes             virbr0-nic
  • Vagrantfile
Vagrantfile

# -*- mode: ruby -*-
# vi: set ft=ruby :

Vagrant.configure("2") do |config|
  config.vm.define "control" do |cfg|
    cfg.vm.box = "generic/ubuntu2004"
    cfg.vm.provider :libvirt do |resource|
      resource.cpus = 4
      resource.memory = 4096
    end
    cfg.vm.host_name = "control"
    cfg.vm.network "public_network", :dev => "br0",  :type =>"bridge", ip: "211.183.3.166"
    cfg.vm.network "private_network", ip: "10.10.10.10"
    cfg.vm.network "forwarded_port", guest: 22, host: 20010, id: "ssh"
    # 앤서블 설치와 개인키 추가
    cfg.vm.provision "shell", inline: "apt-get -y install ansible"
    cfg.vm.provision "file", source: "mykey.pem", destination: "/home/vagrant/.ssh/id_rsa"
    cfg.vm.provision "shell", inline: "chmod 600 /home/vagrant/.ssh/id_rsa"
    # ssh-keyscan 을 통한 노드등록
    cfg.vm.provision "shell", inline: "ssh-keyscan 10.10.10.11 >> /home/vagrant/.ssh/known_hosts"
    cfg.vm.provision "shell", inline: "ssh-keyscan 10.10.10.12 >> /home/vagrant/.ssh/known_hosts"
    cfg.vm.provision "shell", inline: "ssh-keyscan 10.10.10.13 >> /home/vagrant/.ssh/known_hosts"
    cfg.vm.provision "shell", inline: "ssh-keyscan 10.10.10.14 >> /home/vagrant/.ssh/known_hosts"
    cfg.vm.provision "shell", inline: "ssh-keyscan 10.10.10.15 >> /home/vagrant/.ssh/known_hosts"
    cfg.vm.provision "shell", inline: "chown vagrant.vagrant /home/vagrant/.ssh/known_hosts"
  end

  config.vm.define "node1" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.host_name = "node1"
    cfg.vm.network "public_network", :dev => "br0",  :type =>"bridge", ip: "211.183.3.161"
    cfg.vm.network "private_network", ip: "10.10.10.11"
    cfg.vm.network "forwarded_port", guest: 22, host: 20011, id: "ssh"
    # 공개키 등록
    cfg.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub"
    cfg.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys"
  end

  config.vm.define "node2" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.host_name = "node2"
    cfg.vm.network "public_network", :dev => "br0",  :type =>"bridge", ip: "211.183.3.162"
    cfg.vm.network "private_network", ip: "10.10.10.12"
    cfg.vm.network "forwarded_port", guest: 22, host: 20012, id: "ssh"
    # 공개키 등록
    cfg.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub"
    cfg.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys"
  end

  config.vm.define "node3" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.host_name = "node3"
    cfg.vm.network "public_network", :dev => "br0",  :type =>"bridge", ip: "211.183.3.163"
    cfg.vm.network "private_network", ip: "10.10.10.13"
    cfg.vm.network "forwarded_port", guest: 22, host: 20013, id: "ssh"
    # 공개키 등록
    cfg.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub"
    cfg.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys"
  end

  config.vm.define "node4" do |cfg|
    cfg.vm.box = "generic/ubuntu2004"
    cfg.vm.host_name = "ubuntu1"
    cfg.vm.network "public_network", :dev => "br0", :type => "bridge", ip: "211.183.3.164"
    cfg.vm.network "forwarded_port", guest: 22, host: 20014, id: "ssh"
    cfg.vm.network "private_network", ip: "10.10.10.14"
    # 공개키 등록
    cfg.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub"
    cfg.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys"
  end

  config.vm.define "node5" do |cfg|
    cfg.vm.box = "generic/ubuntu2004"
    cfg.vm.host_name = "ubuntu2"
    cfg.vm.network "public_network", :dev => "br0", :type => "bridge", ip: "211.183.3.165"
    cfg.vm.network "forwarded_port", guest: 22, host: 20015, id: "ssh"
    cfg.vm.network "private_network", ip: "10.10.10.15"
    # 공개키 등록
    cfg.vm.provision "file", source: "mykey.pem.pub", destination: "/home/vagrant/.ssh/mykey.pem.pub"
    cfg.vm.provision "shell", inline: "cat /home/vagrant/.ssh/mykey.pem.pub >> /home/vagrant/.ssh/authorized_keys"
  end
end
  • 실행
vagrant up
  • 생성 확인

- 서버 실행
vagrant up
- 서버 중지
vagrant halt <서버 이름>
- 서버 삭제
vagrant destroy <서버 이름>
- 서버 접속
vagrant ssh <서버 이름>
- 서버 재실행
vagrant reload
- 호스트 네임 변경
sudo vi /etc/hostname
- ssh 정보 확인
vagrant ssh-config <서버 이름>

Ansible Inventory 구성

  • contorl node 접속
vagrant ssh control
  • hosts 파일 수정
sudo vi /etc/ansible/hosts

[centos]
centos1 ansible_host=10.10.10.11
centos2 ansible_host=10.10.10.12
centos3 ansible_host=10.10.10.13

[ubuntu]
ubuntu1 ansible_host=10.10.10.14
ubuntu2 ansible_host=10.10.10.15

[east]
centos1
centos2
ubuntu1

[west]
centos3
ubuntu2

Facts

ansible localhost -m setup
  • setup 모듈을 통해 해당 Node의 facts 확인 가능
  • 사용중인 OS, 패키지 매니저 등

tasks

  • installnginx.yaml
---
- name: install nginx
  hosts: all
  become: yes

  tasks:
# setup 에 있는 정보중에 ansible_distribution 변수를 찾고, 그 밑의 ansible_pkg_mgr을 찾는다.
# {{}} 중괄호로 변수를 감싸면, 엔서블 실행시 값으로 변경됌
#  epel 설치
    - name: epel
      action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"
      when: ansible_distribution == 'CentOS'
#  nginx 설치
    - name: install web server
      action: "{{ ansible_pkg_mgr }} name=nginx state=present"
      when: ansible_distribution == 'CentOS'
#  index.html 파일 업로드
    - name: upload index.html
      get_url: url=https://www.nginx.com dest=/usr/share/nginx/html mode=0644
      when: ansible_distribution == 'CentOS'
#  nginx 실행
    - name: start nginx
      service: name=nginx state=started
      when: ansible_distribution == 'CentOS'
# -------
#  nginx 설치
    - name: install nginx on ubuntu
      action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
      when: ansible_distribution == 'Ubuntu'
#  index.html 파일 업로드
    - name: upload index.html
      get_url: url=https://www.nginx.com dest=/var/www/html/
               mode=0644 validate_certs=no
      when: ansible_distribution == 'Ubuntu'
  • 파일 실행
ansible-playbook installnginx.yaml
  • action에서 {{ ansible_pkg_mgr }}는 각 Node 의 facts 에서 패키지 매니저를 의미한다.
CentOS -> yum
Ubuntu -> apt 
  • when 을 통해 각 OS 를 구분하여, 각 OS에 맞는 작업을 전달하기 때문에 각 Node 별로 skip 이 많이 발생한다.

Task를 사용하여 skip 줄이기

  • when 조건 확인하는 경우를 줄여 skip 발생을 줄여보자
  • 먼저 OS 별로 작업 파일을 나누고 task 파일을 생성하여 실행 시킨다.
  • CentOS
vagrant@control:~$ cat centos.yaml
- name: epel
  action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"

- name: install web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present"

- name: upload index.html
  get_url: url=https://www.nginx.com dest=/usr/share/nginx/html mode=0644

- name: start nginx
  service: name=nginx state=started
  • Ubuntu
vagrant@control:~$ cat ubuntu.yaml
- name: install nginx on ubuntu
  action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"

- name: upload index.html
  get_url: url=https://www.nginx.com dest=/var/www/html/
           mode=0644 validate_certs=no
  • task 파일 구성
vagrant@control:~$ cat installnginx_include_task.yaml
---
- name: install nginx using include_tasks
  hosts: all
  become: yes

  tasks:
    - name: centos
      include_tasks: centos.yaml
      when: ansible_distribution == 'CentOS'

    - name: ubuntu
      include_tasks: ubuntu.yaml
      when: ansible_distribution == 'Ubuntu'
ansible-playbook installnginx_include_task.yaml
  • 이전 작업은 조건을 5번 확인하며, 현 조건은 두번만 확인하게 된다.

remove

  • removenginx.yaml
---
- name: remove nginx
  hosts: all
  become: yes

  tasks:
    - name: remove nginx
      yum:
        name: ['epel-release', 'nginx']
        state: absent
      when: ansible_distribution == 'CentOS'

    - name: remove nginx on ubuntu
      apt:
        name: nginx
        state: absent
        autoremove: true
      when: ansible_distribution == 'Ubuntu'
  • 삭제

vars & if

  • installnginx_using_if.yaml
---
- name: install nginx using if
  hosts: all
  become: yes
  vars:
    dict: "{{ 'centos' if ansible_distribution == 'CentOS'
               else 'ubuntu' if ansible_distribution == 'Ubuntu'
               else 'linux'
           }}"

  tasks:
   - name: file selection
     include_tasks: "{{ dict }}.yaml"

quiz

    1. 직전 실행했던 파일의 결과를 확인하고 정상적으로 설치가 되었다면 웹을 통해 확인하기
    1. "1"에 문제가 없다면 removenginx.yaml 실행하기
    1. if 파일에 handler를 적용하여 각 노드에서 nginx가 설치된 뒤 어떤 버전인지 여부를 debug로 출력 시켜주세요
  • 주의해야 할 점 centos, ubuntu에서 공통적으로 nginx의 버전을 확인 할 수 있는 명령은??
  • installnginx_using_if.yaml
---
- name: install nginx using if
  hosts: all
  become: yes
  vars:
    dict: "{{ 'centos' if ansible_distribution == 'CentOS'
               else 'ubuntu' if ansible_distribution == 'Ubuntu'
               else 'linux'
           }}"

  tasks:
     - name: file selection
       include_tasks: "{{dict}}.yaml"

  handlers:
     - name: trigger
       shell: nginx -v
       register: resulth
       notify:
         - result

     - name: result
       debug:
         var: resulth
  • cat ubuntu.yaml
- name: install nginx on ubuntu
  action: "{{ ansible_pkg_mgr }} name=nginx state=present update_cache=yes"
  notify:
    - trigger

- name: upload index.html
  get_url: url=https://www.nginx.com dest=/var/www/html/
           mode=0644 validate_certs=no
  • cat centos.yaml
- name: epel
  action: "{{ ansible_pkg_mgr }} name=epel-release state=latest"

- name: install web server
  action: "{{ ansible_pkg_mgr }} name=nginx state=present"
  notify:
    - trigger

- name: upload index.html
  get_url: url=https://www.nginx.com dest=/usr/share/nginx/html mode=0644

- name: start nginx
  service: name=nginx state=started
  • changed 하게 되면 notify에 명시된 handler를 실행시킨다.
  • handler 에서는 script을 통해 nginx의 버전을 resulth에 담고 notify를 통해 debug 를 실행하여 버전을 출력 한다.

0개의 댓글