連載 [第8回] :
今日からはじめる Pulumiでカンタン インフラ運用・管理既に存在するリソースをPulumiで管理してみよう
2023年10月19日(木)
第8回となる今回は、既にクラウド環境にデプロイされているリソースをPulumiで管理(import)する方法について、ハンズオンで実践していきます。
Pulumiコマンドによるimport
これまではProgramにimport option(リソースID)を追記してimport実施しましたが、pulumiコマンドによるimportも実施できます。import方法は概ね各リソースのAPIリファレンスに記載されています。今回はS3 Bucketのimportを実施します。
- stateは空(リソースの情報がない)の状態で、AWSマネジメントコンソールには未だPulumiで管理されていないbucketが存在している状態です。
$ pulumi stack export { "version": 3, "deployment": { "manifest": { "time": "2023-09-28T17:27:51.298182+09:00", "magic": "1fce246d436c6e46d168db13ed1014131c96be0ccf8401639052718fba57ac37", "version": "v3.72.2" }, "secrets_providers": { "type": "service", "state": { "url": "https://api.pulumi.com", "owner": "***", "project": "pulumi-import", "stack": "dev" } } } }
- 以下pulumi importコマンドを実行します。文法は「pulumi import [type] [name] [id] [option]」になります。コマンドを実行すると、先ほどのケース「import option(リソースID)を付与した場合のPulumi up」と同様の実行結果が表示され、既存リソースの「import」が実行されることが分かります。
$ pulumi import aws:s3/bucket:Bucket bucket my-bucket-pulumi Previewing import (***/dev) View in Browser (Ctrl+O): https://app.pulumi.com/***/pulumi-import/dev/previews/*** Type Name Plan + pulumi:pulumi:Stack pulumi-import-dev create = └─ aws:s3:Bucket bucket import Resources: + 1 to create = 1 to import 2 changes Do you want to perform this import? yes Importing (***/dev) View in Browser (Ctrl+O): https://app.pulumi.com/***/pulumi-import/dev/updates/6 Type Name Status + pulumi:pulumi:Stack pulumi-import-dev created (3s) = └─ aws:s3:Bucket bucket imported (1s) Resources: + 1 created = 1 imported 2 changes Duration: 5s
- import完了後、stateにリソースの情報が追加されていることが確認できます。
$ pulumi stack export { "version": 3, "deployment": { "manifest": { "time": "2023-09-28T17:29:55.135701+09:00", "magic": "1fce246d436c6e46d168db13ed1014131c96be0ccf8401639052718fba57ac37", "version": "v3.72.2" }, "secrets_providers": { "type": "service", "state": { "url": "https://api.pulumi.com", "owner": "***", "project": "pulumi-import", "stack": "dev" } }, "resources": [ { "urn": "urn:pulumi:dev::pulumi-import::pulumi:pulumi:Stack::pulumi-import-dev", "custom": false, "type": "pulumi:pulumi:Stack", "created": "2023-09-28T08:29:51.720228Z", "modified": "2023-09-28T08:29:51.720228Z" }, { "urn": "urn:pulumi:dev::pulumi-import::pulumi:providers:aws::default_6_2_1", "custom": true, "id": "17e2170c-0dfc-4a37-873c-242eb1fb2eec", "type": "pulumi:providers:aws", "inputs": { "region": "ap-northeast-1", "skipCredentialsValidation": "false", "skipMetadataApiCheck": "true", "skipRegionValidation": "true", "version": "6.2.1" }, "outputs": { "region": "ap-northeast-1", "skipCredentialsValidation": "false", "skipMetadataApiCheck": "true", "skipRegionValidation": "true", "version": "6.2.1" }, "created": "2023-09-28T08:29:52.86169Z", "modified": "2023-09-28T08:29:52.86169Z" }, { "urn": "urn:pulumi:dev::pulumi-import::aws:s3/bucket:Bucket::bucket", "custom": true, "id": "my-bucket-pulumi", "type": "aws:s3/bucket:Bucket", "inputs": { "__defaults": [], "arn": "arn:aws:s3:::my-bucket-pulumi", "bucket": "my-bucket-pulumi", "hostedZoneId": "Z2M4EHUR26P7ZW", "requestPayer": "BucketOwner", "serverSideEncryptionConfiguration": { "__defaults": [], "rule": { "__defaults": [], "applyServerSideEncryptionByDefault": { "__defaults": [], "sseAlgorithm": "AES256" }, "bucketKeyEnabled": true } } }, "outputs": { "accelerationStatus": "", "arn": "arn:aws:s3:::my-bucket-pulumi", "bucket": "my-bucket-pulumi", "bucketDomainName": "my-bucket-pulumi.s3.amazonaws.com", "bucketRegionalDomainName": "my-bucket-pulumi.s3.ap-northeast-1.amazonaws.com", "corsRules": [], "grants": [], "hostedZoneId": "Z2M4EHUR26P7ZW", "id": "my-bucket-pulumi", "lifecycleRules": [], "loggings": [], "objectLockConfiguration": null, "region": "ap-northeast-1", "replicationConfiguration": null, "requestPayer": "BucketOwner", "serverSideEncryptionConfiguration": { "rule": { "applyServerSideEncryptionByDefault": { "kmsMasterKeyId": "", "sseAlgorithm": "AES256" }, "bucketKeyEnabled": true } }, "versioning": { "enabled": false, "mfaDelete": false }, "website": null }, "parent": "urn:pulumi:dev::pulumi-import::pulumi:pulumi:Stack::pulumi-import-dev", "protect": true, "provider": "urn:pulumi:dev::pulumi-import::pulumi:providers:aws::default_6_2_1::17e2170c-0dfc-4a37-873c-242eb1fb2eec", "created": "2023-09-28T08:29:55.135649Z", "modified": "2023-09-28T08:29:55.135649Z" } ] } }
ちなみに、お気づきだとは思いますが、importコマンド実行直後にimportしたリソースの以下ProgramがCLIに表示されます。これをそのままProgramにコピーして利用できますので、実際の運用の現場でも初めからリソースをimportするためのProgramを自分で作らず、importコマンドでProgramを出力しちゃうのが便利かもしれません。Please copy the following code into your Pulumi application. Not doing so will cause Pulumi to report that an update will happen on the next update command. Please note that the imported resources are marked as protected. To destroy them you will need to remove the `protect` option and run `pulumi update` *before* the destroy will take effect. import pulumi import pulumi_aws as aws bucket = aws.s3.Bucket("bucket", arn="arn:aws:s3:::my-bucket-pulumi", bucket="my-bucket-pulumi", hosted_zone_id="Z2M4EHUR26P7ZW", request_payer="BucketOwner", server_side_encryption_configuration=aws.s3.BucketServerSideEncryptionConfigurationArgs( rule=aws.s3.BucketServerSideEncryptionConfigurationRuleArgs( apply_server_side_encryption_by_default=aws.s3.BucketServerSideEncryption ConfigurationRuleApplyServerSideEncryptionByDefaultArgs( sse_algorithm="AES256", ), bucket_key_enabled=True, ), ), opts=pulumi.ResourceOptions(protect=True))
【参考】その他state関連操作について
参考として、stateの操作に関連したその他のPulumiコマンドについて一部紹介します。
pulumi state delete [URN]
特定リソースのURN(Uniform Resource Name)を用いて、stateからリソースの情報を削除できます(実際にクラウド環境にデプロイされているリソース自体は削除されません)。
「実際にリソース自体は削除したくないが、Pulumiの管理からは外したい」場合などに利用します。
- 削除したいリソースのURNを調べます(今回はbucketのstate情報を削除)。stateから該当リソースのURNを確認できます。
$ pulumi stack export { ~~(略)~~ "resources": [ ~~(略)~~ { "urn": "urn:pulumi:dev::quickstart2::gcp:storage/bucket:Bucket::my-bucket-0927", "custom": true, "id": "my-bucket-0927", "type": "gcp:storage/bucket:Bucket", "inputs": { "__defaults": [ "forceDestroy" ], "forceDestroy": false, "location": "ASIA-NORTHEAST1", "name": "my-bucket-0927", "storageClass": "STANDARD", "uniformBucketLevelAccess": true }, ~~(略)~~ }
または、以下pulumiコマンドでURNを表示させることもできます。$ pulumi stack --show-urns Current stack is dev: Owner: *** Last updated: 23 minutes ago (2022-09-28 01:03:49.870847 +0900 JST) Pulumi version: v3.39.1 Current stack resources (3): TYPE NAME pulumi:pulumi:Stack quickstart2-dev │ URN: urn:pulumi:dev::quickstart2::pulumi:pulumi:Stack::quickstart2-dev ├─ gcp:storage/bucket:Bucket my-bucket-0927 │ URN: urn:pulumi:dev::quickstart2::gcp:storage/bucket:Bucket::my-bucket-0927 └─ pulumi:providers:gcp default_6_29_0 URN: urn:pulumi:dev::quickstart2::pulumi:providers:gcp::default_6_29_0 Current stack outputs (0): No output values currently in this stack More information at: https://app.pulumi.com/***/quickstart2/dev Use `pulumi stack select` to change stack; `pulumi stack ls` lists known ones
- URNを指定して、以下コマンドを実行します。
$ pulumi state delete urn:pulumi:dev::quickstart2::gcp:storage/bucket:Bucket::<Bucket名> warning: This command will edit your stack's state directly. Confirm? Yes Resource deleted
- stateから対象のリソース情報(bucket)が削除されました。
$ pulumi stack export { "version": 3, "deployment": { "manifest": { "time": "2022-09-28T01:40:56.95378+09:00", "magic": "c57d2cc6e4ddc1ad908bcf42d81d39304d5e92a1de5a6e1d5a5c485a70ff807b", "version": "v3.39.1" }, "secrets_providers": { "type": "service", "state": { "url": "https://api.pulumi.com", "owner": "***", "project": "quickstart2", "stack": "dev" } }, "resources": [ { "urn": "urn:pulumi:dev::quickstart2::pulumi:pulumi:Stack::quickstart2-dev", "custom": false, "type": "pulumi:pulumi:Stack" }, { "urn": "urn:pulumi:dev::quickstart2::pulumi:providers:gcp::default", "custom": true, "id": "f8f41b6d-87d4-4cd2-93b8-ebdbf766398c", "type": "pulumi:providers:gcp", "inputs": { "project": "pulumi-test", "version": "6.29.0" }, "outputs": { "project": "pulumi-test", "version": "6.29.0" }, "parent": "urn:pulumi:dev::quickstart2::pulumi:pulumi:Stack::quickstart2-dev" } ] } }
pulumi preview [URN]
stateの情報とProgramのコードの差分を確認できます。pulumi upコマンドでも差分を確認できますが、間違えて実際のデプロイを実行してしまう場合もありますので、pulumi previewで差分を確認する方が無難かと思います。
$ pulumi preview Previewing update (dev) View Live: https://app.pulumi.com/***/quickstart2/dev/previews/f8807e3a-5045-4e63-ae14-****** Type Name Plan pulumi:pulumi:Stack quickstart2-dev + └─ gcp:storage:Bucket my-bucket-0927 create Resources: + 1 to create 1 unchanged
おわりに
今回は、Pulumiによるリソース更新の流れについておさらいし、既存リソースのPulumi管理化について紹介しました。基本的には「stateとprogramの比較で実体の更新が行われる」という認識があれば、Pulumi管理化の流れも比較的理解しやすいと思います。どちらかと言うと「既にクラウド環境に存在するリソースをIaCで管理したい」というようなケースが多いと思うので、今回の記事を参考にしていただければと思います。次回もお楽しみに!
連載バックナンバー
Think ITメルマガ会員登録受付中
Think ITでは、技術情報が詰まったメールマガジン「Think IT Weekly」の配信サービスを提供しています。メルマガ会員登録を済ませれば、メルマガだけでなく、さまざまな限定特典を入手できるようになります。
全文検索エンジンによるおすすめ記事
- PulumiでAWSリソースをデプロイしよう
- 「Pulumi Stack」とは ー Pulumiによるマルチステージ環境の構築方法
- TerraformからPulumiへの移行
- SecretもPulumiで使いこなしたい! PulumiのSecurityを試してみよう
- 「Pulumi Automation API」でPulumi CLIの機能をコード化しよう
- Policy as Codeでインフラのコンプライアンスを自動実現! 「Pulumi CrossGuard」を活用してみよう
- Pulumi Kubernetes Operatorを活用してPulumiのCI/CDを実現しよう
- Oracle Cloud Hangout Cafe Season7 #2「IaC のベストプラクティス」(2023年7月5日開催)
- TFXを使った機械学習パイプラインの構築(実装編その1)
- TFXを使った機械学習パイプラインの構築(デプロイ編)