用Tilt加速你的本地开发环境

946 阅读6分钟

我们花了好几个小时在我们的机器上开发应用程序,要求和复杂性越来越多。此外,任何现代应用程序都有多个容器、微服务、在不同环境中的部署、各种堆栈等。因此,任何能够使我们的流程更加敏捷的工具都是很方便的。

在这篇文章中,我想介绍一个强大的工具,它可以为你在开发过程中节省大量时间。这就是Tilt,它最近被Docker收购

为了演示你能用Tilt做什么,我将使用我在一个关于微服务的演讲中使用的这个资源库(葡萄牙语)。这些例子将在Go中进行,但在官方文档中,你可以看到如何在其他技术和场景中使用它。

安装

第一步是在命令行中安装该程序。为此,在我的macOS上,我运行了。

curl -fsSL https://raw.githubusercontent.com/tilt-dev/tilt/master/scripts/install.sh | bash

文档显示了如何在其他操作系统上安装它。

第一个步骤

Tilt通过读取你项目根部的一个名为Tiltfile 的文件来工作。它的语法类似于Python ,而且文档非常详细,显示了我们可以使用的所有选项。

Tiltfile 文件的内容看起来像这样:

local_resource('auth', cmd='cd auth; go build -o bin/auth main.go',
               serve_cmd='auth/bin/auth', deps=['auth/main.go', 'auth/security', 'auth/user', 'pkg'])

local_resource('feedbacks', cmd='cd feedbacks; go build -o bin/feedbacks main.go',
               serve_cmd='feedbacks/bin/feedbacks', deps=['feedbacks/main.go', 'feedbacks/feedback', 'pkg'])


local_resource('votes', cmd='cd votes; go build -o bin/votes main.go',
               serve_cmd='votes/bin/votes', deps=['votes/main.go', 'votes/vote', 'pkg'])

local_resource 函数配置将在你的本地机器上执行的动作,第一个参数是我们要给资源起的名字,这个名字在Tiltfile 中必须是唯一的。

cmd 参数包含要执行的命令。serve_cmd 参数中包含的信息将由Tilt执行,预计不会终止。也就是说,它是将运行我们的服务的命令。

最后一个参数,deps ,是最有趣的参数之一。它表明Tilt将监视哪些项目目录;如果有变化,它将自动运行该进程。因此,例如,如果auth/main.goauth/securityauth/userpkg, 发生任何变化,auth 服务将被重新编译并再次运行。由于它是像Go这样的编译语言,这是一个很大的帮助,因为改变文件会自动生成,节省了我们开发人员的宝贵时间。

由于我们的项目由三个微服务组成,Tiltfile 的其余部分为所有的服务配置了相同的行为。

要运行Tilt,只需打开一个终端并输入。

就会出现以下内容。

按空格键可以进入Tilt的图形界面,我们会在那里花很多时间。

我们可以在这个界面上检查每个应用程序的编译日志,并再次执行需要的步骤。它还可以汇总应用程序的日志,并允许我们对其进行搜索。

编译错误也会出现在这个界面上。

到目前为止,光是我介绍的这些功能就应该足以把Tilt列入你的测试工具清单,对吗?但让我们再深入了解一下。

容器

现在让我们改进一下我们的环境。我们将增加为我们的微服务自动创建和更新容器的能力,而不是在本地运行二进制文件。毕竟,它们应该在生产环境中以这种方式运行。 新版本的Tiltfile ,看起来是这样的:

local_resource(
    'auth-compile',
    cmd='cd auth; CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/auth main.go',
    deps=['auth/main.go', 'auth/security', 'auth/user', 'pkg'],
)

docker_build(
    'auth-image',
    './auth',
    dockerfile='auth/Dockerfile',
)

local_resource(
    'feedbacks-compile',
    cmd='cd feedbacks; CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/feedbacks main.go',
    deps=['feedbacks/main.go', 'feedbacks/feedback', 'pkg'],
)

docker_build(
    'feedbacks-image',
    './feedbacks',
    dockerfile='feedbacks/Dockerfile',
)

local_resource(
    'votes-compile',
    cmd='cd votes; CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/votes main.go',
    deps=['votes/main.go', 'votes/vote', 'pkg'],
)

docker_build(
    'votes-image',
    './votes',
    dockerfile='votes/Dockerfile',
)

docker_compose('./docker-compose.yml')

我添加了docker_build 函数。顾名思义,它生成了容器镜像。为此,为每个微服务创建一个Dockerfile 是必要的。例如,auth 服务的镜像看起来像这样:

FROM alpine
ADD bin/auth /
EXPOSE 8081
CMD ["/auth"]

其他服务非常相似,只是改变了可执行文件的名称和端口:feedbacks 运行在端口8082votes 运行在8083

