使用YAML创建一个 Kubernetes Depolyment

简介: 在之前的文章中,我们已经提到过如何使用Kubernetes去创建资源。到目前为止,我们一直仅仅通过命令行去执行,但是这里有一个更加简单有效的方式去创建资源:通过使用YAML创建一个配置文件。在这篇文章,我们将会关注YAML的工作方式以及如何使用YAML创建一个Kubernetes Pod,然后使用Kubernetes创建一个Depolyment。

在之前的文章中,我们已经提到过如何使用Kubernetes去创建资源。到目前为止,我们一直仅仅通过命令行去 执行,但是这里有一个更加简单有效的方式去创建资源:通过使用YAML创建一个配置文件。在这篇文章,我们将会关注YAML的工作方式以及如何使用YAML创建一个Kubernetes Pod,然后使用Kubernetes创建一个Depolyment。当然您如果是新手可以先了解Kubernetes上运行你的第一个容器

YAML 基础

如果你正在做的事与很多软件领域相关,那么将很难不涉及到YAML,特别是Kubernetes,SDN,和OpenStack。YAML,它代表着另一种标志语言,或者YAML不是标志语言(取决于你问谁)而是特定配置类型基于人类可读的文本格式的信息,例如,在本文中,我们将会分开说说明YAML定义创建Pod和使用Kubernetes创建一个Depolyment。

使用YAML用于k8s的定义将给你一些好处,包括:

  • 便捷性:你将不再需要添加大量的参数到命令行中执行命令
  • 可维护性:YAML文件可以通过源头控制,可以跟踪每次的操作
  • 灵活性:通过YAML你将可以创建比命令行更加复杂的结构

YAML是一个JSON的超集,意味着任何有效JSON文件也都是一个有效的YAML文件。所以一方面,如果你知道JSON,你只是要去写自己的YAML(而不是阅读别人的)也就可以了。另一方面,不太可能,不幸的是,尽管你尝试去网上找到例子,但是他们通常都不是JSON,所以我们可能需要去习惯它。不过,有JSON的情况下可能会更方便,这样你将会很开心你懂得JSON。

幸运的是,YAML只有两种结构类型你需要知道:

  • Lists
  • Maps

那就是说,将有可能存在lists的maps和maps的lists,等等,但是,你只要掌握了这两种结构也就可以了。这并不是说你不能做更加复杂的事,但是通常,这些也就够了。

YAML Maps

我们先开始看YAML maps。Maps让你将键值组合,你就可以更加方便的去设置配置信息。例如,你可能有以下这样一个配置信息:

---
apiVersion: v1
kind: Pod

第一行是分隔符,并且是可选的,除非你试图在单个文件中定义多个结构。从这里你可以看到,我们有两个值,V1和Pod,对应他们的键是apiVersion和kind。

这种比较简单,当然你也可以将之转换为json格式,如下:

{ "apiVersion": "v1", "kind": "Pod" }

注意,在我们的YAML版本中,引号是可选的,处理器可以知道你正在查看基于格式化的字符串。

你也可以指定一个复杂的结构,创建一个key其对应的值不是字符串而是一个maps如下所示:

---
apiVersion: v1
kind: Pod metadata:  name: rss-site  labels:  app: web

这种情况下,我们有metadata这个key对应的值中又有两个key分别为name和labels。labels 这个key的值又是一个map。你可以根据场景进行多层嵌套。

YAML处理器可以根据行缩进来知道内容之间的关联。在这个例子中我用了两个空格使之可读,但是空格的数量不重要,但是至少要求一个,并且所有缩进都保持一致的空格数。例如,name和labels是相同缩进级别,因此YAML处理器知道他们属于同一map;它知道app是lables的值因为app的缩进更大。

注意:在YAML文件中绝对不要使用tab键

因此,如果我们将上述内容翻译成JSON,它看起来结果如下所示:

{ "apiVersion": "v1", "kind": "Pod",  "metadata": {  "name": "rss-site",  "labels": {  "app": "web"  }  } }

现在让我们来看看lists。

YAML lists

YAML lists 简直是一个序列的对象,例如:

