Skip to content

Commit f8cb655

Browse files
committed
update quiz
1 parent 972d08e commit f8cb655

3 files changed

Lines changed: 249 additions & 0 deletions

File tree

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
name: Validate YAML & Lint
2+
3+
on:
4+
push:
5+
branches: [main]
6+
pull_request:
7+
branches: [main]
8+
9+
jobs:
10+
validate:
11+
name: Validate Kubernetes YAML
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Install kubeconform
17+
run: |
18+
curl -sL https://github.com/yannh/kubeconform/releases/latest/download/kubeconform-linux-amd64.tar.gz | tar xz
19+
sudo mv kubeconform /usr/local/bin/
20+
21+
- name: Validate skeleton YAML files
22+
run: |
23+
echo "Validating skeletons/"
24+
for f in skeletons/*.yaml; do
25+
echo " Checking $f..."
26+
kubeconform -strict -summary "$f"
27+
done
28+
29+
- name: Validate exercise YAML (embedded in READMEs)
30+
run: |
31+
echo "Extracting and validating YAML from exercise READMEs..."
32+
for readme in exercises/*/README.md; do
33+
echo " Scanning $readme for YAML blocks..."
34+
# Extract yaml blocks and validate individually
35+
awk '/^```yaml/{flag=1; next} /^```/{if(flag) {print "---"; flag=0}} flag' "$readme" > /tmp/extracted.yaml
36+
if [ -s /tmp/extracted.yaml ]; then
37+
kubeconform -summary -ignore-missing-schemas /tmp/extracted.yaml || true
38+
fi
39+
done
40+
41+
markdown-lint:
42+
name: Lint Markdown
43+
runs-on: ubuntu-latest
44+
steps:
45+
- uses: actions/checkout@v4
46+
47+
- name: Lint markdown files
48+
uses: DavidAnson/markdownlint-cli2-action@v19
49+
with:
50+
globs: |
51+
README.md
52+
exercises/**/*.md
53+
CONTRIBUTING.md
54+
continue-on-error: true

