RPM Orchestrator を使用して GCE VM に AlloyDB Omni 高可用性クラスタをデプロイする

1. はじめに

この Codelab では、Google Compute Engine(GCE)仮想マシン(VM)への AlloyDB Omni 高可用性(HA)クラスタのデプロイについて説明します。この Codelab の最後には、3 つのデータベース ノードと 2 つの HAProxy ノードで構成される HA リファレンス アーキテクチャと、管理オペレーション用のコントロール ノードがプロビジョニングされます。

前提条件

  • Cloud Console から Google Cloud プロジェクトと Cloud Shell にアクセスする。
  • Google Cloud SDK(gcloud)のインストールと構成。gcloud のインストールの詳細については、gcloud-install をご覧ください。
  • Terraform v1.9.8 がインストールされている。

学習内容

  • AlloyDB Omni 用に GCE VM を作成して準備する方法。
  • AlloyDB Omni RPM Orchestrator をインストールして実行する方法。
  • HA リファレンス アーキテクチャ用に AlloyDB Omni RPM をインストールして構成する方法。

必要なもの

  • AlloyDB Omni RPM と RPM オーケストレーターの URL リンクを取得します。これを行うには、AlloyDB Omni 登録フォームに記入する必要があります。リンクは、リポジトリ URL サーバーのメールアドレスに送信されます。Codelab で使用する URL をすぐに使用できるように、次の環境変数を初期化します。
    export ORCHESTRATOR_ANSIBLE_COLLECTION_PATH="..."
    export ALLOYDB_OMNI_REPOSITORY_URL="..."
    export ALLOYDB_OMNI_ORCHESTRATOR_REPOSITORY_URL="..."
    export ALLOYDB_OMNI_COMMON_REPOSITORY_URL=....
    export ETCD_REPOSITORY_URL="..."
    
  • AlloyDB Omni デプロイ スタックにアクセスできる動作中のターミナル。この目的には、Cloud Shell を使用できます。

2. 設定と要件

プロジェクトのセットアップ

Google Cloud プロジェクトの作成

  1. Google Cloud コンソールのプロジェクト セレクタ ページで、Google Cloud プロジェクトを選択または作成します。
  2. Cloud プロジェクトに対して課金が有効になっていることを確認します。プロジェクトで課金が有効になっているかどうかを確認する方法をご覧ください。

Cloud Shell の起動

Google Cloud はノートパソコンからリモートで操作できますが、この Codelab では、Google Cloud Shell(Cloud 上で動作するコマンドライン環境)を使用します。

Google Cloud コンソールで、右上のツールバーにある Cloud Shell アイコンをクリックします。

Cloud Shell をアクティブにするアイコン

または、G キーを押してから S キーを押します。このシーケンスは、Google Cloud コンソール内からアクセスした場合、またはこのリンクを使用した場合に Cloud Shell をアクティブにします。

プロビジョニングと環境への接続にはそれほど時間はかかりません。完了すると、次のように表示されます。

環境が接続されたことを示す Google Cloud Shell ターミナル

この仮想マシンには、必要な開発ツールがすべて用意されています。永続的なホーム ディレクトリが 5 GB 用意されており、Google Cloud で稼働します。そのため、ネットワークのパフォーマンスと認証機能が大幅に向上しています。この Codelab での作業はすべて、ブラウザ内から実行できます。インストールは不要です。

3. Google Cloud Compute Engine 仮想マシンを作成する

Terraform スクリプトを準備する

  1. プロジェクト ID と目的のクラスタ名の環境変数を定義します。これらのサンプルは、この Codelab 全体で使用します。
    export PROJECT="your-project-id"
    export CLUSTER="your-cluster-name"
    
    注: Google Cloud プロジェクト ID は 6 ~ 30 文字の長さにしてください。詳細については、https://docs.cloud.google.com/resource-manager/docs/creating-managing-projects#before_you_begin をご覧ください。
  2. Google Cloud アカウントのユーザーでログインしていることを確認します。
    gcloud auth login
    
  3. デプロイ用の作業ディレクトリを作成し、リポジトリ ソースから必要な Terraform 構成ファイルをコピーします。
    mkdir -p ~/alloydb-omni/$PROJECT/$CLUSTER
    cd ~/alloydb-omni/$PROJECT/$CLUSTER
    gcloud storage cp gs://alloydb-omni-install/rpm-orchestrator/gce/terraform/*.tf .
    
  4. terraform.tfvars ファイルを作成し、次の内容に従ってリファレンス アーキテクチャに必要なパラメータを指定します。
    cat > terraform.tfvars <<EOF
    # Required instance counts for reference architecture
    db_instance_count      = 3
    haproxy_instance_count = 2
    control_instance_count = 1
    
    # Optional: Customize if needed with the below variables
    # os_image             = "rocky-linux-cloud/rocky-linux-9"
    # zone                 = "us-west4-c"
    # region_1             = "us-west4"
    # db_instance_type     = "c4-highmem-4"
    # db_disk_type         = "hyperdisk-balanced"
    # db_data_size         =  "50" # GB
    # data_dir             =  "/data"
    EOF
    

