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

[经验分享] ansible 系列教程

[复制链接]

尚未签到

发表于 2018-7-30 10:22:29 | 显示全部楼层 |阅读模式
ansible 核心组件介绍
Architecture Diagram

  •   ansible core
  •   host iventory
  •   core modules
  •   custom modules
  •   playbook (yaml)
  •   connetc plugin DSC0000.jpg
ansibles 的特性

  •   基于python语言实现,有paramiko,Pyyaml和jinjia2 三个关键模块
  •   部署简单,agegtlees,默认使用SSH协议

  •   基于密钥认证
  •   在inventory 文件中指定账号和密码
支持playbook基于”模块“完成各种任务ansible install
# install the epel-release RPM if needed on CentOS, RHEL, or Scientific Linux  
$ sudo yum install ansible
ansible config
  配置文件:/etc/ansible/ansible.cfg
  inventory:/etc/ansible/hosts
  定制被管理主机:
cat /etc/ansible/host  
[webserver]
  
192.168.0.101
  
192.168.0.102
  管理master 创建ssh密钥
root@node2 ansible]# ssh-keygen  
Generating public/private rsa key pair.
  
Enter file in which to save the key (/root/.ssh/id_rsa):
  
[root@node2 ansible]# ls /root/.ssh/
  
/root/.ssh/id_rsa  /root/.ssh/id_rsa.pub
  将公钥复制给slave节点,并验证ssh证书登录是否成功。
[root@node2 ansible]#ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.0.102  
[root@node2 ansible]# ssh-copy-id -i /root/.ssh/id_rsa.pub root@192.168.0.101
  
[root@node2 ansible]# ssh root@192.168.0.102 'date'
  
Wed Feb  3 19:53:04 CST 2016
  
[root@node2 ansible]# ssh root@192.168.0.101 'date'
  
Wed Feb  3 19:53:58 CST 2016
ansible-doc - show documentation on Ansible modules
[root@node2 ansible]# ansible-doc -l  
cron  Manage cron.d and crontab entries.
  
crypttab  Encrypted Linux block devices
  
datadog_event Posts events to DataDog  service
  
debconf   Configure a .deb package
  
debug Print statements during execution
  
digital_ocean Create/delete a droplet/SSH_key in DigitalOcean
  
digital_ocean_domain  Create/delete a DNS record in DigitalOcean
  查看模块说明
[root@node2 ansible]# ansible-doc -s cronansible命令应用基础
  语法: ansible <host-pattern> [-f forks] [-m module_name] [-a args]

  •   -f forks:启动的并发数
  •   -m module_name:使用的模块
  •   -args:模块特有参数
  EX:使用command模块执行date指令,ansible 默认模块,不支持变量传递。
[root@node2 ansible]# ansible webserver -m command -a "date"  
192.168.0.101 | success | rc=0 >>
  
Wed Feb  3 20:06:50 CST 2016
  

  
192.168.0.102 | success | rc=0 >>
  
Wed Feb  3 20:06:03 CST 2016
  
[root@node2 ansible]# ansible webserver -a "date"
  
192.168.0.102 | success | rc=0 >>
  
Wed Feb  3 20:10:35 CST 2016
  
192.168.0.101 | success | rc=0 >>
  
Wed Feb  3 20:11:22 CST 2016
  EX:cron模块:每十分钟运行“hello”

  •   state
  present 添加任务 absent 删除任务
[root@node2 ansible]# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello word" name="ansibile cron lession"'  验证结果
[root@node2 ansible]# ansible webserver -a "crontab -l"  
192.168.0.101 | success | rc=0 >>
  
#Ansible: ansibile cron lession
  
*/10 * * * * /bin/echo hello word
  
192.168.0.102 | success | rc=0 >>
  
#Ansible: ansibile cron lession
  
*/10 * * * * /bin/echo hello word
  删除一个cron任务:
