Red Hat Training

A Red Hat training course is available for Red Hat OpenStack Platform

付録A 付録

A.1. スケーリング

HCI ノードをスケールアップまたはスケールダウンするには、Compute または Ceph Storage ノードのスケーリングと同じ原則 (および大半はメソッド) が適用されます。以下の点に注意してください。

A.1.1. スケールアップ

単一型の HCI 環境内で HCI ノードをスケールアップするには、コンピュートノードのスケールアップと同じ方法を使用します。詳しくは、「ノードのさらなる追加」 (『director のインストールと使用方法』) を参照してください。

混合型の HCI 環境の HCI ノードのスケールアップにも同じ方法が該当します。新規ノードをタグ付けする場合には、適切なフレーバー (この場合には osdcompute) を使用することを念頭にいれてください。「新規フレーバーの作成と割り当て」を参照してください。

A.1.2. スケールダウン

HCI ノードのスケールダウンプロセス (単一型と混合型の両方の HCI 環境) を簡単に説明すると以下のようになります。

  1. HCI ノード上の Ceph OSD サービスを無効化して、リバランスします。director は、HCI ノードまたは Ceph Storage ノードの削除時に Red Hat Ceph Storage クラスターを自動でリバランスしないので、このステップが必要となります。

    「Ceph Storage ノードのスケールダウンと置き換え」 (『オーバークラウド向けの Red Hat Ceph Storage』) を参照してください。このガイドに記載のノードの削除の手順には従わないでください。ノード上のインスタンスを移行して、Compute サービスを最初に無効化する必要があります。

  2. HCI ノードからインスタンスを移行します。手順については 『インスタンスの移行』を参照してください。
  3. ノード上の Compute サービスを無効にして、そのサービスが新規インスタンス起動に使用されるのを防ぎます。
  4. オーバークラウドからノードを削除します。

3 番目と 4 番目のステップ (Compute サービスの無効化とノードの削除) については、『director のインストールと使用方法』「コンピュートノードの削除」 を参照してください。

A.2. アップストリームのツール

OpenStack におけるハイパーコンバージェンスに関連した Heat テンプレート、環境ファイル、スクリプト、およびその他のリソースは、以下のアップストリームの Github リポジトリーから提供されています。

https://github.com/RHsyseng/hci/tree/master/custom-templates

このリポジトリーは、「Compute の CPU およびメモリーの計算」および「Ceph OSD サービス向けの NUMA ピニングを設定するカスタムスクリプト」のスクリプトに対応しています。

これらのスクリプトを使用するには、お使いのアンダークラウドにこのリポジトリーを直接クローンします。

$ git clone https://github.com/RHsyseng/hci

A.2.1. Compute の CPU およびメモリーの計算

「Compute 用の CPU とメモリーリソースの確保」の項では、ハイパーコンバージドノード上の reserved_host_memory_mb および cpu_allocation_ratio の適切な値を決定する方法について説明しています。以下の Python スクリプト (このスクリプトも「「アップストリームのツール」」のリポジトリーから提供されています) を使用して計算することも可能です。

#!/usr/bin/env python
# Filename:                nova_mem_cpu_calc.py
# Supported Langauge(s):   Python 2.7.x
# Time-stamp:              <2017-03-10 20:31:18 jfulton>
# -------------------------------------------------------
# This program was originally written by Ben England
# -------------------------------------------------------
# Calculates cpu_allocation_ratio and reserved_host_memory
# for nova.conf based on on the following inputs:
#
# input command line parameters:
# 1 - total host RAM in GB
# 2 - total host cores
# 3 - Ceph OSDs per server
# 4 - average guest size in GB
# 5 - average guest CPU utilization (0.0 to 1.0)
#
# It assumes that we want to allow 3 GB per OSD
# (based on prior Ceph Hammer testing)
# and that we want to allow an extra 1/2 GB per Nova (KVM guest)
# based on test observations that KVM guests' virtual memory footprint
# was actually significantly bigger than the declared guest memory size
# This is more of a factor for small guests than for large guests.
# -------------------------------------------------------
import sys
from sys import argv

