Blog

D4D - Exposing the deployment as a LoadBalancer

Cover Image for D4D - Exposing the deployment as a LoadBalancer
Vicens Fayos

Introduction

To deploy a Deployment as Load Balancer Type in K8S in our EC2 AWS self managed we have to do the following steps:

  • Allow our EC2 instance to manage AWS resource

  • Configure K8S to use AWS Control Manager

  • Install The AWS Control Manager K8S plugin

  • Deploy the app itself

  • Configure AWS Load Balancer

  • Open the service port in the the EC2 instance related Security Group

Add permissions so EC2 can interact with AWS resources

For the AWS CCM to function correctly, your EC2 instance needs permissions to interact with AWS resources.

Create and apply a Trust Policy File

Create a file trust-policy.json

{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "Service": "ec2.amazonaws.com"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}

Run:

aws iam create-role --role-name AdminEC2Role --assume-role-policy-document file://trust-policy.json

Busy with IAM

We want to create a role with admin access and attach it to our instance. So our instance will be admin access to the AWS resources

# Attach permissions (let's be permesive for this exercise)
aws iam attach-role-policy --role-name AdminEC2Role --policy-arn arn:aws:iam::aws:policy/AdministratorAccess

# Create an instance profile
aws iam create-instance-profile --instance-profile-name AdminEC2InstanceProfile

# Add the rols to the instance profile
aws iam add-role-to-instance-profile --instance-profile-name AdminEC2InstanceProfile --role-name AdminEC2Role

# Associate the Instance Profile with the EC2 Instance
aws ec2 associate-iam-instance-profile --instance-id <your_instance_id> --iam-instance-profile Name=AdminEC2InstanceProfile

## Bonus: to check if there is an existing association and remove it

aws ec2 describe-iam-instance-profile-associations --filters "Name=instance-id,Values=<your_instance_id>"

aws ec2 disassociate-iam-instance-profile --association-id association-id-value

Configure K8S accordingly

# restart kubelet
sudo systemctl daemon-reload 
sudo systemctl restart kubelet

# Edit API Server Manifest and add `- --cloud-provider=external` under the commadn section
sudo nano /etc/kubernetes/manifests/kube-apiserver.yaml

# Edit Controller Management Manigest adding also - --cloud-provider=external (and it was something cloud relatedpreviously, remove it)
sudo nano /etc/kubernetes/manifests/kube-controller-manager.yaml

Kubernetes will automatically restart the control plane components since we're editing static pod manifests.

Install AWS Cloud Controller Manager

the easiest way is to follow the official steps from:

https://github.com/kubernetes/cloud-provider-aws/tree/master/charts/aws-cloud-controller-manager

what you will need to do also is to tag your aws EC2 resource so it can be found by AWS CCM.

aws ec2 create-tags --resources i-078efac
c5a0834597 --tags Key=kubernetes.io/cluster/kubernetes-cluster,Value=owned

It's finally all in place. All systems are running? If so, time to deploy the application using a deployment file.

Deploy the app.

here are several ways to deploy an app, we will use a manual one based in deployment and services files.

First the deployment vi hello-world-lb-deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: hello-world-lb
spec:
  replicas: 1
  selector:
    matchLabels:
      app: hello-world-lb
  template:
    metadata:
      labels:
        app: hello-world-lb
    spec:
      containers:
      - name: hello-world-lb
        image: psk8s.azurecr.io/hello-app:1.0
        ports:
        - containerPort: 8080

and the service one vi hello-world-lb-service.yaml

```bash
apiVersion: v1
kind: Service
metadata:
  name: hello-world-lb
spec:
  selector:
    app: hello-world-lb
  ports:
    - protocol: TCP
      port: 80        # External port
      targetPort: 8080 # Container port
  type: LoadBalancer

Nothing new, it could be also created inlined.

Now apply those files:

kubectl apply -f hello-world-lb-deployment.yaml
kubectl apply -f hello-world-lb-service.yaml

run `kubectl get services` . After some minutes the IP should be assigned.

NAME             TYPE           CLUSTER-IP     EXTERNAL-IP   PORT(S)        AGE
hello-world-lb   LoadBalancer   10.0.0.123     <pending>     80:XXXXX/TCP   30s

Configure properly the Load Balancer to the instance(s):

Now if you go to your AWS console you should see a Load Balancer was created (Classical LB)

But unfortunately you will not still able to access your application with the DNS provided.

Still you need to link your instance with the load Balancer.

to do that:

aws elb register-instances-with-load-balancer \
    --load-balancer-name <load_balancer_name> \
    --instances <instance_id> \
    --region eu-west-3

to get the instance ID `aws ec2 describe-instances --region eu-west-3 --query 'Reservations[*].Instances[*].InstanceId' --output text

to get the load balancer name aws elb describe-load-balancers --region eu-west-3

Open the service port in the the EC2 instance

Also you need to open the port the service maps so it is reachable from the Load Balancer.

aws ec2 authorize-security-group-ingress \
    --group-id <security-group-id> \
    --protocol tcp \
    --port <port_to_open> \
    --cidr 0.0.0.0/0 \
    --region <your-region>

Summary

This is all, I hope it helped to clarify how to do a Load Balancer Deployment in K8S.


Más historias

Cover Image for AI And The Future Of Developers

AI And The Future Of Developers

AI will not replace developers but will enable us to become 10x developers.

Vicens Fayos
Cover Image for D4D - Adding a K8s cluster to a EC2 AWS instance

D4D - Adding a K8s cluster to a EC2 AWS instance

Step by Step guide to build a K8s cluster in a EC2 AWS instance

Vicens Fayos