[root@node2 ansible]# ansible webserver -m cron -a 'minute="*/10" job="/bin/echo hello word" name="ansibile cron lession" state=absent'  创建一个mysql 系统用户
  home: Check that parent folder is missing and run
[root@node2 ansible]# ansible webserver -m user -a "name=mysql system=yes shell='/sbin/nologin' home='/date/mysql'"  
192.168.0.102 | success >> {
  
"append": false,
  
"changed": true,
  
"comment": "",
  
"group": 497,
  
"home": "/date/mysql",
  
"move_home": false,
  
"name": "mysql",
  
"shell": "/sbin/nologin",
  
"state": "present",
  
"uid": 497
  
}
  

  
192.168.0.101 | success >> {
  
"append": false,
  
"changed": true,
  
"comment": "",
  
"group": 498,
  
"home": "/date/mysql",
  
"move_home": false,
  
"name": "mysql",
  
"shell": "/sbin/nologin",
  
"state": "present",
  
"uid": 498
  
}
  删除一个mysql用户
[root@node2 ansible]# ansible webserver -m user -a "user=mysql remove='yes' state=absent"  
192.168.0.102 | success >> {
  
"changed": true,
  
"force": false,
  
"name": "mysql",
  
"remove": true,
  
"state": "absent"
  
}
  

  
192.168.0.101 | success >> {
  
"changed": true,
  
"force": false,
  
"name": "mysql",
  
"remove": true,
  
"state": "absent"
  
}
  EX:copy 模块:复制文件/etc/fstab 到/tmp/fstab.ansbile,文件所有者为root,所属组为roo并且文件权限为600
[root@node2 ansible]# ansible webserver -m copy -a "src=/etc/fstab dest=/tmp/fstab.ansible owner=root group=root mode=600"  
192.168.0.101 | success >> {
  
"changed": true,
  
"checksum": "f24c68dfd84aa1d30c325285d7aedc26a50e7078",
  
"dest": "/tmp/fstab.ansible",
  
"gid": 0,
  
"group": "root",
  
"md5sum": "05e29801d839073ed23aa6164e58646f",
  
"mode": "0600",
  
"owner": "root",
  
"secontext": "unconfined_u:object_r:admin_home_t:s0",
  
"size": 779,
  
"src": "/root/.ansible/tmp/ansible-tmp-1454504173.49-88392224178700/source",
  
"state": "file",
  
"uid": 0
  
}
  

  
192.168.0.102 | success >> {
  
"changed": true,
  
"checksum": "f24c68dfd84aa1d30c325285d7aedc26a50e7078",
  
"dest": "/tmp/fstab.ansible",
  
"gid": 0,
  
"group": "root",
  
"md5sum": "05e29801d839073ed23aa6164e58646f",
  
"mode": "0600",
  
"owner": "root",
  
"secontext": "unconfined_u:object_r:admin_home_t:s0",
  
"size": 779,
  
"src": "/root/.ansible/tmp/ansible-tmp-1454504173.49-145879281527954/source",
  
"state": "file",
  
"uid": 0
  
}
  EX:生成文件/tmp/test,内容为"hello word"
[root@node2 ansible]# ansible webserver -m copy -a "content='hello word' dest=/tmp/test "  
[root@node2 ansible]# ansible all -m shell -a 'cat /tmp/test'
  
192.168.0.102 | success | rc=0 >>
  
hello word
  

  
192.168.0.101 | success | rc=0 >>
  
hello word
  EX:文件权限管理
[root@node2 ansible]# ansible all -m file -a 'owner=mysql group=mysql mode=600 path=/tmp/fstab.ansible'  EX:创建软连接文件
[root@node2 ansible]# ansible all -m file -a 'path=/tmp/fstab.link src=/tmp/fstab.ansible state=link'  
[root@node2 ~]# ll /tmp/*
  
lrwxrwxrwx. 1 root  root18 Feb  3 21:21 /tmp/fstab.link -> /tmp/fstab.ansible
  EX:service 服务管理模块
  enabled: Whether the service should start on boot
