A friendly name duplicate error occurs when two resources have the same display name in a context where uniqueness is required. This is usually encountered with custom resources (CRs) or when using status fields that expect unique names.
Fixes Friendly Name Duplicate
kubectl get <resource-type> -A | grep <name>
kubectl get <resource-type> --all-namespaces
# Find exact duplicates:
kubectl get <resource-type> -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort | uniq -d
# Describe both resources:
kubectl describe <resource-type> <name> -n <ns1>
kubectl describe <resource-type> <name> -n <ns2>kubectl get <resource-type> -A | grep <name>kubectl get <resource-type> --all-namespaces# Find exact duplicates:kubectl get <resource-type> -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort | uniq -d# Describe both resources:kubectl describe <resource-type> <name> -n <ns1>kubectl describe <resource-type> <name> -n <ns2>Friendly Name Duplicate
Some Kubernetes resources or controllers use a "friendly name" (human-readable identifier) that must be globally unique or unique within a scope. When two resources try to use the same friendly name, the system rejects the second one to prevent ambiguity and conflicts. Common in custom resource definitions (CRDs) and third-party controllers like Ingress, Service, or custom operators.
Find what's causing the conflict:
kubectl get <resource-type> -A | grep <name>
kubectl get <resource-type> --all-namespaces
# Find exact duplicates:
kubectl get <resource-type> -o jsonpath='{.items[*].metadata.name}' | tr ' ' '\n' | sort | uniq -d
# Describe both resources:
kubectl describe <resource-type> <name> -n <ns1>
kubectl describe <resource-type> <name> -n <ns2>Identify which resource was created first.
Resolve the conflict:
Option 1: Rename the new resource
kubectl patch <resource> <old-name> -p '{"metadata":{"name":"<new-name>"}}'
# Or:
kubectl delete <resource> <old-name>
kubectl create -f updated-manifest.yaml # With new nameOption 2: Remove the old resource
kubectl delete <resource> <old-name> -n <namespace>Option 3: Use namespace isolation
# Move resource to different namespace:
kubectl create ns team-a
kubectl apply -f resource.yaml -n team-aChoose based on which resource is still needed.
Understand where names must be unique:
# Cluster-scoped (names unique across entire cluster):
kubectl api-resources | grep "<none>" # <none> = cluster scope
# Namespace-scoped (names unique per namespace):
kubectl api-resources | grep "true" # true = namespaced
# For custom resources:
kubectl get crd <name>.yaml -o jsonpath='{.spec.scope}'
# Two resources can have same name if in different namespaces (if namespaced)
kubectl get pods default/myapp # Namespace 1
kubectl get pods other/myapp # Namespace 2 (OK)Namespaced resources can have duplicate names in different namespaces.
Instead of relying on name alone, use metadata:
apiVersion: myapi.example.com/v1
kind: MyResource
metadata:
name: shared-name # Can be duplicated across namespaces
namespace: team-a
labels:
team: team-a
environment: prod
annotations:
owner: [email protected]
spec:
# ...Use selectors to query by labels:
kubectl get <resource> -l team=team-a
kubectl get <resource> -l environment=prodLabels provide flexible grouping without name collisions.
Prevent duplicates with structured names:
# Convention: <team>-<service>-<environment>
app-api-prod
app-api-staging
app-worker-prod
# Or: <project>-<component>-<version>
myapp-web-v1
myapp-web-v2
myapp-db-v1
# Enforce via kube-linter or similar:
kube-lint --allowed-registry my-registry # Custom rules
# Or via validation in CRD:
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
name: myresources.example.com
spec:
names:
kind: MyResource
validation:
openAPIV3Schema:
properties:
metadata:
properties:
name:
pattern: "^[a-z0-9]([-a-z0-9]*[a-z0-9])$" # Regex validationConsistent naming prevents conflicts.
Review resource validation rules:
# Get CRD definition:
kubectl get crd <resource>.example.com -o yaml
# Look for validation rules:
validation:
openAPIV3Schema:
properties:
spec:
properties:
friendlyName:
type: string
description: "Must be unique"
# If validation exists but isn't working, check controller logs:
kubectl logs -n <controller-ns> deployment/<controller> | grep -i "friendly\|unique"Some validations are in CRD schema, others enforced by controller.
Verify the conflict is properly caught:
# Try creating duplicate:
kubectl apply -f duplicate.yaml
# Should fail with error about duplicate name
# Check what the error message says:
kubectl apply -f duplicate.yaml 2>&1 | head -20
# If no error, enforcement might be missing
# Add validation to CRD:
kubectl patch crd <resource> --type merge -p \
'{"spec":{"validation":{"openAPIV3Schema":{"properties":{"metadata":{"properties":{"name":{"pattern\":"^unique-pattern$"}}}}}}}}'Ensure validation catches duplicates before they're stored.
Prevent future conflicts:
# Document in ConfigMap or wiki:
kubectl create configmap naming-standards \
--from-literal=convention="<team>-<service>-<env>" \
--from-literal=forbidden-prefixes="system-,kube-" \
-n kube-system
# Or in comments in manifests:
# NAMING: Resources must follow pattern: {team}-{service}-{env}
# EXAMPLE: platform-api-prod, platform-worker-stagingClear documentation reduces accidental conflicts.
Friendly name uniqueness is enforced at different levels: API server (for built-in resources), controller (for custom resources), or CRD validation. Some resources allow duplicate names if scoped properly (e.g., Services in different namespaces can have same name). For third-party controllers, read the CRD documentation for uniqueness scope. Implement namespace strategy: one namespace per team to isolate naming. Consider using owners/finalizers to ensure orphaned resources are cleaned up. For GitOps, ensure Git repo structure mirrors namespace structure to prevent conflicts during syncing.