Skip to content

Securing Registries and Pods in KinD

This guide focuses on security best practices for using KinD (Kubernetes in Docker) with a specific emphasis on securing container registries and pods.

Table of Contents

Introduction

When using KinD for development, testing, or CI/CD pipelines, it's essential to follow security best practices even in these ephemeral environments. This guide will help you implement security measures for container registries and pods in your KinD clusters.

Securing Container Registries

Setting Up a Local Secure Registry

Setting up a local registry with TLS can improve security and allow you to test registry authentication configurations.

  1. Create a directory for your registry certificates:
bash
mkdir -p ./certs
  1. Generate self-signed certificates:
bash
openssl req -newkey rsa:4096 -nodes -sha256 -keyout ./certs/domain.key -x509 -days 365 -out ./certs/domain.crt -subj "/CN=registry.local" -addext "subjectAltName = DNS:registry.local"
  1. Create a registry configuration file registry-config.yaml:
yaml
version: 0.1
log:
  fields:
    service: registry
storage:
  cache:
    blobdescriptor: inmemory
  filesystem:
    rootdirectory: /var/lib/registry
http:
  addr: :5000
  headers:
    X-Content-Type-Options: [nosniff]
  tls:
    certificate: /certs/domain.crt
    key: /certs/domain.key
  1. Start the registry container:
bash
docker run -d \
  --restart=always \
  --name registry \
  -v "$(pwd)"/certs:/certs \
  -v "$(pwd)"/registry-config.yaml:/etc/docker/registry/config.yml \
  -p 5000:5000 \
  registry:2
  1. Configure KinD to use this registry by creating a cluster config file kind-with-registry.yaml:
yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."localhost:5000"]
    endpoint = ["https://registry.local:5000"]
  [plugins."io.containerd.grpc.v1.cri".registry.configs."registry.local:5000".tls]
    ca_file = "/etc/ssl/certs/domain.crt"
nodes:
- role: control-plane
  extraMounts:
  - hostPath: ./certs/domain.crt
    containerPath: /etc/ssl/certs/domain.crt
  1. Create your KinD cluster with this configuration:
bash
kind create cluster --config kind-with-registry.yaml

Using Private Registries with Authentication

To use private registries that require authentication:

  1. Create a Docker registry secret:
bash
kubectl create secret docker-registry regcred \
  --docker-server=<your-registry-server> \
  --docker-username=<your-username> \
  --docker-password=<your-password> \
  --docker-email=<your-email>
  1. Reference this secret in your pod specifications:
yaml
apiVersion: v1
kind: Pod
metadata:
  name: private-image-pod
spec:
  containers:
  - name: private-image-container
    image: private-registry.example.com/my-app:1.0
  imagePullSecrets:
  - name: regcred
  1. For cluster-wide usage, add the secret to the default service account:
bash
kubectl patch serviceaccount default -p '{"imagePullSecrets": [{"name": "regcred"}]}'

Registry Mirroring

Registry mirroring can improve security by reducing dependencies on external registries and providing additional control over image sources.

  1. Create a containerd configuration file for registry mirroring:
yaml
kind: Cluster
apiVersion: kind.x-k8s.io/v1alpha4
containerdConfigPatches:
- |-
  [plugins."io.containerd.grpc.v1.cri".registry.mirrors."docker.io"]
    endpoint = ["https://your-mirror-registry.example.com"]
  [plugins."io.containerd.grpc.v1.cri".registry.configs."your-mirror-registry.example.com".auth]
    username = "username"
    password = "password"
  [plugins."io.containerd.grpc.v1.cri".registry.configs."your-mirror-registry.example.com".tls]
    insecure_skip_verify = false
    ca_file = "/path/to/ca.crt"
  1. Create your cluster with this configuration.

Securing Pods in KinD

Pod Security Standards

Kubernetes Pod Security Standards (PSS) define different levels of security for pods:

  1. Create a namespace with security enforcement:
bash
kubectl create namespace restricted-ns
  1. Apply Pod Security Standards labels:
bash
kubectl label --overwrite namespace restricted-ns \
  pod-security.kubernetes.io/enforce=restricted \
  pod-security.kubernetes.io/audit=restricted \
  pod-security.kubernetes.io/warn=restricted
  1. Test deployment to the restricted namespace:
bash
kubectl -n restricted-ns create deployment nginx --image=nginx

The deployment will fail unless the pod spec meets the restricted policy requirements.

Network Policies

Network Policies control pod-to-pod communication:

  1. Create a simple deny-all policy to start from a secure default:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: default-deny-all
  namespace: your-namespace
spec:
  podSelector: {}
  policyTypes:
  - Ingress
  - Egress
  1. Allow specific traffic with more targeted policies:
yaml
apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-specific-traffic
  namespace: your-namespace
spec:
  podSelector:
    matchLabels:
      app: web
  policyTypes:
  - Ingress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          app: api
    ports:
    - protocol: TCP
      port: 80

