Slide 1

Slide 1 text

IaCのベストプラクティス Terraform, Pulumi (AI) Oracle Cloud Hangout Café – Season 7 #2 Shuhei Kawamura Cloud Architect Oracle Digital, Oracle Corporation Japan July 5, 2023

Slide 2

Slide 2 text

Copyright © 2023, Oracle and/or its affiliates 2 • 所属 • 日本オラクル株式会社 • Oracle Digital • 普段の業務 • Digital Nativeなお客様を技術面でご支援 • コミュニティ • OCHaCafe • CloudNative Days – Observability 川村 修平 (Shuhei Kawamura) @shukawam Twitter/GitHub/Qiita

Slide 3

Slide 3 text

Copyright © 2023, Oracle and/or its affiliates 3 Agenda 1. Infrastructure as Code(IaC)とは 2. Terraform 3. Pulumi/Pulumi AI

Slide 4

Slide 4 text

Copyright © 2023, Oracle and/or its affiliates 4 Infrastructure as Code(IaC)とは

Slide 5

Slide 5 text

Copyright © 2023, Oracle and/or its affiliates 5 (広義には)インフラストラクチャを定義、展開、更新、破棄するためのコードを書き、それを実行すること • アドホックなスクリプト – Bash, Ruby, Python, etc. • 構成管理ツール – Chef, Puppet, Ansible, etc. • サーバーテンプレートツール – Docker, Packer, Vagrant, etc. • オーケストレーションツール – Kubernetes, Docker Swarm, Nomad, etc. • プロビジョニングツール – Terraform, Pulumi, etc. 手動で実施してきた作業をコードに変換する先行投資と引き換えに、ソフトウェアのデリバリーを効率化する Infrastructure as Code(IaC)とは? … これ以外にもたくさんツールがあります…

Slide 6

Slide 6 text

Copyright © 2023, Oracle and/or its affiliates 6 セルフサービス ✓ 開発者がインフラ担当者に頼らずにデプロイメントを開始できる スピードと安全性 ✓ 自動化によるデプロイメントの高速化&人的ミスの削減 ドキュメンテーション ✓ IaCのコードは、環境情報を表すドキュメントとして機能 バージョン管理 ✓ Git等のバージョン管理ツールと組み合わせることで、インフラ操作に対する履歴をコミットログとして記録可能 検証 ✓ コード・レビューや自動テスト、静的解析ツールの活用が可能 再利用性 ✓ 再利用可能なモジュールにパッケージ化することで効率的なインフラ定義が可能 反復作業からの解放 ✓ 反復的な作業(コードのデプロイとインフラ管理)からの解放 IaCが提供する価値

Slide 7

Slide 7 text

Copyright © 2023, Oracle and/or its affiliates 7 • 構成管理ツール/プロビジョニングツール • 可変(Mutable)/不変(Immutable) • 手続き型/宣言型 • 汎用言語(GPL*)/ドメイン固有言語(DSL**) • Master/Masterless • Agent/Agentless • Paid/Free • 大規模コミュニティ/小規模コミュニティ *GPL: General Public Licence **DSL: Domain Specific Language IaCのツール選定において検討するべき主な項目

Slide 8

Slide 8 text

Copyright © 2023, Oracle and/or its affiliates 8 • IaC = インフラストラクチャを定義、展開、更新、破棄するためのコードを書き、それを実行すること • ソフトウェアの開発においてクラウド活用が当たり前となった現代では、IaCの需要が非常に高い • IaCツールは、数多く存在する • トレードオフを見ながらツールを選定する • 複数のツールを組み合わせて使う場合もある • e.g. Terraform + Ansible, Docker + Kubernetes, … ここまでのまとめ

Slide 9

Slide 9 text

Copyright © 2023, Oracle and/or its affiliates 9 Terraform

Slide 10

Slide 10 text

Copyright © 2023, Oracle and/or its affiliates 10 Demo: OKE(+周辺リソース)のプロビジョニング まずは、どんなことができるのか見てみよう! . ├── examples │ ├── container-engine │ ├── kube-config │ └── vcn ├── live │ └── oke-tutorial └── modules ├── container-engine ├── kube-config └── vcn OCI Region Availability Domain 1 Fault Domain 1 Fault Domain 2 Fault Domain 3 VCN LB Subnet 10.0.20.0/24 K8s API Subnet 10.0.0.0/28 Node Subnet 10.0.10.0/24 Container Engine for Kubernetes Worker Nodes Service Gateway Internet Gateway NAT Gateway terraform init|plan|apply

Slide 11

Slide 11 text

