|
| 1 | +# Service type-LoadBalancer Network Load Balancer with Security Group |
| 2 | + |
| 3 | +## Overview |
| 4 | + |
| 5 | +The controller can be configured to enable managed Security Group (SG) for Services using AWS Network Load Balancer (NLB) by setting an opt-in configuration in your cloud config. When enabled, each NLB created for a Kubernetes Service of type `LoadBalancer` with annotation `service.beta.kubernetes.io/aws-load-balancer-type=nlb` will have a dedicated Security Group, managed by the cloud provider controller. We are calling this as opt-in Managed NLB Security Group ("Managed SG" mode). |
| 6 | + |
| 7 | +> Note: The BYO SG (user-provided security groups) annotations (`service.beta.kubernetes.io/aws-load-balancer-security-groups` and `service.beta.kubernetes.io/aws-load-balancer-extra-security-groups`) are valid only for Classic Load Balancers. To learn more about supported annotations by load balancer type, see the [service_controller documentation][doc-ctrl-service]. |
| 8 | +
|
| 9 | +[doc-ctrl-service]: https://github.com/kubernetes/cloud-provider-aws/blob/master/docs/service_controller.md |
| 10 | + |
| 11 | +## Configuration |
| 12 | + |
| 13 | +### Opt-in Managed Security Group mode |
| 14 | + |
| 15 | +To enable this feature, add the following to your cloud config (usually `/etc/kubernetes/cloud-config` or as configured in your deployment): |
| 16 | + |
| 17 | +```ini |
| 18 | +[Global] |
| 19 | +NLBSecurityGroupMode = Managed |
| 20 | +``` |
| 21 | + |
| 22 | +- **Default behavior:** If `NLBSecurityGroupMode` is not set or set to any value other than `Managed`, NLBs are provisioned without a dedicated, controller-managed Security Group (legacy behavior). |
| 23 | +- **Opt-in behavior:** When set to `Managed`, the controller will create, attach, update, and delete a dedicated SG for each NLB Service. |
| 24 | + |
| 25 | +## Feature Details and Use Cases |
| 26 | + |
| 27 | +- **Why use this feature?** |
| 28 | + - Improved security: fine-grained, automated control over NLB ingress. |
| 29 | + - Automated lifecycle management of SGs, reducing manual intervention and risk of resource leaks. |
| 30 | +- **When to use:** |
| 31 | + - When you want the controller to manage NLB security groups automatically for NLB. |
| 32 | + - When your security/compliance policies require explicit SGs for each NLB. |
| 33 | + |
| 34 | +## Upgrade and Migration Notes |
| 35 | + |
| 36 | +- **Enabling the feature:** |
| 37 | + - Existing Service type-loadBalancer NLB will not be retroactively assigned a managed SG. Only new Services (created after enabling the feature) will have managed SGs. |
| 38 | + - To migrate existing NLBs, you must recreate the Service or manually update the SGs. |
| 39 | +- **Disabling the feature:** |
| 40 | + - If you disable the feature after using it, previously managed SGs will not be deleted automatically unless the Service and associated NLB is deleted. |
| 41 | +- **Controller restart:** |
| 42 | + - Changing the config requires a controller restart for the new setting to take effect. |
| 43 | + |
| 44 | +## Security Group Lifecycle |
| 45 | + |
| 46 | +### Managed Security Group |
| 47 | + |
| 48 | +- **Creation:** |
| 49 | + - SGs are created with owned cluster tag indicating they are managed by the controller. |
| 50 | +- **Tagging:** |
| 51 | + - Managed SGs are tagged for identification and safe cleanup. Example cluster tag: |
| 52 | + - `kubernetes.io/cluster/<cluster-name>: owned` |
| 53 | +- **Deletion:** |
| 54 | + - Managed SGs are deleted when the corresponding Service is deleted. The controller uses exponential backoff to handle AWS dependency violations. |
| 55 | + |
| 56 | +## Testing and Validation |
| 57 | + |
| 58 | +### Test 1 - **How to test the Managed Security Group:** |
| 59 | + |
| 60 | + 1. Ensure your cloud-config has the configuration `NLBSecurityGroupMode = Managed` |
| 61 | + 2. Create a Service of type `LoadBalancer` after enabling the feature. |
| 62 | +```sh |
| 63 | +APP_NAME=app |
| 64 | +APP_NAMESPACE=$APP_NAME |
| 65 | +SVC_NAME="${APP_NAME}-nlb-sg" |
| 66 | +cat << EOF | kubectl create -f - |
| 67 | +apiVersion: v1 |
| 68 | +kind: Service |
| 69 | +metadata: |
| 70 | + name: "${SVC_NAME}" |
| 71 | + namespace: "${APP_NAMESPACE}" |
| 72 | + annotations: |
| 73 | + service.beta.kubernetes.io/aws-load-balancer-type: nlb |
| 74 | +spec: |
| 75 | + selector: |
| 76 | + app: "${APP_NAME}" |
| 77 | + ports: |
| 78 | + - port: 80 |
| 79 | + targetPort: 8080 |
| 80 | + protocol: TCP |
| 81 | + type: LoadBalancer |
| 82 | +EOF |
| 83 | +``` |
| 84 | + 3. Verify that a managed SG is created and attached to the NLB in the AWS console. |
| 85 | + 4. Check that the SG is tagged appropriately and that ingress rules match your Service spec. |
| 86 | + 5. Ensure you can reach the Service NLB endpoint: |
| 87 | +```sh |
| 88 | +LB_DNS=$(kubectl get svc $SVC_NAME -n ${APP_NAMESPACE} -o jsonpath='{.status.loadBalancer.ingress[0].hostname}') |
| 89 | + |
| 90 | +aws elbv2 describe-tags --resource-arns $(aws elbv2 describe-load-balancers | jq -r ".LoadBalancers[] | select(.DNSName==\"$LB_DNS\").LoadBalancerArn") | jq .TagDescriptions[].Tags |
| 91 | + |
| 92 | +[ |
| 93 | + { |
| 94 | + "Key": "kubernetes.io/service-name", |
| 95 | + "Value": "app/app-svc-ccm" |
| 96 | + }, |
| 97 | + { |
| 98 | + "Key": "kubernetes.io/cluster/mrb-sg-zvcgr", |
| 99 | + "Value": "owned" |
| 100 | + } |
| 101 | +] |
| 102 | + |
| 103 | +# reach the LB endpoint |
| 104 | +curl -v $LB_DNS |
| 105 | +``` |
| 106 | + 4. Delete the Service and verify that the SG is deleted. |
| 107 | + |
| 108 | +## Troubleshooting |
| 109 | + |
| 110 | +- **SG not deleted:** |
| 111 | + - Check for AWS dependency violations (e.g., NLB still deleting). The controller will retry deletion with backoff. |
| 112 | +- **NLB not created:** |
| 113 | + - Ensure the controller has IAM permissions to manage Security Groups. |
| 114 | +- **SG rules not as expected:** |
| 115 | + - Check your Service annotations and cloud config. |
| 116 | +- **Config changes not taking effect:** |
| 117 | + - Ensure you have restarted the controller after changing the config. |
0 commit comments