企业应用场景
Dev开发环境
测试环境
测试环境往往有多套,测试环境满足测试功能即可,不宜过多
测试人员希望测试环境有多套,公司的产品多产品线并发,即多个版本,意味着多个版本同步测试
预发布环境
功能:使用和生产环境一样的数据库,缓存服务等配置,测试是否正常
发布环境
通常是代码发布机或者堡垒机 使用者:运维 功能:发布代码至生产环境 管理者:运维(有经验) 发布机:往往需要有2台(主备)
生产环境
使用者:运维,少数情况开放权限给核心开发人员,极少数公司将权限完全 开放给开发人员并其维护 功能:对用户提供公司产品的服务
灰度环境
是生产环境的一部分 使用者:运维 功能:在全量发布代码前将代码的功能面向少量精准用户发布的环境,可基于主机或用户执行灰度发布 案例:共100台生产服务器,先发布其中的10台服务器,这10台服务器就是灰度服务器 管理者:运维
往往该版本功能变更较大,为保险起见特意先让一部分用户优化体验该功能,待这部分用户使用没有重大问题的时候,再全量发布至所有服务器
自动化运维的场景
Ansible 特性
Paramiko(python对ssh的实现),PyYAML,Jinja2(模板语言)三个关键模块
部署简单,基于python和SSH(默认已安装),agentless
幂等性:一个任务执行1遍和执行n遍效果一样,不因重复执行带来意外情况
Ansible 架构以及原理
Ansible主控端作为ssh客户端连接其他机器的ssh server,然后控制其他服务器完成一些操作。
安装Ansible
rpm
apt
sudo apt update
sudo apt install ansible
mac brew
编译安装
yum -y install python-jinja2 PyYAML python-paramiko python-babel
python-crypto
tar xf ansible-1.5.4.tar.gz
cd ansible-1.5.4
python setup.py build
python setup.py install
mkdir /etc/ansible
cp -r examples/* /etc/ansible
Git clone 编译安装
git clone git://github.com/ansible/ansible.git --recursive
cd ./ansible
source ./hacking/env-setup
Pip安装
yum install python-pip python-devel
yum install gcc glibc-devel zibl-devel rpm-bulid openssl-devel
pip install --upgrade pip
pip install ansible --upgrade
确认安装成功
相关的主要配置
安装完毕,涉及的相关文件:
配置文件
/etc/ansible/ansible.cfg 主配置文件,配置ansible工作特性(一般无需修改)
/etc/ansible/hosts 主机清单(将被管理的主机放到此文件)
/etc/ansible/roles/ 存放角色的目录
程序
/usr/bin/ansible 主程序,临时命令执行工具
/usr/bin/ansible-doc 查看配置文档,模块功能查看工具
/usr/bin/ansible-galaxy 下载/上传优秀代码或Roles模块的官网平台
/usr/bin/ansible-playbook 定制自动化任务,编排剧本工具
/usr/bin/ansible-pull 远程执行命令的工具
/usr/bin/ansible-vault 文件加密工具
/usr/bin/ansible-console 基于Console界面与用户交互的执行工具
ansible.cfg 配置文件
[defaults]
#inventory = /etc/ansible/hosts # 主清单配置文件的位置
#library = /usr/share/my_modules/ # python库文件存放目录
#local_tmp = $HOME/.ansible/tmp # 当执行一条ansible命令,会先在本地生成python脚本,存放到这个路径下
#remote_tmp = $HOME/.ansible/tmp # ansible会将上面存放的临时脚本推送到远程主机的该目录下,并执行
#forks = 5 # 默认并发数,同时可以执行5次
#sudo_user = root # 指定可使用的sudo的用户
#ask_sudo_pass = True # 每次执行ansible命令是否询问ssh密码
#ask_pass = True # 每次执行ansible命令是否询问ssh口令
#remote_port = 22 # 远程主机的端口号(默认22)
#下面的配置建议打开
host_key_checking = False # 检查对应服务器的host_key,如果在.ssh目录下没有对应的 host_key 将会弹出是否连接的确认,当机器过多的时候,该配置建议取消,否则要敲很多yes
deprecation_warnings = False # 光比deprecation过时警告
log_path=/var/log/ansible.log # 日志文件
module_name = command # 默认模块,ansible命令在执行动作时,需要使用-m参数指定模块,这个配置默认为命令模块,可以不使用 -m command 直接使用ansible执行shell命令
主机清单 inventory.ini
ansible的主要功用在于批量主机操作,为了便捷地使用其中的部分主机,可以在inventory file中将其分组命名
默认的inventory file为 /etc/ansible/hosts
inventory file可以有多个,且也可以通过Dynamic Inventory来动态生成
/etc/ansible/hosts
的格式:
# ip:port 远程用户名称 关闭known_host提示
[k8smaster]
10.211.55.100:22 ansible_ssh_user=root
[k8snode]
10.211.55.100 ansible_ssh_user=root
10.211.55.101 ansible_ssh_user=root
10.211.55.102 ansible_ssh_user=root
如果机器ip连续,可以使用如下方式批量加入:
[k8smaster]
10.211.55.100
[k8snode]
10.211.55.[100:102]
相关命令
ansible-doc
适用于查看ansible文档的工具。
# 列出所有的ansible模块
ansible-doc -l
# 查看模块数量,目前有3387个模块
ansible-doc -l | wc -l
# 查询ping名称的模块
ansible-doc -l | grep ping
# 查询ping模块的详细文档
ansible-doc ping
# 查询ping模块的简略文档
ansible-doc -s ping
ansible
ansible <host-pattern> [-m module_name] [-a args]
# host-pattern 主机选择,可以选择所有或者选择某个组
# 常用的,主要的几个选项
# -m 模块名,可以使用ansible-doc -l
# -a 模块的参数,如果模块没有参数,可选
# -v 查看执行过程
# -vv 查看更详细的执行过程
# -vvv 更更详细
其它选项参数:
--version # 显示版本
--list-hosts # 显示主机清单列表
-k --ask-pass # 提示输入ssh连接密码,默认key验证
-C --check # 检查,并不执行
-T --timeout=TIMEOUT # 执行命令超时时间,默认10s
-u --user=REMOTE_USER # 执行远程执行的用户
-b --become # 代替旧版的sudo切换
--become-user=USERNAME # 指定sudo的runas用户,默认为root
-K --ask-become-pass # 提示输入sudo的口令
建议使用基于sshkey的验证
示例:
# 对主机清单中的所有主机执行ping命令
ansible all -m ping
ansible 的 hostpattern 支持多种复杂的形式:
# 匹配所有
ansible all --list
# 通配符匹配(使用通配符需要使用双引号包裹)
ansible "*" -m ping
ansible "10.211.55.*" -m ping
# 匹配master组
ansible k8smaster --list
# 属于组k8snoder的第1台机器
ansible k8snode[0] -m ping
# 属于组k8snode的第1到4台机器
ansible webserver[0:5] -m ping
# 逻辑或(master组或者node组)
ansible "k8smaster:k8snode" --list
# 逻辑与(在master组并且在node组)
ansible "k8smaster:&k8snode" --list
# 逻辑非(在k8s-node组,但是不在k8s-master组中)
ansible 'k8snode:!k8smaster' --list
# 正则,master或者node组
ansible "~(k8smaster|k8snode)" --list
ansible-galaxy
ansible galaxy 工具类似于operationhub.io或者hub.docker.com,是一个存储了很多playbook的网站,可以从galaxy中查询需要的playbook并下载使用。注意,一般我们不直接使用上面的东西,而是自己检查修改后使用。
# 列出所哟已经安装的galaxy
ansible-galaxy list
# 安装galaxy
ansible-galaxy install geerlingguy.redis
# 删除galaxy
ansible-galaxy remove geerlingguy.redis
ansible-pull
ansible默认的工作模式为push模式,也就是说不要在远程主机做任何操作只需要在控制机编排playbook,push 到远程主机即可完成任务。而另一个工作模式就是 ansible pull模式:
每台被控端需要安装Ansible 和git(svn)
所有的配置及playbooks 都存放在git 仓库
被控端的ansible-pull 计划任务会定期检查给定的git 的tag 或者分支
ansible-pull 执行特定的playbooks 即local.yml 或者hostname.yml
每次更改playbooks 只需要提交到git 即可
pull模式适合:
被控节点较多,控制机资源有限无法满足高线程和低时间的运行效率
pull模式的缺点:
pull模式的优点:
不需要中央管理服务器(取决于repository的类型)
分散存储库是可能的。(再次:取决于repository的类型)
连接可以由节点启动(如果不允许您更改防火墙策略,则可能很重要)
增加并行度节点可用时可以pull(在基于push的模型中,如果节点不可用,则无法对其进行配置)
使用ansible pull:
git clone git@xxx:root/pull-test.git
cd pull-test/
vim main.yml
git add main.yml
git commit -m "show route info"
git push -u origin master
# main.yml就是脚本
使用 ansible-pull 拉取配置并应用:
*/5 * * * * ansible-pull -C master -d /root/test -i /opt/ansible-pull-test/hosts -U <github仓库> -e "role=db" shenchan.yml -o
ansible-playbook
用于执行编写好的playbook任务,playbook实际上就是批量脚本【重点】。
编写hello.yml
playbook:
- hosts: k8smaster
remote_user: root
tasks:
- name: hello world
command: /usr/bin/wall hello world
使用ansible-playbook执行脚本:
~/temp ansible-playbook hello.yml
PLAY [k8smaster] ************************************************
TASK [Gathering Facts] ******************************************
ok: [10.211.55.100]
TASK [hello world] **********************************************
changed: [10.211.55.100]
PLAY RECAP ******************************************************
10.211.55.100 : ok=2 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0
ansible-vault
因为playbook脚本中可能存在敏感信息,就提供ansible-vault加密解密yml文件(让我想起了k8s的secret)。
ansible-vault [create|decrypt|edit|encrypt|rekey|view]
范例:
# 加密playbook,会提示输入秘钥,然后yml文件内容就会被加密
ansible-vault encrypt hello.yml
# 查看playbook,会提示输入秘钥,然后yml文件就会被临时解密输出到终端上
ansible-vault view hello.yml
# 解密playbook,会提示输入秘钥,然后yml文件就会被解密
ansible-vault decrypt hello.yml
# 创建一个新的加密的yml
ansible-vault create new.yml
# 编辑加密的playbook
ansible-vault edit new.yml
# 修改口令秘钥
ansible-vault rekey new.yml
ansible-console
ansible交互执行命令的工具,是2.0新增的功能。
可以通过该命令行进入交互命令行,并提示如下的命令行提示符:
执行用户@当前操作主机组(组中包含的主机数量)[f:并发数]$
示例:
yangsx@all (3)[f:5]$
并通过:
等一系列命令管理ansible。
Ansible执行过程
加载自己的配置文件,默认为/etc/ansible/ansible.cfg
通过ansible将模块或命令生成对应的临时py文件,并将该文件传输到远程服务器的对应执行用户的$HOME/.ansible/tmp/ansible-tmp-数字/xxx.py
文件
执行状态:
Ansible常用模块
Command
ansible all -m command -a '要执行的命令列表'
# 因为command是默认模块,所以-m可以省略
# -a 是ansible用于指定模块参数的选项
ansible all -a '要执行的命令列表'
# 比如,查看所有的主机的磁盘利用率
ansible all -a 'df -h'
# command在某些场景下,命令无法正确执行,比如
ansible all -a 'echo $HOSTNAME'
# 故提供Shell模块
Shell
# 打印远程主机名称
ansible all -m shell -a 'echo $HOSTNAME'
# 更改远程口令
ansible all -m shell -a 'echo root|passwd --stdin root123'
Script
用于在其他主机上运行脚本,他会先将脚本推送,再执行:
ansible all -m script -a test.sh
Copy
向其他主机发送文件:
# 向其他主机发送selinux配置,并且备份原有配置文件
# src代表当前主机的文件位置,dest代表拷贝到远程主机的文件位置,backup代表备份
ansible all -m copy -a 'src=/root/ansible/selinux dest=/etc/selinux/config backup=yes'
# 复制指定文件的权限与所属
ansible all -m copy -a 'src=/etc/shadow dest=/data/ mode=000 owner=root'
# 生成f2文件,内容手动指定
ansible all -m copy -a 'content="hell\nworld" dest=/data/a.txt'
Fetch
与copy相反,用于拉取远程主机的文件到本机,只能抓取文件,不可以抓取目录:
# 抓取被控端的日志文件到本机
ansible all -m fetch -a "path=/var/log/messages dest=/data"
# 如果要抓取多个文件,或者路径,需要先打包再抓取
ansible all -m shell -a 'tar Jcf /root/log.tar.xz /var/log/*.log'
ansible all -m fetch -a 'src=/root/log.tar.xz dest=/data/'
File
用于操作文件的模块,包含设置文件相关属性,创建目录文件链接,删除等:
# 创建文件
ansible all -m file -a 'name=/data/f3 state=touch'
# 创建文件夹
ansible all -m file -a 'name=/data/mydir state=directory'
# 删除文件、文件夹
ansible all -m file -a 'name=/data/f3 state=absent'
# 创建软链接
ansible all -m file -a 'src=/etc/fstab dest=/data/fstab.link state=link'
Hostname
主机名管理:
# 一改就统一改,永久且立即生效
ansible 192.168.30.101 -m hostname -a 'name=server1'
Cron
计划任务,支持的时间有: minute, hour, day, month, weekday
# 创建时钟同步任务 每五分钟同步一次
ansible all -m cron -a "minute=*5 job='/usr/sbin/update 172.16.0.1 &> /dev/null' name=Synctime"
# 每周一周三周五,每分钟执行FBI Warning
ansible all -m cron -a 'minute=* weekday=1,3,5 job="/usr/bin/wall FBI warning" name=Warning'
# 可以通过 crontab -e查看生成的定时任务
# 禁用定时任务(注意,job和name必须写,否则关闭的可能不是一个定时任务)
ansible all -m cron -a 'disable=true job="/usr/bin/wall FBI warning" name=Warning'
# 重新启用定时任务
ansible all -m cron -a 'disable=false job="/usr/bin/wall FBI warning" name=Warning'
# 删除定时任务
ansible all -m cron -a 'job="/usr/bin/wall FBI warning" name=Warning state=absent'
Yum
yum包管理:
# 安装httpd
ansible all -m yum -a 'name=httpd state=present'
# 安装httpd最新版
ansible all -m yum -a 'name=httpd state=lasted'
# 安装多个包
ansible all -m yum -a 'name=httpd,memcached state=lasted'
# 删除httpd
ansible all -m yum -a 'name=httpd state=absent'
# 查看已安装的包
ansible all -m yum -a 'name=httpd list=installed'
Service
管理服务。
# 启动、并开启激动 vsftpd,支持的状态还有 restarted、stopped、reloaded
ansible websrvs -m service -a 'name=vsftpd state=started enable=yes'
User
管理用户。
# 设置nginx服务账号
ansible nginxs -m user -a 'name=nginx shell=/sbin/nologin system=yes home=/var/nginx groups=root,bin uid=80 comment="Nginx Server"'
# 删除账号
ansible nginxs -m user -a 'name=nginx state=absent'
Group
管理组。
# 设置nginx组
ansible ngins -m group -a 'name=nginx system=yes gid=80'
PlayBook
剧本,由yaml编写,制定了ansible的任务。
创建playbook yaml文件:
# 一个playbook包含多个play
- hosts: all
remote_user: root
# 一个play包含多个task,一个task对应一个action
tasks:
- name: show me the name
ansible.builtin.command: hostname
- name: say hello
ansible.builtin.shell:
cmd: echo hello
- name: other
# action 等同于上面的写法
action: shell echo hello2
使用ansible-playbook执行剧本:
ansible-playbook hello.yaml
Playbook是由一个或者多个play组成的列表。一个play主要将事先定义好的一组主机装扮成事先通过ansible的task定义好的角色。从根本上来说,一个task就是调用一个ansible的module,一个paly包含多个task。Playbook将多个Play组织在一起,完成一个复杂的的编排。
如果playbook中某个action返回码不为0,也就是出错状态,如果想要忽略错误继续执行action,共有两种方式:
tasks:
- name: test
shell: /usr/bin/somecommand || /bin/true
# 短路或,如果前面失败,继续执行后面
或者(推荐):
tasks:
- name: test
shell: /usr/bin/somecommand
ignore_errors: True
ansible-playbook的其他属性:
--check
只检测可能发生的改变,但是不会真正执行
--limit
只针对某个主机执行,比如--limit 192.168.23.13
Handler和Notify
Handler用于监控task中的某个action,如果达到一定的条件,将会使用Notify出发指定的Handler。
# copy action如果发现文件发生变更,将会触发重启
- hosts: all
remote_user: root
tasks:
- name: install httpd package
ansible.builtin.yum:
name:
- httpd
- name: copy conf file
ansible.builtin.copy:
src: /data/httpd/httpd.conf
dest: /etc/httpd/conf/
backup: true
notify: restart service
tag: update
handlers:
- name: restart service
service:
name: httpd
state: restarted
Tags
上述yaml有一个tags标签,该tags用于标记一个动作。被标记的动作可以在命令行单独执行:
ansible-playbook xxx.yaml -t update
使用变量
变量名,只能有数字、字母、下划线组成,且必须以字母开头
变量来源有:
远程主机信息,ansible setup facts
,可以使用filter参数过滤变量名称查看
# 查询所有主机的所有变量
ansible all -m setup
# 查询所有主机的ip地址(支持通配符)
ansible all -m setup -a 'filter="ansible_default_ipv4"'
在/etc/ansible/hosts
中定义
普通变量:主机组中主机单独定义,优先级高于公共变量
[k8smaster]
10.211.55.100:22 ansible_ssh_user=root varname=value
公共(组)变量:针对主机组中所有主机定义统一变量
# k8smaster的统一变量
[k8smaster:vars]
nodename=www
dominname=com
通过命令行制定变量,优先级最高
ansible-playbook -e varname=value
在playbook中定义
vars:
- var1: value1
- var2: value2
在独立的变量yaml文件中定义
# 定义vars.yml变量文件
var1: xxx1
var2: xxx2
# 应用变量文件,读取变量
- hosts: web
remote_user: root
vars_files:
- vars.yml
....
使用变变量:
- hosts: appsrvs
remote_user: root
tasks:
- name: install package
yum: name={{ packagename }}
Template
配置文件通常不能直接copy,因为不同主机中,某些配置可能不同,这个时候可以使用模板来解决。Ansible的模板基于python的Jinja2模版语言。
定义模板文件,需要以 .j2
作为后缀,定义nginx.conf.j2
: