Creating your production environment
Today marks a significant milestone as we transition our application to a production environment. While it may seem premature to deploy such a nascent application, I am a firm advocate of early production launches in typical development scenarios.
Outlined are the new tools introduced in blog post:
- Kubernetes 1.18.8: Our chosen computing platform for hosting microservices in production.
- Terraform 0.12.29: Utilized for scripting the creation of cloud resources and application infrastructure.
- Kubectl 1.18.6: A command-line tool for interacting with Kubernetes clusters.
- Azure CLI 2.9.1: Helps in authentication with Azure and provides Terraform access to our Azure account. This tool is also useful for managing Azure accounts and cloud resources.
The rationale for moving to production early, particularly when an application is still in its early stages, is compelling. By launching our application in a live environment, we expose it directly to our users. This exposure is crucial for gathering user feedback, which is invaluable for adapting our product to better meet user needs and for developing features that truly add value. Without this direct user engagement, we miss out on essential feedback. Moreover, having a deployment pipeline that supports rapid and reliable updates is our most effective tool for iterative experimentation and refinement, helping us to craft an exceptional product. Additionally, deploying while the application remains small simplifies the process. As the application grows, deployment challenges invariably increase, making early production deployment a strategic move.
Infrastructure as Code
In this chapter, we'll delve into a technique known as Infrastructure as Code (IaC), which will be pivotal in deploying our application to production. This method involves using code to automate the setup of infrastructure, contrasting with the manual, GUI-based approaches we explored in earlier blog post, such as with our private container registry.
Infrastructure as Code transforms the way we build and manage our setups. By writing and executing code, we can describe and construct our infrastructure with precision. This method ensures that our infrastructure can be created and recreated reliably and on demand. Where we use Terraform scripts directly from our development workstations to prototype our cloud infrastructure, including virtual machines and a Kubernetes cluster.
One of the fundamental benefits of Infrastructure as Code is that it acts as a form of executable documentation. This means it accurately reflects our infrastructure in a way that is always up-to-date, unlike traditional static documentation. It specifies how we want our infrastructure to appear and operates as a true reflection of our current setup.
Using a declarative approach, rather than a procedural one, Infrastructure as Code outlines the desired configuration and layout of our infrastructure without dictating the step-by-step procedures for achieving it. This allows our tools to optimize how changes are made, enhancing efficiency and effectiveness.
Why Kubernetes?
Kubernetes offers several compelling reasons for adoption, the most straightforward being its ability to prevent vendor lock-in. While many cloud providers offer their own container orchestration services, they also support Kubernetes as a managed service. This universal support makes Kubernetes an excellent choice for those seeking portability across different cloud environments.
Understanding at least the basics of Kubernetes is beneficial, as the skills are widely applicable. Even though we use Microsoft Azure to host our Kubernetes cluster in this book, the knowledge you gain can easily be applied to any cloud platform of your choice.
While Kubernetes is known for its complexity, especially when installing it on your own hardware or delving deep into its functionalities, managing a Kubernetes cluster on a cloud platform like Azure simplifies the process significantly. Instead of manual setups through a GUI, we will utilize Terraform code to create our cluster, enhancing both efficiency and scalability.
Kubernetes was developed by Google and later open-sourced, allowing the community to contribute and evolve its capabilities. It supports applications that require scaling in various ways, a topic we will explore further in future blog post. For now, our focus is on grasping the basics sufficient to set up a production cluster for deploying a microservices application.
One of the key features of Kubernetes is its automatable API, which we will leverage to construct an automated deployment pipeline in the upcoming chapters. As Kubernetes continues to set the standard for hosting microservices, its robust support, vibrant community, and extensive ecosystem of tools only enhance its appeal as a universal computing platform.
Kubernetes is open source, and its code is accessible on GitHub at: https://github.com/kubernetes/kubernetes. This openness and support across all major cloud platforms ensure that wherever your operations may take you, Kubernetes can be a part of that journey.
Creating Infrastructure with Terraform
We are now at the exciting stage where we begin to construct our infrastructure! While it's possible to build infrastructure manually using GUI tools provided by cloud vendors like the Azure portal, or through command line interfaces such as the Azure CLI, we will take a different approach in this blog post. We are going to automate the process using Infrastructure as Code, specifically utilizing Terraform. This approach not only ensures that the infrastructure setup is reliable and repeatable, but it also allows us to scale our application without proportionally increasing our manual tasks.
Terraform employs the Hashicorp Configuration Language (HCL), a declarative language that we will use to define our infrastructure setup. When we run this Terraform code, it will programmatically establish our infrastructure on the cloud. Moving forward, I will refer to HCL simply as Terraform code for simplicity.
Terraform is versatile, supporting multiple cloud platforms through its plugin providers system. In this blog post, our examples will focus on using Terraform for deploying infrastructure on Microsoft Azure.
For those new to HCL, it's helpful to remember that it is similar to YAML or JSON. Hashicorp designed HCL to be human-readable and easily translatable to YAML and JSON, making it approachable yet powerful for configuring infrastructure.
Terraform is an indispensable tool for configuring cloud-based applications. Its flexibility comes from the ability to extend its functionality through plugins, allowing it to support a variety of cloud vendors including Azure, AWS, and Google Cloud. This adaptability makes Terraform skills highly transferable across different cloud environments. Moreover, Terraform can even be extended to work with other platforms it doesn't yet support, through the creation of custom providers.
Additionally, Terraform's compatibility with Kubernetes enables us to use it for deploying containers to our clusters, integrating smoothly into our deployment pipeline. It acts as a comprehensive tool for scripting infrastructure, filling any gaps in functionality with our own enhancements if necessary. In the following blog post, I'll introduce a straightforward method to extend Terraform's capabilities to accommodate any aspects it might not currently cover.
Terraform positions itself as a universal configuration language, simplifying the creation of infrastructure across various platforms. It's open source, and its code can be accessed here: [Terraform GitHub Repository](https://github.com/hashicorp/terraform).
Scripting Infrastructure Creation
resource "azurerm_resource_group" "retaillooptube" {
name = "retaillooptube"
location = "West US"
}
We have taken the first steps in creating our infrastructure, We wrote a simple script that creates an Azure resource group. But before we invoke Terraform and execute this script, we must first intiialize terraform. To initialize terraform, we run the following command
terraform init
To build the infrastructure after initializing, run the following command
terraform apply
The next step is to create a private container tegistry. We’ll use this registry in the next chapter to publish Docker images for our microservices
resource "azurerm_container_registry"
"container_registry" {
name = "retaillooptube"
resource_group_name = azurerm_resource_group
.retaillooptube.name
location = "westus"
admin_enabled = true
sku = "Basic"
}
... code omitted here ...
run terraform apply to create the infrastructure
Creating our Kubernetes cluster
resource "azurerm_kubernetes_cluster" "cluster" {
name = var.app_name
location = var.location
resource_group_name = azurerm_resource_group.flixtube.name
dns_prefix = var.app_name
kubernetes_version = "1.18.8"
linux_profile {
admin_username = var.admin_username
ssh_key {
key_data = "${trimspace(tls_private_key.key.public_key_openssh)}
➥ ${var.admin_username}@azure.com"
}
}
default_node_pool {
name = "default"
node_count = 1
vm_size = "Standard_B2ms"
}
service_principal {
client_id = var.client_id
client_secret = var.client_secret
}
}
output "cluster_client_key" {
value = azurerm_kubernetes_cluster.cluster.kube_config[0].client_key
}
output "cluster_client_certificate" {
value = azurerm_kubernetes_cluster.cluster.kube_config[0]
➥ .client_certificate
}
output "cluster_cluster_ca_certificate" {
value = azurerm_kubernetes_cluster.cluster.kube_config[0]
➥ .cluster_ca_certificate
}
output "cluster_cluster_username" {
value = azurerm_kubernetes_cluster.cluster.kube_config[0].username
}
output "cluster_cluster_password" {
value = azurerm_kubernetes_cluster.cluster.kube_config[0].password
}
output "cluster_kube_config" {
value = azurerm_kubernetes_cluster.cluster.kube_config_raw
}
output "cluster_host" {
value = azurerm_kubernetes_cluster.cluster.kube_config[0].host
}
We are now set to deploy our Kubernetes cluster using our prepared Terraform scripts. To initiate the creation process, execute the following command:
terraform apply -auto-approve
Upon running this command, Terraform will request inputs for any variables that haven't been predefined. You'll first be prompted to provide a `client_id`:
var.client_id
Enter a value:
Here, you should input the `appId` of your service principal. Following that, Terraform will ask for the `client_secret`:
var.client_secret
Enter a value:
For this, enter the corresponding password for your service principal. With these credentials provided, Terraform will begin constructing your Kubernetes cluster. This process might take some time, so feel free to take a short break and perhaps grab a cup of coffee.
If you encounter any issues with the Kubernetes version number (1.18.8) specified in the code, it might be due to its unavailability on Azure.
Once the process completes, Terraform will display various output information that includes configuration and authentication details for your new cluster. Make sure to note down the following crucial values, which are necessary to interact with your Kubernetes cluster:
- `cluster_client_certificate`
- `cluster_client_key`
- `cluster_cluster_ca_certificate`
These credentials are essential for connecting to and managing your cluster effectively.
Conclusion
If you don’t want to wait for the whole series to end to get the knowledge, you can buy my ebook on gumroad => Microservices . To encourage to keep up the pace with writing this blog post, you can buy me coffee with the button below
Originally published on substack
Enjoyed this?
Subscribe to get new essays in your inbox.