k8s Service服务详解

1. Service 的概念:

  • k8s中Service定义了这样一种抽象:一个pod的逻辑分组,一种可以访问他们的策略—通常称为微服务。这一组pod能够被Service访问到,通常是通过Label Selector

在这里插入图片描述

  • Service能够提供负载均衡的能力,但是在使用上有以下限制:

    • 只提供4层负载均衡能力,而没有7层功能,但有时我们可能需要更多的匹配规则来转发请求,这点上4层负载均衡不支持的。

2. Service的类型:

  • Service在k8s中有以下四种类型:

    • ClusterIp:默认类型,自动分配一个仅Cluster内部可以访问的虚拟IP。
    • NodePort:在ClusterIp基础上为Service在每台机器上绑定一个端口,这样就可以通过 NodeIP:NodePort来访问该服务。
    • LoadBalancer:在NodePort的基础上,借助Cluster Provider创建一个外部负载均衡器,并将请求转发到NodeIP:NodePort
    • ExternalName:把集群外部的服务引入到集群内部来,在集群内部直接使用,没有任何类型代理被创建,这里只有k8s1.7或更高版本的kube-dns才支持。

在这里插入图片描述

3. Vip和Service代理

  • 在k8s集群中,每个Node运行一个kube-proxy进程。kube-proxy负责为service实现一种VIP(虚拟IP)的形式,而不是ExternalName的形式。在k8s V1.0版本,代理完全在userspace。在k8s V1.1版本,新增了Iptables代理 ,但不是默认的运行模式。从k8s V1.2版本起,默认就是Iptables代理,在k8s V1.8.0-beta.0中,添加了ipvs代理。在k8s V1.14版本开始模式使用ipvs代理。
  • 在k8s v1.0版本,Service是“4层”(TCP/UDP over IP)概念。在K8s v1.1版本,新增了Ingress API(beta版),用来表示“7层”(HTTP)服务

4. 代理模式的分类:

4.1. userspace代理模式:

在这里插入图片描述

4.2. iptables代理模式:

在这里插入图片描述

4.3. Ipvs代理模式

  • 这种模式,kube-proxy会监视k8s service对象和Endpoints,调用netlink接口以相应的创建ipvs规则并定期与k8s service对象和Endpoints对象同步ipvs规则,以确保ipvs状态与期望一致。访问服务时,流量将重定向到后端pod。

  • 与iptables类似,ipvs与netfilter的hook功能,但使用哈希表作为底层数据结构并在内核空间工作。这意味着ipvs可以更快的重定向流量,并且在同步代理规则时具有更好的性能。此外ipvs为负载均衡算法提供了更多选项,例如:

    • rr:轮询调度
    • lc:最小连接数
    • dh:目标哈希
    • sh:源哈希
    • sed:最短期望延迟
    • nq:不排队调度
  • 注意:ipvs模式假定在运行kube-proxy之前在节点上都已经安装了ipvs内核模块。当kube-proxy以ipvs代理模式启动时,kube-proxy将验证节点是否安装ipvs模块,如果未安装,则kube-proxy 将退到iptables代理模式。
    在这里插入图片描述

5. ClusterlP

  • clusterlP主要在每个node节点使用iptables,将发向clusterlP对应端口的数据,转发到kube-proxy中。然后kube-proxy自己内部实现有负载均衡的方法,并可以查询到这个service下对应pod的地址和端口,进而把数据转发给对应的pod的地址和端口

在这里插入图片描述

  • 为了实现图上的功能,主要需要以下几个组件的协同工作:

    • apiserver用户通过kubectl命令向apiserver发送创建service的命令,apiserver接收到情求后将数据存储到etcd中
    • kube-proxy kubernetesl的每个节点中都有一个叫做kube-porxy的进程,这个进程负责感知service,pod的变化,并将变化的信息写入本地的iptables规则中
    • iptables使用NAT等技术将virtuallP的流量转至endpoint中

    5.1. 实例:

vim  nginx.yaml

apiVersion: apps/v1  #指定使用的API版本
kind: Deployment     #指定对象类型为Deployment
metadata:   #元数据部分,包含名称和命名空间等信息
  name: nginx-deployment  #定义deployment的名称为nginx-deployment
  namespace: default  #指定创建所在的命名空间
spec:    #指定 deployment 对象的配置信息
  selector:  #选择器,用于选择要部署的Pod
    matchLabels:  #匹配标签,选择具有指定标签的Pod
      app: nginx  
      release: stabel  
  replicas: 3   #指定要创建的Pod副本数量
  template:    #Pod的模板,定义了要创建的Pod的规范
    metadata:  #Pod元数据部分,包含标签等信息
      labels:  #Pod 标签
        app: nginx
        release: stabel
    spec:   #Pod 配置信息
      containers:  #容器列表信息
      - name: nginx  #容器名称
        image: nginx:latest  #指定容器的镜像
        imagePullPolicy: IfNotPresent #指定容器拉取镜像策略,本地不存在镜像时才尝试拉取新镜像
        ports: #容器暴露的端口列表
        - name: http  #端口名称
          containerPort: 80  #容器的端口号

---

apiVersion: v1    #指定使用的API版本 
kind: Service     #指定对象类型为Service
metadata:         #元数据部分,包含名称和命名空间等信息
  name: nginx-service  #定义service的名称为nginx-service
  namespace: default   #指定service创建所在的命名空间
