├── Icon ├── ansible_test.retry ├── .DS_Store ├── SSR ├── .DS_Store ├── sources │ ├── usermysql.json │ ├── userapiconfig.py │ ├── user-config.json │ └── db.sql ├── ssr.yml └── README.md ├── ansible_test.yml ├── MIsc └── README.md /Icon : -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /ansible_test.retry: -------------------------------------------------------------------------------- 1 | 104.224.139.45 2 | -------------------------------------------------------------------------------- /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Homeless-Xu/Ansible-DevOps/master/.DS_Store -------------------------------------------------------------------------------- /SSR/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Homeless-Xu/Ansible-DevOps/master/SSR/.DS_Store -------------------------------------------------------------------------------- /SSR/sources/usermysql.json: -------------------------------------------------------------------------------- 1 | { 2 | "host": "35.194.128.92", 3 | "port": 3306, 4 | "user": “ssr”, 5 | "password": "xujian0219", 6 | "db": "ss-vps1", 7 | "node_id": 2, 8 | "transfer_mul": 1.0, 9 | "ssl_enable": 0, 10 | "ssl_ca": "", 11 | "ssl_cert": "", 12 | "ssl_key": "" 13 | } 14 | -------------------------------------------------------------------------------- /SSR/sources/userapiconfig.py: -------------------------------------------------------------------------------- 1 | # Config 2 | API_INTERFACE = 'sspanelv3ssr' #mudbjson, sspanelv2, sspanelv3, sspanelv3ssr, glzjinmod, legendsockssr, muapiv2(not support) 3 | UPDATE_TIME = 60 4 | SERVER_PUB_ADDR = '127.0.0.1' # mujson_mgr need this to generate ssr link 5 | 6 | #mudb 7 | MUDB_FILE = 'mudb.json' 8 | 9 | # Mysql 10 | MYSQL_CONFIG = 'usermysql.json' 11 | 12 | # API 13 | MUAPI_CONFIG = 'usermuapi.json' 14 | 15 | 16 | -------------------------------------------------------------------------------- /ansible_test.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: vps2 3 | gather_facts: no # 避免收集节点信息, 蛮耗时的. 4 | remote_user: root 5 | 6 | 7 | tasks: 8 | 9 | - name: echo date 10 | command: date 11 | register: date_output 12 | 13 | - name: show results? 14 | debug: msg="{{date_output.stdout}}" 15 | 16 | 17 | - command: "echo {{item}}" 18 | register: result 19 | with_items: [1, 2] 20 | - debug: 21 | var: result 22 | -------------------------------------------------------------------------------- /SSR/sources/user-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "server": "0.0.0.0", 3 | "server_ipv6": "::", 4 | "server_port": 8388, 5 | "local_address": "127.0.0.1", 6 | "local_port": 1080, 7 | 8 | "password": "m", 9 | "method": "chacha20", 10 | "protocol": "auth_aes128_md5", 11 | "protocol_param": "", 12 | "obfs": "tls1.2_ticket_auth_compatible", 13 | "obfs_param": "", 14 | "speed_limit_per_con": 0, 15 | "speed_limit_per_user": 0, 16 | 17 | "additional_ports" : {}, // only works under multi-user mode 18 | "additional_ports_only" : false, // only works under multi-user mode 19 | "timeout": 120, 20 | "udp_timeout": 60, 21 | "dns_ipv6": false, 22 | "connect_verbose_info": 0, 23 | "redirect": "", 24 | "fast_open": false 25 | } 26 | -------------------------------------------------------------------------------- /MIsc: -------------------------------------------------------------------------------- 1 | 2 | 3 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 数据库安装 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 4 | 5 | 怎么创建数据库呢... 6 | RDS 不是 vps.. 好像没有登录功能的按! 怎么登录数据库呢... 7 | 对了 有个 域名. 然后账号密码就可以了. 8 | 但是怎么创建数据库了 mysql xxxx 命令 连到数据库就可以了.! 9 | 也能连上去... 10 | 11 | 1. 首先建立数据库. 12 | 13 | 2. 然后下载一个 db.sql 文件 (默认加密方式是 chacha20) 14 | https://raw.githubusercontent.com/Xu-Jian/Ansible-DevOps/master/sources/db.sql 15 | 16 | 3. 导入数据表, 然后就算创建好了. 17 | 数据库不是重点. 18 | 19 | 把这个直接写成脚本不就可以了. 20 | 让脚本去 连接数据库. 下载配置文件. 执行文件! 21 | 你可以用 shell 也能用python . 运维么. 还是 shell 的通用性强点. python 人家不一定有安装, 而且还要区分版本! 22 | 23 | 24 | 要创建数据库 25 | 26 | 普通人是没有数据库权限的. 27 | 所以数据库操作 最好是 写成 .sql ... 28 | 其实就是 sql 脚本... 29 | 里面都是一些数据库的命令! 为什么不自己写在 脚本里面呢! 30 | 区分啊. 脚本太大了 也不知道干嘛的! sql 脚本肯定是 操作 sql 的 31 | 怎么执行sql 文件呢... ssh 就可以. 32 | mysql –u用户名 –p密码 –D数据库<【sql脚本文件路径全名】 33 | 所以也不需要人工干预... 可以实现自动化的! 34 | 35 | 36 | 下一步就是 ansible 判断数据库状态了... 能不能连上数据库 37 | 还好! 这个也已经有 模块了!!! 也不要你操心... 38 | mysql_db 模块, 配置下 主机,端口,账户密码. 39 | 这个能直接创建数据库. 当然执行 .sql 也不在话下!!! 40 | 41 | ⦿ 创建数据库 42 | 43 | - name: Create a new database with name 'bobdata' 44 | mysql_db: 45 | name: bobdata 46 | state: present 47 | 48 | 49 | ⦿ 执行 sql 脚本... 50 | - name: Import file.sql similar to mysql -u -p < hostname.sql 51 | mysql_db: 52 | state: import 53 | name: all 54 | target: /tmp/{{ inventory_hostname }}.sql 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /SSR/ssr.yml: -------------------------------------------------------------------------------- 1 | --- 2 | - hosts: vps2 3 | gather_facts: no 4 | remote_user: root 5 | sudo: yes 6 | sudo_user: root 7 | 8 | tasks: 9 | - name: ensure libsodium is installed 10 | yum: pkg=libsodium state=latest 11 | 12 | - name: python-setuptools 13 | yum : pkg=python-setuptools state=latest 14 | 15 | - name: Git 16 | yum : pkg=git state=latest 17 | 18 | # - name: install pip with easy_install 19 | # easy_install: name=pip state=latest 20 | 21 | - name: install cymysql use pip 22 | pip: name=cymysql state=latest 23 | 24 | - git: 25 | repo='https://github.com/Xu-Jian/shadowsocksr' 26 | dest=~/shadowsocksr 27 | 28 | 29 | - name: Check that the somefile.conf exists 30 | stat: 31 | path: ~/shadowsocksr/usermysql.json 32 | register: stat_result 33 | 34 | - name: Create the file, if it doesnt exist already 35 | shell: cd ~/shadowsocksr && bash initcfg.sh 36 | when: stat_result.stat.exists == False 37 | 38 | 39 | 40 | 41 | 42 | 43 | - name: Download usermysql.json 44 | get_url: 45 | url: https://raw.githubusercontent.com/Xu-Jian/Ansible-DevOps/master/SSR/sources/usermysql.json 46 | dest: /root/shadowsocksr/ 47 | force: yes 48 | 49 | 50 | - name: Download userapiconfig.py 51 | get_url: 52 | url: https://raw.githubusercontent.com/Xu-Jian/Ansible-DevOps/master/SSR/sources/userapiconfig.py 53 | dest: /root/shadowsocksr/ 54 | force: yes 55 | 56 | 57 | - name: Download user-config.json 58 | get_url: 59 | url: https://raw.githubusercontent.com/Xu-Jian/Ansible-DevOps/master/SSR/sources/user-config.json 60 | dest: /root/shadowsocksr/ 61 | force: yes 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /SSR/sources/db.sql: -------------------------------------------------------------------------------- 1 | SET NAMES utf8; 2 | SET time_zone = '+00:00'; 3 | SET foreign_key_checks = 0; 4 | SET sql_mode = 'NO_AUTO_VALUE_ON_ZERO'; 5 | 6 | DROP TABLE IF EXISTS `sp_config`; 7 | CREATE TABLE `sp_config` ( 8 | `id` int(11) NOT NULL AUTO_INCREMENT, 9 | `key` varchar(128) NOT NULL, 10 | `value` text NOT NULL, 11 | `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 12 | `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 13 | PRIMARY KEY (`id`) 14 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 15 | 16 | 17 | DROP TABLE IF EXISTS `sp_log`; 18 | CREATE TABLE `sp_log` ( 19 | `id` int(11) NOT NULL AUTO_INCREMENT, 20 | `type` varchar(16) NOT NULL, 21 | `msg` text NOT NULL, 22 | `created_time` int(11) NOT NULL, 23 | PRIMARY KEY (`id`) 24 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 25 | 26 | 27 | DROP TABLE IF EXISTS `ss_invite_code`; 28 | CREATE TABLE `ss_invite_code` ( 29 | `id` int(11) NOT NULL AUTO_INCREMENT, 30 | `code` varchar(128) NOT NULL, 31 | `user_id` int(11) NOT NULL, 32 | `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, 33 | `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', 34 | PRIMARY KEY (`id`), 35 | KEY `user_id` (`user_id`) 36 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 37 | 38 | 39 | DROP TABLE IF EXISTS `ss_node`; 40 | CREATE TABLE `ss_node` ( 41 | `id` int(11) NOT NULL AUTO_INCREMENT, 42 | `name` varchar(128) NOT NULL, 43 | `type` int(3) NOT NULL, 44 | `server` varchar(128) NOT NULL, 45 | `method` varchar(64) NOT NULL, 46 | `custom_method` tinyint(1) NOT NULL DEFAULT '0', 47 | `traffic_rate` float NOT NULL DEFAULT '1', 48 | `info` varchar(128) NOT NULL, 49 | `status` varchar(128) NOT NULL, 50 | `offset` int(11) NOT NULL DEFAULT '0', 51 | `sort` int(3) NOT NULL, 52 | PRIMARY KEY (`id`) 53 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4; 54 | 55 | 56 | DROP TABLE IF EXISTS `ss_node_info_log`; 57 | CREATE TABLE `ss_node_info_log` ( 58 | `id` int(11) NOT NULL AUTO_INCREMENT, 59 | `node_id` int(11) NOT NULL, 60 | `uptime` float NOT NULL, 61 | `load` varchar(32) NOT NULL, 62 | `log_time` int(11) NOT NULL, 63 | PRIMARY KEY (`id`) 64 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 65 | 66 | 67 | DROP TABLE IF EXISTS `ss_node_online_log`; 68 | CREATE TABLE `ss_node_online_log` ( 69 | `id` int(11) NOT NULL AUTO_INCREMENT, 70 | `node_id` int(11) NOT NULL, 71 | `online_user` int(11) NOT NULL, 72 | `log_time` int(11) NOT NULL, 73 | PRIMARY KEY (`id`) 74 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 75 | 76 | 77 | DROP TABLE IF EXISTS `ss_password_reset`; 78 | CREATE TABLE `ss_password_reset` ( 79 | `id` int(11) NOT NULL AUTO_INCREMENT, 80 | `email` varchar(32) NOT NULL, 81 | `token` varchar(128) NOT NULL, 82 | `init_time` int(11) NOT NULL, 83 | `expire_time` int(11) NOT NULL, 84 | PRIMARY KEY (`id`) 85 | ) ENGINE=InnoDB DEFAULT CHARSET=latin1; 86 | 87 | 88 | DROP TABLE IF EXISTS `user`; 89 | CREATE TABLE `user` ( 90 | `id` int(11) NOT NULL AUTO_INCREMENT, 91 | `user_name` varchar(128) CHARACTER SET utf8mb4 NOT NULL, 92 | `email` varchar(32) NOT NULL, 93 | `pass` varchar(64) NOT NULL, 94 | `passwd` varchar(16) NOT NULL, 95 | `t` int(11) NOT NULL DEFAULT '0', 96 | `u` bigint(20) NOT NULL, 97 | `d` bigint(20) NOT NULL, 98 | `transfer_enable` bigint(20) NOT NULL, 99 | `port` int(11) NOT NULL, 100 | `protocol` varchar(32) NOT NULL DEFAULT 'origin', 101 | `obfs` varchar(32) NOT NULL DEFAULT 'plain', 102 | `switch` tinyint(4) NOT NULL DEFAULT '1', 103 | `enable` tinyint(4) NOT NULL DEFAULT '1', 104 | `type` tinyint(4) NOT NULL DEFAULT '1', 105 | `last_get_gift_time` int(11) NOT NULL DEFAULT '0', 106 | `last_check_in_time` int(11) NOT NULL DEFAULT '0', 107 | `last_rest_pass_time` int(11) NOT NULL DEFAULT '0', 108 | `reg_date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 109 | `invite_num` int(8) NOT NULL DEFAULT '0', 110 | `is_admin` int(2) NOT NULL DEFAULT '0', 111 | `ref_by` int(11) NOT NULL DEFAULT '0', 112 | `expire_time` int(11) NOT NULL DEFAULT '0', 113 | `method` varchar(64) NOT NULL DEFAULT ‘chacha20’, 114 | `is_email_verify` tinyint(4) NOT NULL DEFAULT '0', 115 | `reg_ip` varchar(128) NOT NULL DEFAULT '127.0.0.1', 116 | PRIMARY KEY (`id`), 117 | UNIQUE KEY `email` (`email`), 118 | UNIQUE KEY `port` (`port`) 119 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 120 | 121 | INSERT INTO `user` (`id`, `user_name`, `email`, `pass`, `passwd`, `t`, `u`, `d`, `transfer_enable`, `port`, `protocol`, `obfs`, `switch`, `enable`, `type`, `last_get_gift_time`, `last_check_in_time`, `last_rest_pass_time`, `reg_date`, `invite_num`, `is_admin`, `ref_by`, `expire_time`, `method`, `is_email_verify`, `reg_ip`) VALUES (NULL, 'admin', '91vps', 'ec7f4e50372f4fa95ff734579d2c36bb', '3yUaDj', '0', '0', '0', '2147483648', '1025', 'origin', 'plain', '1', '1', '1', '0', '0', '0', '2017-05-09 16:01:43', '5', '1', '0', '0', 'rc4-md5', '0', '127.0.0.1'); 122 | 123 | DROP TABLE IF EXISTS `user_token`; 124 | CREATE TABLE `user_token` ( 125 | `id` int(11) NOT NULL AUTO_INCREMENT, 126 | `token` varchar(256) NOT NULL, 127 | `user_id` int(11) NOT NULL, 128 | `create_time` int(11) NOT NULL, 129 | `expire_time` int(11) NOT NULL, 130 | PRIMARY KEY (`id`) 131 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 132 | 133 | 134 | DROP TABLE IF EXISTS `user_traffic_log`; 135 | CREATE TABLE `user_traffic_log` ( 136 | `id` int(11) NOT NULL AUTO_INCREMENT, 137 | `user_id` int(11) NOT NULL, 138 | `u` int(11) NOT NULL, 139 | `d` int(11) NOT NULL, 140 | `node_id` int(11) NOT NULL, 141 | `rate` float NOT NULL, 142 | `traffic` varchar(32) NOT NULL, 143 | `log_time` int(11) NOT NULL, 144 | PRIMARY KEY (`id`) 145 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 146 | 147 | 148 | DROP TABLE IF EXISTS `ss_checkin_log`; 149 | CREATE TABLE `ss_checkin_log` ( 150 | `id` int(11) NOT NULL AUTO_INCREMENT, 151 | `user_id` int(11) NOT NULL, 152 | `checkin_at` int(11) NOT NULL, 153 | `traffic` double NOT NULL, 154 | `created_at` timestamp NULL DEFAULT NULL ON UPDATE CURRENT_TIMESTAMP, 155 | `updated_at` timestamp NULL DEFAULT NULL, 156 | PRIMARY KEY (`id`) 157 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 158 | 159 | DROP TABLE IF EXISTS `sp_email_verify`; 160 | CREATE TABLE `sp_email_verify` ( 161 | `id` int(11) NOT NULL AUTO_INCREMENT, 162 | `email` varchar(32) NOT NULL, 163 | `token` varchar(64) NOT NULL, 164 | `expire_at` int(11) NOT NULL, 165 | PRIMARY KEY (`id`) 166 | ) ENGINE=InnoDB DEFAULT CHARSET=utf8; 167 | 168 | 169 | 170 | -------------------------------------------------------------------------------- /SSR/README.md: -------------------------------------------------------------------------------- 1 | # Ansible-SSR 2 | 3 | 本文目的就是为了可以自动化安装一个多人翻墙SSR 的后端部分. 4 | 5 | 2017-11-1-14 亲测可行 ✔︎ 6 | 7 | 8 | 🔶 SSR 组成 9 | 10 | 前端: 一个网页. 可以用来注册, 查看流量 11 | 后端: SSR 主程序搭在这里. 一台vps就是一个节点.用户通过节点服务器翻墙. 12 | 数据库: 前端注册会把注册信息写到数据库中; 所以前端是要连数据库的. 13 | 用户要连某个翻墙节点,节点(后端)首先要检查数据库有没有该用户. 14 | 所以后端也是要连数据库的! 15 | 16 | 三部分是可以分开的!! 也可以是一起的. 17 | 单节点: 三个部分都安装在一起. 18 | 多节点: 某个节点安装数据库/前端就可以了, 但是需要在所有节点安装后端. 19 | 20 | 本文只介绍 SSR 后端的安装!! 而且你要用的话, 得自己改数据库信息! 21 | 我的数据库是 只有几个固定IP 可以连的. 你是连不上的. 22 | 23 | 24 | 25 | 🔶 数据库安全 26 | 27 | 我的 数据库密码都是直接写在配置文件中的. 28 | 当然这个数据库的用户权限有限制的. 而且只能使用固定的IP 才能连. 29 | 下面就来说说 怎么操作..如果你要连我数据库,会有下面的报错. 30 | 错误码:1045 Access denied for user 'root@xx.xx.xx.xx'(using password:YES) 31 | 这个提示通常是由于Mysql默认的IP限制原因。 32 | 只要登录 mysql 把,某个用户的 host 的值 改为 % 就所有人都可以连了. 33 | 把% 改成 127.0.0.1 就只有本机可连 34 | 把% 改成 23.105.192.96 就只有这个IP可连 35 | 36 | 37 | 38 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 39 | 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 Ansible 实战 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 40 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 41 | 42 | 🔵 1. vps2 配置 ssh 让 gce 可以连上. 43 | 44 | 45 | 🔵 SSR 搭建步骤简介 46 | 47 | 本文只搭建下 ssr 后端! 数据库/前端都不用!! 48 | SSR 后端是需要加密的, 所以要安装依赖: libsodium 49 | 然后就是一些 python 依赖 50 | 最后就是 ssr 安装 51 | 然后 ssr 配置 52 | 再加上 服务的自启动! 就可以了!!! 53 | 54 | 55 | 🔵 libsodium 安装 56 | 57 | 🔶 gce 创建创建 ssr.yml 58 | 59 | --- 60 | - hosts: vps2 61 | remote_user: root 62 | 63 | tasks: 64 | - name: ensure libsodium is installed 65 | yum: pkg=libsodium state=latest 66 | 67 | 🔶 GCE 运行脚本 68 | ✘✘∙GCE ~ ➜ ansible-playbook ssr.yml 69 | 70 | TASK [ensure libsodium is installed] *************************************************** 71 | changed: [104.224.139.45] 72 | 73 | 🔶 vps2 检测 74 | 75 | yum list libsodium 可以看到安装包了.说明安装好了. 76 | 我们再执行 yml 脚本就会发现, 这个任务返回的状态是 ok 而不是 changed, 77 | 说明vps2 已经安装过 这个依赖了! 自然也不需要改变了. 78 | 79 | 80 | 81 | 82 | 🔵 依赖安装 83 | 84 | 🔶 简介 85 | 86 | 安装 SSR 之前 需要安装下面这些依赖. 87 | 88 | yum install python-setuptools -y 89 | && yum install git 90 | && easy_install pip 91 | && pip install cymysql 92 | 93 | 94 | 🔶 python-setuptools 95 | 96 | ⦿ playbook 脚本 97 | 98 | - name: python-setuptools 99 | yum : pkg=python-setuptools state=latest 100 | 101 | ⦿ vps2 验证: 102 | 103 | yum list python-setuptools 104 | 的 Installed Packages 里面如果有 105 | python-setuptools.noarch 0.9.8-7.el7 @base 106 | 就说明安装好了. 107 | 108 | 109 | 🔶 Git 110 | 111 | ⦿ vps2 查看 112 | 113 | 首先去 vps2 看看有没有安装 git ➜ yum list git 114 | Installed Packages 115 | git.x86_64 1.8.3.1-6.el7_2.1 @base 116 | Available Packages 117 | git.x86_64 1.8.3.1-12.el7_4 updates 118 | 发现以及安装了. 而且有个新版本出来了. 不管. 先卸载掉 yum remove git 119 | 再看 yum list git 就发现 120 | Available Packages 121 | git.x86_64 1.8.3.1-12.el7_4 updates 122 | 也就说 当前没有安装! 123 | 124 | ⦿ playbook 脚本 125 | 126 | - name: Git 127 | yum : pkg=git state=latest 128 | 129 | 130 | 🔶 pip 131 | 132 | pip 一般是用 easy_install pip 来安装的, 133 | 这种安装方式 不好卸载. 我们就不卸载了. 134 | 怎么用 Ansible 来安装 php呢! 用 easy_install 模块! 135 | 模块不会用看官方文档就行了! 非常简单的... 136 | http://docs.ansible.com/ansible/latest/easy_install_module.html 137 | 需要搜索什么其他模块, 可以直接右下角进行搜索! 比如 pip 命令 138 | 139 | 官方手册的例子 140 | - easy_install: 141 | name: pip 142 | state: latest 143 | 144 | 我们加个name 上去就可以了 145 | - name: install pip with easy_install 146 | easy_install: name=pip state=latest 147 | 148 | 149 | 🔶 cymysql 150 | 151 | 这个是为了 python 可以连接 mysql 用的 152 | 153 | - name: install cymysql use pip 154 | pip: name=cymysql state=latest 155 | 156 | 157 | 158 | 🔶 安装 SSR 159 | 160 | 这个就是执行 git 命令了.. 161 | 这也是个模块! 而且也能指定安装路径! 原始命令是下面这样的 162 | 🔅 cd ~ && git clone -b manyuser https://github.com/shadowsocksr/shadowsocksr.git 163 | 164 | git 命令非常简单 165 | 最简单直接的命令 git clone xxx.git 166 | 如果想clone到指定目录 git clone xxx.git "指定目录" 167 | 168 | ansible 中的 git 模块, 默认值就是 clone . 所以可以不写. 169 | 一般情况肯定是新建个文件夹来放 git 下载下来的文件的. 170 | 所以要用 dest 参数来指定一个安装路径. 这个路径会自动创建. 171 | 下面的 ~/ 目录下本来是没有shadowsocksr文件夹的, 172 | 执行这个 playbook 后会自动创建! 173 | 174 | - git: 175 | repo='https://github.com/Xu-Jian/shadowsocksr' 176 | dest=~/shadowsocksr 177 | 178 | 179 | 180 | 181 | 🔶 SSR 初始化 182 | 183 | 下载后 是需要进入 ssr 文件夹 进行初始化的! 184 | 虽然只要这么一个命令! cd ~/shadowsocksr && bash initcfg.sh 185 | 初始化脚本,也就是设置下文件权限. 加创建一些配置文件. 186 | 但是这个命令也不能重复运行! 不然你下面设置好的配置文件会被覆盖... 187 | 这个初始化命令会生成一个 usermysql.json 188 | 所以只要事先判断有没有这个文件, 就知道是否初始化过了. 189 | 要判断文件状态 (检查文件存在) 就得用 stat 模块了 190 | 191 | - name: Check that the usermysql.json exists 192 | stat: 193 | path: ~/shadowsocksr/usermysql.json 194 | register: stat_result 195 | 196 | - name: do something, if the file doesn't exist 197 | shell: cd ~/shadowsocksr && bash initcfg.sh 198 | when: stat_result.stat.exists == False 199 | 200 | 201 | 🔶 SSR 配置文件 202 | 203 | 这个配置文件要么事先服务器上配置好! 然后复制给节点了! 204 | 要么就用正则式,改节点的配置文件. 205 | 为了统一, 我的配置文件就放到 github 上了.免得哪天 gce 重装了 啥也没有了. 206 | 207 | userapiconfig.py 208 | 连接前端的, 要配置 v2 还是v3 , 单人ss 还是多人的 ssr 209 | 210 | /root/shadowsocksr/usermysql.json 211 | 连数据库用的! 212 | 213 | /root/shadowsocksr/user-config.json 214 | 配置后端的 加密方式! 215 | 216 | 由于上面进行初始化后,这三个文件肯定是存在的,,,, 要先下载 然后 覆盖! 217 | 下载模块了 get_url 218 | http://docs.ansible.com/ansible/latest/get_url_module.html 219 | 220 | 221 | - name: Download usermysql.json 222 | get_url: 223 | url: https://raw.githubusercontent.com/Xu-Jian/Ansible-DevOps/master/SSR/sources/usermysql.json 224 | dest: /root/shadowsocksr/ 225 | force: yes 226 | 227 | 228 | - name: Download userapiconfig.py 229 | get_url: 230 | url: https://raw.githubusercontent.com/Xu-Jian/Ansible-DevOps/master/SSR/sources/userapiconfig.py.json 231 | dest: /root/shadowsocksr/ 232 | force: yes 233 | 234 | 235 | - name: Download user-config.json 236 | get_url: 237 | url: https://raw.githubusercontent.com/Xu-Jian/Ansible-DevOps/master/SSR/sources/user-config.json 238 | dest: /root/shadowsocksr/ 239 | force: yes 240 | 241 | 242 | 243 | 🔶 启动服务 244 | 245 | - name: start ssr 246 | shell: sh /root/shadowsocksr/run.sh 247 | 248 | 249 | 🔶 开机自启 supervisorctl 250 | 251 | 你可以用 rc.local 来自动启动. 也可以用 supervisor... 252 | andible 就有个 supervisor 模块! supervisorctl ... 253 | 254 | - supervisorctl: 255 | name: my_app 256 | state: started 257 | 258 | 当然这个得先安装并配置 supervisor ... 259 | 260 | 261 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Ansible-DevOps 2 | 3 | 自学苦逼, 不写个项目出来都不敢说自己会配置管理! 4 | 5 | 6 | 7 | # TODO 8 | 9 | # Done 10 | 11 | • Ansible 搭建(服务端+节点) 2017-10-28-22 ✔︎ 12 | 13 | • Ansible 基本介绍 14 | 15 | 16 | 17 | 18 | ## 参考 19 | 20 | ❗️❗️ Ansible中文权威指南 ❗️❗️ 21 | http://ansible-tran.readthedocs.io/en/latest/docs/intro_installation.html 22 | 23 | ★★★ ansible-first-book 24 | https://www.gitbook.com/book/ansible-book/ansible-first-book 25 | 26 | 27 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 28 | 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 Ansible 搭建 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 29 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 30 | 31 | 🔵 Ansible 安装 CentOS_7 ✔︎ 32 | 33 | yum install epel-release 34 | yum search ansible 35 | yum install ansible -y 36 | ansible --version 37 | 38 | 39 | 🔵 Ansible 安装 Mac ✔︎ 40 | 41 | 🔶 Mac 安装 42 | 43 | 其实服务端是不需要公有IP的.所以在Mac 本地搭服务会好很多... 44 | 可以用brew 安装. 但是版本比较老.最好用 pip 安装. 45 | sudo easy_install pip ➜ 安装 pip 46 | sudo pip install ansible --quiet ➜ 安装 ansible 47 | sudo pip install ansible --upgrade ➜ 升级 ansible 48 | ansible --version ➜ 查看安装的版本 49 | 50 | 🔶 Mac 配置 51 | 52 | 配置文件不是必须的!! 但是主机文件是要有的! 53 | 首先你要手动创建一个 /etc/ansible 文件夹 54 | 然后你要 从别的地方下载一个 hosts 文件到上面的文件夹. 55 | 然后配置 hosts. 之后就正常用了 56 | 57 | 58 | 59 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 密钥配置 ✔︎ 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 60 | 61 | 🔶 简介 62 | 63 | Ansible 之所以不要安装客户端 是因为服务端能直接SSH到所有的客户端! 64 | 要实现这个功能,当然要事先配置 SSH 密钥了. 65 | 也就是把 服务端的公钥 放到所有客户端上去. 66 | 目的: 只要 Ansible 服务端 能不用密码直接ssh 到客户端就行. 不管任何方法. 67 | 68 | 🔶 密钥技巧 69 | 70 | 其实一个人只要一套密钥就够了! 比如你用 Mac电脑生成一套密钥 (公钥+私钥) 71 | 如果你把Mac 的公钥上传到 vps1 ➜ Mac 就可以SSH vps1 72 | 如果你把Mac 的公钥上传到 vps2 ➜ Mac 就可以SSH vps2 73 | 如果你把Mac 的私钥上传到 vps3 ➜ vps3 就可以SSH Mac + vps1 + vps2 了 74 | 75 | 如果你有好几个VPS, 需要互相之间能直接SSH, 76 | 那么最简单的方法是 Mac 本地生成一套密钥, 77 | 把这套密钥(公钥+私钥) 上传到 所有的VPS, 78 | 然后所有VPS 就可以互相SSH了 79 | 80 | 81 | 🔶 生成密钥 82 | 83 | • 密钥生成 🔅 ssh-keygen -t rsa 84 | • 公钥位置 ~/.ssh/id_rsa.pub 85 | • 私钥位置 ~/.ssh/id_rsa ⚡ 本文件非常重要,一般绝对不能外泄. 86 | 87 | ⚡ 不管是Mac 还是 Linux 生成密钥的命令都是一样的! 88 | 89 | 🔶 密钥上传 + authorized_keys + 重启SSH 90 | 91 | 用 scp 命令把服务器的公钥传输到所有客户端上! 92 | 下面命令是把本地的密钥上传到服务器 root 用户的 ~/.ssh/ 目录下 93 | 由于服务器是ssh 端口为了安全改成 2190 了 所以需要 -P 2190 参数 94 | 95 | 当然 现在还不能互相SSH, 公钥上传只是第一步. 96 | 还要在服务器上把 公钥添加到 authorized_keys 里面. 97 | 任何客户端想要ssh进服务器, 服务器首先查的就是这个 authorized_keys 文件. 98 | 如果这个文件里面 有客户端的公钥, 那么就允许SSH连接! 99 | 100 | authorized_keys 这步是在对方服务器上设置的. 101 | 比如我Mac 要 SSH 到 GCE , 那么就去GCE设置这步! 102 | GCE是服务器. 然后很多员工都要SSH 到这个服务器. 所以GCE服务器上会有很多 公钥! 103 | 因为每个员工都会生成一套自己的密钥对,私钥自己保存, 公钥上传到GCE 上面. 104 | 每个员工都需要把自己的公钥 用下面命令追加到服务器GCE的 authorized_keys 文件中 105 | cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys 106 | 107 | • GCE 服务器配置 (Ansible 安装在此) 108 | 🔅 本地 ➜ scp -P 2190 -r ~/.ssh/id_rsa.pub root@35.194.128.92:~/.ssh/ 109 | 🔅 本地 ➜ scp -P 2190 -r ~/.ssh/id_rsa root@35.194.128.92:~/.ssh/ 110 | 🔅 远端 ➜ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys 111 | 🔅 远端 ➜ /bin/systemctl restart sshd.service 112 | 113 | • vps1 服务器配置 114 | 🔅 本地 ➜ scp -P 2222 -r ~/.ssh/id_rsa.pub root@23.105.192.96:~/.ssh/ 115 | 🔅 本地 ➜ scp -P 2222 -r ~/.ssh/id_rsa root@23.105.192.96:~/.ssh/ 116 | 🔅 远端 ➜ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys 117 | 🔅 远端 ➜ /bin/systemctl restart sshd.service 118 | 119 | • vps2 服务器配置 120 | 🔅 本地 ➜ scp -P 2222 -r ~/.ssh/id_rsa.pub root@104.224.139.45:~/.ssh/ 121 | 🔅 本地 ➜ scp -P 2222 -r ~/.ssh/id_rsa root@104.224.139.45:~/.ssh/ 122 | 🔅 远端 ➜ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys 123 | 🔅 远端 ➜ /bin/systemctl restart sshd.service 124 | 125 | • aws 服务器配置 ✔︎ 126 | ⚡ AWS 默认是只能用 密钥 登录的, 而且这个密钥还是 AWS生成的. 127 | ⚡ 所以就不能在Mac 本地 用scp 命令把公钥上传到 aws 128 | ⚡ 而是要在 aws 用 scp 命令从某个有公网IP的电脑(比如 vps1) 下载密钥了! 129 | scp 上传命令语法 scp PathA user@IP:PathB ➜ 把A 文件 上传到对方的B 路径下 130 | scp 下载命令语法 scp username@IP:pathB PathA ➜ 从对方B 文件夹 下载内容到本地的A 131 | 132 | 🔅 AWS ➜ scp -P 2222 root@23.105.192.96:~/.ssh/id_rsa.pub ~/.ssh/ 133 | 🔅 AWS ➜ scp -P 2222 root@23.105.192.96:~/.ssh/id_rsa ~/.ssh/ 134 | 🔅 AWS ➜ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys 135 | 🔅 AWS ➜ /bin/systemctl restart sshd.service 136 | 137 | Mac 就能用 ssh root@13.115.230.116 登录 AWS了. 138 | 当然最重要的是 Ansible 服务端 能ssh aws 139 | 140 | 141 | 142 | 🔶 SSH 测试 143 | 144 | ✘✘∙𝒗2 ~ ➜ ssh -p 2222 root@23.105.192.96 145 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 146 | @ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @ 147 | @@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 148 | IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY! 149 | Someone could be eavesdropping on you right now (man-in-the-middle attack)! 150 | It is also possible that a host key has just been changed. 151 | The fingerprint for the RSA key sent by the remote host is 152 | 83:f4:2f:ae:7e:98:71:7c:95:42:ca:f6:88:27:9a:48. 153 | Please contact your system administrator. 154 | Add correct host key in /root/.ssh/known_hosts to get rid of this message. 155 | Offending RSA key in /root/.ssh/known_hosts:2 156 | RSA host key for [23.105.192.96]:2222 has changed and you have requested strict checking. 157 | Host key verification failed. 158 | 159 | 这个错误就只要在本地 rm /root/.ssh/known_hosts 160 | 这个文件没啥用的! 第一次连服务器会记录对方的一些信息到本地而已. 161 | 162 | 163 | 164 | 165 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 Ansible 节点配置 ✔︎ 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 166 | 167 | 🔶 Why 168 | 169 | 服务器必须要知道哪些节点是归自己管理的. 170 | Ansible 服务端安装好后会有个 hosts 文件. 171 | 修改这个配置来配置节点. vi /etc/ansible/hosts 172 | 173 | 174 | 🔶 如何配置 175 | 176 | [webservers] 177 | alpha.example.org 178 | beta.example.org 179 | 192.168.1.100 180 | 192.168.1.110 181 | 182 | [vpses] 是组名.随意取 183 | vps1 vps2 是主机名. 随意取 184 | ansible_ssh_host 指定服务器 ip 185 | ansible_ssh_port=2222 指定服务器ssh 端口 186 | ansible_ssh_user 指定服务器ssh 用户 187 | 188 | ⚡ 大概就是定义一个组来区分节点. 组下面可以写IP, 也能些域名. 189 | ⚡ 目的就是能连上节点服务器的ssh. 默认22端口的话 可以不写端口. 190 | ⚡ 如果SSH不是 22 端口, 就需要跟上端口号如: 23.105.192.96:2222 191 | 192 | 193 | 🔵 实际配置 194 | 195 | vi /etc/ansible/hosts 196 | 197 | [vps1] 198 | 23.105.192.96:2222 199 | 200 | [vps2] 201 | 104.224.139.45:2222 202 | 203 | [aws] 204 | 13.115.230.116 205 | 206 | 207 | 🔵 节点测试 (在 ansible 服务端上进行) 208 | 209 | ⦿ ansible -m ping 'vps1' ✔︎ 210 | 23.105.192.96 | SUCCESS => { 211 | "changed": false, 212 | "failed": false, 213 | "ping": "pong" 214 | } 215 | 216 | ⦿ ansible -m ping 'vps2' ✔ ︎ 217 | 104.224.139.45 | SUCCESS => { 218 | "changed": false, 219 | "failed": false, 220 | "ping": "pong" 221 | } 222 | 223 | ⦿ ansible -m ping 'aws' 👹 224 | 13.115.230.116 | FAILED! => { 225 | "changed": false, 226 | "failed": true, 227 | "module_stderr": "Shared connection to 13.115.230.116 closed.\r\n", 228 | "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n", 229 | "msg": "MODULE FAILURE", 230 | "rc": 0 231 | } 232 | 233 | 为什么会报错呢! 明明 GCE上是可以直接SSH AWS的. 看返回的报错信息吧! 234 | "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n", 235 | 估计是python 没装! 因为 AWS是新系统.. 看看去.. 236 | 237 | 🔶 Ubuntu 安装 Python 2.7 (忽略这步! Ubuntu 自带 Python 3.5 的) 238 | 239 | ★★★★★ 参考: https://vimsky.com/article/3577.html 240 | 241 | ⦿ 安装依赖! 242 | 243 | sudo apt-get install build-essential checkinstall 244 | 245 | sudo apt-get install libreadline-gplv2-dev libncursesw5-dev libssl-dev libsqlite3-dev tk-dev libgdbm-dev libc6-dev libbz2-dev 246 | 247 | ⦿ 下载 Python 248 | 249 | version=2.7.13 250 | wget https://www.python.org/ftp/python/$version/Python-$version.tgz 251 | 252 | ⦿ 解压并cd到相应的目录 253 | 254 | tar -xvf Python-$version.tgz 255 | cd Python-$version 256 | 257 | ⦿ 用checkinstall 命令来安装,这中安装方式的好处是在需要时更容易卸载 258 | 259 | ./configure 260 | make 261 | sudo checkinstall 262 | 263 | ********************************************************************** 264 | 265 | Done. The new package has been installed and saved to 266 | 267 | /root/Python-2.7.13/python_2.7.13-1_amd64.deb 268 | 269 | You can remove it from your system anytime using: 270 | 271 | dpkg -r python 272 | 273 | ********************************************************************** 274 | 275 | 🔶 AWS 节点再次测试 👹 276 | 277 | 还是一样的报错 278 | 那么估计是Python 路径问题了. 279 | CentOS 的 python 是 usr/bin/python 280 | ubuntu 的 Python 是 usr/local/bin/python 281 | 282 | 是不是创建个 快捷方式 就可以了呢... 283 | 还是先谷歌下这个错误吧 "module_stdout": "/bin/sh: 1: /usr/bin/python: not found\r\n" 284 | 285 | 发现只要在 host 文件里面指定python 路径就可以了! 286 | 加两行, 大概就是 aws 这组, 添加一个变量: vars. 变量就是python2.7 的路径 287 | 288 | [aws:vars] 289 | ansible_python_interpreter=/usr/local/bin/python 290 | 291 | 🔶 AWS 节点再次 ping 测试 ✔︎ 292 | 293 | ✘✘∙GCE ansible ➜ ansible -m ping 'aws' 294 | 13.115.230.116 | SUCCESS => { 295 | "changed": false, 296 | "failed": false, 297 | "ping": "pong" 298 | } 299 | 300 | 301 | 🔶 AWS 节点 内存使用情况 302 | 303 | ✘✘∙GCE ansible ➜ ansible -m shell -a 'free -m' 'aws' 304 | 13.115.230.116 | SUCCESS | rc=0 >> 305 | total used free shared buff/cache available 306 | Mem: 990 75 257 4 658 711 307 | Swap: 0 0 0 308 | 309 | ⚡ 到这里Ansible 就搭建好了! 没错! 就搭建好了.... 剩下的就是怎么使用了 310 | 311 | 312 | 313 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 314 | 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 Ansible 基础知识 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 315 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 316 | 317 | 🔶 简介 318 | 319 | 只要 Ansible 能成功连上客户端, 那么就算搭建成功了! 非常简单的! 320 | 当然会搭建 不等于说你会 Ansible 了... 连皮毛都还没学会呢..继续... 321 | 通过上面的搭建,对Ansible 还是没啥了解! 首先我们先学下 Ansible 基础! 322 | 323 | 324 | 🔶 配置管理 325 | 326 | 配置管理系统旨在使管理员和操作团队能够轻松地控制大量服务器。 327 | 它们允许您从一个中心位置以自动方式控制许多不同的系统。 328 | 329 | 配置管理那么多: Puppet、Ansible、Chef.... 330 | Puppet 太重量级了,而且蛮复杂的! 331 | 谷歌很多年前就用 Puppet 管理6000+台 Mac 桌面电脑. 332 | 适合人家大公司的不一定适合中小公司!!! 333 | Ansible 应该是中小公司最佳的选择. Chef.. 没啥了解... 334 | 自己这水平也进不了大公司,于是就选择了 Ansible. 335 | 336 | 337 | 🔶 Ansible 338 | 339 | Ansible 自动化运维工具! 基于Python开发的. 340 | 非常轻量! 搭建只需下面两步! 无须在被控主机安装任何软件. 341 | 1. 管理节点安装 Ansible, 342 | 2. 管理节点配置被控主机的 SSH 就算搭好了. 343 | 344 | Ansible 不需要在节点中安装任何客户端。它使用SSH来和节点进行通信. 345 | Ansible 支持多种系统! Redhat、Debian、Windows 都可以! 346 | 347 | 理论上. 只要能通过SSH 干的事情, Ansible 都能实现. 348 | 拷贝文件、安装软件包、启动服务... 349 | 350 | Ansible 是基于模块工作的!!! 351 | Ansible 本身没有啥功能,就是个框架!提供些基础服务. 重点是模块!!!! 352 | 353 | 你可以使用 Ansible 内置命令 来管理主机. 354 | 你可以使用 Ansible 脚本语言 来管理主机. ➜ Playbook 355 | 356 | 你想让 Absible 去 ping 某个主机, 357 | 你可以自己用 Ansible 内置的命令,你也可以自己写 palybook 来实现! 358 | 359 | 360 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 Ansible 命令 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 361 | 362 | 🔶 简介 363 | 364 | Ansible 自带一些基础命令! 365 | 比如 执行命令、拷贝文件、安装软件包、添加用户、启动服务、查看详细系统信息.... 366 | 其实现在没必要仔细学这个, 暂时的话能看懂就好. 367 | 368 | 🔶 基础用法 1 369 | 370 | ansible -m ping all 所有主机 371 | ansible -m ping vpses 指定一个组 372 | ansible -m ping vps1 指定单个主机 373 | ansible -m ping vps1:vps2 指定多个主机 374 | 375 | 例如,要找出我们的host1机器上的内存使用情况,我们可以使用: 376 | ansible -m shell -a 'free -m' host1 377 | 378 | 379 | 🔶 基础用法 2 380 | 381 | ⦿ 检查ansible安装环境 382 | 383 | 检查所有的远程主机,是否以bruce用户创建了ansible主机可以访问的环境。 384 | $ansible all -m ping -u bruce 385 | 386 | ⦿ 执行命令 387 | 388 | 在所有的远程主机上,以当前bash的同名用户,在远程主机执行“echo bash” 389 | $ansible all -a "/bin/echo hello" 390 | 391 | ⦿ 拷贝文件 392 | 393 | 拷贝文件/etc/host到远程主机(组)web,位置为/tmp/hosts 394 | $ ansible web -m copy -a "src=/etc/hosts dest=/tmp/hosts" 395 | 396 | ⦿ 安装包 397 | 398 | 远程主机(组)web安装yum包acme 399 | $ ansible web -m yum -a "name=acme state=present" 400 | 401 | ⦿ 添加用户 402 | 403 | $ ansible all -m user -a "name=foo password=" 404 | 405 | ⦿ 下载git包 406 | 407 | $ ansible web -m git -a "repo=git://..." 408 | 409 | ⦿ 启动服务 410 | 411 | $ ansible web -m service -a "name=httpd state=started" 412 | 413 | ⦿ 并行执行 414 | 415 | 启动10个并行进行执行重起 416 | $ansible lb -a "/sbin/reboot" -f 10 417 | 418 | ⦿ 查看远程主机的全部系统信息!!! 419 | 420 | $ ansible all -m setup 421 | 422 | 423 | 🔶 基础用法 3 424 | 425 | ⦿ 检查Ansible节点的运行时间(uptime): 426 | ansible -m command -a "uptime" 'dbservers' 427 | 428 | ⦿ 检查节点的内核版本 429 | ansible -m command -a "uname -r" 'dbservers' 430 | 431 | ⦿ 给节点增加用户 432 | ansible -m command -a "useradd david" 'dbservers' 433 | 434 | ⦿ 重定向输出到文件中 435 | ansible -m command -a "df -Th" 'dbservers' > /tmp/command-output.txt 436 | cat /tmp/command-output.txt 437 | 438 | 439 | 440 | 441 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 Playbook 简介 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 442 | 443 | 🔶 Playbook 444 | 445 | 说到自动化,肯定是离不开脚本的! 446 | Ansible 也提供了 脚本功能. Ansible 的脚本有个名字 叫 playbook. 447 | playbook 使用的是 YAML 格式, Playbook 脚本文件以 yml 结尾. YAML 类似 JSON. 448 | 449 | 450 | 🔶 执行 Playbook 的方法 451 | 452 | ansible-playbook deploy.yml 453 | 454 | 455 | 🔵 Playbook 实例 456 | 457 | --- 458 | - hosts: web 459 | vars: 460 | http_port: 80 461 | max_clients: 200 462 | remote_user: root 463 | tasks: 464 | - name: ensure apache is at the latest version 465 | yum: pkg=httpd state=latest 466 | 467 | - name: Write the configuration file 468 | template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf 469 | notify: 470 | - restart apache 471 | 472 | - name: Write the default index.html file 473 | template: src=templates/index.html.j2 dest=/var/www/html/index.html 474 | 475 | - name: ensure apache is running 476 | service: name=httpd state=started 477 | handlers: 478 | - name: restart apache 479 | service: name=httpd state=restarted 480 | 481 | 482 | 483 | 这个playbook的功能是为web主机部署apache, 包含以下部署步骤: 484 | • 安装apache包; 485 | • 拷贝配置文件httpd,并保证拷贝文件后,apache服务会被重启; 486 | • 拷贝默认的网页文件index.html; 487 | • 启动apache服务; 488 | 489 | 490 | playbook deploy.yml包含下面几个关键字,每个关键字的含义:+ 491 | 492 | hosts:为主机的IP,或者主机组名,或者关键字all 493 | remote_user: 以哪个用户身份执行。 494 | vars: 变量 495 | 496 | tasks: playbook的核心,定义顺序执行的动作action。 497 | 每个action调用一个ansbile module。 498 | action 语法: module: module_parameter=module_value 499 | 常用的module有yum、copy、template等... 500 | 501 | handers: 是playbook的event,默认不会执行,在action里触发才会执行。 502 | 多次触发只执行一次。 503 | 504 | 505 | 506 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 Ansible 模块 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 507 | 508 | 🔶 简介 509 | 510 | 模块非常强大的, 很多功能不需要你自己写脚本,可以直接实现某功能. 511 | 比如软件的安装, 比如 配置文件的分发, 比如服务的控制!!! 512 | 你可以在Ansible 命令里用模块, 也能在 Playbook 里用模块. 513 | 514 | 515 | 🔶 模块 (Ansible 命令) 516 | 517 | ⦿ 语法: 518 | -m + 模块名 519 | -a + 模块参数 520 | 521 | ⦿ 例: 522 | 用 copy 模块把管理员节点的 /etc/hosts文件 复制到所有远程主机/tmp/hosts 523 | $ ansible all -m copy -a "src=/etc/hosts dest=/tmp/hosts" 524 | 525 | 用 yum 模块在名为 web 的远程主机上安装httpd包 526 | $ ansible web -m yum -a "name=httpd state=present" 527 | 528 | 529 | 🔶 模块 (Ansible Playbook) 530 | 531 | ⦿ 语法 532 | 在playbook脚本中 533 | tasks中的每一个action都是对module的一次调用。 534 | 在每个action中:冒号前面是module的名字; 冒号后面是调用module的参数 535 | 536 | --- 537 | tasks: 538 | - name: ensure apache is at the latest version 539 | yum: pkg=httpd state=latest 540 | - name: write the apache config file 541 | template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf 542 | - name: ensure apache is running 543 | service: name=httpd state=started 544 | 545 | 546 | 🔶 常用模块 547 | 548 | 有些模块是 Ansible 非常常用的! 如: 549 | • yum 模块可以在节点安装软件! 550 | • template 模块可以把服务器上的某些文件 发送到客户端! 551 | • service 模块可以控制服务. 552 | 553 | 554 | 🔶调试和测试类的module 555 | 556 | ping - ping一下你的远程主机,如果可以通过ansible成功连接,那么返回pong 557 | debug - 用于调试的module,只是简单打印一些消息,有点像linux的echo命令。 558 | 559 | 560 | 🔶 文件类的module 561 | 562 | copy - 从本地拷贝文件到远程节点 563 | template - 从本地拷贝文件到远程节点,并进行变量的替换 564 | file - 设置文件的属性 565 | 566 | 567 | 🔶 linux上常用的操作 568 | 569 | user - 管理用户账户 570 | yum - red hat系linux上的包管理 571 | service - 管理服务 572 | firewalld - 管理防火墙中的服务和端口 573 | 574 | 575 | 🔶 执行Shell命令 576 | 577 | shell - 在节点上执行shell命令,支持$HOME和"<", ">", "|", ";" and "&" 578 | command - 在远程节点上面执行命令,不支持$HOME和"<", ">", "|", ";" and "&" 579 | 580 | 581 | 582 | 583 | 584 | 🔵 Ping 模块 ➜ 节点测试 585 | 586 | 最常用的测试模块, 测试一个节点有没有 配置好SSH. 587 | ping 模块 可不是 Linux 下的 ping 命令! 强大很多. 588 | Ping 模块首先检查能不能SSH登录! 然后还会检查对方Python版本是否满足Ansible的要求. 589 | 如果满足要求 就会返回ping, 不满足就会报错! 590 | 591 | ✘✘∙GCE ~ ➜ ansible aws -m ping 592 | 13.115.230.116 | SUCCESS => { 593 | "changed": false, 594 | "failed": false, 595 | "ping": "pong" 596 | } 597 | 598 | 599 | 🔵 Copy 模块 ➜ 文件复制 600 | 601 | 这个模块可以把服务器上的静态文件, copy 到远程节点上! 而且还能给文件设置权限! 602 | 大概原理就是 首先对比双方文件的 checksum 603 | 如果一致 说明远程的文件是最新的, 无需copy 604 | 如不一致 要么远程没有这个文件,要么文件版本太旧. 会直接复制/替换. 605 | 当然保险一点, 你也可以选择 先备份对方的文件,再进行copy. 606 | 607 | 608 | ⦿ 设置文件权限 609 | 610 | 把本地 myfiles 下的配置文件 复制到远程的 etc 目录下. 611 | 并设置 所属用户、用户组、用户权限 612 | 613 | - copy: 614 | src: /srv/myfiles/foo.conf 615 | dest: /etc/foo.conf 616 | owner: foo 617 | group: foo 618 | mode: 0644 619 | 620 | 621 | ⦿ 先备份再复制 622 | 623 | backup参数为yes的时候,如果发生了拷贝操作,那么会先备份下目标节点上的原文件。 624 | 当两个文件相同时,不会进行拷贝操作,当然也没有必要备份啦。 625 | 626 | - copy: 627 | src: sudoers 628 | dest: /tmp 629 | backup: yes 630 | 631 | 632 | ⦿ Copy + 验证操作 633 | 如果你觉得仅仅复制文件的功能还不够,比如某些配置文件, 你需要检查一下语法!! 634 | 哪怕本地检查过了,远程再检查一遍也是好的.那么你可以加个验证参数, 635 | 这样的话, 不仅仅需要文件拷贝成功, 还需要验证命令返回成功值才行. 636 | visudo -cf /etc/sudoers是验证sudoers文件有没有语法错误的命令。 637 | 638 | - copy: 639 | src: /mine/sudoers 640 | dest: /etc/sudoers 641 | validate: 'visudo -cf %s' 642 | 643 | 644 | 🔵 Template 模块 ➜ 文件模板 645 | 646 | 这个也是复制文件用的. 和copy 差不多, 但是比copy 强大很多. 647 | copy 只适合那些 静态文件! 不需要改变的文件. 648 | 但是事实上.很多文件都需要对服务器的模板文件进行一些修改后再复制到节点. 649 | 这时候你就要用到 Template 模块了. 650 | 651 | 比如我要给所有的远程节点都发送一个 Apache 的测试文件! 一个 index.html 652 | 这个index.html 文件的功能是显示当前节点的主机名和IP地址. 653 | 那么这个 index.html 肯定不是静态文件了... 654 | 这里就需要用到模板了! 如果你接触过模板 那么很好理解. 655 | 大概就是设置几个变量. 然后按照模板的语法就可以了.很简单的. 656 | 657 | 这里也一样! 主机名 和 IP 都是变量! 658 | 我们的 index.html 只要按照下面这么写就可以了 659 | 就用了两个变量而已. ansible_hostname 和 ansible_default_ipv4.address 660 | 变量外面的 {{}} 是模板语法, 就是这个文件再发送给对方之前! 661 | Template 模块 会首先把 {{ ansible_hostname }} ({{ ansible_default_ipv4.address }}) 662 | 变成对方的真实 主机名 和 真实IP. 663 | 664 | 665 | Demo 666 | 667 |
668 |
669 |