Copyright © 2023, Oracle and/or its affiliates 11 Terraform • HashiCorp社が開発しているIaC(プロビジョニング)ツール • あるべき状態を定義し、TerraformがクラウドベンダーへAPIリクエストを行うことでインフラのプロビジョニングを行う • HCL* (or JSON)を用いて宣言的にあるべき状態を定義 • 状態を記録するStateファイルを用いてTerraformのエンジンで計算を行うことで、冪等性を担保 • リソース間の依存関係は、Terraform側で考慮され実行されるため、ユーザーの考慮事項が少ない *: HashiCorp Configuration Language Terraformとは?

Slide 12

Slide 12 text

Cloud Service Provider AWS Provider Copyright © 2023, Oracle and/or its affiliates 12 Terraformのアーキテクチャ Terraform Core/Terraform Plugins Azure Provider OCI Provider Terraform Core Terraform Plugins RPC* Client Library HTTP(S) Golang *: Remote Procedure Call

Slide 13

Slide 13 text

Copyright © 2023, Oracle and/or its affiliates 13 Terraform Core • どのプラットフォームでも使われるTerraformの基本機能、共通のインターフェースを提供 • Terraformのバイナリ • CLI(init, plan, apply, graph, …, etc.) • リソースやデータソース等から依存関係グラフを作成する機能 • ステートファイルを読み書きするロジック • etc. • HashiCorpが所有し、GitHubリポジトリで管理 • https://github.com/hashicorp/terraform Terraform Core

Slide 14

Slide 14 text

Copyright © 2023, Oracle and/or its affiliates 14 Terraform Plugins • Terraform Coreに対応するプラグイン • Golangで実装されたバイナリでTerraform CoreとRPCを用いて通信 • ネットワーク(HTTP, etc.)を用いて対応するプラットフォームと通信する • 各プラグインのコードは、個別のリポジトリで管理される • https://github.com/hashicorp/terraform-provider-aws • https://github.com/oracle/terraform-provider-oci • プラグインの開発やメンテナンスには専用のFrameworkやSDKを用いる • プラグイン開発 … Terraform Plugin Framework • legacy SDKで作られたプラグインのメンテナンス … Terraform Plugin SDKv2 Terraform Plugins

Slide 15

Slide 15 text

Copyright © 2023, Oracle and/or its affiliates 15 Terraform Providers(2023/07現在) 引用:https://registry.terraform.io/browse/providers Partner, Communityまで 含めると3,000以上!

Slide 16

Slide 16 text

Copyright © 2023, Oracle and/or its affiliates 16 Terraformを用いたインフラのプロビジョニングの流れ Write → Plan → Apply provider "oci" { region = var.region } variable "region" {} variable "compartment_ocid" {} variable "vcn_display_name" {} locals { vcn_cidr_block = "10.0.0.0/16" } resource "oci_core_vcn" "vcn" { compartment_id = var.compartment_ocid cidr_block = local.vcn_cidr_block display_name = var.vcn_display_name } $ terraform init . └── .terraform └── providers └── registry.terraform.io └── hashicorp └── oci └── 4.116.0 └── linux_amd64 ├── CHANGELOG.md ├── LICENSE.md ├── README.md └── terraform-provider-oci_v4.116.0 TF Core RPC Client Library OCI Provider TF Plugins $ terraform plan | apply download plugins HTTP(S) terraform.tfstate

Slide 17

Slide 17 text

Copyright © 2023, Oracle and/or its affiliates 17 実際にコードを書いて、 クラウドリソースをプロビジョニングしてみよう! ~ 初めてのTerraform – OCI Object Storage ~

Slide 18

Slide 18 text

Copyright © 2023, Oracle and/or its affiliates 18 Cloud Provider(OCI)と通信するために必要なPluginを指定する プロバイダーを指定する Write variable "region" { default = "ap-tokyo-1" description = "OCI Region Identifier. (e.g. ap-tokyo-1, ...)" } provider "oci" { region = var.region } providers.tf

Slide 19

Slide 19 text

Copyright © 2023, Oracle and/or its affiliates 19 依存ライブラリをダウンロードする(terraform init) 依存ライブラリをダウンロードする Write $ terraform init Initializing the backend... Initializing provider plugins... - Finding latest version of hashicorp/oci... - Installing hashicorp/oci v4.121.0... - Installed hashicorp/oci v4.121.0 (signed by HashiCorp) ... 省略 ... ╷ │ Warning: Additional provider information from registry │ │ The remote registry returned warnings for registry.terraform.io/hashicorp/oci: │ - For users on Terraform 0.13 or greater, this provider has moved to oracle/oci. Please update your source in required_providers. ╵ Terraform has been successfully initialized! ... 省略 ... . ├── .terraform │ └── providers │ └── registry.terraform.io │ └── hashicorp │ └── oci │ └── 4.121.0 │ └── linux_amd64 │ ├── CHANGELOG.md │ ├── LICENSE.md │ ├── README.md │ └── terraform-provider-oci_v4.121.0 ├── .terraform.lock.hcl # ダウンロードしたプロバイダー情報が記録される ├── ... 省略 ...

