k8s | Kubernetes 服务暴露:NodePort、Ingress 与 YAML 配置详解
CodingTechWork
引言
在 Kubernetes 集群中,服务暴露是将集群内部的服务对外部网络提供访问的关键环节。NodePort
和 Ingress
是两种常用的服务暴露方式,它们各有特点和适用场景。本文将详细介绍这两种方式的原理、配置方法以及如何通过 YAML 文件实现服务的正确暴露。
NodePort 服务暴露
NodePort 原理
NodePort 是 Kubernetes 提供的一种简单服务暴露方式。它通过在集群的每个节点上开放一个固定的端口(范围通常是 30000 - 32767),将外部请求转发到对应的服务 Pod 上。这种方式的优点是配置简单,无需额外的组件支持,但缺点是端口范围有限,且直接暴露了节点的端口,不够灵活。
NodePort 配置示例
假设我们有一个简单的 Web 应用,运行在 Kubernetes 集群中,我们希望使用 NodePort 方式将其暴露给外部访问。
-
创建 Deployment
首先,我们需要创建一个 Deployment 来部署应用的 Pod。以下是一个简单的 Deployment YAML 文件:apiVersion: apps/v1 kind: Deployment metadata:name: my-web-applabels:app: my-web-app spec:replicas: 3selector:matchLabels:app: my-web-apptemplate:metadata:labels:app: my-web-appspec:containers:- name: my-web-app-containerimage: my-web-app-image:latestports:- containerPort: 80
这个 Deployment 定义了一个名为
my-web-app
的应用,使用了my-web-app-image
镜像,并且每个 Pod 在容器内部监听 80 端口。 -
创建 Service 使用 NodePort
接下来,我们创建一个 Service 来暴露这个应用。以下是使用 NodePort 的 Service YAML 文件:apiVersion: v1 kind: Service metadata:name: my-web-app-service spec:type: NodePortports:- port: 80targetPort: 80nodePort: 30001selector:app: my-web-app
在这个 Service 中:
type: NodePort
指定了服务类型为 NodePort。port: 80
是集群内部访问服务的端口。targetPort: 80
是 Pod 内部容器的端口。nodePort: 30001
是集群节点上暴露的端口,外部可以通过<节点IP>:30001
访问这个服务。selector
用于选择与这个 Service 关联的 Pod。
-
访问服务
配置完成后,可以通过集群中任意节点的 IP 地址加上端口 30001 来访问这个 Web 应用。例如,如果集群节点的 IP 是192.168.1.100
,那么可以通过http://192.168.1.100:30001
来访问。
Ingress 服务暴露
Ingress 原理
Ingress 是 Kubernetes 提供的一种更高级的服务暴露方式。它允许通过一个统一的入口(通常是 Ingress Controller
)来管理多个服务的外部访问。Ingress 可以基于域名、路径等规则将请求转发到不同的后端服务,提供了更灵活的路由功能和负载均衡能力。使用 Ingress 通常需要安装一个 Ingress Controller,如 Nginx Ingress Controller 或 Traefik。
(二)Ingress 配置示例
假设我们有多个服务需要暴露,并且希望通过域名和路径来区分它们。
-
安装 Ingress Controller
以 Nginx Ingress Controller 为例,可以通过以下命令安装:kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/main/deploy/static/provider/cloud/deploy.yaml
安装完成后,Ingress Controller 会监听集群中的 Ingress 资源,并根据配置进行请求转发。
-
创建 Service
假设我们有两个服务:service-a
和service-b
,分别运行在 8080 和 8081 端口上。以下是它们的 Service YAML 文件:apiVersion: v1 kind: Service metadata:name: service-a spec:selector:app: service-aports:- protocol: TCPport: 80targetPort: 8080 --- apiVersion: v1 kind: Service metadata:name: service-b spec:selector:app: service-bports:- protocol: TCPport: 80targetPort: 8081
这里将两个服务的 Service 端口都设置为 80,方便后续通过 Ingress 进行路由。
-
创建 Ingress 资源
接下来,我们创建一个 Ingress 资源来定义路由规则。以下是 Ingress YAML 文件:apiVersion: networking.k8s.io/v1 kind: Ingress metadata:name: my-ingressannotations:nginx.ingress.kubernetes.io/rewrite-target: /$1 spec:rules:- host: service-a.example.comhttp:paths:- path: /(.*)pathType: Prefixbackend:service:name: service-aport:number: 80- host: service-b.example.comhttp:paths:- path: /(.*)pathType: Prefixbackend:service:name: service-bport:number: 80
在这个 Ingress 配置中:
rules
定义了两条路由规则。- 第一条规则将域名
service-a.example.com
下的所有请求转发到service-a
服务。 - 第二条规则将域名
service-b.example.com
下的所有请求转发到service-b
服务。 annotations
中的nginx.ingress.kubernetes.io/rewrite-target: /$1
是一个可选的注解,用于对请求路径进行重写,确保请求能够正确转发到后端服务。
-
访问服务
配置完成后,可以通过域名访问服务。例如,如果集群的入口地址是192.168.1.200
,并且已经将service-a.example.com
和service-b.example.com
解析到这个地址,那么可以通过以下方式访问:- 访问
http://service-a.example.com
将请求转发到service-a
。 - 访问
http://service-b.example.com
将请求转发到service-b
。
- 访问
NodePort 与 Ingress 的对比
特性 | NodePort | Ingress |
---|---|---|
配置复杂度 | 简单 | 较复杂(需要安装 Ingress Controller 和配置 Ingress 资源) |
端口限制 | 端口范围有限(30000 - 32767) | 无端口限制,通过域名和路径路由 |
灵活性 | 低,直接暴露节点端口 | 高,支持域名、路径路由,负载均衡等 |
适用场景 | 小型应用,对端口数量要求不高 | 大型应用,需要灵活的路由和负载均衡 |
总结
在 Kubernetes 集群中,NodePort 和 Ingress 是两种常见的服务暴露方式。NodePort 适合简单场景,配置简单但不够灵活;Ingress 提供了更强大的路由功能和负载均衡能力,但需要额外的配置和组件支持。根据实际需求选择合适的服务暴露方式,可以更好地满足应用的访问需求。