Service资源配置
# Service资源介绍
# Service介绍
在K8s集群中,Pod的IP会随着Pod的销毁和重新创建而发生改变,因为新Pod的IP地址与之前旧Pod的不同。
Service就是用来解决这个问题的,它能够提供基于标签的服务发现与负载均衡,提供对外的统一访问入口,Service的IP地址不会变、主机名也不会变。
# Service作用
Service一旦发现符合所配置的标签选择器的的Pod,就会立刻将其关联,并作为后端可用Pod之一。
它会代理客户端对Pod的访问请求,代理Pod对容器的访问请求。
# Service特点
它会通过Pod的标签来进行关联,因为Pod的主机名、IP地址等是会变化的。
它是一个规则,并非某个实际运行的服务,它强依赖于K8s的DNS服务。
它提供多种对外访问的方式,例如节点端口、负载均衡、集群IP等。
# Service类型
- ClusterIP
ClusterIP(集群内部IP),它提供一个Service网络的IP和端口号,使得集群中不同Service的Pod节点之间可以互相访问,它只能用于集群内部通信。
- nodePort
nodePort(节点端口),它提供一个Service网络的IP和端口号,同时在各节点上动态生成一个端口来映射该Service的IP端口,使我们可以从集群外部,通过节点IP:动态端口
来访问集群资源。
如果所有的请求都访问一个Node,可能会造成Node压力过大,所以我们应该在Node之上,做一个负载均衡器。
- LoadBalancer
依赖于云环境,我们可以通过设置LoadBalancer映射到云服务商提供的LoadBalancer地址,然后以负载均衡的方式提供外网访问。
该方式仅用于在云平台上设置Service的场景。对该Service的访问请求将会通过云服务商的LoadBalancer转发到后端Pod上,负载分发也依赖于云服务商进行实现。
- ExternalName
ExternalName(外部名称),它能将外部服务名称,映射为集群内部名称。使集群内部的Pod可以像访问集群内部的服务一样,来访问集群外部的服务。
该Name必须是个名称(CNAME记录),且必须要能被本地配置的DNS服务器或K8s的CoreDNS服务器所解析,才能够被访问。
访问流程:
- Pod通过Service请求外部的服务。
- Service将请求发送给集群外部的服务。
- 集群外部的服务响应请求给节点。
- 节点再返回响应给Service,Service再返回响应给Pod。
# Service工作模式
- userspace
- 请求会先到内核空间的Service,然后再到用户空间的Kube-Proxy。
- 然再到内核空间的Service,最后才到目标节点上的Pod。
- IPVS
- 用户对资源发起请求时,直接通过kube-proxy请求Service IP。然后由Service规则(IPVS)直接进行调度给相关Pod资源。调度的Pod资源可能是集群内部的任何一个节点。
- IPVS特性
- ipvs为大型集群提供了更好的可扩展性和性能。
- ipvs支持比iptables更复杂的负载均衡算法(最小负载、最少连接、加权等等)。
- ipvs支持服务器健康检查和连接重试等功能。
- iptables
- 如果没有IPVS,会自动降级为iptables模式。
- iptables和IPVS工作方式差不多,但少了一些适合集群的特性,且性能低于IPVS。
# kube-proxy组件
该组件会始终通过ApiServer监控集群中有关Service资源的变动信息。
一旦有Service资源发生变动或者创建,该组件都会立即将其变动转化为当前节点之上的对应网络规则,以使得Service资源可以正常的将请求调度到本节点的Pod资源上。
# DNS服务介绍
K8s的DNS服务是一个架构级的Pod,该服务一般用于解析Service的地址,使可以通过名称来访问Service。
它支持动态创建、动态删除、动态变动,比如:如果你手动修改了Service的地址,DNS服务会自动触发,将DNS解析记录中的地址也修改。
# 容器的默认域名解析
查看集群的DNS解析服务器可以通过命令:kubectl get service -n kube-system
,进行查看。
在DNS服务能够正常解析时,即便Service的IP变动,我们也可以通过service的name通过解析来正常访问。
如果集群无法正常访问DNS服务器,可以重启一下coredns所在的主节点服务器试试。
Pod容器中的/etc/resolv.conf
配置详解:
nameserver 10.96.0.10
- 每个Pod会自动将kube-dns作为域名解析服务器。用于解析域名为IP,如果没有解析成功则由宿主机的DNS服务器进行解析。
search default.svc.cluster.local svc.cluster.local cluster.local
介绍
- 这条参数是配置名称的搜索域,一个域名以"."结束,就表示一个完整域名(FQDN),反之则不是。如果域名不是完整域名,那么这个域名会到search搜索解析,并会将搜索解析后的域名,依次交给nameserver进行域名解析。
例如nginx-svc不是一个完整域名,所以此处就会搜索解析成:
nginx-svc.default.svc.cluster.local
nginx-svc.svc.cluster.local
nginx-svc.cluster.local
nginx-svc,指的是Pod或Service的名称。
default,指的是该Pod或Service所属的名称空间的名字。
.svc.cluster.local,该后缀指的是K8s集群的本地Pod资源,一般是固定的。
作用
它可以方便k8s内部服务之间的访问,k8s在同一个namespace下是可以直接通过服务名称进行访问的,其原理就是会在search域查找。
- 例如:用nginx来访问,会被拼接成
nginx.default.svc.cluster.local
如果是跨namespace访问,则可以通过servicename.namespace这样的形式。
- 例如:用nginx.[名称空间名]来访问,会被拼接成
nginx.[名称空间].svc.cluster.local
- 例如:用nginx来访问,会被拼接成
options ndots:5
- ndots用来判断一个域名是不是完整域名,它用于指定一个域名中"."的个数大于多少算完整域名。
# Service资源配置清单
# HEAD头部字段
apiVersion: v1
kind: Service
2
# svc.spec.type <string>
- 指定Service类型,默认是"ClusterIP"类型。
# svc.spec.clusterIP <string>
- 指定固定的Service的集群IP,指定的IP需要处在集群网络的网段内。不指定默认是动态分配集群IP给Service。建议不指定固定IP,因为可能发生冲突。
- 也可以指定为"None",表示创建一个HeadLessService(无头Service)。
- 无头Service没有集群IP,只会有Service名称,每当通过Service名称进行请求时,因为Service没有IP,所以请求会被直接调度到Pod的IP上。
# svc.spec.selector <map[string]string>
- 标签选择器,用于指定要关联的Pod资源的标签,Service仅支持matchLables方式。
- 例如:
selector:
app: nginx
release: stable
2
3
# svc.spec.ports <[]Object>
指定Service暴露的端口。
name <string>
- 端口名称,如果定义了名称,该名称也可以在后续被引用。port <integer>
- 对外暴露的Service端口(必选)。targetPort <string>
- 指定容器上的端口,如果未指定则为port的值。nodePort <integer>
- 节点端口。- 指定节点上的端口,只有Service类型为"NodePort"时需要指定。使可以通过节点网络的任意
节点IP:端口
访问。 - 节点端口必须指定在30000~32767范围之间,也可以通过配置修改该范围,不指定会动态分配。自己指定时应当保证指定的节点端口,在节点上没被占用。
- 指定节点上的端口,只有Service类型为"NodePort"时需要指定。使可以通过节点网络的任意
protocol <string>
- 端口协议,可以指定为TCP/UDP/SCTP,默认是TCP协议。
# 例子
apiVersion: v1
kind: Service
metadata:
name: nginx-svc
labels:
app: nginx
release: pro
spec:
type: NodePort
selector:
app: nginx
release: pro
ports:
- name: nginx-80
nodePort: 8080
port: 80
- name: nginx-443
nodePort: 8443
port: 443
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19