Service 与 Ingress

核心知识点

1. Service 详解

1.1 Service 的概念

Service 是 Kubernetes 中用于定义一组 Pod 的访问策略的抽象,它提供稳定的网络端点、负载均衡和服务发现功能。

┌─────────────────────────────────────────────────────┐
│              Service 架构                          │
├─────────────────────────────────────────────────────┤
│                                                     │
│   ┌──────────────┐                                 │
│   │   Service    │                                 │
│   │              │                                 │
│   │  IP: 10.0.0.1│                                 │
│   │  Port: 80    │                                 │
│   └──────┬───────┘                                 │
│          │                                         │
│          ▼                                         │
│   ┌─────────────────────────────────┐               │
│   │         Pods (Selector)         │               │
│   │  ┌─────┐  ┌─────┐  ┌─────┐    │               │
│   │  │Pod 1│  │Pod 2│  │Pod 3│    │               │
│   │  │:8080│  │:8080│  │:8080│    │               │
│   │  └─────┘  └─────┘  └─────┘    │               │
│   └─────────────────────────────────┘               │
│                                                     │
└─────────────────────────────────────────────────────┘

1.2 Service 类型

┌─────────────────────────────────────────────────────┐
│           Service 类型对比                         │
├─────────────────────────────────────────────────────┤
│                                                     │
│  ┌─────────────┐  ┌─────────────┐  ┌─────────────┐ │
│  │ClusterIP    │  │NodePort     │  │LoadBalancer │ │
│  │             │  │             │  │             │ │
│  │仅集群内部    │  │节点端口     │  │外部负载均衡  │ │
│  │访问         │  │访问         │  │访问         │ │
│  └─────────────┘  └─────────────┘  └─────────────┘ │
│                                                     │
│  ┌─────────────────────────────────────────────┐  │
│  │              ExternalName                   │  │
│  │                                             │  │
│  │         映射到外部 DNS 名称                  │  │
│  └─────────────────────────────────────────────┘  │
│                                                     │
└─────────────────────────────────────────────────────┘

1.3 Service 配置示例

apiVersion: v1
kind: Service
metadata:
  name: my-service
  labels:
    app: myapp
spec:
  type: ClusterIP
  selector:
    app: myapp
  ports:
  - name: http
    protocol: TCP
    port: 80
    targetPort: 8080
  - name: https
    protocol: TCP
    port: 443
    targetPort: 8443
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

2. Service 类型详解

2.1 ClusterIP Service

apiVersion: v1
kind: Service
metadata:
  name: clusterip-service
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP

2.2 NodePort Service

apiVersion: v1
kind: Service
metadata:
  name: nodeport-service
spec:
  type: NodePort
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    nodePort: 30080
    protocol: TCP
  externalTrafficPolicy: Local

2.3 LoadBalancer Service

apiVersion: v1
kind: Service
metadata:
  name: loadbalancer-service
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    service.beta.kubernetes.io/aws-load-balancer-cross-zone-load-balancing-enabled: "true"
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
    protocol: TCP
  loadBalancerSourceRanges:
  - 10.0.0.0/8
  - 192.168.0.0/16

2.4 ExternalName Service

apiVersion: v1
kind: Service
metadata:
  name: external-dns
spec:
  type: ExternalName
  externalName: example.com

3. Ingress 详解

3.1 Ingress 的概念

Ingress 是 Kubernetes 中用于管理外部访问集群内服务的 API 对象,它提供 HTTP 和 HTTPS 路由规则。

