service

2022-10-06 08:12:39 浏览数 (1)

文章目录
  • Service 定义
  • 负载分发策略
  • 无头 service
  • 参考文献

Service 定义

Service 用于为一组提供服务的 Pod 抽象一个稳定的网络访问地址。通过 Service 的定义,能够为客户端应用提供稳定的访问地址和负载均衡功能,以及屏蔽后端 Endpoint 的变化,是 kubernetes 实现微服务的核心资源。

name

type

required

backup

version

string

1

kind

string

1

Service

metadate

object

1

m.name

string

1

Service 名称,可配置用于访问

m.namespace

string

1

和上面那个,详见我的 CoreDNS 博文

m.labels[]

list

m.annotation

list

spec

object

1

详细数据

s.selector[]

list

1

将选择具有指定 label 标签的 Pod 作为管理范围

s.type

string

1

Service 的类型,指定 Service 的访问方式。默认值为 ClusterIP。见下方注释1

s.clusterIP

string

当 service.type == ClusterIP 时,用以配置对应 IP;如果不指定,将由系统自动生成;如果是无头 Service,将此项设置为 None。Headless Service 后文再说。

s.sessionAffinity

string

是否支持 Session。可选值为 ClientIP,默认值为 None。ClientIP 表示将同一个客户端IP来的访问请求全都转发到同一个后端 Pod、

s.ports[]

list

Service 端口列表

s.p.name

string

端口名称

s.p.protocol

string

端口协议,支持 TCP/UDP,默认是 TCP

s.p.port

int

服务监听的端口号

s.p.targetPort

int

需要转发到后端 Pod 的端口号

s.p.nodePort

int

当 spec.type == NodePort 时,指定映射到宿主机的端口号

status

object

当 spec.type == LoadBalancer 时,设置外部负载均衡器的地址

status.loadBalancer

object

外部负载均衡器

status.l.ingress

object

外部负载均衡器

status.l.i.ip

string

status.l.i.hostname

string

注1:

  • spec.type Service 的类型,指定 Service 的访问方式,默认值为 ClusterIP。 (1)ClusterIP:虚拟服务 IP 地址,该地址用于 kubernetes 集群内部的 Pod 访问,在 Node 上 kube-proxy 通过设置的 iptables 规则进行转发。 (2)NodePort:使用宿主机的端口,使能够访问各 Node 的外部客户端通过 Node 的 IP 地址和端口号就能访问服务。 (3)LoadBalance:使用外接负载均衡器完成到服务的负载均衡分发,需要在 spec.status.loadBalance 字段指定外部负载均衡器的地址。

注2:这个 targetPort,可以直接用 pod 中的 ports.name,这一点让我有点迷惑,有个问题亟待求证: (1)如果两个 Pod 有同样的 ports.name,但是却对应着不同的 ContainerPort 呢,会怎么样?


负载分发策略

对Service的访问被分发到了后端的Pod上去,目前kubernetes提供了两种负载分发策略:

如果不定义,默认使用kube-proxy的策略,比如随机、轮询等。

基于客户端地址的会话保持模式,即来自同一个客户端发起的所有请求都会转发到固定的一个Pod上,这对于传统基于Session的认证项目来说很友好,此模式可以在spec中添加sessionAffinity: ClusterIP选项。

我们来做个实验:1、创建三个 pod:

代码语言:javascript复制
apiVersion: apps/v1
kind: Deployment      
metadata:
name: pc-deployment
namespace: dev
spec:
replicas: 3
selector:
  matchLabels:
    app: nginx-pod
template:
  metadata:
    labels:
      app: nginx-pod
  spec:
    containers:
    - name: nginx
      image: nginx:1.17.1
      ports:
      - containerPort: 80

2、查看创建结果

