K8S 服务发现-叩丁狼

3.3 服务发现

3.3.1 Service <东西流量 : 服务内部>

在学习service前,先说说为什么需要service,核心原因是pod的问题

  1. 动态 IP:Pod 的 IP 地址不是固定的。当 Pod 重启、迁移或扩缩容时,IP 会变化。
  2. 多个副本:一个 Deployment 可能有多个 Pod 副本,每个都有不同的 IP。
  3. 健康检查:如何知道哪个 Pod 是健康的,可以接收流量?

如果没有service,每次 Pod 变化,你都需要手动更新所有依赖它的应用配置,这在动态的 Kubernetes 环境中完全不可行。

Service作用:

  1. 稳定的虚拟 IP(ClusterIP):客户端只需要记住这个 IP
  2. 负载均衡:将请求均匀分发到后端的健康 Pod
  3. 服务发现:通过 DNS 名称访问服务
  4. 会话保持:可选地将同一客户端的请求转发到同一 Pod
3.3.1.1 Service 工作原理
  1. Service 的整体结构 : 本身不转发流量,他只是规则的制定者,真正干活的是节点上的网络组件
3.3.1.2 核心组件
  • kube-proxy : 流量的实际的指挥者

    • 主要有 iptables 模式, ipvs 模式, userspace 模式(已被废弃)
    • 不是传统意义上的代理,不直接转发数据包,核心工作是:
  • endpoints 控制器 ; Pod 的追踪器

    • kubectl get endpoints my-service -o yaml # 查看 Service 的 Endpoints

    • 编写 Service 配置文件时,不指定 Selecter 属性,不会创建默认的 endPoints

      复制代码
      # 输出示例:如果 `endpoints` 输出为空,说明没有符合 `Pod` 的 `Service` 的 `Selecter`
      
      apiVersion: v1
      kind: Endpoints
      metadata:
        name: my-service # 与 SVC 一致
        namespace: default # 与 SVC 一致
      subsets:
      - addresses:
        - ip: 10.244.1.10
          nodeName: node1
          targetRef:
            kind: Pod
            name: web-pod-1
        - ip: 10.244.1.11
          nodeName: node1
          targetRef:
            kind: Pod
            name: web-pod-2
        ports:
        - port: 8080
          protocol: TCP
  • coreDNS : 服务的电话本 : coreDNS 为 Service 提供 DNS 解析

    • 复制代码
      # 在 Pod 中测试 DNS
      kubectl run -it --rm --image=busybox dns-test -- /bin/sh
      
      # 查询完整域名
      nslookup my-service.default.svc.cluster.local
      
      # 查询同一命名空间内的服务(简写)
      nslookup my-service
      
      # 查询不同命名空间
      nslookup my-service.other-namespace
      
      # 对于 Headless Service(clusterIP: None)
      nslookup headless-service
      # 返回所有 Pod IP,而不是 Service IP
3.3.1.3 Service 类型
  1. ClusterIP : 集群内部服务IP,只能在内部使用,默认

示例 : 指定为 ClusterIP

复制代码
apiVersion: v1
kind: Service
metadata:
  name: backend-api
spec:
  type: ClusterIP  # 可省略,默认就是 ClusterIP
  selector:
    app: backend
  ports:
  - port: 80        # Service 对外的端口
    targetPort: 8080 # Pod 监听的端口
    protocol: TCP	
    
%% 可以通过下面方式访问 %%
# 方式1:使用 DNS 名称(推荐)
# 在同一命名空间内
curl http://backend-api
# 在不同命名空间
curl http://backend-api.dev.svc.cluster.local

# 方式2:使用 ClusterIP
# 先获取 ClusterIP
kubectl get svc backend-api
# NAME          TYPE        CLUSTER-IP      PORT(S)
# backend-api   ClusterIP   10.96.123.456   80/TCP
curl http://10.96.123.456
场景 说明 示例
微服务间通信 服务之间内部调用 前端调用用户服务
数据库访问 应用访问数据库 Web应用访问 MySQL
内部API 不对外暴露的API 监控API、管理API
缓存访问 访问Redis/Memcached 应用访问Redis缓存
  1. ExternalName : ExternalName 是一种特殊的 Service,它没有 selector,也不创建 Endpoints,而是返回一个 DNS CNAME 记录,将 Service 名称重定向到外部域名。

示例 : ExternalName

复制代码
	apiVersion: v1
	kind: Service
	metadata:
	  name: external-database
	spec:
	  type: ExternalName
	  externalName: database.company.com  # 外部服务地址
	  
	  
	集群内部访问: http://external-database.default.svc
        ↓
	DNS 解析时返回 CNAME 记录
	        ↓
	实际解析到: database.company.com
	        ↓
	访问外部服务
场景 说明 示例
访问外部数据库 迁移过程中访问云数据库 AWS RDS, Cloud SQL
第三方API 访问外部 SaaS 服务 Stripe, SendGrid API
混合云架构 访问本地数据中心服务 本地 Oracle 数据库
逐步迁移 从外部服务迁移到内部 临时重定向
  1. NodePort : 节点端口服务,在每一个节点打开一个固定端口(30000~32767),外部可以通过任意节点的 IP:NodePort 访问服务

示例:指定为 NodePort

