Kubernetes 中有很多积木(Building Blocks),比如 object model,pod,rs,deployment,namespace 之类,这些都是 kubernetes 中很重要的东西。
Kubernetes Object Model
kubernetes 有一个非常完善的对象模型,kubernetes 集群可以通过这个对象模型来表现出不同的持久化的整体,比如:
- 我们是在哪个 node 上运行哪个容器化的应用程序?
- 应用程序资源消耗
- 应用程序不同的策略
对于每个对象,我们用 spec
这个 field 声明我们期望的状态,随后 kubernetes 会通过 status
这个 field 记录对象实际的状态并加以管理。随后,kubernetes 的 controller manager 会想办法让这个对象实际的状态和我们声明期望的状态相同。
kubernetes 中的例子比如:Pods,Deployments,ReplicaSets 之类。
如果我们要创建一个对象,我们需要把 spec
这个 field 提供给 API Server,这个 field 会描述我们期望的状态以及一些基础的信息,比如名称。创建对象的 API 请求必须有 spec
这个 field 以及其它详细信息,并且需要是 JSON 的格式。一般情况下,我们用 yaml 格式来提供一个对象的声明,kubectl 会把这个声明转换成 JSON 格式,然后传给 API Server。
下面是一个 Deployment 对象的例子:
apiVersion: apps/v1beta1
kind: Deployment
metadata:
name: nginx-deployment
spec:
replicas: 3
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
复制代码
插播一条广告:
Apps
The core workloads API, which is composed of the DaemonSet, Deployment, ReplicaSet, and StatefulSet kinds, has been promoted to GA stability in the apps/v1 group version. As such, the apps/v1beta2 group version is deprecated, and all new code should use the kinds in the apps/v1 group version.
接着说,apiVersion 指定了我们调用的 api 的 endpoint;通过 kind field,我们指定了我们要创建的对象的类型;通过 metadata,我们给对象附加上了最基本的信息,比如名字;你可以发现这里面有两个 spec
的 field(spec
和 spec.template.spec
),通过 spec
,我们定义了我们对 deployment 的期望状态,在我们的例子中,我们想要确认,在任何时候,都有至少 3 个 pod 在运行。我们再在 spec.template.spec
里面定义我们要运行的每个 pod 都应该是什么状态,所以这就是为啥这里会有两个 spec 的原因。
一旦这个对象被创建了,kubernetes 会直接给对象添加一个 status
的 field,如下:
70B197CF-63EA-401C-B029-AFC9F9271D91
Pods
Pod 是 kubernetes 中最简单也是最小的一个对象,是 kubernetes 部署的一个单元,代表了应用的一个单一实例。一个 Pod 是一个或者多个容器的逻辑上的集合,这些容器拥有以下的特性:
- 在同一个 host 上一起进行调度
- 共享同一个 network namespace
- 挂载同样的 external storage(volumes)
38D8B067-9AD2-4CE0-85C5-70C3D5538FB0
Pod 并非一个持久化的东西,很有可能突然挂了,并且没有能力自我修复,这就是为啥我们把它们和 controller 一起用,这样可以来控制 pod 的 replica,容错,自我修复等等。比较有名的例子比如 Deployments,ReplicaSets 等。我们通过把 Pod 的定义(specification,也就是 spec
)附加到别的对象(也就是之前用的 template.spec
)来完成。
Labels
Labels 都是键值对,这些键值对可以被 attach 到 kubernetes 的对象上,比如 Pod。Labels 一般被用来组织和选择一些符合条件的对象。label 不提供唯一性。
5594660A-4922-497F-9BB6-69CDE96238B3
通过这个图片,我们可以看到我们用了两个 label:app
和 env
。基于我们的需求,我们可以给我们的 pod 不同的值。
Label Selectors
通过 Label Selectors,我们可以选择一系列的对象,Kubernetes 支持两种 Selector 类型:
Equality-Based Selectors
顾名思义,这种 selector 通过 ==
或者 !=
来进行选择,比如我们选择一个 env==dev
的对象,就会找出所有有 env label,并且值为 dev 的。
Set-Based Selectors
这种 selector 支持通过一系列的值来进行过滤,比如通过 in
, notin
和 exist
。
举例:env in (dev, qa)
9DCAECB6-54CF-4789-94B8-4332BABE4B53
Replication Controllers
一个 ReplicationController(rc)是 master node 上 Controller Manager 的一部分,主要作用是保证每个 pod 的 replica 都达到了预期值。不然的话会通过杀死或者新建 pod 的办法来达到。不过现在已经被 ReplicaSet (rs) 取代了。
Replica Sets
Replica Set 是下一代的 Replication Controller,好处在于同时支持 equality 和 set based selector(rc 只支持 equality-based)。目前这是唯一的区别。
Rs 可以单独使用,不过一般是配合 deployment 一起用。Deployment 会自动创建 rs 来管理下面的 pod。
Deployment
deployment 提供了对于 pod 和 rs 的陈述性更新。DeploymentController 是 master node 上 Controller Manager 的一部分,作用和 Controller manager 别的一样 —— 确保当前的状态和期望的状态相同。
在下面这个例子中,我们的 deployment 创建了一个 rs A,然后 rs A 又创建了 3 个 pod,并且在每个 pod 中,都有一个跑了 nginx:1.7.9 镜像的容器。
1A74F83F-00D9-4954-9737-D6C1BBAE3EF3
接下来,在下一个 deployment 中,我们修改了 pod 的 template,把 nginx 从 1.7.9 升级到了 1.9.1。因为我们升级了期望的状态,所以 deployment 会创建一个新的 rs B,这个过程被称为 Deployment rollout:
D9667D97-B328-4C19-AA9F-FD9E7CDEDD65
当 rs B 创建完毕的时候,deployment 开始指向它:
652F4886-8F15-4C27-9DDF-8C1DA7D1DF11
在 rs 之上,deployment 提供了很多特性比如 recording,通过这个特性,如果说更新出错,或者更新后的应用出了 bug,我们可以 rollback 到原先的状态。
Namespaces
如果我们有无数个用户,我们想把这些用户组织到不同的 team 或者 project,我们可以通过 namespace 把 kubernetes 集群分成好多个小集群。所有在 namespace 中创建的 resources/objects 都是唯一的,不会跨命名空间。
一般来说,k8s 会有两个默认 namespace:kube-system 和 default。kube-system 一般会用来放一些 kubernetes 系统的组件,default 会用来放一些属于其它 namespace 的对象。我们默认情况下是会连接到 default 命名空间。kube-public 是一个特殊的 namespace,可以被所有的用户读,一般用于特殊情况比如初始化一个集群。
我们可以通过使用资源配额(Resource Quotas)来限制每个命名空间的资源。
最后再插播一条广告:
[C8E9D1AC-E8F8-4544-8DB0-F4EAA6905F56](