spec:     #指定 service对象的配置信息
  type: ClusterIP  #指定Service类型为ClusterIP,即集群内部访问
  selector:    #选择器,用于选择要关联的Pod
    app: nginx   #匹配具有指定标签的Pod
    release: stabel  #匹配具有指定标签的Pod
  ports:  #Service暴露的端口列表
    - name: http  #端口名称
      protocol: TCP  #端口协议
      port: 80    #Service的端口号
      targetPort: 80  #将流量转发到Pod的端口号

  • 这个示例中,Deployment创建了3个副本的nginx Pod,并将它们的标签设置为app: nginx和release: stabel。Service使用相同的标签选择与这些Pod关联,并在集群内部暴露端口80,以便其他Pod可以通过nginx-service:80的方式访问这些Pod。

5.2. 创建

[root@master1 yaml]# kubectl apply -f nginx.yaml

[root@master1 yaml]# kubectl get svc
NAME            TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.10.0.1       <none>        443/TCP   8h
nginx-service   ClusterIP   10.10.156.191   <none>        80/TCP    12s

[root@master1 yaml]# kubectl get pod
NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-77fd88977b-2rlkk   1/1     Running   0          3m3s
nginx-deployment-77fd88977b-979tp   1/1     Running   0          3m3s
nginx-deployment-77fd88977b-g57b5   1/1     Running   0          3m3s


[root@master1 yaml]# curl 10.10.156.191
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>

6. Headless Service

  • 有时不需要或不想要负载均衡,以及单独的Service IP。遇到这种情况,可以通过指定ClusterIP(spec.clusterlP)的值为"None"来创建Headless Service。这类Service并不会分配ClusterIP,kube-proxy不会处理它们,而且平台也不会为它们进行负载均衡和路由
vim  nginx-service-headless.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-headless-service
  namespace: default
spec:
  selector:
    app: nginx
    release: stabel
  clusterIP: "None"
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80

6.1. 创建

      targetPort: 80
[root@master1 yaml]# kubectl apply -f nginx-service-headless.yaml
service/nginx-headless-service created
[root@master1 yaml]# kubectl get svc
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
kubernetes               ClusterIP   10.10.0.1       <none>        443/TCP   29h
nginx-headless-service   ClusterIP   None            <none>        80/TCP    8s    ---可以看的出来clusterIP是空的
nginx-service            ClusterIP   10.10.196.214   <none>        80/TCP    42m

6.2. 验证:

[root@master1 yaml]# yum -y install bind-utils.x86_64
用dns服务解析nginx-headless-service.default.svc.cluster.local.这个域名下是不是有三个pod的IP地址
[root@master1 yaml]# dig -t A nginx-headless-service.default.svc.cluster.local. @10.244.0.6

在这里插入图片描述

7. NodePort

  • nodePort的原理在于在node上开了一个端口,将向该端口的流量导入到kube-proxy,然后由kube-proxy进一步到给对应的pod
vim  nginx-service-nodeport.yaml

apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport-service
  namespace: default
spec:
  type: NodePort
  selector:
    app: nginx
    release: stabel
  ports:
    - name: http
      protocol: TCP
      port: 80
      targetPort: 80
      nodePort: 30080

7.1. 创建:

[root@master1 yaml]# kubectl apply -f nginx-service-nodeport.yaml
service/nginx-nodeport-service created
[root@master1 yaml]# kubectl get svc
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes               ClusterIP   10.10.0.1       <none>        443/TCP        30h
nginx-headless-service   ClusterIP   None            <none>        80/TCP         26m
nginx-nodeport-service   NodePort    10.10.113.141   <none>        80:30080/TCP   7s
nginx-service            ClusterIP   10.10.196.214   <none>        80/TCP         68m

7.2. 验证:

在这里插入图片描述

8. LoadBalancer

  • loadBalancer和nodePort其实是同一种方式。区别在于loadBalancer比nodePor片多了一步,就是可以调用cloud provider去创建LB来向节点导流

在这里插入图片描述

9. ExternalName

  • 这种类型的Service通过返回CNAME和它的值,可以将服务映射到externalName字段的内容(例如:hub.atguigu.com)。ExternalName Service是Service的特例,它没有selector,也没有定义任何的端口和Endpoint。相反的,对于运行在集群外部的服务,它通过返回该外部服务的别名这种方式来提供服务
vim  externalname-service.yaml

apiVersion: v1
kind: Service
metadata:
  name: my-external-service
  namespace: default
spec:
  type: ExternalName
  externalName: example.com

9.1. 创建:

[root@master1 yaml]# kubectl apply -f externalname-service.yaml
service/my-external-service created
[root@master1 yaml]# kubectl get svc
NAME                     TYPE           CLUSTER-IP      EXTERNAL-IP   PORT(S)        AGE
kubernetes               ClusterIP      10.10.0.1       <none>        443/TCP        31h
my-external-service      ExternalName   <none>          example.com   <none>         4s
nginx-headless-service   ClusterIP      None            <none>        80/TCP         86m
nginx-nodeport-service   NodePort       10.10.113.141   <none>        80:30080/TCP   60m
nginx-service            ClusterIP      10.10.196.214   <none>        80/TCP         129m

9.2. 验证:

[root@master1 yaml]# dig -t A my-external-service.default.svc.cluster.local. @10.244.0.6

在这里插入图片描述

  • 当查询主机my-external-service.default.svc.cluster.local(SVC_NAME.NAMESPACE.svc.cluster.local)时,集群的DNS服务将返回一个值my.database.example.com的CNAME记录。访问这个服务的工作方式和其他的相同,唯一不同的是重定向发生在DNS层,而且不会进行代理或转发
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值