Terraform スクリプトを実行して検証する

  1. これで、VM をプロビジョニングできます。
    terraform init
    
  2. VM を作成する前に、VM やその他のリソースを作成するために必要なアクセス権があることを確認してください。必要な権限は次のとおりです。
    roles/compute.admin
    roles/iam.roleAdmin
    roles/compute.osAdminLogin
    roles/iam.serviceAccountCreator
    roles/iam.serviceAccountUser
    roles/artifactregistry.repoAdmin
    roles/storage.objectUser
    roles/resourcemanager.projectIamAdmin
    roles/serviceusage.serviceUsageAdmin
    
  3. 構成を検証し、構成を適用してリソースをプロビジョニングします。
    terraform validate
    terraform apply --auto-approve
    
    注: デプロイ構成で想定されているとおりに Terraform v1.9.8 を使用していることを確認してください。
  4. Terraform が完了したら、gcloud を使用して作成されたインスタンスを一覧表示し、仮想マシンが正常に作成されたことを確認します。
    gcloud compute instances list --filter="name~$CLUSTER" --project=$PROJECT
    
    3 つの DB ノード、2 つの HAProxy ノード、コントロール VM と対応するゾーンに対応するインスタンスが表示されます。コントロール ノードの ZONE を記録します。この Codelab の後半で必要になります。
    export ZONE=$(gcloud compute instances list \
      --filter="name=$CLUSTER-control"          \
      --format="value(zone)" --project=$PROJECT)
    

4. デプロイ用に VM を準備する

コントロール ノードへの SSH セッションを作成し、すべての VM(ノードとも呼ばれます)への SSH アクセスを有効にする手順を実行する必要があります。

  1. プロジェクトとクラスタの環境変数が定義されていることを確認します。
    export PROJECT="your-project-id"
    export CLUSTER="your-cluster-name"
    
  2. SSH 認証鍵を作成し、コントロール VM にログインするために同じ認証鍵を追加します。
    # Replace values with your specific GCP project, cluster and zone details
    ssh-keygen -t ed25519 -f $HOME/.ssh/google_compute_engine
    gcloud compute os-login ssh-keys add --key-file=$HOME/.ssh/google_compute_engine.pub --project=$PROJECT
    
  3. SSH 接続を許可し、VRRP トラフィックも許可するファイアウォール ルールを作成します。
    gcloud compute config-ssh --project=$PROJECT
    gcloud compute firewall-rules create $CLUSTER-allow-ssh --network=$CLUSTER --project=$PROJECT --direction=INGRESS --action=allow --rules=tcp:22 --source-ranges="0.0.0.0/0"
    gcloud compute firewall-rules create $CLUSTER-allow-vrrp --network=$CLUSTER --project=$PROJECT --allow=112 --source-ranges="0.0.0.0/0"
    
  4. SSH 経由で制御 VM に接続します。
    gcloud compute ssh "$CLUSTER-control" --zone=$ZONE --project=$PROJECT
    
  5. ユーザー名と同じ名前の Linux グループをコントロール ノードに作成します。
    sudo groupadd $(id -un)
    sudo usermod -aG $(id -un) $(id -un)
    
  6. Terraform の設定では、いくつかの構成スクリプトが作成され、クラスタ名、サービス アカウント、プロジェクト名などの情報を含む制御 VM の /tmp/ ディレクトリにステージングされます。制御ノードのセットアップ スクリプトを使用して、制御ノードからすべてのクラスタノードへのパスワードなしの SSH アクセスを作成します。
    /tmp/setup-ssh-for-cluster.sh
    
    重要: service_account ユーザーをメモします。この値は、この Codelab の後半で SSH_USER として使用します。
  7. この Codelab では、すべてのノードで SELinux を無効にできます。Terraform スクリプトは、この目的で使用できる「/tmp/run-all.sh」を追加します。
    /tmp/run-all.sh sudo setenforce 0
    
  8. AlloyDB Omni に登録してリンクを取得したら、これらの URL を環境変数に追加します。
    cat >> ~/.codelab.env <<EOF
    export ORCHESTRATOR_ANSIBLE_COLLECTION_PATH="..."
    export ALLOYDB_OMNI_REPOSITORY_URL="..."
    export ALLOYDB_OMNI_ORCHESTRATOR_REPOSITORY_URL="..."
    export ALLOYDB_OMNI_COMMON_REPOSITORY_URL=....
    export ETCD_REPOSITORY_URL="..."
    EOF
    
    次の例に示すように、ファイル terraform/variables.tf の cidr_range 入力変数から、他のノードと競合しない環境の仮想 IP を決定します。
    cat >> ~/.codelab.env <<EOF
    export VIRTUAL_IP="10.1.0.50"
    EOF
    

