Kubernetes Service 与 Ingress 浅析

Service

Service的本质

Service的本质就是一个统一的网络访问标识,用于将流量转发向提供同种服务的一组后端Pod,以网络访问标识的稳定性来弥补Pod IP动态变化特性带来的问题。

Service的四种类型分别适用于什么样的场景

ClusterIP
供K8s集群内访问,是默认的Service类型,当服务不需要对外暴露时可以采用这张类型。
在Kubernetes 1.11 后,ClusterIP类型的Service主要基于内核的IPVS模块实现的,以提供集群内部的服务发现和负载均衡能力。

NodePort
在每个Node节点上打开相同的端口,供集群外部访问。
这种方式比较简单粗暴,NodePort类型的Service其实就是在ClusterIP类型的基础上,kube-proxy额外在每个Node节点上打开一个端口(默认在30000-32767范围内,可通过kube-proxy命令行参数调整),并将访问该端口的流量导向Service的VIP(NodePort不支持ClusterIP为None)。
NodePort比较适合开发环境,临时验证下服务能否被外部访问,但是它的缺点也很明显:

  1. 每个端口只能是一种服务,多个服务之间端口不能冲突
  2. 如果Node节点的 IP 地址发生变化,需要额外的处理
    由于NodePort类型的服务的这些缺点,在生产环境上都是使用LoadBalancer来对集群外暴露服务的。

LoadBalancer
需要配合云服务商的负载均衡产品实现。
LoadBalancer是在NodePort类型服务的基础上,前置一个云服务商的负载均衡器来管理各个Node节点上的NodePort。所以LoadBalancer创建时除了创建本身的Service这个资源外,还会配合云服务商的API异步地创建一个负载均衡实例(有的云服务商也支持绑定现有的负载均衡实例)。
类似于ClusterIP类型的服务通过IPVS实现集群内部的负载均衡,LoadBalancer类型的服务通过云服务商的负载均衡器实现了外部访问集群时的负载均衡,也就是说生产环境上从外部访问一个服务至少会经过这两层负载均衡。

ExternalName
能够对K8s集群外的后端服务提供服务发现能力。
ExternalName实际上就是创建一个CNAME记录,当其他服务访问Service对应的DNS时,集群的DNS服务就会把流量转向集群外部的DNS名称。

ClusterIP类型中,无头与有头有啥区别

在Cluster IP类型的服务中,无头和有头指的是这个服务是否被分配了一个VIP(虚拟IP),从YAML文件上看就是clusterIP这个字段是否为None。
在有头的情况下,kube-proxy会在netfilter的规则表中设置转发规则,将所有访问VIP的流量分发给各个后端Pod的IP来实现负载均衡。(VIP之所以称为VIP,也是因为它只存在于规则表中作为转发结点,而不像其他IP地址那样跟网卡绑定)
在无头的情况下,流量从Service的域名直接转发到后端Pod,不经过VIP,因此也就无法通过netfiler的机制来实现负载均衡。但是每个后端Pod都会分配到一个形如<pod-name>.<svc-name>.<namespace>.svc.cluster.local的域名,可以在Statefulset中使用用于维护多个实例之间的拓扑状态。

Service的负载均衡策略有哪些

基于IPVS模式的Service支持以下负载均衡策略:

  • rr: round-robin
  • lc: least connection (smallest number of open connections)
  • dh: destination hashing
  • sh: source hashing
  • sed: shortest expected delay
  • nq: never queue
    外层的云服务商提供的负载均衡器也有各自的负载均衡策略,常见的有基于Client IP的会话粘性策略。

Ingress

Ingress的本质

Ingress是Kubernetes对反向代理这一常见Web组件的抽象,用于管理从互联网访问集群内部服务的HTTP、HTTPS流量。

Ingress与IngressController的关系

通常说的Ingress包含Ingress资源本身以及负责动态管理Ingress资源的Ingress Controller。Ingress资源是对反向代理中各种配置规则的抽象,而Ingress Controller就是负责解析这些配置规则并实现监听套接字、流量转发等反向代理能力来使这些规则生效。

Traefik v1.7 helm部署示例
# 下载traefik的helm chart
helm fetch stable/traefik
tar -zxf traefik-1.78.4.tgz && cd traefik

# 仅供测试使用时,可以将Service类型设置为NodePort
sed "/^serviceType:/s/LoadBalancer/NodePort/g" values.yaml

# 安装traefik
helm install . --name my-release --namespace kube-system

# 查看服务信息
kubectl describe svc my-release-traefik --namespace kube-system

安装完成后,在浏览器上访问 NodeIP:NodePort,出现 404 page not found页面(此时还没有管理后端服务),则说明安装成功 。之后就可以创建Ingress资源暴露需要的HTTP服务了。

最流行的几个 IngressController 的比较

Traefik 更加云原生,可以动态感知后端服务的变化,支持的协议种类丰富,包括TCP, HTTP, HTTPS, GRPC 和 Websocket,而且也支持使用免费证书 Let’s Encrypt

Kong 适合做API网关,但是负载均衡性能不好,需要做配置调优或者一些插件支持

Nginx-ingress 最常用,但是缺乏动态服务发现

Haproxy 丰富的负载均衡策略,支持TCP负载均衡

Ambassador 是最新一代的 Ingress Controller,也可以作为API网关,支持TCP负载均衡

Port-forward

在开发/测试环境下,有时候需要临时暴露服务,但又不想费力气去写一个Ingress或者LoadBalancer或NodePort类型的Service,就可以使用 kubectl 命令行自带的 port-forword 子命令进行端口转发来暴露服务,其命令行格式是:

kubectl port-forward TYPE/NAME [options] [LOCAL_PORT:]REMOTE_PORT

其中type为 API对象的类型,如Pod、Deployment、Service,但是最终都会从API对象关联的Pod中选择一个来进行端口转发,LOCAL_PORT就是声明要在kubectl所在的本地打开的端口,REMOTE_PORT是Pod暴露的一个端口。

# 临时暴露一个redis服务
kubectl port-forward service/redis 6379:6379 --address 0.0.0.0

这样就可以在本地访问redis服务了,其中 --address=0.0.0.0 参数是指将端口绑定0.0.0.0,这样其他主机也可以访问,不指定的话默认绑定localhost
ps: port-forword是不稳定的端口映射方式,没有故障切换机制,当连接的后端Pod生命周期结束时,port-forward的会话也就结束了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

wonain

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值