Skip to content

Commit 13ca780

Browse files
authored
chore: improve devcontainer experience (#2097)
## Description The devcontainer is missing several tools needed for development (LLVM/clang, jq), uses a shell script for setup instead of declarative devcontainer features, and has no CI validation. This PR overhauls the devcontainer: - Replace `installMoreTools.sh` with declarative devcontainer features (LLVM 17, pinned versions) - Add persistent Go module/build cache volume mounts - Add jq, Kind cluster auto-creation on startup, and VS Code settings for golangci-lint + gofumpt - Add `devcontainer.yaml` CI workflow that builds the container and validates tooling - Expand development guide with devcontainer quick-start instructions - Fix markdownlint warnings in bpftrace troubleshooting doc ## Related Issue Partially addresses #2027 (lint alignment will be handled in a follow-up PR) ## Checklist - [x] I have read the [contributing documentation](https://retina.sh/docs/Contributing/overview). - [x] I signed and signed-off the commits (`git commit -S -s ...`). - [x] I have correctly attributed the author(s) of the code. - [x] I have tested the changes locally. - [x] I have followed the project's style guidelines. - [x] I have updated the documentation, if necessary. - [ ] I have added tests, if applicable. ## Screenshots (if applicable) or Testing Completed CI will validate the devcontainer builds and all tools are available via the new `devcontainer.yaml` workflow. Signed-off-by: Quang Nguyen <nguyenquang@microsoft.com>
1 parent 732952a commit 13ca780

5 files changed

Lines changed: 152 additions & 37 deletions

File tree

.devcontainer/devcontainer.json

Lines changed: 87 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,101 @@
22
"name": "retina",
33
"image": "mcr.microsoft.com/devcontainers/base:noble",
44
"features": {
5-
"ghcr.io/devcontainers/features/docker-in-docker:2": {},
6-
"ghcr.io/devcontainers/features/github-cli:1": {},
7-
"ghcr.io/devcontainers/features/go:1": {
5+
"ghcr.io/devcontainers/features/docker-in-docker:2.16.1": {},
6+
"ghcr.io/devcontainers/features/github-cli:1.1.0": {},
7+
"ghcr.io/devcontainers/features/go:1.3.3": {
88
"version": "1.24.11"
99
},
10-
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1": {},
11-
"ghcr.io/devcontainers-extra/features/kind:1": {},
12-
"ghcr.io/devcontainers/features/azure-cli:1": {}
10+
"ghcr.io/devcontainers/features/kubectl-helm-minikube:1.3.1": {},
11+
"ghcr.io/devcontainers-extra/features/kind:1.0.15": {},
12+
"ghcr.io/devcontainers/features/azure-cli:1.2.9": {},
13+
// LLVM 17 is the minimum version available for Ubuntu Noble on apt.llvm.org.
14+
// Provides clang and llvm-strip needed for eBPF compilation.
15+
"ghcr.io/devcontainers-community/features/llvm:3.2.0": {
16+
"version": "17"
17+
}
18+
},
19+
"hostRequirements": {
20+
"cpus": 4,
21+
"memory": "8gb",
22+
"storage": "32gb"
23+
},
24+
// Persist Go module and build caches across container rebuilds.
25+
"mounts": [
26+
{
27+
"type": "volume",
28+
"source": "retina-gomodcache",
29+
"target": "/go/pkg/mod"
30+
},
31+
{
32+
"type": "volume",
33+
"source": "retina-gobuildcache",
34+
"target": "/home/vscode/.cache/go-build"
35+
}
36+
],
37+
// These commands run in parallel during container creation.
38+
"onCreateCommand": {
39+
// The LLVM feature installs versioned binaries (clang-17, llvm-strip-17).
40+
// Create unversioned symlinks so the build system can find them.
41+
"symlinks": "sudo ln -sf /usr/bin/clang-17 /usr/bin/clang && sudo ln -sf /usr/bin/llvm-strip-17 /usr/bin/llvm-strip",
42+
// Fix ownership of volume mounts (created as root) and cache dirs,
43+
// then download Go modules.
44+
"go-setup": "sudo chown -R vscode:vscode /go /home/vscode/.cache && go mod download",
45+
// Install jq (needed by some Makefile targets and scripts).
46+
"apt-deps": "sudo apt-get update && sudo apt-get install -y --no-install-recommends jq && sudo rm -rf /var/lib/apt/lists/*"
47+
},
48+
// Wait for Docker-in-Docker to be ready, then create a Kind cluster for local testing.
49+
"postStartCommand": {
50+
"kind": "while ! docker info >/dev/null 2>&1; do sleep 1; done && kind create cluster 2>/dev/null || true"
51+
},
52+
"waitFor": "onCreateCommand",
53+
"forwardPorts": [
54+
9965,
55+
4244,
56+
10093
57+
],
58+
"portsAttributes": {
59+
"9965": {
60+
"label": "Hubble Metrics",
61+
"onAutoForward": "silent"
62+
},
63+
"4244": {
64+
"label": "Hubble Relay",
65+
"onAutoForward": "silent"
66+
},
67+
"10093": {
68+
"label": "Retina Metrics",
69+
"onAutoForward": "silent"
70+
}
1371
},
14-
"postCreateCommand": "bash .devcontainer/installMoreTools.sh && while ! docker info >/dev/null 2>&1; do sleep 1; done && kind create cluster",
1572
"customizations": {
1673
"vscode": {
1774
"extensions": [
18-
"esbenp.prettier-vscode",
1975
"golang.go",
20-
"mutantdino.resourcemonitor",
2176
"ms-vscode.makefile-tools",
22-
"ms-kubernetes-tools.vscode-kubernetes-tools"
23-
]
77+
"ms-kubernetes-tools.vscode-kubernetes-tools",
78+
"ms-azuretools.vscode-docker",
79+
"redhat.vscode-yaml",
80+
"mutantdino.resourcemonitor",
81+
"DavidAnson.vscode-markdownlint"
82+
],
83+
"settings": {
84+
"go.lintTool": "golangci-lint",
85+
"go.lintFlags": [
86+
"--config=.golangci.yaml",
87+
"--timeout=10m"
88+
],
89+
"go.formatTool": "gofumpt",
90+
"files.insertFinalNewline": true,
91+
"markdownlint.config": {
92+
"extends": ".github/.markdownlint.json"
93+
},
94+
"[markdown]": {
95+
"editor.codeActionsOnSave": {
96+
"source.fixAll.markdownlint": "explicit"
97+
}
98+
}
99+
}
24100
}
25101
}
26102
}

