<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[Stories by Sam Gibson on Medium]]></title>
        <description><![CDATA[Stories by Sam Gibson on Medium]]></description>
        <link>https://medium.com/@samolivergibson?source=rss-f091e71a9875------2</link>
        <image>
            <url>https://cdn-images-1.medium.com/fit/c/150/150/1*9Ee5wqgZR366zqOWYh8IqA.png</url>
            <title>Stories by Sam Gibson on Medium</title>
            <link>https://medium.com/@samolivergibson?source=rss-f091e71a9875------2</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Sun, 15 Nov 2026 23:11:53 GMT</lastBuildDate>
        <atom:link href="https://medium.com/@samolivergibson/feed" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com/" rel="hub"/>
        <item>
            <title><![CDATA[Ensuring SaaS reliability with synthetic traffic — ‘SynthMail’]]></title>
            <link>https://medium.com/@samolivergibson/ensuring-saas-reliability-with-synthetic-traffic-synthmail-e1cf73d53bff?source=rss-f091e71a9875------2</link>
            <guid isPermaLink="false">https://medium.com/p/e1cf73d53bff</guid>
            <category><![CDATA[saas]]></category>
            <category><![CDATA[monitoring]]></category>
            <category><![CDATA[test]]></category>
            <category><![CDATA[software-engineering]]></category>
            <category><![CDATA[sre]]></category>
            <dc:creator><![CDATA[Sam Gibson]]></dc:creator>
            <pubDate>Fri, 22 May 2020 10:36:38 GMT</pubDate>
            <atom:updated>2020-05-22T10:36:38.900Z</atom:updated>
            <content:encoded><![CDATA[<h3>Ensuring SaaS reliability with synthetic traffic — ‘SynthMail’</h3><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*BqYRjxSHfMIrSn8I" /><figcaption>Photo by <a href="https://unsplash.com/@sxoxm?utm_source=medium&amp;utm_medium=referral">Sven Mieke</a> on <a href="https://unsplash.com/?utm_source=medium&amp;utm_medium=referral">Unsplash</a></figcaption></figure><p>As a member of <a href="https://sre.glasswallsolutions.com/">Glasswall’s SRE team</a>, the reliability of our products is my number one concern. Reliability of our <a href="https://glasswallsolutions.com/rebuild-for-email/">Rebuild for Email</a> product is especially important, as it’s responsible for ensuring our customers never receive any unsafe and untrusted email attachments. Our system works as a mail transfer agent that scans and remediates email attachments with <a href="https://glasswallsolutions.com/technology/">Glasswall’s d-FIRST system</a>, a form of <a href="https://en.wikipedia.org/wiki/Content_Disarm_%26_Reconstruction">content disarm and reconstruction technology</a>.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*bvKIKyvKi9IXno8lIH9xOw.png" /><figcaption>A graph of our email throughput for a cluster. See how its peaks and troughs align with workdays and weekends.</figcaption></figure><p>Ensuring the reliability of such a system is no small feat. We have set up a full monitoring suite, integrated with <a href="https://www.datadoghq.com/">Datadog</a> and <a href="https://www.pagerduty.com/">PagerDuty</a> to make sure we can detect any abnormalities in the system within minutes of occurrence, but this monitoring depends on email flowing through the system. When a problem occurs it can mean customers will observe delays in mail delivery — which is a bad thing for business when prompt communication is everything in our current fast-paced environment. So, how can we detect problems and delays in the system before they affect any customer?</p><p>In this post I will describe a system we have designed and implemented that sends synthetic emails through the system at a high rate, in order to trigger our monitoring for problems as early as theoretically possible, and ensure we can remediate any problems before they start affecting our customers.</p><h4>Background</h4><p>We’re an SRE team, so we try to follow <a href="https://landing.google.com/sre/books/">Google’s ‘scripture’</a> as often as we can. In a nutshell, this means we define ‘service level objectives’ (SLOs) for the products we manage. These SLOs are based on specific metrics for a system, and are backed by hard data. Our SLOs for Rebuild for Email can be found on <a href="https://sre.glasswallsolutions.com/docs/products/rebuild-email/slos">this page</a>. In this post we’re focusing on the mail latency metrics.</p><p>If mail starts getting delayed, then we start eating into our ‘error budget’ for a particular SLO. If we use up more than 100% of the error budget, then we have broken the SLO. Ideally we don’t want this to happen, so we should be alerted that we’re burning the error budget very soon after it starts happening.</p><p>Google’s SRE workbook states that artificial traffic can be useful for detecting issues before they affect your end users:</p><blockquote>A system can synthesize user activity to check for potential errors and high-latency requests. In the absence of real users, your monitoring system can detect synthetic errors and requests, so your on-call engineers can respond to issues before they impact too many actual users.</blockquote><p>That sounds like exactly what we need, so ‘SynthMail’ was born.</p><h4>Design</h4><figure><img alt="" src="https://cdn-images-1.medium.com/max/702/1*b8ae2f2ke-tpFuOQ-TCWAA.png" /><figcaption>A high-level overview of the Synthetic Mail system.</figcaption></figure><p>This is a diagram showing the overview of the proposed solution. It will be deployed as a set of microservices into our ‘worldwide’ Kubernetes cluster, which will run continuously and send/receive email from our SaaS clusters, essentially acting as a real customer’s mail server. It consists of three components:</p><ul><li><strong>Test sender </strong>— creates emails based on config and sends them on a cron schedule to a list of SMTP endpoints. Informs test receiver every time an email is sent.</li><li><strong>Postfix relay</strong> — receives emails from the SaaS cluster and relays them to test receiver. Postfix was chosen for reliability, because it will queue mail if for some reason it can’t be sent, and it can also be tuned to induce extra SMTP faults to further test the system.</li><li><strong>Test receiver</strong> — waits to receive emails after being informed about them by test sender. When an email is received, computes flight time metrics and sends them to Datadog.</li></ul><p>It’s just a huge loop of email, with some extra metadata being sent through via MIME headers. The metrics are sent to Datadog as a histogram, so we can easily query for percentiles and compute our SLOs.</p><h4>Operation</h4><p>The tests are defined in a YAML config file loaded as a ConfigMap by the test sender microservice. Here is an example that sends a plain email without an attachment, as well as an email with a PNG attached:</p><pre>endpoints:<br>  ukprod: smtp.uk.ourendpoint.io<br>tests:<br>  - name: png_attached<br>    cron: &quot;0 * * * * * *&quot;<br>    spec: ./specs/attach_png.yml<br>    endpoints: [ukprod]<br>  - name: no_attachments<br>    cron: &quot;0 * * * * * *&quot;<br>    spec: ./specs/no_attachments.yml<br>    endpoints: [ukprod]</pre><p>As you can see, SMTP endpoints are defined at the top, and then an array of tests is given. The tests are given a name (to appear in metrics and logs), a cron schedule of how often they should be sent (both here are every minute), a path to a spec file (which describes how to generate the email), and then which endpoints to send the test to.</p><p>A spec file is essentially a YAML syntax that can be converted directly into a MIME email:</p><pre>headers:<br>  To: [ test@synthetic.mail ]<br>  Date: {{ now() }}<br>  From: [ test@synthetic.mail ]<br>  X-FileTrust-Tenant: &lt;removed-for-security&gt;<br>body: This contains a PNG<br>attach:<br>- png.png</pre><p>It’s a really flexible way of generating emails, and can be hooked up to a cloud storage solution to access a shared library of attachments. This is very helpful for ensuring our system is correctly rejecting/sanitising bad files. We are hoping to open source this mail generation code soon.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*wGD9yYCfkLo2kPICfbSlzg.png" /><figcaption>The end result of the SynthMail system — the metrics! This is how they look in Datadog.</figcaption></figure><p>When the test mails are received at the end of the system, the metrics are computed and submitted to Datadog as a histogram. This lets us directly see how many mails are meeting our SLOs and how many are not.</p><p>We can then use Datadog’s SLO monitor system to track our SLOs and error budget!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/780/1*qrMkUMUR-S99ha2RINzzDw.png" /><figcaption>Pictured: a stable system, meeting its targets!</figcaption></figure><h4>Conclusion</h4><p>Ultimately, the synthetic mail system has been a huge success for us. We can now be 100% sure that we can detect any delays in mail flow before they begin affecting our customers, and we can mitigate any issues before they start burning large amounts of our error budget.</p><p>It’s also had a few fringe benefits:</p><ul><li>We can now accurately measure delays when correlated with external events such as cloud service failovers, and deployments.</li><li>We can get a realtime view of the system performance according to our baseline of expected mail throughput. Previously this was difficult with the aforementioned ebb and flow of traffic.</li><li>When we do have incidents, we can use the synthetic mail system to quickly assess the degree of mailflow impact. This greatly reduces operational complexity when it comes to call-outs.</li></ul><p>Ultimately, if you are running a SaaS platform I would encourage using synthetic data to assist in monitoring wherever possible. It’s well worth the initial time investment of developing a system to generate the data.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e1cf73d53bff" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Pulumi end-to-end on Azure, part one]]></title>
            <link>https://medium.com/@samolivergibson/pulumi-end-to-end-on-azure-part-one-91612434f7dc?source=rss-f091e71a9875------2</link>
            <guid isPermaLink="false">https://medium.com/p/91612434f7dc</guid>
            <category><![CDATA[cloud]]></category>
            <category><![CDATA[azure]]></category>
            <category><![CDATA[infrastructure-as-code]]></category>
            <category><![CDATA[pulumi]]></category>
            <category><![CDATA[sre]]></category>
            <dc:creator><![CDATA[Sam Gibson]]></dc:creator>
            <pubDate>Thu, 06 Feb 2020 18:59:20 GMT</pubDate>
            <atom:updated>2020-02-06T18:59:20.206Z</atom:updated>
            <content:encoded><![CDATA[<figure><img alt="" src="https://cdn-images-1.medium.com/max/993/1*g26WQNPpWBRwf9Nny3lxsw.png" /></figure><p><em>At Glasswall SRE, we’ve recently been investigating using </em><a href="https://www.pulumi.com/"><em>Pulumi</em></a><em> as our </em><a href="https://en.wikipedia.org/wiki/Infrastructure_as_code"><em>Infrastructure as Code (IaC)</em></a><em> solution, to speed up infrastructure deployments, reduce errors when creating new environments, and create a more stable platform.</em></p><p><em>This blog post is the first part in a guide to how we’re running Pulumi with a self-managed backend on Azure, complete with using Azure Key Vault as Pulumi’s encryption provider. It includes a short tutorial of bootstrapping a self-managed backend and automating Pulumi infrastructure deployments using Azure Pipelines.</em></p><p><em>Future parts will go into more detail about how to use Pulumi on a self-managed backend, and specifics about how we have implemented our SaaS infrastructure on Azure with Pulumi.</em></p><h3>The story so far</h3><p>For our FileTrust for Email SaaS product, most of our infrastructure is managed through IaC. Our infrastructure is hosted on Azure, and some of the tech we use on/with it is:</p><ul><li>Kubernetes</li><li>Helm</li><li>.NET Core</li><li>Docker</li><li>Python</li><li>SQL Server</li><li>Redis</li><li>Prometheus</li></ul><p>The Glasswall Site Reliability Engineering (SRE) Team is responsible for managing, maintaining, and supporting our infrastructure and the services that run on it in production. Our team is about five months old — comprised mainly of new hires — having inherited the existing CI/CD workflows from contractors before our time.</p><p>We use Azure DevOps as our CI/CD solution, utilising both build and release pipelines to package and deploy our microservices and infrastructure.</p><p>Our inherited IaC solution is written in Python, using the subprocess module to call Azure CLI commands. This has worked <em>okay</em> up until recently, where we’ve experienced a few growing pains with it as we’ve scaled:</p><ul><li>Using subprocess to call out to the Azure CLI can be brittle; if the CLI changes too much over different versions then your IaC is broken. This is amplified by the fact that some infrastructure deployments are run very infrequently. Everything is fine, until you need to redeploy a critical piece of infrastructure when it breaks, only to find your IaC is also broken due to API changes since it was last run.</li><li>Logging errors during a CD run is troublesome when using subprocess. The error causing the run to fail will be a wordy Python exception, indicating that the subprocess exited unsuccessfully, with the actual CLI error hidden away in the logs above.</li><li>The core infrastructure is fairly rigid, with the inability to pass outputs from one section of infrastructure as inputs into another. An example of this is our virtual networking. If we wanted to change a subnet prefix, we would have to modify many instances of it being hard coded (no doubt missing some and breaking deployments), as opposed to changing it in one place and having that propagate outwards. This won’t scale as we onboard new services and products.</li><li>It’s a bespoke system, and difficult for new joiners to learn and adjust to. Documentation is sparse, and normally only says what something does as opposed to why it is doing it. There is no standardisation in terms of what is documented, where, and how.</li><li>Best practices for writing software are generally not followed. Most of the code utilises Python’s globals() in order to read/modify global state. This leads to an almost complete lack of pure functions, numerous errors due to side effects, and code that is <em>incredibly</em> difficult to debug.</li><li>Due to using the raw Azure CLI for a lot of functionality, there’s a tonne of boilerplate in place for ensuring idempotency (being able to run something multiple times without changing the end result beyond the initial run), and in some places operations are just not idempotent.</li><li>It only creates infrastructure. It cannot destroy it.</li></ul><p>So, for these reasons, we were interested in seeing if we could find a more scalable solution for infrastructure deployments. Enter: Pulumi.</p><h3>Halloumi?</h3><p><em>Pulumi.</em> In its own words, it is “Modern Infrastructure as Code”. Basically, it lets you codify your infrastructure in a commonly-used programming language (Javascript, Typescript, Python, Go, or .NET), as opposed to learning a domain-specific language for it (like Terraform’s HCL).</p><p>Pulumi is hooked up to a backend (they offer a SaaS cloud solution, but we have opted for a self-managed backend using Azure Blob Storage) which stores the state of resources as you deploy/destroy things. This allows it be run idempotently, and ensures that when you make a change to your IaC, only the minimal set of changes to your cloud infrastructure are made — speeding up build time! It also automatically detects the optimal order of operations, and even runs some steps in parallel for maximum speed.</p><p>Below are some screenshots of code. The first is our current IaC solution for creating an Azure Container Registry (ACR) in Python using subprocess, and the second is the Pulumi version, also written in Python.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*an8D6KT0QVexDSMv_nUq2g.png" /><figcaption>Our inherited IaC solution for ACR creation</figcaption></figure><figure><img alt="" src="https://cdn-images-1.medium.com/max/529/1*uZKiGzh7eWzEAKtDZ6u06w.png" /><figcaption>A Pulumi program to deploy an ACR in a resource group</figcaption></figure><p>As can be seen, the Pulumi version is a lot simpler; it’s self-documenting, the infrastructure configuration exists directly within the declaration, and we can pass outputs from one stage as inputs to the next using their object model.</p><p>How do you then deploy the infrastructure? Using the old version, you’d have to ensure you ran the Python script on one of our build agents as part of an Azure Pipeline, making sure you were authenticating using the correct service principal in Azure AD.</p><p>With Pulumi, you just sign in with the Azure CLI, log in to the Pulumi backend, and run pulumi up. That’s it! Pulumi stores the state of the deployed resources in your storage backend, so you can run it on any machine and the results are entirely deterministic.</p><p>It’s the exact same process for CD pipelines too, except instead of logging in with the Azure CLI, you provide service principal credentials in environment variables.</p><p>So, without any further hesitation — let’s get stuck in!</p><h3>Bootstrapping a Pulumi backend</h3><p>You’ll need to set up two things on Azure in order for Pulumi to work:</p><ul><li>A storage account and blob container to store state files.</li><li>A key vault and encryption key to encrypt/decrypt secrets.</li></ul><p>This guide assumes you already have:</p><ul><li>An Azure AD account for yourself with permissions to create/destroy Azure resources.</li><li>Azure DevOps set up for you to create Git repositories and pipelines.</li><li><a href="https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&amp;tabs=yaml#create-a-service-connection">An Azure Pipelines service connection to your Azure subscription (via Azure Resource Manager)</a>, to allow build agents to create/destroy Azure resources.</li></ul><p>Unfortunately, we can’t use Pulumi to create the Pulumi backend. It’s not a chicken/egg situation; the backend must be created naively first before we can harness the full power of Pulumi.</p><p>We’ll make a simple shell script to bootstrap Pulumi, and then put this in an Azure Pipeline with a CD trigger so we can deploy changes.</p><p>Create a bash script with the following contents:</p><pre>#!/bin/bash<br># make sure we exit on any errors<br>set -o errexit<br>set -o pipefile</pre><pre>readonly PULUMI_LOC=westeurope</pre><p>This is literally just a bash script that’ll exit correctly if any errors happen. I also define a constant for the Azure location our Pulumi backend will be hosted in. If you want to change the location of the backend then change the constant.</p><p>As you follow this bootstrapping guide, add any code snippets given to the bash script. I’ll explain them along the way.</p><h4>Resource group</h4><p>In order to group our Pulumi backend cloud resources together, we need to create a resource group. Add this to your bash script:</p><pre>az group create \<br>  --name rg-pulumi \<br>  --location &quot;${PULUMI_LOC}&quot;</pre><p>It just creates an Azure resource group called rg-pulumi in our Azure subscription.</p><h4>Storage</h4><p>Now let’s set up the blob storage Pulumi will need to store its state files in. Add this to your bash script:</p><pre>if ! az storage account show --name stpulumi \<br>      --resource-group rg-pulumi; then<br>  az storage account create \<br>    --name stpulumi \<br>    --resource-group rg-pulumi \<br>    --location &quot;${PULUMI_LOC}&quot; \<br>    --sku &quot;Standard_LRS&quot; \<br>    --encryption-services &quot;blob&quot; \<br>    --kind &quot;StorageV2&quot;<br>fi</pre><p>This creates a storage account called stpulumi if it didn’t already exist. Enclosing it in the if statement like that ensures that it’s idempotent.</p><p>Now add this:</p><pre>export AZURE_STORAGE_ACCOUNT=&quot;stpulumi&quot;<br>export AZURE_STORAGE_KEY=$(az storage account keys list \<br>  --account-name stpulumi \<br>  --resource-group rg-pulumi \<br>  --query [0].value \<br>  --o tsv)</pre><pre>az storage container create \<br>  --name pulumi \<br>  --public-access off</pre><p>We’re creating environment variables to store storage account credentials for the Azure CLI to be able to access it, then we’re creating a blob storage container for Pulumi to store its state files.</p><h4>Key vault</h4><p><em>This section is optional, as Pulumi has other methods of securely storing secret information, but this is what we used. If you’re gonna be using a different encryption provider, then feel free to skip this section and the one after it.</em></p><p>Sometimes you want to store secret information in your Pulumi projects — this is achieved through a Pulumi ‘encryption provider’. We’re using Azure Key Vault as ours. The basic principal is that you create an Azure Key Vault with an encryption key inside it. Pulumi will use this key for encrypting and decrypting secret values when they are stored in state files in the storage backend. This is an extra layer of security, and ensures that secrets don’t fall into the wrong hands, even if your state files happen to be compromised.</p><p>Add the following to your bash script:</p><pre>az keyvault create \<br>  --name kvpulumi \<br>  --resource-group rg-pulumi \<br>  --location &quot;${PULUMI_LOC}&quot; \<br>  --enabled-for-template-deployment true \<br>  --sku &quot;standard&quot;</pre><pre>if ! az keyvault key show --vault-name kvpulumi \<br>      --name pulumi; then<br>  az keyvault key create \<br>    --name pulumi \<br>    --vault-name kvpulumi \<br>    --kty &quot;RSA&quot; \<br>    --protection &quot;software&quot; \<br>    --size 2048<br>fi</pre><p>This creates an Azure Key Vault in rg-pulumi with name kvpulumi, then creates an encryption key inside it called pulumi that Pulumi will use to encrypt/decrypt secret values. Again, it has an if statement to ensure idempotency, otherwise the key would be recreated each time (which would be quite bad if we wanted to decrypt existing values in the state file — the key would no longer work!).</p><h4>Authorisation</h4><p>Finally, we need to make sure our user account and Azure Pipelines service connection principal have the correct access policies to encrypt/decrypt using the key we just created.</p><p>For this step you’ll need to know the object IDs of both your user account, and the Azure Pipelines service connection principal.</p><p>You can get the object ID of your user account by running this command:</p><pre>$ az ad user show --id {your-email-address} --query objectId -o tsv</pre><p>I haven’t been able to find an easy way of getting the object ID of the service connection principal, but you should be able to find it by searching your Azure DevOps project name and Azure subscription GUID in the ‘enterprise applications’ section of Azure AD in the Portal.</p><p>Now, add the following to your bash script:</p><pre>az keyvault set-policy \<br>  --name kvpulumi \<br>  --object-id {your-user-account-object-id} \<br>  --key-permissions get list encrypt decrypt</pre><pre>az keyvault set-policy \<br>  --name kvpulumi \<br>  --object-id {service-connection-object-id} \<br>  --key-permissions get list encrypt decrypt</pre><p>Here we’re simply adding the key permissions we need to the Azure AD objects that need them. As Pulumi ‘piggybacks’ your Azure credentials when you’re running it on your machine, you need to make sure your account is authorised to perform the required operations using keys in the vault. It’s the same story with the service principal.</p><h4>Deployment</h4><p>That’s the bash script done! If you run it (after running az login and ensuring you’re on the correct subscription, of course), it should create the backend for Pulumi!</p><p>Please note that this script is quite naive; if you change any of the values within it, it won’t know to tear down the existing infrastructure, as there is no state file. It also doesn’t let you destroy the infrastructure you have created. To do that you’ll have to manually delete the rg-pulumi resource group.</p><h3>Deploying the Pulumi backend on Azure Pipelines</h3><p>Now, let’s set up a CD pipeline to deploy our Pulumi backend.</p><p>Put your bash script in an Azure DevOps Git repository, and add a file called ‘azure-pipelines.yml’ somewhere in that repo. Inside this file, put:</p><pre>name: $(BuildDefinitionName)-$(Date:yyyyMMdd)$(Rev:.r)<br>pool:<br>  vmImage: ubuntu-latest<br>trigger:<br>  - master<br>steps:<br>  - task: AzureCLI@2<br>    inputs:<br>      azureSubscription: &#39;{your-service-connection}&#39;<br>      scriptType: &#39;bash&#39;<br>      scriptLocation: &#39;scriptPath&#39;<br>      scriptPath: &#39;path/to/bootstrap.bash&#39;<br>    displayName: &quot;Deploy Pulumi backend&quot;</pre><p>Make sure you put the name of your Azure Pipelines service connection in the azureSubscription field, and the path to your bootstrap script in the scriptPath field.</p><p>Create a new pipeline in Azure DevOps from an existing YAML file in your repo, and point it at your ‘azure-pipelines.yml’ file (Pipelines / New Pipeline / Azure Repos Git / Your repo / Existing Azure Pipelines YAML file).</p><p>Now, every time you make a push to the master branch of your git repo, the Pulumi backend will be deployed. You shouldn’t have to do this very often, if at all, as the infrastructure should stay fairly static.</p><h3>Wrap up</h3><p>That’s it for part one! We’ve managed to codify the infrastructure required for Pulumi, as well as automate its deployment. Believe it or not, this is actually the hardest part — the rest is a breeze!</p><p>Look out for part two, where I go through how to start creating cloud infrastructure with Pulumi on our self-managed backend.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=91612434f7dc" width="1" height="1" alt="">]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Glasswall SRE — how we work, ‘toil’, and ducks]]></title>
            <link>https://medium.com/@samolivergibson/glasswall-sre-how-we-work-toil-and-ducks-b338f3266494?source=rss-f091e71a9875------2</link>
            <guid isPermaLink="false">https://medium.com/p/b338f3266494</guid>
            <category><![CDATA[site-reliability]]></category>
            <category><![CDATA[google]]></category>
            <category><![CDATA[devops]]></category>
            <category><![CDATA[sre]]></category>
            <dc:creator><![CDATA[Sam Gibson]]></dc:creator>
            <pubDate>Thu, 28 Nov 2019 10:38:43 GMT</pubDate>
            <atom:updated>2019-11-28T10:38:43.735Z</atom:updated>
            <content:encoded><![CDATA[<h3>Glasswall SRE — how we work, ‘toil’, and ducks</h3><p>The Site Reliability Engineering (SRE) team at Glasswall is responsible for making sure our SaaS <em>FileTrust</em> platform is as reliable as possible for our end-users, whilst ensuring this focus on reliability doesn’t hamper innovation in terms of new product features. If you’d like to know more about this, then Alex (our glorious team leader) <a href="https://medium.com/glasswall-engineering/balance-of-reliability-and-new-features-7435e8bc788a">has previously written a great article</a> all about it.</p><p>We manage our work via a Kanban board, similar to the one <a href="https://medium.com/glasswall-engineering/kanban-development-tick-f5a3396aa3f1">described by our cloud architect, Paul, in his article</a>. We create work items on this board, and place them under ‘epics’ and ‘features’ depending on the overarching goal of the work. Based on their nature, pieces of work on this board get placed into one of four categories:</p><ul><li><strong>Planned SRE</strong> — engineering/operations work that originates from within the team, with an end goal of improving reliability, visibility, and productivity. It’s ‘planned’ because we can backlog it and allocate time in our sprints for it.</li><li><strong>Planned business </strong>— engineering/operations work that originates from outside the team, with an end goal of improving reliability and product value. Again, we can backlog this and work on it in a sprint.</li><li><strong>Incident</strong> — unplanned work that is related to addressing defects in the platform, causing unreliability.</li><li><strong>Toil </strong>— unplanned work that could be automated, such as release requests, replaying dead letters, and performing common log analytics queries.</li></ul><p>If you’re a fan of <a href="https://www.amazon.co.uk/Phoenix-Project-DevOps-Helping-Business-ebook/dp/B00AZRBLHO">‘<em>The Phoenix Project</em>’</a>, you may notice that these categories of work align closely with its ‘four types of IT work’.</p><p>Every two weeks, we have a sprint planning meeting, where we pick work from our backlog based on priority and whether we think we can get it done in two weeks.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*-e_0RrPm8GNHvxyFKieXxg.png" /><figcaption>A snippet of our Kanban board, showing work items categorised into the four types of work</figcaption></figure><p>Going by <a href="https://landing.google.com/sre/books/">Google’s <em>SRE book</em></a> (from which our entire profession has risen), we aim to put a hard cap on the amount of unplanned work that any given team member does in a sprint, as if you don’t put in time to do the planned work and make the system more reliable, the unplanned work will quickly pile up and become intractable without a larger team.</p><blockquote>“Eventually, a traditional ops-focused group scales linearly with service size: if the products supported by the service succeed, the operational load will grow with traffic. That means hiring more people to do the same tasks over and over again.”</blockquote><h3>On unplanned work</h3><p>It’s always there. You can’t backlog it, you can’t anticipate it, and it has the potential to completely defenestrate your sprint plan.</p><p>Google’s <em>SRE book</em> <a href="https://landing.google.com/sre/sre-book/chapters/eliminating-toil/">has an entire chapter dedicated to its systematic elimination</a>. To them, unplanned work is ‘toil’, and is characterised by work that has any of the following descriptions:</p><ul><li>Manual</li><li>Automatable</li><li>No enduring value</li><li>Repetitive</li><li>O(n) with service growth (scales linearly)</li><li>Tactical</li></ul><p><em>Sidenote: There really needs to be a better acronym for these. ‘RATNOM’? ‘MAN ROT’? Those don’t sound great.</em></p><p>To us, toil tends to be things like fixing CD pipeline failures due to outdated scripts, updating software on our clusters, carrying out manual processes in the system backend that are currently unautomated, and manually running/checking CD pipelines for production deployments.</p><p>All of these things embody almost all of the values given above. They are also mainly driven by interruption.</p><p>As mentioned previously, it’s very difficult to backlog or anticipate toil. It mainly crops up in the middle of the day when something goes wrong, or someone wants something done, and it tends to be fairly urgent. This leads to members of our team being interrupted when carrying out our planned work, losing their focus on it, and making mistakes or oversights on what is usually critical production-related work.</p><p>This is a fundamental problem with the kind of work we do; how are we supposed to perform mission-critical work to reduce toil and make the system more reliable, when whenever this work is being carried out the team is interrupted and loses their focus?</p><p>The answer? Ducks.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/370/0*PdmEflNYe8ohcMsD.jpg" /></figure><h3>‘Duck duty’</h3><p>If you made it past the large image of the rubber duck and are still taking this article somewhat seriously, then I congratulate you! Bear with me.</p><p>Inspired by <a href="https://landing.google.com/sre/sre-book/chapters/dealing-with-interrupts/">Chapter 29 of the <em>SRE book</em></a>, and Cal Newport’s ‘<a href="https://www.amazon.co.uk/Deep-Work-Focused-Success-Distracted/dp/0349411905"><em>Deep Work</em></a>’, we’ve come up with a solution to the interrupt problem: ‘Duck duty’.</p><p>We’re currently a three-member team, and our on-call rotations last for one week each. What if the person who is on-call handles <em>all</em> interrupts for the entire week that they’re on call? Interrupts are almost always related to changes in the system, and changes in the system are responsible for incidents more than half of the time (some sources place this figure at around 80% of the time!). It makes sense for the on-call person to have the entire week’s context of change requests if they are to also deal with any incidents caused by them.</p><p>If you have a dedicated ‘interrupt person’, this frees up the other members of the team to get their heads down, focus, and truly achieve the ‘flow state’ of deep work — increasing productivity, and decreasing mistakes.</p><p>So, where does the duck come in? Well, Ash (one of our SREs) brought it into work one day and we thought it’d be a good idea if the interrupt person had it on their desk for the week they were on duty. It’s an easily noticable sign for everyone else in the office that this is the person to grab for any queries, and ‘duck duty’ is a lot more fun to say than ‘interrupt person’.</p><p>We’ve been using this system for just over two months now, and it’s working. Routing all interrupts through one person allows us handle the unending flow of toil while still allowing for quality engineering work to be carried out. If you’re having problems managing toil, get a duck!</p><p><em>Sidenote: no one’s replying to my emails asking for Glasswall-branded ducks. If you’re a rubber duck manufacturer and are reading this, please route all requests through the team member with the duck.</em></p><p>Look out for my next post that will go into more detail about our approach to planned work that reduces toil.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b338f3266494" width="1" height="1" alt="">]]></content:encoded>
        </item>
    </channel>
</rss>