RDO(All-in-One)アップグレード(Queens→Yoga)

そろそろOpenStackの環境を更新しようと。

ここここにならってコンポーネント毎にアップグレードを行っていく。

オフィシャルでは始める前にsytemdのスナップショットをとれとあるが,そんなオプションはないと怒られる・・・。もう廃止されたオプションなのか???ググっても情報見つけられず。

Before updating, take a systemd snapshot of the OpenStack services:

# systemctl snapshot openstack-services
https://www.rdoproject.org/install/upgrading-rdo-1/

とりあえずこの手順を飛ばし,以下流れで進めていく。

  1. OpenStackサービスの停止
  2. アップグレード
  3. DBの同期
  4. OpenStackサービス起動

OpenStackサービスの停止

# systemctl stop 'openstack-*'
# systemctl stop 'neutron-*'
# systemctl stop 'openvswitch'

上記で停止するのは以下ユニット

openstack-aodh-evaluator.service
openstack-aodh-listener.service
openstack-aodh-notifier.service
openstack-ceilometer-notification.service
openstack-ceilometer-polling.service
openstack-cinder-api.service
openstack-cinder-backup.service
openstack-cinder-scheduler.service
openstack-cinder-volume.service
openstack-glance-api.service
openstack-losetup.service
openstack-nova-compute.service
openstack-nova-conductor.service
openstack-nova-novncproxy.service
openstack-nova-scheduler.service
openstack-swift-account-auditor.service
openstack-swift-account-reaper.service
openstack-swift-account-replicator.service
openstack-swift-account.service
openstack-swift-container-auditor.service
openstack-swift-container-replicator.service
openstack-swift-container-sync.service
openstack-swift-container-updater.service
openstack-swift-container.service
openstack-swift-object-auditor.service
openstack-swift-object-expirer.service
openstack-swift-object-reconstructor.service
openstack-swift-object-replicator.service
openstack-swift-object-updater.service
openstack-swift-object.service
openstack-swift-proxy.service
neutron-ovn-metadata-agent.service
neutron-server.service
openvswitch.service

アップグレード

# dnf install -y https://www.rdoproject.org/repos/rdo-release.rpm
# dnf update

DBの同期

# su -s /bin/sh -c "keystone-manage db_sync" keystone
# su -s /bin/sh -c "glance-manage db_sync" glance
# su -s /bin/sh -c "cinder-manage db sync" cinder
# su -s /bin/sh -c "neutron-db-manage upgrade heads" neutron
# su -s /bin/sh -c "nova-manage cell_v2 map_cell0" nova

# su -s /bin/sh -c "nova-manage --config-file /etc/nova/nova.conf cell_v2 create_cell --name=cell1 --verbose" nova
# su -s /bin/sh -c "nova-manage db sync" nova
# su -s /bin/sh -c "nova-manage cell_v2 discover_hosts --verbose" nova
# nova-manage cell_v2 list_cells
# su -s /bin/sh -c "nova-manage cell_v2 map_instances --cell_uuid <cell UUID>" nova
# su -s /bin/sh -c "nova-manage api_db sync" nova

うちの環境特有かもしれないが,httpdもアップグレードされ,デフォルトのssl.confが作成されているので削除。

# rm /etc/httpd/conf.d/ssl.conf

OpenStackサービス起動

再起動して完了。

と,思いきややはりというかエラーで起動しない。

エラー1つめ(nova)

コンピュートのバージョンが古すぎる?

こんなログがnova-scheduler.logに出てNG。

ERROR nova   File "/usr/lib/python3.6/site-packages/nova/utils.py", line 1100, in raise_if_old_compute
 ERROR nova     oldest_supported_service=oldest_supported_service_level)
 ERROR nova nova.exception.TooOldComputeService: Current Nova version does not support computes older than Xena but the minimum compute service level in your system is 56 and the oldest supported service level is 57.

QからYはサポート外なのか???とりあえずutils.pyの1100行目を見てみるとバージョン判定箇所らしい。私の力ではこれ以上解析が無理なので力業でコメントアウト。

1095     if current_service_version < oldest_supported_service_level:
1096 #        raise exception.TooOldComputeService(
1097 #            oldest_supported_version=service.OLDEST_SUPPORTED_SERVICE_VERSION,
1098 #            scope=scope,
1099 #            min_service_level=current_service_version,
1100 #            oldest_supported_service=oldest_supported_service_level)
1101         return

novaはこれで起動したw (今はこれでいいんだ)

エラー2つ目(neutronというかopenvswitch)

openvswichの6642に接続できないというエラーを吐いてNeutronも起動しない。ovn-northd.serviceが起動していなかったので起動したらここはクリアになった。

終わらないトラブル

無事にアップデート前の状態までもっていくことが出来たと思いきや,インスタンスは起動するものの外部ネットワークへ繋がらない問題発生。新しいインスタンスを作成してみるもエラー,既存のインスタンスを削除しようにもエラー。ログを見ると「’c.consumer_type_id という知らない引数が渡されている」的なメッセージが出ていた。ググってみるとどうやらPlacement関連で何か引っかかっている模様。そういえばplacementのDB同期はやっていなかった。ひとまずインスタンスは空にして今の環境で作り直すとする。

必要なインスタンスだけスナップショットをとり,DBから直接インスタンスを削除してから↓。

# placement-manage db sync 

インスタンス作成→失敗・・・orz。インスタンス削除 → 成功 !一歩前進。DB直でいじったからインスタンス割り当たっているけどDBに無いよというエラーメッセージが永遠と出る。対処法はこれ

$ pip install osc-placement       # resourceオプションがなかったから入れる
$ openstack resource provider list   # compute nodeのUUID確認
$ openstack resource provider show --allocations <UUID>  # ServerのUUID確認(念のためエラーメッセージのUUIDと同じか確認)
$ openstack resource provider allocation delete <Server UUID> 

nova周りはさらにエラーは続き,Neutron周りでもエラーが出続ける。

ERROR ovsdbapp.backend.ovs_idl.command [-] Error executing command (DbAddCommand): ovsdbapp.backend.ovs_idl.idlutils.RowNotFound: Cannot find Chassis_Private with name=xxx

色々ググったあげく,Southband側の問題のように見えたのでovs-sbなんたらとかでいじっていると,そもそもSouthband側が機能していないことに気づき,以下で解決した。

# systemctl start ovn-controller.service

アップグレード前と後でサービスの起動ってこんなに違ったかしら・・・・?

要らないと思っていたsystemctlのSnapshot,必要だったかもしれない・・・。

一応すったもんだ丸2日かかったけれど,無事にYogaへアップグレード完了した。

まとまっていないが,何年か後に自分が見直すためのメモとして。

NICのTeaming設定(RHEL)

想定構成

以下構成で10GbpsのNICを2本束ねる。

参考URL  nmcli を使用したネットワークチーミングの設定

  1. チーミングインタフェースを作成
  2. 物理IFをチーミングに所属
  3. チーミングIFを有効化

teamingを設定する方法にはいくつかあるが,ここでは公式ドキュメント最初に出てくるnmcliを利用して設定する。なお,teamdは永続性がないためnmcliやifcfgファイルで設定する方がよさそう。

想定する設定は,

  1. interfaceは「enp1s0f0」「enp1s0f1」の2つを利用。
  2. LACP利用
  3. 送信負荷分散のハッシュ値にmac address(scx/dst), ip address(src/dst), tcp port(src/dst) の3つを含める。

Teamingインタフェース作成

nmcliコマンドでTeamingの論理インタフェースを作成する。

# nmcli connection add type team ifname team0 con-name team0 config '{"device": "team0", "runner": {"name": "lacp", "active": true, "fast_rate": true, "tx_hash":  ["eth", "ipv4", "ipv6", "l4"]}, "link_watch": {"name": "ethtool"}}'
接続 'team0' (380df2de-dcef-4436-aded-9c4ab20e13e6) が正常に追加されました。

team0に所属させるインタフェースを設定する。オプションで「con-name」をつけると別名でインタフェースを定義できるが指定しないと「team-slave-enp1s0f0」のようになる。

# nmcli con add type team-slave ifname enp1s0f0 master team0
# nmcli con add type team-slave ifname enp1s0f1 master team0

IFの有効化

物理IF,TeamingIFのどちらを有効にしてもよい。

# nmcli con up team-slave-enp1s0f0
接続が正常にアクティベートされました (D-Bus アクティブパス: /org/freedesktop/NetworkManager/ActiveConnection/22)
# nmcli con up team-slave-enp1s0f1
接続が正常にアクティベートされました (D-Bus アクティブパス: /org/freedesktop/NetworkManager/ActiveConnection/25)

# nmclie con up team0
# ip link
18: team0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default qlen 1000
    link/ether 00:1b:21:6e:82:1d brd ff:ff:ff:ff:ff:ff

IPアドレスが設定されないとUPにならないが,後々内部ブリッジに接続させる予定なので今回はここまで。

cronの期間指定

cronの書き方で毎度悩む期間指定。めったに触らないから調べても忘れる。

ということでメモ。

基本的な記述は,「分,時,日,月,曜日」の5つのフィールドに指定したい値を書く。

cron(8) examines cron entries every minute.

The time and date fields are:

    field          allowed values
     -----          --------------
     minute         0-59
     hour           0-23
     day of month   1-31
     month          1-12 (or names, see below)
     day of week    0-7 (0 or 7 is Sunday, or use names)

毎時,毎月などは スラッシュで指定する。例えば「2時間毎に」としたいならば

* */2 * * * 

とする。それは分かる。だがしかし,これは何処を起点に2時間をカウントしはじめるのだろう,設定した時間からカウント始めるのか?それとも0時0分をスタートとして0,2,4,6,8,10,12,・・・としていくのだろうか?と毎度分からなくなる(忘れる)。ソースコードを読み解けば分かるのかもしれないが,そんな技量はないので実際に設定して確認する。

*/3 * * * * date >> /home/user/check

このときの実行状況は以下の通り。

2021年  3月 13日 土曜日 10:18:01 JST
2021年  3月 13日 土曜日 10:21:01 JST
2021年  3月 13日 土曜日 10:24:01 JST
2021年  3月 13日 土曜日 10:27:01 JST
2021年  3月 13日 土曜日 10:30:01 JST
2021年  3月 13日 土曜日 10:33:01 JST
2021年  3月 13日 土曜日 10:36:01 JST
2021年  3月 13日 土曜日 10:39:01 JST

0分からカウントされているっぽい。では41分に4分間隔に変更するとどうだろう。

*/4 * * * * date >> /home/user/check

41分からカウント開始とするなら45分に実行されるはずだが,0分スタートとするならば,44分に実行されるはず。

2021年  3月 13日 土曜日 10:39:01 JST
2021年  3月 13日 土曜日 10:44:01 JST

44分。デスヨネ。なんとなく気づいていましたよ。everyや毎にという言葉が悪い(違。

ただ,そうすると「50分毎に」や「9ヶ月毎に」など時刻ベースではなく純粋に時間間隔で実行したいときはどうするのだろう。

50 * * * *

とすると,0時50分,1時50分,2時50分と毎時50分になる。cronではそういうことは想定していないのだろうな。そもそもマニュアルに“run this command at this time on this date”ってあるしね・・・。個別にスクリプトを書くしかないのか。

Catalyst3560CでGREトンネル

とある検証でL3SWでGREトンネルのみ張る設定を確認した。普通にいけるかなと思ったが,keepaliveでひっかかったのでメモ。

基本的には,Vlan IFにIPアドレスを設定し,tunnel source / destination でそれぞれ指定すれば完了。ただし,Keepaliveを設定するとDownとなる。デバッグをとっても応答が返ってこず(recieveが無い)Down判定されていた。

interface Tunnel1
 ip address 192.168.254.2 255.255.255.252
 keepalive 5 2
 tunnel source Vlan1
 tunnel destination 192.168.10.1

なんでだろうなと調べてみると,以下の一文を見つけた。

Support is available for gre ip tunnel mode. The tunnel source can be loopback and Layer 3 (physical or Etherchannel) interfaces only.

https://www.cisco.com/c/dam/en/us/td/docs/switches/lan/catalyst3850/software/release/16-1/workflows/gre-feature-guide.pdf

なるほど。型番もバージョンも違うけれどこれっぽい。試しにip routingを有効にしてLoopback IFを追加,対向のLoに対するスタティックルート追加したところ無事にkeepalive有りでトンネルが張れた。

枯れた技術だけれど,結構まだハマるところがあるという。精進が足りませんね。

Microsoft Azure Fundamentals

先日,Microsoftのオンラインセミナー受講したらバウチャーを配布してくれたので受験してきました。
Azureの初級という位置づけで,「クラウド初めてさわる」「これからAzure案件に関わる予定」という人向けのようです。(個人的には新人のスキルアップに丁度良い教材&資格ではないかと思っています。)

私自身は初心者ではありませんが,Azureというクラウドサービスを理解するというきっかけには丁度良い試験でした。もちろんセミナーを受けただけでは受からないので

  • Microsoftのラーニングパスを通して理解を深める。
  • Azureアカウントを作成して一通り操作や見方を覚える。

と,ある程度対策をしたうえで受験し,無事に合格しました。

個人的にオススメラーニングパスは以下の通り。

Microsoft Azure クラウドの概念について調べる (AZ-900) ・・・ 4つのモジュールがあり,これはオンラインセミナーと結構重複していたので,復習のためやっておくと良い。

Azure の基礎 ・・・ 12個のモジュールがある。実際にAzureを操作してVMや可用性ペアを作るなどのハンズオンが盛り込まれている。まったくのクラウド初心者だと,これくらいまでは最低限やっておかないと厳しいかもしれない。

以下のモジュールでさらに理解を深めておくと余裕をもっていけるはず。ただ,受けた感想として,クラウド一般的な技術の話というよりは,Azureに特化したサービス(ポリシー/課金/サポート)に重点を置いて対策をとったほうがよいと感じた。

Azureを触ってみてAWSとは違う使いやすいさ,チュートリアルの豊富さが良いと感じたので今後個人的にも使ってみよう。

WordPress構築

Bloggerを使っていたけれど,使い勝手がよいWiki形式へ切り替えたいと思い,勉強がてらWordpressを自前で立ててこちらへ引っ越し。

1発目はWordpress構築メモ。

構想

イメージ
構成概要

構成イメージはこのような感じ。GCP上にCentOS8の仮想マシンを1つたて,その上で完結させる。DBは分けた方がよいのだろうが,まずは無事に立ち上がるところまで。

ドメインはさくらインターネットで取得。.comドメインで年間1886円。GCPでグローバルIPアドレスを確保した後,設定画面でDNS登録をする。

大まかな流れ

  1. DBインストール,設定
  2. PHPインストール,設定
  3. HTTPDインストール,設定
  4. HTTPS化

いざゆかん。

とその前に,構築中は自宅からのみアクセス可能とするためGCPのファイアウォールでソースIPアドレスを限定する。

DBインストール,設定

オフィシャルサイトを参考。

$ sudo dnf install mariadb-server.x86_64

DBセキュア化

$ sudo mysql_secure_installation

NOTE: RUNNING ALL PARTS OF THIS SCRIPT IS RECOMMENDED FOR ALL MariaDB
      SERVERS IN PRODUCTION USE!  PLEASE READ EACH STEP CAREFULLY!

In order to log into MariaDB to secure it, we'll need the current
password for the root user.  If you've just installed MariaDB, and
you haven't set the root password yet, the password will be blank,
so you should just press enter here.

Enter current password for root (enter for none):
OK, successfully used password, moving on...

Setting the root password ensures that nobody can log into the MariaDB
root user without the proper authorisation.

Set root password? [Y/n] y
New password:
Re-enter new password:
Password updated successfully!
Reloading privilege tables..
 ... Success!

By default, a MariaDB installation has an anonymous user, allowing anyone
to log into MariaDB without having to have a user account created for
them.  This is intended only for testing, and to make the installation
go a bit smoother.  You should remove them before moving into a
production environment.

Remove anonymous users? [Y/n] y
 ... Success!

Normally, root should only be allowed to connect from 'localhost'.  This
ensures that someone cannot guess at the root password from the network.

Disallow root login remotely? [Y/n] y
 ... Success!

By default, MariaDB comes with a database named 'test' that anyone can
access.  This is also intended only for testing, and should be removed
before moving into a production environment.

Remove test database and access to it? [Y/n] y
 - Dropping test database...
 ... Success!
 - Removing privileges on test database...
 ... Success!

Reloading the privilege tables will ensure that all changes made so far
will take effect immediately.

Reload privilege tables now? [Y/n] y
 ... Success!

Cleaning up...

All done!  If you've completed all of the above steps, your MariaDB
installation should now be secure.

Thanks for using MariaDB!

wordpress用DB設定。

MariaDB [(none)]> CREATE DATABASE wordpress;
Query OK, 1 row affected (0.004 sec)


MariaDB [(none)]>


MariaDB [(none)]> GRANT ALL PRIVILEGES ON wordpress.* TO "DBアドミン名"@"localhost" IDENTIFIED BY "パスワード";
Query OK, 0 rows affected (0.004 sec)


MariaDB [(none)]> FLUSH PRIVILEGES;
Query OK, 0 rows affected (0.002 sec)

ログに認証エラーが出た。ケルベロス認証などは使わないので無効化で対処する。

[ERROR] mysqld: Server GSSAPI error (major 851968, minor 2529639093) : gss_acquire_cred failed -Unspecified GSS failure. Minor code may provide more information. Keytab FILE:/etc/krb5.keytab is nonexistent or empty.
/var/log/mariadb/mariadb.log の内容
$ sudo mv /etc/my.cnf.d/auth_gssapi.cnf /etc/my.cnf.d/auth_gssapi.cnf.org

起動設定。

$ systemctl enable mariadb
$ systemctl start mariadb

PHPインストール,設定

$ sudo dnf install php php-mysqlnd php-mbstring.x86_64 php-json php-gd php-xml php-zip php-dom

php-gdがないとwordpress上で画像の編集ができない

推奨

参考) https://qiita.com/kogache/items/00dc37774dfe20f03a72

/etc/php-fpm.d/www.conf 編集。httpdとしてnginxを使うのでユーザとグループを修正する。

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
; RPM: apache user chosen to provide access to the same directories as httpd
;user = apache
user = nginx
; RPM: Keep a group allowed to write in log dir.
;group = apache
group = nginx

nginxインストール,設定

$ sudo dnf install nginx

wordpress設定

wordpressもあわせてインストールをする。今回は /usr/share/nginx の下に WP というディレクトリを作成して,そこへwordpressを配置する。

$ wget https://ja.wordpress.org/latest-ja.tar.gz
$ tar xvfz latest-ja.tar.gz ./
$ sudo chown -R nginx:nginx /usr/share/nginx/WP
$ sudo mv wordpress/* /usr/share/nginx/WP/

nginx設定ファイル変更。 /etc/nginx/conf.d/wp.conf として編集。TLS1.2 と1.3に限定する。こちらを参考。

# HTTPSへリダイレクト
server {
        listen 80;
        server_name zassoul.com;
        return 301 https://$host$request_uri;
}
server {
        listen 443 ssl;
        server_name zassoul.com;
        root /usr/share/nginx/WP;
        index index.php;
        charset utf-8;

        ssl_certificate /etc/letsencrypt/live/zassoul.com/fullchain.pem;
        ssl_certificate_key /etc/letsencrypt/live/zassoul.com/privkey.pem;
        ssl_protocols TLSv1.2 TLSv1.3;
        ssl_prefer_server_ciphers on;

        location = /favicon.ico {
                log_not_found off;
                access_log off;
        }

        location / {
                try_files $uri $uri/ /index.php?$args;
        }

        # Deny to wp-config.php
        location ~* /wp-config.php {
                deny all;
        }

        #php-fpm
        location ~ \.php$ {
                try_files $uri = 404;
                fastcgi_split_path_info ^(.+\.php)(/.+)$;
                include fastcgi_params;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                fastcgi_pass php-fpm;
        }

        location ~* \.(js|css|png|jpg|jpgeg|gif|ico)$ {
               expires max;
               log_not_found off;
        }
}

wp-config.php を編集する。(オフィシャルサイトを参考)

// ** MySQL 設定 - この情報はホスティング先から入手してください。 ** //
/** WordPress のためのデータベース名 */
define( 'DB_NAME', 'wordpress' );

/** MySQL データベースのユーザー名 */
define( 'DB_USER', '上で設定したユーザ名' );

/** MySQL データベースのパスワード */
define( 'DB_PASSWORD', '上で設定したパスワード' );

/** MySQL のホスト名 */
define( 'DB_HOST', 'localhost' );

/** データベースのテーブルを作成する際のデータベースの文字セット */
define( 'DB_CHARSET', 'utf8mb4' );

/** データベースの照合順序 (ほとんどの場合変更する必要はありません) */
define( 'DB_COLLATE', '' );

/**#@+
 * 認証用ユニークキー
 */
define( 'AUTH_KEY',         'ジェネレートしたキー' );
define( 'SECURE_AUTH_KEY',  'ジェネレートしたキー' );
define( 'LOGGED_IN_KEY',    'ジェネレートしたキー' );
define( 'NONCE_KEY',        'ジェネレートしたキー' );
define( 'AUTH_SALT',        'ジェネレートしたキー' );
define( 'SECURE_AUTH_SALT', 'ジェネレートしたキー' );
define( 'LOGGED_IN_SALT',   'ジェネレートしたキー' );
define( 'NONCE_SALT',       'ジェネレートしたキー' );

/**#@-*/

HTTPS化

常時HTTPSもするのでLet’s EncryptでSSL証明書を発行する。サイト認証のため80番ポートでアクセスしてくる必要があるということで,一時的に80番ポート全解放をする。

こちらを参考にLet’s Encryptで証明書発行を実施。

Certbotのインストール。

$ sudo dnf install epel-release
$ sudo dnf install certbot

お試しdry-run。

$ sudo certbot certonly --dry-run --standalone -w /usr/share/nginx/WP/ -d zassoul.com -m "Email-Address"

本番実行。

$ sudo certbot certonly  --standalone -d zassoul.com -m "Email-Address" --agree-tos
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Plugins selected: Authenticator webroot, Installer None
Obtaining a new certificate
Performing the following challenges:
http-01 challenge for zassoul.com
Using the webroot path /usr/share/nginx/WP for all unmatched domains.
Waiting for verification...
Cleaning up challenges
Subscribe to the EFF mailing list (email: "Email-Address").


IMPORTANT NOTES:
 - Congratulations! Your certificate and chain have been saved at:
   /etc/letsencrypt/live/zassoul.com/fullchain.pem
   Your key file has been saved at:
   /etc/letsencrypt/live/zassoul.com/privkey.pem
   Your cert will expire on 2020-12-07. To obtain a new or tweaked
   version of this certificate in the future, simply run certbot
   again. To non-interactively renew *all* of your certificates, run
   "certbot renew"
 - If you like Certbot, please consider supporting our work by:


   Donating to ISRG / Let's Encrypt:   https://letsencrypt.org/donate
   Donating to EFF:                    https://eff.org/donate-le

ここで80番を閉じる。nginx起動設定。

$ sudo systemctl enable nginx
$ sudo systemctl start nginx

完了。

LinuxでPBR

AWSでインスタンスを立ち上げたとき,2つのサブネットに所属させ一方は社内ネットワーク,一方はメンテナンス用に外部(インターネット)からSSHアクセス用にと構成することがある。

この場合,それぞれのNICに着信したトラフィックはそのNICから応答を返して欲しいが通信元が不特定だとスタティックルートで処理するのは不可能。このような時はPBRを設定して対応する。
参考) 

手順

  • ルートテーブルの作成
  • ポリシーの作成
  • ルーティングの追加
  • 永続的設定

ルートテーブルの作成

/etc/iproute2/rt_tables にens192用のルーティングテーブル「rt10」とens224用のルーティングテーブル「rt100」を追加する。なお,IDは1~255まであり,254はmainテーブル,255はlocalでリザーブされている。ここでは100と101を使用する。
#
# reserved values
#
255 local
254 main
253 default
0 unspec
#
# local
#
#1 inr.ruhep
100 rt100 #追加
101 rt10 #追加

ポリシーの作成

書式: ip rule add from <IF address> table <table name> priority <priority number>
# ip rule add from 192.168.10.40 table rt10 priority 100
# ip rule add from 192.168.1.40 table rt100 priority 101

prioritを指定しないとカーネルが一番古いpriorityの前に自動で採番する。何も設定されていなければmainの32766の前に順に追加される。(32765,32764という感じで)

ルーティングの追加

書式: ip route add default via <Gateway address> dev <IF name> table <table name> 
# ip route add default via 192.168.10.1 dev ens192 table rt10
# ip route add default via 192.168.1.1 dev ens224 table rt100
まずはこれでPBRは設定完了。
192.168.1.0/24にいるPCからpingのテスト。
PBR設定前はens192からreplyが返っていない。(なお,リバースパスフィルタリングが有効になっているのでens224では戻りのパケットがかえらない)
PBR設定後はしっかり着信IFからreplyが返っている。

永続的設定

コマンドで設定したルールとルートは再起動で消えるため,/etc/sysconfig/network-script配下に定義ファイルを作成するとあったが,NetworkMangerを利用している環境では利用できない。

・ ルール定義

/etc/sysconfig/network-script/rule-<IF名>
各IFに先のコマンドを記述。
ip rule add from 192.168.10.40 table rt10 priority 100
ip rule add from 192.168.1.40 table rt100 priority 101

・ ルート定義

/etc/sysconfig/network-script/route-<IF名>
各IFに先のコマンドを記述。
ip route add default via 192.168.10.1 dev ens192 table rt10
ip route add default via 192.168.1.1 dev ens224 table rt100
これがNGとなると,起動スクリプトに上のコマンドを実行するように仕込む方法が考えられる。
pbr.sh
#!/bin/sh
## create rules for pbr

ip rule add from 192.168.10.40 table rt10 priority 100
ip rule add from 192.168.1.40 table rt100 priority 101

## create default route for each routing tables
ip route add default via 192.168.10.1 dev ens192 table rt10
ip route add default via 192.168.1.1 dev ens224 table rt100
/etc/systemd/system/pbr.service
[Unit]
Description = PBR setting script
After = network-online.target # NICがオンラインにならないとコマンドが失敗に終わるため

[Service]
ExecStart = /root/pbr.sh
Type = simple

[Install]
WantedBy = multi-user.target

ここまで準備できたら
# systemctl enable pbr.service
# systemctl start pbr.service
で完了。
ただここまでやっておきながら,nmcliを使えばコマンド1行で終わることが分かった。

nmcliを使う方法

ens192の設定
nmcli con add type ethernet con-name ens192 ifname ens192 ipv4.method manual ipv4.addresses 192.168.10.40/24 ipv4.routes "0.0.0.0/1 192.168.10.1 table=100, 128.0.0.0/1 192.168.10.1 table=100" ipv4.routing-rules "priority 100 from 192.168.10.40 table 100"
ens224の設定
nmcli con add type ethernet con-name ens224 ifname ens224 ipv4.method manual ipv4.addresses 192.168.1.40/24 ipv4.routes "0.0.0.0/1 192.168.1.1 table=101, 128.0.0.0/1 192.168.1.1 table=101" ipv4.routing-rules "priority 101 from 192.168.1.40 table 101"
以上。超簡単。再起動後もこれで対応している。
RHELの公式ドキュメントによると,nmcliは0.0.0.0/0の表記に対応していないとのことで,0.0.0.0/1と128.0.0.0/1の2つ定義を入れて0.0.0.0/0をカバーしなくてはならないとのこと。この点とテーブルを名前指定ができず番号で記述する必要があるのがややわかりにくい。
ちなみにIFの設定ファイルは以下にある。
/etc/NetworkManager/system-connections/ens192.nmconnection 
/etc/NetworkManager/system-connections/ens224.nmconnection 

MikroTik CRS309を手に入れた

欲しかった10Gのスイッチを米アマ経由で調達した。
環境準備や設定・スループット測定などいろいろと手間取ったのでメモ。
購入したのMikroTik CRS309。米アマで購入当時およそ$270。輸送費やもろもろ税がかかって日本円で3.3万円程度で本体を手に入れた。
こちらは日本アマゾン

ざっと所感

– それなりにお金がかかる

・10GのSFPが必要なので,本体以外にもケーブル/デバイス側の10G NICといった費用も考えて調達しないとキツイ。なお,SFP+は(こちらも米アマで購入)SFP+とDACで大体4万円くらいかかった。
1なので,トータルで7.3万円で10GのL3SWを手に入れたことになる。

– 仕様はよくチェックしよう

公式のガイドラインで「10Gbase-TのときはRJ45モジュールが熱くなるから1ポート間隔あけて搭載することが推奨」あった。想定外だった。確かに触っていると火傷するほどアッツイ。よく調べよう。(以下,ガイドライン抜粋)
Even when using devices that come with separated SFP+ cages, for example CRS309-1G-8S+, it is still not recommended to deploy the S+RJ10 transceivers beside each other. Use S+RJ10 in every second interface to avoid transceivers overheating which may cause unpredictable behavior.

– CLIが独特

show run のような現状のConfigを確認するコマンドが無いので,CLIとWebUIを組み合わせて操作することになると思う。

– 設定も独特

bridgeやらswitchやらinterfaceやらと設定のセクション分けが困惑する。丸1日2日触っているとだいぶ慣れてくるけど,IOSやJunosのような感覚でいると訳分からなくなる。

スループット測定

– snake test

snake test
snake test イメージ
10Gに対応しているPCを2台準備できなかったので,CentOS8にDual portの10Gを積んで,network namespaceで分離しiperf3で測定した。

– 測定準備

予めNIC側のMTUを9000に設定する。
nmcli connection show でデバイスのUUIDを確認。
9000へ変更。
nmcli con mod UUID1 802-3.mtu 9000
nmcli con mod UUID2 802-3.mtu 9000
systemctl restart NetworkManager
Namespace作成
sudo ip netns add NIC1
sudo ip netns add NIC2
そえぞれのNICをNamespaceへ割り当てる。
sudo ip link set enp1s0f0 netns NIC1 up
sudo ip link set enp1s0f1 netns NIC2 up
IP設定
sudo ip netns exec NIC1 bash
ip addr add 10.10.10.1/30 dev enp1s0f0
sudo ip netns exec NIC2 bash
ip addr add 10.10.10.2/30 dev enp1s0f1
CSR309のL2MTUはMAXで10218。
interface set l2mtu=10218 1

テスト結果

およそ10Gbpsでました。
実環境ではここまでではないだろうけれど,パーソナルユースなので細かいところまではテストしない。
なお,公式でスループットのテスト結果が公開されているのでこれで十分だと思う。
この後はCisco891Mとのリプレースをやる。

【娯楽】ESXiにWIn10をたててゲーミングPCとして利用する

背景

昨今の在宅の流れにより家のメインPCが夫婦で取り合いになる状況が多くなってきた。
それを受けて,新しくPCを新調することにした。
せっかくなのでゲームもできるPCにしようと小型ながらもゲームに耐えうるものを自作した。

そしてMHWがセールで安く売っていたので購入。
当然ながら奥様も「私もやる!」となる。しかしもう1台調達する資金は無い。最低限のパーツでもう1台準備するとなると・・・。

ということを考えた結果,ESXiのリソースが余っていたのでこれにGPUを積んでVMにパススルーさせればいけるだろうと思ったのが発端。

要件

  • 新しいPCはコスト的に手配は無理(調達するものは最低限に抑えたい)
  • 今のESXiのリソースを活用して仮想マシンで構築したい
  • ESXiがおいてある部屋とMHWをやる部屋は別なので,リモートアクセスしたい
  • タイムラグが無い操作感

<描いた構想>

<実際にできた構成>

