如何使用ansible批量初始化服務器
簡介
本文詳細介紹ansible怎么批量初始化服務器,包括ansible批量初始化服務器詳細配置和步驟,有需要的小伙伴們可以參考借鑒,希望對大家有所幫助。
詳細步驟
1、ansible要初始化的主機
[root@nginx ansible]# tail -3 /etc/ansible/hosts #要初始的主機如下 [node] 192.168.20.4 192.168.20.5
2、配置ssh免密登錄
playbook文件內(nèi)容如下:
[root@nginx ansible]# cat ssh.yaml --- - name: configure ssh connection hosts: node gather_facts: false connection: local tasks: - name: configure ssh connection shell: | ssh-keyscan {{inventory_hostname}} >>~/.ssh/known_hosts sshpass -p '123.com' ssh-copy-id root@{{inventory_hostname}} ...
注:
- gather\_facts:如果值為false,則表示不收集目標主機上的節(jié)點信息,默認為true,為收集節(jié)點信息,如果收集節(jié)點信息,則會慢很多,如果在接下來的操作中,不需要節(jié)點上的信息,可設置為false。
- connection:local表示在ansible端本地執(zhí)行任務,hosts:localhost和connection:local容易搞混,雖然兩者的效果都是在本地執(zhí)行任務,但是hosts:localhost是從inventory中篩選出了目標節(jié)點localhost來執(zhí)行任務,而connection:local則篩選出來執(zhí)行任務的目標主機是node組中的節(jié)點,但因為指定了local連接類型,使得node組中有多少個節(jié)點,就會在ansible本地執(zhí)行幾次該play。
3、配置主機名
配置主機名可以使用shell模塊,但是對于不太專業(yè),ansible提供了一個專用于配置主機名的模塊:hostname模塊。
當然,要使用ansible去設置多個主機名,要求目標主機和目標名稱已經(jīng)關聯(lián)好,否則多個主機和多個主機名之間無法對應去設置。
例如:分別設置node組中的兩個節(jié)點主機名為node01和node02,playbook內(nèi)容如下:
[root@ansible ansible]# cat test.yaml --- - name: set hostname hosts: node gather_facts: false vars: hostnames: - host: 192.168.20.4 name: node01 - host: 192.168.20.5 name: node02 tasks: - name: set hostname hostname: name: "{{item.name}}" when: item.host == inventory_hostname loop: "{{hostnames}}"
在上面的hostname模塊中,需要詳細介紹vars指令以及when、loop指令。
1)vars設置變量
vars指令可用于設置變量,可以設置一個或多個變量。下面幾種方式都是合理的:
# 設置單個變量 vars: var1: value1 vars: - var1: value1 # 設置多個變量 vars: var1: value1 var2: value2 vars: - var1: value1 - var2: value2
vars可以設置在play級別,也可以設置在task級別,設置在play級別,該play范圍內(nèi)的task可以訪問這些變量,其他play范圍內(nèi)則無法訪問;設置在task級別,只有該task能訪問這些變量,其他task和其他play則無法訪問。
例如:
[root@ansible ansible]# cat test.yaml --- - name: play1 hosts: localhost gather_facts: false vars: - var1: "value1" tasks: - name: access var1 debug: msg: "var1's value: {{var1}}" - name: play2 hosts: localhost gather_facts: false tasks: - name: cat's access vars from play1 debug: var: var1 - name: set and access var2 in this task debug: var: var2 vars: var2: "value2" - name: cat't accesss var2 debug: var: var2
執(zhí)行結果如下:
[root@ansible ansible]# ansible-playbook test.yaml
PLAY [play1] **************************************************************************
TASK [access var1] ********************************************************************
ok: [localhost] => {
"msg": "var1's value: value1"
}
PLAY [play2] **************************************************************************
TASK [cat's access vars from play1] ***************************************************
ok: [localhost] => {
"var1": "VARIABLE IS NOT DEFINED!"
}
TASK [set and access var2 in this task] ***********************************************
ok: [localhost] => {
"var2": "value2"
}
TASK [cat't accesss var2] *************************************************************
ok: [localhost] => {
"var2": "VARIABLE IS NOT DEFINED!"
}
PLAY RECAP ****************************************************************************
localhost : ok=4 changed=0 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
回到我們更改主機名的配置vars指令中:
vars: hostnames: - host: 192.168.20.4 name: node01 - host: 192.168.20.5 name: node02
上面只設置了一個變量hostnames,但這個變量的值是一個數(shù)組結構,數(shù)組的兩個元素又都是對象(字典/hash)結構。
所以想要訪問主機名node01和它的IP地址192.168.20.4,可以:
tasks: - debug: var: hostnames[0].name - debug: var: hostnames[0].host
2)when條件判斷
在ansible中,提供的唯一一個通用的條件判斷是when指令,當when指令的值為true時,則執(zhí)行該任務,否則不執(zhí)行該任務。
例如:
[root@ansible ansible]# cat test.yaml --- - name: play1 hosts: localhost gather_facts: false vars: - myname: "Ray" tasks: - name: task will skip debug: msg: "myname is : {{myname}}" when: myname == "lv" - name: task will execute debug: msg: "myname is : {{myname}}" when: myname == "Ray"
在上面的myname值設置為Ray,第一個任務因為when的判斷條件是myname==“lv”,所以判斷結果為false,該任務不執(zhí)行,同理,第二個任務因為when的值為true,所以執(zhí)行了。
該playbook的執(zhí)行結果:
PLAY [play1] **************************************************************************
TASK [task will skip] *****************************************************************
skipping: [localhost]
TASK [task will execute] **************************************************************
ok: [localhost] => {
"msg": "myname is : Ray"
}
PLAY RECAP ****************************************************************************
localhost : ok=1 changed=0 unreachable=0 failed=0 skipped=1 rescued=0 ignored=0
4、互相添加DNS解析記錄
[root@ansible ansible]# cat add_dns.yaml --- - name: play1 hosts: node gather_facts: true tasks: - name: add DNS lineinfile: path: "/etc/hosts" line: "{{item}} {{hostvars[item].ansible_hostname}}" when: item != inventory_hostname loop: "{{ play_hosts }}"
執(zhí)行結果如下:
TASK [Gathering Facts] ****************************************************************
ok: [192.168.20.4]
ok: [192.168.20.5]
TASK [add DNS] ************************************************************************
skipping: [192.168.20.4] => (item=192.168.20.4)
changed: [192.168.20.4] => (item=192.168.20.5)
changed: [192.168.20.5] => (item=192.168.20.4)
skipping: [192.168.20.5] => (item=192.168.20.5)
5、配置yum鏡像源并安裝軟件
需求如下:
- 備份原有yum鏡像源文件,并配置清華大學的yum鏡像源:os源和epel源
- 安裝常用軟件,包括lrzsz、dos2unix、wget、curl、vim等;
playbook如下:
[root@ansible ansible]# cat config_yum.yaml - name: config yum repo add install software hosts: node gather_facts: false tasks: - name: backup origin yum repos shell: cmd: "mkdir bak; mv *.repo bak" chdir: /etc/yum.repos.d creates: /etc/yum.repos.d/bak - name: add os repo and epel repo yum_repository: name: "{{item.name}}" description: "{{item.name}} repo" baseurl: "{{item.baseurl}}" file: "{{item.name}}" enabled: 1 gpgcheck: 0 reposdir: /etc/yum.repos.d loop: - name: os baseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch" - name: epel baseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch" - name: install pkgs yum: name: lrzsz,vim,dos2unix,wget,curl state: present
在上面的yaml文件中,第一個任務是將所有系統(tǒng)默認的repo文件備份到bak目錄中,chdir參數(shù)表示在執(zhí)行shell模塊的命令前先切換到/etc/yum.repos.d目錄下,creates參數(shù)表示bak目錄存在時則不執(zhí)行shell模塊。
第二個任務是使用yum\_repository模塊配置yum源,該模塊可添加或移除yum源。
相關參數(shù)如下:
name:指定repo的名稱,對應于repo文件中的[name];
description:repo的描述信息,對應repo文件中的name:xxx;
baseurl:指定該repo的路徑;
file:指定repo的文件名,不需要加.repo后綴,會自動加上;
reposdir:repo文件所在的目錄,默認為/etc/yum.repos.d目錄;
enabled:是否啟用該repo,對應于repo文件中的enabled;
gpgcheck:該repo是否啟用gpgcheck,對應于repo文件中的gpgcheck;
state:present表示保證該repo存在,absent表示移除該repo。
在上面的配置中使用了一個loop循環(huán)來添加兩個repo:os和epel。
第三個任務是使用yum模塊安裝一些rpm包,yum模塊可以更新、安裝、移除、下載包。
yum常用參數(shù)說明:
- name:指定要操作的包名
- 可以帶版本號;
- 可以是單個包名,也可以是包名列表,或者逗號分隔多個包名;
- 可以是url;
- 可以是本地rpm包
- state:
- present和installed:保證包已安裝,它們是等價的別名;
- latest:保證包已安裝了最新版本,如果不是則更新;
- absent和removed:移除包,它們是等價的別名;
- download\_only:僅下載不安裝包(ansible 2.7才支持)
- download\_dir:下載包存放在哪個目錄下(ansible 2.8才支持)
yum模塊是RHEL系列的包管理器,如果是ubuntu則無法使用,可以使用另一個更為通用的包管理器模塊:package,它可以自動探測目標節(jié)點的包管理器類型并使用它們?nèi)ス芾碥浖?。大多?shù)時候使用package來代替yum或代替apt-install等不會有什么問題,但是有些包名在不同的操作系統(tǒng)上是不一樣的,這是需要注意的。
6、時間同步
保證時間同步可以避免很多玄學性的問題,特別是對集群中的節(jié)點。
通常會使用ntpd時間服務器來保證時間的同步,這里使用aliyun提供的時間服務器來保證時間同步,并將同步后的時間同步到硬件。
playbook文件如下:
--- - name: sync time hosts: node gather_facts: false tasks: - name: install and sync time block: - name: install ntpdate yum: name: ntpdate state: present - name: ntpdate to sync time shell: | ntpdate ntp1.aliyun.com hwclock -w
上面使用了一個block指令來組織了兩個有關聯(lián)性的任務,將他們作為了一個整體。block更多的用于多個關聯(lián)性任務之間的異常處理。
7、關閉selinux
關閉selinux的playbook如下:
[root@ansible roles]# cat disable_selinux.yaml --- - name: disable selinux hosts: node gather_facts: false tasks: - name: disable on the fly shell: setenforce 0 ignore_errors: true #由于上條命令執(zhí)行后的返回狀態(tài)碼不一定為0,所以為了防止非0報錯并停止palsybook接下來的任務,所以使用ignore_errors忽略錯誤 - name: disable forever in config lineinfile: path: /etc/selinux/config line: "SELINUX=disabled" #修改配置文件中的值,以便永久關閉 regexp: '^SELINUX=' #要修改的內(nèi)容
注:ignore\_errors也經(jīng)常結合block使用,因為在block級別上設置異常處理,可以處理block內(nèi)部的所有錯誤。
8、配置iptables規(guī)則
playbook文件如下:
- name: Set Firewall hosts: node gather_facts: false tasks: - name: set iptables rule shell: | # 備份已有規(guī)則 iptables-save > /tmp/iptables.bak$(date +"%F-%T") # 給它三板斧 iptables -X iptables -F iptables -Z # 放行l(wèi)o網(wǎng)卡和允許ping iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p icmp -j ACCEPT # 放行關聯(lián)和已建立連接的包,放行22、443、80端口 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT # 配置filter表的三鏈默認規(guī)則,INPUT鏈丟棄所有包 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT
9、遠程修改sshd配置文件并重啟
有時候為了服務器的安全,可能會去修改目標節(jié)點上sshd服務的默認配置,比如禁止root用戶登錄、禁止密碼認證登錄而只允許使用ssh密碼認證等。
在修改服務的配置文件時,一般有幾種方法:
- 通過遠程執(zhí)行sed等命令進行修改配置文件;
- 通過lineinfile模塊去修改配置文件;
- 在ansible本地段寫好配置文件,然后使用copy模塊或者template模塊傳輸?shù)侥繕斯?jié)點上。
相對來說,第三種方案是最統(tǒng)一、最易維護的方案。
此外,對于服務進程來說,修改了配置文件往往意味著要重啟服務,使其加載新的配置文件,對于sshd也一樣如此,但是sshd要比其他服務特殊一些,因為ansible默認基于ssh連接,重啟sshd服務會使ansible連接斷開,好在ansible默認會重試建立連接,無非是多等待幾秒。但重建連接有可能會失敗,比如修改了配置文件不允許重試、修改了sshd的監(jiān)聽端口等,這可能會使得ansible因連接失敗而無法再繼續(xù)執(zhí)行后續(xù)任務。
所以,在修改sshd配置文件時,有如下建議:
- 將此任務作為初始化服務器的最后一個任務,即使連接失敗也無所謂;
- 在playbook中加入連接失敗的異常處理;
- 如果目標節(jié)點修改了sshd端口號,建議通過ansible自動或者我們手動去修改inventory文件中的ssh連接端口號。
這里為了簡單,我準備使用lineinfile模塊去修改配置文件,要修改的內(nèi)容只有兩項:
- 將PermitRootLogin指令設置為no,禁止root用戶直接登錄;
- 將PasswordAuthentication指令設置為no,不允許使用密碼認證的方式登錄
playbook內(nèi)容如下:
[root@ansible roles]# cat sshd_config.yaml --- - name: modify sshd_config hosts: node gather_facts: false tasks: # 1.備份/etc/ssh/sshd_config文件 - name: backup sshd config shell: /usr/bin/cp -f {{path}} {{path}}.bak vars: - path: /etc/ssh/sshd_config # 2.設置PermitRootLogin no - name: disable root login lineinfile: path: "/etc/ssh/sshd_config" line: "PermitRootLogin no" insertafter: "^#PermitRootLogin" regexp: "^PermitRootLogin" notify: "restart sshd" # 3.設置PasswordAuthentication no - name: disable password auth lineinfile: path: "/etc/ssh/sshd_config" line: "PasswordAuthentication no" regexp: "^PasswordAuthentication yes" notify: "restart sshd" handlers: - name: "restart sshd" service: name: sshd state: restarted
關于notify和handlers的作用如下:
ansible會監(jiān)控playbook執(zhí)行后的changed的狀態(tài),如果changed=1,則表示關注的狀態(tài)發(fā)生了改變,即本次任務的執(zhí)行不具備冪等性,如果changed=0,則表示本次任務要么沒執(zhí)行,要么執(zhí)行了也沒有影響,即本次任務具備冪等性。ansible提供了notify指令和handlers功能,如果在某個task中定義notify指令,當ansible在監(jiān)控到該任務changed=1時,會觸發(fā)該notify指令所定義的handler,然后去執(zhí)行handler。所謂handler,其實就是task,無論是在寫法上還是作用上它和task都沒有什么區(qū)別,唯一的區(qū)別在于handler是被觸發(fā)而被動執(zhí)行的,不像普通task一樣會按流程正常執(zhí)行。
唯一需要注意的是,notify和handler中任務的名稱必須一致。比如: notify: "restart sshd",那么handlers中必須得有一個任務設置了 name: "restart sshd"。
此外,在上面的playbook中,兩個lineinfile任務都設置了相同的notify,但ansible不會多次去重啟sshd,而是在最后重啟一次。實際上,ansible在執(zhí)行完某個任務之后,并不會立即去執(zhí)行對應的handler,而是在當前play中所有普通任務都執(zhí)行完成后再去執(zhí)行handler,這樣的好處是可以多次觸發(fā)notify,但最后只執(zhí)行一次對應的handler,從而避免多次重啟。
10、整合所有任務到單個playbook中
這里將前面所有的playbook集合到單個playbook文件中去,這樣就可以一次性執(zhí)行所有任務。
整合后的playbook如下:
--- - name: Configure ssh Connection hosts: node gather_facts: false connection: local tasks: - name: configure ssh connection shell: | ssh-keyscan {{inventory_hostname}} >>~/.ssh/known_hosts sshpass -p'123.com' ssh-copy-id root@{{inventory_hostname}} - name: Set Hostname hosts: node gather_facts: false vars: hostnames: - host: 192.168.20.4 name: node01 - host: 192.168.20.5 name: node02 tasks: - name: set hostname hostname: name: "{{item.name}}" when: item.host == inventory_hostname loop: "{{hostnames}}" - name: Add DNS For Each hosts: node gather_facts: true tasks: - name: add DNS lineinfile: path: "/etc/hosts" line: "{{item}} {{hostvars[item].ansible_hostname}}" when: item != inventory_hostname loop: "{{ play_hosts }}" - name: Config Yum Repo And Install Software hosts: node gather_facts: false tasks: - name: backup origin yum repos shell: cmd: "mkdir bak; mv *.repo bak" chdir: /etc/yum.repos.d creates: /etc/yum.repos.d/bak - name: add os repo and epel repo yum_repository: name: "{{item.name}}" description: "{{item.name}} repo" baseurl: "{{item.baseurl}}" file: "{{item.name}}" enabled: 1 gpgcheck: 0 reposdir: /etc/yum.repos.d loop: - name: os baseurl: "https://mirrors.tuna.tsinghua.edu.cn/centos/7/os/$basearch" - name: epel baseurl: "https://mirrors.tuna.tsinghua.edu.cn/epel/7/$basearch" - name: install pkgs yum: name: lrzsz,vim,dos2unix,wget,curl state: present - name: Sync Time hosts: node gather_facts: false tasks: - name: install and sync time block: - name: install ntpdate yum: name: ntpdate state: present - name: ntpdate to sync time shell: | ntpdate ntp1.aliyun.com hwclock -w - name: Disable Selinux hosts: node gather_facts: false tasks: - block: - name: disable on the fly shell: setenforce 0 - name: disable forever in config lineinfile: path: /etc/selinux/config line: "SELINUX=disabled" regexp: '^SELINUX=' ignore_errors: true - name: Set Firewall hosts: node gather_facts: false tasks: - name: set iptables rule shell: | # 備份已有規(guī)則 iptables-save > /tmp/iptables.bak$(date +"%F-%T") # 給它三板斧 iptables -X iptables -F iptables -Z # 放行l(wèi)o網(wǎng)卡和允許ping iptables -A INPUT -i lo -j ACCEPT iptables -A INPUT -p icmp -j ACCEPT # 放行關聯(lián)和已建立連接的包,放行22、443、80端口 iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 22 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 443 -j ACCEPT iptables -A INPUT -p tcp -m tcp --dport 80 -j ACCEPT # 配置filter表的三鏈默認規(guī)則,INPUT鏈丟棄所有包 iptables -P INPUT DROP iptables -P FORWARD DROP iptables -P OUTPUT ACCEPT - name: Modify sshd_config hosts: node gather_facts: false tasks: - name: backup sshd config shell: /usr/bin/cp -f {{path}} {{path}}.bak vars: - path: /etc/ssh/sshd_config - name: disable root login lineinfile: path: "/etc/ssh/sshd_config" line: "PermitRootLogin no" insertafter: "^#PermitRootLogin" regexp: "^PermitRootLogin" notify: "restart sshd" - name: disable password auth lineinfile: path: "/etc/ssh/sshd_config" line: "PasswordAuthentication no" regexp: "^PasswordAuthentication yes" notify: "restart sshd" handlers: - name: "restart sshd" service: name: sshd state: restarted
按照以上步驟一步一步操作,你將輕松完成批量服務器的初始化。
到此這篇關于使用ansible批量初始化服務器的文章就介紹到這了,更多相關ansible批量初始化服務器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
如何解決啟動hadoop集群沒有SecondaryNode和DataNode和NameNode問題
本文提供了Hadoop集群中缺少SecondaryNode、DataNode和NameNode時的解決方案,包括環(huán)境變量配置、文件刪除和格式化namenode等操作,希望對使用Hadoop的用戶有所幫助2024-10-10VPS主機快速搬家方法:邊打包邊傳輸邊解壓適合大中型論壇網(wǎng)站
本篇文章給大家分享如何在VPS主機之間快速搬家,一邊打包壓縮原主機上的文件,一邊傳輸文件數(shù)據(jù)到新的主機上,一邊在新的VPS主機上解壓文件,因為所有的操作都是在VPS主機上之間進行,傳輸速度可以達到幾MB/s以上,特別適合一些大中型的論壇和網(wǎng)站搬家2017-07-07DELL DOSA 6.X 服務器引導光盤Dell Systems Build and Update Utility I
戴爾系統(tǒng)構建和更新實用程序是可引導的實用程序,適用于單一服務器操作系統(tǒng)安裝、預加載操作系統(tǒng)固件更新和預加載操作系統(tǒng)系統(tǒng)配置2016-04-04虛擬主機管理系統(tǒng)DirectAdmin、Websitepanel和Cpanel功能對比評測
最近不少人問DirectAdmin、Websitepanel和Cpanel的區(qū)別,這里簡單介紹下,方便需要的朋友2013-12-12網(wǎng)站解決和優(yōu)化Server is too busy的一些方法
有時候我們在訪問網(wǎng)站的時候提示Server is too busy,一般情況都是因為服務器iis或web服務器資源不足引起的,一般情況下都有限制2014-04-04