#46 Demo

670 |

Served by {{ ansible_hostname }} ({{ ansible_default_ipv4.address }}).

671 |
672 |
673 | 674 | 675 | 676 | ➜ 真正发给对方的是类似下面的 677 | 678 | 679 | Demo 680 | 681 |
682 |
683 |

#46 Demo

684 |

Served by GCE (35.194.128.92).

685 |
686 |
687 | 688 | 689 | 690 | 再来说说那两个变量, 这个是 Ansible 自带的变量. 所以变量名不能乱改的. 691 | 当然你也可以 使用普通变量 (自己设置变量). 692 | 普通变量的值 就需要你自己设置了!!! 在 playbook 中用 vars 来定义变量. 693 | 694 | - hosts: localhost 695 | vars: 696 | http_port: 8080 697 | remote_user: root 698 | tasks: 699 | 700 | - name: Write the configuration file 701 | template: src=templates/httpd.conf.j2 dest=/etc/httpd/conf/httpd.conf 702 | 703 | 然后你就可以在 httd.conf.j2 中使用 http_port 这个变量了, 比如. 704 | Listen {{ http_port }} 705 | 706 | 707 | 708 | 🔵 File 模块 ➜ 文件操作 709 | 710 | 设置远程主机 文件/文件夹 权限、 创建/删除文件.... 711 | 712 | 🔶 创建文件 713 | 714 | - file: 715 | path: /etc/foo.conf 716 | state: touch 717 | mode: "u=rw,g=r,o=r" 718 | 719 | 🔶 创建文件夹 720 | 721 | - file: 722 | path: /etc/some_directory 723 | state: directory 724 | mode: 0755 725 | 726 | 727 | 🔵 User 模块 728 | 729 | user module可以增、删、改Linux远程节点的用户账户,并为其设置账户的属性。+ 730 | 731 | 🔶 增加账户 732 | 733 | 增加账户johnd,并且设置uid为1040,设置用户的primary group为admin 734 | - user: 735 | name: johnd 736 | comment: "John Doe" 737 | uid: 1040 738 | group: admin 739 | 创建账户james,并为james用户额外添加两个group 740 | - user: 741 | name: james 742 | shell: /bin/bash 743 | groups: admins,developers 744 | append: yes 745 | 746 | 747 | 🔶 删除账户 748 | 749 | 删除账户johnd 750 | - user: 751 | name: johnd 752 | state: absent 753 | remove: yes 754 | 755 | 🔶 修改账户的属性 756 | 757 | 为账户jsmith创建一个 2048-bit的SSH key,放在~jsmith/.ssh/id_rsa 758 | - user: 759 | name: jsmith 760 | generate_ssh_key: yes 761 | ssh_key_bits: 2048 762 | ssh_key_file: .ssh/id_rsa 763 | 为用户添加过期时间: 764 | - user: 765 | name: james18 766 | shell: /bin/zsh 767 | groups: developers 768 | expires: 1422403387 769 | 770 | 771 | 772 | 🔵 yum ➜ 软件安装 773 | 774 | yum module是用来管理red hat系的Linux上的安装包的,包括RHEL,CentOS... 775 | 776 | 🔶 从yum源上安装和删除包 777 | 778 | 安装最新版本的包,如果已经安装了老版本,那么会更新到最新的版本: 779 | - name: install the latest version of Apache 780 | yum: 781 | name: httpd 782 | state: latest 783 | 安装指定版本的包 784 | - name: install one specific version of Apache 785 | yum: 786 | name: httpd-2.2.29-1.4.amzn1 787 | state: present 788 | 删除httpd包 789 | - name: remove the Apache package 790 | yum: 791 | name: httpd 792 | state: absent 793 | 从指定的repo testing中安装包 794 | - name: install the latest version of Apache from the testing repo 795 | yum: 796 | name: httpd 797 | enablerepo: testing 798 | state: present 799 | 800 | 801 | 🔶 从yum源上安装一组包 802 | 803 | - name: install the 'Development tools' package group 804 | yum: 805 | name: "@Development tools" 806 | state: present 807 | 808 | - name: install the 'Gnome desktop' environment group 809 | yum: 810 | name: "@^gnome-desktop-environment" 811 | state: present 812 | 813 | 814 | 🔶 从本地文件中安装包 815 | 816 | - name: install nginx rpm from a local file 817 | yum: 818 | name: /usr/local/src/nginx-release-centos-6-0.el6.ngx.noarch.rpm 819 | state: present 820 | 821 | 822 | 🔶 从URL中安装包 823 | 824 | - name: install the nginx rpm from a remote repo 825 | yum: 826 | name: http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm 827 | state: present 828 | 829 | 830 | 831 | 🔵 service 模块 ➜ 服务控制 832 | 833 | 管理远程节点上的服务,开、关、重起、重载服务 834 | 什么是服务呢,比如httpd、sshd、nfs、crond等。 835 | 836 | 🔶 开httpd服务 837 | 838 | - service: 839 | name: httpd 840 | state: started 841 | 842 | 🔶 关服务 843 | 844 | - service: 845 | name: httpd 846 | state: stopped 847 | 848 | 🔶 重起服务 849 | 850 | - service: 851 | name: httpd 852 | state: restarted 853 | 854 | 🔶 重载服务 855 | 856 | - service: 857 | name: httpd 858 | state: reloaded 859 | 860 | 🔶 设置开机启动的服务 861 | 862 | - service: 863 | name: httpd 864 | enabled: yes 865 | 866 | 🔶 启动网络服务下的接口 867 | 868 | - service: 869 | name: network 870 | state: restarted 871 | args: eth0 872 | 873 | 874 | 875 | 876 | 🔵 firewalld 模块 877 | 878 | firewalld module为某服务和端口添加firewalld规则。 879 | firewalld中有正在运行的规则,和永久的规则,firewalld module都支持。 880 | firewalld要求远程节点上的firewalld版本在0.2.11以上。 881 | 882 | 🔶 为服务添加firewalld规则 883 | 884 | - firewalld: 885 | service: https 886 | permanent: true 887 | state: enabled 888 | - firewalld: 889 | zone: dmz 890 | service: http 891 | permanent: true 892 | state: enabled 893 | 894 | 🔶 为端口号添加firewalld规则 895 | 896 | - firewalld: 897 | port: 8081/tcp 898 | permanent: true 899 | state: disabled 900 | - firewalld: 901 | port: 161-162/udp 902 | permanent: true 903 | state: enabled 904 | 905 | 🔶 其它复杂的firewalld规则 906 | 907 | - firewalld: 908 | rich_rule: 'rule service name="ftp" audit limit value="1/m" accept' 909 | permanent: true 910 | state: enabled 911 | - firewalld: 912 | source: 192.0.2.0/24 913 | zone: internal 914 | state: enabled 915 | - firewalld: 916 | zone: trusted 917 | interface: eth2 918 | permanent: true 919 | state: enabled 920 | - firewalld: 921 | masquerade: yes 922 | state: enabled 923 | permanent: true 924 | zone: dmz 925 | 926 | 927 | 🔵 Shell 模块 ➜ 执行命令 928 | 929 | 通过/bin/sh在远程节点上执行命令。 930 | 931 | 如果一个操作你可以通过Module yum,copy操作实现,那么你不要使用shell或者command这样通用的命令module。 932 | 933 | 因为通用的命令module不会根据具体操作的特点进行status的判断, 934 | 所以当没有必要再重新执行的时候,它还是要重新执行一遍。 935 | 支持$home,支持$HOME和"<", ">", "|", ";" and "&"。 936 | 937 | 🔶 支持$home ➜ shell: echo "Test1" > ~/tmp/test1 938 | 🔶 支持&& ➜ - shell: service jboss start && chkconfig jboss on 939 | 🔶 支持>> ➜ - shell: echo foo >> /tmp/testfoo 940 | 941 | 🔶 调用脚本 942 | - shell: somescript.sh >> somelog.txt 943 | 944 | 🔶 执行命令前,改变工作目录 945 | - shell: somescript.sh >> somelog.txt 946 | args: 947 | chdir: somedir/ 948 | 949 | 🔶 在执行命令前改变工作目录,且仅在文件somelog.txt不存在时才执行该action。 950 | - shell: somescript.sh >> somelog.txt 951 | args: 952 | chdir: somedir/ 953 | creates: somelog.txt 954 | 955 | 🔶 指定用bash运行命令 956 | - shell: cat < /tmp/\*txt 957 | args: 958 | executable: /bin/bash 959 | 960 | 961 | 962 | 963 | 964 | 965 | 966 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 Ansible 配置 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 967 | 任何软件都要配置.. Ansible 当然也是...你需要有个大概的了解! 968 | 969 | ⦿ 主机清单文件: ➜ inventory = /etc/ansible/hosts 970 | ⦿ 额外模块放置路径 ➜ library = /usr/share/my_modules/ 971 | ⦿ 远程主机的临时文件位置 ➜ remote_tmp = $HOME/.ansible/tmp 972 | ⦿ 管理节点上临时文件的位置 ➜ local_tmp = $HOME/.ansible/tmp 973 | 974 | 975 | 976 | 🔵 Host Inventory(主机清单) 977 | 978 | 主机清单,告诉ansible需要管理哪些server,和server的分类和分组信息。 979 | 可以根据你自己的需要根据地域分类,也可以按照功能的不同分类。 980 | 981 | 主机清单默认文件位置 /etc/ansible/hosts 982 | 983 | 984 | 🔶 简单的分组[]内是组名 985 | 986 | mail.example.com 987 | 988 | [webservers] 989 | foo.example.com 990 | bar.example.com 991 | 992 | [dbservers] 993 | one.example.com 994 | two.example.com 995 | three.example.com 996 | 997 | [webservers] 998 | www[01:50].example.com 999 | 1000 | [databases] 1001 | db-[a:f].example.com 1002 | 1003 | 1004 | 🔶 指定连接参数 1005 | 1006 | [targets] 1007 | 1008 | localhost ansible_connection=local 1009 | other1.example.com ansible_connection=ssh ansible_user=mpdehaan 1010 | other2.example.com ansible_connection=ssh ansible_user=mdehaan 1011 | 1012 | 1013 | 🔶 变量 1014 | 1015 | 为一个组指定变量 1016 | 1017 | [atlanta] 1018 | host1 1019 | host2 1020 | 1021 | [atlanta:vars] 1022 | ntp_server=ntp.atlanta.example.com 1023 | proxy=proxy.atlanta.example.com 1024 | 1025 | 1026 | 1027 | 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 Playbook 详解 🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶🔶 1028 | 1029 | 🔶 别人的Playbook 1030 | 1031 | 能够学会快速用别人的成果,高效地分享自己的成果,才是好码农. 1032 | 在你动手从头开始写一个Playbook之前,不如先参考一下别人的成果吧。 1033 | 1034 | ⦿ 官方例子 1035 | 1036 | Ansible官方提供了一些比较常用的、经过测试的Playbook例子: 1037 | https://github.com/ansible/ansible-examples 1038 | 1039 | ⦿ Playbook分享平台 1040 | 1041 | 此外,Ansible还提供了Playbook的分享平台,上面的例子是Ansible用户自己上传的。 1042 | 你如果在没有思路的情况下参考下吧,不过一定要再重新严谨的测试下。 1043 | https://galaxy.ansible.com/ 1044 | 1045 | 1046 | 🔶 Playbook 基本语法 1047 | 1048 | 运行脚本 ➜ ansible-playbook deploy.yml 1049 | 脚本详细输出➜ ansible-playbook playbook.yml --verbose 1050 | 查看脚本影响哪些hosts➜ ansible-playbook playbook.yml --list-hosts 1051 | 并行执行脚本 ➜ ansible-playbook playbook.yml -f 10 1052 | 1053 | 1054 | 🔶 Playbook 组成 1055 | 1056 | 最基本的 playbook 脚本分为三部分. 1057 | 1058 | ⦿ 在什么机器上,用什么身份执行 ➜ hosts users 1059 | ⦿ 执行哪些任务 ➜ tasks 1060 | ⦿ 善后的任务 ➜ handlers 1061 | 1062 | 1063 | 🔶 deploy.yml 例子 1064 | 1065 | --- 1066 | - hosts: webservers 1067 | vars: 1068 | http_port: 80 1069 | max_clients: 200 1070 | user: root 1071 | tasks: 1072 | - name: ensure apache is at the latest version 1073 | yum: pkg=httpd state=latest 1074 | - name: write the apache config file 1075 | template: src=/srv/httpd.j2 dest=/etc/httpd.conf 1076 | notify: 1077 | - restart apache 1078 | - name: ensure apache is running 1079 | service: name=httpd state=started 1080 | handlers: 1081 | - name: restart apache 1082 | service: name=httpd state=restarted 1083 | 1084 | 1085 | 🔵 主机和用户 1086 | 1087 | hosts 为主机的IP,或者主机组名,或者关键字all 1088 | user 在远程以哪个用户身份执行。 1089 | 1090 | 1091 | 🔵 Tasks任务列表 1092 | 1093 | tasks是从上到下顺序执行,如果中间发生错误,那么整个playbook会中止。 1094 | 1095 | 每一个task是对module的一次调用。使用不同的参数和变量而已。 1096 | 1097 | 每一个task最好有name属性,这个是供人读的,没有实际的操作。 1098 | 然后会在命令行里面输出,提示用户执行情况。 1099 | 1100 | 1101 | 🔶 task的基本写法: 1102 | 1103 | tasks: 1104 | - name: make sure apache is running 1105 | service: name=httpd state=running 1106 | 1107 | 其中name是可选的,也可以简写成下面的例子。 1108 | 1109 | tasks: 1110 | - service: name=httpd state=running 1111 | 1112 | 写name的task在playbook执行时,会显示对应的名字,信息更友好、丰富。 1113 | 写name是个好习惯! 1114 | TASK: [make sure apache is running] ************************************************************* 1115 | changed: [yourhost] 1116 | 1117 | 没有写name的task在playbook执行时,直接显示对应的task语法。 1118 | 在调用同样的module多次后,不好分辨执行到哪步了。 1119 | TASK: [service name=httpd state=running] ************************************** 1120 | changed: [yourhost] 1121 | 1122 | 1123 | 🔶 参数写法 key=value 1124 | 1125 | tasks: 1126 | - name: make sure apache is running 1127 | service: name=httpd state=running 1128 | 1129 | 当需要传入参数列表太长时,可以分隔到多行: 1130 | 1131 | tasks: 1132 | - name: Copy ansible inventory file to client 1133 | copy: src=/etc/ansible/hosts dest=/etc/ansible/hosts 1134 | owner=root group=root mode=0644 1135 | 1136 | 或者用yml的格式传入参数 1137 | tasks: 1138 | - name: Copy ansible inventory file to client 1139 | copy: 1140 | src: /etc/ansible/hosts 1141 | dest: /etc/ansible/hosts 1142 | owner: root 1143 | group: root 1144 | mode: 0644 1145 | 1146 | 1147 | 1148 | 🔶 TASK的执行状态 1149 | 1150 | task中每个action会调用一个module, 1151 | 在module中会去检查当前系统状态是否需要重新执行。 1152 | 1153 | 如果本次执行了,那么action会得到返回值changed; 1154 | 如果不需要执行,那么action得到返回值ok 1155 | 1156 | module的执行状态的具体判断规则由各个module自己决定和实现的。 1157 | 例如,"copy" module的判断方法是比较文件的checksum 1158 | 1159 | 1160 | 🔵 响应事件 Handler 1161 | 1162 | 每个主流的编程语言都会有event机制,那么handler就是playbook的event。 1163 | 1164 | Handlers里面的每一个handler,也是对module的一次调用。 但是 handlers与tasks不同, 1165 | tasks会默认的按定义顺序执行每一个task, 1166 | handlers则不会,它需要在tasks中被调用,才有可能被执行。 1167 | 1168 | Tasks中的任务都是有状态的,changed或者ok。 1169 | 在Ansible中,只在task的执行状态为changed的时候,才会执行该task调用的handler, 1170 | 这也是handler与普通的event机制不同的地方。 1171 | 1172 | 1173 | 🔶 Handler 应用场景 1174 | 1175 | 什么情况下使用handlers呢? 1176 | 1177 | 如果你在tasks中修改了apache的配置文件。需要重起apache。 1178 | 此外还安装了apache的插件。那么还需要重起apache。 像这样的应该场景中, 1179 | 不要在每个 task 后面 立即重启 Apache. 而是把 重起apache 设计成一个handler. 1180 | 这个 Handler 放在所有 Tasks 后面. 1181 | 用了Handle 只要重启一次就好了... 而不是 重启很多次... 1182 | 1183 | 1184 | 🔶 一个handler最多只执行一次 1185 | 在所有的任务里表执行之后执行 1186 | 如果有多个task notify同一个handler,那么只执行一次。 1187 | 1188 | 1189 | 1190 | 1191 | 1192 | 🔵 变量 1193 | 1194 | 用户可以在Playbook中,通过vars关键字自定义变量,使用时用{{ }}引用以来即可。+ 1195 | 1196 | 1197 | 🔶 主机的系统变量 facts 1198 | 1199 | ansible 会通过 setup 模块来收集主机的系统信息! 1200 | 这些收集到的信息叫做 facts. 1201 | 这些 facts 是可以直接用变量的形式使用的. 1202 | 1203 | 你用 ansible aws -m setup 命令就会输出 aws 收集到的信息! 非常的多! 1204 | 1205 | "ansible_hostname": "ip-172-31-18-193", 1206 | 1207 | "ansible_eth0": { 1208 | "active": true, 1209 | "device": "eth0", 1210 | "hw_timestamp_filters": [], 1211 | "ipv4": { 1212 | "address": "172.31.18.193", 1213 | "broadcast": "172.31.31.255", 1214 | "netmask": "255.255.240.0", 1215 | "network": "172.31.16.0" 1216 | }, 1217 | 1218 | 1219 | 这些变量都是能直接用的!!! 某些变量还是非常有用的. 1220 | 上面的变量分两种! 一种简单的. 只有一行, 1221 | 一种复杂的, 比如 IPv4 这个变量 里面有好几个值. 1222 | 1223 | 简单变量直接用 比如: {{ansible_hostname}} 1224 | 1225 | 如果我想获取 ip 地址怎么办呢, 加个[] 就行! 或者用.号(推荐) 1226 | {{ ansible_eth0.ipv4.address }} 1227 | {{ ansible_eth0["ipv4"]["address"] }} 1228 | 1229 | 1230 | 1231 | 🔶 命令行传递变量. 1232 | 1233 | playbook 允许用户在执行的时候传入变量值. 1234 | 当然 变量的定义还是要在 playbook 里定义的. 1235 | 比例 1236 | 1237 | 在release.yml文件里,hosts和user都定义为变量, 1238 | 脚本里面先不指定变量值! 我们从命令行传递变量值。 1239 | --- 1240 | 1241 | - hosts: '{{ hosts }}' 1242 | remote_user: '{{ user }}' 1243 | 1244 | tasks: 1245 | - ... 1246 | 1247 | 然后你就可以这样传入值了 也就是用 --extra-vars 额外变量! 1248 | 1249 | ansible-playbook e33_var_in_command.yml --extra-vars "hosts=web user=root" 1250 | 1251 | 1252 | 🔶 1253 | 1254 | 1255 | 1256 | 🔶 1257 | 1258 | 1259 | 1260 | 1261 | 🔶 1262 | 1263 | 1264 | 1265 | 🔵 模块分类 1266 | 1267 | Core Module 和 Extra module 1268 | 1269 | 核心模块 不需要下载. 经过严格测试,直接能用的! 1270 | 额外模块 需要下载并配置, 有可能有BUG. 1271 | 1272 | 1273 | 1274 | 🔵 Playbook 脚本指南 1275 | 1276 | 1. 尽量用include 和 role 避免重复的代码 1277 | 2. 尽量把大的文件分成小的文件. 1278 | 1279 | 一个 playbook 由一个或多个 paly 组成! 1280 | 每个play 定义了一系列的 task, 1281 | 其中每个 task 一般就是调用一个 ansible 模块. 1282 | 1283 | 例子:只带有一个play的playbook文件test.yml: 1284 | 1285 | 1286 | --- #任何playbook文件(其实就是yaml文件)都要以这个开头 1287 | - hosts: webservers #对webservers主机组下的所有主机进行操作 1288 | vars: #为该play定义两个变量 1289 | http_port: 80 1290 | max_clients: 200 1291 | remote_user: sapser #连接到远程主机的用户 1292 | sudo: yes #以sudo模式运行该play 1293 | sudo_user: root #sudo到哪个用户,默认为root,如果sudo到该用户需要密码,则在执行ansible-playbook的时候指定-K选项来输入sudo密码 1294 | tasks: #开始定义task 1295 | - name: ensure apache is at the latest version #这既是每个task的说明也是每个task的名字 1296 | yum: pkg=httpd state=latest 1297 | tags: #给该task打一个标签 1298 | - last_http 1299 | - name: write the apache config file 1300 | template: src=/srv/httpd.j2 dest=/etc/httpd.conf 1301 | notify: #提供watch功能,这里当apache配置文件改变时,就调用handlers中名为"restart apache"的task来重启apache 1302 | - restart apache 1303 | - name: ensure apache is running 1304 | service: name=httpd state=started 1305 | handlers: #notify通知这里的task执行,谨记:定义在handlers下的task只有在notify触发的时候才会执行 1306 | - name: restart apache 1307 | service: name=httpd state=restarted 1308 | 1309 | 1310 | 执行该playbook文件: 1311 | 1312 | $ ansible-playbook test.yml 1313 | 1314 | 1315 | 1316 | 1317 | 1318 | 1319 | 1320 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 1321 | 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 Ansible 进阶 🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵🔵 1322 | ⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️------⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️⬛️ 1323 | 1324 | 🔵 Playbook 1325 | 1326 | 其实这个是 状态管理组件! 1327 | 目的是让你用一种更简单的语言 (而不是脚本!) 来描述你的服务应该是怎样的. 1328 | 但是 Playbook 不是万能的! 因为 playbook 底层使用各种模块来帮你完成任务. 1329 | 虽然现在模块非常多, 但是偶尔还是要写 shell 脚本的. 1330 | 1331 | 1332 | 🔶 基本概念 1333 | 1334 | ⦿ yaml: 一种文本格式, 你只要知道是用 缩进来表示层级就可以了!!! 1335 | 1336 | ⦿ task: 一个任务!一般用一次模块 就是一个任务 1337 | 1338 | ⦿ play: 一组任务! 从上到下 按顺序执行!!!! 1339 | 1340 | ⦿ host: 这个playbook 的应用范围. 1341 | 1342 | ⦿ user: 用什么用户运行 playbook 1343 | 1344 | ⦿ role: 角色,一组 playbook, 以及和其配合的元素(vars,files等) 的集合 1345 | 1346 | ⦿ hadnler: 1347 | task 可以触发一定的事件(比如重启服务), 处理该事件的task就是 handler 1348 | 就像我要用ansible 脚本 自动搭建一个 Nginx, 脚本里很多task 都需要重启Nginx. 1349 | 这些 task 都会触发重启Nginx事件,但是其实整个脚本只要重启一次就可以了! 1350 | 这时候就可以把 重启Nginx 写到 Handler 里面去! 1351 | 如果有task 触发了 这个重启事件, 不管你触发多少次, 最早只重启一次! 1352 | 1353 | 1354 | 🔵 Roles 1355 | 1356 | Role 是非常重要的一个概念! 主要是为了提高代码复用. 1357 | 很多时候你只要在自己的 playbook 里引用下别人的 role 即可. 1358 | 大家写的 role 可以相互共享. 1359 | 1360 | 1361 | 1362 | 1363 | 1364 | 1365 | 1366 | 🔵 facts ✔︎ 1367 | 1368 | 默认每次执行 Playbook 前都会自动获取节点设备信息! 比如IP/主机名. 1369 | 查看facts: ansible hostname -m setup 1370 | 所有这些获取到的信息都可以直接作为变量 应用到 playbook 中. 1371 | 这些信息在你用模板的时候比较有用, 1372 | 如果你用不到这些数据, 关闭这个功能, 能非常明显的加快脚本执行速度. 1373 | 关闭获取 facts 很简单,只需要在 playbook 文件中加上“gather_facts: no”即可. 1374 | 1375 | --- 1376 | - hosts: 172.16.64.240 1377 | gather_facts: no 1378 | 1379 | 1380 | 1381 | 1382 | 1383 | 🔵 register ?? 1384 | 1385 | 把任务的输出 保存到某个变量中, 然后用于其他任务. 1386 | 这功能对自定义脚本的非常有用! 脚本执行完后肯定有输出来的. 1387 | 至于 register 的具体值是什么, 要看task的. 1388 | 如果task 是shell. 那么会包含stdout、stderr 还有个 stat 1389 | 要输出 register的值.. 得用 debug... 1390 | 1391 | 🔶 例1 1392 | 1393 | tasks: 1394 | 1395 | - name: echo date 1396 | command: date 1397 | register: date_output 1398 | 1399 | - name: show results? 1400 | debug: msg="{{date_output.stdout}}" 1401 | 1402 | 然后执行 yml 脚本的时候 就会显示一个 1403 | TASK [show results?] *********************************************************** 1404 | ok: [104.224.139.45] => { 1405 | "msg": "Wed Nov 1 19:08:38 CST 2017" 1406 | } 1407 | 1408 | 🔶 例2 1409 | 1410 | - command: "echo {{item}}" 1411 | register: result 1412 | with_items: [1, 2] 1413 | - debug: 1414 | var: result 1415 | 1416 | 这样应该能显示 result 这个值的详细信息! 1417 | 1418 | 1419 | 1420 | 1421 | 1422 | 1423 | 1424 | 1425 | 1426 | 🔵 Debug 1427 | 1428 | 1429 | 1430 | 1431 | 🔵 命令行变量 1432 | 1433 | 在执行命令的时候传入参数值, 是非常必须的...比如数据库的密码. 1434 | 你总不能把密码写在配置文件中吧.... 1435 | 1436 | 🔶 定义变量 1437 | 1438 | - hosts: '{{ hosts }}' 1439 | remote_user: '{{ user }}' 1440 | ... 1441 | 1442 | 🔶 使用变量 1443 | 1444 | ansible-playbook command.yml --extra-vars "hosts=web user=root" 1445 | 1446 | 1447 | 1448 | 1449 | 🔵 条件控制 1450 | 1451 | 可用于task,role和include,在满足条件时task才会被执行。 1452 | 至于when指令后跟的逻辑表达式也是标准的逻辑表达式,示例如下: 1453 | 1454 | tasks: 1455 | - shell: echo "only on Red Hat 6, derivatives, and later" 1456 | when: ansible_os_family == "RedHat" and ansible_lsb.major_release|int >= 6 1457 | - shell: echo "This certainly is epic!" 1458 | when: epic is defined 1459 | 1460 | 1461 | 🔵 循环 1462 | 1463 | 🔶 标准遍历 with_items 1464 | 1465 | 用with_items可以遍历一个列表,注意这里只会遍历一层。示例如下: 1466 | 1467 | - name: add several users 1468 | user: name={{ item }} state=present groups=wheel 1469 | with_items: 1470 | - testuser1 1471 | - testuser2 1472 | 1473 | 1474 | 1475 | 🔶 嵌套遍历 with_nested 1476 | 1477 | 用with_nested可以遍历一个列表,注意这里会遍历多层,直到最内层... 1478 | 1479 | 1480 | 🔶 配合register循环列表 ?? 1481 | 1482 | register注册一个变量后,可以配合with_items来遍历变量结果。 1483 | 1484 | 示例如下: 1485 | 1486 | - shell: echo "{{ item }}" 1487 | with_items: 1488 | - one 1489 | - two 1490 | register: echo 1491 | - name: Fail if return code is not 0 1492 | fail: 1493 | msg: "The command ({{ item.cmd }}) did not have a 0 return code" 1494 | when: item.rc != 0 1495 | with_items: echo.results 1496 | --------------------------------------------------------------------------------