5. すべての VM に必要なソフトウェア コンポーネントをインストールします。

次のステップでは、必要な SW コンポーネントを VM にインストールします。これは制御ノードで調整できます。次のコマンドはすべてコントロール ノードで実行する必要があります。

  1. コントロール ノードにまだ接続していない場合は、SSH 経由でコントロール VM に接続します。
    gcloud compute ssh "$CLUSTER-control" --zone=$ZONE --project=$PROJECT
    
    制御 VM の ssh プロンプトが表示されたら、移行元の環境ファイルを指定します。
    source ~/.codelab.env
    
  2. コントロール ノードに Ansible と必要な Python ライブラリをインストールします。
    sudo dnf install -y https://dl.fedoraproject.org/pub/epel/epel-release-latest-9.noarch.rpm -y
    sudo dnf install -y ansible
    sudo dnf install -y python3-grpcio python3-protobuf python3-googleapis-common-protos python3-grpcio-status
    
  3. 次に、RPM Orchestrator Ansible コレクションの tar ファイルをダウンロードしてインストールします。
    gcloud storage cp "gs://${ORCHESTRATOR_ANSIBLE_COLLECTION_PATH#https://storage.googleapis.com/}google-alloydbomni_orchestrator-*.tar.gz" .
    ansible-galaxy collection install google-alloydbomni_orchestrator-0.1.0-6.tar.gz
    ansible-galaxy collection list | grep alloydbomni_orchestrator
    
    注: ORCHESTRATOR_ANSIBLE_COLLECTION_PATH 変数の末尾に「/」があることを確認します。
  4. オーケストレーターは、Ansible インベントリ形式のデプロイ仕様ファイルを使用して、クラスタ トポロジを把握します。コントロール ノードにノードの詳細を含む deployment_spec.yaml という名前のファイルを作成します。
    cat > deployment_spec.yaml <<EOF
    alloydbomni:
      vars:
        cluster_manager:
          name: "$CLUSTER"
        etcd:
          setup: true
          config_forcewrite: true
        alloydbomni:
          major_version: "18"
          repo_url: $ALLOYDB_OMNI_REPOSITORY_URL
        alloydbomni_monitor:
          repo_url: $ALLOYDB_OMNI_COMMON_REPOSITORY_URL
        alloydbomni_cluster_manager:
          repo_url: $ALLOYDB_OMNI_ORCHESTRATOR_REPOSITORY_URL
        alloydbomni_node_manager:
          repo_url: $ALLOYDB_OMNI_ORCHESTRATOR_REPOSITORY_URL
        pgbouncer:
          repo_url: $ALLOYDB_OMNI_COMMON_REPOSITORY_URL
        pgbackrest:
          repo_url: $ALLOYDB_OMNI_COMMON_REPOSITORY_URL
    
      children:
        primary_instance_nodes:
          hosts:
            $CLUSTER-db1:
            $CLUSTER-db2:
            $CLUSTER-db3:
        load_balancer_nodes:
          hosts:
            $CLUSTER-haproxy1:
            $CLUSTER-haproxy2:
    EOF
    
    注: 生成されたファイルを確認して、有効な値が参照されていることを確認します。
  5. オーケストレーター コレクションのインストール ロールを参照する install.yaml という名前のプレイブックを作成します。
    cat > install.yaml <<EOF
    - name: Install AlloyDB Omni cluster components
      hosts: all
      vars:
        ansible_become: true
        ansible_user: $SSH_USER
        ansible_ssh_private_key_file: $HOME/ssh-key-cluster-sa
      roles:
        - role: google.alloydbomni_orchestrator.install
    EOF
    
    注: 生成されたファイルを確認して、有効な値が参照されていることを確認します。
  6. インベントリ ファイルを使用して Playbook を実行し、指定されたすべてのノードに RPM をダウンロードしてインストールします。
    ansible-playbook -i deployment_spec.yaml install.yaml
    

