用 ChatGPT 写了一点代码
帮我看着点 Ingress 好吧
ChatGPT 发布之后,一直在半真半假的用着:有时候写一些代码片段,例如让他用 Python、Rust 分别帮我写一点方法级别的代码;有时候会跟他“探讨”一些问题——是的你没看错,真的是探讨一些问题,例如刚刚我跟他探讨了一下 SRE、DevOps 和平台工程的区别、联系和发展情况。总的说来,如果不求输出成品,那效果还是相当不错的,至少触发灵感是没问题的。
前些天跟蔡书夸下海口,用 ChatGPT 也能给 PP 写个 Ingress 控制器来,奈何俗务缠身,一直也没能完成,今天抽出两个小时,总算完成了一个 Ingress 监听的原型代码。大体过程讲解一下。
我的第一个 Prompt:
我想用循序渐进的方式逐步用 Golang 开发一个 Ingress 控制器,我想到的步骤包括:
1. 创建目录布局
2. 编写第一个可执行的控制台应用的圆形,并完成构建和测试运行
3. 在这个原型基础上,加入连接 Kubernetes 集群的能力,同样完成构建和运行
4. 加入 Watch Ingress 对象的能力。并在 Ingress 发生变化的时候输出提示信息。
首先我们完成第一个步骤,使用 shell 命令创建对应的目录结构。
是的,你没看错,我连目录结构都让他给我创建。ChatGPT 的回复很不错——必须很不错,这个太简单了:
mkdir -p my-ingress-controller/cmd/my-ingress-controller
mkdir -p my-ingress-controller/pkg/ingress
mkdir -p my-ingress-controller/pkg/kube
touch my-ingress-controller/cmd/my-ingress-controller/main.go
touch my-ingress-controller/pkg/ingress/ingress.go
touch my-ingress-controller/pkg/kube/kube.go
并且给出了解释:
这将创建一个名为
my-ingress-controller
的目录,并在其中创建cmd
和pkg
目录,分别用于存放主应用程序和包。此外,我们在cmd/my-ingress-controller
目录中创建了main.go
文件,用于编写第一个可执行的控制台应用程序的圆形;在pkg/ingress
和pkg/kube
目录中,分别创建了ingress.go
和kube.go
文件,用于存放后续的代码。
我照章办事执行之后,当然生成了对应的目录和文件,接下来我给出第二个 Prompt:
然后完成第二步骤,完成一个可执行的控制台应用的圆形。
ChatGPT 给出了经典的 Hello World 代码,填充了 my-ingress-controller/cmd/my-ingress-controller/main.go
:
package main
import (
"fmt"
)
func main() {
fmt.Println("Hello, Ingress!")
}
接着他解释了代码的作用,提示使用 go build -o my-ingress-controller ./cmd/my-ingress-controller
命令进行构建。
对此我的回复是
go build 执行失败了,返回信息“go: go.mod file not found in current directory or any parent directory; see 'go help modules'”
ChatGPT 回应大意是:
- 这是因为 Go 1.11 版本后引入了模块(module)的概念,用于解决依赖管理的问题。如果我们的项目使用了 Go 模块,则需要在项目根目录中创建一个 go.mod 文件来记录项目的依赖关系。
go mod init my-ingress-controller
- 如果你使用的是 Go 1.16 及以上的版本,也可以使用以下命令自动初始化 Go 模块:
go mod init
照章办事之后,果然构建通过了。
运行成功后,我们开始连接 Kubernetes,对此我给出的 Prompt 是:
这一步运行成功之后,我们完成第三个步骤,加入连接 Kubernetes 集群的代码。并再次进行构建和试运行。
ChatGPT 并未含糊,给出了 kube.go
和 main.go
的代码:
// kube.go 两种方法进行连接
package kube
import (
"k8s.io/client-go/kubernetes"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/rest"
)
func NewClient() (*kubernetes.Clientset, error) {
config, err := clientcmd.BuildConfigFromFlags("", clientcmd.RecommendedHomeFile)
if err != nil {
return nil, err
}
clientset, err := kubernetes.NewForConfig(config)
if err != nil {
return nil, err
}
return clientset, nil
}
func InClusterConfig() (*rest.Config, error) {
return rest.InClusterConfig()
}
//main.go:列出 Namespace
package main
import (
"fmt"
"my-ingress-controller/pkg/kube"
)
func main() {
client, err := kube.NewClient()
if err != nil {
fmt.Println(err)
return
}
namespaces, err := client.CoreV1().Namespaces().List(context.Background(), metav1.ListOptions{})
if err != nil {
fmt.Println(err)
return
}
for _, ns := range namespaces.Items {
fmt.Println(ns.Name)
}
}
在这个步骤之后,ChatGPT 开始不太灵了,主要出现的问题包括:
- Client-Go 和 Kubernetes 之间存在对应关系,他对于这方面并没有一个稳定的假设,导致 API 的兼容频频出错
- 偶尔会在 Import 方面出现疏漏
Import 问题基本上来说,贴出构建错误就能解决;而版本问题则需要反复调试和提示才得以解决。
最后的一个坑是,他给我生成的 Informer 语句如下:
informerFactory := informers.NewSharedInformerFactoryWithOptions(
client,
0,
informers.WithNamespace("default"),
informers.WithTweakListOptions(func(options *metav1.ListOptions) {
options.LabelSelector = "app=my-ingress-controller"
}),
)
这里暗含了对命名空间和标签的要求,导致测试无法通过。在我发现问题发出疑问时,这位很淡定的回答:
是的,如果要测试 Ingress 资源的监控,可以在创建 Ingress 资源的时候添加一个
app=my-ingress-controller
的标签,这样就会触发事件并输出日志信息。
也算总结吧
所以以后学编程,是不是可以不用费劲加那么多啥微信群了?