If you write or use Ansible playbooks, then you're used to reading YAML configuration files. YAML can be deceptively simple and yet strangely overwhelming all at once, especially when you consider the endless possible Ansible modules at your disposal. It feels like it should be easy to jot down a few options in a YAML file and then run Ansible, but what options does your favorite module require? And why are some key-value pairs while others are lists?
YAML for Ansible can get complex, so understanding how Ansible modules translate to YAML is an important part of getting better at both. Before you can understand how YAML works for Ansible modules, you must understand the basics of YAML.
If you don't know the difference between a mapping block and a sequence block in YAML, read this quick introduction to the basics of YAML article.
Command syntax
Aside from ad-hoc use, Ansible is used through playbooks. A playbook is composed of one or more plays in an ordered list (a YAML sequence). Each play can run one or more tasks, and each task invokes an Ansible module.
Ansible modules are basically front-ends for commands. If you're familiar with the Linux terminal or Microsoft's Powershell, then you know how to construct a command using options (such as --long
or -s
) along with arguments (also called parameters).
Here's a simple example:
$ mkdir foo
This command uses the mkdir
command to create a directory called foo
.
An Ansible playbook also constructs commands. They're the same commands, but they're invoked using a different syntax than what you're used to in a terminal.
[ You might also enjoy: Getting started with Ansible ]
Ansible modules and YAML
As a task in an Ansible playbook, though, the syntax is a lot different. First, the play is given a name, which is a human-readable description of what is being performed. A play accepts many keywords, including hosts
to limit what hosts it's meant to run on and remote_user
to define the username Ansible must use to access remote hosts.
Keywords for plays are defined by Ansible itself, and there's a list of keys (and the types of information each expects as its value) available in the Ansible Play Keywords documentation.
These keys are not separate list items. In YAML terminology, they're mappings embedded in the play sequence.
Here's a simple play declaration:
---
- name: “Create a directory”
hosts: localhost
The final mapping block in a play declaration is the tasks
keyword, which opens up a new sequence to define what Ansible module the play is going to run, and with what arguments. It's here that you're using familiar commands in an unfamiliar, YAML-ified way. In fact, it's so unfamiliar to you that you probably need to read up on the module in order to discover what arguments it expects from you.
In this example, I use the builtin file module. From the module's documentation, you can see that the required parameter is path
, which expects a valid POSIX file path. Armed with that information, you can generate a very simple Ansible playbook that looks like this:
---
- name: "Create a directory"
hosts: localhost
tasks:
- name: "Instantiate"
file:
path: "foo"
If you're still getting used to the significance of YAML's indentation, notice that the task's name is not indented relative to tasks
because name
is the start of a new YAML sequence block (which, as it happens, serves as the value for the tasks
key). The word file
identifies what module is being used, which is part of the task definition, and path
is a required parameter of the file
module.
In other words, a play's task is a YAML sequence block (that is, an ordered list) of definitions invoking a module and its parameters.
You can test this play to verify that it works as expected, but first, run yamllint
on it to avoid any syntactical surprises:
$ yamllint folder.yaml || echo “fail”
$ ansible-playbook folder.yaml
[…]
TASK [Instantiate] ******************
fatal: [localhost]:
FAILED! => {“changed”: false,
“msg”: “file (foo) is absent, cannot continue” …
The playbook was processed, but the task failed. Reading through the parameter list of the file
module reveals that its behavior largely depends on the value of state
. Specifically, the default action is to return the status of path
.
Modify your sample YAML file to include a state
mapping:
---
- name: "Create a directory"
hosts: localhost
tasks:
- name: "Instantiate"
file:
path: "foo"
state: directory
Run it again for success:
$ yamllint folder.yaml || echo “fail”
$ ansible-playbook folder.yaml
[…]
$ ls
foo
Control modules
Not all Ansible modules map directly to a single command. Some modules modify how Ansible processes your playbook. For instance, the with_items
module enumerates items you want another module to operate upon. You might think of it as a sort of do while
or for
loop.
Its documentation indicates it only accepts one parameter: a list of items. A "list" in YAML terminology is a sequence, so you know without even looking at the sample code in the docs that each item must start with a dash space (-
).
Here's a new iteration of folder creation, this time with multiple subfolders (using the recurse
parameter in the file
module) and an extra parameter to set file permissions. Don't let the additional lines fool you. This is essentially the same code as before, only with extra parameters as described in the file
module documentation, plus the with_items
module to enable iteration:
---
- name: "Create directory structure"
hosts: localhost
tasks:
- name: "Instantiate"
file:
path: "{{ item }}"
recurse: true
mode: "u=rwx,g=rwx,o=r"
state: directory
with_items:
- "foo/src"
- "foo/dist"
- "foo/doc"
Run the playbook to see the results:
$ yamllint folder.yaml
$ ansible-playbook folder.yaml
[…]
$ ls foo
dist doc src
[ Need more on Ansible? Take a free technical overview course from Red Hat. Ansible Essentials: Simplicity in Automation Technical Overview. ]
Ansible principles
An Ansible playbook is a YAML sequence, which itself consists of mappings and sequences.
Playbooks also contain Ansible modules, each of which accepts parameters as defined by its developer. Both required and optional parameters are listed in a module's documentation.
To construct an Ansible playbook, start a YAML sequence that names the play, and then lists (in a sequence) one or more tasks. In each task, one or more modules may be invoked.
Pay close attention to indentation by understanding the type of data you're entering into your YAML file. It might help to avoid thinking of indentation as an indication of logical inheritance and, instead, to view each line as its YAML data type (that is, a sequence or a mapping).
Use yamllint
to verify your YAML files.
Once you understand the structure of a playbook, it's just a matter of following along with module documentation to execute the tasks you want your playbook to perform. There are hundreds of modules available, so start exploring them and see what amazing things you can do with this amazing tool.
저자 소개
Seth Kenlon is a Linux geek, open source enthusiast, free culture advocate, and tabletop gamer. Between gigs in the film industry and the tech industry (not necessarily exclusive of one another), he likes to design games and hack on code (also not necessarily exclusive of one another).
채널별 검색
오토메이션
기술, 팀, 인프라를 위한 IT 자동화 최신 동향
인공지능
고객이 어디서나 AI 워크로드를 실행할 수 있도록 지원하는 플랫폼 업데이트
오픈 하이브리드 클라우드
하이브리드 클라우드로 더욱 유연한 미래를 구축하는 방법을 알아보세요
보안
환경과 기술 전반에 걸쳐 리스크를 감소하는 방법에 대한 최신 정보
엣지 컴퓨팅
엣지에서의 운영을 단순화하는 플랫폼 업데이트
인프라
세계적으로 인정받은 기업용 Linux 플랫폼에 대한 최신 정보
애플리케이션
복잡한 애플리케이션에 대한 솔루션 더 보기
오리지널 쇼
엔터프라이즈 기술 분야의 제작자와 리더가 전하는 흥미로운 스토리
제품
- Red Hat Enterprise Linux
- Red Hat OpenShift Enterprise
- Red Hat Ansible Automation Platform
- 클라우드 서비스
- 모든 제품 보기
툴
체험, 구매 & 영업
커뮤니케이션
Red Hat 소개
Red Hat은 Linux, 클라우드, 컨테이너, 쿠버네티스 등을 포함한 글로벌 엔터프라이즈 오픈소스 솔루션 공급업체입니다. Red Hat은 코어 데이터센터에서 네트워크 엣지에 이르기까지 다양한 플랫폼과 환경에서 기업의 업무 편의성을 높여 주는 강화된 기능의 솔루션을 제공합니다.