设为首页 收藏本站
查看: 2237|回复: 0

[经验分享] 轻量级自动化运维工具ansible之二:playbook详解

[复制链接]

尚未签到

发表于 2018-7-30 09:02:55 | 显示全部楼层 |阅读模式
  在介绍playbook之前,我们先了解一下YAML语言,因为playbook是用YAML语言编写的
  一、YAML
  1、YAML是一种可读性高的用来表达资料序列的语言,其语法和其他高阶语言类似,并且可以简单表达清单、散列表、标量等数据结构。所有的yaml文件都以"---"开头表示开始一个document,所有的列表元素以"-"开头,键值对用":",后面的空格是必须的。下面是一个示例:
  ---   #打头符可省略
  - name: John Smith
  age: 41
  gender: Male
  spouse:
  name: Jane Smith
  age: 37
  gender: Female
  children:
  - name: Jimmy Smith
  age: 17
  gender: Male
  - name: Jenny Smith
  age 13
  gender: Female
  YAML文件扩展名通常为.yaml或.yml,如example.yaml
  2、list
  列表的所有元素均使用“-”打头,例如:
  # A list of tasty fruits
  - Apple
  - Orange
  - Strawberry
  3、dictionary
  字典通过key与valuef进行标识,例如:
  # An employee record
  name: Example Developer
  job: Developer
  skill: Elite
  也可以将key:value放置于{}中进行表示,例如:
  # An employee record
  {name: Example Developer, job: Developer, skill: Elite}
  二、playbook详解
  playbook(剧本)是ansible管理配置、部署应用和编排的文件,可用来描述你想在被控主机上执行的策略或者一组任务等。
  一个playbook文件由一个或多个play组成,每个play定义了在一个或多个远程主机上执行的一系列的task,其中每个task一般就是调用一个ansible的模块
  playbook使用YAML语言编写,文件名以.yaml或.yml结尾。此外playbook和模板文件(template)还可使用jinja2语法语法实现高级功能。
  1、playbook的基本组成
  targets:指定要执行playbook的远程主机组
  variables:定义playbook运行时需要使用的变量
  tasks:要执行的任务
  handlers:处理器,在某些条件下被触发的操作
  一个简单的示例:
  vim httpd.yml
  - hosts: websrvs
  remote_user: root
  vars:
  remote_conffile_path: /etc/httpd/conf/httpd.conf
  tasks:
  - name: install httpd
  yum: name+httpd state=latest
  when: ansible_pkg_mgr == "yum"
  - name: configration file
  tags: conf
  copy: src=/root/httpd.conf dest=` remote_conffile_path `
  notify: restart httpd
  - name: start httpd
  service: name=httpd enabled=yes state=started
  handlers:
  - name: restart httpd
  service: name=httpd state=restarted
  2、playbook各基础组件说明
  ⑴hosts和users
  hosts用于指定要执行指定任务的主机,其可以是一个或多个由逗号分隔主机组;remote_user则用于指定远程主机上的执行任务的用户。如上面示例中的
  - hosts: websrvs
  remote_user: magedu   #在远程主机上以哪个用户身份执行
  become: yes   #是否允许身份切换
  become_method: sudo   #切换用户身份的方式,有sudo、su、pbrun等方式,默认为sudo
  become_user: root   #切换成什么用户身份,默认为root
  tasks:
  - name: test connection
  ping:
  以上remote_user、become、become_method、become_use选项不仅可用于全局,也可用于各task中。在absible 2.0以前的版本中,用 sudo 和 sudo_user 两个选项分别表示是否允许sudo和sudo切换到的用户身份
  remote_user、become、become_method、become_user分别对应inventory文件中的ansible_user、ansible_become、ansible_become_method、ansible_become_user
  如果需要指定切换用户身份时的密码,可在执行ansible-playbook时使用选项 --ask-become-pass指定(旧版ansible使用 --ask-sudo-pass指定sudo切换时的密码)
  ⑵任务列表和action
  play的主体部分是task list。task list中的各任务按次序逐个在hosts中指定的所有主机上执行,即在所有主机上完成第一个任务后再开始第二个。如果中途发生错误,所有已执行任务都将回滚,因此,在更正playbook后重新执行一次即可。
  task的目的是使用指定的参数执行模块,而在模块参数中可以使用变量。模块执行是幂等的,这意味着多次执行是安全的,因为其结果均一致
  每个task都应该有其name,用于playbook的执行结果输出,建议其内容尽可能清晰地描述任务执行步骤。如果未提供name,则action的结果将用于输出。
  定义task的可以使用“action: module options”或“module: options”的格式,推荐使用后者以实现向后兼容例如:
  tasks:
  - name: make sure apache is running
  service: name=httpd state=running
  在众多模块中,只有command和shell模块仅需要给定一个列表而无需使用“key=value”格式,例如:
  tasks:
  - name: disable selinux
  command: /sbin/setenforce 0
  如果命令或脚本的退出码不为零(默认情况下,退出码不为零即表示执行失败,任务会立即中止,后续任务不再执行),可以使用如下方式替代:
  tasks:
  - name: run this command and ignore the result
  shell: /usr/bin/somecommand || /bin/true(表示一定会成功)
  或者使用ignore_errors来忽略错误信息:
  tasks:
  - name: run this command and ignore the result
  shell: /usr/bin/somecommand
  ignore_errors: True
  handlers:用于当关注的资源发生变化时触发一定的操作
  “notify”这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之,仅在所有的变化发生完成后一次性地执行指定操作。在notify中列出的操作称为handler,也即notify中调用handler中定义的操作。
  - name: template configuration file
  template: src=/root/template.j2 dest=/etc/foo.conf
  notify:
  - restart memcached
  - restart apache
  handler是task列表,这些task与前述的task并没有本质上的不同
  handlers:
  - name: restart memcached
  service: name=memcached state=restarted
  - name: restart apache
  service: name=apache state=restarted
  ⑷变量
  变量名仅能由字母、数字和下划线组成,且只能以字母开头。
  在playbook中定义变量的格式:
  - host websrvs
  vars:
  variable:value
  如何调用变量` variable `
  在inventory中定义的变量,可在playbook中直接调用
  每个被控节点在接收并运行管理命令之前,会将本主机相关信息(称为facts,这些信息保存于变量中)如操作系统版本,ip地址,cpu数量等报告给ansible主机。这些变量信息通过 ansible <host-pattern> -m setup 获取,我们可在playbook中调用这些变量。
  当给一个主机应用角色的时候可以传递变量,然后在角色内使用这些变量,示例如下:
  - hosts: webservers
  roles:
  - common
  - { role: foo_app_instance, dir: '/web/htdocs/a.com', port: 8080 }
  另外,在运行playbook的时候也可以传递一些变量,示例:
  ansible-playbook test.yml --extra-vars "hosts=www user=magedu"
  4、条件测试
  如果需要根据变量、facts或此前任务的执行结果来做为某task执行与否的前提,这时就要用到条件测试。
  when语句:
  在task后添加when子句即可使用条件测试;when语句支持Jinja2表达式语法。例如:
  tasks:
  - name: "shutdown Debian flavored systems"
  command: /sbin/shutdown -h now
  when: ansible_os_family == "Debian"
  when语句中还可以使用Jinja2的大多“filter”,例如要忽略此前某语句的错误并基于其结果(failed或者sucess)运行后面指定的语句,可使用类似如下形式:
  tasks:
  - command: /bin/false
  register: result
  ignore_errors: True
  - command: /bin/something
  when: result|failed
  - command: /bin/something_else
  when: result|success
  - command: /bin/still/something_else
  when: result|skipped
  此外,when语句中还可以使用facts或playbook中定义的变量。
  5、迭代
  当有需要重复性执行的任务时,可以使用迭代机制。其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items语句来指明迭代的元素列表即可。例如:
  - name: add several users
  user: name=` item ` state=present groups=wheel
  with_items:
  - testuser1
  - testuser2
  上面语句的功能等同于下面的语句:
  - name: add user testuser1
  user: name=testuser1 state=present groups=wheel
  - name: add user testuser2
  user: name=testuser2 state=present groups=wheel
  事实上,with_items中可以使用元素还可以是hashes,例如:
  - name: add several users
  user: name=` item`.`name ` state=present groups=` item`.`groups `
  with_items:
  - { name: 'testuser1', groups: 'wheel' }
  - { name: 'testuser2', groups: 'root' }
  6、tags(标签)
  tags用于让用户选择运行playbook中的某个或某些任务。虽然ansible具有幂等性,会跳过没有变化的部分,但是,有些代码为测试其确实没有发生变化,也会耗费很长时间。我们将playbook中的指定任务打上标签,在运行playbook时指定标签名称,这样就不用运行全部代码了。
  playbook中可定义多个标签,且可重名。
  示例:
  - name: configration file
  copy: src=/root/httpd.conf dest=/etc/httpd/conf/httpd.conf
  notify: restart httpd
  tags: conf
  运行指定标签的任务:ansible-playbook httpd.yml -t conf
  7、运行playbook
  ansible-playbook <filename.yml> ... [options]
  例:ansible-playbook httpd.yml
  8、案例:使用ansible对websrvs组的两台主机做httpd的高可用
  以下node1为ansible节点,node2和node3为被控节点,已被添加至主机组websrvs。这里假设两个被控节点上已安装好httpd服务程序,且已建立双机互信。
