12
votes

I'm using k8s 1.11.2 to build my service, the YAML file looks like this:

Deployment

apiVersion: apps/v1beta2
kind: Deployment
metadata:
  name: nginx-test
  namespace: default
  labels:
  - type: test 
spec:
  replicas: 1
  selector:
    matchLabels:
    - type: test 
  template:
    metadata:
      labels:
      - type: test 
    spec:
      containers:
      - image: nginx:1.14
        name: filebeat
        ports:
        - containerPort: 80

Service

apiVersion: v1
kind: Service
metadata:
    labels:
    - type:test
spec:
  type: ExternalName
  externalName: my.nginx.com
  externalIPs:
  - 192.168.125.123
  clusterIP: 10.240.20.1
  ports: 
  - port: 80
    name: tcp
  selector:
  - type: test

and I get this error:

error validating data: [ValidationError(Service.metadata.labels): invalid type for io.k8s.apimachinery.pkg.apis.meta.v1.ObjectMeta.labels: got "array", expected "map", ValidationError(Service.spec.selector): invalid type for io.k8s.api.core.v1.ServiceSpec.selector: got "array", expected "map"];

I am sure the format of my YAML file is right, because I used the website http://www.yamllint.com/ to validate it.

Why am I getting this error?

4
My question is: Why isn't it showing WHICH LINE NUMBER the error is at? In a large yaml file this error is totally useless, as I don't know where it is. Is it too much to ask for kubectl to tell us where it found the error? - Markus Bawidamann

4 Answers

30
votes

yamllint.com is a dubious service because it does not tell us which YAML version it is checking against and which implementation it is using. Avoid it.

More importantly, while your input may be valid YAML, this does not mean that it is a valid input for kubernetes. YAML allows you to create any kind of structure, while kubernetes expects a certain structure from you. This is what the error is telling you:

got "array", expected "map"

This means that at a place where kubernetes expects a mapping you provided an array (sequence in proper YAML terms). The error message also gives you the path where this problem occurs:

ValidationError(Service.metadata.labels):

A quick check on metadata labels in kubernetes reveals this documentation, which states that labels need to be mappings, not arrays.

So in your input, the last line here is the culprit:

metadata:
  name: nginx-test
  namespace: default
  labels:
  - type: test

- is a YAML indicator for a sequence item, creating a sequence as value for the key labels:. Dropping it will make it a mapping instead:

metadata:
  name: nginx-test
  namespace: default
  labels:
    type: test
6
votes

In yaml formatting the character "-" implies the start of an array.

You have:

apiVersion: v1
kind: Service
metadata:
    labels:
    - type:test

You want:

apiVersion: v1
kind: Service
metadata:
    labels:
      type:test
2
votes

The problem is in your second file:

apiVersion: v1
kind: Service
metadata:
    labels:
    - type:test
        #  ^

Above the caret (^) it is missing a space making type:test a single scalar (string) instead of the mapping which is what you get through using

apiVersion: v1
kind: Service
metadata:
    labels:
    - type: test

and what is that you program expects.

Both are valid YAML so primitive syntax checking doesn't help you.

1
votes

Rendering of values from values.yaml to config.yaml :

values.yaml :


sites:
  - dataprovider: abcd
  - dataprovider: xyzx

config.yaml :


     sites:
 {{ toYaml .Values.sites | indent 10 }}