易陆发现互联网技术论坛

 找回密码
 开始注册
查看: 2415|回复: 1
收起左侧

使用Ansible 在OpenStack平台创建实例

[复制链接]
发表于 2021-8-2 10:30:56 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?开始注册

x

Ansible 中的新模块使用Python Shade库 。 Shade目前不为CentOS或Red Hat Enterprise Linux打包,如果您使用的是其中一个发行版,则需要使用pip安装。 Shade可用作最新版本的Ubuntu和Fedora的操作系统软件包,并且可以通过常规机制安装。

+ v  y% k! X' a; a) b& q
yum install -y epel-release4 o. V; `! J& [+ c% P- L7 i" C8 z
yum install -y  python-devel libffi-devel openssl-devel gcc ansible
9 J6 s4 |0 z& @0 x2 Gpython get-pip.py  f6 T, ~# W- I- P- J


, H* ?- W2 S- v" b3 u& dpip install -U pip    ##当前python2支持pip-20.3.40版本
% k$ I( ^1 b( `' @$ ]3 N' E
+ B; u: N2 k# q! R3 z9 q# M- x* ?" C- {
pip install shade" V& p; g- ]( G. c
+ @  \+ c1 G' t

& d& |( }3 {6 L

这二个模块最大的变化是认证。 使用nova_compute模块,在任务中将认证详细信息指定为选项。 使用新的os_server模块,认证是从由“openrc”脚本设置的环境变量中提取的。 大多数openstack安装有一个选项,可以在Horizon的“访问和安全”下为您的特定租户下载openrc。 要设置这些变量,只需在运行playbook之前先运行openrc脚本,如下所示:

./openrc.sh

编写一个在OpenStack云中创建实例的例子:

1 q( v) D* l1 N$ @; g: W2 t/ v# r# S" k
vi openstack_deploy.yaml' N  T0 w* ~4 m( ]: `- L8 V

( a% u0 B/ m% }. U. T$ E, C+ X4 ?; p! C$ J* ?* Z
---   I- s  Y4 Z' \% m: p
" J+ y; x3 U( ?& U" c

) H, i2 ~/ c4 g5 f6 T2 n-
# m* x* |! \& `8 z2 h% ?4 q; }- h+ ?

$ N2 F1 _+ R. p- L  gather_facts: false
3 {% u2 ]% }  X9 I
" {* _( f+ @7 o7 D& ~; X
# F) K$ A0 n7 E* T  hosts: controller- V0 v, }  p, }  @; {& g
' W, k8 R  I; {- h! m

+ u0 j" ]/ Q7 I, B7 d: R2 h  name: "Deploy on OpenStack"6 t/ N  k$ K; ]$ K" C

8 i0 n' Y5 c" [1 Y' W) t5 B4 L1 N, b: x
  tasks:
- c+ I7 @3 _4 c+ p( g
1 w- D5 z6 ^2 @2 \6 p1 F/ h/ x
1 X' I3 S5 z* q" a' R2 p   -
; ^  {$ p( l1 o* W8 G
% N- s: A$ a* Q# c6 n1 X7 L7 w' c1 T/ p$ W$ k- [$ G! C/ F- a
     os_server: 6 C# D% @# w  c7 \% j5 Y
! y6 O7 U8 s) ~9 z* V: `

. o+ Y& U! f8 t/ |7 v, {* J       auto_floating_ip: yes
' D( z9 e" B1 b( V- M9 \* r" A/ |9 p7 a8 c$ u/ r4 \3 \9 x# |
$ q; P0 m- B6 s1 r; s$ e. k
       flavor: 1C_1024M_50G
- X6 P, x3 @; H1 l( _
7 M% S, i1 ~/ W4 _* o. K! ]9 @. d1 ^: Z
       image: 69e26018-2456-4f5b-aaeb-8821f23a4329
% ~2 Z# U1 a" s5 i" A/ E3 I. f9 C% b9 s

7 `# F9 Q* f8 H8 R& Q$ a       key_name: ansible_key& t" i7 t9 _$ C$ D

6 Y0 Z" b( M; G
. X! Y: C$ e% T; @; ~       name: testopenstack$ D0 U$ F1 [, h
$ K  H. v% l7 Z1 a3 [
$ S2 R  O, u+ H
       network: linuxbridge: b% f$ ~9 C9 n) W6 }6 ]) Y

