LoginSignup
16
0

AWSにTerraformを使ってCMLを構築してみた

Last updated at Posted at 2023-12-05

はじめに

この記事はCisco Systems Japan Advent Calendar 2023の6日目の記事となります。

2017年版: https://qiita.com/advent-calendar/2017/cisco
2018年版: https://qiita.com/advent-calendar/2018/cisco
2019年版: https://qiita.com/advent-calendar/2019/cisco
2020年版 1枚目: https://qiita.com/advent-calendar/2020/cisco
2020年版 2枚目: https://qiita.com/advent-calendar/2020/cisco2
2021年版 1枚目https://qiita.com/advent-calendar/2021/cisco
2021年版 2枚目https://qiita.com/advent-calendar/2021/cisco2
2022年版(1,2): https://qiita.com/advent-calendar/2022/cisco
2023年版: https://qiita.com/advent-calendar/2023/cisco<---こちら

CMLを使用したいが、サーバーはない。

そんな時は、AWSのCloud環境でCMLを構築することができます。これで、サーバなど大掛かりな環境がなくても手軽に構築することができます。でも、AWSは利用時の費用が心配ですよね。
今回、CML2.6からTerraformを使ってCMLが作成できるようになりました。これによりAWSで作成するのに時間がとられて、検証をできない!!という状況を脱し、サクッと構築し、使わない際は消して、できるだけ費用負担がかからないようにしたいと考えました。CMLの構築方法はGitHubを参考に作成しております。

実施環境

次の環境にて構築を行いました。Macbook、Windows環境はテストされていませんのでご注意ください。

  • WSL : version2(Ubuntu : 22.04.2)
  • Terraform : 1.6.5
  • AWS : aws-cli/2.14.3
  • bash : 5.1.16 注:Versionが低いとAWS CLIが動作しません。
  • CML2 : 2.6.1-11

事前準備

  • AWSアカウント作成
  • GitHubの環境をクローン
  • 作業を行う端末にTerraformAWS CLI、他関連する環境設定
  • CMLのイメージ、ライセンスを準備(cml2_2.6.x_amd64-6.pkg、refplat-2023xxxx-fcs.iso)

1章 AWS環境の作成

You Tubeを参考に作成可能です。手順は以下のように実施します。

  1. VPCを作成
  2. S3バケットを作成
  3. ユーザグループを作成
  4. 新規ポリシーの作成
  5. ユーザグループにポリシーをアタッチさせる
  6. ロールを作成
  7. ユーザグループに割当
  8. ユーザを作成
  9. インスタンス作成、認証情報の作成※Terraform起動時に使用
  10. AWSのインスタンスへSSHを実行
AWS環境作成の詳細はこちら You Tubeの内容+αを備忘録として残します。

1. VPCを作成

[VPCを作成]->[VPCなど]->[VPC作成]

2. S3バケットを作成

Amazon S3->[バケットを作成] ->
・ [AWSリージョン]を”ap-northeast-1”プルダウンで選択
・ バケット名"cmlbucket"入力
->[バケットを作成]

3. ユーザグループを作成

IAM->[グループの作成]->
・ [グループ名]を入力
・ [ポリシー]にて以下選択
ポリシー:AmazonEC2FullAccess
->[グループの作成]
1.png

4. 新規ポリシーの作成

[ポリシーの作成]->
[サービスを選択]から「S3」選択
・ リスト:ListBucket
・ 読み取り:GetObject
・ 書き込み:PutObject
・ リソース:[特定]を選択
・ Bucketの[ARNを追加]で先ほどのバケットを指定
・ objectの[ARNを追加]で先ほどのバケットを指定、
[任意オブジェクト名]をチェック
2.png

->[次へ]
・ポリシー名を入力※今回は"cml-s3-access"
->[ポリシーを作成]

5. ユーザグループにポリシーを割当

ユーザグループより先ほどのグループを選択
->[許可]タブ->[ポリシーをアタッチ]->
先ほどのポリシー"cml-s3-access"を追加
3.png