TRAFFIC_STRATEGY.md

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
# Growth Strategy — Making This the #1 CKAD Repo
2+
3+
Actionable checklist to maximize reach, stars, and traffic.
4+
5+
## Phase 1: Content Completeness (Week 1-2)
6+
7+
- [ ] Add Exercise 11: StatefulSet (stable identity, headless Service, persistent storage)
8+
- [ ] Add Exercise 12: DaemonSet (node-level logging agent, tolerations)
9+
- [ ] Add Exercise 13: Init Containers (dependency checks, migration runners)
10+
- [ ] Add Exercise 14: In-Place Pod Vertical Scaling (new in v1.35 GA)
11+
- [ ] Add difficulty badges to every exercise README (`Easy` / `Medium` / `Hard`)
12+
- [ ] Add `verify.sh` scripts to exercises (automated answer checking)
13+
- [ ] Create Anki deck export (.apkg) of key kubectl commands + YAML patterns
14+
15+
## Phase 2: CI/CD & Quality Signals (Week 1)
16+
17+
- [x] GitHub Actions: validate all skeleton YAML with kubeconform
18+
- [x] GitHub Actions: lint markdown files
19+
- [ ] Add badges to README: build passing, YAML valid, last commit, stars count
20+
- [ ] Add `.markdownlint.json` config for consistent formatting
21+
22+
## Phase 3: SEO & Discoverability (Week 2)
23+
24+
- [ ] Set GitHub repo **description**: `CKAD Exam 2026 — Practice Questions, Mock Exam, Exercises & Study Guide | Kubernetes v1.35 | Scored 91%`
25+
- [ ] Set GitHub **topics**: `ckad`, `kubernetes`, `ckad-exam`, `ckad-exercises`, `kubernetes-certification`, `ckad-2026`, `ckad-practice`, `kubectl`, `cncf`, `ckad-study-guide`, `gateway-api`
26+
- [ ] Set **website** field to blog post URL
27+
- [ ] Enable GitHub Pages (render README as searchable site)
28+
- [ ] Add `<meta>` SEO in GitHub Pages `_config.yml`: title, description, keywords
29+
- [ ] Cross-link: blog → repo, repo → blog (done), LinkedIn → repo
30+
- [ ] Submit to Google Search Console once Pages is live
31+
32+
## Phase 4: Community & Social Proof (Week 2-3)
33+
34+
- [ ] Enable GitHub Discussions (Q&A, exam results sharing, study groups)
35+
- [ ] Add "Contributors" section to README with `all-contributors` bot
36+
- [ ] Add Star History badge from `star-history.com`
37+
- [ ] Add "If this helped, star the repo" CTA at top AND bottom of README
38+
- [ ] Create issue templates: bug report, exercise request, content update
39+
40+
## Phase 5: Distribution Blitz (Week 3)
41+
42+
- [ ] **Reddit**: Post to r/kubernetes, r/devops, r/CKAD, r/sysadmin — angle: "Scored 91%, open-sourcing my complete CKAD prep (K8s v1.35, Gateway API)"
43+
- [ ] **Hacker News**: "Show HN: CKAD Study Guide — scored 91%, open-sourced"
44+
- [ ] **Dev.to**: Write article "How I Passed CKAD 2026 with 91% — Complete Open Source Study Guide"
45+
- [ ] **LinkedIn**: Write post with exam score card image
46+
- [ ] **Twitter/X**: Thread — "I just passed CKAD with 91%. Here's everything I used (open source):" with 10-tweet breakdown
47+
- [ ] **YouTube**: Record 5-10 min overview walkthrough of the repo + exercises
48+
- [ ] **Discord**: Post in Kubernetes, CNCF, DevOps Discord servers
49+
50+
## Phase 6: Backlinks & Partnerships (Week 3-4)
51+
52+
- [ ] Email/DM authors of popular "How I passed CKAD" blog posts — ask to link this repo
53+
- [ ] Submit to awesome-kubernetes / awesome-ckad lists
54+
- [ ] Reach out to Killercoda — propose integration or cross-link
55+
- [ ] Create a PR to `kubernetes/community` repo linking this as a study resource
56+
- [ ] Comment on Stack Overflow CKAD questions with link to repo (where relevant and helpful)
57+
58+
## Phase 7: Unique Features (Ongoing)
59+
60+
- [x] Interactive quiz script (`scripts/quiz.sh`)
61+
- [ ] Exam simulator: bash script that deploys kind cluster + presents 17 timed questions
62+
- [ ] PDF export of the README (for offline study)
63+
- [ ] Flashcard mode in terminal (kubectl commands + expected output)
64+
- [ ] Weekly automated check that Kubernetes version references are current
65+
66+
## Competitive Analysis
67+
68+
| Repo | Stars | Weakness | Our Advantage |
69+
|------|-------|----------|---------------|
70+
| dgkanatsios/CKAD-exercises | 8k+ | Outdated (v1.28), no Gateway API, no mock exam | Current v1.35, Gateway API, full mock exam |
71+
| bmuschko/ckad-crash-course | 2k+ | Minimal explanations, no exam tips | Deep exam strategy, mistakes section, PSI tips |
72+
| lucassha/CKAD-resources | 1k+ | Link collection only, no original content | Full original content, exercises, skeletons |
73+
74+
## Key Metrics to Track
75+
76+
- GitHub stars (weekly)
77+
- Google ranking for "CKAD study guide 2026"
78+
- README page views (GitHub Insights → Traffic)
79+
- Blog post organic traffic
80+
- Reddit/HN post engagement
81+
- Contributors count

scripts/quiz.sh

