iac脚本

    科技2025-03-20  27

    iac脚本

    Hy guys, how are you? I hope you’re all doing fine.

    嗨,大家好。 希望你们一切都好。

    It has been a while since I wrote in here, so please, just bare with me. I’ve been studying a lot recently and doing several labs and PoC’s. And today I’d like to share one with you.

    自从我在这里写信已经有一段时间了,所以请随便露面。 我最近一直在学习很多东西,并做了一些实验室和PoC。 今天,我想与您分享一个。

    I wanted to test my Terraform code, just to check if everything would go up according to what was planned.

    我想测试我的Terraform代码,只是为了检查一切是否按照计划进行。

    So I was looking in the Internet and found out about Terratest. I really encourage you to read and study this, it is a great tool and it is so easy to get the hang of it.

    因此,我在Internet上寻找有关Terratest的信息。 我真的鼓励您阅读和研究它,它是一个很好的工具,很容易掌握它。

    In this first part, I want to discuss my Terraform code, the way I did it and why I did it. I’d like to make some considerations and talk about IaC in general.

    在第一部分中,我要讨论我的Terraform代码,执行方式以及执行原因。 我想作一些考虑,并大致讨论IaC。

    In the second part, I’ll cover the testing and how we could create a pipeline in order to achive IaC as a whole development process.

    在第二部分中,我将介绍测试以及如何创建管道以实现IaC整个开发过程。

    The GitHub repository is right here, you can take a look if you want, share it, be inspired by it. Just let you imagination flow.

    GitHub存储库就在这里,您可以看一下是否要共享它,并从中得到启发。 只是让您发挥想像力。

    架构 (The Architecture)

    From the beggining I wanted to try something new, I found about this Python Library which is amazing. It let’s you design you system using code and then creates a png out of it. I tried for about 15 minutes and was able to come up with the image in my GitHub. The code is pretty straight forward and simple:

    从开始我想尝试一些新东西开始,我发现这个Python库很棒。 它使您可以使用代码设计系统,然后从中创建png。 我尝试了大约15分钟,并且能够在GitHub上提出图像。 该代码非常简单明了:

    from diagrams import Cluster, Diagram, Edge from diagrams.aws.compute import EC2 from diagrams.aws.database import RDS from diagrams.aws.network import ELB, VPC, NATGateway, InternetGateway from diagrams.aws.management import SystemsManager as SSM from diagrams.onprem.client import Users from diagrams.onprem.network import Internet with Diagram("3 Tier Web Module", show=False): users = Users("Users") internet = Internet("Internet") with Cluster("Region Sa-East-1"): ssm = SSM("SSM Management") with Cluster("VPC"): with Cluster("subnet/public"): igw = InternetGateway("InternetGateway") lb = ELB("lb") with Cluster("subnet/private"): with Cluster("App"): auto_scaling_group = [EC2("app1"), EC2("app2")] with Cluster("Database"): database = RDS("app_db") natgw = NATGateway("NATGW") users >> internet >> lb >> auto_scaling_group natgw - auto_scaling_group auto_scaling_group - Edge(style="dotted") - database ssm >> Cluster("subnet/private")

    I really liked this one because I’m not a good designer, but I can write some code. It’s not the best of my work, but it’s understandable.

    我真的很喜欢这个,因为我不是一个好的设计师,但是我可以写一些代码。 这不是我最好的工作,但这是可以理解的。

    网络 (The Network)

    Let’s start from the ground up! Our network is divided in public and private. In the public part, we’ll have our loadbalancer, which will be responsible to balance the application load.

    让我们从头开始! 我们的网络分为公共和私有。 在公共部分,我们将有我们的负载平衡器,它将负责平衡应用程序负载。

    In the private part, we have our application layer, and our database.

    在私有部分,我们拥有应用程序层和数据库。

    I decided to use a module for our VPC just to make things easier to understand. And the cool part of it, we don’t need to decide a specific region of AWS for our code to run, it works in any region, this’ll be explained in the testing section.

    我决定为我们的VPC使用一个模块,以使事情更容易理解。 而其中最酷的部分是,我们不需要为要运行的代码确定AWS的特定区域,它可以在任何区域运行,这将在测试部分中进行说明。

    负载均衡器 (The Load Balancer)

    For the load balancer, we have this amazing module, that abstracts most of the original Terraform resources in a simple and clean way. The more complicated part was the security group, because I found the module documentation not so clear in the ingress/egress rules computed. But I’ve managed to work.

    对于负载均衡器,我们有一个了不起的模块,该模块以简单干净的方式抽象了大多数原始Terraform资源。 更复杂的部分是安全组,因为我发现模块文档在计算的入口/出口规则中不太清楚。 但是我设法工作了。

    申请代码 (The Application Code)

    We have here a Flask API, written in Python. Our app connects to a database and returns, in JSON:

    我们这里有一个用Python编写的Flask API。 我们的应用程序连接到数据库并以JSON返回:

    the database version

    数据库版本 the region which was deployed

    被部署的区域an unique id

    唯一ID

    To set up our environment, I decided not to use a Configuration Management Tool, like Ansible, but to do it using a userdata script. I had some trouble in the past using those scripts, but I’ve found the right way to do it, which is using as a .tpl file, like below:

    为了设置我们的环境,我决定不使用像Ansible这样的配置管理工具,而是使用userdata脚本来进行配置。 过去我在使用这些脚本时遇到了一些麻烦,但是我找到了正确的方法来使用它,将其用作.tpl文件,如下所示:

    data "template_file" "user_data" { template = file("./scripts/userdata.tpl") vars = { rds_username = module.db.this_db_instance_username, rds_endpoint = element(split(":", module.db.this_db_instance_endpoint), 0) rds_database = module.db.this_db_instance_name, rds_password = random_password.rds_password.result, unique_id = var.unique_id }}

    In the .tpl file we just write simple bash script as usual.

    在.tpl文件中,我们照常编写简单的bash脚本。

    Another thing I’d like to point out, is that I left a pub key for SSH, but in fact we don’t need that, we are going to connect to our instances using SSM, a faster and more secure way to do it.

    我想指出的另一件事是,我为SSH保留了一个发布密钥,但实际上我们并不需要它,我们将使用SSM连接到我们的实例,这是一种更快,更安全的方法。

    应用程序可伸缩性 (The Application Scalability)

    To scale our app up, if needed, I used and auto scaling group. I’ve found the module pretty well documented except for one thing: tagging. Tagging was really difficult in this module, so I had to use another one just for it.

    为了扩大我们的应用程序,如果需要,我使用了自动缩放组。 我发现该模块的文档很好,除了一件事:标记。 在这个模块中标记确实非常困难,因此我不得不为此使用另一个标记。

    Turns out the return format of the ASG Module it doesn’t match a mapping that I was doing. Many people faced the same issue so the community came up with a module:

    证明ASG模块的返回格式与我正在做的映射不匹配。 许多人面临相同的问题,因此社区提出了一个模块:

    module "asg_tags" { source = "rhythmictech/asg-tag-transform/aws" version = "1.0.0" tag_map = merge(local.common_tags, { ResourceGroup = var.tag_name } )}

    数据库 (The Database)

    For our database, I chose a MySQL instance, because it’s simple and fast. Here is something I’ve wanted to try for a while. Our RDS master password is random. We generate the password during the terraform apply and we save a connection string in the SSM Parameter Store. With this, we have now a secure way to store our secrets and we don’t even know they.

    对于我们的数据库,我选择了一个MySQL实例,因为它既简单又快速。 这是我想尝试一段时间的东西。 我们的RDS主密码是随机的。 我们在terraform应用期间生成密码,并将连接字符串保存在SSM参数存储中。 有了这个,我们现在有了安全的方式来存储我们的秘密,而我们甚至都不知道它们。

    Here is the way to do it:

    这是这样做的方法:

    resource "random_password" "rds_password" { length = 16 special = false} resource "aws_ssm_parameter" "rds_connection_string" { name = "/rds/rds_connection_string" type = "SecureString" value = jsonencode({ "URL" = module.db.this_db_instance_address, "PORT" = module.db.this_db_instance_port, "DATABASE" = module.db.this_db_instance_name, "USER" = module.db.this_db_instance_username, "PASS" = random_password.rds_password.result }) key_id = data.aws_kms_key.pass_kms_key.id} data "aws_kms_key" "pass_kms_key" { key_id = "alias/aws/ssm"}

    标记资源 (Tagging Resources)

    Personally, tagging is one of the most important subjects when we are talking about public cloud.

    就个人而言,当我们谈论公共云时,标记是最重要的主题之一。

    With the right tags, we don’t face issues when dealing with cost management, or resource management.

    有了正确的标签,我们在处理成本管理或资源管理时就不会遇到问题。

    In our module I decided to have mandatory tags and optional ones. In any resouce I’d just do a merge of them.

    在我们的模块中,我决定使用强制性标签和可选性标签。 无论如何,我只会将它们合并。

    The mandatory tags are in the locals:

    强制标签位于本地:

    locals { common_tags = map( "Name", var.tag_name, "Owner", var.tag_owner, "Env", var.tag_env )}

    And then we just merge it like this:

    然后我们像这样合并它:

    tags = merge( local.common_tags, map( "Resource", "alb" ) )

    It’s simple and scalable.

    它简单且可扩展。

    SSM管理 (SSM Management)

    For the last part(and also my favourite) we are talking about SSM. I’m using SSM extensivly in my daily work because it’s a simple to learn and easy to use.

    对于最后一部分(也是我的最爱),我们将讨论SSM。 我的日常工作中广泛使用SSM,因为它易于学习且易于使用。

    AWS has been doing a great job adding features to this service and now I’m here to use a little bit.

    AWS一直在为该服务添加功能方面做得很出色,现在我来使用一下。

    The first thing we need to use SSM is having the agent installed. If you are using any of AWS official images, they already install it for you, so you don’t have to worry.

    我们需要使用SSM的第一件事是安装代理。 如果您使用的是任何AWS官方映像,那么他们已经为您安装了它,因此您不必担心。

    The second thing, is to make sure you have the right policy in your instance profile. The policy is SSMManagedInstanceCore. I’ve attached it in the iam.tf file.

    第二件事是确保实例配置文件中具有正确的策略。 该策略是SSMManagedInstanceCore。 我已将其附加在iam.tf文件中。

    The last thing, is to make sure you instance has and outbound security rule that allows your agent to communicate with AWS. I’ve used the easier way, which is to allow HTTPS/443 for anyone. If are considering a more secure way to do it, you might want to create a VPC endpoint for the SSM URL and point it in you security group.

    最后一件事是确保您的实例具有出站安全规则,该规则允许您的代理与AWS进行通信。 我使用了更简单的方法,即允许所有人使用HTTPS / 443。 如果正在考虑一种更安全的方法,则可能要为SSM URL创建一个VPC端点并将其指向您的安全组。

    There is also another thing that I’ve done, it’s not mandatory, but for sure is nice to have. I’ve created a Resouce Group, which allows me to manage a bunch of instances using a common tag(remember how I said tagging was important?).

    我还做了另一件事,它不是强制性的,但是肯定有它。 我创建了一个Resouce组,该组使我可以使用一个公共标签来管理一堆实例(还记得我说的标记很重要吗?)。

    With this, we can easily connect and manage our instances using SSM Session Manager or Run Command.

    这样,我们可以使用SSM Session Manager或Run Command轻松连接和管理实例。

    OK, this is cool. This code is fun. But…

    好,这很酷。 这段代码很有趣。 但…

    What now?

    现在怎么办?

    Well, I was wondering the same thing. Being able to write a good code is nice, but it is useless if this code fails in production. This is why we need testing. Our code should be tested extensivly and must cover most scenarios. What if we want to deploy this in another region of AWS, for example. Will it work?

    好吧,我在想同样的事情。 能够编写好的代码很不错,但是如果该代码在生产中失败,那将是无用的。 这就是为什么我们需要测试。 我们的代码应该经过广泛的测试,并且必须涵盖大多数情况。 例如,如果我们要将其部署在另一个AWS区域中,该怎么办。 能行吗

    In cases like this, we need to test if our code can support those changes and be able to adapt.

    在这种情况下,我们需要测试我们的代码是否可以支持那些更改并能够适应。

    This is why I used Terratest, in order to be certain that my code won’t fail in some parts, I tested. And in the next part of this article you’ll find how I did it.

    这就是我使用Terratest的原因,为了确定我的代码在某些部分不会失败,我进行了测试。 在本文的下一部分,您将发现我是如何做到的。

    Guys, thanks for reading this artcle, I’ve been waiting so long to write something like this. The last part is here, in which I talk about testing our Terraform code.

    伙计们,感谢您阅读本文,我一直在等待这么长时间写这样的东西。 最后一部分是在这里,我在其中谈论测试我们的Terraform代码。

    If you like it, leave a Clap and share with your friends.

    如果您喜欢,请拍拍手并与您的朋友分享。

    See ya!

    再见!

    翻译自: https://medium.com/@mschirbel/testing-iac-why-should-we-do-it-c7ebf51becef

    iac脚本

    Processed: 0.018, SQL: 8