中文亚洲精品无码_熟女乱子伦免费_人人超碰人人爱国产_亚洲熟妇女综合网

當(dāng)前位置: 首頁(yè) > news >正文

怎樣建設(shè)網(wǎng)站施工上海網(wǎng)站優(yōu)化

怎樣建設(shè)網(wǎng)站施工,上海網(wǎng)站優(yōu)化,微信小程序官網(wǎng)平臺(tái)入口官網(wǎng)登錄,網(wǎng)站制作優(yōu)勢(shì)一、ansible簡(jiǎn)介1. ansible是什么2.ansible的特點(diǎn)ansible的架構(gòu)圖 二、ansible 任務(wù)執(zhí)行1、ansible 任務(wù)執(zhí)行模式2、ansible 執(zhí)行流程3、ansible 命令執(zhí)行過程 二 .Ansible安裝部署1.yum安裝2.ansible 程序結(jié)構(gòu)3、ansible配置文件查找順序4、ansible配置文件5.ansible自動(dòng)化配置…

  • 一、ansible簡(jiǎn)介
    • 1. ansible是什么
    • 2.ansible的特點(diǎn)
    • ansible的架構(gòu)圖
  • 二、ansible 任務(wù)執(zhí)行
    • 1、ansible 任務(wù)執(zhí)行模式
    • 2、ansible 執(zhí)行流程
    • 3、ansible 命令執(zhí)行過程
  • 二 .Ansible安裝部署
    • 1.yum安裝
    • 2.ansible 程序結(jié)構(gòu)
    • 3、ansible配置文件查找順序
    • 4、ansible配置文件
    • 5.ansible自動(dòng)化配置
  • 三、模塊介紹
    • 1.ping模塊
    • 2.command模塊
    • 3.shell模塊
    • 4.copy模塊
    • 5.file模塊
    • 6.fetch 模塊
    • cron模塊
    • 7.yum模塊
    • 8.service 模塊
    • 9.USER模塊
    • 10.group模塊
    • 11.script模塊
    • 12.setup模塊
  • 四、Ansible playbook簡(jiǎn)介
    • Ansible playbook使用場(chǎng)景
      • 1.格式簡(jiǎn)介
      • 2、核心元素
      • 3、基本組件
    • 運(yùn)行三部曲
    • 舉例:部署wordpress
  • 五、角色訂制:roles
    • ① 簡(jiǎn)介
    • ② 角色集合
    • ③ 角色定制實(shí)例
  • 六、 Ansible 性能調(diào)優(yōu)
    • (1) Ansible SSH 關(guān)閉秘鑰檢測(cè)
    • (2) OpenSSH 連接優(yōu)化
    • (3) SSH pipelining 加速 Ansible
    • (4)Ansible Facts 緩存優(yōu)化

一、ansible簡(jiǎn)介

1. ansible是什么

ansible是最受歡迎的自動(dòng)化運(yùn)維工具,基于pythen開發(fā),集合了眾多運(yùn)維工具的優(yōu)點(diǎn),實(shí)現(xiàn)了批量應(yīng)用部署,批量系統(tǒng)配置,批量程序配置
ansible是基于 paramiko 開發(fā)的,并且基于模塊化工作,本身沒有批量部署的能力。真正具有批量部署的是ansible所運(yùn)行的模塊,ansible只是提供一種框架。ansible不需要在遠(yuǎn)程主機(jī)上安裝client/agents,因?yàn)樗鼈兪腔趕sh來和遠(yuǎn)程主機(jī)通訊的。ansible目前已經(jīng)已經(jīng)被紅帽官方收購(gòu),是自動(dòng)化運(yùn)維工具中大家認(rèn)可度最高的,并且上手容易,學(xué)習(xí)簡(jiǎn)單。是每位運(yùn)維工程師必須掌握的技能之一。

2.ansible的特點(diǎn)

1.部署簡(jiǎn)單,只需在主控端部署,被控端不需要部署
2.默認(rèn)使用SSH協(xié)議對(duì)設(shè)備進(jìn)行管理
3.有大量常規(guī)運(yùn)維操作模塊,可實(shí)現(xiàn)日常絕大部分操作
4.配置簡(jiǎn)答,功能強(qiáng)大,擴(kuò)展性強(qiáng)
5.支持API及自定義模塊,可以通過Python輕松擴(kuò)展
6.通過Ploybooks來制定強(qiáng)大的配置,狀態(tài)管理
7. 輕量級(jí),無需在客戶端安裝agent,更新時(shí),只需在操作機(jī)上進(jìn)行一次更新即可;
8. 提供一個(gè)功能強(qiáng)大、操作性強(qiáng)的Web管理界面和REST API接口——AWX平臺(tái)

ansible的架構(gòu)圖

img

Ansible:Ansible核心程序。
HostInventory:記錄由Ansible管理的主機(jī)信息,包括端口、密碼、ip等。
Playbooks:“劇本”YAML格式文件,多個(gè)任務(wù)定義在一個(gè)文件中,定義主機(jī)需要調(diào)用哪些模塊來完成的功能。
CoreModules核心模塊,主要操作是通過調(diào)用核心模塊來完成管理任務(wù)。
CustomModules:自定義模塊,完成核心模塊無法完成的功能,支持多種語言。
ConnectionPlugins:連接插件,Ansible和Host通信使用

二、ansible 任務(wù)執(zhí)行

1、ansible 任務(wù)執(zhí)行模式

Ansible 系統(tǒng)由控制主機(jī)對(duì)被管節(jié)點(diǎn)的操作方式可分為兩類,即ad-hocplaybook

  • ad-hoc模式(點(diǎn)對(duì)點(diǎn)模式) 使用單個(gè)模塊,支持批量執(zhí)行單條命令。ad-hoc 命令是一種可以快速輸入的命令,而且不需要保存起來的命令。就相當(dāng)于bash中的一句話shell。
  • playbook模式(劇本模式) 是Ansible主要管理方式,也是Ansible功能強(qiáng)大的關(guān)鍵所在。playbook通過多個(gè)task集合完成一類功能,如Web服務(wù)的安裝部署、數(shù)據(jù)庫(kù)服務(wù)器的批量備份等??梢院?jiǎn)單地把playbook理解為通過組合多條ad-hoc操作的配置文件。 類似于shell腳本,可以進(jìn)行多個(gè)步驟
  • role模式(角色模式) 類似于多個(gè)腳本導(dǎo)入

2、ansible 執(zhí)行流程

img   簡(jiǎn)單理解就是Ansible在運(yùn)行時(shí), 首先讀取ansible.cfg中的配置, 根據(jù)規(guī)則獲取Inventory中的管理主機(jī)列表, 并行的在這些主機(jī)中執(zhí)行配置的任務(wù), 最后等待執(zhí)行返回的結(jié)果。

3、ansible 命令執(zhí)行過程

  1. 加載自己的配置文件,默認(rèn)/etc/ansible/ansible.cfg
  2. 查找對(duì)應(yīng)的主機(jī)配置文件,找到要執(zhí)行的主機(jī)或者組;
  3. 加載自己對(duì)應(yīng)的模塊文件,如 command;
  4. 通過ansible將模塊或命令生成對(duì)應(yīng)的臨時(shí)py文件(python腳本), 并將該文件傳輸至遠(yuǎn)程服務(wù)器;
  5. 對(duì)應(yīng)執(zhí)行用戶的家目錄的.ansible/tmp/XXX/XXX.PY文件;
  6. 給文件 +x 執(zhí)行權(quán)限;
  7. 執(zhí)行并返回結(jié)果;
  8. 刪除臨時(shí)py文件,sleep 0退出;

二 .Ansible安裝部署

1.yum安裝

[root@ansible ~]# yum install epel-release -y 
[root@ansible ~]# yum install ansible -y

2.ansible 程序結(jié)構(gòu)

安裝目錄如下(yum安裝):   
配置文件目錄:/etc/ansible/   
執(zhí)行文件目錄:/usr/bin/   
Lib庫(kù)依賴目錄:/usr/lib/pythonX.X/site-packages/ansible/   
Help文檔目錄:/usr/share/doc/ansible-X.X.X/   
Man文檔目錄:/usr/share/man/man1/

3、ansible配置文件查找順序

ansible與我們其他的服務(wù)在這一點(diǎn)上有很大不同,這里的配置文件查找是從多個(gè)地方找的,順序如下:

  1. 檢查環(huán)境變量ANSIBLE_CONFIG指向的路徑文件(export ANSIBLE_CONFIG=/etc/ansible.cfg);
  2. ~/.ansible.cfg,檢查當(dāng)前目錄下的ansible.cfg配置文件;
  3. /etc/ansible.cfg檢查etc目錄的配置文件。

