<?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: J.D. Hollis</title>
    <description>The latest articles on DEV Community by J.D. Hollis (@jdhollis).</description>
    <link>https://dev.to/jdhollis</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%2F403393%2F69b00048-00f4-47d1-9970-ea45dcd0bd09.jpeg</url>
      <title>DEV Community: J.D. Hollis</title>
      <link>https://dev.to/jdhollis</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jdhollis"/>
    <language>en</language>
    <item>
      <title>Terraform for Teams</title>
      <dc:creator>J.D. Hollis</dc:creator>
      <pubDate>Tue, 30 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/jdhollis/terraform-for-teams-5c60</link>
      <guid>https://dev.to/jdhollis/terraform-for-teams-5c60</guid>
      <description>&lt;p&gt;A lot of my work over the past few years has involved introducing Terraform into teams that are unfamiliar with both Terraform and the AWS resources we’re building with. The challenge throughout has been to train each developer while ensuring high team productivity by delivering working software. I have not always been successful, but I’ve learned a thing or two along the way.&lt;/p&gt;

&lt;p&gt;Terraform has changed a lot since I started using it back at the end of 2016. Getting into a technology early is like stepping on a treadmill—you’re going to have to work to stay in the same place. How can you introduce this technology into a working team while buffering them from the treadmill effect?&lt;/p&gt;

&lt;p&gt;Also, when you’re &lt;a href="https://theconsultingcto.com/posts/continuous-delivery-with-terraform/#programming-with-infrastructure"&gt;programming with infrastructure&lt;/a&gt; you can’t just spin up a local instance of a &lt;a href="https://theconsultingcto.com/posts/continuous-delivery-with-terraform/#services"&gt;service&lt;/a&gt; for a developer. Everything has to be built in the cloud. How can you make it easy for developers to create working environments for themselves? And how can you prevent developers working on the same service from stepping on each other’s toes?&lt;/p&gt;

&lt;p&gt;Finally, Terraform is not prescriptive in how to architect your infrastructure. This is probably the single hardest thing for developers to overcome when they start working with Terraform. Terraform provides a lot of primitives, but it’s up to you to assemble them. How can you create a coherent architecture shared across services that a developer will find familiar even as they move from service to service?&lt;/p&gt;

&lt;p&gt;Well, &lt;a href="https://github.com/jdhollis/fenna/blob/master/fenna"&gt;I wrote a script for that&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing Fenna
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/jdhollis/fenna"&gt;&lt;code&gt;fenna&lt;/code&gt;&lt;/a&gt; is a thin wrapper for Terraform built around &lt;a href="https://github.com/jdhollis/fenna#conventions"&gt;a set of conventions&lt;/a&gt; extracted from my experience introducing Terraform into teams. It simplifies &lt;a href="https://www.terraform.io/docs/backends/index.html"&gt;backend management&lt;/a&gt; and &lt;a href="https://github.com/jdhollis/fenna#onboard"&gt;developer onboarding&lt;/a&gt; while not being overly prescriptive in how you structure your Terraform or your architecture.&lt;/p&gt;

&lt;p&gt;I have more to share on how to apply &lt;code&gt;fenna&lt;/code&gt; to your work, but in the meantime, &lt;a href="https://github.com/jdhollis/fenna"&gt;give it a try&lt;/a&gt; and &lt;a href="https://github.com/jdhollis/fenna/issues/new"&gt;open an issue&lt;/a&gt; if you have any questions.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>serverless</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Continuous Delivery with Terraform</title>
      <dc:creator>J.D. Hollis</dc:creator>
      <pubDate>Tue, 09 Jun 2020 00:00:00 +0000</pubDate>
      <link>https://dev.to/jdhollis/continuous-delivery-with-terraform-2ohp</link>
      <guid>https://dev.to/jdhollis/continuous-delivery-with-terraform-2ohp</guid>
      <description>&lt;p&gt;When I first started consulting with &lt;a href="https://nuid.io"&gt;NuID&lt;/a&gt; almost 2 years ago, one of our objectives was to bake DevOps into the culture. Given our choice to rely heavily on serverless to keep initial costs down, it was essential for the team to be much more intimate with AWS and operations than is typical for developers working exclusively in their language of choice. Instead of building services that run on top of a shared infrastructure, NuID’s AWS resources are inseparable from the code utilizing them. This has significant implications for how NuID delivers software.&lt;/p&gt;

