この記事は、カサレアル Advent Calendar 2022 の2日目のエントリです。
はじめに
TerraformでEC2インスタンスやKerPairなどのリソースを作成し、それをAnsibleで活用します。
以下の流れで試します。
- [Terraform] EC2インスタンスやSSHキー(KeyPair)などのリソースを作成します
- [Terraform] Amazon Secrets ManagerにSSHキーを登録します
- [Ansible] Amazon Secrets ManagerからSSHキーをダウンロードします
- [Ansible] SSHキーを使って、対象ノードにパッケージをインストールします
- はじめに
- Terraformのリソース「Secrets Manager」について
- Ansibleのlookupプラグイン「amazon.aws.aws_secret」について
- 環境
- 用意するファイル
- 実行ログ
- 備考
Terraformのリソース「Secrets Manager」について
リソースaws_secretsmanager_secretでシークレットの名前を、リソースaws_secretsmanager_secret_versionでユーザ名/パスワードやキー/バリューなどのシークレット情報が登録できます。
locals { KEY = { ssh_key = file("./xxxx.pem") } } resource "aws_secretsmanager_secret" "asm_secret" { name = "シークレット名" } resource "aws_secretsmanager_secret_version" "asm_secret_version" { secret_id = aws_secretsmanager_secret.asm_secret.id secret_string = jsonencode(local.KEY) }
Ansibleのlookupプラグイン「amazon.aws.aws_secret」について
lookupプラグインを使って、Amazon Secrets ManagerからKerPair情報を取得します。
amazon.aws.aws_secret lookup – Look up secrets stored in AWS Secrets Manager — Ansible Documentation
"{{ lookup('amazon.aws.aws_secret', 'シークレット名', region='リージョン', aws_access_key='XXXXXX', aws_secret_key='XXXXXX') }}"
環境
- ホストOS: Amazon Linux 2
- 対象ノードOS: Amazon Linux 2(terraformで作成)
- terraform: v1.3.4
- ansible core: v2.13.6
- amazon.aws: v5.1.0
- Python: v3.10.6
- python3-boto: v2.49.0-4
- python3-botocore: v1.23.34
用意するファイル
- main.tf
- main.yml
- 実装内容
- Secrets ManagerからKeyPairを取得する
- KeyPairを使ってgitをインストールする
- 実装内容
- ansible.cfg
- 実装内容
- host_key_checkingの無効
- 実装内容
main.tf
provider "aws" { region = "ap-northeast-1" access_key = "XXXXXX" secret_key = "XXXXXX" } # EC2インスタンスの作成 resource "aws_instance" "mito_ec2" { ami = "ami-072bfb8ae2c884cc4" # Amazon Linux 2 instance_type = "t2.micro" associate_public_ip_address = "true" key_name = aws_key_pair.deployer.key_name vpc_security_group_ids = [aws_security_group.sg_mito.id] tags = { Name = "mito_ec2" } } # キーペアの作成 resource "tls_private_key" "rsa_4096" { algorithm = "RSA" rsa_bits = 4096 } resource "aws_key_pair" "deployer" { key_name = "mito_key" public_key = tls_private_key.rsa_4096.public_key_openssh lifecycle { ignore_changes = [key_name] } } # セキュリティグループの作成 resource "aws_security_group" "sg_mito" { name = "sg_mito" description = "sg_mito" ingress { description = "SSH" from_port = 22 to_port = 22 protocol = "tcp" cidr_blocks = ["${chomp(data.http.myip.response_body)}/32"] # ホストのパブリックIPを許可する } egress { from_port = 0 to_port = 0 protocol = "-1" cidr_blocks = ["0.0.0.0/0"] } tags = { Name = "sg_mito" } } # 返り値でホストのパブリックIPを取得する data "http" "myip" { url = "http://ipv4.icanhazip.com" } # Secrets ManagerにSSHキーを登録する resource "aws_secretsmanager_secret" "asm_secret" { name = "test_asm_secret" } resource "aws_secretsmanager_secret_version" "asm_secret_version" { secret_id = aws_secretsmanager_secret.asm_secret.id secret_string = jsonencode( {"ssh_key" = tls_private_key.rsa_4096.private_key_pem}) }
main.yml
1Play目でSSHキーをダウンロードし、2Play目でパッケージをインストールします。
--- - hosts: localhost gather_facts: no tasks: - name: create ssh_key ansible.builtin.copy: content: "{{ key.ssh_key}}" dest: ./mito_key.pem mode: 0600 vars: key: "{{ lookup('amazon.aws.aws_secret', 'test_asm_secret', region='ap-northeast-1', aws_access_key='XXXXXX', aws_secret_key='XXXXXX') }}" - hosts: all gather_facts: no become: yes tasks: - name: install git yum: name: git state: present
ansible.cfg
[defaults] host_key_checking = False
実行ログ
まずは、Terraformコマンドでリソースを作成します。
$ terraform init Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/tls... - Finding latest version of hashicorp/http... - Finding latest version of hashicorp/aws... - Installing hashicorp/tls v4.0.4... - Installed hashicorp/tls v4.0.4 (signed by HashiCorp) - Installing hashicorp/http v3.2.1... - Installed hashicorp/http v3.2.1 (signed by HashiCorp) - Installing hashicorp/aws v4.44.0... - Installed hashicorp/aws v4.44.0 (signed by HashiCorp) (略) $ $ $ terraform apply Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols: + create Terraform will perform the following actions: # aws_instance.mito_ec2 will be created + resource "aws_instance" "mito_ec2" { + ami = "ami-072bfb8ae2c884cc4" + arn = (known after apply) + associate_public_ip_address = true + availability_zone = (known after apply) (略) # aws_secretsmanager_secret.asm_secret will be created + resource "aws_secretsmanager_secret" "asm_secret" { + arn = (known after apply) + force_overwrite_replica_secret = false + id = (known after apply) + name = "test_asm_secret" + name_prefix = (known after apply) + policy = (known after apply) + recovery_window_in_days = 30 + rotation_enabled = (known after apply) + rotation_lambda_arn = (known after apply) + tags_all = (known after apply) + replica { + kms_key_id = (known after apply) + last_accessed_date = (known after apply) + region = (known after apply) + status = (known after apply) + status_message = (known after apply) } + rotation_rules { + automatically_after_days = (known after apply) } } # aws_secretsmanager_secret_version.asm_secret_version will be created + resource "aws_secretsmanager_secret_version" "asm_secret_version" { + arn = (known after apply) + id = (known after apply) + secret_id = (known after apply) + secret_string = (sensitive value) + version_id = (known after apply) + version_stages = (known after apply) } (略) Plan: 6 to add, 0 to change, 0 to destroy. Do you want to perform these actions? Terraform will perform the actions described above. Only 'yes' will be accepted to approve. Enter a value: yes tls_private_key.rsa_4096: Creating... aws_secretsmanager_secret.asm_secret: Creating... aws_security_group.sg_mito: Creating... (略) Apply complete! Resources: 6 added, 0 changed, 0 destroyed. $
AWSコンソールでシークレットマネージャへのSSHキー登録を確認します。
作成したEC2インスタンスのinventory.iniを作成します。
$ cat inventory.ini 35.79.224.19
Playbookを実行します。
$ ansible-playbook main.yml -i inventory.ini -u ec2-user --private-key=./mito_key.pem [DEPRECATION WARNING]: Ansible will require Python 3.8 or newer on the controller starting with Ansible 2.12. Current version: 3.7.10 (default, Jun 3 2021, 00:02:01) [GCC 7.3.1 20180712 (Red Hat 7.3.1-13)]. This feature will be removed from ansible-core in version 2.12. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg. PLAY [localhost] ******************************************************************************** TASK [create ssh_key] *************************************************************************** changed: [localhost] PLAY [all] ************************************************************************************** TASK [install git] ****************************************************************************** [WARNING]: Platform linux on host 35.79.224.19 is using the discovered Python interpreter at /usr/bin/python, but future installation of another Python interpreter could change the meaning of that path. See https://docs.ansible.com/ansible- core/2.11/reference_appendices/interpreter_discovery.html for more information. changed: [35.79.224.19] PLAY RECAP ************************************************************************************** 35.79.224.19 : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 localhost : ok=1 changed=1 unreachable=0 failed=0 skipped=0 rescued=0 ignored=0 $
無事に対象ノードへ接続し、パッケージもインストールできました。
備考
inventory.iniの作成はダイナミックインベントリを使えば不要になるけど手、 SSHキー名などの固定値は、別途管理する必要があります。