<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Romain Vernoux</title>
    <description>The latest articles on DEV Community by Romain Vernoux (@romainvernoux).</description>
    <link>https://dev.to/romainvernoux</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F560592%2F6c5587b0-dbae-41f6-9064-1e7e945927fb.png</url>
      <title>DEV Community: Romain Vernoux</title>
      <link>https://dev.to/romainvernoux</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/romainvernoux"/>
    <language>en</language>
    <item>
      <title>Google Kubernetes Engine, CircleCI and Traefik for a full-fledged GitOps platform in the cloud - Part 2</title>
      <dc:creator>Romain Vernoux</dc:creator>
      <pubDate>Sat, 23 Jan 2021 20:01:33 +0000</pubDate>
      <link>https://dev.to/zenika/google-kubernetes-engine-circleci-and-traefik-for-a-full-fledged-gitops-platform-in-the-cloud-part-2-21ag</link>
      <guid>https://dev.to/zenika/google-kubernetes-engine-circleci-and-traefik-for-a-full-fledged-gitops-platform-in-the-cloud-part-2-21ag</guid>
      <description>&lt;p&gt;This is the second part of "Google Kubernetes Engine, CircleCI and Traefik for a full-fledged GitOps platform in the cloud" ! Part 1 is &lt;a href="https://dev.to/zenika/google-kubernetes-engine-circleci-and-traefik-for-a-full-fledged-gitops-platform-in-the-cloud-part-1-2bai"&gt;accessible here&lt;/a&gt; and mandatory for the following. &lt;/p&gt;

&lt;h2&gt;
  
  
  3. A first "whoami" toy project
&lt;/h2&gt;