6. ロールを作成

[ロールの作成]
・ ユースケースの[EC2]選択
->[次へ]
・ 許可を追加にて"cml-s3-access"選択
->[次へ]
・ ロール名を入力※今回は"s3-access-for-ec2"にて作成
->[ロール作成]
4.png

7. ユーザグループに割当

・ ユーザグループより先ほど作成したグループを選択
->[許可]タブ->[インラインポリシーを作成]->
・[サービスを選択]にて以下項目を選択
 - 書き込み:PassRole
 - Roleの[ARNを追加]
・[このアカウント]をクリック
・"s3-access-for-ec2"を入力
->[次へ]
・ポリシー名"pass-role"を入力
->[ポリシーを作成]
5.png

8.ユーザの作成

ユーザ->
ユーザ名を入力
->[次へ]
・ユーザグループにて先ほど作成したグループを選択
->[次へ]
->[ユーザを作成]
作成したユーザを選択
->[セキュリティ認証情報]
->[アクセスキーの生成]
アクセスキーはTerraform実行時に入力します。
アクセスキー、シークレットアクセスキーは保存してください。
6.png

9.インスタンス作成、認証情報の作成

[インスタンス作成]->
名前を入力
キーペアから[新しいキーペアの作成]->
キーペア名"cml-key"を入力
[ED25519]
[.pem]
->[キーペアの作成]
ほかの項目はデフォルトの設定にて実施(Amazon Linux AMI、インスタンスタイプ"t2.micro"、シークレットグループの作成)
[インスタンスを起動]
高度な詳細配下のIAMインスタンスプロファイルのタブ
先ほど作成した"s3-access-for-ec2"ポリシーを選択
->[インスタンスを作成]
7.png

10.AWSのインスタンスへSSHを実行

・ キーペアを作成した際の.pemファイルを自身の端末に格納します。.sshへ格納後権限の変更を行っておきます。

.ssh % chomod 400 cml-key.pem

・ 先ほど作成したインスタンスを選択
[インスタンスに接続]->[SSHクライアント]タブ
SSH例を参考に自身の端末からSSHを行い次の画面が表示されたら成功です。

スクリーンショット 2023-12-05 130551.png

失敗するときは

  • VPCが作成されていて、インスタンスがグローバルIPアドレスを取得しているか確認する。
  • .sshディレクトリがない場合は作成する。
  • sshの設定ファイルを確認する。
cat /etc/resolv.conf
# [network]
# generateResolvConf = false
nameserver 8.8.8.8

AWS CLI の確認

まずはAWS CLIが動作するかバージョンを確認します。

$ aws --version
aws-cli/1.18.69 Python/3.8.10 Linux/5.15.0-1050-aws botocore/1.16.19

設定が完了していない場合はAWS CLIを参考に設定を行います。

プロキシの使用

今回の環境では設定しておりませんが、プロキシを使用する場合は設定が必要となります。プロキシを使用して AWS にアクセスする必要がある場合は、環境変数を使用してプロキシを定義します。
例:export HTTPS_PROXY=http://my.proxy.corp:80/bash

AWS CLI の設定

先述の2.S3バケット作成で設定したリージョン情報、7.ユーザの作成で取得したアクセスキーをLinuxへ設定します。

$ aws configure
AWS Access Key ID []: ********************
AWS Secret Access Key []: ********************
Default region name []: p-northeast-1
Default output format []: json
$

2章 CML構築の設定ファイル

GitHubのファイルをもとに作成するとフォルダ構成は次のようになります。
cloud-cml-main
├ images
├ module-cml2-deploy-aws
│ └scripts
├ module-cml2-readyness
├ config.yaml
├ main.tf
├ output.tf
├ Terraform.tf
├ upload-images-to-aws.sh
└ variables.tf