Lines changed: 114 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,114 @@
1+
#!/usr/bin/env bash
2+
# CKAD Quick Quiz — Terminal-based random practice questions
3+
# Usage: bash scripts/quiz.sh
4+
# Requires: a running Kubernetes cluster (kind, minikube, or remote)
5+
6+
set -euo pipefail
7+
8+
GREEN='\033[0;32m'
9+
RED='\033[0;31m'
10+
YELLOW='\033[1;33m'
11+
CYAN='\033[0;36m'
12+
BOLD='\033[1m'
13+
NC='\033[0m'
14+
15+
QUESTIONS=(
16+
"Create a pod named 'quiz-pod' with image nginx in namespace 'quiz'. Expose port 80.|kubectl create namespace quiz --dry-run=client -o yaml | kubectl apply -f - && kubectl run quiz-pod --image=nginx --port=80 -n quiz|kubectl get pod quiz-pod -n quiz -o jsonpath='{.status.phase}'"
17+
"Create a ConfigMap named 'quiz-config' with key 'MODE=exam' in namespace 'quiz'.|kubectl create configmap quiz-config --from-literal=MODE=exam -n quiz|kubectl get configmap quiz-config -n quiz -o jsonpath='{.data.MODE}'"
18+
"Create a Deployment named 'quiz-deploy' with image nginx:alpine, 3 replicas, in namespace 'quiz'.|kubectl create deployment quiz-deploy --image=nginx:alpine --replicas=3 -n quiz|kubectl get deployment quiz-deploy -n quiz -o jsonpath='{.spec.replicas}'"
19+
"Create a Secret named 'quiz-secret' with key 'password=ckad2026' in namespace 'quiz'.|kubectl create secret generic quiz-secret --from-literal=password=ckad2026 -n quiz|kubectl get secret quiz-secret -n quiz -o jsonpath='{.data.password}'"
20+
"Create a ServiceAccount named 'quiz-sa' in namespace 'quiz'.|kubectl create serviceaccount quiz-sa -n quiz|kubectl get serviceaccount quiz-sa -n quiz -o jsonpath='{.metadata.name}'"
21+
"Create a Job named 'quiz-job' using image busybox that runs 'echo CKAD' in namespace 'quiz'.|kubectl create job quiz-job --image=busybox -n quiz -- echo CKAD|kubectl get job quiz-job -n quiz -o jsonpath='{.metadata.name}'"
22+
"Create a CronJob named 'quiz-cron' with schedule '*/5 * * * *' using image busybox that runs 'date' in namespace 'quiz'.|kubectl create cronjob quiz-cron --image=busybox --schedule='*/5 * * * *' -n quiz -- date|kubectl get cronjob quiz-cron -n quiz -o jsonpath='{.spec.schedule}'"
23+
"Create a Role named 'quiz-role' in namespace 'quiz' that allows get,list on pods.|kubectl create role quiz-role --verb=get,list --resource=pods -n quiz|kubectl get role quiz-role -n quiz -o jsonpath='{.metadata.name}'"
24+
"Scale the deployment 'quiz-deploy' to 5 replicas in namespace 'quiz'.|kubectl scale deployment quiz-deploy --replicas=5 -n quiz|kubectl get deployment quiz-deploy -n quiz -o jsonpath='{.spec.replicas}'"
25+
"Set the image of deployment 'quiz-deploy' to nginx:latest in namespace 'quiz'.|kubectl set image deployment/quiz-deploy nginx-alpine=nginx:latest -n quiz || kubectl set image deployment/quiz-deploy nginx=nginx:latest -n quiz|kubectl get deployment quiz-deploy -n quiz -o jsonpath='{.spec.template.spec.containers[0].image}'"
26+
)
27+
28+
score=0
29+
total=0
30+
TIME_PER_QUESTION=300 # 5 minutes per question
31+
32+
cleanup() {
33+
echo ""
34+
echo -e "${YELLOW}Cleaning up quiz resources...${NC}"
35+
kubectl delete namespace quiz --ignore-not-found --force --grace-period=0 2>/dev/null || true
36+
echo -e "${GREEN}Cleanup complete.${NC}"
37+
}
38+
39+
show_score() {
40+
echo ""
41+
echo -e "${BOLD}═══════════════════════════════════════${NC}"
42+
echo -e "${BOLD} FINAL SCORE: ${score}/${total}${NC}"
43+
if [ "$total" -gt 0 ]; then
44+
pct=$((score * 100 / total))
45+
if [ "$pct" -ge 80 ]; then
46+
echo -e " ${GREEN}Excellent! You're exam-ready.${NC}"
47+
elif [ "$pct" -ge 66 ]; then
48+
echo -e " ${YELLOW}Passing range. Keep practicing.${NC}"
49+
else
50+
echo -e " ${RED}Below passing. Review weak areas.${NC}"
51+
fi
52+
fi
53+
echo -e "${BOLD}═══════════════════════════════════════${NC}"
54+
}
55+
56+
trap cleanup EXIT
57+
58+
echo -e "${BOLD}╔═══════════════════════════════════════╗${NC}"
59+
echo -e "${BOLD}║ CKAD Quick Quiz — Practice Mode ║${NC}"
60+
echo -e "${BOLD}${TIME_PER_QUESTION}s per question, ${#QUESTIONS[@]} questions ║${NC}"
61+
echo -e "${BOLD}╚═══════════════════════════════════════╝${NC}"
62+
echo ""
63+
64+
# Ensure quiz namespace exists
65+
kubectl create namespace quiz --dry-run=client -o yaml | kubectl apply -f - 2>/dev/null
66+
67+
# Shuffle questions
68+
shuffled=($(shuf -i 0-$((${#QUESTIONS[@]}-1)) -n ${#QUESTIONS[@]} 2>/dev/null || seq 0 $((${#QUESTIONS[@]}-1))))
69+
70+
for idx in "${shuffled[@]}"; do
71+
IFS='|' read -r question solution verify <<< "${QUESTIONS[$idx]}"
72+
total=$((total + 1))
73+
74+
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
75+
echo -e "${BOLD}Question ${total}/${#QUESTIONS[@]}:${NC}"
76+
echo -e "${YELLOW}${question}${NC}"
77+
echo ""
78+
echo -e "You have ${TIME_PER_QUESTION} seconds. Press ${BOLD}Enter${NC} when done (or type ${BOLD}skip${NC}):"
79+
80+
start_time=$(date +%s)
81+
read -r user_input
82+
83+
if [ "$user_input" = "skip" ]; then
84+
echo -e "${RED}Skipped.${NC}"
85+
echo -e " Solution: ${GREEN}${solution}${NC}"
86+
echo ""
87+
continue
88+
fi
89+
90+
elapsed=$(( $(date +%s) - start_time ))
91+
if [ "$elapsed" -gt "$TIME_PER_QUESTION" ]; then
92+
echo -e "${RED}Time's up! (${elapsed}s)${NC}"
93+
else
94+
echo -e " Completed in ${elapsed}s"
95+
fi
96+
97+
# Verify
98+
if eval "$verify" &>/dev/null; then
99+
result=$(eval "$verify" 2>/dev/null)
100+
if [ -n "$result" ]; then
101+
echo -e " ${GREEN}✓ CORRECT — Resource verified successfully${NC}"
102+
score=$((score + 1))
103+
else
104+
echo -e " ${RED}✗ NOT FOUND — Resource not created correctly${NC}"
105+
echo -e " Expected solution: ${GREEN}${solution}${NC}"
106+
fi
107+
else
108+
echo -e " ${RED}✗ VERIFICATION FAILED${NC}"
109+
echo -e " Expected solution: ${GREEN}${solution}${NC}"
110+
fi
111+
echo ""
112+
done
113+
114+
show_score

0 commit comments

Comments
 (0)