args
 - sleep
 - "1000" - message
 - "Bring back Firefly!"

正如你可以看到,你可以有任何数量的项在列表中,项的定义以破折号(-)开头,并且与父元素之间存在缩进。在JSON格式中,它将表示如下:

{ "args": ["sleep", "1000", "message", "Bring back Firefly!"] }

当然,list的子项也可以是maps,maps的子项也可以是list如下所示:

---
apiVersion: v1
kind: Pod
metadata:
 name: rss-site
 labels:
 app: web
spec:  containers:  - name: front-end  image: nginx  ports:  - containerPort: 80  - name: rss-reader  image: nickchase/rss-php-nginx:v1
 ports:  - containerPort: 88

正如你所看到的,我们有一个叫container的list对象,每个子项都由name、image、ports组成,每个ports都由一个key为containerPort map组成

如下所示,是上述内容的JSON格式:

{ "apiVersion": "v1", "kind": "Pod", "metadata": { "name": "rss-site", "labels": { "app": "web" } }, "spec": { "containers": [{ "name": "front-end", "image": "nginx", "ports": [{ "containerPort": "80" }] }, { "name": "rss-reader", "image": "nickchase/rss-php-nginx:v1", "ports": [{ "containerPort": "88" }] }] } }

正如你所看到的,我们写的内容开始变的复杂,甚至我们还没有进入任何特别复杂!难怪YAML代替JSON如此之快。

现在然我们复习一下,我们有:

  • maps,键值对
  • lists,单独的项
  • maps的maps
  • maps的lists
  • lists的lists
  • lists的maps

基本上,无论你想要什么样结构,你都可以通过这两个结构去组合实现。

使用YAML创建Pod

所以现在我们已经有了基础知识,让我们将他们用起来。我们将使用YAML创建一个Pod然后创建Deployment。

如果你还没有搭建起集群和kubectl,那么在你继续下去之前需要阅读之前关于如何搭建kubernets集群的文章,等搭建完成了我们再继续下去。
回来了?好的!让我们开始创建一个Pod。

创建Pod文件

在之前的例子中,我们通过YAML描述了一个简单的Pod文件内容:


apiVersion: v1
kind: Pod
metadata:
name: rss-site
labels:
app: web
spec:
containers:
– name: front-end
image: nginx
ports:
– containerPort: 80
– name: rss-reader
image: nickchase/rss-php-nginx:v1
ports:
– containerPort: 88

让我们分开来解析这些内容,先从apiVersion 这个关键字开始;这里它的值是v1.(当我们要创建Depolyment的时候,这个值将会指定一个不一样的值,因为Depolyment没有v1版本。)

接下来,我们指定我们要创建的是一个Pod;根据我们想要得到的结果,我们将会指定Pod而不是Deployment,Job,Services等等。

最后我们将指定组成pod的实际对象。spec属性包括一些containers,storage,volumes,或者其他Kubernetes需要知道的参数,以及诸如是否在容器失败时重新启动容器的属性。你可以在特定Kubernetes API找到完整的Kubernetes Pod的属性,让我们进一步来看一个典型的容器的定义:


spec:
containers:
– name: front-end
image: nginx
ports:
– containerPort: 80
– name: rss-reader

在这个例子中,这是一个简单的最小定义:一个名字(front-end),基于nginx的镜像,以及容器 将会监听的一个端口(80)。在这些当中,只有名字是非常需要的,但是通常如果你想做更多的事情,你需要更多的定义。

你也可以指定一个更加复杂的属性,例如在容器启动时运行的命令,应使用的参数,工作目录,或每次实例化时是否拉取映像的新副本。 您还可以指定更深入的信息,例如容器的退出日志的位置。

以下有一些容器可以设置的属性:

  • name
  • image
  • command
  • args
  • workingDir
  • ports
  • env
  • resources
  • volumeMounts
  • livenessProbe
  • readinessProbe
  • livecycle
  • terminationMessagePath
  • imagePullPolicy
  • securityContext
  • stdin
  • stdinOnce
  • tty

现在让我继续真正的去创建Pod。