.devcontainer/installMoreTools.sh

Lines changed: 0 additions & 25 deletions
This file was deleted.
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
name: DevContainer
2+
on:
3+
merge_group:
4+
push:
5+
branches: [main]
6+
paths:
7+
- ".devcontainer/**"
8+
- "go.mod"
9+
pull_request:
10+
branches: [main]
11+
paths:
12+
- ".devcontainer/**"
13+
- "go.mod"
14+
15+
permissions:
16+
contents: read
17+
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.ref }}
20+
cancel-in-progress: true
21+
22+
jobs:
23+
build:
24+
name: Build DevContainer
25+
runs-on: ubuntu-latest
26+
timeout-minutes: 30
27+
steps:
28+
- uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
29+
30+
- name: Build and validate devcontainer
31+
uses: devcontainers/ci@8bf61b26e9c3a98f69cb6ce2f88d24ff59b785c6 # v0.3.1900000417
32+
with:
33+
runCmd: |
34+
clang --version
35+
llvm-strip --version
36+
go version
37+
EXPECTED_GO=$(grep '^go ' go.mod | awk '{print $2}')
38+
ACTUAL_GO=$(go version | grep -oP '\d+\.\d+\.\d+')
39+
if [ "$EXPECTED_GO" != "$ACTUAL_GO" ]; then
40+
echo "::error::Go version mismatch: devcontainer has $ACTUAL_GO but go.mod requires $EXPECTED_GO"
41+
exit 1
42+
fi
43+
kubectl version --client
44+
helm version
45+
kind version
46+
grep -rl 'go:generate.*bpf2go' pkg/plugin/ | xargs -I{} go generate {}

docs/06-Troubleshooting/bpftrace.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
The `retina bpftrace` command allows you to trace network issues on a Kubernetes node in real-time using eBPF/bpftrace.
66

77
This is useful for debugging connectivity problems such as:
8+
89
- Packet drops (with reason codes)
910
- TCP RST events (connection resets)
1011
- Socket errors (ECONNREFUSED, ETIMEDOUT, etc.)
@@ -60,6 +61,7 @@ The full list of drop reasons is kernel-version specific and is printed at the s
6061
### RST_SENT / RST_RECV - TCP Reset Events
6162

6263
Captures TCP RST packets sent or received. These indicate:
64+
6365
- Connection refused (no service listening)
6466
- Connection reset by peer
6567
- Firewall rejecting connections
@@ -78,6 +80,7 @@ Captures socket-level errors reported to applications:
7880
### RETRANS - TCP Retransmissions
7981

8082
Captures TCP segment retransmissions, which indicate:
83+
8184
- Packet loss in the network
8285
- Network congestion
8386
- Slow or unresponsive peers

docs/08-Contributing/02-development.md

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,22 @@ This document provides steps to set up your dev environment and start contributi
66

77
Retina uses a forking workflow. To contribute, fork the repository and create a branch for your changes.
88

9-
The easiest way to set up your Development Environment is to use the provided GitHub Codespaces configuration.
9+
### Using a devcontainer (recommended)
10+
11+
The easiest way to get started is to use the provided [devcontainer](https://github.com/microsoft/retina/blob/main/.devcontainer/devcontainer.json), which works with both [GitHub Codespaces](https://github.com/features/codespaces) and [VS Code Dev Containers](https://code.visualstudio.com/docs/devcontainers/containers).
12+
13+
The devcontainer comes pre-configured with all required tools:
14+
15+
- Go, clang/LLVM (for eBPF compilation), Docker, Helm, kubectl, Kind, Azure CLI, GitHub CLI, and jq
16+
- Go modules are pre-downloaded; run `make generate` to compile eBPF programs and generate mocks before building
17+
- A Kind cluster is created on startup for local testing
18+
- VS Code is configured with golangci-lint and gofumpt so editor feedback matches CI
19+
20+
To launch in Codespaces, click **Code > Codespaces > New codespace** on the repository page. To use locally, open the repository in VS Code and select **Reopen in Container** from the command palette.
21+
22+
### Manual setup
23+
24+
If you prefer to set up your environment manually, see the requirements below.
1025

1126
## Environment Config
1227

0 commit comments

Comments
 (0)