# Ansible
*橘圈表示機器, 灰框表示群組*

**Ansible較適用於中小型的管理**
**安裝在圖中的主機器上, 讓他去控制其他機器**
**控制方式**
1. ad hoc (在command line 一行一行輸入)
2. script (寫一個ansible 的腳本一次執行多項指令)
---
## 先設定無密碼登入
**建議使用root的無密碼登入, 後續需要進行一些系統的操作才不須提權**
https://hackmd.io/@LSX-0123/SkgsSOt8p
否則後續執行時都須輸入sudo 密碼

## 安裝及配置
改權限的東東
https://how64bit.com/posts/ansible/2022/ansible-configuration/
* 安裝軟體
`sudo yum install -y ansible`
* 設定權限 (如果無密碼登入部分使用root 權限操作跳到下一項)
參考: [Ansible - 管理 Ansible 設定組態檔](https://how64bit.com/posts/ansible/2022/ansible-configuration/)
修改下面兩項 (defaults 和 privilege_escalation)
`sudo vim /etc/ansible/ansible.cfg`
```bash=
[defaults]
inventory = /etc/ansible/hosts
ask_pass = False
[privilege_escalation]
become=True
become_method=sudo
become_user=root
become_password=user
become_ask_pass=True
```
* 配置設定
`sudo vim /etc/ansible/hosts`
**新增群組**
```bash=
[server1]
192.168.68.157
[server2]
192.168.68.163
[servers]
192.168.68.157
192.168.68.163
```
* ping 測試
```bash=
ansible server1 -m ping
ansible servers -m ping
ansible server2 -m ping
```

## ansible 操作
* 加入ubuntu (server2)
**修改 vim /etc/ssh/sshd_config**
**PermitedRootLogin yes**
```bash=
# 如果 "a" 不存在, 新增 "a" 如果 "a" 存在 跳過後面的命令
[user@d1 ~]$ ansible server1 -m command -a "creates=a touch a"
[WARNING]: Consider using the file module with state=touch rather than running
'touch'. If you need to use command because file is insufficient you can add
'warn: false' to this command task or set 'command_warnings=False' in
ansible.cfg to get rid of this message.
192.168.68.157 | CHANGED | rc=0 >>
[user@d1 ~]$ ansible server1 -m command -a "creates=a touch a"
192.168.68.157 | SUCCESS | rc=0 >>
skipped, since a exists
[user@d1 ~]$ ansible server1 -m command -a "ls"
192.168.68.157 | CHANGED | rc=0 >>
a
```
* ad hoc
* command ( 較複雜的混合指令無法用它 )
`$ ansible server1 -m command -a "ifconfig"`

* 腳本
```bash=
[user@d1 Desktop]$ cat test.sh
whoami
hostname
```
```bash=
[user@d1 Desktop]$ ansible all -m script -a "./test.sh"
192.168.68.154 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.68.154 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.68.154 closed."
],
"stdout": "user\r\nvm\r\n",
"stdout_lines": [
"user", # response
"vm" # response
]
}
192.168.68.157 | CHANGED => {
"changed": true,
"rc": 0,
"stderr": "Shared connection to 192.168.68.157 closed.\r\n",
"stderr_lines": [
"Shared connection to 192.168.68.157 closed."
],
"stdout": "user\r\nd2\r\n",
"stdout_lines": [
"user", # response
"d2" # response
]
}
```
* 安裝 刪除
```bash=
[user@d1 Desktop]$ ansible server3 -m apt -a "name=tree state=absent"
BECOME password:
192.168.68.154 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": true,
"stderr": "",
"stderr_lines": [],
"stdout": "Reading package lists...\nBuilding dependency tree...\nReading state information...\nThe following packages were automatically installed and are no longer required:\n cpu-checker ibverbs-providers ipxe-qemu ipxe-qemu-256k-compat-efi-roms\n libaio1 libcacard0 libdaxctl1 libdecor-0-0 libdecor-0-plugin-1-cairo libfdt1\n libgfapi0 libgfrpc0 libgfxdr0 libglusterfs0 libibverbs1 libiscsi7 libndctl6\n libpmem1 libpmemobj1 libqrencode4 librados2 librbd1 librdmacm1 libsdl2-2.0-0\n libspice-server1 liburing2 libusbredirparser1 libvirglrenderer1 msr-tools\n ovmf qemu-block-extra qemu-system-common qemu-system-data qemu-system-gui\n qemu-system-x86 qemu-utils qrencode seabios uidmap xclip\nUse 'sudo apt autoremove' to remove them.\nThe following packages will be REMOVED:\n pass tree\n0 upgraded, 0 newly installed, 2 to remove and 211 not upgraded.\nAfter this operation, 249 kB disk space will be freed.\n(Reading database ... \r(Reading database ... 5%\r(Reading database ... 10%\r(Reading database ... 15%\r(Reading database ... 20%\r(Reading database ... 25%\r(Reading database ... 30%\r(Reading database ... 35%\r(Reading database ... 40%\r(Reading database ... 45%\r(Reading database ... 50%\r(Reading database ... 55%\r(Reading database ... 60%\r(Reading database ... 65%\r(Reading database ... 70%\r(Reading database ... 75%\r(Reading database ... 80%\r(Reading database ... 85%\r(Reading database ... 90%\r(Reading database ... 95%\r(Reading database ... 100%\r(Reading database ... 224892 files and directories currently installed.)\r\nRemoving pass (1.7.4-5) ...\r\nRemoving tree (2.0.2-1) ...\r\nProcessing triggers for man-db (2.10.2-1) ...\r\n",
"stdout_lines": [
"Reading package lists...",
"Building dependency tree...",
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
"(Reading database ... 224892 files and directories currently installed.)",
"Removing pass (1.7.4-5) ...",
"Removing tree (2.0.2-1) ...",
"Processing triggers for man-db (2.10.2-1) ..."
]
}
[user@d1 Desktop]$ ansible server3 -m apt -a "name=tree state=present"
BECOME password:
192.168.68.154 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"cache_update_time": 1717550543,
"cache_updated": false,
"changed": true,
"stderr": "",
. . . . . . . . . .
. . . . . . . . . .
. . . . . . . . . .
"(Reading database ... 224855 files and directories currently installed.)",
"Preparing to unpack .../tree_2.0.2-1_amd64.deb ...",
"Unpacking tree (2.0.2-1) ...",
"Setting up tree (2.0.2-1) ...",
"Processing triggers for man-db (2.10.2-1) ..."
]
}
```
* 複製資料 ( copy )
```bash=
$ echo "hello" > hello.txt
[user@d1 ansible]$ ansible server1 -m copy -a "src=./hello.txt dest=/tmp/hello.txt owner=user group=user mode=0644"
192.168.68.157 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"checksum": "f572d396fae9206628714fb2ce00f72e94f2258f",
"dest": "/tmp/hello.txt",
"gid": 1000,
"group": "user",
"md5sum": "b1946ac92492d2347c6235b4d2611184",
"mode": "0644",
"owner": "user",
"size": 6,
"src": "/home/user/.ansible/tmp/ansible-tmp-1718346500.52-6651-92054779023352/source",
"state": "file",
"uid": 1000
}
[user@d1 ansible]$ ansible server1 -m command -a "ls -l /tmp/hello.txt"
192.168.68.157 | CHANGED | rc=0 >>
-rw-r--r-- 1 user user 6 Jun 13 23:28 /tmp/hello.txt
```
* 改變屬性 ( file )
```bash=
[user@d1 ansible]$ ansible server1 -m file -a "path=/tmp/hello.txt owner=root group=root mode=0755"
192.168.68.157 | CHANGED => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python"
},
"changed": true,
"gid": 0,
"group": "root",
"mode": "0755",
"owner": "root",
"path": "/tmp/hello.txt",
"size": 6,
"state": "file",
"uid": 0
}
[user@d1 ansible]$ ansible server1 -m command -a "ls -l /tmp/hello.txt"
192.168.68.157 | CHANGED | rc=0 >>
-rwxr-xr-x 1 root root 6 Jun 13 23:28 /tmp/hello.txt
```
* 腳本使用 (playbook)
* ping
```yaml=
---
- hosts: server1
tasks:
- name: test ping
ping:
```
**結果**

* 新增檔案
```taml=
---
- hosts: server1
gather_facts: no
tasks:
- name: create an empty file under /tmp
command:
chdir: /tmp
cmd: touch a.txt
- name: list all files under /tmp and grep
shell:
chdir: /tmp
cmd: "ls -l | grep a.txt"
register: results
- name: show the results
debug:
msg: "{{ results['stdout'] }}"
```

* 套用變數 ( JinJa2 )
**test3.yml**
```yaml=
---
- hosts: server1
gather_facts: no
vars:
dynamic_world: "World"
tasks:
- name: test template
template:
src: hi.j2
dest: /tmp/hello_world.txt
```
**hi.j2**
```jinja2=
hello "{{ dynamic_world }}"
```
**run**
```bash=
$ ansible-playbook test3.yml
$ ansible server1 -m command -a "cat /tmp/hello_world.txt"
192.168.68.157 | CHANGED | rc=0 >>
hello "World"
```
* 指定作業系統
**test4.yml**
```yaml=
---
- hosts: servers
gather_facts: yes
tasks:
- name: test ping
ping:
- name: install software packages in CentOS
yum:
name:
- vim
- curl
state: present
when: ansible_facts['distribution'] == "CentOS"
```

* 改變網頁伺服器的port
**複製配置檔**
`$ cp /etc/httpd/conf/httpd.conf ./httpd.conf.j2`
**把裡面port 的位置改成j2 的變數格式**

**簡單網頁**
```bash=
$ cat hi.htm
hi
```
**test5.yml**
```yaml=
---
- hosts: server1
gather_facts: no
vars:
listen_port: 8080
tasks:
- name: install httpd
yum:
name:
- httpd
state: present
- name: copy conf file
template:
src: httpd.conf.j2
dest: /etc/httpd/conf/httpd.conf
- name: htm
copy:
src: ./hi.htm
dest: /var/www/html/hi.htm
- name: restart httpd server
service:
name: httpd
state: restarted
```
**結果**

```bash=
$ curl http://d2:8080/hi.htm
hi
```