┌─────────────────────────────────────────────────────┐
│              Ingress 架构                          │
├─────────────────────────────────────────────────────┤
│                                                     │
│   ┌──────────────┐                                 │
│   │   Client     │                                 │
│   └──────┬───────┘                                 │
│          │                                         │
│          ▼                                         │
│   ┌──────────────┐                                 │
│   │  Ingress     │                                 │
│   │  Controller  │                                 │
│   └──────┬───────┘                                 │
│          │                                         │
│          ▼                                         │
│   ┌─────────────────────────────────┐               │
│   │         Services                │               │
│   │  ┌─────────┐  ┌─────────┐      │               │
│   │  │ Service │  │ Service │      │               │
│   │  │   A     │  │   B     │      │               │
│   │  └────┬────┘  └────┬────┘      │               │
│   └───────┼────────────┼───────────┘               │
│           │            │                            │
│           ▼            ▼                            │
│   ┌─────────────────────────────────┐               │
│   │         Pods                    │               │
│   └─────────────────────────────────┘               │
│                                                     │
└─────────────────────────────────────────────────────┘

3.2 Ingress Controller

Ingress Controller 是实现 Ingress 功能的组件,常见的有:

  • NGINX Ingress Controller:最流行的 Ingress Controller
  • Traefik:自动服务发现和配置
  • HAProxy Ingress:高性能负载均衡
  • Istio Gateway:服务网格集成
  • AWS ALB Ingress Controller:AWS 集成

3.3 Ingress 配置示例

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: my-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    - www.example.com
    secretName: example-tls
  rules:
  - host: example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /v1
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 8080

4. Service 管理命令

4.1 创建和查看 Service

# 创建 Service
kubectl apply -f service.yaml

# 查看 Service 列表
kubectl get services

# 查看 Service 详细信息
kubectl describe service my-service

# 查看 Service 端点
kubectl get endpoints my-service

# 查看 Service YAML 配置
kubectl get service my-service -o yaml

# 删除 Service
kubectl delete service my-service

# 查看 Service 的 Cluster IP
kubectl get service my-service -o jsonpath='{.spec.clusterIP}'

# 查看 Service 的端口
kubectl get service my-service -o jsonpath='{.spec.ports}'

4.2 Service 调试

# 测试 Service 连通性
kubectl run test-pod --image=busybox --rm -it -- wget -O- http://my-service

# 查看 Service 的 DNS 解析
kubectl run test-pod --image=busybox --rm -it -- nslookup my-service

# 查看 Service 的端点
kubectl get endpoints my-service -o wide

# 查看 Service 事件
kubectl describe service my-service

# 查看 Service 关联的 Pod
kubectl get pods -l app=myapp

5. Ingress 管理命令

5.1 创建和查看 Ingress

# 创建 Ingress
kubectl apply -f ingress.yaml

# 查看 Ingress 列表
kubectl get ingress

# 查看 Ingress 详细信息
kubectl describe ingress my-ingress

# 查看 Ingress YAML 配置
kubectl get ingress my-ingress -o yaml

# 删除 Ingress
kubectl delete ingress my-ingress

# 查看 Ingress 地址
kubectl get ingress my-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

5.2 Ingress 调试

# 查看 Ingress Controller 日志
kubectl logs -n ingress-nginx deployment/ingress-nginx-controller

# 查看 Ingress Controller 状态
kubectl get pods -n ingress-nginx

# 测试 Ingress 路由
curl -H "Host: example.com" http://<ingress-ip>/

# 查看 Ingress 配置
kubectl exec -n ingress-nginx deployment/ingress-nginx-controller -- cat /etc/nginx/nginx.conf

# 重新加载 Ingress Controller
kubectl exec -n ingress-nginx deployment/ingress-nginx-controller -- nginx -s reload

6. 高级配置

6.1 Service 会话保持

apiVersion: v1
kind: Service
metadata:
  name: session-service
spec:
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080
  sessionAffinity: ClientIP
  sessionAffinityConfig:
    clientIP:
      timeoutSeconds: 10800

6.2 Service 健康检查

apiVersion: v1
kind: Service
metadata:
  name: health-check-service
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-path: /health
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-interval: "30"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-timeout: "5"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-healthy-threshold: "2"
    service.beta.kubernetes.io/aws-load-balancer-healthcheck-unhealthy-threshold: "3"
spec:
  type: LoadBalancer
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 8080

