k8s

257 阅读7分钟

基本概念

pod 是最小的调度单元,比如一个drop 的 container 就是一个pod。 node 就是用于工作的服务器。它有一些状态和信息,当这些条件都满足一些条件判断时,Node 便处于 Ready 状态,可用于执行后续的工作。 Deployment 可理解为一种对期望状态的描述。 Docker 是我们选择的容器运行时。

前面我们已经说过,Pod 是 K8S 中最小的调度单元,所以我们无法直接在 K8S 中运行一个 container 但是我们可以运行一个 Pod 而这个 Pod 中只包含一个 container 。

cs架构构成

# k8s server 也就是 master,包含多个组件:
Cluster state store 存储(etcd)和 watch
API Server 接受指令
Controller Manager 调节集群状态
Scheduler 是集群的调度器,它会持续的关注集群中未被调度的 Pod ,并根据各种条件,比如资源的可用性,节点的亲和性或者其他的一些限制条件,通过绑定的 API 将 Pod 调度/绑定到 Node 上。

#node
Kubelet 实现了集群中最重要的关于 Node 和 Pod 的控制功能。在前面,我们提到了 Master 节点的 Scheduler 组件,它会调度未绑定的 Pod 到符合条件的 Node 上,而至于最终该 Pod 是否能运行于 Node 上,则是由 Kubelet 来裁定的。
Container runtime 一般是 Docker。
Kube Proxy 我们都知道,想要访问某个服务,那要么通过域名,要么通过 IP。而每个 Pod 在创建后都会有一个虚拟 IP,K8S 中有一个抽象的概念,叫做 Service ,kube-proxy 便是提供一种代理的服务(service),让你可以**通过 Service 访问到 Pod**。实际的工作原理是在每个 Node 上启动一个 kube-proxy 的进程,通过编排 iptables 规则来达到此效果。

几个状态

使用 kubectl get all 输出内容的格式 / 前代表类型,/ 后是名称。

~ kubectl get all
NAME                         READY     STATUS    RESTARTS   AGE
pod/redis-7c7545cbcb-2m6rp   1/1       Running   0          30s

NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   32s

NAME                    DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/redis   1         1         1            1           30s

NAME                               DESIRED   CURRENT   READY     AGE
replicaset.apps/redis-7c7545cbcb   1         1         1         30s

Deployment

kubectl get deployment.apps/redis -o wide Deployment 是一种高级别的抽象,允许我们进行扩容,滚动更新及降级等操作。 我们使用 kubectl run redis --image='redis:alpine 命令便创建了一个名为 redis 的 Deployment,并指定了其使用的镜像为 redis:alpine。

ReplicaSet

简写 rs kubectl get rs -o wide ReplicaSet 是一种较低级别的结构,允许进行扩容。Deployment 主要是声明一种预期的状态,并且会将 Pod 托管给 ReplicaSet,而 ReplicaSet 则会去检查当前的 Pod 数量及状态是否符合预期,并尽量满足这一预期。

Service

简写 svc kubectl get rs -o wide Service 简单点说就是为了能有个稳定的入口访问我们的应用服务或者是一组 Pod。通过 Service 可以很方便的实现服务发现和负载均衡。

Service 目前有 4 种类型:

ClusterIP: 是 K8S 当前默认的 Service 类型。将 service 暴露于一个仅集群内可访问的虚拟 IP 上。
NodePort: 是通过在集群内所有 Node 上都绑定固定端口的方式将服务暴露出来,这样便可以通过 <NodeIP>:<NodePort> 访问服务了。
LoadBalancer: 是通过 Cloud Provider 创建一个外部的负载均衡器,将服务暴露出来,并且会自动创建外部负载均衡器路由请求所需的 NodeportClusterIP 。
ExternalName: 是通过将服务由 DNS CNAME 的方式转发到指定的域名上将服务暴露出来,这需要 kube-dns 1.7 或更高版本支持

pod

kubectl get pods Pod 是 K8S 中的最小化部署单元。 我们进行一次简单的扩容操作。kubectl scale deploy/redis --replicas=2

可以通过 kubectl describe pod/redis-bb7894d65-7vsj8 查看摸个pod的详情。

