Chapter 1. Installing Developer Hub on EKS with the Operator The Red Hat Developer Hub Operator installation requires the Operator Lifecycle Manager (OLM) framework. Additonal resources For information about the OLM, see Operator Lifecycle Manager(OLM) documentation. 1.1. Installing the Developer Hub Operator with the OLM framework You can install the Developer Hub Operator on EKS using the Operator Lifecycle Manager (OLM) framework . Following that, you can proceed to deploy your Developer Hub instance in EKS. Prerequisites You have set the context to the EKS cluster in your current kubeconfig . For more information, see Creating or updating a kubeconfig file for an Amazon EKS cluster . You have installed kubectl . For more information, see Installing or updating kubectl . You have subscribed to registry.redhat.io . For more information, see Red Hat Container Registry Authentication . You have installed the Operator Lifecycle Manager (OLM). For more information about installation and troubleshooting, see OLM QuickStart or How do I get Operator Lifecycle Manager? Procedure Run the following command in your terminal to create the rhdh-operator namespace where the Operator is installed: kubectl create namespace rhdh-operator Create a pull secret using the following command: kubectl -n rhdh-operator create secret docker-registry rhdh-pull-secret \ --docker-server=registry.redhat.io \ --docker-username=<user_name> \ 1 --docker-password=<password> \ 2 --docker-email=<email> 3 1 Enter your username in the command. 2 Enter your password in the command. 3 Enter your email address in the command. The created pull secret is used to pull the Developer Hub images from the Red Hat Ecosystem. Create a CatalogSource resource that contains the Operators from the Red Hat Ecosystem: cat <<EOF | kubectl -n rhdh-operator apply -f - apiVersion: operators.coreos.com/v1alpha1 kind: CatalogSource metadata: name: redhat-catalog spec: sourceType: grpc image: registry.redhat.io/redhat/redhat-operator-index:v4.17 secrets: - "rhdh-pull-secret" displayName: Red Hat Operators EOF Create an OperatorGroup resource as follows: cat <<EOF | kubectl apply -n rhdh-operator -f - apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: rhdh-operator-group EOF Create a Subscription resource using the following code: cat <<EOF | kubectl apply -n rhdh-operator -f - apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: rhdh namespace: rhdh-operator spec: channel: fast installPlanApproval: Automatic name: rhdh source: redhat-catalog sourceNamespace: rhdh-operator startingCSV: rhdh-operator.v1.3.5 EOF Run the following command to verify that the created Operator is running: kubectl -n rhdh-operator get pods -w If the operator pod shows ImagePullBackOff status, then you might need permissions to pull the image directly within the Operator deployment's manifest. Tip You can include the required secret name in the deployment.spec.template.spec.imagePullSecrets list and verify the deployment name using kubectl get deployment -n rhdh-operator command: kubectl -n rhdh-operator patch deployment \ rhdh.fast --patch '{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"rhdh-pull-secret"}]}}}}' \ --type=merge Update the default configuration of the operator to ensure that Developer Hub resources can start correctly in EKS using the following steps: Edit the backstage-default-config ConfigMap in the rhdh-operator namespace using the following command: kubectl -n rhdh-operator edit configmap backstage-default-config Locate the db-statefulset.yaml string and add the fsGroup to its spec.template.spec.securityContext , as shown in the following example: db-statefulset.yaml: | apiVersion: apps/v1 kind: StatefulSet --- TRUNCATED --- spec: --- TRUNCATED --- restartPolicy: Always securityContext: # You can assign any random value as fsGroup fsGroup: 2000 serviceAccount: default serviceAccountName: default --- TRUNCATED --- Locate the deployment.yaml string and add the fsGroup to its specification, as shown in the following example: deployment.yaml: | apiVersion: apps/v1 kind: Deployment --- TRUNCATED --- spec: securityContext: # You can assign any random value as fsGroup fsGroup: 3000 automountServiceAccountToken: false --- TRUNCATED --- Locate the service.yaml string and change the type to NodePort as follows: service.yaml: | apiVersion: v1 kind: Service spec: # NodePort is required for the ALB to route to the Service type: NodePort --- TRUNCATED --- Save and exit. Wait for a few minutes until the changes are automatically applied to the operator pods. 1.2. Deploying the Developer Hub instance on EKS with the Operator Prerequisites A cluster administrator has installed the Red Hat Developer Hub Operator. You have an EKS cluster with AWS Application Load Balancer (ALB) add-on installed. For more information, see Application load balancing on Amazon Elastic Kubernetes Service and Installing the AWS Load Balancer Controller add-on . You have configured a domain name for your Developer Hub instance. The domain name can be a hosted zone entry on Route 53 or managed outside of AWS. For more information, see Configuring Amazon Route 53 as your DNS service documentation. You have an entry in the AWS Certificate Manager (ACM) for your preferred domain name. Make sure to keep a record of your Certificate ARN. You have subscribed to registry.redhat.io . For more information, see Red Hat Container Registry Authentication . You have set the context to the EKS cluster in your current kubeconfig . For more information, see Creating or updating a kubeconfig file for an Amazon EKS cluster . You have installed kubectl . For more information, see Installing or updating kubectl . Procedure Create a ConfigMap named app-config-rhdh containing the Developer Hub configuration using the following template: apiVersion: v1 kind: ConfigMap metadata: name: app-config-rhdh data: "app-config-rhdh.yaml": | app: title: Red Hat Developer Hub baseUrl: https://<rhdh_dns_name> backend: auth: externalAccess: - type: legacy options: subject: legacy-default-config secret: "USD{BACKEND_SECRET}" baseUrl: https://<rhdh_dns_name> cors: origin: https://<rhdh_dns_name> Create a Secret named secrets-rhdh and add a key named BACKEND_SECRET with a Base64-encoded string as value: apiVersion: v1 kind: Secret metadata: name: secrets-rhdh stringData: # TODO: See https://backstage.io/docs/auth/service-to-service-auth/#setup BACKEND_SECRET: "xxx" Important Ensure that you use a unique value of BACKEND_SECRET for each Developer Hub instance. You can use the following command to generate a key: node-p'require("crypto").randomBytes(24).toString("base64")' To enable pulling the PostgreSQL image from the Red Hat Ecosystem Catalog, add the image pull secret in the default service account within the namespace where the Developer Hub instance is being deployed: kubectl patch serviceaccount default \ -p '{"imagePullSecrets": [{"name": "rhdh-pull-secret"}]}' \ -n <your_namespace> Create a Custom Resource file using the following template: apiVersion: rhdh.redhat.com/v1alpha1 kind: Backstage metadata: # TODO: this the name of your Developer Hub instance name: my-rhdh spec: application: imagePullSecrets: - "rhdh-pull-secret" route: enabled: false appConfig: configMaps: - name: "app-config-rhdh" extraEnvs: secrets: - name: "secrets-rhdh" Create an Ingress resource using the following template, ensuring to customize the names as needed: apiVersion: networking.k8s.io/v1 kind: Ingress metadata: # TODO: this the name of your Developer Hub Ingress name: my-rhdh annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip # TODO: Using an ALB HTTPS Listener requires a certificate for your own domain. Fill in the ARN of your certificate, e.g.: alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-xxx:xxxx:certificate/xxxxxx alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' alb.ingress.kubernetes.io/ssl-redirect: '443' # TODO: Set your application domain name. external-dns.alpha.kubernetes.io/hostname: <rhdh_dns_name> spec: ingressClassName: alb rules: # TODO: Set your application domain name. - host: <rhdh_dns_name> http: paths: - path: / pathType: Prefix backend: service: # TODO: my-rhdh is the name of your Backstage Custom Resource. # Adjust if you changed it! name: backstage-my-rhdh port: name: http-backend In the template, replace ` <rhdh_dns_name>` with your Developer Hub domain name and update the value of alb.ingress.kubernetes.io/certificate-arn with your certificate ARN. Verification Wait until the DNS name is responsive, indicating that your Developer Hub instance is ready for use.

