---
# System prepended metadata

title: Ansible
tags: [docker, Linux]

---

# Ansible

*橘圈表示機器, 灰框表示群組*
![photo_2024-06-14_13-01-32](https://hackmd.io/_uploads/H1KT0SFr0.jpg)
    
**Ansible較適用於中小型的管理** 
**安裝在圖中的主機器上, 讓他去控制其他機器**

**控制方式**
1. ad hoc (在command line 一行一行輸入)
2. script (寫一個ansible 的腳本一次執行多項指令)

---

## 先設定無密碼登入

**建議使用root的無密碼登入, 後續需要進行一些系統的操作才不須提權**
https://hackmd.io/@LSX-0123/SkgsSOt8p

否則後續執行時都須輸入sudo 密碼
![image](https://hackmd.io/_uploads/Bk0YVUKrA.png)

## 安裝及配置
改權限的東東
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
    ```
    ![螢幕擷取畫面 2024-05-29 102206](https://hackmd.io/_uploads/S1brDfV4A.png)


## 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"`
    ![image](https://hackmd.io/_uploads/BkDwKUKB0.png)

    * 腳本

        ```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:
        ```
        **結果**
        ![image](https://hackmd.io/_uploads/ryUEO8tS0.png)

    * 新增檔案
        ```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'] }}"
        ```
        ![photo_2024-06-14_13-54-44](https://hackmd.io/_uploads/B1OUiUFrC.jpg)

* 套用變數 ( 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"

    ```
    ![image](https://hackmd.io/_uploads/HkLCdvFBA.png)

* 改變網頁伺服器的port

    **複製配置檔**
    `$ cp /etc/httpd/conf/httpd.conf ./httpd.conf.j2`

    **把裡面port 的位置改成j2 的變數格式**
    ![image](https://hackmd.io/_uploads/S1q89vFr0.png)

    **簡單網頁**
    ```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

    ```

    **結果**
    ![image](https://hackmd.io/_uploads/BJfE2DYBC.png)
    ```bash=
    $ curl http://d2:8080/hi.htm
    hi
    ```
    
