如何为Kubernetes编写YAML文件?

作者:Ben Hirschberg 编译:沈建苗

虽然Kubernetes越来越受欢迎,但学习曲线仍然很陡峭,因而很难采用该技术。如果用户无法克服这道最初的障碍,常常会在快节奏的软件开发领域成为落伍者。

本文介绍配置Kubernetes对象的YAML文件。YAML提供了一种声明式配置Kubernetes应用程序的方法,这种声明性文件让你可以有效地扩展和管理应用程序。如果不了解Kubernetes对象配置方面的基础知识,很容易掉入这个陷阱:在没有真正了解应用程序如何运作的情况下贸然运行。

要注意的是,用于配置Kubernetes时,YAML和JSON可相互换用。然而,尽管YAML在一些情况下被认为更难编写,但异常紧凑。在考虑为大型应用程序管理所有YAML文件时,这是一大优势。

总体而言,YAML往往对用户更友好,紧凑性让你可以将相关的Kubernetes对象分组,从而减少所需的文件数量。这是由于YAML的设计目标是,增强可读性,并提供更完整的信息模型。它可以简单地看作是JSON的演进。

YAML for Kubernetes

要开始使用YAML for Kubernetes,我们不妨探讨YAML的基本结构类型,可以在下表中看到:

为Kubernetes编写YAML文件时,必须存在四个必需的字段:APIVersion、Kind、Metadata和Specifications。

apiVersion

该字段指的是API,它用于创建所定义的Kubernetes对象。 Kubernetes提供各种API,使你能够创建不同的Kubernetes对象。比如说,apiVersion: v1含有许多核心对象。

apiVersion: v1通常被认为是Kubernetes的第一个稳定版本。另一个流行的APIVersion是apps/v1,它采用v1中的对象,并提供了关键功能,比如部署和ReplicaSet。

因此,在我们的YAML文件中,定义APIVersion可能是:apiVersion:v1。

kind

kind让你可以指定要定义的Kubernetes对象类型。该字段中指定的对象将链接到之前指定的apiVersion,因为APIVersion字段使你能够访问不同类型的对象及其特定定义。可以定义的一些对象类型有pod、服务和DaemonSet。

因此若要定义pod对象,在指定apiVersion之后,我们将指定kind字段,如下所示:

apiVersion:v1
kind:pod

metadata

指定要定义的对象类型后,metadata(元数据)字段提供了该特定对象的独特属性。这可能包括name、uuid和namespace等字段。为这些字段指定的值为我们提供了对象的上下文,它们可以被其他对象所引用。因此,该字段允许我们指定对象的标识符属性。

比如说,如果我们在构建一个spring应用程序,pod可能具有如下所示的名称值:

apiVersion: v1
kind: Pod

metadata:

  name: spring-pod

spec

spec字段允许我们定义对构建的对象有何要求。它由定义对象操作所特有的所有键值对组成。就像对象本身一样,对象的规范取决于之前指定的apiVersions。因此,不同的APIVersions可能含有同一个对象,但可以定义的对象规范可能有所不同。

如果我们继续以构建Spring应用程序的pod对象为例,spec字段可能类似你在下面看到的内容:

apiVersion: v1
kind: Pod

metadata:

name: spring-pod

containers:

– image: armo/springapp:example

spec:

name: spring-app

ports:

– containerPort: 80

protocol: TCP

在上面最后一个示例文件中,我们使用API v1创建了Pod对象,并将其命名为spring-pod。按照规范,我们将使用的端口是80,要使用的镜像是armo/springapp:example。

下图比较了JSON和YAML中的配置。如你所见,YAML极其简洁易读。

图1:将JSON与YAML进行比较

管理YAML文件的几种策略

我们已构建了Kubernetes YAML文件,不妨看看进一步加快构建Kubernetes应用程序的几种策略。

YAML版本控制

如上所述,使用YAML字段允许你以声明式管理Kubernetes应用程序。这些YAML文件可以存储在一个公共目录中,可以使用kubectl apply -f <directory>来全部应用。

这相当简单。不过,随着应用程序的发展,加上对Kubernetes对象定义所作的更改,你要考虑目前部署了哪个版本和哪种变更。这是由于如果没有版本控制,可能无法回滚到以前的镜像,而旧镜像可能比新的活动镜像更稳定。

有几种方法可以处理YAML版本控制,复杂性和易管理性各不相同。这可能需要在YAML中使用简单的标签以及手动的kubectl命令,或者可能需要使用Helm之类的特殊工具。详细介绍这每种方法超出了本文的范围,但值得一提的是,版本控制是一种重要的做法。

管理Secrets

在应用程序的整个生命周期中,你可能需要使用机密数据来支持其功能。这可能包括密码、用户信息,甚至信用卡详细信息。

在定义Kubernetes对象时,你可以将这些数据作为变量直接放入到YAML文件中。但是这可能导致重大的安全漏洞,并加大这些数据落入坏人之手的可能性。因此,建议使用Kubernetes提供的Secrets(机密)对象以及Secrets管理工具。

在使用Secrets对象时,pod必须引用Secret。所以,这时候我们要使用metadata字段。pod将使用Secret name字段,其中Secret对象的名称将是有效的DNS子域名。

定义的Secrets对象的示例如下所示:

apiVersion: v1

kind: Secret

metadata:

name: mysecret

 type: Opaque

data:

 username: YWRtaW4=

 password: MWYyZDFlMmU2N2Rm

请务必记下Secret类型。在上面的示例中,我们将Secrets类型指定为不透明。这是Secret对象的默认类型。另一种Secret类型是kubernetes.io/service-account-token,用于存储服务帐户标识符令牌。

YAML模板

YAML模板旨在通过面对众多Kubernetes应用程序重用YAML文件,以减少要编写和管理这些文件的数量。比如说,不妨考虑下面的pod定义:

apiVersion: v1

kind: Pod

metadata:

name: spring-pod

spec:

containers:

– image: armo/springapp:example

name: spring-app

env:

– name: eu-west-1

value: postgres://db_url:5432

该pod将位于eu-west-1区域。然而,如果我们想为美国的客户部署到us-west-1,将不得不编写一个新的YAML文件,因为我们使用硬编码值。

解决这个问题的办法是YAML模板,它允许我们重用具有不同值的YAML文件。 YAML模板有几种方法,但最基本的方法是搜索和替换我们在YAML文件中使用占位符的对应值。

因此,使用原来那个示例,我们在env字符下将有一个占位符值,如下所示:

apiVersion: v1

kind: Pod

metadata:

name: spring-pod

spec:

containers:

– image: armo/springapp:example

name: spring-app

env:

– name: ENV

value: %DEPLOYMENT_ENV%

如果在bash中利用sed,我们可以在处理YAML文件之前搜索和替换这些值。然而,这是最基本、最不方便的方法,因为你必须手动执行占位符的硬编码。

一种更方便的方法是利用Helm之类的工具来构建和管理模板。

结论

由于YAML的结构方式及其设计目标,它是Kubernetes配置的最佳解决方案。加强的可读性和简洁结构允许你扩展Kubernetes配置,而不迷失在大量的配置文件中。

此外,如果了解如何以声明式构建Kubernetes应用程序,我们还可以了解Kubernetes应用程序运行方式和原因方面的机制。考虑YAML模板等高级功能有助于简化定义和构建Kubernetes应用程序的过程。

参考链接:https://www.cncf.io/blog/2022/03/03/how-to-write-yaml-file-for-kubernetes/

K8S中文社区微信公众号

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址