一、Kubernetes 架构:
Kubernetes Cluster 由 Master 和 Node 组成,节点上运行着若干 Kubernetes 服务。
Master 节点
Master 是 Kubernetes Cluster 的大脑,运行着如下 Daemon 服务:kube-apiserver、kube-scheduler、kube-controller-manager、etcd 和 Pod 网络(例如 flannel)。
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093644767-930056414.png)
API Server(kube-apiserver)
API Server 提供 HTTP/HTTPS RESTful API,即 Kubernetes API。API Server 是 Kubernetes Cluster 的前端接口,各种客户端工具(CLI 或 UI)以及 Kubernetes 其他组件可以通过它管理 Cluster 的各种资源。
Scheduler(kube-scheduler)
Scheduler 负责决定将 Pod 放在哪个 Node 上运行。Scheduler 在调度时会充分考虑 Cluster 的拓扑结构,当前各个节点的负载,以及应用对高可用、性能、数据亲和性的需求。
Controller Manager(kube-controller-manager)
Controller Manager 负责管理 Cluster 各种资源,保证资源处于预期的状态。Controller Manager 由多种 controller 组成,包括 replication controller、endpoints controller、namespace controller、serviceaccounts controller 等。
不同的 controller 管理不同的资源。例如 replication controller 管理 Deployment、StatefulSet、DaemonSet 的生命周期,namespace controller 管理 Namespace 资源。
etcd
etcd是一种非关系型数据库,以key=value的形式存储数据的。 负责保存 Kubernetes Cluster 的配置信息和各种资源的状态信息。当数据发生变化时,etcd 会快速地通知 Kubernetes 相关组件。
Pod 网络
Pod 要能够相互通信,Kubernetes Cluster 必须部署 Pod 网络,flannel 是其中一个可选方案。
以上是 Master 上运行的组件,下一节我们讨论 Node。
node节点
Node 是 Pod 运行的地方,Kubernetes 支持 Docker、rkt 等容器 Runtime。 Node上运行的 Kubernetes 组件有 kubelet、kube-proxy 和 Pod 网络(例如 flannel)。
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093708056-444180464.png)
kubelet
kubelet 是 Node 的 agent,当 Scheduler 确定在某个 Node 上运行 Pod 后,会将 Pod 的具体配置信息(image、volume 等)发送给该节点的 kubelet,kubelet 根据这些信息创建和运行容器,并向 Master 报告运行状态。
kube-proxy
service 在逻辑上代表了后端的多个 Pod,外界通过 service 访问 Pod。service 接收到的请求是如何转发到 Pod 的呢?这就是 kube-proxy 要完成的工作。
每个 Node 都会运行 kube-proxy 服务,它负责将访问 service 的 TCP/UPD 数据流转发到后端的容器。如果有多个副本,kube-proxy 会实现负载均衡。
Pod 网络
Pod 要能够相互通信,Kubernetes Cluster 必须部署 Pod 网络,flannel 是其中一个可选方案。
完整的架构图
结合实验环境,我们得到了如下的架构图:
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093728011-602583224.png)
你可能会问:为什么 k8s-master 上也有 kubelet 和 kube-proxy 呢?
这是因为 Master 上也可以运行应用,即 Master 同时也是一个 Node。
几乎所有的 Kubernetes 组件本身也运行在 Pod 里,执行如下命令:
kubectl get pod --all-namespaces -o wide
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093744933-1189944403.png)
Kubernetes 的系统组件都被放到 kube-system namespace 中。这里有一个 kube-dns 组件,它为 Cluster 提供 DNS 服务,我们后面会讨论。kube-dns是在执行 kubeadm init 时(第 ⑤ 步)作为附加组件安装的。
二、Kubernetes 实践:
通过例子理解 k8s 架构
执行如下命令:
kubectl run httpd-app --image=reg.yunwei.edu/learn/httpd:latest --replicas=2 kubectl get deployment kubectl get pod -n default -o wide
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093757601-1449119347.png)
Kubernetes 部署了 deployment httpd-app,有两个副本 Pod,分别运行在k8s-node2 和 k8s-node3上。
详细讨论整个部署过程。
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093855341-1168295815.png)
① kubectl 发送部署请求到 API Server。
② API Server 通知 Controller Manager 创建一个 deployment 资源。
③ Scheduler 执行调度任务,将两个副本 Pod 分发到 k8s-node1 和 k8s-node2。
④ k8s-node1 和 k8s-node2 上的 kubectl 在各自的节点上创建并运行 Pod。
补充两点:
-
应用的配置和当前状态信息保存在 etcd 中,执行 kubectl get pod 时 API Server 会从 etcd 中读取这些数据。
-
flannel 会为每个 Pod 都分配 IP。因为没有创建 service,目前 kube-proxy 还没参与进来。
Kubernetes 架构就讨论到这里。从下节开始,我们将通过实践深入学习 Kubernetes 的各种特性。作为容器编排引擎,最重要也是最基本的功能当然是运行容器化应用。
用 Deployment 运行应用
Kubernetes 作为容器编排引擎,最重要也是最基本的功能当然是运行容器化应用。
Deployment
前面我们已经了解到,Kubernetes 通过各种 Controller 来管理 Pod 的生命周期。为了满足不同业务场景,Kubernetes 开发了 Deployment、ReplicaSet、DaemonSet、StatefuleSet、Job 等多种 Controller。我们首先学习最常用的 Deployment。
(1)上面我们运行了一个http-app,下面详细分析 Kubernetes 都做了些什么工作。
kubectl get deployment -n default -o wide
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093925335-854872090.png)
接下来我们用 kubectl describe deployment httpd-app了解更详细的信息。
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613093945493-1901973614.png)
大部分内容都是自解释的,我们重点看最下面部分。这里告诉我们创建了一个 ReplicaSet httpd-app-cfb6dc947,Events 是 Deployment 的日志,记录了 ReplicaSet 的启动过程。
(2)通过上面的分析,也验证了 Deployment 通过 ReplicaSet 来管理 Pod 的事实。接着我们将注意力切换到 httpd-app-cfb6dc947,执行 kubectl describe replicaset:
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613094022843-1435436809.png)
两个副本已经就绪,用 kubectl describe replicaset 查看详细信息:
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613094042305-1478768357.png)
Controlled By 指明此 ReplicaSet 是由 Deployment/httpd-app 创建。Events 记录了两个副本 Pod 的创建。
(3)接着我们来看 Pod,执行 kubectl get pod -n default
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613094055903-983886096.png)
两个副本 Pod 都处于 Running 状态,用 kubectl describe pod -n default 查看更详细的信息:
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613094619578-1984023855.png)
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613094855194-1912934322.png)
Controlled By 指明此 Pod 是由 ReplicaSet/httpd-app-cfb6dc947 创建。Events 记录了 Pod 的启动过程(httpd-app-cfb6dc947-mrtlz 和 httpd-app-cfb6dc947-rhgbs)。如果操作失败(比如 image 不存在),也能在这里查看到原因。
总结一下这个过程:
-
用户通过 kubectl 创建 Deployment。
-
Deployment 创建 ReplicaSet。
-
ReplicaSet 创建 Pod。
![](https://img2018.cnblogs.com/blog/1584426/201906/1584426-20190613094641522-964167221.png)
从上图也可以看出,对象的命名方式是:子对象的名字 = 父对象名字 + 随机字符串或数字。