OpenVZ と LXC で目に見える CPU の数
8834 ワード
同じ問題に遭遇したため、このブログ投稿が見つかる場合があります.現時点では、解決策がないことに注意してください.この最初の段落を削除して、すぐに解決策を追加したいと考えています;)
Virtuozzo/OpenVZ 仮想化を使用する Jelastic に YugabyteDB をインストールしようとしましたが、yb-master の起動に失敗しました:
要するに、これは、この percpu_rwlock() アサートで、CPU 数が使用可能な CPU の数よりも大きいことを意味します...これはどのように可能ですか?
どうやら、OpenVZ では、報告される CPU の数 (ここでは
それを確認するために、両方の値を取得するこの小さな C プログラムを作成しました.
sched_getcpu() からの論理 CPU 番号 _SC_NPROCESSORS_CONF からの 可視 CPU 数 (
OpenVZ 仮想化を使用して、Jelastic のコンテナーでこれを実行しています.
結果は次のとおりです.
残念ながら、私が実行しているプロセッサの数は常に CPU の数 (K8 によってオフラインにされた CPU を差し引いたもの) よりも大きくなります. 1 つの値はホストから取得され、もう 1 つは Kubernetes 制限から取得されます.また、プロセッサ アフィニティを管理したい YugabyteDB (または OpenJDK には same problem または puppet があった) のようなプログラムは、回避策を見つける必要があります.
では、コンテナーはオンラインの vCPU のみを表示する必要がありますか?おそらくですが、少なくともプロセッサ番号と一致している必要があります.これは、1/8 OCPU を実行している Oracle Cloud フリー VM の例です.したがって、OS から 2 CPU が表示されます.
これは、64 スレッド プロセッサ上の 2 つの vCPU です.
仮想化は KVM です.
そして、私の小さなプログラムは一貫した sched_getcpu() 数値を示します:
また、目に見える CPU の数のみを表示する機能もあります (LXC が/sys 内のすべてのホストのものを表示した場合、bug と見なされていました).
YugabyteDB マスター サーバーで数値がどこから来ているか見てみましょう.
これは正しい動作のように見えますが、一部のハイパーバイザーで sched_getcpu() から得られる数値と一致しません.おそらく、このアサートを削除する必要があります (OSX に対して行われているため).
私の汚いハックは、コマンド (私の場合は
/sys/devices/system/cpu の代わりにカスタム/tmp/devices/system/cpu から読み取ることで、より広い範囲の CPU を提供する代替手段もあります.
この方法で既存の yb-master ステートフル セットにパッチを適用して、sched_getcpu が最高のオンライン セットを返すように強制します.
または、ホスト CPU に対応する 0 ~ 64 の範囲をハードコードします.
ただし、これは完全にサポートされていないことに注意してください.解決策については https://github.com/yugabyte/yugabyte-db/issues/9619 を確認してください
Virtuozzo/OpenVZ 仮想化を使用する Jelastic に YugabyteDB をインストールしようとしましたが、yb-master の起動に失敗しました:
*** Check failure stack trace: ***
F0805 13:33:58.388178 28 locks.h:201] Check failed: cpu < n_cpus_ (21 vs. 6)
@ 0x7f2760d809a1 yb::(anonymous namespace)::DumpStackTraceAndExit()
@ 0x7f276016200d google::LogMessage::Fail()
@ 0x7f2760164536 google::LogMessage::SendToLog()
@ 0x7f2760161a6a google::LogMessage::Flush()
@ 0x7f2760165159 google::LogMessageFatal::~LogMessageFatal()
@ 0x7f27695992c8 yb::percpu_rwlock::get_lock()
@ 0x7f276958ebcd yb::log::Log::Reserve()
@ 0x7f27695905bb yb::log::Log::AsyncAppendReplicates()
@ 0x7f2769849e67 yb::consensus::LogCache::AppendOperations()
@ 0x7f276982b0d2 yb::consensus::PeerMessageQueue::AppendOperations()
@ 0x7f276985b8e5 yb::consensus::RaftConsensus::AppendNewRoundsToQueueUnlocked()
@ 0x7f276985a2b3 yb::consensus::RaftConsensus::AppendNewRoundToQueueUnlocked()
@ 0x7f276985a7df yb::consensus::RaftConsensus::BecomeLeaderUnlocked()
@ 0x7f276986fcc4 yb::consensus::RaftConsensus::DoElectionCallback()
@ 0x7f2760e1ec54 yb::ThreadPool::DispatchThread()
@ 0x7f2760e1b40f yb::Thread::SuperviseThread()
@ 0x7f275c6de694 start_thread
@ 0x7f275be1b41d __clone
要するに、これは、この percpu_rwlock() アサートで、CPU 数が使用可能な CPU の数よりも大きいことを意味します...これはどのように可能ですか?
どうやら、OpenVZ では、報告される CPU の数 (ここでは
n_cpus_
) は K8 によって可視化された仮想 CPU の数ですが、論理 CPU の数 (ここでは cpu
) はハイパーバイザーから取得され、VM プロセッサ全体をカバーできます.それを確認するために、両方の値を取得するこの小さな C プログラムを作成しました.
lscpu
で確認できるものと同じ)cat > sched_getcpu.c <<CAT
#define _GNU_SOURCE
#include <stdio.h>
#include <unistd.h>
int main(void) {
printf("sched_getcpu = %3d _SC_NPROCESSORS_CONF = %3d\n", sched_getcpu(),sysconf(_SC_NPROCESSORS_CONF));
return 0;
}
CAT
type gcc || yum install -y gcc
gcc sched_getcpu.c && for i in {1..10} ; do ./a.out ; done
OpenVZ 仮想化を使用して、Jelastic のコンテナーでこれを実行しています.
[root@yb-tserver-0 ~]# yum install -y virt-what
Package virt-what-1.18-4.el7.x86_64 already installed and latest version
Nothing to do
[root@yb-tserver-0 ~]# virt-what
openvz
lxc
結果は次のとおりです.
[root@yb-tserver-0 ~]# gcc sched_getcpu.c && for i in {1..10} ; do ./a.out ; done
sched_getcpu = 31 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 15 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 17 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 17 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 19 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 21 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 19 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 19 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 21 _SC_NPROCESSORS_CONF = 6
sched_getcpu = 19 _SC_NPROCESSORS_CONF = 6
[root@yb-tserver-0 ~]#
残念ながら、私が実行しているプロセッサの数は常に CPU の数 (K8 によってオフラインにされた CPU を差し引いたもの) よりも大きくなります. 1 つの値はホストから取得され、もう 1 つは Kubernetes 制限から取得されます.また、プロセッサ アフィニティを管理したい YugabyteDB (または OpenJDK には same problem または puppet があった) のようなプログラムは、回避策を見つける必要があります.
では、コンテナーはオンラインの vCPU のみを表示する必要がありますか?おそらくですが、少なくともプロセッサ番号と一致している必要があります.これは、1/8 OCPU を実行している Oracle Cloud フリー VM の例です.したがって、OS から 2 CPU が表示されます.
[opc@a ~]$ lscpu | grep -E "^Model|^CPU|^Hyper"
CPU op-mode(s): 32-bit, 64-bit
CPU(s): 2
CPU family: 23
Model: 1
Model name: AMD EPYC 7551 32-Core Processor
CPU MHz: 1996.250
Hypervisor vendor: KVM
これは、64 スレッド プロセッサ上の 2 つの vCPU です.
仮想化は KVM です.
[root@yb-tserver-0 cores]# virt-what
lxc
kvm
そして、私の小さなプログラムは一貫した sched_getcpu() 数値を示します:
[root@yb-tserver-0 cores]# for i in {1..10} ; do ./a.out ; done
sched_getcpu = 6 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 1 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 4 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 3 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 5 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 7 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 1 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 4 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 6 _SC_NPROCESSORS_CONF = 8
sched_getcpu = 2 _SC_NPROCESSORS_CONF = 8
また、目に見える CPU の数のみを表示する機能もあります (LXC が/sys 内のすべてのホストのものを表示した場合、bug と見なされていました).
YugabyteDB マスター サーバーで数値がどこから来ているか見てみましょう.
cpu
は sched_getcpu() in yb::percpu_rwlock::get_lock() から来ていますn_cpus_
は n_cpus_ = base::MaxCPUIndex() + 1; からのもので、sysinfo.cc は /sys/devices/system/cpu/present
を解析し、私の OpenVZ VM では次のようになります.root@node88695-yb-demo ~ $ cat /sys/devices/system/cpu/present
0-5
これは正しい動作のように見えますが、一部のハイパーバイザーで sched_getcpu() から得られる数値と一致しません.おそらく、このアサートを削除する必要があります (OSX に対して行われているため).
私の汚いハックは、コマンド (私の場合は
exec /home/yugabyte/bin/yb-master
) の前に次を追加して、LD_PRELOAD で sched_getcpu() をハイジャックし、常に _SC_NPROCESSORS_CONF から最後のプロセッサ番号を返します.yum install -y gcc && echo -e "#define _GNU_SOURCE\n#include <unistd.h>\nint sched_getcpu (void) { return sysconf(_SC_NPROCESSORS_CONF)-1 ; };\n" > sched_getcpu.c && gcc -shared -o /tmp/sched_getcpu.so -fPIC sched_getcpu.c ; export LD_PRELOAD=/tmp/sched_getcpu.so &&
/sys/devices/system/cpu の代わりにカスタム/tmp/devices/system/cpu から読み取ることで、より広い範囲の CPU を提供する代替手段もあります.
echo 0-64 > /tmp_devices_system_cpu_present ; sed -e 's@/sys/devices/system/cpu/present@/tmp_devices_system_cpu_present@g' -i /home/yugabyte/lib/yb/libgutil.so
この方法で既存の yb-master ステートフル セットにパッチを適用して、sched_getcpu が最高のオンライン セットを返すように強制します.
for i in yb-master yb-tserver ; do kubectl get statefulsets $i -n yb-demo -o yaml | awk '/^ *exec [/]home[/]yugabyte[/]bin[/]yb-master/{sub(/exec/,patch" exec")}{print}' patch='yum install -y gcc ; echo -e "#define _GN
U_SOURCE\\n#include <unistd.h>\\nint sched_getcpu (void) { return sysconf(_SC_NPROCESSORS_CONF)-1 ; };\\n" > sched_getcpu.c ; gcc -shared -o /tmp/sched_getcpu.so -fPIC sched_getcpu.c ; export LD_PRELOAD=/tmp/sched_getcpu.so ; ' | kubectl apply -f /dev/stdin -n yb-demo ; done
または、ホスト CPU に対応する 0 ~ 64 の範囲をハードコードします.
for i in yb-master yb-tserver ; do kubectl get statefulsets $i -n yb-demo -o yaml | tee $i.b.yaml | awk '/^ *exec [/]home[/]yugabyte[/]bin[/]yb-/{sub(/exec/,patch" exec")}{print}' patch=' echo 0-64 > /tmp_devices_system_cpu_present ; sed -e 's@/sys/devices/system/cpu/present@/tmp_devices_system_cpu_present@g' -i /home/yugabyte/lib/yb/libgutil.so ; ' | tee $i.e.yaml | kubectl apply -f /dev/stdin -n yb-demo ; done
ただし、これは完全にサポートされていないことに注意してください.解決策については https://github.com/yugabyte/yugabyte-db/issues/9619 を確認してください
Reference
この問題について(OpenVZ と LXC で目に見える CPU の数), 我々は、より多くの情報をここで見つけました https://dev.to/yugabyte/visible-number-of-cpu-on-openvz-2h7dテキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol