All Projects → 3scale-ops → aws-nlb-helper-operator

3scale-ops / aws-nlb-helper-operator

Licence: Apache-2.0 license
Simple operator to manage AWS NLB attributes using Kubernetes Service object annotations

Programming Languages

go
31211 projects - #10 most used programming language
Makefile
30231 projects
Dockerfile
14818 projects

Projects that are alternatives of or similar to aws-nlb-helper-operator

horusec-platform
Horusec Platform is a set of web services that integrate with the Horusec CLI to facilitate the visualization and management of found vulnerabilities.
Stars: ✭ 32 (+39.13%)
Mutual labels:  operator, operator-sdk
pulp-operator
Kubernetes Operator for Pulp 3. Under active development.
Stars: ✭ 32 (+39.13%)
Mutual labels:  operator, operator-sdk
k8s-notify
Turn kubernetes events into useful notifications & alerts
Stars: ✭ 46 (+100%)
Mutual labels:  operator, operator-sdk
mysql-operator
A Kubernetes Operator for MySQL Community Server
Stars: ✭ 21 (-8.7%)
Mutual labels:  operator, operator-sdk
opdemo
Kubernetes Operator 快速入门教程(Kubernetes Operator 101)
Stars: ✭ 158 (+586.96%)
Mutual labels:  operator, operator-sdk
Litmus
Litmus helps SREs and developers practice chaos engineering in a Cloud-native way. Chaos experiments are published at the ChaosHub (https://hub.litmuschaos.io). Community notes is at https://hackmd.io/a4Zu_sH4TZGeih-xCimi3Q
Stars: ✭ 2,377 (+10234.78%)
Mutual labels:  operator, operator-sdk
rabbitmq-operator
RabbitMQ Kubernetes operator
Stars: ✭ 16 (-30.43%)
Mutual labels:  operator, operator-sdk
clowder
Operator for operating cloud.redhat.com
Stars: ✭ 21 (-8.7%)
Mutual labels:  operator, operator-sdk
tarantool-operator
Tarantool Operator manages Tarantool Cartridge clusters atop Kubernetes
Stars: ✭ 48 (+108.7%)
Mutual labels:  operator
marin3r
Lightweight, CRD based envoy control plane for kubernetes
Stars: ✭ 51 (+121.74%)
Mutual labels:  operator
s2ioperator
Operator for Source to image
Stars: ✭ 41 (+78.26%)
Mutual labels:  operator
aws-wireguard-linux
WireGuard VPN implemented on Amazon Linux 2 with Load Balancing
Stars: ✭ 93 (+304.35%)
Mutual labels:  nlb
cmak-operator
CMAK (prev. Kafka Manager) for Kubernetes
Stars: ✭ 45 (+95.65%)
Mutual labels:  operator
ts-action-operators
TypeScript action operators for NgRx and redux-observable
Stars: ✭ 34 (+47.83%)
Mutual labels:  operator
terraform-aws-lb-s3-bucket
Terraform module to provision an S3 bucket with built in IAM policy to allow AWS Load Balancers to ship access logs
Stars: ✭ 29 (+26.09%)
Mutual labels:  nlb
falcon-operator
artifacthub.io/packages/olm/falcon-operator/falcon-operator
Stars: ✭ 28 (+21.74%)
Mutual labels:  operator
sieve
Automatic Reliability Testing for Kubernetes Controllers
Stars: ✭ 183 (+695.65%)
Mutual labels:  operator
r6operators
r6operators is a collection of high-quality vectorized Rainbow Six: Siege Operator icons & metadata for Node.js
Stars: ✭ 75 (+226.09%)
Mutual labels:  operator
microcks-ansible-operator
Kubernetes Operator for easy setup and management of Microcks installs
Stars: ✭ 21 (-8.7%)
Mutual labels:  operator
mongodb
MongoDB Operator for Kubernetes
Stars: ✭ 38 (+65.22%)
Mutual labels:  operator

Go Report Card build latest release release license

AWS NLB Helper operator

This operator allows to manage some settings for AWS Network Load Balanacer using Kubernetes annotations in the service objects.

Disclaimer: This operator is in the early development stages.

Motivations

The current ingress controller for AWS Network Load Balanacers doesn't support setting some attributes like enabling the termination protection, the proxy protocol or the stickness. This operator adds support to change those settings by providing some extra annotations to the kubernetes service objects.

Annotations

Setting Annotations Values Default
Load Balancer Termination Protection aws-nlb-helper.3scale.net/loadbalanacer-termination-protection true, false false
Target Group Proxy Protocol aws-nlb-helper.3scale.net/enable-targetgroups-proxy-protocol true, false false
Target Group Stickness aws-nlb-helper.3scale.net/enable-targetgroups-stickness true, false false
Target Group Deregistration Delay aws-nlb-helper.3scale.net/targetgroups-deregisration-delay 0-3600 300

AWS authentication

By default, the operator will use the role provided by the service acccount to connect to the AWS API. The YAMLs for deploying using IAM roles for service accounts are available at deploy/iam-service-account.

Otherwise, if the environment variables AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY are set, the operator will use them to interact with the AWS API. You can find the YAMLs for deploying the resources using the environment access keys at deploy/iam-env-credentials.

OLM installation

At this stage, we use a custom CatalogSource specific for this operator:

apiVersion: operators.coreos.com/v1alpha1
kind: CatalogSource
metadata:
  name: aws-nlb-helper-operator-catalog
  namespace: openshift-marketplace
  # Installed openshift-marketplace to enable multi-namespace support
  # - https://bugzilla.redhat.com/show_bug.cgi?id=1779080
spec:
  sourceType: grpc
  image: quay.io/3scale/aws-nlb-helper-operator-catalog:latest
  displayName: AWS NLB Helper Operator
  updateStrategy:
    registryPoll:
      interval: 30m

And can be installed via Subscription:

apiVersion: v1
kind: List
items:
  - apiVersion: operators.coreos.com/v1alpha2
    kind: OperatorGroup
    metadata:
      name: aws-nlb-helper
      namespace: aws-nlb-helper
    spec:
      targetNamespaces:
        - 3scale-saas
        - aws-nlb-helper
  - apiVersion: operators.coreos.com/v1alpha1
    kind: Subscription
    metadata:
      name: aws-nlb-helper-operator
      namespace: aws-nlb-helper
    spec:
      channel: alpha
      installPlanApproval: Automatic
      name: aws-nlb-helper-operator
      source: aws-nlb-helper-operator-catalog
      sourceNamespace: openshift-marketplace
      config:
        env:
          - name: AWS_ACCESS_KEY_ID
            valueFrom:
              secretKeyRef:
                name: aws-nlb-helper-iam
                key: AWS_ACCESS_KEY_ID
          - name: AWS_SECRET_ACCESS_KEY
            valueFrom:
              secretKeyRef:
                name: aws-nlb-helper-iam
                key: AWS_SECRET_ACCESS_KEY
          - name: AWS_REGION
            valueFrom:
              secretKeyRef:
                name: aws-nlb-helper-iam
                key: AWS_REGION

Requirements

Secret with IAM credentials (when using env based credentials)

kind: Secret
apiVersion: v1
metadata:
  name: aws-nlb-helper-iam
type: Opaque
data:
  AWS_ACCESS_KEY_ID: __AWS_ACCESS_KEY_ID__
  AWS_REGION: __AWS_REGION__
  AWS_SECRET_ACCESS_KEY: __AWS_SECRET_ACCESS_KEY__

The user needs the following permissions:

  • tag:GetResources
  • elasticloadbalancing:DescribeListeners
  • elasticloadbalancing:DescribeLoadBalancers
  • elasticloadbalancing:DescribeTags
  • elasticloadbalancing:DescribeTargetGroupAttributes
  • elasticloadbalancing:DescribeTargetGroups
  • elasticloadbalancing:ModifyTargetGroupAttributes
  • elasticloadbalancing:ModifyLoadBalancerAttributes

If you use Terraform, the following code will create the required user.

data "aws_iam_policy_document" "this" {
  statement {
    actions = [
      "tag:GetResources",
      "elasticloadbalancing:DescribeListeners",
      "elasticloadbalancing:DescribeLoadBalancers",
      "elasticloadbalancing:DescribeTags",
      "elasticloadbalancing:DescribeTargetGroupAttributes",
      "elasticloadbalancing:DescribeTargetGroups",
      "elasticloadbalancing:ModifyTargetGroupAttributes",
      "elasticloadbalancing:ModifyLoadBalancerAttributes"
    ]
    resources = ["*"]
  }
}

resource "aws_iam_user_policy" "this" {
  name   = "aws-nlb-helper-user-policy"
  user   = aws_iam_user.this.name
  policy = data.aws_iam_policy_document.this.json
}

resource "aws_iam_user" "this" {
  name = "aws-nlb-helper"
}

resource "aws_iam_access_key" "this" {
  user = aws_iam_user.this.name
}

Manual Deployment

For manualy deployment, check the available Deployment targets with make help.

...
Deployment
  install          Install CRDs into the K8s cluster specified in ~/.kube/config.
  uninstall        Uninstall CRDs from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
  deploy           Deploy controller to the K8s cluster specified in ~/.kube/config.
  deploy-iam-env   Deploy controller using env IAM variables to the K8s cluster specified in ~/.kube/config.
  undeploy         Undeploy controller from the K8s cluster specified in ~/.kube/config. Call with ignore-not-found=true to ignore resource not found errors during deletion.
...

Deploy manifests can be generated to the ./deploy/ folder using the make generate-deploy-manifests and make generate-deploy-manifests-with-iam-env targets:

...
Generate deployment manifests
  generate-deploy-manifests  Generate the controller manifests to the ./deploy folder.
  generate-deploy-manifests-iam-env  Generate the controller manifests using env IAM variables to the ./deploy folder.
...

Example service

apiVersion: v1
kind: Service
metadata:
  name: test-api
  annotations:
    service.beta.kubernetes.io/aws-load-balancer-type: "nlb"
    aws-nlb-helper.3scale.net/enable-targetgroups-proxy-protocol: "true"
    aws-nlb-helper.3scale.net/enable-targetgroups-stickness: "true"
    aws-nlb-helper.3scale.net/loadbalanacer-termination-protection: "true"
    aws-nlb-helper.3scale.net/targetgroups-deregisration-delay: "450"
spec:
  type: LoadBalancer
  selector:
    deployment: kuard
  ports:
  - name: http
    port: 80
    protocol: TCP
    targetPort: http

Controller logs

When the service is created, the externalName is not yet available (the load balancer is being provisioned), so it try to read the DNS until is available.

{"level":"info","ts":1591461948.7908804,"logger":"controller_service","msg":"Matching annotations found","AnnotationPrefix":"aws-nlb-helper.3scale.net","AnnotationKey":"aws-nlb-helper.3scale.net/enable-targetgroups-proxy-protocol","AnnotationValue":"true"}
{"level":"info","ts":1591461948.7909887,"logger":"controller_service","msg":"Reconciling Service","Namespace":"aws-nlb-helper","Service":"test-api"}
{"level":"info","ts":1591461948.7910357,"logger":"controller_service","msg":"AWS load balancer type set","Namespace":"aws-nlb-helper","Service":"test-api","awsLoadBalancerType":"nlb"}
{"level":"info","ts":1591461948.7910464,"logger":"controller_service","msg":"AWS load balancer DNS not ready.","Namespace":"aws-nlb-helper","Service":"test-api","serviceNameTagValue":"aws-nlb-helper/test-api","loadBalancerNotReadyRetryInterval":30}

Next try after the loadBalancerNotReadyRetryInterval interval, the externalName is still not available.

{"level":"info","ts":1591461948.8010314,"logger":"controller_service","msg":"Matching annotations found","AnnotationPrefix":"aws-nlb-helper.3scale.net","AnnotationKey":"aws-nlb-helper.3scale.net/enable-targetgroups-proxy-protocol","AnnotationValue":"true"}
{"level":"info","ts":1591461948.8010733,"logger":"controller_service","msg":"Reconciling Service","Namespace":"aws-nlb-helper","Service":"test-api"}
{"level":"info","ts":1591461948.801088,"logger":"controller_service","msg":"AWS load balancer type set","Namespace":"aws-nlb-helper","Service":"test-api","awsLoadBalancerType":"nlb"}
{"level":"info","ts":1591461948.8010914,"logger":"controller_service","msg":"AWS load balancer DNS not ready.","Namespace":"aws-nlb-helper","Service":"test-api","serviceNameTagValue":"aws-nlb-helper/test-api","loadBalancerNotReadyRetryInterval":30}

On the third try, the externalName is available. It will be used along the service name to identify the load balancer.

{"level":"info","ts":1591461951.3948922,"logger":"controller_service","msg":"Matching annotations found","AnnotationPrefix":"aws-nlb-helper.3scale.net","AnnotationKey":"aws-nlb-helper.3scale.net/enable-targetgroups-proxy-protocol","AnnotationValue":"true"}
{"level":"info","ts":1591461951.3949463,"logger":"controller_service","msg":"Reconciling Service","Namespace":"aws-nlb-helper","Service":"test-api"}
{"level":"info","ts":1591461951.39497,"logger":"controller_service","msg":"AWS load balancer type set","Namespace":"aws-nlb-helper","Service":"test-api","awsLoadBalancerType":"nlb"}
{"level":"info","ts":1591461951.3949816,"logger":"controller_service","msg":"AWS load balancer type set","Namespace":"aws-nlb-helper","Service":"test-api","awsLoadBalancerDNS":"ac9e5c9af3c404884a410ab59ba57490-f738846f56f647b9.elb.us-east-1.amazonaws.com"}

All the annotations are read, the ones not defined are defaulted to the values defined in the table above.

{"level":"info","ts":1591461951.394987,"logger":"controller_service","msg":"Unable to parse Deregistration Delay value, defaulting.","Namespace":"aws-nlb-helper","Service":"test-api","awsLoadBalancerSettingsDeregistrationDelay":300}

Now the controller looks for the load balancer, first using the tag kubernetes.io/service-name set by the AWS kubernetes controller.

{"level":"info","ts":1591461951.3951344,"logger":"helper_aws","msg":"Looking for tagged resources","LoadBalancerDNS":"ac9e5c9af3c404884a410ab59ba57490-f738846f56f647b9.elb.us-east-1.amazonaws.com","ServiceName":"aws-nlb-helper/test-api","Tags":{"kubernetes.io/service-name":"aws-nlb-helper/test-api"}}

If the previous filter returns at least one load balancer, will look for a load balancer matching the externalName.

{"level":"info","ts":1591461951.7107737,"logger":"helper_aws","msg":"Load balancer matching tags and DNS found","LoadBalancerDNS":"ac9e5c9af3c404884a410ab59ba57490-f738846f56f647b9.elb.us-east-1.amazonaws.com","ServiceName":"aws-nlb-helper/test-api","LoadBalancerARN":"arn:aws:elasticloadbalancing:us-east-1:170744112331:loadbalancer/net/ac9e5c9af3c404884a410ab59ba57490/f738846f56f647b9","LoadBalancerDNS":"ac9e5c9af3c404884a410ab59ba57490-f738846f56f647b9.elb.us-east-1.amazonaws.com"}

If there is a match, it found a load balancer with the kubernetes.io/service-name and externalName.

The first update will change the load balancer resource, enabling or disabling the termination protection.

{"level":"info","ts":1591461951.7357097,"logger":"helper_aws","msg":"Load balancer updated","ModifyLoadBalancerAttributesOutput":{"Attributes":[{"Key":"deletion_protection.enabled","Value":"false"},{"Key":"access_logs.s3.enabled","Value":"false"},{"Key":"load_balancing.cross_zone.enabled","Value":"false"},{"Key":"access_logs.s3.prefix","Value":""},{"Key":"access_logs.s3.bucket","Value":""}]}}

After the load balancer attribute has been updated, will look for the Target Groups attached to the listeners and then update the stickness, proxy-protocol and deregistration delay attributes.

{"level":"info","ts":1591461951.7687242,"logger":"helper_aws","msg":"Updating target group","targetGroupARN":"arn:aws:elasticloadbalancing:us-east-1:170744112331:targetgroup/k8s-awsnlbhe-testapi-b3a8421265/0522c9888807019c"}
{"level":"info","ts":1591461951.7973483,"logger":"helper_aws","msg":"Target groups updated","TargetGroupARN":"arn:aws:elasticloadbalancing:us-east-1:170744112331:targetgroup/k8s-awsnlbhe-testapi-b3a8421265/0522c9888807019c","ModifyLoadBalancerAttributesOutput":{"Attributes":[{"Key":"proxy_protocol_v2.enabled","Value":"true"},{"Key":"stickiness.enabled","Value":"false"},{"Key":"deregistration_delay.timeout_seconds","Value":"300"},{"Key":"stickiness.type","Value":"source_ip"}]}}
{"level":"info","ts":1591461951.7974193,"logger":"controller_service","msg":"Load balancer updated","Namespace":"aws-nlb-helper","Service":"test-api","awsLoadBalancerIngressHostname":"ac9e5c9af3c404884a410ab59ba57490-f738846f56f647b9.elb.us-east-1.amazonaws.com"}

If a service is added or updated, will run again. A part for those kind of events, the reconciliation loop will run again after the reconcileInterval, this way any manual change will be reverted to the state defined in the service.

Contributing

You can contribute by:

  • Raising any issues you find using the operator
  • Fixing issues by opening Pull Requests
  • Submitting a patch or opening a PR
  • Improving documentation
  • Talking about the operator

All bugs, tasks or enhancements are tracked as GitHub issues.

Note that the project description data, including the texts, logos, images, and/or trademarks, for each open source project belongs to its rightful owner. If you wish to add or remove any projects, please contact us at [email protected].