博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Kubernetes基础:Service
阅读量:5880 次
发布时间:2019-06-19

本文共 3086 字,大约阅读时间需要 10 分钟。

本文的试验环境为CentOS 7.3,Kubernetes集群为1.11.2,安装步骤参见

Service 介绍

我们通过Pod、Deployment等可以将应用发布到Kubernetes平台中,但是如果我们如何才能访问我们部署的应用呢?有一个办法就是通过节点的IP加上节点的端口来访问这个节点上的容器应用,但是如果我们有多个跨节点的相通应用时该怎么办呢?特别是应用发生扩容、缩容时应该如何处理,这时我们就需要利用Service来实现。

在Kubernetes中,Service是一种资源,提供了我们访问单个或多个容器应用的能力。每个服务在其生命周期内,都拥有一个固定的IP地址和端口。每个服务对应了后台的一个或多个Pod,通过这种方式,客户端就不需要关心Pod所在的位置,方便后端进行方便的Pod扩容、缩容等操作。

可以通过下面的示意图来理解Service的作用。

39469-20181023132306675-1899988743.png

由此可知,服务可以被外部的客户访问,也可以被内部的客户访问。Service通过创建时指定的标签选择器来决定用户的请求转发到后台的哪些Pods中。看一下Service创建的具体例子。

apiVersion: v1kind: Servicemetadata:  name: tomcat-svcspec:  sessionAffinity: ClientIP # 该参数可以设置相同IP的请求总是定位到同一个Pod  ports:  - port: 8080    targetPort: 8080  selector:    app: tomcat

这个例子定义了一个Service名为tomcat-svc,端口为8080,该服务会将用户的请求转发到后台带有app=tomcat标签的Pods上。

kubectl get svc

我们在测试服务是否正常的时候,不能使用ping命令。因为Kubernetes中实现服务时,并不支持ping。因此不能使用ping的方式检查服务是否正常,应当使用telnet或者nc等命令进行测试。

Pod中的应用访问Service有两种方式,一种是通过向Pod中注入环境变量的方式,这种方式缺点很明显,必须首先创建Service,Pod内的应用才能通过环境变量访问;另一种方式是通过DNS的方式,这种方式非常灵活。

Service 与 endpints

Endpoints 是组成Service的一组IP地址和端口资源。

kubectl get endpoints kubia

默认情况下创建Service的时候,会创建一个同名的Endpoints资源,通过kubectl descirbe svc svc-name可以看到这个服务对应的Endpoints。

如果创建Service的时候,不指定Pod的选择器,则不会创建Endpoints资源。也可以手工创建Endpoints类型。创建时需要注意名称要与Service的名称一致。

apiVersion: v1kind: Endpointsmetadata:   name: external-servicesubsets:  - addresses:    - ip: 11.11.11.11    - ip: 22.22.22.22    ports:    - port: 80

Service 的类型

  • NodePort
  • Loadbalance
  • Ingress

实例解析

1. 创建内部服务

创建用于内部访问的服务很简单,创建后服务将在生命周期内拥有固定的IP和端口。

apiVersion: v1kind: Servicemetadata:  name: tomcat-svcspec:  sessionAffinity: ClientIP # 该参数可以设置相同IP的请求总是定位到同一个Pod  ports:  - port: 8080    targetPort: 8080  selector:    app: tomcat

客户每次链接Service时,都会对应到后端的一个Pod上,如果客户需要链接所有的后端Pod呢,可以使用headless service。通过这种方式,Kubernetes内部的DNS服务会将Service对应的所有IP返回。

apiVersion: v1kind: Servicemetadata:  name: tomcat-headlessspec:  clusterIP: None  ports:  - port: 8080    targetPort: 8080  selector:    app: tomcat

或者可以在客户端通过程序调用Kubernetes API的方式获取地址列表。

2. 为外部服务创建一个内部别名

容器内部的应用要访问外部应用时,可以直接在容器内访问外部服务地址,也可以通过创建一个外部服务的别名进行转发,这样相当于将内外部调用关系解耦了,每次外部发生变化的时候,可以不用修改应用的代码。

apiVersion: v1kind: Servicemetadata:  name: external-servicespec:  type: ExternalName  externalName: api.baidu.com  ports:  - port: 80

3. 向外部暴露内部服务

向外部暴露内部服务有三种方式:

  • NodePort
  • LoadBalancer
  • Ingress,7层负载均衡
3.1 NodePort 方式

创建这种方式的Service,内部可以通过ClusterIP进行访问,外部用户可以通过NodeIP:NodePort的方式单独访问每个Node上的实例。这种方式有很多问题,直接访问节点的地址和端口需要在客户端记录很多信息,Pod发生迁移后这些信息没办法动态更新,节点的防火墙及节点所在网络区域的防火墙策略配置会比较麻烦。

apiVersion: v1kind: Servicemetadata:  name: nodeportspec:  type: NodePort  ports:  - port: 80    targetPort: 8080    nodePort: 30123  selector:    app: httpd

端口如果忽略,Kubernetes会自动生成。

$ kubectl get svc nodeport

获取一些信息

kubectl get nodes -o jsonpath='{.items[*].status.addresses[?(@.type="InternalIP")].address}'

3.2 load balancer 方式

这种方式一般需要云供应商的支持,或者一些本地资源如F5的支持。这里不做过多介绍了。

3.3 Ingress 方式

LoadBalancer要求的IP资源较多,每个负载均衡服务都需要一个IP,Ingress可以只用一个IP,通过URL来判断需要访问的服务。Ingress工作在HTTP层,配置与使用更加灵活。目前为止还是一个beta特性。

目前有很多Ingress的支持:

  • Kubernetes提供的基于GCE、Nginx的Ingress控制器
  • Kong提供的
  • 提供收费的解决方案
  • NGINX提供的
  • 基于HAProxy的
  • Istio提供的

使用过程中的最佳实践:

  • 总是添加 Readiness 探测
  • 不要在探测中使用关闭的逻辑

39469-20180710163655709-89635310.png

参考资料

转载地址:http://wodix.baihongyu.com/

你可能感兴趣的文章
Android实战简易教程-第二十三枪(基于Baas的用户注冊验证username是否反复功能!)...
查看>>
在odl中怎样实现rpc
查看>>
leetcode 110 Balanced Binary Tree
查看>>
python活用isdigit方法显示系统进程
查看>>
项目开发总结
查看>>
知行合一
查看>>
jmeter插件之jsonpath提取响应结果和做断言
查看>>
发布支持多线程的PowerShell模块 —— MultiThreadTaskRunner
查看>>
Ubuntu ctrl+alt会导致窗口还原的问题
查看>>
第四十期百度技术沙龙笔记整理
查看>>
推荐系统那点事 —— 基于Spark MLlib的特征选择
查看>>
linux 下RTL8723/RTL8188调试记录(命令行)【转】
查看>>
SpringMVC案例1——对User表进行CRUD操作
查看>>
看雪CTF第十四题
查看>>
[Contiki系列论文之1]Contiki——为微传感器网络而生的轻量级的、灵活的操作系统...
查看>>
Android 网络编程 记录
查看>>
微软同步发行Windows 10和Windows 10 Mobile系统更新
查看>>
Maven 传递依赖冲突解决(了解)
查看>>
Zeppelin的入门使用系列之使用Zeppelin运行shell命令(二)
查看>>
[Spark][Python]Spark Join 小例子
查看>>