4、ansible配置文件

ansible 的配置文件為/etc/ansible/ansible.cfg,ansible 有許多參數(shù),下面我們列出一些常見的參數(shù):

inventory = /etc/ansible/hosts #這個(gè)參數(shù)表示資源清單inventory文件的位置
library = /usr/share/ansible   #指向存放Ansible模塊的目錄,支持多個(gè)目錄方式,只要用冒號(hào)(:)隔開就可以
forks = 5       #并發(fā)連接數(shù),默認(rèn)為5
sudo_user = root        #設(shè)置默認(rèn)執(zhí)行命令的用戶
remote_port = 22        #指定連接被管節(jié)點(diǎn)的管理端口,默認(rèn)為22端口,建議修改,能夠更加安全
host_key_checking = False #設(shè)置是否檢查SSH主機(jī)的密鑰,值為True/False。關(guān)閉后第一次連接不會(huì)提示配置實(shí)例
timeout = 60        #設(shè)置SSH連接的超時(shí)時(shí)間,單位為秒
log_path = /var/log/ansible.log     #指定一個(gè)存儲(chǔ)ansible日志的文件(默認(rèn)不記錄日志)

5.ansible自動(dòng)化配置

[root@ansible ~]# vim /etc/hosts  #域名解析,不解析也可以直接使用ip
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6
10.36.192.100 package.qf.com
192.168.20.142 web1
192.168.20.143 web2
[root@ansible ~]# vim /etc/ansible/hosts  #添加ansible組成員
web1
web2[web]
web1
web2
[root@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:ehSHBudIgje/wFwNB23QgqAVvh8sOB+QnNCa1oJb7r8 root@ansible
The key's randomart image is:
+---[RSA 2048]----+
|..++..*Bo        |
|o=+ +oo*=.       |
|==o+ +.o= .      |
|+=.++ .. o       |
|++= o. .S        |
|.o.+ ..o         |
| .. . . .        |
|  .    .         |
|   .E.           |
+----[SHA256]-----+
[root@ansible ~]# ls
anaconda-ks.cfg  yum.repo.sh
[root@ansible ~]# ssh-copy-id 192.168.2
0.142
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.20.142 (192.168.20.142)' can't be established.
ECDSA key fingerprint is SHA256:dWovuygINJWYMOHuvV0FwX0pLKMURbVczsPeHQBI1Ts.
ECDSA key fingerprint is MD5:68:84:47:c5:45:13:75:ce:98:40:2d:8f:be:2f:71:c2.
Are you sure you want to continue connecting (yes/no)? yes
/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
root@192.168.20.142's password: Number of key(s) added: 1Now try logging into the machine, with:   "ssh '192.168.20.142'"
and check to make sure that only the key(s) you wanted were added.[root@ansible ~]# ssh-copy-id 192.168.20.143
/usr/bin/ssh-copy-id: INFO: Source of key(s) to be installed: "/root/.ssh/id_rsa.pub"
The authenticity of host '192.168.20.143 (192.168.20.143)' can't be established.
ECDSA key fingerprint is SHA256:dWovuygINJWYMOHuvV0FwX0pLKMURbVczsPeHQBI1Ts.
ECDSA key fingerprint is MD5:68:84:47:c5:45:13:75:ce:98:40:2d:8f:be:2f:71:c2.
Are you sure you want to continue connecting (yes/no)? yes
/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
root@192.168.20.143's password: Number of key(s) added: 1Now try logging into the machine, with:   "ssh '192.168.20.143'"
and check to make sure that only the key(s) you wanted were added.

組成員可以使用通配符來匹配,這樣對(duì)于一些標(biāo)準(zhǔn)化的管理來說就很輕松方便了

三、模塊介紹

1.ping模塊

使用ansible web -m ping命令來進(jìn)行主機(jī)連通性測(cè)試

[root@ansible ~]# ansible web1 -m ping
web1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"
}
[root@ansible ~]# ansible web2 -m ping 
web2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"
}
[root@ansible ~]# ansible web -m ping
web2 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"
}
web1 | SUCCESS => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": false, "ping": "pong"
}

2.command模塊

這個(gè)模塊可以直接在遠(yuǎn)程主機(jī)上執(zhí)行命令,并將結(jié)果返回給主機(jī)

chdir    # 在執(zhí)行命令之前,先切換到該目錄
executable # 切換shell來執(zhí)行命令,需要使用命令的絕對(duì)路徑
free_form   # 要執(zhí)行的Linux指令,一般使用Ansible的-a參數(shù)代替。
creates   # 一個(gè)文件名,當(dāng)這個(gè)文件存在,則該命令不執(zhí)行,可以用來做判斷
removes # 一個(gè)文件名,這個(gè)文件不存在,則該命令不執(zhí)行

[root@ansible ~]# ansible web -m command -a 'ls'
web2 | CHANGED | rc=0 >>
anaconda-ks.cfg
file
yum.repo.sh
web1 | CHANGED | rc=0 >>
anaconda-ks.cfg
file
yum.repo.sh

不會(huì)通過shell進(jìn)行處理,比如$HOME和操作如"<“,”>“,”|“,”;“,”&" 工作(需要使用(shell)模塊實(shí)現(xiàn)這些功能)。注意,該命令不支持| 管道命令。

chdir 先切換目錄在執(zhí)行命令
[root@ansible ~]# ansible web -m command -a 'chdir=/data touch file'
[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.
web2 | CHANGED | rc=0 >>web1 | CHANGED | rc=0 >>
[root@ansible ~]# ansible web -m command -a 'chdir=/data ls -l'
web2 | CHANGED | rc=0 >>
總用量 8
-rw-r--r-- 1 root root  0 11月  9 13:15 aaa.jpg
lrwxrwxrwx 1 root root 13 11月  9 13:15 bbb.jpg -> /data/aaa.jpg
-rw-r--r-- 1 root root  0 11月  9 13:36 fileweb1 | CHANGED | rc=0 >>
總用量 8
-rw-r--r-- 1 root root  0 11月  9 13:14 aaa.jpg
lrwxrwxrwx 1 root root 13 11月  9 13:15 bbb.jpg -> /data/aaa.jpg
-rw-r--r-- 1 root root  0 11月  9 13:36 file
[root@ansible ~]# ansible web -m command -a 'creates=/data/ ls'
web2 | SUCCESS | rc=0 >>
skipped, since /data/ exists
web1 | SUCCESS | rc=0 >>
skipped, since /data/ exists
[root@ansible ~]# ansible web -m command -a 'removes=/data/ ls'
web2 | CHANGED | rc=0 >>
anaconda-ks.cfg
file
yum.repo.sh
web1 | CHANGED | rc=0 >>
anaconda-ks.cfg
file
yum.repo.sh
[root@ansible ~]# ansible web -m command -a 'creates=/data/dir ls'
web2 | CHANGED | rc=0 >>
anaconda-ks.cfg
file
yum.repo.sh
web1 | CHANGED | rc=0 >>
anaconda-ks.cfg
file
yum.repo.sh
[root@ansible ~]# ansible web -m command -a 'removes=/data/dir ls'
web2 | SUCCESS | rc=0 >>
skipped, since /data/dir does not exist
web1 | SUCCESS | rc=0 >>
skipped, since /data/dir does not exist

3.shell模塊

shell模塊可以在遠(yuǎn)程主機(jī)上調(diào)用shell解釋器運(yùn)行命令,支持shell的各種功能

[root@ansible ~]# ansible web -m shell -a 'cat /etc/passwd | grep root'
web2 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
web1 | CHANGED | rc=0 >>
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin

只要是我們的shell命令,都可以通過這個(gè)模塊在遠(yuǎn)程主機(jī)上運(yùn)行

4.copy模塊

模塊用于將文件復(fù)制到遠(yuǎn)程主機(jī),同時(shí)支持給定內(nèi)容生成文件和修改權(quán)限等

src     #被復(fù)制到遠(yuǎn)程主機(jī)的本地文件??梢允墙^對(duì)路徑,也可以是相對(duì)路徑。如果路徑是一個(gè)目錄,則會(huì)遞歸復(fù)制,用法類似于"rsync"
content  #用于替換"src",可以直接指定文件的值
dest    #必選項(xiàng),將源文件復(fù)制到的遠(yuǎn)程主機(jī)的絕對(duì)路徑
backup   #當(dāng)文件內(nèi)容發(fā)生改變后,在覆蓋之前把源文件備份,備份文件包含時(shí)間信息
directory_mode    #遞歸設(shè)定目錄的權(quán)限,默認(rèn)為系統(tǒng)默認(rèn)權(quán)限
force    #當(dāng)目標(biāo)主機(jī)包含該文件,但內(nèi)容不同時(shí),設(shè)為"yes",表示強(qiáng)制覆蓋;設(shè)為"no",表示目標(biāo)主機(jī)的目標(biāo)位置不存在該文件才復(fù)制。默認(rèn)為"yes"
others #所有的 file 模塊中的選項(xiàng)可以在這里使用

復(fù)制文件

[root@ansible ~]# ansible web -m copy -a 'src=/root/hello dest=/data/hello'
web2 | SUCCESS => {"changed": false, "dest": "/data/hello/", "src": "/root/hello"
}
web1 | SUCCESS => {"changed": false, "dest": "/data/hello/", "src": "/root/hello"
}
[root@ansible ~]# ansible web -m copy -a 'content="I am zx\n" dest=/data/name mode=666'
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "checksum": "26cb5bd8bbbe3a7c26dd7ea358ff2bdf00ba7dc2", "dest": "/data/name", "gid": 0, "group": "root", "md5sum": "c3a60e23801dec079e23a2278f3c45af", "mode": "0666", "owner": "root", "size": 8, "src": "/root/.ansible/tmp/ansible-tmp-1699509721.65-6361-39694660058027/source", "state": "file", "uid": 0
}
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "checksum": "26cb5bd8bbbe3a7c26dd7ea358ff2bdf00ba7dc2", "dest": "/data/name", "gid": 0, "group": "root", "md5sum": "c3a60e23801dec079e23a2278f3c45af", "mode": "0666", "owner": "root", "size": 8, "src": "/root/.ansible/tmp/ansible-tmp-1699509721.65-6363-47560471525069/source", "state": "file", "uid": 0
}#查看一下我們生成的文件及其權(quán)限
[root@ansible ~]# ansible web -m shell -a 'ls -l /data'
web2 | CHANGED | rc=0 >>
總用量 1
-rw-rw-rw- 1 root root  8 11月  9 14:02 name
web1 | CHANGED | rc=0 >>
總用量 1
-rw-rw-rw- 1 root root  8 11月  9 14:01 name

