Ansible
In this section, some aspects on ansible is discussed.
Common modules in Ansible
file
copy
command
cron: name attr must be specfied, otherwise, the crontab task shall be added repeatedly
debug:
msg
info to be printeduser
service
setup: get basic facts as variables collecting from nodes, note the key prefix ansible_ is not used
template: backup=yes
authorized_keys
lineinfile: When modifying a line the regexp should typically match both the initial state of the line as well as its state after replacement by
line
to ensure idempotence. Insert lines logic: blogapt
make
hostname
mysql_user: mysql-python package missing issue: post,
apt: name=python3-mysqldb state=present
is enough, howeverpip install mysql-python
wouldn't work.pip
set_fact: set varible per host and used later in playbooks
gluster_volume: Using ansible to deploy gluster fs blog
General syntax in playbooks
Conditionals
when
: the argument is rendered by jinja2, but no need for bracketor
,and
,not
compare operator in general language is ok to use in the condition statement, linke
!=
,>=
changed_when
,failed_when
Loops
loop
: list or list of hash, corresponding variables in leading tasksome moudules directly support list argument
register of a loop task, has attr
results
as a listwith_items
, register.results is automatically a list, see this postnested loop, use jinja template as
"{{ ['alice', 'bob'] |product(['clientdb', 'employeedb', 'providerdb'])|list }}"
, see here.
Useful keywords
environment
: config the env variables,http_proxy:http://blah
, play level or task levelbecome
: the user after sshremote_user
: the user used for ssh
CLI commands
ansible-vault
, encrypt protected info by given password, used as!value|eencrypted strings
in playbooksansible-galaxy init
: create the directory structure for ansible rolesansible-playbook -e "var=value"
, overwrite var with highest priority-vv
: verbose modeexample:
ansible -i ~/hpc/hosts cn -m apt -a "name=iperf state=present" --become -K
host pattern in ansible adhoc: doc. As quoted "You can refer to hosts within the group by adding a subscript to the group name", that is to say, the pattern is group[1:2] instead of c[1:2] as host names.
eg.
ansible -i ./hosts cn[1:2] -m service -a "name=ganglia-monitor state=restarted" --become -K
check mode,
--check
in cli args, no real change happen but only reported as a simulation, also--diff
to show difference
Jinja Template Extension in Ansible
filters
Jinja template rendering only happen before the task is sent to nodes.
int
, string to intto_json
,to_yaml
,from_json
,from_yaml
default(val)
for default value of undefined variables,default(omit)
use default value from external such as system defaultsmin
,flatten
,flatten(levels=1)
unique
,union(list)
,intersect(list)
,difference(list)
,symmetric_difference(list)
"{{mac_prefix| random_mac}}"
"{{ 60|random }}"
,"{{ [1,2,3]|random }}"
"{{ list|shuffle }}"
log(3)
, default base is e,pow(5)
,root(3)
, default power is 2,abs
,round
"{{json or yml data| json_query("query pattern")}}"
, this query pattern is backend with jmespathipaddr
,ipv4
,ipv6
, return bool default, but can extract more info if arguments are given, see docparse_cli("spec")
parse output by given spec file, for details of syntax, see dochash
, arguments can be sha1 or md5 or more choices.password_hash('sha256', 'mysecretsalt')
{{dict|combine(dict2)}}
similar todict.update(dict2)
in pythonurlsplit
get info from url by given arguments, see docregex_search('regexpr')
,regex_search('regexpr', new)
test
Example
Ansible Vault
Development consideration
Future plan: a spack module for ansible (settled by
changed_when
to avoid changed report of command)molecule: full stack to test ansible
Misc
Cautions
In template system, just use
{{}}
instead of quote""
outside.indent in jinja template config files: blog
ansible_facts
, the key should rip the ansible part off, which is ...but for
host_vars[hostname]
to access the facts, the ansible prefix is must, which is in contrast withansible_facts
...lookup plugin dont take
become: yes
as a thing, it just cannot cat other user's file….for
copy
to copy files without permission, use remote_src: yes option, otherwisebecome
is also useless...the dest path cannot be a relative one, but use
{{role_path}}
insteadeach task has it own ssh session and shell: how source work with ansible. The default shell of ansible is
sh
, while source is a bash builtin instead of sh.{{ D['key']|default ('undefined') }}
can be used as default value for non existing keys of dictdifferece between command and shell module: blog. Command is weaker, it doesn't support evaluation on env vars and no support for
|
,&
like things in shell.Hostname is not persistent due to cloud init system in ubuntu, see solution here.
default_ipv4 item in ansible fact could be empty, dont rely on this variable to setup networks. It seems that there is value only after
dhclient <nic>
? It is actually the default route ip, see this post.
More references
My comments
In general, ansible playbooks is definitely a type of domain specific language (DSL). There are so many fields, that config files (json or yaml) have been evolving into DSL which go far beyond the scope of some nouns, but also complicated adjective and verbs in the configurations. In some sense, it is always a question, that whether such a scheme is really simple and efficient enough as claimed? Maybe, say playbooks in this case, is easier to handle and suitable for more complicated cases when implemented directly as python scripts instead of a indirect level of abstraction (yml, which one needs reinvent basically all wheels of grammars in a Turing complete language like if and for, and still has less expression power than a Turing complete language). Of course, it is just my personal thought.
Last updated