使用YAML文件创建Pod
第一步,创建一个文本文件,叫做pod.yaml,然后添加我们之前定义的内容,如下所示:


apiVersion: v1
kind: Pod
metadata:
name: rss-site
labels:
app: web
spec:
containers:
– name: front-end
image: nginx
ports:
– containerPort: 80
– name: rss-reader
image: nickchase/rss-php-nginx:v1
ports:
– containerPort: 88

保存这个文件,让Kubernetes去执行内容所描述的动作:

> kubectl create -f pod.yaml
pod "rss-site" created

正如你所见,k8s 引用了你给pod的命名。如果你想看pods列表可以通过以下方式:

> kubectl get pods
NAME READY STATUS RESTARTS AGE
rss-site 0/2 ContainerCreating 0 6s

如果你更早的查看的话,你可以看到它仍然处于created的状态,大概几秒之后,你就可以看到容器处于running状态:

> kubectl get pods
NAME READY STATUS RESTARTS AGE
rss-site 2/2 Running 0 14s

至此,你可以测试以下Pod(正如我们之前文章做的),但是最后我们要创建一个Deployment,因此我们先删除这个pod以免发生名字冲突:

> kubectl delete pod rss-site
pod "rss-site" deleted

pod创建故障定位

有时候,事情并不会如我们所想的发展下去。可能你会遇到一个网络问题,或者在YAML文件用错了内容。你可能会看到以下类似以下的错误:

> kubectl get pods
NAME READY STATUS RESTARTS AGE
rss-site 1/2 ErrImagePull 0 9s

在这个情况下,我们可以看到我们其中一个容器启动正常,但是另一个出现了问题。我们可以用以下方式去查看pod的详细信息并定位这个问题:

> kubectl describe pod rss-site
Name: rss-site
Namespace: default Node: 10.0.10.7/10.0.10.7 Start Time: Sun, 08 Jan 2017 08:36:47 +0000 Labels: app=web
Status: Pending
IP: 10.200.18.2 Controllers: <none> Containers:
 front-end: Container ID: docker://a42edaa6dfbfdf161f3df5bc6af05e740b97fd9ac3d35317a6dcda77b0310759 Image: nginx
 Image ID: docker://sha256:01f818af747d88b4ebca7cdabd0c581e406e0e790be72678d257735fad84a15f Port: 80/TCP
 State: Running Started: Sun, 08 Jan 2017 08:36:49 +0000 Ready: True Restart Count: 0 Environment Variables: <none>
 rss-reader: Container ID: Image: nickchase/rss-php-nginx
 Image ID: Port: 88/TCP
 State: Waiting Reason: ErrImagePull Ready: False Restart Count: 0 Environment Variables: <none> Conditions: Type Status Initialized True Ready False PodScheduled True No volumes. QoS Tier: BestEffort Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ ------- 45s 45s 1 {default-scheduler } Normal Scheduled Successfully assigned rss-site to 10.0.10.7 44s 44s 1 {kubelet 10.0.10.7} spec.containers{front-end} Normal Pulling pulling image "nginx" 45s 43s 2 {kubelet 10.0.10.7} Warning MissingClusterDNS kubelet does not have ClusterDNS IP configured and cannot create Pod using "ClusterFirst" policy. Falling back to DNSDefault policy. 43s 43s 1 {kubelet 10.0.10.7} spec.containers{front-end} Normal Pulled Successfully pulled image "nginx" 43s 43s 1 {kubelet 10.0.10.7} spec.containers{front-end} Normal Created Created container with docker id a42edaa6dfbf
 43s 43s 1 {kubelet 10.0.10.7} spec.containers{front-end} Normal Started Started container with docker id a42edaa6dfbf
 43s 29s 2 {kubelet 10.0.10.7} spec.containers{rss-reader} Normal Pulling pulling image "nickchase/rss-php-nginx"  42s 26s 2 {kubelet 10.0.10.7} spec.containers{rss-reader} Warning Failed Failed to pull image "nickchase/rss-php-nginx": Tag latest not found in repository docker.io/nickchase/rss-php-nginx  42s 26s 2 {kubelet 10.0.10.7} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "rss-reader" with ErrImagePull: "Tag latest not found in repository docker.io/nickchase/rss-php-nginx"  41s 12s 2 {kubelet 10.0.10.7} spec.containers{rss-reader} Normal BackOff Back-off pulling image "nickchase/rss-php-nginx"  41s 12s 2 {kubelet 10.0.10.7} Warning FailedSync Error syncing pod, skipping: failed to "StartContainer" for "rss-reader" with ImagePullBackOff: "Back-off pulling image \"nickchase/rss-php-nginx\""

