Skip to content

Intermediate · Configuration management with Ansible, and YAML · topic 34 of 53 · 30 min

YAML in depth

Explanation

YAML is a text format for configuration that uses indentation instead of brackets. It has three building blocks: scalars (single values), maps (key: value pairs) and lists (lines starting with "- "). Indentation must use spaces, never tabs. Most YAML bugs come from bad indentation, unquoted special values like NO or 1.10, and colons or # inside plain text.

Why learn YAML properly

YAML (it stands for "YAML Ain't Markup Language") is the configuration format of Kubernetes, Docker Compose, GitHub Actions, GitLab CI and Ansible. A DevOps engineer reads and writes YAML every day. It looks simple, and that is the trap: one wrong space can change the meaning of a file or stop a deployment.

Scalars, maps and lists

A scalar is a single value: a string, a number, a boolean (true or false) or null (no value). A map (also called a dictionary or mapping) is a set of key: value pairs. There must be a space after the colon. A list (also called a sequence) is a set of items, each on its own line starting with a dash and a space.

yaml
# a comment starts with #
name: college-portal        # string
replicas: 3                 # integer
price: 49.5                 # float
debug: false                # boolean
owner: null                 # null (~ also means null)
ports:                      # a list
  - 80
  - 443
database:                   # a nested map
  host: db.internal
  port: 5432
Nesting is shown only by indentation. Items at the same level must line up exactly.

Lists and maps can nest inside each other. A list of maps is very common, for example a list of containers in Kubernetes or a list of tasks in Ansible. Short forms also exist: [80, 443] for a list and {host: db, port: 5432} for a map. This is called flow style, and it looks like JSON.

yaml
users:
  - name: asha
    shell: /bin/bash
  - name: ravi
    shell: /bin/zsh
tags: [web, prod]            # flow style list
A list of two maps. The keys of one item line up under the first key after the dash.

Indentation rules

YAML allows only spaces for indentation. Tabs are not allowed. Two spaces per level is the usual style. The exact number does not matter, but all items at the same level must have the same indentation, and a child must be indented more than its parent.

Quoting strings

Most strings need no quotes. Use quotes when the text could be misread. Single quotes take the text literally (write two single quotes to include one). Double quotes allow escapes such as \n for a new line.

yaml
country: "NO"               # without quotes, a YAML 1.1 parser reads this as false
version: "1.10"            # without quotes, this is the float 1.1
message: "Error: disk full" # a colon followed by a space inside plain text breaks parsing
colour: "#ff6600"          # without quotes, # starts a comment and the value is null
mode: "0644"               # without quotes, some parsers read 0644 as an octal number
greeting: 'It''s ready'    # two single quotes make one apostrophe
When in doubt, quote it.

The Norway problem

YAML 1.1, the older version still used by many parsers (including PyYAML, which Ansible uses), treats yes, no, on, off, y and n (in several capitalisations) as booleans. So a list of country codes with NO for Norway becomes false. YAML 1.2 fixed this: in its core schema only true and false are booleans. Because you rarely know which version a tool uses, quote any string that looks like a boolean, a number, a date or null.

Multi-line strings

yaml
script: |
  echo "line one"
  echo "line two"
description: >
  This long sentence is folded
  into a single line with spaces.
The pipe | keeps the new lines (good for scripts and certificates). The > folds lines into one, joined with spaces (good for long text).

Add a minus sign (|- or >-) to remove the final new line. Indent the text block more than its key.

Anchors and aliases

An anchor (&name) labels a value, and an alias (*name) reuses it, so you do not repeat yourself. Many tools also support the merge key <<, which copies a map into another one. The merge key comes from YAML 1.1 and is not part of the YAML 1.2 core, so check that your tool supports it.

yaml
defaults: &defaults
  restart: always
  log_level: info
web:
  <<: *defaults
  port: 8080
worker:
  <<: *defaults
  log_level: debug   # overrides the copied value
web and worker both get restart: always.

Many documents in one file

Three dashes (---) start a new document. Kubernetes uses this to keep a Deployment and a Service in one file. A file may also start with --- even if it has only one document; Ansible playbooks often do.

YAML and JSON

JSON is almost a subset of YAML 1.2: nearly every JSON file is also valid YAML. That is why flow style looks like JSON. The reverse is not true: comments, anchors and indentation-based nesting do not exist in JSON.

Common mistakes

  • A tab used for indentation: error "found character that cannot start any token". Set your editor to insert spaces for YAML.
  • Inconsistent indentation: a key indented by 3 spaces under siblings at 2 becomes a parse error or, worse, a different structure.
  • Forgetting the space after a colon or a dash: key:value is a plain string, not a map.
  • Unquoted special values: NO, yes, on, 1.10, 0644, 2026-10-19 (a date), ~ (null).
  • A colon and space, or a #, inside an unquoted value.