看出我們的name文件已經(jīng)生成,并且權(quán)限為666

[root@ansible ~]# ansible web -m copy -a 'content="I am zhangxiao\n" backup=yes  dest=/data/name mode=666'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "backup_file": "/data/name.12174.2023-11-09@14:05:39~", "changed": true, "checksum": "9421436680fddec0ef052697e1f8193f05477718", "dest": "/data/name", "gid": 0, "group": "root", "md5sum": "3f7addfff5ebd2e9b7a4b3b0805ce8fe", "mode": "0666", "owner": "root", "size": 15, "src": "/root/.ansible/tmp/ansible-tmp-1699509935.19-6479-111214173298969/source", "state": "file", "uid": 0
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "backup_file": "/data/name.15224.2023-11-09@14:05:32~", "changed": true, "checksum": "9421436680fddec0ef052697e1f8193f05477718", "dest": "/data/name", "gid": 0, "group": "root", "md5sum": "3f7addfff5ebd2e9b7a4b3b0805ce8fe", "mode": "0666", "owner": "root", "size": 15, "src": "/root/.ansible/tmp/ansible-tmp-1699509935.19-6477-223241063689385/source", "state": "file", "uid": 0
}
[root@ansible ~]# ansible web -m shell -a 'ls -l /data'
web2 | CHANGED | rc=0 >>
總用量 8
-rw-rw-rw- 1 root root 15 11月  9 14:05 name
-rw-rw-rw- 1 root root  8 11月  9 14:02 name.12174.2023-11-09@14:05:39~web1 | CHANGED | rc=0 >>
總用量 8
-rw-rw-rw- 1 root root 15 11月  9 14:05 name
-rw-rw-rw- 1 root root  8 11月  9 14:01 name.15224.2023-11-09@14:05:32~[root@ansible ~]# ansible web -m shell -a 'cat /data/name'
web2 | CHANGED | rc=0 >>
I am zhangxiao
web1 | CHANGED | rc=0 >>
I am zhangxiao

源文件被備份

5.file模塊

模塊主要用于設(shè)置文件的屬性,比如創(chuàng)建文件、創(chuàng)建鏈接文件、刪除文件

force  #需要在兩種情況下強(qiáng)制創(chuàng)建軟鏈接,一種是源文件不存在,但之后會(huì)建立的情況下;另一種是目標(biāo)軟鏈接已存在,需要先取消之前的軟鏈,然后創(chuàng)建新的軟鏈,有兩個(gè)選項(xiàng):yes|no

group  #定義文件/目錄的屬組。后面可以加上

mode:定義文件/目錄的權(quán)限

owner  #定義文件/目錄的屬主。后面必須跟上

path:定義文件/目錄的路徑

recurse  #遞歸設(shè)置文件的屬性,只對(duì)目錄有效,后面跟上

src:被鏈接的源文件路徑,只應(yīng)用于state=link的情況

dest  #被鏈接到的路徑,只應(yīng)用于state=link的情況

state  #狀態(tài),有以下選項(xiàng):

directory:如果目錄不存在,就創(chuàng)建目錄 link:創(chuàng)建軟鏈接 hard:創(chuàng)建硬鏈接 touch:如果文件不存在,則會(huì)創(chuàng)建一個(gè)新的文件,如果文件或目錄已存在,則更新其最后修改時(shí)間 absent:刪除目錄、文件或者取消鏈接文件

創(chuàng)建目錄
[root@ansible ~]# ansible web -m file -a 'path=/data/app state=directory'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/data/app", "size": 6, "state": "directory", "uid": 0
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/data/app", "size": 6, "state": "directory", "uid": 0
}
[root@ansible ~]# ansible web -m shell -a 'ls -l /data/'
web2 | CHANGED | rc=0 >>
總用量 8
drwxr-xr-x 2 root root  6 11月  9 14:14 app總用量 8
drwxr-xr-x 2 root root  6 11月  9 14:14 app
[root@ansible ~]# ansible web -m file -a 'path=/data/app state=directory'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/data/app", "size": 6, "state": "directory", "uid": 0
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "gid": 0, "group": "root", "mode": "0755", "owner": "root", "path": "/data/app", "size": 6, "state": "directory", "uid": 0
}
[root@ansible ~]# ansible web -m shell -a 'ls -l /data/'
web2 | CHANGED | rc=0 >>
總用量 8
-rw-r--r-- 1 root root  0 11月  9 13:15 aaa.jpg
drwxr-xr-x 2 root root  6 11月  9 14:14 app
lrwxrwxrwx 1 root root 13 11月  9 13:15 bbb.jpg -> /data/aaa.jpg
-rw-r--r-- 1 root root  0 11月  9 13:36 file
-rw-rw-rw- 1 root root 15 11月  9 14:05 name
-rw-rw-rw- 1 root root  8 11月  9 14:02 name.12174.2023-11-09@14:05:39~
web1 | CHANGED | rc=0 >>
總用量 8
-rw-r--r-- 1 root root  0 11月  9 13:14 aaa.jpg
drwxr-xr-x 2 root root  6 11月  9 14:14 app
lrwxrwxrwx 1 root root 13 11月  9 13:15 bbb.jpg -> /data/aaa.jpg
-rw-r--r-- 1 root root  0 11月  9 13:36 file
-rw-rw-rw- 1 root root 15 11月  9 14:05 name
-rw-rw-rw- 1 root root  8 11月  9 14:01 name.15224.2023-11-09@14:05:32~
[root@ansible ~]# ansible web -m file -a 'path=/data/ccc.jpg src=/data/aaa.jpg state=link'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "dest": "/data/ccc.jpg", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 13, "src": "/data/aaa.jpg", "state": "link", "uid": 0
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "dest": "/data/ccc.jpg", "gid": 0, "group": "root", "mode": "0777", "owner": "root", "size": 13, "src": "/data/aaa.jpg", "state": "link", "uid": 0
}[root@ansible ~]# ansible web -m shell -a 'ls -l /data/'
web2 | CHANGED | rc=0 >>
總用量 8
-rw-r--r-- 1 root root  0 11月  9 13:15 aaa.jpg
drwxr-xr-x 2 root root  6 11月  9 14:14 app
lrwxrwxrwx 1 root root 13 11月  9 14:20 ccc.jpg -> /data/aaa.jpg
-rw-r--r-- 1 root root  0 11月  9 13:36 file
-rw-rw-rw- 1 root root 15 11月  9 14:05 name
-rw-rw-rw- 1 root root  8 11月  9 14:02 name.12174.2023-11-09@14:05:39~
web1 | CHANGED | rc=0 >>
總用量 8
-rw-r--r-- 1 root root  0 11月  9 13:14 aaa.jpg
drwxr-xr-x 2 root root  6 11月  9 14:14 app
lrwxrwxrwx 1 root root 13 11月  9 14:20 ccc.jpg -> /data/aaa.jpg
-rw-r--r-- 1 root root  0 11月  9 13:36 file
-rw-rw-rw- 1 root root 15 11月  9 14:05 name
-rw-rw-rw- 1 root root  8 11月  9 14:01 name.15224.2023-11-09@14:05:32~
[root@ansible ~]# ansible web -m file -a 'path=/data/app state=absent'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "path": "/data/app", "state": "absent"
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "path": "/data/app", "state": "absent"
}

