3.ansible使用和模組化深入解析

2020-08-14 11:06:36

1.主組態檔介紹

ansible組態檔 /etc/ansible/ansible.cfg(一般保持預設)
[defaults]  #預設值
#inventory      = /etc/ansible/hosts  #主機列表組態檔
#library        = /usr/share/my_modules/  #庫檔案存放目錄
#module_utils   = /usr/share/my_module_utils/
#remote_tmp     = ~/.ansible/tmp   #在被控制上執行 並刪除
#local_tmp      = ~/.ansible/tmp  #兩個搭配使用 執行完命令後會自動生成指令碼 到遠端主機 執行完即刪除
#plugin_filters_cfg = /etc/ansible/plugin_filters.yml
#forks          = 5   #併發執行5次
#poll_interval  = 15  #15秒拉取一次數據
#sudo_user      = root  #普通使用者無法在遠端主機管理root 所以要使用sudo
#ask_sudo_pass = True   #每次執行ansible命令是否詢問ssh密碼
#ask_pass      = True
#transport      = smart
#remote_port    = 22   #遠端主機預設埠號
#module_lang    = C
#module_set_locale = False  
#host_key_checking = False #檢查對應伺服器的host_key,建議取消註釋   這個如果不取消就會出現 2情況
#log_path=/var/log/ansible.log #日誌檔案 (取消註釋,建議開啓)

2.沒有建立連線 所以無法ping 通

[root@ansible ~]# cd .ssh/
[root@ansible .ssh]# ls
known_hosts   #這是信任檔案  我們ssh之後就出產生記錄  才能 纔能ping  要不然註釋下面 下麪的預設值  
[root@ansible .ssh]# rm -rf known_hosts

[root@ansible .ssh]# ansible all -m ping -k
SSH password:
10.0.0.48 | FAILED! => {
    "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."
}
10.0.0.49 | FAILED! => {
    "msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this.  Please add this host's fingerprint to your known_hosts file to manage this host."
}

所有的主機都要手動ssh連線一遍才行 
所以
#host_key_checking = False #檢查對應伺服器的host_key,建議取消註釋


#註釋後
[root@ansible .ssh]# ansible all -m ping -k
SSH password:
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

3.ansible系列命令

[root@ansible ~]# ansible  # tab
ansible               ansible-console       ansible-doc-2.7       ansible-playbook      ansible-pull-2.7
ansible-2             ansible-console-2     ansible-galaxy        ansible-playbook-2    ansible-test
ansible-2.7           ansible-console-2.7   ansible-galaxy-2      ansible-playbook-2.7  ansible-vault
ansible-config        ansible-doc           ansible-galaxy-2.7    ansible-pull          ansible-vault-2
ansible-connection    ansible-doc-2         ansible-inventory     ansible-pull-2        ansible-vault-2.7


Ansible系列命令
ansible ansible-doc ansible-playbookansible-vault
ansible-consoleansible-galaxyansible-pull
ansible-doc:顯示模組幫助
ansible-doc [options][module...]
顯示所有模組的文件
-a
-l,--list列出可用模組
-s, --snippet顯示指定模組的playbook片段
範例:
ansible-docl列出所有模組
ansible-doc ping檢視指定模組幫助用法
ansible-doc -s ping檢視指定模組幫助用法

[root@ansible ~]# ansible doc ping  #加上模組名 檢視怎麼使用
usage: ansible [-h] [--version] [-v] [-b] [--become-method BECOME_METHOD]
               [--become-user BECOME_USER] [-K] [-i INVENTORY] [--list-hosts]
               [-l SUBSET] [-P POLL_INTERVAL] [-B SECONDS] [-o] [-t TREE] [-k]
               [--private-key PRIVATE_KEY_FILE] [-u REMOTE_USER]
               [-c CONNECTION] [-T TIMEOUT]
               [--ssh-common-args SSH_COMMON_ARGS]
               [--sftp-extra-args SFTP_EXTRA_ARGS]
               [--scp-extra-args SCP_EXTRA_ARGS]
               [--ssh-extra-args SSH_EXTRA_ARGS] [-C] [--syntax-check] [-D]
               [-e EXTRA_VARS] [--vault-id VAULT_IDS]
               [--ask-vault-pass | --vault-password-file VAULT_PASSWORD_FILES]
               [-f FORKS] [-M MODULE_PATH] [--playbook-dir BASEDIR]
               [-a MODULE_ARGS] [-m MODULE_NAME]
               pattern
