[2023-05-22 월] 앤서블 총정리
- 목차 -
1. 앤서블 CLI
서버 준비
$ sudo su - root // 우분투 서버 루트 사용자로 바꾸기
# cat /etc/ansible/hosts // 서버 그룹별로 관리 대상 보기
센토스 아파치 애드혹 관리
# ansible centos -m yum -a "name=httpd state=present" -k #centos그룹에 httpd 설치. yum install -y httpd와 같음
# curl https://www.nginx.com/ -o index.html # nginx 홈페이지에서 index.html 파일을 다운받는다
# ansible centos -m copy -a "src=index.html dest=/var/www/html/index.html" -k # copy명령은 파일을 전송하는 명령. 관리 서버에서 centos서버 경로로 index.html로 전송한다
# ansible centos -m service -a "name=httpd state=started" -k # httpd를 기동. systemctl start httpd와 같은 명령
# ansible centos -m shell -a "systemctl status firewalld" -k # 방화벽이 acitve되었는지 상태를 확인하는 명령
// # ansible centos -m shell -a "systemctl start firewalld" -k # 방화벽이 멈춰있다면 방화벽을 기동시키는 명령
# ansible centos -m shell -a "firewall-cmd --permanent --zone=public --add-service=http" -k # httpd 포트 방화벽 허용
# ansible centos -m shell -a "firewall-cmd --reload" -k # 설정을 변경했으므로 reload해주는 명령
접속테스트
# ansible centos -m service -a "name=httpd state=stopped" -k # 서비스를 멈추는 명령. systemtctl stop httpd 와 같음
# ansible centos -m shell -a "systemctl stop firewalld" -k # 방화벽을 멈추는 명령
# ansible centos -m yum -a "name=httpd state=absent" -k # 서비스를 제거하는 명령. yum remove -y httpd
# ansible centos -m shell -a "systemctl status httpd" -k # 삭제되어서 상태가 뜨지 않는다
우분투 아파치 애드혹 관리
# ansible ubuntu -m apt -a "name=apache2 state=present" -k # 우분투 서버에 apache를 설치하는 명령
# curl https://www.nginx.com/ -o index.html
// # ansible ubuntu -m copy -a "src=index.html dest=/var/www/html/index.html" -k # index.html 파일을 우분투 서버 그룹에 전송하는 방법
# scp index.html root@192.168.1.202:/var/www/html/ # index.html 파일을 원하는 하나의 서버에 전송하는 방법
접속테스트
# ansible ubuntu -m service -a "name=apache2 state=stopped" -k # 서비스를 멈추는 명령
// # ansible ubuntu -m service -a "name=apache2 state=started" -k
# ansible ubuntu -m apt -a "name=apache2 state=absent" -k # 서비스를 지우는 명령. apt remove -y apache2와 같음
2. 앤서블 플레이북
멱등성
앤서블은 멱등성(Idempotency)이란 특징을 가집니다. 이는 여러 번 적용해도 결과가 바뀌지 않으며, 수정된 부분이 있다면 그 부분만 새롭게 반영되는 특징이 있다.
# echo "172.16.0.100" >> inventory.list # 파일 내용 마지막 줄에 내용을 추가
# cat inventory.list
# echo "172.16.0.100" >> inventory.list
# cat inventory.list # 똑같은 내용을 또 입력한다. = 멱등성이 없다
# ansible localhost -c local -m lineinfile -a "path=inventory.list line=172.16.0.200" # -c는 connection을 뜻하며 ssh를 사용하지 않는 local인 것을 명시함. lineinfile은 문장을 입력하는 명령
# cat inventory.list
# ansible localhost -c local -m lineinfile -a "path=inventory.list line=172.16.0.200" # 전송은 success이지만 입력은 되지 않는다
# cat inventory.list # ansible의 lineinfile 명령은 멱등성이 있어서 똑같은 내용을 또 입력하지 않는다
플레이북 구조
YAML 형식으로 작성된 각각의 Playbook들은 하나 이상의 Play를 가지며, 각각의 Play는 하나 이상의 task(앤서블 모듈)을 실행한다
(chef:레시피, puppet:메니페스트)
- name: Playbook Tutorial # - 로 시작하는 3줄이 한 블록이다.
hosts: all # ":" 으로 구분해 항목명과 값을 설정한 키-값 형식으로 되어 있다.
tasks: # 항목명의 위치가 정렬되어 있다. yaml은 들여쓰기가 데이터 구조의 깊이가 된다.
센토스, 우분투 아파치 설치 플레이북
현재 파일 목록
# vi apache_install.yml # 현재 파일에 2개의 play(centos, ubuntu)가 있다
- name: Install apache on centos # 간략한 설명(생략 가능)
hosts: centos # 서버 그룹에 있는 IP 대상. default는 all임
tasks:
- name: install apache web server
yum: name=httpd state=present # ansible centos -m yum -a "name=httpd state=present" -k # httpd 설치
- name: upload default index.html for web server
get_url: url=https://www.nginx.com dest=/var/www/html/ mode=0644 # index.html 다운로드하고 전송하는 명령. 관리 서버에는 다운로드 파일이 남아있지 않는다.
- name: start apache web server
service: name=httpd state=started enabled=yes # httpd 기동시키는 명령. enabled는 껐다 켜도 httpd가 실행되는 명령
- name: Install apache on ubuntu
hosts: ubuntu
tasks:
- name: install apache web server
apt: name=apache2 state=present
- name: upload default index.html for web server
get_url: url=https://www.nginx.com dest=/var/www/html/ mode=0644
- name: start apache web server
service: name=apache2 state=started
# ansible-playbook apache_install.yml -k # ok는 전에 설치가 되었고 이미 서비스가 기동된 것을 의미. 멱등성의 의미
changed는 실제로 설치가 된 것
접속 테스트
3. 앤서블 환경 설정
센토스, 우분투 아파치 삭제 플레이북
# vi apache_remove.yml
- name: Remove apache on centos
hosts: centos
tasks:
- name: remove apache web server
yum: name=httpd state=absent
- name: Remove apache on ubuntu
hosts: ubuntu
tasks:
- name: remove apache web server
apt: name=apache2 state=absent
# ansible-playbook apache_remove.yml -k
앤서블 환경 설정 자동화
완전 처음부터 플레이북으로 세팅하기 위해 기존 설정들을 지워준다
# vi /etc/ansible/hosts
G # 명령줄 제일 아래로 가는 명령
세팅해놓았던 서버 그룹 지우고 저장하고 나오기
# vi env.yml
- name: Setup for the Ansible's Environment
hosts: localhost
tasks:
- name: Add "/etc/ansible/hosts"
blockinfile: # block으로 내용을 추가해줌
path: /etc/ansible/hosts
block: |
[centos]
192.168.1.212
[ubuntu]
192.168.1.202 ansible_python_interpreter=/usr/bin/python3
- name: Configure Bashrc
lineinfile: # 원하는 경로에 명령줄 하나를 넣는다
path: /root/.bashrc
line: "{{ item }}"
with_items: # with 반복을 통해 alias 설정을 해서 단축명령 등록
- "alias ans='ansible'"
- "alias anp='ansible-playbook'"
# ansible-playbook env.yml -k
# cat /etc/ansible/hosts # 블록이 잘 추가되었다
# cat .bashrc # alias가 잘 추가되었다
# source .bashrc # exit하고 r로 재접속하는 것과 똑같은 기능
이제 ansible을 ans로 쓸 수 있고 ansible-playbook을 anp로 쓸 수 잇다
4. 앤서블 Keypair
known_hosts는 처음 ssh로 접속할 때 안전한 서버인지 물어보고 yes라고 치면 IP가 키와 함께 기록됨
그래서 처음 한 번만 묻고 두 번째부터는 안물어봄
# cat .ssh/known_hosts
서버가 2000대면 yes를 2000번 쳐줘야한다. 그래서 key-pair를 등록해줘야함
# rm -rf .ssh/known_hosts # 먼저 등록된 IP를 삭제한다
# vi keypair_old.yml
- name: Setup for the Ansible's Environment
hosts: localhost
tasks:
- name: Generate sshkey
shell: "{{ item }}"
with_items: # 한 줄 입력이 반복적으로 실행됨. 하지만 2000대면 2000대를 적어줘야한다
- "ssh-keyscan 192.168.1.212 >> ~/.ssh/known_hosts"
- "ssh-keyscan 192.168.1.202 >> ~/.ssh/known_hosts"
# anp keypair_old.yml -k
# ans all -m ping -k # IP가 잘 등록되었고 ping이 잘 나간다
# rm -rf .ssh/knwon_hosts # 반복 문제를 해결하는 플레이북을 생성하기 위해 등록한 IP 삭제
# vi keypair_new.yml
- name: Create known_hosts between server and nodes
hosts: all # 관리 서버(centos, ubuntu)를 대상
connection: local # 로컬 서버를 대상
serial: 1 # task 작업을 하나씩 하나씩 처리함. 얘가 없으면 누락이 발생할 수 있음
tasks:
- name: ssh-keyscan for known_hosts file
command: /usr/bin/ssh-keyscan -t ecdsa {{ ansible_host }} # command 명령으로 ecdsa 타입의
매직변수는 ansible이 설치될 때 ansible이 미리 정해놓은 변수. 매직 변수 ansible_host 활용하여 hosts ip 호출. ansoble_host변수는 hosts파일을 뒤져서 hosts ip를 가져온다
register: keyscan # keyscan 변수를 만듦. keyscan을 register(임시로 저장하는 공간)에 저장
- name: input key
lineinfile:
path: ~/.ssh/known_hosts
line: "{{ item }}"
create: yes
with_items: # 반복문을 통해 item 매개변수에 한 줄씩 들어감. 서버 개수에 상관없이 등록할 수 있다
- "{{ keyscan.stdout_lines }}" # 표준 출력
- name: Create authorized_keys between server and nodes # ansible이 퍼블릭 키와 프라이빗 키를 만들어서 퍼블릭 키를 보내는 명령
hosts: all
connection: local
vars: # 패스워드를 키에다 집어넣어서 키 인증을 패스워드 없이 접속
ansible_password:
tasks:
- name: ssh-keygen for authorized_keys file
openssh_keypair: # 해당 경로에 키 페어(프라이빗 키와 퍼블릭 키)를 생성하는 명령
path: ~/.ssh/id_rsa
size: 2048 # 암호화 방식의 비트수
type: rsa # 비대칭 방식. 암호화, 복호화, 로그인 기능
force: False # overwrite하지 않는다는 False라고 값을 넣거나 아니면 삭제하거나 하면 되겠습니다. = 이미 키가 있으면 그것을 활용한다는 명령
- name: input key for each node
connection: ssh # ssh를 통해 모든 호스트에 접속해서 root사용자에게 퍼블릭 키를 전송하는 명령. ssh-copy-id와 같은 명령
authorized_key:
user: root
state: present
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}" # 위에서 만든 파일 형태의 퍼블릭 키를 가져오는 명령
5. 앤서블 Nginx
# cd .ssh
# rm -rf known_hosts # 키 인증 방식을 실행하기 위해 known_hosts 파일 삭제
# vi keypair_new.yml
- name: Create known_hosts between server and nodes
hosts: all
connection: local
serial: 1
tasks:
- name: ssh-keyscan for known_hosts file
command: /usr/bin/ssh-keyscan -t ecdsa {{ ansible_host }} # 매직 변수 ansible_host 활용하여 hosts ip 호출
register: keyscan
- name: input key
lineinfile:
path: ~/.ssh/known_hosts
line: "{{ item }}"
create: yes
with_items:
- "{{ keyscan.stdout_lines }}"
- name: Create authorized_keys between server and nodes
hosts: all
connection: local
vars:
ansible_password:
tasks:
- name: ssh-keygen for authorized_keys file
openssh_keypair:
path: ~/.ssh/id_rsa
size: 2048
type: rsa
force: False # overwrite하지 않는다는 False라고 값을 넣거나 아니면 삭제하거나 하면 되겠습니다.
- name: input key for each node
connection: ssh
authorized_key:
user: root
state: present
key: "{{ lookup('file', '~/.ssh/id_rsa.pub') }}"
# anp keypair_new.yml
# cat .ssh/known_hosts # 없었던 known_hosts파일이 생겼다
iac 서버의 # cat .ssh/peach.pub 내용과 각 서버의 # cat .ssh/authorized_keys의 내용이 똑같다. 퍼블릭 키(자물쇠)가 전송되었다는 뜻
# ssh root@192.168.1.212 # 키 인증 방식으로 centos서버와 ubuntu 서버로 비밀번호 없이 접근이 가능하다
# ssh root@192.168.1.202
# ans all -m ping # -k 명령을 넣지 않아도(패스워드를 입력하지 않아도) ping 명령이 나간다
센토스, 우분투 NGINX 설치 플레이북
# vi nginx_install.yml
- name: Install nginx on centos
hosts: centos
tasks:
- name: install epel-release # 가장 최신의 저장소를 설치
yum: # 3줄로 명령을 적는 방법 (가독성, 취향 차이)
name: epel-release
state: latest
- name: install nginx web server # nginx를 설치
yum: name=nginx state=present # 1줄로 명령을 적는 방법
- name: upload default index.html for web server # index.html 를 다운로드 받아서 centos로 보냄
get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/ mode=0644
- name: start nginx web server # httpd 실행
service: name=nginx state=started enabled=yes
- name: Install nginx on ubuntu
hosts: ubuntu
tasks:
- name: install nginx web server
apt: pkg=nginx state=present update_cache=yes # apt update 명령과 같음
- name: Upload default index.html for web server # index.html 를 다운로드 받아서 ubuntu로 보냄
get_url: url=https://www.nginx.com dest=/var/www/html/
mode=0644 validate_certs=no
- name: Install nginx on centos
hosts: centos
tasks:
- name: install epel-release
yum:
name: epel-release
state: latest
- name: install nginx web server
yum: name=nginx state=present
- name: upload default index.html for web server
get_url: url=https://www.nginx.com dest=/usr/share/nginx/html/ mode=0644
- name: start nginx web server
service: name=nginx state=started enabled=yes
- name: Install nginx on ubuntu
hosts: ubuntu
tasks:
- name: install nginx web server
apt: pkg=nginx state=present update_cache=yes
- name: Upload default index.html for web server
get_url: url=https://www.nginx.com dest=/var/www/html/
mode=0644 validate_certs=no
# anp nginx_install.yml # 설치 파일 실행
센토스, 우분투 엔진엑스 삭제 플레이북
# vi nginx_remove.yml
- name: Remove nginx on centos
hosts: centos
tasks:
- name: remove nginx web server
yum: name=nginx state=absent
- name: Remove nginx on ubuntu
hosts: ubuntu
tasks:
- name: remove nginx web server
apt: pkg=nginx* state=absent
# anp nginx_remove.yml # 제거 파일 실행
6. 앤서블 NFS
센토스, 우분투 NFS 설치 플레이북
# vi nfs.yml
- name: Setup for nfs server
hosts: localhost # local호스트 서버에 nfs 설치
tasks:
- name: Open firewall services
firewalld: # 방화벽에 nfs를 허용하도록 추가
permanent: yes
immediate: yes
service: "{{ item }}"
state: enabled
with_items:
- rpc-bind
- nfs
- mountd
- name: make nfs_shared directory
file: # 공유하고 싶은 폴더 생성
path: /root/nfs_shared
state: directory
mode: 0777
- name: configure /etc/exports # 접근할 수 있는 네트워크 범위 설정
lineinfile:
path: /etc/exports
line: /root/nfs_shared 192.168.0.0/21(rw,sync) # 강의실 IP대역
- name: Install NFS
yum: # nfs-utils 설치 명령
name: nfs-utils
state: present
- name: nfs service start
service: # 서버 시작 명령
name: nfs-server
state: restarted
enabled: yes
- name: Setup for nfs clients
hosts: centos # CentOS 서버에 nfs-clients 설치
tasks:
- name: make nfs_client directory
file: # 공유할 파일 생성
path: /root/nfs
state: directory
- name: Install NFS
yum: # nfs-utils 설치
name: nfs-utils
state: present
- name: mount point directory as client # mount -t nfs 192.168.1.166:/root/nfs_shared /root/nfs와 같은 명령
mount: # 마운트할 경로 설정
path: /root/nfs
src: 192.168.1.166:/root/nfs_shared # local 서버(ansible서버)의 IP를 소스로 설정
fstype: nfs
state: mounted
- name: Setup for nfs clients U
hosts: ubuntu # Ubuntu 서버에 nfs-clients 설치
tasks:
- name: make nfs_client directory
file: # 공유할 파일 생성
path: /root/nfs
state: directory
- name: Install NFS-U
apt: # nfs-common 설치
pkg: nfs-common
state: present
update_cache: yes
- name: mount point directory as client
mount: # 마운트할 경로 설정
path: /root/nfs
src: 192.168.1.166:/root/nfs_shared # local 서버(ansible서버)의 IP를 소스로 설정
fstype: nfs
opts: nfsvers=3 # nfs 서버 버전을 명시해야한다
state: mounted
- name: Setup for nfs server
hosts: localhost
tasks:
- name: open firewall services
firewalld:
permanent: yes
immediate: yes
service: "{{ item }}"
state: enabled
with_items:
- rpc-bind
- nfs
- mountd
- name: make nfs_shared directory
file:
path: /root/nfs_shared
state: directory
mode: 0777
- name: configure /etc/exports
lineinfile:
path: /etc/exports
line: /root/nfs_shared 192.168.0.0/20(rw,sync)
- name: Install NFS
yum:
name: nfs-utils
state: present
- name: nfs service start
service:
name: nfs-server
state: restarted
enabled: yes
- name: Setup for nfs clients
hosts: centos
tasks:
- name: make nfs_client directory
file:
path: /root/nfs
state: directory
- name: Install NFS
yum:
name: nfs-utils
state: present
- name: mount point directory as client
mount:
path: /root/nfs
src: 192.168.1.166:/root/nfs_shared
fstype: nfs
state: mounted
- name: Setup for nfs clients U
hosts: ubuntu
tasks:
- name: make nfs_client directory
file:
path: /root/nfs
state: directory
- name: Install NFS-U
apt:
pkg: nfs-common
state: present
update_cache: yes
- name: mount point directory as client
mount:
path: /root/nfs
src: 192.168.1.166:/root/nfs_shared
fstype: nfs
opts: nfsvers=3
state: mounted
# anp nfs.yml
nfs 테스트 // 우분투 서버에서 txt파일 작성
# ehco "hello wolrd" > nfs/test.txt
centos 서버에서 txt파일 확인
cat nfs/test.txt
7. 앤서블 워드프레스
워드프레스 만들기
# vi /etc/ansible/hosts # centos서버에 웹서버를 설치하고 ubuntu서버에 db서버를 설치할 것이기 때문에 hosts그룹을 수정한다
[webserver]
192.168.1.212
[dbserver]
192.168.1.202 ansible_python_interpreter=/usr/bin/python3
# vi wordpress.yml
- name: Setup for webserver
hosts: webserver # webserver 세팅
tasks:
- name: Install http
yum: # 설치할 모듈들을 적어놓음
name: "{{ item }}"
state: present
with_items:
- httpd
- php
- php-mysql
- php-gd
- php-mbstring
- wget
- unzip
- name: Unarchive a file that needs to be downloaded (added in 2.0)
ansible.builtin.unarchive: # 압축된 파일을 다운로드 받고 /var/www/html 경로에 압축을 해제
src: https://ko.wordpress.org/wordpress-4.8.2-ko_KR.zip
dest: /var/www/html
remote_src: yes
- name: chown
file: # apache에 퍼미션을 주고싶은 경로 설정
path: /var/www/html/wordpress
owner: "apache"
group: "apache"
recurse: "yes"
- name: web service restart
service: # httpd 서비스 재시작
name: httpd
state: restarted
- name: Setup for dbserver
hosts: dbserver # dbserver 세팅
tasks:
- name: Install mariadb
apt: # mariadb 설치
pkg: mariadb-server
state: present
update_cache: yes
- name: Install pymysql
apt: # 파이썬을 이용한 mysql연결도구 설치
pkg: python-pymysql
state: present
- name: Install pymysql
apt: # 파이썬을 이용한 mysql연결도구 설치
pkg: python3-pymysql
state: present
- name: set root password
mysql_user: # mariadb root사용자 패스워드 설정
name: 'root'
password: '{{ mysql_root_password }}' # 비밀번호는 매개변수로 받겠다는 명령
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
- name: edit file
replace: # bind-adress는 로컬 호스트에서만 mysql 접속하게하는 명령. remote환경에서 접속을 위해 이 명령을 주석처리하는 명령
path: /etc/mysql/mariadb.conf.d/50-server.cnf
regexp: "bind-address"
replace: "#bind-address"
- name: db service restart
service: # mariadb 서비스 재시작
name: mysql
state: restarted
- name: Create database
mysql_db: # wordpress 데이터베이스 생성
db: wordpress
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
- name: Create database user
mysql_user:
user: wpuser
password: wppass
priv: "wordpress.*:ALL,GRANT" # wpuser에게 모든 권한을 다준다
host: '%' # remote 환경(웹서버)에서 wpuser가 접근할 수 있도록 하는 옵션
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
- name: Setup for webserver
hosts: webserver
tasks:
- name: Install http
yum:
name: "{{ item }}"
state: present
with_items:
- httpd
- php
- php-mysql
- php-gd
- php-mbstring
- wget
- unzip
- name: Unarchive a file that needs to be downloaded (added in 2.0)
ansible.builtin.unarchive:
src: https://ko.wordpress.org/wordpress-4.8.2-ko_KR.zip
dest: /var/www/html
remote_src: yes
- name: chown
file:
path: /var/www/html/wordpress
owner: "apache"
group: "apache"
recurse: "yes"
- name: web service restart
service:
name: httpd
state: restarted
- name: Setup for dbserver
hosts: dbserver
tasks:
- name: Install mariadb
apt:
pkg: mariadb-server
state: present
update_cache: yes
- name: Install pymysql
apt:
pkg: python-pymysql
state: present
- name: Install pymysql
apt:
pkg: python3-pymysql
state: present
- name: set root password
mysql_user:
name: 'root'
password: '{{ mysql_root_password }}'
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
- name: edit file
replace:
path: /etc/mysql/mariadb.conf.d/50-server.cnf
regexp: "bind-address"
replace: "#bind-address"
- name: db service restart
service:
name: mysql
state: restarted
- name: Create database
mysql_db:
db: wordpress
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
- name: Create database user
mysql_user:
user: wpuser
password: wppass
priv: "wordpress.*:ALL,GRANT"
host: '%'
login_unix_socket: /var/run/mysqld/mysqld.sock
state: present
# anp wordpress.yml --extra-vars "mysql_root_password=asdqwe123456"
접속 테스트
URL에 '192.168.1.212/wordpress' 입력
8. 도커 가상머신 생성
가상머신 그룹으로 묶기
도커 가상머신 설치
가상머신 이름 docker
스냅샷 찍기