Tip: Use a linter such as yamllint, or your editor's YAML extension, and check a file before you push it. Many CI pipelines run yamllint on every pull request.

Need help?

Stuck on a word or an idea? Search this course, or every course, and jump straight to the explanation or a worked question.

Try:

Watch the lesson

YAML in depth · 1/8

YAML in depth

In this lesson you will learn YAML, the format behind Kubernetes, Compose, GitHub Actions and Ansible.

Prefer a video by a teacher? Find free videos on “yaml tutorial for beginners devops indentation anchors multi-line” on YouTube ↗

In real life: A broken CI pipeline in a Hyderabad startup

A team adds a Python test matrix to their CI config with python-version: [3.9, 3.10]. The 3.10 jobs fail with a strange message about Python 3.1. YAML read 3.10 as the float 3.1. The fix is to quote the versions. The same week, a release script for the Norway store of their e-commerce app breaks, because a list of country codes read NO as false. Both bugs were fixed by quoting, and the team added yamllint to every pull request.

yaml
python-version: ["3.9", "3.10", "3.11"]
countries: ["IN", "SG", "NO"]
Quoted, these stay strings.

Practice (0/3 done)

Task 1 · Question

A YAML 1.1 parser reads country: NO. What value does country get?

Task 2 · Code · Python

Parse a simple YAML-like config. Write parse_config(text) for this restricted format: - each line is "key: value" or "key:" (a key with nothing after the colon starts a nested map); - nesting is shown by indentation of 2 spaces per level; - blank lines and lines whose first non-space character is # are ignored; - values: a whole number (like 8080 or -5) becomes an int, true and false become booleans, text in double or single quotes keeps the text inside the quotes (as a string), anything else is a plain string. Return a dict (with nested dicts).

Task 3 · Code · Python

Find indentation errors. Write find_indent_errors(text) that returns a list of line numbers (starting at 1) where the leading whitespace contains a tab, or where the number of leading spaces is odd. Skip blank lines.

Quick quiz

Question 1

1.Which character is NOT allowed for indentation in YAML?

Question 2

2.version: 1.10 is parsed as what?

Question 3

3.Which block style keeps every new line of a shell script?

Question 4

4.What does --- mean in a YAML file?

Question 5

5.colour: #ff6600 (unquoted). What value does colour get?

Read more (free)

Open a question to see the answer and why. The first ones are this topic's own quiz, so try the quiz above before you peek.

Which character is NOT allowed for indentation in YAML?

Answer: Tab

YAML forbids tabs for indentation. Use spaces.

version: 1.10 is parsed as what?

Answer: The float 1.1

Unquoted, it is a number, and 1.10 equals 1.1. Quote version numbers.

Which block style keeps every new line of a shell script?

Answer: |

The literal style | keeps line breaks; > folds them into spaces.

What does --- mean in a YAML file?

Answer: The start of a new document

Kubernetes files often hold several resources separated by ---.

colour: #ff6600 (unquoted). What value does colour get?

Answer: null, because # starts a comment

After a space, # starts a comment, so the value is empty (null). Quote it.

Which is NOT allowed in YAML indentation?Related

Answer: Tabs

YAML forbids tabs for indentation.

From What Ansible is and how it works

Which data format do Ansible playbooks use?Related

Answer: YAML

Ansible playbooks are written in YAML, which uses indentation instead of braces.

From REST APIs and JSON

In an OpenAPI file, what is under paths -> /api/notes -> get?Related

Answer: The operation: summary, parameters and responses

Each path has methods, and each method (operation) lists its summary, parameters, request body and responses.

From Documenting your API with OpenAPI

Which option makes the JSON output multi-line and readable?Related

Answer: WriteIndented

WriteIndented = true pretty-prints the output.

From Files and JSON with System.Text.Json

Pass the quiz (60% or more) or mark this topic as done when you are ready.

Your progress is saved on this device only.

Next steps

  1. 3 more topics in “Configuration management with Ansible, and YAML” before its exam: Ansible: inventory and ad-hoc commands, Ansible playbooks, Roles, templates, Galaxy and Vault.
  2. Module 8 exam: Configuration management with Ansible, and YAML · 13 questions · 20 min, without help. 4 topics of this module still to finish first.
  3. Then the next module, Monitoring and logging. 53 topics left in the course before the final exam.

← Previous: Modules, environments and Terraform in CI