用 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 的目录,并在其中创建 cmdpkg 目录,分别用于存放主应用程序和包。此外,我们在 cmd/my-ingress-controller 目录中创建了 main.go 文件,用于编写第一个可执行的控制台应用程序的圆形;在 pkg/ingresspkg/kube 目录中,分别创建了 ingress.gokube.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 回应大意是:

  1. 这是因为 Go 1.11 版本后引入了模块(module)的概念,用于解决依赖管理的问题。如果我们的项目使用了 Go 模块,则需要在项目根目录中创建一个 go.mod 文件来记录项目的依赖关系。
  2. go mod init my-ingress-controller
  3. 如果你使用的是 Go 1.16 及以上的版本,也可以使用以下命令自动初始化 Go 模块:go mod init

照章办事之后,果然构建通过了。

运行成功后,我们开始连接 Kubernetes,对此我给出的 Prompt 是:

这一步运行成功之后,我们完成第三个步骤,加入连接 Kubernetes 集群的代码。并再次进行构建和试运行。

ChatGPT 并未含糊,给出了 kube.gomain.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 开始不太灵了,主要出现的问题包括:

  1. Client-Go 和 Kubernetes 之间存在对应关系,他对于这方面并没有一个稳定的假设,导致 API 的兼容频频出错
  2. 偶尔会在 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 的标签,这样就会触发事件并输出日志信息。

也算总结吧

所以以后学编程,是不是可以不用费劲加那么多啥微信群了?

Avatar
崔秀龙

简单,是大师的责任;我们凡夫俗子,能做到清楚就很不容易了。

comments powered by Disqus
下一页
上一页

相关