搭建K8s容器化应用的开发调试环境
对开发人员而言,Kubernetes(简称k8s)真的是想说爱你不容易。因为k8s基本与我们的业务无关,它的关注点是容器编排,涉及到的都是系统的网络、存储、计算等基础资源,是我们比较陌生的领域;另外,因为众所周知的原因,谷歌系的网站基本上在国内没法访问,这就导致了很多对k8s的探索都是止步于安装,无果而终。本文是笔者踩坑无数后,在k8s路上的一点收获,在Win10上搭建单机的k8s环境,进行容器化应用的开发、调试与部署。
1、容器化带来的问题
把应用容器化是为了方便测试和部署,解决开发人员“我这里可以呀”而测试或用户“我这里不行”的问题。我们开发出来的软件需要比较良好的可部署性,容器化与无服务器架构是实现这个目标的发展方向和趋势。Docker和Kubernetes是容器化和容器编排的行业标准,在现阶段也相对成熟;无服务器(Serverless)目前支持的业务场景还比较有限,也缺少行业标准,容易被厂商锁定。
作为开发人员,我们当然还需要良好的可调试性。那种把应用编译部署到容器后,有问题只能看容器里应用输出的日志,而无法做代码跟踪、断点调试的方案,都不是我们想要的。
这里说的应用容器化后影响调试,是不包括单体应用的,主要是说部署在容器里并且跟其他容器里的应用有交互的应用,也就是服务间相互调用,微服务就是最典型的例子。比如你用docker compose启动微服务的其它应用,然后试图在IntelliJ IDEA里跟踪调试某个服务,这时你会发现,IDEA跟docker compose启动的服务不在一个世界,网络不通。Docker可以暴露端口供外部调用,但IDEA里启动的这个应用没法暴露给容器世界里的服务,微服务的服务发现(Eureka Server、Zookeeper等)只能发现容器世界里的服务。
Java或者其它支持远程调试的语言,虽然提供了一种可行的方式,但在应用部署到容器后,特别是k8s环境,要连接远程调试端口也变得困难了,何况远程调试本身就没有本机来得简单快捷。K8s对容器进行调度、编排,带来了比docker更高级的功能,但同时也增加了系统的复杂性。
良好的可部署性和可调试性,鱼与熊掌,可以兼得吗?我们不相信世上有可以解决一切问题的银弹,但却总是走在寻找银弹的路上^_^

2、解决方案概述
笔者给的这个兼顾可部署性和可调试性的开发环境搭建方案,重点是用k3s来解决Kubernetes的安装难题,用Telepresence来打通容器和IDE进行代码的跟踪调试,用Skaffold来自动化处理容器构建和部署。
如果你有更好的建议,还望不吝赐教👏
K3s是经CNCF一致性认证的Kubernetes发行版,重点是k3s被打包成单个小于60MB的二进制文件,从而简化了安装、运行和升级k8s集群所需的依赖性和步骤,也就是说k3s是开箱即用的,不再需要去联网下载相关镜像,“完美”解决了k8s的安装难题;
Telepresence为部署在k8s环境里的应用提供快速本地化开发功能,其基本原理是在k8s集群中部署双向网络代理,使得本机环境的服务和k8s集群里的服务完全互访,包括k8s的环境变量、Secrets和ConfigMap等;
Skaffold是谷歌提供的开发支持工具,主要是跟谷歌提供的云服务(Google Cloud)结合来加速应用的容器化构建、部署,这里我们只用它的基础功能就行了,自动构建并部署到应用到k8s集群。

3、安装Docker Desktop
系统要求:Microsoft Windows 10 Professional or Enterprise 64-bit, or Windows 10 Home 64-bit with WSL 2.
Docker在后续的容器镜像构建(build)会用到,所以这里先提出来做好准备。在Windows开发环境做容器化部署,Docker Desktop也是必备软件了。
这里再推荐一个终端工具:Windows Terminal,笔者觉得比cmd和power shell用着舒服多了,可以在Microsoft Store上搜索安装。微软的store有一个bug,就是很容易“无法加载页面,请稍候重试”,解决办法是打开IE(Internet Explorer),在“Internet选项”的“高级”里勾选TLS1.1和TLS1.2,“应用”即可解决问题。
真的是IE不死,bug长存啊😂微软Store的这个bug,笔者没去细究,可能是国内的某些安全工具在坑微软,或者某些银行软件做的修改,但是微软这个软件帝国,自己的Store门被堵了也无动于衷,真是够稳重的啊👍
给一个在Windows Terminal里查看Docker Desktop是否就绪的截图:

4、安装Multipass
Multipass是Ubuntu 发行商 Canonical 旗下的一款产品,是一个轻量级 Linux 虚拟机命令行管理工具。通过 Multipass,用户可以用一条命令启动虚拟机镜像,并在短短数秒内让 Linux在Mac和Windows上运行起来。显然这里的Linux是专指Ubuntu,你如果喜欢其它的Linux,也有熟悉的方式和趁手的工具,可以略过这一部分。Canonical这些大厂,为了推广自己的产品,也是够拼的。
系统要求:Windows 10专业版、企业版、教育版,或者安装了VirtualBox。
Multipass安装就绪后,就可以用命令来管理ubuntu虚拟机了:
multipass help 查看帮助,授人以鱼不如授人以渔
multipass list 查看现有的虚拟机实例
multipass find 查看可用的镜像
multipass launch 创建并启动Ubuntu实例
multipass shell 连接实例进行shell操作
multipass start 启动虚拟机
multipass stop 停止虚拟机
multipass delete 删除虚拟机
multipass recover 恢复删除的虚拟机
multipass purge 彻底清除删除的虚拟机
接下来我们用Multipass创建一个LTS版的Ubuntu 20.04,取名为test,shell进去修改root的密码,然后试一下multipass对虚拟机的管理:启动、停止、删除等:



安装好Docker Desktop和Multipass后,就可以进入正题,开始安装K3s、Telepresence和Skaffold,搭建有良好可调试性的k8s开发环境。

5、安装K3s
先用Multipass创建并启动Ubuntu虚拟机,作为安装k3s的Linux服务器:
# 这个虚拟机命名为k3s-1,使用LTS版的Ubuntu 20.04
multipass launch -n k3s-1 20.04
连接虚拟机k3s-1上的ubuntu并修改root的密码,以便后续使用root进行操作:
# shell连接ubuntu
multipass shell k3s-1
# 修改root密码,Ubuntu默认的root密码为空
sudo passwd
# 修改密码才能切换用户为root
su root
国内用户,可以使用以下方法加速安装:
curl -sfL http://rancher-mirror.cnrancher.com/k3s/k3s-install.sh | INSTALL_K3S_MIRROR=cn sh -
安装成功的话会输出如下内容:
[INFO] Finding release for channel stable
[INFO] Using v1.21.7+k3s1 as release
[INFO] Downloading hash http://rancher-mirror.cnrancher.com/k3s/v1.21.7-k3s1/sha256sum-amd64.txt
[INFO] Downloading binary http://rancher-mirror.cnrancher.com/k3s/v1.21.7-k3s1/k3s
[INFO] Verifying binary download
[INFO] Installing k3s to /usr/local/bin/k3s
[INFO] Creating /usr/local/bin/kubectl symlink to k3s
[INFO] Creating /usr/local/bin/crictl symlink to k3s
[INFO] Creating /usr/local/bin/ctr symlink to k3s
[INFO] Creating killall script /usr/local/bin/k3s-killall.sh
[INFO] Creating uninstall script /usr/local/bin/k3s-uninstall.sh
[INFO] env: Creating environment file /etc/systemd/system/k3s.service.env
[INFO] systemd: Creating service file /etc/systemd/system/k3s.service
[INFO] systemd: Enabling k3s unit
[INFO] systemd: Starting k3s
检查k3s是否运行正常:
# 查看k3s的进程
ps aux|grep k3s
# k3s的位置
which k3s
# 用kubectl看看node(安装k3s时也会安装kubectl,确实比较省心)
kubectl get node
# 用kubectl看看pod
# -A参数表示查看所有,可用-n参数指定具体的namespace,默认是default
kubectl get pod -A

6、在本机上安装kubectl
Kubectl是Kubernetes工具,使用kubectl可以对 k8s 集群运行命令,比如部署应用、监测和管理集群资源以及查看日志等。
要在本机(windows 10)上访问k3s-1虚拟机里安装的kubernetes集群,需要先安装windows版的kubectl,kubectl是用golang开发的,只有一个执行程序,可以直接下载,然后在环境变量path里增加kubectl执行程序的路径即可。
Kubectl安装好后,还需要配置一下,告诉它待连接的k8s集群的相关参数。这个配置文件的位置是:
# 检查kubectl是否安装就绪,在Power Shell里执行下述命令
# 期待的输出是有具体的Client Version,但是Server连接失败
kubectl version
# 进入kubectl的配置路径
cd ~/.kube
Windows上kubectl的配置文件是“~/.kube/config”(这里的~只在power shell里有效,跟当前登录的用户名有关,在资源管理器里要替换为实际的路径),远端Ubuntu主机(虚拟机k3s-1)里k3s的KUBECONFIG是在这个文件里:/etc/rancher/k3s/k3s.yaml,所以现在要做的就是把k3s.yaml里的内容,复制到config里。
记得要改Server的IP地址,在k3s.yaml文件里指向的k8s集群Server地址是127.0.0.1,在windows的~/.kube/config里则要修改为虚拟机k3s-1的地址:
cat /etc/rancher/k3s/k3s.yaml

用Multipass list查看k3s-1的IP地址,以及配置好之后,在windows本机上验证一下:

7、用kubectl管理k8s
Kubernetes的基础知识这里简单讲一下:
Node,一个节点就是是一台主机(虚拟主机或者物理主机),一个k8s集群可以管理若干主机;
Pod,在英文中的原意是豆荚的意思,在k8s的一个pod中可以运行一个或者多个容器,并且k8s会为每个pod都分配一个集群内唯一的IP地址;K8s一般会为一个服务部署多个pod副本,副本的数量可以增加或减少,构成一个pod集群来对外提供服务,所以要访问k8s集群里的服务,直接写某个pod的地址是不行的;
Service,是k8s中的一个核心资源,主要就是解决上述服务访问的问题。Service一旦创建就会分配固定的IP地址,并且在它的整个生命周期里都不会改变。
Ingress,可以简单理解为Nginx或微服务里的网关(Zuul,Gateway),如果说Service是解决k8s集群内服务访问的问题,Ingress就是把Service暴露到集群外部,供外部访问集群提供的服务。
当然k8s集群还有一些其它的概念,比如存储PV、PVC,Secrets,ConfigMap等,这些我们都可以简单理解为k8s管理的资源,这些资源汇集起来构成整个集群。
有了用k3s运行的k8s集群,也了解了一些基本的概念,接下来我们实际部署一个简单的服务,进一步体验一下k8s的容器编排能力。
以bootcamp为例,这是k8s世界的Hello World。
7.1 创建Pod
先编写一个部署文件(bootcamp-deployment.yaml):
apiVersion: apps/v1
kind: Deployment
metadata:
labels:
app: k8s-bootcamp-v1
name: k8s-bootcamp-v1
spec:
replicas: 2
selector:
matchLabels:
app: k8s-bootcamp-v1
template:
metadata:
labels:
app: k8s-bootcamp-v1
spec:
containers:
- image: jocatalin/kubernetes-bootcamp:v1
name: k8s-bootcamp-v1
resources:
requests:
memory: "128Mi"
cpu: "50m"
limits:
memory: "512Mi"
cpu: "100m"
上述配置里资源(resource)的内存(memory)单位Mi=1024*1024字节,cpu的50m则表示50/1000个cpu内核(Core),也可以表示为0.05
在windows本机使用kubectl运行部署命令:
kubectl apply -f bootcamp-deployment.yaml

Deployment对应的是Pod
7.2 创建Service
编写Service文件(bootcamp-svc.yaml):
apiVersion: v1
kind: Service
metadata:
labels:
app: k8s-bootcamp-v1
name: k8s-bootcamp-v1
spec:
ports:
- port: 8080
protocol: TCP
targetPort: 8080
selector:
app: k8s-bootcamp-v1
type: ClusterIP
同样用kubectl apply发布这个Service(k8s世界里通常把service简称为svc):

7.3 创建Ingress
k3s内置的Ingress Controller是Traefik,也有基于Nginx的Ingress,Traefik在代理容器化应用时具有一定的优势,既支持Docker也支持k8s,在容器里部署的应用实例数量变化时,Traefik可以自动感知,不需要调整配置参数。但不管是哪个具体的Ingress实现,创建Ingress的操作都是一样的(bootcamp-ingress.yaml):
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: "bootcamp-ingress"
labels:
app: bootcamp-ingress
spec:
rules:
- host: bootcamp.me
http:
paths:
- path: /
backend:
serviceName: "k8s-bootcamp-v1"
servicePort: 8080
还是kubectl apply来发布这个Ingress:

7.4 访问(内网、外网)
至此,已经把应用部署到k8s的Pod,并创建了供内部访问的Service,也通过Ingress把服务暴露给外部。现在就来验证一下,在Ubuntu主机上,用curl在内部通过Service的固定IP访问:

在Windows 10本机上,先修改hosts(需要用管理员权限打开文本编辑工具才修改,C:\Windows\System32\drivers\etc\hosts),添加域名解析:
172.28.189.231 bootcamp.me
然后在浏览器访问http://bootcamp.me

这样我们的bootcamp就完成部署了!接下来我们稍微接触一点k8s的高端能力,看看它的容器编排能力。
7.5 手动扩容(Scale)
手工增加或者缩小bootcamp的Pod副本数量,这个能力非常实用,某个服务的负载高了,就增加Pod副本数量来支撑业务的正常运转,负载小就减少副本数量,把资源让出来。
使用kubectl scale命令,手动扩容和缩容:
kubectl scale deployment k8s-bootcamp-v1 --replicas=3

7.6 自动扩容(Autoscale)
有了手动扩容,来一个自动扩容就是很自然的事情了。K8s的Horizontal Pod Autoscaler(HPA)的控制器,用来实现基于CPU使用率进行自动Pod扩容和缩容的功能。
# cpu的使用率超过50%就扩容Pod副本的数量,最多10个,至少保留1个
# 注意这里的cpu使用率是按depolyment部署指定的资源参数来计算的
# 可以结合bootcamp-deployment.yaml里的resources来理解
kubectl autoscale deployment k8s-bootcamp-v1 --min=1 --max=10 --cpu-percent=50

HPA是通过循环控制来实现的,默认30秒检查一次应用使用资源的情况(cpu使用率),扩容的时间间隔是3分钟,缩容则是5分钟。所以在进行上述操作的时候,不会立即看到效果。
7.7 清理(善后工作)
测试的最后,把前面创建的这些资源都释放掉,完成bootcamp的有始有终。Say Hello之后Say Bye Bye
K8s的资源删除有两种方式,一种用kubectl执行delete命令,带上资源类型和资源名称这两个参数:
kubectl delete hpa k8s-bootcamp-v1
另一种方式是使用yaml文件来传递资源类型和名称这两个参数:
kubectl delete -f bootcamp-deployment.yaml

如果在Windows的hosts文件里配置了bootcamp.me的域名解析,也别忘了把它删除掉。
7.8 小结
K8s对容器的管理能力,确实够强大,但也够复杂,但相信软件发展的趋势,好的东西总是会向前发展并简化。

