在此上下文中不允许映射值。

54

我对YAML格式和Kubernetes都很新手。

以下是一个dep_prom.yml文件。

---
apiVersion: extensions/v1beta1
kind: Deployment
metadata:
  labels:
    name: prometheus-deployment
  name: prometheus
  #namespace: prometheus
spec:
  replicas: 1
  template:
    metadata:
      labels:
        app: prometheus
    spec:
      containers:
      - image: prom/prometheus:master
        name: prometheus
        command:
        - "/bin/prometheus"
        args:
        - "-config.file=/etc/prometheus/prometheus.yml"
        - "-storage.local.path=/prometheus"
        - "-storage.local.retention=24h"
        ports:
        - containerPort: 9090
          protocol: TCP
        volumeMounts:
        - mountPath: "/prometheus"
          name: data
        - mountPath: "/etc/prometheus"
          name: config-volume
        resources:
          requests:
            cpu: 100m
            memory: 100Mi
          limits:
            cpu: 500m
            memory: 2500Mi
      volumes:
      - name: data
        hostPath:
          path: /data/prometheus
      - name: config-volume
        configMap:
          name: prometheus
      nodeSelector: westporch-kubeminion-1
        kubernetes.io/hostname: 10.0.24.52
---

然而...当我执行kubectl create -f dep_prom.yml

错误:将YAML转换为JSON出错:yaml: 第47行:在此上下文中不允许映射值

第47行是nodeSelector:westporch-kubeminion-1

我认为YAML文件格式是正常的。

是什么导致了这个错误?


1
删除 westporch-kubeminion-1nodeSelector 是一个映射而不是单值字段。 - fishi0x01
12个回答

42
你表示认为YAML格式是正常的,但实际上它并不是。这是一个YAML错误,原因是在第一个文档的末尾有一行以kubernetes.io/hostname开头的缩进相对于前面的那一行而言。由于这两行都是键值对行(即块样式映射的项对),而不是闭合标签。


      nodeSelector: westporch-kubeminion-1
        kubernetes.io/hostname: 10.0.24.52

你需要执行以下操作:

      nodeSelector: westporch-kubeminion-1
      kubernetes.io/hostname: 10.0.24.52

但可能需要将nodeSelector的参数映射而不是现在它所拥有的标量westporch-kubeminion-1

      nodeSelector:
        kubernetes.io/hostname: 10.0.24.52
这个错误可能掩盖了文件中的第二个错误,这取决于kubernetes有多宽容。 ---是指令结束标记,由于指令是可选的,因此它可以出现在YAML文档的开头。您示例底部的一行表示开始一个新文档。解决第一个错误后,您可能会收到有关基于该错误的单个文档的警告。(文档结尾标记由前面带有空格的三个点 ... 组成)。当然,您所做的任何更改都应符合kubernetes的要求,但是以上流程本身在YAML中显然无效。

12

在我的案例中,错误的原因是yaml文件中第一行为空。

当遇到此类错误时,我强烈建议将yaml文件粘贴到YAML Linters(例如这个)中,有时可以更快地识别问题所在。


7
大多数情况下,当您遇到这样的错误(一般而言)时,要么是因为:-
1). yaml文件中存在语法错误(在您的情况下不是),请使用YAML linter确保您的语法正确。(感谢@rtmy的回答,我现在在此处包括YAML Linter。)
2). 或者像错误提示所说,“mapping values are not allowed in this context”。这意味着您在yaml中使用的键/值可能在语法上是正确的,但在语义上不正确。
例如,在您的情况下,上下文是“deployment”,它属于“apiversion: extensions/v1beta1”,并且它期望节点选择器如下所示:-
nodeSelector:
  kubernetes.io/hostname: 10.0.24.52

理想情况下,您不应该像上面那样使用IP地址,而是使用类似这样的键值对:- topologyKey: failure-domain.beta.kubernetes.io/zone 或者在您的情况下,可以使用类似这样的键值对:- kubernetes.io/hostname: zone-a-node

7
有时候在YAML文件中,如果使用特殊字符,比如:,则需要将整行内容放在单引号'中。
可以查看GitLab文档中的这个例子:https://docs.gitlab.com/ee/ci/yaml/README.html#script 有时候,脚本命令必须用单引号(')或双引号括起来。例如,包含冒号(:)的命令必须用单引号括起来,以便YAML解析器将文本解释为字符串而不是“key: value”对。
例如,以下脚本使用了冒号:*
job:
  script:
    - curl --request POST --header 'Content-Type: application/json' "https://gitlab/api/v4/projects"

为了被视为有效的YAML,您必须将整个命令用单引号括起来。如果命令已经使用了单引号,如果可能应该将其改为双引号("):

job:
  script:
    - 'curl --request POST --header "Content-Type: application/json" "https://gitlab/api/v4/projects"'

5
在我的情况下,问题归结于YAML文件的缩进格式。我被指向了与错误无关的一行。我不得不将该文件与我拥有的另一个项目进行比较。在https://www.kubeval.com上的工具对于验证我已经找到并解决了问题很有用。

3

正如大多数人所提到的,yaml文件可能存在一些问题,由于yaml文件通常会变得混乱,很难确定问题所在。

幸运的是,可以使用像yaml lint这样的工具轻松地识别问题,您可能不需要社区的帮助。

安装它。

npm install -g yaml-lint

以下是如何进行验证的步骤:

E:\>yamllint docker-compose.yaml
√ YAML Lint successful.

3

虽然不是直接回答问题,但这可能会帮助其他遇到相同错误信息的人:

在我的情况下,我正在构建管道中进行令牌替换,以设置YAML文件中的Docker镜像标记。而我读取要替换的值时出现了错误,因此它被设置为空字符串。

所以,替换结果不是这样的:

my_image_name:1.0.0

实际上我得到的是:

my_image_name:

这被解释为一个没有值的YAML映射或字典键,因此出现了错误信息。


1

如前所述,nodeSelector不能有那样的值。它是用来指定键值对映射的。您可以在此处阅读更多关于具体用法的信息。例如,正确使用nodeSelector的示例可能是:

    nodeSelector:
       disktype: ssd

1

在我的情况中,我发现这是一个标准的缩进错误,如果你的YAML有正确的缩进,它就会消失。


你的回答可以通过提供额外的支持信息来改进。请 [编辑] 添加更多细节,例如引用或文档,以便他人可以确认您的答案是否正确。您可以在 帮助中心 中找到有关编写好答案的更多信息。 - Community

1
如果您复制/粘贴,请确保破折号“-”是预期的字符。在我的情况下,它是一个不同的字符。
这是可以接受的:
  volumes:
    - name: docker-data

这是错误的:

  volumes:
    —name: docker-data

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接