[root@node1 ~]# vim /etc/ansible/hosts  

  
[websrvs]
  
192.168.30.20
  
192.168.30.13
  
[dbsrvs]
  
192.168.30.14
  
[root@node1 ~]# ls hb_conf   #准备好需要的文件
  
authkeys  ha.cf  haresources
  
[root@node1 ~]# vim heartbeat.yml   #创建playbook
  

  
- hosts: websrvs
  
  remote_user: root
  
  tasks:
  
  - name: ensure heartbeat latest version
  
    yum: name=heartbeat state=present
  
  - name: authkeys
  
    copy: src=/root/hb_conf/authkeys dest=/etc/ha.d/ mode=600
  
    notify: restart heartbeat
  
  - name: ha.cf
  
    copy: src=/root/hb_conf/ha.cf dest=/etc/ha.d/
  
    notify: restart heartbeat
  
    tags: conf   #打标签
  
  - name: haresources
  
    copy: src=/root/hb_conf/haresources dest=/etc/ha.d/
  
    notify: restart heartbeat
  
  handlers:
  
  - name: restart heartbeat
  
    service: name=heartbeat state=restarted
  

  
[root@node1 ~]# ansible-playbook heartbeat.yml    #运行playbook
  

  
PLAY ***************************************************************************
  

  
TASK [setup] *******************************************************************
  