[root@node2 ~]# ansible webserver -m service -a 'enabled=true name=nginx state=started'  EX: SHELL 指令模块,可以使用变量及参数传递
[root@node2 ~]# ansible all -m shell -a 'echo redhat| passwd --stdin mysql'  
192.168.0.102 | success | rc=0 >>
  
Changing password for user mysql.
  
passwd: all authentication tokens updated successfully.
  

  
192.168.0.101 | success | rc=0 >>
  
Changing password for user mysql.
  
passwd: all authentication tokens updated successfully.
  EX:script 在远端执行本地脚本
[root@node2 ~]# ansible all -m script -a '/tmp/test.sh'  EX:YUM 安装软件
[root@node2 ~]# ansible all -m yum -a 'name=nginx'  EX: setup 收集远程主机facts,每个被管理几点在接受并运行管理命令之前,会将自己主机相关信息,如系统版本、IP报告给远程的ansible主机。
[root@node2 ~]# ansible all -m setupansible的YAML介绍
  YAML是"YAML Ain't a Markup Language"(YAML不是一种置标语言)的递归缩写。 YAML是一个类似GNU的递归式定义。GNU对Unix说“No”,YMAL则是对XML说“No”。而在Ruby的世界里,YAML可以说是Ruby流动的血液。YAML 之于Ruby,犹如XML之于Java。

  •   YAML的可读性好。
  •   YAML和脚本语言的交互性好。
  •   YAML使用宿主语言的数据类型。
  •   YAML有一个一致的信息模型。
  YAML实例
# MySQL (default setup).  Versions 4.1 and 5.0 are recommended.  
# 此处省略一些注释。
  
development:
  
  adapter: mysql
  
  database: demo_development
  
  username: root
  
  password:
  
  host: localhos
ansible的基础元素、变量、组嵌套
变量

  •   变量命名:变量名仅能由字母、数字和下划线组成、且只能以字母开头
  •   facts 信息被保存在ansible变量中,可以引用使用
  •   register:把任务的输出定义为变量,
  实例如下
task:  
shell:/usr/bin/foo
  
register:foo_result
  
ignore_error:True
ansible playbook 介绍
  playbooks 是 Ansible的配置,部署,编排语言.他们可以被描述为一个需要希望远程主机执行命令的方案,或者一组IT程序运行的命令集合. 如果 Ansible 模块你是工作室中的工具,那么 playbooks 就是你设置的方案计划. 在基础层面, playbooks 可以被用来管理用于部署到远程主机的配置文件.在更高的层面上,playbooks 可以依次对多层式架构上的服务器执行上线包括滚动更新在内的操作并可以将操作委托给其他主机包括在此过程中发生的与监视服务器,负载均衡服务器的交互操作在内.
  实例
- hosts: webservers  
  vars:
  
http_port: 80
  
max_clients: 200
  
  remote_user: root
  
  tasks:
  
  - name: ensure apache is at the latest version
  
yum: pkg=httpd state=latest
  
  - name: write the apache config file
  
template: src=/srv/httpd.j2 dest=/etc/httpd.conf
  
notify:
  
- restart apache
  
  - name: ensure apache is running
  
service: name=httpd state=started
  
  handlers:
  
- name: restart apache
  
  service: name=httpd state=restarted
ansible playbook 基础组件

  •   Inventor
  •   Modules
  •   Ad hot commands
  •   Playbooks
  •   Tasks:任务,及调佣模块完成基础操作
  •   variables:变量
  •   tempalates:模板
  •   handlers:处理器。由某事件触发执行的操作
  •   roles:角色
主机与用户
  playbook 中的每一个 play,个别地选择操作的目标机器是哪些,以哪个用户身份去完成要执行的步骤。hosts 行的内容是一个或多个组或主机的 patterns,以逗号为分隔符,
  实例:
- hosts: webservers  
  remote_user: root
