目前在 DevOps 設定管理的工具中,以 Puppe、Chef、Salt、Ansible 四者最有名,而 Puppe 跟 Chef 兩者是以 ruby 開發, Salt 與 Ansible 都是以 python 開發的,在 2016 及 2017 DevOps 的統計中,Ansible 自 2015 由 10% 上升至 20% 及 21%,chef 及 puppet 在 2017 的比例有下降一些,但還是比較多人使用的工具。
Ansible is Simple IT Automation 最簡單的 IT 自動化工具,包含 自動化部署APP、自動化管理配置、自動化的持續交付、自動化的(AWS)雲服務管理。ansible 是利用 paramiko 開發的,paramiko是一個純Python實現的ssh協議庫。因此不需要在遠端主機上安裝client或agents,因為 ansible 單純地是以 ssh 來和遠程主機進行通訊。
在 Ender's Game 裡面,Ender 是利用一個的超光速即時的通訊系統,在後端指揮中心,遠端下達指令給前方的戰機及戰艦,這個系統被稱為 Ansible,用途是 instantaneous communication across any distance。因此 Ansible 就跟 devops 的目標一致,這樣的工具就是要讓隱身在後面的工程師,個個都像 Ender 一樣,一呼百應而且沒有絲毫的遲疑,當然瞬間的成敗也由 Ender 獨力承擔。
安裝
ansible 對於管理端的主機,稱為 control machine,必須要安裝 python 2.6+,被管理(託管)的主機,稱為 managed node,要安裝 sshd,也要安裝 python 2.6+。
在 macos 安裝 ansible 可使用 macports 或是 homebrew
sudo port install ansible
當然也可以因應不同 OS 用 yum, apt, pip, deb 進行安裝。
安裝測試環境
可用 VM 來進行測試,目前可選用 virtualbox 或是 docker
- vagrant
必須安裝 vagrant 及 virtualbox,可選用 vagrant 官方提供的 VM
mkdir vagrant_centos7
cd vagrant_centos7
vagrant init geerlingguy/centos7
vagrant up
# 關機
vagrant halt
# 重開機
vagrant reload
# ssh
vagrant ssh
# 移除
vagrant destory
取得 VM 的 ssh 設定
$ vagrant ssh-config
Host default
HostName 127.0.0.1
User vagrant
Port 2222
UserKnownHostsFile /dev/null
StrictHostKeyChecking no
PasswordAuthentication no
IdentityFile /Users/charley/VirtualBoxVMs/vagrant/.vagrant/machines/default/virtualbox/private_key
IdentitiesOnly yes
LogLevel FATAL
ansible.cfg 設定檔
$ vi ansible.cfg
[defaults]
inventory = hosts
remote_user = vagrant
private_key_file = .vagrant/machines/default/virtualbox/private_key
host_key_checking = False
ansible 會依照這四個順序尋找適合的 ansible.cfg
* ANSIBLE_CONFIG 環境變數
* 目前工作目錄的 ansible.cfg
* 使用者 Home 目錄的 .ansible.cfg
* 系統設定 /etc/ansible/ansible.cfg (如果是用macports 安裝則是在 /opt/local/etc/ansible/ansible.cfg)
hosts 設定檔
$ vi hosts
server1 ansible_ssh_host=127.0.0.1 ansible_ssh_port=2222
[local]
server1
利用 ansible echo 一段文字
$ ansible all -m command -a 'echo Hello World on Vagrant.'
server1 | SUCCESS | rc=0 >>
Hello World on Vagrant.
- docker
準備一個有安裝了 sshd 的 docker VM,將 10022 對應到 TCP 22 (ssh),因為 CentOS 7 預設會安裝 python 2.7.5,就不需要處理 python 的安裝問題。
docker run -d \
-p 10022:22\
--sysctl net.ipv6.conf.all.disable_ipv6=1\
-e "container=docker" --privileged=true -v /sys/fs/cgroup:/sys/fs/cgroup --name atest centosssh /usr/sbin/init
如果直接用 ssh client 連線
ssh root@localhost -p 10022
在另一個新的工作目錄,建立 ansible.cfg 設定檔
$ vi ansible.cfg
[defaults]
inventory = hosts
remote_user = root
host_key_checking = False
建立 hosts 設定檔
$ vi hosts
server1 ansible_ssh_host=127.0.0.1 ansible_ssh_port=10022 ansible_ssh_pass=max168kit
[local]
server1
測試 echo 指令
$ ansible all -m command -a 'echo Hello World on Docker.'
server1 | SUCCESS | rc=0 >>
Hello World on Docker.
使用 ansible
有兩種方式使用 ansible,分別是 ad-hoc command 及 playbook
- ad-hoc command
一次只能使用一個指令,像是在 console mode,一次下達一個指令
$ ansible all -m ping
server1 | SUCCESS => {
"changed": false,
"ping": "pong"
}
$ ansible all -m command -a "echo Hello World"
server1 | SUCCESS | rc=0 >>
Hello World
- playbook
像是 shell script 一樣,可組合多個指令,這是一份使用 YAML 格式製作的文件。通常一個 playbook 中會有多個 Play, Task, Module
Play: 某個特定的工作,裡面會包含多個 Task
Task: 為了實現 Play,每一個 Play 都會有一個 Task 列表,每一個 Task 在所有對應的主機上都執行完成後,才會進行下一個 Task
Module: 每一個 Task 的目的是執行一個 Module,Module 也就是 ansible 提供的一些操作指令,可到 Module Index 文件查詢可以使用的 Modules
以下是一個簡單的 hello world playbook,裡面有一個 Play: say 'hello world',兩個 Tasks,第一個 Task 使用了 command 這個 Module,第二個 Task 使用 debug
vi hello_world.yml
---
- name: say 'hello world'
hosts: all
tasks:
- name: echo 'hello world'
command: echo 'hello world'
register: result
- name: print stdout
debug:
msg: "{{ result.stdout }}"
執行 playbook
$ ansible-playbook hello_world.yml
PLAY [say 'hello world'] ***************************************************************************
TASK [Gathering Facts] *****************************************************************************
ok: [server1]
TASK [echo 'hello world'] **************************************************************************
changed: [server1]
TASK [print stdout] ********************************************************************************
ok: [server1] => {
"msg": "hello world"
}
PLAY RECAP *****************************************************************************************
server1 : ok=3 changed=1 unreachable=0 failed=0
常用的 Modules
- name: install the latest version of Apache
yum:
name: httpd
state: latest
- name: remove the Apache package
yum:
name: httpd
state: absent
- name: upgrade all packages
yum:
name: '*'
state: latest
- name: upgrade all packages, excluding kernel & foo related packages
yum:
name: '*'
state: latest
exclude: kernel*,foo*
- name: install the 'Development tools' package group
yum:
name: "@Development tools"
state: present
- name: Reboot at now
command: /sbin/shutdown -r now
- name: create .ssh directory
command: mkdir .ssh creates=.ssh/
- name: cat /etc/passwd
command: cat passwd
args:
chdir: /etc
- name: check files number
shell: ls /home/docker/ | wc -l
- name: kill all python process
shell: kill -9 $(ps aux | grep python | awk '{ print $2 }')
- copy 將 local file 傳送到遠端機器
- name: copy ssh public key to remote node
copy:
src: files/id_rsa.pub
dest: /home/docker/.ssh/authorized_keys
owner: docker
group: docker
mode: 0644
- name: copy nginx vhost and backup the original
copy:
src: files/ironman.conf
dest: /etc/nginx/sites-available/default
owner: root
group: root
mode: 0644
backup: yes
- file 遠端建立和刪除檔案、目錄、links
- name: touch a file, and set the permissions
file:
path: /etc/motd
state: touch
mode: "u=rw,g=r,o=r"
- name: create a directory, and set the permissions
file:
path: /home/docker/.ssh/
state: directory
owner: docker
mode: "700"
- name: create a symlink file
file:
src: /tmp
dest: /home/docker/tmp
state: link
- lineinfile 可用正規表示式對檔案進行插入或取代文字,類似 sed
- name: remove sudo permission of docker
lineinfile:
dest: /etc/sudoers
state: absent
regexp: '^docker'
- name: set localhost as 127.0.0.1
lineinfile:
dest: /etc/hosts
regexp: '^127\.0\.0\.1'
line: '127.0.0.1 localhost'
owner: root
group: root
mode: 0644
- service 管理遠端系統服務
- name: start nginx service
service:
name: nginx
state: started
- name: stop nginx service
service:
name: nginx
state: stopped
- name: restart network service
service:
name: network
state: restarted
args: eth0
- stat 檢查檔案狀態
- name: check the 'vimrc' target exists
stat:
path: /home/docker/.vimrc
register: stat_vimrc
- name: touch vimrc
file:
path: /home/docker/.vimrc
state: touch
mode: "u=rw,g=r,o=r"
when: stat_vimrc.stat.exists == false
- name: Use md5sum to calculate checksum
stat:
path: /path/to/something
checksum_algorithm: md5sum
沒有留言:
張貼留言