Virtual nodes in ACK Serverless Pro clusters do not support DaemonSet. To run auxiliary workloads—such as logging agents and monitoring agents—alongside application pods on virtual nodes, use the OpenKruise SidecarSet feature to automatically inject sidecar containers.
SidecarSet decouples sidecar definitions from application Deployments. You define the sidecar once in a SidecarSet, and OpenKruise injects it into every matching pod automatically, including pods scheduled to virtual nodes.
Prerequisites
Before you begin, ensure that you have:
An ACK Serverless Pro cluster running Kubernetes 1.22 or later
ack-virtual-node v2.10.0 or later installed — see ACK Virtual Node
ack-kruise v1.3.0 or later installed — see OpenKruise
The
SidecarSetServerlessPod=truefeature gate enabled in featureGates of the Kube API server component — see Customize the parameters of a control plane component
In virtual node scenarios, all SidecarSet features from OpenKruise v1.3.0 and earlier are supported. Features introduced in versions later than v1.3.0 are not supported.
Key concepts
Sidecar pattern
A design pattern that separates auxiliary functions—such as logging and monitoring—from the application itself into separate containers. This lets you extend application capabilities without modifying application code or container images.
SidecarSet
A core feature of OpenKruise, the open-source cloud-native application automation engine from Alibaba Cloud. SidecarSet automatically injects sidecar containers into pods that match a label selector, and manages the sidecar lifecycle independently from application containers.
SidecarSetResourceBinding
An Alibaba Cloud extension to OpenKruise. When a sidecar container references a ConfigMap or Secret from a different namespace than the application pod, you must create a SidecarSetResourceBinding to grant read-only access (Get, List, Watch).
How it works
SidecarSet selects pods using label selectors. When a pod is scheduled to a virtual node, ACK automatically adds the label serverless.alibabacloud.com/virtual-node: "true". To target all pods on virtual nodes, set this label as the matchLabels selector in your SidecarSet.
The following table shows how the selector label controls injection:
Pod has serverless.alibabacloud.com/virtual-node: "true" | SidecarSet matchLabels set to this label | Result |
|---|---|---|
| Yes | Yes | Sidecar injected |
| No | Yes | Sidecar not injected |
| Yes | No | Sidecar not injected (selector does not match) |
Because virtual nodes do not support DaemonSet, sidecar containers are also the recommended approach for cross-namespace ConfigMap and Secret access. Use the Namespace/Name format (for example, kube-system/filebeat-config) to reference resources from another namespace in a volume definition—then authorize access with a SidecarSetResourceBinding.
Inject a sidecar container into a virtual node pod
The following example injects a filebeat sidecar container into an echo-server application pod. The sidecar container:
Mounts a ConfigMap from the
kube-systemnamespace (cross-namespace reference)Mounts the standard output logs of the application pod (stdlog volume)
Step 1: Create the ConfigMap
Create a ConfigMap in the kube-system namespace to hold the filebeat configuration.
kubectl apply -f filebeat-config.yamlThe following filebeat-config.yaml mounts the configuration file to the sidecar container. The placeholder variables (such as ${NODE_NAME} and ${ELASTIC_CLOUD_ID}) are not evaluated in this example and do not need to be replaced.
apiVersion: v1
kind: ConfigMap
metadata:
name: filebeat-config
namespace: kube-system
labels:
k8s-app: filebeat
data:
filebeat.yml: |-
filebeat.inputs:
- type: log
paths:
- /var/log/std/*.log
processors:
- add_kubernetes_metadata:
host: ${NODE_NAME} # Not evaluated in this example. Use as-is.
matchers:
- logs_path:
logs_path: "/var/log/std/"
# To enable hints-based autodiscover, remove filebeat.inputs and uncomment:
#filebeat.autodiscover:
# providers:
# - type: kubernetes
# node: ${NODE_NAME}
# hints.enabled: true
# hints.default_config:
# type: container
# paths:
# - /var/log/containers/*${data.kubernetes.container.id}.log
processors:
- add_cloud_metadata:
- add_host_metadata:
cloud.id: ${ELASTIC_CLOUD_ID} # Not evaluated in this example. Use as-is.
cloud.auth: ${ELASTIC_CLOUD_AUTH} # Not evaluated in this example. Use as-is.
output.elasticsearch:
hosts: ['${ELASTICSEARCH_HOST:elasticsearch}:${ELASTICSEARCH_PORT:9200}']
username: ${ELASTICSEARCH_USERNAME} # Not evaluated in this example. Use as-is.
password: ${ELASTICSEARCH_PASSWORD} # Not evaluated in this example. Use as-is.Step 2: Deploy the SidecarSet
Create a SidecarSet to describe the filebeat sidecar container. The SidecarSet selects pods with the serverless.alibabacloud.com/virtual-node: "true" label and injects the sidecar automatically.
kubectl apply -f sidecarset.yamlapiVersion: apps.kruise.io/v1alpha1
kind: SidecarSet
metadata:
name: filebeat-sidecarset
spec:
selector:
matchLabels:
serverless.alibabacloud.com/virtual-node: "true" # Selects all pods scheduled to virtual nodes.
updateStrategy:
type: NotUpdate
containers:
# This example uses busybox instead of the actual filebeat image.
# To use filebeat, replace the container spec with:
#- name: filebeat
# image: docker.elastic.co/beats/filebeat:8.6.1
# args: ["-c", "/etc/filebeat.yml", "-e"]
- name: filebeat
image: busybox
imagePullPolicy: IfNotPresent
args:
- "/bin/sh"
- "-c"
- "cat /etc/filebeat.yml && sleep 36000"
env:
- name: ECI_SIDECAR_CONTAINER # Causes the sidecar to exit after the application container exits.
value: "true"
volumeMounts:
- name: config
mountPath: /etc/filebeat.yml
readOnly: true
subPath: filebeat.yml
- name: stdlog # Mounts the pod's standard output logs for the sidecar to read.
mountPath: /var/log/std
readOnly: true
volumes:
- name: config
configMap:
name: kube-system/filebeat-config # Namespace/Name format for cross-namespace reference.
- name: stdlog
csi:
driver: stdlogplugin.csi.alibabacloud.comStep 3: Authorize cross-namespace ConfigMap access
The application pod is in the default namespace, but the ConfigMap is in kube-system. Create a SidecarSetResourceBinding to grant the SidecarSet read-only access to the ConfigMap.
kubectl apply -f sidecarset-resourcebinding.yaml# Grants filebeat-sidecarset read-only access to filebeat-config in the kube-system namespace.
apiVersion: sidecarset.alibabacloud.com/v1alpha1
kind: SidecarSetResourceBinding
metadata:
name: filebeat-sidecarset-resourcebinding
namespace: kube-system # Grants permissions only on resources in this namespace.
labels:
spec:
subjects:
- kind: SidecarSet
name: filebeat-sidecarset
resourceRefs:
- kind: ConfigMap # Read-only: Get, List, and Watch.
name: filebeat-configStep 4: Deploy the application pod
Deploy the echo-server application. Adding the alibabacloud.com/eci: "true" label schedules the pod to a virtual node, which also adds the serverless.alibabacloud.com/virtual-node: "true" label—triggering sidecar injection.
kubectl apply -f echo-server.yamlapiVersion: apps/v1
kind: Deployment
metadata:
name: echo-server
labels:
app: echo-server
spec:
replicas: 1
selector:
matchLabels:
app: echo-server
template:
metadata:
labels:
app: echo-server
alibabacloud.com/eci: "true" # Schedules the pod to a virtual node.
spec:
containers:
- name: echo-server
image: hashicorp/http-echo
imagePullPolicy: IfNotPresent
args:
- -listen=:8080
- -text="hello world"Verify injection
Check that the sidecar was injected. Before injection, the pod shows
1/1 READY(application container only). After the SidecarSet injects the sidecar, the count becomes2/2.kubectl get podExpected output:
NAME READY STATUS RESTARTS AGE echo-server-f8bdc5844-r44nj 2/2 Running 0 14mVerify the sidecar can read the application pod's standard output logs.
kubectl exec echo-server-f8bdc5844-r44nj -c filebeat -- cat /var/log/std/echo-server/0.logExpected output:
2025-04-29T11:26:06.783205694+08:00 stderr F 2025/04/29 03:26:06 Server is listening on :8080Verify the sidecar can read the ConfigMap mounted from the
kube-systemnamespace.kubectl exec echo-server-f8bdc5844-r44nj -c filebeat -- cat /etc/filebeat.ymlThe output shows the full contents of the filebeat.yml ConfigMap, confirming the cross-namespace mount is working.
Additional SidecarSet capabilities
Control container startup and exit order
Sidecar containers often need to start before application containers and exit after them. Configure this behavior using container startup and exit priorities.
The example SidecarSet in this topic also demonstrates an inline approach: setting the ECI_SIDECAR_CONTAINER: "true" environment variable causes the sidecar container to exit automatically after the application container exits. This is the recommended approach for virtual node scenarios.
Handle sidecar containers in Job pods
For Job workloads, a long-running sidecar container can block the Job from completing after the application container finishes. To prevent this, set ECI_SIDECAR_CONTAINER: "true" in the sidecar container environment:
env:
- name: ECI_SIDECAR_CONTAINER # Causes the sidecar to exit after the application container exits.
value: "true"This causes the sidecar to exit automatically when the application container finishes, so the Job can complete normally. For full details, including how to ignore the sidecar's exit code, see Forcibly terminate sidecar containers and ignore exit codes.
Upgrade sidecar containers
To update a sidecar container already injected into running pods, use the OpenKruise sidecar hot upgrade feature. Hot upgrade updates the sidecar in-place without restarting the pod or affecting application availability, and is fully compatible with virtual node pods.
After triggering an upgrade, monitor progress by checking the SidecarSet status:
kubectl get sidecarset filebeat-sidecarset -o yamlThe status section reports the following counters:
| Field | Description |
|---|---|
matchedPods | Total number of pods matched and managed by this SidecarSet |
updatedPods | Number of pods updated to the latest sidecar version |
readyPods | Number of matched pods with Ready condition |
updatedReadyPods | Number of pods that are both updated and ready |
Collect standard output logs
Mount the application pod's standard output logs into the sidecar container using a stdlog CSI volume. The sidecar can then forward logs to your logging backend without any changes to the application container.
The example SidecarSet in this topic already includes the stdlog volume configuration. For more details on the stdlog volume type, see Mount stdlog to a pod.
The stdlog volume mounts logs at /var/log/std/<container-name>/0.log inside the sidecar container:
volumes:
- name: stdlog
csi:
driver: stdlogplugin.csi.alibabacloud.comWhat's next
SidecarSet reference — full list of SidecarSet fields and strategies
Configure container startup and exit priorities — control the order in which containers start and stop
Forcibly terminate sidecar containers — handle Job pod completion with sidecar containers
Mount stdlog to a pod — collect standard output logs using CSI volumes