CMLの構成はconfig.ymlで設定を行います。AWS環境の作成で記載したリージョン名などから設定する例です。項目の詳細についてはGitHubを参照してください。また、今回はお試しのため、アップロードするデバイスを2つに制限しております。
- csr1000v
- ubuntu

config.yml
#
# This file is part of Cisco Modeling Labs
# Copyright (c) 2019-2023, Cisco Systems, Inc.
# All rights reserved.
#

aws:
  region: ap-northeast-1
  bucket: cmlbucket
  flavor: m5zn.metal
  profile: s3-access-for-ec2
  key_name: cml-key
  disk_size: 64

hostname: cml-controller

app:
  user: admin
  pass: Password123!
in case
  # 00- and 01- are commented out!
  customize:
    # - 00-patch_vmx.sh
    # - 01-patty.sh
    - 99-dummy.sh

sys:
  user: sysadmin
  pass: Password123!

license:
  flavor: CML_Enterprise
  token: 
  1234567890qwer
  # unless you have additional nodes, leave this at zero
  nodes: 0

refplat:
  definitions:
    - csr1000v
    - ubuntu
  images:
    - csr1000v-17-03-06
    - ubuntu-22-04-20221028

3章 バケットにイメージをアップロード

イメージのアップロードはupload-images-to-aws.shのスクリプトから実施します。スクリプトを実行する前に、まずはCMLへアップロードするイメージを準備しょう。事前準備で用意したisoファイルを解凍ソフトやTarコマンドで解凍します。
・ cml2_2.6.x_amd64-6.pkg
・ refplat-2023xxxx-fcs.iso

解凍したファイルは新たに作成したimage2のフォルダ配下に.pkgrefplat-2023xxxx-fcs.isoを展開したものを格納します。※yamlやqcowファイルは省略しています。
cloud-cml-main
├ images2
│ ├ cml2_2.6.x_amd64-6.pkg
│ ├ node-definitions
│ └ virl-base-inages
│  ├ csr1000v-17-03-06
│  └ ubuntu-22-04-20221028
└ upload-images-to-aws.sh

upload-images-to-aws.shスクリプトを実行します。

upload-images-to-aws.sh設定内容
upload-images-to-aws.sh
#!/bin/bash

#
# Copyright (c) 2019-2023, Cisco Systems, Inc.
# All rights reserved.
#
# This script can be installed on an on-prem CML controller which also has the
# required reference platform images and definitions.
#
# In addition to standard tools already installed on the controller, the AWS CLI
# utility must be installed and configured. For configuration, the access key
# and secret must be known. Then, run "aws configure" to provide these.
#
# Alternatively, they can be provided via environment variables:
# AWS_ACCESS_KEY_ID=ABCD AWS_SECRET_ACCESS_KEY=EF1234 aws ec2 describe-instances
#
DEFAULT_BUCKET="sato-cmlbucket"

BUCKETNAME=${1:-$DEFAULT_BUCKET}
ISO=${2:-/home/user/cloud-cml-main/images2}
PKG=${3:-cml2_*.pkg}

function help() {
    cmd=$(basename $0)
    cat <<EOF
CML2 S3 bucket upload helper script

Usage: $cmd [bucketname] [reference platform directory] [PKG wildcard]

For this to work, the dialog and the AWS CLI tool need to be installed.
The AWS CLI tool must also be configured with a valid access and secret key
(via 'aws configure').

If a CML software .pkg package is located in the current directory, then
the tool can upload it to the bucket, too.

defaults:
- bucketname = $DEFAULT_BUCKET
- directory = $ISO
- software pkg wildard = $PKG
EOF
}

if [[ "$1" =~ (--)?help|-h ]]; then
    help
    exit
fi

if [ -z "$(which aws)" ]; then
    echo "AWS CLI tool required but not present in path!"
    echo "see https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html"
    echo "or install it via 'apt install awscli'"
    exit 255
fi

if [ -z "$(which dialog)" ]; then
    echo "dialog utility required but not present in path!"
    echo "install it via 'apt install dialog'"
    exit 255
