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:  
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:    
    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:  
Tolerations:     node.kubernetes.io/not-ready:NoExecute for 300s
                 node.kubernetes.io/unreachable:NoExecute for 300s
Events:
  Type    Reason     Age        From               Message
  ----    ------     ----       ----               -------
  Normal  Scheduled    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   
     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 
     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 
     Standard object metadata.

   spec 
     Specification of the desired behavior of the Deployment.

   status   
     Most recently observed status of the Deployment.
 
 

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

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

RESOURCE: spec 

DESCRIPTION:
     Specification of the desired behavior of the Deployment.

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

FIELDS:
   minReadySeconds  
     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   
     Indicates that the deployment is paused.

   progressDeadlineSeconds  
     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 
     Number of desired pods. This is a pointer to distinguish between explicit
     zero and not specified. Defaults to 1.

   revisionHistoryLimit 
     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  -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 
     The deployment strategy to use to replace existing pods with new ones.

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

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

你可能感兴趣的:(03 YAML文件)