본문 바로가기
Development(Web, Server, Cloud)/22) LINUX - Cloud

클라우드 71일차

by tonyhan18 2022. 5. 9.
728x90

ansible 서버가 노드들에게 docker 을 설치하라는 playbook을 만들어서 전달하게 된다. 그런데 node 들 별로 배포판 정보가 다른것이다.

 

그러면 모든 node에서 설치가 안될 수 있다. 왜냐하면 명령어가 다르기 때문이다.

 

그래도 다양한 서비스를 받아들이기 위해서는 각 조건에 맞는 환경을 구축해주어야 한다.

그리고 각 환경에 따른 파일을 나누어 주어야 한다.

1. 재사용성

2. 개발용의(협업)

두가지 장점이 있기 때문이다.

개발시 파일을 나누게 되면 main.yaml을 기반으로 나누어서 개발이 가능해지기 때문에 협업이 가능하게 된다.

또 파일별로 CI/CD 가 가능해진다는 장점도 존재한다.

 

---

vagrant init 을 하면 로컬 저장소/Vagrantfile가 생성된다 (.vagrant 를 이용하여 버전관리 할 수 있는 준비가 된 상태)

 

Vagrantfile을 작성 또는 수정 -> vagrant up (서버 또는 가상 디바이스 들의 환경배포) -> 가상머신 들에게 추가적으로 필요한 작업 진행(패키지 설치, 파일/디렉토리 생성/복사, 파일에 특정 내용 삽입, 서비스의 실행, 주로 쉘의 실행)을 하고 싶다면 provision을 진행한다.

-> vagrant provision을 실행(provision이 부착된 라인만 추가 실행 됨) 이전에 프로비전을 실행했고 추가적으로 필요하지 않다면 주석처리를 권장

 

hosts: localhost 는 작업대상을 의미한다. 작업대상은 인벤토리 파일에 의존한다. 즉 인벤토리 파일에 의해서 작업대상을 지정할 수 있다. localhost는 자기자신만을 의미하게된다.(기본 인벤토리 파일 /etc/ansible/hosts)(혹은 lst를 만들어서 ansible-playbook -i a.lst 로 리스트를 지정해줄 수도 있다.)

 

```

vagrant ssh ansible-server

ansible all -m setup > info.txt

```

가저온 정보를 보면 CentOS, 버전, DNS 정보등을 볼 수 있다.

 

연결된 ip 정보도 볼 수 있다.

 

어떤 OS인지도 확인이 가능하다.

 

이걸 이용해서 OS 별로 다른 ansible-playbook 파일을 만들 수 있다.

 

---
- name: test configuration
  hosts: localhost
  gather_facts: no

  tasks:
    - name: install git
      yum:
        name: git
        state: present

    - name: install httpd
      yum:
        name: httpd
        state: present

    - name: start httpd
      service:
        name: httpd
        state: started

    - name: stop firewalld
      service:
        name: firewalld
        state: stopped
    - name: creating index.html
      get_url: url=https://www.naver.com dest=/var/www/html/index.html

이제 test.yaml 파일을 이용해서 페이지까지 띄워보자

이때 gather_facts: no로 하는 이유는 두가지

1. python이 설치되지 않은 환경이거나

2. 구지 정보를 수집해서 시간이 걸리도록 하지 않기 위한 경우

 

get_url은 curl을 이용하여 index.html 파일을 생성하는 모듈.

 

이렇게하면 `https://www.naver.com`의 내용이 index.html로 옮겨가게 된다.

 

---

 

추가적인 ansible module 들을 확인해보자

All modules — Ansible Documentation

 

All modules — Ansible Documentation

 

docs.ansible.com

shell은 원격지에서 명령을 실행하라는 모듈이다.

 

args를 사용해 chdir를 사용하면 soomedir directory를 변경한다음 soomedir에 있는 somescript.sh을 사용하라는 의미가 된다.

 

쉘 모듈: 멱등성을 보장하지 않는다. 기존 내용을 덮어쓰기 할 수 있다.

- name:

  shell: 실행할 명령

 

replace 모듈 : 파일 내용 변경하기 (sed를 대체)

- name: test

  replace:

    path: /etc/test/test.txt

    regexp: 'hello'

    replace: 'hi'

-> 노드에 전달할 때에는 sed -i 's/hello/hi/' /etc/test/test.txt

 

변수 활용하기

- hosts: loc

  tasks:

  - name: ANsible shell module multiple commands

    shell: "cat {{ item }} | grep ansible"

    with_items:

      - hello.txt

      - hello2.txt

      - hello3.txt

    args:

      chdir: /root/ansible

