概念介绍
Kubernetes是一个开源的容器编排平台,用于自动化部署、扩展和管理容器化应用。在Kubernetes中,Service是一种抽象,它定义了一组Pod的逻辑集合,并且能够在这些Pod之间实现负载均衡。Service 使得我们可以通过一个固定的IP地址或DNS名称访问Pod,即使这些Pod的数量和位置在不断变化。
Service实现方式
1.userspace
在userspace模式下,kube-proxy会为每个Service创建一个监听端口。通过Iptables规则,发往Cluster IP的请求被重定向到kube-proxy监听的端口。kube-proxy根据负载均衡算法选择一个服务的Pod,与其建立连接并将请求转发给该Pod。在这种模式下,kube-proxy充当四层负载均衡器的角色。由于kube-proxy在用户空间运行,转发过程中涉及内核与用户空间之间的数据拷贝,虽然这种方式较为稳定,但效率相对较低。
kube-proxy userspace模式
2.iptables
在iptables模式下,kube-proxy为每个Service的后端Pod创建相应的iptables规则,将发往Cluster IP的请求直接重定向到一个Pod IP。这种模式下,kube-proxy并不充当四层负载均衡器的角色,只负责创建和维护iptables规则。相比于userspace模式,iptables模式的效率更高,但无法提供灵活的负载均衡策略,并且当后端Pod不可用时也无法进行请求重试。
kube-proxy iptables模式
3.ipvs
IPVS模式与 iptables 类似,kube-proxy通过监控Pod的变化来创建相应的IPVS规则。与 iptables 相比,IPVS转发效率更高,并且支持更多的负载均衡算法。
kube-proxy ipvs模式
Service 的类型
Service的资源清单文件:
kind:Service# 资源类型
apiVersion:v1# 资源版本
metadata:# 元数据
name:service# 资源名称
namespace:dev# 命名空间
spec:# 描述
selector:# 标签选择器,用于确定当前service代理哪些pod
app:nginx
type:# Service类型,指定service的访问方式
clusterIP:# 虚拟服务的ip地址
sessionAffinity:# session亲和性,支持ClientIP、None两个选项
ports:# 端口信息
-protocol:TCP
port:3017# service端口
targetPort:5003# pod端口
nodePort:31122# 主机端口
Kubernetes 提供了几种类型的 Service,以满足不同的需求:
- ClusterIP:默认类型,创建一个只能在集群内部访问的虚拟IP。
- NodePort:在每个Node上打开一个特定的端口,并将流量转发到ClusterIP。
- LoadBalancer:使用云提供商的负载均衡器,将外部流量分发到NodePort和ClusterIP。
- ExternalName:将服务映射到外部的DNS名称。
部署一个简单的 Web 应用
接下来,我们通过一个实际案例来展示如何创建和使用 Service。假设我们有一个简单的 Nginx Web 应用,我们将使用 Kubernetes 部署它,并通过 Service 进行访问。
Step 1: 创建 Deployment
首先,我们需要创建一个 Deployment 来部署 Nginx 容器。创建一个名为 nginx-deployment.yaml 的文件,内容如下:
apiVersion:apps/v1
kind:Deployment
metadata:
name:nginx-deployment
labels:
app:nginx
spec:
replicas:3
selector:
matchLabels:
app:nginx
template:
metadata:
labels:
app:nginx
spec:
containers:
-name:nginx
image:nginx:1.17.1
ports:
-containerPort:80
使用以下命令来应用这个 Deployment:
kubectl apply -f nginx-deployment.yaml
创建完成后,查看每个pod的IP地址,如下图所示:
Step 2: 创建 Service
现在,我们创建一个 Service 来暴露这个 Deployment。创建一个名为 nginx-service.yaml 的文件,内容如下:
apiVersion:v1
kind:Service
metadata:
name:nginx-service
spec:
selector:
app:nginx
ports:
-protocol:TCP
port:80
targetPort:80
type:ClusterIP
使用以下命令来应用这个 Service:
kubectl apply -f nginx-service.yaml
Step 3: 验证 Service
应用成功后,我们可以使用以下命令来查看 Service 的详情:
kubectl get services
你应该会看到类似如下的输出:
通过 Service 的CLUSTER-IP,我们可以在集群内部访问 Nginx 服务。
HeadlessService的概念和应用
在某些应用场景中,客户端应用不需要通过Kubernetes内置 Service 实现的负载均衡功能,或需要自行完成对服务后端各实例的服务发现机制,或者自行实现负载均衡功能。这时,可以创建一种特殊的服务类型,称为 Headless Service。
Headless Service的特点是,这种服务没有入口访问地址(即没有 ClusterIP 地址),kube-proxy不会为其创建负载转发规则。其服务名(DNS 域名)的解析机制则取决于该 Headless Service 是否设置了 Label Selector。
1.已设置Label Selector
如果Headless Service设置了Label Selector,Kubernetes则将根据Label Selector查询后端Pod列表,自动创建Endpoint列表,将服务名(DNS域名)的解析机制设置为:当客户端访问该服务名时,得到的是全部Endpoint列表(而不是一个确定的IP地址)。以下面的Headless Service为例,其设置了Label Selector:
apiversion:v1
kind:Service
metadata:
name:nginx
labels:
app:nginx
spec:
ports:
-port:80
clusterIP:None
selector:
app:nginx
使用kubectl create命令创建完之后,可以查看该Headless Service的详细信息,可以看到后端的Endpoint列表:
用nslookup工具对Headless Service名称尝试域名解析,将会看到DNS系统返回的全部Endpoint的IP地址,例如:
结论
通过本教程,我们学习了如何在 Kubernetes 中创建和使用 Service 来暴露应用。我们通过一个简单的 Nginx 部署案例,演示了如何使用 ClusterIP 和 NodePort 类型的 Service。掌握这些基本概念和操作后,可以更轻松地管理和扩展 Kubernetes 集群中的应用服务。