k8s service type_【大强哥-k8s从入门到放弃13】Service详解

5841293841598c0e721669cde2bf0d81.png

一、何为Service

Service 是一个应用服务抽象,定义了 Pod 逻辑集合和访问这个 Pod 集合的策略。
Service 代理 Pod 集合对外表现是为一个访问入口,分配一个集群 IP 地址及端口,来自这个 IP 的请求将被负载均衡 (kube-proxy)转发到后端 Pod 中的容器。
Service 通过 LableSelector 选择一组 Pod 提供服务。(以标签的形式标识服务)

Service 其实就是我们经常提起的微服务架构中的一个“微服务”,Pod、RC 等资源对象其实都是为它作“嫁衣”的。

Kubernetes 的 Service 定义了一个服务的访问入口地址,前端的应用(Pod)通过这个入口地址访问其背后的一组由 Pod 副本组成的集群实例,Service 与其后端 Pod 副本集群之间则是通过 Label Selector 来实现“无缝对接”的。而 RC 的作用实际上是保证 Service 的服务能力服务质量始终处于预期的标准。

通过分析、识别并建模系统中的所有服务为微服务——Kubernetes Service,最终我们的系统由多个提供不同业务能力而又彼此独立的微服务单元所组成,服务之间通过TCP/IP 进行通信,从而形成了强大而又灵活的弹性集群,拥有了强大的分布式能力、弹性扩展能力、容错能力。因此,我们的系统架构也变得简单和直观许多。

既然每个 Pod 都会被分配一个单独的 IP 地址,而且每个 Pod 都提供了一个独立的 Endpoint(Pod IP+ContainerPort)以被客户端访问,多个 Pod 副本组成了一个集群来提供服务,那么客户端如何来访问它们呢?

一般的做法是部署一个负载均衡器(软件或硬件),但这样无疑增加了运维的工作量。在 Kubernetes 集群里使用了 Service(服务),它提供了一个虚拟的 IP 地址(Cluster IP)和端口号,Kubernetes 集群里的任何服务都可以通过 Cluster IP+端口的方式来访问此服务,至于访问请求最后会被转发到哪个 Pod,则由运行在每个 Node 上的 kube-proxy 负责。kube-proxy 进程其实就是一个智能的软件负载均衡器,它负责把对 Service 的请求转发到后端的某个 Pod 实例上,并在内部实现服务的负载均衡与会话保持机制。

三、Service实例

1、拉取镜像

[root@k8s-master docker]#  docker pull daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim

2、验证镜像可用性

[root@k8s-master docker]# docker run -d -p 58080:8080 --name mytomcat daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim
c8a00a7aab85ee3b342fb7cd1515a464bde1195397432173b6126f4242244ef9
[root@k8s-master docker]# docker ps -a|grep tomcat
c8a00a7aab85        daocloud.io/library/tomcat:9.0.22-jdk11-openjdk-slim               "catalina.sh run"        2 minutes ago       Up 2 minutes                 0.0.0.0:58080->8080/tcp   mytomcat

浏览器访问验证 http://192.168.111.130:58080/

3、创建一个Deployment

root@k8s-master ~]# cat deployment-hello.yaml 

4、定义Service

apiVersion

上述内容定义了一个名为 “tomcat-service” 的 Service,它的服务端口为 8080,拥有 “tier=frontend” 这个 Label 的所有 Pod 实例。 很多服务都存在多个端口的问题,通常一个端口提供业务服务,另外一个端口提供管理服务,比如 Mycat、Codis 等常见中间件。Kubernetes Service 支持多个 Endpoint,要求每个 Endpoint 定义一个名字来区分,下面是 tomcat 多端口的 Service 定义样例。

apiVersion

对外暴露端口实例