fi

if [ ! -d $ISO ]; then 
    echo "Provided reference platform path \"$ISO\" does not exist!"
    exit 255
fi

cd $ISO
if [ ! -d virl-base-images -a ! -d node-definitions ]; then
    echo "Provided path \"$ISO\" has no CML node / image definitions!"
    exit 255
fi

function ctrlc() {
    echo
    echo "Ctrl-C detected -- exiting!"
    exit 1
}

trap ctrlc SIGINT

cmlpkg=$(find . -name "$PKG" | sort | tail -1)
if [ -n "$cmlpkg" ]; then
    echo $cmlpkg
    if ! dialog --title "Software PKG found, copy to Bucket?" \
        --defaultno --yesno \
        "$(basename $cmlpkg)" 5 40; then
        # if no is selected...
        cmlpkg=""
    fi
fi

pushd &>/dev/null virl-base-images
options=$(find . -name '*.yaml' -exec sh -c 'basename '{}'; echo "on"' \; )
popd &>/dev/null

if [ -z "$options" ]; then
    echo "there's apparently no images in the directory specified ($ISO)"
    echo "please ensure that there's at least one image and node definition"
    exit 255
fi

selection=$(dialog --stdout --no-items --separate-output --checklist \
    "Select images to copy to AWS bucket \"${BUCKETNAME}\"" 0 60 20 $options \
)
s=$?
clear
if [ $s -eq 255 ]; then
    echo "reference platform image upload aborted..."
    exit 255
fi

declare -A nodedefs
for imagedef in $selection; do
    fullpath=$(find $ISO -name $imagedef)
    defname=$(sed -nE '/^node_definition/s/^.*:(\s+)?(\S+)$/\2/p' $fullpath)
    nodedefs[$defname]="1"
done

if [ -n "$cmlpkg" ]; then
    dialog --progressbox "Upload software package to bucket" 20 70 < <(
        tmpdir=$(mktemp --directory)
        pushd $tmpdir
        tar xf $cmlpkg --wildcards 'cml2_*.deb'
        aws s3 cp *.deb s3://${BUCKETNAME}/
        rm cml2_*.deb
        popd
        rmdir $tmpdir
    )
fi

target="s3://${BUCKETNAME}/refplat"

dialog --progressbox "Upload node definitions to bucket" 20 70 < <(
    for nodedef in ${!nodedefs[@]}; do
        fname=$(grep -l $ISO/node-definitions/* -Ee "^id:(\s+)?${nodedef}$")
        aws s3 cp $fname $target/node-definitions/
        s=$?
        if [ $s -ne 0 ]; then
            clear
            echo "An error occured during node definition upload, exiting..."
            exit 255
        fi
    done
)

dialog --progressbox "Upload images to bucket" 20 70 < <(
    for imagedef in $selection; do
        imagedir=$(find $ISO -name $imagedef | xargs dirname)
         https://www.linuxjournal.com/article/8919
        # ${imagedir <-- from variable imagedir
        #   ##       <-- greedy front trim
        #   *        <-- matches anything
        #   /        <-- until the last '/'
        # }
        aws s3 cp --recursive $imagedir $target/virl-base-images/${imagedir##*/}
        s=$?
        if [ $s -ne 0 ]; then
            clear
            echo "An error occured during image upload, exiting..."
            exit 255
        fi
    done
)

clear
echo "done!"

今回実行したファイルでは.pkgを展開するところが失敗しました。そのため、isoファイルと同様にpkg展開して格納し、関連するコードを修正します。再度スクリプトを実行すると、imageがバケットにアップロードできました。

  • パッケージの選択
    スクリーンショット 2023-12-05 153710.png
  • アップロードするイメージの選択
    スクリーンショット 2023-12-05 153803.png

・ アップロード中の画面
スクリーンショット 2023-12-05 153837.png

  • バケットにアップロード完了したファイル等
