Kubernetes Service 与 Ingress 知识总结

一、理解标签与 Service 中的 Endpoint

**核心概念:**Service 通过标签选择器(Selector)匹配后端 Pod,被匹配到的 Pod 会出现在 Service 的 Endpoints 列表中,从而被暴露。

1. 建立 Service

使用命令生成 Service 的 YAML 模板,并修改为指定选择器:

bash 复制代码
kubectl create service clusterip --tcp 80:80 testservice --dry-run=client -o yaml >> testservice.yaml
yaml 复制代码
apiVersion: v1
kind: Service
metadata:
  labels:
    app: testservice
  name: testservice
spec:
  ports:
  - name: webport
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: webserver
  type: ClusterIP
bash 复制代码
kubectl apply -f testservice.yaml

2. 标签匹配决定 Pod 是否被暴露

**关键结论:**当 Pod 的标签与 Service 选择器上的标签不一致时,Pod 不会被暴露,Endpoints 为空。

bash 复制代码
kubectl run webserver --image myapp:v1 --dry-run=client -o yaml > webserver.yml
yaml 复制代码
kind: Pod
metadata:
  labels:
    run: webserver
  name: webserver
spec:
  containers:
  - image: myapp:v1
    name: webserver

此时 Service 的 Endpoints 为空,因为 Pod 标签是 run=webserver,而 Service 选择器是 app=webserver

修改标签后即可被暴露:

bash 复制代码
kubectl label pods webserver app=webserver
curl 10.100.62.227
# 输出:Hello MyApp | Version: v1 | Pod Name

此时 Endpoints 显示为 10.244.2.7:80

二、利用 Service 暴露控制器(Deployment)

**核心概念:**Service 可以关联 Deployment 管理的 Pod,实现负载均衡和自动调度。

1. 生成控制器和 Service 的组合 YAML

bash 复制代码
kubectl create service clusterip --tcp 80:80 webservice --dry-run=client -o yaml >> webservice.yaml
kubectl create deployment webcluster --image myapp:v1 --dry-run=client -o yaml >> webservice.yaml
yaml 复制代码
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: webservice
  name: webservice
spec:
  ports:
  - name: webport
    port: 80
    protocol: TCP
    targetPort: 80
  selector:
    app: webcluster
  type: ClusterIP
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: webcluster
name: webcluster
spec:
replicas: 2
selector:
matchLabels:
app: webcluster
template:
metadata:
labels:
app: webcluster
spec:
containers:
- image: myapp:v1
name: myapp

2. 验证负载均衡

bash 复制代码
kubectl apply -f webservice.yaml
curl 10.98.31.55/hostname.html
# 多次访问会轮询到不同 Pod

Endpoints 显示两个后端:10.244.2.8:80,10.244.5.95:80,多次访问会轮询到不同 Pod。

三、Service 的 IPVS 模式

**核心概念:**kube-proxy 支持 IPVS 模式,相比 iptables 模式性能更高,支持更多调度算法。

1. 安装 ipvsadm 工具

bash 复制代码
for name in 100 10 20 200
do
  ssh -l root 172.25.254.$name "dnf install ipvsadm -y"
done

2. 配置 kube-proxy 使用 IPVS 模式

bash 复制代码
kubectl -n kube-system edit cm kube-proxy
# 将 mode 改为 "ipvs"
kubectl -n kube-system delete pods kube-proxy-6kp78 kube-proxy-hvk7k kube-proxy-p7fdf kube-proxy-tb29j

3. 验证效果

bash 复制代码
ipvsadm -Ln
# 可以看到 Service 的 VIP 和对应的后端 Pod

IPVS 模式下,每个 Service 的 VIP 会出现在 ipvsadm -Ln 输出中,并显示对应的后端 Pod 地址。

四、Service 的 ClusterIP 类型

1. ClusterIP 基本模式

**核心概念:**ClusterIP 是 Service 的默认类型,提供一个集群内部虚拟 IP(VIP),通过该 IP 可以访问后端 Pod。

bash 复制代码
kubectl describe svc webservice
# IP: 10.109.112.7(VIP,访问此 IP 可进行调度)

2. 集群内部 DNS 解析

核心概念: 集群内部通过 CoreDNS 解析 Service 名称,格式为 <servicename>.<namespace>.svc.cluster.local

bash 复制代码
dig webservice.default.svc.cluster.local @10.96.0.10
# 返回 Service 的 VIP:10.109.112.7

**重要结论:**集群内部通常使用 Service 的解析名称进行通信,因为资源的 IP 会变但名字不会变。

3. ClusterIP 的 Headless 模式

核心概念: 设置 clusterIP: None 后,Service 不会被分配 VIP,而是直接把 Endpoints 的 IP 通过 DNS 暴露。