&lt;h2&gt;
  
  
  Services
&lt;/h2&gt;

&lt;p&gt;So, what is a service?&lt;/p&gt;

&lt;p&gt;A service is a collection of AWS resources and code that fulfills a desired function. It has a well-defined interface that other services and users can interact with. And it is something we want to deploy and test as a unit.&lt;/p&gt;

&lt;p&gt;Defining a service in this way makes it easier to evolve the architecture over the long term. If a service provides a consistent interface, it can be rearchitected internally as needed. For example, it could be migrated from (potentially many) Lambda functions to a shared EKS cluster without impacting customers or dependent services.&lt;/p&gt;

&lt;p&gt;NuID uses &lt;a href="https://www.terraform.io"&gt;Terraform&lt;/a&gt; to manage its infrastructure. Each service has its own Terraform state to maintain isolation and minimize blast radius. Each service also has its own pipeline (with the exception of some shared services that don’t change all that often or should only be changed with special care). Terraform enables NuID to maintain consistency from &lt;code&gt;dev&lt;/code&gt; to &lt;code&gt;stage&lt;/code&gt; to &lt;code&gt;prod&lt;/code&gt;, eliminating “works on my machine” issues and simplifying integration across services.&lt;/p&gt;

&lt;h2&gt;
  
  
  Continuous Delivery
&lt;/h2&gt;

&lt;p&gt;We wanted to instill continuous delivery in NuID’s culture from the start. We began with the principle that any code in &lt;code&gt;master&lt;/code&gt; can go live in &lt;code&gt;prod&lt;/code&gt; at any time. This requires developers to consider the operational impact of anything they push to &lt;code&gt;master&lt;/code&gt;, both in terms of the service they’re working on and other dependent services. Following from this principle, code review, testing, and monitoring are essential—no one wants to break the build.&lt;/p&gt;

&lt;p&gt;NuID uses the &lt;a href="https://guides.github.com/introduction/flow/"&gt;GitHub flow&lt;/a&gt; model with the exception that feature branches aren’t deployed into production for testing. Instead, pull requests are reviewed in &lt;code&gt;dev&lt;/code&gt; by spinning up a unique instance of the service from the feature branch. This is valuable both for testing and for soliciting feedback from other stakeholders.&lt;/p&gt;

&lt;p&gt;Integration testing amongst services happens in &lt;code&gt;stage&lt;/code&gt;. &lt;code&gt;stage&lt;/code&gt; and &lt;code&gt;prod&lt;/code&gt; are kept nearly identical. Excluding questions of scale, if a service works in &lt;code&gt;stage&lt;/code&gt;, it will likely work in &lt;code&gt;prod&lt;/code&gt;. This consistency simplifies the code and increases confidence in a given release.&lt;/p&gt;

&lt;p&gt;Each environment is maintained in a separate AWS account. Developers are only able to deploy directly to &lt;code&gt;dev&lt;/code&gt;. Deployment to &lt;code&gt;stage&lt;/code&gt; and &lt;code&gt;prod&lt;/code&gt; is only possible via a service’s pipeline. This restriction eliminates the risks of environmental drift and “&lt;a href="https://www.youtube.com/watch?v=-Gh1lTcwdGY"&gt;doing it live&lt;/a&gt;”.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;“I can’t imagine a more ideal approach for the way I want to work. Our decision budget is tight—Clojure, Terraform, AWS. And with our infrastructure as code, every seam is exposed. With this approach, I feel like there isn’t anything we couldn’t build rapidly.”&lt;/p&gt;


— &lt;cite&gt;&lt;a href="https://www.linkedin.com/in/notalwaysgray/"&gt;Nolan Smith&lt;/a&gt;, CTO of NuID&lt;/cite&gt;

&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Developer Experience
&lt;/h2&gt;

&lt;p&gt;NuID is primarily a &lt;a href="https://clojure.org"&gt;Clojure&lt;/a&gt; shop, so enabling &lt;a href="https://clojure.org/guides/repl/introduction"&gt;REPL-driven development&lt;/a&gt; was a priority. Interactive development is one of the keys to a Clojure developer’s productivity, so access to AWS resources from the REPL is essential.&lt;/p&gt;

