準備好安裝了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)] #