【云驻共创】华为云云原生黄金课程07 轻松搞定 Kubernetes 网络与服务管理
一、Service
1.1. Service 基本概念
Kubernetes Service 定义了这样一种抽象:一个 Pod 的逻辑分组,以及一种可以访问他的策略——通常称为微服务。这一组 Pod 能够被 Service 访问,通常是通过 Label Selector 筛选 Pod 中的 Label 实现的。
- Cluster:Kubernetes 集群内部虚拟服务 IP(VIP),是 Service 的入口,由 kube-proxy 实现。
- Endpoints:Kubernetes 资源对象 Service 实际服务后端的集合。手动创建或 Endpoints controller 自动生成。
1.2. Service 的定义
我们通过一个简单的 Service yaml 认识一下 Service。
apiVersion: v1
kind: Service
spec:
type: ClusterIP
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 8080
- type: ClusterIP:是指集群内部服务之间访问的方式暴露服务。
- selector:就是开篇介绍过的 Label Selector 方式,Label Selector 将会选择有这样 Label 的 Pod 作为 Service 的后端。
- ports:常见的 protocol 有 TCP 和 HTTP,port 是指通过 ClusterIP 访问该服务时,需要使用什么端口,targetPort 是指运行在 Pod 内部的服务监听的端口。
下面简单介绍一下 Client Pod 访问集群内部的过程。
首先,Client Pod 通过 ClusterIP:port 访问集群内服务,结合前面介绍的 yaml,上图的中 Client Pod 应该使用 10.10.10.55:80 发起访问请求,kube-proxy 将会把流量转发到能处理请求的 Pod 中。
下面是一个相对完整的 Service 的结构,以及简单的说明:
apiVersion: v1
kind: Service
matadata: #元数据
name: string #service的名称
namespace: string #命名空间
labels: #自定义标签属性列表
- name: string
annotations: #自定义注解属性列表
- name: string
spec: #详细描述
selector: [] #label selector配置,将选择具有label标签的Pod作为管理 范围
type: string #service的类型,指定service的访问方式,默认为clusterIp
clusterIP: string #虚拟服务地址
sessionAffinity: string #是否支持session
ports: #service需要暴露的端口列表
- name: string #端口名称
protocol: string #端口协议,支持TCP和UDP,默认TCP
port: int #服务监听的端口号
targetPort: int #需要转发到后端Pod的端口号
nodePort: int #当type = NodePort时,指定映射到物理机的端口号
status: #当spce.type=LoadBalancer时,设置外部负载均衡器的地址
loadBalancer: #外部负载均衡器
ingress: #外部负载均衡器
ip: string #外部负载均衡器的Ip地址值
hostname: string #外部负载均衡器的主机名
1.3. 特殊的 Service 类型
- Services Without Selector
- Headless Service
Services Without Selector:selector 并非必须添加,在没有添加 selector 的情况下,需要我们自己手动创建 endpoint 的资源对象,并且 endpoint 的名字要和 service 是相同的,从而让 service 和 endpoint 可以进行自动关联.
Headless Service:通过指定 Cluster IP(spec.clusterIP)的值为“None”来创建 Headless Service,这样他就不会被分配 Cluster IP,kube-proxy 不会处理该类 service,可以通过域名解析直接访问 backend pod 一跳直达,具体的实现还是取决于 DNS 实现。
Headless Service 的应用场景
- 自主选择权,client 可以自己来决定使用哪个 Real Server,可以通过查询 DNS 来获取 Real Server 的信息。
- Headless Service 对应的每一个 Endpoint,即每一个 Pod,都会有对应的 DNS 域名,这样 Pod 之间就可以互相访问。
1.4. 发布服务-服务类型
- ClusterIP:通过集群内部的 IP 暴露服务,选择该值,服务只能够在集群内部访问。
- NodePort:通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务,NodePort 服务会路由到 ClusterIP 服务,这个 ClusterIP 服务会自动创建。通过请求 <NodeIP>:<NodePort>,可以集群的外部访问一个 NodePort 服务。
- LoadBalancer:使用云提供商的负载均衡器,向外部暴露服务,外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。
- ExtenalName:通过返回 CNAME 和它的值,可以将服务映射到 externalName 字段的内容(例如,foo.bar.example.com)。没有任何代理被创建,只有 Kubernetes 1.17 或者更高版本的 kube-dns 才支持。
1.5. NodePort Service
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
type: NodePort
selector:
app: MyApp
port:
- protocol: TCP
port: 80
targetPort: 80
nodePort: 30036
- type: NodePort:使用 NodePort 方式暴露服务。
- selector:用来选择后端服务。
- nodePort:30036:可以自己填,也可以由 Kubernetes 自动分配。一般 Kubernetes 会分配 30000 以上的端口给 NodePort 服务使用。
下面为 NodePort 服务工作的示意图
1.6. LoadBalancer Service
LoadBalancer 服务是暴露服务到 internet 的标准方式,转发所有流量到对应的服务。
下面是一个 LoadBalancer Service 的简单结构:
kind: Service
apiVersion: v1
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- potocol: TCP
port: 80
targetPort: 80
nodePort: 30061
clusterIP: 10.0.171.239
loadBalancerIP: 78.11.24.19
type: LoadBalancer
1.7. ExternalName Service
1.7.1. ExternalName Service 介绍
类型为 ExternalName 的服务将服务映射到 DNS 名称,而不是典型的选择器,例如 my-service ,我们可以使用 spec.externalName 参数指定这些服务。
例如,以下 Service 定义将 my-ns 名称空间中的 my-service 服务映射到 my.app.example.com:
kind: service
apiVersion: v1
metadata:
name: my-service
namespace: my-ns
spec:
type: ExternalName
externalName: my.app.example.com
externalName既然是Service,它就可以被Ingress作为backend。这样做的话,就等于直接在ingress上反向代理了exernalName Service上的服务。
1.7.2. ExternalName Service 使用场景
当一个集群中的某个服务 ServiceA 需要迁移到另外一个集群时,在 foobar 内创建一个 “ExternalName” 服务 ServiceA,该服务将流量重定向到外部服务 foo.ServiceA, 此服务在内核级别执行简单的 CNAME 重定向,因此对性能的影响非常小。将外部服务映射到内部服务可以灵活应对未来可能将这些服务纳入集群的情况,同时最大限度地减少重构工作。
1.8. Service 背后的实现:kube-proxy
每台机器上都运行一个 kube-proxy 服务,它监听 API server 中 service 和 endpoint 的变化情况,并通过 iptables 等来为服务配置负载均衡。
二、Ingress
2.1. 什么是 Ingress
Ingress 是从 Kubernetes 集群外部访问集群内部服务的入口,主要负责 7 层流量的转发,而 Service 是 4 层协议,因为它主要是 TCP 和 UDP 协议。Ingress 的实现依赖 Service。
通常情况下,service 和 pod 仅可在集群内部网络中通过 IP 地址访问。所有到达边界路由器的流量或被丢弃,或被转发到其他地方。
Client 端通过 Ingress 管理的负载均衡器转发器,再根据路由规则转发到具体的 Service,最终请求分配给 Pod 。
2.2. Ingress 定义
apiVersion: networking.k8s.io/v1
king: Ingress
metadata:
name: name-virtual-host-ingress
spec:
rules:
- host: foo.bar.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service1
port:
number: 80
- host: bar.foo.com
http:
paths:
- pathType: Prefix
path: "/"
backend:
service:
name: service2
port:
number: 80
- rules: 定义路由妆发规则。
- pathType:是指匹配规则。
- path:是指匹配的 url 路径。
- backend:是指被匹配到的流量,最终会被转发到哪些 Service。
client 端的请求流量通过转发规则,首先根据 host 进行匹配,再根据路径进行匹配,最后匹配到 Service,Service 再根据自己的负载均衡器将流量转发给 Pod。
2.3. Ingress controllers
Ingress controller 负责实现 Ingress,是 k8s Ingress 能够生效的先决条件。为了使 Ingress 正常工作,集群中必须运行 Ingress controller。
首先,Ingress controller 会监听 Ingress 的对象,然后,通过给负载均衡器的 Provider 添加一些转发规则,最后,根据转发规则将流量转发到 Pod
三、总结
Service 是后端真实服务的抽象,一个 Service 可以代表多个相同的后端服务。Ingress 是反向代理规则,用来规定 HTTP/S 请求应该被转发到哪个 Service 上,比如根据请求中不同的 Host 和 url 路径让请求落到不同的 Service 上。Ingress Controller 就是一个反向代理程序,它负责解析 Ingress 的反向代理规则,如果 Ingress 有增删改的变动,所有的 Ingress Controller 都会及时更新自己相应的转发规则,当 Ingress Controller 收到请求后就会根据这些规则将请求转发到对应的 Service。
本文整理自华为云社区【内容共创】活动第12期。
查看活动详情:https://bbs.huaweicloud.com/blogs/325315
相关任务详情:任务35. 华为云云原生黄金课程 07 : Kubernetes 网络与服务管理
- 点赞
- 收藏
- 关注作者
评论(0)