--- title: '#90DaysOfDevOps - Tags, Variables, Inventory & Database Server config - Day 68' published: false description: '90DaysOfDevOps - Tags, Variables, Inventory & Database Server config' tags: 'devops, 90daysofdevops, learning' cover_image: null canonical_url: null id: 1048780 --- ## Tag, Variable, Inventory 및 Database 서버 구성 ### Tag 어제 세션에 playbook을 남겨두었으므로 모든 작업을 실행하고 해당 playbook 내에서 play해야 합니다. 즉, 웹서버와 로드밸런서 play 및 작업을 모두 실행해야 완료할 수 있습니다. 하지만 Tag를 사용하면 원하는 경우 이러한 작업을 분리할 수 있습니다. 이는 환경에 매우 크고 긴 playbook이 있는 경우 효율적인 방법이 될 수 있습니다. 이 경우 playbook 파일에서는 [ansible-scenario5](/2022/Days/Configmgmt/ansible-scenario5/playbook5.yml)를 사용하고 있습니다. ```Yaml - hosts: webservers become: yes vars: http_port: 8000 https_port: 4443 html_welcome_msg: "Hello 90DaysOfDevOps - Welcome to Day 66!" roles: - common - apache2 tags: web - hosts: proxy become: yes roles: - common - nginx tags: proxy ``` 그런 다음 `ansible-playbook playbook5.yml --list-tags`를 사용하여 이를 확인할 수 있으며, list Tag는 우리가 playbook에서 정의한 Tag의 윤곽을 나타냅니다. ![](/2022/Days/Images/Day68_config1.png) 이제 프록시만 타깃팅하려면 `ansible-playbook playbook5.yml --tags proxy`를 실행하면 아래에서 볼 수 있듯이 프록시에 대해서만 playbook을 실행할 수 있습니다. ![](/2022/Days/Images/Day68_config2.png) Tag는 작업 수준에서도 추가할 수 있으므로 원하는 위치와 작업을 세분화할 수 있습니다. 예를 들어 애플리케이션 중심 Tag가 될 수도 있고, 작업을 살펴보고 설치, 구성 또는 제거에 따라 작업에 Tag를 지정할 수도 있습니다. 사용할 수 있는 또 다른 매우 유용한 Tag는 다음과 같습니다. `tag: always` 이것은 명령에 어떤 --tags를 사용하든 상관없이 항상 값으로 Tag가 지정된 항목이 있으면 ansible-playbook 명령을 실행할 때 항상 실행되도록 보장합니다. Tag를 사용하여 여러 Tag를 함께 묶을 수도 있으며, `ansible-playbook playbook5.yml --tags proxy,web`을 실행하도록 선택하면 해당 Tag가 있는 모든 항목이 실행됩니다. 물론 이 예제에서는 playbook을 실행하는 것과 같은 의미이지만, 다른 play가 여러 개 있는 경우에는 이 방법이 의미가 있을 것입니다. 둘 이상의 Tag를 정의할 수도 있습니다. ### Variable Ansible에는 크게 두 가지 유형의 Variable이 있습니다. - User created - Ansible Facts ### Ansible Facts playbook을 실행할 때마다 "Gathering facts"라는 정의되지 않은 작업이 있었는데, 이러한 Variable 또는 fact를 사용하여 자동화 작업을 수행할 수 있습니다. ![](/2022/Days/Images/Day68_config3.png) 다음 `ansible proxy -m setup` 명령을 실행하면 JSON 형식의 많은 출력을 볼 수 있습니다. 이를 사용하려면 터미널에 많은 정보가 있어야 하므로 `ansible proxy -m setup >> facts.json`을 사용하여 파일로 출력하고 싶습니다. [여기](/2022/Days/Configmgmt/ansible-scenario5/facts.json)에서 이 파일을 볼 수 있습니다. ![](/2022/Days/Images/Day68_config4.png) 이 파일을 열면 명령에 대한 모든 종류의 정보를 볼 수 있습니다. IP 주소, 아키텍처, 바이오스 버전을 확인할 수 있습니다. 이 정보를 활용하여 playbook에 사용하려는 경우 유용한 정보가 많이 있습니다. 한 가지 아이디어는 웹서버의 IP 주소를 하드코딩한 nginx template mysite.j2 내에서 이러한 Variable 중 하나를 잠재적으로 사용하는 것입니다. mysite.j2에 for 루프를 생성하면 [webservers] 그룹을 순환하여 2개 이상의 웹서버를 자동으로 동적으로 생성하거나 이 로드 밸런서 구성에 추가할 수 있습니다. ``` #Dynamic Config for server {{ ansible_facts['nodename'] }} upstream webservers { {% for host in groups['webservers'] %} server {{ hostvars[host]['ansible_facts']['nodename'] }}:8000; {% endfor %} } server { listen 80; location / { proxy_pass http://webservers; } } ``` 위의 결과는 지금과 동일하게 보이지만 웹 서버를 더 추가하거나 제거하면 프록시 구성이 동적으로 변경됩니다. 이 기능을 사용하려면 이름 확인을 구성해야 합니다. ### User created User created Variable은 우리가 직접 만든 Variable입니다. playbook을 살펴보면 `vars:`가 있고 거기에 3개의 Variable 목록이 있는 것을 볼 수 있습니다. ```Yaml - hosts: webservers become: yes vars: http_port: 8000 https_port: 4443 html_welcome_msg: "Hello 90DaysOfDevOps - Welcome to Day 68!" roles: - common - apache2 tags: web - hosts: proxy become: yes roles: - common - nginx tags: proxy ``` 그러나 Variable을 해당 파일로 이동하여 playbook에 Variable이 없도록 할 수 있습니다. 이 작업을 수행하되, [ansible-scenario6](/2022/Days/Configmgmt/ansible-scenario6) 폴더로 이동하겠습니다. 해당 폴더의 루트에 group_vars 폴더를 만들겠습니다. 그런 다음 all이라는 또 다른 폴더를 만듭니다(모든 그룹이 이 Variable을 가져옵니다). 이 폴더에 `common_variables.yml`이라는 파일을 만들고 playbook의 Variable을 이 파일에 복사합니다. Variable과 함께 playbook에서 Variable을 제거합니다. ```Yaml http_port: 8000 https_port: 4443 html_welcome_msg: "Hello 90DaysOfDevOps - Welcome to Day 68!" ``` 이 Variable을 전역 Variable로 연결하기 때문에 여기에 NTP 및 DNS 서버도 추가할 수 있습니다. Variable은 우리가 만든 폴더 구조에서 설정됩니다. 이제 playbook이 얼마나 깔끔해졌는지 아래에서 확인할 수 있습니다. ```Yaml - hosts: webservers become: yes roles: - common - apache2 tags: web - hosts: proxy become: yes roles: - common - nginx tags: proxy ``` 그 Variable 중 하나는 http_port로, 아래와 같이 mysite.j2 내의 for 루프에서 이 Variable을 다시 사용할 수 있습니다: ```J2 #Dynamic Config for server {{ ansible_facts['nodename'] }} upstream webservers { {% for host in groups['webservers'] %} server {{ hostvars[host]['ansible_facts']['nodename'] }}:{{ http_port }}; {% endfor %} } server { listen 80; location / { proxy_pass http://webservers; } } ``` 또한, 어떤 웹서버를 사용하고 있는지 파악할 수 있도록 roles/apache2/templates/index.HTML.j2 파일에 분석 가능한 사실을 정의할 수도 있습니다. ```J2

