OpenShift Container Platform setup on Red Hat Demo Platform Open Environment Lab for Red Hat Consulting team
The purpose of this project is to help the Red Hat Consulting team quickly setup an OpenShift cluster using an AWS Blank Open Environment Red Hat Demo Platform item.
It supports both IPI (Installer-Provisioned Infrastructure) and UPI (User-Provisioned Infrastructure) methods for installation on AWS.
The entire installation process, including Day 2 configuration, takes about 1 hour or more.
This OCP installation includes a rich set of optional Day 2 components deployed via a Profile-Based GitOps Architecture, such as:
- Storage: OpenShift Data Foundation (ODF) in MultiCloud Gateway only (MCG) or Full modes (Lean, Balanced, Performance).
- Integration: OpenShift Service Mesh, Red Hat Connectivity Link (Kuadrant API Gateway), Red Hat build of Keycloak operator (RHBK - no instances).
- Observability: Logging (Pico, Small, Medium), Loki, Monitoring, Tempo, OpenTelemetry, Network Observability (with or without Loki).
- Security: Red Hat Advanced Cluster Security (ACS) - Central or Secured Cluster modes.
- Management: Red Hat Advanced Cluster Management (ACM) - Hub or Managed modes.
- AI/ML: Red Hat OpenShift AI (RHOAI), Nvidia GPU Operator, Kueue.
- CI/CD: OpenShift GitOps, Pipelines, Builds.
- Utilities: cert-manager, Sealed Secrets, WebTerminal, Node Feature Discovery, AWS Controllers for Kubernetes (ACK) Route53.
- Multi-Configuration Support: Manage different cluster types (e.g.,
standard,odf-full,ai,acs-central) from a single codebase using dedicated config files. - Clean Workspace: All runtime artifacts (keys, logs, sessions) are isolated in an
output/directory. - Parallel Execution: Run multiple cluster installations simultaneously on different AWS accounts or regions without conflict.
- Robust Recovery:
- Auto-Resume: If your network drops, simply rerun the script to reattach to the session.
- Provisioning Recovery: Detects existing Bastion instances to avoid duplication.
- Modular GitOps: Uses a "Lego-like" Component + Base + Profile architecture (Kustomize) for flexible composition.
- Production-Ready Security:
- Least-Privilege RBAC: All 20 GitOps Jobs use dedicated ServiceAccounts with minimal permissions (0 cluster-admin usage).
- Zero-Trust Network Isolation: AdminNetworkPolicy + BaselineAdminNetworkPolicy for namespace-level network security.
- Secrets Management: AWS Secrets Manager integration for credential handling.
- Air-Gap Compatible: Uses Red Hat registry images exclusively.
New user? Follow these steps in order. Skipping any step will break the installation.
Option A: Use as-is (no customization)
git clone https://github.com/lautou/ocp-open-env-install-tool.git
cd ocp-open-env-install-toolOption B: Fork first (recommended β allows you to customize GitOps profiles)
- Fork this repository on GitHub to your own org/account
- Clone your fork:
git clone https://github.com/<your-org>/ocp-open-env-install-tool.git
cd ocp-open-env-install-tool
β οΈ If you forked, you must updateGIT_REPO_URLinconfig/common.config(Step 3) to point to your fork β otherwise ArgoCD will sync from the upstream repo, not yours.
Every time you run the installer, pull the latest version first. Running an outdated version can cause cryptic failures (missing RBAC, outdated CRDs, etc.):
git pull origin master # or your target branchThe config/ directory does not exist by default β you must create it.
# Create the config directory
mkdir -p config
# 1. Create the shared common config (required)
cp config_examples/common.config.example config/common.config
# 2. Create a cluster-specific config (choose the profile matching your use case)
cp config_examples/ocp-ai.config.example config/ocp-ai.config # AI/ML profile
# or
cp config_examples/ocp-standard.config.example config/ocp-standard.config # Standard profileThen edit both files with your values:
# In config/common.config β mandatory fields:
# - OCP_ADMIN_PASSWORD / OCP_NON_ADMIN_PASSWORD β cluster passwords
# - GIT_REPO_URL β YOUR fork URL (if forked)
# - GIT_REPO_REVISION β branch (default: master)
# In config/ocp-ai.config β mandatory fields:
# - CLUSTER_NAME β e.g. "myocp"
# - AWS_DEFAULT_REGION β e.g. "eu-central-1"
# - AWS_ACCESS_KEY_ID / AWS_SECRET_ACCESS_KEY β from RHDP environment
# - RHDP_TOP_LEVEL_ROUTE53_DOMAIN β from RHDP environment (e.g. ".sandbox1234.opentlc.com")Download your pull secret from console.redhat.com and place it in the project root:
# The file must be named exactly pull-secret.txt at the project root
ls pull-secret.txt # verify it existsEnsure these tools are installed on your workstation:
| Tool | Purpose | macOS install |
|---|---|---|
oc |
OpenShift CLI | brew install openshift-cli |
git |
Version control | pre-installed |
yq |
YAML processing (mikefarah/yq) | brew install yq |
podman |
Registry credential check | brew install podman |
aws |
AWS CLI | brew install awscli |
./init_openshift_installation_lab_cluster.sh --config-file ocp-ai.configThe installation takes ~1 hour. If your connection drops, re-run the same command β the script auto-resumes.
- An active AWS Blank Open Environment from Red Hat Demo Platform
pull-secret.txtin the project rootconfig/common.configandconfig/<profile>.configcreated and filled in- CLI tools:
oc,git,yq,podman,aws - (If forked)
GIT_REPO_URLupdated inconfig/common.config
init_openshift_installation_lab_cluster.sh: The main entry point script.config/: Directory for your active configuration files (.config).config_examples/: Templates for creating new configurations.scripts/: Helper scripts (bastion_script.sh,clean_aws_tenant.sh,approve_cluster_csrs.sh, etc.).output/: (Ignored by Git) Stores all runtime artifacts: SSH keys, logs, session info, and upload staging folders.components/: The "Bricks" - Raw Kustomize definitions for applications.gitops-bases/: The "Groups" - ApplicationSets grouping components together.gitops-profiles/: The "Menu" - Kustomize entry points that select specific bases.
The tool uses a Split-Configuration model to support multiple environments while sharing common variables.
Shared variables (e.g., OpenShift Version, Base Domain, Passwords) live here.
cp config_examples/common.config.example config/common.config
# Edit config/common.config with your preferred defaults and credentialsChoose an example from config_examples/ and copy it to config/.
Example: Creating a Full ODF Performance Cluster
Bash
cp config_examples/ocp-odf-full-aws-performance.config.example config/my-odf-cluster.config
Key Variables in Config Files:
CLUSTER_NAME: Name of your cluster.AWS_DEFAULT_REGION: Target region.GITOPS_PROFILE_PATH: Points to the specific GitOps profile to deploy (e.g.,gitops-profiles/odf-full-aws-performance).
This uses the settings defined in your custom config file inside the config/ directory.
Bash
./init_openshift_installation_lab_cluster.sh --config-file my-odf-cluster.config
If no argument is provided, it defaults to config/ocp-standard.config.
Bash
./init_openshift_installation_lab_cluster.sh
Display available options.
Bash
./init_openshift_installation_lab_cluster.sh --help
The scripts/ directory contains useful tools for Day 2 operations and maintenance.
If your cluster certificates expire or nodes are stuck in NotReady (e.g., after a shutdown), run this script to auto-approve pending CSRs.
Bash
# Usage: ./scripts/approve_cluster_csrs.sh <BASTION_HOST> <SSH_KEY>
./scripts/approve_cluster_csrs.sh ec2-x-x-x-x.compute.amazonaws.com output/bastion_mycluster.pem
This script is automatically called by the init script but can be run manually to force-clean resources related to a cluster name in a region.
# Usage: ./scripts/clean_aws_tenant.sh <AWS_KEY> <AWS_SECRET> <REGION> <CLUSTER_NAME> <DOMAIN>
./scripts/clean_aws_tenant.sh $AWS_ACCESS_KEY_ID $AWS_SECRET_ACCESS_KEY us-east-2 mycluster sandbox1234.opentlc.comThis project uses a modular "App of Apps" pattern controlled by Kustomize profiles.
- Components (
components/): Individual applications (e.g.,rhacs,openshift-logging). They may containoverlaysfor specific flavors (e.g.,logging/overlays/1x.small). - Bases (
gitops-bases/): ArgoCD ApplicationSets that group components. For example,bases/acs/centralinstalls the Operator AND the Central instance. - Profiles (
gitops-profiles/): The top-level Kustomize file referenced by your config (GITOPS_PROFILE_PATH). It mixes and matches bases.
Example: "Standard Secured" Profile
- Base:
core(System components) - Base:
storage/mcg-only(Lightweight storage) - Base:
logging/pico(Minimal logging) - Base:
netobserv/default(Network Observability without Loki) - Base:
acs/secured(Sensor connecting to a Central)
- Disconnected? Just run the exact same command again. The script will detect the active session and ask if you want to resume.
- Bastion Provisioning Stuck? If you killed the script while the Bastion was creating, run it again. It will detect the pending Instance ID and resume waiting for it to be ready.
- It allows provisioning an OCP environment rapidly with zero paperwork.
- Limitation: AWS Blank Open Environment service lifetime is usually limited (e.g., 30 hours). Be cautious!
The default configuration points to the upstream repository. To make changes (like pinning specific operator versions or adding custom apps):
- Fork this repository.
- Update
GIT_REPO_URLinconfig/common.configto point to your fork. - Run the installation. ArgoCD will now sync from your fork.
β IMPLEMENTED: AWS credentials are now securely stored in AWS Secrets Manager instead of being passed to the bastion in plaintext.
How It Works:
- Simple Config: You edit AWS credentials in
config/*.configfiles (workflow unchanged) - Automatic Upload: The installer stores credentials in AWS Secrets Manager
- Secure Retrieval: Bastion retrieves credentials using IAM instance profile (not from uploaded files)
- Automatic Cleanup: Secrets are deleted when cleaning the environment
Security Benefits:
- β Encrypted Storage: Secrets Manager encrypts credentials at rest with AWS KMS
- β Secure Transit: Retrieved via TLS (AWS API)
- β No Plaintext Upload: Credentials NOT sent to bastion in config files
- β IAM-Based Access: Only the bastion instance can read its secret
- β Audit Trail: CloudTrail logs all secret access
- β Automatic Deletion: Secrets purged during cleanup (idempotent)
What's Still in Config Files:
β οΈ Local config files still contain AWS credentials (needed for initial AWS setup from your workstation)β οΈ Cluster passwords (OCP_ADMIN_PASSWORD,OCP_NON_ADMIN_PASSWORD) remain inconfig/common.config
This is acceptable for RHDP demo/lab environments (30h lifespan, dedicated tenants, single-user).
Best Practices:
- Use temporary credentials: Generate short-lived IAM credentials from RHDP (auto-expire with environment)
- Delete local configs: Remove
config/*.configfiles after cluster destruction - Verify cleanup: Ensure
clean_aws_tenant.shcompletes successfully - Clean output/: Delete
output/directory after teardown
For Production Use: The tool already uses AWS Secrets Manager for credentials. For production adaptation:
- β Secrets Manager is production-ready
β οΈ Consider adding OCP passwords to Secrets Manager- β Enable credential rotation policies
- β Use dedicated IAM users with minimal permissions
β PRODUCTION-READY: All GitOps automation Jobs use dedicated ServiceAccounts with minimal permissions.
Implementation:
- 20 Jobs deployed via GitOps for Day 2 configuration
- 13 Dedicated ServiceAccounts with task-specific permissions
- 0 cluster-admin usage (all Jobs use least-privilege RBAC)
- Namespace-scoped Roles preferred over cluster-scoped permissions
Security Improvements:
- β ~95-99% permission reduction per Job (vs cluster-admin)
- β Blast radius containment - Compromised Job cannot access unrelated resources
- β Audit compliance - Clear permission boundaries
- β Production-ready - No overly permissive access
Examples:
console-plugin-manager- ONLY console.operator.openshift.io patch (~99% reduction)cert-manager-operator- cert-manager.io + specific namespaces (~95% reduction)loki-s3-secret-creator- Secret create/update in logging/netobserv only (~95% reduction)
See docs/claude/security.md for detailed RBAC implementation.
β IMPLEMENTED: AdminNetworkPolicy (ANP) + BaselineAdminNetworkPolicy (BANP) for namespace-level network security.
Architecture:
- AdminNetworkPolicy (priority 10, highest) - Explicit Allow rules for cluster services
- NetworkPolicy (medium priority) - User/developer policies
- BaselineAdminNetworkPolicy (lowest priority) - Default deny fallback
Security Benefits:
- β Zero-trust by default - All traffic denied unless explicitly allowed
- β Guaranteed cluster services - DNS, monitoring, ingress cannot be blocked
- β
Opt-in per namespace - Label
network-policy.gitops/enforce: "true"to enable - β 90% resource reduction - 2 policies vs 72+ NetworkPolicy objects
Critical Implementation Detail:
- Kubernetes API access requires
nodes:selector (not IP-based rules) - OVN-Kubernetes performs DNAT before ANP evaluation
- See
CLAUDE.md"Network Isolation with AdminNetworkPolicy" section