一、YAML 文件基本语法格式

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

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

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

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

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

$ kubectl create -f xxxx.yaml

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

二、第一个容器化应用

比如现在我们通过 YAML 文件编写了一个如下的资源清单,命名为 nginx-deployment.yaml:

apiVersion: apps/v1  # API版本
kind: Deployment # API对象类型
metadata:
name: nginx-deploy
labels:
chapter: first-app
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # Pod 副本数量
template: # Pod 模板
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80

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

$ kubectl create -f nginx-deployment.yaml
deployment.apps/nginx-deploy created
$ kubectl get pods
NAME READY STATUS RESTARTS AGE
nginx-deploy-54f57cf6bf-2fdjz 1/1 Running 0 7s
nginx-deploy-54f57cf6bf-57287 1/1 Running 0 7s

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

$ kubectl get deployment
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 2/2 2 2 12m

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 get deployment -l chapter=first-app
NAME READY UP-TO-DATE AVAILABLE AGE
nginx-deploy 2/2 2 2 51m
$ kubectl get pods -l app=nginx
NAME READY STATUS RESTARTS AGE
nginx-deploy-54f57cf6bf-2fdjz 1/1 Running 0 51m
nginx-deploy-54f57cf6bf-57287 1/1 Running 0 51m

到这里我们就完成了我们的第一个应用的容器化部署,但是往往我们在部署应用的过程中或多或少会遇到一些问题,这个时候我们可以使用一个 kubectl describe 命令来查看资源对象的详细信息,比如我们用下面的命令来查看 Pod 的详细信息:

$ kubectl describe pod nginx-deploy-54f57cf6bf-2fdjz
Name: nginx-deploy-54f57cf6bf-2fdjz
Namespace: default
Priority: 0
Node: ydzs-node2/10.151.30.23
Start Time: Sat, 09 Nov 2019 15:20:32 +0800
Labels: app=nginx
pod-template-hash=54f57cf6bf
Annotations: <none>
Status: Running
IP: 10.244.2.199
IPs:
IP: 10.244.2.199
Controlled By: ReplicaSet/nginx-deploy-54f57cf6bf
Containers:
nginx:
Container ID: docker://e40e78eee7a431b6e7277b414967cce936ac750e2a8ba30298302cdd89e54300
Image: nginx:1.7.9
Image ID: docker-pullable://nginx@sha256:e3456c851a152494c3e4ff5fcc26f240206abac0c9d794affb40e0714846c451
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sat, 09 Nov 2019 15:20:35 +0800
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from default-token-5tsh4 (ro)
Conditions:
Type Status
Initialized True
Ready True
ContainersReady True
PodScheduled True
Volumes:
default-token-5tsh4:
Type: Secret (a volume populated by a Secret)
SecretName: default-token-5tsh4
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-54f57cf6bf-2fdjz to ydzs-node2
Normal Pulled 52m kubelet, ydzs-node2 Container image "nginx:1.7.9" already present on machine
Normal Created 52m kubelet, ydzs-node2 Created container nginx
Normal Started 52m kubelet, ydzs-node2 Started container nginx

我们可以看到看到很多这个 Pod 的详细信息,比如调度到的节点、状态、IP 等,一般我们比较关心的是下面的 Events 部分,就是我们说的事件。

在 Kubernetes 创建资源对象的过程中,对该对象的一些重要操作,都会被记录在这个对象的 Events 里面,可以通过 kubectl describe 指令查看对应的结果。所以这个指令也会是以后我们排错过程中会经常使用的命令,一定要记住这个重要的命令。比如上面我们描述的这个 Pod,我们可以看到它被创建之后,被调度器调度(Successfully assigned)到了 ydzs-node2 节点上,然后指定的镜像已经在该节点上存在了,所以没有再去拉取镜像,然后创建我们定义的 nginx 容器,最后启动定义的容器。

另外一个方面如果我们相对我们的应用进行升级的话应该怎么办呢?这个操作在我们日常工作中还是非常常见的,而在 Kubernetes 这里也是非常简单的,我们只需要修改我们的资源清单文件即可,比如我们把镜像升级到最新版本nginx:latest:

...
spec:
containers:
- name: nginx
image: nginx:latest # 这里被从 1.7.9 修改为latest
ports:
- containerPort: 80

然后我们可以通过kubectl apply命令来直接更新,这个命令也是推荐我们使用的,我们不必关心当前的操作是创建,还是更新,执行的命令始终是 kubectl apply,Kubernetes 则会根据 YAML 文件的内容变化,自动进行具体的处理,所以无论是创建还是更新都可以直接使用这个命令:

$ kubectl apply -f nginx-deployment.yaml

通过这个命令就可以来更新我们的应用了,由于我们这里使用的是一个 Deployment 的控制器,所以会滚动更新我们的应用,我们可以通过在命令后面加上 --watch 参数来查看 Pod 的更新过程:

$ kubectl get pods -l app=nginx --watch
NAME READY STATUS RESTARTS AGE
nginx-deploy-54f57cf6bf-2fdjz 1/1 Terminating 0 72m
nginx-deploy-54f57cf6bf-57287 1/1 Running 0 72m
nginx-deploy-786b576769-69lrl 1/1 Running 0 4s
nginx-deploy-786b576769-wwmvz 0/1 ContainerCreating 0 2s
nginx-deploy-54f57cf6bf-2fdjz 0/1 Terminating 0 72m
nginx-deploy-786b576769-wwmvz 1/1 Running 0 3s
nginx-deploy-54f57cf6bf-57287 1/1 Terminating 0 72m
nginx-deploy-54f57cf6bf-57287 0/1 Terminating 0 72m
nginx-deploy-54f57cf6bf-57287 0/1 Terminating 0 72m
nginx-deploy-54f57cf6bf-57287 0/1 Terminating 0 72m
nginx-deploy-54f57cf6bf-2fdjz 0/1 Terminating 0 72m
nginx-deploy-54f57cf6bf-2fdjz 0/1 Terminating 0 72m

可以看到更新过程是先杀掉了一个 Pod,然后又重新创建了一个新的 Pod,然后又杀掉一个旧的 Pod,再创建一个新的 Pod,这样交替替换的,最后剩下两个新的 Pod,这就是我们所说的滚动更新,滚动更新对于我们的应用持续提供服务是非常重要的手段,在日常工作中更新应用肯定会采用这种方式。

最后,如果需要把我们的应用从集群中删除掉,可以用 kubectl delete 命令来清理:

$ kubectl delete -f nginx-deployment.yaml

下一篇将介绍Kubernetes中YAML如何编写资源清单