&lt;p&gt;In this section, we will illustrate how to use Traefik to expose multiple instances/branches/versions of a same app on subdomains. Suppose we chose to dedicate the &lt;code&gt;whoami&lt;/code&gt; subdomain (e.g., &lt;code&gt;whoami.mywebsite.com&lt;/code&gt;) to this project. Our goal is to expose the master version of the app on a &lt;code&gt;master&lt;/code&gt; subdomain (e.g., &lt;code&gt;master.whoami.mywebsite.com&lt;/code&gt;) and the changes of a &lt;code&gt;feature1&lt;/code&gt; branch on the &lt;code&gt;feature1&lt;/code&gt; subdomain (e.g., &lt;code&gt;feature1.whoami.mywebsite.com&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;For this example, we will use the containous/whoami Docker image as a dummy web application, which only serves some information about the server and the received request for any request on port 80.&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a namespace for the project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace whoami
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Deploy the master version
&lt;/h3&gt;

&lt;p&gt;Fill the following placeholders in the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/whoami-master.yaml"&gt;whoami-master descriptor&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DOMAIN&lt;/code&gt;: the domain you own (e.g., &lt;code&gt;mywebsite.com&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then apply it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f whoami-master.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will instantiate 3 instances of the &lt;code&gt;whoami&lt;/code&gt; Pod, create a Service to load balance between them, and expose this Service through an IngressRoute. Notice the use of the &lt;code&gt;traefik&lt;/code&gt; TLS certificate resolver created in step 2, the request for a &lt;code&gt;*.whoami.[DOMAIN]&lt;/code&gt; wildcard certificate and the use of the &lt;code&gt;master.whoami.[DOMAIN]&lt;/code&gt; Host rule to route traffic to this URL to our Service. In just a few seconds, the certificate is generated and your application server is exposed securely on the &lt;code&gt;master.whoami&lt;/code&gt; of your domain (try it!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy the feature1 branch
&lt;/h3&gt;

&lt;p&gt;Fill the following placeholders in the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/whoami-branch1.yaml"&gt;whoami-branch1 descriptor&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DOMAIN&lt;/code&gt;: the domain you own (e.g., &lt;code&gt;mywebsite.com&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then apply it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f whoami-branch1.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will instantiate 3 new instances of the Pod, create a new Service to load balance between them, and expose this Service through an IngressRoute. Notice again the use of the &lt;code&gt;traefik&lt;/code&gt; TLS certificate resolver created in step 2, the request for a &lt;code&gt;*.whoami.[DOMAIN]&lt;/code&gt; wildcard certificate (which is already managed by Traefik and will be reused) and the use of the &lt;code&gt;branch1.whoami.[DOMAIN]&lt;/code&gt; Host rule to route traffic to this URL to our Service. Your new app instance, distinct from the master environment is already live (try it!).&lt;/p&gt;

&lt;h3&gt;
  
  
  Use a template
&lt;/h3&gt;

&lt;p&gt;Notice the very few differences between the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/whoami-master.yaml"&gt;whoami-master&lt;/a&gt; and the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/whoami-branch1.yaml"&gt;whoami-branch1&lt;/a&gt; descriptors: all occurences of &lt;code&gt;master&lt;/code&gt; have simply be replaced by &lt;code&gt;branch1&lt;/code&gt;. In real world use cases, the Docker image will probably be different too.&lt;/p&gt;

&lt;p&gt;Take a look at the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/whoami-template.yaml"&gt;whoami-template descriptor template&lt;/a&gt; file. Env-like placeholders (e.g., &lt;code&gt;${INSTANCE_NAME}&lt;/code&gt;) are used. We will use the &lt;code&gt;envsubst&lt;/code&gt; tool to instantiate our template.&lt;/p&gt;

&lt;p&gt;Fill the following placeholders in the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/whoami-template.yaml"&gt;whoami-template descriptor template&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DOMAIN&lt;/code&gt;: the domain you own (e.g., &lt;code&gt;mywebsite.com&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Do not touch the env-like placeholders.&lt;/p&gt;

&lt;p&gt;Set the required environement variables, then instantiate the template and apply it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;export INSTANCE_NAME=branch2
export IMAGE=containous/whoami:v1.5.0
envsubst &amp;lt; whoami-template.yaml &amp;gt; whoami-branch2.yaml
kubectl apply -f whoami-branch2.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Quick, your &lt;code&gt;branch2&lt;/code&gt; instance is already up!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;envsubst&lt;/code&gt; approach will get you quite far, but look into &lt;a href="https://github.com/kubernetes-sigs/kustomize"&gt;Kustomize&lt;/a&gt; or &lt;a href="https://helm.sh/"&gt;Helm&lt;/a&gt; if you need a more advanced configuration management tool.&lt;/p&gt;

&lt;h2&gt;
  
  
  4. A "myapp" project with CI/CD
&lt;/h2&gt;

&lt;p&gt;In this section, we will illustrate how the manual deployment described in step 3 can be integrated in about any CI/CD pipeline. Suppose we chose to dedicate the &lt;code&gt;myapp&lt;/code&gt; subdomain (e.g., &lt;code&gt;myapp.mywebsite.com&lt;/code&gt;) to this project. Our goal is to expose any branch X on the X subdomain (e.g., branch &lt;code&gt;feat1&lt;/code&gt; exposed on &lt;code&gt;feat1.myapp.mywebsite.com&lt;/code&gt;, &lt;code&gt;feat2&lt;/code&gt; exposed on &lt;code&gt;feat2.myapp.mywebsite.com&lt;/code&gt;, etc.).&lt;/p&gt;

&lt;p&gt;For this example, we will build our own Docker image in a CircleCI pipeline. For the sake of simplicity, this guide will use the same containous/whoami image, but feel free to build your own for real!&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a namespace for the project
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace myapp
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Create a "myapp" project on GitHub
&lt;/h3&gt;

&lt;p&gt;In the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/sample_project"&gt;sample_project&lt;/a&gt; folder, fill the following placeholders in the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/sample_project/myapp-template.yaml"&gt;myapp-template descriptor&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DOMAIN&lt;/code&gt;: the domain you own (e.g., &lt;code&gt;mywebsite.com&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then push the content of the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/sample_project"&gt;sample_project&lt;/a&gt; folder at the root of your GitHub repository (i.e., the &lt;code&gt;.circleci&lt;/code&gt; folder, the &lt;code&gt;Dockerfile&lt;/code&gt; and the descriptor template should be visible at the root of your repository).&lt;/p&gt;

&lt;p&gt;Notice in particular the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/sample_project/.circleci/config.yml"&gt;.circleci/config.yml&lt;/a&gt; build configuration file for CircleCI (more about the syntax &lt;a href="https://circleci.com/docs/2.0/configuration-reference/"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;h3&gt;
  
  
  Create a CircleCI service account on GCP
&lt;/h3&gt;

&lt;p&gt;This can easily be done in the &lt;a href="https://console.cloud.google.com/iam-admin/serviceaccounts"&gt;Cloud Console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Create a new &lt;code&gt;CircleCI&lt;/code&gt; account with role &lt;code&gt;Storage Admin&lt;/code&gt; and &lt;code&gt;Kubernetes Engine Admin&lt;/code&gt;. Create and download a (JSON) key for this account. This technical user will have write access to the Google Container Registry (GCR) of you project and permission to deploy to your cluster.&lt;/p&gt;

&lt;h3&gt;
  
  
  Build the project on CircleCI
&lt;/h3&gt;

&lt;p&gt;In CircleCI, add your project in the build list in the &lt;code&gt;Add Projects&lt;/code&gt; tab (use the &lt;code&gt;Add manually&lt;/code&gt; button, since you have already committed a &lt;code&gt;.circleci/config.yml&lt;/code&gt; file).&lt;/p&gt;

&lt;p&gt;In the &lt;code&gt;Settings&lt;/code&gt; tab, find your project in the &lt;code&gt;Projects&lt;/code&gt; sub-tab and open its settings.&lt;/p&gt;

&lt;p&gt;In &lt;code&gt;Environment Variables&lt;/code&gt;, create the following variables. They are used in the CircleCI configuration and in the descriptor template.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;GCP_PROJECT&lt;/code&gt;: The id of your GCP project (visible in the &lt;a href="https://console.cloud.google.com/home/"&gt;Cloud Console&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GCP_AUTH&lt;/code&gt;: The content of the JSON key file created in the previous step.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GCP_REGISTRY&lt;/code&gt;: The GCR registry of your choice (&lt;code&gt;eu.gcr.io/[GCP_PROJECT]&lt;/code&gt; for a storage in Europe)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GCP_ZONE&lt;/code&gt;: The GCP Zone in which your cluster is hosted (visible in the &lt;a href="https://console.cloud.google.com/kubernetes/list"&gt;Cloud Console&lt;/a&gt;, e.g., &lt;code&gt;europe-west3-a&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GCP_KUBE_CLUSTER&lt;/code&gt;: The name of your Kubernetes cluster&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Relaunch the build: the master branch is deployed on the &lt;code&gt;master&lt;/code&gt; subdomain (e.g., &lt;code&gt;master.myapp.mywebsite.com&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;Create branches on your GitHub repository and push them... and let the magic happen! From source code to production in less than 20 seconds!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--7yblTBIA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/41xzdcvk587c538f9e9i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--7yblTBIA--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/41xzdcvk587c538f9e9i.png" alt="Screenshot CircleCI"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  5. Bonus track: delete stale instances in Kubernetes
&lt;/h2&gt;

&lt;p&gt;Now you know how to deploy an instance of your app per GitHub branch in Kubernetes... But how to delete stale instances in Kubernetes (instances of the app created for branches that are since deleted in GitHub)?&lt;/p&gt;

&lt;h3&gt;
  
  
  Add a second job in your CircleCI configuration
&lt;/h3&gt;

&lt;p&gt;As you can see, it involves quite a bit of bash wizardry...&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;jobs:
  build:
    [...]
  delete-stale-ci-stacks:
    docker:
      - image: google/cloud-sdk
    working_directory: /home/circleci/myapp
    steps:
      - checkout
      - run:
        name: Authenticate with GCP
        command: |
          echo ${GCP_AUTH} &amp;gt; /home/circleci/gcp-key.json
          gcloud auth activate-service-account --key-file /home/circleci/gcp-key.json
          gcloud --quiet config set project ${GCP_PROJECT}
          gcloud config set compute/zone ${GCP_ZONE}
          gcloud --quiet container clusters get-credentials ${GCP_KUBE_CLUSTER}
      - run:
        name: Delete stale instances
        command: |
          KUBE_FEATURE_BRANCHES=`kubectl get po -n myapp -l 'app.kubernetes.io/name=myapp' -o jsonpath="{.items[*].metadata.labels['app\.kubernetes\.io/instance']}"`
          GIT_BRANCHES=`git branch --list --remote | sed 's/  origin\///g'`
          for kube_branch in $KUBE_FEATURE_BRANCHES; do
            echo "Checking branch ${kube_branch}"
            git_branch_still_exists=false
            for git_branch in $GIT_BRANCHES; do
              if [ "${git_branch}" == "${kube_branch}" ]; then
                git_branch_still_exists=true
                echo "Git branch ${git_branch} still exists, instance ${kube_branch} will not be deleted."
              fi
            done
            if [ "${git_branch_still_exists}" = false ]; then
              echo "Git branch corresponding to instance ${kube_branch} has been deleted, deleting instance..."
              kubectl delete all,ingressroute -n myapp -l app.kubernetes.io/instance=$kube_branch
            fi
          done
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Add the job in a new workflow triggered by a CRON
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;workflows:
  version: 2
  build-test-and-deploy:
    [...]
  delete-stale-deployments:
    triggers:
      - schedule:
        cron: "0 0,6,12,18 * * *" # Every six hours
        filters:
          branches:
            only:
              - master
    jobs:
          - delete-stale-ci-stacks
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For a toy project, the cost of this infrastructure is about $100 a month. For real-world projects with large architectures we average $500 per project per month, and the &lt;em&gt;pay-as-you-go&lt;/em&gt; pricing model of the services we use guarantees this cost to be quite linear. This might look like a lot, but in fact it is ridiculously low when you take into account the billable time not spent on maintaining this type of platform ourselves (or being slowed down by it!).&lt;/p&gt;

&lt;p&gt;As of this writing, we have been using these tools and techniques for all our projects at Zenika Labs for more than two years. Feel free to use it, share it, suggest improvements or ask any question!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>circleci</category>
      <category>traefik</category>
      <category>gitops</category>
    </item>
    <item>
      <title>Google Kubernetes Engine, CircleCI and Traefik for a full-fledged GitOps platform in the cloud - Part 1</title>
      <dc:creator>Romain Vernoux</dc:creator>
      <pubDate>Fri, 15 Jan 2021 16:19:42 +0000</pubDate>
      <link>https://dev.to/zenika/google-kubernetes-engine-circleci-and-traefik-for-a-full-fledged-gitops-platform-in-the-cloud-part-1-2bai</link>
      <guid>https://dev.to/zenika/google-kubernetes-engine-circleci-and-traefik-for-a-full-fledged-gitops-platform-in-the-cloud-part-1-2bai</guid>
      <description>&lt;p&gt;As teams start new projects, they usually waste precious time deploying and configuring a CI/CD pipeline from scratch. At Zenika Labs, our goal is to deliver proofs of concept or minimum viable products as efficiently as possible, without compromising on quality.&lt;/p&gt;

&lt;p&gt;Our teams usually work on short-lived (from a few minutes to a few hours) &lt;em&gt;feature branches&lt;/em&gt;, with a strong focus on technical/functional exploration and quick iterations with the Product Owner. We expect our infrastructure to be able todeploy a new version of the product in a few minutes, but also to dynamically deploy an instance for each active featurebranch on each Git push. These production-like instances, accessible from anywhere (web) and at any time, are targeted by automated end-to-end tests, used by the Product Owner to try new features, and sometimes showed to the end users to validate or invalidate new concepts and ideas.&lt;/p&gt;

&lt;p&gt;We work on a large range of technical stacks and on very diverse products, from static websites to complex event-drivenmicroservices architectures. We need to deploy both stateless and stateful workloads, some very light such as Node.js backends, others more compute or data-intensive such as Kafka clusters. Build processes also vary from trivial to very complex in the case of large microservice architectures in a monorepo.&lt;/p&gt;

&lt;p&gt;In any case, our job is not to build or maintain infrastructures, but rather to deliver software. This is why we want toreuse most of our tooling across projects and need language, architecture and size-agnostic services. Moreover, theprice of most managed services for CI/CD are so low compared to a developer daily cost that there is no actual reason for us not to use them extensively and focus our precious time on more useful work.&lt;/p&gt;

&lt;p&gt;This guide describes how to set up, in probably &lt;em&gt;less than an hour&lt;/em&gt;, the infrastructure supporting the development workflow we use every day to build, test and deploy our projects. For all the reasons listed above and after a lot of investigation, we settled on Google's managed Kubernetes (GKE) as well as CircleCI, Traefik and other Google Cloud services.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Kubernetes?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Kubernetes, also known as k8s, is an open-source system for automating deployment, scaling, and management of containerized applications. In the past years, Kubernetes has become the de-facto industrial standard to deploy containers on-premise or in the cloud.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We use a shared, autoscaling Kubernetes cluster as an all-purpose (and now quite standard) deployment target. Each of our projects has its own namespace, with resources quotas et closed network boundaries.&lt;/p&gt;

&lt;p&gt;If you have never used Kubernetes before, this guide will probably feel a bit too hard to follow. You may start by &lt;a href="https://kubernetes.io/docs/concepts/overview/"&gt;reading a bit about Kubernetes&lt;/a&gt; first.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is CircleCI?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;CircleCI is a cloud-native continuous integration and continuous delivery (CI/CD) platform. It integrates with GitHub and Bitbucket and runs a configured pipeline on each commit. Think Jenkins multibranch pipelines on steroids, in the cloud, and fully managed for you.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We chose CircleCI as a managed, modern and reliable alternative to Jenkins and prefer it over TravisCI or GitHub Actions for its best-in-class performance and ability to configure and run workflows on large polyglot monorepos requiring advanced caching mechanisms.&lt;/p&gt;

&lt;p&gt;If you have never used CircleCI before, welcome aboard and enjoy the &lt;a href="https://circleci.com/pricing/"&gt;free plan&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;What is Traefik?&lt;/strong&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Traefik Proxy is a dynamic, modern, open-source Edge Router that automatically inspects your infrastructure to discover services and how to route traffic to them. Traefik is natively compliant with every major cluster technology, such as Kubernetes, Docker, Docker Swarm, AWS, Mesos, Marathon... and even bare metal! Used as an ingress controller in Kubernetes, it is probably a drop-in replacement for the one you already use (if any), and brings awesome features such as automated TLS certificate management via Let's Encrypt, middlewares, plugins...&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Traefik is the cornerstone of our platform, allowing new instances to be deployed and made accessible over &lt;code&gt;https&lt;/code&gt; without any human intervention. &lt;/p&gt;

&lt;p&gt;If you have never used Traefik before, welcome aboard and enjoy the ride (you will)!&lt;/p&gt;

&lt;p&gt;The following guide contains some data and commands gathered from the following resources:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/kubernetes-engine/docs/quickstart"&gt;Kubernetes' Quickstart&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://docs.traefik.io"&gt;Traefik's official documentation&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Read them in details if you want to deep dive into how things work.&lt;/p&gt;

&lt;h2&gt;
  
  
  Architecture and outline
&lt;/h2&gt;

&lt;p&gt;Our pipeline uses GitHub for version control, CircleCI for CI/CD, a Google Kubernetes Engine cluster as the deployment platform, Traefik as ingress controller and load balancer and Let's Encrypt for a fully automated and free TLS certificate management. The corresponding architecture is pictured below:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--szjTOoyP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ng5g1xnenlr1jv0onn1t.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--szjTOoyP--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://dev-to-uploads.s3.amazonaws.com/i/ng5g1xnenlr1jv0onn1t.png" alt="architecture"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Everytime a developers pushes a new feature branch on GitHub, the platform builds it and deploys it to an isolated, short-lived environment (&lt;code&gt;App 1&lt;/code&gt;, ..., &lt;code&gt;App n&lt;/code&gt; in the picture above). This new, separate instance of the app is made accessible on the web with a dedicated URL and a TLS certificate, allowing the team and our users to test it in a production-like environment. In this setup &lt;code&gt;master&lt;/code&gt; in just another instance of the app which can act as an integration environment.&lt;/p&gt;

&lt;p&gt;The following sections will describe how to assemble step by step the different components pictured above in order to reproduce our pipeline on your own environments in about an hour.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requirements
&lt;/h2&gt;

&lt;p&gt;For that, you will need&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a Google Cloud account, with full access rights to create and configure a Kubernetes cluster&lt;/li&gt;
&lt;li&gt;a GitHub account, with ability to create and configure projects&lt;/li&gt;
&lt;li&gt;a CircleCI account linked to your GitHub account, with ability to configure and run builds&lt;/li&gt;
&lt;li&gt;to own a domain (e.g., &lt;code&gt;mywebsite.com&lt;/code&gt;) managed by one of the providers &lt;a href="https://docs.traefik.io/https/acme/#dnschallenge"&gt;compatible with Traefik&lt;/a&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The following command-line tools must be installed and configured on your computer:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://cloud.google.com/sdk/docs/quickstarts"&gt;gcloud SDK&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/"&gt;kubectl&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;htpasswd  (&lt;code&gt;sudo apt-get install htapasswd&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;envsubst (&lt;code&gt;sudo apt-get install gettext&lt;/code&gt;)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Login in gcloud (this command should open a page in your browser asking for access to your Google account):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud auth login
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Finally, download the descriptors and resources from our &lt;a href="https://github.com/Zenika/labs-tooling/tree/master/ci-cd-platform-deployment"&gt;GitHub repository&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Kubernetes cluster
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Deploy a GKE cluster instance on GCP
&lt;/h3&gt;

&lt;p&gt;This can easily be done through the &lt;a href="https://console.cloud.google.com/kubernetes"&gt;Cloud Console&lt;/a&gt;. The following instructions do not assume a particular configuration or size for your cluster, except for the HTTP load balancing add-on, which must be enabled after creation.&lt;/p&gt;

&lt;h3&gt;
  
  
  Authenticate to the cluster:
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;gcloud container clusters get-credentials [CLUSTER_NAME]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Traefik
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Create a "traefik" namespace in the cluster
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create namespace traefik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Import Traefik's Custom Resource Definitions (CRDs) in the cluster
&lt;/h3&gt;

&lt;p&gt;Apply the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/crd.yaml"&gt;CRD descriptor&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f crd.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Apply the Role-Based Access Control (RBAC) rules required by Traefik
&lt;/h3&gt;

&lt;p&gt;Apply the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/rbac.yaml"&gt;RBAC descriptor&lt;/a&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f rbac.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will create the RBAC rules, create a service account for Traefik and bind the rules to the service account.&lt;/p&gt;

&lt;h3&gt;
  
  
  Deploy Traefik in the cluster
&lt;/h3&gt;

&lt;p&gt;Create a secret file with a pair user / password hash. These will be the credentials to use to access Traefik's dashboard.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;htpasswd -bc [FILENAME] [USER] [PASSWORD]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Import the secret into your cluster's traefik namespace:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create secret generic traefik-auth --from-file [FILENAME] --namespace=traefik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In order for Traefik to generate wildcard TLS certificates using Let's Encrypt, it must fulfill a DNS challenge. Since our domain is registered with Google Domains and our DNS is handled by Google Cloud DNS, we use Traefik's Google Cloud provider to do so (other providers are listed &lt;a href="https://docs.traefik.io/https/acme/#dnschallenge"&gt;here&lt;/a&gt;). This provider requires the key of a GCP Service Account with DNS write access to edit DNS records. This service account and its key can be generated through the &lt;a href="https://console.cloud.google.com/iam-admin/serviceaccounts"&gt;Cloud Console&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Note that if you opt for another provider, you will probably need to adapt or remove the &lt;code&gt;volume&lt;/code&gt;, &lt;code&gt;volumeMount&lt;/code&gt; and environment variables parts of the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/traefik.yaml"&gt;traefik descriptor&lt;/a&gt; in order to pass the correct configuration to Traefik.&lt;/p&gt;

&lt;p&gt;Import the key file into your cluster's traefik namespace as a secret with key &lt;code&gt;traefik-service-account&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl create secret generic traefik-service-account --from-file=traefik-service-account.json=[FILENAME] --namespace=traefik
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Fill the following placeholders in the &lt;a href="https://github.com/Zenika/labs-tooling/blob/master/ci-cd-platform-deployment/traefik.yaml"&gt;traefik descriptor&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;DOMAIN&lt;/code&gt;: the domain you own (e.g., &lt;code&gt;mywebsite.com&lt;/code&gt;)&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ACME_EMAIL_ADDRESS&lt;/code&gt;: the contact email address to use to generate the TLS certificates&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;GCE_PROJECT&lt;/code&gt;: the name of the Google Cloud project&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Then apply it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl apply -f traefik.yaml
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;instantiate a Traefik instance using a Deployment&lt;/li&gt;
&lt;li&gt;expose this Traefik instance on a public IP using a Service of type LoadBalancer&lt;/li&gt;
&lt;li&gt;configure Traefik's entrypoints to listen to ports 80 (HTTP) and 443 (HTTPS)&lt;/li&gt;
&lt;li&gt;redirect all HTTP (port 80) traffic to the HTTPS entrypoint (port 443) using a RedirectScheme middleware&lt;/li&gt;
&lt;li&gt;expose Traefik's dashboard on the &lt;code&gt;traefik&lt;/code&gt; subdomain (e.g., &lt;code&gt;traefik.mywebsite.com&lt;/code&gt;) using an IngressRoute, protected with a BasicAuth middleware (using the secret created above)&lt;/li&gt;
&lt;li&gt;configure a Traefik certificate resolver to generate wildcard certificates on demand&lt;/li&gt;
&lt;li&gt;create and use the wildcard TLS certificate (e.g., &lt;code&gt;*.mywebsite.com&lt;/code&gt;) required by the dashboard IngressRoute&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Wait for a bit and get the public IP associated by GKE to the Traefik Service:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;kubectl -n traefik get services
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The IP will eventually be displayed in the "EXTERNAL-IP" column, but it may take a few seconds.&lt;/p&gt;

&lt;p&gt;Configure your DNS records manually to redirect all traffic from your domain to this IP (this is an &lt;code&gt;A&lt;/code&gt; record from &lt;code&gt;*.mywebsite.com&lt;/code&gt; to the external IP).&lt;/p&gt;

&lt;p&gt;Traefik's dashboard should now be accessible on the traefik subdomain (e.g., &lt;code&gt;traefik.mywebsite.com&lt;/code&gt;) and all HTTP traffic should be redirected to HTTPS with valid Let's Encrypt certificates.&lt;/p&gt;

&lt;h2&gt;
  
  
  End of part 1!
&lt;/h2&gt;

&lt;p&gt;Stay tuned for part 2 and the deployment of your first app on your brand new CI/CD platform!&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>circleci</category>
      <category>traefik</category>
      <category>gitops</category>
    </item>
  </channel>
</rss>
