Playbook简介 Playbooks与Ad-Hoc相比,是一种完全不同的运用Ansible的方式,而且是非常之强大的;也是系统ansible命令的集合,其利用yaml语法 编写,运行过程,ansbile-playbook命令根据自上而下的顺序
依次执行任务。playbook 由一个或多个 ‘plays’ 组成.它的内容是一个以 ‘plays’为元素的列表,在 play 之中,一组机器被映射为定义好的角色.在 ansible 中,play 的内容,被称为 tasks,即任务.在基本层次的应用中,一个任务是一个对 ansible模块的调用。当第一个任务依次在所有主机上执行完毕后,开始执行第二个任务。如果某个主机执行时发生错误,则所有操作将会回滚。
Playbook基础组件
hosts
:运行执行任务(task)的目标主机
remote_user
:在远程主机上执行任务的用户
tasks
:任务列表
handlers
:任务,与tasks不同的是只有在接受到通知时才会被触发
templates
:使用模板语言的文本文件,使用jinja2语法。
variables
:变量,变量替换
tag
:标签,为某tasks指定标签,运行该标签可以即运行特定的tasks,定义为always的tag总会执行
when
: 条件判断,当条件成立则执行tasks,不成立不执行表达式 判断表达式如:not
or
and
!=
=
with_items
:循环迭代需要重复执行的任务列表,用{item}}
引用列表值
例如一个简单的playbook文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 --- - hosts: test remote_user: root vars: - bsh: b.sh - httprpm: httpd task: - name: install httpd yum: name={{ httprpm }} state=present tags: install_httpd - name: copy b.sh copy: src=/root/{{ bsh }} dest=/root/ owner=ala group=ala mode=0644 notify: - reload httpd when: ansible_distribution == "CentOS" - name: copy b.sh copy: src=/root/{{ bsh }} dest=/opt/ owner=ala group=ala mode=0644 notify: - reload httpd when: ansible_distribution == "Ubuntu" - name: start httpd service: name=httpd state=started enabled=yes handlers: - name: reload httpd service: name=httpd state=reloaded
其中的ansible_distribution
是ansible收集的facts变量。
playbook定义变量 ** ansible 常见定义变量有以下 6 种**
/etc/ansible/hosts文件主机中定义
/etc/ansible/hosts/文件主机组中定义
playbook的yaml文件中通过vars定义
获取系统变量,也称facts变量
分文件定义主机和主机组的变量
playbook 的role中定义
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 192.168.200.136 http_port=808 maxRequestsPerChild=808 192.168.200.137 http_port=8080 maxRequestsPerChild=909 [websers] 192.168.200.136 192.168.200.137 [websers:vars] ntp_server=ntp.exampl.com proxy=proxy.exampl.com --- - hosts: test remote_user: root vars: - bsh: b.sh - httprpm: httpd ansible 192.168.200.136 -m setup /etc/ansible/group_vars/websers /etc/ansible/host_vars/hostpc $ cat /etc/ansible/host_vars/hostpc --- ntp_server: acme.example.org database_server: storage.example.org $ cat /etc/ansible/roles/nginx/vars/main.yml --- nginx_port: 80 nginx_domain: www.abc.com nginx_user: nginx
playbook role目录结构 Roles简介 Ansible为了层次化、结构化地组织Playbook,使用了角色(roles)。Roles能够根据层次型结构自动装载变量文件、task及handlers等。简单来讲,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中,并可以便捷地include它们,roles一般用于基于主机构建服务的场景中,但也可以用于构建守护进程等场景中。
创建Roles 创建roles时一般需要以下步骤:首先创建以roles命名的目录。然后在roles目标下分别创建以这个角色名称命令的目录,如websevers等,然后在每个角色命令的目录中分别创建files、handlers、tasks、templates、meta、defaults和vars目录,用不到的目录可以创建为空目录。最后在Playbook文件中调用各角色进行使用。
roles内各目录含义解释
files
:用来存放由copy模块或script模块调用的文件。
templates
:用来存放jinjia2模板,template模块会自动在此目录中寻找jinjia2模板文件。
tasks
:此目录应当包含一个main.yml文件,用于定义此角色的任务列表,此文件可以使用include包含其它的位于此目录的task文件。
handlers
:此目录应当包含一个main.yml文件,用于定义此角色中触发条件时执行的动作。
vars
:此目录应当包含一个main.yml文件,用于定义此角色用到的变量。
defaults
:此目录应当包含一个main.yml文件,用于为当前角色设定默认变量。
meta
:此目录应当包含一个main.yml文件,用于定义此角色的特殊设定及其依赖关系。
如下定义了一个nginx服务的playbook目录结构树。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 [root@k8s-master1 roles] /etc/ansible/roles/nginx ├── defaults │ └── main.yml ├── files │ └── nginx.tar.gz ├── handlers │ └── main.yml ├── meta │ └── main.yml ├── tasks │ └── main.yml ├── templates │ └── nginx.conf.j2 │ └── default.conf.j2 └── vars └── main.yml
使用roles安装nginx案例 实例环境
主机名
IP
系统
角色
ansible
192.168.20.210
centos7.5
ansible控制器
web-nginx
192.168.20.213
centos7.5
web服务器
hosts主机组清单 1 2 3 $ cat /etc/ansilbe/hosts [web-node] 192.168.20.213
生成ssh密钥 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 $ ssh-keygen -t rsa 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:m4+23Eh+dJ8r/9zSjpUbHJECh1iFQU8Z0QMlygrRm98 root@k8s-node1 The key's randomart image is: +---[RSA 2048]----+ | .. +==OB. | | .o.o*..o.| | . oo o o.| | .o. . .| | S.. . . | | o...E. o| | +. . . *.| | +.=. . ++=| | .*oo o+*=| +----[SHA256]-----+ # 复制ansible控制机上的公钥到nginx web服务器 $ ssh-copy-id -i ~/.ssh/id_rsa.pub 192.168.20.213 这里是root用户验证,输入完root密码后,就可以在ansible主机上无密码ssh登陆nginx web服务器了。
创建nginx的roles结构目录 1 $ mkdir -pv /etc/ansible/roles/nginx/{defaults,files,handlers,meta,tasks,templates,vars}
准备安装包和依赖包 1 2 3 4 5 cd /etc/ansible/roles/nginx/files $ wget http://nginx.org/download/nginx-1.16.0.tar.gz $ wget https://www.openssl.org/source/openssl-1.0.2r.tar.gz $ wget ftp://ftp.csx.cam.ac.uk/pub/software/programming/pcre/pcre-8.42.tar.gz $ wget http://www.zlib.net/zlib-1.2.11.tar.gz
准备安装脚本
该脚本已在手动安装测试过,建议各位在通过ansible playbook安装服务器前,先手动安装一遍确保无误。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 $ cat /etc/ansible/roles/nginx/files/install_nginx.shexport PATH=`echo $PATH ` PWD="/opt" NGINX=nginx-1.16.0 OPENSSL=openssl-1.0.2r PCRE=pcre-8.42 ZLIB=zlib-1.2.11 RUN_USER=nginxid -u ${RUN_USER} >/dev/null 2>&1 [ $? -ne 0 ] && useradd -M -s /sbin/nologin ${RUN_USER} mkdir -p /var/log/nginx yum install -y epel-release yum install -y jemalloc jemalloc-devel yum install -y gcc \ gcc-c++ \ gcc++ \ perl \ perl-devel \ perl-ExtUtils-Embed \ libxslt \ libxslt-devel \ libxml2 \ libxml2-devel \ gd \ gd-devel \ GeoIP \ GeoIP-develcd $PWD for tar in `ls *.tar.gz`; do tar zxf $tar done cd $PWD /$NGINX && ./configure --prefix=/usr/local/nginx \ --sbin-path=/usr/sbin/nginx \ --user=nginx \ --group=nginx \ --pid-path=/var/run/nginx.pid \ --lock-path=/var/run/nginx.lock \ --error-log-path=/var/log/nginx/error.log \ --http-log-path=/var/log/nginx/access.log \ --with-select_module \ --with-poll_module \ --with-threads \ --with-file-aio \ --with-http_ssl_module \ --with-http_v2_module \ --with-http_realip_module \ --with-http_addition_module \ --with-http_xslt_module=dynamic \ --with-http_image_filter_module=dynamic \ --with-http_geoip_module=dynamic \ --with-http_sub_module \ --with-http_dav_module \ --with-http_flv_module \ --with-http_mp4_module \ --with-http_gunzip_module \ --with-http_gzip_static_module \ --with-http_auth_request_module \ --with-http_random_index_module \ --with-http_secure_link_module \ --with-http_degradation_module \ --with-http_slice_module \ --with-http_stub_status_module \ --with-mail=dynamic \ --with-mail_ssl_module \ --with-stream \ --with-stream_ssl_module \ --with-stream_realip_module \ --with-stream_geoip_module=dynamic \ --with-stream_ssl_preread_module \ --with-compat \ --with-ld-opt="-ljemalloc" \ --with-pcre=../${PCRE} \ --with-pcre-jit \ --with-zlib=../${ZLIB} \ --with-openssl=../${OPENSSL} \ --with-openssl-opt=no-nextprotoneg \ --with-debug && make -j 4 && make install
配置变量 在安装nginx的时候或者其他服务的时候常常用到变量,下面配置变量是通过roles方式配置。 1 2 3 4 5 $ cat /etc/ansible/roles/nginx/vas/main.ymlcat nginx/vars/main.yml nginx_user: nginx nginx_port: 80 nginx_dir: /usr/local/nginx
准备nginx.conf模版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 $ cat /etc/ansible/roles/nginx/templates/nginx.conf.j2 user {{ nginx_user }}; worker_processes {{ ansible_processor_vcpus }}; error_log /var/log/nginx/error_nginx.log crit; pid /var/run/nginx.pid; worker_rlimit_nofile 51200; events { use epoll; worker_connections 51200; multi_accept on; } http { map $http_upgrade $connection_upgrade { default upgrade; '' close; } include mime.types; default_type application/octet-stream; server_names_hash_bucket_size 128; client_header_buffer_size 4k; large_client_header_buffers 4 4k; client_max_body_size 100m; client_body_buffer_size 10m; sendfile on; tcp_nopush on; keepalive_timeout 120; server_tokens off; tcp_nodelay on; gzip on; gzip_buffers 16 8k; gzip_comp_level 6; gzip_http_version 1.1; gzip_min_length 1k; gzip_proxied any; gzip_vary on; gzip_types text/xml application/xml application/atom+xml application/rss+xml application/xhtml+xml image/svg+xml text/javascript application/javascript application/x-javascript text/x-json application/json application/x-web-app-manifest+json text/css text/plain text/x-component font/opentype application/x-font-ttf application/vnd.ms-fontobject image/x-icon; gzip_disable "MSIE [1-6]\.(?!.*SV1)" ; open_file_cache max=65535 inactive=20s; open_file_cache_valid 30s; open_file_cache_min_uses 1; open_file_cache_errors on; include upstream/*.conf; include vhost/*.conf; }
nginx.conf.j2文件中nginx_user
和ansible_processor_vcpus
分别为用户自定义变量和-m setup
获取的facts。
定义默认server模版 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 ```bash $ cat /etc/ansible/roles/nginx/templates/default.conf.j2 server { listen {{ nginx_port }}; server_name {{ ansible_all_ipv4_addresses }}; index index.html index.htm index.jsp index.do; access_log off; location / { root /data/wwwroot; } location /nginx_status { stub_status on; access_log off; } }
default.conf.j2文件中nginx_port
和ansible_all_ipv4_addresses
分别为用户自定义变量和-m setup
获取的facts。
定义一个测试index.html文件 1 2 $ cat /etc/ansible/roles/nginx/templates/index.html this is test pages!
定义nginx启动脚本 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 $ cat /etc/ansible/roles/nginx/files/nginx.service [Unit] Description=The NGINX HTTP and reverse proxy server After=syslog.target network.target remote-fs.target nss-lookup.target [Service] Type=forking PIDFile=/var/run/nginx.pid ExecStartPre=/usr/sbin/nginx -t ExecStart=/usr/sbin/nginx ExecReload=/usr/sbin/nginx -s reload ExecStop=/usr/bin/kill -s QUIT $MAINPID PrivateTmp=true [Install] WantedBy=multi-user.target
定义tasks任务 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 $ cat /etc/ansible/roles/nginx/tasks/copy.yaml - name: copy nginx-1.16.0.tar.gz to client copy: src=/etc/ansible/roles/nginx/files/nginx-1.16.0.tar.gz dest=/opt/nginx-1.16.0.tar.gz - name: copy install_nginx.sh to client copy: src=/etc/ansible/roles/nginx/files/install_nginx.sh dest=/opt/install_nginx.sh - name: mkdir nginx data directory file: path=/data/wwwroot state=directory recurse=yes - name: copy index.html copy: src=/etc/ansible/roles/nginx/files/index.html dest=/data/wwwroot/index.html - name: copy nginx systemctl file copy: src=/etc/ansible/roles/nginx/files/nginx.service dest=/usr/lib/systemd/system/nginx.service - name: copy dependency pac - kage copy: src=/etc/ansible/roles/nginx/files/{{ item }} dest=/opt/{{ item }} with_items: - openssl-1.0.2r.tar.gz - pcre-8.42.tar.gz - zlib-1.2.11.tar.gz
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 $ cat /etc/ansible/roles/nginx/tasks/main.yml --- - include: copy.yml - name: install nginx shell: /usr/bin/sh /opt/install_nginx.sh - name: replace nginx.conf file template: src=/etc/ansible/roles/nginx/templates/nginx.conf.j2 dest={{ nginx_dir }}/conf/nginx.conf - name: mkdir nginx vhost directory file: path={{nginx_dir}}/conf/vhost state=directory - name: relpace default.conf file template: src=/etc/ansible/roles/nginx/templates/default.conf.j2 dest={{nginx_dir}}/conf/vhost/default.conf tags: ngxdef notify: - reload nginx - name: start nginx command: /usr/sbin/nginx
定义触发通知handlers 1 2 3 4 $ cat /etc/ansible/roles/nginx/handlers/main.yml --- - name: reload nginx shell: /usr/sbin/nginx -t; /usr/sbin/nginx -s reload
定义role入口文件 1 2 3 4 5 6 $ cat /etc/ansible/roles/nginx.yml --- - hosts: web-node remote_user: root roles: - nginx
查看当前nginx roles目录树结构 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 $ tree /etc/ansible/roles/ /etc/ansible/roles/ ├── nginx │ ├── defaults │ ├── files │ │ ├── index.html │ │ ├── nginx.service │ │ ├── install_nginx.sh │ │ ├── nginx-1.16.0.tar.gz │ │ ├── openssl-1.0.2r.tar.gz │ │ ├── pcre-8.42.tar.gz │ │ └── zlib-1.2.11.tar.gz │ ├── handlers │ │ └── main.yml │ ├── meta │ ├── tasks │ │ ├── copy.yml │ │ └── main.yml │ ├── templates │ │ ├── default.conf.j2 │ │ └── nginx.conf.j2 │ └── vars │ └── main.yml └── nginx.yml
playbook语法检测 通过上面的配置,我们已经完成了使用playbook方式安装nginx所需要的步骤,现在我们应该在执行该playbook前检查一下上述语法有没有错误。
1 2 3 $ ansible-playbook --syntax-check /etc/ansible/roles/nginx.yml playbook: /etc/ansible/roles/nginx.yml
测试安装 ansible-playbook -C
命令可以测试运行playbook剧本,而非真正在远端服务器上执行,这样可以方便查看playbook在执行过程中将会做哪些事情。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 $ ansible-playbook -C nginx.yml PLAY [web-node] ************************************************************************************************************************************************ TASK [nginx : copy nginx-1.16.0.tar.gz to client] ************************************************************************************************************** changed: [192.168.20.213] TASK [nginx : copy install_nginx.sh to client] ***************************************************************************************************************** changed: [192.168.20.213] TASK [nginx : mkdir nginx data directory] ********************************************************************************************************************** changed: [192.168.20.213] TASK [nginx : copy index.html] ********************************************************************************************************************************* changed: [192.168.20.213] TASK [nginx : copy nginx systemctl file] *********************************************************************************************************************** changed: [192.168.20.213] TASK [nginx : copy dependency package] ************************************************************************************************************************* changed: [192.168.20.213] => (item=openssl-1.0.2r.tar.gz) changed: [192.168.20.213] => (item=pcre-8.42.tar.gz) changed: [192.168.20.213] => (item=zlib-1.2.11.tar.gz) TASK [nginx : install nginx] *********************************************************************************************************************************** skipping: [192.168.20.213] TASK [nginx : replace nginx.conf file] ************************************************************************************************************************* changed: [192.168.20.213] TASK [nginx : mkdir nginx vhost directory] ********************************************************************************************************************* changed: [192.168.20.213] TASK [nginx : relpace default.conf file] *********************************************************************************************************************** changed: [192.168.20.213] TASK [nginx : start nginx] ************************************************************************************************************************************* skipping: [192.168.20.213] RUNNING HANDLER [nginx : reload nginx] ************************************************************************************************************************* skipping: [192.168.20.213] PLAY RECAP ***************************************************************************************************************************************************** 192.168.20.213 : ok=8 changed=8 unreachable=0 failed=0
运行nginx playbook 1 $ ansible-playbook nginx.yml
执行ansible-playbook nginx.yml
命令后,ansible将会按照刚刚测试安装的步骤在远端进行安装nginx服务并且启动。
验证安装结果 等待一会nginx playbook将会在远端服务器上安装完毕,现在我们来验证一下结果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 $ netstat -ptln | grep 80 tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 14461/nginx: master $ ps -ef | grep nginx root 14461 1 0 00:39 ? 00:00:00 nginx: master process /usr/sbin/nginx nginx 14474 14461 0 00:39 ? 00:00:00 nginx: worker process nginx 14475 14461 0 00:39 ? 00:00:00 nginx: worker process nginx 14476 14461 0 00:39 ? 00:00:00 nginx: worker process nginx 14477 14461 0 00:39 ? 00:00:00 nginx: worker process root 39501 1664 0 11:38 pts/0 00:00:00 grep --color=auto nginx $ curl http://192.168.20.213 this is a test pages! $ curl http://192.168.20.213/nginx_status Active connections: 1 server accepts handled requests 8 8 10 Reading: 0 Writing: 1 Waiting: 0
至此,一个使用ansible-playbook安装nginx服务已完成。