|
|
.使用playbook安装启用httpd服务. g5 T& d! D7 d5 k
首先编写xxx.yaml文件
3 \% O. E% I5 j5 X( j7 E1 K0 l" y- L$ g" _5 x% F, {; s. G
--- #多个yaml文件以---开头,以表明这是一个yaml文件,可省略3 t+ E5 `& a1 L9 D9 R
- name: apache play #定义一个play的名称,可省略! C' H8 l" W+ g& r8 P( G5 J
gather_facts: false #设置不进行facts信息收集(即setup模块收集信息),这可以加快执行速度,如果不使用其中的信息可省略
# s6 d; g/ q/ ]6 R) [3 x hosts: webservers #指定要执行任务的被管理主机组,如多个主机组用冒号:分隔
5 @$ \( p! |( W$ D* F% K remote_user: root #指定被管理主机上执行任务的用户2 q! N1 z5 ?, o9 \) e3 R$ T
tasks: #定义任务列表,任务列表中的各任务按次序逐个在hosts中指定的主机上执行
# t8 G: A+ a) p& j' N5 a - name: disable selinux #自定义任务名称" H$ |3 ]/ [. S. g1 y
command: '/usr/sbin/setenforce 0' 键值对,键是ansible模块,值是 -a 中的内容' H# j& K' e. I6 H4 i* Q; S
ignore_errors: true #如执行命令的返回值不为0,就会报错,tasks停止,可使用ignore_errors忽略失败的任务3 ^& n' O5 s2 e, G# G! X
2 H+ J2 H9 L: O5 B5 E* j" k r) o& | - name: disable firewalld; N- l& Z/ @4 l. I- Y0 k( e2 j
service: name=firewalld state=stopped enabled=no
4 m: P8 x6 R3 c, P' Z% r) F
+ B! A& C, ~- h! [ - name: prepare local repo e1 n7 Q6 K. h9 l; I
copy: src=/etc/yum.repos.d/local.repo dest=/etc/yum.repos.d/local.repo$ \5 Q. ?2 f. [% p
2 s; X' p( G% S+ Q" C6 `+ n - name: mount cdrom
" M" {. `, G( j mount: src=/dev/sr0 path=/mnt fstype=iso9660 state=mounted
. b( Z' h" f. c - name: install apache; R( v& T6 d; K
yum: name=httpd state=latest
. D; x$ t8 p( B, S2 ? - name: prepare httpd configuration file" X. q; V) B% B! Q2 _0 t
copy: src=/opt/httpd.conf dest=/etc/httpd/conf/httpd.conf mode=644 owner=apache group=apache
- a1 x# E- f9 y7 q" \9 F notify: "restart httpd" #如以上操作后为changed的状态时,会通过notify指定的名称触发对应名称的handlers操作
: w* c' L# x3 A
9 C" A+ f. i/ a# K3 j - name: start httpd, ?! i; s+ n: Q k
service: name=httpd state=started enabled=yes, U- Z' B0 p$ K" p3 x2 I
* v0 S9 t" r4 }: w& K$ K handlers: #handlers中定义的就是任务,此处handlers中的任务使用的是service模块
* F8 {5 K+ s6 X' f - name: restart httpd #notify和handlers中任务的名称必须一致
9 V8 U" j3 h. S: G service: name=httpd state=restarted4 ?/ Y% [% b6 ?& l, g
运行playbook
+ j* v/ i: Y# J1 Q& u! c# z" `9 A. `
ansible-playbook xxx.yaml) M* f# }2 C: k7 C) Z2 a2 G
8 I6 G9 ~) G& \/ M& o+ `. o
补充参数:
! ^: y# X3 V0 R -k(–ask-pass):用来交互输入ssh密码
# z* k1 ^; i! j1 M5 Z1 H _$ m -K(-ask-become-pass):用来交互输入sudo密码
( C: O' E F9 D -u:指定用户
( M4 e- E6 |5 a
/ c& N& R5 F9 ?8 s6 Y" k9 K% H1 L5 G! z7 T% [0 L( b+ t
6 I; L# k" v8 e/ O+ Y
Ansible在执行完某个任务之后并不会立即去执行对应的handler,而是在当前play中所有普通任务都执行完后再去执行handler,这样的好处是可以多次触发notify,但最后只执行一次对应的handler,从而避免多次重启。
5 o% W' v4 I8 X( V J# j7 J
$ R- M& A/ a' e3 S; O- _& d2 ^& J2.使用playbook安装启用nginx服务
4 z1 t5 U$ b( R) ], O! f首先编写xxx.yaml文件2 P3 I# |- W: p$ T- t9 q+ z0 }
2 K& P* a; h7 S---! n5 {0 l% X# Z0 R% t: f4 T
- name: nginx play
& P- N% p n$ j# R gather_facts: false
0 {0 R2 u/ D* u1 z7 {: y hosts: webservers4 t% h- e( A( L' ~1 Q, n# Z
remote_user: root
* H6 R& C/ C; s- `/ c tasks:
; _6 }# Q6 Q8 r5 Z - name: test connection5 K( s s! S9 y* t2 v7 R5 l$ [/ T
ping:
% r. W/ e2 g! B- V+ l+ [, s! t" l
- name: disable selinux
9 L F8 T3 Y9 }4 I2 z! h. O0 E3 N command: '/usr/sbin/setenforce 0'2 \: u6 f( Y: i- k6 d
ignore_errors: true
]; a: a, ?. Z/ S# j y7 d
; d9 y; }" W2 z7 R. K3 y - name: disable firewalld0 u3 F2 t: k) f3 l
service: name=firewalld state=stopped enabled=no+ B! D& D" g5 \& j4 I
0 }' d% Y- D+ \3 L! c5 X
- name: prepare nginx repo
- p9 x. B7 P0 | |* ? k/ u copy: src=/etc/yum.repos.d/nginx.repo dest=/etc/yum.repos.d/nginx.repo
- R. E* a8 p) M" H5 M; k2 I* U7 U ^: m. l
- name: add dns
3 A$ d! x/ L- D$ \9 N9 d- H copy: content="nameserver 8.8.8.8" dest=/etc/resolv.conf
# p+ B5 \& `/ j, q3 D; {5 i
5 E, i/ A( v0 r _ - name: install nginx
) ~+ p) R' e4 [, K6 U yum: name=nginx state=latest( [- N3 v6 y# s1 ^% G3 k
$ V ]0 `3 z# Y# i8 q( P6 H) j - name: prepare nginx configuration file
b# ?9 P+ j+ ?4 }) C copy: src=/opt/nginx.conf dest=/etc/nginx/nginx.conf mode=644 owner=nginx group=nginx
) N9 s$ a) _+ B. f+ n, g- L U) \- x; V& k8 a# a
- name: prepare nginx configuration.d file: ?' B# Z2 m0 H* Z ?
copy: src=/opt/default.conf dest=/etc/nginx/conf.d/default.conf mode=644 owner=nginx group=nginx
# Z( n+ q1 Y4 L/ s ~: e notify: "restart nginx"
% {0 |. X0 }( V- P6 l4 t5 g7 Y G5 a# Q) a! ]1 ^1 b
- name: start nginx
: I! R/ `$ D7 Z7 W8 x! f! E service: name=nginx state=started enabled=yes
u9 y0 x: t6 B C( N9 y }# ?
' K- i3 N* g9 i7 y$ X handlers:' n! D6 V1 s$ g& f$ {2 |( X
- name: restart nginx. l! h; ?+ J3 C( u. V V
service: name=nginx state=restarted
+ ~7 v: C6 X6 w) Z0 E3 ]- {8 ]运行playbook
% L3 t9 o! J! u1 m( i- r2 t
' | ^) ?& k' | j* X检查yaml文件的语法是否正确; h9 P) V# Q7 ?! H0 \, z* v) D& y
ansible-playbook xxx.yaml --syntax-check
0 u# \1 h! i9 ]+ `: A2 p4 n8 G8 c
( Y9 T6 ~' w9 L1 x; A0 ]: r如果语法格式有问题会报错 $ _9 [8 }3 w2 g% K
- \ q8 ?2 Y6 @: U8 h: `$ P% i: e, ?0 v2 q7 r
3 K( j# ?! C9 ~0 \( [( Z3 ~2.检查tasks任务) z. r! F1 X+ k. j% N
ansible-playbook xxx.yaml --list-task( s0 ?$ v/ O+ v* d. f3 ~
. s) Z' a3 m6 ^如果任务列表中的语法格式有问题会报错 0 M! l. H. M% t) }* A/ R
$ w+ T. u$ i3 g
4 l1 @( _( k) R. _8 V
4 |& r, m3 S9 T8 @3.检查指定的主机
) Y V0 w7 k# V) M( Lansible-playbook test1.yaml --list-hosts! R0 Q- d% V& H& z% E) ^# {
6 N2 F1 Z \: c
/ i! ]6 q* y$ w$ H. m
$ O% h% Q+ u& v k
4.指定从某个task开始运行
$ D9 \( A* |+ F; r7 n$ ^2 _ansible-playbook xxx.yaml --start-at-task='任务名' , n2 d. }! M5 G8 m4 n6 M
" N; J3 t n* d, G M
四、playbook进阶语法
8 T$ X/ v: u! ~8 F+ ]/ Q" A1.引用变量% p7 I* k$ g' c* X# V+ i \
(1)自定义变量% g' }1 Z4 H6 x- N, P
编写文件8 G2 q+ c+ q9 o d4 w' Q' p3 @
( C$ N& L1 F: i2 k4 I3 V
/ |7 O, E! ?! I: K
) A: ?! d) ^+ ~! l- t3 `运行playbook, Z+ g, B. e( x7 Y
9 R3 l9 @6 \( {0 ~. U# ?! K
# x6 d0 \5 M/ {
* h8 z" y2 p+ T$ ?2 q' F查看结果
4 @, e0 g2 _( z1 w4 V" z h3 p* F. L9 N& N Z" L! E, l
h* L, a I) `
) ^. {/ o, g& E. D0 W s
(2)引用setup模块信息中的变量
6 H) _0 S4 B0 l" Y- ^编写文件' A' ?5 {! \" v$ T' B# t/ Z
% _4 V! }2 y* }7 |
: n& b+ k& O7 g4 K v( D/ M
$ i% J( d* t* w3 [, Z& U运行playbook
3 B) P% V4 a# T
2 u& L0 `4 r7 N# K' y1 C5 ] T1 n1 ?2 k+ u8 j q# q2 ?0 r
6 M/ v# D$ s8 c$ @
查看结果
' L# _! j2 k) T3 p
3 \/ m" G3 ]8 X% ~7 C0 U/ `/ Q$ k* ]- w
4 B. f5 h2 }5 x/ i
2.遍历值 |" ?/ ?, u( T2 E
Ansible提供了很多种循环结构,一般都命名为with_items,作用等同于 loop 循环。
! I3 @/ v0 K3 A8 @/ L8 y" X( Y* Y! |4 b* g1 E/ \! X8 b9 W. i' K( T
with_items:将每个列表中所有值遍历输出。' V, ]$ ?8 O# ~$ k: F# ~: g
( [, ~# n3 c$ Zwith_list:将每个列表作为一个整体输出。% x! ]$ w. ^4 E i. }
m' m" l/ Z% W- Z
with_together:将每个列表中对应的值混合输出,如果个数不一致,将无法混合输出的值用null值填补组合的空缺。2 Z8 |# ~ m2 _
7 N, O, v* [3 e- ?: a
with_nested:将每个列表中的每个值组合输出,类似多重循环。
& V# {8 A3 L( K0 ]4 ]' x+ D& _0 \) u: s7 c
(1)遍历变量中的值
2 I6 q1 s( U+ G! u; P* f& v* U1 v* ^- v' l8 O1 L
/ U3 k; W# l3 b
2 O t, L+ z) p+ `; b4 p/ o7 [7 @
6 z) r% T6 E3 V% P(2)遍历指定的多个值6 W/ Q2 } h! N$ X; M
" [8 F' k$ R, b. s {( H* t3 O2 _3 }3 b
指定方式,也可以是列表的格式
+ G# i1 k0 g" H2 S- }3 Z
/ X4 o6 Q& F/ o
% X( F5 H4 |. w, z( \ P: M$ c
5 Q1 D, ^4 Q+ q# ^ g(3)遍历参数列表$ g' I4 f8 t) H9 w( G2 J! j# }
* l) |# v* {7 T" `6 O
1 |8 j) j- ?# ~) W5 }; J1 ?格式也可以是 - {username: zhangsan, filename: 1.txt} 7 p3 }2 W9 G1 ~- t" ^
6 ?- U! }- x! k9 [3 x% I- n- z8 X0 Q
9 b+ v" |) P; |: j3 ^2 e0 |# k4 q3.条件判断
+ W# v. _4 d9 q" X. M2 W0 g; D 在Ansible中,提供的唯一一个通用的条件判断是when指令,当when指令的值为true时,则该任务执行,否则不执行该任务。
+ H5 E: }+ n4 ]+ ]; X: {2 n# Q: Z& H
5 p* V" }: [7 Y when一个比较常见的应用场景是实现跳过某个主机不执行任务或者只有满足条件的主机执行任务。
7 n y" l# G) k. R% ^* c: \" O: j
5 C v& S. b- g% x. j/ D; i2 Gwhen: ansible_default_ipv4.address 条件表达式 "ip地址" * l& S8 x# E3 j# P2 M
when: inventory_hostname 条件表达式 "主机名"$ E" B' B6 i4 O
+ }5 T; ~- g" }0 u. K. x# j
: i |8 o# v) j
6 w1 F) O4 ]+ u3 c+ Y- @9 L& `
2 ]# d# g. K" r' U0 u" R1 \. w/ o4 ?4 o2 ?4 J) N# C# F
4.指定远程主机sudo切换用户
+ Q) ^$ F$ f3 ]1 S) k当ssh不允许root用户登录时,打开普通用户sudo提权
: p/ ]3 m( y8 E1 [1 o& n1 J5 z' M; q: S4 A" `9 U/ [/ X
; |4 p5 r) H. j9 v' o0 ~- r- J& S
' d9 i( x% i( ]# s( x9 Z
5.tags 模块 , p- E2 Z; g' A* r( p; d, z
可以在一个playbook中为某个或某些任务定义“标签”,在执行此playbook时通过ansible-playbook命令使用--tags选项能实现仅运行指定的tasks。
& a. G. S7 [% K! E4 x2 k3 P# v' J4 w/ \7 ~; F
playbook还提供了一个特殊的tags为always。作用就是当使用always作为tags的task时,无论执行哪一个tags时,定义有always的tags都会执行。0 O1 S+ k; `2 D; C9 J
/ K0 R/ S3 J, M' a+ a
- V- w4 K$ J8 w( a9 G9 i/ P( S
% m t& f. p" l1 `5 {- w; ^# H; n! Q" @, E8 u" \
. U7 W4 {5 ^1 W* b3 A# i( W8 r1 b# X4 ^. b' X6 D1 `1 ]
; N3 J/ W" l! F& k
3 P2 T- I6 ^% i2 h X% K! o: C/ _0 t: Q" E' |
$ ?* Q% s8 {. x5 a5 ]
: j; Y0 s# Q* R; S |
|