文章目录
一、Service
简介
Kubernetes (k8s) 中的 Service 对象是一种抽象,它定义了一组 Pod 的逻辑集合和访问它们的策略。Service 为 Pod 提供了一个稳定的网络端点,使得其他 Pod 或外部客户端可以可靠地访问这些 Pod,即使 Pod 的 IP 地址可能会发生变化。
Service的关键概念和特征:
-
稳定性和发现:尽管Pod的IP地址可能会因为重启或者扩缩容而变化,但是Service的虚拟IP(ClusterIP)保持稳定,提升了服务发现的稳定性。
-
选择器 (Selector):Service通常使用标签选择器来选择需要暴露的Pod集合。这允许动态更新后台Pod集群,而无需手动维护Pod列表。
Service的关键概念和特征:
- 服务发现:Service 为一组 Pod 提供一个统一的访问点(通常是 DNS 名称),使得其他组件可以轻松发现和访问这些 Pod。
- 负载均衡:当多个 Pod 提供相同的服务时,Service 可以自动在这些 Pod 之间进行负载均衡。
- 稳定的网络地址:Service 提供一个稳定的 IP 地址和端口,即使底层 Pod 发生变化,这个地址也保持不变。
- 抽象底层实现:Service 使得应用程序可以不必关心具体的 Pod IP 地址,只需要知道 Service 的名称即可。
- 支持多种类型:Kubernetes 支持多种类型的 Service,包括 ClusterIP、NodePort、LoadBalancer 和 ExternalName。
Service 的主要类型:
- ClusterIP(默认):为 Service 分配一个集群内部的 IP 地址,只能在集群内部访问。
- NodePort:在 ClusterIP 的基础上,为 Service 在每个节点上分配一个端口,可以通过 <NodeIP>:<NodePort> 从集群外部访问服务。
- LoadBalancer:在 NodePort 的基础上,使用云提供商的负载均衡器,将流量转发到 <NodeIP>:<NodePort>。(公有云使用)
- ExternalName:将服务映射到一个外部的 DNS 名称。
Service和kube-proxy的作用与区别
Kubernetes中的Service和kube-proxy都是与网络流量管理密切相关的组件,但它们的功能和工作机制有很大的不同。
Service的工作过程
-
Service定义:服务在Kubernetes中通过YAML或JSON格式的配置文件来定义。配置文件中通常包括服务的类型(如ClusterIP、NodePort、LoadBalancer)、端口信息、标签选择器等。
-
选择Pod:Service根据定义的标签选择器(Selector)来识别需要暴露的Pod。Kubernetes通过这些选择器将流量转发到匹配的Pod。
-
Endpoints创建:一旦Service被创建或更新,Kubernetes会创建或更新一个Endpoints对象,其中包含当前符合选择条件的Pod的IP和端口。
-
流量路由:每个Service都有一个稳定的虚拟IP(ClusterIP),集群内部的请求通过这个IP进入,然后根据Endpoints信息进行内部负载均衡,将流量路由到合适的Pod。
-
服务类型扩展:
- ClusterIP:默认类型,仅在集群内部访问。
- NodePort:通过集群中每个节点的同一端口暴露服务,使得服务可以从外部访问。
- LoadBalancer:利用云提供商的负载均衡器在外部直接暴露服务。
- ExternalName:将服务映射到外部DNS名称。
kube-proxy的工作过程
kube-proxy是Kubernetes中的网络代理,它在每个节点上运行,用于实现Kubernetes服务抽象的流量路由。它的工作过程包括:
-
监听API服务器:kube-proxy持续监听API服务器,以获取所有Service和Endpoints的最新信息。当这些对象发生变化时,kube-proxy会相应地更新自身的配置。
-
网络规则管理:根据服务规则和对应的Endpoints,kube-proxy在节点上设置网络规则。这些规则负责拦截经过的请求并将其转发到适当的Pod。
-
实现机制:
- iptables模式(传统):kube-proxy使用iptables为每个Service生成规则。规则通过NAT(网络地址转换)将请求从Service IP和端口重定向到Pod的IP和端口。
- IPVS模式(更现代):使用Linux内核的IP虚拟服务器(IPVS)来实现更高效的负载均衡。IPVS对大量服务和流量提供了更好的性能。
-
负载均衡:根据Endpoints信息,kube-proxy负责在多个后端Pod之间负载均衡来自Service的流量。
总结
- Service:在Kubernetes中用于将一组Pod作为服务来暴露,提供TCP/IP网络接口,从而实现负载均衡和服务发现。
- kube-proxy:是一个网络代理,负责具体实现Service所需的流量转发和负载均衡功能。它运行在每个节点上,通过管理底层网络规则,确保集群内部外部的流量能够被正确地路由到相应的Pod。
二、具体实践
下面逐个演示service的四种类型,但LoadBalancer只在公有云环境中使用,故不演示。
ClusterIP
ClusterIP是Kubernetes中服务(Service)资源的默认类型,用于在集群内部提供对服务的稳定访问。
ClusterIP 基本概念
- 集群内部访问:ClusterIP 为服务分配一个虚拟IP,只能在 Kubernetes 集群内部使用。外部无法直接访问。
- 服务发现:集群内的其他 Pod 可以通过服务名称来访问这个服务,简单直观。
- 负载均衡:当服务由多个 Pod 提供时,ClusterIP 会自动在这些 Pod 之间分配流量。
应用场景
- 内部服务通信:所有需要在 Kubernetes 内部通信的组件,比如微服务架构中的不同服务,通过 ClusterIP 互相调用。
- 数据库接入:集群内部的应用程序可以通过 ClusterIP 来访问数据库服务。
- 后端服务调用:前端应用或 API 网关访问后端服务时,利用 ClusterIP 提供稳定的网络路径。
yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx-dep
spec:
replicas: 10
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx1
image: harbor.hiuiu.com/nginx/nginx:1.22a
imagePullPolicy: IfNotPresent
ports:
- containerPort: 80
--- 上面是启动模板文件,创建10个pod
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec:
type: ClusterIP
ports:
- port: 80 暴露的端口
targetPort: 80 pod的实际端口
selector:
app: nginx
bash
kubectl get service myapp-service -o wide
查看service的状态
结果是集群内部可以访问,集群外部不可以访问。
NodePort
NodePort 简介
-
什么是 NodePort :
NodePort 是 Kubernetes 提供的一种服务类型,它允许外部流量通过特定端口访问集群内的服务。
-
如何工作:
- 在每个节点上开放一个固定范围的端口(30000-32767)。
- 可以通过访问任一节点的 IP 和这个端口来访问服务。
应用场景
-
快速测试:
- 在开发或测试环境中快速暴露服务给外部用户。
-
简单外部访问:
- 没有复杂负载均衡需求的小规模或本地网络中使用。
-
结合负载均衡:
- 可以与外部负载均衡器结合使用,提供更好的流量管理。
yaml
apiVersion: v1
kind: Service
metadata:
name: my-nodeport
spec:
type: NodePort
selector:
app: nginx
ports:
- port: 80
targetPort: 80
nodePort: 30007
bash
在这里插入代码片
ExternalName
ExternalName
是 Kubernetes 中的一种特殊服务类型,用于将集群内的服务请求直接映射到外部的 DNS 名称。
简介
-
DNS 名称映射:
ExternalName
服务通过将 Kubernetes 服务名称解析为外部 DNS 名称来工作。这意味着它不生成实际的网络代理,而是直接将域名解析为外部地址。
-
无需端口或代理:
- 这种服务类型不涉及 Kubernetes 代理,不需要暴露任何端口,只需简单地做 DNS 级别的转发。
应用场景
-
访问外部服务:
- 当您需要从 Kubernetes 内部访问集群外部的服务时,可以使用
ExternalName
类型。例如,某些第三方 API 或外部数据库服务。
- 当您需要从 Kubernetes 内部访问集群外部的服务时,可以使用
-
服务切换/重定向:
- 在迁移阶段,可以使用
ExternalName
将流量指向临时的外部主机,简化服务切换过程。
- 在迁移阶段,可以使用
-
统一服务访问:
- 可以通过
ExternalName
为 Kubernetes 集群内的服务提供与外部服务一致的访问接口,统一服务调用方式。
- 可以通过
yaml
apiVersion: v1
kind: Pod
metadata:
name: external-pod
spec:
containers:
- name: external-c
image: harbor.hiuiu.com/linux_system/centos/centos7:7.9.2009
command: ["/bin/sh"]
args: ["-c","while true; do echo aaa; sleep 10; done"]
---
apiVersion: v1
kind: Service
metadata:
name: external(集群内部的域名)
spec:
type: ExternalName
externalName: baidu.com
进入集群内部,去查看那个域名,解析出来的名字是baidu.com