部署

文档 通过部署 kind: Deployment 的服务,就会已经有pod运行起来了。 kubectl apply -f redis-deployment.yaml

如果是其他服务的依赖,即希望被访问到,我们需要将它作为 Service 暴露出来。通过部署 kind: Service 的服务来进行,kubectl apply -f redis-service.yaml,

庖丁解牛

kube-apiserver

为集群的统一入口,接收来自外部的信号和请求,并将一些信息存储至 etcd 中。 一个请求依次会经过认证,授权,准入控制等环节,当这些环节都已经通过后,该请求便到了 kube-apiserver 的实际处理逻辑中了。

其实和普通的 Web server 类似,kube-apiserver 提供了 restful 的接口,增删改查等基本功能都基本类似。

etcd

etcd 是由 CoreOS 团队发起的一个分布式,强一致的键值存储。它用 Go 语言编写,使用 Raft 协议作为一致性算法。多数情况下会用于分布式系统中的服务注册发现,或是用于存储系统的关键数据。

etcd 在 K8S 中,最主要的作用便是其高可用,强一致的键值存储以及监听机制。

在 kube-apiserver 收到对应请求经过一系列的处理后,最终如果是集群所需要存储的数据,便会存储至 etcd 中。主部分主要是集群状态信息和元信息。

kube-controller-manager

一句话来讲 kube-controller-manager 是一个嵌入了 K8S 核心控制循环的守护进程。

它通过 kube-apiserver 提供的信息持续的监控集群状态,并尝试将集群调整至预期的状态。由于访问 kube-apiserver 也需要通过认证,授权等过程,所以可以看到上面启动 kube-controller-manager 时提供了一系列的参数。

它主要会去 watch 相关的资源,但是出于性能上的考虑,也不能过于频繁的去请求 kube-apiserver 或者永久 watch ,所以在实现上借助了 client-go 的 informer 包,相当于是实现了一个本地的二级缓存。这里不做过多展开。

kube-scheduler

同样是通过定时的向 kube-apiserver 请求获取信息,并进行处理。而他们所起到的作用并不相同。

kube-scheduler 的作用就是将待调度的 Pod 调度至最佳的 Node 上,而这个过程中则需要根据不同的策略,考虑到 Node 的资源使用情况,比如端口,内存,存储等。

kubelet

按照一般架构设计上的习惯,kubelet 所承担的角色一般会被叫做 agent,这里叫做 kubelet 很大程度上受 Borg 的命名影响,Borg 里面也有一个 Borglet 的组件存在。kubelet 便是 K8S 中的 agent,负责 Node 和 Pod 相关的管理任务。

kube-scheduler 处理了 Pod 应该调度至哪个 Node,而 kubelet 则是保障该 Pod 能按照预期,在对应 Node 上启动并保持工作。

同时,kubelet 在保障 Pod 能按预期工作,主要是做了两方面的事情:

健康检查:通过 LivenessProbe 和 ReadinessProbe 探针进行检查,判断是否健康及是否已经准备好接受请求。
资源监控:通过 cAdvisor 进行资源监。

另外 kubelet 其实还承担着清理 Node 上一些由 K8S 调度 Pod 所造成的磁盘占用之类的工作。

kube-proxy

当 Pod 在 Node 上正常运行之后,若是需要对外提供服务,则需要将其暴露出来。是 kube-proxy 来处理这些工作的。

默认情况下我们使用 iptables 的代理模式,当创建新的 Service ,或者 Pod 进行变化时,kube-proxy 便会去维护 iptables 规则,以确保请求可以正确的到达后端服务。

Container Runtime

它的主要作用在于下载镜像,运行容器等。

kube-scheduler 决定了 Pod 将被调度到哪个 Node 上,而 kubelet 则负责 Pod 在此 Node 上可按预期工作。如果没有 Container Runtime,那 Pod 中的 container 在该 Node 上也便无法正常启动运行了。 docker

ingress

Ingress 是一组允许外部请求进入集群的路由规则的集合。它可以给 Service 提供集群外部访问的 URL,负载均衡,SSL 终止等。