[

下面是一个完整实例

apiVersion

多端口为什么需要给每个端口命名呢?这就涉及 Kubernetes 的服务发现机制了。

四、Kubernetes 的服务发现机制

每个 Kubernetes 中的 Service 都有一个唯一的 Cluster IP 及唯一的名字,而名字是由我们自己定义的,那我们是否可以通过 Service 的名字来访问呢? 最早时 Kubernetes 采用了 Linux 环境变量的方式来实现,即每个 Service 生成一些对应的 Linux 环境变量(ENV),并在每个Pod的容器启动时,自动注入这些环境变量,以实现通过 Service 的名字来建立连接的目的。 考虑到通过环境变量获取 Service 的 IP 与端口的方式仍然不方便、不直观,后来 Kubernetes 通过 Add-On 增值包的方式引入了 DNS 系统,把服务名作为 DNS 域名,这样程序就可以直接使用服务名来建立连接了。

五、暴露服务

Kubernetes集群里有三种IP地址,分别如下:

  • Node IP:Node 节点的IP地址,即物理网卡的IP地址。
  • Pod IP:Pod 的IP地址,即 docker 容器的IP地址,此为虚拟IP地址。
  • Cluster IP:Service 的IP地址,此为虚拟IP地址。

外部访问 Kubernetes 集群里的某个节点或者服务时,必须要通过 Node IP 进行通信。 Pod IP 是 Docker Engine 根据 flannel.1 网桥的 IP 地址段进行分配的一个虚拟二层网络IP地址,Pod 与 Pod 之间的访问就是通过这个虚拟二层网络进行通信的,而真实的TCP/IP 流量则是通过 Node IP 所在的物理网卡流出的。 Service 的 Cluster IP 具有以下特点:

  • Cluster IP 仅仅作用于 Service 这个对象,并由 Kubernetes 管理和分配 IP 地址。
  • Cluster IP 只能结合 Service Port 组成一个具体的通信端口,供 Kubernetes 集群内部访问,单独的 Cluster IP 不具备 TCP/IP 通信的基础,并且外部如果要访问这个通信端口,需要做一些额外的工作。
  • Node IP、Pod IP 和 Cluster IP 之间的通信,采用的是 Kubernetes 自己设计的一种特殊的路由规则,与我们熟悉的 IP 路由有很大的区别。

我们的应用如果想让外部访问,最常用的作法是使用 NodePort 方式。

apiVersion

NodePort 的实现方式是在 Kubernetes 集群里的每个 Node 上为需要外部访问的 Service 开启一个对应的 TCP 监听端口,外部系统只要用任意一个 Node 的 P 地址+具体的 NodePort 端口号即可访问此服务。 NodePort 还没有完全解决外部访问Service的所有问题,比如负载均衡问题,常用的做法是在 Kubernetes 集群之外部署一个负载均衡器。

Load balancer 组件独立于 Kubernetes 集群之外,可以是一个硬件负载均衡器,也可以是软件方式实现,例如 HAProxy 或者 Nginx。这种方式,无疑是增加了运维的工作量及出错的概率。 于是 Kubernetes 提供了自动化的解决方案,如果我们使用谷歌的 GCE 公有云,那么只需要将 type: NodePort 改成 type: LoadBalancer,此时 Kubernetes 会自动创建一个对应的 Load balancer 实例并返回它的 IP 地址供外部客户端使用。其他公有云提供商只要实现了支持此特性的驱动,则也可以达到上述目的。

四、端口详解

服务中的3个端口设置

这几个port的概念很容易混淆,比如创建如下service

apiVersion

port

The port that the service is exposed on the service’s cluster ip (virsual ip). Port is the service port which is accessed by others with cluster ip.
这里的port表示:service暴露在cluster ip上的端口,:port 是提供给集群内部客户访问service的入口。

nodePort

On top of having a cluster-internal IP, expose the service on a port on each node of the cluster (the same port on each node). You'll be able to contact the service on any:nodePortaddress. So nodePort is alse the service port which can be accessed by the node ip by others with external ip.
首先,nodePort是kubernetes提供给集群外部客户访问service入口的一种方式(另一种方式是LoadBalancer),所以,:nodePort 是提供给集群外部客户访问service的入口。

targetPort

The port on the pod that the service should proxy traffic to.
targetPort很好理解,targetPort是pod上的端口,从port和nodePort上到来的数据最终经过kube-proxy流入到后端pod的targetPort上进入容器。

port、nodePort总结

总的来说,port和nodePort都是service的端口,前者暴露给集群内客户访问服务,后者暴露给集群外客户访问服务。从这两个端口到来的数据都需要经过反向代理kube-proxy流入后端pod的targetPod,从而到达pod上的容器内。

When a client connects to the VIP the iptables rule kicks in, and redirects the packets to the serviceproxy's own port (random port). The service proxy chooses a backend, and starts proxying traffic from the client to the backend. This means that service owers can choose any port they want without risk of collision.The same basic flow executes when traffic comes in through a nodePort or through a LoadBalancer, though in those cases the client IP does get altered.

kube-proxy反向代理

kube-proxy与iptables

当service有了port和nodePort之后,就可以对内/外提供服务。那么其具体是通过什么原理来实现的呢?原因就在kube-proxy在本地node上创建的iptables规则。

Kube-Proxy 通过配置 DNAT 规则(从容器出来的访问,从本地主机出来的访问两方面),将到这个服务地址的访问映射到本地的kube-proxy端口(随机端口)。然后 Kube-Proxy 会监听在本地的对应端口,将到这个端口的访问给代理到远端真实的 pod 地址上去。

不管是通过集群内部服务入口:port还是通过集群外部服务入口:nodePort的请求都将重定向到本地kube-proxy端口(随机端口)的映射,然后将到这个kube-proxy端口的访问给代理到远端真实的 pod 地址上去。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值