正如你所见,这里有很多信息,但是最有用的信息在Events中,详细的显示出了曾经出现的警告和错误信息。从这里我们可以很快的看出,我忘记将:有v1 标签的镜像,所以它用了最新的镜像,但是它不存在。

为了解决这个问题,我先删了这个Pod,然后修复YAML文件,重新启动。我修复了之后Kubernetes 将能够从镜像库中到到,之后也就能够安装下去了。

现在我们已经成功运行了一个Pod,接下让让我们同样的运行Deployment。

使用YAML文件创建Deployment
最后,我们将要进行真正的创建Depolyment。在那之前,我们必须了解它实际上是在做什么。

k8s,记住和管理基于容器的资源。在这个Deployment的例子中,你正在创建一组要管理的资源。例如,在之前的例子中,我们给Pod创建了一个实例,我们将创建一个Deployment去让Kubernetes管理一组Pod的副本,也就是副本集,保证一定数量的副本一直可用。因此我们可以这样定义一个Deployment:


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: rss-site
spec:
replicas: 2

这里我们指定了apiVersion为extensions/v1beta1,记住,Deployments并不像Pods是v1,我们这里想要的是Deployments。接下来我们指定名字,我们也可以指定我们想要的元数据,但是我们现在尽量保持简单。

最后,我们进入配置spec项,我们之前在其中指定我们想要在Pod中做的事;同样的我们也需要在其中指定Deployment中做的事。我们将开始,在这种情况下,通过说我们部署的任何Pod,我们总是想有2个副本。 当然,你可以设置这个数字,你还可以设置属性,如定义受此Deployment影响的Pod的选择器,或者一个Pod在没有任何错误变成准备的情况下必须达到的最小秒数。

你可以在Kubernetes v1beta1 API参考中找到一个完整的Depolyment可指定的参数列表。

因此目前我们想要创建两个副本,我们需要知道我们做的是什么的副本?他们可以通过以下模板定义:


apiVersion: extensions/v1beta1
kind: Deployment
metadata:
name: rss-site
spec:
replicas: 2
template:
metadata:
labels:
app: web
spec:
containers:
– name: front-end
image: nginx
ports:
– containerPort: 80
– name: rss-reader
image: nickchase/rss-php-nginx:v1
ports:
– containerPort: 88

看起来很熟悉?没错,它和我们之前的Pod定义很类似,它就是这么设计的。模板是对要复制的对象的简单定义,在其他情况下,可以通过自己创建的对象。

现在让我们继续创建Deployment。添加一个叫做deployment.yaml文件并执行以下命令:

> kubectl create -f deployment.yaml
deployment "rss-site" created

想要查看它正在做的情况,我们可以检查Deployment的列表:

> kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
rss-site 2 2 2 1 7s

正如你所看到的,Kubernetes启动了所有的副本,但是只有一个可用。你可以如之前一样查看event日志对Deployment的描述:

> kubectl describe deployment rss-site
Name: rss-site
Namespace: default CreationTimestamp: Mon, 09 Jan 2017 17:42:14 +0000= Labels: app=web
Selector: app=web
Replicas: 2 updated | 2 total | 1 available | 1 unavailable
StrategyType: RollingUpdate MinReadySeconds: 0 RollingUpdateStrategy: 1 max unavailable, 1 max surge
OldReplicaSets: <none> NewReplicaSet: rss-site-4056856218 (2/2 replicas created) Events: FirstSeen LastSeen Count From SubobjectPath Type Reason Message --------- -------- ----- ---- ------------- -------- ------ -------  46s 46s 1 {deployment-controller } Normal ScalingReplicaSet Scaled up replica set rss-site-4056856218 to 2

