FAQ
How does the value informed via the domain flag (i.e. kubebuilder init --domain example.com
) when we init a project?
创建项目后,通常您会希望扩展 Kubernetes API,并定义由您的项目拥有的新 API。因此,域值会被记录在 PROJECT 文件中,该文件定义了您的项目配置,并将作为域来创建您的 API 端点。请确保您了解 组、版本和种类,真是让人头大!。
该域名用于组后缀,以明确显示资源组类别。例如,如果设置为 --domain=example.com
:
kubebuilder init --domain example.com --repo xxx --plugins=go/v4
kubebuilder create api --group mygroup --version v1beta1 --kind Mykind
那么结果资源组将是 mygroup.example.com
。
如果域字段未设置,默认值为
my.domain
。
我希望自定义我的项目,使用 klog 替代 controller-runtime 提供的 zap。我该如何使用 klog
或其他日志记录器作为项目的日志记录器?
在 main.go
中,你可以替换:
opts := zap.Options{
Development: true,
}
opts.BindFlags(flag.CommandLine)
flag.Parse()
ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts)))
与:
flag.Parse()
ctrl.SetLogger(klog.NewKlogr())
在执行 make run
后,我看到类似“无法找到领导者选举命名空间:未在集群内运行…“的错误。
您可以启用领导者选举。不过,如果您使用 make run
目标在本地测试项目,这将使管理器在集群外部运行,那么您可能还需要设置领导者选举资源将要创建的命名空间,如下所示:
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Port: 9443,
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionID: "14be1926.testproject.org",
LeaderElectionNamespace: "<project-name>-system",
如果您在集群上运行项目并使用 make deploy
目标,那么您可能不想添加此选项。因此,您可以使用环境变量自定义此行为,仅在开发目的时添加此选项,例如:
leaderElectionNS := ""
if os.Getenv("ENABLE_LEADER_ELECTION_NAMESPACE") != "false" {
leaderElectionNS = "<project-name>-system"
}
mgr, err := ctrl.NewManager(ctrl.GetConfigOrDie(), ctrl.Options{
Scheme: scheme,
MetricsBindAddress: metricsAddr,
Port: 9443,
HealthProbeBindAddress: probeAddr,
LeaderElection: enableLeaderElection,
LeaderElectionNamespace: leaderElectionNS,
LeaderElectionID: "14be1926.testproject.org",
...
当我在旧版本的 Kubernetes 上部署我的项目时,出现错误“open /var/run/secrets/kubernetes.io/serviceaccount/token: permission denied“。我该如何解决这个问题?
如果您遇到错误:
`当您在较旧版本的 Kubernetes 上运行项目(可能是 \<= 1.21)时,可能会遇到 [这个问题](https://github.com/kubernetes/kubernetes/issues/82573),其原因是挂载的令牌文件设置为
0600`,请查看 解决方案。然后,解决方法是:
在 manager.yaml 中添加 fsGroup
。
安全上下文:
以非root用户身份运行: true
fsGroup: 65532 # 添加此 fsGroup 以使令牌文件可读
不过,请注意,此问题已被修复,如果您在高版本(可能大于或等于1.22)中部署项目,则不会发生该问题。
当我运行 make install
来应用 CRD 清单时,出现错误 过长:必须最多为 262144 字节
。如何解决这个问题?为什么会出现这个错误?
在尝试运行 make install
来应用 CRD 清单时,可能会遇到错误 Too long: must have at most 262144 bytes
。这个错误是由于 Kubernetes API 强制执行的大小限制所导致。请注意,make install
目标将使用 kubectl apply -f -
来应用位于 config/crd
下的 CRD 清单。因此,当使用 apply 命令时,API 会用 last-applied-configuration
注解该对象,该注解包含整个之前的配置。如果这个配置太大,就会超过允许的字节大小。(更多信息)
在理想情况下,客户端应用可能看起来是完美的解决方案,因为整个对象配置不必作为注解(last-applied-configuration)存储在服务器上。 However,值得注意的是,目前它并不被 controller-gen 或 kubebuilder 支持。有关更多信息,请参见:Controller-tool-discussion。
因此,您有一些选项可以绕过此情况,例如:
通过从 CRD 中移除描述:
您的 CRD 是使用 controller-gen 生成的。通过使用选项 maxDescLen=0
来移除描述,您可以减少大小,从而解决问题。为此,您可以按照以下示例更新 Makefile,然后调用目标 make manifest
以重新生成没有描述的 CRD,具体如下:
通过重新设计您的 API:
您可以审查您的 API 设计,看看它是否有超过应有的规格,从而违反单一职责原则。例如,这样您可能需要重新设计它们。
How can I validate and parse fields in CRDs effectively?
为了提高用户体验,建议在编写 CRD 时使用 OpenAPI v3 schema 验证。然而,这种方法有时可能需要额外的解析步骤。例如,请考虑以下代码:
type StructName struct {
// +kubebuilder:validation:Format=日期-时间
TimeField string `json:"timeField,omitempty"`
}
在这种情况下会发生什么?
- 如果用户尝试创建具有无效 timeField 值的 CRD,Kubernetes API 会向其发送错误通知。
- 在开发者端,字符串值需要在使用之前手动解析。
有没有更好的方法?
为了提供更好的用户体验和简化开发人员体验,建议使用预定义类型,如 metav1.Time
。例如,考虑以下代码:
type StructName struct {
TimeField metav1.Time `json:"timeField,omitempty"`
}
在这种情况下会发生什么?
- 用户仍然会收到来自 Kubernetes API 的错误通知,提示无效的
timeField
值。 - 开发人员可以直接在代码中使用解析后的 TimeField,而无需额外的解析,从而减少错误并提高效率。