Skip to content

Conversation

@devbini
Copy link

@devbini devbini commented Jan 8, 2026

Checklist:

  • Either (a) I've created an enhancement proposal and discussed it with the community, (b) this is a bug fix, or (c) this does not need to be in the release notes.
  • The title of the PR states what changed and the related issues number (used for the release note).
  • The title of the PR conforms to the Title of the PR
  • I've included "Closes [ISSUE #]" or "Fixes [ISSUE #]" in the description to automatically close the associated issue.
  • I've updated both the CLI and UI to expose my feature, or I plan to submit a second PR with them.
  • Does this PR require documentation updates?
  • I've updated documentation as required by this PR.
  • I have signed off all my commits as required by DCO
  • I have written unit and/or e2e tests for my change. PRs without these are unlikely to be merged.
  • My build is green (troubleshooting builds).
  • My new feature complies with the feature status guidelines.
  • I have added a brief description of why this PR is necessary and/or what this PR solves.
  • Optional. My organization is added to USERS.md.
  • Optional. For bug fixes, I've indicated what older releases this fix should be cherry-picked into (this may or may not happen depending on risk/complexity).

Summary

This PR addresses issue #24406. ( Fixes #24406 )
The core problem occurs when users want to use an external Redis instance instead of the bundled in-cluster Redis for better maintainability and scalability.

To replicate the issue in a test environment, I configured Argo CD to run in a Minikube cluster and attempted to connect it to an external Redis running in a separate, logically isolated Docker container.

Problem Replay

The following command was used to attempt cluster creation.
argocd cluster add minikube --name cluster-name --upsert --yes --core

As a result, the following fatal error was encountered.

{
  "level":"fatal",
  "msg":"rpc error: code = Unknown desc = failed to set cluster info in cache: cannot find ready pod with selector: [app.kubernetes.io/name=argocd-redis-ha-haproxy app.kubernetes.io/name=argocd-redis] ..."
}

In contrast, when using the in-cluster Redis (without the --core mode or when the Redis pod is available),
the command completes successfully. (Cluster 'https://127.0.0.1:61284' added)

Changes

I have identified that when creating a cluster using the --core CLI, the execution flow enters the doLazy function within the headless.go file. To address the reported issue, I introduced a new environment variable ARGOCD_REDIS_SERVER to store connection information for an external Redis instance.

func (c *forwardCacheClient) doLazy(action func(client cache.CacheClient) error) error {
	c.init.Do(func() {
		// Check for external Redis server address to bypass in-cluster pod discovery and port-forwarding.
		externalRedis := os.Getenv("ARGOCD_REDIS_SERVER")
		if externalRedis != "" {
			redisClient := redis.NewClient(&redis.Options{Addr: externalRedis, Password: c.redisPassword})
			c.client = cache.NewRedisCache(redisClient, time.Hour, c.compression)
			return
		}

		overrides := clientcmd.ConfigOverrides{
			CurrentContext: c.context,
		}
               // ...

In this logic, externalRedis retrieves the connection details from the $ARGOCD_REDIS_SERVER environment variable:

  • If empty or unset: The existing code proceeds as usual, maintaining current behavior.
  • If set: The CLI uses the provided address to create the redisClient directly, bypassing the in-cluster pod discovery.

Verification

  1. Set the environment variable

Set the environment variable in IP:port format.
ARGOCD_REDIS_SERVER="localhost:6379"

  1. Add the cluster using the same command

cluster add minikube --name cluster-name --upsert --yes --core

  1. Result

The cluster is successfully created. (Cluster 'https://127.0.0.1:61284' added)

  1. Confirmation in Redis

Below shows the data stored in the separate Docker Redis container.
image

If the in-cluster Redis is active and the environment variable is not set, the CLI correctly falls back to the default behavior.

  1. Check Side-Effect.

kubectl scale deployment argocd-redis --replicas=1 -n argocd
Remove-Item Env:ARGOCD_REDIS_SERVER

  1. Result

The cluster is added via the internal cluster Redis as expected.
Running the following command confirms the data is stored in the in-cluster Redis.

kubectl exec -it deployment/argocd-redis -n argocd -- redis-cli -a $REDIS_PASS keys "*"
Defaulted container "redis" out of: redis, secret-init (init)
Warning: Using a password with '-a' or '-u' option on the command line interface may not be safe.
1) "cluster|info|https://kubernetes.default.svc|1.8.3.gz"
2) "cluster|info|https://127.0.0.1:61284|1.8.3.gz"

Notes

  • I have used the ARGOCD_ prefix to maintain consistency with Argo CD's existing environment variable naming conventions. Please let me know if any changes are required.
  • Please note that the connection to the external Redis server currently utilizes the existing REDIS_PASSWORD logic.

This env var allows bypassing in-cluster Redis to use an external service. (24406)

Signed-off-by: devbini <[email protected]>
@devbini devbini requested review from a team as code owners January 8, 2026 16:36
@bunnyshell
Copy link

bunnyshell bot commented Jan 8, 2026

❗ Preview Environment deployment failed on Bunnyshell

See: Environment Details | Pipeline Logs

Available commands (reply to this comment):

  • 🚀 /bns:deploy to redeploy the environment
  • /bns:delete to remove the environment


func (c *forwardCacheClient) doLazy(action func(client cache.CacheClient) error) error {
c.init.Do(func() {
// Check for external Redis server address to bypass in-cluster pod discovery and port-forwarding.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this PR @devbini!

Could you please add:
Unit tests in a new headless_test.go file covering:
External Redis connection (when ARGOCD_REDIS_SERVER is set)
Fallback to port-forwarding (when env var is not set)
Optional..Cache operations (Set/Get/Delete)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the feedback, @pbhatnagar-oss!

I will create the new headless_test.go file as requested.
To ensure I'm on the right track, please review my proposed testing plan.

  1. I'll use miniredis to simulate an external Redis server within the unit tests.

  2. Test Scenarios is Three.

  • External Redis connection

    Verify that doLazy correctly initializes the CacheClient using the address from ARGOCD_REDIS_SERVER.

  • Fallback Path

    Verify that doLazy falls back to the default port-forwarding logic when the environment variable is not set.

  • Cache Operations

    I'll perform Set, Get, and Delete operations to ensure the initialized CacheClient correctly communicates with the Redis instance.

I aim to complete these tests and update the PR by the end of today.
Does this approach sound good to you?

Three test scenarios were created.
1. Verify external Redis connection when 'ARGOCD_REDIS_SERVER' is config.
2. Confirm fallback to internal cluster port forwarding when the env var is unset.
3. Validate cache operations (SET/GET/DELTE) with the external Redis server.

Signed-off-by: devbini <[email protected]>
@devbini devbini force-pushed the fix-24406-core-redis branch from 8bdcff5 to 26cad6b Compare January 10, 2026 04:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

argocd cluster add fails when Redis is external (GCP Memorystore): “cannot find ready pod with selector: [argocd-redis-ha-haproxy argocd-redis]”

2 participants