# Run yc-360 Script in Sidecar Container on OpenShift
This guide walks you through deploying the yc-360 Script in an OpenShift environment using a sidecar container to monitor the BuggyApp application in M3 Mode (Micro-metrics Monitoring). It covers:
- Creating the yc-360 script configuration as a Secret
- Deploying BuggyApp with the yc-360 script as a sidecar
- Enabling access logging and application log capture
- Generating traffic with a lightweight sidecar container
Not sure what M3 Mode means? Learn more about Execution Modes
Follow the steps below to run the yc-360 script in an OpenShift Pod.
# 1. Create a Secret for yc-360 Script Configuration
The yc-360 script requires a configuration file named yc-config.yaml, which must be mounted as a secret in the container.
Create an OpenShift Secret manifest (yc-secret.yaml) to securely store the YAML configuration file.
Secret File: yc-secret.yaml
apiVersion: v1
kind: Secretn
metadata:
name: yc-config
namespace: yc-apps
stringData:
yc-config.yaml: |
version: "1"
options:
k: <API_KEY>
s: <http://MY-YC-SERVER:PORT>
j: /opt/java/openjdk
kubernetes: false
m3: true
m3Frequency: 60s
storagePath: /opt/workspace/yc-360-script/yc-output
processTokens:
- buggyapp$BuggyApp
accessLogs:
- /opt/workspace/ba/logs/app.log$BuggyApp
accessLogFormats:
- %h %l %u %t %r %s %b %D$BuggyApp
accessLogSources:
- Tomcat$BuggyApp
appLogs:
- /opt/workspace/ba/logs/app.log$BuggyApp
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Replace the placeholders in the YAML configuration file with your actual values:
<API_KEY>: Your API key was provided with your license at the time of registration. If you're not sure where to find the API key, click here (opens new window).<http://MY-YC-SERVER:PORT>: URL of the yCrash server (e.g.,http://localhost:8080)./opt/java/openjdk: The directory path where Java is installed in your container. If you're using the official yc-360 script image, set this to/opt/java/openjdk.
# Configuration Options Explained
| Option | Description |
|---|---|
m3: true | Enables Micro-metrics Monitoring mode |
m3Frequency: 60s | Interval between M3 metric submissions |
storagePath | Writable directory for yc-360 script output files |
processTokens | Token to identify the Java process (token$appName format) |
accessLogs | Path to the access log file (filePath$appName format) |
accessLogFormats | The log pattern format matching your access log output |
accessLogSources | The source type of the access log (e.g., Tomcat, Nginx) |
appLogs | Path to the application log file (filePath$appName format) |
kubernetes: false | Set to true if your ServiceAccount has cluster-level namespace listing permissions |
For a full list of arguments, refer to the All yc-360 Script Arguments page.
Apply the Secret: Once your secret file is ready, apply it using:
oc apply -f yc-secret.yaml
# 2. Create a PersistentVolumeClaim for Logs
A PersistentVolumeClaim (PVC) is used to share logs between the BuggyApp container and the yc-360 script sidecar. Create a file ba-logs-pvc.yaml:
PVC File: ba-logs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ba-logs-pvc
namespace: yc-apps
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
2
3
4
5
6
7
8
9
10
11
Apply the PVC:
oc apply -f ba-logs-pvc.yaml
# 3. Configure ServiceAccount
The yc-360 script needs a ServiceAccount. Create yc-360-script-serviceaccount.yaml:
ServiceAccount File: yc-360-script-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: yc-360-script-serviceaccount
namespace: yc-apps
2
3
4
5
Apply the ServiceAccount:
oc apply -f yc-360-script-serviceaccount.yaml
TIP
If you need the yc-360 script to enrich data with Kubernetes namespace metadata, you'll also need a ClusterRoleBinding or RoleBinding. Set kubernetes: true in your yc-config.yaml and create the appropriate binding. See Step 5 below.
# 4. Deploy BuggyApp with yc-360 Script as a Sidecar
In this step, you'll deploy three containers within the same OpenShift Pod:
- yc-360 Script: Collects performance metrics from the application.
- BuggyApp: A sample Java application used for simulating performance scenarios. You can replace BuggyApp with your Java application.
- Traffic Generator: A lightweight
busyboxcontainer that generates HTTP requests to simulate real traffic and produce access log entries.
# Key Points
- ServiceAccount: The yc-360 script container uses the
yc-360-script-serviceaccountServiceAccount. - shareProcessNamespace: Set to
trueso the yc-360 script can see the BuggyApp's Java process. - Volumes: The yc-360 script mounts
yc-config.yamlfrom a Secret, logs from a shared PVC, and writes output to a writableemptyDirvolume. - Access Logging: BuggyApp uses webapp-runner's
--access-logflag to write Tomcat access logs to STDOUT, which are captured to a file viatee. - Ports: yc-360 Script listens on
8085, BuggyApp listens on9010.
# Deployment Manifest: buggyapp-yc-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: yc-apps
namespace: yc-apps
labels:
app: yc-apps
spec:
replicas: 1
selector:
matchLabels:
app: yc-apps
template:
metadata:
labels:
app: yc-apps
spec:
serviceAccountName: yc-360-script-serviceaccount
shareProcessNamespace: true
terminationGracePeriodSeconds: 180
containers:
- name: yc-360-script
image: ycrash/yc-360-script:latest
imagePullPolicy: Always
env:
- name: APP_NAME
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: HOST_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
ports:
- containerPort: 8085
resources:
requests:
memory: 100Mi
cpu: "50m"
limits:
memory: 350Mi
cpu: "100m"
volumeMounts:
- name: yc-config
mountPath: "/opt/workspace/yc-360-script/yc-config.yaml"
subPath: yc-config.yaml
- name: ba-logs-pvc
mountPath: "/opt/workspace/ba/logs"
readOnly: true
- name: yc-workspace
mountPath: "/opt/workspace/yc-360-script/yc-output"
- name: tmp
mountPath: "/tmp"
- name: traffic-gen
image: busybox:latest
imagePullPolicy: Always
command: ["/bin/sh", "-c"]
args:
- >-
while true; do
wget -q -O /dev/null http://localhost:9010/ 2>/dev/null || true;
sleep $(( RANDOM % 3 + 1 ));
done
resources:
requests:
memory: 16Mi
cpu: "10m"
limits:
memory: 32Mi
cpu: "25m"
- name: buggyapp
image: ycrash/buggyapp:alpine
imagePullPolicy: Always
env:
- name: APP_NAME
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: HOST_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
command: ["/bin/sh", "-c"]
args:
- >-
java -Xms512m -Xmx1g -verbose:gc
-Xlog:gc*:file=/opt/workspace/ba/logs/ba-gclog-%p.gc:time,uptime,level,tags
-XX:+UnlockDiagnosticVMOptions
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/workspace/ba/logs/ba-heapdump-%p.hprof
-XX:ErrorFile=/opt/workspace/ba/logs/ba-log-hs_err_pid-%p.log
-jar webapp-runner.jar --port 9010 --access-log --access-log-pattern '%h %l %u %t %r %s %b %D' buggyapp.war
2>&1 | tee /opt/workspace/ba/logs/app.log
ports:
- containerPort: 9010
resources:
requests:
memory: 512Mi
cpu: "200m"
limits:
memory: 1Gi
cpu: "500m"
volumeMounts:
- name: tomcat-files
mountPath: "/opt/workspace/ba/target"
- name: ba-logs-pvc
mountPath: "/opt/workspace/ba/logs"
- name: tmp
mountPath: "/tmp"
volumes:
- name: yc-config
secret:
secretName: yc-config
items:
- key: yc-config.yaml
path: yc-config.yaml
- name: tomcat-files
emptyDir: {}
- name: ba-logs-pvc
persistentVolumeClaim:
claimName: ba-logs-pvc
- name: yc-workspace
emptyDir: {}
- name: tmp
emptyDir: {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
TIP
This deployment uses the shareProcessNamespace: true flag. It allows containers within the same Pod to share the process namespace, enabling the yc-360 script to monitor processes running in the application container.
For more details on process namespace sharing, refer to the official Kubernetes documentation (opens new window).
Apply the deployment:
oc apply -f buggyapp-yc-deployment.yaml
# How Access Logging Works
The BuggyApp container uses a shell wrapper to enable Tomcat access logging:
java ... -jar webapp-runner.jar --port 9010 --access-log --access-log-pattern '%h %l %u %t %r %s %b %D' buggyapp.war 2>&1 | tee /opt/workspace/ba/logs/app.log
--access-log: Enables Tomcat's AccessLogValve to STDOUT--access-log-pattern '%h %l %u %t %r %s %b %D': Sets the log format including response time (%D)2>&1 | tee /opt/workspace/ba/logs/app.log: Captures all output (access logs + application logs) to a file that the yc-360 script can read
# Access Log Pattern Reference
| Token | Description | Example |
|---|---|---|
%h | Remote IP address | 10.0.0.1 |
%l | Remote logical username | - |
%u | Authenticated user | - |
%t | Timestamp | [07/Aug/2026:16:10:46 +0000] |
%r | Request line | GET / HTTP/1.1 |
%s | HTTP status code | 200 |
%b | Bytes sent | 15999 |
%D | Response time (ms) | 15 |
# Container Volumes Explained
| Volume | Mount Path | Purpose |
|---|---|---|
yc-config | /opt/workspace/yc-360-script/yc-config.yaml | yc-360 script configuration (from Secret) |
ba-logs-pvc | /opt/workspace/ba/logs | Shared PVC for GC logs, access logs, and app logs |
yc-workspace | /opt/workspace/yc-360-script/yc-output | Writable directory for yc-360 script output |
tomcat-files | /opt/workspace/ba/target | BuggyApp Tomcat working directory |
tmp | /tmp | Temporary files |
# 5. Create Services
Define services to expose both BuggyApp and the yc-360 script within the cluster.
# Service for BuggyApp: buggyapp-service.yaml
apiVersion: v1
kind: Service
metadata:
name: buggyapp-service
labels:
app: yc-apps
namespace: yc-apps
spec:
selector:
app: yc-apps
ports:
- protocol: TCP
port: 9010
targetPort: 9010
type: ClusterIP
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# Service for yc-360 Script: yc-360-script-service.yaml
apiVersion: v1
kind: Service
metadata:
name: yc-360-script-service
namespace: yc-apps
spec:
selector:
app: yc-apps
ports:
- protocol: TCP
port: 8085
targetPort: 8085
type: ClusterIP
2
3
4
5
6
7
8
9
10
11
12
13
Apply the Services:
oc apply -f buggyapp-service.yaml
oc apply -f yc-360-script-service.yaml
2
# 6. Create Route for External Access
Expose the BuggyApp outside the cluster using an OpenShift Route.
# Route for BuggyApp: buggyapp-ingress.yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: buggyapp-route
namespace: yc-apps
spec:
to:
kind: Service
name: buggyapp-service
port:
targetPort: 9010
tls:
termination: edge
wildcardPolicy: None
2
3
4
5
6
7
8
9
10
11
12
13
14
Apply the Route:
oc apply -f buggyapp-ingress.yaml
TIP
The yc-360 script does not serve HTTP traffic, so a Route for it is not required. You can access its logs and output via oc logs and oc exec.
# 7. Deploying the Configuration
# 1. Create the Namespace (if not already created)
oc new-project yc-apps --display-name 'yCrash Apps'
WARNING
If your OpenShift sandbox does not allow self-provisioning of new projects, use an existing namespace that you have access to. Replace yc-apps with your namespace in all YAML files.
# 2. Apply All Resources in Order
oc apply -f yc-360-script-serviceaccount.yaml
oc apply -f ba-logs-pvc.yaml
oc apply -f yc-secret.yaml
oc apply -f buggyapp-yc-deployment.yaml
oc apply -f buggyapp-service.yaml
oc apply -f yc-360-script-service.yaml
oc apply -f buggyapp-ingress.yaml
2
3
4
5
6
7
# 3. Verify the Deployment
# Check pods are running (should see 3 containers)
oc get pods -n yc-apps
# Check routes
oc get routes -n yc-apps
# Get the BuggyApp URL
oc get route buggyapp-route -n yc-apps -o jsonpath='{.spec.host}'
2
3
4
5
6
7
8
# 4. Access the Applications
- BuggyApp: Open the route URL in your browser
# 8. Verify Log Capture
Once the pods are running, verify that logs are being captured:
# Get the pod name
POD=$(oc get pod -n yc-apps -l app=yc-apps -o jsonpath='{.items[0].metadata.name}')
# Check that app.log has both access logs and application output
oc exec $POD -c buggyapp -n yc-apps -- tail -10 /opt/workspace/ba/logs/app.log
# Check GC logs are being written
oc exec $POD -c buggyapp -n yc-apps -- ls -la /opt/workspace/ba/logs/
# Check yc-360-script logs for M3 metric submissions
oc logs $POD -c yc-360-script -n yc-apps --tail=20
2
3
4
5
6
7
8
9
10
11
Expected access log output:
127.0.0.1 - - [07/Aug/2026:17:35:12 +0000] GET / HTTP/1.1 200 15999 1
127.0.0.1 - - [07/Aug/2026:17:35:13 +0000] GET / HTTP/1.1 200 15999 1
2
# 9. Execute yc-360 Script Manually (Optional)
The yc-360 script in M3 mode automatically reads the yc-config.yaml file and executes. If you need to trigger a manual capture:
oc exec -it $POD -c yc-360-script -n yc-apps -- /bin/bash
/opt/workspace/yc-360-script/yc -onlyCapture -p buggyapp -j /opt/java/openjdk -a BuggyApp
2
Arguments:
-onlyCapture: Triggers a one-time capture instead of continuous monitoring-p buggyapp: Unique token to identify the target Java process. Learn more about What is Unique Token?-j /opt/java/openjdk: The directory path where Java is installed in your container-a BuggyApp: Friendly name for the application (displayed in the yCrash dashboard)
# (Optional) Configure RBAC for Kubernetes Enrichment
If you want the yc-360 script to enrich data with Kubernetes namespace metadata, set kubernetes: true in your yc-config.yaml and create the appropriate RBAC resources.
# RoleBinding (namespace-scoped): yc-360-script-rolebinding.yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: yc-360-script-rolebinding
namespace: yc-apps
subjects:
- kind: ServiceAccount
name: yc-360-script-serviceaccount
namespace: yc-apps
roleRef:
kind: ClusterRole
name: view
apiGroup: rbac.authorization.k8s.io
2
3
4
5
6
7
8
9
10
11
12
13
WARNING
A RoleBinding only grants permissions within the namespace. If you need cluster-wide namespace listing, you'll need a ClusterRoleBinding with cluster-admin or a custom ClusterRole. Not all OpenShift sandboxes allow creating ClusterRoleBindings.
# Troubleshooting
# 1. Check Pod Logs
# BuggyApp logs (includes access logs and application output)
oc logs <pod_name> -c buggyapp -n yc-apps --tail=50
# yc-360-script logs
oc logs <pod_name> -c yc-360-script -n yc-apps --tail=50
2
3
4
5
# 2. Check Service Routes
oc get routes -n yc-apps
# 3. Check ServiceAccount Permissions
oc describe serviceaccount yc-360-script-serviceaccount -n yc-apps
# Complete Deployment YAML Files
Below are all the YAML files needed for the complete deployment.
# yc-secret.yaml
apiVersion: v1
kind: Secret
metadata:
name: yc-config
namespace: yc-apps
stringData:
yc-config.yaml: |
version: "1"
options:
k: <API_KEY>
s: <http://MY-YC-SERVER:PORT>
j: /opt/java/openjdk
kubernetes: false
m3: true
m3Frequency: 60s
storagePath: /opt/workspace/yc-360-script/yc-output
processTokens:
- buggyapp$BuggyApp
accessLogs:
- /opt/workspace/ba/logs/app.log$BuggyApp
accessLogFormats:
- %h %l %u %t %r %s %b %D$BuggyApp
accessLogSources:
- Tomcat$BuggyApp
appLogs:
- /opt/workspace/ba/logs/app.log$BuggyApp
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# ba-logs-pvc.yaml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: ba-logs-pvc
namespace: yc-apps
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 5Gi
2
3
4
5
6
7
8
9
10
11
# yc-360-script-serviceaccount.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
name: yc-360-script-serviceaccount
namespace: yc-apps
2
3
4
5
# buggyapp-yc-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: yc-apps
namespace: yc-apps
labels:
app: yc-apps
spec:
replicas: 1
selector:
matchLabels:
app: yc-apps
template:
metadata:
labels:
app: yc-apps
spec:
serviceAccountName: yc-360-script-serviceaccount
shareProcessNamespace: true
terminationGracePeriodSeconds: 180
containers:
- name: yc-360-script
image: ycrash/yc-360-script:latest
imagePullPolicy: Always
env:
- name: APP_NAME
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: HOST_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
ports:
- containerPort: 8085
resources:
requests:
memory: 100Mi
cpu: "50m"
limits:
memory: 350Mi
cpu: "100m"
volumeMounts:
- name: yc-config
mountPath: "/opt/workspace/yc-360-script/yc-config.yaml"
subPath: yc-config.yaml
- name: ba-logs-pvc
mountPath: "/opt/workspace/ba/logs"
readOnly: true
- name: yc-workspace
mountPath: "/opt/workspace/yc-360-script/yc-output"
- name: tmp
mountPath: "/tmp"
- name: traffic-gen
image: busybox:latest
imagePullPolicy: Always
command: ["/bin/sh", "-c"]
args:
- >-
while true; do
wget -q -O /dev/null http://localhost:9010/ 2>/dev/null || true;
sleep $(( RANDOM % 3 + 1 ));
done
resources:
requests:
memory: 16Mi
cpu: "10m"
limits:
memory: 32Mi
cpu: "25m"
- name: buggyapp
image: ycrash/buggyapp:alpine
imagePullPolicy: Always
env:
- name: APP_NAME
valueFrom:
fieldRef:
fieldPath: metadata.labels['app']
- name: HOST_NAME
valueFrom:
fieldRef:
fieldPath: spec.nodeName
command: ["/bin/sh", "-c"]
args:
- >-
java -Xms512m -Xmx1g -verbose:gc
-Xlog:gc*:file=/opt/workspace/ba/logs/ba-gclog-%p.gc:time,uptime,level,tags
-XX:+UnlockDiagnosticVMOptions
-XX:+HeapDumpOnOutOfMemoryError
-XX:HeapDumpPath=/opt/workspace/ba/logs/ba-heapdump-%p.hprof
-XX:ErrorFile=/opt/workspace/ba/logs/ba-log-hs_err_pid-%p.log
-jar webapp-runner.jar --port 9010 --access-log --access-log-pattern '%h %l %u %t %r %s %b %D' buggyapp.war
2>&1 | tee /opt/workspace/ba/logs/app.log
ports:
- containerPort: 9010
resources:
requests:
memory: 512Mi
cpu: "200m"
limits:
memory: 1Gi
cpu: "500m"
volumeMounts:
- name: tomcat-files
mountPath: "/opt/workspace/ba/target"
- name: ba-logs-pvc
mountPath: "/opt/workspace/ba/logs"
- name: tmp
mountPath: "/tmp"
volumes:
- name: yc-config
secret:
secretName: yc-config
items:
- key: yc-config.yaml
path: yc-config.yaml
- name: tomcat-files
emptyDir: {}
- name: ba-logs-pvc
persistentVolumeClaim:
claimName: ba-logs-pvc
- name: yc-workspace
emptyDir: {}
- name: tmp
emptyDir: {}
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# buggyapp-service.yaml
apiVersion: v1
kind: Service
metadata:
name: buggyapp-service
labels:
app: yc-apps
namespace: yc-apps
spec:
selector:
app: yc-apps
ports:
- protocol: TCP
port: 9010
targetPort: 9010
type: ClusterIP
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# yc-360-script-service.yaml
apiVersion: v1
kind: Service
metadata:
name: yc-360-script-service
namespace: yc-apps
spec:
selector:
app: yc-apps
ports:
- protocol: TCP
port: 8085
targetPort: 8085
type: ClusterIP
2
3
4
5
6
7
8
9
10
11
12
13
# buggyapp-ingress.yaml
apiVersion: route.openshift.io/v1
kind: Route
metadata:
name: buggyapp-route
namespace: yc-apps
spec:
to:
kind: Service
name: buggyapp-service
port:
targetPort: 9010
tls:
termination: edge
wildcardPolicy: None
2
3
4
5
6
7
8
9
10
11
12
13
14