6.fetch 模塊

從遠(yuǎn)程某主機(jī)獲取(復(fù)制)文件到本地

dest:用來存放文件的目錄

src:在遠(yuǎn)程拉取的文件,并且必須是一個(gè)file,不能是目錄

[root@ansible ~]# ansible web -m fetch -a 'src=/root/yum.repo.sh dest=/opt'
web2 | CHANGED => {"changed": true, "checksum": "35c324d53225248f3def18df5d12f21b0b74ac1d", "dest": "/opt/web2/root/yum.repo.sh", "md5sum": "d907be33e4cfa20622c4e8054a589685", "remote_checksum": "35c324d53225248f3def18df5d12f21b0b74ac1d", "remote_md5sum": null
}
web1 | CHANGED => {"changed": true, "checksum": "35c324d53225248f3def18df5d12f21b0b74ac1d", "dest": "/opt/web1/root/yum.repo.sh", "md5sum": "d907be33e4cfa20622c4e8054a589685", "remote_checksum": "35c324d53225248f3def18df5d12f21b0b74ac1d", "remote_md5sum": null
}
[root@ansible ~]# cd /opt
[root@ansible opt]# ll
總用量 0
drwxr-xr-x 3 root root 18 11月  9 14:27 web1
drwxr-xr-x 3 root root 18 11月  9 14:27 web2

cron模塊

該模塊適用于管理cron計(jì)劃任務(wù)的。   
其使用的語法跟我們的crontab文件中的語法一致
0

day= #日應(yīng)該運(yùn)行的工作( 1-31, , /2, )

hour= # 小時(shí) ( 0-23, , /2, )

minute= #分鐘( 0-59, , /2, )

month= # 月( 1-12, *, /2, )

weekday= # 周 ( 0-6 for Sunday-Saturday, )

job= #指明運(yùn)行的命令是什么

name= #定時(shí)任務(wù)描述

reboot # 任務(wù)在重啟時(shí)運(yùn)行,不建議使用,建議使用special_time

special_time #特殊的時(shí)間范圍,參數(shù):reboot(重啟時(shí)),annually(每年),monthly(每月),weekly(每周),daily(每天),hourly(每小時(shí))

state #指定狀態(tài),present表示添加定時(shí)任務(wù),也是默認(rèn)設(shè)置,absent表示刪除定時(shí)任務(wù)

user # 以哪個(gè)用戶的身份執(zhí)行

創(chuàng)建計(jì)劃任務(wù)

[root@ansible ~]# ansible web -m cron -a 'name="ping baidu" minute=*/20 job="ping -w1 -c1 baidu.com &> /dev/null "'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "envs": [], "jobs": ["ping baidu"]
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "envs": [], "jobs": ["ping baidu"]
}
[root@ansible ~]# ansible web -m shell -a 'crontab -l'
web2 | CHANGED | rc=0 >>
#Ansible: ping baidu
*/20 * * * * ping -w1 -c1 baidu.com &> /dev/null 
web1 | CHANGED | rc=0 >>
#Ansible: ping baidu
*/20 * * * * ping -w1 -c1 baidu.com &> /dev/null 

刪除計(jì)劃任務(wù)

[root@ansible ~]# ansible web -m cron -a 'name="ping baidu" minute=*/20 job="ping -w1 -c1 baidu.com &> /dev/null"'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "envs": [], "jobs": ["ping baidu"]
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "envs": [], "jobs": ["ping baidu"]
}

7.yum模塊

模塊主要用于軟件的安裝

name=   #所安裝的包的名稱

state=  #present—>安裝, latest—>安裝最新的, absent—> 卸載軟件。

update_cache  #強(qiáng)制更新yum的緩存

conf_file  #指定遠(yuǎn)程yum安裝時(shí)所依賴的配置文件(安裝本地已有的包)。

disable_gpg_check  #是否禁止GPG checking,只用于presentor latest

disablerepo  #臨時(shí)禁止使用yum庫(kù)。 只用于安裝或更新時(shí)。

enablerepo   #臨時(shí)使用的yum庫(kù)。只用于安裝或更新時(shí)。

安裝軟件包

web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "changes": {"installed": ["httpd"]}, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-99.el7.centos.1 will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-99.el7.centos.1 for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Running transaction check\n---> Package apr.x86_64 0:1.4.8-7.el7 will be installed\n---> Package apr-util.x86_64 0:1.5.2-6.el7_9.1 will be installed\n---> Package httpd-tools.x86_64 0:2.4.6-99.el7.centos.1 will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package          Arch        Version                      Repository      Size\n================================================================================\nInstalling:\n httpd            x86_64      2.4.6-99.el7.centos.1        myupdates      2.7 M\nInstalling for dependencies:\n apr              x86_64      1.4.8-7.el7                  mybase         104 k\n apr-util         x86_64      1.5.2-6.el7_9.1              myupdates       92 k\n httpd-tools      x86_64      2.4.6-99.el7.centos.1        myupdates       94 k\n mailcap          noarch      2.1.41-2.el7                 mybase          31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+4 Dependent packages)\n\nTotal download size: 3.0 M\nInstalled size: 10 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                               23 MB/s | 3.0 MB  00:00     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : apr-1.4.8-7.el7.x86_64                                       1/5 \n  Installing : apr-util-1.5.2-6.el7_9.1.x86_64                              2/5 \n  Installing : httpd-tools-2.4.6-99.el7.centos.1.x86_64                     3/5 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 \n  Installing : httpd-2.4.6-99.el7.centos.1.x86_64                           5/5 \n  Verifying  : httpd-2.4.6-99.el7.centos.1.x86_64                           1/5 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  2/5 \n  Verifying  : apr-1.4.8-7.el7.x86_64                                       3/5 \n  Verifying  : httpd-tools-2.4.6-99.el7.centos.1.x86_64                     4/5 \n  Verifying  : apr-util-1.5.2-6.el7_9.1.x86_64                              5/5 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-99.el7.centos.1                                          \n\nDependency Installed:\n  apr.x86_64 0:1.4.8-7.el7                    apr-util.x86_64 0:1.5.2-6.el7_9.1 \n  httpd-tools.x86_64 0:2.4.6-99.el7.centos.1  mailcap.noarch 0:2.1.41-2.el7     \n\nComplete!\n"]
}
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "changes": {"installed": ["httpd"]}, "msg": "", "rc": 0, "results": ["Loaded plugins: fastestmirror\nLoading mirror speeds from cached hostfile\nResolving Dependencies\n--> Running transaction check\n---> Package httpd.x86_64 0:2.4.6-99.el7.centos.1 will be installed\n--> Processing Dependency: httpd-tools = 2.4.6-99.el7.centos.1 for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Processing Dependency: /etc/mime.types for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Processing Dependency: libaprutil-1.so.0()(64bit) for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Processing Dependency: libapr-1.so.0()(64bit) for package: httpd-2.4.6-99.el7.centos.1.x86_64\n--> Running transaction check\n---> Package apr.x86_64 0:1.4.8-7.el7 will be installed\n---> Package apr-util.x86_64 0:1.5.2-6.el7_9.1 will be installed\n---> Package httpd-tools.x86_64 0:2.4.6-99.el7.centos.1 will be installed\n---> Package mailcap.noarch 0:2.1.41-2.el7 will be installed\n--> Finished Dependency Resolution\n\nDependencies Resolved\n\n================================================================================\n Package          Arch        Version                      Repository      Size\n================================================================================\nInstalling:\n httpd            x86_64      2.4.6-99.el7.centos.1        myupdates      2.7 M\nInstalling for dependencies:\n apr              x86_64      1.4.8-7.el7                  mybase         104 k\n apr-util         x86_64      1.5.2-6.el7_9.1              myupdates       92 k\n httpd-tools      x86_64      2.4.6-99.el7.centos.1        myupdates       94 k\n mailcap          noarch      2.1.41-2.el7                 mybase          31 k\n\nTransaction Summary\n================================================================================\nInstall  1 Package (+4 Dependent packages)\n\nTotal download size: 3.0 M\nInstalled size: 10 M\nDownloading packages:\n--------------------------------------------------------------------------------\nTotal                                               15 MB/s | 3.0 MB  00:00     \nRunning transaction check\nRunning transaction test\nTransaction test succeeded\nRunning transaction\n  Installing : apr-1.4.8-7.el7.x86_64                                       1/5 \n  Installing : apr-util-1.5.2-6.el7_9.1.x86_64                              2/5 \n  Installing : httpd-tools-2.4.6-99.el7.centos.1.x86_64                     3/5 \n  Installing : mailcap-2.1.41-2.el7.noarch                                  4/5 \n  Installing : httpd-2.4.6-99.el7.centos.1.x86_64                           5/5 \n  Verifying  : httpd-2.4.6-99.el7.centos.1.x86_64                           1/5 \n  Verifying  : mailcap-2.1.41-2.el7.noarch                                  2/5 \n  Verifying  : apr-1.4.8-7.el7.x86_64                                       3/5 \n  Verifying  : httpd-tools-2.4.6-99.el7.centos.1.x86_64                     4/5 \n  Verifying  : apr-util-1.5.2-6.el7_9.1.x86_64                              5/5 \n\nInstalled:\n  httpd.x86_64 0:2.4.6-99.el7.centos.1                                          \n\nDependency Installed:\n  apr.x86_64 0:1.4.8-7.el7                    apr-util.x86_64 0:1.5.2-6.el7_9.1 \n  httpd-tools.x86_64 0:2.4.6-99.el7.centos.1  mailcap.noarch 0:2.1.41-2.el7     \n\nComplete!\n"]
}

