从 Kubernetes 中同一命名空间中的进程 运行 中删除 ClusterRoleBinding 和命名空间
Delete ClusterRoleBinding and Namespace from process running in same Namespace in Kubernetes
我在 kube 集群上创建了一个 Namespace
并在该命名空间中安装了我的应用程序。该应用程序定期向服务器发送心跳请求,如果它从服务器收到 "remove yourself" 响应,它会通过在整个 kube 命名空间上调用 delete 来删除自己。我还通过创建一个 ClusterRoleBinding
来为应用程序集群提供广泛的访问权限,使 ServiceAccount
受 ClusterRoleBinding
和 运行 的 pod 约束 ServiceAccount
.
问题是我想在应用程序的自我删除过程中删除 ClusterRoleBinding
(如果可能的话)。如果我在此之前删除 ClusterRoleBinding
,应用程序将无法在 Namespace
上执行删除操作,因此这似乎是先有鸡还是先有蛋的问题。有办法吗?
这是我已经尝试过但无济于事的方法:
在应用程序容器中添加了 PreStop 处理程序。所以现在当应用程序在整个命名空间上调用 delete 时,kube 会在终止容器之前调用此处理程序。在这个 PreStop 处理程序中,如果我在 ClusterRoleBinding
上调用 delete 之前睡了超过 5 秒,我会从 kubernetes 得到 "Unauthorized" 响应。
这让我想到,在应用程序有机会删除 ClusterRoleBinding
之前,链接到 ClusterRoleBinding
的 ServiceAccount
可能会被删除PreStop 处理程序。因此,为了测试这一点,在对命名空间发出删除之前,我向 ServiceAccount
添加了一个终结器,然后在 PreStop 处理程序中等待 5 秒,在 ClusterRoleBinding
上发出删除(再次返回 "Unauthorized" 错误), 然后我通过名称 获取 ServiceAccount
对象(返回 "Unauthorized" 错误),删除来自 ServiceAccount
(获取错误 "error="finalizer 对于对象 ''") 的终结器,因为它无法删除空对象上的终结器。当我使用 kubectl 时,我发现 ServiceAccount
存在但处于 "Terminating" 状态,正如预期的那样,终结器仍然设置。
当 ServiceAccount
处于 "Terminating"
状态时,即使尚未硬删除,kube 是否会撤销访问权限?
有没有办法从需要 Namespace
中的 运行 的同一进程中删除 ClusterRoleBinding
和 Namespace
被删除? (鉴于我们要删除的 ClusterRoleBinding
首先授予应用程序删除 Namespace
的权限)
如有任何帮助,我们将不胜感激!
ClusterRoleBinding
和 ServiceAccount
的 YAML 定义如下:
### ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: xyz-myapp-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: xyz
namespace: xyz-myapp
### ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: xyz
namespace: xyz-myapp
相关申请日志:
time="2020-02-18T16:08:33Z" level=info msg="App instructed to remove itself"
time="2020-02-18T16:08:33Z" level=info msg="Created finalizer 'xyz.myapp.com/my-finalizer' on ServiceAccount"
time="2020-02-18T16:08:33Z" level=info msg="Called delete on Namespace"
time="2020-02-18T16:08:38Z" level=info msg="PreStop handler called"
time="2020-02-18T16:08:38Z" level=info msg="----- sleeping for 5 sec -----"
time="2020-02-18T16:08:43Z" level=info msg="Deleting ClusterRoleBinding"
time="2020-02-18T16:08:43Z" level=warning msg="Failed to delete ClusterRoleBinding" error="Unexpected error removing ClusterRolebinding: Unauthorized"
time="2020-02-18T16:08:43Z" level=warning msg="Failed to get ServiceAccount" error=Unauthorized
time="2020-02-18T16:08:43Z" level=warning msg="Failed to remove finalizer from ServiceAccount" error="finalizer 'xyz.myapp.com/my-finalizer' doesn't exist for object ''"
在深入了解 kubernetes 文档后,我发现最可靠的方法是:
- 当应用程序从服务器收到 "remove yourself" 响应时,它使
ClusterRoleBinding
成为运行该应用程序的 Namespace
的所有者.
- 这可以通过使用补丁在命名空间的
medatadata.owerReferences
下添加 ClusterRoleBinding
来完成。
- 一旦
ClusterRoleBinding
成功添加为 Namespace
的所有者,应用程序就可以使用 DeletePropagationBackground
在 ClusterRoleBinding
上调用删除。
下面是一个示例,说明如何应用将 ClusterRoleBinding
添加到 Namespace
的 ownerReferences
的补丁(在 Golang 中)。
import (
"encoding/json"
"k8s.io/client-go/kubernetes"
v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ownerReferencePatch struct {
Op string `json:"op"`
Path string `json:"path"`
Value []metav1.OwnerReference `json:"value"`
}
func AddClusterRoleBindingOwnerReferenceToNamespace(client kubernetes.Interface, crb *rbacv1.ClusterRoleBinding, ns *v1.Namespace) (*v1.Namespace, error) {
patch, err := json.Marshal([]ownerReferencePatch{
{
Op: "add",
Path: "/metadata/ownerReferences",
Value: []metav1.OwnerReference{
{
APIVersion: crb.RoleRef.APIGroup,
BlockOwnerDeletion: func(in bool) *bool {return &in}(true),
Kind: "ClusterRoleBinding",
Name: crb.GetName(),
UID: crb.GetUID(),
},
},
},
})
if err != nil {
return nil, err
}
return client.CoreV1().Namespaces().Patch(ns.GetName(), types.JSONPatchType, patch)
}
我在 kube 集群上创建了一个 Namespace
并在该命名空间中安装了我的应用程序。该应用程序定期向服务器发送心跳请求,如果它从服务器收到 "remove yourself" 响应,它会通过在整个 kube 命名空间上调用 delete 来删除自己。我还通过创建一个 ClusterRoleBinding
来为应用程序集群提供广泛的访问权限,使 ServiceAccount
受 ClusterRoleBinding
和 运行 的 pod 约束 ServiceAccount
.
问题是我想在应用程序的自我删除过程中删除 ClusterRoleBinding
(如果可能的话)。如果我在此之前删除 ClusterRoleBinding
,应用程序将无法在 Namespace
上执行删除操作,因此这似乎是先有鸡还是先有蛋的问题。有办法吗?
这是我已经尝试过但无济于事的方法:
在应用程序容器中添加了 PreStop 处理程序。所以现在当应用程序在整个命名空间上调用 delete 时,kube 会在终止容器之前调用此处理程序。在这个 PreStop 处理程序中,如果我在
ClusterRoleBinding
上调用 delete 之前睡了超过 5 秒,我会从 kubernetes 得到 "Unauthorized" 响应。这让我想到,在应用程序有机会删除
ClusterRoleBinding
之前,链接到ClusterRoleBinding
的ServiceAccount
可能会被删除PreStop 处理程序。因此,为了测试这一点,在对命名空间发出删除之前,我向ServiceAccount
添加了一个终结器,然后在 PreStop 处理程序中等待 5 秒,在ClusterRoleBinding
上发出删除(再次返回 "Unauthorized" 错误), 然后我通过名称 获取ServiceAccount
对象(返回 "Unauthorized" 错误),删除来自ServiceAccount
(获取错误 "error="finalizer 对于对象 ''") 的终结器,因为它无法删除空对象上的终结器。当我使用 kubectl 时,我发现ServiceAccount
存在但处于 "Terminating" 状态,正如预期的那样,终结器仍然设置。
当 ServiceAccount
处于 "Terminating"
状态时,即使尚未硬删除,kube 是否会撤销访问权限?
有没有办法从需要 Namespace
中的 运行 的同一进程中删除 ClusterRoleBinding
和 Namespace
被删除? (鉴于我们要删除的 ClusterRoleBinding
首先授予应用程序删除 Namespace
的权限)
如有任何帮助,我们将不胜感激!
ClusterRoleBinding
和 ServiceAccount
的 YAML 定义如下:
### ClusterRoleBinding
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
creationTimestamp: null
name: xyz-myapp-cluster-admin
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: cluster-admin
subjects:
- kind: ServiceAccount
name: xyz
namespace: xyz-myapp
### ServiceAccount
apiVersion: v1
kind: ServiceAccount
metadata:
creationTimestamp: null
name: xyz
namespace: xyz-myapp
相关申请日志:
time="2020-02-18T16:08:33Z" level=info msg="App instructed to remove itself"
time="2020-02-18T16:08:33Z" level=info msg="Created finalizer 'xyz.myapp.com/my-finalizer' on ServiceAccount"
time="2020-02-18T16:08:33Z" level=info msg="Called delete on Namespace"
time="2020-02-18T16:08:38Z" level=info msg="PreStop handler called"
time="2020-02-18T16:08:38Z" level=info msg="----- sleeping for 5 sec -----"
time="2020-02-18T16:08:43Z" level=info msg="Deleting ClusterRoleBinding"
time="2020-02-18T16:08:43Z" level=warning msg="Failed to delete ClusterRoleBinding" error="Unexpected error removing ClusterRolebinding: Unauthorized"
time="2020-02-18T16:08:43Z" level=warning msg="Failed to get ServiceAccount" error=Unauthorized
time="2020-02-18T16:08:43Z" level=warning msg="Failed to remove finalizer from ServiceAccount" error="finalizer 'xyz.myapp.com/my-finalizer' doesn't exist for object ''"
在深入了解 kubernetes 文档后,我发现最可靠的方法是:
- 当应用程序从服务器收到 "remove yourself" 响应时,它使
ClusterRoleBinding
成为运行该应用程序的Namespace
的所有者. - 这可以通过使用补丁在命名空间的
medatadata.owerReferences
下添加ClusterRoleBinding
来完成。 - 一旦
ClusterRoleBinding
成功添加为Namespace
的所有者,应用程序就可以使用DeletePropagationBackground
在ClusterRoleBinding
上调用删除。
下面是一个示例,说明如何应用将 ClusterRoleBinding
添加到 Namespace
的 ownerReferences
的补丁(在 Golang 中)。
import (
"encoding/json"
"k8s.io/client-go/kubernetes"
v1 "k8s.io/api/core/v1"
rbacv1 "k8s.io/api/rbac/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
)
type ownerReferencePatch struct {
Op string `json:"op"`
Path string `json:"path"`
Value []metav1.OwnerReference `json:"value"`
}
func AddClusterRoleBindingOwnerReferenceToNamespace(client kubernetes.Interface, crb *rbacv1.ClusterRoleBinding, ns *v1.Namespace) (*v1.Namespace, error) {
patch, err := json.Marshal([]ownerReferencePatch{
{
Op: "add",
Path: "/metadata/ownerReferences",
Value: []metav1.OwnerReference{
{
APIVersion: crb.RoleRef.APIGroup,
BlockOwnerDeletion: func(in bool) *bool {return &in}(true),
Kind: "ClusterRoleBinding",
Name: crb.GetName(),
UID: crb.GetUID(),
},
},
},
})
if err != nil {
return nil, err
}
return client.CoreV1().Namespaces().Patch(ns.GetName(), types.JSONPatchType, patch)
}