はじめに
この記事は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の環境をクローン
- 作業を行う端末にTerraform、AWS CLI、他関連する環境設定
- CMLのイメージ、ライセンスを準備(cml2_2.6.x_amd64-6.pkg、refplat-2023xxxx-fcs.iso)
1章 AWS環境の作成
You Tubeを参考に作成可能です。手順は以下のように実施します。
- VPCを作成
- S3バケットを作成
- ユーザグループを作成
- 新規ポリシーの作成
- ユーザグループにポリシーをアタッチさせる
- ロールを作成
- ユーザグループに割当
- ユーザを作成
- インスタンス作成、認証情報の作成※Terraform起動時に使用
- AWSのインスタンスへSSHを実行
AWS環境作成の詳細はこちら
You Tubeの内容+αを備忘録として残します。1. VPCを作成
[VPCを作成]->[VPCなど]->[VPC作成]
2. S3バケットを作成
Amazon S3->[バケットを作成] ->
・ [AWSリージョン]を”ap-northeast-1”プルダウンで選択
・ バケット名"cmlbucket"入力
->[バケットを作成]
3. ユーザグループを作成
IAM->[グループの作成]->
・ [グループ名]を入力
・ [ポリシー]にて以下選択
ポリシー:AmazonEC2FullAccess
->[グループの作成]
4. 新規ポリシーの作成
[ポリシーの作成]->
[サービスを選択]から「S3」選択
・ リスト:ListBucket
・ 読み取り:GetObject
・ 書き込み:PutObject
・ リソース:[特定]を選択
・ Bucketの[ARNを追加]で先ほどのバケットを指定
・ objectの[ARNを追加]で先ほどのバケットを指定、
[任意オブジェクト名]をチェック
->[次へ]
・ポリシー名を入力※今回は"cml-s3-access"
->[ポリシーを作成]
5. ユーザグループにポリシーを割当
ユーザグループより先ほどのグループを選択
->[許可]タブ->[ポリシーをアタッチ]->
先ほどのポリシー"cml-s3-access"を追加
6. ロールを作成
[ロールの作成]
・ ユースケースの[EC2]選択
->[次へ]
・ 許可を追加にて"cml-s3-access"選択
->[次へ]
・ ロール名を入力※今回は"s3-access-for-ec2"にて作成
->[ロール作成]
7. ユーザグループに割当
・ ユーザグループより先ほど作成したグループを選択
->[許可]タブ->[インラインポリシーを作成]->
・[サービスを選択]にて以下項目を選択
- 書き込み:PassRole
- Roleの[ARNを追加]
・[このアカウント]をクリック
・"s3-access-for-ec2"を入力
->[次へ]
・ポリシー名"pass-role"を入力
->[ポリシーを作成]
8.ユーザの作成
ユーザ->
ユーザ名を入力
->[次へ]
・ユーザグループにて先ほど作成したグループを選択
->[次へ]
->[ユーザを作成]
作成したユーザを選択
->[セキュリティ認証情報]
->[アクセスキーの生成]
アクセスキーはTerraform実行時に入力します。
アクセスキー、シークレットアクセスキーは保存してください。
9.インスタンス作成、認証情報の作成
[インスタンス作成]->
名前を入力
キーペアから[新しいキーペアの作成]->
キーペア名"cml-key"を入力
[ED25519]
[.pem]
->[キーペアの作成]
ほかの項目はデフォルトの設定にて実施(Amazon Linux AMI、インスタンスタイプ"t2.micro"、シークレットグループの作成)
[インスタンスを起動]
高度な詳細配下のIAMインスタンスプロファイルのタブ
先ほど作成した"s3-access-for-ec2"ポリシーを選択
->[インスタンスを作成]
10.AWSのインスタンスへSSHを実行
・ キーペアを作成した際の.pem
ファイルを自身の端末に格納します。.sshへ格納後権限の変更を行っておきます。
.ssh % chomod 400 cml-key.pem
・ 先ほど作成したインスタンスを選択
[インスタンスに接続]->[SSHクライアント]タブ
SSH例を参考に自身の端末からSSHを行い次の画面が表示されたら成功です。
失敗するときは
- 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
#
# 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
のフォルダ配下に.pkg
、refplat-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設定内容
#!/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がバケットにアップロードできました。
- バケットにアップロード完了したファイル等
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
うまくいかない場合
・ 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が完了すると以下のように表示されます。
試しに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ブラウザからインスタンスへ接続します。
表示されました!
ここからは通常のCMLと同様にラボを作成して検証作業が行えることでしょう。
もしもうまくいかない場合は
VPCを追加で作成してみましょう。
VPC作成の際は”VPC”とデフォルトを設定します。
こちらのように設定されていれば成功です。
インスタンスの破棄
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 サイトの利用に関するあらゆる責任からシスコを免責することに同意したものとします。