从 Kubernetes 中同一命名空间中的进程 运行 中删除 ClusterRoleBinding 和命名空间

Delete ClusterRoleBinding and Namespace from process running in same Namespace in Kubernetes

我在 kube 集群上创建了一个 Namespace 并在该命名空间中安装了我的应用程序。该应用程序定期向服务器发送心跳请求,如果它从服务器收到 "remove yourself" 响应,它会通过在整个 kube 命名空间上调用 delete 来删除自己。我还通过创建一个 ClusterRoleBinding 来为应用程序集群提供广泛的访问权限,使 ServiceAccountClusterRoleBinding 和 运行 的 pod 约束 ServiceAccount.

问题是我想在应用程序的自我删除过程中删除 ClusterRoleBinding(如果可能的话)。如果我在此之前删除 ClusterRoleBinding,应用程序将无法在 Namespace 上执行删除操作,因此这似乎是先有鸡还是先有蛋的问题。有办法吗?

这是我已经尝试过但无济于事的方法:

ServiceAccount 处于 "Terminating" 状态时,即使尚未硬删除,kube 是否会撤销访问权限?

有没有办法从需要 Namespace 中的 运行 的同一进程中删除 ClusterRoleBindingNamespace被删除? (鉴于我们要删除的 ClusterRoleBinding 首先授予应用程序删除 Namespace 的权限)

如有任何帮助,我们将不胜感激!

ClusterRoleBindingServiceAccount 的 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 文档后,我发现最可靠的方法是:

  1. 当应用程序从服务器收到 "remove yourself" 响应时,它使 ClusterRoleBinding 成为运行该应用程序的 Namespace 的所有者.
  2. 这可以通过使用补丁在命名空间的 medatadata.owerReferences 下添加 ClusterRoleBinding 来完成。
  3. 一旦 ClusterRoleBinding 成功添加为 Namespace 的所有者,应用程序就可以使用 DeletePropagationBackgroundClusterRoleBinding 上调用删除。

下面是一个示例,说明如何应用将 ClusterRoleBinding 添加到 NamespaceownerReferences 的补丁(在 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)
}