在 Kubernetes 集群中,Pod 默认只能在集群内部访问。为了让外部用户能够访问集群中的应用,我们需要采用适当的网络暴露方式。本文将介绍几种主要的外部访问方法,每种方法都有其特定的使用场景和优缺点。
Kubernetes 提供了多种从外部访问 Pod 和 Service 的方式:
需要注意的是,暴露 Pod 和暴露 Service 本质上是一回事,因为 Service 就是 Pod 的抽象层。
当在 Pod 规格中设置 hostNetwork: true 时,Pod 将直接使用宿主机的网络命名空间。这意味着 Pod 中的应用程序可以直接绑定到宿主机的网络接口上。
以下是相关的示例代码:
apiVersion: v1
kind: Pod
metadata:
name: influxdb
spec:
hostNetwork: true
containers:
- name: influxdb
image: influxdb:1.8
ports:
- containerPort: 8086
以下是具体的使用方法:
# 部署 Pod
kubectl apply -f influxdb-hostnetwork.yaml
# 获取 Pod 所在节点 IP
kubectl get pod influxdb -o wide
# 直接访问宿主机 IP 和端口
curl -v http://<NODE_IP>:8086/ping
适用场景:
注意事项:
hostPort 将容器端口直接映射到宿主机端口,类似于 Docker 的端口映射功能。
以下是相关的示例代码:
apiVersion: v1
kind: Pod
metadata:
name: influxdb
spec:
containers:
- name: influxdb
image: influxdb:1.8
ports:
- containerPort: 8086
hostPort: 8086
protocol: TCP
以下是相关的代码示例:
# 通过任意节点 IP + hostPort 访问
curl http://<NODE_IP>:8086/ping
NodePort 是 Kubernetes Service 的一种类型,它会在每个节点上开放一个端口(默认范围 30000-32767),将外部流量转发到对应的 Pod。
以下是相关的示例代码:
# Pod 定义
apiVersion: v1
kind: Pod
metadata:
name: influxdb
labels:
app: influxdb
spec:
containers:
- name: influxdb
image: influxdb:1.8
ports:
- containerPort: 8086
---
# Service 定义
apiVersion: v1
kind: Service
metadata:
name: influxdb
spec:
type: NodePort
ports:
- port: 8086
targetPort: 8086
nodePort: 30086 # 可选,不指定则自动分配
selector:
app: influxdb
以下是相关的代码示例:
# 通过任意节点 IP + NodePort 访问
curl http://<NODE_IP>:30086/ping
# 或通过 ClusterIP 在集群内访问
curl http://<CLUSTER_IP>:8086/ping
优点:
缺点:
LoadBalancer 类型的 Service 会自动创建云平台提供的负载均衡器,并为 Service 分配一个外部 IP。
以下是相关的示例代码:
apiVersion: v1
kind: Service
metadata:
name: influxdb
spec:
type: LoadBalancer
ports:
- port: 8086
targetPort: 8086
selector:
app: influxdb
以下是相关的代码示例:
# 查看服务状态
kubectl get svc influxdb
# NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
# influxdb LoadBalancer 10.97.121.42 203.0.113.123 8086:30051/TCP 1m
# 通过外部 IP 访问
curl http://203.0.113.123:8086/ping
# 也可以通过 NodePort 访问
curl http://<NODE_IP>:30051/ping
Ingress 是 Kubernetes 中用于管理外部访问集群内服务的 API 对象。它提供 HTTP 和 HTTPS 路由功能,支持基于域名和路径的流量分发。
使用 Ingress 前需要部署 Ingress Controller,常用的有:
以下是相关的示例代码:
# 基础 Ingress 配置
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: influxdb
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: influxdb.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: influxdb
port:
number: 8086
以下是相关的示例代码:
# 支持 HTTPS 和多路径的 Ingress
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: multi-service-ingress
annotations:
nginx.ingress.kubernetes.io/ssl-redirect: "true"
cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
tls:
- hosts:
- api.example.com
secretName: api-tls
rules:
- host: api.example.com
http:
paths:
- path: /influxdb
pathType: Prefix
backend:
service:
name: influxdb
port:
number: 8086
- path: /grafana
pathType: Prefix
backend:
service:
name: grafana
port:
number: 3000
以下是相关的代码示例:
# 通过域名访问
curl http://influxdb.example.com/ping
# HTTPS 访问
curl https://api.example.com/influxdb/ping
| 方式 | 复杂度 | 性能 | 灵活性 | 适用场景 |
|---|---|---|---|---|
| hostNetwork | 低 | 最高 | 低 | 系统级应用、网络插件 |
| hostPort | 低 | 高 | 低 | 简单应用、开发环境 |
| NodePort | 中 | 中 | 中 | 开发测试、内部服务 |
| LoadBalancer | 中 | 高 | 中 | 云环境生产服务 |
| Ingress | 高 | 高 | 最高 | 生产环境、多服务场景 |
以下是相关的代码示例:
# 检查服务状态
kubectl get svc,ingress,endpoints
# 查看 Ingress Controller 日志
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller
# 测试服务连通性
kubectl run test-pod --rm -it --image=busybox -- sh
选择合适的外部访问方式需要考虑多个因素:
在现代云原生应用中,Ingress 已成为暴露 HTTP/HTTPS 服务的主流方式,它不仅提供了强大的路由功能,还与服务网格、API 网关等技术很好地集成,是构建可扩展微服务架构的重要组件。