03 YAML文件

前面我们的kubernets集群已经搭建成功了,现在我们就可以在集群里面来跑我们的应用了。要在集群里面运行我们自己的应用,首先我们需要知道几个概念。

第一个当然就是应用的镜像,因为我们在集群中运行的是容器,所以我们首先需要将我们的应用打包成镜像,前面的文章已经学习过如何将应用打包成镜像,这里不再赘述。

镜像准备好了,k8s集群也准备好了,其实我们就可以把我们的应用部署到集群中了。但是镜像到集群中运行这个过程是如何完成的呢?必然有一个地方可以来描述我们的应用,然后把这份描述告诉k8s集群,然后集群按照这个描述来部署应用。

在之前Docker环境下面我们直接通过命令docker run来运行我们的应用,在k8s环境下我们同样也可以用类似kubectl run这样的命令来运行我们的应用,但是在k8s中却不推荐使用命令行的方式,而是希望使用我们称为资源清单的东西来描述应用,资源清单可以用YAML或者JSON文件来编写,一般来说YAML文件更方便阅读和理解,所以我们使用YAML文件来进行描述。

通过一个资源清单文件来定义好一个应用后,我们就可以通过kubectl工具来直接运行它:
kubectl create -f xxx.yaml

我们知道kubectl是直接操作APIServer的,所以就相当于把我们的清单提交给了APIServer,然后集群获取到清单描述的应用信息后存储到etcd数据库中,然后kube-scheduler组件发现这个时候有一个Pod还没有绑定到节点上,就会对这个Pod进行一系列的调度,把它调度到一个最合适的节点上,然后把这个节点和Pod绑定到一起(信息再写回etcd),然后节点上的kubelet组件这个时候watch到有一个Pod被分配过来了,就去把这个Pod的信息垃取下来,然后根据描述通过容器运行时把容器创建出来,最后当然同样把Pod状态再写回道etcd中去,这样就完成了一整个的创建流程。

第一个容器化应用

apiVersion: apps/v1 # 新版本的deployment都使用这个apiVersion
kind: Deployment # API对象类型,也就是资源对象类型
metadata: # 资源对象的元信息
  name: nginx-deploy # deployment的名称
  namespace: default # 如果不写的话就默认是default命名空间的
  labels: # 标识或过滤
    chapter: first-app
spec: 
  selector: # required,必须填写的。当资源对象类型是Deployment时
    matchLabels: # Lable selector,匹配标签(labels),下面一行就是要匹配的值,即匹配的就是 "app:nginx"标签
      app: nginx # Pod的标签  "此处是第11行"
  replicas: 2 # Pod副本数
  template: # Pod 模版
    metadata: # Pod的元信息
      labels: # Pod的Label标签
        app: nginx # 此处和"第11行必须是一致的"
    spec:
      containers: # Pod下面有多个容器
      - name: nginx # 容器名称
        image: nginx:1.7.9 #使用的镜像名称
        ports: # 容器暴露的端口
          - containerPort: 80
          - containerPort: 443

Deployment 这个资源对象就是用来定义多副本应用的对象,而且还支持对每个副本进行滚动更新,上面我们的资源清单中的描述中有一个属性 replicas: 2,所以最后生成两个副本的 Pod。
而这个 Deployment 定义的副本 Pod 具体是什么样的,是通过下面的 Pod 模板来定义的,就是 template 下面的定义,这个模板中定义了我们的 Pod 中只有一个名为 nginx 的容器,容器使用的镜像是 nginx:1.7.9(spec.containers[0].image),并且这个容器监听的端口是 80(spec.containers[0].ports[0].containerPort),另外我们还为 Pod 添加了一个app: nginx这样的 Label 标签,这里需要非常注意的是上面的 selector.matchLabels 区域就是来表示我们的 Deployment 来管理哪些 Pod 的,所以这个地方需要和 Pod 模板中的 Label 标签保持一致,这个 Label 标签之前我们也提到过是非常重要的。
另外我们也可以发现每个 API 对象都有一个 Metadata 的字段,用来表示该对象的元数据的,比如定义 name、namespace 等,比如上面 Deployment 和 Pod 模板中都有这个字段,至于为什么 Pod 模板中没有 name 这个元信息呢,这是因为 Deployment 这个控制器会自动在他自己的 name 基础上生成 Pod 名,不过 Deployment 下面定义的 Label 标签就没有 Pod 中定义的 Label 标签那么重要了,只是起到一个对该对象标识和过滤的作用。比如我们在查询对象的时候可以带上标签来进行过滤。

然后直接用 kubectl 命令来创建这个应用:

[root@master my_kubernets_yaml]# kubectl create -f nginx-deployment.yaml  # 创建应用
deployment.apps/nginx-deploy created

