Configure
In this part, you will
- Create an IAM Role for Service Accounts (IRSA) so that pods have the necessary permissions to provision AWS elastic load balancers.
- Apply the newly created blueprint to the EKS cluster.
Important
IRSA is an optional configuration and is used when the permissions to provision load balancers is not given to the node instance role. It is a common practice to give the necessary permissions to the node instance role and it is possible to enable this in the UI and cluster specification at the time the cluster is created. It is also possible to grant the necessary permissions directly to the node instance role after the cluster has been created. The necessary permissions can be found here for the AWS Load Balancer Controller.
Important
If using the node instance role to grant the necessary permissions skip Step 1 and proceed to Step 2.
Step 1: IRSA (Optional)¶
In this step, you will create an IRSA so that pods on the EKS cluster will have the necessary permissions to provision AWS elastic load balancers. In AWS, it is a recommended best practice to use IAM roles for service accounts (IRSA) to access AWS services outside the EKS cluster because of the following benefits:
Benefit | Description |
---|---|
Least Privilege | No longer need to provide extended permissions to the node IAM role so that pods on that node can call AWS APIs. You can scope IAM permissions to a service account, and only pods that use that service account have access to those permissions. This feature also eliminates the need for third-party solutions such as kiam or kube2iam. |
Credential Isolation | A container can only retrieve credentials for the IAM role that is associated with the service account to which it belongs. A container never has access to credentials that are intended for another container that belongs to another pod. |
Auditability | Access and event logging is available through CloudTrail to help ensure retrospective auditing. |
Create IRSA (Optional)¶
To create the IRSA we will define a policy that will allow AWS get and describe actions to the secret resource.
- We will use the following policy which we will supply during the IAM Service Account creation.
{
"Statement": [
{
"Action": "iam:CreateServiceLinkedRole",
"Condition": {
"StringEquals": {
"iam:AWSServiceName": "elasticloadbalancing.amazonaws.com"
}
},
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:DescribeAccountAttributes",
"ec2:DescribeAddresses",
"ec2:DescribeAvailabilityZones",
"ec2:DescribeInternetGateways",
"ec2:DescribeVpcs",
"ec2:DescribeVpcPeeringConnections",
"ec2:DescribeSubnets",
"ec2:DescribeSecurityGroups",
"ec2:DescribeInstances",
"ec2:DescribeNetworkInterfaces",
"ec2:DescribeTags",
"ec2:GetCoipPoolUsage",
"ec2:DescribeCoipPools",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeLoadBalancerAttributes",
"elasticloadbalancing:DescribeListeners",
"elasticloadbalancing:DescribeListenerCertificates",
"elasticloadbalancing:DescribeSSLPolicies",
"elasticloadbalancing:DescribeRules",
"elasticloadbalancing:DescribeTargetGroups",
"elasticloadbalancing:DescribeTargetGroupAttributes",
"elasticloadbalancing:DescribeTargetHealth",
"elasticloadbalancing:DescribeTags"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"cognito-idp:DescribeUserPoolClient",
"acm:ListCertificates",
"acm:DescribeCertificate",
"iam:ListServerCertificates",
"iam:GetServerCertificate",
"waf-regional:GetWebACL",
"waf-regional:GetWebACLForResource",
"waf-regional:AssociateWebACL",
"waf-regional:DisassociateWebACL",
"wafv2:GetWebACL",
"wafv2:GetWebACLForResource",
"wafv2:AssociateWebACL",
"wafv2:DisassociateWebACL",
"shield:GetSubscriptionState",
"shield:DescribeProtection",
"shield:CreateProtection",
"shield:DeleteProtection"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:CreateSecurityGroup"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"ec2:CreateTags"
],
"Condition": {
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "false"
},
"StringEquals": {
"ec2:CreateAction": "CreateSecurityGroup"
}
},
"Effect": "Allow",
"Resource": "arn:aws:ec2:*:*:security-group/*"
},
{
"Action": [
"ec2:CreateTags",
"ec2:DeleteTags"
],
"Condition": {
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "true",
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
},
"Effect": "Allow",
"Resource": "arn:aws:ec2:*:*:security-group/*"
},
{
"Action": [
"ec2:AuthorizeSecurityGroupIngress",
"ec2:RevokeSecurityGroupIngress",
"ec2:DeleteSecurityGroup"
],
"Condition": {
"Null": {
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
},
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"elasticloadbalancing:CreateLoadBalancer",
"elasticloadbalancing:CreateTargetGroup"
],
"Condition": {
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "false"
}
},
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"elasticloadbalancing:CreateListener",
"elasticloadbalancing:DeleteListener",
"elasticloadbalancing:CreateRule",
"elasticloadbalancing:DeleteRule"
],
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"elasticloadbalancing:AddTags",
"elasticloadbalancing:RemoveTags"
],
"Condition": {
"Null": {
"aws:RequestTag/elbv2.k8s.aws/cluster": "true",
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
},
"Effect": "Allow",
"Resource": [
"arn:aws:elasticloadbalancing:*:*:targetgroup/*/*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/net/*/*",
"arn:aws:elasticloadbalancing:*:*:loadbalancer/app/*/*"
]
},
{
"Action": [
"elasticloadbalancing:AddTags",
"elasticloadbalancing:RemoveTags"
],
"Effect": "Allow",
"Resource": [
"arn:aws:elasticloadbalancing:*:*:listener/net/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener/app/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener-rule/net/*/*/*",
"arn:aws:elasticloadbalancing:*:*:listener-rule/app/*/*/*"
]
},
{
"Action": [
"elasticloadbalancing:ModifyLoadBalancerAttributes",
"elasticloadbalancing:SetIpAddressType",
"elasticloadbalancing:SetSecurityGroups",
"elasticloadbalancing:SetSubnets",
"elasticloadbalancing:DeleteLoadBalancer",
"elasticloadbalancing:ModifyTargetGroup",
"elasticloadbalancing:ModifyTargetGroupAttributes",
"elasticloadbalancing:DeleteTargetGroup"
],
"Condition": {
"Null": {
"aws:ResourceTag/elbv2.k8s.aws/cluster": "false"
}
},
"Effect": "Allow",
"Resource": "*"
},
{
"Action": [
"elasticloadbalancing:RegisterTargets",
"elasticloadbalancing:DeregisterTargets"
],
"Effect": "Allow",
"Resource": "arn:aws:elasticloadbalancing:*:*:targetgroup/*/*"
},
{
"Action": [
"elasticloadbalancing:SetWebAcl",
"elasticloadbalancing:ModifyListener",
"elasticloadbalancing:AddListenerCertificates",
"elasticloadbalancing:RemoveListenerCertificates",
"elasticloadbalancing:ModifyRule"
],
"Effect": "Allow",
"Resource": "*"
}
],
"Version": "2012-10-17"
}
Create IAM Service Account (Optional)¶
- Click on Infrastructure -> Clusters
- Click on the cluster tile we will be adding the IRSA to
- Click on the "IAM Service Accounts" tab
- Click on "NEW IAM SERVICE ACCOUNT"
- Enter a name we configured in the previous step "demo-aws-lb-controller-sa", select the namespace "kube-system", and supply the policy above. Policies can be supplied as an ARN if created previously, uploaded as an IAM Inline Policy Document, or supplied as input.
- Copy the above policy as an IAM Inline Policy Document
- Select "SAVE"
Verify IRSA (Optional)¶
Creation of the IRSA can take a few minutes. You can verify the status of the IRSA by doing the following:
- Click on the "IAM Service Accounts" tab for the cluster.
You can also verify that the k8s service account was created in the EKS cluster in the kube-system namespace.
- Click on the Zero Trust Kubectl Shell on the web console for the cluster where the IRSA was created and run the following kubectl command.
kubectl get sa -n kube-system demo-aws-lb-controller-sa
NAME SECRETS AGE
demo-aws-lb-controller-sa 1 2m29s
As you can see in this example, the "demo-aws-lb-controller-sa" service account was successfully created in the "kube-system" namespace.
Step 2: Apply Blueprint¶
Now, we are ready to apply the newly created, custom blueprint to our EKS cluster.
- Select Infrastructure -> Clusters.
- Click on the gear icon on the far right of the EKS cluster.
- Update blueprint and select the new blueprint and version.
In a few minutes, all the k8s resources matching the custom cluster blueprint will become operational on the cluster.
Notice that the cluster's blueprint name and version match what you created in the prior step.
Next Steps¶
You are now ready to move on to the next part of the recipe where you will create a workload and provision an ALB.