在 Kubernetes
中,一个 Endpoint
代表一个网络地址(IP地址和端口,是实现实际服务的端点的集合,通常用于将服务的客户端请求路由到后端 Pod 的 IP 地址和端口上。
Endpoint
可以手动创建,也可以由 Kubernetes
的 service
控制器自动创建和更新。当创建一个 Service
对象时,Kubernetes
会创建一个关联的 Endpoint
对象,自动添加 Pod
的 I
P 地址和端口到 Endpoint
中。
当客户端通过 Service
访问后端 Pod
时,Kubernetes
会自动将客户端请求路由到后端 Pod
的 IP
地址和端口上。这种路由方式是通过 iptables
实现的,对于一个 Service
的每个端口,Kubernetes
会自动创建一条 iptables
规则将该端口上的请求转发到对应的 Endpoint
地址和端口上。
官方目前推荐使用endpointslice
, 创建一个service
会自动创建一个endpoint
和endpointSlice
.发现如果删除掉endpoint
服务也能正常访问。
可以使用下面的yaml
文件创建Service
观察对应的endpoint
.
1 | cat > ep.yaml <<EOF |
1 | I0503 15:23:44.009583 131717 round_trippers.go:463] POST apis/apps/v1/namespaces/default/deployments?fieldManager=kubectl-create&fieldValidation=Strict |
调用接口分别创建了deployment
和service
,假如关掉kube-controller-manager
的话会发现kubectl get ep
并不能看到对应的Endpoint
,Endpoint
是由kube-controller-manager
创建的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// pkg/apis/discovery/types.go
// Endpoint represents a single logical "backend" implementing a service.
type Endpoint struct {
// addresses of this endpoint. The contents of this field are interpreted
// according to the corresponding EndpointSlice addressType field. Consumers
// must handle different types of addresses in the context of their own
// capabilities. This must contain at least one address but no more than
// 100.
// +listType=set
Addresses []string
// conditions contains information about the current status of the endpoint.
Conditions EndpointConditions
// hostname of this endpoint. This field may be used by consumers of
// endpoints to distinguish endpoints from each other (e.g. in DNS names).
// Multiple endpoints which use the same hostname should be considered
// fungible (e.g. multiple A values in DNS). Must pass DNS Label (RFC 1123)
// validation.
// +optional
Hostname *string
// targetRef is a reference to a Kubernetes object that represents this
// endpoint.
// +optional
TargetRef *api.ObjectReference
// deprecatedTopology is deprecated and only retained for round-trip
// compatibility with v1beta1 Topology field. When v1beta1 is removed, this
// should be removed, too.
// +optional
DeprecatedTopology map[string]string
// nodeName represents the name of the Node hosting this endpoint. This can
// be used to determine endpoints local to a Node.
// +optional
NodeName *string
// zone is the name of the Zone this endpoint exists in.
// +optional
Zone *string
// hints contains information associated with how an endpoint should be
// consumed.
// +featureGate=TopologyAwareHints
// +optional
Hints *EndpointHints
}
// 从代码中可以看该Controller通过Informer机制监听了三种资源
// Service
// Pod
// endpoint
// pkg/controller/endpoint/endpoints_controller.go
// NewEndpointController returns a new *Controller.
func NewEndpointController(podInformer coreinformers.PodInformer, serviceInformer coreinformers.ServiceInformer,
endpointsInformer coreinformers.EndpointsInformer, client clientset.Interface, endpointUpdatesBatchPeriod time.Duration) *Controller {
broadcaster := record.NewBroadcaster()
recorder := broadcaster.NewRecorder(scheme.Scheme, v1.EventSource{Component: "endpoint-controller"})
e := &Controller{
client: client,
queue: workqueue.NewNamedRateLimitingQueue(workqueue.DefaultControllerRateLimiter(), "endpoint"),
workerLoopPeriod: time.Second,
}
// onServiceUpdate,onServiceDelete都是执行入队操作
serviceInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: e.onServiceUpdate,
UpdateFunc: func(old, cur interface{}) {
e.onServiceUpdate(cur)
},
DeleteFunc: e.onServiceDelete,
})
e.serviceLister = serviceInformer.Lister()
e.servicesSynced = serviceInformer.Informer().HasSynced
podInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
AddFunc: e.addPod,
UpdateFunc: e.updatePod,
DeleteFunc: e.deletePod,
})
e.podLister = podInformer.Lister()
e.podsSynced = podInformer.Informer().HasSynced
// e.onEndpointsDelete将key(default/ep)入队
endpointsInformer.Informer().AddEventHandler(cache.ResourceEventHandlerFuncs{
DeleteFunc: e.onEndpointsDelete,
})
e.endpointsLister = endpointsInformer.Lister()
e.endpointsSynced = endpointsInformer.Informer().HasSynced
e.triggerTimeTracker = endpointutil.NewTriggerTimeTracker()
e.eventBroadcaster = broadcaster
e.eventRecorder = recorder
e.endpointUpdatesBatchPeriod = endpointUpdatesBatchPeriod
return e
}
1 | func (e *Controller) processNextWorkItem(ctx context.Context) bool { |