Service 类型
Kubernetes 中可以通过不同方式发布 Service,通过 ServiceType 字段指定,该字段的默认值是 ClusterIP,可选值有:
- ClusterIP: Kuboard 已支持 默认值。通过集群内部的一个 IP 地址暴露 Service,只在集群内部可以访问
NodePort: Kuboard 已支持 通过每一个节点上的的静态端口(NodePort)暴露 Service,同时自动创建 ClusterIP 类型的访问方式
- 在集群内部通过 $(ClusterIP): $(Port) 访问
- 在集群外部通过 $(NodeIP): $(NodePort) 访问
LoadBalancer: Kuboard 不支持 通过云服务供应商(AWS、Azure、GCE 等)的负载均衡器在集群外部暴露 Service,同时自动创建 NodePort 和 ClusterIP 类型的访问方式
- 在集群内部通过 $(ClusterIP): $(Port) 访问
- 在集群外部通过 $(NodeIP): $(NodePort) 访问
- 在集群外部通过 $(LoadBalancerIP): $(Port) 访问
替代方案
- LoadBalancer 类型的 Service,可以自动调用云服务商在 IaaS 层面的接口,并自动创建 LoadBalancer,将其指向该 Service。
- 由于 Kuboard 不限定云服商,因此不能实现此类型的 Service,建议用户先创建 NodePort 类型的 Service,再手工创建 LoadBalancer,将其配置到各节点上对应的 Service 的 NodePort。此操作最终效果与 LoadBalancer 类型 Service 的效果相同
- ExternalName: Kuboard 暂不支持 将 Service 映射到 externalName 指定的地址(例如:foo.bar.example.com),返回值是一个 CNAME 记录。不使用任何代理机制。
TIP如使用 ExternalName 类型的 Service,CoreDNS 版本不能低于 1.7
ClusterIP
ClusterIP 是 ServiceType 的默认值。在 Iptables 代理模式 中,详细讲述了 ClusterIP 类型 Service 的工作原理。
NodePort
对于 NodePort 类型的 Service,Kubernetes 为其分配一个节点端口(对于同一 Service,在每个节点上的节点端口都相同),该端口的范围在初始化 apiserver 时可通过参数 —service-node-port-range 指定(默认是:30000-32767),参考 修改NodePort的范围。节点将该端口上的网络请求转发到对应的 Service 上。可通过 Service 的 .spec.ports[*].nodePort 字段查看该 Service 分配到的节点端口号。
在启动 kube-proxy 时使用参数 —nodeport-address 可指定阶段端口可以绑定的 IP 地址段。该参数接收以逗号分隔的 CIDR 作为参数值(例如:10.0.0.0/8,192.0.2.0/25),kube-proxy 将查找本机符合该 CIDR 的 IP 地址,并将节点端口绑定到符合的 IP 地址上。
例如,
- 如果启动 kube-proxy 时指定了参数 —nodeport-address=127.0.0.0/8,则 kube-proxy 只将阶段端口绑定到 loopback 地址上。
- —nodeport-address 的默认值是一个空列表。则 kube-proxy 将节点端口绑定到该节点所有的网络 IP 地址上。
您可以通过 nodePort 字段指定节点端口号(必须在 —service-node-port-range 指定的范围内)。Kubernetes 在创建 Service 时将使用该节点端口,如果该端口已被占用,则创建 Service 将不能成功。在这种情况下,您必须自己规划好端口使用,以避免端口冲突。
使用 NodePort,您可以:
- 根据自己的需要配置负载均衡器
- 配置 Kubernetes / 非 Kubernetes 的混合环境
- 直接暴露一到多个节点的 IP 地址,以便客户端可访问 Kubernetes 中的 Service
NodePort 类型的 Service 可通过如下方式访问:
在支持外部负载均衡器的云环境中(例如 GCE、AWS、Azure 等),将 .spec.type 字段设置为 LoadBalancer,Kubernetes 将为该Service 自动创建一个负载均衡器。负载均衡器的创建操作异步完成,您可能要稍等片刻才能真正完成创建,负载均衡器的信息将被回写到 Service 的 .status.loadBalancer 字段。如下所示:
apiVersion: v1kind: Servicemetadata:name: my-servicespec:selector:app: MyAppports:- protocol: TCPport: 80targetPort: 9376clusterIP: 10.0.171.239loadBalancerIP: 78.11.24.19type: LoadBalancerstatus:loadBalancer:ingress:- ip: 146.148.47.155
发送到外部负载均衡器的网络请求就像被转发到 Kubernetes 中的后端 Pod 上。负载均衡的实现细节由各云服务上确定。
由于 Kuboard 不限定 Kubernetes 是运行在裸机上、私有云上或者是公有云上,因此 Kuboard 暂不支持 LoadBalancer 类型的 Service。关于更多 LoadBalancer Service 相关的描述,请参考 Type LoadBalancer(opens new window)和您所使用的云供应商的文档
ExternalName
ExternalName 类型的 Service 映射到一个外部的 DNS name,而不是一个 pod label selector。可通过 spec.externalName 字段指定外部 DNS name。
下面的例子中,名称空间 prod 中的 Service my-service 将映射到 my.database.example.com:
apiVersion: v1kind: Servicemetadata:name: my-servicenamespace: prodspec:type: ExternalNameexternalName: my.database.example.com
执行 nslookup my-service.prod.svc.cluster.local 指令时,集群的 DNS 服务将返回一个 CNAME 记录,其对应的值为 my.database.example.com。访问 my-service 与访问其他类型的 Service 相比,网络请求的转发发生在 DNS level,而不是使用 proxy。如果您在后续想要将 my.database.example.com 对应的数据库迁移到集群内部来,您可以按如下步骤进行:
- 在 Kubernetes 中部署数据库(并启动数据库的 Pod)
- 为 Service 添加合适的 selector 和 endpoint
- 修改 Service 的类型
注意事项
- ExternalName 可以接受一个 IPv4 地址型的字符串作为 .spec.externalName 的值,但是这个字符串将被认为是一个由数字组成的 DNS name,而不是一个 IP 地址。
- 如果要 hardcode 一个 IP 地址,请考虑使用 headless Service
External IP
如果有外部 IP 路由到 Kubernetes 集群的一个或多个节点,Kubernetes Service 可以通过这些 externalIPs 进行访问。externalIP 需要由集群管理员在 Kubernetes 之外配置。
在 Service 的定义中, externalIPs 可以和任何类型的 .spec.type 一通使用。在下面的例子中,客户端可通过 80.11.12.10:80 (externalIP:port) 访问my-service
apiVersion: v1kind: Servicemetadata:name: my-servicespec:selector:app: MyAppports:- name: httpprotocol: TCPport: 80targetPort: 9376externalIPs:- 80.11.12.10