Tasks 任务列表
  每一个 play 包含了一个 task 列表(任务列表).一个 task 在其所对应的所有主机上(通过 host pattern 匹配的所有主机)执行完毕之后,下一个 task 才会执行.有一点需要明白的是(很重要),在一个 play 之中,所有 hosts 会获取相同的任务指令,这是 play 的一个目的所在,也就是将一组选出的 hosts 映射到 task
  每个 task 的目标在于执行一个 moudle, 通常是带有特定的参数来执行.在参数中可以使用变量(variables).
  每个task都应该有name,用于playboo的执行结果输出,建议其内容尽可能详细描述任务步骤。如果未提供name,测action 的结果将用于输出
  modules 具有”幂等”性,意思是如果你再一次地执行 moudle(译者注:比如遇到远端系统被意外改动,需要恢复原状),moudle 只会执行必要的改动,只会改变需要改变的地方.所以重复多次执行 playbook 也很安全.
  对于 command module 和 shell module,重复执行 playbook,实际上是重复运行同样的命令.如果执行的命令类似于 ‘chmod’ 或者 ‘setsebool’ 这种命令,这没有任何问题.也可以使用一个叫做 ‘creates’ 的 flag 使得这两个 module 变得具有”幂等”特性
  下面是一种基本的 task 的定义,service moudle 使用 key=value 格式的参数,这也是大多数 module 使用的参数格式:
tasks:  
  - name: make sure apache is running
  
    service: name=httpd state=running
  比较特别的两个 modudle 是 command 和 shell ,它们不使用 key=value 格式的参数,而是这样
tasks:  
  - name: disable selinux
  
    command: /sbin/setenforce 0
  EX:
- hosts: webserver  
  remote_user: root
  
  tasks:
  
  - name: create nginx group
  
    group: name=nginx system=yes gid=208
  
  - name: create nginx user
  
    user: name=nginx uid=208 group=nginx system=yes
  
- hosts: dbserver
  
  remote_user: root
  
  tasks:
  
  - name: copy file to dbserver
  
    copy: src=/etc/inittab dest=/tmp/initab.ans
handlers
  用于当关注的资源发生变化时采取一定的操作。'notify'这个action可用于在每个play的最后被触发,这样可以避免多次有改变发生时每次都执行指定的操作,取而代之仅在所有的变化发生完成后一次性地执行操作。在‘notify’中列出的操作称之为handler。
  EX: 步骤1,写一个playbook 要求如下

  •   自动部署一个httpd服务
  •   提供一个特殊的配置文件端口监听8080
  •   开机自动启动
- hosts: webserver  
  remote_user: root
  
  tasks:
  
  - name: install httpd package
  
    yum: name=httpd state=latest
  
  - name: install congfiguration file for httpd
  
    copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
  
  - name: start httpd service
  
    service: enabled=true name=httpd state=started
  步骤2 修改配置文件端口监听为80。重新执行playbook查看端口是否被修改!
- hosts: webserver  
  remote_user: root
  
  tasks:
  
  - name: install httpd package
  
    yum: name=httpd state=latest
  
  - name: install congfiguration file for httpd
  
    copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
  
    notify:
  
    - restart httpd
  
  - name: start httpd service
  
    service: enabled=true name=httpd state=started
  
  handlers:
  
  - name: restart httpd
  
    service: name=httpd state=restarted
playbooks 变量的使用

  •   自定变量引用
  •   调用ansible系统变量
  •   调用Inventor 定义的变量
  EX1:自定变量引用
- hosts: webserver  
  remote_user: root
  
  vars:
  
  - package: httpd
  
  - service: httpd
  
  tasks:
  
  - name: install httpd package
  
    yum: name={{ package }} state=latest
  
  - name: install congfiguration file for httpd
  
    copy: src=/root/playboos/conf/httpd.conf dest=/etc/httpd/conf/httpd.conf
  
    notify:
  
    - restart httpd
  
  - name: start httpd service
  
    service: enabled=true name={{ service }} state=started
  
  handlers:
  
  - name: restart httpd
  
    service: name=httpd state=restarted
  EX2:调用ansible系统变量
  系统变量查看