8.service 模塊

該模塊用于服務(wù)程序的管理。

arguments #命令行提供額外的參數(shù)
enabled #設(shè)置開機(jī)啟動(dòng)。
name= #服務(wù)名稱
runlevel #開機(jī)啟動(dòng)的級(jí)別,一般不用指定。
sleep #在重啟服務(wù)的過程中,是否等待。如在服務(wù)關(guān)閉以后等待2秒再啟動(dòng)。(定義在劇本中。)
state #有四種狀態(tài),分別為:started—>啟動(dòng)服務(wù), stopped—>停止服務(wù), restarted—>重啟服務(wù), reloaded—>重載配置

開啟服務(wù)并設(shè)置開機(jī)自啟

[root@ansible ~]# ansible web -m service -a 'name=httpd state=started enabled=true'

關(guān)閉服務(wù)

[root@ansible ~]# ansible web -m service -a 'name=httpd state=stopped'
[root@ansible ~]# curl -Ik 192.168.20.142
curl: (7) Failed connect to 192.168.20.142:80; 拒絕連接
[root@ansible ~]# curl -Ik 192.168.20.143
curl: (7) Failed connect to 192.168.20.143:80; 拒絕連接

9.USER模塊

該模塊主要是用來管理用戶賬號(hào)
comment  # 用戶的描述信息
createhome  # 是否創(chuàng)建家目錄
force  # 在使用state=absent時(shí), 行為與userdel –force一致.
group  # 指定基本組
groups  # 指定附加組,如果指定為(groups=)表示刪除所有組
home   # 指定用戶家目錄
move_home  # 如果設(shè)置為home=時(shí), 試圖將用戶主目錄移動(dòng)到指定的目錄
name  # 指定用戶名
non_unique  # 該選項(xiàng)允許改變非唯一的用戶ID值
password  # 指定用戶密碼,對(duì)密碼加密可以使用python的crypt和passlib
remove  # 在使用state=absent時(shí), 行為是與userdel –remove一致
shell  # 指定默認(rèn)shell
state  # 設(shè)置帳號(hào)狀態(tài),不指定為創(chuàng)建,指定值為absent表示刪除
system  # 當(dāng)創(chuàng)建一個(gè)用戶,設(shè)置這個(gè)用戶是系統(tǒng)用戶。這個(gè)設(shè)置不能更改現(xiàn)有用戶
uid  # 指定用戶的uid

[root@ansible ~]# ansible web -m user -a 'name=king uid=6666'
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "comment": "", "create_home": true, "group": 6666, "home": "/home/king", "name": "king", "shell": "/bin/bash", "state": "present", "system": false, "uid": 6666
}
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "comment": "", "create_home": true, "group": 6666, "home": "/home/king", "name": "king", "shell": "/bin/bash", "state": "present", "system": false, "uid": 6666
}
[root@ansible ~]# ansible web -m shell -a 'id king'
web1 | CHANGED | rc=0 >>
uid=6666(king) gid=6666(king) 組=6666(king)
web2 | CHANGED | rc=0 >>
uid=6666(king) gid=6666(king) 組=6666(king)

刪除用戶

[root@ansible ~]# ansible web -m user -a 'name=king state=absent'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "force": false, "name": "king", "remove": false, "state": "absent"
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "force": false, "name": "king", "remove": false, "state": "absent"
}
[root@ansible ~]# ansible web -m shell -a 'id king'
web2 | FAILED | rc=1 >>
id: king: no such usernon-zero return code
web1 | FAILED | rc=1 >>
id: king: no such usernon-zero return code

10.group模塊

該模塊主要用于添加或刪除組
gid=  #設(shè)置組的GID號(hào)
name=  #指定組的名稱
state=  #指定組的狀態(tài),默認(rèn)為創(chuàng)建,設(shè)置值為absent為刪除 system=  #設(shè)置值為yes,表示創(chuàng)建為系統(tǒng)組

創(chuàng)建組

[root@ansible ~]# ansible web -m group -a 'name=liuliu gid=3333'
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "gid": 3333, "name": "liuliu", "state": "present", "system": false
}
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "gid": 3333, "name": "liuliu", "state": "present", "system": false
}
[root@ansible ~]# ansible web -m shell -a 'grep '3333' /etc/group'
web2 | CHANGED | rc=0 >>
liuliu:x:3333:
web1 | CHANGED | rc=0 >>
liuliu:x:3333:

刪除組

[root@ansible ~]# ansible web -m group -a 'name=liuliu state=absent'
web2 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "name": "liuliu", "state": "absent"
}
web1 | CHANGED => {"ansible_facts": {"discovered_interpreter_python": "/usr/bin/python"}, "changed": true, "name": "liuliu", "state": "absent"
}
[root@ansible ~]# ansible web -m shell -a 'grep '3333' /etc/group'
web2 | FAILED | rc=1 >>
non-zero return code
web1 | FAILED | rc=1 >>
non-zero return code

11.script模塊

模塊用于將本機(jī)的腳本在被管理端的機(jī)器上運(yùn)行

[root@ansible ~]# ansible web -m script -a '/root/a.sh'
web2 | CHANGED => {"changed": true, "rc": 0, "stderr": "Shared connection to web2 closed.\r\n", "stderr_lines": ["Shared connection to web2 closed."], "stdout": "", "stdout_lines": []
}
web1 | CHANGED => {"changed": true, "rc": 0, "stderr": "Shared connection to web1 closed.\r\n", "stderr_lines": ["Shared connection to web1 closed."], "stdout": "", "stdout_lines": []
}
[root@ansible ~]# ansible web -m shell -a 'cat /tmp/disk_total.log'
web2 | CHANGED | rc=0 >>
2023年 11月 09日 星期四 18:20:15 CST
文件系統(tǒng)                 容量  已用  可用 已用% 掛載點(diǎn)
devtmpfs                 1.9G     0  1.9G    0% /dev
tmpfs                    1.9G     0  1.9G    0% /dev/shm
tmpfs                    1.9G   12M  1.9G    1% /run
tmpfs                    1.9G     0  1.9G    0% /sys/fs/cgroup
/dev/mapper/centos-root   35G  1.5G   34G    5% /
/dev/sda1               1014M  150M  865M   15% /boot
tmpfs                    378M     0  378M    0% /run/user/0
web1 | CHANGED | rc=0 >>
2023年 11月 09日 星期四 18:20:08 CST
文件系統(tǒng)                 容量  已用  可用 已用% 掛載點(diǎn)
devtmpfs                 1.9G     0  1.9G    0% /dev
tmpfs                    1.9G     0  1.9G    0% /dev/shm
tmpfs                    1.9G   12M  1.9G    1% /run
tmpfs                    1.9G     0  1.9G    0% /sys/fs/cgroup
/dev/mapper/centos-root   35G  1.6G   34G    5% /
/dev/sda1               1014M  150M  865M   15% /boot
tmpfs                    378M     0  378M    0% /run/user/0