ansible: error: unrecognized arguments: ping

#統計ansible模組數量
[root@ansible ~]# ansible-doc -l | wc -l
3387

[root@ansible ~]# ansible-doc -s ping
- name: Try to connect to host, verify a usable python and return `pong' on success
  ping:
      data:                  # Data to return for the `ping' return value. If this parameter is set to `crash', the
                               module will cause an exception.

ansible通過ssh實現設定管理、應用部署、任務執行等功能,建議設定ansible
端能基子金鑰認證的方式聯繫各被管理節點
ansible <host-pattern?[-m module_name] [-a args]
–version顯示版本
-m module指定模組,預設爲command
-v詳細過程→vv -vv更詳細

–list-hosts顯示主機列表,可簡寫—list

[root@ansible ~]# ansible all --list-hosts
  hosts (2):
    10.0.0.48
    10.0.0.49

-k,–ask-pass提示輸入ssh連線密碼,預設Key驗證
-K,–ask-become-pass提示輸入sudo時的口令
-C,–check檢查,並不執行
-T,–timeout=TIMEOUT 執行命令的超時時間,預設10s
-u,–user=REMOTE_USER執行遠端執行的使用者

[root@ansible ~]# ansible webserver -m ping -u y -k
SSH password:
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

[root@ansible ~]# ansible webserver -u y -k -m command -a'ls /root'
SSH password:
10.0.0.48 | FAILED | rc=2 >>
ls: cannot open directory /root: Permission deniednon-zero return code
#做不了許可權以外的事

-b,–become代替l舊版的sudo切換

實戰

1.生成金鑰

[root@ansible ansible]# ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /root/.ssh/id_rsa.
Your public key has been saved in /root/.ssh/id_rsa.pub.
The key fingerprint is:
SHA256:jd0oYIQ0Ms/MYd5V3mV3W3DEr4xfOHbP2dCV3ZIATv0 root@ansible
The key's randomart image is:
+---[RSA 2048]----+
|  o.=.. ..+o  ++*|
|   X.= . + .oo o=|
|    * +   o .o o=|
|     . . + o  E.=|
|        S + .o =.|
|         .  . B +|
|             o *+|
|              ..+|
|                 |
+----[SHA256]-----+

2.拷貝到目標主機

[root@ansible ansible]# ssh-copy-id 10.0.0.48
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '10.0.0.48'"
and check to make sure that only the key(s) you wanted were added.
[root@ansible ansible]# ssh-copy-id 10.0.0.49
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
/usr/bin/ssh-copy-id: INFO: attempting to log in with the new key(s), to filter out any that are already installed
/usr/bin/ssh-copy-id: INFO: 1 key(s) remain to be installed -- if you are prompted now it is to install the new keys
[email protected]'s password:

Number of key(s) added: 1

Now try logging into the machine, with:   "ssh '10.0.0.49'"
and check to make sure that only the key(s) you wanted were added.

3.ansible的Host-pattern

3.1 all

ansible all -m ping

表示所有Inventory中的所有主機

[root@ansible ansible]# ansible all -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
[root@ansible ansible]#

3.2支援分組

ansible webserver -m ping

[root@ansible ansible]# ansible webserver -m ping
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
[root@ansible ansible]# ansible dbserver -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

3.3 * :萬用字元

ansible *server -m ping
[root@ansible ansible]# ansible *server -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
ansible 「10.0.0.*」 -m ping
[root@ansible ansible]# ansible "10.0.0.*" -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
ansible 「*」 -m ping
[root@ansible ansible]# ansible "*" -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

3.4 關係

: 邏輯或

[root@ansible ansible]# ansible webserver:dbserver -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

:& 邏輯與

#必須是兩個分組裏有相同的主機 纔可以使用
ansible 'webserver:&dbserver' -m ping

