Chapter 8. Tutorial: AWS Load Balancer Operator on Red Hat OpenShift Service on AWS
Install and configure the AWS Load Balancer Operator to provision advanced AWS Application Load Balancers (ALBs) and Network Load Balancers (NLBs) for your Red Hat OpenShift Service on AWS cluster.
This content is authored by Red Hat experts, but has not yet been tested on every supported configuration.
8.1. AWS Load Balancer Operator overview Copy linkLink copied to clipboard!
The AWS Load Balancer Operator installs and manages the AWS Load Balancer Controller, which provisions Application Load Balancers (ALBs) and Network Load Balancers (NLBs) with advanced annotations beyond the default in-tree provider.
Load Balancers created by the AWS Load Balancer Operator cannot be used for OpenShift Routes, and should only be used for individual services or ingress resources that do not need the full layer 7 capabilities of an OpenShift Route.
Compared with the default AWS in-tree load balancer provider, the AWS Load Balancer Controller is developed with advanced annotations for both ALBs and NLBs. Some advanced use cases are:
- Using native Kubernetes Ingress objects with ALBs.
- Integrating ALBs with the AWS Web Application Firewall (WAF) service. WAFv1, WAF classic, is no longer supported; use WAFv2.
- Specifying custom NLB source IP ranges.
- Specifying custom NLB internal IP addresses.
The AWS Load Balancer Operator is used to install, manage, and configure an instance of aws-load-balancer-controller in a Red Hat OpenShift Service on AWS cluster. For more information, see Additional resources.
8.2. Set up your environment Copy linkLink copied to clipboard!
Set environment variables for your cluster name, region, and OpenID Connect (OIDC) endpoint to ensure consistency across AWS Load Balancer Operator commands.
Prerequisites
You have created a multi-availability zone (AZ) Red Hat OpenShift Service on AWS cluster.
NoteAWS Application Load Balancers (ALBs) require a multi-AZ cluster and three public subnets split across three AZs in the same Virtual Private Cloud (VPC) as the cluster. This makes ALBs unsuitable for many PrivateLink clusters. AWS Network Load Balancers (NLBs) do not have this restriction.
- You have created a Bring Your Own (BYO) VPC cluster.
-
You have access to the AWS CLI (
aws). -
You have access to the OpenShift CLI (
oc).
Procedure
Prepare the environment variables:
$ export AWS_PAGER="" $ export ROSA_CLUSTER_NAME=$(oc get infrastructure cluster -o=jsonpath="{.status.infrastructureName}" | sed 's/-[a-z0-9]\{5\}$//') $ export REGION=$(oc get infrastructure cluster -o=jsonpath="{.status.platformStatus.aws.region}") $ export OIDC_ENDPOINT=$(oc get authentication.config.openshift.io cluster -o jsonpath='{.spec.serviceAccountIssuer}' | sed 's|^https://||') $ export AWS_ACCOUNT_ID=$(aws sts get-caller-identity --query Account --output text) $ export SCRATCH="/tmp/${ROSA_CLUSTER_NAME}/alb-operator" $ mkdir -p ${SCRATCH} $ echo "Cluster: ${ROSA_CLUSTER_NAME}, Region: ${REGION}, OIDC Endpoint: ${OIDC_ENDPOINT}, AWS Account ID: ${AWS_ACCOUNT_ID}"
8.2.1. Tag your AWS VPC and subnets Copy linkLink copied to clipboard!
Tag your Virtual Private Cloud (VPC) and subnets so the AWS Load Balancer Operator can identify your network resources and assign load balancers to the correct public or private subnets.
This section only applies to clusters that were deployed into existing VPCs. If you did not deploy your cluster into an existing VPC, skip this section and proceed to the installation section below.
Procedure
Set the below variables to the proper values for your cluster deployment:
$ export VPC_ID=<vpc-id> $ export PUBLIC_SUBNET_IDS=<public-subnets> $ export PRIVATE_SUBNET_IDS=<private-subnets> $ export CLUSTER_NAME=$(oc get infrastructure cluster -o=jsonpath="{.status.infrastructureName}")Add a tag to your cluster’s VPC with the cluster name:
$ aws ec2 create-tags --resources ${VPC_ID} --tags Key=kubernetes.io/cluster/${CLUSTER_NAME},Value=owned --region ${REGION}Add a tag to your public subnets:
$ aws ec2 create-tags \ --resources ${PUBLIC_SUBNET_IDS} \ --tags Key=kubernetes.io/role/elb,Value='' \ --region ${REGION}Add a tag to your private subnets:
$ aws ec2 create-tags \ --resources "${PRIVATE_SUBNET_IDS}" \ --tags Key=kubernetes.io/role/internal-elb,Value='' \ --region ${REGION}
8.3. Install the AWS Load Balancer Operator Copy linkLink copied to clipboard!
Install the AWS Load Balancer Operator to provision and manage AWS Application Load Balancers (ALBs) and Network Load Balancers (NLBs) for your Red Hat OpenShift Service on AWS cluster.
Procedure
Create an AWS Identity and Access Management (IAM) policy for the AWS Load Balancer Controller:
NoteThe policy is sourced from the upstream AWS Load Balancer Controller policy plus permission to create tags on subnets. This is required by the Operator to function.
$ oc new-project aws-load-balancer-operator $ POLICY_ARN=$(aws iam list-policies --query \ "Policies[?PolicyName=='aws-load-balancer-operator-policy'].{ARN:Arn}" \ --output text) $ if [[ -z "${POLICY_ARN}" ]]; then wget -O "${SCRATCH}/load-balancer-operator-policy.json" \ https://raw.githubusercontent.com/rh-mobb/documentation/main/content/rosa/aws-load-balancer-operator/load-balancer-operator-policy.json POLICY_ARN=$(aws --region "$REGION" --query Policy.Arn \ --output text iam create-policy \ --policy-name aws-load-balancer-operator-policy \ --policy-document "file://${SCRATCH}/load-balancer-operator-policy.json") fi $ echo $POLICY_ARNCreate an AWS IAM trust policy for AWS Load Balancer Operator:
$ cat <<EOF > "${SCRATCH}/trust-policy.json" { "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Condition": { "StringEquals" : { "${OIDC_ENDPOINT}:sub": ["system:serviceaccount:aws-load-balancer-operator:aws-load-balancer-operator-controller-manager", "system:serviceaccount:aws-load-balancer-operator:aws-load-balancer-controller-cluster"] } }, "Principal": { "Federated": "arn:aws:iam::$AWS_ACCOUNT_ID:oidc-provider/${OIDC_ENDPOINT}" }, "Action": "sts:AssumeRoleWithWebIdentity" } ] } EOFCreate an AWS IAM role for the AWS Load Balancer Operator:
$ ROLE_ARN=$(aws iam create-role --role-name "${ROSA_CLUSTER_NAME}-alb-operator" \ --assume-role-policy-document "file://${SCRATCH}/trust-policy.json" \ --query Role.Arn --output text) $ echo $ROLE_ARN $ aws iam attach-role-policy --role-name "${ROSA_CLUSTER_NAME}-alb-operator" \ --policy-arn $POLICY_ARNCreate a secret for the AWS Load Balancer Operator to assume the newly created AWS IAM role:
$ cat << EOF | oc apply -f - apiVersion: v1 kind: Secret metadata: name: aws-load-balancer-operator namespace: aws-load-balancer-operator stringData: credentials: | [default] role_arn = $ROLE_ARN web_identity_token_file = /var/run/secrets/openshift/serviceaccount/token EOFInstall the AWS Load Balancer Operator:
$ cat << EOF | oc apply -f - apiVersion: operators.coreos.com/v1 kind: OperatorGroup metadata: name: aws-load-balancer-operator namespace: aws-load-balancer-operator spec: upgradeStrategy: Default --- apiVersion: operators.coreos.com/v1alpha1 kind: Subscription metadata: name: aws-load-balancer-operator namespace: aws-load-balancer-operator spec: channel: stable-v1.0 installPlanApproval: Automatic name: aws-load-balancer-operator source: redhat-operators sourceNamespace: openshift-marketplace startingCSV: aws-load-balancer-operator.v1.0.0 EOFDeploy an instance of the AWS Load Balancer Controller using the Operator:
NoteIf you get an error, the Operator has not completed installing yet. Wait briefly and retry the step.
$ cat << EOF | oc apply -f - apiVersion: networking.olm.openshift.io/v1 kind: AWSLoadBalancerController metadata: name: cluster spec: credentials: name: aws-load-balancer-operator EOFCheck that the Operator and controller pods are both running:
$ oc -n aws-load-balancer-operator get podsExample output
NAME READY STATUS RESTARTS AGE aws-load-balancer-controller-cluster-6ddf658785-pdp5d 1/1 Running 0 99s aws-load-balancer-operator-controller-manager-577d9ffcb9-w6zqn 2/2 Running 0 2m4s
8.4. Validate the AWS Load Balancer Operator deployment Copy linkLink copied to clipboard!
Deploy a sample application with Application Load Balancer (ALB) and Network Load Balancer (NLB) resources to verify that the AWS Load Balancer Operator successfully provisions load balancers to your cluster.
Procedure
Create a new project:
$ oc new-project hello-worldDeploy a
hello-worldapplication:$ oc new-app -n hello-world --image=docker.io/openshift/hello-openshiftConfigure a NodePort service for the AWS Application Load Balancer (ALB) to connect to:
$ cat << EOF | oc apply -f - apiVersion: v1 kind: Service metadata: name: hello-openshift-nodeport namespace: hello-world spec: ports: - port: 80 targetPort: 8080 protocol: TCP type: NodePort selector: deployment: hello-openshift EOFDeploy an AWS ALB using the AWS Load Balancer Operator:
$ cat << EOF | oc apply -f - apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: hello-openshift-alb namespace: hello-world annotations: alb.ingress.kubernetes.io/scheme: internet-facing spec: ingressClassName: alb rules: - http: paths: - path: / pathType: Exact backend: service: name: hello-openshift-nodeport port: number: 80 EOFCurl the AWS ALB Ingress endpoint to verify the
hello-worldapplication is accessible:NoteAWS ALB provisioning takes a few minutes. If you receive an error that says
curl: (6) Could not resolve host, wait and try again.$ INGRESS=$(oc -n hello-world get ingress hello-openshift-alb \ -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') $ curl "http://${INGRESS}"Example output
Hello OpenShift!Deploy an AWS Network Load Balancer (NLB) for your
hello-worldapplication:$ cat << EOF | oc apply -f - apiVersion: v1 kind: Service metadata: name: hello-openshift-nlb namespace: hello-world annotations: service.beta.kubernetes.io/aws-load-balancer-type: external service.beta.kubernetes.io/aws-load-balancer-nlb-target-type: instance service.beta.kubernetes.io/aws-load-balancer-scheme: internet-facing spec: ports: - port: 80 targetPort: 8080 protocol: TCP type: LoadBalancer selector: deployment: hello-openshift EOFTest the AWS NLB endpoint:
NoteNLB provisioning takes a few minutes. If you receive an error that says
curl: (6) Could not resolve host, wait and try again.$ NLB=$(oc -n hello-world get service hello-openshift-nlb \ -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') $ curl "http://${NLB}"Example output
Hello OpenShift!
8.5. Clean up AWS resources Copy linkLink copied to clipboard!
Remove the sample application, AWS Load Balancer Operator, and associated Identity and Access Management (IAM) roles and policies created during this tutorial.
Procedure
Delete the
hello-worldapplication namespace and all the resources in the namespace:$ oc delete project hello-worldDelete the AWS Load Balancer Operator and the AWS IAM roles:
$ oc delete subscription aws-load-balancer-operator -n aws-load-balancer-operator $ aws iam detach-role-policy \ --role-name "${ROSA_CLUSTER_NAME}-alb-operator" \ --policy-arn $POLICY_ARN $ aws iam delete-role \ --role-name "${ROSA_CLUSTER_NAME}-alb-operator"Delete the AWS IAM policy:
$ aws iam delete-policy --policy-arn $POLICY_ARN