Commands:
create namespace rhdh-operator
-n rhdh-operator create secret docker-registry rhdh-pull-secret --docker-server=registry.redhat.io --docker-username=<user_name> \ 1 --docker-password=<password> \ 2 --docker-email=<email> 3
cat <<EOF | kubectl -n rhdh-operator apply -f - apiVersion: operators.coreos.com/v1alpha1 kind: CatalogSource metadata: name: redhat-catalog spec: sourceType: grpc image: registry.redhat.io/redhat/redhat-operator-index:v4.17 secrets: - "rhdh-pull-secret" displayName: Red Hat Operators EOF
cat <<EOF | kubectl apply -n rhdh-operator -f - apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: rhdh-operator-group EOF
cat <<EOF | kubectl apply -n rhdh-operator -f - apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: rhdh namespace: rhdh-operator spec: channel: fast installPlanApproval: Automatic name: rhdh source: redhat-catalog sourceNamespace: rhdh-operator startingCSV: rhdh-operator.v1.3.5 EOF
-n rhdh-operator get pods -w
-n rhdh-operator patch deployment rhdh.fast --patch '{"spec":{"template":{"spec":{"imagePullSecrets":[{"name":"rhdh-pull-secret"}]}}}}' --type=merge
-n rhdh-operator edit configmap backstage-default-config
db-statefulset.yaml: | apiVersion: apps/v1 kind: StatefulSet --- TRUNCATED --- spec: --- TRUNCATED --- restartPolicy: Always securityContext: # You can assign any random value as fsGroup fsGroup: 2000 serviceAccount: default serviceAccountName: default --- TRUNCATED ---
deployment.yaml: | apiVersion: apps/v1 kind: Deployment --- TRUNCATED --- spec: securityContext: # You can assign any random value as fsGroup fsGroup: 3000 automountServiceAccountToken: false --- TRUNCATED ---
service.yaml: | apiVersion: v1 kind: Service spec: # NodePort is required for the ALB to route to the Service type: NodePort --- TRUNCATED ---
apiVersion: v1 kind: ConfigMap metadata: name: app-config-rhdh data: "app-config-rhdh.yaml": | app: title: Red Hat Developer Hub baseUrl: https://<rhdh_dns_name> backend: auth: externalAccess: - type: legacy options: subject: legacy-default-config secret: "USD{BACKEND_SECRET}" baseUrl: https://<rhdh_dns_name> cors: origin: https://<rhdh_dns_name>
apiVersion: v1 kind: Secret metadata: name: secrets-rhdh stringData: # TODO: See https://backstage.io/docs/auth/service-to-service-auth/#setup BACKEND_SECRET: "xxx"
node-p'require("crypto").randomBytes(24).toString("base64")'
patch serviceaccount default -p '{"imagePullSecrets": [{"name": "rhdh-pull-secret"}]}' -n <your_namespace>
apiVersion: rhdh.redhat.com/v1alpha1 kind: Backstage metadata: # TODO: this the name of your Developer Hub instance name: my-rhdh spec: application: imagePullSecrets: - "rhdh-pull-secret" route: enabled: false appConfig: configMaps: - name: "app-config-rhdh" extraEnvs: secrets: - name: "secrets-rhdh"
apiVersion: networking.k8s.io/v1 kind: Ingress metadata: # TODO: this the name of your Developer Hub Ingress name: my-rhdh annotations: alb.ingress.kubernetes.io/scheme: internet-facing alb.ingress.kubernetes.io/target-type: ip # TODO: Using an ALB HTTPS Listener requires a certificate for your own domain. Fill in the ARN of your certificate, e.g.: alb.ingress.kubernetes.io/certificate-arn: arn:aws:acm:us-xxx:xxxx:certificate/xxxxxx alb.ingress.kubernetes.io/listen-ports: '[{"HTTP": 80}, {"HTTPS":443}]' alb.ingress.kubernetes.io/ssl-redirect: '443' # TODO: Set your application domain name. external-dns.alpha.kubernetes.io/hostname: <rhdh_dns_name> spec: ingressClassName: alb rules: # TODO: Set your application domain name. - host: <rhdh_dns_name> http: paths: - path: / pathType: Prefix backend: service: # TODO: my-rhdh is the name of your Backstage Custom Resource. # Adjust if you changed it! name: backstage-my-rhdh port: name: http-backend