:!邏輯非

#使用單引號
ansible 'webserver:!dbserver' -m ping

綜合邏輯

#既在webserver和dbserver裏面並且在appserver裏面 不在ftpserver裏面
ansible 'webserver:dbserver:&appservers:!ftpserver' -m ping

3.5正則表達式

ansible "webserver:&dbserver" -m ping
ansible "~(web|db).*\.magedu\.com" -m ping
~ :表示主機裏面是web|db開頭的
. 結尾包含的magedu
[root@ansible ansible]# ansible '~(web|db)' -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}



[root@ansible ansible]# ansible '~(web|db)server' -m ping
10.0.0.49 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}
10.0.0.48 | SUCCESS => {
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    },
    "changed": false,
    "ping": "pong"
}

4.ansible命令執行的過程

ansible命令執行過程

  1. 載入自己的組態檔預設/etc/ansible/ansible.cfg
  2. 載入自己對應的模組檔案,如command
  3. 通過ansible將模組或命令生成對應的臨時py檔案,並將該檔案傳輸至遠端伺服器
    的對應執行使用者$HOME/.ansible/tmp/ansible-tmp-數位/xxX.PY檔案
  4. 給檔案+x執行
  5. 執行並返回結果
  6. 刪除臨時py檔案,sleep o退出

執行狀態︰

  • 綠色∶執行成功並且不需要做改變的操作
  • 黃色︰執行成功並且對目標主機做變更
  • 紅色:執行失敗

檢視詳細的執行命令

 ansible all -m ping -vvv

5.ansible使用範例

#以wang使用者執行ping存活檢測
ansible all -m ping-u wang -k

#以wang sudo至root執行ping存活檢測
ansible all -m ping -u wang-b-k

#以wang sudo至mage使用者執行ping存活檢測
ansible all -m|ping-u wang -b-k --become-user mage

#以wang sudo至root使用者執行ls
ansible all -m command -u wang --become-user=root -a 'ls /root' -b -k -K

6.ansible常見模組

1.簡介

  • Command:在遠端主機執行命令,預設模組,可忽略-m選項

