| """Task: Kubernetes Service & Ingress Issues — MEDIUM-HARD. |
| |
| Agent fixes networking issues in Kubernetes: |
| selector mismatch, port mismatch, ingress path errors, |
| NetworkPolicy blocking traffic, missing ingress annotations. |
| """ |
|
|
| from server.models import TaskDifficulty |
| from server.tasks.base import BaseTask |
|
|
|
|
| class K8sNetworkingTask(BaseTask): |
| NAME = "Kubernetes Service & Ingress Issues" |
| DESCRIPTION = "Fix Kubernetes networking issues including Service selectors, port mismatches, and Ingress configuration" |
| DIFFICULTY = TaskDifficulty.HARD |
| AVAILABLE_SECRETS = [] |
|
|
| SCENARIOS = [ |
| |
| { |
| "id": "selector_mismatch", |
| "files": [ |
| { |
| "path": "k8s/deployment.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: apps/v1\n" |
| "kind: Deployment\n" |
| "metadata:\n" |
| " name: api\n" |
| "spec:\n" |
| " replicas: 3\n" |
| " selector:\n" |
| " matchLabels:\n" |
| " app: api-server\n" |
| " template:\n" |
| " metadata:\n" |
| " labels:\n" |
| " app: api-server\n" |
| " spec:\n" |
| " containers:\n" |
| " - name: api\n" |
| " image: myapp:latest\n" |
| " ports:\n" |
| " - containerPort: 8080\n" |
| ), |
| }, |
| { |
| "path": "k8s/service.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: v1\n" |
| "kind: Service\n" |
| "metadata:\n" |
| " name: api-service\n" |
| "spec:\n" |
| " selector:\n" |
| " app: api\n" |
| " ports:\n" |
| " - port: 80\n" |
| " targetPort: 8080\n" |
| ), |
| }, |
| ], |
| "error": { |
| "phase": "k8s_networking", |
| "message": ( |
| "$ kubectl get endpoints api-service\n" |
| "NAME ENDPOINTS AGE\n" |
| "api-service <none> 5m\n" |
| "\n" |
| "$ kubectl describe service api-service\n" |
| "Name: api-service\n" |
| "Selector: app=api\n" |
| "Type: ClusterIP\n" |
| "Endpoints: <none>\n" |
| "\n" |
| "$ kubectl get pods --show-labels\n" |
| "NAME READY STATUS LABELS\n" |
| "api-7f8d9c6b5-x2k9m 1/1 Running app=api-server\n" |
| "api-7f8d9c6b5-y3l0n 1/1 Running app=api-server\n" |
| "api-7f8d9c6b5-z4m1o 1/1 Running app=api-server\n" |
| "\n" |
| "Hint: Compare the Service selector with the pod labels shown above." |
| ), |
| }, |
| "expected_fixes": [ |
| { |
| "file": "k8s/service.yaml", |
| "type": "contains", |
| "expected": "app: api-server", |
| "hint": "Service selector 'app: api' doesn't match Deployment label 'app: api-server'", |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "port_mismatch", |
| "files": [ |
| { |
| "path": "k8s/deployment.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: apps/v1\n" |
| "kind: Deployment\n" |
| "metadata:\n" |
| " name: frontend\n" |
| "spec:\n" |
| " replicas: 2\n" |
| " selector:\n" |
| " matchLabels:\n" |
| " app: frontend\n" |
| " template:\n" |
| " metadata:\n" |
| " labels:\n" |
| " app: frontend\n" |
| " spec:\n" |
| " containers:\n" |
| " - name: frontend\n" |
| " image: frontend:v1.0\n" |
| " ports:\n" |
| " - containerPort: 3000\n" |
| ), |
| }, |
| { |
| "path": "k8s/service.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: v1\n" |
| "kind: Service\n" |
| "metadata:\n" |
| " name: frontend-svc\n" |
| "spec:\n" |
| " selector:\n" |
| " app: frontend\n" |
| " ports:\n" |
| " - port: 80\n" |
| " targetPort: 8080\n" |
| ), |
| }, |
| ], |
| "error": { |
| "phase": "k8s_networking", |
| "message": ( |
| "$ kubectl get endpoints frontend-svc\n" |
| "NAME ENDPOINTS AGE\n" |
| "frontend-svc 10.244.0.5:8080 3m\n" |
| "\n" |
| "$ curl http://frontend-svc\n" |
| "curl: (7) Failed to connect to frontend-svc port 80: Connection refused\n" |
| "\n" |
| "$ kubectl exec -it test-pod -- wget -qO- http://10.244.0.5:3000\n" |
| "<!DOCTYPE html><html>...</html>\n" |
| "\n" |
| "Hint: The container responds on a different port than the Service expects." |
| ), |
| }, |
| "expected_fixes": [ |
| { |
| "file": "k8s/service.yaml", |
| "type": "contains", |
| "expected": "targetPort: 3000", |
| "hint": "Service targetPort (8080) doesn't match container port (3000)", |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "ingress_wrong_service", |
| "files": [ |
| { |
| "path": "k8s/deployment.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: apps/v1\n" |
| "kind: Deployment\n" |
| "metadata:\n" |
| " name: api\n" |
| "spec:\n" |
| " replicas: 2\n" |
| " selector:\n" |
| " matchLabels:\n" |
| " app: api\n" |
| " template:\n" |
| " metadata:\n" |
| " labels:\n" |
| " app: api\n" |
| " spec:\n" |
| " containers:\n" |
| " - name: api\n" |
| " image: myapi:v1.0\n" |
| " ports:\n" |
| " - containerPort: 8080\n" |
| ), |
| }, |
| { |
| "path": "k8s/service.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: v1\n" |
| "kind: Service\n" |
| "metadata:\n" |
| " name: api-service\n" |
| "spec:\n" |
| " selector:\n" |
| " app: api\n" |
| " ports:\n" |
| " - port: 80\n" |
| " targetPort: 8080\n" |
| ), |
| }, |
| { |
| "path": "k8s/ingress.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: networking.k8s.io/v1\n" |
| "kind: Ingress\n" |
| "metadata:\n" |
| " name: api-ingress\n" |
| "spec:\n" |
| " rules:\n" |
| " - host: api.example.com\n" |
| " http:\n" |
| " paths:\n" |
| " - path: /\n" |
| " pathType: Prefix\n" |
| " backend:\n" |
| " service:\n" |
| " name: api-svc\n" |
| " port:\n" |
| " number: 80\n" |
| ), |
| }, |
| ], |
| "error": { |
| "phase": "k8s_networking", |
| "message": ( |
| "$ kubectl describe ingress api-ingress\n" |
| "Name: api-ingress\n" |
| "Rules:\n" |
| " Host Path Backends\n" |
| " ---- ---- --------\n" |
| " api.example.com\n" |
| " / api-svc:80 (<error: endpoints \"api-svc\" not found>)\n" |
| "\n" |
| "$ kubectl get svc\n" |
| "NAME TYPE CLUSTER-IP PORT(S)\n" |
| "api-service ClusterIP 10.96.0.10 80/TCP\n" |
| "\n" |
| "Hint: The Ingress backend service name does not match any existing Service." |
| ), |
| }, |
| "expected_fixes": [ |
| { |
| "file": "k8s/ingress.yaml", |
| "type": "contains", |
| "expected": "name: api-service", |
| "hint": "Ingress backend references 'api-svc' but the Service is named 'api-service'", |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "network_policy_blocking", |
| "files": [ |
| { |
| "path": "k8s/deployment.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: apps/v1\n" |
| "kind: Deployment\n" |
| "metadata:\n" |
| " name: database\n" |
| "spec:\n" |
| " replicas: 1\n" |
| " selector:\n" |
| " matchLabels:\n" |
| " app: database\n" |
| " template:\n" |
| " metadata:\n" |
| " labels:\n" |
| " app: database\n" |
| " spec:\n" |
| " containers:\n" |
| " - name: postgres\n" |
| " image: postgres:15\n" |
| " ports:\n" |
| " - containerPort: 5432\n" |
| " env:\n" |
| " - name: POSTGRES_PASSWORD\n" |
| ' value: "secretpass"\n' |
| ), |
| }, |
| { |
| "path": "k8s/service.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: v1\n" |
| "kind: Service\n" |
| "metadata:\n" |
| " name: database-svc\n" |
| "spec:\n" |
| " selector:\n" |
| " app: database\n" |
| " ports:\n" |
| " - port: 5432\n" |
| " targetPort: 5432\n" |
| ), |
| }, |
| { |
| "path": "k8s/networkpolicy.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: networking.k8s.io/v1\n" |
| "kind: NetworkPolicy\n" |
| "metadata:\n" |
| " name: db-policy\n" |
| "spec:\n" |
| " podSelector:\n" |
| " matchLabels:\n" |
| " app: database\n" |
| " policyTypes:\n" |
| " - Ingress\n" |
| " ingress: []\n" |
| ), |
| }, |
| ], |
| "error": { |
| "phase": "k8s_networking", |
| "message": ( |
| "$ kubectl exec -it api-pod -- pg_isready -h database-svc -p 5432\n" |
| "database-svc:5432 - no response\n" |
| "\n" |
| "$ kubectl get pods\n" |
| "NAME READY STATUS RESTARTS AGE\n" |
| "database-6b8f9d7c4-kj3m2 1/1 Running 0 5m\n" |
| "api-pod 1/1 Running 0 5m\n" |
| "\n" |
| "$ kubectl get networkpolicy\n" |
| "NAME POD-SELECTOR AGE\n" |
| "db-policy app=database 5m\n" |
| "\n" |
| "$ kubectl describe networkpolicy db-policy\n" |
| "Spec:\n" |
| " PodSelector: app=database\n" |
| " Allowing ingress traffic: <none> (Selected pods are isolated for ingress connectivity)\n" |
| "\n" |
| "Note: NetworkPolicy with empty ingress list blocks ALL inbound traffic to the database" |
| ), |
| }, |
| "expected_fixes": [ |
| { |
| "file": "k8s/networkpolicy.yaml", |
| "type": "contains", |
| "expected": "app: api", |
| "hint": "NetworkPolicy has empty ingress rules (blocks all traffic). Add an ingress rule allowing traffic from pods with label 'app: api'.", |
| } |
| ], |
| }, |
|
|
| |
| { |
| "id": "missing_ingress_class", |
| "files": [ |
| { |
| "path": "k8s/deployment.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: apps/v1\n" |
| "kind: Deployment\n" |
| "metadata:\n" |
| " name: webapp\n" |
| "spec:\n" |
| " replicas: 2\n" |
| " selector:\n" |
| " matchLabels:\n" |
| " app: webapp\n" |
| " template:\n" |
| " metadata:\n" |
| " labels:\n" |
| " app: webapp\n" |
| " spec:\n" |
| " containers:\n" |
| " - name: webapp\n" |
| " image: webapp:v2.0\n" |
| " ports:\n" |
| " - containerPort: 8080\n" |
| ), |
| }, |
| { |
| "path": "k8s/service.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: v1\n" |
| "kind: Service\n" |
| "metadata:\n" |
| " name: webapp-svc\n" |
| "spec:\n" |
| " selector:\n" |
| " app: webapp\n" |
| " ports:\n" |
| " - port: 80\n" |
| " targetPort: 8080\n" |
| ), |
| }, |
| { |
| "path": "k8s/ingress.yaml", |
| "type": "kubernetes", |
| "content": ( |
| "apiVersion: networking.k8s.io/v1\n" |
| "kind: Ingress\n" |
| "metadata:\n" |
| " name: webapp-ingress\n" |
| "spec:\n" |
| " rules:\n" |
| " - host: webapp.example.com\n" |
| " http:\n" |
| " paths:\n" |
| " - path: /\n" |
| " pathType: Prefix\n" |
| " backend:\n" |
| " service:\n" |
| " name: webapp-svc\n" |
| " port:\n" |
| " number: 80\n" |
| ), |
| }, |
| ], |
| "error": { |
| "phase": "k8s_networking", |
| "message": ( |
| "$ kubectl describe ingress webapp-ingress\n" |
| "Name: webapp-ingress\n" |
| "Address: \n" |
| "Rules:\n" |
| " Host Path Backends\n" |
| " ---- ---- --------\n" |
| " webapp.example.com / webapp-svc:80 (10.244.0.5:8080)\n" |
| "\n" |
| "$ curl -H 'Host: webapp.example.com' http://<loadbalancer-ip>/\n" |
| "curl: (7) Failed to connect: Connection refused\n" |
| "\n" |
| "$ kubectl get ingressclass\n" |
| "NAME CONTROLLER PARAMETERS AGE\n" |
| "nginx k8s.io/ingress-nginx <none> 10d\n" |
| "\n" |
| "Note: Ingress has no ingressClassName specified. The cluster requires " |
| "explicit ingressClassName: nginx" |
| ), |
| }, |
| "expected_fixes": [ |
| { |
| "file": "k8s/ingress.yaml", |
| "type": "contains", |
| "expected": "ingressClassName: nginx", |
| "hint": "Ingress needs 'ingressClassName: nginx' in the spec to be picked up by the nginx ingress controller", |
| } |
| ], |
| }, |
| ] |
|
|