Goer-Docker系列-1-在K8s中实现服务发现

内容分享2小时前发布 LatteYea
0 0 0

在Kubernetes中,服务发现的核心目标是让集群内的Pod(服务实例)能够动态找到并通信,而无需手动管理IP地址(因为Pod的IP是动态变化的)。K8s通过Service资源DNS系统实现了自动化的服务发现,具体机制和实操如下:

一、核心原理:Service + DNS 协同工作

Service资源:为一组具有相同标签的Pod提供固定的访问入口(ClusterIP),并自动维护Pod的动态变化(新增/删除/重启时自动更新关联关系)。DNS解析:通过CoreDNS(K8s默认DNS服务)将Service名称解析为对应的ClusterIP,使得Pod可以通过“Service名称”而非IP访问目标服务。

二、实操步骤:实现服务发现的完整流程

步骤1:部署目标服务(带标签的Pod)

首先需要部署一组提供服务的Pod,并为其添加统一标签(如
app: backend
),以便后续Service通过标签关联它们。

示例:部署一个简单的后端服务(用nginx模拟):


# backend-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: backend
spec:
  replicas: 3  # 3个副本,模拟服务集群
  selector:
    matchLabels:
      app: backend  # 标签选择器
  template:
    metadata:
      labels:
        app: backend  # Pod标签,与Service关联
    spec:
      containers:
      - name: backend
        image: nginx:1.25
        ports:
        - containerPort: 80  # 容器暴露的端口

部署并验证:


kubectl apply -f backend-deployment.yaml
kubectl get pods -l app=backend  # 查看3个Pod是否运行(IP会动态变化)

步骤2:创建Service关联Pod

通过Service为上述Pod分配固定访问地址(ClusterIP),并通过标签选择器与Pod绑定。

示例:创建ClusterIP类型的Service(仅集群内部可访问):


# backend-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-service  # Service名称(后续用于DNS解析)
spec:
  selector:
    app: backend  # 匹配标签为app=backend的Pod
  ports:
  - port: 8080        # Service暴露的端口(集群内访问时用)
    targetPort: 80    # 转发到Pod的端口(需与Pod的containerPort一致)
  type: ClusterIP     # 默认类型,仅集群内部可见

创建并验证:


kubectl apply -f backend-service.yaml
kubectl get service backend-service  # 查看Service的ClusterIP(如10.96.xx.xx)

此时,Service会自动关联所有
app=backend
的Pod,并维护一个Endpoint列表(记录Pod的IP和端口):


kubectl describe service backend-service | grep Endpoints  # 查看关联的Pod地址

步骤3:通过Service名称实现服务发现

其他Pod(如前端服务)可以直接通过“Service名称”访问后端服务,无需关心具体Pod的IP。

示例:部署一个前端Pod,验证能否访问后端服务:


# frontend-pod.yaml
apiVersion: v1
kind: Pod
metadata:
  name: frontend
spec:
  containers:
  - name: frontend
    image: busybox:1.35
    command: ["sh", "-c", "sleep 3600"]  # 保持Pod运行

部署后,进入前端Pod内部测试访问:


kubectl apply -f frontend-pod.yaml
kubectl exec -it frontend -- sh  # 进入前端Pod

# 在前端Pod内部,通过Service名称访问后端服务
wget -qO- backend-service:8080  # 成功返回nginx首页,说明服务发现生效

原理:CoreDNS会将
backend-service
解析为其ClusterIP,且解析记录会自动更新(当Service的ClusterIP变化时)。

步骤4:跨命名空间的服务发现

如果服务部署在不同命名空间,访问时需要加上命名空间后缀:
服务名称.命名空间.svc.cluster.local
(完整域名)。

示例:假设后端服务在
backend-ns
命名空间,前端Pod在
frontend-ns
,则访问方式为:


# 在前端Pod内部
wget -qO- backend-service.backend-ns:8080  # 简化写法(省略.svc.cluster.local)

三、特殊场景:无头服务(Headless Service)

对于有状态应用(如数据库集群、分布式系统),需要直接访问具体Pod(而非通过Service的ClusterIP负载均衡),此时可使用无头服务(不分配ClusterIP,DNS直接返回Pod的IP列表)。

示例:创建无头服务:


# headless-service.yaml
apiVersion: v1
kind: Service
metadata:
  name: backend-headless
spec:
  selector:
    app: backend
  ports:
  - port: 8080
    targetPort: 80
  clusterIP: None  # 关键:设置为None即无头服务

部署后,解析服务名称会返回所有关联Pod的IP:


# 在前端Pod内部执行DNS解析
nslookup backend-headless  # 返回3个Pod的IP(因replicas=3)

四、核心组件与排查

CoreDNS:确保CoreDNS正常运行,否则无法解析Service名称:


kubectl get pods -n kube-system | grep coredns  # 检查CoreDNS Pod状态

Service与Pod关联:若服务发现失败,先检查Service的标签选择器是否与Pod标签匹配:


kubectl describe service backend-service | grep Selector  # 查看选择器
kubectl get pods --show-labels | grep backend  # 查看Pod标签

Endpoint状态:若Service关联的Endpoint为空,说明标签匹配失败:


kubectl get endpoints backend-service  # 正常应显示Pod的IP和端口

总结

K8s服务发现的核心是:

Service为动态Pod提供固定访问点;用CoreDNS将Service名称解析为网络地址;通过标签选择器自动维护Service与Pod的关联。

无论是集群内、跨命名空间,还是有状态应用,都可以通过上述机制实现高效的服务发现。

© 版权声明

相关文章

暂无评论

none
暂无评论...