Slide 20

Slide 20 text

Copyright © 2023, Oracle and/or its affiliates 20 ドキュメントなどを参照しながら、プロビジョニングしたいリソースを定義する プロビジョニングしたいクラウドリソースを定義する Write variable "compartment_ocid" { description = "OCID of compartment." } variable "objectstorage_namespace" { description = "Namespace of Object Storage." } variable "objectstorage_bucket_name" { description = "Name of Object Storage Bucket." } ##### # Object Storage resource "oci_objectstorage_bucket" "objectstorage_bucket" { compartment_id = var.compartment_ocid name = var.objectstorage_bucket_name namespace = var.objectstorage_namespace } main.tf https://registry.terraform.io/providers/oracle/oci/latest/ docs/resources/objectstorage_bucket

Slide 21

Slide 21 text

Copyright © 2023, Oracle and/or its affiliates 21 プロビジョニングされるリソースを確認する(terraform plan) プロビジョニングされるリソースを確認する(1/2) Plan $ terraform plan var.compartment_ocid OCID of compartment. Enter a value: ocid1.compartment.oc1... var.objectstorage_bucket_name Name of Object Storage Bucket. Enter a value: example-bucket var.objectstorage_namespace Namespace of Object Storage. Enter a value: orasejapan var.region OCI Region Identifier. (e.g. ap-tokyo-1, ...) Enter a value: ap-tokyo-1 入力変数(以下、順に評価され後勝ち) • variables.tfのdefault属性にデフォルト値を記載する • 環境変数から渡す(TF_VAR_xxx) • terraform.tfvars(.json)ファイルから渡す • *.auto.tfvars(.json)ファイルから渡す • CLIから渡す • -var=“xxx=…” or -var-file=“xxx.tfvars” • (←参照)実行時に対話形式で指定する

Slide 22

Slide 22 text

Copyright © 2023, Oracle and/or its affiliates 22 プロビジョニングされるリソースを確認する(2/2) 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: # oci_objectstorage_bucket.objectstorage_bucket will be created + resource "oci_objectstorage_bucket" "objectstorage_bucket" { + access_type = "NoPublicAccess" + approximate_count = (known after apply) + approximate_size = (known after apply) + auto_tiering = (known after apply) + bucket_id = (known after apply) + compartment_id = "ocid1.compartment.oc1..aaaaaaaanjtbllhqxcg67dq7em3vto2mvsbc6pbgk4pw6cx37afzk3tngmoa" + created_by = (known after apply) + defined_tags = (known after apply) + etag = (known after apply) + freeform_tags = (known after apply) + id = (known after apply) + is_read_only = (known after apply) + kms_key_id = (known after apply) + name = “example-bucket" + namespace = "orasejapan" + object_events_enabled = (known after apply) + object_lifecycle_policy_etag = (known after apply) + replication_enabled = (known after apply) + storage_tier = (known after apply) + time_created = (known after apply) + versioning = (known after apply) } Plan: 1 to add, 0 to change, 0 to destroy. Plan 出力 概要 + リソースが作成される - リソースが破棄される +/-, -/+ リソースが破棄および再作成される ~ リソースがインプレースで更新される

Slide 23

Slide 23 text

Copyright © 2023, Oracle and/or its affiliates 23 リソースをプロビジョニングする(terraform apply) クラウドリソースをプロビジョニングする Apply $ terraform apply # ... 省略 ... 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 oci_objectstorage_bucket.objectstorage_bucket: Creating... oci_objectstorage_bucket.objectstorage_bucket: Creation complete after 1s [id=n/orasejapan/b/example-bucket] Apply complete! Resources: 1 added, 0 changed, 0 destroyed. Outputs: # ... 省略 ...

Slide 24

Slide 24 text

Copyright © 2023, Oracle and/or its affiliates 24 再度、同じ入力変数を与えてプロビジョニングしてみる(terraform apply) 参考: 冪等性の確認のために同一リソースの再作成を試みる Apply $ terraform apply -var-file variables.tfvars oci_objectstorage_bucket.objectstorage_bucket: Refreshing state... [id=n/orasejapan/b/example-bucket] No changes. Your infrastructure matches the configuration. Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed. Apply complete! Resources: 0 added, 0 changed, 0 destroyed. Outputs: objectstorage_bucket_name = "example-bucket"

Slide 25

Slide 25 text

Copyright © 2023, Oracle and/or its affiliates 25 リソース間の依存関係を出力する(terraform graph) 参考: リソース間の依存関係を参照する $ terraform graph | dot -Tpng > object-storage-graph.png object-storage-graph.png

Slide 26

Slide 26 text

