"""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 = [ # Scenario 1: Service selector does not match Deployment labels { "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 5m\n" "\n" "$ kubectl describe service api-service\n" "Name: api-service\n" "Selector: app=api\n" "Type: ClusterIP\n" "Endpoints: \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'", } ], }, # Scenario 2: Service targetPort does not match container port { "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" "...\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)", } ], }, # Scenario 3: Ingress path not matching backend service { "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 ()\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'", } ], }, # Scenario 4: NetworkPolicy blocking all ingress traffic { "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: (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'.", } ], }, # Scenario 5: Ingress missing ingressClassName { "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:///\n" "curl: (7) Failed to connect: Connection refused\n" "\n" "$ kubectl get ingressclass\n" "NAME CONTROLLER PARAMETERS AGE\n" "nginx k8s.io/ingress-nginx 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", } ], }, ]