With the following YAML file:
why does policyTypes
contain a list but metadata
doesn't?
why does ports
have 1 list item below it (i.e. protocol
) whereas port
doesn't?
I'm not interested in the Kubernetes side of things just the YAML syntax.
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
name: test-network-policy
namespace: default
spec:
podSelector:
matchLabels:
role: db
policyTypes:
- Ingress
- Egress
ingress:
- from:
- ipBlock:
cidr: 172.17.0.0/16
except:
- 172.17.1.0/24
- namespaceSelector:
matchLabels:
project: myproject
- podSelector:
matchLabels:
role: frontend
ports:
- protocol: TCP
port: 6379
egress:
- to:
- ipBlock:
cidr: 10.0.0.0/24
ports:
- protocol: TCP
port: 5978
E.g. syntactically this is valid YAML:
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
- name: test-network-policy
- namespace: default
How is it different (from a YAML standpoint) to the first example?
policyTypes
contain a list but metadata
doesn't?As written in kubernetes API Reference docs policyTypes
field is a string array
(in YAML data structure called a list) what means that it is a collection of values. For these particular objects only these 2 values can be specified (but standard YAML list allows to extend the values amount).
policyTypes:
- Ingress
- Egress
Metadata
is a map- it consists of key value pairs but can be further expanded by adding another map to it- for example labels
field in metadata
section:
apiVersion: v1
kind: Pod
metadata:
name: podname
labels:
key: value
[...]
All lines must be prefixed with the same amount of spaces to belong to the same map
Similar as before- ports
field is a map inside list
and for NetworkPolicy
object only port
and protocol
can be specified. Definition of port
field:
The
port
on the given protocol. This can either be a numerical or named port on a pod. If this field is not provided, this matches all port names and numbers.
So it is key: value
pair, same as protocol
field.
Completely ignoring the Kubernetes context: YAML has sequences and mappings (exactly like JSON arrays and objects). Everywhere you have a -
marker it's a list item; everywhere there is a key: value
pair it is a mapping. You can have one inside the other.
ports:
- protocol: TCP
port: 6379
# is equivalent to
ports: [{"protocol": "TCP", "port": 6379}]
metadata:
name: test-network-policy
namespace: default
# is equivalent to
metadata: {"name": "test-network-policy", "namespace": "default"}
metadata:
- name: test-network-policy
- namespace: default
# is equivalent to
metadata: [
{"name": "test-network-policy"},
{"namespace": "default"}
]
The differences between mappings and sequences matters, and if the application expects a mapping but actually gets a sequence of mappings (compare the two metadata:
blocks) you'll get an application-level error.
A pattern that does appear in the Kubernetes API but can be a little confusing is to have a list of objects with some logical "kind". Volumes within a pod spec are a good example. These each have a key to say what kind they are, but you're allowed to have multiple volumes of the same kind, so a mapping isn't the right structure.
volumes:
# This is a list of mappings
- name: logs
emptyDir: {}
- name: coreDumps
emptyDir: {}