cloud-cml-main$ aws s3 ls --recursive s3://cmlbucket/
2023-12-01 15:29:34   85766356 cml2_2.6.1-11_amd64.deb
2023-12-01 14:21:46          0 refplat/
2023-12-01 15:29:38       2280 refplat/node-definitions/csr1000v.yaml
2023-12-01 15:29:38       3159 refplat/node-definitions/ubuntu.yaml
2023-12-01 15:29:39        275 refplat/virl-base-images/csr1000v-17-03-06/csr1000v-17-03-06.yaml
2023-12-01 15:29:39 1422000128 refplat/virl-base-images/csr1000v-17-03-06/csr1000v-universalk9.17.03.06-serial.qcow2
2023-12-01 15:30:19  664862720 refplat/virl-base-images/ubuntu-22-04-20221028/jammy-server-cloudimg-amd64.img
2023-12-01 15:30:19        320 refplat/virl-base-images/ubuntu-22-04-20221028/ubuntu-22-04-20221028.yaml
  • AWSのバケット
    スクリーンショット 2023-12-01 153108.png

うまくいかない場合
・ sshができるか再度確認
・ Bashのバージョンを確認
・ WSLを再起動
・ イメージ格納先のディレクトリ構成がiso展開時と同様か確認
・ イメージ格納先に不要なファイルがないか確認

4章 Terraformでインスタンスをデプロイ

デプロイする上で必要な項目が準備されているかチェック

  • Terraform がインストールされている
  • AWS IAM で設定されたポリシーとユーザー
  • AWS S3 のバケットにCMLのソフトウェア類がアップロードされている
  • config.yamlの値が正しく設定されている
  • アクセスキー、シークレットアクセスキーが用意されている
    ※GitHub上は環境変数を使っていますが今回は用意していません

Terraform のバージョンを確認します。

user:~/cloud-cml$ terraform -version
Terraform v1.6.5
on linux_amd64
+ provider registry.terraform.io/ciscodevnet/cml2 v0.6.2
+ provider registry.terraform.io/hashicorp/aws v5.29.0
+ provider registry.terraform.io/hashicorp/random v3.5.1

terraformを実行

インスタンスを作成するために、以下に記載の通りterraformを実行します。
plan、applyは実行時に完了までに数分かかることがあります。
・ terraform init
・ terraform plan
・ terraform apply -auto-approve
無事にapplyが完了すると以下のように表示されます。
スクリーンショット 2023-12-04 095509-2.png

試しにsshを実行してみると接続できました!

$ ssh -p1122 -i "cml-key.pem" sysadmin@ec2-52-xxx-xxx-xxx.ap-northeast-1.compute.amazona
ws.com

