Kubernetes 中的 Service 是用于暴露应用服务的核心抽象,为 Pod 提供稳定的访问入口、负载均衡和服务发现机制。Service在Kubernetes中代表了一组Pod的逻辑集合,通过创建一个Service,可以为一组具有相同功能的容器应用提供一个统一的入口地址,并将请求负载分发到后端的各个容器应用上。
流量转发流程
1、客户端访问 Service 的 ClusterIP 或 DNS 名称。
2、kube-proxy 根据 Service 规则将请求转发到后端 Pod。
3、请求到达 Pod 后由应用处理。
ExternalName类型
在Kubernetes(k8s)中,创建一个ExternalName类型的Service可以让你将集群内部的服务通过DNS CNAME机制映射到一个外部域名上。这样,集群内部的Pod就可以通过内部服务名访问外部服务,而无需知道外部服务的真实域名。以下是创建ExternalName类型Service的步骤:
定义YAML文件
首先,你需要定义一个YAML文件来描述Service的属性。以下是一个示例YAML文件,用于创建一个ExternalName类型的Service:
apiVersion: v1
kind: Service
metadata:name: my-externalname-servicenamespace: default # 或者你指定的其他命名空间
spec:type: ExternalNameexternalName: www.example.com # 外部服务的域名
指定IP地址
apiVersion: v1
kind: Service
metadata:name: web-nodeport
spec:type: NodePortselector:app: webports:- port: 80targetPort: 80nodePort: 31000 # 手动指定节点端口(可选)ClusterIP: IP地址
HeadLess Service
apiVersion: v1
kind: Service
metadata:name: web-nodeport
spec:type: NodePortselector:app: webports:- port: 80targetPort: 80nodePort: 31000 # 手动指定节点端口(可选)ClusterIP: None
# nginx 部署的yaml文件
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxweb
spec:selector:matchLabels:app: nginxweb1replicas: 2template:metadata:labels:# 容器标签的名字,发布 Service时,selector 需要和这里对应app: nginxweb1spec:# 配置容器,数组类型,说明可以配置多个容器containers:# 容器名称- name: nginxwebc# 容器镜像image: nginx:latestimagePullPolicy: IfNotPresent# 暴露端口ports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginxweb-service
spec:externalTrafficPolicy: Clusterselector:# 选择哪一个容器标签作为服务, labels:》》 app:》》 nginxweb1 通过容器标签关联的 # 上面 Deployment可以单独一个yaml文件 只有知道 label标签就可以了 ,不需要知道 pod的ip地址。 相当于面对服务名不是IP地址app: nginxweb1ports:- protocol: TCP# Service 暴露的端口port: 80# Pod上的端口 这里是将 Service 暴露的端口 转发到 Pod 端口上targetPort: 80nodePort: 30080type: NodePort
K8S 分配给Service一个固定IP,这是一个虚拟IP(也称为 ClusterIP),并不是一个真实存在的IP,而是由K8S虚拟出来的,外部是寻址不到的。在K8S系统中,实际上是由kubernetes Proxy 组件负责实现虚拟IP路由和转发的。所以说在K8s node中我们都运行了Kubernetest Proxy,从而在容器覆盖网络之上又实现了Kubernetes层级的虚拟转发网络。
通过服务名访问》要在Pod内部才能通过服务名访问
# 同一命名空间内的 Service 访问
域名格式:<service-name>
# 跨命名空间的 Service 访问
域名格式:<service-name>.<namespace>.svc.cluster.local
# nginx 部署的yaml文件
---
apiVersion: apps/v1
kind: Deployment
metadata:name: nginxweblabels:app: niginx-l1
spec:selector:matchLabels:app: nginxweb1replicas: 2template:metadata:labels:# 容器标签的名字,发布 Service时,selector 需要和这里对应app: nginxweb1spec:# 配置容器,数组类型,说明可以配置多个容器containers:# 容器名称- name: nginxwebc# 容器镜像image: nginx:latestimagePullPolicy: IfNotPresent# 暴露端口ports:- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:name: nginxweb-servicelabels:app: niginx-s
spec:selector:app: nginxweb1ports:- protocol: TCP# Service 暴露的端口port: 80# Pod上的端口 这里是将 Service 暴露的端口 转发到 Pod 端口上targetPort: 80type: ClusterIP
创建Service会自动创建同名的Endpoint
Service 不仅可以代理Pod,还可以代理任意其他后端。
比如代理K8s外部的服务。
虽然不常见,但Endpoint也可以手动创建。这通常用于特殊情况,比如需要显式指定Endpoint的IP地址和端口,例如在与外部非K8s管理的服务进行集成时,可能需要手动创建Endpoint来定义服务的访问信息,以便将其纳入K8s的服务管理体系中。
apiVersion: v1
kind: Endpoints
metadata:name: my-endpoint
subsets:- addresses:- ip: 地址ports:- port: 2020protocol: TCP
---
apiVersion: v1
kind: Service
metadata:name: my-endpoint
spec:ports:- protocol: TCPport: 80targetPort: 2020nodePort: 30100type: NodePort