你可以看到,并没有什么问题,他只是还没创建好副本。再过一会之后,我们发现所有的Pods正在运行:

> kubectl get deployments
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
rss-site 2 2 2 2 1m

到目前为止我们所看到的

让我们复习以下,我们基本上涵盖了三个主题:

  1. YAML是一种基于人类可读的基于文本的格式,通过使用名称 – 值对映射和项目列表(以及每个项目的嵌套版本)的组合,您可以轻松地指定配置类型信息。
  2. YAML是使用Kubernetes对象的最方便的方法,在本文中,我们考虑创建Pods和Deployments。
  3. 您可以通过要求Kubernetes描述它们来获取关于运行(或应该运行)对象的更多信息。

这是我们的基本YAML教程。我们将在未来几个月内处理大量与Kubernetes相关的内容。

本文转自中文社区-使用YAML创建一个 Kubernetes Depolyment

相关实践学习
通过Ingress进行灰度发布
本场景您将运行一个简单的应用,部署一个新的应用用于新的发布,并通过Ingress能力实现灰度发布。
容器应用与集群管理
欢迎来到《容器应用与集群管理》课程,本课程是“云原生容器Clouder认证“系列中的第二阶段。课程将向您介绍与容器集群相关的概念和技术,这些概念和技术可以帮助您了解阿里云容器服务ACK/ACK Serverless的使用。同时,本课程也会向您介绍可以采取的工具、方法和可操作步骤,以帮助您了解如何基于容器服务ACK Serverless构建和管理企业级应用。 学习完本课程后,您将能够: 掌握容器集群、容器编排的基本概念 掌握Kubernetes的基础概念及核心思想 掌握阿里云容器服务ACK/ACK Serverless概念及使用方法 基于容器服务ACK Serverless搭建和管理企业级网站应用
相关文章
|
3月前
|
JSON Kubernetes API
深入理解Kubernetes配置:编写高效的YAML文件
深入理解Kubernetes配置:编写高效的YAML文件
|
2月前
|
Kubernetes 应用服务中间件 nginx
k8s学习--YAML资源清单文件托管服务nginx
k8s学习--YAML资源清单文件托管服务nginx
k8s学习--YAML资源清单文件托管服务nginx
|
2月前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
93 3
|
2月前
|
Kubernetes Docker Perl
k8s常见故障--yaml文件检查没有问题 pod起不来(一直处于创建中)
k8s常见故障--yaml文件检查没有问题 pod起不来(一直处于创建中)
125 1
|
4月前
|
存储 Kubernetes 数据格式
精通Kubernetes:利用YAML轻松管理资源
精通Kubernetes:利用YAML轻松管理资源
|
4月前
|
JSON Kubernetes 数据格式
k8s集群yaml文件方式迁移
k8s集群yaml文件方式迁移
|
4月前
|
Kubernetes API 容器
在K8S中,deployment的yaml文件如何编写呢?
在K8S中,deployment的yaml文件如何编写呢?
|
4月前
|
Kubernetes 应用服务中间件 nginx
在K8S中,deploy的yaml如何编写?
在K8S中,deploy的yaml如何编写?
|
4月前
|
Kubernetes API 容器
Kubernetes(K8S) yaml 介绍
Kubernetes(K8S) yaml 介绍
43 0
|
3天前
|
Kubernetes 网络协议 应用服务中间件
Kubernetes Ingress:灵活的集群外部网络访问的利器
《Kubernetes Ingress:集群外部访问的利器-打造灵活的集群网络》介绍了如何通过Ingress实现Kubernetes集群的外部访问。前提条件是已拥有Kubernetes集群并安装了kubectl工具。文章详细讲解了Ingress的基本组成(Ingress Controller和资源对象),选择合适的版本,以及具体的安装步骤,如下载配置文件、部署Nginx Ingress Controller等。此外,还提供了常见问题的解决方案,例如镜像下载失败的应对措施。最后,通过部署示例应用展示了Ingress的实际使用方法。
18 2