用Ansible部署服务器续篇
说明
主要是不想让上一篇太长了,把一些相对次要的东西放在这篇里补充一下,其实有了上一篇的基础,大部分内容都可以通过官方文档查到。
模板
在上篇里说到,安装系统时更新软件源有个问题就是软件源配置文件如果写死的,就只能用于指定版本的系统,如果需要灵活配置就需要使用模板。
这里是一个例子。
把原来的files/sources.list
改为templates/sources.list.j2
,内容如下:
{% if ansible_distribution == 'Debian' %}
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} main contrib non-free
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }}-updates main contrib non-free
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }}-backports main contrib non-free
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }}-security {{ ansible_distribution_release }}/updates main contrib non-free
deb-src http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} main contrib non-free
deb-src http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }}-updates main contrib non-free
deb-src http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }}-backports main contrib non-free
deb-src http://{{ source_mirror }}/{{ ansible_distribution | lower }}-security {{ ansible_distribution_release }}/updates main contrib non-free
{% else %}
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }} main restricted universe multiverse
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }}-updates main restricted universe multivers
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }}-backports main restricted universe multiverse
deb http://{{ source_mirror }}/{{ ansible_distribution | lower }} {{ ansible_distribution_release }}-security main restricted universe multiverse
{% endif %}
其中ansible_
开头的是一些系统变量,ansible初始化时取值。这在docker角色定义里说过了,只是那个是用于tasks里,这里用在模板文件里,因为都是用Jinja2引擎,所以用法是一样的。
其中还有一个地方是if语句,这也是Jinja2的语法,因为Debian和Ubuntu的源链接格式不太一样。
source_mirror
则是一个自定义的变量,可以放在group_vars/all
里,也可以放在inventory/hosts
里,除了这两个还有很多地方可以放,其中一个地方是roles/debian/defaults/main.yml
,这里可以放角色变量的默认值:
source_mirror: 'mirrors.163.com'
现在需要把tasks里的步骤改一下:
- name: copy sources.list
template:
src: sources.list.j2
dest: /etc/apt/sources.list
owner: root
group: root
mode: '0644'
修改的地方就两个:一个是把copy改成template,一个是把源文件改成带j2的。
条件检测
如果我们需要在更新源之前备份一下,并且防止备份被重复覆盖,就需要先检测一下文件是否存在,可以这样操作:
- name: Check sources.list.orig
stat: path=/etc/apt/sources.list.orig
register: stat_sources_orig
- name: Backup sources.list
command: mv /etc/apt/sources.list /etc/apt/sources.list.orig
when: not stat_sources_orig.stat.exists
- name: Copy sources.list
template:
src: sources.list.j2
dest: /etc/apt/sources.list
owner: root
group: root
mode: '0644'
先注册一个检测器,然后在备份操作中检查一下检测结果,如果检测结果为false则跳过本操作。
包管理器
之前的例子都是以debian/ubuntu为例的,用的都是apt包管理器,如果要用CentOS的yum或Alpine的apk之类呢?
Ansible有通用方法,比如安装一个Nginx:
- name: install nginx
action: >
{{ ansible_pkg_mgr }} pkg=nginx state=latest update_cache=no install_recommends=no
使用非root用户连接
假设现在是用非root用户(比如raptor)连接到服务器,需要sudo才能操作。那么可以在tasks/main.yml
在每个操作中指定:
- name: xxx
become: yes
become_method: sudo
xxxx:
...
但这样很麻烦,因为每个操作都要加。简单的办法就是使用全局变量,比如在inventory/hosts
的[myserver:vars]
里加上:
ansible_become: yes
ansible_become_method: sudo
如果sudo需要密码,则需要在运行ansbile_playbook
时加上--ask-become-pass
。
如果某些操作需要使用当前登录用户,则在相应的操作里加上:
- name: xxx
become: no
xxxx:
...
或者以root用户登录时,需要切换到别的用户上操作,则同样可以用:
- name: xxx
become: yes
become_user: raptor
xxxx:
...
循环
比如设置语言的时候,如果我们要设置多种语言,当然可以写两个同样的操作,但这样效率就低了,因为有可能类似的操作很多——比如修改多个系统参数之类。
所以这时可以用循环:
- name: Ensure locales exists
locale_gen:
name: "{{ item.name }}"
state: present
with_items:
- { name: 'en_US.UTF-8' }
- { name: 'zh_CN.UTF-8' }
表示同时设置两种语言。注意:要使用双引号
文件修改
比如修改SSH的设置,编辑/etc/ssh/sshd_config
:
- name: Update sshd config
lineinfile:
path: /etc/ssh/sshd_config
regexp: "{{ item.regexp }}"
line: "{{ item.line }}"
insertbefore: "{{ item.insertbefore }}"
with_items:
- { regexp: '^PermitRootLogin', line: 'PermitRootLogin no', insertbefore: '#PermitRootLogin' }
- { regexp: '^PasswordAuthentication', line: 'PasswordAuthentication no', insertbefore: '#PasswordAuthentication' }
这里将修改PermitRootLogin
禁止root用户登录,修改PasswordAuthentication
关闭密码登录(只能使用证书登录)。注意,这里的循环使用了三个变量:regexp, line, insertbefore。
修改的原理就是:找到匹配regexp的行,替换为line的内容,如果没找到,就插入在insertbefore的前面,如果insertbefore的内容不存在,则插在文件的末尾。
重启服务(handlers)
正如我们所知,修改过配置文件必须重启服务才能生效,当然这个可以通过一个command操作进行,但更好的办法是用异步通知,在所有任务执行完后统一重启。
方法是在角色下创建handlers/main.yml
:
---
- name: Restart sshd
service:
name: sshd
state: restarted
然后在需要重启地方加上:
- name: Update sshd config
lineinfile:
...
notify:
Restart sshd
即可。
推送到[go4pro.org]