学习 Dapr 的开发
Dapr开发学习
- 1: 准备工作
- 1.1: Fork Dapr相关的仓库
- 1.2: 安装golang
- 1.3: 安装jdk/maven等
- 1.4: 安装配置IDE
- 1.5: 为lint做准备
- 1.6: 安装Protoc
- 2: dapr各项目的构建
- 2.1: kit项目的构建
- 2.2: components-contrib项目的构建
- 2.3: dapr项目的构建
- 2.4: go-sdk项目的构建
- 2.5: java-sdk项目的构建
- 2.5.1: Java SDK的proto代码生成
- 3: 构建原生开发环境
- 3.1: Linux amd64
- 3.1.1: 开发
- 3.1.2: 原生运行daprd
- 3.1.3: 在容器中运行daprd
- 3.1.4: 在容器中运行外部组件
- 3.1.5: 在k8s上debug控制平面
- 3.2: 使用M1芯片的Macos
- 4: 构建远程开发环境
- 4.1: goland远程开发环境
- 4.2: vscode远程开发环境
- 5: 构建混合开发环境
1 - 准备工作
1.1 - Fork Dapr相关的仓库
将 https://github.com/dapr/ 组织下的各个需要用到的仓库都 fork 一遍,如:
- https://github.com/skyao/dapr
- https://github.com/skyao/components-contrib
- https://github.com/skyao/kit
- https://github.com/skyao/go-sdk/
- https://github.com/skyao/java-sdk/
以及一些部分同学可能不需要关注的仓库:
如果已经 fork 了,注意 master 分支到最新(GitHub 页面上点 “Fetch upstream” 即可)。
注意:绝对不要在 master 分支上直接修改代码。
1.2 - 安装golang
版本要求
dapr 对 golang 的版本一直要求比较高,基本上是用最新版本的 golang。
具体版本要求可以查看 dapr 下的 go.mod 中的要求,如:
https://github.com/dapr/dapr/blob/master/go.mod
module github.com/dapr/dapr
go 1.20
require (......)
下载安装golang
在golang官方下载地址下载安装对应的版本即可。
安装方式参考官方安装文档:
1.3 - 安装jdk/maven等
如果需要开发 dapr java-sdk,则需要安装 Java SDK。
为了方便在多个 JDK 版本中切换,建议采用 sdkman 来管理 JDK 版本。
安装 sdkman
参考:
- https://skyao.io/learning-ubuntu-server/docs/development/common/sdkman.html
- https://skyao.io/learning-macos/docs/programing/common/sdkman.html
判断需要的 jdk 版本
参考java sdk 项目的 maven pom 文件设定:
https://github.com/dapr/java-sdk/blob/master/pom.xml
对 java source 和 target 的要求都是8,也就是 Java 8
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
安装 jdk 版本
TBD
sdk list java
sdk install java 11.0.20-zulu
安装 mvn
1.4 - 安装配置IDE
goland
IDEA 系列,一直都很好用。我长期使用 goland。
但最近为了 remote ssh改用vs code了。
备注: IDEA 系列的 remote ssh 模式是真的很难用
vs code
为了更好的利用 macbook pro m1 max ,remote ssh模式成为刚需。
在 IDEA remote ssh 不给力的情况下,只好改用 vs code。
VS code 的 remote ssh 是真方便,相比之下 IDEA 的复杂设置强太多了。
1.5 - 为lint做准备
golangci-lint
amd64 机器上安装
适用于 amd64 linux 和 macOS。
dapr提供了 make lint
target 来执行 golangci-lint, 如果没有安装 golangci-lint 则会报错:
$ cd dapr
$ make lint
golangci-lint run --timeout=20m
make: golangci-lint: No such file or directory
make: *** [Makefile:341: lint] Error 127
之前 dapr 用的是 v1.31 老版本,在2022年5月之后, dapr CI 中采用的是最新版本,具体是 golangci-lint v1.51.2。
TIPs: 如何知道 dapr 目前采用的是哪个版本的 golangci-lint?
请查看 dapr 仓库下的 Makefile 文件,找到下述内容:
Please use golangci-lint version v1.51.2 , otherwise you might encounter errors.
查看 .github/workflows/dapr.yml 文件,找到下述内容:
GOLANGCILINT_VER: “v1.51.2”
安装方式参考 https://golangci-lint.run/usage/install/ 。在release页面找到对应版本,主要不要直接安装最新版本:
https://github.com/golangci/golangci-lint/releases/tag/v1.51.2
linux下执行如下命令:
$ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.51.2 # 特别注意这里一定要指定正确的版本
golangci/golangci-lint info checking GitHub for tag 'v1.51.2'
golangci/golangci-lint info installed /home/sky/work/soft/gopath/bin/golangci-lint
$ golangci-lint --version
golangci-lint has version 1.51.2 built from 3e8facb4 on 2023-02-19T21:43:54Z
切记
golangci-lint 一定要安装对应的版本!m1 macbook上安装
在 m1 macbook 上, dapr之前使用的 1.31 版本发布较早,没有提供对 m1 (也就是darwin-arm64)的支持,但最新的dapr改用 1.45.2 版本之后就支持 arm64 了,所以可以用同样的方式安装:
$ curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.52.1
golangci/golangci-lint info checking GitHub for tag 'v1.52.1'
golangci/golangci-lint info found version: 1.52.1 for v1.52.1/linux/amd64
golangci/golangci-lint info installed /home/sky/work/soft/gopath/bin/golangci-lint
$ golangci-lint --version
golangci-lint has version 1.52.1 built with go1.20.2 from d92b38cc on 2023-03-21T19:48:38Z
注意:golangci-lint 新版本似对 go 有版本要求,如果遇到报错,如我在 golang 1.17 版本下运行会报错:
$ golangci-lint --version
panic: load embedded ruleguard rules: rules/rules.go:13: can't load fmt
goroutine 1 [running]:
github.com/go-critic/go-critic/checkers.init.22()
github.com/go-critic/go-critic@v0.6.2/checkers/embedded_rules.go:46 +0x494
$ go version
go version go1.17.8 darwin/arm64
升级 golang 到新版本如 1.18 就正常了。
gofumpt
运行 lint 之后如果发现 File is not
gofumpt-ed
:
$ make lint
golangci-lint run --timeout=20m
tests/perf/utils/grpc_helpers.go:4 gofumpt File is not `gofumpt`-ed
tests/perf/utils/grpc_helpers.go:9 gofumpt File is not `gofumpt`-ed
则需要安装 gofumpt 进行文件格式,参考 https://github.com/mvdan/gofumpt :
$ go install mvdan.cc/gofumpt@latest
go: downloading golang.org/x/sync v0.0.0-20220819030929-7fc1605a5dde
go: downloading golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
然后对有问题的文件执行 gofumpt :
gofumpt -w tests/perf/utils/grpc_helpers.go
goimports
运行 lint 之后如果发现 File is not
goimports-ed
:
$ make lint
golangci-lint run --timeout=20m
tests/perf/utils/grpc_helpers.go:5 goimports File is not `goimports`-ed with -local github.com/dapr/
则需要安装 goimports 对import内容进行文件格式:
go get golang.org/x/tools/cmd/goimports
手工执行
$ goimports -e -d -local github.com/dapr/ tests/perf/utils/grpc_helpers.go
diff -u tests/perf/utils/grpc_helpers.go.orig
tests/perf/utils/grpc_helpers.go
--- tests/perf/utils/grpc_helpers.go.orig 2022-04-08 22:47:08.199473748 +0800
+++ tests/perf/utils/grpc_helpers.go 2022-04-08 22:47:08.199473748 +0800
@@ -4,10 +4,11 @@
"context"
"time"
- v1 "github.com/dapr/dapr/pkg/proto/common/v1"
- runtimev1pb "github.com/dapr/dapr/pkg/proto/runtime/v1"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/anypb"
+
+ v1 "github.com/dapr/dapr/pkg/proto/common/v1"
+ runtimev1pb "github.com/dapr/dapr/pkg/proto/runtime/v1"
)
$ goimports -w tests/perf/utils/grpc_helpers.go
配置 goland 自动执行
参考下面文章的建议:
需要修改的地方有几个,打开 goland 的 settings:
-
“Action on Save” 中,勾选 “reformat code” 和 “Optimize imports”
-
“Code Style” -> “Go” -> “Import” 中,“sorting by” 下拉框默认是 “gofmt”,修改为 “goimports”,然后勾选相关的选项
-
“Code Style” -> “Go” -> “other” 中, 勾选 “add a leading space to comments”,这会在注释内容前加一个空格
配置vs code
参考: Formatting Go code with goimports (hyr.mn)
打开 File -> Preferences -> Settings, 搜索 “format on save”,勾选:
搜索 go:format,在 format tool 中选择 goimports:
注意:
- 如果 go:format 搜索时找不到 extends / go,则应该是没有安装 go extensin,或者安装之后没有重启 vs code
- 下拉框选 goimports 时如果报错没有安装 goimports,点安装即可
参考资料
1.6 - 安装Protoc
Dapr 新版本中对proto文件的代码生成有了极大改进,非常方便。
Dapr 新版本中proto文件的代码生成可以简单参考官方 README 文件的说明:
https://github.com/dapr/dapr/tree/master/dapr
步骤一:安装Protoc
目前 daprd 要求的版本是 [v3.21.12 ](https://github.com/protocolbuffers/protobuf/releases/tag/v21.12)。
linux-amd64 安装
如果之前安装过其他,则需要删除已经安装的版本:
sudo rm -rf /usr/local/include/google/protobuf/
sudo rm /usr/local/bin/protoc
下载并解压缩之后,按照 readme.txt 文件的提示,复制bin文件和clude目录到合适的位置:
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-linux-x86_64.zip
$ unzip protoc-21.12-linux-x86_64.zip
$ sudo cp -r include/google/ /usr/local/include/
# 需要设置权限可读和可执行,755
$ sudo chmod -R 755 /usr/local/include/google
$ sudo cp bin/protoc /usr/local/bin/
$ sudo chmod +x /usr/local/bin/protoc
验证安装结果:
$ protoc --version
libprotoc 3.21.12
Macos-amd64 安装
备注:不再更新,我已经没有intel cpu的macos了。
Macos-arm64 安装
如果之前安装过其他,则需要删除已经安装的版本:
sudo rm -rf /usr/local/include/google/protobuf/
sudo rm /usr/local/bin/protoc
下载 pr
$ wget https://github.com/protocolbuffers/protobuf/releases/download/v21.12/protoc-21.12-osx-aarch_64.zip
$ unzip protoc-21.12-osx-aarch_64.zip
$ sudo cp -r include/ /usr/local/include/
# 需要设置权限可读和可执行,755
$ sudo chmod -R 755 /usr/local/include/google
$ sudo cp bin/protoc /usr/local/bin/
$ sudo chmod +x /usr/local/bin/protoc
如果遇到macos禁止protoc运行,在设置中找到 “security & Privacy”,会有 protoc 运行的提示,点击容许即可。
protoc 安装完成之后,验证一下版本:
$ protoc --version
libprotoc 3.21.12
步骤二:初始化proto工具
安装 protoc-gen-go 和 protoc-gen-go,dapr的 make file 为此准备了专门的命令 init-proto
:
# 进入 dapr/dapr 仓库
$ cd dapr
$ make init-proto
go install google.golang.org/protobuf/cmd/protoc-gen-go@v1.28.1
go install google.golang.org/grpc/cmd/protoc-gen-go-grpc@v1.2.0
步骤三:从proto生成代码
终于可以开始正式的代码生成了,dapr的 make file 也为此准备了专门的命令 gen-proto
:
# 进入 dapr/dapr 仓库
$ cd dapr
$ make gen-proto
protoc --go_out=. --go_opt=module=github.com/dapr/dapr --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false,module=github.com/dapr/dapr ./dapr/proto/common/v1/*.proto
protoc --go_out=. --go_opt=module=github.com/dapr/dapr --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false,module=github.com/dapr/dapr ./dapr/proto/internals/v1/*.proto
protoc --go_out=. --go_opt=module=github.com/dapr/dapr --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false,module=github.com/dapr/dapr ./dapr/proto/operator/v1/*.proto
protoc --go_out=. --go_opt=module=github.com/dapr/dapr --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false,module=github.com/dapr/dapr ./dapr/proto/placement/v1/*.proto
protoc --go_out=. --go_opt=module=github.com/dapr/dapr --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false,module=github.com/dapr/dapr ./dapr/proto/runtime/v1/*.proto
protoc --go_out=. --go_opt=module=github.com/dapr/dapr --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false,module=github.com/dapr/dapr ./dapr/proto/sentry/v1/*.proto
go mod tidy
执行 git status
命令,对比一下新生成的代码和dapr 仓库中已经保存的代码,如果代码没有改动说明我们的protoc代码生成和dapr项目保持一致了。
常见错误
找不到共享文件
报错如下:
$ make gen-proto
protoc --go_out=. --go_opt=module=github.com/dapr/dapr --go-grpc_out=. --go-grpc_opt=require_unimplemented_servers=false,module=github.com/dapr/dapr ./dapr/proto/common/v1/*.proto
google/protobuf/any.proto: File not found.
dapr/proto/common/v1/common.proto:10:1: Import "google/protobuf/any.proto" was not found or had errors.
dapr/proto/common/v1/common.proto:55:3: "google.protobuf.Any" is not defined.
dapr/proto/common/v1/common.proto:76:3: "google.protobuf.Any" is not defined.
make: *** [Makefile:260:gen-proto-common] 错误 1
这个错误发生的原因通常是 protoc 安装时的 include 文件未能放置好,或者是相关的目录没有权限。经测试验证需要读和可执行权限,因此设置755:
# 需要设置权限可读和可执行,755
$ sudo chmod -R 755 /usr/local/include/google
2 - dapr各项目的构建
2.1 - kit项目的构建
在终端中执行以下命令:
make go.mod
make test
make lint
make check-diff
2.2 - components-contrib项目的构建
components-contrib
在终端中执行以下命令:
make go.mod
make modtidy-all
make test
make lint
make check-mod-diff
备注: conf-tests 和 e2e-tests-zeebe 在本地是跑不起来的。
2.3 - dapr项目的构建
在终端中构建
在终端中执行以下命令:
make modtidy
make modtidy-all
make test
make lint
make check-diff
备注: conf-tests 和 e2e-tests-zeebe 在本地是跑不起来的。
在vs code中构建
设置 build tag
在 vs code 中打开 dapr/dapr 项目之后,会遇到报错:
原因是。MockActors 定义在 pkg/actors/actors_mock.go
这个文件中,但它的 build tag 设置为 unit,而默认 vs code 没有使用 build tag,所以这个 MockActors 文件不在编译范围内,导致使 MockActors 的其他 go 文件报错。
解决方式是设置 vs code 的 build tags(以及test tags),打开 (如果没有就新建)项目根目录下的 .vscoee/settings.json
,加入以下内容:
{
......
"go.buildFlags": [
"-tags=unit,e2e"
],
"go.testTags": "unit,e2e",
}
正常就立即生效,错误消失。如果没有,则重启 vscode 看是否生效。
2.4 - go-sdk项目的构建
在终端中执行以下命令:
make tidy
make test
make lint
make check-diff
2.5 - java-sdk项目的构建
2.5.1 - Java SDK的proto代码生成
从 dapr java sdk 仓库 clone下来代码之后,直接用IDE 如 IntelliJ 导入,是会报错的:有部分 dapr 的类找不到。这是因为这些代码是需要从 dapr 的 proto 代码中临时生成然后被项目装载。因此如果要进行 dapr java sdk 项目的开发或者代码阅读,需要从proto文件中生成这些类。
备注:
不同语言的sdk对生成代码的处理方式不同:
- java sdk:采用的是不保存生成的代码到git仓库,每次需要的时候从proto文件生成,然后以 generated-sources 的方式被挂载到 mvn 项目中。
- go sdk:有些语言的sdk如 go sdk,是将生成的代码直接提交到git仓库,这样如果不需要重新生成代码,是可以clone下来仓库就直接可以使用和阅读的。
准备protoc等工具
安装Protoc,目前 daprd 要求的版本是 v3.14.0。sdk 和 daprd保持一致。
具体见准备工作中的 安装Protoc
从proto文件生成Java代码
在 dapr java sdk 项目下,有名为 sdk-augogen
的子项目,在这里执行 generate-sources
命令就可以生成对应的java类:
$ cd sdk-augogen
$ mvn generate-sources
代码生成的过程有几个主要步骤:
步骤1: 下载proto文件
从命令输出中能看到,maven会下载三个proto文件: common.proto, dapr.proto,appcallback.proto:
[INFO] --- download-maven-plugin:1.6.0:wget (getCommonProto) @ dapr-sdk-autogen ---
[INFO] Downloading: https://raw.githubusercontent.com/dapr/dapr/4a6369caaba9cf46eae9bfa4fa6e76b474854c89/dapr/proto/common/v1/common.proto
[INFO] Downloading: https://raw.githubusercontent.com/dapr/dapr/4a6369caaba9cf46eae9bfa4fa6e76b474854c89/dapr/proto/runtime/v1/dapr.proto
[INFO] Downloading: https://raw.githubusercontent.com/dapr/dapr/4a6369caaba9cf46eae9bfa4fa6e76b474854c89/dapr/proto/runtime/v1/appcallback.proto
对照 sdk-autogen 子项目下的 pom.xml 文件,可以找到相关的maven插件配置:
<plugin>
<groupId>com.googlecode.maven-download-plugin</groupId>
<artifactId>download-maven-plugin</artifactId>
<version>1.6.0</version>
<executions>
<execution>
<id>getCommonProto</id>
<!-- the wget goal actually binds itself to this phase by default -->
<phase>initialize</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>${dapr.proto.baseurl}/common/v1/common.proto</url>
<outputFileName>common.proto</outputFileName>
<!-- default target location, just to demonstrate the parameter -->
<outputDirectory>${protobuf.input.directory}/dapr/proto/common/v1</outputDirectory>
</configuration>
</execution>
<execution>
<id>getDaprProto</id>
<!-- the wget goal actually binds itself to this phase by default -->
<phase>initialize</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>${dapr.proto.baseurl}/runtime/v1/dapr.proto</url>
<outputFileName>dapr.proto</outputFileName>
<!-- default target location, just to demonstrate the parameter -->
<outputDirectory>${protobuf.input.directory}</outputDirectory>
</configuration>
</execution>
<execution>
<id>getDaprClientProto</id>
<!-- the wget goal actually binds itself to this phase by default -->
<phase>initialize</phase>
<goals>
<goal>wget</goal>
</goals>
<configuration>
<url>${dapr.proto.baseurl}/runtime/v1/appcallback.proto</url>
<outputFileName>appcallback.proto</outputFileName>
<!-- default target location, just to demonstrate the parameter -->
<outputDirectory>${protobuf.input.directory}</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
在这里特别要注意的是 ${dapr.proto.baseurl}
,这个属性在根目录下的 pom.xml 中设置,比如我当前版本的值是:
<dapr.proto.baseurl>
https://raw.githubusercontent.com/dapr/
dapr/4a6369caaba9cf46eae9bfa4fa6e76b474854c89/dapr/proto
</dapr.proto.baseurl>
这意味着如果要针对某个版本的 proto 文件进行代码生成,则需要修改这里的 ${dapr.proto.baseurl}
的值,比如指向某个分支/tag或者如上面指向某个commit。
步骤2: 生成代码
protoc-jar-maven-plugin 插件负责将前面下载的proto文件生成java 代码,生成之后的代码存在的 target/generated-sources
目录下:
[INFO] --- protoc-jar-maven-plugin:3.11.4:run (default) @ dapr-sdk-autogen ---
[INFO] Protoc version: 3.13.0
protoc-jar: protoc version: 3.13.0, detected platform: osx-x86_64 (mac os x/x86_64)
protoc-jar: cached: /var/folders/vr/8yl21p696dd41c776p67qlkm0000gp/T/protocjar.webcache/com/google/protobuf/protoc/maven-metadata.xml
protoc-jar: cached: /var/folders/vr/8yl21p696dd41c776p67qlkm0000gp/T/protocjar.webcache/com/google/protobuf/protoc/3.13.0/protoc-3.13.0-osx-x86_64.exe
protoc-jar: executing: [/var/folders/vr/8yl21p696dd41c776p67qlkm0000gp/T/protocjar852218627845177615/bin/protoc.exe, --version]
libprotoc 3.13.0
[INFO] Processing (grpc-java): dapr.proto
[INFO] Processing (grpc-java): common.proto
[INFO] Processing (grpc-java): appcallback.proto
[INFO] Adding generated sources (java): /Users/sky/work/code/skyao/java-sdk/sdk-autogen/target/generated-sources
[INFO] Adding generated sources (grpc-java): /Users/sky/work/code/skyao/java-sdk/sdk-autogen/target/generated-sources
[INFO] BUILD SUCCESS
刷新项目,比如 idea 下可以在 java-sdk 根目录下pom.xml上右键 maven -> reload project 。
相关的文件路径小结
一目了然:
遇到过的问题
proto文件缓存
有一个比较坑的事情是,download-maven-plugin 插件在下载文件时,不是每次都去请求,有时会从maven本地缓存中拿文件。
比如我某次被坑的时候,就发现有如下日志:
[INFO] --- download-maven-plugin:1.6.0:wget
[INFO] Got from cache: /Users/sky/.m2/repository/.cache/download-maven-plugin/common.proto_d701b2bbc1c789dfa25b99c95a8cd8c2
[INFO] Got from cache: /Users/sky/.m2/repository/.cache/download-maven-plugin/dapr.proto_372181342afa932d4684925872c96d22
[INFO] Got from cache: /Users/sky/.m2/repository/.cache/download-maven-plugin/appcallback.proto_e110e7ac8ee53213ecf133574e146d64
[INFO]
这个缓存会导致拿到的 proto 文件和原来期望的proto文件内容可能不一样,因此后面生成的代码也会有偏差,某些情况下就会出现代码编译不过,错误可能是某个类或者某个方法找不到。
这个时候最简单的办法就是删除这个缓存目录,让 maven 去远程下载,然后再重新生成:
rm -rf ~/.m2/repository/.cache/download-maven-plugin/
mvn generate-sources
Error extracting protoc for version 3.17.3 错误
在配置 Artifactory 开启 mirror 之后,遇到一个奇怪的问题:
[ERROR] Failed to execute goal com.github.os72:protoc-jar-maven-plugin:3.11.4:run (default) on project dapr-sdk-autogen: Error extracting protoc for version 3.17.3: Unsupported platform: protoc-3.17.3-linux-x86_64.exe -> [Help 1]
org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal com.github.os72:protoc-jar-maven-plugin:3.11.4:run (default) on project dapr-sdk-autogen: Error extracting protoc for version 3.17.3
at org.apache.maven.lifecycle.internal.MojoExecutor.doExecute (MojoExecutor.java:306)
at org.apache.maven.lifecycle.internal.MojoExecutor.execute (MojoExecutor.java:211)
......
Caused by: org.apache.maven.plugin.MojoExecutionException: Error extracting protoc for version 3.17.3
......
Caused by: java.io.FileNotFoundException: Unsupported platform: protoc-3.17.3-linux-x86_64.exe
......
修改 maven settings.xml ,不使用 artifactory 而是直接连接 maven 中央仓库,就可以回避这个问题。
参考: https://github.com/os72/protoc-jar-maven-plugin/issues/68
3 - 构建原生开发环境
3.1 - Linux amd64
3.1.1 - 开发
编码
通过 replace 引用修改的代码
以 dapr 仓库 和 components-contrib 仓库为例,如果我们在本地修改了 components-contrib 仓库的代码,然后希望在 dapr 仓库中使用这些修改后的代码,则可以修改 dapr 仓库中的 go.mod 文件,将对 components-contrib 仓库的依赖进行 replace 。
如果目标代码还没有提交到 github,则 replace 为 components-contrib 仓库的本地目录,如:
replace github.com/dapr/components-contrib => /home/sky/work/code/dapr-fork/components-contrib
如果代码已经提交到 github 仓库,则可以指定要 replace 的仓库、分支和commit:
replace github.com/dapr/components-contrib => github.com/skyao/components-contrib v1.7.1-0.20220418003919-48d8dbd6dfc8
后面这个方案适合在提交跨多个仓库的pr时使用。
测试
本地跑单元测试:
make test
e2e 测试和性能测试等运行比较麻烦,单独在测试篇中讲。
打包
构建二进制包
在 dapr/dapr 仓库下执行 make build
命令:
$ make build
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-X github.com/dapr/dapr/pkg/version.gitcommit=b298e16f6bd641545c1b76b074b622578989f171 -X github.com/dapr/dapr/pkg/version.gitversion=v1.7.0-rc.4-34-gb298e16-dirty -X github.com/dapr/dapr/pkg/version.version=edge -X github.com/dapr/kit/logger.DaprVersion=edge -s -w" -o ./dist/linux_amd64/release/daprd ./cmd/daprd/;
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-X github.com/dapr/dapr/pkg/version.gitcommit=b298e16f6bd641545c1b76b074b622578989f171 -X github.com/dapr/dapr/pkg/version.gitversion=v1.7.0-rc.4-34-gb298e16-dirty -X github.com/dapr/dapr/pkg/version.version=edge -X github.com/dapr/kit/logger.DaprVersion=edge -s -w" -o ./dist/linux_amd64/release/placement ./cmd/placement/;
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-X github.com/dapr/dapr/pkg/version.gitcommit=b298e16f6bd641545c1b76b074b622578989f171 -X github.com/dapr/dapr/pkg/version.gitversion=v1.7.0-rc.4-34-gb298e16-dirty -X github.com/dapr/dapr/pkg/version.version=edge -X github.com/dapr/kit/logger.DaprVersion=edge -s -w" -o ./dist/linux_amd64/release/operator ./cmd/operator/;
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-X github.com/dapr/dapr/pkg/version.gitcommit=b298e16f6bd641545c1b76b074b622578989f171 -X github.com/dapr/dapr/pkg/version.gitversion=v1.7.0-rc.4-34-gb298e16-dirty -X github.com/dapr/dapr/pkg/version.version=edge -X github.com/dapr/kit/logger.DaprVersion=edge -s -w" -o ./dist/linux_amd64/release/injector ./cmd/injector/;
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-X github.com/dapr/dapr/pkg/version.gitcommit=b298e16f6bd641545c1b76b074b622578989f171 -X github.com/dapr/dapr/pkg/version.gitversion=v1.7.0-rc.4-34-gb298e16-dirty -X github.com/dapr/dapr/pkg/version.version=edge -X github.com/dapr/kit/logger.DaprVersion=edge -s -w" -o ./dist/linux_amd64/release/sentry ./cmd/sentry/;
生成的二进制文件存放在 dist/linux_amd64
目录下:
构建dapr容器
先设置 dapr 相关的环境变量:
export DAPR_TAG=dev
export DAPR_REGISTRY=docker.io/skyao
在 dapr/dapr 仓库下执行 make docker-build
命令:
$ make docker-build
Building docker.io/skyao/dapr:dev docker image ...
docker build --build-arg PKG_FILES=* -f ./docker/Dockerfile ./dist/linux_amd64/release -t docker.io/skyao/dapr:dev-linux-amd64
Sending build context to Docker daemon 236.4MB
Step 1/4 : FROM gcr.io/distroless/static:nonroot
---> bbd57f9cdb20
Step 2/4 : ARG PKG_FILES
---> Using cache
---> 0072a00d6320
Step 3/4 : WORKDIR /
---> Using cache
---> 01a8cf2e1345
Step 4/4 : COPY /$PKG_FILES /
---> Using cache
---> 42555e58ba97
Successfully built 42555e58ba97
Successfully tagged skyao/dapr:dev-linux-amd64
docker build --build-arg PKG_FILES=daprd -f ./docker/Dockerfile ./dist/linux_amd64/release -t docker.io/skyao/daprd:dev-linux-amd64
Sending build context to Docker daemon 236.4MB
Step 1/4 : FROM gcr.io/distroless/static:nonroot
---> bbd57f9cdb20
Step 2/4 : ARG PKG_FILES
---> Using cache
---> 0072a00d6320
Step 3/4 : WORKDIR /
---> Using cache
---> 01a8cf2e1345
Step 4/4 : COPY /$PKG_FILES /
---> Using cache
---> 3d189af067d0
Successfully built 3d189af067d0
Successfully tagged skyao/daprd:dev-linux-amd64
docker build --build-arg PKG_FILES=placement -f ./docker/Dockerfile ./dist/linux_amd64/release -t docker.io/skyao/placement:dev-linux-amd64
Sending build context to Docker daemon 236.4MB
Step 1/4 : FROM gcr.io/distroless/static:nonroot
---> bbd57f9cdb20
Step 2/4 : ARG PKG_FILES
---> Using cache
---> 0072a00d6320
Step 3/4 : WORKDIR /
---> Using cache
---> 01a8cf2e1345
Step 4/4 : COPY /$PKG_FILES /
---> Using cache
---> 18f7e2261d82
Successfully built 18f7e2261d82
Successfully tagged skyao/placement:dev-linux-amd64
docker build --build-arg PKG_FILES=sentry -f ./docker/Dockerfile ./dist/linux_amd64/release -t docker.io/skyao/sentry:dev-linux-amd64
Sending build context to Docker daemon 236.4MB
Step 1/4 : FROM gcr.io/distroless/static:nonroot
---> bbd57f9cdb20
Step 2/4 : ARG PKG_FILES
---> Using cache
---> 0072a00d6320
Step 3/4 : WORKDIR /
---> Using cache
---> 01a8cf2e1345
Step 4/4 : COPY /$PKG_FILES /
---> Using cache
---> 10523d0ff4a5
Successfully built 10523d0ff4a5
Successfully tagged skyao/sentry:dev-linux-amd64
生成的镜像文件可以通过 docker images
命令查看:
$ docker images
REPOSITORY TAG IMAGE ID CREATED SIZE
skyao/sentry dev-linux-amd64 10523d0ff4a5 2 days ago 39.4MB
skyao/placement dev-linux-amd64 18f7e2261d82 2 days ago 17MB
skyao/daprd dev-linux-amd64 3d189af067d0 2 days ago 113MB
skyao/dapr dev-linux-amd64 42555e58ba97 2 days ago 239MB
3.1.2 - 原生运行daprd
运行二进制文件
daprd的二进制文件可以来自从源码编译的 dist/release
目录下,也可以来自通过 dapr cli 安装的 daprd。大多数情况下我们在开发时是运行刚编译出来的daprd 二进制文件。
Daprd 在运行时,通常需要和业务应用一起启动,需要和配置的外部组件相互连接,有些功能还需要 dapr 控制面的配合。
最小依赖运行
这是启动 daprd 最简单的方式,只需要指定 app-id
和 components-path
(里面为空,不配置component):
$ ./dist/linux_amd64/release/daprd --components-path=./dist/components --app-id=app1
INFO[0000] starting Dapr Runtime -- version edge -- commit b298e16f6bd641545c1b76b074b622578989f171 app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] log level set to: info app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] metrics server started on :9090/ app_id=app1 instance=skywork scope=dapr.metrics type=log ver=edge
INFO[0000] loading default configuration app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] standalone mode configured app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] app id: app1 app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] mTLS is disabled. Skipping certificate request and tls validation app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] local service entry announced: app1 -> 192.168.100.10:35921 app_id=app1 instance=skywork scope=dapr.contrib type=log ver=edge
INFO[0000] Initialized name resolution to mdns app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] loading components app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] waiting for all outstanding components to be processed app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] all outstanding components processed app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] gRPC proxy enabled app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] enabled gRPC tracing middleware app_id=app1 instance=skywork scope=dapr.runtime.grpc.api type=log ver=edge
INFO[0000] enabled gRPC metrics middleware app_id=app1 instance=skywork scope=dapr.runtime.grpc.api type=log ver=edge
INFO[0000] API gRPC server is running on port 50001 app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] enabled metrics http middleware app_id=app1 instance=skywork scope=dapr.runtime.http type=log ver=edge
INFO[0000] enabled tracing http middleware app_id=app1 instance=skywork scope=dapr.runtime.http type=log ver=edge
INFO[0000] http server is running on port 3500 app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] The request body size parameter is: 4 app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] enabled gRPC tracing middleware app_id=app1 instance=skywork scope=dapr.runtime.grpc.internal type=log ver=edge
INFO[0000] enabled gRPC metrics middleware app_id=app1 instance=skywork scope=dapr.runtime.grpc.internal type=log ver=edge
INFO[0000] internal gRPC server is running on port 35921 app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
WARN[0000] app channel is not initialized. did you make sure to configure an app-port? app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
WARN[0000] failed to init actors: no actor state store defined app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
WARN[0000] failed to read from bindings: app channel not initialized app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
INFO[0000] dapr initialized. Status: Running. Init Elapsed 2.781127ms app_id=app1 instance=skywork scope=dapr.runtime type=log ver=edge
如果需要启动指定的 component ,则需要在通过 --components-path
指定的目录下(如./dist/components
)放置对应的 yaml 文件。
依赖外部组件
当测试某些构建块的功能时,如 state / pubsub 等,流程比较简单,本机开发时只需要在本机将对应的组件的外部依赖启动起来,然后在 daprd 将配置好 component 的 yaml 文件放置在 --components-path
指定的目录下(如./dist/components
) 即可。
需要和业务App互动
TBD
需要dapr控制平面
TBD
在IDE中运行
最小依赖运行
在 IDE (如 goland) 中启动 daprd 的方式是打开 cmd/daprd/main.go
文件,然后运行,注意也要配置最基本的参数如 app-id
和 components-path
。
以 goland 为例:
运行日志如下:
GOROOT=/usr/local/go #gosetup
GOPATH=/home/sky/work/soft/gopath #gosetup
/usr/local/go/bin/go build -o /tmp/GoLand/___daprd github.com/dapr/dapr/cmd/daprd #gosetup
/tmp/GoLand/___daprd --app-id=app1 --components-path=./dist/components
INFO[0000] starting Dapr Runtime -- version edge -- commit app_id=app1 instance=skywork scope=dapr.runtime type=log ver=unknown
......
在 IDE 中用这种方式运行 daprd,最大的优势在于可以 debug!
3.1.3 - 在容器中运行daprd
3.1.4 - 在容器中运行外部组件
本地开发时,各个组件只需要使用最简单的部署方案即可。
redis
执行下面命令,指定端口映射和访问密码:
docker run -d -p 6379:6379 redis --requirepass "abc123"
可以看到后台启动的 redis 进行:
ps -ef | grep redis
999 3348 3327 0 14:18 ? 00:00:12 redis-server *:6379
然后就可以配置基于 redis 的 component,如 state:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: statestore
spec:
type: state.redis
version: v1
initTimeout: 1m
metadata:
- name: redisHost
value: localhost:6379
- name: redisPassword
value: abc123
- name: actorStateStore
value: true
kafka
kafka 相对 redis 要麻烦一些,因为 kafka 需要 zookeeper。因此需要使用 docker-compose 工具来启动多个 container。
https://github.com/conduktor/kafka-stack-docker-compose
这里有配置好的多种 kafka 方案,我们可以选择最简单的一种,zk-single-kafka-single
$ wget https://github.com/conduktor/kafka-stack-docker-compose/blob/master/zk-single-kafka-single.yml
$ docker-compose -f zk-single-kafka-single.yml up -d
# 可以看到 kafka 和 zeekeeper 在运行
$ ps -ef | grep kafka
sky 3172 2436 0 18:05 pts/0 00:00:00 /usr/bin/python3 /usr/bin/docker-compose -f zk-single-kafka-single.yml up
sky 3930 3908 1 18:06 ? 00:00:04 java -Xmx512M -Xms512M -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xlog:gc*:file=/var/log/kafka/zookeeper-gc.log:time,tags:filecount=10,filesize=100M -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Dkafka.logs.dir=/var/log/kafka -Dlog4j.configuration=file:/etc/kafka/log4j.properties -cp /usr/bin/../share/java/kafka/*:/usr/bin/../share/java/confluent-telemetry/* org.apache.zookeeper.server.quorum.QuorumPeerMain /etc/kafka/zookeeper.properties
sky 4114 4090 3 18:06 ? 00:00:10 java -Xmx1G -Xms1G -server -XX:+UseG1GC -XX:MaxGCPauseMillis=20 -XX:InitiatingHeapOccupancyPercent=35 -XX:+ExplicitGCInvokesConcurrent -XX:MaxInlineLevel=15 -Djava.awt.headless=true -Xlog:gc*:file=/var/log/kafka/kafkaServer-gc.log:time,tags:filecount=10,filesize=100M -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.authenticate=false -Dcom.sun.management.jmxremote.ssl=false -Djava.rmi.server.hostname=127.0.0.1 -Dcom.sun.management.jmxremote.local.only=false -Dcom.sun.management.jmxremote.rmi.port=9999 -Dcom.sun.management.jmxremote.port=9999 -Dcom.sun.management.jmxremote.port=9999 -Dkafka.logs.dir=/var/log/kafka -Dlog4j.configuration=file:/etc/kafka/log4j.properties -cp /usr/bin/../share/java/kafka/*:/usr/bin/../share/java/confluent-telemetry/* kafka.Kafka /etc/kafka/kafka.properties
kafka 和 zookeeper 运行的端口信息可以通过下面的命令看到:
$ docker-compose -f zk-single-kafka-single.yml ps
Name Command State Ports
-------------------------------------------------------------------------------------------------------------------------------
kafka1 /etc/confluent/docker/run Up 0.0.0.0:9092->9092/tcp,:::9092->9092/tcp, 0.0.0.0:9999->9999/tcp,:::9999->9999/tcp
zoo1 /etc/confluent/docker/run Up 0.0.0.0:2181->2181/tcp,:::2181->2181/tcp, 2888/tcp, 3888/tcp
kafka 运行在 localhost:9092
。
然后就可以配置基于 kafka 的 component,如 pubsub:
apiVersion: dapr.io/v1alpha1
kind: Component
metadata:
name: pubsub
spec:
type: pubsub.kafka
version: v1
metadata:
- name: brokers
value: localhost:9092
- name: consumerGroup
value: pubsubgroup1
- name: authRequired
value: "false"
- name: initialOffset
value: oldest
- name: disableTls
value: true
参考: https://www.conduktor.io/kafka/how-to-start-kafka-using-docker
3.1.5 - 在k8s上debug控制平面
参考官方文档:
https://docs.dapr.io/developing-applications/debugging/debug-k8s/debug-dapr-services/
准备工作
打包和推送可debug的镜像
cd dapr
make release GOOS=linux GOARCH=amd64 DEBUG=1
export DAPR_TAG=dev
export DAPR_REGISTRY=docker.io/skyao
docker login
make docker-push DEBUG=1
但 docker-push 速度会很慢,非常拖累速度,本地开发和debug完全没有不要用 docker 的正式 register,完全可以本地启动一个私有的 registery 。
docker private register
运行一下命令来启动一个容器承担 docker private register 的角色,以加速镜像文件推送到 docker register 的速度,避免浪费太多时间在镜像的上传上:
docker run -d -p 5000:5000 --name registry registry:2
为了可以使用 http,而不是默认使用 https 来执行镜像推送,需要修改 docker 配置:
sudo vi /etc/docker/daemon.json
增加内容:
{
......,
"insecure-registries": [
"127.0.0.1:5000"
]
}
修改之后要重启 docker daemon,否则不生效:
sudo systemctl daemon-reload
sudo systemctl restart docker
然后再重启 registry 容器,否则无法访问:
docker restart registry
这时可以访问 http://127.0.0.1:5000/v2/ 查看是否正常工作。
此时再执行 make docker-push DEBUG=1
就非常快了:
export DAPR_TAG=dev
export DAPR_REGISTRY=127.0.0.1:5000
make docker-push DEBUG=1
参考资料:
准备 debug values 配置文件
准备一个 values-debug-templates.yaml 文件放在 dapr 仓库的 charts/dapr/
目录下,内容为:
global:
registry: "docker.io/skyao"
tag: "dev-linux-amd64"
dapr_operator:
debug:
enabled: true
runAsNonRoot: false
dapr_placement:
debug:
enabled: true
runAsNonRoot: false
dapr_sentry:
debug:
enabled: true
runAsNonRoot: false
dapr_sidecar_injector:
debug:
enabled: true
runAsNonRoot: false
sidecarRunAsNonRoot: false
一般每次我们只debug 一个控制面组件,因此上面的四段内容我们只需要用对应的其中一段即可。
如果有本地启动 docker private registry, 注意修改这里的 registry 地址:
global:
registry: "127.0.0.1:5000"
tag: "dev-linux-amd64"
......
开始 debug
debug sentry
复制 values-debug-templates.yaml 文件,改名 values-debug.yaml ,内容只保留 dapr_sentry 这一段:
global:
registry: "127.0.0.1:5000"
tag: "dev-linux-amd64"
dapr_sentry:
debug:
enabled: true
runAsNonRoot: false
安装控制面:
cd dapr
helm install dapr charts/dapr --namespace dapr-system --values charts/dapr/values-debug.yaml --wait
其中 sentry 会以 debug 模式启动,然后等待连接:
k logs -n dapr-system dapr-sentry-7d9898fdb9-rt4kj
2023-03-29T07:09:47Z warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
2023-03-29T07:09:47Z info layer=debugger launching process with args: [/sentry --log-level info --enable-metrics --metrics-port 9090 --trust-domain cluster.local]
API server listening at: [::]:40000
下面是 debug 模式启动的 sentry pod 的部分内容,可以看到容器的启动命令(/dlv)和参数(exec /sentry):
dapr-sentry:
Container ID: docker://6b1c380486b9d06c639b63f152ea5ca61a30bd740cf3cbdf4a80d899a3abb973
Image: 127.0.0.1:5000/sentry:dev-linux-amd64
Image ID: docker-pullable://127.0.0.1:5000/sentry@sha256:6625c43de22c794ca4b5e828fe18ba9ccf8d7f62a77ed143129b1a78d6e35a4c
Ports: 50001/TCP, 9090/TCP, 40000/TCP
Host Ports: 0/TCP, 0/TCP, 0/TCP
Command:
/dlv
Args:
--listen=:40000
--accept-multiclient
--headless=true
--log
--api-version=2
exec
/sentry
--
--log-level
info
--enable-metrics
--metrics-port
9090
--trust-domain
cluster.local
State: Running
Started: Wed, 29 Mar 2023 16:11:08 +0800
Ready: False
Restart Count: 0
Liveness: http-get http://:8080/healthz delay=30000s timeout=1s period=3s #success=1 #failure=5
Readiness: http-get http://:8080/healthz delay=30000s timeout=1s period=3s #success=1 #failure=5
Environment:
NAMESPACE: dapr-system (v1:metadata.namespace)
Mounts:
/var/run/dapr/credentials from credentials (ro)
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-xwc55 (ro)
此时的 dapr 控制平面状态为:
$ kubectl get pods -n dapr-system -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
dapr-dashboard-7c5c6bf5cf-rs757 1/1 Running 0 6m1s 10.244.0.104 skywork <none> <none>
dapr-operator-cbcb6c4fb-vz625 0/1 Running 6 (90s ago) 6m1s 10.244.0.102 skywork <none> <none>
dapr-placement-server-0 0/1 CrashLoopBackOff 6 (13s ago) 6m1s 10.244.0.103 skywork <none> <none>
dapr-sentry-7d9898fdb9-rt4kj 0/1 Running 0 6m1s 10.244.0.101 skywork <none> <none>
dapr-sidecar-injector-dcbd7fcbd-cj52p 1/1 Running 0 6m1s 10.244.0.105 skywork <none> <none>
做一下 dapr-sentry pod 的 debug 端口的端口映射:
$ kubectl port-forward -n dapr-system dapr-sentry-7d9898fdb9-rt4kj 40000:40000
Forwarding from 127.0.0.1:40000 -> 40000
Forwarding from [::1]:40000 -> 40000
打开 IDE,以 vs code 为例,我打开 dapr/dapr 仓库,然后设置断点为 cmd/sentry/main.go
中 main 行数的第一行,这样就可以从 sentry 启动开始 debug。
修改 lanch.json 文件,加入以下内容:
{
"version": "0.2.0",
"configurations": [
{
"name": "debug sentry",
"type": "go",
"request": "attach",
"mode": "remote",
"remotePath": "${workspaceFolder}",
"port": 40000,
"host": "127.0.0.1"
}
]
}
然后在 “Run and Debug” 中选择 “debug sentry”,点击三角形启动:
图上可以看到 debug 启动成功,代码执行停留在 main() 函数的第一行位置,后面就可以按照自己的需要进行断点设置和代码debug了。
如果要重新开始 debug (比如再次debg sentry 启动的过程),最快捷的方式是重新启动 sentry 的pod:
# 删除 dapr-sentry 的现有 pod
k delete pod -n dapr-system dapr-sentry-7d9898fdb9-rt4kj
# 稍后 k8s 会重新启动一个新的 pod,然后依然是以 debug 的方式启动
# 需要再做一次端口映射
kubectl port-forward -n dapr-system dapr-sentry-7d9898fdb9-xxxx 40000:40000
常见错误
runAsNonRoot 错误导致容器启动失败
cd dapr
helm install dapr charts/dapr --namespace dapr-system --values charts/dapr/values-debug.yaml --wait
发现 dapr 的控制面启动不起来:
$ k get pods -n dapr-system
NAME READY STATUS RESTARTS AGE
dapr-dashboard-7c5c6bf5cf-qkq9j 1/1 Running 0 7m14s
dapr-operator-684d455b4f-9gwk5 0/1 CreateContainerConfigError 0 7m14s
dapr-placement-server-0 0/1 CrashLoopBackOff 6 (78s ago) 7m14s
dapr-sentry-6b47f647bb-nr8ld 0/1 CreateContainerConfigError 0 7m14s
dapr-sidecar-injector-699dfb595f-xvgjc 0/1 CreateContainerConfigError 0 7m14s
injector 报错:
Normal Scheduled 6m25s default-scheduler Successfully assigned dapr-system/dapr-sidecar-injector-699dfb595f-xvgjc to skywork
Warning Failed 4m18s (x12 over 6m25s) kubelet Error: container has runAsNonRoot and image will run as root (pod: "dapr-sidecar-injector-699dfb595f-xvgjc_dapr-system(1643bcd9-3453-430a-b135-a48361311639)", container: dapr-sidecar-injector)
Normal Pulled 75s (x25 over 6m25s) kubelet Container image "192.168.0.90:5000/injector:dev-linux-amd64" already present on machine
这是因为容器要求 runAsNonRoot,但是 debug 打包出来的镜像要求 root。
解决方式: 在 values 文件中将 runAsNonRoot 设置为 false 来暂时避开这个问题。
sentry 调试时其他组件启动失败
k get pods -n dapr-system
NAME READY STATUS RESTARTS AGE
dapr-dashboard-7c5c6bf5cf-r5nsz 1/1 Running 0 37s
dapr-operator-6487d8f4fb-vqdnc 0/1 Running 0 37s
dapr-placement-server-0 0/1 CrashLoopBackOff 2 (19s ago) 37s
dapr-sentry-b74b47fc-sfq6f 0/1 Running 0 37s
dapr-sidecar-injector-7699f486c6-lqxs8 1/1 Running 0 37s
placement 失败的原因是:
k logs -n dapr-system dapr-placement-server-0
time="2023-03-28T15:55:27.175204696Z" level=info msg="Starting Dapr Placement Service -- version edge -- commit ccec8b8dc58f4b5e892f7806f895f6d5a85d7eeb" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=edge
time="2023-03-28T15:55:27.175289436Z" level=info msg="Log level set to: info" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=edge
time="2023-03-28T15:55:27.175357952Z" level=info msg="metrics server started on :9090/" instance=dapr-placement-server-0 scope=dapr.metrics type=log ver=edge
time="2023-03-28T15:55:27.175394106Z" level=fatal msg="open /var/run/dapr/credentials/ca.crt: no such file or directory" instance=dapr-placement-server-0 scope=dapr.placement type=log ver=edge
operator 失败的原因:
I0329 07:04:11.751075 1 leaderelection.go:248] attempting to acquire leader lease dapr-system/operator.dapr.io...
time="2023-03-29T07:04:11.852009943Z" level=info msg="Getting TLS certificates" instance=dapr-operator-6487d8f4fb-vqdnc scope=dapr.operator type=log ver=edge
time="2023-03-29T07:04:11.852046755Z" level=info msg="TLS certificate not found; waiting for disk changes. err=open /var/run/dapr/credentials/ca.crt: no such file or directory" instance=dapr-operator-6487d8f4fb-vqdnc scope=dapr.operator type=log ver=edge
time="2023-03-29T07:04:11.852065157Z" level=info msg="Starting watch for certs on filesystem: /var/run/dapr/credentials" instance=dapr-operator-6487d8f4fb-vqdnc scope=dapr.operator type=log ver=edge
3.2 - 使用M1芯片的Macos
4 - 构建远程开发环境
4.1 - goland远程开发环境
准备工作
sftp
服务器端要求安装 sftp,通常安装ssh之后就可以了,尝试用sftp命令登录试试:
$ sftp sky@192.168.0.40
Connected to 192.168.0.40.
sftp>
安装 Jetbrans Gateway
参考 https://www.jetbrains.com/help/go/remote-development-starting-page.html
在 goland 中启用 Remote Development Gateway 插件。重启 goland,就能在 goland 的欢迎界面看到 remote development 和 ssh 。
添加 ssh 登录之后:
运行
经常卡在这里,长时间等待然后报错,但有时又工作正常,快速进入ide界面。
反复测试过,不清楚原因。
这就导致每次使用时都有进不去的风险,非常头疼。
暂时没搞定。
参考
4.2 - vscode远程开发环境
准备工作
无,只要安装好 vs code 和远程服务器能支持 ssh 即可,非常方便。
运行
打开vs code,左下角点击 “open a remote windows”,然后选 “connect to host… Remote-SSH”:
输入可以连接到远程服务器的 ssh 命令即可。
也可以通过 “open ssh configurtion file” 选择修改 config 文件,比如设置 port :
Host home.yourdomain.com
HostName home.yourdomain.com
Port 34022
User sky
Host 192.168.0.40
HostName 192.168.0.40
User sky
打开 dapr 项目所在目录:
注意:plugin 要在 remote 这边再安装一次,比如最基本的 go plugin。