{"id":21178684,"url":"https://github.com/poabob/lab-zero","last_synced_at":"2026-01-02T02:00:44.892Z","repository":{"id":193171199,"uuid":"688264236","full_name":"POABOB/lab-zero","owner":"POABOB","description":null,"archived":false,"fork":false,"pushed_at":"2023-10-22T09:32:54.000Z","size":25882,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-14T18:49:04.848Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"HTML","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/POABOB.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-09-07T01:56:08.000Z","updated_at":"2023-09-09T10:46:07.000Z","dependencies_parsed_at":"2023-09-07T04:10:24.977Z","dependency_job_id":"48543faa-046f-4423-9352-873ef26f45b7","html_url":"https://github.com/POABOB/lab-zero","commit_stats":null,"previous_names":["poabob/lab-zero"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/POABOB/lab-zero","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/POABOB%2Flab-zero","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/POABOB%2Flab-zero/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/POABOB%2Flab-zero/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/POABOB%2Flab-zero/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/POABOB","download_url":"https://codeload.github.com/POABOB/lab-zero/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/POABOB%2Flab-zero/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":28167270,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2026-01-02T02:00:06.235Z","response_time":54,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-20T17:23:24.540Z","updated_at":"2026-01-02T02:00:44.875Z","avatar_url":"https://github.com/POABOB.png","language":"HTML","funding_links":[],"categories":[],"sub_categories":[],"readme":"# lab-zero\n\nThis is a two microserives of Users and Orders.\n\n## how to init a microservice of go-zero\n### init a rpc service\n\n1. add a structure of go-zero rpc sample.\n\n```bash\ngoctl rpc new demo\n```\n\n2. edit the protobuffer file of demo, and generate a new structure of real service.\n\n```bash\ncd demo\ngoctl rpc protoc --go_out=. --go-grpc_out=. --zrpc_out=. demo.proto\n```\n\n3. edit the bussiness logic in `demo/internal/logic` of your microservice.\n\n4. run it.\n\n```bash\ngo run demo.go\n```\n\n### init a gateway of rpc service\n\n1. generate a proto descriptor of microservice\n\n```bash\nprotoc --include_imports --proto_path=. --descriptor_set_out=demo.pb demo.proto\n```\n\n2. edit `demo/internal/config/config.go` in order to add the config to struct.\n\n```go\npackage config\n\nimport (\n\t\"github.com/zeromicro/go-zero/gateway\" // add this line\n\t\"github.com/zeromicro/go-zero/zrpc\"\n)\n\ntype Config struct {\n\tzrpc.RpcServerConf\n\tGateway          gateway.GatewayConf // add this line\n}\n```\n\n3. edit `demo/etc/demo.yaml` in order to add gateway config.\n\n```yaml\n# add this\nGateway:\n  Name: gateway\n  Port: 80\n  Upstreams:\n    - Grpc:\n        Target: 0.0.0.0:8888\n      ProtoSet: demo.pb\n```\n\n4. edit `demo/demo.go` in order to start two service. One is rpc service, and the other is gateway service.\n\n```go\nfunc main() {\n\tflag.Parse()\n\n\tvar c config.Config\n\tconf.MustLoad(*configFile, \u0026c)\n\tctx := svc.NewServiceContext(c)\n\n    // init a gateway server\n\tgw := gateway.MustNewServer(c.Gateway)\n\n    // init a service group\n\tgroup := service.NewServiceGroup()\n\n    // init a demo server\n\ts := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {\n\t\tdemo.RegisterDemoServer(grpcServer, server.NewDemoServer(ctx))\n\n\t\tif c.Mode == service.DevMode || c.Mode == service.TestMode {\n\t\t\treflection.Register(grpcServer)\n\t\t}\n\t})\n    // add demo server to service group\n\tgroup.Add(s)\n\n    // add gateway server to service group \n\tgroup.Add(gw)\n\tdefer group.Stop()\n\n\tfmt.Printf(\"Starting rpc server at %s...\\n\", c.ListenOn)\n\tfmt.Printf(\"Starting gateway at %s:%d...\\n\", c.Gateway.Host, c.Gateway.Port)\n    // service group start\n\tgroup.Start()\n}\n```\n\n\n5. run it.\n\n```bash\ngo run demo.go\n```\n\n### add validate to rpc service\n\n1. add rule to the `demo.proto`.\n\n\u003e protoc-gen-validate\n doc: https://github.com/bufbuild/protoc-gen-validate/blob/main/docs.md\n\n```proto\nmessage CreateRequest {\n  string name = 1 [(validate.rules).string = {\n    max_bytes: 256,\n  }];\n}\n```\n\n2. generate the validate file(`demo.pb.validate.go`).\n```bash\nprotoc --validate_out=lang=go:./ *.proto\n```\n\n3.1. add to the logic in `demo/internal/logic` mannually .\n\n```go\nfunc (l *CreateLogic) Create(in *demo.CreateRequest) (*demo.CreateResponse, error) {\n\tif err := in.ValidateAll(); err != nil {\n\t\treturn \u0026user.CreateResponse{\n\t\t\tMsg: err.Error(),\n\t\t}, nil\n\t}\n\n\treturn \u0026demo.CreateResponse{\n\t\tMsg: \"Ok\",\n\t}, nil\n}\n```\n\n3.2. use middleware to validate it.\n\n- add `demo/internal/middleware/validate/validate.go`\n\n```go\n// Copyright 2016 Michal Witkowski. All Rights Reserved.\n// See LICENSE for licensing terms.\n\npackage validate\n\nimport (\n\t\"context\"\n\n\t\"google.golang.org/grpc\"\n\t\"google.golang.org/grpc/codes\"\n\t\"google.golang.org/grpc/status\"\n)\n\n// The validate interface starting with protoc-gen-validate v0.6.0.\n// See https://github.com/envoyproxy/protoc-gen-validate/pull/455.\ntype validator interface {\n\tValidate(all bool) error\n}\n\n// The validate interface prior to protoc-gen-validate v0.6.0.\ntype validatorLegacy interface {\n\tValidate() error\n}\n\nfunc validate(req interface{}) error {\n\tswitch v := req.(type) {\n\tcase validatorLegacy:\n\t\tif err := v.Validate(); err != nil {\n\t\t\treturn status.Error(codes.InvalidArgument, err.Error())\n\t\t}\n\tcase validator:\n\t\tif err := v.Validate(false); err != nil {\n\t\t\treturn status.Error(codes.InvalidArgument, err.Error())\n\t\t}\n\t}\n\treturn nil\n}\n\n// UnaryServerInterceptor returns a new unary server interceptor that validates incoming messages.\n//\n// Invalid messages will be rejected with `InvalidArgument` before reaching any userspace handlers.\nfunc UnaryServerInterceptor() grpc.UnaryServerInterceptor {\n\treturn func(ctx context.Context, req interface{}, info *grpc.UnaryServerInfo, handler grpc.UnaryHandler) (interface{}, error) {\n\t\tif err := validate(req); err != nil {\n\t\t\treturn nil, err\n\t\t}\n\t\treturn handler(ctx, req)\n\t}\n}\n\n// UnaryClientInterceptor returns a new unary client interceptor that validates outgoing messages.\n//\n// Invalid messages will be rejected with `InvalidArgument` before sending the request to server.\nfunc UnaryClientInterceptor() grpc.UnaryClientInterceptor {\n\treturn func(ctx context.Context, method string, req, reply interface{}, cc *grpc.ClientConn, invoker grpc.UnaryInvoker, opts ...grpc.CallOption) error {\n\t\tif err := validate(req); err != nil {\n\t\t\treturn err\n\t\t}\n\t\treturn invoker(ctx, method, req, reply, cc, opts...)\n\t}\n}\n\n// StreamServerInterceptor returns a new streaming server interceptor that validates incoming messages.\n//\n// The stage at which invalid messages will be rejected with `InvalidArgument` varies based on the\n// type of the RPC. For `ServerStream` (1:m) requests, it will happen before reaching any userspace\n// handlers. For `ClientStream` (n:1) or `BidiStream` (n:m) RPCs, the messages will be rejected on\n// calls to `stream.Recv()`.\nfunc StreamServerInterceptor() grpc.StreamServerInterceptor {\n\treturn func(srv interface{}, stream grpc.ServerStream, info *grpc.StreamServerInfo, handler grpc.StreamHandler) error {\n\t\twrapper := \u0026recvWrapper{stream}\n\t\treturn handler(srv, wrapper)\n\t}\n}\n\ntype recvWrapper struct {\n\tgrpc.ServerStream\n}\n\nfunc (s *recvWrapper) RecvMsg(m interface{}) error {\n\tif err := s.ServerStream.RecvMsg(m); err != nil {\n\t\treturn err\n\t}\n\n\tif err := validate(m); err != nil {\n\t\treturn err\n\t}\n\n\treturn nil\n}\n```\n\n- edit `demo/demo.go` to use this middleware.\n\n```go\nfunc main () {\n    // ...\n    s := zrpc.MustNewServer(c.RpcServerConf, func(grpcServer *grpc.Server) {\n\t\tdemo.RegisterDemoServer(grpcServer, server.NewDemoServer(ctx))\n\n\t\tif c.Mode == service.DevMode || c.Mode == service.TestMode {\n\t\t\treflection.Register(grpcServer)\n\t\t}\n\t})\n    s.AddUnaryInterceptors(validate.UnaryServerInterceptor())\n    group.Add(s)\n    // ...\n}\n```\n\n4. run it.\n\n```bash\ngo run demo.go\n```\n\n## Start a Kubernetes cluster by Kind\n\n```bash\n# CASE A\nkind create cluster --name lab --config deployment/kind-cluster.yaml\n# CASE B-E\nkind create cluster --name lab --config deployment/kind-cluster-istio.yaml\n```\n\n## Change HPA sync period\n\nIn order to make the HPA controller scale faster, we need change the period of `--horizontal-pod-autoscaler-sync-period` (default is 15s) in `kube-controller-manager`.\nWe need change this config to 5s.\n\n```bash\n# access control-panel for mac and linux\ndocker exec -it lab-control-plane bash\n# access control-panel for win\nwinpty docker exec -it lab-control-plane bash\n\n# edit it\napt update\napt install nano\nnano /etc/kubernetes/manifests/kube-controller-manager.yaml\n# leave docker contianer\nexit\n\n# after edited it, restart control-plane\ndocker restart lab-control-plane\n```\n\n`/etc/kubernetes/manifests/kube-controller-manager.yaml`\n```yaml\napiVersion: v1\nkind: Pod\nmetadata:\n  creationTimestamp: null\n  labels:\n    component: kube-controller-manager\n    tier: control-plane\n  name: kube-controller-manager\n  namespace: kube-system\nspec:\n  containers:\n  - command:\n    - kube-controller-manager\n    - --allocate-node-cidrs=true\n    - --authentication-kubeconfig=/etc/kubernetes/controller-manager.conf\n    - --authorization-kubeconfig=/etc/kubernetes/controller-manager.conf\n    - --bind-address=127.0.0.1\n    - --client-ca-file=/etc/kubernetes/pki/ca.crt\n    - --cluster-cidr=10.244.0.0/16\n    - --cluster-name=mac\n    - --cluster-signing-cert-file=/etc/kubernetes/pki/ca.crt\n    - --cluster-signing-key-file=/etc/kubernetes/pki/ca.key\n    - --controllers=*,bootstrapsigner,tokencleaner\n    - --enable-hostpath-provisioner=true\n    - --kubeconfig=/etc/kubernetes/controller-manager.conf\n    - --leader-elect=true\n    - --requestheader-client-ca-file=/etc/kubernetes/pki/front-proxy-ca.crt\n    - --root-ca-file=/etc/kubernetes/pki/ca.crt\n    - --service-account-private-key-file=/etc/kubernetes/pki/sa.key\n    - --service-cluster-ip-range=10.96.0.0/16\n    - --use-service-account-credentials=true\n    - --horizontal-pod-autoscaler-sync-period=5s # add this line\n# ...\n```\nrestart it, it will work!\n\n## Install metric-server\n\nIn test environment, we need add a args of `--kubelet-insecure-tls`. `deployment/metric-server.yaml` was configured.\n\n```bash\nkubectl apply -f deployment/metric-server.yaml\n```\n\nTest it.\n```bash\nkubectl top pod\nkubectl top node\n```\n\n## Istall Kubernetes Dashboard\n\n```bash\nkubectl apply -f https://github.com/kubernetes/dashboard/blob/master/charts/kubernetes-dashboard.yaml\n\n# 建立admin user\nkubectl apply -f - \u003c\u003cEOF\napiVersion: rbac.authorization.k8s.io/v1\nkind: ClusterRoleBinding\nmetadata:\n  name: kube-system-default\n  labels:\n    k8s-app: kube-system\nroleRef:\n  apiGroup: rbac.authorization.k8s.io\n  kind: ClusterRole\n  name: cluster-admin\nsubjects:\n  - kind: ServiceAccount\n    name: default\n    namespace: kube-system\n\n---\n\napiVersion: v1\nkind: Secret\nmetadata:\n  name: default\n  namespace: kube-system\n  labels:\n    k8s-app: kube-system\n  annotations:\n    kubernetes.io/service-account.name: default\ntype: kubernetes.io/service-account-token\nEOF\n\nTOKEN=$(kubectl -n kube-system describe secret default| awk '$1==\"token:\"{print $2}')\n\nkubectl config set-credentials docker-desktop --token=\"${TOKEN}\"\n\necho $TOKEN\n\nkubectl proxy\n```\n\naccess with this url http://localhost:8001/api/v1/namespaces/kubernetes-dashboard/services/https:kubernetes-dashboard:/proxy/.\n\n## Set up Case A\n\n1. install microservices and redis.\n\n```bash\nkubectl apply -f ./deployment/case-A.yaml\n```\n\n2. install nginx ingress.\n\n```bash\n# install nginx ingress\nkubectl create namespace istio-system\nistioctl install -f ingress.yaml\nkubectl patch svc istio-ingressgateway -n istio-system --patch-file ./deployment/gateway-svc-patch.yaml\n```\n\n4. delete it...\n\n```bash\nkubectl delete -f ./deployment/case-A.yaml\nistioctl uninstall --purge\n```\n\n## Set up Case B/C\n\n1. install istio and set the default  configuration profile.\n\n```bash\nistioctl install --set profile=default -y\n```\n\n2. add a namespace label to instruct Istio to automatically inject Envoy sidecar proxies.\n\n```bash\nkubectl label namespace default istio-injection=enabled\n```\n\n3. create a root certificate and private key to sign the certificates for our services.\n\n```bash\nmkdir certs\nopenssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=local Inc./CN=local.com' -keyout certs/local.com.key -out certs/local.com.crt\n```\n\n4. generate a certificate and a private key for lab.local.com.\n\n```bash\nopenssl req -out certs/lab.local.com.csr -newkey rsa:2048 -nodes -keyout certs/lab.local.com.key -subj \"/CN=lab.local.com/O=lab organization\"\nopenssl x509 -req -sha256 -days 365 -CA certs/local.com.crt -CAkey certs/local.com.key -set_serial 0 -in certs/lab.local.com.csr -out certs/lab.local.com.crt\n```\n\n5. create a secret for the ingress gateway\n\n```bash\nkubectl create -n istio-system secret tls lab-credential \\\n  --key=certs/lab.local.com.key \\\n  --cert=certs/lab.local.com.crt\n```\n\n6. install microservices and redis.\n\n```bash\nkubectl apply -f ./deployment/case-B.yaml\n```\n\n7. edit the Service type of istio ingress gateway from `LoadBalancer` to `NodePort` and change to port.\n\n```bash\nkubectl patch svc istio-ingressgateway -n istio-system --patch-file ./deployment/gateway-svc-patch.yaml\n```\n\n8. delete it...\n\n```bash\nkubectl delete -f ./deployment/case-B.yaml\nistioctl uninstall --purge\nkubectl delete -n istio-system secret tls lab-credential\n```\n\n## Set up Case D/E\n\n1. install istio and set the default  configuration profile.\n\n```bash\nistioctl install --set profile=ambient --set components.ingressGateways[0].enabled=true --set components.ingressGateways[0].name=istio-ingressgateway --skip-confirmation\n```\n\n2. create a root certificate and private key to sign the certificates for our services.\n\n```bash\nmkdir certs\nopenssl req -x509 -sha256 -nodes -days 365 -newkey rsa:2048 -subj '/O=local Inc./CN=local.com' -keyout certs/local.com.key -out certs/local.com.crt\n```\n\n3. generate a certificate and a private key for lab.local.com.\n\n```bash\nopenssl req -out certs/lab.local.com.csr -newkey rsa:2048 -nodes -keyout certs/lab.local.com.key -subj \"/CN=lab.local.com/O=lab organization\"\nopenssl x509 -req -sha256 -days 365 -CA certs/local.com.crt -CAkey certs/local.com.key -set_serial 0 -in certs/lab.local.com.csr -out certs/lab.local.com.crt\n```\n\n4. create a secret for the ingress gateway\n\n```bash\nkubectl create -n istio-system secret tls lab-credential \\\n  --key=certs/lab.local.com.key \\\n  --cert=certs/lab.local.com.crt\n```\n\n5. install microservices and redis.\n\n```bash\nkubectl apply -f ./deployment/case-D.yaml\n```\n\n6. edit the Service type of istio ingress gateway from `LoadBalancer` to `NodePort` and change to port.\n\n```bash\nkubectl patch svc istio-ingressgateway -n istio-system --patch-file ./deployment/gateway-svc-patch.yaml\n```\n\n7. add a namespace label to instruct Istio to automatically inject Envoy sidecar proxies.\n\n```bash\nkubectl label namespace default istio.io/dataplane-mode=ambient\n```\n\n8. deploy a waypoint proxy for the services(just for case E)\n\n```bash\nistioctl x waypoint apply --service-account lab-zero-orders\nistioctl x waypoint apply --service-account lab-zero-users\nistioctl x waypoint apply --service-account lab-zero-redis\n```\n\n9. delete it...\n\n```bash\nkubectl delete -f ./deployment/case-B.yaml\nistioctl uninstall --purge\nkubectl delete -n istio-system secret tls lab-credential\n# just for case E\nistioctl x waypoint delete --service-account lab-zero-orders\nistioctl x waypoint delete --service-account lab-zero-users\nistioctl x waypoint delete --service-account lab-zero-redis\n```\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoabob%2Flab-zero","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpoabob%2Flab-zero","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpoabob%2Flab-zero/lists"}