6. AlloyDB Omni クラスタをブートストラップする

この段階では、必要なすべてのコンポーネントがすべてのノードにインストールされています。AlloyDB Omni クラスタをブートストラップする準備が整いました。

  1. コントロール ノードにまだ接続していない場合は、SSH 経由でコントロール VM に接続します。
    gcloud compute ssh "$CLUSTER-control" --zone=$ZONE --project=$PROJECT
    
    制御 VM の ssh プロンプトが表示されたら、移行元の環境ファイルを指定します。
    source ~/.codelab.env
    
  2. パスワードのハッシュを生成してメモします。
    encoded_password=$(echo -n "your unique password" | base64)
    
  3. クラスタを作成するには、AlloyDB Omni がクラスタの構成方法を認識している必要があります。DB クラスタ仕様のファイル名 dbcluster.yaml を作成します。
    cat > dbcluster.yaml <<EOF
    Secret:
      metadata:
        name: db-pw-$CLUSTER
      spec:
        type: Opaque
        data:
          $CLUSTER: $encoded_password
    ---
    DBCluster:
      metadata:
        name: $CLUSTER
      spec:
        databaseVersion: 18.1.0
        mode: ""
        availability:
          numberOfStandbys: 2
          enableAutoFailover: true
          enableAutoHeal: true
          autoFailoverTriggerThreshold: 2
          autoHealTriggerThreshold: 2
          healthcheckPeriodSeconds: 5
          replayReplicationSlotsOnStandbys: false
        primarySpec:
          adminUser:
            passwordRef:
              name: db-pw-$CLUSTER
          resources:
            cpu: 4
            memory: 32Gi
            disks:
            - name: DataDisk
              path: $PGDATA
          dbLoadBalancerOptions:
            gcp:
              loadBalancerIP: "$VIRTUAL_IP"
              loadBalancerType: "internal"
              loadBalancerInterface: "eth0"
    EOF
    
  4. AlloyDB Omni クラスタの作成に使用するブートストラップ Ansible ロールを参照する bootstrap.yaml という名前のプレイブックを作成します。
    cat > bootstrap.yaml <<EOF
    - name: Create DBCluster
      hosts: localhost
      vars:
        ansible_become: true
        ansible_user: $SSH_USER
        ansible_ssh_private_key_file: $HOME/ssh-key-cluster-sa
      roles:
      - role: google.alloydbomni_orchestrator.bootstrap
    EOF
    
  5. プレイブックを実行してクラスタを作成する
    ansible-playbook bootstrap.yaml -i deployment_spec.yaml -e resource_spec=dbcluster.yaml
    

7. (省略可)PgBouncer 接続プーラーを構成する

AlloyDB Omni は、PgBouncer を使用した軽量接続プーリングをサポートしています。クラスタのプロビジョニング直後に PgBouncer を構成してブートストラップできます。

  1. 接続プーラーをデータベース クラスタに関連付ける pgbouncer.yaml という名前のリソース仕様ファイルを作成します。
    cat > pgbouncer.yaml <<EOF
    PgBouncer:
      metadata:
        name: pgbouncer-pooler
      spec:
        dbclusterRef: $CLUSTER
        allowSuperUserAccess: true
        accessMode: "rw"
        port: 6432
    EOF
    
  2. 前に作成した同じ bootstrap.yaml プレイブックを使用して PgBouncer プーラーをブートストラップし、新しい仕様ファイルを渡します。
    ansible-playbook bootstrap.yaml -i deployment_spec.yaml -e resource_spec=pgbouncer.yaml
    