12.setup模塊

該模塊主要用于收集信息,是通過調(diào)用facts組件來實(shí)現(xiàn)的。

 [root@ansible ~]# ansible web -m setup -a 'filter="*mem*"'
web2 | SUCCESS => {"ansible_facts": {"ansible_memfree_mb": 3015, "ansible_memory_mb": {"nocache": {"free": 3484, "used": 286}, "real": {"free": 3015, "total": 3770, "used": 755}, "swap": {"cached": 0, "free": 4095, "total": 4095, "used": 0}}, "ansible_memtotal_mb": 3770, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false
}
web1 | SUCCESS => {"ansible_facts": {"ansible_memfree_mb": 3158, "ansible_memory_mb": {"nocache": {"free": 3489, "used": 281}, "real": {"free": 3158, "total": 3770, "used": 612}, "swap": {"cached": 0, "free": 4095, "total": 4095, "used": 0}}, "ansible_memtotal_mb": 3770, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false
}

保存信息

[root@ansible ~]# ansible web -m setup -a 'filter="*mem*"' --tree /tmp/mess
web1 | SUCCESS => {"ansible_facts": {"ansible_memfree_mb": 3157, "ansible_memory_mb": {"nocache": {"free": 3489, "used": 281}, "real": {"free": 3157, "total": 3770, "used": 613}, "swap": {"cached": 0, "free": 4095, "total": 4095, "used": 0}}, "ansible_memtotal_mb": 3770, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false
}
web2 | SUCCESS => {"ansible_facts": {"ansible_memfree_mb": 3014, "ansible_memory_mb": {"nocache": {"free": 3483, "used": 287}, "real": {"free": 3014, "total": 3770, "used": 756}, "swap": {"cached": 0, "free": 4095, "total": 4095, "used": 0}}, "ansible_memtotal_mb": 3770, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false
}
[root@ansible tmp]# cd mess
[root@ansible mess]# ls
web1  web2
[root@ansible mess]# cat web1
{"ansible_facts": {"ansible_memfree_mb": 3157, "ansible_memory_mb": {"nocache": {"free": 3489, "used": 281}, "real": {"free": 3157, "total": 3770, "used": 613}, "swap": {"cached": 0, "free": 4095, "total": 4095, "used": 0}}, "ansible_memtotal_mb": 3770, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false}[root@ansible mess]# cat web2
{"ansible_facts": {"ansible_memfree_mb": 3014, "ansible_memory_mb": {"nocache": {"free": 3483, "used": 287}, "real": {"free": 3014, "total": 3770, "used": 756}, "swap": {"cached": 0, "free": 4095, "total": 4095, "used": 0}}, "ansible_memtotal_mb": 3770, "discovered_interpreter_python": "/usr/bin/python"}, "changed": false}
[root@ansible ~]# vim a.yaml
hosts: web1remote_user: roottasks:- name: install nginxyum: name=nginx state=present- name: start nginxservice: name=nginx state=started

四、Ansible playbook簡(jiǎn)介

playbook是ansible用于配置,部署和管理被控節(jié)點(diǎn)的劇本
通過 playbook 的詳細(xì)描述,執(zhí)行其中的一系列 tasks ,可以讓遠(yuǎn)端主機(jī)達(dá)到預(yù)期的狀態(tài)。playbook 就像 Ansible 控制器給被控節(jié)點(diǎn)列出的的一系列 to-do-list ,而被控節(jié)點(diǎn)必須要完成。   也可以這么理解,playbook 字面意思,即劇本,現(xiàn)實(shí)中由演員按照劇本表演,在Ansible中,這次由計(jì)算機(jī)進(jìn)行表演,由計(jì)算機(jī)安裝,部署應(yīng)用,提供對(duì)外服務(wù),以及組織計(jì)算機(jī)處理各種各樣的事情。

Ansible playbook使用場(chǎng)景

1.格式簡(jiǎn)介

以下為playbook常用到的YMAL格式:   
1、文件的第一行應(yīng)該以 “—” (三個(gè)連字符)開始,表明YMAL文件的開始。   
2、在同一行中,#之后的內(nèi)容表示注釋,類似于shell,python和ruby。   
3、YMAL中的列表元素以”-”開頭然后緊跟著一個(gè)空格,后面為元素內(nèi)容。   
4、同一個(gè)列表中的元素應(yīng)該保持相同的縮進(jìn)。否則會(huì)被當(dāng)做錯(cuò)誤處理。   
5、play中hosts,variables,roles,tasks等對(duì)象的表示方法都是鍵值中間以":“分隔表示,”:"后面還要增加一個(gè)空格。

例子:

---
- hosts: web1remote_user: roottasks:- name: install nginxyum: name=nginx state=present- name: start nginxservice: name=nginx state=started

host部分:使用 hosts 指示使用哪個(gè)主機(jī)或主機(jī)組來運(yùn)行下面的 tasks ,每個(gè) playbook 都必須指定 hosts ,hosts也可以使用通配符格式。主機(jī)或主機(jī)組在 inventory 清單中指定,可以使用系統(tǒng)默認(rèn)的/etc/ansible/hosts,也可以自己編輯,在運(yùn)行的時(shí)候加上-i選項(xiàng),指定清單的位置即可。在運(yùn)行清單文件的時(shí)候,–list-hosts選項(xiàng)會(huì)顯示那些主機(jī)將會(huì)參與執(zhí)行 task 的過程中。

remote_user:指定遠(yuǎn)端主機(jī)中的哪個(gè)用戶來登錄遠(yuǎn)端系統(tǒng),在遠(yuǎn)端系統(tǒng)執(zhí)行 task 的用戶,可以任意指定,也可以使用 sudo,但是用戶必須要有執(zhí)行相應(yīng) task 的權(quán)限。

tasks:指定遠(yuǎn)端主機(jī)將要執(zhí)行的一系列動(dòng)作。tasks 的核心為 ansible 的模塊,前面已經(jīng)提到模塊的用法。tasks 包含 name要執(zhí)行的模塊,name 是可選的,只是為了便于用戶閱讀,不過還是建議加上去,模塊是必須的,同時(shí)也要給予模塊相應(yīng)的參數(shù)。

在這里插入圖片描述

2、核心元素

Playbook的核心元素:

Hosts:主機(jī)組; Tasks:任務(wù)列表; Variables:變量,設(shè)置方式有四種; Templates:包含了模板語法的文本文件; Handlers:由特定條件觸發(fā)的任務(wù);

3、基本組件

Playbooks配置文件的基礎(chǔ)組件:

Hosts:運(yùn)行指定任務(wù)的目標(biāo)主機(jī)

remote_user:在遠(yuǎn)程主機(jī)上執(zhí)行任務(wù)的用戶;

sudo_user

tasks:任務(wù)列表
模塊,模塊參數(shù)

格式:     (1) action: module arguments     (2) module: arguments     注意:shell和command模塊后面直接跟命令,而非key=value類的參數(shù)列表;
handlers:任務(wù),在特定條件下觸發(fā);接收到其它任務(wù)的通知時(shí)被觸發(fā);

(1) 某任務(wù)的狀態(tài)在運(yùn)行后為changed時(shí),可通過“notify”通知給相應(yīng)的handlers;

(2) 任務(wù)可以通過“tags“打標(biāo)簽,而后可在ansible-playbook命令上使用-t指定進(jìn)行調(diào)用;

運(yùn)行三部曲

運(yùn)行前三部曲
檢查錯(cuò)誤
ansible-playbook nginx.yml --syntax-check

列出所有任務(wù)
ansible-playbook nginx.yml --list-task

列出在那些機(jī)器執(zhí)行
ansible-playbook nginx.yml --list-hosts

運(yùn)行
ansible-playbook nginx.yml

舉例:部署wordpress

---
- hosts: web2vars:db_name: wordpressdb_password: Qianfeng@123remote_user: roottasks:- name: yum下載shell: curl -o /opt/yum.sh http://10.36.192.100/yum-server.sh- name: yum安裝shell: sh /opt/yum.sh- name: 安裝數(shù)據(jù)庫(kù)yum: name=mariadb-server,mariadb state=present disablerepo=mysql-5.7-community- name: 啟動(dòng)數(shù)據(jù)庫(kù)service: name=mariadb state=started- name: 配置數(shù)據(jù)庫(kù)shell: mysql -e "create database {{ db_name }}; grant all on wordpress.* to 'wordpress'@'%' identified by '{{ db_password }}'; flush privileges"
---
- hosts: web1remote_user: rootvars:nginx_name: nginxnginx_port: 80tasks:- name: yum下載shell: curl -o /opt/yum.sh http://10.36.192.100/yum-server.sh- name: yum安裝shell: cd /opt/ , sh yum.sh- name: nginx安裝yum: name=nginx state=present- name: nginx 配置文件template: src=/root/nginx.conf dest=/etc/nginx/nginx.conf- name: nginx 開啟service: name=nginx state=restarted- name: 安裝PHPyum: name=php80-php-xsl,php80-php,php80-php-cli,php80-php-devel,php80-php-gd,php80-php-pdo,php80-php-mysql,php80-php-fpm state=present- name: 啟動(dòng)PHPservice: name=php80-php-fpm state=started enabled=true- name: 拷貝wordpress源代碼unarchive: src=/root/wordpress-6.4.1-zh_CN.tar.gz dest=/usr/share/nginx/html
[root@ansible ~]# ansible-playbook web.yaml PLAY [web1] *******************************************************************************************************************************TASK [Gathering Facts] ********************************************************************************************************************
ok: [web1]TASK [yum下載] ******************************************************************************************************************************
[WARNING]: Consider using the get_url or uri module rather than running 'curl'.  If you need to use command because get_url or uri 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.
changed: [web1]TASK [yum安裝] ******************************************************************************************************************************
changed: [web1]TASK [nginx安裝] ****************************************************************************************************************************
ok: [web1]TASK [nginx 配置文件] *************************************************************************************************************************
changed: [web1]TASK [nginx 開啟] ***************************************************************************************************************************
changed: [web1]TASK [安裝PHP] ******************************************************************************************************************************
ok: [web1]TASK [啟動(dòng)PHP] ******************************************************************************************************************************
ok: [web1]TASK [拷貝wordpress源代碼] *********************************************************************************************************************
ok: [web1]PLAY RECAP ********************************************************************************************************************************
web1                       : ok=9    changed=4    unreachable=0    failed=0    skipped=0    rescued=0    ignored=0 

在這里插入圖片描述
瀏覽器訪問
在這里插入圖片描述

在這里插入圖片描述

五、角色訂制:roles

① 簡(jiǎn)介

對(duì)于以上所有的方式有個(gè)弊端就是無法實(shí)現(xiàn)復(fù)用假設(shè)在同時(shí)部署Web、db、ha 時(shí)或不同服務(wù)器組合不同的應(yīng)用就需要寫多個(gè)yml文件。很難實(shí)現(xiàn)靈活的調(diào)用。   roles 用于層次性、結(jié)構(gòu)化地組織playbook。roles 能夠根據(jù)層次型結(jié)構(gòu)自動(dòng)裝載變量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。簡(jiǎn)單來講,roles就是通過分別將變量(vars)、文件(file)、任務(wù)(tasks)、模塊(modules)及處理器(handlers)放置于單獨(dú)的目錄中,并可以便捷地include它們的一種機(jī)制。角色一般用于基于主機(jī)構(gòu)建服務(wù)的場(chǎng)景中,但也可以是用于構(gòu)建守護(hù)進(jìn)程等場(chǎng)景中。

② 角色集合

角色集合:roles/ mysql/ httpd/ nginx/ files/:存儲(chǔ)由copy或script等模塊調(diào)用的文件; tasks/:此目錄中至少應(yīng)該有一個(gè)名為main.yml的文件,用于定義各task;其它的文件需要由main.yml進(jìn)行“包含”調(diào)用; handlers/:此目錄中至少應(yīng)該有一個(gè)名為main.yml的文件,用于定義各handler;其它的文件需要由main.yml進(jìn)行“包含”調(diào)用; vars/:此目錄中至少應(yīng)該有一個(gè)名為main.yml的文件,用于定義各variable;其它的文件需要由main.yml進(jìn)行“包含”調(diào)用; templates/:存儲(chǔ)由template模塊調(diào)用的模板文本; meta/:此目錄中至少應(yīng)該有一個(gè)名為main.yml的文件,定義當(dāng)前角色的特殊設(shè)定及其依賴關(guān)系;其它的文件需要由main.yml進(jìn)行“包含”調(diào)用; default/:此目錄中至少應(yīng)該有一個(gè)名為main.yml的文件,用于設(shè)定默認(rèn)變量;

③ 角色定制實(shí)例

1. 在roles目錄下生成對(duì)應(yīng)的目錄結(jié)構(gòu)

[root@server ansible]# cd roles/
[root@server roles]# ls
[root@server roles]# mkdir -pv ./{nginx,mysql,httpd}/{files,templates,vars,tasks,handlers,meta,default}
[root@server roles]# tree
.
├── httpd
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
├── mysql
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
└── nginx├── default├── files├── handlers├── meta├── tasks├── templates└── vars24 directories, 0 files

2. 定義配置文件   我們需要修改的配置文件為/tasks/main.yml,下面,我們就來修改一下:

[root@server roles]# vim nginx/tasks/main.yml
- name: cp rpm for nginxcopy: src=nginx-1.10.2-1.el7.ngx.x86_64.rpm dest=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm
- name: installyum: name=/tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm state=latest
- name: conftemplate: src=nginx.conf.j2 dest=/etc/nginx/nginx.conftags: nginxconfnotify: new conf to reload
- name: start serviceservice: name=nginx state=started enabled=true

http://nginx.org/packages/rhel/7/x86_64/RPMS/nginx-1.10.2-1.el7.ngx.x86_64.rpm

3. 放置我們所需要的文件到指定目錄   因?yàn)槲覀兌x的角色已經(jīng)有了新的組成方式,所以我們需要把文件都放到指定的位置,這樣,才能讓配置文件找到這些并進(jìn)行加載。   rpm包放在files目錄下,模板放在templates目錄下:

[root@server nginx]# cp /tmp/nginx-1.10.2-1.el7.ngx.x86_64.rpm ./files/
[root@server nginx]# cp /tmp/nginx.conf.j2 ./templates/
[root@server nginx]# tree
.
├── default
├── files
│   └── nginx-1.10.2-1.el7.ngx.x86_64.rpm
├── handlers
├── meta
├── tasks
│   └── main.yml
├── templates
│   └── nginx.conf.j2
└── vars7 directories, 3 files

4. 修改變量文件   我們?cè)谀0逯卸x的變量,也要去配置文件中加上:

[root@server nginx]# vim vars/main.yml
nginxprot: 9999

5. 定義handlers文件   我們?cè)谂渲梦募卸x了notify,所以我么也需要定義handlers,我們來修改配置文件:

[root@server nginx]# vim handlers/main.yml
- name: new conf to reloadservice: name=nginx state=restarted

6. 定義劇本文件   接下來,我們就來定義劇本文件,由于大部分設(shè)置我們都單獨(dú)配置在了roles里面,所以,接下來劇本就只需要寫一點(diǎn)點(diǎn)內(nèi)容即可:

[root@server ansible]# vim roles/roles.yml 
- hosts: webremote_user: rootroles:- nginx
完成后的目錄結(jié)構(gòu)
# tree ./
./
├── httpd
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
├── mysql
│   ├── default
│   ├── files
│   ├── handlers
│   ├── meta
│   ├── tasks
│   ├── templates
│   └── vars
├── nginx
│   ├── default
│   ├── files
│   │   └── nginx-1.10.2-1.el7.ngx.x86_64.rpm
│   ├── handlers
│   │   └── main.yml
│   ├── meta
│   ├── tasks
│   │   └── main.yml
│   ├── templates
│   │   └── nginx.conf.j2
│   └── vars
│       └── main.yml
└── roles.yml

7. 啟動(dòng)服務(wù)   劇本定義完成以后,我們就可以來啟動(dòng)服務(wù)了:

[root@server ansible]# ansible-playbook roles.ymlPLAY [web] *********************************************************************TASK [setup] *******************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]TASK [nginx : cp] **************************************************************
ok: [192.168.37.122]
ok: [192.168.37.133]TASK [nginx : install] *********************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]TASK [nginx : conf] ************************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]TASK [nginx : start service] ***************************************************
changed: [192.168.37.122]
changed: [192.168.37.133]RUNNING HANDLER [nginx : new conf to reload] ***********************************
changed: [192.168.37.122]
changed: [192.168.37.133]PLAY RECAP *********************************************************************
192.168.37.122             : ok=6    changed=4    unreachable=0    failed=0   
192.168.37.133             : ok=6    changed=4    unreachable=0    failed=0   