NOTOK = 1  # process exit status signifying failure
MB_per_GB = 1000

GB_per_OSD = 3
GB_overhead_per_guest = 0.5  # based on measurement in test environment
cores_per_OSD = 1.0  # may be a little low in I/O intensive workloads

def usage(msg):
  print msg
  print(
    ("Usage: %s Total-host-RAM-GB Total-host-cores OSDs-per-server " +
     "Avg-guest-size-GB Avg-guest-CPU-util") % sys.argv[0])
  sys.exit(NOTOK)

if len(argv) < 5: usage("Too few command line params")
try:
  mem = int(argv[1])
  cores = int(argv[2])
  osds = int(argv[3])
  average_guest_size = int(argv[4])
  average_guest_util = float(argv[5])
except ValueError:
  usage("Non-integer input parameter")

average_guest_util_percent = 100 * average_guest_util

# print inputs
print "Inputs:"
print "- Total host RAM in GB: %d" % mem
print "- Total host cores: %d" % cores
print "- Ceph OSDs per host: %d" % osds
print "- Average guest memory size in GB: %d" % average_guest_size
print "- Average guest CPU utilization: %.0f%%" % average_guest_util_percent

# calculate operating parameters based on memory constraints only
left_over_mem = mem - (GB_per_OSD * osds)
number_of_guests = int(left_over_mem /
                       (average_guest_size + GB_overhead_per_guest))
nova_reserved_mem_MB = MB_per_GB * (
                        (GB_per_OSD * osds) +
                        (number_of_guests * GB_overhead_per_guest))
nonceph_cores = cores - (cores_per_OSD * osds)
guest_vCPUs = nonceph_cores / average_guest_util
cpu_allocation_ratio = guest_vCPUs / cores

# display outputs including how to tune Nova reserved mem

print "\nResults:"
print "- number of guests allowed based on memory = %d" % number_of_guests
print "- number of guest vCPUs allowed = %d" % int(guest_vCPUs)
print "- nova.conf reserved_host_memory = %d MB" % nova_reserved_mem_MB
print "- nova.conf cpu_allocation_ratio = %f" % cpu_allocation_ratio

if nova_reserved_mem_MB > (MB_per_GB * mem * 0.8):
    print "ERROR: you do not have enough memory to run hyperconverged!"
    sys.exit(NOTOK)

if cpu_allocation_ratio < 0.5:
    print "WARNING: you may not have enough CPU to run hyperconverged!"

if cpu_allocation_ratio > 16.0:
    print(
        "WARNING: do not increase VCPU overcommit ratio " +
        "beyond OSP8 default of 16:1")
    sys.exit(NOTOK)

print "\nCompare \"guest vCPUs allowed\" to \"guests allowed based on memory\" for actual guest count"

A.2.2. Ceph OSD サービス向けの NUMA ピニングを設定するカスタムスクリプト

「Ceph NUMA ピニングの設定」の項では、Ceph OSD サービスを利用可能な NUMA ソケットにピニングするスクリプトの作成について説明しています。このスクリプト ~/templates/numa-systemd-osd.sh は、以下の操作を行う必要があります。

  • Ceph のネットワークトラフィックに使用されているネットワークインターフェースを取得します。
  • lstopo を使用して、そのインターフェースの NUMA ソケットを特定します。
  • Ceph のネットワークに使用されているネットワークインターフェースのある NUMA ノードを優先する NUMA ポリシーを使用して、numactl が OSD サービスを起動するように設定します。
  • 各 Ceph OSD デーモンを順次再起動して、サービスが新しい NUMA オプションを使用して実行されるようにします。
重要

numa-systemd-osd.sh のスクリプトは、NUMA 設定ツールのインストールも試みます。そのため、「ノードの登録」 (『オーバークラウド向けの Red Hat Ceph Storage』) の説明に従って、オーバークラウドノードを Red Hat に登録しておく必要もあります。