{{ html_welcome_msg }}! I'm webserver {{ ansible_facts['nodename'] }}

``` Variable을 변경하여 `ansible-playbook playbook6.yml` 명령을 실행한 결과, 로드밸런서에 도달하면 그룹에 있는 웹서버 중 하나에 도달한 것을 볼 수 있습니다. ![](/2022/Days/Images/Day68_config5.png) 또한 host_vars라는 폴더를 추가하고 web01.yml을 생성하여 원하는 경우 특정 메시지를 표시하거나 호스트별로 표시되는 내용을 변경할 수 있습니다. ### Inventory 파일 지금까지 호스트를 결정하기 위해 /etc/ansible 폴더에 있는 기본 호스트 파일을 사용했습니다. 그러나 프로덕션 및 스테이징과 같이 환경마다 다른 파일을 사용할 수 있습니다. 더 많은 환경을 만들지는 않겠습니다. 하지만 호스트 파일은 만들 수 있습니다. 서버와 노드의 다양한 Inventory에 대해 여러 개의 파일을 만들 수 있습니다. 우리는 `ansible-playbook -i dev playbook.yml`을 사용하여 이를 호출합니다. 호스트 파일 내에 Variable을 정의한 다음 이를 출력하거나 playbook의 다른 곳에서 해당 Variable을 활용할 수도 있습니다. 예를 들어 아래 예제 및 교육 과정에서는 호스트 파일에서 생성된 환경 Variable을 로드밸런서 웹 페이지 template에 추가하여 웹 페이지 메시지의 일부로 환경을 표시했습니다. ### Database 서버 배포 아직 전원을 켜고 구성하지 않은 머신이 하나 더 있습니다. vagrant 파일이 있는 곳에서 `vagrant up db01`을 사용하여 이 작업을 수행할 수 있습니다. 전원이 켜지고 액세스할 수 있게 되면 `ssh-copy-id db01`을 사용하여 SSH 키를 복사하여 액세스할 수 있도록 해야 합니다. 여기서는 [ansible-scenario7](/2022/Days/Configmgmt/ansible-scenario7) 폴더에서 작업할 것입니다. 그런 다음 `ansible-galaxy init roles/mysql`을 사용하여 "MySQL"이라는 새 Role에 대한 새 폴더 구조를 만들어 보겠습니다. playbook에서 Database 구성을 위한 새로운 play 블록을 추가하겠습니다. /etc/ansible/hosts 파일에 그룹 Database가 정의되어 있습니다. 그런 다음 Database 그룹에 공통 Role과 이전 단계에서 생성한 MySQL이라는 새 Role을 갖도록 지시합니다. 또한 Database 그룹에 Database Tag를 지정하고 있는데, 이는 앞서 설명한 것처럼 원하는 경우 이러한 Tag에 대해서만 실행하도록 선택할 수 있음을 의미합니다. ```Yaml - hosts: webservers become: yes roles: - common - apache2 tags: web - hosts: proxy become: yes roles: - common - nginx tags: proxy - hosts: database become: yes roles: - common - mysql tags: database ``` 이제 Role 폴더 구조 내에서 트리가 자동으로 생성되었으므로 다음을 채워야 합니다: Handlers - main.yml ```Yaml # handlers file for roles/mysql - name: restart mysql service: name: mysql state: restarted ``` Tasks - install_mysql.yml, main.yml & setup_mysql.yml install_mysql.yml - 이 작업은 MySQL을 설치하고 서비스가 실행 중인지 확인하기 위해 수행됩니다. ```Yaml - name: "Install Common packages" apt: name={{ item }} state=latest with_items: - python3-pip - mysql-client - python3-mysqldb - libmysqlclient-dev - name: Ensure mysql-server is installed latest version apt: name=mysql-server state=latest - name: Installing python module MySQL-python pip: name: PyMySQL - name: Ensure mysql-server is running service: name: mysql state: started ``` main.yml은 이러한 파일에서 작업을 가져오도록 제안하는 포인터 파일입니다. ```Yaml # tasks file for roles/mysql - import_tasks: install_mysql.yml - import_tasks: setup_mysql.yml ``` setup_mysql.yml - 이 작업은 Database와 Database 사용자를 생성합니다. ```Yaml - name: Create my.cnf configuration file template: src=templates/my.cnf.j2 dest=/etc/mysql/conf.d/mysql.cnf notify: restart mysql - name: Create database user with name 'devops' and password 'DevOps90' with all database privileges community.mysql.mysql_user: login_unix_socket: /var/run/mysqld/mysqld.sock login_user: "{{ mysql_user_name }}" login_password: "{{ mysql_user_password }}" name: "{{db_user}}" password: "{{db_pass}}" priv: '*.*:ALL' host: '%' state: present - name: Create a new database with name '90daysofdevops' mysql_db: login_user: "{{ mysql_user_name }}" login_password: "{{ mysql_user_password }}" name: "{{ db_name }}" state: present ``` 위에서 비밀번호, 사용자 이름 및 Database와 같은 일부 구성을 결정하기 위해 몇 가지 Variable을 사용하고 있음을 알 수 있으며, 이 Variable은 모두 group_vars/all/common_variables.yml 파일에 저장되어 있습니다. ```Yaml http_port: 8000 https_port: 4443 html_welcome_msg: "Hello 90DaysOfDevOps - Welcome to Day 68!" mysql_user_name: root mysql_user_password: "vagrant" db_user: devops db_pass: DevOps90 db_name: 90DaysOfDevOps ``` 또한 template 폴더에 아래와 같은 my.cnf.j2 파일이 있습니다: ```J2 [mysql] bind-address = 0.0.0.0 ``` ### playbook 실행 이제 VM이 실행 중이고 구성 파일이 준비되었으므로 이제 playbook을 실행할 준비가 되었습니다. 다음 `ansible-playbook playbook7.yml`을 실행하면 이전에 수행한 모든 작업이 포함된 playbook을 실행할 수 있고, `ansible-playbook playbook7.yml --tags database` 명령으로 Database 그룹에 배포하여 새 구성 파일만 실행하도록 선택할 수도 있습니다. Database Tag에 대해서만 실행했지만, 오류가 발생했습니다. 이 오류는 pip3(파이썬)가 설치되어 있지 않다는 것을 알려줍니다. 이 오류는 일반 작업에 추가하여 해결할 수 있습니다. ![](/2022/Days/Images/Day68_config6.png) 위의 문제를 수정하고 playbook을 다시 실행했더니 성공적으로 변경되었습니다. ![](/2022/Days/Images/Day68_config7.png) 이제 새로 구성한 db01 서버에서 모든 것이 우리가 원하는 대로 작동하는지 확인해야 합니다. Control Node에서 `ssh db01` 명령을 사용하여 이 작업을 수행할 수 있습니다. MySQL에 연결하기 위해 `sudo /usr/bin/mysql -u root -p`를 사용하고 프롬프트에서 root에 대한 vagrant 암호를 제공했습니다. 연결이 완료되면 먼저 DevOps라는 사용자가 생성되었는지 확인합니다. `select user, host from mysql.user;` ![](/2022/Days/Images/Day68_config8.png) 이제 `SHOW DATABASES;` 명령을 실행하여 생성된 새 Database를 확인할 수 있습니다. ![](/2022/Days/Images/Day68_config9.png) 루트를 사용하여 연결했지만 이제 `sudo /usr/bin/MySQL -u devops -p`를 사용하여 동일한 방법으로 DevOps 계정으로 로그인할 수도 있지만 여기서 암호는 DevOps90입니다. 제가 발견한 한 가지는 `setup_mysql.yml`에 `login_unix_socket: /var/run/mysqld/mysqld.sock` 줄을 추가해야 db01 MySQL 인스턴스에 성공적으로 연결할 수 있었고 이제 이 작업을 실행할 때마다 사용자를 만들 때 변경 사항을 보고하므로 어떤 제안이라도 대단히 감사하겠습니다. ## 자료 - [What is Ansible](https://www.youtube.com/watch?v=1id6ERvfozo) - [Ansible 101 - Episode 1 - Introduction to Ansible](https://www.youtube.com/watch?v=goclfp6a2IQ) - [NetworkChuck - You need to learn Ansible right now!](https://www.youtube.com/watch?v=5hycyr-8EKs&t=955s) - [Your complete guide to Ansible](https://www.youtube.com/playlist?list=PLnFWJCugpwfzTlIJ-JtuATD2MBBD7_m3u) 위에 나열된 마지막 재생 목록은 이 섹션의 많은 코드와 아이디어가 나온 곳이며, 동영상 형식의 훌륭한 리소스이자 워크스루입니다. [Day 69](day69.md)에서 봐요!