5 Essential Kubernetes Deployment Strategies for Optimal Performance
The 5 Main Kubernetes Deployment Strategies
Rolling Update
Blue/Green Deployment
Canary Deployment
A/B Testing
Shadow Deployment
Choosing the Right Strategy
5 Essential Kubernetes Deployment Strategies for Optimal Performance
Kubernetes is entirely designed for large-scale deployments, allowing engineers to orchestrate containerized applications across clusters of machines, automatically handling the management, scaling, and operations of these deployments.
Deployment strategies in Kubernetes encompass the methods and practices used to update applications running in a Kubernetes environment. These strategies play a crucial role in application lifecycle management, directly influencing application availability, service continuity, and the capacity to adapt to new requirements.
Deciding on the correct deployment strategy for your use case isn’t trivial. Deployment strategies need to be tailored to specific scenarios and requirements. Each strategy offers unique benefits and challenges, from ensuring zero downtime to prioritizing data and testing. Understanding these nuances aids in selecting the most appropriate approach for different deployment scenarios.
Here, we will take you through the five main Kubernetes deployment strategies you might need to use, how to make the decision, and how to deploy using each of these strategies.
The 5 Main Kubernetes Deployment Strategies
All Kubernetes deployment strategies have unique characteristics and fits for different scenarios. The decision on which strategy to employ depends on various factors, including the application's nature, updates' criticality, user tolerance for disruptions, and organizational capacity for handling potential rollback scenarios.
Here are the five core Kubernetes deployment strategies:
- Rolling update. A rolling update is the default deployment strategy for Kubernetes. This strategy ensures that the application remains available during the update. It allows for gradual exposure to traffic to the new version, reducing the risk of significant failures. This is a suitable strategy for general updates where immediate rollback is not a primary concern and minimal impact on availability is crucial.
- Blue/Green deployment. This method involves running two identical environments, a new version (green) alongside the old version (blue), and only one serves live production traffic at any time. After deploying the latest version to the idle environment, traffic is switched over if the new version is stable. This deployment strategy facilitates testing the latest version in a production-like environment and allows for immediate rollback by switching traffic back. It works well with a CI/CD pipeline and is ideal for critical applications where the risk of downtime or failure must be minimized, and rapid rollback is necessary.
- Canary releases. In canary deployments, the new version is rolled out to a small subset of users before being rolled out to the entire user base. Based on feedback and performance, it is either gradually rolled out to the rest or rolled back. This approach limits the impact of any new bugs and allows for real-world testing on a small scale before broad deployment. It is helpful for applications where user feedback or real-world performance data is crucial for validation.
- A/B testing. A/B testing involves routing a subset of user traffic to a new version of the application to test new features or changes, typically driven by user behavior or other criteria. A/B testing allows for comparative analysis between different versions based on specific user segments' responses. It is an effective strategy for testing feature variations and user experience enhancements where user behavior influences decisions.
- Shadow deployment. In this strategy, the new version of the application runs alongside the old version but does not serve real user traffic. Instead, real-world requests are mirrored to the new version for testing purposes. This strategy enables validation of the new version under real-world load without exposing users to changes. It is suitable for performance testing under actual load conditions and validating changes without impacting users.
What makes all of this possible easily with Kubernetes is the Kubernetes Deployment Controller. The primary objective of a deployment controller is to maintain the desired state of an application as defined by the user. It ensures that a specified number of pod replicas are running at any given time, automating the deployment and scaling of applications and their underlying infrastructure. Let’s look more closely at each of these Kubernetes deployment stratgies and how to deploy an application using them.
Rolling Update
Rolling updates are the default strategy for deployments in Kubernetes. This process allows you to update your application in Kubernetes with minimal downtime, as it ensures that some instances of your application are always running during the update process.
Setting up a rolling update in Kubernetes involves configuring your deployment to update Pods in a rolling manner, replacing existing Pods with new ones incrementally.
Let’s say we’re initially using this simple deployment:
apiVersion: apps/v1kind: Deploymentmetadata:name: example-deploymentspec:replicas: 3selector:matchLabels:app: exampletemplate:metadata:labels:app: examplespec:containers:- name: nginximage: nginx:1.16
We create the deployment using:
kubectl apply -f deployment.yaml
Then, we can check the status of this current deployment:
kubectl get deployment example-deployment
To perform a rolling update, you only need to change the container image or other specifications. For example, update the image version in your deployment YAML:
spec:...containers:- name: nginximage: nginx:1.17 # Update the image version
Then apply the update using:
kubectl apply -f deployment.yaml
Kubernetes will start the rolling update process. It will incrementally terminate existing Pods and replace them with new Pods. You can monitor the rollout status:
kubectl rollout status deployment/example-deploymen
Once the update is complete, verify the new version is running:
kubectl get pods -l app=example
If something goes wrong, you can rollback to the newer version:
kubectl rollout undo deployment/example-deployment
Given that we are just updating the image used for our application, we can also use kubectl set image to make the update
kubectl set image deployment/[DEPLOYMENT_NAME] [CONTAINER_NAME]=[NEW_IMAGE]:[TAG]
You can define the update strategy and parameters (like max surge and max unavailable) in the deployment YAML under spec.strategy. Having readiness and liveness probes in your containers is good practice to ensure smooth rolling updates.
Blue/Green Deployment
Setting up a blue/green deployment in Kubernetes involves deploying two separate but identical environments: one (Blue) is the current production environment, and the other (Green) is the new version of your application. Traffic is switched from Blue to Green once the newer version is ready. This setup ensures minimal downtime and allows easy rollback in case of issues.
First, you need to deploy the current version of your application (Blue). Create a deployment YAML file (blue-deployment.yaml) for your application:
apiVersion: apps/v1kind: Deploymentmetadata:name: blue-appspec:replicas: 3selector:matchLabels:app: my-appversion: bluetemplate:metadata:labels:app: my-appversion: bluespec:containers:- name: my-appimage: my-app:1.0 # Use your application's image
Deploy it using:
kubectl apply -f blue-deployment.yaml
Expose the Blue deployment using a Kubernetes service. Create a service YAML file (blue-service.yaml):
apiVersion: v1kind: Servicemetadata:name: my-app-servicespec:selector:app: my-appversion: blueports:- protocol: TCPport: 80targetPort: 8080 # The port your app listens on
Apply it using:
kubectl apply -f blue-service.yaml
Next, deploy the new version of your application (Green). Create a similar deployment YAML file (green-deployment.yaml), but with the latest version of your application:
apiVersion: apps/v1kind: Deploymentmetadata:name: green-appspec:replicas: 3selector:matchLabels:app: my-appversion: greentemplate:metadata:labels:app: my-appversion: greenspec:containers:- name: my-appimage: my-app:2.0 # New version of your application
Deploy it using:
kubectl apply -f green-deployment.yaml
Before exposing the Green deployment to actual users, you should access it internally for testing purposes. To do this, you can use Kubernetes port forwarding to access the Green deployment from your local machine:
kubectl port-forward deployment/green-app 8080:80
This command forwards the local port 8080 to port 80 on the Green deployment, allowing you to access it via localhost:8080. Then, create an internal service (ClusterIP) that exposes the Green deployment only within the cluster:
apiVersion: v1kind: Servicemetadata:name: green-app-internalspec:selector:app: my-appversion: greenports:- protocol: TCPport: 80targetPort: 8080
You can then run your suite of automated tests against the Green deployment by configuring your test suite to target the Green deployment's access point. These could be unit tests, integration tests, or end-to-end tests, depending on your application.
Once confident with the Green deployment, update the service to redirect traffic from Blue to Green. Modify the blue-service.yaml file to point to the Green deployment:
spec:selector:app: my-appversion: green
Apply the changes using:
kubectl apply -f blue-service.yam
After switching, monitor the Green deployment closely to ensure everything is running smoothly. If the Green deployment is stable, you can then move your api development to the Blue deployment. You then work on Blue until that version is ready to be deployed and reverse the above process. You switch between Blue and Green, always using one for production and one for development.
Out of all Kubernetes deployment strategies, Blue/Green deployments typically involve the most manual intervention, especially in switching the service selector from Blue to Green. It's essential to have good monitoring and logging in place to quickly detect any issues after the switch. You might consider automating the switch and cleanup process as part of your CI/CD pipeline.
Canary Deployment
Setting up a canary deployment (sometimes called progressive delivery) in Kubernetes involves deploying a new version of your application to a small subset of users before rolling it out to everyone. This approach allows you to test the newer version in a production environment with minimal risk.
First, you need your primary or stable deployment, which serves the majority of the traffic. Create a deployment YAML file (primary-deployment.yaml):
apiVersion: apps/v1kind: Deploymentmetadata:name: primary-appspec:replicas: 3selector:matchLabels:app: my-apptrack: stabletemplate:metadata:labels:app: my-apptrack: stablespec:containers:- name: my-appimage: my-app:1.0 # Replace with your current application version
Deploy it using:
kubectl apply -f primary-deployment.yaml
Create a service that targets the stable deployment. Here's an example service definition (primary-service.yaml):
apiVersion: v1kind: Servicemetadata:name: my-app-servicespec:selector:app: my-apptrack: stableports:- protocol: TCPport: 80targetPort: 8080 # Replace with the port your app listens on
Apply the service using:
kubectl apply -f primary-service.yaml
Now, deploy the canary version of your application. Create a similar deployment (canary-deployment.yaml), but with the new version of your application and fewer replicas:
apiVersion: apps/v1kind: Deploymentmetadata:name: canary-appspec:replicas: 1 # Less than the primary to limit exposureselector:matchLabels:app: my-apptrack: canarytemplate:metadata:labels:app: my-apptrack: canaryspec:containers:- name: my-appimage: my-app:2.0 # Replace with your new application version
Deploy the canary version using:
kubectl apply -f canary-deployment.yaml
To split traffic between your primary and canary deployments, you can use a service mesh like Istio or Kubernetes Ingress if it supports advanced traffic routing rules. Here's a simplified example using Kubernetes Ingress:
apiVersion: networking.k8s.io/v1kind: Ingressmetadata:name: my-app-ingressspec:rules:- http:paths:- path: /my-apppathType: Prefixbackend:service:name: my-app-serviceport:number: 80# Additional rules to route a percentage of traffic to the canary service
Canary deployments in Kubernetes might require additional tools or service mesh capabilities to manage and route traffic effectively. Edge Stack allows you to easily deploy canary releases, using a weighted round-robin scheme to route traffic between multiple services. Here’s an example:
---apiVersion: getambassador.io/v3alpha1kind: Mappingmetadata:name: quote-backendspec:prefix: /backend/service: quote---apiVersion: getambassador.io/v3alpha1kind: Mappingmetadata:name: quote-backend2spec:prefix: /backend/service: quotev2weight: 10
This would push 10% of the traffic to the quotev2 service.
Closely monitor the canary deployment for any issues. Look at logs, metrics, and user feedback.
Based on the monitoring feedback, either gradually increase the traffic to the canary deployment or roll back if issues are detected. To rollback, simply reduce or remove the replicas in the canary deployment and route the traffic back to the primary deployment.
A/B Testing
Setting up an A/B testing deployment in Kubernetes requires complex routing rules, often achieved with a service mesh like Istio or advanced Ingress capabilities. The goal is to serve different versions of your application state to different user segments based on specific criteria (e.g., user type, location, etc.).
First, you must deploy both versions (A and B) of your application. Create separate deployment YAML files for each:
Version A (deployment-a.yaml):
apiVersion: apps/v1kind: Deploymentmetadata:name: app-version-aspec:replicas: 2selector:matchLabels:app: my-appversion: Atemplate:metadata:labels:app: my-appversion: Aspec:containers:- name: my-appimage: my-app:A # Replace with your Version A image
Version B (deployment-b.yaml):
apiVersion: apps/v1kind: Deploymentmetadata:name: app-version-bspec:replicas: 2selector:matchLabels:app: my-appversion: Btemplate:metadata:labels:app: my-appversion: Bspec:containers:- name: my-appimage: my-app:B # Replace with your Version B image
Deploy both versions using:
kubectl apply -f deployment-a.yamlkubectl apply -f deployment-b.yaml
Then create Kubernetes services for each deployment. Service for Version A (service-a.yaml):
apiVersion: v1kind: Servicemetadata:name: service-aspec:selector:app: my-appversion: Aports:- protocol: TCPport: 80targetPort: 8080 # Your app's port
Service for Version B (service-b.yaml):
apiVersion: v1kind: Servicemetadata:name: service-bspec:selector:app: my-appversion: Bports:- protocol: TCPport: 80targetPort: 8080 # Your app's port
Deploy the services using:
kubectl apply -f service-a.yaml
kubectl apply -f service-b.yaml
Using Istio or a capable Ingress controller, configure routing rules to distribute traffic between the two versions based on your A/B testing criteria. Here’s a simplified example using Istio:
Istio Virtual Service (virtual-service.yaml):
apiVersion: networking.istio.io/v1alpha3kind: VirtualServicemetadata:name: my-appspec:hosts:- my-apphttp:- match:- headers:user-type:exact: "A"route:- destination:host: service-a- route:- destination:host: service-b
This allows for routing traffic for users with a user-type header of "A" to Version A, and all others to Version B. Apply the virtual service using:
kubectl apply -f virtual-service.yaml
Monitor both versions of your application. Analyze metrics, user feedback, and other relevant data to determine the performance of each version. After your A/B test concludes, clean up by scaling down or removing the less successful version and updating the routing rules accordingly.
The specifics of how you configure A/B testing may vary based on your service mesh or Ingress controller's capabilities. Proper monitoring and analytics are crucial to gather meaningful insights from your A/B test. Ensure that your application versions are instrumented to track the necessary metrics for your test.
Shadow Deployment
The final Kubernetes deployment strategy we’re highlighting is shadow deployment. Setting up a shadow deployment in Kubernetes involves deploying a new version of your application (the "shadow") alongside the existing version. The shadow version receives a copy of the live traffic but does not impact the actual user experience. This setup allows you to test traffic to the new version under real-world conditions without exposing users to potential issues.
Shadow deployments can be complex but achieved easily in Edge Stack by defining appropriate mappings in your YAML configuration files. Here's how you can put together these mapping YAML files for shadow deployments
First, define the mapping for your primary service. This is the service currently handling your production traffic (primary-service.yaml):
apiVersion: getambassador.io/v3alpha1kind: Mappingmetadata:name: primary-service-mappingspec:prefix: /service/service: primary-service
In this example, traffic going to /service/ is routed to a service named primary-service. Next, define the mapping for your shadow service. This service will receive a copy of the live traffic (shadow-service.yaml):
apiVersion: getambassador.io/v3alpha1kind: Mappingmetadata:name: shadow-service-mappingspec:prefix: /service/service: shadow-serviceshadow: true
Here, we specify the same prefix as the primary service, but set shadow: true to indicate that this is a shadow mapping. Traffic to /service/ will also be mirrored to shadow-service. Apply these mappings to your Kubernetes cluster using kubectl:
kubectl apply -f primary-service.yaml
kubectl apply -f shadow-service.yaml
Ensure that Edge Stack API Gateway is running in your cluster and is configured to handle traffic for your services. Since the shadow service receives a copy of the live traffic, monitoring it closely for testing is crucial. Ensure it doesn't impact your live environment, especially in terms of data integrity and system performance.
Shadow deployments are useful for testing in production-like test environment without affecting the actual user experience. Be cautious with shadow services that interact with databases or external systems, as they might cause unintended side effects. Shadow deployments can generate significant load since they process real traffic in parallel with the primary application. Ensure your infrastructure can handle this additional load.
Using shadow deployments with Edge Stack API Gateway, you can test new features or changes under real-world conditions.
Choosing the Right Strategy
Selecting an appropriate Kubernetes deployment strategy involves several key considerations. This decision impacts not only the immediate deployment process but also the ongoing maintenance and scalability of the application.
- Application criticality. Evaluate the importance of the application in the business context. High-impact applications may require strategies like blue/green deployments for minimal downtime. Consider the tolerance for downtime. Some applications can afford brief outages, making strategies like rolling updates feasible.
- Update frequency. For applications requiring frequent updates, choose a strategy that offers speed and efficiency, such as rolling updates or canary releases. In cases where updates are less frequent but significant, strategies like blue/green deployments might be more suitable.
- Risk tolerance: Assess the acceptable level of risk. Canary releases and A/B testing allow for controlled exposure and are suitable for applications where new features might carry higher risks. Blue/green deployments provide a safer option with easy rollback capabilities for applications where stability is paramount.
- Resource availability. Consider the available infrastructure and resources. Some strategies, like blue/green deployments, require double the resources as both versions run simultaneously. Ensure sufficient capacity and budget to support the chosen strategy without affecting other operations.
- Team expertise. The team's familiarity with Kubernetes and its deployment strategies plays a critical role. Complex strategies require skilled personnel for effective implementation. Training and experience levels should align with the complexity of the chosen deployment strategy.
- User impact. Consider the end-user experience. Strategies like A/B testing and canary releases allow for user feedback incorporation and minimal disruption. Ensure the strategy aligns with user expectations and service level agreements (SLAs).
- Compliance and security. Review compliance requirements and security implications. Specific strategies may better align with regulatory and security standards. Assess the impact of each strategy on data integrity and confidentiality.
- Rollback plans. A robust rollback plan is essential. Ensure the chosen strategy allows for swift and effective rollback in case of deployment issues. Test rollback procedures regularly as part of the deployment strategy.
No single strategy fits all scenarios. The decision should stem from thoroughly analyzing the application requirements, organizational context, and operational capabilities. The chosen strategy should align with the broader goals of reliability, scalability, and continuous improvement.
Learn more about Edge Stack API Gateway to understand how it can simplify your Kubernetes deployments. You can also read more about the specific Kubernetes deployment strategies such as canary releases, shadowing, and the use of ingress controllers in our blog and documentation.