[root@node2 conf]# ansible all -m setup  调用ansible系统变量ansibleallipv4_addresses'
- hosts: webserver  
  remote_user: root
  
  tasks:
  
  - name: copy file
  
copy: content="{{ ansible_all_ipv4_addresses }}" dest=/tmp/ip.ans
  EX3:调用Inventor 定义的变量
# Ex 1: Ungrouped hosts, specify before any group headers.  
[webserver]
  
192.168.0.101 testvar='0.101' ansible_ssh_user=root ansible_ssh_pass=redhat
  
192.168.0.102 testvar='0.102'
  
[dbserver]
  
192.168.0.102
  

  
[root@node2 playboos]# cat vars.yml
  
- hosts: webserver
  
  remote_user: root
  
  tasks:
  
  - name: copy file
  
    copy: content="{{ ansible_all_ipv4_addresses }}, {{ testvar }}" dest=/tmp/ip.ans
ansible之条件测试
  when语句:在task后添加when子句即可使用条件测试。
  EX:
tasks:  
  - name: "shutdown Debian flavored systems"
  
    command: /sbin/shutdown -t now
  
    when: ansible_os_family == "Debian"
  EX:2
[root@node2 playboos]# cat cond.yml  
- hosts: all
  
  remote_user: root
  
  vars:
  
  - username: major
  
  tasks:
  
  - name: create {{ username }} user
  
    user: name={{ username }}
  
    when: ansible_fqdn == "node3.huizhuang.com"
  迭代语句 当有需要重复性执行的任务时,可以使用迭代机制。 其使用格式为将需要迭代的内容定义为item变量引用,并通过with_items 语句来指明迭代的元素列表即可。
  EX:为了保持简洁,重复的任务可以用以下简写的方式。
  ` item ` 为固定变量名
- 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
  请note使用 ‘with_items’ 用于迭代的条目类型不仅仅支持简单的字符串列表.如果你有一个哈希列表,那么你可以用以下方式来引用子项:
- name: add several users  
  user: name={{ item.name }} state=present groups={{ item.groups }}
  
  with_items:
  
    - { name: 'testuser1', groups: 'wheel' }
  
    - { name: 'testuser2', groups: 'root' }
ansible之tempalates 使用
  要求为webserver两台主机安装httpd 服务要求如下 - 监听端口80 - 0.101主机maxclient 值为100 - 0.102主机maxclient 值为200 - ServerName 为各自主机名 定义 httpd template 模板文件httpd.conf.j2
MaxClients   {{ maxclient }}  
Listen {{ http_port }}
  
ServerName {{ ansible_fqdn}}:80
  在Inventor hosts文件定义变量值
[root@node2 templates]# cat /etc/ansible/hosts  
[webserver]
  
192.168.0.101 http_port=80 maxclient=100
  
192.168.0.102 http_port=80 maxclient=200
  在http.yml 引用模板变量
- hosts: webserver  
  remote_user: root
  
  vars:
  
  - package: httpd
  
  - service: httpd
  
  tasks:
  
  - name: install httpd package
  
    yum: name={{ package }} state=latest
  
  - name: install congfiguration file for httpd
  
    template: src=/root/playboos/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  
    notify:
  
    - restart httpd
  
  - name: start httpd service
  
    service: enabled=true name={{ service }} state=started
  
  handlers:
  
  - name: restart httpd
  
    service: name=httpd state=restarted
ansible标签 tags
  如果你有一个大型的 playbook,那能够只运行其中特定部分的配置而无需运行整个 playbook 将会很有用.
