kdotnet-dump 0.1.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,49 @@
1
+ name: Build Test Images
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ permissions:
7
+ contents: read
8
+ packages: write
9
+
10
+ jobs:
11
+ build-test-image:
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ dotnet-version:
16
+ - "10.0"
17
+ rt-image:
18
+ - noble
19
+ - alpine3.22
20
+ - noble-chiseled
21
+ steps:
22
+ - name: Checkout code
23
+ uses: actions/checkout@v4
24
+ - name: Login to Docker Hub
25
+ uses: docker/login-action@v3
26
+ with:
27
+ registry: ghcr.io
28
+ username: ${{ github.actor }}
29
+ password: ${{ secrets.GITHUB_TOKEN }}
30
+ - name: Set up QEMU
31
+ uses: docker/setup-qemu-action@v3
32
+ - name: Set up Docker Buildx
33
+ uses: docker/setup-buildx-action@v3
34
+ - name: Build and push
35
+ uses: docker/build-push-action@v6
36
+ with:
37
+ context: ./testimages
38
+ push: true
39
+ build-args: |
40
+ rt_image=${{ format('mcr.microsoft.com/dotnet/aspnet:{0}-{1}', matrix.dotnet-version, matrix.rt-image) }}
41
+ sdk_image=${{ format('mcr.microsoft.com/dotnet/sdk:{0}', matrix.dotnet-version) }}
42
+ tags: ghcr.io/gprossliner/kdotnet-dump-testapp:${{ matrix.dotnet-version }}-${{ matrix.rt-image }}
43
+ platforms: linux/amd64,linux/arm64
44
+ annotations: |
45
+ org.opencontainers.image.source="https://github.com/gprossliner/kdotnet-dump"
46
+ org.opencontainers.image.description="Test application for kdotnet-dump integration tests"
47
+
48
+
49
+
@@ -0,0 +1,35 @@
1
+ name: Build and Publish to PyPI
2
+
3
+ on:
4
+ workflow_dispatch:
5
+
6
+ push:
7
+ tags:
8
+ - 'v*'
9
+
10
+ jobs:
11
+ build-and-publish:
12
+ runs-on: ubuntu-latest
13
+ permissions:
14
+ # IMPORTANT: this permission is mandatory for Trusted Publishing
15
+ id-token: write
16
+ steps:
17
+ - name: Checkout code
18
+ uses: actions/checkout@v4
19
+
20
+ - name: Set up Python
21
+ uses: actions/setup-python@v5
22
+ with:
23
+ python-version: '3.14'
24
+
25
+ - name: Install build tools
26
+ run: |
27
+ python -m pip install --upgrade pip
28
+ pip install build hatchling hatch-vcs
29
+
30
+ - name: Build package
31
+ run: python -m build
32
+
33
+ - name: Publish to PyPI
34
+ uses: pypa/gh-action-pypi-publish@release/v1
35
+
@@ -0,0 +1,54 @@
1
+ name: Integration Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main ]
6
+ pull_request:
7
+ branches: [ main ]
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ test:
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Set up Python
19
+ uses: actions/setup-python@v5
20
+ with:
21
+ python-version: '3.11'
22
+
23
+ - name: Install dependencies
24
+ run: |
25
+ pip install -r tests/requirements.txt
26
+
27
+ - name: Create kind cluster
28
+ uses: helm/kind-action@v1
29
+ with:
30
+ cluster_name: kdotnet-dump-test
31
+ wait: 120s
32
+
33
+ - name: Verify cluster
34
+ run: |
35
+ kubectl cluster-info
36
+ kubectl get nodes
37
+
38
+ - name: Run integration tests
39
+ run: |
40
+ cd tests
41
+ pytest test_entry.py -v -s --tb=short
42
+
43
+ - name: Upload test results
44
+ if: always()
45
+ uses: actions/upload-artifact@v4
46
+ with:
47
+ name: test-results
48
+ path: tests/test-results/
49
+ if-no-files-found: ignore
50
+
51
+ - name: Cleanup
52
+ if: always()
53
+ run: |
54
+ kind delete cluster --name kdotnet-dump-test || true
@@ -0,0 +1,4 @@
1
+ core_*
2
+
3
+ __pycache__/
4
+ latest_dump
@@ -0,0 +1,17 @@
1
+ {
2
+ // Use IntelliSense to learn about possible attributes.
3
+ // Hover to view descriptions of existing attributes.
4
+ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5
+ "version": "0.2.0",
6
+ "configurations": [
7
+
8
+ {
9
+ "name": "Python Debugger: Current File with Arguments",
10
+ "type": "debugpy",
11
+ "request": "launch",
12
+ "program": "${file}",
13
+ "console": "integratedTerminal",
14
+ "args": "-l app=test-noble-root --strategy=debug-container --dump-type mini"
15
+ }
16
+ ]
17
+ }
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Günter Prossliner
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,239 @@
1
+ Metadata-Version: 2.4
2
+ Name: kdotnet-dump
3
+ Version: 0.1.0
4
+ Summary: CLI tool for dumping dotnet processes running in kubernetes pods
5
+ Author-email: Günter Prossliner <6724584+gprossliner@users.noreply.github.com>
6
+ License-Expression: MIT
7
+ License-File: LICENSE
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: Programming Language :: Python :: 3
10
+ Requires-Python: >=3.11
11
+ Description-Content-Type: text/markdown
12
+
13
+ # kdotnet-dump
14
+
15
+ A tool to create and download .NET process dumps from Kubernetes pods, supporting both standard and hardened (non-root) containers.
16
+
17
+ ## Purpose
18
+
19
+ Creating .NET dumps from containers running in Kubernetes can be challenging, especially with:
20
+ - **Non-root containers** - Can't install tools or write to most filesystem locations
21
+ - **Restricted Pod Security Standards** - Limited privileges and capabilities
22
+ - **Large dump files** - Can exceed 350MB, causing kubectl cp to fail
23
+
24
+ `kdotnet-dump` solves these problems by:
25
+ 1. Using ephemeral debug containers to isolate diagnostic tooling from application containers
26
+ 2. Automatically detecting container UID/GID and matching security context
27
+ 3. Downloading dotnet-dump dynamically (no need to bake it into images)
28
+ 4. Using chunked base64 transfer to handle large files reliably
29
+ 5. Working with `/proc/1/root/tmp` to share filesystem between debug and target containers
30
+
31
+ ## Installation
32
+
33
+ ```bash
34
+ git clone https://github.com/gprossliner/kdotnet-dump.git
35
+ cd kdotnet-dump
36
+ ```
37
+
38
+ No additional dependencies required - just Python 3 and `kubectl`.
39
+
40
+ ## Command Line Arguments
41
+
42
+ ```
43
+ usage: entry.py [-h] [--strategy {same-container,debug-container}]
44
+ [-n NAMESPACE] [-l SELECTOR] [--dump-type {mini,heap,triage,full}]
45
+ [--dump-pid DUMP_PID] [--debug-image DEBUG_IMAGE]
46
+ [pod]
47
+
48
+ positional arguments:
49
+ pod Pod name (or use --selector)
50
+
51
+ optional arguments:
52
+ -h, --help Show this help message and exit
53
+
54
+ --strategy {same-container,debug-container}
55
+ Strategy to create the dump (default: debug-container)
56
+ - same-container: Runs dotnet-dump in the target container (requires root)
57
+ - debug-container: Uses ephemeral debug container (works with non-root)
58
+
59
+ -n, --namespace NAMESPACE
60
+ Kubernetes namespace (default: default)
61
+
62
+ -l, --selector SELECTOR
63
+ Label selector to find pod (e.g., app=myapp)
64
+ Use this instead of specifying pod name directly
65
+
66
+ --dump-type {mini,heap,triage,full}
67
+ Dump type (default: mini)
68
+ - mini: Minimal dump with stacks and exception info
69
+ - heap: Includes heap memory
70
+ - triage: Minimal info for initial diagnosis
71
+ - full: Complete memory dump (can be very large)
72
+
73
+ --dump-pid DUMP_PID Process ID to dump (default: 1)
74
+ Usually PID 1 is the main application process
75
+
76
+ --debug-image DEBUG_IMAGE
77
+ Debug container image to use
78
+ (default: mcr.microsoft.com/dotnet/sdk:latest)
79
+ ```
80
+
81
+ ## Examples
82
+
83
+ ### Basic Usage - Find pod by label selector
84
+
85
+ ```bash
86
+ python3 entry.py -n production -l app=api --dump-type mini
87
+ ```
88
+
89
+ This will:
90
+ 1. Find a pod with label `app=api` in namespace `production`
91
+ 2. Create an ephemeral debug container
92
+ 3. Download and run dotnet-dump to create a mini dump
93
+ 4. Download the dump to `./latest_dump`
94
+
95
+ ### Specify pod name directly
96
+
97
+ ```bash
98
+ python3 entry.py -n production my-app-pod-12345 --dump-type full
99
+ ```
100
+
101
+ ### Create full heap dump for memory analysis
102
+
103
+ ```bash
104
+ python3 entry.py -l app=api --dump-type heap
105
+ ```
106
+
107
+ ### Use custom debug image (e.g., specific .NET SDK version)
108
+
109
+ ```bash
110
+ python3 entry.py -l app=api --debug-image mcr.microsoft.com/dotnet/sdk:8.0
111
+ ```
112
+
113
+ ### Use same-container strategy (requires root)
114
+
115
+ ```bash
116
+ python3 entry.py -l app=api --strategy same-container --dump-type mini
117
+ ```
118
+
119
+ ## Analyzing Dumps
120
+
121
+ ### On Linux
122
+
123
+ ```bash
124
+ dotnet tool install -g dotnet-dump
125
+ dotnet-dump analyze ./latest_dump
126
+ ```
127
+
128
+ ### On macOS (using Docker)
129
+
130
+ macOS doesn't support analyzing Linux dumps natively. Use a Docker container with the correct platform:
131
+
132
+ ```bash
133
+ # For Apple Silicon (M1/M2/M3), specify linux/amd64 platform
134
+ docker run --rm -it --platform linux/amd64 \
135
+ -v $(pwd):/dumps \
136
+ mcr.microsoft.com/dotnet/sdk:10.0 \
137
+ bash
138
+
139
+ # Inside the container
140
+ dotnet tool install dotnet-dump
141
+ dotnet tool run dotnet-dump analyze /dumps/latest_dump
142
+ ```
143
+
144
+ Common dotnet-dump commands:
145
+ ```
146
+ clrthreads # List managed threads
147
+ clrstack # Show managed stack trace
148
+ dumpheap -stat # Show heap statistics
149
+ sos help # Show all available commands
150
+ ```
151
+
152
+ ## How It Works
153
+
154
+ ### Debug Container Strategy (Recommended)
155
+
156
+ 1. **Pod Discovery**: Finds target pod using label selector or name
157
+ 2. **Container Detection**: Identifies the default container and extracts UID/GID
158
+ 3. **Security Context Matching**: Creates debug container with same UID/GID as target
159
+ 4. **Shared Process Namespace**: Uses `--share-processes` to access target container's processes
160
+ 5. **Dump Creation**: Downloads dotnet-dump and creates dump in `/proc/1/root/tmp/dumps`
161
+ 6. **File Transfer**: Uses chunked base64 encoding to reliably download large files
162
+
163
+ ### Same Container Strategy
164
+
165
+ Simpler but requires:
166
+ - Container running as root
167
+ - Writable `/tmp` directory
168
+ - Works by installing dotnet-dump directly in the target container
169
+
170
+ ## Requirements
171
+
172
+ ### Kubernetes Cluster
173
+ - Kubernetes 1.23+ (for ephemeral containers)
174
+ - Kubernetes 1.28+ recommended (for UID/GID detection from status)
175
+
176
+ ### RBAC Permissions
177
+ For debug-container strategy, the user needs:
178
+ ```yaml
179
+ apiVersion: rbac.authorization.k8s.io/v1
180
+ kind: ClusterRole
181
+ metadata:
182
+ name: ephemeral-container-access
183
+ labels:
184
+ # This label causes the ClusterRole to be aggregated to the edit / admin role
185
+ rbac.authorization.k8s.io/aggregate-to-edit: "true"
186
+ rbac.authorization.k8s.io/aggregate-to-admin: "true"
187
+ rules:
188
+ - apiGroups: [""]
189
+ resources: ["pods/ephemeralcontainers"]
190
+ verbs: ["patch", "create", "get"]
191
+ ```
192
+
193
+ ### Target Container Requirements
194
+ - .NET application running (tested with .NET 8.0, 9.0, 10.0)
195
+ - Writable `/tmp` directory OR mounted emptyDir volume
196
+ - For `readOnlyRootFilesystem: true`, mount emptyDir at `/tmp`
197
+
198
+ ## Troubleshooting
199
+
200
+ ### "Access to the path '/.dotnet' is denied"
201
+ This occurs in non-root containers. Use `--strategy debug-container` (default).
202
+
203
+ ### "Read-only file system" errors
204
+ For containers with `readOnlyRootFilesystem: true`, ensure `/tmp` has an emptyDir mount:
205
+ ```yaml
206
+ volumeMounts:
207
+ - name: tmp
208
+ mountPath: /tmp
209
+ volumes:
210
+ - name: tmp
211
+ emptyDir: {}
212
+ ```
213
+
214
+ ### Large files fail with websocket errors
215
+ The tool automatically uses chunked transfer for reliability. If issues persist, the chunks are 10MB by default and can't be adjusted without code changes.
216
+
217
+ ### "No pods found with selector"
218
+ Verify the label selector matches your pods:
219
+ ```bash
220
+ kubectl get pods -l app=myapp -n your-namespace
221
+ ```
222
+
223
+ ## Testing
224
+
225
+ Integration tests are available in the `tests/` directory:
226
+
227
+ ```bash
228
+ pip install -r tests/requirements.txt
229
+ pytest tests/test_entry.py -v
230
+ ```
231
+
232
+ Tests deploy sample applications and verify dump creation across different configurations:
233
+ - Root vs non-root containers
234
+ - Debian vs Alpine vs Chiseled images
235
+ - With and without `readOnlyRootFilesystem`
236
+
237
+ ## License
238
+
239
+ MIT
@@ -0,0 +1,31 @@
1
+ [build-system]
2
+ requires = ["hatchling >= 1.26", "hatch-vcs"]
3
+ build-backend = "hatchling.build"
4
+
5
+ [project]
6
+ name = "kdotnet-dump"
7
+ dynamic = ["version"]
8
+ description = "CLI tool for dumping dotnet processes running in kubernetes pods"
9
+ authors = [
10
+ { name = "Günter Prossliner", email = "6724584+gprossliner@users.noreply.github.com" }
11
+ ]
12
+ readme = "readme.md"
13
+ requires-python = ">=3.11"
14
+ dependencies = []
15
+ classifiers = [
16
+ "Programming Language :: Python :: 3",
17
+ "Operating System :: OS Independent",
18
+ ]
19
+ license = "MIT"
20
+
21
+ [project.scripts]
22
+ kdotnet-dump = "kdotnet_dump.cli:main"
23
+
24
+ [tool.hatch.version]
25
+ source = "vcs"
26
+
27
+ [tool.hatch.build.targets.wheel]
28
+ packages = ["src/kdotnet_dump"]
29
+
30
+ [tool.hatch.build.targets.wheel.force-include]
31
+ "src/kdotnet_dump/remote.sh" = "kdotnet_dump/remote.sh"
@@ -0,0 +1,12 @@
1
+ apiVersion: rbac.authorization.k8s.io/v1
2
+ kind: ClusterRole
3
+ metadata:
4
+ name: ephemeral-containers-edit
5
+ labels:
6
+ # This label causes the ClusterRole to be aggregated to the edit role
7
+ rbac.authorization.k8s.io/aggregate-to-edit: "true"
8
+ rbac.authorization.k8s.io/aggregate-to-admin: "true"
9
+ rules:
10
+ - apiGroups: [""]
11
+ resources: ["pods/ephemeralcontainers"]
12
+ verbs: ["get", "list", "watch", "create", "update", "patch"]
@@ -0,0 +1,227 @@
1
+ # kdotnet-dump
2
+
3
+ A tool to create and download .NET process dumps from Kubernetes pods, supporting both standard and hardened (non-root) containers.
4
+
5
+ ## Purpose
6
+
7
+ Creating .NET dumps from containers running in Kubernetes can be challenging, especially with:
8
+ - **Non-root containers** - Can't install tools or write to most filesystem locations
9
+ - **Restricted Pod Security Standards** - Limited privileges and capabilities
10
+ - **Large dump files** - Can exceed 350MB, causing kubectl cp to fail
11
+
12
+ `kdotnet-dump` solves these problems by:
13
+ 1. Using ephemeral debug containers to isolate diagnostic tooling from application containers
14
+ 2. Automatically detecting container UID/GID and matching security context
15
+ 3. Downloading dotnet-dump dynamically (no need to bake it into images)
16
+ 4. Using chunked base64 transfer to handle large files reliably
17
+ 5. Working with `/proc/1/root/tmp` to share filesystem between debug and target containers
18
+
19
+ ## Installation
20
+
21
+ ```bash
22
+ git clone https://github.com/gprossliner/kdotnet-dump.git
23
+ cd kdotnet-dump
24
+ ```
25
+
26
+ No additional dependencies required - just Python 3 and `kubectl`.
27
+
28
+ ## Command Line Arguments
29
+
30
+ ```
31
+ usage: entry.py [-h] [--strategy {same-container,debug-container}]
32
+ [-n NAMESPACE] [-l SELECTOR] [--dump-type {mini,heap,triage,full}]
33
+ [--dump-pid DUMP_PID] [--debug-image DEBUG_IMAGE]
34
+ [pod]
35
+
36
+ positional arguments:
37
+ pod Pod name (or use --selector)
38
+
39
+ optional arguments:
40
+ -h, --help Show this help message and exit
41
+
42
+ --strategy {same-container,debug-container}
43
+ Strategy to create the dump (default: debug-container)
44
+ - same-container: Runs dotnet-dump in the target container (requires root)
45
+ - debug-container: Uses ephemeral debug container (works with non-root)
46
+
47
+ -n, --namespace NAMESPACE
48
+ Kubernetes namespace (default: default)
49
+
50
+ -l, --selector SELECTOR
51
+ Label selector to find pod (e.g., app=myapp)
52
+ Use this instead of specifying pod name directly
53
+
54
+ --dump-type {mini,heap,triage,full}
55
+ Dump type (default: mini)
56
+ - mini: Minimal dump with stacks and exception info
57
+ - heap: Includes heap memory
58
+ - triage: Minimal info for initial diagnosis
59
+ - full: Complete memory dump (can be very large)
60
+
61
+ --dump-pid DUMP_PID Process ID to dump (default: 1)
62
+ Usually PID 1 is the main application process
63
+
64
+ --debug-image DEBUG_IMAGE
65
+ Debug container image to use
66
+ (default: mcr.microsoft.com/dotnet/sdk:latest)
67
+ ```
68
+
69
+ ## Examples
70
+
71
+ ### Basic Usage - Find pod by label selector
72
+
73
+ ```bash
74
+ python3 entry.py -n production -l app=api --dump-type mini
75
+ ```
76
+
77
+ This will:
78
+ 1. Find a pod with label `app=api` in namespace `production`
79
+ 2. Create an ephemeral debug container
80
+ 3. Download and run dotnet-dump to create a mini dump
81
+ 4. Download the dump to `./latest_dump`
82
+
83
+ ### Specify pod name directly
84
+
85
+ ```bash
86
+ python3 entry.py -n production my-app-pod-12345 --dump-type full
87
+ ```
88
+
89
+ ### Create full heap dump for memory analysis
90
+
91
+ ```bash
92
+ python3 entry.py -l app=api --dump-type heap
93
+ ```
94
+
95
+ ### Use custom debug image (e.g., specific .NET SDK version)
96
+
97
+ ```bash
98
+ python3 entry.py -l app=api --debug-image mcr.microsoft.com/dotnet/sdk:8.0
99
+ ```
100
+
101
+ ### Use same-container strategy (requires root)
102
+
103
+ ```bash
104
+ python3 entry.py -l app=api --strategy same-container --dump-type mini
105
+ ```
106
+
107
+ ## Analyzing Dumps
108
+
109
+ ### On Linux
110
+
111
+ ```bash
112
+ dotnet tool install -g dotnet-dump
113
+ dotnet-dump analyze ./latest_dump
114
+ ```
115
+
116
+ ### On macOS (using Docker)
117
+
118
+ macOS doesn't support analyzing Linux dumps natively. Use a Docker container with the correct platform:
119
+
120
+ ```bash
121
+ # For Apple Silicon (M1/M2/M3), specify linux/amd64 platform
122
+ docker run --rm -it --platform linux/amd64 \
123
+ -v $(pwd):/dumps \
124
+ mcr.microsoft.com/dotnet/sdk:10.0 \
125
+ bash
126
+
127
+ # Inside the container
128
+ dotnet tool install dotnet-dump
129
+ dotnet tool run dotnet-dump analyze /dumps/latest_dump
130
+ ```
131
+
132
+ Common dotnet-dump commands:
133
+ ```
134
+ clrthreads # List managed threads
135
+ clrstack # Show managed stack trace
136
+ dumpheap -stat # Show heap statistics
137
+ sos help # Show all available commands
138
+ ```
139
+
140
+ ## How It Works
141
+
142
+ ### Debug Container Strategy (Recommended)
143
+
144
+ 1. **Pod Discovery**: Finds target pod using label selector or name
145
+ 2. **Container Detection**: Identifies the default container and extracts UID/GID
146
+ 3. **Security Context Matching**: Creates debug container with same UID/GID as target
147
+ 4. **Shared Process Namespace**: Uses `--share-processes` to access target container's processes
148
+ 5. **Dump Creation**: Downloads dotnet-dump and creates dump in `/proc/1/root/tmp/dumps`
149
+ 6. **File Transfer**: Uses chunked base64 encoding to reliably download large files
150
+
151
+ ### Same Container Strategy
152
+
153
+ Simpler but requires:
154
+ - Container running as root
155
+ - Writable `/tmp` directory
156
+ - Works by installing dotnet-dump directly in the target container
157
+
158
+ ## Requirements
159
+
160
+ ### Kubernetes Cluster
161
+ - Kubernetes 1.23+ (for ephemeral containers)
162
+ - Kubernetes 1.28+ recommended (for UID/GID detection from status)
163
+
164
+ ### RBAC Permissions
165
+ For debug-container strategy, the user needs:
166
+ ```yaml
167
+ apiVersion: rbac.authorization.k8s.io/v1
168
+ kind: ClusterRole
169
+ metadata:
170
+ name: ephemeral-container-access
171
+ labels:
172
+ # This label causes the ClusterRole to be aggregated to the edit / admin role
173
+ rbac.authorization.k8s.io/aggregate-to-edit: "true"
174
+ rbac.authorization.k8s.io/aggregate-to-admin: "true"
175
+ rules:
176
+ - apiGroups: [""]
177
+ resources: ["pods/ephemeralcontainers"]
178
+ verbs: ["patch", "create", "get"]
179
+ ```
180
+
181
+ ### Target Container Requirements
182
+ - .NET application running (tested with .NET 8.0, 9.0, 10.0)
183
+ - Writable `/tmp` directory OR mounted emptyDir volume
184
+ - For `readOnlyRootFilesystem: true`, mount emptyDir at `/tmp`
185
+
186
+ ## Troubleshooting
187
+
188
+ ### "Access to the path '/.dotnet' is denied"
189
+ This occurs in non-root containers. Use `--strategy debug-container` (default).
190
+
191
+ ### "Read-only file system" errors
192
+ For containers with `readOnlyRootFilesystem: true`, ensure `/tmp` has an emptyDir mount:
193
+ ```yaml
194
+ volumeMounts:
195
+ - name: tmp
196
+ mountPath: /tmp
197
+ volumes:
198
+ - name: tmp
199
+ emptyDir: {}
200
+ ```
201
+
202
+ ### Large files fail with websocket errors
203
+ The tool automatically uses chunked transfer for reliability. If issues persist, the chunks are 10MB by default and can't be adjusted without code changes.
204
+
205
+ ### "No pods found with selector"
206
+ Verify the label selector matches your pods:
207
+ ```bash
208
+ kubectl get pods -l app=myapp -n your-namespace
209
+ ```
210
+
211
+ ## Testing
212
+
213
+ Integration tests are available in the `tests/` directory:
214
+
215
+ ```bash
216
+ pip install -r tests/requirements.txt
217
+ pytest tests/test_entry.py -v
218
+ ```
219
+
220
+ Tests deploy sample applications and verify dump creation across different configurations:
221
+ - Root vs non-root containers
222
+ - Debian vs Alpine vs Chiseled images
223
+ - With and without `readOnlyRootFilesystem`
224
+
225
+ ## License
226
+
227
+ MIT