目录
系列
容器化技术与微服务结合—docker(一)
容器化技术与微服务结合—Kubernetes基本介绍(二)
容器化技术与微服务结合—Pod详解(三)
容器化技术与微服务结合—实操service并部署一个简单对外开放的springboot HelloWord服务(四)
容器化技术与微服务结合—结合springcloud微服务框架进行部署(含切换成阿里云docker仓库)(五)
容器化技术与微服务结合—SpringCloud框架与阿里云serverless k8s的结合(六)
首语
仅仅只是有了docker并不够,因为docker的跨节点通信、维护性都是比较麻烦的,在中小型甚至中型业务集群中,你会发现仅仅使用简单的docker做容器然后部署,只能解决服务器的利用率问题(1台机器部署多个docker),但是docker跨地域的通信以及docker的管理却变得非常麻烦。甚至想想,还不如直接云原生独占式来的爽,瞧瞧人家aws的auto scaling,瞧瞧阿里云的api编排,再看看你docker,什么渣渣,相当于服务器上在挂几个服务器。
所以在大型集群中,需要重新定义infra,重新定义网关、安全、通信等等,基于所谓云上,而重新建立一套容器化平台,管理这些容器各种操作和连接,就可以利用酷半儿内提斯(Kubernetes)。
一般来说,Kubernetes的运用,可以将java cloud微服务体系直接代替,不再使用eureka等组件,不过这也是看需求而定,如果你追求的是,在任意云或者是自建infra层都可以部署上线,那么Kubernetes对于你来说,仅仅只是用于容器化的编排,更多的devops脚本可能需要你重新编写。
Kubernetes是个什么玩意
Kubernetes是工业级的容器编排平台,远超一个业务系统级,你可以将阿里云的ecs或者aws的ec2比作docker,那么整个你操作的平台便是Kubernetes。
用技术层面来讲,Kubernetes其实就是一个自动化的容器编排平台,自动化肯定包含
- 部署:自动化的部署方式及操作
- 弹性:极强的弹性扩充,快速自动进行弹性水平或者垂直扩容
- 管理:管理好内部所有的容器
如下图:
Kubernetes调度
Kubernetes内置的调度器,会去执行调度,将用户提交的容器,放在Kubernetes所管理的集群的某一台机器上。Kubernetes会根据容器所需要的参数如cpu、mem等,然后根据集群中资源的情况进行安置,这里有点类似hadoop的hdfs(habse数据库)将数据切分后,放置在某个资源上(参考博主的大数据系列博客)
Kubernetes的自动恢复
Kubernetes 有一个节点健康检查的功能,它会监测这个集群中所有的宿主机,当宿主机本身出现故障,或者软件出现故障的时候,这个节点健康检查会自动对它进行发现。
Kubernetes 会把运行在这些失败节点上的容器进行自动迁移,迁移到一个正在健康运行的宿主机上,来完成集群内容器的一个自动恢复。
Kubernetes的水平伸缩
Kubernetes 有业务负载检查的能力,它会监测业务上所承担的负载,如果这个业务本身的 CPU 利用率过高,或者响应时间过长,它可以对这个业务进行一次扩容。
比如说当某个容器A过度忙碌,Kubernetes 就可以把A的负载从一份变为三份。接下来,它就可以通过负载均衡把A的负载分配到B和C上,以此来提高响应的时间。
其实说白了,就是内置的检查机制,检测到负载居高不下,就自动在扩充几个,分摊流量。
Kubernetes架构
Kubernetes的架构其实很好理解,是一个二层架构,有master作为boss,来掌控全局(参考hadoop、zk等)。 所以任何请求都不会直接和node进行通信,都是通过master,master才是真正的爹!!!!
Master
如图,master其实包含四个组件:
Api Server
API Server是用来处理 API 操作的,Kubernetes 中所有的组件都会和 API Server 进行连接,组件与组件之间一般不进行独立的连接,都依赖于 API Server 进行消息的传送;
APIServer负责对外提供RESTful的Kubernetes API服务,它是系统管理指令的统一入口,任何对资源进行增删改查的操作都要交给APIServer处理后再提交给etcd。如架构图中所示,kubectl(Kubernetes提供的客户端工具,该工具内部就是对Kubernetes API的调用)是直接和APIServer交互的。
Controller
Controller是控制器,它用来完成对集群状态的一些管理。比如刚刚我们提到的两个例子之中,第一个自动对容器进行修复、第二个自动进行水平扩张,都是由 Kubernetes 中的 Controller 来进行完成的;
如果说APIServer做的是“前台”的工作的话,那controller manager就是负责“后台”的。每个资源一般都对应有一个控制器,而controller manager就是负责管理这些控制器的。比如我们通过APIServer创建一个pod,当这个pod创建成功后,APIServer的任务就算完成了。而后面保证Pod的状态始终和我们预期的一样的重任就由controller manager去保证了。
Scheduler
Scheduler是调度器,“调度器”顾名思义就是完成调度的操作,把一个用户提交的 Container,依据它对 CPU、对 memory 请求大小,找一台合适的节点,进行放置, 就是上面介绍的;
scheduler的职责很明确,就是负责调度pod到合适的Node上。如果把scheduler看成一个黑匣子,那么它的输入是pod和由多个Node组成的列表,输出是Pod和一个Node的绑定,即将这个pod部署到这个Node上。Kubernetes目前提供了调度算法,但是同样也保留了接口,用户可以根据自己的需求定义自己的调度算法。
Etcd
etcd是一个高可用的键值存储系统,Kubernetes使用它来存储各个资源的状态,从而实现了Restful的API。
Etcd是一个分布式的一个存储系统,API Server 中所需要的这些原信息都被放置在 etcd 中,etcd 本身是一个高可用系统,通过 etcd 保证整个 Kubernetes 的 Master 组件的高可用性。
我们刚刚提到的 API Server,它本身在部署结构上是一个可以水平扩展的一个部署组件;Controller 是一个可以进行热备的一个部署组件,它只有一个 active,它的调度器也是相应的,虽然只有一个 active,但是可以进行热备。
Node
Kubernetes 的 Node 是真正运行业务负载的,Kubernetes 的 Node 并不会直接和 user 进行 interaction,它的 interaction 只会通过 Master。而 User 是通过 Master 向节点下发这些信息的。
- Pod: 每个业务负载会以 Pod 的形式运行。一个 Pod 中运行的一个或者多个容器,真正去运行这些 Pod 的组件的是叫做 kubelet,也就是 Node 上最为关键的组件,它通过 API Server 接收到所需要 Pod 运行的状态,然后提交到 Container Runtime 组件中。
- Storage Plugin: 在 OS 上去创建容器所需要运行的环境,最终把容器或者 Pod 运行起来,也需要对存储跟网络进行管理。Kubernetes 并不会直接进行网络存储的操作,他们会靠 Storage Plugin 或者是网络的 Plugin 来进行操作。用户自己或者云厂商都会去写相应的 Storage Plugin 或者 Network Plugin,去完成存储操作或网络操作。
- Network: 在 Kubernetes 自己的环境中,也会有 Kubernetes 的 Network,它是为了提供 Service network 来进行搭网组网的。
- Kube-proxy: 真正完成 service 组网的组件的是 Kube-proxy,它是利用了 iptable 的能力来进行组建 Kubernetes 的 Network。
组件交互
我们来看一个例子,看Kubernetes的组件如何进行交互:
- 用户可以通过 UI 或者 CLI 提交一个 Pod 给 Kubernetes 进行部署,这个 Pod 请求首先会通过 CLI 或者 UI 提交给 Kubernetes API Server,
- API Server 会把这个信息写入到它的存储系统 etcd,
- Scheduler 会通过 API Server 的 watch 或者叫做 notification 机制得到这个信息:有一个 Pod 需要被调度。这个时候 Scheduler 会根据它的内存状态进行一次调度决策,
- 完成这次调度之后,它会向 API Server report 说:“OK!这个 Pod 需要被调度到某一个节点上。”
- API Server 接收到请求操作,会把这次的结果再次写到 etcd 中,然后 API Server 会通知相应的节点进行这次 Pod 真正的执行启动。
- 相应节点的 kubelet 会得到这个通知,kubelet 就会去调 Container runtime 来真正去启动配置这个容器和这个容器的运行环境,去调度 Storage Plugin 来去配置存储,network Plugin 去配置网络。
这个例子我们可以看到:这些组件之间是如何相互沟通相互通信,协调来完成一次Pod的调度执行操作的。
Kubernetes核心概念以及APi
核心概念
Pod
Pod被分配到一个Node上之后,就不会离开这个Node,直到被删除。当某个Pod失败,首先会被Kubernetes清理掉,之后ReplicationController将会在其它机器上(或本机)重建Pod,重建之后Pod的ID发生了变化,那将会是一个新的Pod。所以,Kubernetes中Pod的迁移,实际指的是在新Node上重建Pod。以下给出Pod的生命周期图。
Pod 是 Kubernetes 的一个最小调度以及资源单元。用户可以通过 Kubernetes 的 Pod API 生产一个 Pod,让 Kubernetes 对这个 Pod 进行调度,也就是把它放在某一个 Kubernetes 管理的节点上运行起来。一个 Pod 简单来说是对一组容器的抽象,它里面会包含一个或多个容器。
- 最小的调度及资源单元
- 由一个或者多个容器组成
- 定义容器的运行方式(环境变量、command命令等)
- 提供容器的共享运行环境(网络、进程等),容器可以用 localhost 来进行直接的连接,而 Pod 与 Pod 之间,是互相有 isolation 隔离的。
如上图,它包含了两个容器,每个容器可以指定它所需要资源大小。比如说,一个核一个 G,或者说 0.5 个核,0.5 个 G。
当然在这个 Pod 中也可以包含一些其他所需要的资源:比如说我们所看到的 Volume 卷这个存储资源;比如说我们需要 100 个 GB 的存储或者 20GB 的另外一个存储。
Volume
Volume 就是卷的概念,它是用来管理 Kubernetes 存储的,是用来声明在 Pod 中的容器可以访问文件目录的,一个卷可以被挂载在 Pod 中一个或者多个容器的指定路径下面。
Volume 本身是一个抽象的概念,一个 Volume 可以去支持多种的后端的存储。比如说 Kubernetes 的 Volume 就支持了很多存储插件,它可以支持本地的存储,可以支持分布式的存储,比如说像 ceph,GlusterFS ;它也可以支持云存储,比如说阿里云上的云盘、AWS 上的云盘、Google 上的云盘等等。
Deployment
Deployment 是在 Pod 这个抽象上更为上层的一个抽象,它可以定义一组 Pod 的副本数目、以及这个 Pod 的版本。一般大家用 Deployment 这个抽象来做应用的真正的管理,而 Pod 是组成 Deployment 最小的单元。
- 定义一组Pod副本数、版本等
- 通过控制器(Controller)维持Pod的数目,自动恢复失败的Pod
- 通过控制器(Controller)来制定版本策略及控制,如:滚动升级、重新生成、回滚等
比如说我可以定义一个 Deployment,这个 Deployment 里面需要两个 Pod,当一个 Pod 失败的时候,控制器就会监测到,它重新把 Deployment 中的 Pod 数目从一个恢复到两个,通过再去新生成一个 Pod。通过控制器,我们也会帮助完成发布的策略。比如说进行滚动升级,进行重新生成的升级,或者进行版本的回滚。
Service
Service 提供了一个或者多个 Pod 实例的稳定访问地址。这点类似于DDD中的service,更多的是做调用链的处理。
对一个外部用户来讲,提供了多个具体的 Pod 地址,这个用户要不停地去更新 Pod 地址,当这个 Pod 再失败重启之后,我们希望有一个抽象,把所有 Pod 的访问能力抽象成一个第三方的一个 IP 地址,实现这个的 Kubernetes 的抽象就叫 Service。
- 提供访问一个或者多个Pod实例的稳定的访问地址(一定是稳定的不变的,否则各种变化的情况下,就无法访问了,这里固定并不是指IP固定)
- 支持多种访问方式,如ClusterIP、NodePort、LB
比如在上面的例子中,我们看到:一个 Deployment 可能有两个甚至更多个完全相同的 Pod。对于一个外部的用户来讲,访问哪个 Pod 其实都是一样的,所以它希望做一次负载均衡,在做负载均衡的同时,我只想访问某一个固定的 VIP,也就是 Virtual IP 地址,而不希望得知每一个具体的 Pod 的 IP 地址。
这个 pod 本身可能出错或者终止,如果一个 Pod 失败了,可能会换成另外一个新的。
实现 Service 有多种方式,Kubernetes 支持 Cluster IP,上面我们讲过的 kuber-proxy 的组网,它也支持 nodePort、 LoadBalancer 等其他的一些访问的能力。
Namespace
Namespace 是用来做一个集群内部的逻辑隔离的,它包括鉴权、资源管理等。Kubernetes 的每个资源,比如刚才讲的 Pod、Deployment、Service 都属于一个 Namespace,同一个 Namespace 中的资源需要命名的唯一性,不同的 Namespace 中的资源可以重名。
你可以将它当做是一个大模块的隔离,类似于DDD中domain领域,有明确的边界,是一个大型group的概念
- 提供一个集群内部的逻辑隔离机制(比如鉴权、资源调度等)
- 每个资源都被一个Namespace包含
- 同一个集群内,Namespace名称唯一
- 同一个Namespace中,资源名称不可重复,不同Namespace中,资源名称可重复
Kubernetes API
Kubernetes API 是由 HTTP+JSON 组成的:用户访问的方式是 HTTP,访问的 API 中 content 的内容是 JSON 格式的。
Kubernetes 的 kubectl 也就是 command tool,Kubernetes UI,或者有时候用 curl,直接与 Kubernetes 进行沟通,都是使用 HTTP + JSON 这种形式。
Pod的配置信息中有几个重要部分,apiVersion、kind、metadata、spec以及status。其中apiVersion和kind是比较固定的,status是运行时的状态,所以最重要的就是metadata和spec两个部分。
对于这个 Pod 类型的资源,它的 HTTP 访问的路径,就是 API,然后是 apiVesion: V1, 之后是相应的 Namespaces,以及 Pods 资源,最终是 Podname,也就是 Pod 的名字。
如果我们去提交一个 Pod,或者 get 一个 Pod 的时候,它的 content 内容都是用 JSON 或者是 YAML 表达的。上图就是一个yaml。
- Api version: 比如在这个例子中是 V1,它也会描述我在操作哪个资源;
- Kind: 资源的类型,比如我想要操作pod资源;
- metadata: 资源的元信息,比如名称、标签label(label 可以是一组 KeyValuePair。
比如下图的第一个 pod 中,label 就可能是一个 color 等于 red,即它的颜色是红颜色。当然你也可以加其他 label,比如说 size: big 就是大小,定义为大的,它可以是一组 label。
这些 label 是可以被 selector,也就是选择器所查询的。这个能力实际上跟我们的 sql 类型的 select 语句是非常相似的,比如下图中的三个 Pod 资源中,我们就可以进行 select。name color 等于 red,就是它的颜色是红色的,我们也可以看到,只有两个被选中了,因为只有他们的 label 是红色的,另外一个 label 中写的 color 等于 yellow,也就是它的颜色是黄色,是不会被选中的。)。在 Metadata 中,有时候也会去写 annotation,也就是对资源的额外的一些用户层次的描述。 - SPec: 比较重要的一个部分叫做 Spec,Spec 也就是我们希望 Pod 达到的一个预期的状态。比如说它内部需要有哪些 container 被运行;比如说这里面有一个 nginx 的 container,它的 image 是什么?它暴露的 port 是什么?
简单的demo,操作一下k8s
mac准备
先安装一下docker,之前博客有介绍,这里不再赘述
首先得安装好环境,我们先下载虚拟机:
https://www.virtualbox.org/wiki/Downloads
其次我们需要在虚拟机中启动 Kubernetes,Kubernetes 有一个非常有意思的项目,叫 minikube,也就是启动一个最小的 local 的 Kubernetes 的一个环境。
https://yq.aliyun.com/articles/221687 (你没看错,就是阿里爹的资源,毕竟阿里爹无所不能)
最后在安装完 virtualbox 和 minikube 之后,大家可以对 minikube 进行启动,也就是下面这个命令。
minikube start —vm-driver virtualbox
其他系统参考:
https://kubernetes.io/docs/tasks/tools/install-minikube/
安装错误
如果安装后,各种启动失败,或者ssh tcp 拒绝连接,就使不要使用阿里的改装版本
使用下面命令安装
brew cask install minikube
或者
curl -Lo minikube https://storage.googleapis.com/minikube/releases/v0.29.0/minikube-darwin-amd64 && chmod +x minikube && sudo cp minikube /usr/local/bin/ && rm minikube
然后
minikube start
参考:https://www.jianshu.com/p/3b419cc7d290
如果还是有问题,比如:
The connection to the server x.x.x.x:x was refused - did you specify the right host or port?,有下面几种解决方式:
- minikube delete 然后minikube start
- minikube stop -> kubectl config use-context minikube -> minikube start
- 实在不行的话,minikube stop, minikube delete, rm -rf ~/.minikube, minikube start
操作起来
先用常用的命令看一下
按照官网做一个测试
以下步骤均来自于官网,更多信息点击标题进入官网查看
创建和探究一个nginx deployment
创建一个deployment.yaml文件
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 2 # tells deployment to run 2 pods matching the template
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.7.9
ports:
- containerPort: 80
执行kubectl apply -f deployment.yaml
更新deployment
我们创建一个deployment-scale.yaml,更新ngxin镜像版本:
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
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 # Update the version of nginx from 1.7.9 to 1.8
ports:
- containerPort: 80
执行 kubectl apply -f deployment-update.yaml, 然后kubectl get pods -l app=nginx 查看pod信息, kubectl describe deployment nginx-deployment查看具体的 pod信息
通过增加副本数来弹缩应用
和上面步骤一样,创建一个deployment-scale.yaml,里面修改副本个数:
apiVersion: apps/v1 # for versions before 1.9.0 use apps/v1beta2
kind: Deployment
metadata:
name: nginx-deployment
spec:
selector:
matchLabels:
app: nginx
replicas: 4 # Update the replicas from 2 to 4
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.8
ports:
- containerPort: 80
执行 kubectl apply -f deployment-scale.yaml, 然后kubectl get pods -l app=nginx 查看pod信息, kubectl describe deployment nginx-deployment查看具体的 pod信息
问题须知
大家可以看到上面启动后,一直都是creating,并且ready一直是0.这个时候通过:
minikube logs
可以看到镜像没获取成功,这是因为,博主家里网络太tm渣。
小结
提供几个不错的博客参考链接
Kubernetes核心概念总结
kubernetes系列二:概念梳理
Kubernetes 配置Pod和容器(八) 拉取私有仓库镜像