kins
kins

Reputation: 1

how to change a clusterrole with kubectl gracefully

By default, the data in clusterrole system:node is as below:

$ kubectl get clusterrole system:node -o yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
name: system:node
rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - create
  - delete
- apiGroups:
  - ""
  resources:
  - pods/status
  verbs:
  - patch
  - update

Now, I want to change the clusterrole system:node, and added a - patch under the pods resources, it should be like this:

- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
  - patch

I could update it by using kubectl edit, but I want to update it in the bash script, so kubectl edit is not suitable, is there any other solution using kubectl?

Upvotes: 0

Views: 14150

Answers (4)

ericfossas
ericfossas

Reputation: 2196

If you don't mind storing the entire manifest, then I recommend Blokje5's answer of using kubectl apply. However, if you're looking for a minimal command that doesn't require storing the entire manifest, then you have two options here using kubectl patch --type 'json':

1 - Use an 'add' operation

kubectl patch clusterrole system:node --type='json' -p='[{"op": "add", "path": "/rules/0", "value":{ "apiGroups": [""], "resources": ["pods"], "verbs": ["get","list","watch","patch"]}}]'

This will insert your new rule at the beginning of the array. Since permissions are additive, the role will get the additional permission you want.

2 - Use a 'replace' operation

kubectl patch clusterrole system:node --type='json' -p='[{"op": "replace", "path": "/rules/0/verbs", "value":["get","list","watch","patch"]}]'

This will replace the verbs array of the first element in the rules array.


Here is an explanation as to why these are your only options:

kubectl patch can use 3 different patch strategies. It defaults to using the 'strategic' patch.

Elements in the containers array of the Deployment object have the unique name field and so when doing a 'strategic' patch, it will replace the element that matches the unique value of that field.

containers:
- name: this-is-unique-and-a-match-will-replace-this
  image: nginx

However, elements in the rules array of the ClusterRole object do not have a field that requires a unique value. And so the 'strategic' patch has no way of knowing which element you want replaced. Therefore, it just replaces the entire array with whatever patch you give it.

Since the 'strategic' patch is not a viable option for you here (unless you're okay with replacing the entire rules array), you have to resort to using the 'json' patch, which allows you to explicitly define array inserts and replaces.

The disadvantage here is that in option 1, you can add permissions, but not remove them as Kubernetes RBAC is purely additive. And in option 2, you must know the index of the element you want to replace.


Here are some useful links:

http://jsonpatch.com/

https://kubernetes.io/docs/tasks/manage-kubernetes-objects/update-api-object-kubectl-patch/

Upvotes: 3

weibeld
weibeld

Reputation: 15252

Probably, the simplest automatable way is to add a new rule to the ClusterRole.

Create a file named append.yaml with the following content:

- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - patch

Then, append this rule to the existing YAML manifest of the ClusterRole and reapply it with:

kubectl apply -f <(cat <(kubectl get clusterrole system:node -o yaml) append.yaml)

The new rule will be merged with the other permissions for pods, which you can verify with:

kubectl describe clusterrole system:node

The nicest imperative solution would be to patch the object with kubectl patch, but it doesn't seem to be easily possible:

  • If you want to use a strategic patch: the rules array of the ClusterRole object seems to use a replace patch strategy, that is, the provided patch would just replace the existing array rather being merged with it.
  • If you want to use a JSON patch to add an additional rule: it doesn't seem to be possible to add a deeply structured array element to an existing array.

Upvotes: 0

Kamol Hasan
Kamol Hasan

Reputation: 13456

chages.yaml

rules:
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - get
  - list
  - watch
  - patch #added
- apiGroups:
  - ""
  resources:
  - pods
  verbs:
  - create
  - delete
- apiGroups:
  - ""
  resources:
  - pods/status
  verbs:
  - patch
  - update

Use the following bash command to update the ClusterRole


kubectl patch clusterrole system:node  --patch "$(cat changes.yaml)" 

For more details visit k8s official documentations

Upvotes: 3

Blokje5
Blokje5

Reputation: 4993

You can use a kubectl apply -f node-role.yaml where node-role.yaml contains the yaml definition of the ClusterRole with your change included. kubectl apply will update the role if it already exists (and create it otherwise).

Upvotes: 9

Related Questions