准备好安装了Ansible的主机,做为实验环境。
有一台新安装的Centos7系统,利用ansible在主机上完成如下操做:html
准备好一台安装了Centos7系统的主机,而后去ansible的主机上对目标主机进行操做。
我这里的ansible也是新安装的,因此若是遇到一些没有的工具,也会在遇到的时候一步一步进行添加。下面是汇总的内容。python
对于一台新装好的ansible,仍是会缺乏不少依赖项,有些和特定模块关联的比较紧密,能够在使用特定模块的时候再安装。
还有一些使用范围比较广,建议先装好:linux
修改ansible.cfg配置文件
个人实验环境,为了测试方便,暂时只有下面3项作了设置:git
[defaults] #host_key_checking = False inventory = ~/hosts vault_password_file = ~/vault_password_file
配置文件第一行的[defaults]不能省。github
编辑 /etc/ansible/hosts 添加主机信息:docker
host1 ansible_host=192.168.24.172
个人实验环境是直接放到了家目录里了shell
先用ping模块测试一下连通性:json
[root@Ansible ~]# ansible host1 -m ping -k SSH password: host1 | SUCCESS => { "ansible_facts": { "discovered_interpreter_python": "/usr/bin/python" }, "changed": false, "ping": "pong" } [root@Ansible ~]#
这里使用了-k参数,手动输入密码。
测试联通性,能够再加上-c参数,指定local。不过这里要验证一下ssh链接。centos
安装 sshpass
若是是第一次使用,可能会提示须要安装sshpass。这个简单,yum安装便可:安全
$ yum install sshpass
添加密码信息
最好的作法是用SSHKey实现免密码登陆。这里讲使用密码的状况。
为了方便,也能够把密码加到配置中,这样不用每次都输入密码:
host2 ansible_host=192.168.24.172 ansible_ssh_pass=123456
这样作,密码就是明码存放了,很不安全。下面有更安全的作法。
使用 ansible-vault 来加密敏感信息
修改配置文件
这步不是必须的,运行命令的时候能够加上参数 --vault_password_file 来指定你的密码文件。不过经过设置就能够把这个参数省了:
$ vi /etc/ansible/ansible.cfg # If set, configures the path to the Vault password file as an alternative to # specifying --vault-password-file on the command line. vault_password_file = ~/vault_password_file
使用openssl来生成随机密码
使用 openssl 来生成随机的base64编码的内容:
$ openssl rand -base64 128 -out vault_password_file $ chmod a-w vault_password_file $ chattr +i vault_password_file
文件生成后,对文件作了一些保护,防止文件被修改。修改文件的ugo权限只对普通用户有效,root依然能够修改文件。后面的命令能够锁定文件,即便root也没法修改了,防止对文件的意外操做。
若是须要修改或者删除文件,能够先把文件解锁,只要把命令的 +i 改为 -i 就能够了:
$ chattr -i vault_password_file
生成加密后的字符串
下面是使用 ansible-vault 来生成加密后的字符串:
[root@Ansible ~]# ansible-vault encrypt_string "123456" --name ansible_ssh_pass ansible_ssh_pass: !vault | $ANSIBLE_VAULT;1.1;AES256 33336539373437373161326537323836343163633532396235383334326562303134626565613537 3134313631393931376361363761313165393966613831360a343338353765326331663433613533 31636238613133363639336130613264386366363931663230333663363062333836323730383563 6562626265393535310a623732633863633765363066636265303265316661373464323961666131 6561 Encryption successful [root@Ansible ~]#
接下来须要把这里得到的信息复制到配置文件中。
修改主机配置文件
这里对配置文件进行了大修改,原来是INI格式的,如今改为了YAML格式:
--- all: hosts: host1: ansible_host: 192.168.24.172 ansible_ssh_pass: !vault | $ANSIBLE_VAULT;1.1;AES256 33336539373437373161326537323836343163633532396235383334326562303134626565613537 3134313631393931376361363761313165393966613831360a343338353765326331663433613533 31636238613133363639336130613264386366363931663230333663363062333836323730383563 6562626265393535310a623732633863633765363066636265303265316661373464323961666131 6561 ...
要使用YAML是由于INI格式不支持内嵌vault,官方的说明以下:
This is an example using an extract from a YAML inventory, as the INI format does not support inline vaults:
INI格式的主机配置文件,可读性感受更好。若是依然但愿使用INI格式的配置,能够另外再建立vars文件,把额外的参数以YAML格式写在另外一个文件中。
验证
此次用command模块了进行验证:
$ ansible host1 -a hostname host1 | CHANGED | rc=0 >> Host1 $
至此准备工做都作完了,已经能成功链接到主机。
python多个版本并存是很常见的状况。Centos7系统安装后默认就有一个python2,通常本身要使用python3就会再安装一个,这个就会带来一些问题。
以前遇到的问题,就是ansible使用了目标主机的python3来执行任务,而有模块使用python3会有问题。
以前有问题的主机是将系统的python命令指向了python3。而且去yum相关的命令中修改了开头的#!/usr/bin/python2
来保证yum能够正常运行。
而ansible默认就会去目标主机查找 /usr/bin/python
来执行,这就形成了默认使用python3来执行的状况。
这里就强行将ansible_python_interpreter的值指向目标主机的python3来将问题再现出来。
yum 是用python2写的,因此不支持python3。下面是报错的状况:
[root@Ansible ~]# ansible host1 -m yum -a "name=wget state=present" -e "ansible_python_interpreter=/usr/bin/python3" host1 | FAILED! => { "ansible_facts": { "pkg_mgr": "yum" }, "changed": false, "msg": "The Python 2 bindings for rpm are needed for this module. If you require Python 3 support use the `dnf` Ansible module instead.. The Python 2 yum module is needed for this module. If you require Python 3 support use the `dnf` Ansible module instead." } [root@Ansible ~]#
根据msg的提示。建议使用dnf,可是尝试以后仍是失败了。
简单的办法就是指定 ansible_python_interpreter 参数,使用Python2。
使用yum模块必须指定python2,暂时没别的办法。
在使用 get_utl 模块的时候,就会遇到selinux的问题。这类问题应该只要把selinux关掉应该就解决了(没试过),不过这里看看不关的状况。
[root@Ansible ~]# ansible host1 -m get_url -a 'url="http://mirrors.aliyun.com/repo/epel-7.repo" dest="/etc/yum.repos.d/epel-7.repo"' -e "ansible_python_interpreter=/usr/bin/python3" host1 | FAILED! => { "changed": false, "msg": "Aborting, target uses selinux but python bindings (libselinux-python) aren't installed!" } [root@Ansible ~]#
一个办法仍是使用python2,由于系统默认已经安装好了python2版本的selnux,应该就是下面这个:
[root@PlayHost ~]# yum info libselinux-python 已加载插件:fastestmirror Loading mirror speeds from cached hostfile * base: ftp.sjtu.edu.cn * extras: ftp.sjtu.edu.cn * updates: ftp.sjtu.edu.cn 已安装的软件包 名称 :libselinux-python 架构 :x86_64 版本 :2.5 发布 :14.1.el7 大小 :589 k 源 :installed 来自源:anaconda 简介 : SELinux python bindings for libselinux 网址 :https://github.com/SELinuxProject/selinux/wiki 协议 : Public Domain 描述 : The libselinux-python package contains the python bindings for developing : SELinux applications. [root@PlayHost ~]#
若是使用python2也就没这个问题了。
使用python3也是能够的,只要把这个包装上。在yum里没有找到对应的python3版本,不过pip里有:
[root@PlayHost ~]# pip install selinux Collecting selinux Downloading https://files.pythonhosted.org/packages/59/38/780baac7aafcf44cca8e77318ec935660f93fc30e3de92f8de7a7dbc0513/selinux-0.1.6-py2.py3-none-any.whl Installing collected packages: selinux Successfully installed selinux-0.1.6 [root@PlayHost ~]#
这里的操做是在目标主机上进行的,也能够用ansible远程来操做。不过这里主要是为了讲明白问题。
建议在目标主机上安装python3以后,就顺便把selinux也装上。这样有些python2和python3都兼容的模块使用任何版本都不会有问题
初始的系统是没有pip的,以后我也只会为python3安装pip。而且全部须要pip安装的python模块都是为python3安装的。
因此在安装pip的时候,须要指定 ansible_python_interpreter 参数,使用Python3。这个和yum模块正好相反。
使用pip模块的时候,能够加参数 extra_args: -i https://mirrors.aliyun.com/pypi/simple/
来指定pypi源。
不过为方便起见,也能够直接写在配置文件中指定默认的pypi源。配置文件也用命令能够添加,不用编辑文件。使用的命令以下:
$ pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/
运行命令能够用command模块来实现。
安装pip和更新
安装我是用yum模块来安装python36-pip(使用easy_install模块安装会有问题,我解决不了)。安装完成后,再用pip模块更新pip。
更新了pip以后,再顺便把selinux也装上,就是上一小节的问题。
这里要用本身测试环境的ansible去配置一台主机。完成初始配置后,要安装好python3和docker,而后再建立一个ansible的镜像。最后还有SSH和帐户的安全设置。
主要是设置国内的镜像源,而后使用yum来安装工具:
--- - hosts: host1 vars: ansible_python_interpreter: /usr/bin/python2 # 指定使用python2,防止有坑 tasks: - name: 删除默认的repo文件 file: path: "/etc/yum.repos.d/{{ item }}" state: absent with_items: - CentOS-Base.repo - CentOS-Debuginfo.repo - CentOS-Media.repo - CentOS-Vault.repo - CentOS-CR.repo - CentOS-fasttrack.repo - CentOS-Sources.repo - name: 下载阿里源的 Centos-7.repo epel-7.repo get_url: url: "http://mirrors.aliyun.com/repo/{{ item.url }}" dest: "/etc/yum.repos.d/{{ item.dest }}" with_items: - {url: "Centos-7.repo", dest: "CentOS-7.repo"} - {url: "epel-7.repo", dest: "epel-7.repo"} - name: yum安装 wget net-tools bind-utils net-snmp-utils traceroute lrzsz yum: name: - wget - net-tools - bind-utils - net-snmp-utils - traceroute - lrzsz state: present ...
使用yum来安装python3和pip,而后再更新pip到最新版本,并设置国内的pip镜像源:
--- - hosts: host1 tasks: - name: yum 安装 python3 yum: name: [python36, python36-setuptools, python36-pip] state: present - name: 更新 pip # 有 easy_install 安装会报错,这里用 pip 更新 pip: name: pip state: latest extra_args: -i https://mirrors.aliyun.com/pypi/simple/ # 用python3的pip要指定python3,不然有可能去调用python2的pip vars: {ansible_python_interpreter: /usr/bin/python3} - name: 检查pip配置文件是否存在 file: path: ~/.config/pip/pip.conf state: file ignore_errors: True register: result - name: 若是pip配置文件不存在:设置使用阿里源 command: pip config set global.index-url https://mirrors.aliyun.com/pypi/simple/ when: result is failed - name: 安装 selinux pip: {name: selinux, state: present} vars: {ansible_python_interpreter: /usr/bin/python3} ...
按以前说的,顺便把selinux也安装上。
安装docker没有太大问题,须要先把docker-py安装上。用pip安装,因此docker模块只能在python3环境上运行、
以前已经把selinux也装上。这样除了yum,其余均可以在python3环境上运行了。
--- - hosts: host1 vars: ansible_tag: v1 # 指定ansible镜像的tag(版本号) tasks: - name: 下载阿里的安装源 get_url: url: http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo dest: /etc/yum.repos.d/ - name: yum 安装 docker-ce 指定版本 yum: name: docker-ce-18.06.0.ce-3.el7 state: present - name: 启动docker,开机启动 service: name=docker.service state=started enabled=yes - name: 检查docker配置文件是否存在 file: path: /etc/docker/daemon.json state: file ignore_errors: True register: result - name: 若是docker配置文件不存在,则建立初始文件设置镜像加速器 when: result is failed block: - name: 文件写入内容,设置设置镜像加速器 lineinfile: path: /etc/docker/daemon.json create: yes line: | { "registry-mirrors": ["http://hub-mirror.c.163.com", "https://docker.mirrors.ustc.edu.cn"] } - name: 重启docker,使镜像加速器生效 service: name=docker.service state=restarted - name: 安装管理docker的模块,检查镜像是否存在 vars: {ansible_python_interpreter: /usr/bin/python3} block: - name: pip 安装 docker-py selinux pip: name: [docker-py, selinux] state: present - name: 检查 Ansible 镜像是否存在 vars: {ansible_python_interpreter: /usr/bin/python3} docker_image: name: ansible tag: "{{ ansible_tag }}" source: local ignore_errors: True register: result - name: 制做 Ansible 镜像 vars: {ansible_python_interpreter: /usr/bin/python3} when: result is failed block: - name: 将 Dockerfile copy 到目标主机 # copy 须要 selinux,因此上面用 pip 安装了 python3 的版本 copy: src: ansible/Dockerfile dest: /tmp/docker_file/ansible/ - name: docker build docker_image: name: ansible tag: "{{ ansible_tag }}" build: path: /tmp/docker_file/ansible/ pull: yes source: build - name: 删除 Dockerfile file: path: /tmp/docker_file/ state: absent ...
docker的配置文件是json格式的,json没有注释,因此不能用blockinfile模块。能够用lineinfile模块,也能够用copy模块。不过copy模块有个小问题,无法递归建立目录。而lineinfile模块有create参数,而且也支持多行。
这个是构架ansible的Dockerfile:
FROM centos:centos7 RUN curl -o /etc/yum.repos.d/epel.repo http://mirrors.aliyun.com/repo/epel-7.repo && \ yum -y install python36 python36-setuptools python36-pip && \ yum clean all && \ pip3 install pip --upgrade -i https://mirrors.aliyun.com/pypi/simple/ && \ /usr/local/bin/pip3 install ansible -i https://mirrors.aliyun.com/pypi/simple/ && \ mkdir /opt/ansible_project/etc/ansible -p && \ ln -s /opt/ansible_project/etc/ansible/ /etc/ansible VOLUME /opt/ansible_project CMD ["ansible", "--version"]
建立镜像查找的Dockerfile所在的文件夹是在目标主机上的。因此须要先用copy模块将文件夹复制过去。
copy模块使用相对目录时,源文件的起始目录是playbook所在的目录,目标的起始目录有目标主机决定(Centos的系统,默认登陆后就在用户的家目录)。
中文乱码
测试后发现这个基础镜像是不支持中文字符的。须要在Dockerfile中在添加以下的内容:
RUN yum install kde-l10n-Chinese -y RUN yum install glibc-common -y RUN localedef -c -f UTF-8 -i zh_CN zh_CN.utf8 RUN export LANG=zh_CN.UTF-8 RUN echo "export LANG=zh_CN.UTF-8" >> /etc/locale.conf ENV LANG zh_CN.UTF-8 ENV LC_ALL zh_CN.UTF-8
只在作好的镜像上解决了中文字符的问题。上面的内容没有测试,因此先单独列出来,没有合并到整个Dockerfile中。
主要作了2件事:
playbook以下:
--- - hosts: host1 vars: ansible_python_interpreter: /usr/bin/python2 # 指定使用python2,防止有坑 init_ssh_user: admin # 是否建立用户,而且会禁用root密码登陆 init_ssh_port: 2849 # 是否修改默认ssh端口 tasks: # 建立管理员用户,禁用root登陆 - block: - name: 建立用户 {{ init_ssh_user }} user: name: "{{ init_ssh_user }}" # 这个是加盐的对称加密,因此能够反解,官网有生成密码的方式: # https://docs.ansible.com/ansible/latest/reference_appendices/faq.html#how-do-i-generate-encrypted-passwords-for-the-user-module password: "$6${{ my_secret_salt }}$CSQSsXSoAkwtWDzjlReQ3u0jy1YyxBLouwe403dCVe.ystdi9JQvjSxhoTpYwNoT5nprsJV/UpYb9Ktj.7jLX/" groups: wheel state: present - name: 修改 /etc/ssh/sshd_config 禁止root登陆 lineinfile: dest: /etc/ssh/sshd_config state: present regexp: "^#?PermitRootLogin" line: "PermitRootLogin no" notify: systemctl restart sshd.service when: init_ssh_user is defined # 修改ssh端口 - block: - name: 防火墙开启端口 {{ init_ssh_port }} firewalld: port: "{{ init_ssh_port }}/tcp" state: enabled permanent: yes immediate: yes - name: yum安装 policycoreutils-python yum: { name: policycoreutils-python, state: present} - name: 设置selinux:`semanage port -a -t ssh_port_t -p tcp {{ init_ssh_port }}` seport: ports: "{{ init_ssh_port }}" proto: tcp setype: ssh_port_t state : present - name: 修改 /etc/ssh/sshd_config 的端口设置 lineinfile: dest: /etc/ssh/sshd_config state: present regexp: "^#?Port" line: "Port {{ init_ssh_port }}" notify: systemctl restart sshd.service when: init_ssh_port is defined handlers: - name: systemctl restart sshd.service service: name=sshd.service state=restarted ...
去目标主机上验证:
# docker run --rm ansible:v1 ansible 2.8.4 config file = None configured module search path = ['/root/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules'] ansible python module location = /usr/local/lib/python3.6/site-packages/ansible executable location = /usr/local/bin/ansible python version = 3.6.8 (default, Apr 25 2019, 21:02:35) [GCc 4.8.5 20150623 (Red Hat 4.8.5-36)] #