이 글은 CloudNet@ 팀 gasida님의 스터디 A101 1기 내용 및 실습으로 작성된 글입니다.
Playbook 개발
앤서블의 플레이 북을 생성하기 위해서 사전 분석과 함께 플레이 북 설계가 이루어져야한다. 플레이북을 설계 할 때는 생각하는 플레이북의 파일 이름과 태스크명, 사용할 모듈과 변수를 정의하고 변수명, 변수를 선언할 위치도 함께 설계하는 것이 좋다.
* 사용자 계정 생성하기
1. 먼저 사용자 계정을 생성하기 위한 프로젝트 디렉터리와 ansible.cfg, inventory 파일을 작성한다.
2. 사용자 계정 정보가 정의된 변수 파일을 생성하는데, vault로 생성을 진행하며 vault로 생성 시 처음에 비밀번호를 입력해서 생성해주어야한다.
아래 내용을 에디터 창으로 변환이 되었을 때 기재해주면 되는데, user_info라는 변수에 userid와 userpw가 같이 있는 사전형 변수를 정의한다.
cat으로 생성한 yml 파일을 열어보면 내용이 암호화 되어있는 것을 확인할 수 있다.
---
user_info:
- userid: "ansible"
userpw: "ansiblePw1"
- userid: "stack"
userpw: "stackPw1"
3. 사용자 계정을 생성하는 플레이북을 만들고, 사용자 계정은 모든 호스트에 동일하게 생성하고 이때 위에서 생성한 secret.yml 파일(vault로 작성된 변수 파일)을 읽어서 계정을 생성한다.
사용자 계정 생성 시, ansible.builtin.user 모듈과 loop 문을 사용해서 생성하게 된다.
---
- hosts: all
vars_files:
- vars/secret.yml
tasks:
- name: Create user
ansible.builtin.user:
name: "{{ item.userid }}"
password: "{{ item.userpw | password_hash('sha512', 'mysecret') }}"
state: present
shell: /bin/bash # 설정하지 않을 경우 default로 /bin/sh
loop: "{{ user_info }}"
4. 플레이북을 실행하기 전에 문법을 체크하고 실행하는 것이 좋다. ansible-playbook 명령어에 --syntax-check 옵션을 사용해서 user 생성을 위한 yml 파일의 문법을 확인한다. 문법을 확인했을 때, 문제가 없다면 --ask-vault-pass 옵션을 사용하여 user 생성을 진행한다.
* --ask-vault-password / --ask-vault-pass: vault의 비밀번호를 묻는 옵션
* --syntax-check: playbook의 구문만 검사하고, 수행은 하지 않는 옵션
처음에 --syntax-check 옵션만 주고 실행하니 에러가 발생되었다. 아마도 vault 암호를 넣어주지 않아서(?) 인증을하지 못한 것 같다.
그래서 --ask-vault-pass옵션을 함께 주고 실행하니 구문에 이상이 없는 것이 확인되었다.
그리고 플레이북 실행하고, 계정이 생성되었는지 확인하니 stack과 ansible 계정을 확인된다.
* SSH 키 생성 및 복사
user 생성 후 ssh 키를 만들어서 각 node에 생성한 ssh 키를 복사한다.
ssh 키를 생성하는 태스크와 생성된 키를 복사하는 태스크가 있는 플레이북을 생성한다.
해당 태스크를 실행할 때 ssh 키 생성은 localhost에서 실행하고, ssh 키 copy는 각 node에서 실행한다.
1. ssh 키 생성과 복사를 진행할 프로젝트 디렉터리와 inventory 파일을 생성한다. 이전에 사용했던 cfg를 copy하고 inventory 내용(그룹 추가)을 수정한다.
2. 위에서 말한 대로 태스크가 실행될 호스트별로 태스크를 작성한다. localhost ansible-server에서 생성된 ssh pub 키는 ansible.posix.authorized_key라는 모듈을 통해 inventory에 기재한 각 노드로 키가 복사된다. 키를 복사할 때는 lookup 함수가 사용된다.
3. 플레이북을 실행하기 전에 --syntax-check 옵션을 사용해서 문법을 체크하고, 이상이 없는 것을 확인 한 다음에 플레이북을 실행한다.
이때 -e 옵션을 사용하였는데, 이 옵션은 --extra-vars로 플레이북에 전달할 인자 값이나 변수(?)으로 정의한 userid가 플레이북에 전달되어 실행된다.
아니 근데 플레이북을 실행하면 failed이 된다. 원인이 뭔가해서 찾고 있는데, 이상하게 node안에서 sudo 명령어를 사용하면 비밀번호를 잘 넣어도 계속 sorry, try again. 이라고 계속 뜨면서 root 스위칭이 안된다. 근데 su 로 하면 비밀번호 넣고 root로 스위칭되고... 내 생각엔 node에서 sudo가 안되는게 원인 같은데 왜 안되는지 답답하다... 이거 원인 찾는다고 한 40분 찾아본 거 같은데 원인을 못찾았다 아직😭 답답하구만... sudo su - , sudo -i 다 안됨...
+ 어 sudo 명령어 고쳐도 copy가 안되는데 원인이 뭐지??
아무튼 임시 조치로 ansible.cfg 파일의 계정을 root로 바꿔주고 나서 실행하니 정상적으로 바뀌는 것을 볼 수 있었다.
4. 이제 ansible 계정으로 스위치 한 다음에 각 node에 ssh 키 파일 복사 잘 되었는지 확인하고 ssh 접속 테스트도 해보니 ssh 접속 되는 것이 확인된다.
5. 각 node의 ansible 계정이 sudo 명령어를 사용할 때 비밀번호 입력하지 않아도 스위칭 될 수 있도록 설정했다.
아래 플레이북을 만들어 준다음에 --ask-pass 옵션을 넣어서 실행하고 노드에서 sudoers.d 확인하면 잘(?) 들어가있는 것을 볼 수 있다.
* NTP 서버 설치 및 설정
NTP 서버 주소는 메인 플레이북에서 정의하고, 운영체제가 Ubuntu이면 apt 모듈을 사용하여 chrony를 설치한다. Jinja2 템플릿 방식의 chrony.conf 파일을 대상 호스트로 복사하고, 설정 파일 복사가 완료되면, chrony 서비스를 재시작 한다.
chrony 서비스 설치를 위한 롤은 변수를 정의하는 vars, 환경 설정 템플릿을 위한 templates, 태스크를 정의하는 tasks, 환경 설정 후 chrony 서비스 재시작을 위한 handler를 사용한다.
1. ansible 계정으로 프로젝트 디렉터리 생성 및 ansible.cfg와 inventory 파일을 생성한 다음에 --init-path 옵션을 사용해서 롤을 생성하는데, 이때 경로를 ./roles로 설정한다.
* --init-path: roles 명령어로 역할 디렉토리 구조를 생성
2. role 디렉터리에 vars/main.yaml 파일에 내용을 추가해주고, templates아래의 chrony.conf.j2 파일에 내용을 추가하고 핸들러에는 chrony 서비스를 재시작하는 태스크를 추가해준다.
3. 메인 태스크를 위한 파일 을 생성하는데, ansible_facts.distribution이라는 팩트 변수를 이용해서 다른 파일의 태스크를 포함시킨다. 운영체제마다 chrony환경 설정 파일 위치도 달라 각 운영체제에 맞는 chrony 환경 설정 파일을 복사해야 한다. 설정 파일 복사를 하고나면 notify를 통해 restart chrony 핸들러를 호출한다.
4. chrony를 설치하는 플레이북 파일의 구문을 검사하고, 이상이 없으면 설치를 진행한다.
5. 설치를 진행한 후 설치가 잘 되었는지 확인하니 잘 설치가 된 것 같다.
환경 설정 자동화
* 네트워크 IP 설정하기
ansible을 사용해서 환경 구성을 하다보면 네트워크 IP를 구성할 일이 많다. 기본 네트워크 이외 IP설정은 앤서블을 사용해서 설정할 수 있다.
OS가 ubuntu인 경우 netplan 파일을 이용하여 IP를 설정한다. netplan은 파일이고, 사전에 파일구조 확인 후 jinja2 템플릿으로 작성해야 한다.
IP 설정 관련 정보는 메인 플레이북에서 변수로 정의하고, 변수로 정의한 네트워크 인터페이스가 실제 호스트에 존재하는지는 ansible fact를 통해 확인한다.
1. 네트워크 IP설정을 위한 프로젝트 디렉터리 생성과 ansible.cfg 및 inventory 파일 작성한다.
2. ansible-galaxy role init 명령어를 통해 myrole.nmcli, myrole.netplan 롤을 생성한다.
생성된 롤 myrole.nmcli 디렉터리로 이동해서 tasks/main.yml 파일에 태스크 내용을 작성한다. 이때 community.general.nmcli 모듈을 사용해서 외부로부터 받은 변수로 네트워크 IP를 설정하게 된다. 변수는 배열 방식으로 받은 변수로 loop를 사용하였고, when 키워드를 사용해 외부로부터 받은 인터페이스가 앤서블 팩트에 있는지 확인한다.
myrole.netplan에 jinja2 템플릿을 이용해 내용을 작성한다. jinja2 템플릿을 이용해 외부로부터 받은 배열형 변수를 for문으로 하나씩 꺼내 사용할 수 있고, jinja2 템플릿에서 제어문이나 반복문을 사용할 때는 %~%을 사용한다.
3. myrole.netplan에 태스크 파일과 핸들러 파일을 작성한다. 핸들러는 command 모듈을 이용해서 netplan apply 명령어를 수행한다.
그리고 role을 호출할 메인 플레이북을 작성한다. 메인 플레이북에는 role에 전달할 변수들을 vars 섹션에 선언하고, tasks 섹션에 role을 추가한다.
4. 플레이북을 실행하기 전에 tnode1의 네트워크 정보를 사전에 먼저 확인하고, 작성한 플레이북의 문법 체크 후 플레이 북을 실행한다.
# tnode1 정보 확인
ssh tnode1 ls /etc/netplan
ssh tnode1 cat /etc/netplan/50-cloud-init.yaml
ssh tnode1 ip -br -c addr
ssh tnode1 ip -c route
ssh tnode1 nslookup blog.cloudneta.net
#
ansible -m shell -a "cat /var/log/syslog | grep -i dhcp" tnode1
ssh tnode1 sudo dhclient -v ens5
<실행 전>
<실행 후>
* 호스트명 설정
호스트명을 설정하기 위해 ansible.builtin.hostname 모듈을 사용하고, /etc/hosts에 node 정보들을 등록하기 위해 필요한 정보들을 변수로 정의한다.
호스트명을 hosts 파일에 추가 할 때는 ansible.builtin.lineinfile 모듈을 사용하게 된다.
1. 호스트명 설정을 위한 프로젝트 디렉터리와 ansible.cfg, inventory 파일을 작성한다.
2. hosts에 추가할 정보를 사전형 변수로 정의해서 반복문에서 사용할 수 있게 변수 파일을 생성한다.
그리고 메인 플레이북을 작성하는데, hostname은 inventroy 정보를 통해 설정하고, /etc/hosts 파일 내용추가는 변수 정의 파일에서 반복문을 통해 가져온다.
3. 플레이북을 실행하기 전에 각 노드들의 /etc/hosts 파일 내용을 확인하고, 작성한 메인 파일의 문법을 --syntax-check 옵션을 통해 문법 체크를 하고 플레이 북을 실행했다. 그리고 결과를 확인해보니 /etc/hosts 파일에 내용이 들어간 것을 확인할 수 있었다.
<실행 전>
<실행 후>
* NFS 서버 설치
1. NFS 서버 설치 및 구성을 위한 프로젝트 디렉터리와 ansible.cfg, inventory 파일을 생성한다.
2. ansible-galaxy role init 명령어를 통해 필요한 롤을 생성하고, 롤 생성이 완료되면 myrole.nfs_server 디렉터리로 이동하여 vars/main.yml 파일을 열어 변수를 정의한다. 해당 파일에 정의된 nfs_packages 변수는 설치할 NFS 서버 관련 패키지이다.
3. myrole.nfs_server에 태스크 파일을 작성한 뒤에 핸들러 파일도 작성한다.
4. myrole.nfs_client에 설치를 진행할 NFS패키지 변수 파일을 생성하고, 태스크 파일도 생성한다.
5. 메인 플레이북에 사용할 변수를 정의해주고, 메인 플레이북을 생성한다.
6. 플레이북을 실행하기 전에 작성한 플레이북의 문법을 --syntax-check 옵션을 통해 검사하고 이상이 없으면 플레이북을 실행한다.
실행 후에 노드에 nfs가 구성되었는지 확인하고, tnode1에서 nfs에 파일을 생성 테스트 하였더니 정상적으로 생성된 것을 확인할 수 있었다.
'CloudNetaStudy > [Study] Ansible' 카테고리의 다른 글
[4주차] 보안설정 / 모니터링 자동화 (0) | 2024.02.09 |
---|---|
[2주차] Ansible 반복문과 조건문 (0) | 2024.01.20 |
[1주차] Ansible 개념과 설치 (0) | 2024.01.11 |