复制代码
	apiVersion: v1
	kind: Service
	metadata:
	  name: web-app
	spec:
	  type: NodePort
	  %% nodeport可以指定流量路径:
		  - Cluster:流量可能跨节点,丢失真实客户端IP 
		  - Local:保留客户端IP,但要求节点上有 Pod(否则连接失败)
	  %%
	  externalTrafficPolicy: Local # 或者Cluster(默认的流量路径是cluster)
	  selector:
	    app: web
	  ports:
	  - port: 80          # Service 端口(集群内部用)
	    targetPort: 8080  # Pod 端口
	    nodePort: 31080   # 节点端口(可选,不指定则随机分配)
	    

	    
	# 1. 查看分配的 NodePort
	kubectl get svc web-app
	# NAME      TYPE       CLUSTER-IP      EXTERNAL-IP   PORT(S)
	# web-app   NodePort   10.96.123.456   <none>        80:31080/TCP
	#                               ↑节点端口
	
	# 2. 通过节点IP访问(假设节点IP是 192.168.1.100)
	curl http://192.168.1.100:31080
	curl http://192.168.1.101:31080  # 另一个节点也可以
场景 说明 优点 缺点
开发测试 快速验证服务 简单,无需额外配置 端口范围有限
演示环境 给客户演示 直接访问,无需域名 需要知道节点IP
没有云负载均衡器 本地/裸机集群 不依赖云服务 需要外部负载均衡
临时外部访问 临时暴露服务 快速启用 生产环境不推荐
  1. LoadBalancer : LoadBalancer 是 NodePort 的升级版,它会自动创建云厂商的负载均衡器(如 AWS ELB、GCP Load Balancer、Azure LB),并提供外部 IP 或 DNS 名称。

3.3.2 Ingress <南北流量>

3.3.2.1 Ingress Controller

ngress Controller 是负责处理 Ingress 请求的组件。

Kubernetes 提供了多种 Ingress Controller,可以根据需要选择。以下是常用的 Ingress Controller:

  • Nginx Ingress Controller:基于 Nginx 的 Ingress Controller,功能强大,易于配置。
  • HAProxy Ingress Controller:基于 HAProxy 的 Ingress Controller,性能优异,适用于高并发场景。
  • Contour Ingress Controller:基于 Envoy 的 Ingress Controller,功能丰富,适用于多云场景。

常规来说,我们一般使用nginx ingress, 先下载对应yaml文件 - [[https://gitee.com/mirrors/ingress-nginx\](https://gitee.com/mirrors/ingress-nginx\)]

对于大多数国内用户,如果你的Kubernetes集群是搭建在:

  • 阿里云、腾讯云、华为云等公有云上 → 应选择 cloud 目录下的 deploy.yaml

  • 公司内部机房或家用服务器上 → 应选择 baremetal 目录下的 deploy.yaml

    替换镜像

    将文件中的 registry.k8s.io 镜像替换为国内源

    使用sed命令一键替换(推荐)

    sed -i 's|registry.k8s.io/ingress-nginx/|registry.aliyuncs.com/google_containers/|g' deploy.yaml

    修改

    hostNetwork : true
    dnsPolicy : ClusterFirstWithHostwork
    kind : DeamonSet
    nodeSelecter
    ingress : "true" # 增加选择器
    admissionWebhooks
    enabled : "false" # 关闭证书校验
    Service
    type : ClusterIP # 从云服务改成内部

    部署

    kubectl apply -f deploy.yaml

3.3.2.2 创建 Ingress 规则

定义了外部访问的路由规则,以下是一个将特定域名流量转发到上面创建的 nginx-service 的示例

复制代码
apiVersion: networking.k8s.io/v1  # Kubernetes API版本,v1是当前稳定版本
kind: Ingress                     # 资源类型:Ingress
metadata:
  name: example-ingress          # Ingress资源的名称,在命名空间中必须唯一
spec:
  rules:
  - host: "demo.yourdomain.com"  # 规则1:基于域名的虚拟主机
  # - host: "api.yourdomain.com" # 规则2:可以添加多个规则
  http:
  paths:
  - pathType: Prefix # 前缀匹配
    path: "/"
    backend:
      service:
        name: nginx-service # # Service资源名称,必须在同一命名空间
        port:
          number: 80 # # Service端口(或使用 name: "http" 引用端口名称)

pathType - 路径匹配模式(v1 API 关键字段):

类型 匹配规则 示例 path: "/api" 优先级
Exact 精确匹配,区分大小写 匹配 /api,不匹配 /api//api/v1
Prefix 前缀匹配,按路径元素分隔 匹配 /api/api/v1,不匹配 /apis
ImplementationSpecific 由 Ingress Controller 决定 取决于实现,通常同 Prefix
相关推荐
IMPYLH2 小时前
Linux 的 dd 命令
linux·运维·服务器
minji...2 小时前
Linux 进程间通信(一)进程间通信与匿名管道
linux·运维·服务器·数据结构·数据库·c++
feng_you_ying_li2 小时前
linux的指令终章与权限之用户权限(3)
linux·运维·服务器
s6516654962 小时前
Linux内核学习-汇编笔记
linux
IMPYLH2 小时前
Linux 的 csplit 命令
linux·运维·服务器·数据库
sleP4o2 小时前
[Docker] ‘s Basic Usage
docker·容器·eureka
钰衡大师2 小时前
Nohup 使用技术文档
linux·服务器·运维开发·unix
一直都在5722 小时前
K8s详解
云原生·容器·kubernetes
Sakuyu434682 小时前
zabbix源码安装
linux·运维·zabbix