Global Pull Secret for Hosted Control Planes
Overview
The Global Pull Secret functionality enables Hosted Cluster administrators to include additional pull secrets for accessing container images from private registries without requiring assistance from the Management Cluster administrator. This feature allows you to merge your custom pull secret with the original HostedCluster pull secret, making it available to all nodes in the cluster.
The implementation uses a DaemonSet approach that automatically detects when you create an additional-pull-secret in the kube-system namespace of your DataPlane (Hosted Cluster). The system then merges this secret with the original pull secret and deploys the merged result to all nodes via a DaemonSet that updates the kubelet configuration.
Note
This feature is designed to work autonomously - once you create the additional pull secret, the system automatically handles the rest without requiring Management Cluster administrator intervention.
Adding your Pull Secret
Important
All actions described in this section must be performed on the HostedCluster's workers (DataPlane), not on the Management Cluster.
To use this functionality, follow these steps:
1. Create your additional pull secret
Create a secret named additional-pull-secret in the kube-system namespace of your Hosted Cluster (DataPlane). The secret must contain a valid DockerConfigJSON format:
apiVersion: v1
kind: Secret
metadata:
name: additional-pull-secret
namespace: kube-system
type: kubernetes.io/dockerconfigjson
data:
.dockerconfigjson: <base64-encoded-docker-config-json>
2. Example DockerConfigJSON format
Your .dockerconfigjson should follow this structure:
{
"auths": {
"registry.example.com": {
"auth": "base64-encoded-credentials"
},
"quay.io/mycompany": {
"auth": "base64-encoded-credentials"
}
}
}
Using Namespace-Specific Registry Entries
For registries like Quay.io that support organization/namespace-specific authentication, you can specify the full path in your registry entry (e.g., quay.io/mycompany instead of just quay.io). This allows you to provide different credentials for different namespaces within the same registry, and helps avoid conflicts with existing registry entries in the original pull secret.
3. Apply the secret
kubectl apply -f additional-pull-secret.yaml
4. Verification
After creating the secret, the system will automatically:
- Validate the secret format
- Merge it with the original pull secret
- Deploy a DaemonSet to all nodes
- Update the kubelet configuration on each node
You can verify the deployment by checking:
# Check if the DaemonSet is running
kubectl get daemonset global-pull-secret-syncer -n kube-system
# Check the merged pull secret
kubectl get secret global-pull-secret -n kube-system
# Check DaemonSet pods
kubectl get pods -n kube-system -l name=global-pull-secret-syncer
How it works
The Global Pull Secret functionality operates through a multi-component system:
Automatic Detection
- The Hosted Cluster Config Operator (HCCO) continuously monitors the
kube-systemnamespace - When it detects the creation of
additional-pull-secret, it triggers the reconciliation process
Validation and Merging
- The system validates that your secret contains a proper DockerConfigJSON format
- It retrieves the original pull secret from the HostedControlPlane
- Your additional pull secret is merged with the original one
- If there are conflicting registry entries, the original pull secret takes precedence (the additional pull secret entry is ignored for conflicting registries)
- The system supports namespace-specific registry entries (e.g.,
quay.io/namespace) for better credential specificity
Deployment Process
- A
global-pull-secretis created in thekube-systemnamespace containing the merged result - RBAC resources (ServiceAccount, Role, RoleBinding) are created for the DaemonSet in both
kube-systemandopenshift-confignamespaces - We use Role and RoleBinding in both namespaces to access secrets in
kube-systemandopenshift-confignamespaces - A DaemonSet named
global-pull-secret-synceris deployed to eligible nodes
NodePool InPlace Strategy Restriction
The Global Pull Secret DaemonSet is not deployed to nodes that belong to NodePools using the InPlace upgrade strategy. This restriction prevents conflicts between the DaemonSet's modifications to /var/lib/kubelet/config.json and the Machine Config Daemon (MCD) during InPlace upgrades.
- Nodes with Replace strategy: ✅ Receive Global Pull Secret DaemonSet
- Nodes with InPlace strategy: ❌ Do not receive Global Pull Secret DaemonSet
This ensures that MCD operations during InPlace upgrades do not fail due to unexpected changes in kubelet configuration files.
Node-Level Synchronization
- Each DaemonSet pod runs a controller that watches the secrets under kube-system namespace
- When changes are detected, it updates
/var/lib/kubelet/config.jsonon the node - The kubelet service is restarted via DBus to apply the new configuration
- If the restart fails after 3 attempts, the system rolls back the file changes
Automatic Cleanup
- If you delete the
additional-pull-secret, the HCCO automatically removes theglobal-pull-secretsecret - The system reverts to using only the original pull secret from the HostedControlPlane
- The DaemonSet continues running but now syncs only the original pull secret to nodes
Registry Precedence and Conflict Resolution
The Global Pull Secret system uses a specific precedence model when merging your additional pull secret with the original one:
Merge Behavior
- Original pull secret entries always take precedence over additional pull secret entries for the same registry
- If both secrets contain an entry for
quay.io, the original pull secret's credentials will be used - Your additional pull secret entries are only added if they don't conflict with existing entries
- Warnings are logged when conflicts are detected
Recommended Approach
To avoid conflicts and ensure your credentials are used, consider these strategies:
- Use namespace-specific entries: Instead of
quay.io, usequay.io/your-namespace - Target specific registries: Add entries only for registries not already in the original pull secret
- Check existing entries: Review what registries are already configured in the HostedControlPlane
Example Merge Scenario
Original Pull Secret:
{
"auths": {
"quay.io": {
"auth": "original-credentials"
}
}
}
Your Additional Pull Secret:
{
"auths": {
"quay.io": {
"auth": "your-credentials"
},
"quay.io/mycompany": {
"auth": "your-namespace-credentials"
}
}
}
Resulting Merged Pull Secret:
{
"auths": {
"quay.io": {
"auth": "original-credentials"
},
"quay.io/mycompany": {
"auth": "your-namespace-credentials"
}
}
}
Note how the quay.io entry keeps the original credentials, but quay.io/mycompany is added from your additional secret.
Implementation details
The implementation consists of several key components working together:
Core Components
- Global Pull Secret Controller (
globalpspackage) - Handles validation of user-provided pull secrets
- Manages the merging logic between original and additional pull secrets
- Creates and manages RBAC resources
- Deploys and manages the DaemonSet
-
Node eligibility assessment: Labels nodes from InPlace NodePools and configures DaemonSet scheduling restrictions
-
Sync Global Pull Secret Command (
sync-global-pullsecretpackage) - Runs as a DaemonSet on each node
- Watches for changes to the
global-pull-secretinkube-systemnamespace - Accesses the original
pull-secretinopenshift-confignamespace - Updates the kubelet configuration file
-
Manages kubelet service restarts via DBus
-
Hosted Cluster Config Operator Integration
- Monitors for the presence of
additional-pull-secret - Orchestrates the entire process
- Handles cleanup when the secret is removed
Architecture Diagram
Key Features
- Security: Only watches specific secrets in
kube-systemandopenshift-confignamespaces - Robustness: Includes automatic rollback in case of failures
- Efficiency
- Only updates when there are actual changes
- The globalPullSecret implementation has their own controller so it cannot interfere with the HCCO reonciliation
- Security considerations: Uses specific RBAC for only the required resources in each namespace. The DaemonSet containers run in privileged mode due to the need to:
- Write to
/var/lib/kubelet/config.json(kubelet configuration file) - Connect to systemd via DBus for service management
- Restart kubelet.service, which requires root privileges
- Smart node targeting: Automatically excludes nodes from InPlace NodePools to prevent MCD conflicts
InPlace NodePool Handling
To prevent conflicts with Machine Config Daemon operations, the implementation includes intelligent node targeting:
Node Labeling Process
- MachineSets Discovery: The controller queries the management cluster for MachineSets with InPlace-specific annotations (
hypershift.openshift.io/nodePoolTargetConfigVersion) - Machine Enumeration: For each InPlace MachineSets, it lists all associated Machines
- Node Identification: Maps Machine objects to their corresponding nodes via
machine.Status.NodeRef.Name - Labeling: Applies
hypershift.openshift.io/nodepool-inplace-strategy=truelabel to identified nodes
DaemonSet Scheduling Configuration
The DaemonSet uses NodeAffinity to exclude InPlace nodes:
spec:
template:
spec:
affinity:
nodeAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
nodeSelectorTerms:
- matchExpressions:
- key: hypershift.openshift.io/nodepool-inplace-strategy
operator: DoesNotExist
This ensures that: - Nodes without the label: ✅ Are eligible for DaemonSet scheduling - Nodes with the label (any value): ❌ Are excluded from DaemonSet scheduling
Conflict Prevention Benefits
- Prevents MCD failures: Avoids conflicts when MCD expects specific kubelet configuration during InPlace upgrades
- Maintains upgrade reliability: InPlace upgrade processes are not interrupted by Global Pull Secret modifications
- Automatic detection: No manual intervention required - the system automatically identifies and handles InPlace nodes
Error Handling
The system includes comprehensive error handling:
- Validation errors: Invalid DockerConfigJSON format is caught early
- Restart failures: If kubelet restart fails after 3 attempts, the file is rolled back
- Resource cleanup: If the additional pull secret is deleted, the HCCO automatically removes the globalPullSecret
This implementation provides a secure, autonomous solution that allows HostedCluster administrators to add private registry credentials without requiring Management Cluster administrator intervention.