3 U2 |; Y- J/ `( Z: n  ^0 {) E$ G
( a' E' U8 L$ d7 f' n: l4 H. c       security_groups: default, B9 q3 O; l5 ?$ k4 y
# H) e, R6 i% u  y0 n/ ~- K6 I: k

$ m0 e7 w) U9 S, L       state: present
: l) ~$ a/ ~; l( _) T+ K/ c* N4 r
* D* ~& D3 d9 f; u& J& T, z+ w' l" q) L" Y$ B
       wait: true) t$ [+ R8 K' i0 ]
1 U4 z$ ^) P( L0 l* B5 _

' }; o* k, e1 v- F( a/ f( c# C
$ |* H- s( r" B7 B, n* y

运行测试

# . admin-openrc.sh  L3 \! x. W- n  q

# ansible-playbook -vv openstack_deploy.yaml) E8 O4 W; s# a0 W; ^! Y& O

这应该在OpenStack上部署名为“test142”的实例。输出将如下所示:

1 _) E* A6 o& R5 N; Z
Using /etc/ansible/ansible.cfg as config file1 t: O3 h( _. S5 c, @8 R  r
& S3 ?' U8 c, L3 c. w
. m& i5 \1 ]6 p: h4 M/ \
. E  ?# z; N! V+ c( M9 _5 U
0 ^' Y( Q; }4 C: a2 Q/ K
PLAYBOOK: openstack_deploy.yaml *******************************************************
  |3 M" j- v+ V' o, ~8 p( L4 Y5 {# }4 \
, `, a# m* W2 C& `+ E  ^
1 plays in openstack_deploy.yaml
; M% a% k1 t+ {2 A
8 @" d! M$ o+ i: U5 ~  C5 U( r% J' l" E) r; }5 N* T) m
PLAY [Deploy on OpenStack] *****************************************************
- M+ g' v  e( Q/ y' F- ?+ J# O! x* c' v& J0 s& G' J/ K
; g7 h( {* s5 U; Z3 T$ P
TASK [os_server] ***************************************************************  J8 d& _+ }+ J: X

0 g0 o1 h8 ~5 |2 ?4 [* e+ F6 y0 d+ o% D1 X; j& ~
task path: /root/openstack_deploy.yaml:8
. f$ ^- ]$ W) g5 O8 D6 [( j' m$ ?& M7 U, `) W9 n

0 {! T! j7 e! O- x" T
' Y0 n& a3 ~) Q% Z( i5 R4 c... ...6 T; L( {7 [* B

4 p. m, u( K* ]% B! @) M$ s, S* ~# j  Z7 Z4 I; _

+ {* ^: ]% s2 f3 O& n+ F, N( r0 BPLAY RECAP *********************************************************************
) {; I. F; N1 ^, Y+ T9 {
0 p8 t( |7 }4 Y& c" D
) |  B5 e+ t0 Z6 @4 b% ]4 n
& I: A2 ~+ \( F: w6 x4 }4 Gcontroller                 : ok=1    changed=1    unreachable=0    failed=0  
  |. A4 x8 a' T, @6 n# n
& t2 Q( g$ v' l6 T& |# @! [6 O: \9 {4 ~" L0 ?! ^
) [1 s0 ]4 H% p

在Openstack云中检查实例是否已创建成功。

 楼主| 发表于 2021-8-2 10:51:52 | 显示全部楼层
1 Ansible管理docker
$ p+ s$ E6 K. G近年来Linux容器技术越来越受欢迎,通过容器技术,可以保持程序运行环境的一致性,快速启动并高效率运行,涉及到的开销也比较小,此外,在系统层次上完成容器级别的资源隔离非常快速。, d* l; d' r4 G8 y
Docker是管理Linux容器最流行的工具,它为管理Linux容器提供了许多方便的工具,比如创建、销毁Linux容器,还提供了一些除管理Linux容器之外的工具,比如管理镜像、编排。通过它的易用性,Docker已经成为管理容器的最流行的方法之一。- Z3 ~( k% E" O1 k. |5 o: e/ b4 n
题外话:关于容器和Docker
1 q+ V! @% Q. S: U5 n# aLinux容器是内核的几种功能组合在一起实现的。换句话说,Linux容器技术是内核层次的功能,Docker只是提供了一系列工具,包括从底层和内核交互到高层和用户交互的一条龙。除了Docker外,也还有其它操作Linux容器的工具,只是对大众来说,Docker是最流行的。
2 i& P$ {  @/ w+ C7 Y9 mAnsible为Docker提供了一整套工具,包括相关模块、连接插件(ansible_connection: docker)和inventory脚本,因此Ansible可在许多方面与Docker进行交互。例如Ansible可构建Docker镜像、启动或停止容器、组合多个容器服务、连接到活动容器并与之交互,甚至可以从容器中获取inventory。
, F  s+ i3 Y8 a- D如下是Ansible官方目前提供的和Docker相关的模块:. U( Z1 G7 V% G" x
Code1 l. g+ `' K$ Y7 p
" ]9 R8 t/ l: J: E) t
docker_compose – Manage multi-container Docker applications with Docker Compose5 Q4 U, v8 @7 g4 Y1 C
docker_config – Manage docker configs# \# b0 |' i$ ~7 ]) d4 U
docker_container – manage docker containers9 c" S9 {$ o5 l: {  u7 {3 g
docker_container_info – Retrieves facts about docker container
8 t; I0 ^! d  |7 v. v, a) o9 Edocker_host_info – Retrieves facts about docker host and lists of objects of the services
0 V; U' c; V/ r3 e. b+ P, Tdocker_image – Manage docker images
0 `; x. t) L& }docker_image_info – Inspect docker images; F8 @0 o" g1 e+ P; i
docker_login – Log into a Docker registry
- z6 l2 n! S, P1 ldocker_network – Manage Docker networks1 i$ M* ?( b  w) A
docker_network_info – Retrieves facts about docker network
  W# {1 z$ O5 ^docker_node – Manage Docker Swarm node
2 S% ]9 \" {, D( u0 Qdocker_node_info – Retrieves facts about docker swarm node from Swarm Manager
& K* c- i, J! M% {+ M  R  wdocker_prune – Allows to prune various docker objects
7 ^, M' A& ^( T8 M2 ?& zdocker_secret – Manage docker secrets# L6 a4 F2 M, b1 {/ C' d' f
docker_stack – docker stack module
6 k8 F) D" I. ]( i, fdocker_swarm – Manage Swarm cluster( E% h- m) \9 V
docker_swarm_info – Retrieves facts about Docker Swarm cluster9 K. |; O( I3 w
docker_swarm_service – docker swarm service4 x; Q% n8 q% v/ {9 w9 C5 U, ?
docker_swarm_service_info – Retrieves information about docker services from a Swarm Manager9 g: q$ H2 U2 ~' n2 B
docker_volume – Manage Docker volumes/ D0 z, E8 a6 G
docker_volume_info – Retrieve facts about Docker volumes( W% @( Q1 ^- {/ [. X. v, g5 M
要使用Ansible管理连接Docker,要求安装如下包(注意:Ansible端和docker端都安装,这一点和其它模块不一样,如报错,请自行在两端安装、卸载、升级调试):/ J* w- h! F4 G5 L3 ?) X3 \1 e
Shell, i! h  t, }4 j! J( O
" ?! h3 H. M' O# X8 @( Z
# 两端都安装,如果已经安装了,则在报错的情况下按需更新. m, J5 D# i0 k' s4 }4 R
# 此外,根据Ansible使用的python解释器版本,按需决定使用pip还是pip3,
0 Y% I4 i. ]& R& k: ]! {& u# 如果需要的是pip,则yum install python-pip
1 I1 a) q; w/ k- G$ pip3 install docker requests9 G1 r$ \, ?7 p
如下是其中两次报错信息,注意其中的结尾:No module named ‘XXX’。% u' s$ m, o, K3 T2 L
Code7 Y; W, W8 Q# `
) Y& P1 c+ |6 ?" T: x3 |
fatal: [192.168.8.65]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (Docker SDK for Python: docker (Python >= 2.7) or docker-py (Python 2.75)) on controller's Python /usr/bin/python3. Please read module documentation and install in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` or `pip install docker-py` (Python 2.75). The error was: No module named 'requests'"}
4 Z: K2 p- d& D: f, o- mfatal: [192.168.8.65]: FAILED! => {"changed": false, "msg": "Failed to import the required Python library (Docker SDK for Python: docker (Python >= 2.7) or docker-py (Python 2.75)) on controller's Python /usr/bin/python3. Please read module documentation and install in the appropriate location. If the required library is installed, but Ansible is using the wrong Python interpreter, please consult the documentation on ansible_python_interpreter, for example via `pip install docker` or `pip install docker-py` (Python 2.75). The error was: No module named 'docker'"}* B" z7 z" N% ~: v
2 Ansible构建并运行Docker镜像
  I4 Q: i$ r# h7 k7 m0 }通Ansible提供的docker_image模块可管理Docker镜像(比如构建、移除、pull镜像),使用docker_container模块可管理容器,比如将镜像运行起来成为容器。
  p: w4 T2 h5 K) `对我们而言,一般都是在已有镜像的基础上通过Dockerfile来定义新的操作,然后构建出自己的Docker镜像。所以需要提供两个文件:一个基础镜像和一个Dockerfile文件(基础镜像不存在时会自动下载)。如果使用Ansible来构建镜像,那么这个Dockerfile文件需要能够被Ansible读取,比如可以放在Ansible playbook文件的同目录下。% M# \3 j7 [/ Z+ {5 a8 @6 s
为了演示以下Ansible构建Docker镜像,此处已经写好了一个非常简单的Dockerfile,该Docker镜像是在CentOS 7镜像的基础上添加nginx,然后让nginx运行起来并提供cowsay页面。, W/ s: G% ?; g4 E/ l: h8 w2 w
Dockerfile内容如下:
! {- }: R" t  S# _7 z, f8 XDockerfile8 T/ e2 _& P# C7 O" J" R- ]
: S/ F/ D" h/ B9 T
FROM centos:centos7' h7 V1 }8 ]" z% v" i& f0 u3 E  t
LABEL maintainer="test.com"
7 D) `* D4 }& A2 b; h' \RUN rm -rf /etc/yum.repos.d/*.repo && \1 z1 ?- _8 W, E( S: }& D
    echo -e ' \( ^  |" _) r! k& u, c  x+ B
[base] \n\7 e4 `. I& T- g; L3 }3 _
name=os \n\
) n* ~8 `7 W& Xbaseurl=https://mirrors.163.com/centos/$releasever/os/$basearch/ \n\; M$ H5 z0 M' C3 }& e! J
enable=1 \n\9 O( _/ ~9 r3 e; U5 u  K6 j
gpgcheck=0 \n\+ C( @/ D' @& V
[epel] \n\7 v% D8 q- l, s. T1 A
name=epel \n\
2 p9 ~6 ?) N! Jbaseurl=https://mirrors.163.com/epel/7Server/$basearch/ \n\
0 R7 A/ X4 B, I" U4 J: z! denable=1 \n\
8 H8 g; N, Y! a, q1 l9 ygpgcheck=0 \n\
( g9 U( I6 z2 a/ {$ {' >/etc/yum.repos.d/base.repo && \# s9 L7 ?0 q6 F" C1 I5 P. u
    yum -y install cowsay nginx && \
" i1 h; v' ]8 d) u    rm -rf /usr/share/nginx/html/index.html && \
; d3 y4 u# Z1 T+ f" M2 `$ s    cowsay test >/usr/share/nginx/html/index.html && \
9 w# z; K; C: z9 A+ c4 D9 ?    echo 'daemon off;' >>/etc/nginx/nginx.conf && \
( C8 I* F7 @$ j    yum clean all
% S. U' U  b' J) p7 W   
% l' A9 |* Q+ K  B" p% WEXPOSE 80
3 z" j2 l/ S- q( A, }& _CMD /usr/sbin/nginx
" k8 F% s* g* k& ~% X6 C8 U然后写一个Ansible任务文件,假设名为build_and_run_image.yaml,内容如下:
4 P, e- D# J6 ~  ~Yaml6 o1 `$ l6 v, y# I3 K) @
) ?/ V% t5 G3 V" w+ ?
- hosts: docker
8 k- q! d9 z' i1 ?  gather_facts: no
% V% u7 X" @& L4 h: B  tasks: 3 k5 K, E" k& A; i3 D
    - name: scp Dockerfile
0 `- R! K1 q& P, G- t* H      copy: * P( E: f  H& g- J2 S" H( A
        src: Dockerfile1 r1 t% W8 k& D! K; q3 H
        dest: /tmp/Dockerfile
% a7 `% P; h' o4 H& f7 G    - name: build Docker image centos_nginx:v0.1.1$ n/ g1 i) F7 K/ Q, S7 `
      docker_image: $ @* r/ v, c$ k, M$ m1 M" ?
        name: centos_nginx
; v7 {+ J3 T2 F        source: build7 K8 K; z" r+ U) M  O5 y* r
        tag: v0.1.1
1 z* ^. U' K  |1 V* I% I$ y/ n        build:
- D) T% q. t% o; s# X' s6 K          path: /tmp' X' }% e9 R0 V2 `& L
          pull: yes
4 D, h* ^  d: p    - name: start centos_nginx, V( _, I  F+ v) Q5 G
      docker_container:
' G3 |9 R, Z8 H. \7 R) d9 x3 }; j+ J        name: cng
5 x  u, r3 }" u$ B. d7 }        image: centos_nginx:v0.1.1
4 g# Z- L5 D' ^: A        ports: 8080:80
7 ]9 x' G/ f7 t6 `! c# z& ~        state: started
5 U" N* x4 u- ^6 X. x  IAnsible执行完成上述任务后,可直接在Ansible端使用curl来测试页面是否可获取:
0 r5 D$ S3 J6 a. _Shell( {1 A  ?! c1 h
9 c; ]. T! H  `3 G
$ curl 192.168.8.65:8080( r: O& L0 }! ?0 M: b# G
______________$ C: z" x" u2 ]% j% k, U3 e
< Junmajinlong >& N; M, l* e( `
--------------# Y2 w" w3 Y5 r  }" F: l& @; f
        \   ^__^- y# \: }% j& A  v8 e5 U
         \  (oo)\_______& E# v' a4 [9 o; n9 m
            (__)\       )\/\4 X& q9 z! A+ x& |) S
                ||----w |1 n" c6 Y" t4 [  H
                ||     ||
+ @9 S9 d& c* F  {' x0 M这里对上述两个模块稍作解释。- N% H2 H- G" Y- T7 i
对于docker_image任务来说,通过sourec: build指令来表示这是一次镜像构建操作,source指令可包含如下值:. O" O% Y/ i) z$ J6 [
build:根据build指令的path参数指定的Dockerfile构建镜像
# e, t: S: L; g- _$ ]3 Xload:从镜像tar文件中提取镜像$ z: K, B# N# @; ^/ `
pull: 从registry中拉取镜像
2 Q% m+ D" ?' n, _% K' a1 P1 h0 r& A  Elocal:保证docker端已经具备指定的镜像0 ?& m7 }1 w: b% e
对于build指令来说:1 f7 j$ `6 @  ]; k! c
path:指定构建时的上下文目录,该目录要求包含Dockerfile文件
; B) Z; z  M8 _9 o& Qdockerfile:明确指定使用哪个Dockerfile文件,而不是默认的上下文目录中的Dockerfile文件
: b( c8 s  X! w) n9 opull:构建时是否从registry中拉取基础和中间镜像镜像1 z/ D' l, U9 d+ k" ~
cache_from:构建时使用缓存的中间镜像
8 X  C& M6 c: M5 C: t. Fargs:可按照key:value方式指定镜像的参数,对应于Dockerfile中的ARG指令,例如listen_port: 8080! G6 s. S6 N' s' [& G4 d: ^; \
其它指令应该都通俗易懂。
4 ?; I, D" \/ t' v( \构建镜像完成后,可使用docker_container模块启动该镜像。该模块指令非常非常多,几乎包含了docker container命令的所有选项功能,但是熟悉docker命令,这些指令的用法也通俗易懂。比如,指定卷和环境变量:4 i( C: h. {5 s. `0 d9 Z9 E6 }3 ^
Yaml2 x' b* o3 r+ c
# \" Q: @" I" q; u9 w# z+ a

% k1 ?/ k! V. l+ E' [" ^1 A' J- name: Create a data container
7 _$ J% o9 ~, _# Z2 Q' l  docker_container:
( P9 @  K- E' l7 I/ J# ^    name: mydata
8 n- K% b8 J! }7 ^1 m    image: busybox
8 ]- `/ `8 K7 ]3 W& ~! f9 N    volumes:; N! A+ }( E' j0 M. r* D
      - /data9 M( c5 Q9 ]: v6 P( ^
- name: Restart a container
' C' f" Q& K/ F- F/ z$ F( y5 m  docker_container:) C! x) N/ u' d
    name: myapplication4 E! t; [) c) j# e/ R2 o
    image: someuser/appimage
! ~: j. s) z1 ?6 l3 p& p7 i) u    state: started
. S2 {7 u' e7 F5 x  g  U    restart: yes4 w  D( ?( U  i$ Q
    devices:4 j  p  G2 _' U9 W* [4 i
     - "/dev/sda:/dev/xvda:rwm"
4 w' W% ^  o0 P) Z    ports:5 V7 N, i0 z1 a; `1 [
     - "8080:9000"
9 w7 i4 f9 a; c- [5 j$ Z$ R. N9 S     - "127.0.0.1:8081:9001/udp") I1 J' K4 `6 s1 @* [2 j
    env:
2 ~2 R2 A" F4 ^9 x7 }        SECRET_KEY: "ssssh"3 M1 j/ N8 b" S# t
        BOOLEAN_KEY: "yes"6 _; l1 H. x9 I# m: W
3 无Dockerfile启动镜像并连接容器
: l2 z: z- V9 R8 ~# ^3 l2 z在上面的playbook中明确使用了Dockerfile来构建镜像并启动镜像提供服务,但因为Dockerfile自身也是基于基础镜像构建的,所以可以省略这个构建过程,而是直接启动基础镜像并连接到启动的容器进行操作。
! B0 W7 X3 H; d: C3 O& `下面实现与上述示例相同的效果,只是不使用Dockerfile构建。
; p4 \- C5 Y$ e( T2 ]" v. ^playbook文件内容如下:; t; Q0 b/ V% v" E+ c6 d* _
Yaml6 Q) ^. R! B- j2 v9 u- c8 w
. b0 ]& P, e2 i- D  L0 ]
---
) ~) E3 `  c; y1 R( v/ T- name: start image
1 h6 p- I( m9 L7 A5 G$ r" n  hosts: docker
4 I) }3 j  y4 _( h: g( }: I# F& P  gather_facts: no
/ f( X% U( d9 p! g  a( C9 G) l  vars: % u. {4 X" R. ~. h
    container_name: "centos7"
7 O5 }, Y6 X8 A4 x6 g* G% n. _  tasks:
( Q% B/ O8 O- M    - name: start basic container "centos7"
9 |* f; a' a  h; v" W; T6 N) a      docker_container:
( y, ?  B+ \7 m4 s        name: "{{container_name}}"
6 D9 [! L! ?& M        hostname: "{{container_name}}"
9 g- P6 s: u$ i- ^4 c, w: l        image: centos:centos7
  w8 m, p0 C; x' n9 O        ports: 8080:80
5 |8 f& [: R; i) C) V        state: started
( [3 ^2 [- O- H        auto_remove: yes: a& b( o+ \5 @& L/ o! H/ g" L! e0 B
        command: bash4 Y0 u# G- I6 z: G  F2 q4 a# h0 L
        tty: yes- O+ u- ?0 d0 l8 @3 g
        ! H! @* j5 G2 I; [% `, U6 v
    - name: add container to inventory+ r" U$ u6 S; e- r
      add_host:
* q+ E' I" @/ M4 \; s        name: "{{container_name}}"
3 H) G) i9 ~' C0 l7 Y/ e, l/ d* F        ansible_connection: docker
( F9 }3 u7 x2 S$ `' F, H        ansible_host: "{{container_name}}"
0 F& e" X7 o# [        ansible_user: root6 M9 m0 _6 {- @  @* U9 g
        groups: containers, E& C- I. l% a, w
        
* ~2 w$ u) ^) ~8 t% l. ^- name: do something in container
8 M* i% X0 _% N; P4 y6 v* I  Z  hosts: containers3 K; c  X- O2 F4 w) [
  gather_facts: no! K" W$ l5 L) v* @5 r+ W
  tasks:* m" F$ C! A% b  e; n
    - name: install python if needed3 E' Q$ F- g& `# i
      raw: yum install -y python! q0 R, l5 w, k! v; L6 \4 V7 u2 Y
    - name: remove all repos exists
' u8 R0 Q- X* ~6 j- C      shell: rm -rf /etc/yum.repos.d/*; w9 q3 f7 E$ i
      
: [6 ^0 R+ L( a6 v+ m, E# k    - name: add os repo and epel repo
+ f4 C. F$ R% N! N! x* q      yum_repository: / P7 i, d- [7 J4 |; e4 K) O
        name: "{{item.name}}"
1 g& g4 ~* ^+ P/ A. d        description: "{{item.name}} repo"' e" W/ }5 C8 [- u* D8 P# Y
        baseurl: "{{item.baseurl}}"
; @9 ]! Z: O. P        file: "{{item.name}}"
- B4 i* }/ \! q7 V4 I0 r3 e        enabled: 1
& n, Z. N8 i4 E& e( T$ ]        gpgcheck: 0  T; |( r+ K6 F) Z9 [& U9 X, F
        reposdir: /etc/yum.repos.d9 `6 k8 V0 M) @$ k% z
      loop:8 m! S4 I4 U. O& T6 j
        - name: os4 L3 F  `/ G  b
          baseurl: "https://mirrors.163.com/centos/$releasever/os/$basearch". y8 R, i$ ?* V3 ~& a) E+ e
        - name: epel
5 w% D# ?/ P& Q  T          baseurl: "https://mirrors.163.com/epel/$releasever/$basearch"      
/ c. N/ [  _* _( {4 E" |6 _5 o    - name: install nginx and cowsay  2 a3 c' H* U) M8 [3 }3 D! x
      shell: yum -y install nginx cowsay2 N' R. f  X* ?/ |/ R
      
2 y# Y! r% \7 g, W9 J% ]6 e/ X    - name: configure nginx
" Q% e) I9 W3 Z. T0 B! d      lineinfile:
% C5 i7 L; M! L0 Z" }8 m        line: "daemon off;"8 ~2 l) p  ^7 A) l0 L% ?" o" O# _
        dest: /etc/nginx/nginx.conf
; v2 i4 S' u3 I/ F, L! p        
! a3 J% g9 D% F& H5 Y    - name: change index page. e% @* _# W- A. X8 S
      block:
9 U* ]& D" h9 x7 ?( B5 b- h+ x        # 先移除index.html,因为它可能是一个软链接) j$ U1 m1 B! G6 X$ |; a
        - name: remove old index.html page
1 [. s3 h, N5 X& G6 G          shell: |
* u) {  S# s( g4 C3 l: M+ `! {            rm -rf /usr/share/nginx/html/index.html6 m! q: b. W9 H; \* \4 F2 C. U; ?
            cowsay test >/usr/share/nginx/html/index.html
- Q9 Y9 Y% L, r1 [2 j    - name: run nginx7 H4 E4 C2 K9 u$ U7 y
      shell: nginx &: |& U0 g7 H- H% P8 G/ }
在执行上述playbook之前,需要先在Ansible端导出连接方式docker所在主机的环境变量,比如Ansible连接到远程docker时,使用tcp:: y) v/ _8 f( h6 m: d8 b/ [
Shell
, y& x+ x/ g8 Z% w* N5 O' }& z0 \3 |

9 d7 r4 h+ j- O3 u+ N, }$ export DOCKER_HOST=tcp://192.168.8.65:2376
9 b9 N2 F/ P( M5 g7 X* |$ ansible-playbook -i inventoryname playbookname.yaml
0 s' g- S" w6 R4 A3 g- Q上面的playbook任务中,首先启动docker容器,然后使用了connection: docker连接器添加该容器到containers主机组中,以便后续的连接。之后在第二个play中连接到containers组,安装Python(CentOS系统都会带有python),配置yum源,安装Nginx和cowsay,并启动nginx。任务流程比较简单。  u1 ^+ i, g# q& m; D
唯一需要关注的是add_hosts添加容器节点到inventory时指定的docker连接方式,这里不能使用默认的ssh连接方式,因为目标容器不一定开启了ssh服务,也不一定能和外界通信,而使用connection: docker连接方式,Ansible将会先ssh连接到docker服务所在主机,然后通过docker container exec的方式连接到容器内部。
, x, I* U8 f! o/ b% {* X0 N     docker inventory. v. P& f& D) R- f  ~
Ansible为Docker提供了动态inventory的脚本。可下载该脚本:0 j; F) H: W; o. C  T$ M
Shell
' H  J+ l; ~  Z
9 y# w: t5 \3 c  t: h5 D
( I" ]& Y  n* g& d: R% y( i7 Qwget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/docker.py6 V4 K, N( L# t9 e7 E
chmod +x docker.py' U! ?) K# c. h4 d/ D
执行该脚本测试:: A0 W) d* d) [' M0 i% {$ h+ G
Shell
7 X9 v3 R5 Z) O8 _! s1 w' s
2 {# ^1 |# ~, Y# T7 dDOCKER_HOST=tcp://192.168.8.65:2376 ./docker.py --pretty
) Q+ ^, i  Y* ?% s或者直接在ansible命令或ansible-playbook命令中使用-i选项指定:
5 a. [* E% {2 Y% z& z  ^Shell( e% c# D# b1 k' k& ^& h! I
8 x0 C2 Y( {2 E# T& q
ansible-playbook -i docker.py docker_containers.yml
: a& l! T& h) x, ^1 Q4 其它Ansible容器管理工具; b7 V/ F" p' {% g9 A
Ansible除了在官方提供了docker相关的模块外,还有一些第三方的工具可用来管理容器。
- o' Z4 R5 I7 o! h6 z0 {比如ansible-container、ansible-bender、Ansible Operator,它们需要单独安装,对于ansible-container来说,在之前几年比较知名,但是作者现在已经将该项目废弃,据作者本人所说,ansible-bender和Ansible Operator更好。- ]' Z0 g) Q# M$ ~
ansible-bender:
5 [" z& `% X, w简化Ansible Playbook构建容器(注:此容器是符合OCI标准的容器,docker所构建的底层容器也是OCI容器)
- O% @- W$ }1 c' `9 v地址:https://github.com/ansible-community/ansible-bender; Z- p3 Z3 \/ V: X# ]
Ansible Operator:
/ g* k( G( ]. Q$ w是Red Hat Ansible Automation和Red Hat OpenShift团队联合开发的用来将容器部署到K8s上的工具
  }( E1 j+ C7 l; @" E2 Q/ o$ n0 f地址:https://learn.openshift.com/ansibleop: S2 h/ N$ h( z. X2 i" f
5 Ansible管理OpenStack
7 d% X* F5 r0 c4 B% lOpenStack可整合一台或多台物理计算机的资源来按需创建、管理、配置、删除虚拟机(在OpenStack中,虚拟机对应的术语是”计算实例”,但后文都以虚拟机来描述),对OpenStack提供者来说,提高了硬件资源的利用率;对受益用户来说,可按自己的需求申请带有各种性能、各种资源配置的操作系统,比如公有云的模式,就像去网吧上网一样,想上多久、想体验什么配置的主机都按需付费来享用。
- ?% u% H5 y+ x; ^' O6 e, l; m对于OpenStack来说,Ansible几乎是全程参与其发展的,因为从OpenStack很早的版本开始,就已经逐步支持通过Ansible来配置管理OpenStack,而Ansible管理OpenStack相关的模块也随着OpenStack的版本迭代在不断更新。目前为止,Ansible官方提供的关于OpenStack的模块已经有五十多个,下面是Ansible官方目前提供的模块列表信息简介:
3 m1 D; f5 u7 N! p+ P  e; ]7 qCode: ?  V5 c& c$ z/ o1 ~

, U/ K. M2 J" f2 D- q3 U( z' d3 Ios_auth – Retrieve an auth token
9 E( d9 r( M; L' kos_client_config – Get OpenStack Client config
$ O: ?  q) \7 j! g- M/ X# bos_coe_cluster – Add/Remove COE cluster from OpenStack Cloud1 Y: j+ c4 T! ~0 b0 l0 R% w
os_coe_cluster_template – Add/Remove COE cluster template from OpenStack Cloud# x0 q- C) k' l! X) [( [
os_flavor_info – Retrieve information about one or more flavors
( B( M% g# j# Z/ v3 j& jos_floating_ip – Add/Remove floating IP from an instance
& d1 @* i' l- U0 L9 _5 Tos_group – Manage OpenStack Identity Groups
/ \! }3 c1 n1 ^  a- l: xos_group_info – Retrieve info about one or more OpenStack groups1 b  C+ E" s% ]* u
os_image – Add/Delete images from OpenStack Cloud, O7 ~( @# t, I$ N8 V) z* a
os_image_info – Retrieve information about an image within OpenStack
# l8 e/ Y" G# Sos_ironic – Create/Delete Bare Metal Resources from OpenStack
; ]: i- I& e) k) wos_ironic_inspect – Explicitly triggers baremetal node introspection in ironic! H2 o7 P! d3 f) e. o+ j( Y
os_ironic_node – Activate/Deactivate Bare Metal Resources from OpenStack% i, x4 e9 q8 M) G
os_keypair – Add/Delete a keypair from OpenStack% b0 c- {' B0 n% B  j8 ]) F
os_keystone_domain – Manage OpenStack Identity Domains; E0 j  G/ [; L0 D" ?
os_keystone_domain_info – Retrieve information about one or more OpenStack domains
% ]% x5 T' I3 J+ }& ^os_keystone_endpoint – Manage OpenStack Identity service endpoints
8 h7 L) ^* ^# v" R: Z4 E9 i6 qos_keystone_role – Manage OpenStack Identity Roles' S7 X. |/ ^' I; {9 d
os_keystone_service – Manage OpenStack Identity services  b1 n5 E2 f  A% I" s  Q& E
os_listener – Add/Delete a listener for a load balancer from OpenStack Cloud* A& u! S5 Z8 ^' Z' g4 c) m9 Y( B
os_loadbalancer – Add/Delete load balancer from OpenStack Cloud
* E* f0 O9 ~# q: ]! e" t: q' _4 ros_member – Add/Delete a member for a pool in load balancer from OpenStack Cloud8 A3 f/ ^6 n  U8 o- |
os_network – Creates/removes networks from OpenStack- [7 }) K4 n6 r: ?! K
os_networks_info – Retrieve information about one or more OpenStack networks. X- J/ E# x  |  t
os_nova_flavor – Manage OpenStack compute flavors: w9 I9 D0 [8 s+ D4 H/ Y. Q" C
os_nova_host_aggregate – Manage OpenStack host aggregates
* z3 D% e1 Q3 H  `os_object – Create or Delete objects and containers from OpenStack
, w& x+ q8 Y4 J, Z! {. [# x3 U& Wos_pool – Add/Delete a pool in the load balancing service from OpenStack Cloud
, i) b9 s# J6 Q' Mos_port – Add/Update/Delete ports from an OpenStack cloud
; w( Z. V0 X% o% I/ v. Z3 Fos_port_info – Retrieve information about ports within OpenStack( }/ e! j& l+ {% T- [6 _
os_project – Manage OpenStack Projects( O8 C8 Y! j, I' V0 m
os_project_access – Manage OpenStack compute flavors access9 g/ u% e/ g4 q! A( W
os_project_info – Retrieve information about one or more OpenStack projects4 X; ^+ _, ?/ P! Y  ^  }8 W1 t; L
os_quota – Manage OpenStack Quotas
* ]7 L6 e0 ?5 ~2 g4 N" r- t$ nos_recordset – Manage OpenStack DNS recordsets
; H& f* s9 ^# _! F* Eos_router – Create or delete routers from OpenStack7 l. M1 [( `7 x* n' p9 q# s% v
os_security_group – Add/Delete security groups from an OpenStack cloud" `& ]. A% M" H% B- ]- e
os_security_group_rule – Add/Delete rule from an existing security group' x) \7 N- R# ^" ?
os_server – Create/Delete Compute Instances from OpenStack
* h0 i% b* I2 Eos_server_action – Perform actions on Compute Instances from OpenStack
7 B# K3 D7 T) o) [os_server_group – Manage OpenStack server groups3 B- K3 C% l, d) L- t1 z
os_server_info – Retrieve information about one or more compute instances7 ]0 Z5 _% z6 N" X% Z
os_server_metadata – Add/Update/Delete Metadata in Compute Instances from OpenStack
5 B1 O. ^# j' p6 ~3 _os_server_volume – Attach/Detach Volumes from OpenStack VM’s2 A4 z; p- Z" f2 u3 s
os_stack – Add/Remove Heat Stack$ [9 H9 D0 s4 r) j
os_subnet – Add/Remove subnet to an OpenStack network
- `% h* i6 ?! n" gos_subnets_info – Retrieve information about one or more OpenStack subnets
; v$ s* ?1 d% mos_user – Manage OpenStack Identity Users
' Y# H$ a( `+ b7 g4 o& Sos_user_group – Associate OpenStack Identity users and groups
  ?' j$ l1 W+ Z4 ?" A/ cos_user_info – Retrieve information about one or more OpenStack users
% |$ E: `. Q. ]3 k( dos_user_role – Associate OpenStack Identity users and roles
& F  M" `! f( ?- z. G4 ~os_volume – Create/Delete Cinder Volumes
- n6 G- |0 N9 Y- c  q1 Q& ^0 [os_volume_snapshot – Create/Delete Cinder Volume Snapshots
% o6 O( O& i/ Cos_zone – Manage OpenStack DNS zones
  L. B7 e% s( T% ]9 Z# U, r* l虽然看上去很多,但大致可总结为Ansible可对以下资源做管理:1 ^# Z  [( q& W! r; L0 _
(1).计算资源
& g. Q2 M/ N! e" T6 R(2).镜像管理
. F4 j8 t( ?8 A% t6 y% `1 c(3).账户管理和账户认证' h7 @& E/ v4 ~2 |
(4).网络管理
8 H3 y3 w' U8 s(5).对象存储管理
' e* |- {  ?$ n. ]( T% x6 }(6).块存储管理
  R" n5 f& A8 N- R0 r. Q对每种资源的管理可分为四类操作:
; s6 [0 W' I. d% K% l  Q(1).获取管理目标的信息) k+ Y% ]$ `, b+ ?* O$ q
(2).添加管理目标4 s( S) g- e/ i
(3).修改管理目标的属性1 l& @1 ?/ i4 T( r+ [8 z
(4).删除管理目标
7 M" f" O; f/ y% f7 W7 N即增、删、改、查。* m7 `( I$ R  j2 H
此外,由于OpenStack自身已经跟踪了其创建的每个虚拟机的信息,所以Ansible还可以直接从OpenStack中获取这些虚拟机的信息,比如从OpenStack取得某些虚拟机信息来构建动态inventory,这样就免去了手动提供虚拟机inventory的麻烦。8 Y3 w+ C, V5 J6 s7 x
本文不会介绍Ansible如何操作OpenStack自身(比如添加网络、上传镜像等),这和管理普通服务做的一些基本操作没任何区别,不同的仅仅只是做不同操作而已。本文会介绍Ansible管理OpenStack虚拟机时最常见的两种场景需求:
% ?4 l* z7 E0 K9 l% x5 `, ^2 V, y(1).使用Ansible创建虚拟机,然后像平时管理远程主机一样管理这些虚拟机,最后删除这些虚拟机3 t) u( I* @$ K
(2).从OpenStack生成动态inventory' J$ I( Y5 S/ q3 N& O+ r
14.2.1 创建虚拟机8 c' R% `$ m- ]  p; c+ C
OpenStack管理虚拟机相关的模块都以os_server开头,目前包括如下6个模块:本文大概只会用到os_server模块# ^- t* K- V( B, w2 j( Z0 J& W
Code
$ }# A. E4 G& o/ l9 J: {8 l# e: C1 H5 ^0 n
os_server – 创建或删除虚拟机0 K! X/ |" z) R
os_server_action – 对虚拟机做一些操作,比如虚拟机的关机、开机、重启、暂停、恢复等操作
) S+ J4 C: M" Dos_server_group – 管理OpenStack虚拟机分组,比如测试环境的虚拟机可属于test组,生成环境的虚拟机可属于prod组  
- q, M# c$ r& D; G% Sos_server_info – 检索一或多个虚拟机信息,在Ansible2.9之前,该模块名称为os_server_facts,用于检索虚拟机facts信息* f, y1 e3 u) t& X  [! n
os_server_metadata – 增、删、改虚拟机的元数据信息,比如设置虚拟机的主机名、虚拟机设备信息,如网卡配置、磁盘路径/dev/sda  % t/ Q7 ~. P* q! W
os_server_volume – 附加、剥离虚拟机的卷
, U; o! P% H% }9 F3 a4 J. B这6个模块都要求先安装好版本高于0.12的openstacksdk包,在CentOS 7中只需执行如下命令即可:* D% M1 ~4 x( R; N* M$ s
Shell* @, c5 B, n0 t3 p- \2 G2 b

( u, g9 h# `* L$ pip3 install openstacksdk( j3 C1 q1 I* d' ^4 d# v2 y
为了让Ansible连接到Controller进行管理,需要添加Controller的inventory信息。假如OpenStack的Controller的IP地址为192.168.8.65,可inventory文件openstack中添加如下内容:
9 K- s% F' \3 `( eUndefined
! O2 x6 T4 i/ g4 B8 ]1 ]/ R
. }8 B  j, i9 w4 E2 e7 H& j[openstack_controller]
  j% l4 Q# m) O! q+ m9 \# U# Z192.168.8.659 ?2 k* \: G+ P2 G
配置Ansible段和controller的ssh认证互信可自行配置,此处不赘述。. ~& Y$ r) r) {$ ]! j% H; b
然后就可以编写playbook来创建虚拟机,假如playbook文件名为create_vm.yml,其内容如下:
" M4 i) g2 D6 V4 eYaml
  Q1 s1 [" n4 F& c! A% ~5 H: \) q; Y5 d( h9 s- x
- name: create vm/ U: l1 i/ C! |. N( r) Z- D' X
  hosts: openstack_controller" W/ t1 \4 G& p, z* V/ @- C- B: g
  gather_facts: no
0 p  m- |% W2 h1 g6 x5 p" Z  tasks:
2 H! \7 p9 F  q9 N+ Z) T. I# U    - name: Create a new instance$ X- P& F5 @6 V0 M& q
      os_server:% w& \- m5 W5 M0 [$ v4 W) m+ S
        state: present
$ q( P0 E& P( R" \& j        auth:
9 |& ~2 @% |0 [          auth_url: http://192.168.8.65:5000/v3
2 U7 A9 M7 `( R1 a2 {) W          username: admin! A. d! @1 e0 n8 H4 Q) Y
          password: admin1237 U  j# k% X- n& y6 s
          project_name: admin2 r& X0 ~# F3 h# e* N
          project_domain_name: "Default": J. W; Z) j5 T' p( T7 z0 T. A9 A
          user_domain_name: "Default"# [5 b. K6 G- B7 q+ m
        name: vm1
0 q8 o9 S% t3 j0 G' z( T  T, I8 \$ W        image: "CentOS-7.9-x86_64"* P4 r# A( @" O5 l% Z+ K- ~
        key_name: ansible_key
; y1 T; k/ B8 `+ ^        timeout: 200: U7 S, c* K2 h. v' o
        flavor: m1.small
9 j0 t" l7 `$ ?" l7 x1 F        network: 'ext_net'/ z" K% a) \$ ]6 S! K) V
        wait: yes; q0 T7 K8 R6 _# k2 v
        meta:
, b2 c5 |0 k4 i  H7 _* u2 g. [          hostname: test1; I, l. N( V9 E3 S- c  o7 h2 F
          group: test_group9 t3 b2 i1 x" t( v$ t- g( \
          userdata: |; g/ L$ }- J. ~/ e! J) m3 S
            {%- raw -%}#!/bin/bash4 q0 }( }2 Y$ Y4 K
            cp  /home/centos/.ssh/authorized_keys /root/.ssh/0 T+ M2 k+ X) y6 Z/ O/ P% z' n
            {% endraw %}
$ T: F% ~; G& _; Z! W* Oauth部分是认证相关信息,name1表示创建一个名为vm1的虚拟机,image、key_name、falvor、network都是OpenStack中已经配置好的。这里还同时设置了虚拟机创建出来后的主机名为test1,并加入到了test_group主机组。
; C' q* @3 N8 B( V' F; ?6 o因为是CentOS镜像系统,该虚拟机创建出来后,默认登录用户名为”centos”,而且默认不支持root登录,为了后续可以使用root登录,上面使用userdata定义了该虚拟机创建后自定义的操作,即将保存的公钥信息拷贝到/root/.ssh目录下。
- Z( D: P" ^1 i" s. ~% m3 D注意os_server创建虚拟机任务中的一项wait: yes,它是默认选项,表示Ansible会等待虚拟机创建完成才会继续执行下面的任务。4 ^9 y7 x: k9 e: p( ^
因为所有的模块在连接OpenStack时都需要进行身份认证,为了简化playbook中的认证内容,将上面的auth选项段落的内容保存到OpenStack Controller的~/.config/openstack/clouds.yaml文件中。例如:
% t, P* N* l! T; a6 \% p) d- e! R/ i: a- GYaml
+ j, a, f! O5 `5 e/ N$ `& ]" @# \! e) u% `# n7 M, _
clouds:1 }& C4 d  {3 n6 S$ f
  mycloud:
5 X9 N$ ^# ]$ K* A' `( H: q    auth:  T+ `6 _! `. s! |& F! n
     auth_url: http://192.168.8.65:5000/v3( H, Y  U, W! d0 M# a
     username: admin" u- ^$ m. y) N$ t
     password: admin1231 x1 h) p& ?0 m4 {( {0 h
     project_name: admin0 d& N0 ^( y' X, a1 J8 L) t
     project_domain_name: "Default"1 c0 O  W) @. C: H* [
     user_domain_name: "Default"9 w' o+ b# T; a6 z' X# N( y6 G
以后在模块选项中就可以省略auth,而使用一个cloud: CLOUDNAME即可:1 d* H' |7 N2 K2 n/ y! e6 j$ l) _
Yaml& H# [( G$ D1 d! m4 k8 \1 z
( Z# F* [1 N% k) Z* F6 ?3 Y
tasks: ; o& m0 u  d/ x/ ^9 r3 l. Z  W
  - name: Create a new instance* q. z9 ]  ~9 B# V: K8 N8 W
    os_server:3 v8 ^/ k% \/ W1 K; h
      clouds: mycloud
6 [" s' J7 N$ H( C% U; b+ f9 j3 x( y      state: present
8 c# u4 G6 j% [( b1 c: ^      name: vm1
6 d" @/ g3 R  s* R. T7 ~      image: "CentOS-7-x86_64"
4 U) A! m0 t% R/ _2 R      key_name: ansible_key
1 ^% H+ F8 G0 d/ Z3 a+ e      timeout: 2008 P2 f% S. y$ F" U' N0 `$ x- |
      flavor: m1.small# s/ _. G) b* x, x& q6 D
      network: 'ext_net'
& h( Y( i# }8 O7 O      wait: yes
' Z, g; x4 t! t! F      meta:
" j0 i! a/ e; U4 E2 t1 ?: f        hostname: test1
" n7 ]# H# X* O. r9 P  |        group: test_group7 q# c* X5 Z) S1 d. h9 d# T7 Q
但是要注意,将认证信息以明文方式写入文件是不安全的,可以使用Ansible的Valut加密。不过OpenStack的dashboard中也已经提供了一个环境配置文件,可以先按照如图所示的位置下载:$ g5 ?9 J7 C+ ?" {

1 q) w2 D# c6 p3 ~! e( m( {然后以source的方式执行下载到的admin-openrc.sh脚本文件:
  N  E! N8 Z0 m2 i3 |Shell
3 w5 S9 v! h* I8 Y, g, j+ f1 G* N$ l8 P4 @0 ?/ d
source admin-openrc.sh
# x2 ^3 K( x( z- U/ G6 K执行完后,Ansible的OpenStack相关模块执行时,auth和cloud指令都可以省略。+ T/ B7 [. x, V8 X- c' n
上面只是创建一个虚拟机实例,但很多时候可能需要一次性创建多个虚拟机。可以将每个虚拟机相关信息定义到一个变量文件中,然后去遍历想要创建的虚拟机实例。例如:9 ?" Z) ?! P4 {6 v1 Q6 q
Code
, ~- E7 G6 f5 t0 }2 E6 R7 F
! @$ q/ g/ s  s---' r3 I* M2 |# n# ?: |
servers:
/ n% i% Q8 a( c  - name: vm1& _) z7 K, k4 R& V% Z
    image:
' \! r/ Z" ~8 f; U5 [: {    flavor: , r; e% \. A& W  \7 x8 N, {
    key: 7 ^" c" q( m% I. }
    nics:
$ A8 ^( n9 A! l4 j- `; k* j" s    meta:
* [2 h, J" z' _9 c. Y! C3 D" s      hostname:
+ J) l( _0 A# j, G      group:
) e( O1 [  z$ z' C" T) _. m# y* _  - name: vm2
+ Q# Q/ _/ n# ^6 _9 z6 v2 v    image: 3 a$ f, ^! S' t
    flavor:
0 X( c+ I9 l& H" l2 X+ }3 _! P    key: 2 i+ a8 P* O6 @- k- J  E3 [
    nics: # W3 ?6 Z9 D8 N2 d% f
    meta:
* }( E( j) l/ J# O! [# I      hostname: % |- x6 T& W; o* S2 E4 I
      group:
6 s) y7 O$ ?7 V# }5 C+ E有了前面的Ansible基础后,此处批量创建虚拟机应该毫无难度。
' r2 {" d" |$ ^  o8 A7 C创建虚拟机后,可以将os_server的任务注册到一个变量,从而可以获取该虚拟机的信息,包括该虚拟机的IP地址:0 L! F" `1 u  w4 k' n
Yml5 V: x! P* K/ `

- W, N% a0 |* P4 btasks:
( K' W0 I$ O" e  - name: Create a new instance
* A" n- B, G6 {5 }0 o    os_server:. p; V' w5 r; @. ]3 m+ T( I8 d2 I
      cloud: mycloud8 J  I5 i2 y8 _/ X! T  V# M- G: t
      state: present
) V7 ~% @4 z& s  y4 C' f      name: vm19 `0 M' q# n" |8 L  ^0 g
      image: "CentOS-7.9-x86_64"
8 N: Y" _8 c9 E3 x- A3 Z/ p) Y      key_name: ansible_key
2 F, d: ?! V8 @! ?      timeout: 200! ]" V* c- b- S* w$ [: F
      flavor: m1.small, H; m& A9 ?$ k) O: t. }+ j
      network: 'ext_net'
1 r2 n. ]) c' W: R! B      wait: yes6 d& @$ S3 K1 o# V, g. p$ n. k
      meta:$ `2 ~  ]/ R6 r1 ?9 v* U  ?
        hostname: test11 E; y1 |1 C1 Q* w# W, R3 g
        group: test_group
. m+ J6 ~+ e, a    register: newserver$ E. j2 E% a- a/ U2 I( w
   
$ ]. U/ K. y4 S3 t+ z) o$ I  - name: get instance ip
) o+ |2 ]" ^! S' ?' O  Z    debug:
- H$ I/ {. \8 J( N$ F      var: newserver.openstack.accessIPv4
; L3 F+ ~% [6 o# X4 s有了IP地址,对Ansible来说就获得了最关键的信息,因为只要将新虚拟机添加到Ansible inventory中,新虚拟机便像普通节点一样可接受Ansible的控制。
1 n% B; _, V" z- U- S- y8 ~9 W6、将新虚拟机动态添加到inventory5 O% F/ D% S& ^
获取到IP地址后,可以将该节点通过add_host模块动态加入到inventory中:
6 B" k- Z; o  h: a+ q; \" S3 hYaml
& S* G* y! X: Y7 p1 F! W) V9 z. i
2 q  Y1 C( q% T/ f; @' t& S7 u- name: add new vm to inventory; L+ G1 m/ T7 O3 L& V% q9 f( ?
  add_host:
5 ^* U8 [8 U. D' g  Z    name: "{{ newserver.openstack.accessIPv4 }}"9 m# M& d& r$ ]! u/ Z+ j
    ansible_host: "{{ newserver.openstack.accessIPv4 }}"
4 x: W' Q' G, D' P2 @7 t    ansible_user: "centos"
1 E& \- M& G2 W% G    ansible_port: 22
8 y% `" T& ^. i+ ]9 Q8 x    groups: , {& ^8 j* ~. F: i* v. d- k
      - vm_hosts
) j! m% m+ _0 Z+ K# v似乎这里的逻辑不太良好?如果虚拟机启动了但是不可连接呢?对于OpenStack创建的虚拟机来说,完全不用担心,因为os_server创建虚拟机成功后会等待该虚拟机可连接才真正返回。但对于非OpenStack的其它云主机实例则不一定,这时应当使用wait或wait_for_connection模块定义一个等待任务。尽管OpenStack中可以省略该步骤,但在脑海中应当要知道有这个步骤。
+ F  j% w/ s1 b  h$ D' P3 \, h此外,OpenStack安装的镜像系统可能是比较精简的系统,甚至没有安装Python,所以为了能管理这些虚拟主机,应先使用raw模块安装Python。4 d4 n! ]5 O1 I* \" m
Yaml
1 J+ L$ j8 e6 b' J" @8 ?- name: for new vm host
, C4 o/ D4 I6 ^( y, p" Y  hosts: vm_hosts
0 \8 F9 x/ s2 G0 a/ ^  gather_facts: no
: ^# _+ O. {& [# A! _% B# e6 M( ~: W  tasks:
/ B( Y+ y. n5 H1 B9 n5 a    - name: install python if needed9 X* h( y& J& M2 E9 ^
      raw: "sudo yum install -y python"8 h. _. i) ~9 d1 R8 ]* z
如此,Ansible便可以像管理普通主机一样管理OpenStack虚拟机。
1 ]1 |. F+ w/ K1 E$ n, `7、收集OpenStack虚拟机的动态inventory
9 C4 T( ~/ P- s7 _( X动态inventory一般需要写脚本(几乎是Python脚本)来收集,但即使不会Python也不用担心,因为对于OpenStack来说,官方已经提供了openstack插件,还提供了openstack_inventory.py脚本,该脚本位于Ansible官方github仓库的contrib/inventory目录下,查看文件时记得先选择对应Ansible版本的分支。
4 A; r9 ]8 u& M  I' i- X下载openstack_inventory.py并设置可执行权限:
/ O- z7 N2 q$ f( d) h: CShell
; R/ g7 g# l: U2 n5 m7 s3 I" X! ~- ^; l) A2 z4 M
wget https://raw.githubusercontent.com/ansible/ansible/stable-2.9/contrib/inventory/openstack_inventory.py
' v9 _. [5 G% I  q% L; Cchmod +x openstack_inventory.py
) C" E0 H$ |2 t/ x, R3 @然后source以下admin-openrc.sh脚本,再执行:. h& v; [, i5 h& R5 T" B
Shell
) O) w' l" g7 x4 A. a- k$ y$ ^* n' E) J  ^9 E
source admin-openrc.sh/ P0 Q9 N" l& g* A# N
./openstack_inventory.py --list8 l, l7 i) P% g
可查看inventory信息。0 y8 C; N! z% a) _( E# E! m& M
之后要将该脚本在ansible或ansible-playbook中使用,使用-i选项指定即可:
- @, U+ Y0 y# r: t$ Q9 Q5 ~; `3 jShell. u, v# p0 T$ y

+ R$ x' F! c3 ?  `0 |ansible-playbook -i openstack_inventory.py -m ping5 u# J; V3 V9 A
除了使用openstack_inventory.py脚本动态生成inventory外,还可以使用名为”openstack”的inventory插件。要使用openstack inventory插件,首先要在/etc/ansible.cfg中的[inventory]段的enable_plugins中开启script功能:
) k4 V7 @, f" y8 pShell$ {3 a9 W4 @9 `7 J& m

$ `6 O/ D* P7 h* M" e. `$ grep 'enable_plugins' /etc/ansible/ansible.cfg 3 f) l0 U8 Y+ Y$ ?! v( m; G
#enable_plugins = host_list, virtualbox, yaml, constructed$ M" a1 t4 i/ r+ ~5 w& J
取消上面的注释,加上script:
7 V' g* N  x, V; wIni; z; [. I+ X) {
9 X' E2 o( [6 u
[inventory]8 S0 x5 ?3 \/ A$ W
enable_plugins = host_list, script, ini, virtualbox, yaml, constructed
0 [9 o+ Z- \2 E3 J' I5 w以后只需在yml文件中加上如下plugin指令即可:# [. C/ s  F  d2 C$ ^( v# {# A  h
Code
8 ^5 p3 ]7 ~% G, ^/ V9 x! h7 P" z) c1 t* ?  z
plugin: openstack. B  Y5 |* w  L0 h: B
3 n, v# C7 ]$ T0 P, {$ ^
您需要登录后才可以回帖 登录 | 开始注册

本版积分规则

关闭

站长推荐上一条 /4 下一条

北京云银创陇科技有限公司以云计算运维,代码开发

QQ|返回首页|Archiver|小黑屋|易陆发现技术论坛 点击这里给我发消息

GMT+8, 2026-4-10 16:26 , Processed in 0.051246 second(s), 22 queries .

Powered by Discuz! X3.4 Licensed

© 2012-2025 Discuz! Team.

快速回复 返回顶部 返回列表