在做这个改变的时候,Tilt会警告说,必须要有一些部署容器的方法;否则,它将无法工作。一种方法是创建一个docker-compose.yml 并在docker_compose 函数中使用它。你的内容看起来像这样:

version: "3"
services:
  auth:
    image: auth-image
    ports:
      - "8081:8081"
    container_name: auth
  feedbacks:
    image: feedbacks-image
    ports:
      - "8082:8082"
    container_name: feedbacks
  votes:
    image: votes-image
    ports:
      - "8083:8083"
    container_name: votes

有了这些变化,Tilt现在可以观察到项目代码的修改,如果这些修改发生了,它就会进行编译、生成容器和更新环境的工作!

Kubernetes!

现在让我们把它变得更严肃一些!让我们让Tilt把我们的应用程序部署到Kubernetes集群上。为此,我将使用minikube,一个为开发而安装本地环境的解决方案。

在macOS上,只需运行:

brew install minikube
minikube start

现在我们已经建立了我们的集群,让我们改变我们的Tiltfile ,以反映新的环境:

load('ext://restart_process', 'docker_build_with_restart')
local_resource(
    'auth-compile',
    cmd='cd auth; CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/auth main.go',
    deps=['auth/main.go', 'auth/security', 'auth/user', 'pkg'],
)

docker_build_with_restart(
    'auth-image',
    './auth',
    dockerfile='auth/Dockerfile',
    entrypoint=['/auth'],
    live_update=[
        sync('./auth/bin/auth', '/auth'),
    ],
)

k8s_yaml('auth/kubernetes.yaml')
k8s_resource('ms-auth', port_forwards=8081,
             resource_deps=['auth-compile'])


local_resource(
    'feedbacks-compile',
    cmd='cd feedbacks; CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/feedbacks main.go',
    deps=['feedbacks/main.go', 'feedbacks/feedback', 'pkg'],
)

docker_build_with_restart(
    'feedbacks-image',
    './feedbacks',
    dockerfile='feedbacks/Dockerfile',
    entrypoint=['/feedbacks'],
    live_update=[
        sync('./feedbacks/bin/feedbacks', '/feedbacks'),
    ],
)

k8s_yaml('feedbacks/kubernetes.yaml')
k8s_resource('ms-feedbacks', port_forwards=8082,
             resource_deps=['feedbacks-compile'])


local_resource(
    'votes-compile',
    cmd='cd votes; CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o bin/votes main.go',
    deps=['votes/main.go', 'votes/vote', 'pkg'],
)

docker_build_with_restart(
    'votes-image',
    './votes',
    dockerfile='votes/Dockerfile',
    entrypoint=['/votes'],
    live_update=[
        sync('./votes/bin/votes', '/votes'),
    ],
)

k8s_yaml('votes/kubernetes.yaml')
k8s_resource('ms-votes', port_forwards=8083,
             resource_deps=['votes-compile'])

这里有很多新的东西!

第一个是load 功能,它可以加载Tilt扩展。这是一种扩展工具功能的方式,有几个可用。这里我们使用docker_build_with_restart, ,它将更新在我们Kubernetes集群内运行的容器。

另一个变化是与Kubernetes内的应用程序部署设置有关。k8s_yaml 函数指出哪个文件包含用于部署的 "配方"。而k8s_resource 函数在这里被用来将集群端口转发到我们的本地环境,使测试更加方便。

auth/kubernetes.yaml 文件的内容是:

apiVersion: v1
kind: Service
metadata:
  labels:
    app: ms-auth
  name: ms-auth
spec:
  ports:
    - port: 8081
      name: http
      protocol: TCP
      targetPort: 8081
  selector:
    app: ms-auth
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ms-auth
  labels:
    app: ms-auth
spec:
  selector:
    matchLabels:
      app: ms-auth
  template:
    metadata:
      labels:
        app: ms-auth
    spec:
      containers:
        - name: ms-auth
          image: auth-image
          ports:
            - containerPort: 8081

其他文件实际上是一样的,只是改变了二进制文件的名称和端口。

现在,Tilt为我们完成了所有繁重的工作。

要检查我们的微服务是否在集群上运行,我们可以使用命令:

kubectl get pods -n default
NAME                          READY   STATUS    RESTARTS   AGE
ms-auth-7446897869-89r2j      1/1     Running   0          81s
ms-feedbacks-b5df67d6-wzbj2   1/1     Running   0          81s
ms-votes-76565ddc9c-nkkt7     1/1     Running   0          81s

结论

我不知道我是否成功地展示了我对这个工具有多兴奋!我已经用Tilt做了一段时间了。

我在一个复杂的项目上使用Tilt几周了,创建了一个Kubernetes控制器。由于所有这些自动化,我可以专注于应用逻辑,而其他部分则自动完成。这就节省了大量的时间。