Skip to content

Commit ea27712

Browse files
h4x3rotabclaude
andcommitted
add smoke test script for k3s tutorial
Deploys an nginx pod with Traefik IngressRoute and verifies: - HTTPS traffic through wildcard cert - TLS certificate CN - Evidence endpoints (quote, cc_eventlog, raw_quote) - k3s API server via TLS passthrough - kubectl node readiness Leaves the workload running for manual testing. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3a21efd commit ea27712

2 files changed

Lines changed: 164 additions & 28 deletions

File tree

k3s/README.md

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -107,38 +107,37 @@ Retry until you see an HTTP response (a 404 is fine — it means TLS works but n
107107
HTTP/1.1 404 Not Found
108108
```
109109

110-
### 5. Deploy a Test Workload
110+
### 5. Deploy and Test a Workload
111+
112+
Run the included test script to deploy an nginx pod, verify HTTPS, check evidence endpoints, and confirm kubectl access — all in one command:
111113

112114
```bash
113-
CLUSTER_DOMAIN=k3s.example.com
114-
115-
# Create an nginx pod and service
116-
kubectl run nginx --image=nginx:alpine --port=80
117-
kubectl expose pod nginx --port=80 --target-port=80 --name=nginx
118-
kubectl wait --for=condition=Ready pod/nginx --timeout=120s
119-
120-
# Create a Traefik IngressRoute to route traffic to nginx
121-
kubectl apply -f - <<EOF
122-
apiVersion: traefik.io/v1alpha1
123-
kind: IngressRoute
124-
metadata:
125-
name: nginx
126-
spec:
127-
entryPoints: [web]
128-
routes:
129-
- match: Host(\`nginx.${CLUSTER_DOMAIN}\`)
130-
kind: Rule
131-
services:
132-
- name: nginx
133-
port: 80
134-
EOF
135-
136-
# Wait for route propagation, then test
137-
sleep 10
138-
curl -s "https://nginx.${CLUSTER_DOMAIN}/"
115+
./test.sh k3s.example.com
116+
```
117+
118+
Expected output:
119+
139120
```
121+
==> Deploying test workload...
122+
==> Waiting for pod to be ready...
123+
==> Running smoke tests...
124+
125+
PASS: https://nginx.k3s.example.com/ returned 200
126+
PASS: TLS cert CN matches *.k3s.example.com
127+
PASS: /evidences/quote returned 200
128+
PASS: /evidences/cc_eventlog returned 200
129+
PASS: /evidences/raw_quote returned 200
130+
PASS: k3s API /version returned 200
131+
PASS: kubectl reports node Ready
132+
133+
==> Results: 7/7 passed
134+
```
135+
136+
The test workload stays running so you can try it yourself:
140137

141-
You should see the nginx welcome page served over HTTPS with a valid Let's Encrypt certificate.
138+
```bash
139+
curl "https://nginx.k3s.example.com/"
140+
```
142141

143142
### 6. Clean Up
144143

@@ -311,6 +310,7 @@ phala ssh <app-id> -- "docker logs dstack-k3s-1 2>&1 | tail -30"
311310
```
312311
k3s/
313312
├── docker-compose.yaml # k3s + kmod-installer + dstack-ingress
313+
├── test.sh # One-command smoke test
314314
├── README.md
315315
└── manifests/
316316
├── rbac.yaml # Optional: scoped service account

k3s/test.sh

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
#!/usr/bin/env bash
2+
# Deploy a test workload to a k3s-on-dstack cluster and run smoke tests.
3+
# Leaves the workload running so you can test manually afterward.
4+
#
5+
# Usage:
6+
# export KUBECONFIG=./k3s.yaml
7+
# ./test.sh k3s.example.com
8+
#
9+
# Prerequisites:
10+
# - kubectl configured (steps 1-3 in README)
11+
# - Wildcard cert issued (step 4 in README)
12+
13+
set -euo pipefail
14+
15+
CLUSTER_DOMAIN="${1:-${CLUSTER_DOMAIN:-}}"
16+
if [[ -z "$CLUSTER_DOMAIN" ]]; then
17+
echo "Usage: $0 <cluster-domain>"
18+
echo " e.g. $0 k3s.example.com"
19+
exit 1
20+
fi
21+
22+
NGINX_HOST="nginx.${CLUSTER_DOMAIN}"
23+
PASS=0
24+
FAIL=0
25+
26+
pass() { PASS=$((PASS + 1)); echo " PASS: $1"; }
27+
fail() { FAIL=$((FAIL + 1)); echo " FAIL: $1"; }
28+
29+
# ---------- Deploy test workload ----------
30+
31+
echo "==> Deploying test workload..."
32+
33+
kubectl run nginx --image=nginx:alpine --port=80 --restart=Never 2>/dev/null || true
34+
kubectl expose pod nginx --port=80 --target-port=80 --name=nginx 2>/dev/null || true
35+
36+
kubectl apply -f - <<EOF
37+
apiVersion: traefik.io/v1alpha1
38+
kind: IngressRoute
39+
metadata:
40+
name: nginx
41+
spec:
42+
entryPoints: [web]
43+
routes:
44+
- match: Host(\`${NGINX_HOST}\`)
45+
kind: Rule
46+
services:
47+
- name: nginx
48+
port: 80
49+
EOF
50+
51+
echo "==> Waiting for pod to be ready..."
52+
kubectl wait --for=condition=Ready pod/nginx --timeout=120s
53+
54+
echo "==> Waiting for route propagation (15s)..."
55+
sleep 15
56+
57+
# ---------- Smoke tests ----------
58+
59+
echo ""
60+
echo "==> Running smoke tests..."
61+
echo ""
62+
63+
# 1. HTTPS to nginx workload
64+
echo "[HTTPS workload]"
65+
HTTP_CODE=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "https://${NGINX_HOST}/" 2>/dev/null || echo "000")
66+
if [[ "$HTTP_CODE" == "200" ]]; then
67+
pass "https://${NGINX_HOST}/ returned 200"
68+
else
69+
fail "https://${NGINX_HOST}/ returned ${HTTP_CODE} (expected 200)"
70+
fi
71+
72+
# 2. TLS certificate validity
73+
echo "[TLS certificate]"
74+
CERT_CN=$(echo | openssl s_client -servername "${NGINX_HOST}" -connect "${NGINX_HOST}:443" 2>/dev/null \
75+
| openssl x509 -noout -subject 2>/dev/null | grep -oP 'CN\s*=\s*\K.*' || echo "")
76+
if [[ "$CERT_CN" == "*.${CLUSTER_DOMAIN}" ]]; then
77+
pass "TLS cert CN matches *.${CLUSTER_DOMAIN}"
78+
else
79+
fail "TLS cert CN is '${CERT_CN}' (expected *.${CLUSTER_DOMAIN})"
80+
fi
81+
82+
# 3. Evidence endpoints
83+
echo "[Evidence endpoints]"
84+
for path in /evidences/quote /evidences/cc_eventlog /evidences/raw_quote; do
85+
CODE=$(curl -s -o /dev/null -w '%{http_code}' --max-time 10 "https://${NGINX_HOST}${path}" 2>/dev/null || echo "000")
86+
if [[ "$CODE" == "200" ]]; then
87+
pass "${path} returned 200"
88+
else
89+
fail "${path} returned ${CODE} (expected 200)"
90+
fi
91+
done
92+
93+
# 4. k3s API server (via gateway TLS passthrough)
94+
echo "[k3s API]"
95+
K3S_SERVER=$(kubectl config view --minify -o jsonpath='{.clusters[0].cluster.server}' 2>/dev/null || echo "")
96+
if [[ -n "$K3S_SERVER" ]]; then
97+
API_CODE=$(curl -sk -o /dev/null -w '%{http_code}' --max-time 10 "${K3S_SERVER}/version" 2>/dev/null || echo "000")
98+
if [[ "$API_CODE" == "200" ]]; then
99+
pass "k3s API /version returned 200"
100+
else
101+
fail "k3s API /version returned ${API_CODE} (expected 200)"
102+
fi
103+
else
104+
fail "could not determine k3s API server from kubeconfig"
105+
fi
106+
107+
# 5. kubectl works
108+
echo "[kubectl]"
109+
NODE_STATUS=$(kubectl get nodes -o jsonpath='{.items[0].status.conditions[?(@.type=="Ready")].status}' 2>/dev/null || echo "")
110+
if [[ "$NODE_STATUS" == "True" ]]; then
111+
pass "kubectl reports node Ready"
112+
else
113+
fail "kubectl reports node status '${NODE_STATUS}' (expected True)"
114+
fi
115+
116+
# ---------- Summary ----------
117+
118+
echo ""
119+
TOTAL=$((PASS + FAIL))
120+
echo "==> Results: ${PASS}/${TOTAL} passed"
121+
122+
if [[ $FAIL -gt 0 ]]; then
123+
echo ""
124+
echo "Some tests failed. Check the wildcard cert and ingress logs:"
125+
echo " phala ssh <app-id> -- \"docker logs dstack-dstack-ingress-1 2>&1 | tail -30\""
126+
exit 1
127+
fi
128+
129+
echo ""
130+
echo "==> Test workload is running. Try it yourself:"
131+
echo " curl https://${NGINX_HOST}/"
132+
echo ""
133+
echo "==> To clean up later:"
134+
echo " kubectl delete ingressroute.traefik.io nginx"
135+
echo " kubectl delete svc nginx"
136+
echo " kubectl delete pod nginx"

0 commit comments

Comments
 (0)