Ansible 命令 安装 sh yum install ansible apt install ansible sh pip3 install ansible for python2 - default installation pip install ansible 卸载 sh rm -rf $HOME/.ansible rm -rf $HOME/.ansible.cfg sudo rm -rf /usr/local/lib/python2.7/dist-packages/ansible sudo rm -rf /usr/local/lib/python2.7/dist-packages/ansible-2.5.4.
```sh yum install ansible apt install ansible
pip3 install ansible # for python2 - default installation pip install ansible
远程机器应该有 'python' - 'gather_facts: False' 或 'gather_facts: no',否则
## 卸载 ```bash ```sh rm -rf $HOME/.ansible rm -rf $HOME/.ansible.cfg sudo rm -rf /usr/local/lib/python2.7/dist-packages/ansible sudo rm -rf /usr/local/lib/python2.7/dist-packages/ansible-2.5.4.dist-info sudo rm -rf /usr/local/bin/ansible sudo rm -rf /usr/local/bin/ansible-config sudo rm -rf /usr/local/bin/ansible-connection sudo rm -rf /usr/local/bin/ansible-console sudo rm -rf /usr/local/bin/ansible-doc sudo rm -rf /usr/local/bin/ansible-galaxy sudo rm -rf /usr/local/bin/ansible-inventory sudo rm -rf /usr/local/bin/ansible-playbook sudo rm -rf /usr/local/bin/ansible-pull sudo rm -rf /usr/local/bin/ansible-vault sudo rm -rf /usr/lib/python2.7/dist-packages/ansible sudo rm -rf /usr/local/lib/python2.7/dist-packages/ansible
## Ansible 配置位置 * 路径变量 $Ansible_Config * ~/.ansible.cfg * /etc/ansible/ansible.cfg ```bash ```sh ansible-config view # list of possible environment variables ansible-config dump
### 外部角色的配置 文件名: ~/.ansible.cfg ```bash ```properties [defaults] roles_path = ~/repos/project1/roles:~/repos/project2/roles
### 检查配置 ```bash ```sh ansible-config view
## 清单 ### 没有清单的内联主机 IP ```bash
ansible all -i desp000111.vantage.zur, --user=my_user -m "ping" -vvv
生成 PEM 文件
```sh ssh-keygen -t rsa -b 4096 -m PEM -f my_ssh_key.pem ll my_ssh_key.pem ansible all -i desp000111.vantage.zur, --user=vitalii.cherkashyn -e ansible_ssh_private_key_file=my_ssh_key.pem -m "ping" -vvv
### INI 文件 ```bash ```properties # example cfg file [web] host1 host2 ansible_port=222 # defined inline, interpreted as an integer [web:vars] http_port=8080 # all members of 'web' will inherit these myvar=23 # defined in a :vars section, interpreted as a string
## 使用特定的远程 Python 版本执行、重写默认变量、重写变量、覆盖变量 ```bash
--extra-vars "remote_folder=$REMOTE_FOLDER ansible_python_interpreter=/usr/bin/python"
```sh ansible-playbook -i "ubs000015.vantage.org , " mkdir.yaml ansible-playbook welcome-message.yaml -i airflow-test-account-01.ini --limit worker --extra-vars="ACCOUNT_ID=QA01" --user=ubuntu --ssh-extra-args="-i $EC2_KEY" -vvv ansible all -i airflow-test-account-01.ini --user=ubuntu --ssh-extra-args="-i $EC2_KEY" -m "ping" -vvv ansible main,worker -i airflow-test-account-01.ini --user=ubuntu --ssh-extra-args="-i $EC2_KEY" -m "ping"
创建一个简单的文件来建立一个文件夹
```yaml - hosts: all tasks: - name: Creates directory file: path: ~/spark-submit/trafficsigns state: directory mode: 0775 - name: copy all files from folder copy: src: "/home/projects/ubs/current-task/nodes/ansible/files" dest: ~/spark-submit/trafficsigns mode: 0775 - debug: msg='folder was amazoncreated for host {{ ansible_host }}'
## 在本地执行 Ansible、本地执行 ```bash ```sh # --extra-vars="mapr_stream_path={{ some_variable_from_previous_files }}/some-argument" \ ansible localhost \ --extra-vars="deploy_application=1" \ --extra-vars=@group_vars/all/vars/all.yml \ --extra-vars=@group_vars/ubs-staging/vars/ubs-staging.yml \ -m include_role \ -a name="roles/labeler"
## 使用外部参数执行 ansible-playbook、带参数的 Bash 脚本 ansible-playbook、额外变量、外部变量、环境变量 ```bash ```j2 # variable from env {{ lookup('env','DB_VARIANT_USERNAME') }}
ansible-playbook -i inventory.ini playbook.yml --extra-vars "$*"
带有指向外部参数文件的路径、从外部文件添加附加变量
```sh ansible-playbook -i inventory.ini playbook.yml --extra-vars @/path/to/var.properties ansible-playbook playbook.yml --extra-vars=@/path/to/var.properties
## 内联外部变量 ```bash ```sh ansible-playbook playbook.yml --extra-vars="oc_project=scenario-test mapr_stream_path=/mapr/prod.zurich/vantage/scenario-test"
## 检查是否工作、即席命令 ```bash ```sh ansible remote* -i inventory.ini -m "ping" ansible remote* -i inventory.ini --module-name "ping"
ansible remote* -i inventory.ini -a "hostname"
## 循环示例 ```bash ```sh - name: scripts {{ item }} template: mode: 0777 src: "templates/{{ item }}" dest: "{{ root_folder }}/{{ item }}" loop: - "start-all.sh" - "status.sh" - "stop-all.sh"
## 重复执行 ```bash ```sh --limit {playbookfile}.retry
## 从任务开始执行、从任务开始执行、从任务开始执行、跳过之前的任务 ```bash ```sh ansible-playbook playbook.yml --start-at-task="name of the start to be started from"
## 将文件中的变量替换到专用文件中、将变量移动到单独的文件中 * 之前 ```bash ```yaml vars: db_user: my_user db_password: my_password ansible_ssh_pass: my_ssh_password ansible_host: 192.168.1.14
```sh ./host_vars/id_of_the_server
或 groupvars:
```sh ./group_vars/id_of_the_group_into_square_brakets
代码
```yaml db_user: my_user db_password: my_password ansible_ssh_pass: my_ssh_password ansible_host: 192.168.1.14
## 将代码移到单独的文件中、任务移到文件中 从原始文件剪切代码并粘贴到单独的文件中(必须适当对齐), 替换代码为: ```bash ```yaml - include: path_to_folder/path_to_file
应创建适当的文件:
```sh ./path_to_folder/path_to_file
## 通过标签跳过/激活某些任务 ```bash ```yaml tasks: - template src: template/activation.sh.j2 dest: /usr/bin/activation.sh tags: - flag_activation
多标签、多标签
```yaml tasks: - template src: template/activation.sh.j2 dest: /usr/bin/activation.sh tags: - flag_activation - flag_skip
```bash ```sh ansible-playbook previous-block.yml --skip-tags "flag_activation" # ansible-playbook previous-block.yml --skip-tags=flag_activation # ansible-playbook previous-block.yml --tags "flag_activation" # ansible-playbook previous-block.yml --tags=flag_activation
```bash export ANSIBLE_STRATEGY=debug # revert it afterwards ( avoid "ERROR! Invalid play strategy specified: "): # export ANSIBLE_STRATEGY=linear
打印变量
```python task.args task.args['src'] vars()
更改变量
```python del(task.args['src']) task.args['src']="/new path to file"
设置变量
name: Set Apache URL
set_fact:
apache_url: 'http://example.com/apache'
name: Download Apache
shell: wget {{ apache_url }}
shell == ansible.builtin.shell 管理播放 ```bash
redo
continue
quit
```bash ```yaml - name: airflow setup for main (web server) and workers hosts: all tasks: - name: airflow hostname debug: msg="{{ lookup('vars', 'ansible_host') }}" - name: all variables from host debug: msg="{{ vars }}" when: run_mode == "debug"
shell: /usr/bin/uptime
register: result
debug:
var: result
```sh - name: source bashrc sudo: no shell: . /home/username/.bashrc && [the actual command you want run]
## rsync 复制文件 ```bash
export PATH=$PATH:/home/ubuntu/.local/bin
nohup airflow webserver
参数文件 (args.json)
```json { "ANSIBLE_MODULE_ARGS": { "task_parameter_1": "just a string", "task_parameter_2": 50 } }
执行文件
```bash python3 -m pdb library/oc_collaboration.py args.json
设置断点
```python import pdb ... pdb.set_trace()
运行到断点
```sh until 9999 next
## 内联调试模块、内联执行模块、即席模块检查 ```bash ```sh ansible localhost -m debug --args msg="my custom message" # collect facts ansible localhost -m setup
## 任务打印所有变量 ```bash ```yaml - name: "Ansible | List all known variables and facts" debug: var: hostvars[inventory_hostname]
## ansible-console ```bash ```sh ansible-console debug msg="my custom message" shell pwd
# 错误处理、try catch ## 当至少一个服务器抛出错误时停止步骤(剧本)的执行 ```bash ```yaml any_errors_fatal:true
## 不要为某个特定任务抛出错误 ```bash ```yaml - mail: to: 1@yahoo.com subject: info body: das ist information ignore_errors: yes
## 条件失败、根据条件失败、解析日志文件以查找错误 ```bash ```yaml - command: cat /var/log/server.log register: server_log_file failed_when : "'ERROR' in server_log_file.stdout"
# 模板、Jinja2 模板、管道、[Ansible 过滤器](https://docs.ansible.com/ansible/latest/user_guide/playbooks_filters.html) 默认值 ```bash
default path is {{ my_custom_path | default("/opt/program/script.sh") }}
转义特殊字符
{{ '{{ filename }}.log' }}
列表操作
{{ [1,2,3] | min }}
{{ [1,2,3] | max }}
{{ [1,2,3] | first }}
{{ [1,2,3] | last }}
{{ [1,2,3,2,3,] | unique }}
{{ [1,2,3] | union([1,2]) }}
{{ [1,2,3] | intersect([3]) }}
{{ 100 | random }}
{{ ["space", "separated", "value"] | join(" ") }}
{{'latest' if (my_own_value is defined) else 'local-build'}}
从路径获取文件名 (返回 'script.sh')
{{ "/etc/program/script.sh" | basename }}
```yaml - name: Create DAG config template: src={{ item }} dest={{ airflow_dag_dir }}/config/{{ item | basename | regex_replace('\.j2','') }} with_fileglob: - ../airflow_dags/airflow_dags_gt/config/*.py.j2
## 从目标机器反向复制 ```bash
为了全局改善文件的缩进,在文件开头添加以下任意一行
```yaml #jinja2: lstrip_blocks: True #jinja2: trim_blocks:False #jinja2: lstrip_blocks: True, trim_blocks: True
为了仅改善块的缩进 ```bash ```j2 <div> {%+ if something %}<span>hello</span>{% endif %} </div>
条件示例 ```bash ```j2 {% if lookup('env','DEBUG') == "true" %} CMD ["java", "start-debug"] {% else %} CMD ["java", "start"] {% endif %}
### 循环指令、循环最后、循环最后 ```bash
[
{% for stream in deployment.streams %}
{
"stream": "{{ stream.stream_name }}",
"classN": "{{ stream.class_name }}",
"script": "{{ stream.script_name }}",
"sibFolders": [
{% for folder in stream.sub_folders %}
"{{ folder }}"{% if not loop.last %},{% endif %}
{% endfor %}
]
}{% if not loop.last %},{% endif %}
{% endfor %}
]
单个符号
{{ '{{' }}
较大段落的代码
{% raw %}
tempfile:
state: file
suffix: config
register: temp_config
template:
src: templates/configfile.j2
dest: "{{ temp_config.path }}"
还需要“通知” Ansible 关于模块,选择以下选项之一:
```properties library=/path/to/module/library
ansible-doc -t module {name of the module}
from ansible.module_utils.basic import AnsibleModule
def main():
input_fields = {
"operation": {"required": True, "type": "str"},
"file": {"required": True, "type": "str"},
"timeout": {"required": False, "type": "int", "default": "120"}
}
module = AnsibleModule(argument_spec=input_fields)
operation = module.params["operation"]
file = module.params["file"]
timeout = module.params["timeout"]
# module.fail_json(msg="you must be logged in into OpenShift")
module.exit_json(changed=True, meta={operation: "create"})
示例插件
{{ list_of_values | average }}
插件的 Python 代码
dev average(list):
return sum(list) / float(len(list))
class AverageModule(object):
def filters(self):
return {'average': average}
执行
export ANSIBLE_FILTER_PLUGINS=/full/path/to/folder/with/plugin
ansible-playbook playbook.yml
```sh # documentation ansible-doc -t lookup -l ansible-doc -t lookup csvfile
替换文件中具有特殊格式的值 ```bash ```python {{ lookup('csvfile', 'web_server file=credentials.csv delimiter=,') }} {{ lookup('ini', 'password section=web_server file=credentials.ini') }} {{ lookup('env','DESTINATION') }} {{ lookup('file','/tmp/version.txt') }}
查找器变量 ```bash
{{ hostvars[inventory_hostname]['somevar_' + other_var] }}
For ‘non host vars’ you can use the vars lookup plugin:
{{ lookup('vars', 'somevar_' + other_var) }}
```yaml - name: airflow setup for main (web server) and workers hosts: all tasks: - name: airflow hostname debug: msg="{{ lookup('vars', 'ansible_host') }}" - name: variable lookup debug: msg="lookup data {{ lookup('vars', 'ansible_host')+lookup('vars', 'ansible_host') }}" - name: read from ini, set variable set_fact: queues: "{{ lookup('ini', lookup('vars', 'ansible_host')+' section=queue file=airflow-'+lookup('vars', 'account_id')+'-workers.ini') }}" - name: airflow lookup debug: msg=" {{ '--queues '+lookup('vars', 'queues') if lookup('vars', 'queues') else '<default>' }}"
# 清单文件 --- ## 清单文件、带有变量的清单文件、[规则](https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html) ```bash
[remote_ssh]
172.28.128.3 ansible_connection=ssh ansible_port=22 ansible_user=tc ansible_password=tc
Python inventory.py (带 'py' 扩展名) 代替 txt
import json
data = {"databases": {"hosts": ["host1", "host2"], "vars": {"ansible_ssh_host":"192.168.10.12", "ansible_ssh_pass":"Passw0rd"} }}
print(json.dumps(data))
还应该包含以下逻辑
inventory.py --list
inventory.py --host databases
[remote_ssh]
172.28.128.3 ansible_connection=ssh ansible_port=22 ansible_user=tc ansible_password=tc http_port=8090
剧本使用:
'{{http_port}}'
没有清单文件对特定主机
```sh ansible-playbook playbook.yml -i 10.10.10.10
带有清单文件 ```bash ```sh ansible-playbook -i inventory.ini playbook.yml
仅对本地主机执行剧本的问题 ```bash ```text Note that the implicit localhost does not match 'all' ... skipping: no hosts matched
解决方案
```sh ansible-playbook --inventory="localhost," --connection=local --limit=localhost --skip-tag="python-script" playbook.yaml # example with external variables ansible-playbook --inventory="localhost," --connection=local --limit=localhost \ --extra-vars="oc_project=scenario-test mapr_stream_path=/mapr/prod.zurich/vantage/scenario-test" \ --tag="scenario-service" deploy-scenario-pipeline.yaml
解决方案2 ```bash ```sh #vim /etc/ansible/hosts localhost ansible_connection=local
# 策略 --- ```bash
strategy: linear
* 线性 (默认) * 每一步等待所有服务器完成 * 自由 * 对所有服务器独立执行 - 某些服务器可以比其他服务器显著提前完成安装 额外参数 - 指定同时执行的服务器数量(仅对默认策略有效) ```bash
serial: 3
```bash
serial: 20%
```bash
serial: [5,15,20]
默认值 "serial" 到配置文件 ansible.cfg
forks = 5
并非所有模块都支持此操作
以异步模式执行命令(初步估计为 120 秒),默认轮询结果为 10 秒
async: 120
以异步模式执行命令(初步估计为 120 秒),轮询结果为 60 秒
async: 120
poll: 60
执行命令并忘记,不等待执行
async: 120
poll: 0
以异步模式执行命令,
注册结果
在文件末尾检查结果
command: /opt/my_personal_long_run_command.sh
async: 120
poll: 0
register: custom_command_result
name: check status result
async_status: jid={{ custom_command_result.ansible_job_id }}
register: command_result
until: command_result.finished
retries: 20
在你的项目文件夹 './roles' 中执行代码
ansible-galaxy init {project/role name}
结果:
./roles/{project/role name}
/defaults
/handlers
/meta
/tasks
/tests
/vars
插入代码
roles:
所有创建项目的文件夹将应用于你的项目(tasks、vars、defaults)
ansible-galaxy search {project/role name}
cd roles
ansible-galaxy import {name of the project/role}
插入代码
roles:
所有导入项目的文件夹将应用于你的项目(tasks、vars、defaults)
```yaml - hosts: localhost # hosts: all # hosts: <name of section from inventory file> tasks: - name: first step include_role: name: mapr-kafka tasks_from: cluster-login
## 导出 创建/更新文件: ```bash
./roles/{project/role name}/meta/main.yml
```yaml - hosts: localhost tasks: - name: Ansible create file with content example copy: dest: "/tmp/remote_server.txt" content: | dog tiger
```yaml - hosts: localhost tasks: - name: Ansible create file with content example copy: dest: "/tmp/remote_server.txt" content: | {{ lookup('env','TEST_1') }} {{ lookup('env','TEST_2') }}
```bash ```sh ansible-playbook ansible-example.yml
## 执行角色、角色执行、本地启动角色、本地启动、角色本地执行 ```bash ```sh ansible localhost \ --extra-vars="deploy_application=1" \ --extra-vars=@group_vars/all/defaults/all.yaml \ --extra-vars=@group_vars/all/vars/all.yaml \ --extra-vars="mapr_stream_path={{ some_variable_from_previous_files }}/some-argument" \ -m include_role \ -a name="new_application/new_role"
其中 "include_role" 是运行模块(魔法词)
其中 "new_application/new_role" 是角色子文件夹
其中 @group_vars/all/default/all.yaml 是带有额外变量的 YAML 文件子路径
## 控制台输出与应用角色应显示如下 ```bash
TASK [{project/role name}: {task name}] ***********************************
例如 ```bash
TASK [java : install java with jdbc libraries] ***********************************
ansible-vault encrypt inventory.txt
ansible-vault view inventory.txt
ansible-vault create inventory.txt
通过命令行请求密码 ```bash
ansible-playbook playbook.yml -i inventory.txt -ask-vault-pass
文件应包含密码 ```bash
ansible-playbook playbook.yml -i inventory.txt -vault-password-file ./file_with_pass.txt
脚本应返回密码 ```bash
ansible-playbook playbook.yml -i inventory.txt -vault-password-file ./file_with_pass.py
```json - name: External variables include_vars: roles/marker-table/defaults/main.yaml tags: deploy
### echo 添加标志用于 ```ansible``` 或 ```ansible-playbook```:-vvv(3) -vv (2) 或 -v (1) ```bash
name: Ensure MOTD file is in place
copy:
src: files/motd
dest: /etc/motd
owner: root
group: root
mode: 0644
name: Ensure MOTD file is in place
copy:
content: "Welcome to this system."
dest: /etc/motd
owner: root
group: root
mode: 0644
```json - name: Ensure MOTD file is in place template: src: templates/motd.j2 dest: /etc/motd owner: root group: root mode: 0644
### [user](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/user_module.html) ```bash ```json - name: Ensure user1 exists user: name: user1 group: users groups: wheel uid: 2001 password: "{{ 'mypassword' | password_hash('sha512') }}" state: present
### [package](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/package_module.html) ```bash ```json - name: Ensure Apache package is installed package: name: httpd state: present
### [firewalld](https://docs.ansible.com/ansible/latest/collections/ansible/posix/firewalld_module.html) ```bash ```json - name: Ensure port 80 (http) is open firewalld: service: http state: enabled permanent: yes immediate: yes
### [file](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/file_module.html) ```bash ```json - name: Ensure directory /app exists file: path: /app state: directory owner: user1 group: docker mode: 0770
### [lineinfile](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/lineinfile_module.html) ```bash ```json - name: Ensure host my-own-host in hosts file lineinfile: path: /etc/hosts line: 192.168.0.36 my-own-host state: present - name: Ensure root cannot login via ssh lineinfile: path: /etc/ssh/sshd_config regexp: '^PermitRootLogin' line: PermitRootLogin no state: present
### [unarchive](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/unarchive_module.html) ```bash ```json - name: Extract content from archive unarchive: src: /home/user1/Download/app.tar.gz dest: /app remote_src: yes
### [command](https://docs.ansible.com/ansible/latest/collections/ansible/builtin/command_module.html) ```bash ```json - name: Run bash script command: "/home/user1/install-package.sh"
### 待办事项 * 系统 * 命令 * 数据库 * 云 * Windows # [ansible awx](https://github.com/ansible/awx) # 问题 ## 指纹检查 ```bash
fatal: [172.28.128.4]: FAILED! => {"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add this host's fingerprint to your known_hosts file to manage this host."}
解决方法 ```bash
export ANSIBLE_HOST_KEY_CHECKING=False
ansible-playbook -i inventory.ini playbook-directory.yml
声明:
本文件灏天文库团队进行了翻译。尽管我们力求准确,但请注意,翻译可能包含错误或不准确之处。原文档以其原始语言为准。我们不对因使用此翻译而产生的任何误解或误译负责。