8、安装Teleprensence
Telepresence是一款为Kubernetes或者Openshift微服务开发提供快速本地化支持的开源软件。
8.1 安装
Windows版的下载地址:
安装比较简单,下载后解压,在Power Shell下执行install-telepresence.ps1
# 进入解压后的文件夹
cd telepresence
# 执行install-telepresence.ps1
.\install-telepresence
默认安装在C:\telepresence
查看帮助:
telepresence --help
8.2 连接K8s集群(Connect)
连接(代理)K8s集群(跟kubectl一样,也是从~/.kube/config文件里获取K8s集群的信息进行连接):
PS D:\temp\k3s> telepresence connect
Launching Telepresence Root Daemon
Launching Telepresence User Daemon
Connected to context default (https://x.x.x.x:6443)
Connect成功后,就可以在本机上访问远端K8s集群里的Service了。测试一下,还有用bootcamp。前面我们已经把bootcamp删除了,但是有了k8s,重新部署很轻松:
PS D:\temp\k3s> kubectl apply -f bootcamp-deployment.yaml
deployment.apps/k8s-bootcamp-v1 created
PS D:\temp\k3s> kubectl apply -f bootcamp-svc.yaml
service/k8s-bootcamp-v1 created
PS D:\temp\k3s> kubectl get pod
NAME READY STATUS RESTARTS AGE
k8s-bootcamp-v1-7c898bf695-l9vwb 1/1 Running 0 31s
k8s-bootcamp-v1-7c898bf695-cp52l 1/1 Running 0 31s
PS D:\temp\k3s> kubectl get svc
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.43.0.1 443/TCP 3d19h
k8s-bootcamp-v1 ClusterIP 10.43.188.82 8080/TCP 72s
PS D:\temp\k3s> curl http://10.43.188.82:8080
StatusCode : 200
StatusDescription : OK
Content : Hello Kubernetes bootcamp! | Running on: k8s-bootcamp-v1-7c898bf695-cp52l | v=1
退出Telepresence的connect:
PS D:\temp\k3s> telepresence quit
Telepresence Root Daemon quitting... done
Telepresence User Daemon quitting... done
8.3 接管K8s集群的流量(Intercept)
接管(拦截)K8s集群里的访问流量,通过代理转到本机:
telepresence intercept
--port [: ] --env-file
拦截(intercept)操作,稍微要复杂一点,流量拦截到本机后,需要本机启动一个相应的服务来处理这些流量。如果是调试的话,就应该是用IDE的调试模式来启动bootcamp,这里我们用docker启动。
# 本机启动一个bootcamp,向外暴露的访问端口是8081
PS D:\temp\k3s> docker run -p 8081:8080 -d jocatalin/kubernetes-bootcamp:v1
0934023b1a6a37ef35a4f0bedc21d4306db970b02a80775858972aebe95aa1df
# 测试对本机bootcamp的访问
PS D:\temp\k3s> curl http://localhost:8081
StatusCode : 200
StatusDescription : OK
Content : Hello Kubernetes bootcamp! | Running on: 0934023b1a6a | v=1
...
# Telepresence连接K8s集群,如果已经连接则可以省略
PS D:\temp\k3s> telepresence connect
Launching Telepresence Root Daemon
Launching Telepresence User Daemon
Connected to context default (https://172.28.186.230:6443)
# 接管K8s集群里k8s-bootcap-v1这个service的流量
PS D:\temp\k3s> telepresence intercept k8s-bootcamp-v1 --port 8081:8080
Using Deployment k8s-bootcamp-v1
intercepted
Intercept name : k8s-bootcamp-v1
State : ACTIVE
Workload kind : Deployment
Destination : 127.0.0.1:8081
Service Port Identifier: 8080
Volume Mount Point : T:
Intercepting : all TCP connections
Intercepting all traffic to your service.
# 再次测试对bootcamp的访问
PS D:\temp\k3s> curl http://10.43.188.82:8080
StatusCode : 200
StatusDescription : OK
Content : Hello Kubernetes bootcamp! | Running on: 0934023b1a6a | v=1
为了更直观地看到本地8081端口的bootcamp接管了访问流量,可以看看docker的日志:
PS D:\temp\k3s> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0934023b1a6a jocatalin/kubernetes-bootcamp:v1 "/bin/sh -c 'node se…" 45 minutes ago Up 45 minutes 0.0.0.0:8081->8080/tcp condescending_sinoussi
PS D:\temp\k3s> docker logs 0934023b1a6a -f
Kubernetes Bootcamp App Started At: 2021-12-04T08:09:41.108Z | Running On: 0934023b1a6a
Running On: 0934023b1a6a | Total Requests: 1 | App Uptime: 9.505 seconds | Log Time: 2021-12-04T08:09:50.613Z
Running On: 0934023b1a6a | Total Requests: 2 | App Uptime: 288.663 seconds | Log Time: 2021-12-04T08:14:29.771Z
结束Intercept:
telepresence leave
9、安装Skaffold
Skaffold可以自动构建镜像,推送到镜像仓库,部署应用。如果团队已经有这方面的规范流程了,则可以评估一下,看是否需要用Skaffold来代替。比如Maven插件fabric8,或者类似Jenkins这样的CI/CD工具。
9.1 安装
Skaffold的安装跟kubectl类似,就是一个独立的可执行程序,下载后设置一下环境变量path即可。下载下来是skaffold-windows-amd64.exe,为了后续操作方便,请改名为skaffold.exe,这样设置了path后,在Power Shell里可以直接使用了。
9.2 准备镜像仓库
Skaffold的操作的对象是应用的容器镜像(Docker Image),所以需要一个K8s集群和本机环境都可以访问的容器镜像仓库,以这个仓库为中转,完成应用容器镜像的推送和部署。
如果不是纯学习,就移动办公而言,或者为了自己工作学习的方便,在互联网上弄一个镜像仓库还是很有必要的。像,或者腾讯云、华为云等,都有提供类似的服务。

也可以使用Docker的registry镜像,搭建自己的私有镜像仓库,这里就不赘述了。后续的操作以阿里云的镜像容器服务为例,主要参考Skaffold的官网教程:
先clone官网的例子:
PS> git clone --depth 1 https://github.com/GoogleContainerTools/skaffold
...
PS> cd skaffold/examples/getting-started
PS> ls
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 2021-12-04 17:54 445 Dockerfile
-a---- 2021-12-04 17:54 141 k8s-pod.yaml
-a---- 2021-12-04 17:54 142 main.go
-a---- 2021-12-04 17:54 579 README.md
-a---- 2021-12-04 17:54 148 skaffold.yaml
从文件看非常简单,重点是Dockerfile和yaml文件,那个main.go虽然表明这个例子是go语言开发的,但是不需要你懂go,也不需要安装go的相关程序。
9.3 准备访问镜像仓库的secret
K8s的Secret用来管理敏感数据,这里我们创建一个存放镜像仓库账号密码的Secret,供Deployment从镜像仓库拉取镜像时提供访问凭证。
# 下述指令里的***和邮件,请替换你自己的信息
# 如果是linux请把行尾的`换成\
kubectl create secret `
docker-registry my-registry-key `
--docker-server=registry.cn-chengdu.aliyuncs.com/***/getting-started `
--docker-username=*** `
--docker-password=*** `
--docker-email=a@b.com
编辑getting-started文件夹下的k8s-pod.yaml,把访问镜像仓库的secret配置上去。
apiVersion: v1
kind: Pod
metadata:
name: getting-started
spec:
imagePullSecrets:
- name: my-registry-key
containers:
- name: getting-started
image: skaffold-example
9.4 Skaffold run
运行Skaffold run命令会执行一次构建和部署。容器镜像的构建请查看getting-started文件夹下的Dockerfile文件,做了两件事情,先编译main.go,然后用编译得到的可执行程序创建Docker镜像。部署则是先推送镜像到镜像仓库,然后deployment到k8s集群。
# 在本机先登录镜像仓库
PS > docker login --username=*** registry.cn-chengdu.aliyuncs.com
PS > cd skaffold\examples\getting-started
# 注意default-repo指向的仓库地址是skaffold-example的上级路径
# 最后得到的镜像路径是registry.cn-chengdu.aliyuncs.com/***/skaffold-example
PS > skaffold run --default-repo=registry.cn-chengdu.aliyuncs.com/***
# 顺利的话,skaffold-example已经部署到k8s集群
PS > kubectl get pod
NAME READY STATUS RESTARTS AGE
getting-started 1/1 Running 0 4m4s
9.5 其他
Skaffold dev则是一直监控代码的修改,反复构建、部署。
Skaffold debug需要下载这个镜像:gcr.io/k8s-skaffold/skaffold-debug-support/go,无法下载,此路不通。
另外,Skaffold还开发了IntelliJ IDEA的插件,在IDE里辅助开发,主要是结合谷歌云进行快速部署,被墙了所以没啥用。

10、总结及后续
不管怎么说,这个Kubernetes的开发环境算是搭建起来了。
K3s总体来讲很不错,给了国内开发人员一个容易上手的K8s,降低了难度,一旦入门,慢慢探索,总会越来越好。
Telepresence解决了调试的一个大问题,特别是团队协作的时候,大家基于云部署一个云端的k8s开发环境,在联调方面省很多事,也减少了开发终端的负担;或者生产环境解决问题的时候,除了远程调试,也多出一个手段。
Skaffold本身还是优秀的,只不过跟谷歌云结合的比较多,对国内开发人员来说有点鸡肋。
本文有点技术选型的意思,后续有时间考虑结合微服务的开发来实际应用一下,看看还有哪些坑。。。