• Ansible之playbook&&roles


    运维:
    	手动 --> 标准化-->工具化-->自动化 --> 智能化
    	
    工具化:
    	OS Install:PXE,Cobbler;Virtualization & Cloud Computing
    	OS Config:ansible,fabric,puppet,saltstack,chef,cfengine,...
    	Deploy:fabric,ansible,...
    	Task Exec:fabric,ansible,func,...
    

    YAML语法格式

    
    

    ansible之Playbook

    Playbook的核心元素:
    	Hosts:关联到的主机
    	Tasks:任务列表,要做哪些事
    	Variables:变量
    	Templates:包含了模板语法的文本文件;
    	Handlers:由特定条件触发的任务;
    	Roles:
    	
    	playbook的基础组件:
    		Hosts:运行指定任务的目标主机;
    		remoute_user:在远程主机上执行任务的用户;
    			sudo_user:
    		tasks:任务列表
    			模块,模块参数;
    			格式:
    				(1)action:module arguments
    				(2)module:arguments
    				
    				注意:shell和command模块后面直接跟命令,而非key=value类的参数列表;
    		
    			(1)某任务的状态在运行后为changed时,可通过“notify”通知给相应的handlers;
    			(2)任务可以通过“tags”打标签,而后可在ansible-playbook命令上使用-t指定进行调用;
    			
    		运行playbook的方式:
    			(1)测试:
    				ansible-playbook --check
    					只检测可能会发生的改变,但不真正执行操作;
    				ansible-playbook --list-hosts
    					列出运行任务的主机;
    			(2)运行
    		
    		handlers:
    			任务,在特定条件下触发;
    			接收到其它任务的通知时被触发;
    				notify:HANDLER TASK NAME
    		
    		variables:
    			(1)facts:可直接调用;
    				注意:可使用setup模块直接获取目标主机的facters;
    				ansible 192.168.0.111 -m setup | less
    				
    			(2)用户自定义变量:变量引用: {{ variable }}
    				(a) ansible-playbook命令的命令行中的:
    					-e VARS,--extra-vars=VARS
    			
    				(b) 在playbook中定义变量的方法:
    					vars:
    						- var1: value1
    						- var2: value2 
    			
    			(3) 通过roles传递变量;
    			(4) Host Inventory;
    				(a) 向不同的主机传递不同的变量;
    					IP/HOSTNAME variable=value var2=value2
    				(b) 向组中的主机传递相同的变量;
                        [groupname:vars]
                        variable=value
    			
    				注意:invertory参数:
    					用于定义ansible远程连接目标主机时使用的参数,而非传递给playbook的变量;
    						ansible_ssh_host
    						ansible_ssh_port
    						ansible_ssh_user
    						ansible_ssh_pass
    						ansible_sudo_pass
    					...
    					
    			模块:
    				template模块:基于模板方式生成一个文件复制到远程主机
    	
    
    ansible-playbook --help
    	-C
        -D
        -e
        -f FORKS,--forks=FORKS
        -i INVENTORY
        -l SUBNET,--limit=SUBNET
        --list-hosts
        --list-tags
        --list-tasks
        -M MODULE_PATH
    	--step:单步执行
    
    	--syntax-check
    
    ansible-playbook --list-hosts --list-tasks first.yaml
    ansible-playbook -C first.yaml # 干跑
    

    案例

    vim first.yml
    - hosts: all
      remote_user: root
      tasks:
      - name: install redis
        yum: name=redis state=latest
      - name: start redis
        service: name=redis state=started
    
    ansible 192.168.0.111 -m fetch -a "src=/etc/redis.conf dest=./"
    
    vim ~/playbooks/redis.conf
    	# bind 127.0.0.1
    	bind 0.0.0.0
    	# requirepass foobared
    	requirepass admin123 
    
    vim first.yml
    - hosts: all
      remote_user: root
      tasks:
      - name: install redis
        yum: name=redis state=latest
      - name: copy config file
      	copy: "src=/root/playbooks/redis.conf dest=/etc/redis.conf"
      - name: start redis
        service: name=redis state=started
    
    ansible-playbook syntax-check first.yml
    ansible-playbook -C first.yml
    
    ansible-playbook  first.yml
    

    再次修改配置文件,如何热加载配置文件?可以通过handlers,在某个任务上添加属性notify,notify和handlers的name对应的名称要一致。如果配置文件没改变,handlers是不会触发的。

    vim second.yml
    - hosts: all
      remote_user: root
      tasks:
      - name: install redis
        yum: name=redis state=latest
      - name: copy config file
      	copy: "src=/root/playbooks/redis.conf dest=/etc/redis.conf"
        notify: restart redis
      - name: start redis
        service: name=redis state=started
      handlers:
        - name:restart redis  # notify通过其定义的名称,去找handlers的name触发,所以notify的名称要和这里的name一致
          service: name=redis state=restarted
    
    vim ~/playbooks/redis.conf
    	requirepass admin123123
    
    ansible-playbook second.yml
    
    在192.168.0.111机器上:
    	redis-cli
    	auth admin123123 # 认证成功
    

    如果我们只想跑某个任务,可以使用tags打标签,然后跑任务时加上 -t参数

    vim second.yml
    - hosts: all
      remote_user: root
      tasks:
      - name: install redis
        yum: name=redis state=latest
      - name: copy config file
      	copy: "src=/root/playbooks/redis.conf dest=/etc/redis.conf"
        notify: restart redis
        tags:configfile
      - name: start redis
        service: name=redis state=started
      handlers:
        - name:restart redis  # notify通过其定义的名称,去找handlers的name触发,所以notify的名称要和这里的name一致
          service: name=redis state=restarted
    
    
    
    ansible-playbook -t configfile second.yml
    

    # 再次修改本地redis.conf文件中的密码为admin123
    vim ~/playbooks/redis.conf
    	requirepass admin123
    
    ansible-playbook -t configfile second.yml # 如下图,通过tags标签copy这个任务,只跑了copy,而我们修改了redis.conf文件,又触发了handlers任务。
    

    yum install facter 
    facter -p  # 查看当前主机上的变量
    
    vim third.yml
    	- hosts: 192.168.0.111
    	  remote_user: root
    	  tasks:
    	  - name: copy file
            copy: content={{ ansible_env }} dest=/tmp/ansible.env
    	  
    

    variables的三种自定义方式

    vim var.yml
    
    - hosts: websrvs
      remote_user: root
      vars: # 直接在playbook中定义变量
      - pbvar: playbook variable testing  
      tasks:
      - name: command line variables # 使用ansible-playbook命令行传递变量值
        copy: content={{ cmdvar }} dest=/tmp/cmd.var
      - name: playbook variables
        copy: content={{ pbvar }} dest=/tmp/pb.var
      - name: host iventory variables  # 使用主机清单定义变量,如下图
        copy: content={{ http_port }} dest=/tmp/http_port.var
    

    编辑/etc/ansible/hosts文件传递变量:


    补充模块

    setup模块:
    
    template模块:基于模板方式生成一个文件复制到远程主机
    	
    	*src=
    	*dest=
    	owner=
    	group=
    	mode=
    	
    	模板:templates
    		ansible-doc -s template
    		文本文件,嵌套有脚本 (使用模板编程语言编写)
    			Jinja2:	
    				字面量:
    					字符串:使用单引号或双引号;
    					数字:证书,浮点数;
    					列表:[item1,item2,...]
    					元组:[item1,item2,...]
    					字典:{key1:value1,key2:value2,...}
    					布尔值:true/false
    				
    				算数运算:
    					+,-,*,/,//,%,**
    				比较操作:
    					==,!=,>,>=,<,<=
    				逻辑运算:
    					and,or,not
    
    			示例:
    				- hosts: websrvs
    				remote_user: root
    				tasks:
    				  - name: install nginx
    				  yum: name=nginx state=present
    				  - name: install conf file
    				  template: src=files/nginx.conf.j2 dest=/etc/nginx/nginx.conf
    				  notify: restart nginx
    				  tags: instconf
    				  - name: start nginx service
    				  service: name=nginx state=started
    				  handlers:
    				  - name: restart nginx
    				  service: name=nginx state=restarted
    				  
    				  模板配置文件: nginx.conf.j2
    				  worker_processes {{ ansible_processor_vcpus }};
    				  listen {{ http_port }};
    

    template模板使用案例

    ansible 192.168.0.111 -m setup | less  # 通过setup模块查看192.168.0.111虚拟机上的内置变量,得到ansible_default_ipv4有address属性
    cp /root/playbooks/redis.conf{,.j2}
    vim /root/playbooks/redis.conf.j2
    	bind {{ ansible_default_ipv4.address }}
    
    vim template.yml
    	- hosts: 192.168.0.111
      remote_user: root
      tasks:
      - name: install config file
        template: src=/root/playbooks/redis.conf.j2 dest=/tmp/redis.conf
    
    ansible-playbook template.yml
    
    在192.168.0.111虚拟机上,查看配置文件/tmp/redis.conf的bind后的变量是否被渲染出来:# 如下图
    
    

    将template.yml文件中的hosts改成all,再次执行 ansible-playbook template.yml,192.168.0.112的/tmp/redis.conf 中的bind后的变量也被渲染出来,如下图:
    
    

    案例:使用template在被ansible主机控制的主机上监听一个额外的端口

    vim /root/playbooks/mylisten.conf
    	Listen {{ http_port }}  # 这个变量在/etc/ansible/hosts文件中
    
    vim /root/playbooks/httpd.yml
    
    - hosts: websrvs
      remote_user: root
      tasks:
      - name: install httpd
        yum: name=httpd state=latest
      - name: install config file
        template: src=/root/playbooks/mylisten.conf dest=/etc/httpd/conf.d/mylisten.conf
        notify: restart httpd
      - name: start httpd
        service: name=httpd state=started
      handlers:
      - name: restart httpd
        service: name=httpd state=restarted
    

    案例:nginx启动的进程数是cpu核心数和cpu个数的乘积减1

    cp /etc/nginx/nginx.conf /root/playbooks/nginx.conf.j2
    
    ansible 192.168.0.111 -m setup | less
    	   ansible_processor_cores:"2"
           ansible_processor_vcpus:"2"
    
    vim nginx.conf.j2
    	worker_processes {{ ansible_processor_cores*ansible_processor_vcpus-1 }};
    
    vim nginx.yml
        - hosts: websrvs
          remote_user: root
          tasks:
          - name: install nginx
            yum: name=nginx state=latest
          - name: change nginx.conf
            template: src=/root/playbooks/nginx.conf.j2 dest=/etc/nginx/nginx.conf
            notify: restart nginx
          - name: start nginx
            service: name=nginx state=started
          handlers:
          - name: restart nginx
            service: name=nginx state=restarted
    
    ansible-playbook -C nginx.yml
    ansible-plabook nginx.yml
    
    当再次修改/root/playbooks/nginx.conf.j2,就会触发handlers,重新加载nginx配置文件(nginx.conf)
    

    条件测试(when)和循环(迭代)

    条件测试:
    	when语句:在task中使用,jinja2的语法格式
    		tasks:
    		- name: install conf file to centos7
    		  template: src=files/nginx.conf.c7.j2
    		  when: ansible_distribution_major_version == "7"
    		- name: install conf file to cnetos6
    		  template: src=files/nginx.conf.c6.j2
    		  when: ansible_distribution_major_version == "6"
    
    循环:迭代,需要重复执行的任务;
    	对迭代项的引用,固定变量名为“item”,而后,要在task中使用with_items给定要迭代的元素列表;
    		列表方法:
    			字符串
    			字典
    			
    	- name: install some packages
    	  yum: name={{ item }} state=pretent
    	  with_items:
    	  - nginx
    	  - memcached
    	  - php-fpm
    	  
    	- name: add some groups
    	  group: name={{ item }} state=present
    	  with_items:
    	  - group1
    	  - group2
    	  - group3
    	
    	- name: add some users
    	  user: name={{ item.name }} group={{ item.group }} state=present
    	  with_items:
    	  - { name: 'user11', group: 'group11' }
    	  - { name: 'user12', group: 'group12' }
    	  - { name: 'user13', group: 'group13' }
    	
    

    案例:根据不同的发行版安装不同的web服务

    vim os.yml
        - hosts: websrvs
          remote_user: root
          tasks:
          - name: install httpd
            yum: name=httpd state=latest
            when: ansible_os_family == "Redhat"
          - name: install apache2
            apt: name=apache2 state=latest
            when: ansible_os_family == "Debian"
    
    ansible-playbook -C os.yml
    

    迭代

    vim iter.yml
        - hosts: websrvs
          remote_user: root
          tasks:
          - name: install {{ item }} package
            yum: name={{ item }} state=latest
            with_items:
            - tomcat
            - tomcat-webapps
            - tomcat-admin-webapps
    
    

    角色(roles)

    在安装nginx之前,需要配置yum仓库:epel.repo:
    	这个仓库是epel-release模块:
    		yum info epel-release
    		yum intall epel-release
    		rpm -ql epel-release
    
    角色(roles):
    	角色集合:
    		roles/
    			mysql/
    			httpd/
    			nginx/
    			memcached/
    	每个角色,以特定的层级目录结构进行组织:
    		mysql/
    			files/:存放由copy或script模块等调用的文件;
    			templates/:template模块查找所需要模板文件的目录;
    			tasks/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
    			handlers/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
    			vars/:至少应该包含一个名为main.yml的文件;其它的文件需要在此文件中通过include进行包含;
    			meta/:至少应该包含一个名为main.yml的文件,定义当前角色的特殊设定及其依赖关系;其它的文件需要在此文件中通过include进行包含;
    			default/:设定默认变量时使用此目录中的main.yml文件;
    	
    	在playbook调用角色方法1:
    		- hosts: websrvs
    		  remote_user: root
    		  roles:
    		  - mysql
    		  - memcached
    		
    	在playbook调用角色方法2:传递变量给角色
    		- hosts:
    		  remote_user:
    		  roles:
    		  - { role: nginx,username: nginx }
    		    键role用于指定角色名称;后续的k/v用于传递变量给角色;
    		 
    		还可以基于条件测试实现角色调用;
    		roles:
    		- { role: nginx, when: "ansible_distribution_major_version == '7'" }
    ansible-vcs:可实现ansible-pull机制
    	https://github.com/andrewrothstein/ansible-vcs
    
    实战项目:
    	主/备模式高可用keepalived+nginx(proxy)
    	两台主机:httpd+php
    	一台主机:mysql-server或mariadb-server;
    
    http://www.ansible.com.cn
    
    
    ansible在配置文件(/etc/ansible/ansible.cfg)中已经说明,它的角色应该放在 /etc/ansible/roles或/usr/share/ansible/roles目录下,才能默认被找到,不然自己修改配置文件的role_path定义路径。。。。。。# 如下图1
    			
    

    图1:

    mkdir -pv /etc/ansible/roles/nginx/{files,templates,tasks,vars,handlers,meta,default}
    vim /etc/ansible/roles/nginx/tasks/main.yml
        - name: install nginx
          yum: name=nginx state=latest
          when: ansible_os_family == "RedHat"
          
    vim ~/playbooks/nginx_roles.yml
    	- hosts: websrvs
      	remote_user: root
      	roles:
     	- nginx
    
    
    ansible-playbook --syntax-check nginx_roles.yml 
    ansible-playbook -C nginx_roles.yml # 如图2
    

    图2:

    (1)
    cd /etc/ansible
    vim roles/nginx/templates/vhost1.conf.j2
    	server {
    		listen 80;
    		server_name {{ ansible_fqdn }};
    		location / {
    				root "/ngxdata/vhost1";
    		}
    	}
    	
    (2)
    vim roles/nginx/tasks/main.yml
        - name: install nginx
          yum: name=nginx state=latest
          when: ansible_os_family == "RedHat"
    	- name: install config file
      	  template: src=vhost1.conf.j2 dest=/etc/nginx/conf.d/vhost1.conf  # 自动去../templates中找vhost1.conf.j2文件
    
    ansible-playbook -C nginx_roles.yml # 如下图3 
    
    ======================================================================================================
    
    vim roles/nginx/tasks/main.yml
    单独执行某个任务,添加如下两行:
    	tags: conf
    	notify: restart nginx
    	
    vim roles/nginx/handlers/main.yml
    	- name: restart nginx
    	  service: name=nginx state=restarted
    
    vim roles/nginx/tasks/main.yml
    	nginx没有start,也就没有restart,所以添加第三个任务:
    		- name: start nginx
    		  service: name=nginx state=started
    
    vim roles/nginx/tasks/main.yml
    	还需要给nginx提供一个测试页和家目录,因此还需要添加一个创建家目录的任务:
    		- name: install site home directory
    		  file: path={{ ngxroot }} state=directory
    		- name: install index page
    		  copy: src=index.html dest={{ ngxroot }}/ 
    
    vim roles/nginx/vars/main.yml
    	ngxroot: /ngxdata/vhost1 # 这是定义成的字典格式,前面不需要加'-'
    
    vim roles/nginx/files/index.html
    	<h1>Vhost1<h1>
    
    ansible-playbook -C nginx_roles.yml # 如下图4
    
    # 停掉192.168.0.111和192.168.0.112虚拟机上监听在80端口的服务:
    ansible websrvs -m service -a "name=nginx state=stopped"
    
    ansible-playbook  nginx_roles.yml
    

    图3:

    图4:

    被管控的两台虚拟机nginx已经启动,在浏览器中能正常访问。。。

    但这不是我们设定的测试页,因为我们templates中定义的变量访问的是主机名,可以更改监听端口为8080;修改roles/nginx/templates/vhost1.conf.j2 中的 listen:8080;

    ansible-playbook -t conf /root/playbooks/nginx_roles.yml # 按照我们定义的tags,只跑修改nginx配置文件的这个任务,又触发handlers重载nginx。
    
    在浏览器中访问8080端口,可以看到我们的测试页了。。。。。如下图
    

  • 相关阅读:
    scrum项目冲刺_day03总结
    scrum项目冲刺_day02总结
    关于Map的PUT的value值的问题
    oracle见表
    sql优化(转载)
    oracle注意事项
    mybatis中jdbcType的作用和是否必须
    spring 的web.xml的加载顺序
    spring 另开线程时的注入问题
    获取客户端的ip
  • 原文地址:https://www.cnblogs.com/zhangchaocoming/p/15224756.html
Copyright © 2020-2023  润新知