Resource Limits

Setting resource limits prevents resource exhaustion attacks:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: secured-pod
spec:
  containers:
  - name: app
    image: nginx
    resources:
      requests:
        memory: "64Mi"
        cpu: "250m"
      limits:
        memory: "128Mi"
        cpu: "500m"

You can enforce this with LimitRange objects:

yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: default-limits
  namespace: your-namespace
spec:
  limits:
  - default:
      memory: 512Mi
      cpu: 1
    defaultRequest:
      memory: 256Mi
      cpu: 0.5
    type: Container

securityContext Configuration

Configure pod and container security contexts:

yaml
apiVersion: v1
kind: Pod
metadata:
  name: security-context-pod
spec:
  securityContext:
    runAsNonRoot: true
    fsGroup: 2000
  containers:
  - name: secure-container
    image: nginx
    securityContext:
      allowPrivilegeEscalation: false
      capabilities:
        drop:
        - ALL
      readOnlyRootFilesystem: true
      runAsUser: 1000

Advanced Security Configurations

OPA Gatekeeper Integration

OPA Gatekeeper can enforce custom security policies:

  1. Install Gatekeeper in your KinD cluster:
bash
kubectl apply -f https://raw.githubusercontent.com/open-policy-agent/gatekeeper/release-3.11/deploy/gatekeeper.yaml
  1. Create a constraint template:
yaml
apiVersion: templates.gatekeeper.sh/v1
kind: ConstraintTemplate
metadata:
  name: k8srequiredlabels
spec:
  crd:
    spec:
      names:
        kind: K8sRequiredLabels
      validation:
        openAPIV3Schema:
          type: object
          properties:
            labels:
              type: array
              items:
                type: string
  targets:
    - target: admission.k8s.gatekeeper.sh
      rego: |
        package k8srequiredlabels
        violation[{"msg": msg}] {
          provided := {label | input.review.object.metadata.labels[label]}
          required := {label | label := input.parameters.labels[_]}
          missing := required - provided
          count(missing) > 0
          msg := sprintf("Missing required labels: %v", [missing])
        }
  1. Apply a constraint:
yaml
apiVersion: constraints.gatekeeper.sh/v1beta1
kind: K8sRequiredLabels
metadata:
  name: require-team-label
spec:
  match:
    kinds:
      - apiGroups: [""]
        kinds: ["Pod"]
  parameters:
    labels: ["team"]

Image Vulnerability Scanning

Integrate Trivy for scanning images in your KinD cluster:

  1. Create a job to scan images:
yaml
apiVersion: batch/v1
kind: Job
metadata:
  name: trivy-scanner
spec:
  template:
    spec:
      containers:
      - name: trivy
        image: aquasec/trivy
        args:
        - image
        - --severity
        - HIGH,CRITICAL
        - nginx:latest
      restartPolicy: Never
  backoffLimit: 1
  1. For a more integrated approach, use admission controllers like Kyverno:
bash
kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.8.5/install.yaml
  1. Create an image scanning policy:
yaml
apiVersion: kyverno.io/v1
kind: ClusterPolicy
metadata:
  name: scan-image
spec:
  validationFailureAction: Enforce
  background: false
  webhookTimeoutSeconds: 30
  rules:
  - name: verify-image
    match:
      resources:
        kinds:
        - Pod
    validate:
      message: "Image failed security scan"
      image:
        verifyImages:
        - image: "*"
          repositories:
          - "myregistry.example.com/*"

RBAC for KinD Clusters

Set up proper RBAC for your KinD cluster:

  1. Create a restricted role:
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: default
  name: pod-reader
rules:
- apiGroups: [""]
  resources: ["pods"]
  verbs: ["get", "watch", "list"]
  1. Bind the role to a user or group:
yaml
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods
  namespace: default
subjects:
- kind: User
  name: jane
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

Troubleshooting

Private Registry Authentication Issues

If your pods can't pull from a private registry:

bash
# Check if the secret exists
kubectl get secret regcred

# Check pod events
kubectl describe pod <pod-name>

# Verify the image pull secret is correctly specified
kubectl get pod <pod-name> -o yaml | grep imagePullSecrets -A 1

Network Policy Troubleshooting

If network policies are blocking legitimate traffic:

bash
# Deploy a debug pod to test connectivity
kubectl run tmp-shell --rm -i --tty --image nicolaka/netshoot -- /bin/bash

# Inside the pod, test connectivity
curl http://service-name

# Check network policies affecting a pod
kubectl get networkpolicy -A

Security Context Issues

If a pod fails to start due to security context constraints:

bash
# Check pod events
kubectl describe pod <pod-name>

# Test with a more permissive security context
kubectl run test-pod --image=nginx --overrides='{"spec":{"securityContext":{"runAsNonRoot":false}}}'

Additional Resources


This guide provides an overview of securing registries and pods in KinD environments. As you build more complex systems, consider implementing additional security measures and conducting regular security audits.