PodDecoration
PodDecoration works in conjunction with CollaSet to selectively inject specific configurations to Pods that meet certain criteria.
PodDecoration not only allows injecting sidecar containers to Pods but also enables modifying existing container configurations, metadata, and scheduling parameters etc.
The PodDecoration controller does not control the upgrade of Pods. The actual upgrade process is fully controlled by the CollaSet controller. This means that the injection upgrade of PodDecoration can also be performed InPlaceIfPossible
.
About CollaSet.
Example
1. Create CollaSetβ
# collaset.yaml
apiVersion: apps.kusionstack.io/v1alpha1
kind: CollaSet
metadata:
name: foo
namespace: default
spec:
replicas: 3
selector:
matchLabels:
app: foo
template:
metadata:
labels:
app: foo
spec:
containers:
- image: nginx:1.25.2
name: foo
Use collaset.yaml
to create three pods under CollaSet foo
management.
$ kubectl apply -f collaset.yaml
collaset.apps.kusionstack.io/foo created
$ kubectl get cls
NAME DESIRED CURRENT AVAILABLE UPDATED UPDATED_READY UPDATED_AVAILABLE CURRENT_REVISION UPDATED_REVISION AGE
foo 3 3 3 3 3 3 foo-7bdb974bc7 foo-7bdb974bc7 7s
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
foo-2wnnf 1/1 Running 0 41s
foo-hqpx7 1/1 Running 0 41s
foo-mqt48 1/1 Running 0 41s
2. Create PodDecorationβ
The following poddecoration.yaml
file describes a PodDecoration, which selects the pod under CollaSet foo
and injects the content in template
into the pod with instance-id=0
.
# poddecoration.yaml
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
selector: # selected pod range in which PodDecoration takes effect
matchLabels:
app: foo
updateStrategy:
rollingUpdate:
selector: # select pod to upgrade in effect range
matchLabels:
collaset.kusionstack.io/instance-id: "0"
template:
metadata:
- patchPolicy: Overwrite
labels:
custom.io/sidecar-version: "v1"
containers:
- injectPolicy: AfterPrimaryContainer
name: sidecar-a
image: ubuntu:22.04
command: ["sleep", "2h"]
volumeMounts:
- name: sample-volume
mountPath: /vol/sample
volumes:
- name: sample-volume
emptyDir: {}
Create PodDecoration sample-pd
to upgrade selected pod
$ kubectl apply -f poddecoration.yaml
poddecoration.apps.kusionstack.io/sample-pd created
The status of PodDecoration is updated, and one pod is injected with sidecar through recreate.
$ kubectl get pd
NAME EFFECTIVE MATCHED INJECTED UPDATED UPDATED_READY CURRENT_REVISION UPDATED_REVISION AGE
sample-pd true 3 1 1 1 sample-pd-9465f4c84 20s
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
foo-2gnnl 2/2 Running 0 15s
foo-2wnnf 1/1 Running 0 2m
foo-hqpx7 1/1 Running 0 2m
$ kubectl get pd sample-pd -o yaml | grep -A20 status
status:
details:
- affectedReplicas: 3
collaSet: foo
pods:
- name: foo-2gnnl
revision: sample-pd-9465f4c84
- name: foo-2wnnf
escaped: true
- name: foo-hqpx7
escaped: true
matchedPods: 3
injectedPods: 1
updatedPods: 1
updatedReadyPods: 1
updatedAvailablePods: 1
isEffective: true
updatedRevision: sample-pd-9465f4c84
3. Update PodDecorationβ
3.1. Rolling update v1β
Edit sample-pd
to expand the upgrade scope.
$ kubectl edit pd sample-pd
# poddecoration.yaml
# Edit updateStrategy to select instance-id in [0, 1, 2]
...
spec:
...
updateStrategy:
rollingUpdate:
selector:
matchExpressions:
- key: collaset.kusionstack.io/instance-id
operator: In
values:
- "0"
- "1" # add
- "2" # add
template:
...
All pods updated.
$ kubectl get pd
NAME EFFECTIVE MATCHED INJECTED UPDATED UPDATED_READY CURRENT_REVISION UPDATED_REVISION AGE
sample-pd true 3 3 3 3 sample-pd-9465f4c84 sample-pd-9465f4c84 3m
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
foo-2gnnl 2/2 Running 0 3m
foo-lftw8 2/2 Running 0 8s
foo-n57rr 2/2 Running 0 8s
$ kubectl get pd sample-pd -o yaml | grep -A20 status
status:
currentRevision: sample-pd-9465f4c84
details:
- affectedReplicas: 3
collaSet: foo
pods:
- name: foo-2gnnl
revision: sample-pd-9465f4c84
- name: foo-lftw8
revision: sample-pd-9465f4c84
- name: foo-n57rr
revision: sample-pd-9465f4c84
matchedPods: 3
injectedPods: 3
updatedPods: 3
updatedReadyPods: 3
updatedAvailablePods: 3
isEffective: true
currentRevision: sample-pd-9465f4c84
updatedRevision: sample-pd-9465f4c84
3.2. Rolling update v1 -> v2β
Update sample-pd
's sidecar container image and updateStrategy
.
$ kubectl edit pd sample-pd
# poddecoration.yaml
# Update sidecar-a's image with ubuntu:22.10
# Edit updateStrategy to select instance-id in [0]
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
...
updateStrategy:
rollingUpdate:
selector:
- key: collaset.kusionstack.io/instance-id
operator: In
values:
- "0"
template:
...
containers:
- injectPolicy: AfterPrimaryContainer
name: sidecar-a
image: ubuntu:22.10
...
Pod foo-2gnnl
in-place upgrade sidecar container image.
$ kubectl get pd
NAME EFFECTIVE MATCHED INJECTED UPDATED UPDATED_READY CURRENT_REVISION UPDATED_REVISION AGE
sample-pd true 3 3 1 1 sample-pd-9465f4c84 sample-pd-8697d4bf8c 6min
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
foo-2gnnl 2/2 Running 1 (12s ago) 6m
foo-lftw8 2/2 Running 0 3min
foo-n57rr 2/2 Running 0 3min
$ kubectl get pod foo-2gnnl -o yaml | grep "image: ubuntu"
image: ubuntu:22.10
$ kubectl get pd sample-pd -o yaml | grep -A20 status
status:
details:
- affectedReplicas: 3
collaSet: foo
pods:
- name: foo-2gnnl
revision: sample-pd-8697d4bf8c
- name: foo-lftw8
revision: sample-pd-9465f4c84
- name: foo-n57rr
revision: sample-pd-9465f4c84
matchedPods: 3
injectedPods: 3
updatedPods: 1
updatedReadyPods: 1
updatedAvailablePods: 1
isEffective: true
currentRevision: sample-pd-9465f4c84
updatedRevision: sample-pd-8697d4bf8c
Features
Injectionβ
Metadataβ
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
template:
metadata:
- patchPolicy: MergePatchJson
annotations:
cafe.sofastack.io/decoration-version: '[{"name":"sample-pd","version":"v2"}]'
- patchPolicy: Overwrite
labels:
custom.io/sidecar-version: "v2"
annotations:
cafe.sofastack.io/decoration-name: sample-pd
patchPolicy
is the injected policy, as follows:
Retain
: The original value of annotations and labels will be retained.Overwrite
: The value of annotations and labels corresponding to the existing key will be overwritten.MergePatchJson
: It only takes effect for annotation. If the key does not exist, the value will be written directly. Otherwise, the json value will be merged.
For exampleοΌ
# Old pod metadata
metadata:
labels:
custom.io/sidecar-version: "v1"
annotations:
cafe.sofastack.io/decoration-version: '[{"name":"old-pd","version":"v1"}]'
# After metadata injected
metadata:
labels:
custom.io/sidecar-version: "v2"
annotations:
cafe.sofastack.io/decoration-type: sample-pd
cafe.sofastack.io/decoration-version: '[{"name":"old-pd","version":"v1"}, {"name":"sample-pd","version":"v2"}]'
Primary Containerβ
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
# ...
template:
primaryContainers:
- targetPolicy: ByName
name: foo
image: foo:v2
env:
- name: APP_NAME
value: foo
volumeMounts:
- name: sample-volume
mountPath: /vol/sample
volumes:
- name: sample-volume
emptyDir: {}
Injection into the primary containers only supports limited fields: image
, env
and volumeMounts
.
targetPolicy
indicates which existed container these configuration should inject into, as follows:
ByName
: Only inject containers matchingname
.All
: Inject all primary containers.First
: Inject into first primary container.Last
: Inject into last primary container.
Sidecar Containerβ
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
# ...
template:
containers:
- injectPolicy: AfterPrimaryContainer # Container injected policy, AfterPrimaryContainer or BeforePrimaryContainer
name: sidecar-a
image: ubuntu:22.04
...
Inject a new sidecar container. Optional, it can be placed in front or behind the primary container.
InitContainerβ
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
# ...
template:
initContainers:
- name: init
image: custom-init-image:v1
...
Upgrade strategyβ
selectorβ
You can use selector
to select the pod. The CollaSet
provides a unique instance-id
for each pod. Of course, custom labels can also be used to label pods for triggering upgrades.
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
# ...
updateStrategy:
rollingUpdate:
selector:
- key: collaset.kusionstack.io/instance-id
operator: In
values:
- "0"
partitionβ
Partition is the desired number or percent of Pods in old revisions, defaults to 0
.
apiVersion: apps.kusionstack.io/v1alpha1
kind: PodDecoration
metadata:
name: poddecoration
spec:
# ...
updateStrategy:
rollingUpdate:
partition: 2 # int number