[root@master my_kubernets_yaml]# kubectl get pods  #查看Pod
NAME                            READY   STATUS    RESTARTS   AGE
nginx-deploy-7cb4fc6c56-8ljb7   1/1     Running   0          84s
nginx-deploy-7cb4fc6c56-9fnjs   1/1     Running   0          84s

[root@master my_kubernets_yaml]# kubectl get pods  -l app=nginx # 或者加个标签过滤
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deploy-7cb4fc6c56-8ljb7       1/1     Running   0          33m
nginx-deploy-7cb4fc6c56-9fnjs       1/1     Running   0          33m

[root@master my_kubernets_yaml]# kubectl get deployment  #查看deployment
NAME           READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy   2/2     2            2           8m17s

[root@master my_kubernets_yaml]# kubectl get deployment -l chapter=first-app # 或者加个标签过滤
NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deploy       2/2     2            2           29m

我们可以看到会在集群中生成两个 Pod 出来。而整个资源清单文件对应到 Kubernetes 中就是一个 API Object(API 对象),我们按照这些对象的要求填充上对应的属性后,提交给 Kubernetes 集群,就可以为我们创建出对应的资源对象,比如我们这里定义的是一个 Deployment 类型的 API 对象,我们按照这个 API 对象的要求填充了一些属性,就会为我们创建出对应的资源对象。

查看某个pod的具体信息
kubectl describe pod "pod名称"

[root@node02 ~]#  kubectl describe pod nginx-deploy-7cb4fc6c56-8ljb7
Name:         nginx-deploy-7cb4fc6c56-8ljb7
Namespace:    default
Priority:     0
Node:         node01/172.17.122.151
Start Time:   Wed, 15 Jan 2020 17:21:49 +0800
Labels:       app=nginx
              pod-template-hash=7cb4fc6c56
Annotations:  <none>
Status:       Running
IP:           10.244.1.3
IPs:
  IP:           10.244.1.3
Controlled By:  ReplicaSet/nginx-deploy-7cb4fc6c56
Containers:
  nginx:
    Container ID:   docker://951e1e4dcab3b990a68f6225ad63f1aa0b4f105a0e10639aeca127d9243f25e5
    Image:          nginx:1.7.9
    Image ID:       docker-pullable://nginx@sha256:e3456c851a152494c3e4ff5fcc26f240206abac0c9d794affb40e0714846c451
    Ports:          80/TCP, 443/TCP
    Host Ports:     0/TCP, 0/TCP
    State:          Running
      Started:      Wed, 15 Jan 2020 17:22:43 +0800
    Ready:          True
    Restart Count:  0
    Environment:    <none>
    Mounts:
      /var/run/secrets/kubernetes.io/serviceaccount from default-token-557h9 (ro)
Conditions:
  Type              Status
  Initialized       True
  Ready             True
  ContainersReady   True
  PodScheduled      True
Volumes:
  default-token-557h9:
    Type:        Secret (a volume populated by a Secret)
    SecretName:  default-token-557h9
    Optional:    false
QoS Class:       BestEffort
Node-Selectors:  <none>
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled  <unknown>  default-scheduler  Successfully assigned default/nginx-deploy-7cb4fc6c56-8ljb7 to node01
  Normal  Pulling    41m        kubelet, node01    Pulling image "nginx:1.7.9"
  Normal  Pulled     40m        kubelet, node01    Successfully pulled image "nginx:1.7.9"
  Normal  Created    40m        kubelet, node01    Created container nginx
  Normal  Started    40m        kubelet, node01    Started container nginx

如果镜像升级了,这时我们需要重新运行应用,此时只需要改动下image即可。

apiVersion: apps/v1 # 新版本的deployment都使用这个apiVersion
kind: Deployment # API对象类型,也就是资源对象类型
metadata: # 资源对象的元信息
  name: nginx-deploy
  namespace: default # 如果不写的话就默认是default命名空间的
  labels: # 标识或过滤
    chapter: first-app
spec:
  selector: # required,必须填写的。当资源对象类型是Deployment时
    matchLabels: # Lable selector,匹配标签(labels)等于 app:nginx
      app: nginx # Pod的标签
  replicas: 4 # Pod副本数
  template: # Pod 模版
    metadata: # Pod的元信息
      labels: # Pod的Label标签
        app: nginx # 此处和11行必须是一致的
    spec:
      containers: # Pod下面有多个容器
      - name: nginx # 容器名称
        image: nginx:latest ############## "使用的镜像名称,镜像升级,修改镜像名称"
        ports: # 容器暴露的端口
          - containerPort: 80
          - containerPort: 443

然后使用kubectl apply xxx.yaml来更新应用(滚动更新)即可。