위와 같이 with_items 내에 있는 것들을 shell을 통해 하나씩 실행해보겠다는 의미가 된다.

보통 변수명으로 item이라고 쓰게 된다.

 

-> 작업시 먼저 /root/ansible 디렉토리로 이동하여

cat hello.txt | grep ansible 이 끝나면 cat hello2.txt로 작업이 진행된다.

 

서비스 모듈 : service

- name: test

  service:

    name: sshed

    state: restarted/started

    enabled: yes == systemctl enable sshd

 

file 모듈 (파일/디렉토리 만들기, 속성변경, hard/soft link 생성도 가능)

- name: test

  file:

    path: /home/vagrant/test

    state: touch(파일생성)/directory/absent(삭제)/file(이미 있는 파일 속성 변경)/hard(하드 링크)/link(소프트 링크)

    mode: 0777

 

lineinfile : 특정 파일내 필요한 내용을 덧붙이기한다.

- name: test

  lineinfile: 

    path: /etc/test.txt

    line: "hello all"

 

만약 덧붙일 내용이 여러줄이라면?

- name: test

  lineinfile:

    path: /etc/test.txt

    line: "{{ item }}"

  with_items:

    - "hello gildong"

    - "hello sunhee"

    - "hello minsoo"

*그래서 line은 for과 비슷하다.

 

blockinfile

여러줄을 덧붙이는 방법으로 blockinfile도 있다. 둘 사이의 차이점은 blockinfile은 전체를 통으로 옮겨서 작성한다.

- name: test

  blockinfile:

    path: /etc/test.txt

    block: |

      [friends]

      gildong

      chulsoo

 

얘는 한번에 정보가 가버린다.

 

여러줄을 작성할 때에는 지정된 변수인 item을 사용해야한다. 하지만 별도로 지정한 변수를 사용하고자 한다면 다음과 같은 방법을 이용할 수 있다.

 

- name: test

  hosts: all

  gather_facts: yes

  vars:

    test_shell:

      - "hostname &&"

      - date

  tasks:

    - name:

      shell: "{{ test_shell }}"

 

이렇게하면 hostname과 date가 함께 실행된다.

 

SELINUX 사용하기, 기본적으로 실행중이다.

- name: disable selinux

  selinux:

    state: disabled  # 비 활성화 된다.

 

---

 

리소스를 바꾸고 싶은경우가 있을 수 있다. 일단 위의 방법은 잘 안된다.

 

그래서 권하는게 위와같이 작성해주는 방법이다.

resource는 임의로 적는거니 원하는걸로 작성해주어도 된다.

 

---

 

클라이언트의 ssh 연결/설정 파일은 /etc/ssh/sshd_config 파일을 확인해보면 된다.

 

ansible-server 에서 노드의 퍼블릭키를 수집하기 위하여 ssh-keyscan도 이미 실행한 상태이다.

 

---

플레이북

한개의 playbook으로 nginx 배포하기

 

 

---
- name: httpd installation
  hosts: all
  gather_facts: no

  tasks:
    - name: SELINUX disabled
      become: yes
      replace:
        path: /etc/selinux/config
        regexp: 'SELINUX=enforcing'
        replace: 'SELINUX=disabled'

    - name: DIRECTORY CREATION
      file:
        path: /home/vagrant/testdir
        state: directory

    - name: libselinux-python install
      become: yes
      yum:
        name: libselinux-python
        state: present

    - name: httpd install
      become: yes
      yum:
        name: httpd
        state: present

    - name: index.html creation
      become: yes
      get_url: url=https://www.nginx.com dest=/var/www/html/index.html

    - name: start httpd
      become: yes
      service:
        name: httpd
        state: started
        enabled: true

    - name: stop firewalld
      become: yes
      service:
        name: firewalld
        state: stopped
        enabled: false

httpdinstall.yaml 을 이용해서 nginx 홈페이지를 배포해보자

 

```

ansible-playbook httpdinstall.yaml -k

```

 

---

nfs를 설치해보자

- name : NFS CLIENT

  hosts: centos

  gather_facts: no

  tasks:

 

클라이언트는 로컬에 (/home/vagrant 아래에) remote 라는 디렉토리를 생성하고 nfs 서버의 172.16.1.10:/home/vagrant/shared를 remote와 마운트 시킨다. 

 

---
- name: NFS SERVER
  hosts: localhost
  gather_facts: no

  tasks:
    - name: DIR creation
      file:
        path: /home/vagrant/shared
        state: directory
        mode: 0777

    - name: installation nfs server
      become: yes
      yum:
        name: nfs-utils
        state: present

    - name: configuring /etc/exports
      become: yes
      lineinfile:
        path: /etc/exports
        line: /home/vagrant/shared 172.16.1.0/24(rw,sync)

    - name: start nfs server
      become: yes
      service:
        name: nfs-server
        state: restarted

    - name: stop firewalld
      become: yes
      service:
        name: firewalld
        state: stopped
        enabled: false

