Kubernetes容器编排

kubernetes ginotang 1509℃ 0评论

简介

容器编排指对容器的创建、部署、销毁、网络处理、故障转移等管理行为,Kubernetes的容器编排能力强大,上手简单。

部署应用

准确来说是部署容器,前面说过,Pod是Kubernetes的最小管理单元,但我们一般不会直接管理Pod,通常是利用Controller作为媒介,这些Controller包括Deployment、ReplicaSet、DaemonSet、Job等。

使用Deployment

有两种方式使用Deployment,一种是直接使用命令行创建,另一种是通过yaml文件创建,即Kubernetes对象。

  • 通过命令行创建Deployment

    以前我们Docker run命令运行一个容器,Deployment的创建非常类似,使用的是kubectl run。例如创建两个副本的nginx应用

    很简单就创建了一个Deployment,webapp是deployment的名字,但它也作为lable使用,label后面会说。正如提示信息中显示,这种方式已被标记为deprecated,即不建议使用。创建好Deployment,查看它是否正常运行

    也可以检查Deployment中的pod运行情况

  • 通过yaml文件创建

    这次我们通过http镜像创建web服务,同样是两个副本,下面是简单的yaml格式

    httpd.yaml:

    文件准备好后通过kubectl apply命令创建Deployment

    通过kubectl describe命令查看pod的详细信息,其中一部分信息如下

    从Controlled By可以看出,这些Pod由ReplicaSet控制,而由此之中我们都没有使用过ReplicaSet,证明Deployment管理着ReplicaSet。describe命令可以查看很多资源的详细信息,不仅仅限于Pod。

两种部署方式各有好处:

  • 命令行适合于临时测试
  • yaml适合产品部署
  • 命令行方式部署方式不可追踪
  • yaml方式可追踪

使用DaemonSet

Deployment不限制Pod在Host中的数量,而DaemonSet限制一个Host上面只能运行Pod的单个实例,即不能有副本的Pod。Kubernetes必要组件就运行有daemonset:flannel组件和proxy组件

按照这个特征,daemonset非常适合运行用于日志收集和容器监控的Pod。

以日志收集系统ELK Stack为例子

查看系统现有的daemonset

使用Service

Pod很可能会因为某种原因而发生故障,为了保证服务的高可用,Controller就会创建新的Pod替换掉发生故障的Pod。这也就产生一个问题:Pod的IP地址发生变化,客户端如何正确访问Pod提供的服务。

答案是使用Service。

Service也有自己的IP地址,它会根据label来连接对应的Pod,一旦Service和Pod建立好逻辑关系之后,我们就可以通过Service的IP地址来访问与之连接的Pod。Pod的地址会发生变化,但Service的则不会。

以上面的elk stack为例子,一般来说,我们都是通过kibana的web端口访问数据,也就是说需要开放5601端口给外网

elk-svc.yaml:

准备好后通过kubectl apply创建Service

外网访问Service的三种方式

这三种方式分别是:

  • ClusterIP 默认Service的行为,只能在cluster内部访问Pod
  • NodePort 把外部到Host的端口流量转发到Pod中,实现外网访问Pod
  • LoadBalancer Service 利用 cloud provider 特有的 load balancer 对外提供服务,cloud provider 负责将 load balancer 的流量导向 Service。目前支持的 cloud provider 有 GCP、AWS、Azur 等。

上面的例子中Service的type设置了NodePort,这样就可以通过Host的IP地址访问到Pod。使用NodePort的时候我们设置了三个端口,分别是

  • nodePort host开放的端口
  • port clusterIP开放的端口
  • targetPort Pod开放的端口

实际上,NodePort方式是在clusterIP的基础上发展出来的,通过host上的端口访问clusterIP的端口,最后clusterIP访问Pod暴露的端口。

检查现有的service

通过DNS访问Service

在Cluster中,除了可以使用ClusterIP访问service外,还可以使用kubernetes提供的DNS访问,该功能由core-dns组件提供。Cluster 中的 Pod 可以通过 <SERVICE_NAME>.<NAMESPACE_NAME> 访问 Service
如果默认名称空间default中运行着nginx,那么nginx就可以通过kubernetes.default访问默认的Service,由于它们在同一个namespace中,因此可以省略.default,直接使用kubernetes就可以了

而不同名称空间的Pod/Service使用DNS,必须通过<SERVICE_NAME>.<NAMESPACE_NAME>的方式,这个例子是kubernetes.default。

控制Pod的运行位置

默认情况下,Scheduler会将Pod分配到所有可用的节点,但master节点除外。因为master设置了一个taint

node-role.kubernetes.io/master:NoSchedule表示Pod不会被分配到该节点。

我们可以手动控制Pod的运行位置,例如CPU密集型的任务部署在CPU性能高的节点,硬盘IO密集型的任务部署在硬盘性能高的节点。

