Dec 6, 2022

serverless vs container

Serverless is a development approach where your cloud service provider manages the servers. This replaces the long-running virtual machine with computing power which comes into existence on demand and disappears immediately after use. The most common AWS serverless services are: Compute - Lambda, Fargate; Data Storage - S3, EFS, DynamoDB; Integration - API Gateway, SQS, SNS, EventBridge, and Step Functions.

Pros of serverless

  • Pay for the time when the server is executing the action.
  • Allows the app to be elastic, it can automatically scale up/down.
  • Much less time managing the servers like provisioning infrastructure, managing capacity, patching, monitoring, etc. For example in the case of lambda, you configure memory and storage based on which you pay.
  • Help reduces development time as you focus less on infrastructure and more on business logic. In my opinion, this is one of the key benefits.
  • Fits well with microservices to build loosely-coupled components.
  • You just take care of the code in terms of testing, security, and vulnerability.


Cons of serverless

  • One of the biggest channels is a cold start. A few technics which can help are SnapStart (currently only supported in java runtime), AOT with .net core 7, and Provisioned concurrency (extra cost).
  • Vendor lock-in, the same code will not run in Azure or GPC. Also, you will have to find a way to run it on the local developer machine. Visual Studio template (like serverless.AspNetCoreWebAPI) helps you create a project with both local entry points (for debugging on the dev machine) and a lambda entry point. This also adds a code separation which can be helpful in case you need to use a different cloud provider.
  • The maximum timeout is 15 minutes, so if you have a long-running process, this may be a challenge. Leveraging the step function may be an option to break long-running tasks.
  • You do not have much control over the server which for most cases should be fine, but in the special case where you would want GPU for processing large video or some machine learning processing, this may not be the right choice.
  • For complex apps, you may have to perform a lot of coordination and manage dependencies between all of the serverless functions.
  • Can't scale over the hard limit. You may have to use a different account/region.


Pros of EKS

  • Portability - you can run it anywhere, so cloud agnostic. You can run the same code on the developer's machine using minikube or Kubernetes in Docker Desktop. Easy to replicate the environment.
  • You have better control over the underlying infrastructure. You define the entire container ecosystem and the server they run. You can manage all the resources, set all of the policies, oversee security, and determine how your application is deployed and behaves. You can debug and monitor in a standard way.
  • No timeout restriction.
  • You have greater control to optimize according to instance type/size by defining affinity/tolerance. You can make use of spot instances to control cost. So by optimizing the resources, you can achieve the biggest saving, but definitely, it will be at the cost of DevOps work. 


Cons of EKS

  • Lot more time to build and manage infrastructure work. 
  • You will need to make sure you are keeping up to date with the container base image and any package you are using. If you don't keep up to date with the short-release cycle it can become difficult to maintain the application.
  • You need to manage to scale up and scale down. You can use technologies like Auto scaling (Horizontal pod autoscaling)/Karpenter(node-based autoscaling) can help.
  • Containers are created/destroyed so this adds complexity in terms of monitoring, data storage, etc compared to running applications in VM. You need to account for this during the application design.

As with everything, it all depends on the use case. Here are some of the guidelines which I use. For any new project, my first preference is serverless for apparent reasons. If it's for a long-running application, and I am not willing to re-architect, my preference is a container. If cost is the factor for your decision, you need to consider extra DevOps time needed to devolve/maintain the k8s solution, and for serverless are you designing an application for continuous use (like a web service) or one-off use case (only a few times in a day). If you have a use case for multiple cloud providers, you need to give thought as eks has better portability, but on the other hand, other cloud providers are providing serverless support and if you maintain separation of concern this may not be a challenge.

Sep 23, 2022

k8s Services

A Kubernetes service enables network access to a set of pods. A service listens on a local port (services.spec.ports.port) and forward them to the selector (services.spec.selector) pods at the target port (services.spec.ports.targetPort). Since pods are ephemeral, a service enables a group of pods, which provide specific functions like web service to be assigned a name and unique IP address (clusterIP)

ClusterIP – The service is only accessible from within the Kubernetes cluster.

NodePort – This makes the service accessible on a static port (high port) on each Node in the cluster. Each cluster node opens a port on the node itself and redirects traffic received on that port to the underlying service. 

LoadBalancer – The service becomes accessible externally through a cloud provider's load balancer functionality. If you inspect the load balancer, you will notice that nodes will be instances where the traffic will be redirected at a specific Instance Port, so you should be able to access the application using the node port

Get Instance Port - kubectl get svc <svc name> -o jsonpath="{.spec.ports[0].nodePort}" 

Get Node IP - kubectl get node -o wide

Ingress

Loadbalancer is the default method for many k8s installations in the cloud, but it adds cost and complexity as every service needs to have its own cloud-native load balancer and hence increased the cost. Along with this, you may need to handle SSL for each application, which can be configured at different levels- like application level, load balancer level, etc and also configure firewall rule. This is where an ingress helps. You can consider this as a layer 7 load balancer that is built in a k8s cluster which can be configured as a k8s object using YAML just like any object. Now even with this you still need to expose this to the outside world load balancer (or may be node port), but that's just going to be a single cloud-native load balancer and all the routing will be configured through the ingress controller.

K8s cluster does not come with an ingress controller by default. There is multiple ingress controller available like AWS Load Balancer Controller, GLBC, and Nginx which are currently being supported and maintained by the k8s project. Along with this Isio is also a popular one that provides a lot of service mesh capabilities. An ingress resource is a set of rules and configurations to be applied to the ingress controller. 


Jun 21, 2022

Argo CD

Argo CD is a declarative, GitOps continuous delivery tool for Kubernetes. This is based on the pull mechanism. You can configure  Argo CD using the following steps after which argocd agent pulls manifest changes and applies them

  • Deploy ArgoCd to K8s cluster. Refer this for more details
  • Create a new Application in ArgoCd either through the command-line tool or the UI or using YAML of custom type Application. Here you connect the source repository to the destination k8s server.

In a typical CI/CD pipeline, when you make a code change, the pipeline will test, build, and create the image, push the image to the hub, and update the manifest file (like update deployment with a new image tag). At this stage, the CD will apply the new manifest to the k8s cluster using tools like kubectl or helm on the cd runner. For CD to work, it need to have access to the k8s and also to the cloud, like AWS. This may have a security concerns as you need to give cluster credentials to an external tool. This can even get more complicated if you have multiple applications from different repositories being deployed to different k8s. Also once you apply the manifest, you do not have direct visibility of the status of the configuration change. These are some of the challenges that gitops tools like Argo CD address as the CD is part of k8s cluster.  Here are some of the benefits of using gitops tool like like Argo CD
  • Source Repository is a single source of truth. Even if someone makes manual changes, Argo CD will detect the actual state (in k8s cluster) to be different than the desired state (application config git repo). You can always disable this by setting it to manual. 
  • Rollback is just a matter of reverting code in the repository.
  • Disaster recovery is easy as you can apply this to any destination. 
  • No cluster credential outside of k8s.
  • This is an extension to k8s API as it uses Kubernetes resources itself like etcd to store data, controller for monitoring/controlling actual state to the desired state. It can be configured using YAML as a custom resource.


It's a good idea to have a separate repo for application code and application config (manifest files). This way you can make configuration changes like updates to config maps without involving the application pipeline. In this case, your application pipeline should perform the following - test, build and push the image and then update the manifest file in the configuration repository after which Argo CD will find that the source and destination are not in sync, so it will apply changes from the source. 

At the time of writing, I ran into some challenges while running Argo Cd on eks fargate profile, but no issues with eks node group.