Copyright © 2023, Oracle and/or its affiliates 26 リソースを削除する(terraform apply -destroy) ※terraform destroyは、改善の計画があるため可能な限り、terraform apply -destroyを使う クラウドリソースを削除する $ terraform apply -destroy # ... 省略 ... Plan: 0 to add, 0 to change, 1 to destroy. Changes to Outputs: - objectstorage_bucket_name = "example-bucket" -> null Do you really want to destroy all resources? Terraform will destroy all your managed infrastructure, as shown above. There is no undo. Only 'yes' will be accepted to confirm. Enter a value: yes oci_objectstorage_bucket.objectstorage_bucket: Destroying... [id=n/orasejapan/b/example-bucket] oci_objectstorage_bucket.objectstorage_bucket: Destruction complete after 2s Apply complete! Resources: 0 added, 0 changed, 1 destroyed. # ... 省略 ... Apply

Slide 27

Slide 27 text

Copyright © 2023, Oracle and/or its affiliates 27 • プロバイダーのバージョンが上がって非互換がでたらどうしよう? • 作ったコードを他の箇所でも流用したいけど、同じ定義をもう一度しないとダメなのか? • チームで開発を進めたい時、冪等性の担保のためのTerraform Stateはどうやって共有したらいい? • 期待するリソースが作成されることを自動的に確認したいけど、どうすれば? クラウドリソースは作られたけど…これで満足ですか?

Slide 28

Slide 28 text

Copyright © 2023, Oracle and/or its affiliates 28 • プロバイダーのバージョンが上がって非互換がでたらどうしよう? → プロバイダーのバージョンはきちんと指定する • 作ったコードを他の箇所でも流用したいけど、同じ定義をもう一度しないとダメなのか? → Terraformの再利用可能な仕組み(Terraform Module)を活用する • チームで開発を進めたい時、冪等性の担保のためのTerraform Stateはどうやって共有したらいい? → 専用のバックエンドを用いて共有する • 期待するリソースが作成されることを自動的に確認したいけど、どうすれば? → Terraformでも静的解析や自動テストに取り組む クラウドリソースは作られたけど…これで満足ですか?

Slide 29

Slide 29 text

Copyright © 2023, Oracle and/or its affiliates 29 terraformブロックを用いると、Terraformによるプロバイダーのインストールに細かな条件を設けることができる Terraform Provider provider "oci" { region = var.region } terraform { required_version = ">=1.4.5" required_providers { oci = { source = "oracle/oci" version = ">= 4.116.0, < 5.0.0" } } } .terraform └── providers └── registry.terraform.io └── oracle └── oci └── 4.122.0 .terraform └── providers └── registry.terraform.io └── hashicorp └── oci └── 4.122.0 providerブロックのみ指定した場合 provider "oci" { region = var.region }

Slide 30

Slide 30 text

Copyright © 2023, Oracle and/or its affiliates 30 Terraform Module • 一緒に使用する複数リソースが書かれた.tf(.tf.json)ファイルをディレクトリにまとめたもの • Terraformでリソースの設定をパッケージ化して再利用するための主な方法 Terraform Module 再利用性の高いTerraform Code module "vcn-stage" { source = "../modules" compartment_ocid = "..." region = "ap-osaka-1" vcn_display_name = "vcn-stage" } module "vcn-prod" { source = "../modules" compartment_ocid = "..." region = "ap-tokyo-1" vcn_display_name = "vcn-prod" } provider "oci" { region = var.region } variable "region" {} variable "compartment_ocid" {} variable "vcn_display_name" {} locals { vcn_cidr_block = "10.0.0.0/16" } resource "oci_core_vcn" "vcn" { compartment_id = var.compartment_ocid cidr_block = local.vcn_cidr_block display_name = var.vcn_display_name } output "vcn" { value = oci_core_vcn.vcn } modules/main.tf stage/main.tf prod/main.tf

Slide 31

Slide 31 text

Copyright © 2023, Oracle and/or its affiliates 31 Terraformのモジュールには、標準の構造が存在する https://developer.hashicorp.com/terraform/language/modules/develop/structure Terraform Module 標準のモジュール構造に従う $ tree complete-module/ . ├── README.md ├── main.tf ├── variables.tf ├── outputs.tf ├── ... ├── modules/ │ ├── nestedA/ │ │ ├── README.md │ │ ├── variables.tf │ │ ├── main.tf │ │ ├── outputs.tf │ ├── nestedB/ │ ├── .../ ├── examples/ │ ├── exampleA/ │ │ ├── main.tf │ ├── exampleB/ │ ├── .../ ルートモジュール • main.tf • ルートモジュールのエントリーポイント • 複雑なモジュールの場合には、複数に分割する場合もある • variables.tf • ルートモジュールに対する入力変数を宣言する • descriptionは、可能な限り記述する • outputs.tf • ルートモジュールに対する出力変数を宣言する • descriptionは、可能な限り記述する

Slide 32

Slide 32 text