首先, 为目标节点添加一个label

其次,通过nodeSelector分配节点

修改yaml文件

重新部署应用

检查运行情况

因为ubuntu-host1标记了高性能(performance=high),因此两个副本都运行在这个节点上面,达到预期效果。

删除label

通过下面的方式删除label(在key后面添加一个横线)

删除label后Pod不会被迁移,依然运行在这个节点,除非重新部署。

应用的弹性伸缩

通过replicas参数,可以在线动态增加或减少Pod的数量,以上面的yaml文件为例,一开始创建了2个副本的应用,现在增加到5个

然后执行apply命令

现在deployment中的Pod数量应该就是5

减少Pod数量同理,只需要设置replicas设为相应的值然后执行apply命令即可。

滚动更新

滚动更新指的是对镜像版本的更新,假设原先服务器上部署的nginx应用如下

nginx.yaml

过了一段时间之后,需要把nginx更新到1.15,只需要把nginx的镜像版本改为对应版本,然后执行apply命令

通过输出可知,kubernetes每次执行一个更新,假如前面的更新失败,更新停止

更新策略

虽然不可以直接设置每次更新的副本数量,但是可以控制副本更新时的可用数量。这两个参数是

  • maxSurge 滚动更新过程中副本总数可超过 DESIRED 的上限(向上取整)。可以是数值或百分比,默认是25%
  • maxUnavailable 更新过程中不可用的Pod的最大数量(向下取整)。可以是数值或百分比,默认是25%

具体配置文件

执行相关命令获取输出信息

由于maxSurge和maxUnavailable的值都设置为30%,因此更新情况如下:

  • Pod的数量马上增加30%,原先有10个,即多了3个,所以CURRENT是13
  • 不可用的Pod数量只能是3个(30%),因此10-3=7,所以AVAILABLE值为7

结论:

maxSurge 值越大,初始创建的新副本数量就越多;maxUnavailable 值越大,初始销毁的旧副本数量就越多。

回滚

在测试过程中,我们可能经常会在不同版本之间切换,kubernetes提供了版本回滚支持。

当使用kubectl apply命令的时候,通过--record参数,可以让kubernetes记录下每次更新的版本信息,这样就可以很方便地使用回滚功能。例如有两个Deployment文件,对应的nginx版本是1.14和1.15

我们先部署1.14版本的

通过--record参数,kubernetes已经记录下了部署该应用的对应文件。

现在我们把nginx更新到1.15

现在版本变更里面有两个记录。

假如项目需要进行回滚,那么通过下面的命令即可

nginx成功退回到1.14版本。

健康检查

kubernetes默认根据容器中CMD或ENTRYPOINT的返回值来检查容器的健康状况,如果它们返回0,则容器正常,非0则表示容器状态异常,异常的容器是否需要重启,还需要看restartPolicy

kubernetes提供了两种自定义的方式检查容器的健康状况:

  • liveness探测 判断容器是否需要重启以实现自愈
  • readiness探测 判断容器是否已经准备好对外提供服务,如果探测失败,service不会转发流量给此容器

如果没有对它们进行配置,使用默认健康检查。

Liveness探测

通过以下文件创建一个Pod, 通过关键字livenessProbe设置liveness探测。

Pod的相关设定:

  • 重启策略(restartPolicy):OnFailure 失败的时候重启
  • liveness探测: 如果/tmp/healthy文件存在,则说明Pod健康,否则需要重启
  • initialDelaySeconds 10表示容器启动10秒后进行健康检查
  • periodSeconds 5表示每5秒执行一次检查

Readiness探测

Readiness探测使用和Liveness探测一样,只不过把livenessProbe改为readinessProbe

当Readiness探测失败(/tmp/healthy不存在的时候),那么Service就不会把流量转发给这个Pod,保证了服务的可靠性。

httpGet

除了使用exec执行特定命令外,Kubernetes还提供了httpGet方案,用于向指定url发起请求,通过返回的状态码检测页面是否可用。通常成功的状态码在200~400之间,但不包含400。

下面的例子创建了一个Deployment和对应的Service

Readiness探测使用httpGet方式访问uri地址/healthy,通过返回的状态码获取地址的可用性,当状态码在非200~400之间,表示容器还没有就绪,Service不会将流量转发给这个Deployment。直到检测周期内状态码变为可用,Service才会把流量发给它。

对于/healthy这个uri,可以编写自己的检测逻辑,并根据这个逻辑返回状态码,例如,healty脚本检测数据库是否可用,如果可用则返回状态码200,否则不可用。

转载请注明:Pure nonsense » Kubernetes容器编排

喜欢 (0)
0 0 投票数
文章评分
订阅评论
提醒
guest
0 评论
内联反馈
查看所有评论
0
希望看到您的想法,请您发表评论x
()
x