&lt;p&gt;Because the AWS resources are inseparable from NuID’s code, it’s not possible to create a self-contained environment on a developer’s individual machine. Instead, we’ve created shell scripts wrapping Terraform that enable a developer to easily spin up a unique instance of any service in &lt;code&gt;dev&lt;/code&gt;. This developer interface to Terraform is shared across all services, keeping the developer experience consistent and making it easier for a small team to maintain multiple services. This tooling also makes it easy for developers to rapidly develop new services.&lt;/p&gt;

&lt;p&gt;NuID’s infrastructure is treated as immutable, so there’s no need to SSH into a particular box to make changes. However, some resources such as private APIs on API Gateway and Elasticsearch clusters are not accessible directly from the internet (with good reason). To facilitate developer access from the REPL, we created &lt;a href="https://theconsultingcto.com/posts/bastions-on-demand/"&gt;an on-demand bastion service&lt;/a&gt; for securely proxying to resources within a particular VPC. Bastion instances are locked to a particular developer and are kept running only while in use to minimize attack surface.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deployment
&lt;/h2&gt;

&lt;p&gt;Because the infrastructure and code are inseparable, NuID’s pipelines plan and apply Terraform. If you’d like to see what this looks like in action, check out my &lt;a href="https://github.com/jdhollis/pipeline-example"&gt;&lt;code&gt;pipeline-example&lt;/code&gt;&lt;/a&gt;. This ensures consistency across the environments, minimizing unexpected behavior. It also facilitates integration testing across services.&lt;/p&gt;

&lt;p&gt;While Terraform is not intended or recommended for orchestration, it works well enough for NuID on deployment of Lambdas and, with judicious use of &lt;a href="https://www.terraform.io/docs/providers/null/resource.html"&gt;&lt;code&gt;null_resource&lt;/code&gt;&lt;/a&gt;, &lt;a href="https://theconsultingcto.com/posts/datomic-with-terraform/#datomic-ions"&gt;Datomic ions&lt;/a&gt;. The same approach can be used for deploying containers if a service requires it, providing NuID with a lot of flexibility to evolve services going forward.&lt;/p&gt;

&lt;h2&gt;
  
  
  Programming with Infrastructure
&lt;/h2&gt;

&lt;p&gt;As I’ve previously written, &lt;a href="https://theconsultingcto.com/posts/maximize-velocity-by-minimizing-risk/"&gt;the best code is no code&lt;/a&gt;. If you can diffuse your logic into the infrastructure declaratively, that’s less code for your team to maintain.&lt;/p&gt;

&lt;p&gt;Maintaining portability between cloud environments is a white elephant. For a small team, it’s better to take advantage of your chosen cloud provider as much as possible.&lt;/p&gt;

&lt;p&gt;Overall, this approach has given NuID the ability to grow its headcount slowly and deliberately while maintaining high productivity and keeping costs low without foreclosing the future evolution of the platform.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>serverless</category>
      <category>terraform</category>
    </item>
    <item>
      <title>Bastions on Demand</title>
      <dc:creator>J.D. Hollis</dc:creator>
      <pubDate>Mon, 08 Jun 2020 16:13:59 +0000</pubDate>
      <link>https://dev.to/jdhollis/bastions-on-demand-31o4</link>
      <guid>https://dev.to/jdhollis/bastions-on-demand-31o4</guid>
      <description>&lt;p&gt;Hi, all.&lt;/p&gt;

&lt;p&gt;I recently wrote up an in-depth guide on how to dynamically create bastions for accessing resources within a VPC on AWS: &lt;a href="https://theconsultingcto.com/posts/bastions-on-demand/"&gt;https://theconsultingcto.com/posts/bastions-on-demand/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Bastions can be handy for securely proxying to resources such as Elasticsearch clusters, private APIs, and pretty much any AWS resource you might want to develop against from your local environment.&lt;/p&gt;

&lt;p&gt;The guide covers a lot of ground, so if you have any questions, hit me up here in the comments.&lt;/p&gt;

</description>
      <category>aws</category>
      <category>devops</category>
      <category>serverless</category>
      <category>security</category>
    </item>
  </channel>
</rss>