```bash
ansible srvs -m command -a 'service vsftpd start'
ansible srvs-m command -a 'echo magedu |passwd --stdin wang’不成功
>此命令不支援$VARNAME< > |;&等,用shell模組實現
  • Shell :和command相似,用shell執行命令
ansible srv-m shell -a 'echo magedu |passwd -stdin wang'
呼叫bash執行命令類似cat/tmp/stanley.md | awk -F'I'‘iprint $1,$2y&>
/tmp/example.txt這些複雜命令,即使使用shell也可能會失敗,解決辦法∶寫到指令碼
時,copy到遠端,執行,再把需要的結果拉回執行命令的機器
  • Script:執行指令碼
-a "/PATH/TO/SCRIPT_FILE「
snsible websrvs -m script -a f1.sh
  • Copy:從伺服器複製檔案到用戶端
ansible all -m copy -a "src=/root/f1.sh dest=/tmp/f2.sh owner=wang mode=600 backup=yes"
如果目標存在,預設覆蓋,此處指定先備份
ansible all -m copy -a "content='test content\n' dest=/tmp/f1.txt" 利用內容,直接生成目標檔案
  • Fetch:從用戶端取檔案至伺服器端,copy相反,目標可先tar
ansible all -m fetch -a 'src=/root/a.sh dest=/data/scripts'

File: 設定檔案屬性

ansible all -m file -a "path=/root/a.sh owner=wang mode=755"
ansible web -m file -a 'src=/app/testfile dest=/app/testfile-link state=link'

2.範例

1.預設command模組

1.條件判斷
removes    如果存在 執行
creates    如果不存在 執行
#如果存在/etc/fs 檔案 則執行cat
ansible all -a 'removes=/etc/fs cat /etc/fstab'

#如果不存在 所以要執行
ansible all -a 'creates=/etc/fs cat /etc/fstab'
2.切換目錄
 ansible all -a 'chdir=/boot ls'
3.建立使用者
[root@ansible ansible]# ansible 10.0.0.48 -a 'useradd test1'
10.0.0.48 | CHANGED | rc=0 >>

[root@ansible ansible]# ansible 10.0.0.48 -a 'getent passwd test1'
10.0.0.48 | CHANGED | rc=0 >>
test1:x:1002:1002::/home/test1:/bin/bash
4.command對特殊符號有bug

建議用shell模組

[root@ansible ansible]# ansible 10.0.0.48 -a 'echo magedu|passwd --stdin test1'
10.0.0.48 | CHANGED | rc=0 >>
magedu|passwd --stdin test1
[root@ansible ansible]# ansible 10.0.0.48 -a 'getent shadow test1'
10.0.0.48 | CHANGED | rc=0 >>
test1:!!:18488:0:99999:7:::   #!! 提示爲空
[root@ansible ansible]# ansible 10.0.0.48 -a 'echo $HOSTNAME'
10.0.0.48 | CHANGED | rc=0 >>
$HOSTNAME   #直接列印了$HOSTNAME

2.shell模組

shell 比command強
[root@ansible ansible]# ansible 10.0.0.48 -m shell -a 'echo $HOSTNAME'
10.0.0.48 | CHANGED | rc=0 >>
c7-48    #輸出成功

#修改密碼 也是成功的
[root@ansible ansible]# ansible 10.0.0.48 -m shell -a "echo magedu|passwd --stdin test1"
10.0.0.48 | CHANGED | rc=0 >>
Changing password for user test1.
passwd: all authentication tokens updated successfully.
[root@ansible ansible]# ansible 10.0.0.48 -m shell -a "getent shadow test1"       10.0.0.48 | CHANGED | rc=0 >>
test1:$6$2zu5Lawc$5UgDQI8CR7cImwOu.AcTzM9pnM4UjW.svTM9mY3h3HI4nX4ECMEnoVzzwY0kWPaYVRRLL1p/FFzQQEsvaD.hU/:18488:0:99999:7:::

script模組

## 在本地新建一個指令碼
[root@ansible ansible]# vim host.sh 
#!/bin/bash
hostname
[root@ansible ansible]# chmod +X host.sh
[root@ansible ansible]# pwd
/etc/ansible
使用script的模組能使遠端主機執行本地指令碼

[root@ansible ansible]# ansible all -m script -a "/etc/ansible/host.sh"
10.0.0.48 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 10.0.0.48 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 10.0.0.48 closed."
    ],
    "stdout": "c7-48\r\n",
    "stdout_lines": [
        "c7-48"
    ]
}
10.0.0.49 | CHANGED => {
    "changed": true,
    "rc": 0,
    "stderr": "Shared connection to 10.0.0.49 closed.\r\n",
    "stderr_lines": [
        "Shared connection to 10.0.0.49 closed."
    ],
    "stdout": "c7-49\r\n",  #標準輸出
    "stdout_lines": [
        "c7-49"
    ]
}

copy模組

查詢copy選項
ansible-doc -s copy 
  • 將檔案複製到目標主機
ansible all -m copy -a 'src=/root/ansible/selinux dest=/etc/selinux/config backup=yes'

ansible all -a 'cat /etc/selinux/config' #驗證
ansible all -a 'ls /etc/selinux'  #檢視複製檔案
ansible all -m shell -a 'rm -f /etc/selinux/config.*'  #刪除複製的檔案

ansible all -m shell -a 'reboot'
#更改爲selinux後需要重新啓動生效
ansible all -m shell -a 'getenforce' #驗證

#複製完更改許可權
ansible all -m copy -a 'src=/etc/shadow dest=/data/ mode=000 owner=wang'
ansible all -a 'ls -l /data/'  #檢視

#編輯檔案發送到目標主機
ansible all -m copy -a 'content="hello\nthanks\n" dest=/data/f2'
ansible all -m ping -a 'cat /data/f2'
#content裏面是檔案內容

src是本機原始檔
dest是目標檔案
backup=yes 是在推播是進行復制 保留原始檔
mode= 許可權可以設定
owner= 所有者也可以設定
ansible all -a ‘cat /etc/selinux/config’