Copyright © 2023, Oracle and/or its affiliates 32 Terraformのモジュールには、標準の構造が存在する https://developer.hashicorp.com/terraform/language/modules/develop/structure Terraform Module 標準のモジュール構造に従う $ tree complete-module/ . ├── README.md ├── main.tf ├── variables.tf ├── outputs.tf ├── ... ├── modules/ │ ├── nestedA/ │ │ ├── README.md │ │ ├── variables.tf │ │ ├── main.tf │ │ ├── outputs.tf │ ├── nestedB/ │ ├── .../ ├── examples/ │ ├── exampleA/ │ │ ├── main.tf │ ├── exampleB/ │ ├── .../ • モジュールは、modules/*に配置する • 小さなモジュールに分割し、ユーザーが選択可能にするべき • README.md • 存在するモジュール → 外部ユーザーが使用可能なモジュール • 存在しないモジュール → 内部利用に限定されたモジュール

Slide 33

Slide 33 text

Copyright © 2023, Oracle and/or its affiliates 33 Terraformのモジュールには、標準の構造が存在する https://developer.hashicorp.com/terraform/language/modules/develop/structure Terraform Module 標準のモジュール構造に従う $ tree complete-module/ . ├── README.md ├── main.tf ├── variables.tf ├── outputs.tf ├── ... ├── modules/ │ ├── nestedA/ │ │ ├── README.md │ │ ├── variables.tf │ │ ├── main.tf │ │ ├── outputs.tf │ ├── nestedB/ │ ├── .../ ├── examples/ │ ├── exampleA/ │ │ ├── main.tf │ ├── exampleB/ │ ├── .../ • モジュールの使用例を examples/*に配置する • examples/*の目的、使い方を説明するREADMEを置いても良い

Slide 34

Slide 34 text

Copyright © 2023, Oracle and/or its affiliates 34 • モジュールは、GitHubのパブリックリポジトリとして公開する • リポジトリが命名規則(terraform-[PROVIDER]-[NAME])に則っている • e.g. terraform-oci-oke-quickstart • リポジトリにdescriptionを設定する • モジュールの標準構造に従っていること • リリースのタグ名がセマンティックバージョンであること • e.g. v1.0.4, 0.9.2 参考: 作ったTerraform Moduleを公開する

Slide 35

Slide 35 text

Copyright © 2023, Oracle and/or its affiliates 35 Terraform State = 管理対象のインフラや構成に関する状態を保存したもの 現実世界のリソースと構成ファイルとのマッピングや、メタデータの追跡等に用いられる Terraform State 宣言的なインフラを実現するための状態管理 { "version": 4, "terraform_version": "1.3.0", "serial": 16, "lineage": "9bcb7903-7f6a-ede8-d00c-1d5b34af2892", "outputs": {}, "resources": [ { "module": "module.shukawam_containerengine_cluster", "mode": "data", "type": "oci_containerengine_cluster_option", "name": "cluster_option", "provider": "module.shukawam_containerengine_cluster.provider[¥"registry.terraform.io/hashicorp/oci¥"]", "instances": [ { "schema_version": 0, "attributes": { "cluster_option_id": "all", "cluster_pod_network_options": [{"cni_type": "OCI_VCN_IP_NATIVE"}, {"cni_type": "FLANNEL_OVERLAY"}], "compartment_id": "ocid1.compartment.oc1..aaaaaaaanjtbllhqxcg67dq7em3vto2mvsbc6pbgk4pw6cx37afzk3tngmoa", "id": "ContainerengineClusterOptionDataSource-3081187312", "kubernetes_versions": ["v1.23.4", "v1.24.1", "v1.25.4"] }, "sensitive_attributes": [] } ] }, ... omit ... ], "check_results": [] } terraform.tfstate チーム間で共有したい場合はどうするか ロック…?更新漏れ…?機密情報…?

Slide 36

Slide 36 text

Copyright © 2023, Oracle and/or its affiliates 36 チーム間で何かを共有する → バージョン管理システム(Git, etc.)を使うのが一般的 Terraform Stateの場合 • バージョン管理下に置くことは良くないとされている • 最新のStateファイルのプッシュし忘れ • 同じStateファイルに対して、terraform applyを実行することをロックする機構が存在しない • 機密情報の扱いが複雑になる(Stateファイルが平文で保存されるため) • … バージョン管理システムではなく、専用のバックエンドを用いる • local, azurerm, consul, gcs, http, Kubernetes, pg, s3, Terraform Cloud, … *: OCI Object Storageの場合は、HTTP or S3互換バックエンドを用いる Terraform State Stateをチーム間でセキュアに公開する

Slide 37

Slide 37 text