以下のスクリプトは、これらすべての操作を混合型 HCI デプロイメントで実行します。各ハイパーコンバージドノードのホスト名には ceph または osd-compute が使用されていることを前提とします。ハイパーコンバージドのホスト名をカスタマイズする場合には、最上位の IF ステートメントを適宜編集します。

#!/usr/bin/env bash
{
if [[ `hostname` = *"ceph"* ]] || [[ `hostname` = *"osd-compute"* ]]; then  # 1

    # Verify the passed network interface exists
    if [[ ! $(ip add show $OSD_NUMA_INTERFACE) ]]; then
	exit 1
    fi

    # If NUMA related packages are missing, then install them
    # If packages are baked into image, no install attempted
    for PKG in numactl hwloc; do
	if [[ ! $(rpm -q $PKG) ]]; then
	    yum install -y $PKG
	    if [[ ! $? ]]; then
		echo "Unable to install $PKG with yum"
		exit 1
	    fi
	fi
    done

    if [[ ! $(lstopo-no-graphics | tr -d [:punct:] | egrep "NUMANode|$OSD_NUMA_INTERFACE") ]];
    then
	echo "No NUMAnodes found. Exiting."
	exit 1
    fi

    # Find the NUMA socket of the $OSD_NUMA_INTERFACE
    declare -A NUMASOCKET
    while read TYPE SOCKET_NUM NIC ; do
	if [[ "$TYPE" == "NUMANode" ]]; then
	    NUMASOCKET=$(echo $SOCKET_NUM | sed s/L//g);
	fi
	if [[ "$NIC" == "$OSD_NUMA_INTERFACE" ]]; then
	    # because $NIC is the $OSD_NUMA_INTERFACE,
	    # the NUMASOCKET has been set correctly above
	    break # so stop looking
	fi
    done < <(lstopo-no-graphics | tr -d [:punct:] | egrep "NUMANode|$OSD_NUMA_INTERFACE")

    if [[ -z $NUMASOCKET ]]; then
	echo "No NUMAnode found for $OSD_NUMA_INTERFACE. Exiting."
	exit 1
    fi

    UNIT='/usr/lib/systemd/system/ceph-osd@.service'
    # Preserve the original ceph-osd start command
    CMD=$(crudini --get $UNIT Service ExecStart)

    if [[ $(echo $CMD | grep numactl) ]]; then
	echo "numactl already in $UNIT. No changes required."
	exit 0
    fi

    # NUMA control options to append in front of $CMD
    NUMA="/usr/bin/numactl -N $NUMASOCKET --preferred=$NUMASOCKET"

    # Update the unit file to start with numactl
    # TODO: why doesn't a copy of $UNIT in /etc/systemd/system work with numactl?
    crudini --verbose --set $UNIT Service ExecStart "$NUMA $CMD"

    # Reload so updated file is used
    systemctl daemon-reload

    # Restart OSDs with NUMA policy (print results for log)
    OSD_IDS=$(ls /var/lib/ceph/osd | awk 'BEGIN { FS = "-" } ; { print $2 }')
    for OSD_ID in $OSD_IDS; do
	echo -e "\nStatus of OSD $OSD_ID before unit file update\n"
	systemctl status ceph-osd@$OSD_ID
	echo -e "\nRestarting OSD $OSD_ID..."
	systemctl restart ceph-osd@$OSD_ID
	echo -e "\nStatus of OSD $OSD_ID after unit file update\n"
	systemctl status ceph-osd@$OSD_ID
    done
fi
}  2>&1 > /root/post_deploy_heat_output.txt
1
最上位の IF ステートメントは、各ハイパーコンバージドノードのホスト名に ceph または osd-compute が含まれていることを前提としています。ハイパーコンバージドノードのホスト名をカスタマイズする場合には、IF ステートメントを適宜編集してください。

また同様に、単一型の HCI デプロイメントでは、全コンピュートノードがハイパーコンバージド化されるので、単一型の HCI デプロイメントでは、最上位の IF ステートメントを以下のように変更してください。

if [[ `hostname` = *"compute"* ]]; then