Kubernetes Serivce 是一组具有相同 label Pod 集合的抽象(可以简单的理解为集群内的 LB),集群内外的各个服务可以通过 Service 进行互相通信。
Service 和 kube-proxy 在 kubernetes 集群中的工作原理
上图流程:
1:运行在每个 Node 节点的 kube-proxy 会实时的 watch Services 和 Endpoints 对象。
当用户在 kubernetes 集群中创建了含有 label 的 Service 之后,同时会在集群中创建出一个同名的 Endpoints 对象,用于存储该 Service 下的 Pod IP. 它们的关系如下图所示:
2、每个运行在 Node 节点的 kube-proxy 感知到 Services 和 Endpoints 的变化之后,会在各自的 Node 节点设置相关的 iptables 或 IPVS 规则,用于之后用户通过 Service 的 ClusterIP 去访问该 Service 下的服务。
3、当 kube-proxy 把需要的规则设置完成之后,用户便可以在集群内的 Node 或客户端 Pod 上通过 ClusterIP 经过 iptables 或 IPVS 设置的规则进行路由和转发,最终将客户端请求发送到真实的后端 Pod。
Service 类型
ClusterIP
ClusterIP 类型的 Service 是 Kubernetes 集群默认的 Service, 它只能用于集群内部通信。不能用于外部通信。
ClusterIP Service 类型的结构如下图所示:
NodePort
如果你想要在集群外访问集群内部的服务,你可以使用这种类型的 Service。NodePort 类型的 Service 会在集群内部的所有 Node 节点打开一个指定的端口。之后所有的流量直接发送到这个端口之后,就会转发的 Service 去对真实的服务进行访问。
NodePort Service 类型的结构如下图所示:
LoadBalancer
如果我们希望有一个单独的 IP 地址,将请求分配给所有的外部节点IP(比如使用 round robin),我们就可以使用 LoadBalancer 服务,所以它是建立在 NodePort 服务之上的。
LoadBalancer Service 类型的结构如下图所示:
ExternalName
类型为 ExternalName 的service将服务映射到 DNS 名称,而不是使用选择器,例如my-service
或者cassandra
。 您可以使用spec.externalName
参数指定这些服务。
创建 ExternalName 类型的服务的 yaml 如下:
kind: Service apiVersion: v1 metadata: name: service-python spec: ports: - port: 3000 protocol: TCP targetPort: 443 type: ExternalName externalName: remote.server.url.com
Headless
在某些场景中,开发人员可能不想使用Service提供的负载均衡功能,而希望自己来控制负载均衡策略,针对这种情况,kubernetes提供了HeadLiness Service,这类Service不会分配Cluster IP,如果想要访问service,只能通过service的域名进行查询。
创建service-headliness.yaml
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
# 创建service
[root@master ~]# kubectl create -f service-headliness.yaml
service/service-headliness created
# 获取service, 发现CLUSTER-IP未分配
[root@master ~]# kubectl get svc service-headliness -n dev -o wide
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE SELECTOR
service-headliness ClusterIP None <none> 80/TCP 11s app=nginx-pod
# 查看service详情
[root@master ~]# kubectl describe svc service-headliness -n dev
Name: service-headliness
Namespace: dev
Labels: <none>
Annotations: <none>
Selector: app=nginx-pod
Type: ClusterIP
IP: None
Port: <unset> 80/TCP
TargetPort: 80/TCP
Endpoints: 10.244.1.39:80,10.244.1.40:80,10.244.2.33:80
Session Affinity: None
Events: <none>
# 查看域名的解析情况
[root@master ~]# kubectl exec -it pc-deployment-66cb59b984-8p84h -n dev /bin/sh
/ # cat /etc/resolv.conf
nameserver 10.96.0.10
search dev.svc.cluster.local svc.cluster.local cluster.local
[root@master ~]# dig @10.96.0.10 service-headliness.dev.svc.cluster.local
service-headliness.dev.svc.cluster.local. 30 IN A 10.244.1.40
service-headliness.dev.svc.cluster.local. 30 IN A 10.244.1.39
service-headliness.dev.svc.cluster.local. 30 IN A 10.244.2.33