Welcome to Ubuntu 20.04.6 LTS (GNU/Linux 5.15.0-1050-aws x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Tue Dec  5 07:25:58 UTC 2023

  System load:  0.18              Processes:               745
  Usage of /:   8.1% of 61.84GB   Users logged in:         1
  Memory usage: 0%                IPv4 address for ens6:   172.10.10.10
  Swap usage:   0%                IPv4 address for virbr0: 192.168.255.1

 * Ubuntu Pro delivers the most comprehensive open source security and
   compliance features.

   https://ubuntu.com/aws/pro

Expanded Security Maintenance for Applications is not enabled.

0 updates can be applied immediately.

14 additional security updates can be applied with ESM Apps.
Learn more about enabling ESM Apps service at https://ubuntu.com/esm


Web console: https://ip-172.10.10.10.ap-northeast-1.compute.internal:9090/ or https://172.31.34.62:9090/

Last login: Mon Dec  4 02:22:51 2023 from 1.1.1.1
To run a command as administrator (user "root"), use "sudo <command>".
See "man sudo_root" for details.

sysadmin@cml-controller:~$ 

次に自分の端末のWebブラウザからインスタンスへ接続します。
表示されました!

スクリーンショット 2023-12-04 115627.png

ここからは通常のCMLと同様にラボを作成して検証作業が行えることでしょう。スクリーンショット 2023-12-05 214518.png

もしもうまくいかない場合は
VPCを追加で作成してみましょう。
VPC作成の際は”VPC”とデフォルトを設定します。
スクリーンショット 2023-12-07 104019.png
こちらのように設定されていれば成功です。
image.png

インスタンスの破棄

Terraformはdestroyで簡単に登録したものを削除ができますが、ライセンスを解除しておかないと紐づけが保たれたまま消えてしますのでそのライセンスは使えなくなってしまします。
そのためdestroy前に以下の方法でライセンス削除します。
注:事前にCMLで稼働しているLabを停止します。

$ ssh -p1122 sysadmin@IP_ADDRESS_OF_CONTROLLER /provision/del.sh
$ terraform destroy -auto-approve

試しにライセンスの紐づけを外しました。

kannishi@DESKTOP-L3UF0CR:~/cloud-cml$ ssh -p1122 sysadmin@ec2-5x-xx-xx-xx.ap-northeast-1.compute.amazonaws.com /provision/del.sh
The authenticity of host '[ec2-5x-xx-xx-xx.ap-northeast-1.compute.amazonaws.com]:1122 ([5x-xx-xx-xx]:1122)' can't be established.
ED25519 key fingerprint is SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
This host key is known by the following other names/addresses:
    ~/.ssh/known_hosts:12: [hashed name]
    ~/.ssh/known_hosts:14: [hashed name]
    ~/.ssh/known_hosts:16: [hashed name]
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '[ec2-52-68-139-248.ap-northeast-1.compute.amazonaws.com]:1122' (ED25519) to the list of known hosts.
sysadmin@ec2-5x-xx-xx-xx.ap-northeast-1.compute.amazonaws.com: Permission denied (publickey).
kannishi@DESKTOP-L3UF0CR:~/cloud-cml$ terraform destroy -auto-approve
var.access_key
  AWS access key / credential for the provisioning user

  Enter a value: yes

var.secret_key
  AWS secret key matching the access key

  Enter a value: xxxxxxxxxxxxxxxxxx

module.deploy.random_id.id: Refreshing state... [id=hwJq-A]
module.deploy.data.aws_ami.ubuntu: Reading...
module.deploy.aws_security_group.sg-tf: Refreshing state... [id=sg-0c62569dc49d088ef]
module.deploy.data.aws_ami.ubuntu: Read complete after 0s [id=ami-0970b3a12761f4b74]
module.deploy.aws_instance.cml: Refreshing state... [id=i-0c069cba149b83253]

Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the
following symbols:
  - destroy

Terraform will perform the following actions:

  # module.deploy.aws_instance.cml will be destroyed
  - resource "aws_instance" "cml" {
[...]
module.deploy.aws_instance.cml: Destroying... [id=i-0c069cba149b83253]
module.deploy.aws_instance.cml: Still destroying... [id=i-0c069cba149b83253, 10s elapsed]
[...]
Destroy complete! Resources: 3 destroyed.

おわりに

苦節1週間AWS初心者で、色々つまるところはありましたが何とか作成することができました。これでサクッとCMLを作成して、消すことができます。
今回構築したCMLに加え、AWS上のCMLへTerraformでラボを構築できれば、ネットワークデバイスを配備し、ある程度のコンフィグを投入できるかと思います。ただ、ラボを配置するTerraformは接続がうまくいかず、構築できなかったためまた今度トライしたいと思います。

免責事項

本サイトおよび対応するコメントにおいて表明される意見は、投稿者本人の個人的意見であり、シスコの意見ではありません。本サイトの内容は、情報の提供のみを目的として掲載されており、シスコや他の関係者による推奨や表明を目的としたものではありません。各利用者は、本Webサイトへの掲載により、投稿、リンクその他の方法でアップロードした全ての情報の内容に対して全責任を負い、本Web サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。

16
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
16
0