- name: setup nfs client
  hosts: all  # /etc/ansible/hosts (주체 : 노드)
  gather_facts: yes
# 정보수집을 먼저 거치기

  tasks:
    - name: make nfs_client directory
      file:
        path: "{{ ansible_user_dir }}/remote"
        state: directory
        # 받아온 정보를 보면 ansible_user_dir = /home/vagrant 이다
        # 여기가 home dir이라서 위와같이 작성해주었다.

    - name: mount
      become: yes
      mount:
        path: "{{ ansible_user_dir}}remote"
        src: 172.16.1.10:/home/vagrant/shared   # server [nfs-server]
        fstype: nfs
        opts: nfsvers=3  # nfs 버전, 일반적으로 4
        state: mounted

vi nfsconfiguration.yaml

 

파일을 열어서 위와같이 작성해주면된다.

 

위와같이 nfs 가 공유된것을 확인할 수 있다.

 

추가적으로 우분투를 추가해보자

이를 위해 노드에서 나와서 master에서 Vagrantfile을 만져야한다.

이렇게 작성해주었다. 바뀐 부분이 많기 때문에 그냥 다 지우고 코드를 복붙해주자

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

###### ANSIBLE NODE 1~3 ######
Vagrant.configure("2") do |config|
  config.vm.define "ansible-ubuntu1" do |cfg|
    cfg.vm.box = "generic/ubuntu1804"
    cfg.vm.host_name = "ansible-ubuntu1"
    cfg.vm.network "private_network", ip: "172.16.1.14"
    cfg.vm.network "forwarded_port", guest: 22, host: 60014, auto_correct: true, id: "ssh"
    cfg.vm.provider :libvirtd do |cpuram|
      cpuram.memory = 1024
      cpuram.cpus = 1
      end
    end

  config.vm.define "ansible-node1" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.host_name = "ansible-node1"
    cfg.vm.network "private_network", ip: "172.16.1.11"
    cfg.vm.network "forwarded_port", guest: 22, host: 60011, auto_correct: true, id: "ssh"
    # cfg.vm.provision "file", source: "auth.sh", destination: "auth.sh"
    # cfg.vm.provision "shell", inline: "/bin/bash auth.sh",privileged: true
    end

  config.vm.define "ansible-node2" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.host_name = "ansible-node2"
    cfg.vm.network "private_network", ip: "172.16.1.12"
    cfg.vm.network "forwarded_port", guest: 22, host: 60012, auto_correct: true, id: "ssh"
    # cfg.vm.provision "file", source: "auth.sh", destination: "auth.sh"
    # cfg.vm.provision "shell", inline: "/bin/bash auth.sh",privileged: true
    end

  config.vm.define "ansible-node3" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.host_name = "ansible-node3"
    cfg.vm.network "private_network", ip: "172.16.1.13"
    cfg.vm.network "forwarded_port", guest: 22, host: 60013, auto_correct: true, id: "ssh"
    # cfg.vm.provision "file", source: "auth.sh", destination: "auth.sh"
    # cfg.vm.provision "shell", inline: "/bin/bash auth.sh",privileged: true
    end
end

###### ANSIBLE SERVER CONFIG #######
Vagrant.configure("2") do |config|
  config.vm.define "ansible-server" do |cfg|
    cfg.vm.box = "centos/7"
    cfg.vm.host_name = "ansible-server"
    cfg.vm.network "private_network", ip: "172.16.1.10"
    cfg.vm.network "forwarded_port", guest: 22, host: 60010, auto_correct: true, id: 'ssh'
    #cfg.vm.provision "shell", inline: "yum -y install epel-release"
    #cfg.vm.provision "shell", inline: "yum -y install ansible"
    #cfg.vm.provision "file", source: "test.yml", destination: "test.yml"
    #cfg.vm.provision "shell", inline: "ansible-playbook test.yml"
    cfg.vm.provider :libvirt do |resource|
      resource.memory = 2048
      resource.cpus = 2
    end
  end
end

```

vagrant up

```

완성되었다.

 

wok에서도 확인가능하다.

 

ubuntu라는 것도 추가해주자

 

물론 ansible을 등록할때 이런 방식으로 OS를 기준으로 나누면 안되지만... 뭐 암튼 프로젝트를 해야하니까

 

잘 갔다오는 것을 확인할 수 있다.

 