ok: [192.168.30.20]
  
ok: [192.168.30.13]
  

  
TASK [ensure heartbeat latest version] *****************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
TASK [authkeys] ****************************************************************
  
changed: [192.168.30.13]
  
changed: [192.168.30.20]
  

  
TASK [ha.cf] *******************************************************************
  
changed: [192.168.30.13]
  
changed: [192.168.30.20]
  

  
TASK [haresources] *************************************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
RUNNING HANDLER [restart heartbeat] ********************************************
  
changed: [192.168.30.13]
  
changed: [192.168.30.20]
  

  
PLAY RECAP *********************************************************************
  
192.168.30.13              : ok=6    changed=5    unreachable=0    failed=0
  
192.168.30.20              : ok=6    changed=5    unreachable=0    failed=0
#验证  
[root@node2 ~]# ls /etc/ha.d
  
authkeys  ha.cf  harc  haresources  rc.d  README.config  resource.d  shellfuncs
  
[root@node2 ~]# ll /etc/ha.d/authkeys
  
-rw------- 1 root root 680 May  3 20:07 /etc/ha.d/authkeys
  
[root@node2 ~]# service heartbeat status
  
heartbeat OK [pid 7595 et al] is running on node2 [node2]...
  
[root@node2 ~]# ip addr show
  
...
  
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
  
    link/ether 00:0c:29:bd:68:23 brd ff:ff:ff:ff:ff:ff
  
    inet 192.168.30.20/24 brd 192.168.30.255 scope global eth0
  
    inet 192.168.30.100/24 brd 192.168.30.255 scope global secondary eth0
  
    inet6 fe80::20c:29ff:febd:6823/64 scope link
  
       valid_lft forever preferred_lft forever
  
