github.com/micro/go-micro/examples@v0.0.0-20210105173217-bf4ab679e18b/kubernetes/README.md (about) 1 # Micro on Kubernetes 2 3 Micro on Kubernetes is a kubernetes native micro service deployment. 4 5 ## Overview 6 7 Micro is a blueprint for microservice development. Kubernetes is a container orchestration system. 8 Together they provide the foundations for a microservice platform. Micro on Kubernetes 9 provides a kubernetes native runtime to help build micro services. 10 11 ## Features 12 13 - No external dependencies 14 - K8s native services 15 - Service mesh integration 16 - gRPC communication protocol 17 - Pre-initialised micro images 18 - Healthchecking sidecar 19 20 ## Getting Started 21 22 - [Installing Micro](#installing-micro) 23 - [Writing a Service](#writing-a-service) 24 - [Deploying a Service](#deploying-a-service) 25 - [Writing a Web Service](#writing-a-web-service) 26 - [Healthchecking](#healthchecking-sidecar) 27 - [Load Balancing](#load-balancing) 28 - [Using Service Mesh](#using-service-mesh) 29 - [Using Config Map](#using-config-map) 30 - [Contribute](#contribute) 31 32 ## Installing Micro 33 34 35 ``` 36 go get github.com/micro/go-micro/examples/kubernetes/cmd/micro 37 ``` 38 39 or 40 41 ``` 42 docker pull microhq/micro:kubernetes 43 ``` 44 45 For go-micro 46 47 ``` 48 import "github.com/micro/go-micro/examples/kubernetes/go/micro" 49 ``` 50 51 ## Writing a Service 52 53 Write a service as you would any other [go-micro](https://github.com/micro/go-micro) service. 54 55 ```go 56 import ( 57 "github.com/micro/go-micro/v2" 58 k8s "github.com/micro/go-micro/examples/kubernetes/go/micro" 59 ) 60 61 func main() { 62 service := k8s.NewService( 63 micro.Name("greeter"), 64 ) 65 service.Init() 66 service.Run() 67 } 68 ``` 69 70 ## Deploying a Service 71 72 Here's an example k8s deployment for a micro service 73 74 ### Create a Deployment 75 76 ``` 77 apiVersion: apps/v1 78 kind: Deployment 79 metadata: 80 namespace: default 81 name: greeter 82 spec: 83 replicas: 1 84 template: 85 metadata: 86 labels: 87 app: greeter-srv 88 spec: 89 containers: 90 - name: greeter 91 command: [ 92 "/greeter-srv", 93 "--server_address=0.0.0.0:8080", 94 "--broker_address=0.0.0.0:10001" 95 ] 96 image: microhq/greeter-srv:kubernetes 97 imagePullPolicy: Always 98 ports: 99 - containerPort: 8080 100 name: greeter-port 101 ``` 102 103 Deploy with kubectl 104 105 ``` 106 kubectl create -f greeter.yaml 107 ``` 108 109 ### Create a Service 110 111 ``` 112 apiVersion: v1 113 kind: Service 114 metadata: 115 name: greeter 116 labels: 117 app: greeter 118 spec: 119 ports: 120 - port: 8080 121 protocol: TCP 122 selector: 123 app: greeter 124 ``` 125 126 Deploy with kubectl 127 128 ``` 129 kubectl create -f greeter-svc.yaml 130 ``` 131 132 ## Writing a Web Service 133 134 Write a web service as you would any other [go-micro/web](https://github.com/micro/go-micro/web) service. 135 136 ```go 137 import ( 138 "net/http" 139 140 "github.com/micro/go-micro/v2/web" 141 k8s "github.com/micro/go-micro/examples/kubernetes/go/web" 142 ) 143 144 func main() { 145 service := k8s.NewService( 146 web.Name("greeter"), 147 ) 148 149 service.HandleFunc("/greeter", func(w http.ResponseWriter, r *http.Request) { 150 w.Write([]byte(`hello world`)) 151 }) 152 153 service.Init() 154 service.Run() 155 } 156 ``` 157 158 ## Healthchecking Sidecar 159 160 The healthchecking sidecar exposes `/health` as a http endpoint and calls the rpc endpoint `Debug.Health` on a service. 161 Every go-micro service has a built in Debug.Health endpoint. 162 163 ### Install 164 165 ``` 166 go get github.com/micro/go-micro/examples/kubernetes/cmd/health 167 ``` 168 169 or 170 171 ``` 172 docker pull microhq/health:kubernetes 173 ``` 174 175 ### Run 176 177 Run e.g healthcheck greeter service with address localhost:9091 178 179 ``` 180 health --server_name=greeter --server_address=localhost:9091 181 ``` 182 183 Call the healthchecker on localhost:8080 184 185 ``` 186 curl http://localhost:8080/health 187 ``` 188 189 ### K8s Deployment 190 191 Add the healthchecking sidecar to a kubernetes deployment 192 193 ``` 194 apiVersion: apps/v1 195 kind: Deployment 196 metadata: 197 namespace: default 198 name: greeter 199 spec: 200 replicas: 1 201 template: 202 metadata: 203 labels: 204 app: greeter-srv 205 spec: 206 containers: 207 - name: greeter 208 command: [ 209 "/greeter-srv", 210 "--server_address=0.0.0.0:8080", 211 "--broker_address=0.0.0.0:10001" 212 ] 213 image: microhq/greeter-srv:kubernetes 214 imagePullPolicy: Always 215 ports: 216 - containerPort: 8080 217 name: greeter-port 218 - name: health 219 command: [ 220 "/health", 221 "--health_address=0.0.0.0:8081", 222 "--server_name=greeter", 223 "--server_address=0.0.0.0:8080" 224 ] 225 image: microhq/health:kubernetes 226 livenessProbe: 227 httpGet: 228 path: /health 229 port: 8081 230 initialDelaySeconds: 3 231 periodSeconds: 3 232 ``` 233 234 ## Load Balancing 235 236 Micro includes client side load balancing by default but kubernetes also provides Service load balancing strategies. 237 In **micro on kubernetes** we offload load balancing to k8s by using the [static selector](https://github.com/micro/go-plugins/tree/master/client/selector/static) and k8s services. 238 239 Rather than doing address resolution, the static selector returns the service name plus a fixed port e.g greeter returns greeter:8080. 240 Read about the [static selector](https://github.com/micro/go-plugins/tree/master/client/selector/static). 241 242 This approach handles both initial connection load balancing and health checks since Kubernetes services stop routing traffic to unhealthy services, but if you want to use long lived connections such as the ones in gRPC protocol, a service-mesh like [Conduit](https://conduit.io/), [Istio](https://istio.io) and [Linkerd](https://linkerd.io/) should be prefered to handle service discovery, routing and failure. 243 244 Note: The static selector is enabled by default. 245 246 ### Usage 247 248 To manually set the static selector when running your service specify the flag or env var 249 250 Note: This is already enabled by default 251 252 ``` 253 MICRO_SELECTOR=static ./service 254 ``` 255 256 or 257 258 ``` 259 ./service --selector=static 260 ``` 261 262 ### Deployment 263 264 An example deployment 265 266 ``` 267 apiVersion: apps/v1 268 kind: Deployment 269 metadata: 270 namespace: default 271 name: greeter 272 spec: 273 replicas: 1 274 template: 275 metadata: 276 labels: 277 app: greeter-srv 278 spec: 279 containers: 280 - name: greeter 281 command: [ 282 "/greeter-srv", 283 "--server_address=0.0.0.0:8080", 284 "--broker_address=0.0.0.0:10001" 285 ] 286 image: microhq/greeter-srv:kubernetes 287 imagePullPolicy: Always 288 ports: 289 - containerPort: 8080 290 name: greeter-port 291 ``` 292 293 Deploy with kubectl 294 295 ``` 296 kubectl create -f deployment-static-selector.yaml 297 ``` 298 299 ### Service 300 301 The static selector offloads load balancing to k8s services. So ensure you create a k8s Service for each micro service. 302 303 Here's a sample service 304 305 ``` 306 apiVersion: v1 307 kind: Service 308 metadata: 309 name: greeter 310 labels: 311 app: greeter 312 spec: 313 ports: 314 - port: 8080 315 protocol: TCP 316 selector: 317 app: greeter 318 ``` 319 320 Deploy with kubectl 321 322 ``` 323 kubectl create -f service.yaml 324 ``` 325 326 Calling micro service "greeter" from your service will route to the k8s service greeter:8080. 327 328 ## Using Service Mesh 329 330 Service mesh acts as a transparent L7 proxy for offloading distributed systems concerns to an external source. 331 332 See [linkerd2](https://linkerd.io/) for usage. 333 334 ## Using Config Map 335 336 [Go Config](https://github.com/micro/go-micro/config) is a simple way to manage dynamic configuration. We've provided a pre-initialised version 337 which reads from environment variables and the k8s config map. 338 339 It uses the `default` namespace and expects a configmap with name `micro` to be present. 340 341 ### Example 342 343 Create a configmap 344 345 ``` 346 // we recommend to setup your variables from multiples files example: 347 $ kubectl create configmap micro --namespace default --from-file=./testdata 348 349 // verify if were set correctly with 350 $ kubectl get configmap micro --namespace default 351 { 352 "apiVersion": "v1", 353 "data": { 354 "config": "host=0.0.0.0\nport=1337", 355 "mongodb": "host=127.0.0.1\nport=27017\nuser=user\npassword=password", 356 "redis": "url=redis://127.0.0.1:6379/db01" 357 }, 358 "kind": "ConfigMap", 359 "metadata": { 360 ... 361 "name": "micro", 362 "namespace": "default", 363 ... 364 } 365 } 366 ``` 367 368 Import and use the config 369 370 ```go 371 import "github.com/micro/go-micro/examples/kubernetes/go/config" 372 373 cfg := config.NewConfig() 374 375 // the example above "mongodb": "host=127.0.0.1\nport=27017\nuser=user\npassword=password" will be accessible as: 376 conf.Get("mongodb", "host") // 127.0.0.1 377 conf.Get("mongodb", "port") // 27017 378 ``` 379 380 ## Contribute 381 382 We're looking for contributions from the community to help guide the development of Micro on Kubernetes 383 384 ### TODO 385 386 - Fix k8s namespace/service name issue 387 - Add example multi-service application 388 - Add k8s CRD for micro apps