如果要删除deployment的话则使用kubectl delete -f xxx.yaml

关于YAML的字段说明与使用

上面我们了解了 YAML 文件的基本语法,现在至少可以保证我们的编写的 YAML 文件语法是合法的,那么要怎么编写符合 Kubernetes API 对象的资源清单呢?比如我们怎么知道 Pod、Deployment 这些资源对象有哪些功能、有哪些字段呢?

一些简单的资源对象我们可能可以凭借记忆写出对应的资源清单,但是 Kubernetes 发展也非常快,版本迭代也很快,每个版本中资源对象可能又有很多变化,那么有没有一种办法可以让我们做到有的放矢呢?

实际上是有的,最简单的方法就是查找 Kubernetes API 文档,比如我们现在使用的是 v1.16.2 版本的集群,可以通过地址 https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.16/ 查找到对应的 API 文档,在这个文档中我们可以找到所有资源对象的一些字段。

比如我们要了解创建一个 Deployment 资源对象需要哪些字段,我们可以打开上面的 API 文档页面,在左侧侧边栏找到 Deployment v1 apps,点击下面的 Write Operations,然后点击 Create,然后我们查找到创建 Deployment 需要提交的 Body 参数。
每个字段具体什么含义以及每个字段下面是否还有其他字段都可以这样去追溯。

但是如果平时我们编写资源清单的时候都这样去查找文档势必会效率低下,Kubernetes 也考虑到了这点,我们可以直接通过 kubectl 命令行工具来获取这些字段信息,同样的,比如我们要获取 Deployment 的字段信息,我们可以通过 kubectl explain 命令来了解:
kubectl explain 资源对象类型,如下:

[root@master ~]# kubectl explain Deployment
KIND:     Deployment
VERSION:  apps/v1

DESCRIPTION:
     Deployment enables declarative updates for Pods and ReplicaSets.

FIELDS:
   apiVersion   <string>
     APIVersion defines the versioned schema of this representation of an
     object. Servers should convert recognized schemas to the latest internal
     value, and may reject unrecognized values. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

   kind <string>
     Kind is a string value representing the REST resource this object
     represents. Servers may infer this from the endpoint the client submits
     requests to. Cannot be updated. In CamelCase. More info:
     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

   metadata <Object>
     Standard object metadata.

   spec <Object>
     Specification of the desired behavior of the Deployment.

   status   <Object>
     Most recently observed status of the Deployment.

如上,我们可以查看到相关字段的说明,如果要继续深入往下查看呢?则

[root@master ~]# kubectl explain Deployment.spec
KIND:     Deployment
VERSION:  apps/v1

RESOURCE: spec <Object>

DESCRIPTION:
     Specification of the desired behavior of the Deployment.

     DeploymentSpec is the specification of the desired behavior of the
     Deployment.

FIELDS:
   minReadySeconds  <integer>
     Minimum number of seconds for which a newly created pod should be ready
     without any of its container crashing, for it to be considered available.
     Defaults to 0 (pod will be considered available as soon as it is ready)

   paused   <boolean>
     Indicates that the deployment is paused.

   progressDeadlineSeconds  <integer>
     The maximum time in seconds for a deployment to make progress before it is
     considered to be failed. The deployment controller will continue to process
     failed deployments and a condition with a ProgressDeadlineExceeded reason
     will be surfaced in the deployment status. Note that progress will not be
     estimated during the time a deployment is paused. Defaults to 600s.

   replicas <integer>
     Number of desired pods. This is a pointer to distinguish between explicit
     zero and not specified. Defaults to 1.

   revisionHistoryLimit <integer>
     The number of old ReplicaSets to retain to allow rollback. This is a
     pointer to distinguish between explicit zero and not specified. Defaults to
     10.

   selector <Object> -required-   # "可以看到此处是一个必须存在的,当然前提是kind值为Deployment"
     Label selector for pods. Existing ReplicaSets whose pods are selected by
     this will be the ones affected by this deployment. It must match the pod
     template's labels.

   strategy <Object>
     The deployment strategy to use to replace existing pods with new ones.

   template <Object> -required-
     Template describes the pods that will be created.

如果一个字段显示的是required,这就证明该字段是必填的,也就是我们在创建这个资源对象的时候必须声明这个字段,每个字段的类型也都完全为我们进行了说明,所以有了 kubectl explain这个命令我们就完全可以写出一个不熟悉的资源对象的清单说明了,这个命令我们也是必须要记住的,会在以后的工作中为我们提供很大的帮助。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,242评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,769评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,484评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,133评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,007评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,080评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,496评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,190评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,464评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,549评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,330评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,205评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,567评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,889评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,160评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,475评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,650评论 2 335

推荐阅读更多精彩内容