{"id":2088,"date":"2024-05-05T23:23:33","date_gmt":"2024-05-05T23:23:33","guid":{"rendered":"https:\/\/www.aviator.co\/blog\/?p=2088"},"modified":"2025-09-23T12:36:59","modified_gmt":"2025-09-23T12:36:59","slug":"implementing-canary-releases-in-kubernetes-with-istio","status":"publish","type":"post","link":"https:\/\/www.aviator.co\/blog\/implementing-canary-releases-in-kubernetes-with-istio\/","title":{"rendered":"Implementing canary releases in Kubernetes with Istio"},"content":{"rendered":"\n<figure class=\"wp-block-image size-large\"><img fetchpriority=\"high\" decoding=\"async\" width=\"1024\" height=\"574\" src=\"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/service-mes-1024x574.png\" alt=\"\" class=\"wp-image-2089\" srcset=\"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/service-mes-1024x574.png 1024w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/service-mes-300x168.png 300w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/service-mes-768x430.png 768w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/service-mes.png 1456w\" sizes=\"(max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>A canary release is a testing strategy that involves rolling out new versions of applications gradually, so engineers can test new features in production with a limited set of users before making them available to everyone. In the Kubernetes ecosystem, combining <a href=\"https:\/\/istio.io\/v1.14\/\">Istio<\/a> with Kubernetes is a good way to implement canary releases.&nbsp;<\/p>\n\n\n\n<p>This article will guide you through the steps necessary to set up a canary release strategy using Istio on Kubernetes.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Prerequisites<\/h3>\n\n\n\n<p>Before proceeding, ensure that you have the following:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>A&nbsp; Kubernetes cluster that\u2019s up and running.<\/li>\n\n\n\n<li>A Minikube cluster running: <code>minikube start --driver=docker<\/code><\/li>\n\n\n\n<li><code>kubectl<\/code> CLI installed and configured.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Introduction to canary deployment<\/strong><\/h2>\n\n\n\n<p>Named after the &#8220;canary in a coal mine&#8221; concept, canary deployments allow engineers to release a new version of software to a small subset of users or servers before making it available to an entire user base. In this way, the method functions as an early warning system, allowing teams to detect potential problems before those problems can have a huge impact.<\/p>\n\n\n\n<p>One effective way to select a subset of users for a canary deployment is by geographic region. This method is useful for services with a global user base, where certain regions may not get to use the new feature. It makes more sense to deploy to the region that uses the feature.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Introduction to Istio<\/strong><\/h2>\n\n\n\n<p>Istio is an open-source service mesh that provides a way to control how microservices share data with one another. At its core, Istio is designed to handle issues that stem from deploying and managing a microservices architecture, especially at scale.&nbsp;<\/p>\n\n\n\n<p>As applications grow to multiple services across different environments, they often become harder to manage and secure. Istio addresses these challenges by providing a comprehensive suite of tools focused on traffic management, security, and observability.<\/p>\n\n\n\n<p>One of Istio\u2019s core capabilities is traffic management. In this tutorial, we\u2019ll demonstrate controlling the flow of traffic and API calls between services with fine-grained routing rules. We\u2019ll use Istio to divert a small percentage of traffic to the new version of an application while directing the majority to the stable production version.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">How Istio works<\/h3>\n\n\n\n<p>Istio integrates with Kubernetes, but it can also be used with other orchestration platforms. It operates at the platform layer, controlling how different parts of an application interact with one another. The primary components of Istio include:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li><strong>Envoy proxy:<\/strong> Istio uses a proxy called<a href=\"https:\/\/www.envoyproxy.io\/\"> Envoy<\/a> to manage traffic at the network level. Envoy proxies are deployed as<a href=\"https:\/\/learn.microsoft.com\/en-us\/azure\/architecture\/patterns\/sidecar#:~:text=Deploy%20components%20of,to%20a%20motorcycle.\"> sidecars<\/a> to services, meaning that they are run in the same Kubernetes pod as the service. These proxies mediate all inbound and outbound traffic, adding a layer of abstraction and control.<\/li>\n\n\n\n<li><strong>Control plane:<\/strong> The control plane manages and configures proxies to route traffic. It also configures mixers to enforce policies and collect telemetry. The control plane offers a single point of control that can dynamically alter the behavior of the network.<\/li>\n\n\n\n<li><strong>Pilot, Citadel, and Galley:<\/strong> These components serve distinct purposes in the Istio architecture. Pilot translates high-level routing rules that control traffic behavior into configurations that the Envoy proxies can understand. Citadel provides the security capabilities, such as identity and credential management. Galley is responsible for validating, ingesting, aggregating, transforming, and distributing config within Istio.<\/li>\n<\/ul>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Installing Istio on your cluster<\/strong><\/h2>\n\n\n\n<p>First, you need to download the latest version of Istio. You can find the latest release on the<a href=\"https:\/\/github.com\/istio\/istio\/releases\"> Istio releases page<\/a>. Download and extract the Istio release package using curl, and set the istioctl command-line utility in your PATH with the following commands:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>&gt; curl -L https:\/\/istio.io\/downloadIstio | sh -\n&gt; cd istio-*\n&gt; export PATH=$PWD\/bin:$PATH<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Deploy Istio on your cluster<\/h3>\n\n\n\n<p>Now that it\u2019s installed, you can use <code>istioctl<\/code> to deploy Istio on your Kubernetes cluster. The following command installs the default version of Istio, which is suitable for most use cases:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>istioctl install --set profile=default -y<\/code><\/pre>\n\n\n\n<p>This command installs Istio&#8217;s control plane components in the istio-system namespace and configures the necessary CRDs and permissions.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Enable automatic sidecar injection<\/h3>\n\n\n\n<p>Istio\u2019s automatic sidecar injection allows your Kubernetes deployment to automatically inject Envoy containers into your application pods. To enable automatic sidecar injection for a specific namespace, you must label that namespace with <code>istio-injection=enabled<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl label namespace default istio-injection=enabled<\/code><\/pre>\n\n\n\n<p>This command labels your namespace, instructing Istio to automatically inject Envoy sidecar proxies into pods deployed in this namespace.<\/p>\n\n\n\n<p>Check Istio&#8217;s control plane components:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods -n istio-system<\/code><\/pre>\n\n\n\n<p>You should see Istio\u2019s control plane components running in the istio-system namespace.<\/p>\n\n\n\n<p>Verify that the namespace is labeled for automatic sidecar injection:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get namespace -L istio-injection<\/code><\/pre>\n\n\n\n<p>Ensure that your namespace is listed and has <code>istio-injection=enabled<\/code>.<\/p>\n\n\n\n<p>With Istio installed, you&#8217;re now ready to implement canary releases.&nbsp;&nbsp;<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Deploy your application<\/strong><\/h2>\n\n\n\n<p>Start by deploying the initial version (v1) of your application. Create a Kubernetes deployment and a service that routes traffic to your application. Two versions of a<a href=\"https:\/\/github.com\/khabdrick\/canary-istio\/blob\/main\/main.py\"> Python application<\/a> are deployed on<a href=\"https:\/\/hub.docker.com\/r\/khabdrick\/quotes\/tags\"> Docker Hub<\/a>, so we\u2019ll use that throughout this tutorial.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: v1\nkind: Service\nmetadata:\n  name: myapp\nspec:\n  ports:\n  - port: 8000\n    name: http\n  selector:\n    app: myapp\n---\napiVersion: v1\nkind: ServiceAccount\nmetadata:\n  name: myapp-account\n  labels:\n    account: myapp\n---\napiVersion: apps\/v1\nkind: Deployment\nmetadata:\n  name: myapp-v1\nspec:\n  replicas: 1\n  selector:\n    matchLabels:\n      app: myapp\n      version: v1\n  template:\n    metadata:\n      labels:\n        app: myapp\n        version: v1\n    spec:\n      serviceAccountName: myapp-account\n      containers:\n      - name: myapp\n        image: docker.io\/khabdrick\/quotes:v1\n        resources:\n          requests:\n            cpu: \"100m\"  # Requests 100 milliCPUs\n            memory: \"256Mi\" \n          limits:\n            cpu: \"200m\"  # Limits the CPU usage to 200 milliCPUs\n            memory: \"512Mi\"  \n        ports:\n        - containerPort: 8000\n---<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Configure Istio routing<\/strong><\/h3>\n\n\n\n<p>In this section, we\u2019ll use three main Istio resources: Gateway, DestinationRule, and VirtualService. These resources expose the app and control the traffic routing based on specified rules and criteria.<\/p>\n\n\n\n<p>Create a file with the name <code>istio.yaml<\/code> and paste the following as represented here for each kind.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Gateway<\/h3>\n\n\n\n<p>A Gateway exposes the application so that it can be accessed in the browser.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: networking.istio.io\/v1alpha3\nkind: Gateway\nmetadata:\n&nbsp;&nbsp;name: myapp-gateway\nspec:\n&nbsp;&nbsp;selector:\n&nbsp;&nbsp;&nbsp;&nbsp;istio: ingressgateway # use istio default controller\n&nbsp;&nbsp;servers:\n&nbsp;&nbsp;- port:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number: 8080\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;name: http\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;protocol: HTTP\n&nbsp;&nbsp;&nbsp;&nbsp;hosts:\n&nbsp;&nbsp;&nbsp;&nbsp;- \"*\"<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">VirtualService<\/h3>\n\n\n\n<p>A VirtualService in Istio configures how requests are routed to various service versions. It defines a set of traffic routing rules to apply when a host is addressed. Each routing rule defines matching criteria for the traffic of a specific protocol.<\/p>\n\n\n\n<p>Here&#8217;s the VirtualService configuration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: networking.istio.io\/v1alpha3\nkind: VirtualService\nmetadata:\n&nbsp;&nbsp;name: myapp-vs\nspec:\n&nbsp;&nbsp;hosts:\n&nbsp;&nbsp;- \"*\"\n&nbsp;&nbsp;gateways:\n&nbsp;&nbsp;- myapp-gateway\n&nbsp;&nbsp;http:\n&nbsp;&nbsp;- match:\n&nbsp;&nbsp;&nbsp;&nbsp;- uri:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exact: \/themes\/\n&nbsp;&nbsp;&nbsp;&nbsp;- uri:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;prefix: \/quote\/\n&nbsp;&nbsp;&nbsp;&nbsp;- uri:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;exact: \/home\/\n&nbsp;&nbsp;&nbsp;&nbsp;route:\n&nbsp;&nbsp;&nbsp;&nbsp;- destination:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host: myapp # must match the Service we created earlier\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subset: v1\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number: 8000\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;weight: 90&nbsp; # Decrease as v2 proves stable\n&nbsp;&nbsp;&nbsp;&nbsp;- destination:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;host: myapp # must match the Service we created earlier\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;subset: v2\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;port:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;number: 8000\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;weight: 10&nbsp; # Increase as v2 proves stable<\/code><\/pre>\n\n\n\n<p>This configuration routes 90% of the traffic to version 1 (v1) and 10% to version 2 (v2).<\/p>\n\n\n\n<p><code>match.uri<\/code> is used to list the routes to match what we have in the application.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" width=\"1277\" height=\"440\" src=\"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image.png\" alt=\"\" class=\"wp-image-2092\" srcset=\"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image.png 1277w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-300x103.png 300w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-1024x353.png 1024w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-768x265.png 768w\" sizes=\"(max-width: 1277px) 100vw, 1277px\" \/><\/figure>\n\n\n\n<h3 class=\"wp-block-heading\">DestinationRule<\/h3>\n\n\n\n<p>A DestinationRule in Istio defines policies that apply to traffic intended for a service after routing has occurred. Version-specific policies are specified by defining a named subset and overriding the settings specified at the service level. Here, we define subsets corresponding to different versions of the service. This allows Istio to distinguish between different sets of pods (versions of your application).<\/p>\n\n\n\n<p>Here&#8217;s the DestinationRule configuration:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: networking.istio.io\/v1alpha3\nkind: DestinationRule\nmetadata:\n&nbsp;&nbsp;name: myapp-destination\nspec:\n&nbsp;&nbsp;host: myapp\n&nbsp;&nbsp;subsets:\n&nbsp;&nbsp;- name: v1\n&nbsp;&nbsp;&nbsp;&nbsp;labels:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version: v1\n&nbsp;&nbsp;- name: v2\n&nbsp;&nbsp;&nbsp;&nbsp;labels:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version: v2<\/code><\/pre>\n\n\n\n<p>Apply the manifest file:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f istio.yaml<\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\"><strong>Deploy the new version of your application<\/strong><\/h3>\n\n\n\n<p>Deploying the second version (v2) of your application is similar to deploying the first version, but with the version label and container image tag updated to v2. You don\u2019t have to worry about the service because v2 will still utilize the already created service:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>apiVersion: apps\/v1\nkind: Deployment\n\nmetadata:\n&nbsp;&nbsp;name: myapp-v2\n\nspec:\n&nbsp;&nbsp;replicas: 1\n&nbsp;&nbsp;selector:\n&nbsp;&nbsp;&nbsp;&nbsp;matchLabels:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app: myapp\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version: v2\n&nbsp;&nbsp;template:\n&nbsp;&nbsp;&nbsp;&nbsp;metadata:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;labels:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;app: myapp\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;version: v2\n&nbsp;&nbsp;&nbsp;&nbsp;spec:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;containers:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;- name: myapp\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;image: docker.io\/khabdrick\/quotes:v2\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;resources:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;requests:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cpu: \"100m\"&nbsp; # Requests 100 milliCPUs\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memory: \"256Mi\"&nbsp;&nbsp;\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;limits:\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cpu: \"200m\"&nbsp; # Limits the CPU usage to 200 milliCPUs\n&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memory: \"512Mi\"<\/code><\/pre>\n\n\n\n<p>Apply this configuration.<br>Now you can access your application by running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>minikube tunnel<\/code><\/pre>\n\n\n\n<p>You will now be able to access your application at <strong>http:\/\/localhost\/home\/<\/strong>. If you refresh the page rapidly, you will notice that v1 shows up more than v2.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Add autoscaling to deployment&nbsp;<\/strong><\/h2>\n\n\n\n<p>To test how much of the traffic reaches each version, we\u2019ll use<a href=\"https:\/\/github.com\/kubernetes\/autoscaler\"> Kubernetes autoscaler<\/a>. This will handle the replica ratios, creating or deleting pods when necessary. This helps ensure that your application can handle variable loads without manual intervention, maintaining performance while avoiding over-provisioning resources.<\/p>\n\n\n\n<p><a href=\"https:\/\/github.com\/kubernetes-sigs\/metrics-server\">Metrics Server<\/a> is responsible for aggregating resource usage data in Kubernetes and needs to be installed for the autoscaling to work properly.<\/p>\n\n\n\n<p>If Metrics Server is not installed, you can install it using kubectl:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f <a href=\"https:\/\/github.com\/kubernetes-sigs\/metrics-server\/releases\/latest\/download\/components.yaml\">https:\/\/github.com\/kubernetes-sigs\/metrics-server\/releases\/latest\/download\/components.yaml<\/a><\/code><\/pre>\n\n\n\n<p>After installation, verify that Metrics Server is running:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get deployment metrics-server -n kube-system\nkubectl get pods -n kube-system | grep metrics-server<\/code><\/pre>\n\n\n\n<p>Now run the kubectl autoscale commands:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl autoscale deployment myapp-v1 --cpu-percent=50 --min=1 --max=6\nkubectl autoscale deployment myapp-v2 --cpu-percent=50 --min=1 --max=6<\/code><\/pre>\n\n\n\n<p>&nbsp;The commands above tell Kubernetes to manage the scaling of the myapp-v1 and myapp-v1 deployments automatically, adjusting the number of pods between 1 and 6 to achieve an average CPU utilization of 50% for each deployment.<\/p>\n\n\n\n<p>To test, we\u2019ll need to create conditions that increase the CPU usage of the pods in your deployment. This can be done in several ways, depending on the nature of your application. For this example, we\u2019ll use<a href=\"https:\/\/github.com\/khabdrick\/canary-istio\/blob\/main\/load.py\"> a Python script<\/a> to simulate some load on the application.<\/p>\n\n\n\n<p>After implementing the load, the number of pods has increased.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl get pods | grep myapp<\/code><\/pre>\n\n\n\n<p>You may notice that only one pod is running v2 of the application, and v1 maxes out to six pods. This verifies that our 90:10 weight works.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Monitor and Adjust Traffic Split<\/strong><\/h2>\n\n\n\n<p>Monitoring is a significant aspect of canary releases, as it provides insights into the performance and health of the new version of the application under real-world conditions.<\/p>\n\n\n\n<p>To monitor the application&#8217;s performance,we\u2019ll use<a href=\"https:\/\/istio.io\/latest\/docs\/tasks\/observability\/metrics\/\"> Istio&#8217;s built-in telemetry<\/a> features: Prometheus for monitoring and Grafana for visualization. Monitoring these metrics allows you to understand the impact of new versions on your system&#8217;s performance and user experience.<\/p>\n\n\n\n<p>If version 2 of your application demonstrates stable performance and positive feedback, you should gradually shift the traffic weights in the VirtualService to favor version 2. This can be done incrementally \u2014 for example, incrementally shifting 20% more traffic to version 2 and monitoring the outcomes. You can use a tool to automate this process, but in this tutorial we\u2019ll do it manually.<\/p>\n\n\n\n<h3 class=\"wp-block-heading\">Install Prometheus and Grafana<\/h3>\n\n\n\n<p>Istio has add-on manifests to deploy these tools. You can apply them to your cluster by running the following command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl apply -f https:\/\/raw.githubusercontent.com\/istio\/istio\/release-1.11\/samples\/addons\/prometheus.yaml\n\nkubectl apply -f <a href=\"https:\/\/raw.githubusercontent.com\/istio\/istio\/release-1.11\/samples\/addons\/grafana.yaml\">https:\/\/raw.githubusercontent.com\/istio\/istio\/release-1.11\/samples\/addons\/grafana.yaml<\/a><\/code><\/pre>\n\n\n\n<h3 class=\"wp-block-heading\">Access Grafana<\/h3>\n\n\n\n<p>Once Grafana is installed, you can access it through the Kubernetes API:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>kubectl -n istio-system port-forward svc\/grafana 3000:3000<\/code><\/pre>\n\n\n\n<p>Now you can simulate some load by running the<a href=\"https:\/\/github.com\/khabdrick\/canary-istio\/blob\/main\/load.py\"> Python script<\/a>.<\/p>\n\n\n\n<p>Access Grafana by navigating to <strong>http:\/\/localhost:3000<\/strong>, and then navigate to the <strong>mesh dashboard<\/strong>, and you can confirm the success rate or any metric you are interested in. If everything is going well, you can go ahead and increase the load percentage going to v2.\u00a0<\/p>\n\n\n\n<figure class=\"wp-block-image\"><img decoding=\"async\" width=\"1600\" height=\"792\" src=\"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-1.png\" alt=\"\" class=\"wp-image-2093\" srcset=\"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-1.png 1600w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-1-300x149.png 300w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-1-1024x507.png 1024w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-1-768x380.png 768w, https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/image-1-1536x760.png 1536w\" sizes=\"(max-width: 1600px) 100vw, 1600px\" \/><\/figure>\n\n\n\n<p>You could also take a look at the Istio Service Dashboard by navigating to the left-hand corner of Grafana dashboard\u2019s navigation menu or by visiting <strong>http:\/\/localhost:3000\/d\/LJ_uJAvmk\/istio-service-dashboard<\/strong> in your web browser.\u00a0<\/p>\n\n\n\n<p>These metrics will help you make informed decisions about traffic routing.&nbsp;<\/p>\n\n\n\n<p>If the new version is performing well, you might want to increase its traffic share by updating the <code>VirtualService<\/code> weights to gradually shift more traffic to the new version and applying your changes<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>\nspec:\n  ...\n    route:\n    - destination:\n        host: myapp\n        subset: v1\n        port:\n          number: 8000\n      weight: 70  # Adjusted from 90 to 70\n    - destination:\n        host: myapp\n        subset: v2\n        port:\n          number: 8000\n      weight: 30   # Adjusted from 10 to 30<\/code><\/pre>\n\n\n\n<p>Continue adjusting these weights until version 2 is handling 100% of the traffic. Be cautious and proceed in a manner that minimizes risk, based on your observations and metrics.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><strong>Conclusion<\/strong><\/h2>\n\n\n\n<p>Implementing canary releases with Istio and Kubernetes allows you to minimize the risk of introducing new software versions in production. By carefully adjusting traffic between different versions based on real-world performance and feedback, you can ensure a smooth experience for your users. This approach not only improves reliability, but also allows for more aggressive innovation cycles.<\/p>\n\n\n\n<p>You can access the code used in this tutorial on<a href=\"https:\/\/github.com\/khabdrick\/canary-istio\"> GitHub<\/a>.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><a href=\"https:\/\/www.aviator.co\/releases\"><img decoding=\"async\" src=\"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/08\/blog-cta-9Release_CTA.svg\" alt=\"aviator releases\" class=\"wp-image-2489\"\/><\/a><\/figure>\n","protected":false},"excerpt":{"rendered":"<p>This article will guide you through the steps necessary to set up a canary release strategy using Istio on Kubernetes to support gradual rollouts.<\/p>\n","protected":false},"author":23,"featured_media":2089,"comment_status":"closed","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"inline_featured_image":false,"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[58],"tags":[97],"class_list":["post-2088","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-ci-cd-deployment"],"blocksy_meta":[],"acf":[],"aioseo_notices":[],"jetpack_featured_media_url":"https:\/\/www.aviator.co\/blog\/wp-content\/uploads\/2024\/05\/service-mes.png","post_mailing_queue_ids":[],"_links":{"self":[{"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/posts\/2088","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/users\/23"}],"replies":[{"embeddable":true,"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/comments?post=2088"}],"version-history":[{"count":6,"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/posts\/2088\/revisions"}],"predecessor-version":[{"id":3666,"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/posts\/2088\/revisions\/3666"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/media\/2089"}],"wp:attachment":[{"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/media?parent=2088"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/categories?post=2088"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.aviator.co\/blog\/wp-json\/wp\/v2\/tags?post=2088"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}