---
- name: print distribution, pkg mgr
  hosts: all
  gather_facts: yes

  tasks:
    - name: debugging
      debug:
        msg:
          - "호스트네임 : {{ ansible_hostname }}"
          - "배포판: {{ ansible_distribution }}"
          - "패키지 매니저 : {{ ansible_pkg_mgr }}"
          - "사설 인터페이스 주소 : {{ ansible_eth1.ipv4.address }}"

getinfo.yaml을 작성해주자

 

그러면 위와같이 정보가 온 것을 볼 수 있다.

 

그래서 이 정보를 끌고와서 사용하는 것도 가능하다.

 

그럼 이 정보를 가지고 와서 CentOS와 Ubuntu를 다르게 배포하는게 가능할 것이다.

 

---

 

nginx 배포 실습

CentOS -> epel-release, nginx (using yum)

Ubuntu -> nginx (using apt)

 

하나의 yaml 파일에서 yum 모듈을 이용해서 nginx를 설치하고자 한다면 ubuntu는 사용하지 않는 모듈이므로 fail 이 될 것이다. 결국 최종 원하는 결과를 절~대 확인할 수 없다.

1. Ubuntu용과 CentOS 용을 별도로 구분하여 배포한다.

-> 우리실습에서는 인벤토리 섹션에서 centos, ubuntu를 구분해 두었으므로 이를 활용하여 yaml을 두개 만들고 각각의 배포판 버전에 맞는 nginx 설치 구성내용을 입력하면 된다.

 

2. 위의 경우대로라면 무조건 모든 리눅스의 배포판을 구분해야 하는데, 일반적으로 인벤토리에 배포판별로 구분하는 것은 의미가 없다.

결국 우리는 하나의 nginx 설치 파일 내에서 all로 지정된 호스트들의 배포판을 구분하여 각 배포판에 맞는 nginx 설치 방법을 제공해야 한다.

이를 위해 "when 조건"을 사용한다.

 

- name: 이름

  action: 조건에 부합할 경우 해야할 작업

  when: 조건 ansible_distribution == 'CentOS'

 

한번 짜보자

---
- name: nginx install
  hosts: all
  become: yes

  tasks:
    - name: centos > epel-release install
      action: "{{ ansible_pkg_mgr }} name=epel-release state=present"
      when: ansible_distribution == 'CentOS'
    - name: centos > nginx
      action: "yum name=nginx state=present"
      when: ansible_distribution == 'CentOS'
    - name: ubuntu > nginx
      action: "{{ ansible_pkg_mgr }} name=nginx state=present"
      when: ansible_distribution == 'Ubuntu'

newnginx.yaml 파일이다. 일부러 다양한 방식으로 코드를 짜보았다.

 

Quiz. ansible 서버에서 index.html 파일을 간단히 만들고 이를 각 서버의 nginx 기본 데릭토리로 복사한 다음 nginx를 실행해보세요!

 

확인은 ansible-server 에서 curl로 확인하시면 됩니다.

 

---
- name: nginx install
  hosts: all
  become: yes

  tasks:
    - name: centos > epel-release install
      action: "{{ ansible_pkg_mgr }} name=epel-release state=present"
      when: ansible_distribution == 'CentOS'
    - name: centos > nginx
      action: "yum name=nginx state=present"
      when: ansible_distribution == 'CentOS'
    - name: ubuntu > nginx
      action: "{{ ansible_pkg_mgr }} name=nginx state=present"
      when: ansible_distribution == 'Ubuntu'
    - name: cp index.html
      get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/index.html
    - name: copy
      copy:
        src: index.html
        dest: /usr/share/nginx/html
      when: ansible_distribution == 'CentOS'
    - name: copy
      copy:
        src: index.html
        dest: /var/www/html
      when: ansible_distribution == 'Ubuntu'
    - name: start nginx
      services:
        name: nginx
        state: started

newnginx.yaml 파일이다.

get_url과 cp 방식 두개다 준비했다. copy를 하기 위해서는

curl https://www.nginx.com > index.html

 

이제 nginx 관련 정보를 모두 지워주자

---
- name: nginx install
  hosts: all
  become: yes

  tasks:
    - name: centos > epel-release delete
      action: "{{ ansible_pkg_mgr }} name=epel-release state=absent"
      when: ansible_distribution == 'CentOS'

    - name: centos > nginx delete
      action: "{{ ansible_pkg_mgr }} name=nginx state=absent"
      when: ansible_distribution == 'CentOS'

    - name: ubuntu > nginx delete
      action: "{{ ansible_pkg_mgr }} name=nginx state=absent autoremove=yes"
      when: ansible_distribution == 'Ubuntu'

deletenginx.yaml

728x90