Copyright © 2023, Oracle and/or its affiliates 37 1. 事前承認済みリクエスト(Read & Write)を作成する 2. ローカルのStateファイルを手動でアップロードする 3. Terraformバックエンドの構成を追加する 4. Terraformの再初期化(terraform init)を行う 例: OCI Object Storageをバックエンドとして使う https://docs.oracle.com/ja-jp/iaas/Content/API/SDKDocs/terraformUsingObjectStore.htm provider "oci" { region = var.region } terraform { required_version = ">=1.4.5" required_providers { oci = { source = "oracle/oci" version = ">= 4.116.0, < 5.0.0" } } backend "http" { address = "https://objectstorage.ap-tokyo-1.oraclecloud.com/" update_method = "PUT" } } 追記して再初期化

Slide 38

Slide 38 text

Copyright © 2023, Oracle and/or its affiliates 38 参考: セキュアなTerraformの使い方 https://speakerdeck.com/harukasakihara/sekiyuanaterraformfalseshi-ifang-ji-mi-qing-bao-wokodonihan-mezuhuan-jing-gou-zhu-surunihadousitaraiifalse 特にStateファイル(tfstate)に焦点を当てて、 • 機密情報の扱い方 • 機密情報を使うもの(DBのパスワード、etc.) • 機密情報そのもの(OCI Vault、etc.) • IaCで作るもの/CLI等手動で作ったほうが良いもの が非常によくまとまっています。是非、一読を!

Slide 39

Slide 39 text

Copyright © 2023, Oracle and/or its affiliates 39 通常のソフトウェア開発では… 期待する結果が得られることを自動的に確認したい → Unit, Integration, End-to-endテストを書く (特にモジュール開発の文脈では)Terraformでも… • Unitテスト → 再利用可能な単一のモジュールに対して正しく動作することを確認する • ※Terraformを扱う以上、外部依存をゼロにする方法はないので、純粋な意味でのUnitテストとは異なります • Integrationテスト → 複数のモジュールをデプロイし、それが正しく動作することを確認する • End-to-endテスト → 全てのモジュールをデプロイし、それが正しく動作することを確認する Terraformとテスト テストケースの数 コスト/ 忠実性 速度/ 決定性 テストピラミッドの考え方は、 ソフトウェアの開発・Terraformを 用いた開発で変わらない Unit tests Integration tests E2E tests

Slide 40

Slide 40 text

Copyright © 2023, Oracle and/or its affiliates 40 Terratest • Gruntwork社が開発 • インフラストラクチャのコードの自動テストを簡単に書けるようにするためのGoのライブラリ • Terraform, Packer, Docker, Kubernetes, …, etc. に対するヘルパー関数を提供 • Terraformモジュールから提供されているヘルパー関数の一例 • func terraform.WithDefaultRetryableErrors(t testing.TestingT, originalOptions *terraform.Options) • func terraform.InitAndApply(t testing.TestingT, options *terraform.Options) string • func terraform.Plan(t testing.TestingT, options *terraform.Options) string • func terraform.Destroy(t testing.TestingT, options *terraform.Options) string • etc. Terraformのテストを自動化する - Terratest

Slide 41

Slide 41 text

Copyright © 2023, Oracle and/or its affiliates 41 Demo: Terratestを用いたTerraformモジュールに対する自動テスト Buckets Tokyo . ├── .github │ └── workflows ├── terraform │ ├── examples │ ├── live │ └── modules └── test ├── go.mod ├── go.sum └── object-storage_test.go InitAndApply Terratest stretchr/testify assert.Equal(t,expected, actual) Tokyo Destroy Terratest trigger

Slide 42

Slide 42 text

Copyright © 2023, Oracle and/or its affiliates 42 静的解析ツール • 検証可能なエラーは限定的だが、高速&安定的に動作する • クラウドプロバイダに対する認証が不要で使えるのもメリット Terraformと静的解析 terraform validate tfsec tflint Terrascan Overview Terraform組み込みコマンド Terraformコードに対する セキュリティスキャン Terraform用のリンター コンプライアンス、 セキュリティ違反チェック License Terraformと同じ MIT MPL 2.0 Apache 2.0 Built-in checks 構文チェックのみ AWS, Azure, OCI, Kubernetes, etc. AWS, Azure, Google Cloud AWS, Azure, Google Cloud, Kubernetes, etc. Custom checks 非対応 YAML or JSON Go plugin Rego

Slide 43

Slide 43 text

