This repository has been archived on 2026-05-24. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
2026-05-18 00:17:59 +08:00

145 lines
4.7 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
---
tags: [kubernetes, service, ingress, networking, service-discovery]
create time: 2026-05-18 00:30
---
# K8s 网络与服务发现 — Service 与 Ingress
## 概述
Kubernetes 的网络模型解决了容器 IP 频繁变动的问题。Service 提供**稳定的服务发现入口**,Ingress 提供**L7 HTTP 路由能力**。本文将梳理核心概念、典型模式和常见问题。
## Service 类型
| 类型 | 特点 | 使用场景 |
|------|------|---------|
| **ClusterIP** | 集群内 IP,外部不可访问 | 默认,内部服务间调用 |
| **NodePort** | 在每个 Node 上开端口 | 调试、临时访问 |
| **LoadBalancer** | 云厂商分配公网 IP | 对外暴露的服务 |
| **ExternalName** | CNAME 到外部域名 | 对接外部系统 |
### ClusterIP Service — 服务发现的载体
```yaml
apiVersion: v1
kind: Service
metadata:
name: order-service
spec:
selector:
app: order # 匹配带此 label 的 Pod
ports:
- port: 80 # Service 端口(对外暴露)
targetPort: 8080 # 容器实际监听端口
protocol: TCP
type: ClusterIP
```
调用方只需 `http://order-service:80`,K8s 通过 iptables/IPVS 自动实现负载均衡。
> [!question] Service 是怎么做到负载均衡的?
>
> 每个 Node 上的 kube-proxy 会监控 Service 的变动,自动生成 iptables 规则或 IPVS 虚拟服务器配置。当请求发往 ClusterIP 时,内核将其 DNAT 到后端 Pod IP 之一,负载均衡算法默认是 round-robin。K8s 1.14+ 推荐使用 IPVS 模式(`kube-proxy --proxy-mode=ipvs`),性能更高且支持更多算法。
## Ingress — HTTP/HTTPS 路由
```yaml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: main-ingress
annotations:
nginx.ingress.kubernetes.io/rewrite-target: /
spec:
rules:
- host: api.example.com
http:
paths:
- path: /orders
pathType: Prefix
backend:
service:
name: order-service
port:
number: 80
- path: /users
pathType: Prefix
backend:
service:
name: user-service
port:
number: 80
```
> [!info] Ingress Controller 是什么?
>
> Ingress 只是一个 API 对象,真正的 HTTP 路由由 Ingress Controller(如 NGINX、Traefik、Envoy)执行。安装后会在集群中运行一个 LoadBalancer 类型的 Pod 集群,监听 Ingress 资源变化并生成对应配置。
### 常见 Ingress Annotation(NGINX 为例)
| Annotation | 用途 | 示例值 |
|------------|------|--------|
| `rewrite-target` | URL 重写 | `/` |
| `ssl-redirect` | 强制 HTTPS | `"true"` |
| `rate-limit` | 限流 | `100` |
| `whitelist-source-range` | IP 白名单 | `10.0.0.0/8` |
| `client-max-body-size` | 上传文件大小限制 | `50m` |
## Headless Service — 无头服务
Headless Service (`ClusterIP: None`) 不分配虚拟 IP,而是返回所有匹配 Pod 的真实 IP。这是 StatefulSet 的灵魂搭档:
```yaml
apiVersion: v1
kind: Service
metadata:
name: mysql-headless
spec:
clusterIP: None # 关键:不分配 ClusterIP
selector:
app: mysql
ports:
- port: 3306
```
通过 DNS 可以直接访问单个 Pod:
- `mysql-cluster-0.mysql-headless.production.svc.cluster.local:3306`
- `mysql-cluster-1.mysql-headless.production.svc.cluster.local:3306`
## K8s 网络模型总结
```mermaid
flowchart LR
EXT["外部流量"] --> INGRESS["Ingress Controller"]
INGRESS --> SVC_A["order-service:80"]
INGRESS --> SVC_B["user-service:80"]
SVC_A --> Pod1["order-pod-1\n10.244.1.5:8080"]
SVC_A --> Pod2["order-pod-2\n10.244.2.3:8080"]
SVC_B --> Pod3["user-pod-1\n10.244.1.8:3000"]
Pod1 -->|DNS解析| COREDNS["CoreDNS<br/>svc.cluster.local"]
style EXT fill:#e3f2fd
style INGRESS fill:#fff3e0
style SVC_A fill:#e8f5e9
style SVC_B fill:#fce4ec
```
> [!tip] 调试技巧:Service 不通怎么办?
>
> 1. `kubectl get svc <name>` 确认 Service 存在且有 ClusterIP
> 2. `kubectl get endpoints <name>` 检查 Endpoint 列表是否为空
> 3. Endpoint 为空 → 检查 selector 标签是否匹配 Pod
> 4. Endpoint 有值但 curl 不通 → 进入 Pod `curl <ClusterIP>:<port>` 验证
> 5. ClusterIP 通但外部不通 → 检查 Ingress / LoadBalancer 配置
## 关联笔记
- [[../01-核心概念与Deployment]] — Deployment 通过 selector 与 Service 关联
- [[../02-配置管理]] — Service 的端点配置不直接涉及 ConfigMap/Secret
- [[../04-扩缩容与有状态应用]] — Headless Service + StatefulSet 配合
- [[../hhs/MS/02-服务治理/04-服务发现]] — K8s Service 是服务端发现模式的代表