定义
将运行在一组 Pods上的应用程序公开为网络服务的抽象方法。(通俗的来说:service为pods提供一组可以被调用的固定的ip/dns,不会随着pods的改变面变化)
services 与一组pods的关联
通过selector
services 模板
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376(对应pod暴露出来的端口)
没有 selector 的 Service
抽象化其他种类的后端,与endpoint结合使用
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 192.0.2.42
ports:
- port: 9376
EndPoints siles
Endpoint 切片是一种 API 资源,可以为 Endpoint 提供更可扩展的替代方案(测试版本还没有了解)
VIP和service代理
在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟IP)的形式,而不是 ExternalName 的形式。
kube-proxy 与 services
kube-proxy 网络代理,把Kubernetes的网络代理到每个节点上
userspace 代理模式(不重要不用看)
任何连接到kube-proxy的请求,都会被代理到service的backend pods上。
kube-proxy 基于 SessionAffinity 来确定使用哪个backend pods (session 我理解是保持与原来的clientip使用的pods,接着用)
kube-proxy 会监视 Kubernetes master 对 Service 对象和 Endpoints 对象的添加和移除
iptables 代理模式 (主要用这种)
kube-proxy为每个service 配置一个iptables规则
Endpoints 也会配置一个iptables用来选择backend组合
kube-proxy 会监视 Kubernetes 控制节点对 Service 对象和 Endpoints 对象的添加和移除
iptables优势
- iptables 处理流量具有较低的系统开销,因为流量由 Linux netfilter 处理,而无需在用户空间和内核空间之间切换
- kube-proxy与第一个pod连接失败会与其它pod重试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nr3WefSA-1595817190795)(https://d33wubrfki0l68.cloudfront.net/27b2978647a8d7bdc2a96b213f0c0d3242ef9ce0/e8c9b/images/docs/services-iptables-overview.svg)]
IPVS 代理模式(stable版本 可能是以后的主流)
kube-proxy监视kubernetes的服务和端点,调用netlink创建ipvs规则,定期将ipvs规则与kubernetes服务和端点同步,访问服务时,IPVS 将流量定向到后端Pod之一
说明(attention)
- 要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS Linux 在节点上可用。
- 当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
IPVS 优势
与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。与其他代理模式相比,IPVS 模式还支持更高的网络流量吞吐量
多端口 Service
必须提供端口名称
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
指定ip
spec.clusterIp, IP 地址在 service-cluster-ip-range CIDR 范围内;不合法会返回422
环境变量
kubelet 会为每个活跃的 Service添加一组环境变量;
名称规则(具本看源码)如:
REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
如果pod要使用services的环境变量,service发必须先启动
查看pod 环境变量: kubectl exec ${podname} env
DNS
给能够支持集群的dns服务器,kubernetes为其创建dns ,在同个命名空间中,可直接用用serviceName,其他命名空间使用 serviceName.nameSpace
headless service
定义: spec.clusterIp:None ,不分配clusterip ,kube-proxy也不处理
- 有selector
- 会创建endpoints,通过endpoints找到pod
- 无selector
- ExternalName 类型 Service 的 CNAME 记录
- 与 Service 共享一个名称的任何 Endpoints,以及所有其它类型
发布服务
对一些应用(如 Frontend)的某些部分,可能希望通过外部Kubernetes 集群外部IP 地址暴露 Service。
方案: Kubernetes ServiceTypes 允许指定一个需要的类型的 Service,默认是 ClusterIP 类型
- ClusterIP: 只能在集群内部访问
- NodePort: 通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务
- LoadBalancer: 使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。 (不太懂)
- ExternalName:通过返回 CNAME 和它的值,可以将externalName 字段的内容映射到服务 (例如, type=ExternalName,externalName=foo.bar.example.com
- 或者使用ingress(这个好像比较多),它充当集群的入口点,整合路由规则,如: nginx-ingress
nodePods demo
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: MyApp
ports:
# 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
- port: 80
targetPort: 80
# 可选字段
# 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)
nodePort: 30007
ExternalName
启动好了不知道怎么用它,介绍没看懂
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
外部IP externalIP
externalIPs:宿住机对外的ip
apiVersion: v1
kind: Service
metadata:
name: serviceexternalip
spec:
ports:
- protocol: TCP
port: 8083
targetPort: 80
selector:
app: myapp
externalIPs:
- 192.168.203.133
定义
将运行在一组 Pods上的应用程序公开为网络服务的抽象方法。(通俗的来说:service为pods提供一组可以被调用的固定的ip/dns,不会随着pods的改变面变化)
services 与一组pods的关联
通过selector
services 模板
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- protocol: TCP
port: 80
targetPort: 9376(对应pod暴露出来的端口)
没有 selector 的 Service
抽象化其他种类的后端,与endpoint结合使用
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
ports:
- protocol: TCP
port: 80
targetPort: 9376
apiVersion: v1
kind: Endpoints
metadata:
name: my-service
subsets:
- addresses:
- ip: 192.0.2.42
ports:
- port: 9376
EndPoints siles
Endpoint 切片是一种 API 资源,可以为 Endpoint 提供更可扩展的替代方案(测试版本还没有了解)
VIP和service代理
在 Kubernetes 集群中,每个 Node 运行一个 kube-proxy 进程。kube-proxy 负责为 Service 实现了一种 VIP(虚拟IP)的形式,而不是 ExternalName 的形式。
kube-proxy 与 services
kube-proxy 网络代理,把Kubernetes的网络代理到每个节点上
userspace 代理模式(不重要不用看)
任何连接到kube-proxy的请求,都会被代理到service的backend pods上。
kube-proxy 基于 SessionAffinity 来确定使用哪个backend pods (session 我理解是保持与原来的clientip使用的pods,接着用)
kube-proxy 会监视 Kubernetes master 对 Service 对象和 Endpoints 对象的添加和移除
iptables 代理模式 (主要用这种)
kube-proxy为每个service 配置一个iptables规则
Endpoints 也会配置一个iptables用来选择backend组合
kube-proxy 会监视 Kubernetes 控制节点对 Service 对象和 Endpoints 对象的添加和移除
iptables优势
- iptables 处理流量具有较低的系统开销,因为流量由 Linux netfilter 处理,而无需在用户空间和内核空间之间切换
- kube-proxy与第一个pod连接失败会与其它pod重试
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-rT1rlD0t-1595817191055)(https://d33wubrfki0l68.cloudfront.net/27b2978647a8d7bdc2a96b213f0c0d3242ef9ce0/e8c9b/images/docs/services-iptables-overview.svg)]
IPVS 代理模式(stable版本 可能是以后的主流)
kube-proxy监视kubernetes的服务和端点,调用netlink创建ipvs规则,定期将ipvs规则与kubernetes服务和端点同步,访问服务时,IPVS 将流量定向到后端Pod之一
说明(attention)
- 要在 IPVS 模式下运行 kube-proxy,必须在启动 kube-proxy 之前使 IPVS Linux 在节点上可用。
- 当 kube-proxy 以 IPVS 代理模式启动时,它将验证 IPVS 内核模块是否可用。 如果未检测到 IPVS 内核模块,则 kube-proxy 将退回到以 iptables 代理模式运行。
IPVS 优势
与 iptables 模式下的 kube-proxy 相比,IPVS 模式下的 kube-proxy 重定向通信的延迟要短,并且在同步代理规则时具有更好的性能。与其他代理模式相比,IPVS 模式还支持更高的网络流量吞吐量
多端口 Service
必须提供端口名称
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
selector:
app: MyApp
ports:
- name: http
protocol: TCP
port: 80
targetPort: 9376
- name: https
protocol: TCP
port: 443
targetPort: 9377
指定ip
spec.clusterIp, IP 地址在 service-cluster-ip-range CIDR 范围内;不合法会返回422
环境变量
kubelet 会为每个活跃的 Service添加一组环境变量;
名称规则(具本看源码)如:
REDIS_MASTER_SERVICE_HOST=10.0.0.11
REDIS_MASTER_SERVICE_PORT=6379
REDIS_MASTER_PORT=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP=tcp://10.0.0.11:6379
REDIS_MASTER_PORT_6379_TCP_PROTO=tcp
REDIS_MASTER_PORT_6379_TCP_PORT=6379
REDIS_MASTER_PORT_6379_TCP_ADDR=10.0.0.11
如果pod要使用services的环境变量,service发必须先启动
查看pod 环境变量: kubectl exec ${podname} env
DNS
给能够支持集群的dns服务器,kubernetes为其创建dns ,在同个命名空间中,可直接用用serviceName,其他命名空间使用 serviceName.nameSpace
headless service
定义: spec.clusterIp:None ,不分配clusterip ,kube-proxy也不处理
- 有selector
- 会创建endpoints,通过endpoints找到pod
- 无selector
- ExternalName 类型 Service 的 CNAME 记录
- 与 Service 共享一个名称的任何 Endpoints,以及所有其它类型
发布服务
对一些应用(如 Frontend)的某些部分,可能希望通过外部Kubernetes 集群外部IP 地址暴露 Service。
方案: Kubernetes ServiceTypes 允许指定一个需要的类型的 Service,默认是 ClusterIP 类型
- ClusterIP: 只能在集群内部访问
- NodePort: 通过每个 Node 上的 IP 和静态端口(NodePort)暴露服务
- LoadBalancer: 使用云提供商的负载局衡器,可以向外部暴露服务。外部的负载均衡器可以路由到 NodePort 服务和 ClusterIP 服务。 (不太懂)
- ExternalName:通过返回 CNAME 和它的值,可以将externalName 字段的内容映射到服务 (例如, type=ExternalName,externalName=foo.bar.example.com
- 或者使用ingress(这个好像比较多),它充当集群的入口点,整合路由规则,如: nginx-ingress
nodePods demo
apiVersion: v1
kind: Service
metadata:
name: my-service
spec:
type: NodePort
selector:
app: MyApp
ports:
# 默认情况下,为了方便起见,`targetPort` 被设置为与 `port` 字段相同的值。
- port: 80
targetPort: 80
# 可选字段
# 默认情况下,为了方便起见,Kubernetes 控制平面会从某个范围内分配一个端口号(默认:30000-32767)
nodePort: 30007
ExternalName
启动好了不知道怎么用它,介绍没看懂
apiVersion: v1
kind: Service
metadata:
name: my-service
namespace: prod
spec:
type: ExternalName
externalName: my.database.example.com
外部IP externalIP
externalIPs:宿住机对外的ip
apiVersion: v1
kind: Service
metadata:
name: serviceexternalip
spec:
ports:
- protocol: TCP
port: 8083
targetPort: 80
selector:
app: myapp
externalIPs:
- 192.168.203.133