12.牛刀小试:我的第一个容器化应用
1. 我先给你讲解一下 Kubernetes 里面与开发者关系最密切的几个概念。
-
作为一个应用开发者,你首先要做的,是制作容器的镜像。《白话容器基础(三):深入理解容器镜像》重点讲解过了
-
有了容器镜像之后,你需要按照 Kubernetes 项目的规范和要求,将你的镜像组织为它能够“认识”的方式,然后提交上去。就是使用 Kubernetes 的必备技能:编写配置文件。
备注:这些配置文件可以是 YAML 或者 JSON 格式的。为方便阅读与理解,在后面的讲解中,我会统一使用 YAML 文件来指代它们。
1. yaml文件如何使用?
Kubernetes 跟 Docker 等很多项目最大的不同,就在于它不推荐你使用命令行的方式直接运行容器(虽然 Kubernetes 项目也支持这种方式,比如:kubectl run),而是希望你用 YAML 文件的方式,即:把容器的定义、参数、配置,统统记录在一个 YAML 文件中,然后用这样一句指令把它运行起来:
$ kubectl create -f 我的配置文件
2. 如何理解yaml文件中的关键字
这么做最直接的好处是,你会有一个文件能记录下 Kubernetes 到底“run”了什么。比如下面这个例子:
apiVersion: apps/v1 kind: Deployment metadata: name: nginx-deployment spec: selector: matchLabels: app: nginx replicas: 2 template: metadata: labels: app: nginx spec: containers: - name: nginx image: nginx:1.7.9 ports: - containerPort: 80
像这样的一个 YAML 文件,对应到 Kubernetes 中,就是一个 API Object(API 对象)
当你为这个对象的各个字段填好值并提交给 Kubernetes 之后,Kubernetes 就会负责创建出这些对象所定义的容器或者其他类型的 API 资源。
下面我来给大家解释一下上面的配置文件中的一些关键词:
-
Kind字段,指定了这个 API 对象的类型(Type),是一个 Deployment。
所谓 Deployment,是一个定义多副本应用(即多个副本 Pod)的对象,我在前面的文章中(也是第 9 篇文章《从容器到容器云:谈谈 Kubernetes 的本质》)曾经简单提到过它的用法。此外,Deployment 还负责在 Pod 定义发生变化时,对每个副本进行滚动更新(Rolling Update)。
在上面这个 YAML 文件中,我给它定义的 Pod 副本个数 (spec.replicas) 是:2。
-
Pod 模版(spec.template)。这个模版描述了我想要创建的 Pod 的细节。在上面的例子里,这个 Pod 里只有一个容器,这个容器的镜像(spec.containers.image)是 nginx:1.7.9,这个容器监听端口(containerPort)是 80。
Pod 就是 Kubernetes 世界里的“应用”;而一个应用,可以由多个容器组成。
PS: 需要注意的是,像这样使用一种 API 对象(Deployment)管理另一种 API 对象(Pod)的方法,在 Kubernetes 中,叫作“控制器”模式(controller pattern)。在我们的例子中,Deployment 扮演的正是 Pod 的控制器的角色。关于 Pod 和控制器模式的更多细节,我会在后续编排部分做进一步讲解。
-
Metadata 字段。这个字段就是 API 对象的“标识”,即元数据,它也是我们从 Kubernetes 里找到这个对象的主要依据
-
Labels字段。Labels 就是一组 key-value 格式的标签。而像 Deployment 这样的控制器对象,就可以通过这个 Labels 字段从 Kubernetes 中过滤出它所关心的被控制对象。
比如,在上面这个 YAML 文件中,Deployment 会把所有正在运行的、携带“app: nginx”标签的 Pod 识别为被管理的对象,并确保这些 Pod 的总数严格等于两个。
而这个过滤规则的定义,是在 Deployment 的“spec.selector.matchLabels”字段。我们一般称之为:Label Selector。
-
Annotations字段。它专门用来携带 key-value 格式的内部信息。所谓内部信息,指的是对这些信息感兴趣的,是 Kubernetes 组件本身,而不是用户。所以大多数 Annotations,都是在 Kubernetes 运行过程中,被自动加在这个 API 对象上。
总结:一个 Kubernetes 的 API 对象的定义,大多可以分为 Metadata 和 Spec 两个部分。前者存放的是这个对象的元数据,对所有 API 对象来说,这一部分的字段和格式基本上是一样的;而后者存放的,则是属于这个对象独有的定义,用来描述它所要表达的功能。
-
2. 使用yaml文件如何创建资源,查看资源,更新资源,删除资源:
-
创建资源:kubectl create
$ kubectl create -f nginx-deployment.yaml
-
查看资源
# 查看运行的状态 kubectl get pods -l app=nginx 或者 kubectl get pods 具体的pod名称 -o wide -l参数 表示获取所有匹配 app: nginx 标签的 Pod。需要注意的是,在命令行中,所有 key-value 格式的参数,都使用“=”而非“:”表示 -o参数 表示展示的信息更加全面 # 查看运行的详细状态 kubectl describe pods 具体的pod名称
-
更新资源
# 第一种方法:直接修改yaml文件后,然后使用kubectl replace命令进行更新 kubectl replace -f nginx-deployment.yaml # 第二种方法:修改yaml文件后,然后使用kubectl apply 命令进行更新(推荐使用) kubectl apply -f nginx-deployment.yaml
-
删除资源
kubectl delete -f yaml文件名
3. 在yaml中申明一个Vulume数据卷 ( 重点)
第一种: emptyDir类型
在 Kubernetes 中,Volume 是属于 Pod 对象的一部分。所以,我们就需要修改这个 YAML 文件里的 template.spec 字段,如下所示:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-vol
volumes:
- name: nginx-vol
emptyDir: {}
mountPath: "/usr/share/nginx/html" 和 emptyDir: {} 联合在一起就是: 在宿主机上创建一个临时目录(为系统创建), 并将这个目录挂载到pod中的/usr/share/nginx/html目录下.
emptyDir挂载的特点:
- 系统在宿主机上临时创建临时目录,并对pod目录进行挂载
- 当pod资源删除时, 该临时文件也会被删除掉.
第二种: hostPath
而 Pod 中的容器,使用的是 volumeMounts 字段来声明自己要挂载哪个 Volume,并通过 mountPath 字段来定义容器内的 Volume 目录,比如:/usr/share/nginx/html。
当然,Kubernetes 也提供了显式的 Volume 定义,它叫做 hostPath。比如下面的这个 YAML 文件:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8
ports:
- containerPort: 80
volumeMounts:
- mountPath: "/usr/share/nginx/html"
name: nginx-vol
volumes:
- name: nginx-vol
hostPath:
path: "/var/data"
mountPath: "/usr/share/nginx/html" 和 path: /var/data 联合在一起 表示: 把宿主机上的/var/data的目录, 挂载到 /usr/share/nginx/html 目录下(如果宿主机上没有/var/data目录,系统会自动创建).
更多数据卷的分类:
- 本地挂载
- emptyDir
- hostPath
- 网络挂载
- 传统的网络挂载
- SAN: ISCSI
- NAS: NFS, CIFS
- 分布式网络挂载
- glusterfs, rbd, cephfs
- 云存储
- EBS, Azure,Disk,OSS
- 传统的网络挂载