cilium/cilium · error

failed to create CiliumEnvoyConfig for service: %w

Error message

failed to create CiliumEnvoyConfig for service: %w

What it means

This error is returned by the Cilium operator's createOrUpdateEnvoyConfig when the Kubernetes client's Create call for a desired CiliumEnvoyConfig resource fails. The CEC is the resource that configures Envoy load balancing for a service of type LoadBalancer, so this means the operator could not materialize the required Envoy config object. The original API server error is wrapped with %w so it can be inspected with errors.Is/As.

Source

Thrown at operator/pkg/ciliumenvoyconfig/ciliumenvoyconfig_reconcile.go:118

			return nil
		}

		// Update existing CEC
		updated := existing.DeepCopy()
		updated.Spec = desired.Spec

		scopedLog.DebugContext(ctx, "Updating CiliumEnvoyConfig")
		if err := r.client.Update(ctx, updated); err != nil {
			return fmt.Errorf("failed to update CiliumEnvoyConfig for service: %w", err)
		}

		scopedLog.DebugContext(ctx, "Updated CiliumEnvoyConfig for service")
		return nil
	}

	scopedLog.DebugContext(ctx, "Creating CiliumEnvoyConfig")
	if err := r.client.Create(ctx, desired); err != nil {
		return fmt.Errorf("failed to create CiliumEnvoyConfig for service: %w", err)
	}

	scopedLog.DebugContext(ctx, "Created CiliumEnvoyConfig for service")
	return nil
}

func (r *ciliumEnvoyConfigReconciler) deleteEnvoyConfig(ctx context.Context, svc *corev1.Service) error {
	existing := ciliumv2.CiliumEnvoyConfig{}
	if err := r.client.Get(ctx, types.NamespacedName{Namespace: svc.Namespace, Name: fmt.Sprintf("%s-%s", ciliumEnvoyLBPrefix, svc.Name)}, &existing); err != nil {
		if !k8serrors.IsNotFound(err) {
			return fmt.Errorf("failed to lookup CiliumEnvoyConfig: %w", err)
		}
		return nil
	}

	r.logger.DebugContext(ctx, "Deleting CiliumEnvoyConfig")
	if err := r.client.Delete(ctx, &existing); err != nil {
		return fmt.Errorf("failed to delete CiliumEnvoyConfig for service: %w", err)

View on GitHub (pinned to ac7b90affa)

Solutions

  1. Verify the cilium.io_v2 CRDs (including CiliumEnvoyConfig) are installed and up to date with your Cilium version: kubectl get crd ciliumenvoyconfigs.cilium.io
  2. Check the wrapped error with errors.Is(err, k8serrors.IsAlreadyExists) — if it races with creation, the reconciler will normally retry; ensure no conflicting manually created CEC with the same '<prefix>-<svc>' name exists
  3. Confirm the operator's RBAC/ClusterRole allows create/update on ciliumenvoyconfigs.cilium.io
  4. Check API server connectivity/health (kubectl get, operator logs for throttling) and re-trigger reconciliation

Example fix

// before
if err := r.client.Create(ctx, desired); err != nil {
	return fmt.Errorf("failed to create CiliumEnvoyConfig for service: %w", err)
}
// after
err := r.client.Create(ctx, desired)
if k8serrors.IsAlreadyExists(err) {
	if err := r.client.Update(ctx, desired); err != nil {
		return fmt.Errorf("failed to update existing CiliumEnvoyConfig: %w", err)
	}
	return nil
}
if err != nil {
	return fmt.Errorf("failed to create CiliumEnvoyConfig for service: %w", err)
}
Defensive patterns

Strategy: try-catch

Validate before calling

const crd = await k8sApi.getApiResources(); if (!crd.resources.some(r => r.name === 'ciliumenvoyconfigs.cilium.io')) throw new Error('CiliumEnvoyConfig CRD not installed');

Type guard

function isStatusError(err: unknown): err is { response?: { statusCode: number }; reason?: string } { return typeof err === 'object' && err !== null && 'response' in err; }

Try / catch

try { await reconciler.reconcile(svc); } catch (err) { if (k8s.isAlreadyExists(err)) { /* reconcile expected race; safe to retry via controller backoff */ } else { log.error('CEC create failed', err); throw err; } }

Prevention

When it happens

Trigger: r.client.Create(ctx, desired) returns an error while reconciling a service — e.g. the CiliumEnvoyConfig CRD is not installed, an object with the same name exists with different spec (AlreadyExists race), the namespace is forbidden, or the object exceeds validation limits.

Common situations: Cilium Envoy config mode enabled in an older cluster missing the cilium.io CiliumEnvoyConfig CRD; two controllers racing to create the same CEC (AlreadyExists); RBAC denies the operator create on ciliumenvoyconfigs; api-server outage or timeouts during mass service creation.

Related errors


AI-assisted analysis of cilium/cilium@ac7b90affa (2026-08-31). Data as JSON: /api/errors/fe135314708dbe65. Report an issue: GitHub.