[root@node2 ~]# service httpd status
  
httpd (pid  8049) is running...
[root@node1 ~]# vim hb_conf/ha.cf   #修改主配置文件  
...
  
mcast eth0 225.1.1.5 694 1 0   #更改心跳信息的组播地址
  
[root@node1 ~]# ansible-playbook heartbeat.yml -t conf   #只执行指定标签的任务
  

  
PLAY ***************************************************************************
  

  
TASK [setup] *******************************************************************
  
ok: [192.168.30.13]
  
ok: [192.168.30.20]
  

  
TASK [ha.cf] *******************************************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
RUNNING HANDLER [restart heartbeat] ********************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
PLAY RECAP *********************************************************************
  
192.168.30.13              : ok=3    changed=2    unreachable=0    failed=0
  
192.168.30.20              : ok=3    changed=2    unreachable=0    failed=0
[root@node2 ~]# netstat -unl  
...
  
udp        0      0 225.1.1.5:694               0.0.0.0:*
  三、roles
  ansilbe自1.2版本引入的新特性,用于层次性、结构化地组织playbook。roles能够根据层次型结构自动装载变量文件、tasks以及handlers等。要使用roles只需要在playbook中使用include指令即可。简单来讲,roles就是通过分别将变量、文件、任务、模块及处理器放置于单独的目录中,并可以便捷地include它们的一种机制。角色一般用于基于主机构建服务的场景中,但也可以是用于构建守护进程等场景中。
  一个roles的目录结构示例:
  site.yml
  webservers.yml
  fooservers.yml
  roles/
  common/
  files/
  templates/
  tasks/
  handlers/
  vars/
  meta/
  webservers/
  files/
  templates/
  tasks/
  handlers/
  vars/
  meta/
  在playbook中,可以这样使用roles:
  - hosts: webservers
  roles:
  - common
  - webservers
  可以向roles传递参数,如:
  - hosts: webservers
  roles:
  - common
  - { role: some_role, dir: '/opt/a', port: 5000 }
  - { role: some_role, dir: '/opt/b', port: 5001 }
  也可以条件式地使用roles,例如:
  - hosts: webservers
  roles:
  - { role: some_role, when: "ansible_os_family == 'RedHat'" }
  1、创建role的步骤
  ①创建以roles命名的目录;
  ②在roles目录中分别创建以各角色名称命名的目录,如webservers、dbservers等;
  ③在每个角色命名的目录中分别创建files、handlers、meta、tasks、templates和vars目录;用不到的目录可以创建为空目录,也可以不创建;
  ④在playbook文件中,调用各角色;
  2、role内各目录中可用的文件
  tasks目录:至少应该包含一个名为main.yml的文件,其定义了此角色的任务列表;此文件可以使用include包含其它的位于此目录中的task文件;
  files目录:存放由copy或script等模块调用的静态文件;
  templates目录:template模块会自动在此目录中寻找Jinja2模板文件;
  handlers目录:此目录中应当包含一个main.yml文件,用于定义此角色用到的各handler;此文件可以使用include包含其它的位于此目录中的handler文件;
  vars目录:至少有一个main.yml文件,用于定义此角色用到的变量;
  meta目录:至少有一个main.yml文件,用于定义此角色的特殊设定及其依赖关系;ansible 1.3及其以后的版本才支持;
  default目录:为当前角色设定默认变量时使用此目录;应当包含一个main.yml文件;
  四、案例—使用ansible搭建LAMP环境,要求如下:
  ①两台web服务器,一台mysql数据库服务器,php作为httpd的模块
  ②在php服务器上部署独立博客站点wordpress
  ③要求两台web服务器使用不同的端口,设置不同的最大连接数
  1、设计方案
DSC0000.png

  2、添加被控主机,并定义主机变量
  vim /etc/ansible/hosts
[root@node1 ~]# vim /etc/ansible/hosts  

  
[websrvs]
  
192.168.30.20 http_port=80 http_maxclients=300
  
