vlambda博客
学习文章列表

k8s系列第六篇~k8s资源对象-应用类资源对象(三)

上篇文章主要带大家了解了应用类资源的label、标签选择器、poddeploymentserviceclusterIP,本文将带大家学习应用类资源的service的外网访问问题、有状态的应用集群、批处理应用、应用的配置问题。

 

1、Service的外网访问问题

以tomcat-service为例,在service的定义说明NodePort的定义:
apiVersion:v1kind:Servicemetadata:  name:tomcat-servicespec:  selector:name:myweb  type: NodePort  ports:   - protocol:TCP      port:8080 nodePort:30072
nodePort:30072属性表名手动指定tomcat-serviceNodePort30072,否则k8s会自动为其分配一个可用的端口,访问形式:http://<nodeIp>:30072/

 




如上图,负载均衡器组件独立于k8s集群之外,可以是一个硬件的负载均衡器也可以是一个软件的负载均衡器,例如HAProxyNginx。对于每个service,我们通常需要配置一个对应的负载均衡器实例来转发流量到后端的node上,这就增加了工作量和出错的概率。

NodePort虽然功能强大,但是也存在问题,每个service都需要在node上独占一个端口,而端口又是有限的物理资源,ingress资源对象解决了此问题,ingres可以让多个service对外用一个端口。在一定程度上,可以把ingress的实现机制理解为基于nginx的支持虚拟主机的http代理,下面是ingress的实例:

apiVersion: networking.k8s.io/v1kind: Ingressmetadata:  name: name-virtual-host-ingressspec: rules:  - host: first.bar.com    http:      paths:      - pathType: Prefix        path: "/bar"        backend:          service:            name: service1            port:              number: 80  - host: second.foo.com    http:      paths:      - pathType: Prefix        path: "/foo"        backend:          service:            name: service2            port:              number: 80
在以上 ingress 的定义中,访问 first.bar.com/bar 请求的流量会被路由到 service1 ,到 second. foo.com/ foo 请求的流量会被转发到 service2

 

2、有状态的应用集群

Deployment对象是用来实现无状态服务的多副本自动控制功能的,那么有状态的服务,比如zookeeper集群、mysql集群、kafaka集群等,一开始是依赖StatefulSet解决的,但是一些复杂的有状态的集群应用,StatefulSet无法支撑,后面又出现了kubernetes operator

有状态集群中一般有如下特殊共性:

  • 每个节点都有固定的身份id,通过这个id,集群中的成员可以互相发现并通信。

  • 集群的规模是比较固定的,集群规模不能随意变动。

  • 集群中的每个节点都是有状态的,通常会持久化数据到永久存储中,每个节点在重启后都是需要使用原有的持久化数据。

  • 集群中成员节点的启动顺序通常也是确定的。

  • 如果磁盘损坏,则集群里的某个节点无法正常运行,集群功能受损。

 

Kubernetes引入了专门的资源对象StatefulSet,特征如下:

  • StatefulSet里的每个都有稳定、唯一的网络标识,可以用来发现集群中的其他成员。假设StatefulSet的名称为kafka,那么第1podkafka-0,第2podkafka-1,以此类推。

  • StatefulSet控制的pod的启停顺序是受控的,操作第npod时,前n-1pod已经是运行且准备好的状态。

  • StatefulSet里的pod采用稳定的持久化存储卷,通过pvpvc实现,删除pod时默认不会删除与StatefulSet相关的存储卷。

 
StatefulSet 除了要与 pv 卷捆绑使用,以存储 pod 的状态数据,还要与 headless service 配合使用,即在每个 StatefulSet 定义中都要声明它属于哪个 headless service StatefulSet headless service 的基础上又为 StatefulSet 控制的每个 pod 都创建一个 DNS 域名,域名的格式: $(podName).$(headless service name)


3、批处理应用

除了无状态服务、有状态集群,还有批处理应用。批处理应用的特点是一个或多个进程处理一组数据(图像、文件、视频等),在这组数据都处理完成后,批处理任务自动结束。为了支持这类应用, k8s 引入了新的资源对象 --job ,下面是一个计算圆周率的例子:

apiVersion: batch/v1kind: Jobmetadata:  name: pispec:  template:    spec:      containers:      - name: pi        image: perl        command: ["perl",  "-Mbignum=bpi", "-wle", "print bpi(2000)"]      restartPolicy: Never  backoffLimit: 4  parallelism: 1 completion: 5


job控制器提供了两个控制并发的参数:completionsparallelismcompletions表示需要运行任务的总数,parallelism表示并发运行的个数,例如,设置parallelism1,则会依次运行任务,在前面的任务运行后再运行后面的任务。Job所控制的pod副本是短暂运行的,可以将其视为一组容器,其中的每个容器都仅运行一次。当job控制的所有副本都运行结束后,对应的job也就结束了。Job生成的pod副本不能自动重启,podrestartPolicy设置为NeverK8s还提供了CronJob周期性地执行某个任务。

 

4、应用的配置问题

通过前面的学习,我们初步了解了三种应用建模的资源对象,如下:

  • 无状态服务的建模:Deployment
  • 有状态集群的建模:StatefulSet
  • 批处理应用的建模:Job
在进行应用建模时,可以用 ConfigMap Secret 解决配置中心问题。
ConfigMap就是保存配置项的一个Map,和java语言中的map不一样,ConfigMap是分布式系统中“配置中心”的独特实现之一。将应用的配置化信息存储在ConfigMap中的建模做法如下:
  • 用户将配置文件的内容保存在ConfigMap中,文件名可作为keyvalue就是整个文件的内容,多个配置文件都可被放入同一个ConfigMap中。

  • 在建模用户应用时,在pod里将ConfigMap定义为特殊的volume进行挂载。在pod被调度到某个具体的node上时,ConfigMap里的配置文件会被自动还原到本地的目录下,然后映射到pod里指定的配置目录下,这样用户就可以无感知地读取配置了。

  • ConfigMap的内容发生修改后,kubernetes会自动重新获取ConfigMap的内容,并在目标节点上更新对应的文件。


 


Secret用来解决敏感信息配置问题,比如数据库的用户名和密码、应用的数字证书、token等需要保密的敏感配置。对于这类敏感信息,我们可以创建一个Secret对象,在pod中引用。