Copyright © 2023, Oracle and/or its affiliates 43 tfsecを使って、可視性がパブリック(ObjectRead|ObjectReadWithoutList)のバケットの作成を指摘する Demo: Terraformの静的解析 - tfsec tfsec ¥ --var-file variables.tfvars resource "oci_objectstorage_bucket" "objectstorage_bucket" { compartment_id = var.compartment_ocid name = var.objectstorage_bucket_name namespace = var.objectstorage_namespace access_type = var.public_access_type } objectstorage_bucket_name = "example-bucket" objectstorage_namespace = "orasejapan" region = "ap-tokyo-1" public_access_type = "ObjectRead" main.tf variables.tfvars Result #1 HIGH Custom check failed for resource oci_objectstorage_bucket.objectstorage_bucket. Bucket visibility is public. ───────────────────────────────────────────────────────────── main.tf:3-8 ───────────────────────────────────────────────────────────── 3 resource "oci_objectstorage_bucket" "objectstorage_bucket" { 4 compartment_id = var.compartment_ocid 5 name = var.objectstorage_bucket_name 6 namespace = var.objectstorage_namespace 7 access_type = var.public_access_type 8 } ───────────────────────────────────────────────────────────── ID custom-custom-oci-00001 Impact Contents could be accidentally published externally. Resolution Set visibility to private ─────────────────────────────────────────────────────────────

Slide 44

Slide 44 text

Copyright © 2023, Oracle and/or its affiliates 44 Demo: OKE(+周辺リソース)のプロビジョニング 最初に実施したデモを改めて振り返る . ├── examples │ ├── container-engine │ ├── kube-config │ └── vcn ├── live │ └── oke-tutorial └── modules ├── container-engine ├── kube-config └── vcn OCI Region Availability Domain 1 Fault Domain 1 Fault Domain 2 Fault Domain 3 VCN LB Subnet 10.0.20.0/24 K8s API Subnet 10.0.0.0/28 Node Subnet 10.0.10.0/24 Container Engine for Kubernetes Worker Nodes Service Gateway Internet Gateway NAT Gateway terraform init|plan|apply

Slide 45

Slide 45 text

Copyright © 2023, Oracle and/or its affiliates 45 • HashiCorp社が開発しているIaCツールで、主にクラウドリソースのプロビジョニングに焦点を当てたツール • 実装におけるプラクティス • プロバイダーのインストールに細かく条件を設定する • 再利用可能な形でTerraformのコードを実装する(Terraform Module) • 専用のバックエンドを使ったStateのチーム間共有 • (特にモジュール開発では)自動テストや静的解析に取り組む • こんな人に向いている • 目的特化のシンプルな言語(HCL)で素早く習得したい • コミュニティの成熟度でツールを選定したい Terraformまとめ

Slide 46

Slide 46 text

Copyright © 2023, Oracle and/or its affiliates 46 Pulumi/Pulumi AI

Slide 47

Slide 47 text

Copyright © 2023, Oracle and/or its affiliates 47 Pulumi • Pulumi社が開発しているクラウドインフラを作成、デプロイ、管理するためのOSSのIaCツール • あるべき状態を定義し、Pulumi (SDK)がクラウドベンダーへAPIリクエストを行うことでインフラの管理を行う • 既存のプログラミング言語を用いて宣言的にあるべき状態を定義 • TypeScript, JavaScript, Python, Go, .NET, Java, YAMLなどのマークアップ言語, etc. • 状態を記録するStateファイルを用いてPulumiのエンジンが計算を行うことで、冪等性担保 Pulumiとは?

Slide 48

Slide 48 text

Copyright © 2023, Oracle and/or its affiliates 48 Pulumiのアーキテクチャ 引用:https://www.pulumi.com/docs/intro/concepts/how-pulumi-works/

Slide 49

Slide 49 text

Copyright © 2023, Oracle and/or its affiliates 49 Pulumi Providers Terraformには劣るが 主要所は大体カバーできている 参考: https://www.pulumi.com/registry/packages/oci/ Terraform Provider for OCIのラッパーを Pulumiが開発・管理している

Slide 50

Slide 50 text

Copyright © 2023, Oracle and/or its affiliates 50 ところで、今日扱ったIaCツールのコードを実際に書いたことありますか? const opensearchCluster = new oci.opensearch.Cluster("OpenSearch Cluster", { compartmentId: compartmentId, displayName: "opensearch-cluster", dataNodeCount: 1, dataNodeHostType: "FLEX", dataNodeHostOcpuCount: 1, dataNodeHostMemoryGb: 20, dataNodeStorageGb: 50, masterNodeCount: 1, masterNodeHostType: "FLEX", masterNodeHostOcpuCount: 1, masterNodeHostMemoryGb: 20, opendashboardNodeCount: 1, opendashboardNodeHostOcpuCount: 1, opendashboardNodeHostMemoryGb: 8, softwareVersion: "2.3.0", subnetCompartmentId: compartmentId, subnetId: subnet.id, vcnCompartmentId: compartmentId, vcnId: vcn.id, }); ##### VCN resource "oci_core_vcn" "vcn" { compartment_id = var.compartment_ocid cidr_block = local.vcn_cidr_block display_name = var.vcn_display_name } ##### Gateways resource "oci_core_internet_gateway" "internet_gateway" { compartment_id = var.compartment_ocid vcn_id = oci_core_vcn.vcn.id display_name = local.internet_gateway_display_name } resource "oci_core_nat_gateway" "nat_gateway" { compartment_id = var.compartment_ocid vcn_id = oci_core_vcn.vcn.id display_name = local.nat_gateway_display_name } # ... omit ... pulumi/index.ts terraform/main.tf