6.3 Ingress 路由规则

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: advanced-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rate-limit: "100"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - example.com
    secretName: tls-secret
  rules:
  - host: example.com
    http:
      paths:
      - path: /api(/|$)(.*)
        pathType: ImplementationSpecific
        backend:
          service:
            name: api-service
            port:
              number: 8080
      - path: /web
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
      - path: /admin
        pathType: Prefix
        backend:
          service:
            name: admin-service
            port:
              number: 8081

6.4 Ingress 认证

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: auth-ingress
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: basic-auth
    nginx.ingress.kubernetes.io/auth-realm: "Authentication Required"
spec:
  ingressClassName: nginx
  rules:
  - host: secure.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: secure-service
            port:
              number: 8080

实用案例分析

案例 1:部署 Web 应用并暴露服务

场景描述

部署一个 Nginx Web 应用,使用 Service 暴露服务。

操作步骤

# 1. 创建 Deployment
cat > web-deployment.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-deployment
spec:
  replicas: 3
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
EOF

kubectl apply -f web-deployment.yaml

# 2. 创建 ClusterIP Service
cat > web-service-clusterip.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: web-service-clusterip
spec:
  type: ClusterIP
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
EOF

kubectl apply -f web-service-clusterip.yaml

# 3. 查看 Service
kubectl get services

# 4. 测试 Service 连通性
kubectl run test-pod --image=busybox --rm -it -- wget -O- http://web-service-clusterip

# 5. 创建 NodePort Service
cat > web-service-nodeport.yaml << 'EOF'
apiVersion: v1
kind: Service
metadata:
  name: web-service-nodeport
spec:
  type: NodePort
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
    nodePort: 30080
    protocol: TCP
EOF

kubectl apply -f web-service-nodeport.yaml

# 6. 查看 NodePort Service
kubectl get services

# 7. 通过节点端口访问
curl http://<node-ip>:30080

# 8. 清理资源
kubectl delete -f web-deployment.yaml
kubectl delete -f web-service-clusterip.yaml
kubectl delete -f web-service-nodeport.yaml

案例 2:配置 Ingress 实现域名路由

场景描述

使用 Ingress 配置多个服务的域名路由。

操作步骤

# 1. 安装 NGINX Ingress Controller
kubectl apply -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml

# 2. 等待 Ingress Controller 就绪
kubectl wait --namespace ingress-nginx \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/component=controller \
  --timeout=120s

# 3. 创建 Web 应用
cat > web-app.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: web-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: web
  template:
    metadata:
      labels:
        app: web
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: web-service
spec:
  selector:
    app: web
  ports:
  - port: 80
    targetPort: 80
EOF

kubectl apply -f web-app.yaml

# 4. 创建 API 应用
cat > api-app.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: api-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: api
  template:
    metadata:
      labels:
        app: api
    spec:
      containers:
      - name: api
        image: kennethreitz/httpbin
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: api-service
spec:
  selector:
    app: api
  ports:
  - port: 80
    targetPort: 80
EOF

kubectl apply -f api-app.yaml

# 5. 创建 Ingress
cat > multi-host-ingress.yaml << 'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: multi-host-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: web.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: web-service
            port:
              number: 80
  - host: api.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: api-service
            port:
              number: 80
EOF

kubectl apply -f multi-host-ingress.yaml

# 6. 查看 Ingress
kubectl get ingress

# 7. 获取 Ingress IP
kubectl get ingress multi-host-ingress -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

# 8. 测试路由(添加域名到 /etc/hosts)
echo "<ingress-ip> web.example.com api.example.com" | sudo tee -a /etc/hosts
curl -H "Host: web.example.com" http://<ingress-ip>/
curl -H "Host: api.example.com" http://<ingress-ip>/get

# 9. 清理资源
kubectl delete -f web-app.yaml
kubectl delete -f api-app.yaml
kubectl delete -f multi-host-ingress.yaml
kubectl delete -f https://raw.githubusercontent.com/kubernetes/ingress-nginx/controller-v1.8.1/deploy/static/provider/cloud/deploy.yaml

案例 3:配置 HTTPS Ingress