[root@node2 playboos]# cat httpd.yml  
- hosts: webserver
  
  remote_user: root
  
  vars:
  
  - package: httpd
  
  - service: httpd
  
  tasks:
  
  - name: install httpd package
  
    yum: name={{ package }} state=latest
  
  - name: install congfiguration file for httpd
  
    template: src=/root/playboos/templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf
  
    tags:
  
    - conf
  
    notify:
  
    - restart httpd
  
  - name: start httpd service
  
    service: enabled=true name={{ service }} state=started
  
  handlers:
  
  - name: restart httpd
  
    service: name=httpd state=restarted
  如果你只想运行一个非常大的 playbook 中的 “conf” 你可以这样做:
# ansible-playbook httpd.yml --tags='conf'  另一方面,如果你只想执行 playbook 中某个特定任务 之外 的所有任务,你可以这样做:
# ansible-playbook httpd.yml --skip-tags='conf'ansible之role运用
  创建role的步骤

  •   创建以roles命名的目录
  •   在roles目录中分别创建以各个角色名称的目录,如webserver
  •   在每个角色命名的目录中分别创建files、handlers]meta、tasks、templates、vars目录;用不到的目录可以创建,也可以不创建。
  •   在playbook文件中,调用各角色;
  创建目录树
  [root@node2 ~]# mkdir -pv /root/ansible_playbooks/roles/{webservs,dbservs}/{tasks,files,templates,meta,handlers,vars}
tree /root/ansible_playbooks/  
roles/
  
├── dbservs
  
│   ├── files
  
│   ├── handlers
  
│   ├── meta
  
│   ├── tasks
  
│   ├── templates
  
│   └── vars
  
├── site.yml
  
└── webservs
  
├── files
  
│   └── httpd.conf
  
├── handlers
  
│   └── main.yml
  
├── meta
  
├── tasks
  
│   └── main.yml
  
├── templates
  
└── vars
  复制httpd配置文件到files目录
cp /etc/httpd/conf/httpd.conf files/  定义webservs tasks/main.yml
  注意copy src 使用相对路径
[root@node2 ansible_playbooks]# cat /root/ansible_playbooks/roles/webservs/tasks/main.yml  
- name: install httpd package
  
  yum: name=httpd
  
- name: install configureation file
  
  copy: src=httpd.conf dest=/etc/httpd/conf/httpd.conf
  
  tags:
  
  - conf
  
  notify:
  
  - restart httpd
  
- name: start httpd
  
  service: name=httpd state=started
  定义webservs handlers/main.yml
[root@node2 ansible_playbooks]# cat /root/ansible_playbooks/roles/webservs/handlers/main.yml  
- name: restart httpd
  
  service: name=httpd state=restarted
  复制mysql配置文件到files目录
[root@node2 roles]# cp /etc/my.cnf /root/ansible_playbooks/roles/dbservs/files/  定义dbservs tasks/main.yml
[root@node2 roles]# cat dbservs/tasks/main.yml  
- name: install mysql-server package
  
  yum: name=mysql-server state=latest
  
- name: install configuration file
  
  copy: src=my.cnf dest=/etc/my.cnf
  
  tags:
  
  - myconf
  
  notify:
  
  - restart mysqld
  
- name: start mysqld service
  
  service: name=mysqld enabled=true state=started
  定义dbservs handlers/main.yml
- name: restart mysqld  
  service: name=mysqld state=restarted
  定义主机 site.yml
  注意角色名等于roles目录下目录名
[root@node2 ansible_playbooks]# cat /root/ansible_playbooks/roles/site.yml  
- hosts: 192.168.0.101
  
  remote_user: root
  
  roles:
  
  - webservs
  

  
- hosts: 192.168.0.102
  
  remote_user: root
  
  roles:
  
  - dbservs

运维网声明 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-543444-1-1.html 上篇帖子: ansible配置文件介绍及命令介绍 下篇帖子: ansible模块command、shell、raw、script
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

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

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

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

扫描微信二维码查看详情

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


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


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


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



合作伙伴: 青云cloud

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