简单介绍
roles可以理解为ansible的一种规范,使用这种规范编写playbook,可以让我们条例更加清晰,合理拆分将变量、文件、任务、ansible其它工作等分别存储在不同的目录中,方便快速定位。
-
官方文档给出的角色目录拆解过于分散,我以“个人习惯”稍稍精简,拿redis举例:
roles/ # 总的角色目录 ├── redis # redis角色目录,目录名代表角色名。 │ ├── defaults/main.yaml # 存放指定角色所用到的默认变量,以便在没有设置变量值时有默认值可以使用,此文件中定义的变量优先级是最低的。 │ ├── files # 存放执行角色所需要文件。 │ ├── handlers/main.yaml # 当角色调用handlers时,默认会在此目录中的main.yml文件中查找对应的handler。 │ ├── meta/main.yaml # 存放一些元数据,比如作者信息、本角色作用等等。 │ ├── tasks/main.yaml # 角色执行的任务的主要列表。 │ ├── templates # 存放角色相关的模板文件。 │ └── vars/main.yaml # 存放需要修改的变量,优先级较高。 └── redis.yaml # 调用角色的playbook。
-
上述规范可以不用遵守,你自己看得懂也可以;使用上面规范也不是全部目录都必须使用,按需即可,一般情况至少会有一个tasks目录。
-
上面目录结构可以看出,角色调用文件(redis.yaml)和角色目录(redis)是同级的,这是因为角色调用文件会从下面位置查找角色目录:
- 同级目录。
- 同级目录的roles目录。
- 当前用户的~/.ansible/roles目录。
- 也可以编辑/etc/ansible/ansible.cfg的“roles_path”配置项来查找角色目录。
- 上面情况都不符合的情况也可使用绝对路径调用角色。如: - role: "/server/ansible/roles/"
-
变量调用说明:
- 角色中定义的默认变量是全局生效的。
- 调用角色的剧本(就是上面的redis.yaml,以下内容中称角色调用剧本)中定义的变量也是默认全局生效的,但是可以通过修改ansible.cfg配置文件将全局属性修改为private,见下方例1。
- 变量定义优先级:ansible-playbppk -e > 角色本身的vars/main.yaml > 角色调用剧本 > 角色本身的defaults/main.yaml > 同一个角色调用剧本中上一个调用角色的defaults/main.yaml(见例2)。
举例说明
-
例1:rolrs的公/私有变量。
0 16:59:38 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr1/tasks/main.yaml - debug: msg: "hello {{ var1 }}!" 0 16:59:45 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr1/defaults/main.yaml var1: "natasha" 0 16:59:51 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr2/tasks/main.yaml - debug: msg: "hello {{ var1 }}!" 0 16:59:56 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr2/defaults/main.yaml var1: "maria" 0 16:59:59 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr.yaml - hosts: ck-node1 roles: - role: tr1 vars: var1: "selina" - role: tr2 0 17:01:59 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml ... TASK [tr1 : debug] *********************************************************************************************************************** ok: [ck-node1] => { "msg": "hello selina!" } TASK [tr2 : debug] *********************************************************************************************************************** ok: [ck-node1] => { "msg": "hello selina!" } ... # 正常情况下,vars下的变量应该只对tr1角色生效,但从结果上看var1变量对tr1和tr2角色都生效了,这是因为默认情况下,角色中的变量是全局生效的。想要解决这个问题,需要修改ansible配置文件。 0 17:10:11 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # vim /etc/ansible/ansible.cfg private_role_vars = yes # 取消此行的注释。 # 再执行就达到预想的效果了。 0 17:10:54 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml
-
例2:变量调用优先级,五种情况对比,以tr3角色为例。
# 各角色内的tasks/main.yaml文件保持不变。 0 18:17:00 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr1/defaults/main.yaml var1: "tr1-defaults-var1" 0 18:17:02 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr2/defaults/main.yaml var1: "tr2-defaults-var2" 0 18:17:04 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr3/defaults/main.yaml var1: "tr3-defaults-var3"
- 第一种:所有的位置都定义了v1变量,执行时使用-e参数,-e参数优先级最高。
0 18:25:08 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr3/vars/main.yaml var1: "tr3-vars-var1" 0 18:29:14 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr.yaml - hosts: ck-node1 roles: - role: tr1 - role: tr2 - role: tr3 vars: var1: "tr-var1" 0 18:30:57 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook -e var1="command-e-var1" tr.yaml
- 第二种:所有的位置都定义了v1变量时,执行时不是用-e,tr3/vars/main.yaml优先级高。
0 18:31:49 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml
- 第三种:取消定义tr3/vars/main.yaml后,角色调用剧本优先级高。
0 18:32:07 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # m -r tr3/vars 0 18:35:48 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml
- 第四种:取消定义tr3/vars/main.yaml和角色调用剧本后,角色本身的defaults/main.yaml的优先级高。
0 18:38:27 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr.yaml - hosts: ck-node1 roles: - role: tr1 - role: tr2 - role: tr3 0 18:38:28 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml
- 第五种:取消定义tr3/vars/main.yaml、角色调用剧本、tr3/defaultss/main.yaml后,同一个角色调用剧本中上一个调用角色的defaults/main.yaml优先级高。
0 18:38:31 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # m -r tr3/defaults 0 18:40:10 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr.yaml - hosts: ck-node1 roles: - role: tr2 - role: tr1 # 特意把tr1和tr2的调用位置换换,方便查看效果。 - role: tr3 0 18:40:11 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml
-
例3:默认情况下,在同一个角色调用剧本中,无法重复调用一个角色,想要解决这个问题,有两种方式:
- 第一种方法:为角色添加allow_duplicates属性。
# 依然使用上面的测试文件,只修改tr.yaml。 0 18:41:45 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr.yaml - hosts: ck-node1 roles: - role: tr1 - role: tr2 - role: tr2 # 此次调用不会显示内容。 0 18:41:47 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml # 为角色添加allow_duplicates属性。 0 18:43:41 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr2/meta/main.yaml allow_duplicates: true 0 18:43:49 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml
- 第二种方法:此种方法只针对需要传参的角色。
# 依然使用上面的测试文件,删除meta。 0 18:44:02 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # m -r tr2/meta 0 18:44:53 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # cat tr.yaml - hosts: ck-node1 roles: - role: tr1 - role: tr2 vars: var1: peiqian - role: tr2 vars: var1: zhujiu 0 18:44:54 root@ck-ansible,172.16.2.9:/server/ops_ansible/roles # ansible-playbook tr.yaml
-
例4,部署redis。
# 这里把调用文件放在roles目录同级,方便区分。 0 15:18:45 root@ck-ansible,172.16.2.9:/server/ops_ansible # tree ./ ./ ├── redis.yaml └── roles └── redis ├── defaults │ └── main.yaml ├── files │ ├── bin │ │ ├── redis-benchmark │ │ ├── redis-check-aof -> redis-server │ │ ├── redis-check-rdb -> redis-server │ │ ├── redis-cli │ │ ├── redis-sentinel -> redis-server │ │ ├── redis-server │ │ └── redis-shutdown │ ├── redis.service │ └── redis.sh ├── tasks │ ├── main.yaml │ ├── redis_common.yaml │ └── start_redis.yaml └── templates └── redis.conf.j2 # 变量定义 0 15:20:02 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat roles/redis/defaults/main.yaml redis_dirs: - "/usr/local/redis/conf" - "/server/logs/redis" - "/server/data/redis" redis_files: - { src: 'files/bin',dest: '/usr/local/redis/',mode: '0755' } - { src: 'files/redis.sh',dest: '/etc/profile.d/' } - { src: 'files/redis.service',dest: '/etc/systemd/system/' } # redis依赖文件(事先编译好的redis相关二进制文件)。 0 15:20:29 root@ck-ansible,172.16.2.9:/server/ops_ansible # ll roles/redis/files/bin/ 总用量 18848 -rwxr-xr-x 1 root root 4833392 5月 7 12:07 redis-benchmark lrwxrwxrwx 1 root root 12 5月 7 12:07 redis-check-aof -> redis-server lrwxrwxrwx 1 root root 12 5月 7 12:07 redis-check-rdb -> redis-server -rwxr-xr-x 1 root root 5003408 5月 7 12:07 redis-cli lrwxrwxrwx 1 root root 12 5月 7 12:07 redis-sentinel -> redis-server -rwxr-xr-x 1 root root 9450240 5月 7 12:07 redis-server -rwxr-xr-x 1 root root 1118 10月 4 20:24 redis-shutdown # redis的systemd文件和环境变量文件 0 15:20:32 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat roles/redis/files/redis.service [Unit] Description=Redis persistent key-value database After=network.target After=network-online.target Wants=network-online.target [Service] Type=forking ExecStart=/usr/local/redis/bin/redis-server /usr/local/redis/conf/redis.conf ExecStop=/usr/local/redis/bin/redis-shutdown [Install] WantedBy=multi-user.target 0 15:22:08 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat roles/redis/files/redis.sh #set redis environment export REDIS_HOME=/usr/local/redis export PATH=${REDIS_HOME}/bin:${PATH} # 配置文件模板 0 15:22:43 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat roles/redis/templates/redis.conf.j2 daemonize yes port 6379 bind {{ ansible_host }} pidfile /usr/local/redis/redis.pid logfile /server/logs/redis/redis.log dir /server/data/redis requirepass '123456' # 任务执行。 0 15:23:26 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat roles/redis/tasks/main.yaml --- - include: redis_common.yaml - include: start_redis.yaml 0 15:25:07 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat roles/redis/tasks/redis_common.yaml --- - name: create services user user: name: sn_pub uid: 8888 createhome: no shell: /sbin/nologin - name: create redis dir file: path: "{{ item }}" state: directory recurse: yes owner: sn_pub group: sn_pub loop: "{{ redis_dirs }}" - name: copy redis conf.j2 template: src: templates/redis.conf.j2 dest: /usr/local/redis/conf/redis.conf - name: copy redis depend files copy: src: "{{ item.src }}" dest: "{{ item.dest }}" mode: "{{ item.mode | default(omit) }}" owner: sn_pub group: sn_pub loop: "{{ redis_files }}" - name: load redis.sh shell: source /etc/profile.d/redis.sh 0 15:25:11 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat roles/redis/tasks/start_redis.yaml --- - name: start redis systemd: daemon_reload: yes name: redis state: started enabled: yes # 调用redis角色执行部署redis 0 15:25:15 root@ck-ansible,172.16.2.9:/server/ops_ansible # cat redis.yaml - hosts: ck-node1 roles: - role: redis 0 15:26:00 root@ck-ansible,172.16.2.9:/server/ops_ansible # ansible-playbook redis.yaml
写作不易,转载请注明出处,谢谢~~