代码语言:javascript复制
[root@k8s-master wlf]# kubectl get pods -n w -o wide --show-labels
NAME                             READY   STATUS   RESTARTS   AGE     IP               NODE                   NOMINATED NODE   READINESS GATES   LABELS
pc-deployment-6696798b78-2jpf4   1/1     Running   0         2m50s   10.244.102.155   localhost.localdomain   <none>           <none>            app=nginx-pod,pod-template-hash=6696798b78
pc-deployment-6696798b78-lggkb   1/1     Running   0         2m50s   10.244.102.156   localhost.localdomain   <none>           <none>            app=nginx-pod,pod-template-hash=6696798b78
pc-deployment-6696798b78-vsxj8   1/1     Running   0         2m50s   10.244.102.154   localhost.localdomain   <none>           <none>            app=nginx-pod,pod-template-hash=6696798b78

3、为了方便后面的测试,修改下三台nginx的index.html页面。

代码语言:javascript复制
kubectl exec -it pc-deployment-6696798b78-2jpf4 -n w /bin/sh
echo "10.244.102.155" > /usr/share/nginx/html/index.html

4、测试一下是否写入成功

代码语言:javascript复制
[root@k8s-master wlf]# curl 10.244.102.154
10.244.102.154

5、创建集群负载服务:

代码语言:javascript复制
apiVersion: v1
kind: Service
metadata:
name: service-clusterip
namespace: w
spec:
selector:
  app: nginx-pod
clusterIP: 10.97.97.97 # service的ip地址,如果不写,默认会生成一个
type: ClusterIP
ports:
 - port: 80  # Service端口      
  targetPort: 80 # pod端口

6、 查看service的详细信息

代码语言:javascript复制
# 在这里有一个Endpoints列表,里面就是当前service可以负载到的服务入口[root@k8s-master wlf]# kubectl describe svc service-clusterip -n w
Name:             service-clusterip
Namespace:         w
Labels:           <none>
Annotations:       <none>
Selector:          app=nginx-pod
Type:             ClusterIP
IP:                10.97.97.97
Port:             <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.102.154:80,10.244.102.155:80,10.244.102.156:80
Session Affinity: None
Events:           <none>

7、查看ipvs的映射规则【rr 轮询】

代码语言:javascript复制
TCP  10.97.97.97:80 rr
 -> 10.244.102.154:80           Masq    1      0          0        
 -> 10.244.102.155:80           Masq    1      0          0        
 -> 10.244.102.156:80           Masq    1      0          0   

8、默认访问测试

是轮询吧。

9、修改分发策略

代码语言:javascript复制
apiVersion: v1
kind: Service
metadata:
name: service-clusterip
namespace: dev
spec:
selector:
  app: nginx-pod
clusterIP: 10.97.97.97 # service的IP地址,如果不写,默认会生成一个
type: ClusterIP
sessionAffinity: ClientIP # 修改分发策略为基于客户端地址的会话保持模式
ports:
   - port: 80 # Service的端口
    targetPort: 80 # Pod的端口

10、再测试


无头 service

开发人员可能不想使用Service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness Service,这类Service不会分配Cluster IP,如果想要访问service,只能通过service的域名进行查询。

创建一个无头service:

apiVersion: v1 kind: Service metadata: name: service-headliness namespace: dev spec: selector: app: nginx-pod clusterIP: None # 将clusterIP设置为None,即可创建headliness Service type: ClusterIP ports:

  • port: 80 targetPort: 80 进入pod 中:

kubectl exec -it pc-deployment-6696798b78-2jpf4 -n w bash root@pc-deployment-6696798b78-2jpf4:/# cat /etc/resolv.conf nameserver 10.96.0.10 search w.svc.cluster.local svc.cluster.local cluster.local localdomain options ndots:5 通过Service的域名进行查询:

dig @10.96.0.10 service-headliness.w.svc.cluster.local

service-headliness.w.svc.cluster.local.30 IN A10.244.102.155 service-headliness.w.svc.cluster.local.30 IN A10.244.102.154 service-headliness.w.svc.cluster.local.30 IN A10.244.102.156


参考文献

https://kubernetes.io/zh-cn/docs/concepts/services-networking/service/

0 人点赞