結論から言うと,ESXi上のWin10へリモートアクセスしてやることかなわず, MHWをやるときにはESXiがある部屋に行ってやることになった。
できなかった理由は以下の通り。

  • コストを安く上げようと調達したOSがWinHomeであったためリモートデスクトップアクセスができなかった
  • TeamViewerやAnyDeskなどのリモートアクセスツールを試したが,USBのコントローラが利用できなかった
  • ESXiのリモートコンソールならUSB転送ができたが,反応がひどくて使い物にならない(そもそもグラフィックカード出力じゃないからダメ?)
最初からProを買っておけばもしかしたらいけたのかもしれないけど,買いなおすことは無駄なのでやめた。
ということで,結果的に必要となったものは
品名 参考価格
仮想マシン用OS Windows10 Home 64bit 15k
グラフィックカード 玄人志向 NVIDIA GeForce GTX 1650 15k
USBボード オウルテック USB3.0増設ボード 3k
ディスプレイ EVICIV 12.5インチ モバイルディスプレイ 28k
ゲームコントローラ PS4 コントローラー 2.5k
合計 63.5k

となかなかの出費になった。PS4買えるじゃんとも思ったが,Steam版との共闘ができないのでその線はなかった。

構築

いざ構築。手順は次の通り。

手順

  1. ESXiにグラボを搭載する
  2. 仮想マシン作成
  3. 仮想マシンオプション設定
  4. passthru.mapの編集
  5. OSインストール
  6. ESXi再起動
  7. 仮想マシン起動
<参考にしたサイト>
https://qiita.com/maeda_mikio/items/af538169d57bc89f6ca7
https://www.next-hop.net/~hiraga/VMware/esxi-gpupassthrough.shtml
https://qiita.com/strat/items/f741774d129206002cfc
https://www.vmware.com/content/dam/digitalmarketing/vmware/en/pdf/techpaper/vsp-4-vmdirectpath-host-technical-note.pdf

1. グラボ搭載

物理作業のため省略

2. 仮想マシン作成

Win10 Home64bitなのでWindowsのOSバージョンを選択する。

Windows 64ビットを選択

 Windows10 Homeは1ソケットしか対応していないのでコアは全部1つのソケットへ。

今回は4コアにした

仮想マシンオプションの詳細から「構成パラメータ」を設定する。

 「hypervisor.cpuid.v0」を「FALSE」で設定する。
このオプションにより仮想マシンに仮想CPUであることを隠せるらしい。それにより,OSにパススルーするグラフィックボードの(ドライバの)仮想環境チェックに引っかからず,エラーコード34回避に至る(と理解した)。

/etc/vmware/passthru.map を編集するため,ESX ShellとSSHサービスを有効化する。

3. OSインストール

WindowsのインストーラisoをCDドライブにマウントさせてインストールする。
※ vmware toolsもインストールしておいても良い

4. passthru.mapの編集

/etc/vmware/passthru.mapを以下のように編集する。
最後の行に

## NVIDIA
#10de ffff bridge false #コメントアウト
10de ffff d3d0 default #追記

以下のように個別に指定してもよい。

# Graphic
10de 1f82 d3d0 default #追記
# Audio
10de 10fa d3d0 default #追記

PCIデバイスリセット時の挙動を指定するオプションらしい。正直なところ分からなかったが,とりあえずここを設定しないとちゃんとグラフィックボードが機能しなかった。
ちなみにここで入力するデバイスIDとプロダクトIDは esxcfg-infoコマンドで確認できる。

5. ESXi 再起動

まさかこれが必要だとは思わず,3日くらい躓いていた。

6. PCIデバイスの接続

ESXi再起動後に仮想マシンへPCIデバイス(グラボとUSB)を付ける。

7. 仮想マシン起動

無事にグラフィックボードを認識してくれた。(ここまで本当に長かった・・・)
なお,公式サイトから最新のドライバをDLしてインストールするとまた認識してくれなくなった。

ドライバは自動でインストールされる
ちゃんと認識されている

参考にしたサイトではコンソール画面を無効化したりするなどしていたが,私はマルチディスプレイ設定でGeforceのみに出力する設定とした。

2だけを使う設定にしてコンソールは無効化

しかし問題も・・・

無事にうまくいったと思ったのもつかの間。
暫く放置する等でスリープ状態になったり,仮想マシンを再起動するとまたドライバがCode34エラーに陥ってしまう。こうなると再びVMをシャットダウンして,「VMの編集→PCIデバイスを外す→ESXiを再起動→VMへPCIデバイス取り付け」という手順を踏まなくてはならない。
これがまだ解決できていない。
なので当面はVMは絶対に落とさないという運用をすることになった・・・。

もう1つの問題はリモートの線がなくなったので,わざわざ部屋を移動してモンハンしなくてはならないという点か・・・。

とりあえずはサクサクMHWが動いたのでヨシとした。

無事MHWも起動。コントローラもサクサク動いた