场景描述

使用 Let's Encrypt 配置 HTTPS Ingress。

操作步骤

# 1. 安装 cert-manager
kubectl apply -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml

# 2. 等待 cert-manager 就绪
kubectl wait --namespace cert-manager \
  --for=condition=ready pod \
  --selector=app.kubernetes.io/instance=cert-manager \
  --timeout=120s

# 3. 创建 ClusterIssuer
cat > cluster-issuer.yaml << 'EOF'
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
  name: letsencrypt-prod
spec:
  acme:
    server: https://acme-v02.api.letsencrypt.org/directory
    email: your-email@example.com
    privateKeySecretRef:
      name: letsencrypt-prod
    solvers:
    - http01:
        ingress:
          class: nginx
EOF

kubectl apply -f cluster-issuer.yaml

# 4. 创建应用
cat > secure-app.yaml << 'EOF'
apiVersion: apps/v1
kind: Deployment
metadata:
  name: secure-app
spec:
  replicas: 2
  selector:
    matchLabels:
      app: secure
  template:
    metadata:
      labels:
        app: secure
    spec:
      containers:
      - name: nginx
        image: nginx:1.21
        ports:
        - containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
  name: secure-service
spec:
  selector:
    app: secure
  ports:
  - port: 80
    targetPort: 80
EOF

kubectl apply -f secure-app.yaml

# 5. 创建 HTTPS Ingress
cat > https-ingress.yaml << 'EOF'
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: https-ingress
  annotations:
    cert-manager.io/cluster-issuer: "letsencrypt-prod"
    nginx.ingress.kubernetes.io/ssl-redirect: "true"
spec:
  ingressClassName: nginx
  tls:
  - hosts:
    - secure.example.com
    secretName: secure-tls
  rules:
  - host: secure.example.com
    http:
      paths:
      - path: /
        pathType: Prefix
        backend:
          service:
            name: secure-service
            port:
              number: 80
EOF

kubectl apply -f https-ingress.yaml

# 6. 查看 Ingress
kubectl get ingress

# 7. 查看证书状态
kubectl get certificate

# 8. 查看证书详情
kubectl describe certificate secure-tls

# 9. 测试 HTTPS 连接
curl -k https://secure.example.com

# 10. 清理资源
kubectl delete -f secure-app.yaml
kubectl delete -f https-ingress.yaml
kubectl delete -f cluster-issuer.yaml
kubectl delete -f https://github.com/cert-manager/cert-manager/releases/download/v1.13.0/cert-manager.yaml

最佳实践

  1. 使用 ClusterIP 作为默认 Service 类型:仅在需要外部访问时使用其他类型。

  2. 使用 Headless Service 进行有状态应用:直接暴露 Pod IP。

apiVersion: v1
kind: Service
metadata:
  name: headless-service
spec:
  clusterIP: None
  selector:
    app: stateful
  ports:
  - port: 80
    targetPort: 8080
  1. 配置会话保持:确保同一客户端连接到同一 Pod。
sessionAffinity: ClientIP
sessionAffinityConfig:
  clientIP:
    timeoutSeconds: 10800
  1. 使用 Ingress 统一管理外部访问:避免为每个服务创建 LoadBalancer。

  2. 配置 TLS 证书:使用 cert-manager 自动管理证书。

tls:
- hosts:
  - example.com
  secretName: tls-secret
  1. 设置健康检查:确保 Service 只路由到健康的 Pod。

  2. 使用命名空间隔离:不同环境使用不同的命名空间。

  3. 监控 Service 和 Ingress:使用 Prometheus 和 Grafana 监控服务性能。

总结

本教程详细介绍了 Kubernetes 中 Service 和 Ingress 的概念、配置和管理。通过实际案例,我们学习了如何创建和管理服务、配置负载均衡以及实现外部访问。掌握这些知识后,可以构建完整的容器化应用网络架构,实现高可用和高性能的服务部署。

« 上一篇 Service 与 Ingress 下一篇 » 性能优化概述