(转发请注明出处:http://www.cnblogs.com/zhangyongli2011/ 如发现有错,请留言,谢谢)

YAML 文件基本语法格式(十四)的更多相关文章

  1. Atom打开txt文件中文乱码解决、指定文件的语法格式、win10中禁止睡眠

    1.Atom中文乱码解决 首先保证打开的txt文件的编码格式为UTF-8无BOM编码格式,可以使用Notepad++更改,如下图所示: 然后再在atom中打开文件,并右键点击文件内容的任意位置,Cha ...

  2. java 基本语法(十四)Lambda (一)表达式

    1.Lambda表达式使用前后的对比:举例一: @Test public void test1(){ Runnable r1 = new Runnable() { @Override public v ...

  3. django-模板之静态文件加载(十四)

    1.在templates同级目录下建static 2.index.css 3.index.html {% load static %} <!DOCTYPE html> <html l ...

  4. 推荐一个网址:在线检查Yam文件语法格式的错误

    最近在学习Docker和K8S内容时候,经常会遇到要自己写一些容器部署或者组件部署的yaml文件. 但是苦于没有彻底熟悉yaml,有时候要到kubectl creat -f path 部署命令执行后, ...

  5. Python第十四天 序列化 pickle模块 cPickle模块 JSON模块 API的两种格式

    Python第十四天 序列化  pickle模块  cPickle模块  JSON模块  API的两种格式 目录 Pycharm使用技巧(转载) Python第一天  安装  shell  文件 Py ...

  6. 第三百四十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制

    第三百四十四节,Python分布式爬虫打造搜索引擎Scrapy精讲—craw母版l创建自动爬虫文件—以及 scrapy item loader机制 用命令创建自动爬虫文件 创建爬虫文件是根据scrap ...

  7. Ansible 小手册系列 八(Yaml 语法格式)

    YAML 语言(发音 /ˈjæməl/ )的设计目标,就是方便人类读写.它实质上是一种通用的数据串行化格式. 它的基本语法规则如下. • 大小写敏感 • 使用缩进表示层级关系 • 缩进时不允许使用Ta ...

  8. 孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习

     孤荷凌寒自学python第三十四天python的文件操作对file类的对象学习 (完整学习过程屏幕记录视频地址在文末,手写笔记在文末) 一.close() 当一个file对象执行此方法时,将关闭当前 ...

  9. yang文件语法格式

    前言 NETCONF(Network Configuration Protocol),该协议的配置功能非常强大,同时兼顾监控和故障管理,安全验证和访问控制,得到业界的一致认可,被广泛用来配置网络 NE ...

  10. JAVA之旅(二十四)——I/O流,字符流,FileWriter,IOException,文件续写,FileReader,小练习

    JAVA之旅(二十四)--I/O流,字符流,FileWriter,IOException,文件续写,FileReader,小练习 JAVA之旅林林总总也是写了二十多篇了,我们今天终于是接触到了I/O了 ...

随机推荐

  1. Python 按规则解析并替换字符串中的变量及函数

    按规则解析并替换字符串中的变量及函数 需求 1.按照一定规则解析字符串中的函数.变量表达式,并替换这些表达式.这些函数表达式可能包含其它函数表达式,即支持函数嵌套 2.函数表达式格式:${ __函数名 ...

  2. 【js】 reduce、filter、map 数组链式调用求加和

    let data = [ {hierarchy: '香蕉', count: 1}, {hierarchy: '苹果', count: 2}, {hierarchy: '葡萄', count: 3}, ...

  3. java面试一日一题:在创建微服务时,是用RPC还是http

    问题:请讲下在做微服务时,是使用RPC还是http 分析:该问题主要考察对RCP及http的理解,也关系到在进行微服务选型时的两大方向,dubbo和springCloud,都是RPC框架,但前者是RP ...

  4. 嵌入式开发SQLite 快速掌握

    SQLite是什么 SQLite又称(RDBMS)它 是本地数据库,可以用在手机,嵌入式设备的精简数据库和大名的mysql 一样的数据库存,只是可以理解为它是精简版,事务处理.表连接.索引.触发器等都 ...

  5. python adb 安卓app性能测试

    主要是进行cpu.内存.冷启动.热启动.流量.电量的监测 可获取到相关数据,同竞类产品对比,或者同版本对比 cpustatus adb命令:adb shell "dumpsys cpuinf ...

  6. Jmeter函数助手11-BeanShell

    BeanShell函数用于简单的计算或者运行编程脚本. 表达式求值:填入脚本代码或脚本文件${__BeanShell(source("test.bsh"))} 存储结果的变量名(可 ...

  7. Jmeter函数助手1-CSVRead

    CSVRead函数适用于读取文件获取参数值. 用于获取值的CSV文件 | *别名:csv文件路径 CSV文件列号| next| *alias:读取列,0表示第一列,1表示第二列 1.首先我们需要一个文 ...

  8. 测试工程师-年终总结PPT

    2022年年终总结-xxx 一.首页 2022年年终总结暨2023年工作计划 汇报人:测试组-xxx 日期: 2023.1.13 二.目录 1.年度工作概述 2.工作亮点展示 3.持续精进点 4.明年 ...

  9. 【Java】单号创建服务

    需求:ERP项目存在若干个业务功能,每个业务的单子的单号创建规则需要被统一规划 1.每个业务有自己对应的标识 2.业务单号必须以英文字母为前缀,长度在2 - 4个字符 3.单号的组成 = [ 前缀 ] ...

  10. 【Tutorial C】08 函数 Function

    函数的定义 C源程序是由函数组成的. 最简单的程序有一个主函数 main(),但实用程序往往由多个函数组成, 由主函数调用其他函数,其他函数也可以互相调用. 函数是C源程序的基本模块,程序的许多功能是 ...