Slide 51

Slide 51 text

Copyright © 2023, Oracle and/or its affiliates 51 個人的には、結構辛い…

Slide 52

Slide 52 text

Copyright © 2023, Oracle and/or its affiliates 52 • 簡単な構成だけど、意外とパラメータを沢山設定しないといけないものが多い • いちいち、API Docsを調べるのが面倒 • 使用例はあるけど、一部のパラメータの例しか掲載されていなくて丁度良いスニペットが中々ない • 実際に動かしてみる(=実際にデプロイしてみる)までそのコードが正しく動くか分からない いい感じに動くコードをいい感じに生成してくれる何かがあれば… IaCのコードを書くことが辛い理由

Slide 53

Slide 53 text

Copyright © 2023, Oracle and/or its affiliates 53 Pulumi AI is an experimental feature that lets you use natural-language prompts to generate Pulumi infrastructure-as-code programs in any language. This page is a web-based version of the open-source Pulumi AI project. 引用)https://www.pulumi.com/ai/ 日本語訳: Pulumi AIは、自然言語のプロンプトを使って、任意の言語でPulumi infrastructure-as-codeプログラムを生成できる 実験的機能です。このページは、オープンソースのPulumi AIプロジェクトのウェブベース版です。 昨今、流行りのGPTモデルを搭載した自然言語 → インフラ構成コードを自動生成するヤツ Pulumi AI - IaCのコードを書く上での救世主になりえるか…?

Slide 54

Slide 54 text

Copyright © 2023, Oracle and/or its affiliates 54 Demo: Helidon on Kubernetes w/ Pulumi AI OCI Region Availability Domain 1 Fault Domain 1 Fault Domain 2 Fault Domain 3 VCN LB Subnet 10.0.20.0/24 K8s API Subnet 10.0.0.0/28 Node Subnet 10.0.10.0/24 Container Engine for Kubernetes Worker Nodes Service Gateway Internet Gateway NAT Gateway . ├── Pulumi.yaml ├── index.ts ├── node_modules ├── package-lock.json ├── package.json └── tsconfig.json pulumi preview|up Deployment Pulumi AIで作ります

Slide 55

Slide 55 text

Copyright © 2023, Oracle and/or its affiliates 55 • Pulumi社が開発しているクラウドインフラを作成、デプロイ、管理するためのOSSのIaCツール • 既存のプログラミング言語を用いて宣言的にあるべき状態を定義 • あるべき状態を定義し、Pulumi (SDK)がクラウドベンダーへAPIリクエストを行うことでインフラの管理を行う • こんな人に向いている • GPLの知識を活かしたい • GPLならではの柔軟な表現力を活用してインフラ管理したい • 言語の持つエコシステム(IDE、テストライブラリ、etc.)を活用したい Pulumiまとめ

Slide 56

Slide 56 text

Copyright © 2023, Oracle and/or its affiliates 56 Terraform Pulumi/Pulumi AI GPL/DSL DSL GPL(TypeScript, Go, Python, …) Providers 3,000+ 130+ エコシステム Terratest, Terragrunt, tfsec, tflint, … 言語のエコシステムをそのまま活用 表現の自由度 なし(=統一的な書き方を強制できる) 高い コミュニティ 大規模 小~中規模 本日扱ったIaCツール総まとめ ※2023/07現在

Slide 57

Slide 57 text

Copyright © 2023, Oracle and/or its affiliates 57 • IaC =(広義には)インフラストラクチャを定義、展開、更新、破棄するためのコードを書き、それを実行すること • 手動で実施してきた作業をコードに変換する先行投資と引き換えに、ソフトウェアのデリバリーを効率化する • 多くのツールが存在するが、実現したいこと・スキルセット等を考え最適なツールを選ぶことが重要 まとめ

Slide 58

Slide 58 text

Copyright © 2023, Oracle and/or its affiliates 58 Terraform • https://www.terraform.io/ • Terraform: Up and Running, 3rd Edition • Terraformを使用するためのベストプラクティス • Terratest • セキュアなTerraformの使い方 ~ 機密情報をコードに含めず環境構築するにはどうしたらいいの? Pulumi • https://www.pulumi.com/ その他(デモコードなど) • デモコード: https://github.com/oracle-japan/ochacafe-iac/ • モジュール公開のサンプル: https://registry.terraform.io/modules/shukawam/oke-quickstart/oci/latest • Cloud Guardに基づくtfsecのルール(for OCI): https://github.com/shukawam/tfsec-oci-custom-checks 参考情報

Slide 59

Slide 59 text

Thank you Copyright © 2023, Oracle and/or its affiliates 59