k8s之service

k8s-service

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

# 在配置清单中调用service

kind: Service 
apiVersion: v1 
metadata:
  name: test-service
  namespace: default
  labels:
    ddff: qln
spec: 
  type: ClusterIP 
  selector:
    ddff: qln
  ports: 
    - port: 80
      targetPort: 80

1、service的工作方式

在 Kubernetes 迭代过程中,给 Service 设置里三种工作方式,分别是:Userspace 方式、Iptables 以及 Ipvs,这三种方式到现在为止,官方推荐使用 IPVS, 当集群不支持 IPVS 的时候,集群会降级到 Iptables。

1.1、Userspace

#Client Pod 要访问 Server Pod 时,它先将请求发给本机内核空间中的 service 规则,由它再将请求,转给监听 在指定套接字上的 kube-proxy,kube-proxy 处理完请求,并分发请求到指定 Server Pod 后,再将请求递交给内 核空间中的 service,由 service 将请求转给指定的 Server Pod。由于其需要来回在用户空间和内核空间交互通信, 因此效率很差。

1.2、Iptables

#直接由内核中的 iptables 规则,接受 Client Pod 的请求,并处理完成后,直接转发给指定 ServerPod。这 种方式不再将请求转发给 kube-proxy,性能提升很多。

1.3、Ipvs

#在 ipvs 模式下,kube-proxy 监视 Kubernetes 服务和端点,调用 netlink 接口相应地创建 IPVS 规则, 并 定期将 IPVS 规则与 Kubernetes 服务和端点同步。 该控制循环可确保 IPVS 状态与所需状态匹配。 访问服务 时,IPVS 将流量定向到后端 Pod 之一。

#IPVS 代理模式基于类似于 iptables 模式的 netfilter 挂钩函数,但是使用哈希表作为基础数据结构,并且 在内核空间中工作。 这意味着,与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向 通信的延迟要短,并且在同步代理规则时具有更好的性能。与其他代理模式相比,IPVS 模式还支持更高的网络 流量吞吐量。
#以上不论哪种,kube-proxy 都通过 watch 的方式监控着 kube-APIServer 写入 etcd 中关于 Pod 的最新状态 信息,它一旦检查到一个 Pod 资源被删除了 或 新建,它将立即将这些变化,反应再 iptables 或 ipvs 规则中, 以便 iptables 和 ipvs 在调度 Clinet Pod 请求到 Server Pod 时,不会出现 Server Pod 不存在的情况。

#自 k8s1.1 以后,service 默认使用 ipvs 规则,若 ipvs 没有被激活,则降级使用 iptables 规则. 但在 1.1 以前, service 使用的模式默认为 userspace。

2、Service类型

Service 是 Kubernetes 对外访问的窗口,针对不同的场景,kubernetes 为我们设置了四种 Service 的类型。

2.1、ClusterIP

kubernetes 默认就是这种方式,是集群内部访问的方式,外部是无法访问的。其主要用于为集群内 Pod 访问时,提供的固定访问地址,默认是自动分配地址,可使用 ClusterIP 关键字指定固定 IP。

#在配置清单中调用ClusterIP类型的Service

kind: Service
apiVersion: v1
metadata:
  name: my-svc
spec:
  type: ClusterIP
  selector:
    ddff: qln
  ports:
    - port: 80
      targetPort: 80

2.1.1、Headless Service

kubernates 中还有一种 service 类型:headless serivces 功能,字面意思无 service 其实就是改 service 对 外无提供 IP。一般用于对外提供域名服务的时候,配合ingress使用。

# 简单的Headless Service配置清单

kind: Service
apiVersion: v1
metadata:
  name: ddff
spec:
  clusterIP: None
  selector:
    ddff: qln
  ports:
    - port: 80
      targetPort: 80
      name: http
[root@k8s-master-01 ~]# kubectl get svc
NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
ddff         ClusterIP   None         <none>        80/TCP    8s
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   46h

#可以看到此时名为ddff的service并没有内网ip。
service与pod是通过describe来关联的。

[root@k8s-master-01 ~]# kubectl describe service ddff
Name:              ddff
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          ddff=qln
Type:              ClusterIP
IP Families:       <none>
IP:                None
IPs:               None
Port:              http  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.1.41:80
Session Affinity:  None
Events:            <none>


[root@k8s-master-01 ~]# kubectl describe endpoints ddff
Name:         ddff
Namespace:    default
Labels:       service.kubernetes.io/headless=
Annotations:  endpoints.kubernetes.io/last-change-trigger-time: 2021-04-01T09:32:38Z
Subsets:
  Addresses:          10.244.1.41
  NotReadyAddresses:  <none>
  Ports:
    Name  Port  Protocol
    ----  ----  --------
    http  80    TCP

Events:  <none>

2.2、NodePort

NodePort 是将主机 IP 和端口跟 kubernetes 集群所需要暴露的 IP 和端口进行关联,方便其对外提供服务。内部可以通过 ClusterIP 进行访问,外部用户可以通过 NodeIP:NodePort 的方式单独访问每个 Node 上的实例。

kind: Service
apiVersion: v1
metadata:
  name: my-svc
spec:
  type: NodePort
  selector:
    app: nginx
  ports: 
    - port: 80
      targetPort: 80
      nodePort: 30080

2.3、LoadBalancer

LoadBalancer 类型的 service 是可以实现集群外部访问服务的另外一种解决方案。不过并不是所有的 k8s 集群都会支持,大多是在公有云托管集群中会支持该类型。负载均衡器是异步创建的,关于被提供的负载均衡器的信息将会通过 Service 的 status.loadBalancer 字段被发布出去。

LoadBalancer是实现暴露服务的另一种解决方案,它依赖于公有云弹性IP实现

2.4、ExternalName

ExternalName Service 是 Service 的一个特例,它没有选择器,也没有定义任何端口或 Endpoints。它的作用是返回集群外 Service 的外部别名。它将外部地址经过集群内部的再一次封装(实际上就是集群 DNS 服务器将CNAME 解析到了外部地址上),实现了集群内部访问即可。

ExternalName就是将集群外的某些资源在集群内部起一个别名,该别名仅在集群内部使用。

# 简单的ExternalName配置清单
#该配置清单将ddff解析为www.baidu.com,因此在集群内部访问ddff时,会访问到www.baidu.com

apiVersion: v1
kind: Service
metadata:
  name: ddff
spec:
  externalName: www.baidu.com
  type: ExternalName

PS

#查看pod向外暴漏的端口及IP
[root@k8s-master-01 ~]# kubectl get svc
posted @ 2022-10-16 21:33  大胡萝卜没有须  阅读(206)  评论(0编辑  收藏  举报