k8s--基础--16--Service--理论

k8s–基础–16–Service–理论


1、什么是Service

1.1、问题

Kubernetes中,每个Pod都会有IP地址,这些IP地址并不是一直处于稳定的状态,可能随时改变,这会导致一个问题:在Kubernetes集群中,如果一组Pod(称为 backend)为其它Pod(称为 frontend)提供服务,那么那些fronten该如何发现这些backend?

1.2、什么是Service

  1. service是一个固定接入层,客户端可以通过访问service来访问到service关联的后端pod。
  2. service工作依赖于dns服务,service的名称解析是依赖于dns服务,因此在部署完k8s之后需要在部署dns服务
    1. 1.11之前的版本使用的是:kubeDNs
    2. 较新的版本使用的是:coredns
  3. kubernetes要想给客户端提供网络功能,需要依赖第三方的网络插件(flannel,calico等)

1.2.1、简单理解

  1. 可以将Service理解为微服务名称,比如consul的oa-server,这个oa-server有个列表,列表包含所有注册到consul的OA服务。我们通过访问微服务名称oa-server,就可以访问OA服务,且自动负载均衡。
  2. 也可以将Service理解为一个4层的负载均衡。比如haproxy等

1.3、Service定义的一种抽象

逻辑上的一组Pod,访问这组POD的策略(通常称为微服务),这一组Pod能够被Service访问到,通常是通过Label Selector实现的。

1.3.1、举例

  1. 一组Pod(称为 backend),它运行了3个副本,frontend需要访问backend服务。
    1. frontend 不需要关心它们调用了哪个 backend副本,只要能访问就行。
    2. frontend 不需要关心 backend副本的IP是否发生变化,只要能访问就行。
    3. frontend 不需要关心 backend的状态,只要能访问就行。
  2. backend的pod的ip可能会随时变化,那么我们就需要在 backend前面 加上一个固定接入层service(backend_service),frontend只需要访问backend_service地址,就会代理到backend的pod,那么pod就算ip怎么变化,通过service都可以找到
  3. 对Kubernetes集群中的应用
    1. Kubernetes提供了简单的Endpoints API,只要Service中的一组Pod发生变更,应用程序就会被更新。
  4. 对非Kubernetes集群中的应用
    1. Kubernetes提供了基于 VIP 的网桥的方式访问Service,再由Service重定向到backend的Pod。

2、kubernetes集群中的三类ip地址

2.1、node network(节点网络)

  1. 需要实实在在配置的
  2. 节点网络地址是配置在节点接口之上
    1. 因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的

2.2、Pod network(Pod网络)

  1. 需要实实在在配置的
  2. pod网络地址是配置在pod资源之上
    1. 因此这些地址都是配置在某些设备之上的,这些设备可能是硬件,也可能是软件模拟的

2.3、cluster network(集群网络)

  1. 称为集群地址,也称为service network
  2. 是虚拟的地址(virtual ip),没有配置在某个接口上,只是出现在service的规则当中。

3、kube-proxy 组件

  1. 每个K8s节点上 都有 kube-proxy组件
  2. kube-proxy组件将始终监视着apiserver中有关service资源的变动信息,需要跟master之上的apiserver交互,随时连接到apiserver上获取任何一个与service资源相关的资源变动状态,这种是通过kubernetes中固有的一种请求方法watch(监视)来实现的,一旦有service资源的内容发生变动(如创建,删除),kube-proxy都会将它转化成当前节点之上的能够实现service资源调度,把我们请求调度到后端特定的pod资源之上的规则,这个规则可能是iptables,也可能是ipvs,取决于service的实现方式
  3. 如果某个服务背后的pod资源发生改变,比如service的标签选择器适用的pod又多了一个,这个pod使用的信息会立即反应在apiserver上,kube-proxy能监听到这个service的变化,将其立即转为service规则(如iptables规则)

4、service实现方式

4.1、iptables

  1. 客户端ip请求时直接请求service的ip,这个请求报文被本地内核空间中的service规则所截取,进而直接调度给相关的pod
  2. 这个方式是直接工作在内核空间,由iptables规则直接实现
  3. 作用版本:Kubernetes 1.11之前的版本使用

4.2、ipvs

  1. 客户端请求到达内核空间之后直接由ipvs规则来调度到相关的pod资源
  2. 作用版本:1.11+版本使用的是ipvs,ipvs如果没有被激活就会自动降级为iptables

5、创建service

5.1、创建pod

  1. 具体看 k8s–基础–14–deployment
  2. 该pod是为了给service代理使用

5.1.1、配置文件


apiVersion: apps/v1
kind: Deployment
metadata:
  # Deployment 的名称
  name: deployment-nginx
  # Deployment 的标签
  labels:
    k1: k1_la
    k2: k2_la
spec:
  # 副本数目
  replicas: 3
  # 选择器
  selector:
    # 选择器匹配的标签
    matchLabels:
      nginx_pod: nginx_pod_la
  # Pod 模板
  template: 
    metadata:
      # Pod的标签
      labels:
        nginx_pod: nginx_pod_la
    spec:
      containers:
        # 容器名称
      - name: nginx
        # 镜像
        image: nginx
        # 镜像策略
        imagePullPolicy: IfNotPresent
		# 容器端口
        ports:
        - containerPort: 80