8. AlloyDB Omni クラスタを確認する

クラスタが正しく機能し、ロードバランサを使用してアクセスできることを確認するには、コントロール ノードから標準の PostgreSQL クライアントを使用してクラスタに接続します。

  1. コントロール ノードに PostgreSQL 18 クライアント リポジトリとパッケージをインストールします。
    sudo dnf install -y https://download.postgresql.org/pub/repos/yum/reporpms/EL-9-x86_64/pgdg-redhat-repo-latest.noarch.rpm
    sudo dnf install -y postgresql18
    
  2. 前に予約した仮想 IP を使用してクラスタに接続します。dbcluster.yaml でエンコードしたパスワードの入力を求められます。
    /usr/pgsql-18/bin/psql -h $VIRTUAL_IP -U postgres -W
    
  3. 接続したら、基本的な SQL クエリを実行してクラスタの状態を確認できます。たとえば、データベースのバージョンを確認します。
    postgres=# SELECT version();
    
    AlloyDB Omni で PostgreSQL 18 が実行されていることを示す出力が表示されます。\q と入力してプロンプトを終了します。

9. (省略可)pgBackRest を使用してデータをバックアップする

AlloyDB Omni は pgBackRest と統合して、Cloud Storage へのバックアップを直接管理します。バックアップ プランを構成し、Terraform 設定で作成した GCS バケットへのオンデマンド バックアップをトリガーできます。

  1. プロビジョニングされた GCS バケットを指す backup_plan.yaml という名前のバックアップ プラン仕様ファイルを作成します。
    cat > backup_plan.yaml <<EOF
    BackupPlan:
      metadata:
        name: pgb-plan
      spec:
        dbclusterRef: $CLUSTER
        backupLocation:
          type: GCS
          gcsOptions:
            bucket: $CLUSTER-gcs-backups
            key: /backups
    EOF
    
  2. バックアップ管理ロールを参照する backup.yaml という名前の Ansible プレイブックを作成します。
    cat > backup.yaml <<EOF
    - name: Manage AlloyDB Omni Backups
      hosts: localhost
      vars:
        ansible_become: true
        ansible_user: $SSH_USER
        ansible_ssh_private_key_file: $HOME/ssh-key-cluster-sa
      roles:
        - role: google.alloydbomni_orchestrator.backup
    EOF
    
  3. backup.yaml プレイブックを使用してバックアップ プランを適用します。
    ansible-playbook backup.yaml -i deployment_spec.yaml -e resource_spec=backup_plan.yaml
    
  4. プランが正常に確立されたら、create_backup.yaml という名前のオンデマンド バックアップ リソース ファイルを作成します。
    cat > create_backup.yaml <<EOF
    Backup:
      metadata:
        name: on-demand-backup
      spec:
        backupPlanRef: pgb-plan
        dbclusterRef: $CLUSTER
    EOF
    
  5. ハンドブックを実行してバックアップを開始します。
    ansible-playbook backup.yaml -i deployment_spec.yaml -e resource_spec=create_backup.yaml
    
  6. バックアップのステータスを確認するには、status.yaml プレイブックを作成します。
- name: Fetch AlloyDB Omni Resource Status
hosts: localhost
vars:
  ansible_become: true
  ansible_user: $SSH_USER
  ansible_ssh_private_key_file: $HOME/ssh-key-cluster-sa
roles:
  - role: google.alloydbomni_orchestrator.status
EOF
  1. プレイブックを実行して、すべてのバックアップを一覧表示します。
ansible-playbook status.yaml -i deployment_spec.yaml -e resource_type=Backup
  1. 別の方法として、以前に作成した特定のバックアップの詳細情報を取得するには、-e resource_name=on-demand-backup を渡します。
ansible-playbook status.yaml -i deployment_spec.yaml \
  -e resource_type=Backup \
  -e resource_name=on-demand-backup

10. リソースをクリーンアップする

