nebari-dev / nebari-dev/rayserve-pack

Expose image.pullSecrets in values.yaml and wire through head/worker pod templates

Open Beginner friendly
#20 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Makefile
Stars
1
Forks
4
Avg merge
3d 14h
Merged PRs (30d)
5

Description

Summary

chart/values.yaml exposes image.repository and image.tag for the Ray head + worker pods, but doesn't expose image.pullSecrets. As a result, charts deployed against a private container registry can render successfully but the resulting pods sit in ImagePullBackOff because there's no way to wire up registry credentials through helm values.

The chart's templates also don't override serviceAccountName for the pods, so they run as the default ServiceAccount in the release namespace.

Reproduction

  1. Deploy the chart with a private-registry image, e.g.:

    image:
      repository: registry.example.internal/team/ray-worker
      tag: 1.0.0
    
  2. Without an out-of-band step, head + worker pods stay in ImagePullBackOff:

    $ kubectl -n ray describe pod rayservice-pack-rayservice-... | grep -A2 Failed
      Warning  Failed       … kubelet  Failed to pull image "registry.example.internal/…":
                                     failed to resolve reference "...": pulling from host
                                     registry.example.internal failed with status code 401 Unauthorized
    
  3. Currently the only way to fix this is to attach an imagePullSecret to the default ServiceAccount in the release namespace, which means the credential lives outside the chart's helm values and the gitops repo:

    kubectl -n ray create secret docker-registry registry-creds \
        --docker-server=registry.example.internal \
        --docker-username=<user> --docker-password=<token>
    kubectl -n ray patch serviceaccount default --type=merge \
        -p '{"imagePullSecrets":[{"name":"registry-creds"}]}'
    

This is awkward for a few reasons:

  • The chart consumer has to know the chart uses the default SA — that's an implementation detail leaking through.
  • The patch is imperative and lives on the cluster, not in git. If the SA is ever recreated (e.g. namespace prune-and-recreate), the binding silently disappears and the next pod restart fails.
  • It's noisy in multi-tenant clusters where the default SA is shared across unrelated workloads.

Proposed change

Add image.pullSecrets: [] to chart/values.yaml and render it into both pod templates:

# chart/values.yaml
image:
  repository: rayproject/ray
  tag: 2.43.0
  # List of image pull secret names already present in the release
  # namespace. Names must reference Secrets of type
  # kubernetes.io/dockerconfigjson. Defaulted empty so existing
  # deployments using public images are unaffected.
  pullSecrets: []
  # Example:
  # pullSecrets:
  #   - name: my-registry-creds

Then in chart/templates/rayservice.yaml, add the field to both the head pod template (around line 42) and the worker pod template (around line 96), gated so it only renders when set:

template:
  spec:
    {{- with .Values.image.pullSecrets }}
    imagePullSecrets:
      {{- toYaml . | nindent 6 }}
    {{- end }}
    containers:
      - name: ray-head   # or ray-worker
        image: "{{ .Values.image.repository }}:{{ .Values.image.tag }}"
        # …

{{- with }} ensures the field is only rendered when pullSecrets is non-empty, so the existing rendered output is byte-identical when nobody sets it — no diff for users who don't need this.

Acceptance criteria

  • chart/values.yaml exposes image.pullSecrets (list of {name: ...} entries), defaulted empty, with a comment explaining the format and that the referenced Secrets must already exist in the release namespace.
  • chart/templates/rayservice.yaml head pod spec renders imagePullSecrets when image.pullSecrets is non-empty.
  • Same for the worker pod spec.
  • When image.pullSecrets is empty (the default), the rendered manifest is byte-identical to v0.3.1 — confirmed by helm template diff.
  • README example shows wiring a private-registry image with a pre-created pull Secret.

Out of scope

  • Auto-creating the pull Secret from a helm value. The Secret should be pre-created via whatever mechanism the operator uses (sealed-secrets, external-secrets, gitops-managed Secret, manual kubectl create). The chart only consumes a reference, not the credential.
  • A separate serviceAccountName override. That's a different feature (custom SA with extra IAM, IRSA bindings, etc.). The pullSecrets fix doesn't require it — imagePullSecrets on the pod spec works regardless of which SA the pod runs under.

Alternatives considered

  • Patch the default ServiceAccount. What we do today. Documented above — leaky and not gitops-friendly.
  • Add a serviceAccount.create: true with imagePullSecrets. Works but introduces a new SA per release, plus requires serviceAccountName plumbing through the pod templates. Larger surface area than necessary when the only thing that's missing is the per-pod imagePullSecrets field.
  • Use a registry mirror. Workable for organizations that have a public mirror of their private images, but doesn't help the common case where the images themselves are private.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with chart/values.yaml and chart/templates/rayservice.yaml, focusing on the head and worker pod specs described in the issue. Render the chart with helm template and compare the default output with v0.3.1; update the README with the private-registry example, and consider the work done when both pod templates render non-empty imagePullSecrets while the default output is unchanged.

Written by the indexing model from the issue text.

Assessment

Tech stack
helm, kubernetes
Domain
devops, infrastructure
Issue type
Feature
Difficulty
2/5
Estimated time
1-3 hours
Activity status
Quiet
Clarity
Clearly specified
Newbie friendliness
78/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.