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-service
namespace: default # 或者你指定的其他命名空间
spec:
type: ExternalName
externalName: www.example.com # 外部服务的域名
指定IP地址
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 80
nodePort: 31000 # 手动指定节点端口(可选)
ClusterIP: IP地址
HeadLess Service
apiVersion: v1
kind: Service
metadata:
name: web-nodeport
spec:
type: NodePort
selector:
app: web
ports:
- port: 80
targetPort: 80
nodePort: 31000 # 手动指定节点端口(可选)
ClusterIP: None
# nginx 部署的yaml文件
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginxweb
spec:
selector:
matchLabels:
app: nginxweb1
replicas: 2
template:
metadata:
labels:
# 容器标签的名字,发布 Service时,selector 需要和这里对应
app: nginxweb1
spec:
# 配置容器,数组类型,说明可以配置多个容器
containers:
# 容器名称
- name: nginxwebc
# 容器镜像
image: nginx:latest
imagePullPolicy: IfNotPresent
# 暴露端口
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginxweb-service
spec:
externalTrafficPolicy: Cluster
selector:
# 选择哪一个容器标签作为服务, labels:》》 app:》》 nginxweb1 通过容器标签关联的
# 上面 Deployment可以单独一个yaml文件 只有知道 label标签就可以了 ,不需要知道 pod的ip地址。 相当于面对服务名不是IP地址
app: nginxweb1
ports:
- protocol: TCP
# Service 暴露的端口
port: 80
# Pod上的端口 这里是将 Service 暴露的端口 转发到 Pod 端口上
targetPort: 80
nodePort: 30080
type: 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: nginxweb
labels:
app: niginx-l1
spec:
selector:
matchLabels:
app: nginxweb1
replicas: 2
template:
metadata:
labels:
# 容器标签的名字,发布 Service时,selector 需要和这里对应
app: nginxweb1
spec:
# 配置容器,数组类型,说明可以配置多个容器
containers:
# 容器名称
- name: nginxwebc
# 容器镜像
image: nginx:latest
imagePullPolicy: IfNotPresent
# 暴露端口
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: nginxweb-service
labels:
app: niginx-s
spec:
selector:
app: nginxweb1
ports:
- protocol: TCP
# Service 暴露的端口
port: 80
# Pod上的端口 这里是将 Service 暴露的端口 转发到 Pod 端口上
targetPort: 80
type: 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: 2020
protocol: TCP
---
apiVersion: v1
kind: Service
metadata:
name: my-endpoint
spec:
ports:
- protocol: TCP
port: 80
targetPort: 2020
nodePort: 30100
type: NodePort