デプロイが完了したら、プロビジョニングされたリソースを破棄して、料金の発生を防ぐことができます。

  1. teardown.yaml という名前のハンドブックを作成します。
    cat > teardown.yaml <<EOF
    - name: Tear down AlloyDB Omni cluster
      hosts: localhost
      vars:
        ansible_become: true
        ansible_user: $SSH_USER
        ansible_ssh_private_key_file: $HOME/ssh-key-cluster-sa
      roles:
      - role: google.alloydbomni_orchestrator.delete
    EOF
    
  2. ansible-playbook を使用してハンドブックを実行します。バックアップを構成した場合は、まず Backup リソースと BackupPlan リソースを削除します。
    ansible-playbook teardown.yaml -i deployment_spec.yaml  -e "resource_type=Backup" -e "resource_name=on-demand-backup"
    ansible-playbook teardown.yaml -i deployment_spec.yaml  -e "resource_type=BackupPlan" -e "resource_name=pgb-plan"
    
    PgBouncer を構成した場合は、次に接続プーラー リソースを削除します。
    ansible-playbook teardown.yaml -i deployment_spec.yaml  -e "resource_type=PgBouncer" -e "resource_name=pgbouncer-pooler"
    
    次に、resource_type として DBCluster を指定し、データベース クラスタ自体を削除します。
    ansible-playbook teardown.yaml -i deployment_spec.yaml  -e "resource_type=DBCluster" -e "resource_name=$CLUSTER"
    
  3. クラスタが削除されたら、コントロール ノードからログアウトし、ターミナルに戻って Terraform 作業ディレクトリに移動します。
    : Cloud Shell にログインしたばかりの場合は、次の設定を行う必要があります。
    export PROJECT="your-project-id"
    export CLUSTER="your-cluster-name"
    
  4. VRRP ファイアウォール ルールを削除し、Terraform で管理されているリソースを破棄します。
    gcloud compute firewall-rules delete -q "$CLUSTER-allow-vrrp" --project="$PROJECT"
    gcloud compute firewall-rules delete -q "$CLUSTER-allow-ssh" --project="$PROJECT"
    terraform destroy
    
  5. メッセージが表示されたら、破棄を確定します。ネットワーク リソースやルートが残っていると、完全な削除が妨げられることがあるため、次の安全なクリーンアップ コマンドを実行して、関連するファイアウォール ルール、NAT ゲートウェイ、ルーター、ルート、サブネット、ネットワークがすべて完全に削除されるようにします。REGION は、特定のデプロイ リージョン(us-central1 など)に置き換えます。
    # Delete any remaining firewall rules associated with the cluster
    gcloud compute firewall-rules list --project=$PROJECT 2> /dev/null | grep ^$CLUSTER- | cut -f1 -d' ' | \
      while read rule; do gcloud compute firewall-rules delete --project=$PROJECT --quiet $rule; done
    
    # Delete the Cloud NAT gateway and router if they still exist
    gcloud compute routers nats describe $CLUSTER-nat-gw --router=$CLUSTER-router --region=REGION --project=$PROJECT 2>/dev/null \
      && gcloud compute routers nats delete $CLUSTER-nat-gw --router=$CLUSTER-router --region=REGION --project=$PROJECT --quiet
    
    gcloud compute routers describe $CLUSTER-router --region=REGION --project=$PROJECT 2>/dev/null \
      && gcloud compute routers delete $CLUSTER-router --region=REGION --project=$PROJECT --quiet
    
    # Delete any remaining custom routes
    gcloud compute routes list --project=$PROJECT --filter="network:$CLUSTER" --format="value(name)" 2>/dev/null | \
      while read route; do gcloud compute routes delete --project=$PROJECT --quiet $route 2>/dev/null || true; done
    
    # Delete the subnet and network if they still exist
    gcloud compute networks subnets describe $CLUSTER --region=REGION --project=$PROJECT 2>/dev/null \
      && gcloud compute networks subnets delete $CLUSTER --region=REGION --project=$PROJECT --quiet
    
    gcloud compute networks describe $CLUSTER --project $PROJECT 2> /dev/null \
      && gcloud compute networks delete $CLUSTER --project $PROJECT --quiet
    

11. 完了

以上で、この Codelab は完了です。

学習した内容

  • AlloyDB Omni 用に GCE VM を作成して準備する方法。
  • AlloyDB Omni RPM Orchestrator をインストールして実行する方法。
  • HA リファレンス アーキテクチャ用に AlloyDB Omni RPM をインストールして構成する方法。

AlloyDB Omni の詳細については、ドキュメントをご覧ください。

12. アンケート

このチュートリアルの利用方法をお選びください。

全体を通して読むだけ 内容を読んで演習をやり遂げる