192.168.30.13 http_port=8080 http_maxclients=200
  

  
[dbsrvs]
  
192.168.30.14
  3、配置ssh基于密钥认证
[root@node1 ~]# ssh-keygen -t rsa  
...
  
[root@node1 ~]# ssh-copy-id -i .ssh/id_rsa.pub root@192.168.30.14
  
...
  
[root@node1 ~]# ssh root@192.168.30.14 'hostname'
  
node4
  
#以同样的方式将公钥文件复制到其它被控节点
  4、创建各级目录,准备好各角色所需的files和templates
[root@node1 ~]# mkdir -p roles/{web,php,mysql,wordpress}/{files,templates,tasks,handlers,vars}  
[root@node1 ~]# ls roles
  
mysql  php  web  wordpress
  
[root@node1 ~]# ls roles/web/
  
files  handlers  tasks  templates  vars
  
[root@node1 ~]# cp my.cnf roles/mysql/files/   #给mysql提供一个配置文件
  
[root@node1 ~]# vim roles/mysql/files/my.cnf
  

  
[mysqld]
  
datadir=/mydata/data
  
socket=/var/lib/mysql/mysql.sock
  
user=mysql
  
log-bin=/mydata/binlogs/mysql-bin
  
innodb_file_per_table=ON
  
# Disabling symbolic-links is recommended to prevent assorted security risks
  
symbolic-links=0
  
skip-name-resolve
  

  
[mysqld_safe]
  
log-error=/var/log/mysqld.log
  
pid-file=/var/run/mysqld/mysqld.pid
  

  
[root@node1 ~]# cp httpd.conf roles/web/templates/template.j2   #给web提供配置文件模板
  
[root@node1 ~]# vim roles/web/templates/template.j2   #对如下几项引用变量
  
...
  
Listen {{ http_port }}
  
MaxClients       {{ http_maxclients }}
  
ServerName {{ ansible_fqdn }}
  

  
[root@node1 ~]# cp wordpress-3.3.1-zh_CN.zip wp-config.php roles/wordpress/files/
  
[root@node1 ~]# vim roles/wordpress/files/wp-config.php
  
...
  
// ** MySQL 设置 - 具体信息来自您正在使用的主机 ** //
  
/** WordPress 数据库的名称 */
  
define('DB_NAME', 'wpdb');
  

  
/** MySQL 数据库用户名 */
  
define('DB_USER', 'tuser');
  

  
/** MySQL 数据库密码 */
  
define('DB_PASSWORD', 'tpass');
  

  
/** MySQL 主机 */
  
define('DB_HOST', '192.168.30.14');
  5、创建各角色子目录下所需的yml文件
  ①角色mysql:
[root@node1 ~]# vim roles/mysql/tasks/main.yml  

  
- name: install mysql-server
  
  yum: name=mysql-server state=present
  
- name: mkdir
  
  file: path=/mydata/{{ item }} state=directory owner=mysql group=mysql   #创建目录可使用file模块
  
  with_items:   #迭代
  
  - data
  
  - binlogs
  
- name: configure file
  
  copy: src=my.cnf dest=/etc/     #源文件只需指定名称,不需指明具体路径,ansibles具自动到files或templates目录中寻找
  
  notify: restart mysqld
  
  tags: dbconf
  
- name: start mysqld
  
  service: name=mysqld state=started
  
- name: create database and user
  
  shell: mysql -e "create database wpdb;grant all on wpdb.* to tuser@'192.168.30.%' identified by 'tpass';flush privileges"
  

  
[root@node1 ~]# vim roles/mysql/handlers/main.yml
  

  
- name: restart mysqld
  
  service: name=mysqld state=restarted
  ②角色web:
[root@node1 ~]# vim roles/web/tasks/main.yml  

  
- name: install apache
  
  yum: name=httpd state=present
  
- name: configure file
  
  template: src=template.j2 dest=/etc/httpd/conf/httpd.conf
  
  notify: restart httpd
  
  tags: webconf
  

  
[root@node1 ~]# vim roles/web/handlers/main.yml
  

  
- name: restart httpd
  
  service: name=httpd state=restarted
  ③角色php:
[root@node1 ~]# vim roles/php/tasks/main.yml  

  
- name: install php
  
  yum: name={{ item }} state=present
  
  with_items:
  
  - php
  
  - php-mysql
  ④角色wordpress:
[root@node1 ~]# vim roles/wordpress/tasks/main.yml  

  
- name: depoly wordpress
  
  unarchive: src=wordpress-3.3.1-zh_CN.zip dest=/var/www/html/   #解压可用unarchive模块
  
- name: configure file
  
  copy: src=wp-config.php dest=/var/www/html/wordpress/
  
  tags: wpconf
  

  
[root@node1 ~]# tree roles   #结构图
  
roles
  
├── mysql
  
│   ├── files
  
│   │   └── my.cnf
  
│   ├── handlers
  
│   │   └── main.yml
  
│   ├── tasks
  
│   │   └── main.yml
  
│   ├── templates
  
│   └── vars
  
├── php
  
│   ├── files
  
│   ├── handlers
  
│   ├── tasks
  
│   │   └── main.yml
  
│   ├── templates
  
│   └── vars
  
├── web
  
│   ├── files
  
│   ├── handlers
  
│   │   └── main.yml
  
│   ├── tasks
  
│   │   └── main.yml
  
│   ├── templates
  
│   │   └── template.j2
  
│   └── vars
  
└── wordpress
  
    ├── files
  
    │   ├── wordpress-3.3.1-zh_CN.zip
  
    │   └── wp-config.php
  
    ├── handlers
  
    ├── tasks
  
    │   └── main.yml
  
    ├── templates
  
    └── vars
  

  
24 directories, 10 files
  6、最后创建一个总的playbook调用各role
  vim site.yml   #site.yml与roles目录在同一级目录下
[root@node1 ~]# vim site.yml  

  
- hosts: dbsrvs
  
  remote_user: root
  
  roles:
  
  - mysql
  

  
- hosts: websrvs
  
  remote_user: root
  
  roles:
  
  - web
  
  - php
  
  - wordpress
  7、运行playbook
  ansible-playbook site.yml
[root@node1 ~]# ansible-playbook site.yml  

  
PLAY ***************************************************************************
  

  
TASK [setup] *******************************************************************
  
ok: [192.168.30.14]
  

  
TASK [mysql : install mysql-server] ********************************************
  
changed: [192.168.30.14]
  

  
TASK [mysql : mkdir] ***********************************************************
  
changed: [192.168.30.14] => (item=data)
  
changed: [192.168.30.14] => (item=binlogs)
  

  
TASK [mysql : configure file] **************************************************
  
changed: [192.168.30.14]
  

  
TASK [mysql : start mysqld] ****************************************************
  
changed: [192.168.30.14]
  

  
TASK [mysql : create database and user] ****************************************
  
changed: [192.168.30.14]
  

  
RUNNING HANDLER [mysql : restart mysqld] ***************************************
  
changed: [192.168.30.14]
  

  
PLAY ***************************************************************************
  

  
TASK [setup] *******************************************************************
  
ok: [192.168.30.20]
  
ok: [192.168.30.13]
  

  
TASK [web : install apache] ****************************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
TASK [web : configure file] ****************************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
TASK [php : install php] *******************************************************
  
changed: [192.168.30.20] => (item=[u'php', u'php-mysql'])
  
changed: [192.168.30.13] => (item=[u'php', u'php-mysql'])
  

  
TASK [wordpress : depoly wordpress] ********************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
TASK [wordpress : configure file] **********************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
RUNNING HANDLER [web : restart httpd] ******************************************
  
changed: [192.168.30.20]
  
changed: [192.168.30.13]
  

  
PLAY RECAP *********************************************************************
  
192.168.30.13              : ok=7    changed=6    unreachable=0    failed=0
  
192.168.30.14              : ok=7    changed=6    unreachable=0    failed=0
  
192.168.30.20              : ok=7    changed=6    unreachable=0    failed=0
  8、验证:
DSC0001.png

DSC0002.png

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-543359-1-1.html 上篇帖子: ansible之filesystem和mount模块 下篇帖子: ansible playbook 学习
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

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