5.1.2、验证:使用curl 也能调通所有IP地址


kubectl get pods -l nginx_pod=nginx_pod_la  -o wide
curl 10.244.1.89:80


在这里插入图片描述

  1. 注意:容器不会使用该节点上的80端口,也不会使用任何特定的NAT规则去路由流量到Pod上。
    1. 这意味着:可以在同一个节点上运行多个Pod,且使用相同的容器端口
    2. 这意味着:可以从集群中任何其他的Pod或节点上使用IP的方式访问到它们。
  2. 像Docker一样,端口能够被发布到主机节点的接口上,但是出于网络模型的原因应该从根本上减少这种用法。

5.2、创建service

  1. Service从逻辑上定义了运行在集群中的一组Pod,这些Pod提供了相同的功能,当每个Service创建时,会被分配一个唯一的IP地址,也称为clusterIP。
  2. clusterIP与Service的生命周期绑定在一起,当Service存在的时候它不会改变。
  3. 可以配置Pod使它与Service进行通信,通过Service通信,可以做到对Pod的负载均衡。

5.2.1、脚本

vim /root/test/service_nginx.yaml

内容

apiVersion: v1
kind: Service
metadata:
  # Service 的名称
  name: service-nginx
  labels:
  # Service 的标签
    service_k1: k1_la
spec:
  ports:
  # 端口
  - port: 80
  # 协议
    protocol: TCP
  # 标签选择器,选择 pod 的标签
  selector:
    nginx_pod: nginx_pod_la
 
  1. 上面创建一个Service,对应具有标签 nginx_pod: nginx_pod_la 的Pod
  2. 目标TCP端口80,在一个抽象的Service端口上暴露
    1. targetPort:容器接收流量的端口
    2. port:抽象的Service端口,可以使任何其它Pod访问该Service的端口。

5.2.2、启动

kubectl apply -f /root/test/service_nginx.yaml

5.2.3、验证

5.2.3.1、查看service
kubectl get svc service-nginx
 

在这里插入图片描述

5.2.3.2、查看service 的明细
kubectl describe svc service-nginx
 

在这里插入图片描述

正如前面所提到的,一个Service由一组backend Pod组成。这些Pod通过endpoints暴露出来。
10.107.212.90 的请求,会被POST到一个名称为 nginx_pod_la 的 Endpoint对象上。

  1. 当Pod终止后:自动从Endpoint中移除
  2. 当Pod新增后:自动被添加到Endpoint中。
5.2.3.3、查看service的Endpoint
kubectl get ep service-nginx

在这里插入图片描述

5.2.3.4、验证负载均衡

从集群中任意节点上使用 curl 命令请求Nginx

语法:Service <CLUSTER-IP>:<PORT>
# CLUSTER-IP:service的ip
# PORT:service的端口

# 通过访问service ip:port可以路由到后端的pod,具体哪个pod看负载均衡策略
curl 10.107.212.90:80 
 

在这里插入图片描述

6、没有selector的Service

6.1、使用场景:案例

  1. 希望 Service服务 使用外部的数据库集群
  2. 希望Service服务 指向另一个Namespace中或其它集群中的服务。
  3. 将某个服务 负载到Kubernetes集群中

6.2、案例

创建一个没有selector的Service(mysql-service),mysql-service服务能使用外部的数据库集群。

6.2.1、创建Service(mysql-service)服务

6.2.1.1、mysql-service脚本
vi  /root/test/service_mysql.yaml

内容

kind: Service
apiVersion: v1
metadata:
  # Service 的名称
  name: mysql-service
spec:
  ports:
  # 端口
  - port: 80
    # 协议
    protocol: TCP
    # 目标端口
    targetPort: 3306
  # 访问类型
  type:
  # 可以被k8s之外的主机或者浏览器访问
    NodePort
6.2.1.2、mysql-service启动
kubectl apply -f /root/test/service_mysql.yaml

kubectl get svc mysql-service

在这里插入图片描述

6.2.2、创建相关的Endpoints对象

由于mysql-service没有selector,就不会创建相关的Endpoints对象。可以手动将Service映射到指定的Endpoints。

6.2.2.1、mysql-service脚本
vi  /root/test/endpoints_mysql.yaml

内容

kind: Endpoints
apiVersion: v1
metadata:
  # 这里要写service的名称
  name: mysql-service
subsets:
  - addresses:
    # 这个地址可以是集群外部的地址,如mysql等,当访问serveice的时候,会被代理到192.168.187.171:3306
	# 有几个mysql服务,就写几个IP,这样就可以起到负载均衡了。
    - ip: 192.168.187.171
    ports:
      - port: 3306


6.2.2.2、mysql-service启动
kubectl apply -f /root/test/endpoints_mysql.yaml

kubectl describe svc mysql-service
kubectl get ep mysql-service

在这里插入图片描述

注意:Endpoint IP 地址不能是下面的地址
  1. loopback(127.0.0.0/8)
  2. link-local(169.254.0.0/16)
  3. link-local多播(224.0.0.0/24)。
6.2.3、验证

在这里插入图片描述

在这里插入图片描述

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值