Kubernetes 为什么client.Update(…)忽略非原语值?

Kubernetes 为什么client.Update(…)忽略非原语值?,kubernetes,kubernetes-apiserver,kubernetes-custom-resources,kubebuilder,Kubernetes,Kubernetes Apiserver,Kubernetes Custom Resources,Kubebuilder,我试图修改非自有对象的规范,作为我的自定义资源的协调的一部分,但它似乎忽略了任何非原语的字段。我正在使用控制器运行时 我想,因为它只在原语上工作,也许这是一个与DeepCopy相关的问题。然而,删除它并不能解决这个问题,我了解到,对象的任何更新都必须在深度副本上,以避免弄乱缓存 我还尝试设置client.FieldOwner(…),因为它说这是服务器端完成的更新所必需的。我不确定要将其设置为什么,所以我将其设置为req.NamespacedName.String()。这也不管用 以下是我的控制器

我试图修改非自有对象的规范,作为我的自定义资源的
协调
的一部分,但它似乎忽略了任何非原语的字段。我正在使用控制器运行时

我想,因为它只在原语上工作,也许这是一个与DeepCopy相关的问题。然而,删除它并不能解决这个问题,我了解到,对象的任何更新都必须在深度副本上,以避免弄乱缓存

我还尝试设置
client.FieldOwner(…)
,因为它说这是服务器端完成的更新所必需的。我不确定要将其设置为什么,所以我将其设置为
req.NamespacedName.String()
。这也不管用

以下是我的控制器的协调循环:

func(r*MyCustomObjectReconciler)协调(请求控制)(控制结果,错误){
// ...
var myCustomObject customv1.myCustomObject
如果错误:=r.Get(ctx、req.NamespacedName和myCustomObject);错误!=nil{
log.Error(错误,“无法获取ReleaseDefinition”)
返回ctrl.Result{},client.IgnoreNotFound(err)
}
// ...
deployList:=&kappsv1.DeploymentList{}
标签:=映射[字符串]字符串{
“mylabel”:myCustomObject.Name,
}
如果错误:=r.List(ctx、deployList、client.MatchingLabels(标签));错误!=nil{
log.Error(错误,“无法获取部署”)
返回ctrl.Result{},错误
}
//制作深度复制以避免弄乱缓存(由其他控制器使用)
myCustomObjectSpec:=myCustomObject.Spec.DeepCopy()
//影响部署的我的CRD的两个字段
端口:=myCustomObjectSpec.port//type:*int32
customenv:=myCustomObjectSpec.customenv//type:map[string]string
对于u,dep:=范围部署列表项{
newDeploy:=dep.DeepCopy()//已返回指针
//做这些事情:
//1.将第一个容器的containerPort替换为myCustomObjectSpec.Port
//2.用myCustomObjectSpec.CustomEnv中的值替换第一个容器的环境
//3.更新部署
容器:=newDeploy.Spec.Template.Spec.Containers[0]
//1.更换集装箱的端口
container.Ports[0]。ContainerPort=*port
envVars:=make([]kcorev1.EnvVar,0,len(customenv))
对于键,val:=范围customenv{
envVars=append(envVars,kcorev1.EnvVar{
姓名:key,,
值:val,
})
}
//2.替换容器的环境变量
container.Env=envVars
//3.执行部署更新(端口工作,忽略环境)
如果错误:=r.Update(ctx,newDeploy);错误!=nil{
log.Error(错误,“无法更新部署”,“部署”,dep.Name)
返回ctrl.Result{},错误
}
}
返回ctrl.Result{},nil
}
我的CRD的规格如下所示:

// MyCustomObjectSpec defines the desired state of MyCustomObject
type MyCustomObjectSpec struct {
    // CustomEnv is a list of environment variables to set in the containers.
    // +optional
    CustomEnv map[string]string `json:"customEnv,omitempty"`

    // Port is the port that the backend container is listening on.
    // +optional
    Port *int32 `json:"port,omitempty"`
}

我希望当我
kubectl应用一个新的CR并更改端口和CustomEnv字段时,它会按照
协调
中所述修改部署。但是,只更新了端口,并且忽略了对容器的
Env
所做的更改。

问题是我需要一个指向正在修改的容器的指针

这样做反而有效:

container:=&newDeploy.Spec.Template.Spec.Containers[0]

能否在更新之前尝试设置
newDeploy.Spec.Templates.Spec.Containers[0]=container
?或者在更新之前尝试打印出
newDeploy
对象。在手机上行走和打字时,很难在评论中解释,但我认为,因为端口是一个指针,所以您更改它会对newDeploy的端口产生预期的效果,但实际上您并没有更改newDeploy的环境。我想你打印出来的时候会看到这个。所以这将是一个代码问题,与控制器运行时无关是的,你是对的。那是我的问题。我需要一个指向容器的指针:
容器:=&newDeploy.Spec.Template.Spec.Containers[0]
。谢谢你的帮助,甜心,很高兴它成功了!