yaml 复制代码
spec:
  clusterIP: None
bash 复制代码
kubectl describe svc webservice
# IP: None(没有 VIP)
dig webservice.default.svc.cluster.local @10.96.0.10
直接返回后端 Pod 的 IP:10.244.5.99 和 10.244.2.15

五、Service 的 NodePort 模式

**核心概念:**NodePort 模式在 ClusterIP 基础上,在每个节点上开放一个端口(30000-32767),实现集群外部访问。

1. 生成 NodePort Service

yaml 复制代码
spec:
  ports:
  - name: webport
    port: 80
    protocol: TCP
    targetPort: 80
    nodePort: 30951
  selector:
    app: webcluster
  type: NodePort

2. 查看 IPVS 策略

bash 复制代码
ipvsadm -Ln
# 可以看到节点 IP:30951 映射到后端 Pod

3. 外部访问

bash 复制代码
curl 172.25.254.100:30951/hostname.html

六、Ingress 概述

**核心概念:**Ingress 是 Kubernetes 的 API 对象,用于管理集群外部访问集群内服务的 HTTP 和 HTTPS 路由,提供基于域名、路径的转发规则。

1. 基于路径的访问

yaml 复制代码
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress1
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - host: 'www.timinglee.org'
    http:
      paths:
      - backend:
          service:
            name: servicev1
            port:
              number: 80
        path: /v1
        pathType: Prefix
      - backend:
          service:
            name: servicev2
            port:
              number: 80
        path: /v2
        pathType: Prefix
bash 复制代码
curl www.timinglee.org/v1
# Hello MyApp | Version: v1
curl www.timinglee.org/v2
# Hello MyApp | Version: v2

2. 基于域名的访问

yaml 复制代码
spec:
  rules:
  - host: myapp1.timinglee.org
    http:
      paths:
      - backend:
          service:
            name: servicev1
            port:
              number: 80
        path: /
        pathType: Prefix
  - host: myapp2.timinglee.org
    http:
      paths:
      - backend:
          service:
            name: servicev2
            port:
              number: 80
        path: /
        pathType: Prefix
bash 复制代码
curl myapp1.timinglee.org
# Hello MyApp | Version: v1
curl myapp2.timinglee.org
# Hello MyApp | Version: v2

3. 基于动静分离的方式

yaml 复制代码
metadata:
  annotations:
    nginx.ingress.kubernetes.io/use-regex: "true"
    nginx.ingress.kubernetes.io/rewrite-target: /index.html
spec:
  rules:
  - host: www.timinglee.org
    http:
      paths:
      - backend:
          service:
            name: servicev1
            port:
              number: 80
        path: /php
        pathType: ImplementationSpecific
      - backend:
          service:
            name: servicev2
            port:
              number: 80
        path: /static
        pathType: ImplementationSpecific
bash 复制代码
curl www.timinglee.org/php/
# Hello MyApp | Version: v1
curl www.timinglee.org/static/
# Hello MyApp | Version: v2

4. TLS 加密访问

bash 复制代码
openssl req -newkey rsa:2048 -nodes -keyout tls.key -x509 -days 365 -subj "/CN=nginxsvc/O=nginxsvc" -out tls.crt
kubectl create secret tls web-tls-secret --key tls.key --cert tls.crt
yaml 复制代码
spec:
  tls:
  - hosts:
    - myapp-tls.timinglee.org
    secretName: web-tls-secret
  rules:
  - host: myapp-tls.timinglee.org
    http:
      paths:
      - backend:
          service:
            name: servicev1
            port:
              number: 80
        path: /
        pathType: Prefix
bash 复制代码
curl -k https://myapp-tls.timinglee.org
# Hello MyApp | Version: v1

5. Auth 认证

**步骤:**安装 httpd-tools 生成认证文件,创建 Secret,在 Ingress 中配置认证注解。

bash 复制代码
dnf install httpd-tools -y
htpasswd -cm auth admin
kubectl create secret generic web-auth --from-file auth
yaml 复制代码
metadata:
  annotations:
    nginx.ingress.kubernetes.io/auth-type: basic
    nginx.ingress.kubernetes.io/auth-secret: web-auth
    nginx.ingress.kubernetes.io/auth-realm: "Please input username and password"
bash 复制代码
curl www.timinglee.org/v1
# 401 Authorization Required
curl www.timinglee.org/v1 -uadmin:lee
# Hello MyApp | Version: v1

6. Ingress 中的网页重写

利用 app-root 定义默认发布文件:

yaml 复制代码
metadata:
  annotations:
    nginx.ingress.kubernetes.io/app-root: /hostname.html
bash 复制代码
curl -I www.timinglee.org
# 302 重定向到 /hostname.html

利用正则表达式重定向网页:

yaml 复制代码
metadata:
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /$2
    nginx.ingress.kubernetes.io/use-regex: "true"
spec:
  rules:
  - host: www.timinglee.org
    http:
      paths:
      - backend:
          service:
            name: servicev1
            port:
              number: 80
        path: /
        pathType: Prefix
      - backend:
          service:
            name: servicev2
            port:
              number: 80
        path: /lee(/*.*/*|$)(.*)
        pathType: ImplementationSpecific
bash 复制代码
curl -L www.timinglee.org
# Hello MyApp | Version: v1
curl -L www.timinglee.org/lee
# Hello MyApp | Version: v2

七、金丝雀发布(Canary)

**核心概念:**金丝雀发布(灰度发布)允许将部分流量引导到新版本,验证稳定后再全量发布。

1. 基于 Header 的灰度发布

yaml 复制代码
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress2
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-by-header: "version"
    nginx.ingress.kubernetes.io/canary-by-header-value: "2"
spec:
  ingressClassName: nginx
  rules:
  - host: www.timinglee.org
    http:
      paths:
      - backend:
          service:
            name: servicev2
            port:
              number: 80
        path: /
        pathType: Prefix
bash 复制代码
curl www.timinglee.org
# Hello MyApp | Version: v1(默认走 v1)
curl -H "version:2" www.timinglee.org
# Hello MyApp | Version: v2(带指定 Header 走 v2)

2. 基于权重的灰度发布

yaml 复制代码
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress2
  annotations:
    nginx.ingress.kubernetes.io/canary: "true"
    nginx.ingress.kubernetes.io/canary-weight: "10"
    nginx.ingress.kubernetes.io/canary-weight-total: "100"
spec:
  ingressClassName: nginx
  rules:
  - host: www.timinglee.org
    http:
      paths:
      - backend:
          service:
            name: servicev2
            port:
              number: 80
        path: /
        pathType: Prefix
bash 复制代码
# 验证脚本:100 次请求统计 v1/v2 比例
sh check_cannary.sh
# 输出示例:v1:95, v2:5(约 10% 流量到 v2)

八、总结

核心要点回顾:

  • 标签与 Endpoint:Service 通过标签选择器匹配 Pod,标签不一致则 Pod 不会被暴露,Endpoints 为空;标签一致后 Pod 才会被纳入 Endpoints 并对外提供服务。
  • Service 类型:ClusterIP(集群内部访问)、NodePort(节点端口外部访问)、Headless(无 VIP,DNS 直连 Pod)。
  • IPVS 模式 :kube-proxy 切换为 IPVS 后性能更高,每个 Service 的 VIP 会出现在 ipvsadm -Ln 中,并映射到对应后端 Pod。
  • 集群内 DNS 解析 :格式为 <servicename>.<namespace>.svc.cluster.local,集群内部通信优先使用 Service 名称,因为 IP 会变而名字不会变。
  • Ingress 路由:支持基于路径、基于域名、动静分离、TLS 加密、Auth 认证以及网页重写等多种转发方式,统一管理集群外部访问。
  • 金丝雀发布:通过 Header 或权重将部分流量引导到新版本,验证稳定后再全量发布,降低上线风险。

**实践建议:**生产环境中建议优先使用 Deployment 管理 Pod 并结合 Service 暴露,外部流量统一通过 Ingress 按域名或路径转发;灰度发布时先以 Header 方式小范围验证,再逐步调整权重直至全量切换。

相关推荐
滕州市燕猫虎计算机科技工作室个体工商户4 小时前
查看Docker里的日志
运维·docker·容器
JavaPub-rodert4 小时前
Docker Compose 实战:一键部署你的完整应用环境
运维·docker·容器
IT利刃出鞘16 小时前
Docker Compose--安装WordPress--方法/示例
运维·docker·容器
分布式存储与RustFS21 小时前
RustFS 多协议接入全景:S3 之外,Swift/Keystone 与 SFTP/FTPS 怎么选
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
分布式存储与RustFS1 天前
在 Kubernetes 上用 RustFS Operator 给 Tenant 开 KMS 加密:spec.encryption 实战
云原生·开源·对象存储·分布式存储·s3·rustfs·性能基准
wdfk_prog1 天前
大型 Docker 镜像导出导入工程化:可靠性、磁盘与压缩
运维·docker·容器
郝开1 天前
Docker Compose 模块化多环境配置规范指南:示例搭建Alf Tengine MD2DOC 1.1.1
运维·docker·容器
Albart5751 天前
Docker Desktop 增量更新失败终极排查:Failed to apply delta update 反复回滚怎么办?
windows·docker·容器·docker部署大模型
sibylyue1 天前
【云原生系列3】Docker Compose单机多容器编排工具
运维·docker·容器