github.com/jingruilea/kubeedge@v1.2.0-beta.0.0.20200410162146-4bb8902b3879/docs/proposals/edgemesh-design.md (about) 1 --- 2 title: EdgeMesh Design 3 status: implementable 4 authors: 5 - "@qizha" 6 - "@sids-b" 7 approvers: 8 - "@kevin-wangzefeng" 9 - "@CindyXing" 10 creation-date: 2019-03-20 11 last-updated: 2019-03-27 12 --- 13 14 # Edge Mesh on edge 15 16 ## Abstract 17 To support service mesh capabilities on edge to support microservice communication cross cloud and edge. 18 The service discovery, communication should be considered in this feature. 19 Developers can define services on top of the deployments deployed on the cloud or edges in a unified manner without caring about their location. The service name is the only thing they need to know to do the communication. For example, the following address can be used for a REST request: 20 `http://{service_name}/resources` 21 22 ## Motivation 23 The cloud native and microservice architecture is becoming more and more popular and the edge node is becoming more and more powerful. The user want to decompose their application into multiple microservices. Some of those microservices need to be deployed in edge node to get close to the data generated by devices. By simplify the development, the user need to use the same mechanism to do the service discovery and communication with what they are doing on cloud. 24 25 ## Constraints and Assumptions 26 1. No DNS services available for edge. 27 2. The identification and authentication should be handled by microservices. 28 3. When service communication between edge to edge, they may work offline. With the purpose to deliver a "expected result" to the user system, the service definition should be push down to the edge right after the definition operation. That is to say, the istio model may not be suitable for edge, in istio model, the service definition is pull from K8S master when the service is invoked. 29 4. Only support HTTP communication in the first step 30 5. All edge nodes are in the same sub-network and they have the network reachability. 31 32 ## Use cases 33 <img src="../images/proposals/service-design.png"> 34 35 ### Register the service located on cloud 36 * CS0.1: User create service(type ClusterIP) in K8S API Server 37 * CS0.2: ServiceController get the service definition and create router rules with the edge ServiceBus as source and service clusterIP as target. 38 * CS0.3: Send the service definition to edge 39 40 ### Register the service located on edge 41 * CS1: User create service(headless service without ClusterIP) in K8S API Server 42 * CS2, CS3: ServiceController get the service definition and update the service ClusterIP to itself. Then create router rule with the EC(Router) address as the source and edge ServiceBus as target. 43 * CS4: Send the service definition to edge 44 45 ### Service discovery on cloud 46 * Application access service with the same mechanism no matter it located on cloud or edge 47 48 ### Service discovery on edge 49 * Use iptables to redirect inbound and outbound traffic to the EdgeHub/ServiceBus. Then do service discovery in EdgeHub/ServiceBus by pick up the right POD from the service definition. The idea is similar with what istio is doing in the init_container: https://github.com/istio/istio/blob/master/tools/packaging/common/istio-iptables.sh 50 51 ### Service communication from cloud to edge 52 * ESD1: Application on cloud visit service with clusterIP and request goes to EC(refer to step CS2, CS3) 53 * ESD2: Router find out the PODs in this service and pick one with some kind of load balance mechanism. Then send the request to the choosen edge with the router rule set in CS3. 54 * ESD3: EdgeHub/ServiceBus get the request and redirect to the POD 55 56 ### Service communication between edges 57 * ESR1: Application send the request to ServiceBus(refer to the "Service discovery on edge") 58 * ESR2: ServiceBus pick one POD in this service with some kind of load balance mechanism. If the target is in the same node, just forward the request. If not, edgehub wrapper the request and send to the target. 59 * ESR3: EdgeHub open the wrapped package and forward to the POD 60 61 ### Service communication from edge to cloud 62 * ESU1: Application send the request to ServiceBus(refer to the "Service discovery on edge") 63 * ESU2: ServiceBus pick one POD in this service with some kind of load balance mechanism. The target is on cloud, EdgeHub send the request to cloud. 64 * ESU3: Router send the request to the corresponding POD on cloud following the rule created in CS0.2 65 66 ## Proposal Changes 67 ### Add servicebus on Edge to handle request proxy 68 ServiceBus is in the same process with EdgeHub as a module 69 70 ### Router 71 Add two endpoints definition: 72 73 |Endpoint|Type|Capability| 74 |---|---|---| 75 |ClusterIP|Target|Request Forward| 76 |ServiceBus|Source|Request Forward, Service Discovery, Load Balance| 77 |ServiceBus|Target|Request Forward| 78 |Router|Source|Request Forward, Service Discovery, Load Balance| 79 80 <img src="../images/proposals/router-design.png"> 81 82 * R1: ServiceController(SC) watches on k8s apiserver for Services/Endpoints. 83 * R2: SC get the service definition and create router rule definition and save in DB(ETCD). 84 * R3: Router gets the rule definition from DB and initializes the listeners/handlers for source and target. 85 * R4: Users/Applications create a request. 86 * R5: Router receives the request and forwards it to the target based on rule. 87 88 Since Router fetches rules from DB, in later versions it can be started as a different process than edge-controller. Also it enables router to retrieve all the rules after process restarts. 89 ### Router Low-level Design 90 91 ### Providers 92 Providers are plugins to reach a service running on edge or on cloud. For example (ServiceBus, EventBus running in edgecore) 93 Providers can be classified into two types 94 1) Source 95 2) Target 96 97 In Alpha only ServiceBus, REST and EventBus providers will be supported. 98 99 Providers in router work in following way. 100 101 <img src="../images/proposals/router-flow.png"> 102 103 1) Router rule is added by SC say REST as source and ServiceBus at edge as target. 104 2) Router receives the rule and registers a listener in the source which is REST in this case. 105 3) REST provider starts listening on the path mentioned in the SourceResource of the rule. 106 for eg: http://${rest_endpoint}:${rest_endpoint_port}/${node_id}${path of rule.source_resource} 107 4) 4.1 User/App make a request to the endpoint in 3. 108 109 4.2 REST provider forwards the request to ServiceBus provider. 110 5) 5.1 ServiceBus provider then creates a beehive message and sends it to CloudHub. 111 112 5.2 CloudHub then forwards the message to edgeHub. 113 114 5.3 EdgeHub send the message to ServiceBus module. 115 6) 6.1 ServiceBus at edge receives the message, makes the http request to applications running at edge. 116 117 6.2 Receives the response back from the application. 118 7) 7.1 ServiceBus at Edge sends the response in beehive message back to EdgeHub. 119 120 7.2 EdgeHub forwards the message to CloudHub. 121 122 7.3 CloudHub sends the message back to router. 123 124 7.4 The message is then converted to http response and sent to the user/application which made the request in step 4.1 125 126 ### Source Interfaces 127 128 Each provider that wants to register as a Source should implement following interfaces. 129 130 ```go 131 type Source interface { 132 // Name Returns name of the provider 133 Name() string 134 // RegisterListener is used to register listener for a rule with this source type 135 RegisterListener(rule model.Rule, res model.Map, handler func(interface{})) error 136 // UnregisterListener is used to unregister a listener when rule is deleted 137 UnregisterListener(rule model.Rule, res map[string]interface{}) 138 // Callback is function for sending response/ACK if required for a request 139 Callback(map[string]interface{}) 140 } 141 ``` 142 143 ```go 144 type SourceFactory interface { 145 // Type returns type of the source 146 Type() string 147 // GetSource returns Source implementation 148 GetSource(ep *model.Endpoint) Source 149 } 150 ``` 151 152 ### Target Interfaces 153 154 Each provider that wants to register as a Target should implement following interfaces. 155 156 ```go 157 type Target interface { 158 // Name returns name of the provider 159 Name() string 160 // Forward is used to forward the request to target 161 Forward(map[string]interface{}, interface{}, func(map[string]interface{})) error 162 } 163 ``` 164 165 ```go 166 type TargetFactory interface { 167 // Type returns type of the target 168 Type() string 169 // GetTarget returns Target implementation 170 GetTarget(ep *model.Endpoint) Target 171 } 172 ``` 173 174 ### Rule Definition 175 176 ```go 177 // Rule define message translate from Endpoint to Endpoint 178 type Rule struct { 179 // ID is unique id of rule 180 ID string `orm:"column(id); size(36); pk" json:"id" yaml:"id"` 181 // Name is the name of the Rule 182 Name string `orm:"column(name); size(64)" json:"name" yaml:"name"` 183 // ProjectID can be used to differentiate rules across projects 184 ProjectID string `orm:"column(project_id); size(36); index" json:"project_id" yaml:"project_id"` 185 // DomainID is the domain from where the source is accessed 186 DomainID string `orm:"column(domain_id); size(36); index" json:"domain_id" yaml:"domain_id"` 187 // Source is the source Endpoint 188 Source *Endpoint `orm:"column(source); rel(fk)" json:"source" yaml:"source"` 189 // SourceResource is a map used to store resources required for source 190 SourceResource Map `orm:"column(source_resource); size(1024)" json:"source_resource" yaml:"source_resource"` 191 // Target is target endpoint 192 Target *Endpoint `orm:"column(target); rel(fk)" json:"target" yaml:"target"` 193 // TargetResource is a map used to store resources required for target 194 TargetResource Map `orm:"column(target_resource); size(1024)" json:"target_resource" yaml:"target_resource"` 195 // InUse is flag to check if rule is in use 196 InUse bool `orm:"column(in_use); default(true)" json:"in_use" yaml:"in_use"` 197 // IsDeleted is flag to check if rule is deleted 198 IsDeleted bool `orm:"column(is_deleted); default(false)" json:"is_deleted" ` 199 // CreatedAt is rule creation timestamp 200 CreatedAt time.Time `orm:"column(created_at); auto_now_add; type(datetime)" json:"created_at" ` 201 // UpdatedAt is last rule updation timestamp 202 UpdatedAt time.Time `orm:"column(updated_at); auto_now; type(datetime)" json:"updated_at" ` 203 // SuccessMessages is the number of success messages for this rule 204 SuccessMessages uint64 `orm:"column(success_messages); default(0)" json:"success_messages" ` 205 // FailMessages in the number of fail messages for this rule 206 FailMessages uint64 `orm:"column(fail_messages); default(0)" json:"fail_messages" ` 207 // Error is reverse maping of error messages for this rule 208 Error []*Error `orm:"reverse(many)" json:"-"` 209 } 210 ``` 211 212 213 ### Endpoint Definition 214 215 ```go 216 // Endpoint define how to access external service 217 type Endpoint struct { 218 // ID is the ID of the endpoint 219 ID string `orm:"column(id); size(36); pk" json:"id" yaml:"id"` 220 // Type is type of the endpoint 221 Type string `orm:"column(type); size(64)" json:"type" yaml:"type"` 222 // Name is name of the endpoint 223 Name string `orm:"column(name); size(64)" json:"name" yaml:"name"` 224 // ProjectID can be used to differentiate endpoints across projects 225 ProjectID string `orm:"column(project_id); size(36); index; null" json:"project_id" yaml:"project_id"` 226 // IsShared is flag to check if endpoint is shared 227 IsShared bool `orm:"column(is_shared); default(false)" json:"is_shared" ` 228 // URI is unique resource identifier of the endpoint 229 URI string `orm:"column(uri); size(256)" json:"uri" yaml:"uri"` 230 // Properties is map used to store properties of an Endpoint 231 Properties Map `orm:"column(properties); size(10240)" json:"properties" yaml:"properties"` 232 // CreatedAt is endpoint creation timestamp 233 CreatedAt time.Time `orm:"column(created_at); auto_now_add; type(datetime)" json:"created_at" ` 234 // UpdatedAt is last endpoint updation timestamp 235 UpdatedAt time.Time `orm:"column(updated_at); auto_now; type(datetime)" json:"updated_at" ` 236 // Rule is reverse mapping of Rules of this endpoint 237 Rule []*Rule `orm:"reverse(many)" json:"-"` 238 } 239 ``` 240 ### EdgeHub 241 * Listen to the edge communication 242 * Package the message and send to the target 243 244 ### EdgeController 245 * Listen the service definition and create routing rule 246 * Listen the service definition to PODs deployed on edge and update the ClusterIP