28,79 €
The Infrastructure as Code (IaC) approach ensures consistent and repeatable deployment of cloud-based IaaS/PaaS services, saving you time while delivering impeccable results. Infrastructure as Code for Beginners is a practical implementation guide that helps you gain a clear understanding of the foundations of Infrastructure as Code and make informed decisions when implementing it.
With this book, you’ll uncover essential IaC concepts, including planning, selecting, and implementing the right tools for your project. With step-by-step explanations and real-world examples, you'll gain a solid understanding of the benefits of IaC and the scope of application in your projects. You'll learn about the pros, cons, and best practices of different IaC tools such as Terraform and Ansible, and their use at different stages of the deployment process along with GitHub Actions. Using these tools, you'll be able to design, deploy, and secure your infrastructure on two major cloud platforms, Microsoft Azure and Amazon Web Services. In addition, you'll explore other IaC tools such as Pulumi, AWS CloudFormation, and Azure Bicep.
By the end of this book, you’ll be well equipped to approach your IaC projects confidently.
Das E-Book können Sie in Legimi-Apps oder einer beliebigen App lesen, die das folgende Format unterstützen:
Seitenzahl: 270
Veröffentlichungsjahr: 2023
Deploy and manage your cloud-based services with Terraform and Ansible
Russ McKendrick
BIRMINGHAM—MUMBAI
Copyright © 2023 Packt Publishing
All rights reserved. No part of this book may be reproduced, stored in a retrieval system, or transmitted in any form or by any means, without the prior written permission of the publisher, except in the case of brief quotations embedded in critical articles or reviews.
Every effort has been made in the preparation of this book to ensure the accuracy of the information presented. However, the information contained in this book is sold without warranty, either express or implied. Neither the author, nor Packt Publishing or its dealers and distributors, will be held liable for any damages caused or alleged to have been caused directly or indirectly by this book.
Packt Publishing has endeavored to provide trademark information about all of the companies and products mentioned in this book by the appropriate use of capitals. However, Packt Publishing cannot guarantee the accuracy of this information.
Group Product Manager: Preet Ahuja
Publishing Product Manager: Surbhi Suman
Senior Content Development Editor: Adrija Mitra
Technical Editor: Nithik Cheruvakodan
Copy Editor: Safis Editing
Project Coordinator: Ashwin Kharwa
Proofreader: Safis Editing
Indexer: Subalakshmi Govindhan
Production Designer: Prashant Ghare
Marketing Coordinator: Agnes D’souza
First published: May 2023
Production reference: 1110523
Published by Packt Publishing Ltd.
Livery Place
35 Livery Street
Birmingham
B3 2PB, UK.
978-1-83763-163-6
www.packtpub.com
Russ McKendrick is an experienced DevOps practitioner and system administrator with a passion for automation and containers. He has been working in IT and related industries for the better part of 30 years. During his career, he has had responsibilities in many different sectors, including first-line, second-line, and senior support in client-facing and internal teams for small and large organizations.
He works almost exclusively with Linux, using open source systems and tools across dedicated hardware and virtual machines hosted in public and private clouds at Node4, where he holds the title of practice manager (SRE and DevOps). He also buys way too many records!
I would like to thank my family and friends for their support and for being so understanding about all of the time I have spent in front of the computer writing. I would also like to thank my colleagues at Node4 and our customers for their kind words of support and encouragement throughout the writing process.
Adam Hooper has nearly a decade of experience in cloud computing and has held various roles within MSPs and CSPs. Adam started as a support technician initially supporting Citrix and Hyper-V environments and then moved to provide support to customers’ critical Azure environments. He now works as a platform engineer for Node4, where he spends most of his time deploying resources with Terraform and Azure DevOps.
Outside of work, Adam enjoys motorcycles, spending time with his wife, Hannah, and their two cats, spending time with family, and drinking copious amounts of whiskey.
I would like to thank Russ McKendrick for giving me the opportunity to review this book. It’s been a great experience and hopefully the first of many.
Welcome to Infrastructure as Code for Beginners, your guide to managing and deploying your infrastructure through code. This book will equip you with a strong foundation in the essential concepts, tools, and techniques necessary to succeed in this ever-changing landscape.
Throughout the chapters, you will gain hands-on experience with popular Infrastructure-as-Code tools such as Terraform and Ansible, learn how to plan and deploy resources across leading public cloud providers such as Microsoft Azure and Amazon Web Services, and delve into best practices and troubleshooting strategies to help you overcome challenges and optimize your deployments.
As you progress through the book, you’ll also explore the role of Continuous Integration and Continuous Deployment (CI/CD) in automating your Infrastructure-as-Code projects using GitHub Actions. You’ll learn how to leverage CI/CD to create consistent and reliable deployments and implement security practices to secure your deployments.
Furthermore, you’ll expand your Infrastructure-as-Code toolset by exploring alternative tools such as Pulumi, Azure Bicep, and AWS CloudFormation, enhancing your understanding of provider-specific and cloud-agnostic options.
By the end of this journey, you’ll have gained the knowledge and confidence to plan, build, deploy, and manage your Infrastructure-as-Code projects enabling you to create efficient, scalable, and reliable infrastructure solutions that will support your projects and career for years to come.
This book is tailored for Developers and System Administrators who have experience of manually deploying resources to host their applications but now want to increase their skills by automating the creation and management of infrastructure alongside their applications.
This book will empower readers who, while having a great deal of experience deploying and configuring their resources manually, now want to streamline their processes, enhance efficiency and consistency, and integrate Infrastructure as Code into their daily workflows.
In Chapter 1, Choosing the Right Approach – Declarative or Imperative, we introduce fundamental Infrastructure-as-Code concepts, covering the challenges of manual infrastructure management, declarative versus imperative approaches, and the pets versus cattle analogy, setting the stage for understanding its importance in modern deployments.
In Chapter 2, Ansible and Terraform beyond the Documentation, we delve into Terraform, an Infrastructure-as-Code tool by HashiCorp, and Ansible, a configuration management tool by Red Hat. We will explore tool selection criteria, be introduced to Terraform and Ansible, and review some guidance on using Visual Studio Code as an IDE for writing code, including some recommended extensions.
InChapter 3, Planning the Deployment, we highlight the importance of planning in your Infrastructure-as-Code deployments. You will be introduced to the workload to be deployed, learn about deployment approaches, and explore a step-by-step guide for efficient and error-free execution. We will also examine the high-level infrastructure architecture, preparing us for our upcoming Azure and AWS deployment.
In Chapter 4, Deploying to Microsoft Azure, we explore deploying our project to Microsoft Azure, one of the two major public cloud providers covered in this book. Topics include introducing Azure, preparing the cloud environment, creating the low-level design, and using Terraform and Ansible for writing and deploying the infrastructure code.
In Chapter 5, Deploying to Amazon Web Services, we move onto deploying the project to Amazon Web Services (AWS) while highlighting the key differences between Azure and AWS. We will delve deeper into Ansible for deployment and gain insights into using both Ansible and Terraform for managing AWS resources. By the end of the chapter, you will understand how to adapt your deployment approach for different cloud providers.
In Chapter 6, Building upon the Foundations, we delve into the nuances of deploying high-level designs across public cloud providers using cloud-agnostic tools such as Terraform and Ansible. We will learn from my experiences of addressing variations between providers, exploring practical approaches for creating repeatable deployment processes, and looking at the importance of modular code, allowing for streamlined deployment efforts and code reusability.
In Chapter 7, Leveraging CI/CD in the Cloud, we will now focus on using CI/CD to automate infrastructure deployment. We will explore GitHub Actions, a popular CI/CD tool, and learn how to use it to run Terraform and Ansible code for both Azure and AWS.
In Chapter 8, Common Troubleshooting Tips and Best Practices, we will learn essential strategies for planning, writing, and troubleshooting Infrastructure-as-Code projects. The chapter covers best practices and troubleshooting tips for Infrastructure as Code in general and specific guidance for Terraform and Ansible. By understanding the unique challenges associated with each tool, you will be better prepared to handle obstacles that may arise during your Infrastructure-as-Code journey.
In Chapter 9, Exploring Alternative Infrastructure-as-Code Tools, we will expand our Infrastructure-as-Code toolset by exploring three additional tools: Pulumi, Azure Bicep, and AWS CloudFormation. The chapter aims to provide hands-on understanding and knowledge of these tools, highlighting the differences between cloud-agnostic and provider-specific tools and showcasing Pulumi’s unique approach using familiar programming languages.
Before starting, you should understand how you would approach and deploy the infrastructure to support one or more of your existing applications. Ideally, this infrastructure would be hosted in either Microsoft Azure or Amazon Web Services.
While this is optional, the book has been written with the assumption that you have a basic understanding of either Microsoft Azure or Amazon Web Services and some of the core services’ basic concepts, such as networking or virtual machines. While this is not essential, you may have to do some further reading about why we approached tasks in a certain way regarding some of the more hands-on chapters.
We also assume that you would like to follow along with some of the more practical chapters; therefore, having credits or access to a Microsoft Azure or Amazon Web Services account that isn’t used to host production resources is a bonus.
Software/hardware covered in the book
Operating system requirements
Terraform
Windows, macOS, or Linux
Ansible
Windows, macOS, or Linux
The Microsoft Azure CLI and portal
Windows, macOS, or Linux
The Amazon Web Services CLI and portal
Windows, macOS, or Linux
Pulumi
Windows, macOS, or Linux
Visual Studio Code
Windows, macOS, or Linux
There are links to the installation instructions for each tool in the further reading section of the respective chapters.
If you are using the digital version of this book, we advise you to type the code yourself or access the code from the book’s GitHub repository (a link is available in the next section). Doing so will help you avoid any potential errors related to the copying and pasting of code.
Finally, feel free to experiment; check out the code accompanying this book and make changes. However, keep an eye on spending and always ensure that you terminate any resources you deploy after you have finished to avoid any unexpected and unwanted costs.
You can download the example code files for this book from GitHub at https://github.com/PacktPublishing/Infrastructure-as-Code-for-Beginners. If there’s an update to the code, it will be updated in the GitHub repository.
We also have other code bundles from our rich catalog of books and videos available at https://github.com/PacktPublishing/. Check them out!
We also provide a PDF file that has color images of the screenshots and diagrams used in this book. You can download it here: https://packt.link/uvP61.
There are a number of text conventions used throughout this book.
Code in text: Indicates code words in text, database table names, folder names, filenames, file extensions, pathnames, dummy URLs, user input, and Twitter handles. Here is an example: “The first three lines, name, runtime, and description, all define some basic meta information about our deployment.”
A block of code is set as follows:
name: pulumi-yaml runtime: yaml description: A minimal Azure Native Pulumi YAML program outputs: primaryStorageKey: ${storageAccountKeys.keys[0].value}Any command-line input or output is written as follows:
$ pulumi up -c Pulumi.dev.yamlBold: Indicates a new term, an important word, or words that you see onscreen. For instance, words in menus or dialog boxes appear in bold. Here is an example: “The final step is to review your stack before clicking the Submit button, triggering the stack creation.”
Tips or important notes
Appear like this.
Feedback from our readers is always welcome.
General feedback: If you have questions about any aspect of this book, email us at [email protected] and mention the book title in the subject of your message.
Errata: Although we have taken every care to ensure the accuracy of our content, mistakes do happen. If you have found a mistake in this book, we would be grateful if you would report this to us. Please visit www.packtpub.com/support/errata and fill in the form.
Piracy: If you come across any illegal copies of our works in any form on the internet, we would be grateful if you would provide us with the location address or website name. Please contact us at [email protected] with a link to the material.
If you are interested in becoming an author: If there is a topic that you have expertise in and you are interested in either writing or contributing to a book, please visit authors.packtpub.com.
Once you’ve read Infrastructure as Code for Beginners, we’d love to hear your thoughts! Please click here to go straight to the Amazon review page for this book and share your feedback.
Your review is important to us and the tech community and will help us make sure we’re delivering excellent quality content.
Thanks for purchasing this book!
Do you like to read on the go but are unable to carry your print books everywhere? Is your eBook purchase not compatible with the device of your choice?
Don’t worry, now with every Packt book you get a DRM-free PDF version of that book at no cost.
Read anywhere, any place, on any device. Search, copy, and paste code from your favorite technical books directly into your application.
The perks don’t stop there, you can get exclusive access to discounts, newsletters, and great free content in your inbox daily
Follow these simple steps to get the benefits:
Scan the QR code or visit the link belowhttps://packt.link/free-ebook/978-1-83763-163-6
Submit your proof of purchaseThat’s it! We’ll send your free PDF and other benefits to your email directlyIn this part, we will discuss how you can approach your Infrastructure-as-Code journey, using my own as a starting point, before exploring some of the core principles of infrastructure as code.
We will also look at the tools we will be using to deploy our example workload and planning the deployment of the workload itself.
This part has the following chapters:
Chapter 1, Choosing the Right Approach – Declarative or ImperativeChapter 2, Ansible and Terraform beyond the DocumentationChapter 3, Planning the DeploymentWelcome to the first chapter of Infrastructure as Code for Beginners. In this book, we will be going on a journey that will take you through your first Infrastructure-as-Code deployment, and it is an honor to be accompanying you.
Before we dive into the tools we will be using throughout the book, we are first going to discuss some of the key concepts to try and get an understanding of the problems that you could try to solve by introducing Infrastructure as Code into your deployments.
We will be covering the following topics:
The challenges of managing infrastructure manuallyWhat is meant by declarative and imperative?Pets versus cattleWhat does all this mean for our Infrastructure-as-Code deployments?Before we look at some of the challenges you may be facing, I quickly wanted to take you through my journey with Infrastructure as Code before it was really what we now know as Infrastructure as Code.
When I talk about Infrastructure as Code, I mean the following:
Infrastructure as Code is an approach to infrastructure management where it is provisioned and managed using code and automation tools rather than manually configuring resources through a user interface.
This allows you to version control, track, and manage your infrastructure in the same way you do with application code and, in many cases, use the same tooling, processes, and procedures you already have in place.
Infrastructure as Code can help improve your infrastructure operations’ efficiency, reliability, and reproducibility by introducing consistency across your deployments and reducing deployment times versus more traditional manual deployments.
I have been working with servers of all types for longer than I care to remember; back when I first started working with servers, it was all very much a manual process to do pretty much anything.
Before virtualization became a common practice, I remember having to block out a whole day to build a customer’s server. This process would generally start with ensuring that the hardware I was given to work with was of the correct specification – if for some reason it wasn’t, which was quite common, then I would typically have to replace RAM and hard drives, and so on.
This was to ensure that I didn’t get too far into configuring the server, only to find that I had to tear it down and start from scratch; once the hardware was confirmed as being correct, it was time to start on the build itself.
Typically, to build the server, I sat in a tiny, hot, and noisy build room surrounded by equipment, bits of computer, and what felt like reams of paper, which contained not only instructions on how to manually install the various operating systems we supported but also build sheets containing configuration and information on the customer’s required software stack I was deploying.
Once built, the server was packed back into its box, put in the back of someone’s car, and taken to a data center. From there the server was racked and cabled for both power and networking and then powered the server on – if everything was configured correctly, it would spring into life and be available on the network.
After some quick testing, it was back to the comfort of the office to complete the build steps and, finally, hand the server over to the customer for them to deploy their software on.
While this process was fine when there was one or two of these deployments, once in a blue moon, as things got busier, it quickly became unmanageable.
The next logical step was to have a build server that contained drive images for all the supported operating systems and base software stack configurations, with some custom scripts that ran when the server first booted to customize the base configuration and get it onto the network when the server was racked in the data center.
Once we started to move from provisioning bare metal servers for customers to virtualized servers, things got a lot easier – for a start, as you didn’t have to physically connect RAM, CPUs, or hard drives to the servers, assuming the cluster you were building the server in had the resource available, it made quite a dramatic change to the deployment time and also resulted in less time in the build room and data center.
At this point, we had built up a collection of custom scripts that connected to both the virtualization hypervisors and virtual machines – these were shared between the team members in our subversion repository and documented in our internal wiki.
This was my first, extremely basic by today’s standards, introduction to Infrastructure as Code.
The next logical steps were to add a remote configuration into the mix by using a tool, such asPuppet or Chef; we could deploy our virtual machines using our custom scripts and then have the servers call back to our main management server, and then bootstrap itself as per the customer’s desired configuration state.
This was the final piece of the puzzle, which took our deployments from taking a few days per server to an hour or so, with the bulk of that time waiting for automated tasks to complete – though, as a lot of the initial stages of the deployments were initiated by our in-house DIY scripts, we still had to keep a careful eye on the progress.
This was because there wasn’t much logic built in to handle errors or other unexpected hiccups during the deployment, which, in some cases, resulted in some challenging post-deployment problems – but the least said about those, the better.
So, how do today’s challenges differ from my own experiences? During my day job, I get to work with a lot of internal and external teams who are nearly all technical and are very hands-on with the day-to-day management and development of their own applications.
When discussing Infrastructure as Code with teams, one of the most common answers I get is as follows:
“We have the process to deploy our infrastructure documented, and anyone in the team can work through it to quickly deploy a resource.”
While it is great that there is documentation and that it is accessible by all of the members of the team, you would be surprised, even with the presence of comprehensive and easy-to-follow documentation, at just how much variance there is when people come to actually implement it. They don’t fully understand it because it is simply a set of tasks that lack any context as to why the tasks are being actioned.
Another potential issue is that the process is followed so often by a member of the team that they simply just get on with it, missing any updates or steps that have been added to the documentation.
Worst still – and this is more common than you may think – giving three technical people the same set of tasks to do can sometimes result in three very different outputs, as everyone has different experiences, which normally feeds into how we do things – for example, last time I tried to A, B, and C, X happened, so now I do it C, B, and A or I think it would better to do it B, A, and then C – but don’t have time at the moment to update the documentation.
All of these can introduce inconsistencies in your deployments, which may go unnoticed as everyone thinks they are doing it correctly because they are all following the same set of documentation.
The next (pun very much intended) answer I normally get is this:
“We don’t need to do it very often, and when we do, it’s just clicking ‘next, next, next’ in an interface – anyone can do it.”
When I get this answer, what I actually hear is, The process to deploy the resource is so easy that we didn’t bother to document it. While this might be the case for some members of the team, not everyone may have the experience or confidence to simply click next, next, next to deploy and configure the resources without a guide.
As I am sure you can imagine, if it is possible for inconsistencies to be present when everyone is following the same set of documentation, then doing the deployment without any of the guardrails that the documentation puts in place is going to introduce even more potential issues further down the line.
Just because a resource has been deployed without error and works does not mean that it has been deployed securely and in such a way that could support your production workloads.
The final most common answer when discussing Infrastructure as Code is as follows:
“We have deployed everything we need and don’t need any further resources.”
Again, when I get this answer, I normally hear something slightly different – in my experience, this normally means that, a while ago, someone deployed something that is more than capable of the task and has now moved on, either going on to another project or department or has left the company altogether.
While it is great that the resources are running fine, this approach can cause issues if you ever need to redeploy or, worse still, firefight an issue with production, as a lot of knowledge of the underlying configuration is missing.
So, while you know what’s there, you may not necessarily know why.
There are many more examples, but the previous ones are the most common ones I see when working with teams who may not have considered Infrastructure as Code to be a foundation of their deployment pipelines, and if you are reading this, then you may have already come across some of the examples and want to move onto the next step.
So why would you take an Infrastructure-as-Code approach to your deployments? Well, there are several reasons, which include the following:
Documentation: While we have already mentioned documentation, it’s important to note that if you employ Infrastructure as Code, your deployment is documented as part of your code as it defines the desired state of your infrastructure in a human-readable format.Repeatable and consistent: You should be able to pick up your code and deploy it repeatedly – sure, you may make some changes to things such as resource SKUs and names, but that should just be a case of updating some variables that are read at the time of execution rather than rewriting your entire code base.Time-saving: As I mentioned, in my own experience, it sometimes took days to deploy resources – eventually, that got down to hours and, with more modern cloud-based resources, minutes.Secure: Because you have your infrastructure defined in code, you know that you will have a well-documented end-to-end configuration ready to review as needed. Because it is easily deployable, you can quickly spin up an environment to review or deploy your latest fixes into, safe in the knowledge that it is consistent with your production configuration, as you are not relying on someone manually working through a step-by-step document where something may get missed or misinterpreted.Cost savings: I think you should never approach an Infrastructure-as-Code deployment with cost savings being at the top of the list of things you would like to achieve – but it is a most welcome nice-to-have. Depending on your approach, cost savings can be a byproduct of the preceding points. For example, do you need to run your development or testing infrastructure 24/7 when your developers may only need it for a few days a week at most?Well, that infrastructure can be deployed as part of your build pipeline with next to no or little effort. In that case, you may find yourself in the enviable position of only paying for the resources when you need them rather than paying for them to be available 24/7.
So, now that we have discussed my personal journey with Infrastructure as Code and also gotten an idea of the different scenarios where Infrastructure as Code may come in useful and the potential reasons why you would want to incorporate it into your day-to-day workflows, let’s now discuss some of the basic concepts you need to know about before we start to talk about the tools we are going to look at for the remainder of the book.
In programming, there are different ways to give instructions to a computer to achieve the programmer’s desired result. These ways of telling the computer what to do are known as programming paradigms.
In general, they refer to how we build programs from logical ideas such as if statements or loops. There are other classifications as well: functional, structured, object-oriented, and so on. Each of these describes a different kind of task that programmers might perform when writing code or thinking about code.
Imperative and declarative programming is the most fundamental way in which programmers think about defining their tasks and the two main ways in which we need to think about how we write and structure our Infrastructure as Code.
Before we discuss each way, let us define a quick Infrastructure-as-Code project.
The following diagram shows the basic infrastructure for deploying a single virtual machine in Microsoft Azure:
Figure 1.1 – The basic Infrastructure-as-Code project diagram
As you can see, the project is made up of the following components:
Resource group (rg-iac-example-uks-001) – This is a logical container in Azure to store the resources.Virtual network (vnet-iac-example-uks-001) – This is a virtual network that will host our example virtual machine.Subnet (snet-iac-example-uks-001) – This is not shown in the diagram, but the virtual network contains a single subnet.Network Security group (nsg-iac-example-uks-001) – As we don’t want management ports such as 3389 (RDP) or 22 (SSH) open to anyone on the internet, this will add some basic rules to only accept traffic on these ports from trusted sources. This will be attached to the subnet, so the rules apply to all resources deployed there.Virtual machine (vm-iac-example-uks-001) – This, as you may have guessed, is the virtual machine itself.Network interface (nic-iac-example-uks-001) – Here, we have the network interface, which will be attached to the virtual machine and the subnet within the virtual network.Public IP address (pip-iac-example-uks-001) – Finally, we have the public IP address; this is going to be attached to the network interface, which will allow us to route to the virtual machine from the trusted locations defined in the networksecurity group.While this is a basic infrastructure example, there are quite a few different resources involved in the deployment. Also, as we are going to be talking at a very high level about how this could be deployed, we won’t be going into too much detail on Azure itself just yet, as this will be covered in Chapter 4, Deploying to Microsoft Azure.
When talking about my own experiences, I mentioned that I used a configuration tool; in my case, this was Puppet. Puppet uses declarative language to define the target configuration – be it a software stack or infrastructure – but what does that mean?
Rather than try and give an explanation, let’s jump straight in and describe how a declarative tool would deploy our infrastructure.
In its most basic configuration, a declarative tool only cares about the end state and not necessarily how it gets to that point. This means the tool, unless it is told to be, isn’t resource-aware, meaning