啟動(dòng)過后照例查看端口號(hào):

[root@server ansible]# ansible web -m shell -a "ss -ntulp |grep 9999"
192.168.37.122 | SUCCESS | rc=0 >>
tcp    LISTEN     0      128       *:9999                  *:*                   users:(("nginx",pid=7831,fd=6),("nginx",pid=7830,fd=6),("nginx",pid=7829,fd=6))192.168.37.133 | SUCCESS | rc=0 >>
tcp    LISTEN     0      128       *:9999                  *:*                   users:(("nginx",pid=9654,fd=6),("nginx",pid=9653,fd=6),("nginx",pid=9652,fd=6))

可以看出我們的劇本已經(jīng)執(zhí)行成功。

六、 Ansible 性能調(diào)優(yōu)

Ansible 企業(yè)實(shí)戰(zhàn)環(huán)境中,如果管理的服務(wù)器越來越多,Ansibe 執(zhí)行效率會(huì)變得比較慢,可以通過優(yōu)化 Ansible 提供工作效率,由于 Ansible 基于 SSH 協(xié)議通信,SSH 連接慢會(huì)導(dǎo)致整個(gè)基于 Ansible 執(zhí)行變得緩慢,也需要對(duì) Openssh 進(jìn)行優(yōu)化,具體優(yōu)化的方法如下:

(1) Ansible SSH 關(guān)閉秘鑰檢測(cè)

默認(rèn)以 SSH 登錄遠(yuǎn)程客戶端服務(wù)器,會(huì)檢查遠(yuǎn)程主機(jī)的公鑰(public key),并將該主機(jī)的公鑰記錄在~/.ssh/known_hosts 文件中。下次訪問相同主機(jī)時(shí),OpenSSH 會(huì)核對(duì)公鑰,如果公鑰不同,OpenSSH 會(huì)發(fā)出警告,如果公鑰相同,則提示輸入密碼。
SSH對(duì)主機(jī)的public_key的檢查等級(jí)是根據(jù)StrictHostKeyChecking變量來設(shè)定的StrictHostKeyChecking 檢查級(jí)別包括:no(不檢查)、ask(詢問)、yes(每次都檢查)、False(關(guān)閉檢查)。
Ansible 配置文件中加入如下代碼,即可關(guān)閉 StrictHostKeyChecking 檢查:

host_key_checking = False

(2) OpenSSH 連接優(yōu)化

使用 OpenSSH 服務(wù)時(shí),默認(rèn)服務(wù)器端配置文件 UseDNS=YES 狀態(tài),該選項(xiàng)會(huì)導(dǎo)致服務(wù)器根據(jù)客戶端的 IP 地址進(jìn)行 DNS PTR 反向解析,得到客戶端的主機(jī)名,然后根據(jù)獲取到的主機(jī)名進(jìn)行 DNS 正向 A 記錄查詢,并驗(yàn)證該 IP 是否與原始 IP 一致。關(guān)閉 DNS 解析代碼如下:

sed -i '/^GSSAPI/s/yes/no/g; /UseDNS/d; /Protocol/aUseDNS no' /etc/ssh/sshd_config
/etc/init.d/sshd restart

(3) SSH pipelining 加速 Ansible

SSH pipelining 是一個(gè)加速 Ansible 執(zhí)行速度的簡(jiǎn)單方法,SSH pipelining 默認(rèn)是關(guān)閉的,關(guān)閉是為了兼容不同的 sudo 配置,主要是 requiretty 選項(xiàng)。
如果不使用 Sudo 建議開啟該選項(xiàng),打開此選項(xiàng)可以減少 Ansible 執(zhí)行沒有文件傳輸時(shí),SSH 在被控機(jī)器上執(zhí)行任務(wù)的連接數(shù)。使用 Sudo 操作的時(shí)候, 必須在所有被管理的主機(jī)上將配置文件/etc/sudoers 中 requiretty 選項(xiàng)禁用。

sed -i '/^pipelining/s/False/True/g' /etc/ansible/ansible.cfg

(4)Ansible Facts 緩存優(yōu)化

Ansible-playbook 在執(zhí)行過程中,默認(rèn)會(huì)執(zhí)行 Gather facts,如果不需要獲取客戶端的 fact 數(shù)據(jù)的話,可以關(guān)閉獲取 fact 數(shù)據(jù)功能,關(guān)閉之后可以加快 ansible-playbook的執(zhí)行效率。如需關(guān)閉 fact 功能,在 playbook yaml 文件中加入如下代碼即可:

gather_facts: nogather_facts: no

Ansible facts 組件主要用于收集客戶端設(shè)備的基礎(chǔ)靜態(tài)信息,這些信息可以在做配置管理的時(shí)候方便引用。Facts 信息直接當(dāng)做 Ansible Playbook 變量信息進(jìn)行引用,通過定制 facts 以便收集我們想要的信息,同時(shí)可以通過 Facter 和 Ohai 來拓展 facts 信息,也可以將 facts 信息存入 Redis 緩存中,如下為 Facts 使用 Redis 緩存的步驟

在配置文件/etc/ansible/ansible.cfg 中 defaluts 段中加入代碼,如果 redis 密碼為 admin,則開啟 admin 密碼行:
# yum install -y python-pip
# pip install redis==3.0.0
gathering = smart
fact_caching = redis
fact_caching_timeout = 86400
fact_caching_connection = localhost:6379
#fact_caching_connection = localhost:6379:0:admin

也可以使用json來緩存信息

fact_caching = jsonfile
fact_caching_timeout = 86400
fact_caching_connection = /tmp
http://www.risenshineclean.com/news/30844.html

相關(guān)文章:

  • 維護(hù)網(wǎng)站建設(shè)空間出租百度深圳總部
  • wordpress 手機(jī)布局中國(guó)seo高手排行榜
  • 杭州市建設(shè)住房保障局網(wǎng)站有免費(fèi)做網(wǎng)站的嗎
  • 湖南門戶網(wǎng)站建設(shè)鄭州seo排名公司
  • 網(wǎng)站開發(fā)都是用什么做的百度自己的宣傳廣告
  • 如室室內(nèi)設(shè)計(jì)官網(wǎng)網(wǎng)站推廣優(yōu)化的方法
  • 怎么查看網(wǎng)站有沒有做競(jìng)價(jià)免費(fèi)網(wǎng)站推廣工具
  • 無形資產(chǎn) 網(wǎng)站開發(fā)排位及資訊
  • eclipse做企業(yè)網(wǎng)站品牌策劃方案怎么做
  • 做網(wǎng)站公司哪里好活動(dòng)推廣方案策劃
  • 去越南做網(wǎng)站網(wǎng)頁(yè)設(shè)計(jì)軟件dreamweaver
  • 深圳附近建站公司谷歌play商店官網(wǎng)
  • 住房和城鄉(xiāng)建設(shè)部執(zhí)法網(wǎng)站軟文推廣網(wǎng)站
  • 做電影視頻網(wǎng)站賺錢嘛靠譜的代寫平臺(tái)
  • 校慶網(wǎng)站建設(shè)策劃書范文外包公司和勞務(wù)派遣的區(qū)別
  • 網(wǎng)站開發(fā)需求分析報(bào)告廣州競(jìng)價(jià)托管公司
  • 加強(qiáng)網(wǎng)站建設(shè)技術(shù)培訓(xùn)企業(yè)微信營(yíng)銷管理軟件
  • 網(wǎng)站的百度詞條怎么做大眾網(wǎng)濰坊疫情
  • 網(wǎng)站建設(shè)需要哪些步驟灰色seo推廣
  • wordpress證書關(guān)閉泉州網(wǎng)站seo外包公司
  • 北京開網(wǎng)站建設(shè)公司網(wǎng)絡(luò)營(yíng)銷成功的案例
  • 昌吉網(wǎng)站建設(shè)公司服務(wù)營(yíng)銷理論
  • 怎么注冊(cè)網(wǎng)址免費(fèi)國(guó)內(nèi)seo做最好的公司
  • 杭州網(wǎng)站建設(shè)哪里好易觀數(shù)據(jù)
  • 旅游網(wǎng)站建設(shè)的方向足球比賽直播2021歐冠決賽
  • 如何在相關(guān)網(wǎng)站免費(fèi)做宣傳廣告中國(guó)網(wǎng)絡(luò)營(yíng)銷網(wǎng)
  • 公司網(wǎng)站頁(yè)面徐匯網(wǎng)站建設(shè)
  • 學(xué)什么可以做推廣網(wǎng)站網(wǎng)絡(luò)優(yōu)化的流程
  • 網(wǎng)站開發(fā)與運(yùn)維收費(fèi)明細(xì)seo技巧seo排名優(yōu)化
  • 做單掙錢的網(wǎng)站灰色關(guān)鍵詞排名技術(shù)