forked from vitalif/vitastor
Compare commits
333 Commits
hier-failu
...
master
Author | SHA1 | Date |
---|---|---|
antilles | 7fea69ff5f | |
Vitaliy Filippov | c777a0041a | |
Vitaliy Filippov | 2947ea93e8 | |
Vitaliy Filippov | 978bdc128a | |
Vitaliy Filippov | bb2f395f1e | |
Vitaliy Filippov | b127da40f7 | |
Vitaliy Filippov | ca34a6047a | |
Vitaliy Filippov | 38ba76e893 | |
Vitaliy Filippov | 1e3c4edea0 | |
Vitaliy Filippov | e7ac855b07 | |
Vitaliy Filippov | c53357ac45 | |
Vitaliy Filippov | 27e9f244ec | |
Vitaliy Filippov | 8e25a28a08 | |
Vitaliy Filippov | 5d3317e4f2 | |
Vitaliy Filippov | 016115c0d4 | |
Vitaliy Filippov | e026de95d5 | |
Vitaliy Filippov | 77c10fd1f8 | |
Vitaliy Filippov | 581d02e581 | |
Vitaliy Filippov | f03a9db4d9 | |
Vitaliy Filippov | cb9c30bc31 | |
Vitaliy Filippov | a86a380d20 | |
Vitaliy Filippov | d2b43cb118 | |
Vitaliy Filippov | cc76e6876b | |
Vitaliy Filippov | 1cec62d25d | |
Vitaliy Filippov | 1c322b33ed | |
Vitaliy Filippov | d27524f441 | |
Vitaliy Filippov | ba55f91409 | |
Vitaliy Filippov | 80aac39513 | |
Vitaliy Filippov | 2aa5aa7ab6 | |
Vitaliy Filippov | 3ca3b8a8d8 | |
Vitaliy Filippov | 2cf649eba6 | |
Vitaliy Filippov | 5935640a4a | |
Vitaliy Filippov | d00d4dbac0 | |
Vitaliy Filippov | 5d9d6f32a0 | |
antilles | 1e39b80f31 | |
Vitaliy Filippov | 5280d1d561 | |
Vitaliy Filippov | 317b0feb0a | |
Vitaliy Filippov | 247f0552db | |
antilles | f94f76ca89 | |
Vitaliy Filippov | 2f228fa96a | |
Vitaliy Filippov | 2f6b9c0306 | |
Vitaliy Filippov | 48b5f871e0 | |
Vitaliy Filippov | c17f76a3e4 | |
Vitaliy Filippov | a6ab54b1ba | |
Vitaliy Filippov | 99ee8596ea | |
Vitaliy Filippov | c4928e6ecd | |
Vitaliy Filippov | ec7dcd1be5 | |
Vitaliy Filippov | e600bbc151 | |
Vitaliy Filippov | 8b8c1179a7 | |
Vitaliy Filippov | d5a6fa6dd7 | |
Vitaliy Filippov | f757a35a8d | |
Vitaliy Filippov | 1edf86ed26 | |
Vitaliy Filippov | 5ca7cde612 | |
Vitaliy Filippov | 751935ddd8 | |
Vitaliy Filippov | d84dee7098 | |
Vitaliy Filippov | dcc76eee15 | |
Vitaliy Filippov | 2f38adeb3d | |
Vitaliy Filippov | f72f14e6a7 | |
Vitaliy Filippov | 1299373988 | |
Vitaliy Filippov | 178bb0e701 | |
Vitaliy Filippov | 4ece4dfdd0 | |
Vitaliy Filippov | 95631773b6 | |
Vitaliy Filippov | 7239cfb91a | |
Vitaliy Filippov | 7cea642f4a | |
Vitaliy Filippov | dc615403d9 | |
Vitaliy Filippov | 1a704e06ab | |
Vitaliy Filippov | 575475de71 | |
Vitaliy Filippov | aca2bef15f | |
Vitaliy Filippov | 4dd6e89263 | |
Vitaliy Filippov | 9bac99ffb6 | |
Vitaliy Filippov | 62ed130960 | |
Vitaliy Filippov | 9c7755b6e8 | |
Vitaliy Filippov | 691ebd991a | |
Vitaliy Filippov | 6d5df908a3 | |
Vitaliy Filippov | fa87769ed8 | |
Vitaliy Filippov | 2ce8292803 | |
Vitaliy Filippov | 7f8f7ded52 | |
Vitaliy Filippov | 68553eabbb | |
Vitaliy Filippov | 3147c5c8d5 | |
Vitaliy Filippov | 576e2ae608 | |
Vitaliy Filippov | a1c7cc3d8d | |
Vitaliy Filippov | a5e3dfbc5a | |
Vitaliy Filippov | 7972502eaf | |
Vitaliy Filippov | e57b7203b8 | |
Vitaliy Filippov | c8a179dcda | |
Vitaliy Filippov | 845454742d | |
Vitaliy Filippov | d65512bd80 | |
Vitaliy Filippov | 53de2bbd0f | |
Vitaliy Filippov | 628aa59574 | |
Vitaliy Filippov | 037cf64a47 | |
Vitaliy Filippov | 19e2d9d6fa | |
Vitaliy Filippov | bfc7e61909 | |
Vitaliy Filippov | 7da4868b37 | |
Vitaliy Filippov | b5c020ce0b | |
Vitaliy Filippov | 6b33ae973d | |
Vitaliy Filippov | cf36445359 | |
Vitaliy Filippov | 3fd873d263 | |
Vitaliy Filippov | a00e8ae9ed | |
Vitaliy Filippov | 75674545dc | |
Vitaliy Filippov | 225eb2fe3d | |
Vitaliy Filippov | 7e82573ed0 | |
Vitaliy Filippov | 12a6bed2d5 | |
Vitaliy Filippov | 5524dbdab7 | |
Vitaliy Filippov | cd3dec06ac | |
Vitaliy Filippov | 371d79e059 | |
Vitaliy Filippov | 0e888e6c60 | |
Vitaliy Filippov | 408c21d8f0 | |
Vitaliy Filippov | 43cb9ae212 | |
Vitaliy Filippov | e15b6e7805 | |
Vitaliy Filippov | 31017d8412 | |
Vitaliy Filippov | 4819854064 | |
Vitaliy Filippov | 1f509cca77 | |
Vitaliy Filippov | aa8e8e8271 | |
Vitaliy Filippov | 4d79e531c5 | |
Vitaliy Filippov | 30dff8893f | |
Vitaliy Filippov | becf14a705 | |
Vitaliy Filippov | 64388788c1 | |
Vitaliy Filippov | 37653abe4b | |
Vitaliy Filippov | 7c054c6f10 | |
Vitaliy Filippov | bb7709e824 | |
Vitaliy Filippov | ebeace5a2d | |
Vitaliy Filippov | a378789f10 | |
Vitaliy Filippov | 1fe678e57b | |
Vitaliy Filippov | 2e592a2f22 | |
Vitaliy Filippov | b92f644e3a | |
Vitaliy Filippov | 890ea3dbc0 | |
Vitaliy Filippov | 06630369bf | |
Vitaliy Filippov | b4740acf62 | |
Vitaliy Filippov | eae81bbda6 | |
Vitaliy Filippov | 8222e3c77d | |
Vitaliy Filippov | 29cbe70e74 | |
Vitaliy Filippov | a883e79507 | |
Vitaliy Filippov | be7e76f849 | |
Vitaliy Filippov | 6fd2cf5df6 | |
Vitaliy Filippov | 294a754c9e | |
Vitaliy Filippov | 8bfea6e7de | |
Vitaliy Filippov | bac9e34836 | |
Vitaliy Filippov | 8aa4d492c1 | |
Vitaliy Filippov | 9336ee5476 | |
Vitaliy Filippov | ad30b11519 | |
Vitaliy Filippov | a061246997 | |
Vitaliy Filippov | 5066e35a49 | |
Vitaliy Filippov | 93dc31f3fc | |
Vitaliy Filippov | f245b56176 | |
Vitaliy Filippov | befca06f18 | |
Vitaliy Filippov | fbf0263625 | |
Vitaliy Filippov | 3bcf276d4d | |
Vitaliy Filippov | 38db53f5ee | |
Vitaliy Filippov | cd543a90bc | |
Vitaliy Filippov | f600cc07b0 | |
Vitaliy Filippov | 6a8e530e6b | |
Vitaliy Filippov | 5cadb170b9 | |
Vitaliy Filippov | e72d4ed1d4 | |
Vitaliy Filippov | ff479a102d | |
Vitaliy Filippov | 27d0d5b06a | |
Vitaliy Filippov | 33950c1ec8 | |
Vitaliy Filippov | eea7ef1f19 | |
Vitaliy Filippov | cc0fdc6253 | |
Vitaliy Filippov | 79ecd59b10 | |
Vitaliy Filippov | 51081c9b45 | |
Vitaliy Filippov | b7d398be5b | |
Vitaliy Filippov | 85e9f67d9d | |
Vitaliy Filippov | 79c6d6f323 | |
Vitaliy Filippov | ae760dbc1d | |
Vitaliy Filippov | 65487da4b1 | |
Vitaliy Filippov | 7862282938 | |
Vitaliy Filippov | 30ce2bd951 | |
Vitaliy Filippov | b1a0afd10a | |
Vitaliy Filippov | 85b6134910 | |
Vitaliy Filippov | b1b07a393d | |
Vitaliy Filippov | 7333022adf | |
Vitaliy Filippov | ab8627c9fa | |
Vitaliy Filippov | 6acf562e01 | |
Vitaliy Filippov | 6f797f429e | |
Vitaliy Filippov | b8a1734465 | |
Vitaliy Filippov | c752b68167 | |
Vitaliy Filippov | 564df2eb5d | |
Vitaliy Filippov | 9a427dd70a | |
Vitaliy Filippov | 1a4ceb420d | |
Vitaliy Filippov | 21b5124a4b | |
Vitaliy Filippov | 4181add1f4 | |
Vitaliy Filippov | a8464c19af | |
Vitaliy Filippov | 819cb70cdd | |
Vitaliy Filippov | 3c8e4c6b72 | |
Vitaliy Filippov | 8ef4cf89dc | |
Vitaliy Filippov | 7bfb1639ea | |
Vitaliy Filippov | 628e481c32 | |
Vitaliy Filippov | af6f2046fc | |
Vitaliy Filippov | 9357e5293e | |
Vitaliy Filippov | 12851dc07d | |
Vitaliy Filippov | a5753e35a3 | |
Vitaliy Filippov | d6ee1ca17c | |
Vitaliy Filippov | 71674d00cf | |
Vitaliy Filippov | ddb078d5a7 | |
Vitaliy Filippov | d22d56f90a | |
Vitaliy Filippov | eb1331a079 | |
Vitaliy Filippov | c5274f655b | |
Vitaliy Filippov | 45e07d6294 | |
Vitaliy Filippov | a8ee391e05 | |
Vitaliy Filippov | de48fa3fd2 | |
Vitaliy Filippov | 874a766b62 | |
Vitaliy Filippov | 384bd8e28f | |
Vitaliy Filippov | 430994f48a | |
Vitaliy Filippov | 3d7f838c59 | |
Vitaliy Filippov | b909d81f41 | |
Vitaliy Filippov | e42975ffd1 | |
Vitaliy Filippov | 93778324e5 | |
Vitaliy Filippov | eeb6727170 | |
Vitaliy Filippov | 7fe82c692e | |
Vitaliy Filippov | 92c6e16eba | |
Vitaliy Filippov | 213a9ccb4d | |
Vitaliy Filippov | a166147110 | |
Vitaliy Filippov | 7d532880c3 | |
Vitaliy Filippov | 0b0405d115 | |
Vitaliy Filippov | e651c93a90 | |
Vitaliy Filippov | 988e90be69 | |
Vitaliy Filippov | 272a45ad63 | |
Vitaliy Filippov | 25a15d24cf | |
Vitaliy Filippov | 700e0e9bff | |
Vitaliy Filippov | ab0ca7c00f | |
Vitaliy Filippov | f153bc950b | |
Vitaliy Filippov | 425ff8818d | |
Vitaliy Filippov | 9e287a7778 | |
Vitaliy Filippov | f52f58b9e9 | |
Vitaliy Filippov | 1fe6b0c0e2 | |
Vitaliy Filippov | e4237e9ed8 | |
Vitaliy Filippov | 10a5fd6abb | |
Vitaliy Filippov | 1c316ef350 | |
Vitaliy Filippov | 0b2d12eef1 | |
Vitaliy Filippov | 1c10430ae1 | |
Vitaliy Filippov | dfce91d168 | |
Vitaliy Filippov | 332a13ba30 | |
Vitaliy Filippov | d0e257ee81 | |
Vitaliy Filippov | 004912aac0 | |
Vitaliy Filippov | c18e92273e | |
Vitaliy Filippov | 9815d70ffc | |
Vitaliy Filippov | 4a4627dcab | |
Vitaliy Filippov | b963f2fd93 | |
Vitaliy Filippov | ba7427020e | |
Vitaliy Filippov | a0aac7eb2a | |
Vitaliy Filippov | ac7b834af3 | |
Vitaliy Filippov | ee0c78fd74 | |
Vitaliy Filippov | e6646a5b2f | |
Vitaliy Filippov | ae69662b17 | |
Vitaliy Filippov | 57ad4c3636 | |
Vitaliy Filippov | b7e4d0c9bf | |
Vitaliy Filippov | 161a23c966 | |
Vitaliy Filippov | 2f999d8607 | |
Vitaliy Filippov | d007a374f2 | |
Vitaliy Filippov | 45c0694853 | |
Vitaliy Filippov | 57bcba2406 | |
Vitaliy Filippov | 30ac899074 | |
Vitaliy Filippov | 2348d39cf4 | |
Vitaliy Filippov | 3de7929fe5 | |
Vitaliy Filippov | 07b2196bc2 | |
Vitaliy Filippov | b8e30608d6 | |
Vitaliy Filippov | a612cdca47 | |
Vitaliy Filippov | c8d61568b5 | |
Vitaliy Filippov | 84ed3c6395 | |
Vitaliy Filippov | a7b57386c0 | |
Vitaliy Filippov | 9d4ea5f764 | |
Vitaliy Filippov | 000e4944ec | |
Vitaliy Filippov | 8426616d89 | |
Vitaliy Filippov | 1a841344ec | |
Vitaliy Filippov | 8603b5cb1d | |
Vitaliy Filippov | f12b8e45a9 | |
Vitaliy Filippov | 878ccbb6ea | |
Vitaliy Filippov | b14220b4d0 | |
Vitaliy Filippov | 181d6ba407 | |
Vitaliy Filippov | 63c2b9832c | |
Vitaliy Filippov | 10e2e6a7c8 | |
Vitaliy Filippov | a598428992 | |
Vitaliy Filippov | 08a677b684 | |
Vitaliy Filippov | 7c8fbdad16 | |
Vitaliy Filippov | 2f9353df60 | |
Vitaliy Filippov | 57c744f288 | |
Vitaliy Filippov | a11ca56fb1 | |
Vitaliy Filippov | b84927b340 | |
Vitaliy Filippov | 83cacba226 | |
Vitaliy Filippov | 2c8f0bc6d5 | |
Vitaliy Filippov | 7ae5b0e368 | |
Vitaliy Filippov | 926be372fd | |
Vitaliy Filippov | 6222779b52 | |
Vitaliy Filippov | a4186e20aa | |
Vitaliy Filippov | c74a424930 | |
Vitaliy Filippov | 32f2c4dd27 | |
Vitaliy Filippov | 3ad16b9a1a | |
Vitaliy Filippov | 1c2df841c2 | |
Vitaliy Filippov | aa5dacc7a9 | |
Vitaliy Filippov | affe8fc270 | |
Vitaliy Filippov | 4fdc49bdc7 | |
Vitaliy Filippov | 86b4682975 | |
Vitaliy Filippov | bdd48e4cf1 | |
Vitaliy Filippov | af8c3411cd | |
Vitaliy Filippov | 9c405009f3 | |
Vitaliy Filippov | f9fbea25a4 | |
Vitaliy Filippov | 2c9a10d081 | |
Vitaliy Filippov | 150968070f | |
Vitaliy Filippov | cdfc74665b | |
Vitaliy Filippov | 3f60fecd7c | |
Vitaliy Filippov | 3b4cf29e65 | |
Vitaliy Filippov | eeaba11ebd | |
Vitaliy Filippov | aea567cfbd | |
Vitaliy Filippov | ce02f47de6 | |
Vitaliy Filippov | 5fd3208616 | |
Vitaliy Filippov | 5997b76535 | |
Vitaliy Filippov | f1961157f0 | |
Vitaliy Filippov | 88c1ba0790 | |
Vitaliy Filippov | b5bd611683 | |
Vitaliy Filippov | fa90b5a4e7 | |
Vitaliy Filippov | 8d40ad99a6 | |
Vitaliy Filippov | 3475772b07 | |
Vitaliy Filippov | 25fcedf6e7 | |
Vitaliy Filippov | 6ca20aa194 | |
Vitaliy Filippov | 4bfd994341 | |
Vitaliy Filippov | 59e959dcbb | |
Vitaliy Filippov | a9581f0739 | |
Vitaliy Filippov | 105a405b0a | |
Vitaliy Filippov | d55d7d5326 | |
Vitaliy Filippov | 0e5d0e02a9 | |
Vitaliy Filippov | 0439981a66 | |
Vitaliy Filippov | 6648f6bb6e | |
Vitaliy Filippov | 281be547eb | |
Vitaliy Filippov | 0c78dd7178 | |
Vitaliy Filippov | 3c924397e7 | |
Vitaliy Filippov | c3bd26193d | |
Vitaliy Filippov | 43b77d7619 | |
Vitaliy Filippov | a6d846863b | |
Vitaliy Filippov | 8dc427b43c | |
Vitaliy Filippov | bf2112653b | |
Vitaliy Filippov | 0538a484b3 | |
Vitaliy Filippov | 97720fa6b4 | |
Vitaliy Filippov | e60e352df6 |
|
@ -10,6 +10,9 @@ RUN set -e -x; \
|
||||||
ln -s /root/fio-build/fio-*/ ./fio; \
|
ln -s /root/fio-build/fio-*/ ./fio; \
|
||||||
ln -s /root/qemu-build/qemu-*/ ./qemu; \
|
ln -s /root/qemu-build/qemu-*/ ./qemu; \
|
||||||
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
||||||
|
cd mon; \
|
||||||
|
npm install; \
|
||||||
|
cd ..; \
|
||||||
mkdir build; \
|
mkdir build; \
|
||||||
cd build; \
|
cd build; \
|
||||||
cmake .. -DWITH_ASAN=yes -DWITH_QEMU=yes; \
|
cmake .. -DWITH_ASAN=yes -DWITH_QEMU=yes; \
|
||||||
|
|
|
@ -71,7 +71,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
- name: Run test
|
- name: Run test
|
||||||
id: test
|
id: test
|
||||||
timeout-minutes: 3
|
timeout-minutes: 10
|
||||||
run: /root/vitastor/tests/test_add_osd.sh
|
run: /root/vitastor/tests/test_add_osd.sh
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
if: always() && steps.test.outcome == 'failure'
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
@ -190,24 +190,6 @@ jobs:
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
test_failure_domain:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: /root/vitastor/tests/test_failure_domain.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_interrupted_rebalance:
|
test_interrupted_rebalance:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
|
@ -280,7 +262,7 @@ jobs:
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
test_minsize_1:
|
test_failure_domain:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
@ -288,115 +270,7 @@ jobs:
|
||||||
- name: Run test
|
- name: Run test
|
||||||
id: test
|
id: test
|
||||||
timeout-minutes: 3
|
timeout-minutes: 3
|
||||||
run: /root/vitastor/tests/test_minsize_1.sh
|
run: /root/vitastor/tests/test_failure_domain.sh
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_move_reappear:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: /root/vitastor/tests/test_move_reappear.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_rebalance_verify:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: /root/vitastor/tests/test_rebalance_verify.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_rebalance_verify_imm:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_rebalance_verify_ec:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: SCHEME=ec /root/vitastor/tests/test_rebalance_verify.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_rebalance_verify_ec_imm:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: SCHEME=ec IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.sh
|
|
||||||
- name: Print logs
|
|
||||||
if: always() && steps.test.outcome == 'failure'
|
|
||||||
run: |
|
|
||||||
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
|
||||||
echo "-------- $i --------"
|
|
||||||
cat $i
|
|
||||||
echo ""
|
|
||||||
done
|
|
||||||
|
|
||||||
test_rm:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
needs: build
|
|
||||||
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
|
||||||
steps:
|
|
||||||
- name: Run test
|
|
||||||
id: test
|
|
||||||
timeout-minutes: 3
|
|
||||||
run: /root/vitastor/tests/test_rm.sh
|
|
||||||
- name: Print logs
|
- name: Print logs
|
||||||
if: always() && steps.test.outcome == 'failure'
|
if: always() && steps.test.outcome == 'failure'
|
||||||
run: |
|
run: |
|
||||||
|
@ -442,6 +316,132 @@ jobs:
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_minsize_1:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_minsize_1.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_move_reappear:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_move_reappear.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_rm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_rm.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_snapshot_chain:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_snapshot_chain.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_snapshot_chain_ec:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 6
|
||||||
|
run: SCHEME=ec /root/vitastor/tests/test_snapshot_chain.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_snapshot_down:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_snapshot_down.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_snapshot_down_ec:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: SCHEME=ec /root/vitastor/tests/test_snapshot_down.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
test_splitbrain:
|
test_splitbrain:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
|
@ -460,6 +460,96 @@ jobs:
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_rebalance_verify:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: /root/vitastor/tests/test_rebalance_verify.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_rebalance_verify_imm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_rebalance_verify_ec:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: SCHEME=ec /root/vitastor/tests/test_rebalance_verify.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_rebalance_verify_ec_imm:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: SCHEME=ec IMMEDIATE_COMMIT=1 /root/vitastor/tests/test_rebalance_verify.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_switch_primary:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_switch_primary.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
test_write:
|
test_write:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build
|
needs: build
|
||||||
|
@ -550,3 +640,219 @@ jobs:
|
||||||
echo ""
|
echo ""
|
||||||
done
|
done
|
||||||
|
|
||||||
|
test_heal_csum_32k_dmj:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TEST_NAME=csum_32k_dmj OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_metadata false --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS /root/vitastor/tests/test_heal.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_heal_csum_32k_dj:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TEST_NAME=csum_32k_dj OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS /root/vitastor/tests/test_heal.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_heal_csum_32k:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TEST_NAME=csum_32k OSD_ARGS="--data_csum_type crc32c --csum_block_size 32k" OFFSET_ARGS=$OSD_ARGS /root/vitastor/tests/test_heal.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_heal_csum_4k_dmj:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TEST_NAME=csum_4k_dmj OSD_ARGS="--data_csum_type crc32c --inmemory_metadata false --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS /root/vitastor/tests/test_heal.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_heal_csum_4k_dj:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TEST_NAME=csum_4k_dj OSD_ARGS="--data_csum_type crc32c --inmemory_journal false" OFFSET_ARGS=$OSD_ARGS /root/vitastor/tests/test_heal.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_heal_csum_4k:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 10
|
||||||
|
run: TEST_NAME=csum_4k OSD_ARGS="--data_csum_type crc32c" OFFSET_ARGS=$OSD_ARGS /root/vitastor/tests/test_heal.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_scrub:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: /root/vitastor/tests/test_scrub.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_scrub_zero_osd_2:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: ZERO_OSD=2 /root/vitastor/tests/test_scrub.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_scrub_xor:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: SCHEME=xor /root/vitastor/tests/test_scrub.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_scrub_pg_size_3:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: PG_SIZE=3 /root/vitastor/tests/test_scrub.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_scrub_pg_size_6_pg_minsize_4_osd_count_6_ec:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: PG_SIZE=6 PG_MINSIZE=4 OSD_COUNT=6 SCHEME=ec /root/vitastor/tests/test_scrub.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
test_scrub_ec:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
needs: build
|
||||||
|
container: ${{env.TEST_IMAGE}}:${{github.sha}}
|
||||||
|
steps:
|
||||||
|
- name: Run test
|
||||||
|
id: test
|
||||||
|
timeout-minutes: 3
|
||||||
|
run: SCHEME=ec /root/vitastor/tests/test_scrub.sh
|
||||||
|
- name: Print logs
|
||||||
|
if: always() && steps.test.outcome == 'failure'
|
||||||
|
run: |
|
||||||
|
for i in /root/vitastor/testdata/*.log /root/vitastor/testdata/*.txt; do
|
||||||
|
echo "-------- $i --------"
|
||||||
|
cat $i
|
||||||
|
echo ""
|
||||||
|
done
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,22 @@ for my $line (<>)
|
||||||
if ($line =~ /\.\/(test_[^\.]+)/s)
|
if ($line =~ /\.\/(test_[^\.]+)/s)
|
||||||
{
|
{
|
||||||
chomp $line;
|
chomp $line;
|
||||||
my $test_name = $1;
|
my $base_name = $1;
|
||||||
|
my $test_name = $base_name;
|
||||||
my $timeout = 3;
|
my $timeout = 3;
|
||||||
if ($test_name eq 'test_etcd_fail' || $test_name eq 'test_heal' || $test_name eq 'test_interrupted_rebalance')
|
if ($test_name eq 'test_etcd_fail' || $test_name eq 'test_heal' || $test_name eq 'test_add_osd' ||
|
||||||
|
$test_name eq 'test_interrupted_rebalance' || $test_name eq 'test_rebalance_verify')
|
||||||
{
|
{
|
||||||
$timeout = 10;
|
$timeout = 10;
|
||||||
}
|
}
|
||||||
while ($line =~ /([^\s=]+)=(\S+)/gs)
|
while ($line =~ /([^\s=]+)=(\S+)/gs)
|
||||||
{
|
{
|
||||||
if ($1 eq 'SCHEME' && $2 eq 'ec')
|
if ($1 eq 'TEST_NAME')
|
||||||
|
{
|
||||||
|
$test_name = $base_name.'_'.$2;
|
||||||
|
last;
|
||||||
|
}
|
||||||
|
elsif ($1 eq 'SCHEME' && $2 eq 'ec')
|
||||||
{
|
{
|
||||||
$test_name .= '_ec';
|
$test_name .= '_ec';
|
||||||
}
|
}
|
||||||
|
@ -32,6 +39,10 @@ for my $line (<>)
|
||||||
$test_name .= '_'.lc($1).'_'.$2;
|
$test_name .= '_'.lc($1).'_'.$2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if ($test_name eq 'test_snapshot_chain_ec')
|
||||||
|
{
|
||||||
|
$timeout = 6;
|
||||||
|
}
|
||||||
$line =~ s!\./test_!/root/vitastor/tests/test_!;
|
$line =~ s!\./test_!/root/vitastor/tests/test_!;
|
||||||
# Gitea CI doesn't support artifacts yet, lol
|
# Gitea CI doesn't support artifacts yet, lol
|
||||||
#- name: Upload results
|
#- name: Upload results
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
## Contributor License Agreement
|
||||||
|
|
||||||
|
> This Agreement is made in the Russian and English languages. **The English
|
||||||
|
text of Agreement is for informational purposes only** and is not binding
|
||||||
|
for the Parties.
|
||||||
|
>
|
||||||
|
> In the event of a conflict between the provisions of the Russian and
|
||||||
|
English versions of this Agreement, the **Russian version shall prevail**.
|
||||||
|
>
|
||||||
|
> Russian version is published at https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-ru.md
|
||||||
|
|
||||||
|
This document represents the offer of Filippov Vitaliy Vladimirovich
|
||||||
|
("Author"), author and copyright holder of Vitastor software ("Program"),
|
||||||
|
acknowledged by a certificate of Federal Service for Intellectual
|
||||||
|
Property of Russian Federation (Rospatent) # 2021617829 dated 20 May 2021,
|
||||||
|
to "Contributors" to conclude this license agreement as follows
|
||||||
|
("Agreement" or "Offer").
|
||||||
|
|
||||||
|
In accordance with Art. 435, Art. 438 of the Civil Code of the Russian
|
||||||
|
Federation, this Agreement is an offer and in case of acceptance of the
|
||||||
|
offer, an agreement is considered concluded on the conditions specified
|
||||||
|
in the offer.
|
||||||
|
|
||||||
|
1. Applicable Terms. \
|
||||||
|
1.1. "Official Repository" shall mean the computer storage, operated by
|
||||||
|
the Author, containing all prior and future versions of the Source
|
||||||
|
Code of the Program, at Internet addresses https://git.yourcmc.ru/vitalif/vitastor/
|
||||||
|
or https://github.com/vitalif/vitastor/. \
|
||||||
|
1.2. "Contributions" shall mean results of intellectual activity
|
||||||
|
(including, but not limited to, source code, libraries, components,
|
||||||
|
texts, documentation) which can be software or elements of the software
|
||||||
|
and which are provided by Contributors to the Author for inclusion
|
||||||
|
in the Program. \
|
||||||
|
1.3. "Contributor" shall mean a person who provides Contributions to
|
||||||
|
the Author and agrees with all provisions of this Agreement.
|
||||||
|
A Сontributor can be: 1) an individual; or 2) a legal entity or an
|
||||||
|
individual entrepreneur in case when an individual provides Contributions
|
||||||
|
on behalf of third parties, including on behalf of his employer.
|
||||||
|
|
||||||
|
2. Subject of the Agreement. \
|
||||||
|
2.1. Subject of the Agreement shall be the Contributions sent to the Author by Contributors. \
|
||||||
|
2.2. The Contributor grants to the Author the right to use Contributions at his own
|
||||||
|
discretion and without any necessity to get a prior approval from Contributor or
|
||||||
|
any other third party in any way, under a simple (non-exclusive), royalty-free,
|
||||||
|
irrevocable license throughout the world by all means not contrary to law, in whole
|
||||||
|
or as a part of the Program, or other open-source or closed-source computer programs,
|
||||||
|
products or services (hereinafter -- the "License"), including, but not limited to: \
|
||||||
|
2.2.1. to execute Contributions and use them for any tasks; \
|
||||||
|
2.2.2. to publish and distribute Contributions in modified or unmodified form and/or to rent them; \
|
||||||
|
2.2.3. to modify Contributions, add comments, illustrations or any explanations to Contributions while using them; \
|
||||||
|
2.2.4. to create other results of intellectual activity based on Contributions, including derivative works and composite works; \
|
||||||
|
2.2.5. to translate Contributions into other languages, including other programming languages; \
|
||||||
|
2.2.6. to carry out rental and public display of Contributions; \
|
||||||
|
2.2.7. to use Contributions under the trade name and/or any trademark or any other label, or without it, as the Author thinks fit; \
|
||||||
|
2.3. The Contributor grants to the Author the right to sublicense any of the aforementioned
|
||||||
|
rights to third parties on any terms at the Author's discretion. \
|
||||||
|
2.4. The License is provided for the entire duration of Contributor's
|
||||||
|
exclusive intellectual property rights to the Contributions. \
|
||||||
|
2.5. The Contributor grants to the Author the right to decide how and where to mention,
|
||||||
|
or to not mention at all, the fact of his authorship, name, nickname and/or company
|
||||||
|
details when including Contributions into the Program or in any other computer
|
||||||
|
programs, products or services.
|
||||||
|
|
||||||
|
3. Acceptance of the Offer \
|
||||||
|
3.1. The Contributor may provide Contributions to the Author in the form of
|
||||||
|
a "Pull Request" in an Official Repository of the Program or by any
|
||||||
|
other electronic means of communication, including, but not limited to,
|
||||||
|
E-mail or messenger applications. \
|
||||||
|
3.2. The acceptance of the Offer shall be the fact of provision of Contributions
|
||||||
|
to the Author by the Contributor by any means with the following remark:
|
||||||
|
“I accept Vitastor CLA agreement: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md”
|
||||||
|
or “Я принимаю соглашение Vitastor CLA: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-ru.md”. \
|
||||||
|
3.3. Date of acceptance of the Offer shall be the date of such provision.
|
||||||
|
|
||||||
|
4. Rights and obligations of the parties. \
|
||||||
|
4.1. The Contributor reserves the right to use Contributions by any lawful means
|
||||||
|
not contrary to this Agreement. \
|
||||||
|
4.2. The Author has the right to refuse to include Contributions into the Program
|
||||||
|
at any moment with no explanation to the Contributor.
|
||||||
|
|
||||||
|
5. Representations and Warranties. \
|
||||||
|
5.1. The person providing Contributions for the purpose of their inclusion
|
||||||
|
in the Program represents and warrants that he is the Contributor
|
||||||
|
or legally acts on the Contributor's behalf. Name or company details
|
||||||
|
of the Contributor shall be provided with the Contribution at the moment
|
||||||
|
of their provision to the Author. \
|
||||||
|
5.2. The Contributor represents and warrants that he legally owns exclusive
|
||||||
|
intellectual property rights to the Contributions. \
|
||||||
|
5.3. The Contributor represents and warrants that any further use of
|
||||||
|
Contributions by the Author as provided by Contributor under the terms
|
||||||
|
of the Agreement does not infringe on intellectual and other rights and
|
||||||
|
legitimate interests of third parties. \
|
||||||
|
5.4. The Contributor represents and warrants that he has all rights and legal
|
||||||
|
capacity needed to accept this Offer; \
|
||||||
|
5.5. The Contributor represents and warrants that Contributions don't
|
||||||
|
contain malware or any information considered illegal under the law
|
||||||
|
of Russian Federation.
|
||||||
|
|
||||||
|
6. Termination of the Agreement \
|
||||||
|
6.1. The Agreement may be terminated at will of both Author and Contributor,
|
||||||
|
formalised in the written form or if the Agreement is terminated on
|
||||||
|
reasons prescribed by the law of Russian Federation.
|
||||||
|
|
||||||
|
7. Final Clauses \
|
||||||
|
7.1. The Contributor may optionally sign the Agreement in the written form. \
|
||||||
|
7.2. The Agreement is deemed to become effective from the Date of signing of
|
||||||
|
the Agreement and until the expiration of Contributor's exclusive
|
||||||
|
intellectual property rights to the Contributions. \
|
||||||
|
7.3. The Author may unilaterally alter the Agreement without informing Contributors.
|
||||||
|
The new version of the document shall come into effect 3 (three) days after
|
||||||
|
being published in the Official Repository of the Program at Internet address
|
||||||
|
[https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md](https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md).
|
||||||
|
Contributors should keep informed about the actual version of the Agreement themselves. \
|
||||||
|
7.4. If the Author and the Contributor fail to agree on disputable issues,
|
||||||
|
disputes shall be referred to the Moscow Arbitration court.
|
|
@ -0,0 +1,108 @@
|
||||||
|
## Лицензионное соглашение с участником
|
||||||
|
|
||||||
|
> Данная Оферта написана в Русской и Английской версиях. **Версия на английском
|
||||||
|
языке предоставляется в информационных целях** и не связывает стороны договора.
|
||||||
|
>
|
||||||
|
> В случае несоответствий между положениями Русской и Английской версий Договора,
|
||||||
|
**Русская версия имеет приоритет**.
|
||||||
|
>
|
||||||
|
> Английская версия опубликована по адресу https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md
|
||||||
|
|
||||||
|
Настоящий договор-оферта (далее по тексту – Оферта, Договор) адресована физическим
|
||||||
|
и юридическим лицам (далее – Участникам) и является официальным публичным предложением
|
||||||
|
Филиппова Виталия Владимировича (далее – Автора) программного обеспечения Vitastor,
|
||||||
|
свидетельство Федеральной службы по интеллектуальной собственности (Роспатент) № 2021617829
|
||||||
|
от 20 мая 2021 г. (далее – Программа) о нижеследующем:
|
||||||
|
|
||||||
|
1. Термины и определения \
|
||||||
|
1.1. Репозиторий – электронное хранилище, содержащее исходный код Программы. \
|
||||||
|
1.2. Доработка – результат интеллектуальной деятельности Участника, включающий
|
||||||
|
в себя изменения или дополнения к исходному коду Программы, которые Участник
|
||||||
|
желает включить в состав Программы для дальнейшего использования и распространения
|
||||||
|
Автором и для этого направляет их Автору. \
|
||||||
|
1.3. Участник – физическое или юридическое лицо, вносящее Доработки в код Программы. \
|
||||||
|
1.4. ГК РФ – Гражданский кодекс Российской Федерации.
|
||||||
|
|
||||||
|
2. Предмет оферты \
|
||||||
|
2.1. Предметом настоящей оферты являются Доработки, отправляемые Участником Автору. \
|
||||||
|
2.2. Участник предоставляет Автору право использовать Доработки по собственному усмотрению
|
||||||
|
и без необходимости предварительного согласования с Участником или иным третьим лицом
|
||||||
|
на условиях простой (неисключительной) безвозмездной безотзывной лицензии, полностью
|
||||||
|
или фрагментарно, в составе Программы или других программ, продуктов или сервисов
|
||||||
|
как с открытым, так и с закрытым исходным кодом, любыми способами, не противоречащими
|
||||||
|
закону, включая, но не ограничиваясь следующими: \
|
||||||
|
2.2.1. Запускать и использовать Доработки для выполнения любых задач; \
|
||||||
|
2.2.2. Распространять, импортировать и доводить Доработки до всеобщего сведения; \
|
||||||
|
2.2.3. Вносить в Доработки изменения, сокращения и дополнения, снабжать Доработки
|
||||||
|
при их использовании комментариями, иллюстрациями или пояснениями; \
|
||||||
|
2.2.4. Создавать на основе Доработок иные результаты интеллектуальной деятельности,
|
||||||
|
в том числе производные и составные произведения; \
|
||||||
|
2.2.5. Переводить Доработки на другие языки, в том числе на другие языки программирования; \
|
||||||
|
2.2.6. Осуществлять прокат и публичный показ Доработок; \
|
||||||
|
2.2.7. Использовать Доработки под любым фирменным наименованием, товарным знаком
|
||||||
|
(знаком обслуживания) или иным обозначением, или без такового. \
|
||||||
|
2.3. Участник предоставляет Автору право сублицензировать полученные права на Доработки
|
||||||
|
третьим лицам на любых условиях на усмотрение Автора. \
|
||||||
|
2.4. Участник предоставляет Автору права на Доработки на территории всего мира. \
|
||||||
|
2.5. Участник предоставляет Автору права на весь срок действия исключительного права
|
||||||
|
Участника на Доработки. \
|
||||||
|
2.6. Участник предоставляет Автору права на Доработки на безвозмездной основе. \
|
||||||
|
2.7. Участник разрешает Автору самостоятельно определять порядок, способ и
|
||||||
|
место указания его имени, реквизитов и/или псевдонима при включении
|
||||||
|
Доработок в состав Программы или других программ, продуктов или сервисов.
|
||||||
|
|
||||||
|
3. Акцепт Оферты \
|
||||||
|
3.1. Участник может передавать Доработки в адрес Автора через зеркала официального
|
||||||
|
Репозитория Программы по адресам https://git.yourcmc.ru/vitalif/vitastor/ или
|
||||||
|
https://github.com/vitalif/vitastor/ в виде “запроса на слияние” (pull request),
|
||||||
|
либо в письменном виде или с помощью любых других электронных средств коммуникации,
|
||||||
|
например, электронной почты или мессенджеров. \
|
||||||
|
3.2. Факт передачи Участником Доработок в адрес Автора любым способом с одной из пометок
|
||||||
|
“I accept Vitastor CLA agreement: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-en.md”
|
||||||
|
или “Я принимаю соглашение Vitastor CLA: https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-ru.md”
|
||||||
|
является полным и безоговорочным акцептом (принятием) Участником условий настоящей
|
||||||
|
Оферты, т.е. Участник считается ознакомившимся с настоящим публичным договором и
|
||||||
|
в соответствии с ГК РФ признается лицом, вступившим с Автором в договорные отношения
|
||||||
|
на основании настоящей Оферты. \
|
||||||
|
3.3. Датой акцептирования настоящей Оферты считается дата такой передачи.
|
||||||
|
|
||||||
|
4. Права и обязанности Сторон \
|
||||||
|
4.1. Участник сохраняет за собой право использовать Доработки любым законным
|
||||||
|
способом, не противоречащим настоящему Договору. \
|
||||||
|
4.2. Автор вправе отказать Участнику во включении Доработок в состав
|
||||||
|
Программы без объяснения причин в любой момент по своему усмотрению.
|
||||||
|
|
||||||
|
5. Гарантии и заверения \
|
||||||
|
5.1. Лицо, направляющее Доработки для целей их включения в состав Программы,
|
||||||
|
гарантирует, что является Участником или представителем Участника. Имя или реквизиты
|
||||||
|
Участника должны быть указаны при их передаче в адрес Автора Программы. \
|
||||||
|
5.2. Участник гарантирует, что является законным обладателем исключительных прав
|
||||||
|
на Доработки. \
|
||||||
|
5.3. Участник гарантирует, что на момент акцептирования настоящей Оферты ему
|
||||||
|
ничего не известно (и не могло быть известно) о правах третьих лиц на
|
||||||
|
передаваемые Автору Доработки или их часть, которые могут быть нарушены
|
||||||
|
в связи с передачей Доработок по настоящему Договору. \
|
||||||
|
5.4. Участник гарантирует, что является дееспособным лицом и обладает всеми
|
||||||
|
необходимыми правами для заключения Договора. \
|
||||||
|
5.5. Участник гарантирует, что Доработки не содержат вредоносного ПО, а также
|
||||||
|
любой другой информации, запрещённой к распространению по законам Российской
|
||||||
|
Федерации.
|
||||||
|
|
||||||
|
6. Прекращение действия оферты \
|
||||||
|
6.1. Действие настоящего договора может быть прекращено по соглашению сторон,
|
||||||
|
оформленному в письменном виде, а также вследствие его расторжения по основаниям,
|
||||||
|
предусмотренным законом.
|
||||||
|
|
||||||
|
7. Заключительные положения \
|
||||||
|
7.1. Участник вправе по желанию подписать настоящий Договор в письменном виде. \
|
||||||
|
7.2. Настоящий договор действует с момента его заключения и до истечения срока
|
||||||
|
действия исключительных прав Участника на Доработки. \
|
||||||
|
7.3. Автор имеет право в одностороннем порядке вносить изменения и дополнения в договор
|
||||||
|
без специального уведомления об этом Участников. Новая редакция документа вступает
|
||||||
|
в силу через 3 (Три) календарных дня со дня опубликования в официальном Репозитории
|
||||||
|
Программы по адресу в сети Интернет
|
||||||
|
[https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-ru.md](https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/CLA-ru.md).
|
||||||
|
Участники самостоятельно отслеживают действующие условия Оферты. \
|
||||||
|
7.4. Все споры, возникающие между сторонами в процессе их взаимодействия по настоящему
|
||||||
|
договору, решаются путём переговоров. В случае невозможности урегулирования споров
|
||||||
|
переговорным порядком стороны разрешают их в Арбитражном суде г.Москвы.
|
|
@ -2,6 +2,6 @@ cmake_minimum_required(VERSION 2.8.12)
|
||||||
|
|
||||||
project(vitastor)
|
project(vitastor)
|
||||||
|
|
||||||
set(VERSION "0.8.9")
|
set(VERSION "1.4.4")
|
||||||
|
|
||||||
add_subdirectory(src)
|
add_subdirectory(src)
|
||||||
|
|
|
@ -15,7 +15,7 @@ Vitastor архитектурно похож на Ceph, что означает
|
||||||
и автоматическое распределение данных по любому числу дисков любого размера с настраиваемыми схемами
|
и автоматическое распределение данных по любому числу дисков любого размера с настраиваемыми схемами
|
||||||
избыточности - репликацией или с произвольными кодами коррекции ошибок.
|
избыточности - репликацией или с произвольными кодами коррекции ошибок.
|
||||||
|
|
||||||
Vitastor нацелен на SSD и SSD+HDD кластеры с как минимум 10 Гбит/с сетью, поддерживает
|
Vitastor нацелен в первую очередь на SSD и SSD+HDD кластеры с как минимум 10 Гбит/с сетью, поддерживает
|
||||||
TCP и RDMA и на хорошем железе может достигать задержки 4 КБ чтения и записи на уровне ~0.1 мс,
|
TCP и RDMA и на хорошем железе может достигать задержки 4 КБ чтения и записи на уровне ~0.1 мс,
|
||||||
что примерно в 10 раз быстрее, чем Ceph и другие популярные программные СХД.
|
что примерно в 10 раз быстрее, чем Ceph и другие популярные программные СХД.
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ Vitastor поддерживает QEMU-драйвер, протоколы NBD и
|
||||||
- Параметры
|
- Параметры
|
||||||
- [Общие](docs/config/common.ru.md)
|
- [Общие](docs/config/common.ru.md)
|
||||||
- [Сетевые](docs/config/network.ru.md)
|
- [Сетевые](docs/config/network.ru.md)
|
||||||
|
- [Клиентский код](docs/config/client.en.md)
|
||||||
- [Глобальные дисковые параметры](docs/config/layout-cluster.ru.md)
|
- [Глобальные дисковые параметры](docs/config/layout-cluster.ru.md)
|
||||||
- [Дисковые параметры OSD](docs/config/layout-osd.ru.md)
|
- [Дисковые параметры OSD](docs/config/layout-osd.ru.md)
|
||||||
- [Прочие параметры OSD](docs/config/osd.ru.md)
|
- [Прочие параметры OSD](docs/config/osd.ru.md)
|
||||||
|
|
|
@ -14,8 +14,8 @@ Vitastor is architecturally similar to Ceph which means strong consistency,
|
||||||
primary-replication, symmetric clustering and automatic data distribution over any
|
primary-replication, symmetric clustering and automatic data distribution over any
|
||||||
number of drives of any size with configurable redundancy (replication or erasure codes/XOR).
|
number of drives of any size with configurable redundancy (replication or erasure codes/XOR).
|
||||||
|
|
||||||
Vitastor targets SSD and SSD+HDD clusters with at least 10 Gbit/s network, supports
|
Vitastor targets primarily SSD and SSD+HDD clusters with at least 10 Gbit/s network,
|
||||||
TCP and RDMA and may achieve 4 KB read and write latency as low as ~0.1 ms
|
supports TCP and RDMA and may achieve 4 KB read and write latency as low as ~0.1 ms
|
||||||
with proper hardware which is ~10 times faster than other popular SDS's like Ceph
|
with proper hardware which is ~10 times faster than other popular SDS's like Ceph
|
||||||
or internal systems of public clouds.
|
or internal systems of public clouds.
|
||||||
|
|
||||||
|
@ -50,6 +50,7 @@ Read more details below in the documentation.
|
||||||
- Parameter Reference
|
- Parameter Reference
|
||||||
- [Common](docs/config/common.en.md)
|
- [Common](docs/config/common.en.md)
|
||||||
- [Network](docs/config/network.en.md)
|
- [Network](docs/config/network.en.md)
|
||||||
|
- [Client](docs/config/client.en.md)
|
||||||
- [Global Disk Layout](docs/config/layout-cluster.en.md)
|
- [Global Disk Layout](docs/config/layout-cluster.en.md)
|
||||||
- [OSD Disk Layout](docs/config/layout-osd.en.md)
|
- [OSD Disk Layout](docs/config/layout-osd.en.md)
|
||||||
- [OSD Runtime Parameters](docs/config/osd.en.md)
|
- [OSD Runtime Parameters](docs/config/osd.en.md)
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
Subproject commit 45e6d1f13196a0824e2089a586c53b9de0283f17
|
Subproject commit 8de8b467acbca50cfd8835c20e0e379110f3b32b
|
|
@ -1,14 +1,15 @@
|
||||||
# Compile stage
|
# Compile stage
|
||||||
FROM golang:buster AS build
|
FROM golang:bookworm AS build
|
||||||
|
|
||||||
ADD go.sum go.mod /app/
|
ADD go.sum go.mod /app/
|
||||||
RUN cd /app; CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go mod download -x
|
RUN cd /app; CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go mod download -x
|
||||||
ADD . /app
|
ADD . /app
|
||||||
RUN perl -i -e '$/ = undef; while(<>) { s/\n\s*(\{\s*\n)/$1\n/g; s/\}(\s*\n\s*)else\b/$1} else/g; print; }' `find /app -name '*.go'`
|
RUN perl -i -e '$/ = undef; while(<>) { s/\n\s*(\{\s*\n)/$1\n/g; s/\}(\s*\n\s*)else\b/$1} else/g; print; }' `find /app -name '*.go'` && \
|
||||||
RUN cd /app; CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o vitastor-csi
|
cd /app && \
|
||||||
|
CGO_ENABLED=1 GOOS=linux GOARCH=amd64 go build -o vitastor-csi
|
||||||
|
|
||||||
# Final stage
|
# Final stage
|
||||||
FROM debian:buster
|
FROM debian:bookworm
|
||||||
|
|
||||||
LABEL maintainers="Vitaliy Filippov <vitalif@yourcmc.ru>"
|
LABEL maintainers="Vitaliy Filippov <vitalif@yourcmc.ru>"
|
||||||
LABEL description="Vitastor CSI Driver"
|
LABEL description="Vitastor CSI Driver"
|
||||||
|
@ -18,19 +19,30 @@ ENV CSI_ENDPOINT=""
|
||||||
|
|
||||||
RUN apt-get update && \
|
RUN apt-get update && \
|
||||||
apt-get install -y wget && \
|
apt-get install -y wget && \
|
||||||
(echo deb http://deb.debian.org/debian buster-backports main > /etc/apt/sources.list.d/backports.list) && \
|
|
||||||
(echo "APT::Install-Recommends false;" > /etc/apt/apt.conf) && \
|
(echo "APT::Install-Recommends false;" > /etc/apt/apt.conf) && \
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install -y e2fsprogs xfsprogs kmod && \
|
apt-get install -y e2fsprogs xfsprogs kmod iproute2 \
|
||||||
|
# dependencies of qemu-storage-daemon
|
||||||
|
libnuma1 liburing2 libglib2.0-0 libfuse3-3 libaio1 libzstd1 libnettle8 \
|
||||||
|
libgmp10 libhogweed6 libp11-kit0 libidn2-0 libunistring2 libtasn1-6 libpcre2-8-0 libffi8 && \
|
||||||
apt-get clean && \
|
apt-get clean && \
|
||||||
(echo options nbd nbds_max=128 > /etc/modprobe.d/nbd.conf)
|
(echo options nbd nbds_max=128 > /etc/modprobe.d/nbd.conf)
|
||||||
|
|
||||||
COPY --from=build /app/vitastor-csi /bin/
|
COPY --from=build /app/vitastor-csi /bin/
|
||||||
|
|
||||||
RUN (echo deb http://vitastor.io/debian buster main > /etc/apt/sources.list.d/vitastor.list) && \
|
RUN (echo deb http://vitastor.io/debian bookworm main > /etc/apt/sources.list.d/vitastor.list) && \
|
||||||
|
((echo 'Package: *'; echo 'Pin: origin "vitastor.io"'; echo 'Pin-Priority: 1000') > /etc/apt/preferences.d/vitastor.pref) && \
|
||||||
wget -q -O /etc/apt/trusted.gpg.d/vitastor.gpg https://vitastor.io/debian/pubkey.gpg && \
|
wget -q -O /etc/apt/trusted.gpg.d/vitastor.gpg https://vitastor.io/debian/pubkey.gpg && \
|
||||||
apt-get update && \
|
apt-get update && \
|
||||||
apt-get install -y vitastor-client && \
|
apt-get install -y vitastor-client && \
|
||||||
|
wget https://vitastor.io/archive/qemu/qemu-bookworm-8.1.2%2Bds-1%2Bvitastor1/qemu-utils_8.1.2%2Bds-1%2Bvitastor1_amd64.deb && \
|
||||||
|
wget https://vitastor.io/archive/qemu/qemu-bookworm-8.1.2%2Bds-1%2Bvitastor1/qemu-block-extra_8.1.2%2Bds-1%2Bvitastor1_amd64.deb && \
|
||||||
|
dpkg -x qemu-utils*.deb tmp1 && \
|
||||||
|
dpkg -x qemu-block-extra*.deb tmp1 && \
|
||||||
|
cp -a tmp1/usr/bin/qemu-storage-daemon /usr/bin/ && \
|
||||||
|
mkdir -p /usr/lib/x86_64-linux-gnu/qemu && \
|
||||||
|
cp -a tmp1/usr/lib/x86_64-linux-gnu/qemu/block-vitastor.so /usr/lib/x86_64-linux-gnu/qemu/ && \
|
||||||
|
rm -rf tmp1 *.deb && \
|
||||||
apt-get clean
|
apt-get clean
|
||||||
|
|
||||||
ENTRYPOINT ["/bin/vitastor-csi"]
|
ENTRYPOINT ["/bin/vitastor-csi"]
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
VERSION ?= v0.8.9
|
VERSION ?= v1.4.4
|
||||||
|
|
||||||
all: build push
|
all: build push
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,7 @@
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
kind: ConfigMap
|
kind: ConfigMap
|
||||||
data:
|
data:
|
||||||
|
# You can add multiple configuration files here to use a multi-cluster setup
|
||||||
vitastor.conf: |-
|
vitastor.conf: |-
|
||||||
{"etcd_address":"http://192.168.7.2:2379","etcd_prefix":"/vitastor"}
|
{"etcd_address":"http://192.168.7.2:2379","etcd_prefix":"/vitastor"}
|
||||||
metadata:
|
metadata:
|
||||||
|
|
|
@ -49,7 +49,7 @@ spec:
|
||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
allowPrivilegeEscalation: true
|
allowPrivilegeEscalation: true
|
||||||
image: vitalif/vitastor-csi:v0.8.9
|
image: vitalif/vitastor-csi:v1.4.4
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
@ -82,6 +82,8 @@ spec:
|
||||||
name: host-sys
|
name: host-sys
|
||||||
- mountPath: /run/mount
|
- mountPath: /run/mount
|
||||||
name: host-mount
|
name: host-mount
|
||||||
|
- mountPath: /run/vitastor-csi
|
||||||
|
name: run-vitastor-csi
|
||||||
- mountPath: /lib/modules
|
- mountPath: /lib/modules
|
||||||
name: lib-modules
|
name: lib-modules
|
||||||
readOnly: true
|
readOnly: true
|
||||||
|
@ -132,6 +134,9 @@ spec:
|
||||||
- name: host-mount
|
- name: host-mount
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /run/mount
|
path: /run/mount
|
||||||
|
- name: run-vitastor-csi
|
||||||
|
hostPath:
|
||||||
|
path: /run/vitastor-csi
|
||||||
- name: lib-modules
|
- name: lib-modules
|
||||||
hostPath:
|
hostPath:
|
||||||
path: /lib/modules
|
path: /lib/modules
|
||||||
|
|
|
@ -35,10 +35,13 @@ rules:
|
||||||
verbs: ["get", "list", "watch"]
|
verbs: ["get", "list", "watch"]
|
||||||
- apiGroups: ["snapshot.storage.k8s.io"]
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
resources: ["volumesnapshots"]
|
resources: ["volumesnapshots"]
|
||||||
verbs: ["get", "list"]
|
verbs: ["get", "list", "patch"]
|
||||||
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
|
resources: ["volumesnapshots/status"]
|
||||||
|
verbs: ["get", "list", "patch"]
|
||||||
- apiGroups: ["snapshot.storage.k8s.io"]
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
resources: ["volumesnapshotcontents"]
|
resources: ["volumesnapshotcontents"]
|
||||||
verbs: ["create", "get", "list", "watch", "update", "delete"]
|
verbs: ["create", "get", "list", "watch", "update", "delete", "patch"]
|
||||||
- apiGroups: ["snapshot.storage.k8s.io"]
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
resources: ["volumesnapshotclasses"]
|
resources: ["volumesnapshotclasses"]
|
||||||
verbs: ["get", "list", "watch"]
|
verbs: ["get", "list", "watch"]
|
||||||
|
@ -53,7 +56,7 @@ rules:
|
||||||
verbs: ["get", "list", "watch"]
|
verbs: ["get", "list", "watch"]
|
||||||
- apiGroups: ["snapshot.storage.k8s.io"]
|
- apiGroups: ["snapshot.storage.k8s.io"]
|
||||||
resources: ["volumesnapshotcontents/status"]
|
resources: ["volumesnapshotcontents/status"]
|
||||||
verbs: ["update"]
|
verbs: ["update", "patch"]
|
||||||
- apiGroups: [""]
|
- apiGroups: [""]
|
||||||
resources: ["configmaps"]
|
resources: ["configmaps"]
|
||||||
verbs: ["get"]
|
verbs: ["get"]
|
||||||
|
|
|
@ -23,6 +23,11 @@ metadata:
|
||||||
name: csi-vitastor-provisioner
|
name: csi-vitastor-provisioner
|
||||||
spec:
|
spec:
|
||||||
replicas: 3
|
replicas: 3
|
||||||
|
strategy:
|
||||||
|
type: RollingUpdate
|
||||||
|
rollingUpdate:
|
||||||
|
maxUnavailable: 1
|
||||||
|
maxSurge: 0
|
||||||
selector:
|
selector:
|
||||||
matchLabels:
|
matchLabels:
|
||||||
app: csi-vitastor-provisioner
|
app: csi-vitastor-provisioner
|
||||||
|
@ -46,7 +51,7 @@ spec:
|
||||||
priorityClassName: system-cluster-critical
|
priorityClassName: system-cluster-critical
|
||||||
containers:
|
containers:
|
||||||
- name: csi-provisioner
|
- name: csi-provisioner
|
||||||
image: k8s.gcr.io/sig-storage/csi-provisioner:v2.2.0
|
image: k8s.gcr.io/sig-storage/csi-provisioner:v3.0.0
|
||||||
args:
|
args:
|
||||||
- "--csi-address=$(ADDRESS)"
|
- "--csi-address=$(ADDRESS)"
|
||||||
- "--v=5"
|
- "--v=5"
|
||||||
|
@ -116,7 +121,7 @@ spec:
|
||||||
privileged: true
|
privileged: true
|
||||||
capabilities:
|
capabilities:
|
||||||
add: ["SYS_ADMIN"]
|
add: ["SYS_ADMIN"]
|
||||||
image: vitalif/vitastor-csi:v0.8.9
|
image: vitalif/vitastor-csi:v1.4.4
|
||||||
args:
|
args:
|
||||||
- "--node=$(NODE_ID)"
|
- "--node=$(NODE_ID)"
|
||||||
- "--endpoint=$(CSI_ENDPOINT)"
|
- "--endpoint=$(CSI_ENDPOINT)"
|
||||||
|
|
|
@ -12,8 +12,6 @@ parameters:
|
||||||
etcdVolumePrefix: ""
|
etcdVolumePrefix: ""
|
||||||
poolId: "1"
|
poolId: "1"
|
||||||
# you can choose other configuration file if you have it in the config map
|
# you can choose other configuration file if you have it in the config map
|
||||||
|
# different etcd URLs and prefixes should also be put in the config
|
||||||
#configPath: "/etc/vitastor/vitastor.conf"
|
#configPath: "/etc/vitastor/vitastor.conf"
|
||||||
# you can also specify etcdUrl here, maybe to connect to another Vitastor cluster
|
allowVolumeExpansion: true
|
||||||
# multiple etcdUrls may be specified, delimited by comma
|
|
||||||
#etcdUrl: "http://192.168.7.2:2379"
|
|
||||||
#etcdPrefix: "/vitastor"
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
apiVersion: snapshot.storage.k8s.io/v1
|
||||||
|
kind: VolumeSnapshotClass
|
||||||
|
metadata:
|
||||||
|
name: vitastor-snapclass
|
||||||
|
driver: csi.vitastor.io
|
||||||
|
deletionPolicy: Delete
|
||||||
|
parameters:
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
apiVersion: v1
|
||||||
|
kind: PersistentVolumeClaim
|
||||||
|
metadata:
|
||||||
|
name: test-vitastor-clone
|
||||||
|
spec:
|
||||||
|
storageClassName: vitastor
|
||||||
|
dataSource:
|
||||||
|
name: snap1
|
||||||
|
kind: VolumeSnapshot
|
||||||
|
apiGroup: snapshot.storage.k8s.io
|
||||||
|
accessModes:
|
||||||
|
- ReadWriteOnce
|
||||||
|
resources:
|
||||||
|
requests:
|
||||||
|
storage: 10Gi
|
|
@ -0,0 +1,8 @@
|
||||||
|
apiVersion: snapshot.storage.k8s.io/v1
|
||||||
|
kind: VolumeSnapshot
|
||||||
|
metadata:
|
||||||
|
name: snap1
|
||||||
|
spec:
|
||||||
|
volumeSnapshotClassName: vitastor-snapclass
|
||||||
|
source:
|
||||||
|
persistentVolumeClaimName: test-vitastor-pvc
|
|
@ -9,6 +9,7 @@ require (
|
||||||
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb
|
golang.org/x/net v0.0.0-20201202161906-c7110b5ffcbb
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
|
||||||
google.golang.org/grpc v1.33.1
|
google.golang.org/grpc v1.33.1
|
||||||
|
google.golang.org/protobuf v1.24.0
|
||||||
k8s.io/klog v1.0.0
|
k8s.io/klog v1.0.0
|
||||||
k8s.io/utils v0.0.0-20210305010621-2afb4311ab10
|
k8s.io/utils v0.0.0-20210305010621-2afb4311ab10
|
||||||
)
|
)
|
||||||
|
|
|
@ -5,7 +5,7 @@ package vitastor
|
||||||
|
|
||||||
const (
|
const (
|
||||||
vitastorCSIDriverName = "csi.vitastor.io"
|
vitastorCSIDriverName = "csi.vitastor.io"
|
||||||
vitastorCSIDriverVersion = "0.8.9"
|
vitastorCSIDriverVersion = "1.4.4"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Config struct fills the parameters of request or user input
|
// Config struct fills the parameters of request or user input
|
||||||
|
|
|
@ -20,6 +20,7 @@ import (
|
||||||
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
"google.golang.org/protobuf/types/known/timestamppb"
|
||||||
|
|
||||||
"github.com/container-storage-interface/spec/lib/go/csi"
|
"github.com/container-storage-interface/spec/lib/go/csi"
|
||||||
)
|
)
|
||||||
|
@ -45,6 +46,7 @@ type InodeConfig struct
|
||||||
ParentPool uint64 `json:"parent_pool,omitempty"`
|
ParentPool uint64 `json:"parent_pool,omitempty"`
|
||||||
ParentId uint64 `json:"parent_id,omitempty"`
|
ParentId uint64 `json:"parent_id,omitempty"`
|
||||||
Readonly bool `json:"readonly,omitempty"`
|
Readonly bool `json:"readonly,omitempty"`
|
||||||
|
CreateTs uint64 `json:"create_ts,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type ControllerServer struct
|
type ControllerServer struct
|
||||||
|
@ -60,7 +62,7 @@ func NewControllerServer(driver *Driver) *ControllerServer
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetConnectionParams(params map[string]string) (map[string]string, []string, string)
|
func GetConnectionParams(params map[string]string) (map[string]string, error)
|
||||||
{
|
{
|
||||||
ctxVars := make(map[string]string)
|
ctxVars := make(map[string]string)
|
||||||
configPath := params["configPath"]
|
configPath := params["configPath"]
|
||||||
|
@ -73,71 +75,69 @@ func GetConnectionParams(params map[string]string) (map[string]string, []string,
|
||||||
ctxVars["configPath"] = configPath
|
ctxVars["configPath"] = configPath
|
||||||
}
|
}
|
||||||
config := make(map[string]interface{})
|
config := make(map[string]interface{})
|
||||||
if configFD, err := os.Open(configPath); err == nil
|
configFD, err := os.Open(configPath)
|
||||||
|
if (err != nil)
|
||||||
{
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
defer configFD.Close()
|
defer configFD.Close()
|
||||||
data, _ := ioutil.ReadAll(configFD)
|
data, _ := ioutil.ReadAll(configFD)
|
||||||
json.Unmarshal(data, &config)
|
json.Unmarshal(data, &config)
|
||||||
}
|
// Check etcd URL in the config, but do not use the explicit etcdUrl
|
||||||
// Try to load prefix & etcd URL from the config
|
// parameter for CLI calls, otherwise users won't be able to later
|
||||||
|
// change them - storage class parameters are saved in volume IDs
|
||||||
var etcdUrl []string
|
var etcdUrl []string
|
||||||
if (params["etcdUrl"] != "")
|
|
||||||
{
|
|
||||||
ctxVars["etcdUrl"] = params["etcdUrl"]
|
|
||||||
etcdUrl = strings.Split(params["etcdUrl"], ",")
|
|
||||||
}
|
|
||||||
if (len(etcdUrl) == 0)
|
|
||||||
{
|
|
||||||
switch config["etcd_address"].(type)
|
switch config["etcd_address"].(type)
|
||||||
{
|
{
|
||||||
case string:
|
case string:
|
||||||
etcdUrl = strings.Split(config["etcd_address"].(string), ",")
|
url := strings.TrimSpace(config["etcd_address"].(string))
|
||||||
|
if (url != "")
|
||||||
|
{
|
||||||
|
etcdUrl = strings.Split(url, ",")
|
||||||
|
}
|
||||||
case []string:
|
case []string:
|
||||||
etcdUrl = config["etcd_address"].([]string)
|
etcdUrl = config["etcd_address"].([]string)
|
||||||
}
|
case []interface{}:
|
||||||
}
|
for _, url := range config["etcd_address"].([]interface{})
|
||||||
etcdPrefix := params["etcdPrefix"]
|
|
||||||
if (etcdPrefix == "")
|
|
||||||
{
|
{
|
||||||
etcdPrefix, _ = config["etcd_prefix"].(string)
|
s, ok := url.(string)
|
||||||
if (etcdPrefix == "")
|
if (ok)
|
||||||
{
|
{
|
||||||
etcdPrefix = "/vitastor"
|
etcdUrl = append(etcdUrl, s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
if (len(etcdUrl) == 0)
|
||||||
{
|
{
|
||||||
ctxVars["etcdPrefix"] = etcdPrefix
|
return nil, status.Error(codes.InvalidArgument, "etcd_address is missing in "+configPath)
|
||||||
}
|
}
|
||||||
return ctxVars, etcdUrl, etcdPrefix
|
return ctxVars, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func system(program string, args ...string) ([]byte, []byte, error)
|
||||||
|
{
|
||||||
|
klog.Infof("Running "+program+" "+strings.Join(args, " "))
|
||||||
|
c := exec.Command(program, args...)
|
||||||
|
var stdout, stderr bytes.Buffer
|
||||||
|
c.Stdout, c.Stderr = &stdout, &stderr
|
||||||
|
err := c.Run()
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
stdoutStr, stderrStr := string(stdout.Bytes()), string(stderr.Bytes())
|
||||||
|
klog.Errorf(program+" "+strings.Join(args, " ")+" failed: %s, status %s\n", stdoutStr+stderrStr, err)
|
||||||
|
return nil, nil, status.Error(codes.Internal, stdoutStr+stderrStr+" (status "+err.Error()+")")
|
||||||
|
}
|
||||||
|
return stdout.Bytes(), stderr.Bytes(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func invokeCLI(ctxVars map[string]string, args []string) ([]byte, error)
|
func invokeCLI(ctxVars map[string]string, args []string) ([]byte, error)
|
||||||
{
|
{
|
||||||
if (ctxVars["etcdUrl"] != "")
|
|
||||||
{
|
|
||||||
args = append(args, "--etcd_address", ctxVars["etcdUrl"])
|
|
||||||
}
|
|
||||||
if (ctxVars["etcdPrefix"] != "")
|
|
||||||
{
|
|
||||||
args = append(args, "--etcd_prefix", ctxVars["etcdPrefix"])
|
|
||||||
}
|
|
||||||
if (ctxVars["configPath"] != "")
|
if (ctxVars["configPath"] != "")
|
||||||
{
|
{
|
||||||
args = append(args, "--config_path", ctxVars["configPath"])
|
args = append(args, "--config_path", ctxVars["configPath"])
|
||||||
}
|
}
|
||||||
c := exec.Command("/usr/bin/vitastor-cli", args...)
|
stdout, _, err := system("/usr/bin/vitastor-cli", args...)
|
||||||
var stdout, stderr bytes.Buffer
|
return stdout, err
|
||||||
c.Stdout = &stdout
|
|
||||||
c.Stderr = &stderr
|
|
||||||
err := c.Run()
|
|
||||||
stderrStr := string(stderr.Bytes())
|
|
||||||
if (err != nil)
|
|
||||||
{
|
|
||||||
klog.Errorf("vitastor-cli %s failed: %s, status %s\n", strings.Join(args, " "), stderrStr, err)
|
|
||||||
return nil, status.Error(codes.Internal, stderrStr+" (status "+err.Error()+")")
|
|
||||||
}
|
|
||||||
return stdout.Bytes(), nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Create the volume
|
// Create the volume
|
||||||
|
@ -172,32 +172,48 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
|
||||||
volSize = ((capRange.GetRequiredBytes() + MB - 1) / MB) * MB
|
volSize = ((capRange.GetRequiredBytes() + MB - 1) / MB) * MB
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxVars, etcdUrl, _ := GetConnectionParams(req.Parameters)
|
ctxVars, err := GetConnectionParams(req.Parameters)
|
||||||
if (len(etcdUrl) == 0)
|
|
||||||
{
|
|
||||||
return nil, status.Error(codes.InvalidArgument, "no etcdUrl in storage class configuration and no etcd_address in vitastor.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create image using vitastor-cli
|
|
||||||
_, err := invokeCLI(ctxVars, []string{ "create", volName, "-s", fmt.Sprintf("%v", volSize), "--pool", fmt.Sprintf("%v", poolId) })
|
|
||||||
if (err != nil)
|
|
||||||
{
|
|
||||||
if (strings.Index(err.Error(), "already exists") > 0)
|
|
||||||
{
|
|
||||||
stat, err := invokeCLI(ctxVars, []string{ "ls", "--json", volName })
|
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
var inodeCfg []InodeConfig
|
|
||||||
err = json.Unmarshal(stat, &inodeCfg)
|
args := []string{ "create", volName, "-s", fmt.Sprintf("%v", volSize), "--pool", fmt.Sprintf("%v", poolId) }
|
||||||
|
|
||||||
|
// Support creation from snapshot
|
||||||
|
var src *csi.VolumeContentSource
|
||||||
|
if (req.VolumeContentSource.GetSnapshot() != nil)
|
||||||
|
{
|
||||||
|
snapId := req.VolumeContentSource.GetSnapshot().GetSnapshotId()
|
||||||
|
if (snapId != "")
|
||||||
|
{
|
||||||
|
snapVars := make(map[string]string)
|
||||||
|
err := json.Unmarshal([]byte(snapId), &snapVars)
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Internal, "Invalid JSON in vitastor-cli ls: "+err.Error())
|
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
||||||
}
|
}
|
||||||
if (len(inodeCfg) == 0)
|
args = append(args, "--parent", snapVars["name"]+"@"+snapVars["snapshot"])
|
||||||
|
src = &csi.VolumeContentSource{
|
||||||
|
Type: &csi.VolumeContentSource_Snapshot{
|
||||||
|
Snapshot: &csi.VolumeContentSource_SnapshotSource{
|
||||||
|
SnapshotId: snapId,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create image using vitastor-cli
|
||||||
|
_, err = invokeCLI(ctxVars, args)
|
||||||
|
if (err != nil)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Internal, "vitastor-cli create said that image already exists, but ls can't find it")
|
if (strings.Index(err.Error(), "already exists") > 0)
|
||||||
|
{
|
||||||
|
inodeCfg, err := invokeList(ctxVars, volName, true)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
if (inodeCfg[0].Size < uint64(volSize))
|
if (inodeCfg[0].Size < uint64(volSize))
|
||||||
{
|
{
|
||||||
|
@ -217,6 +233,7 @@ func (cs *ControllerServer) CreateVolume(ctx context.Context, req *csi.CreateVol
|
||||||
// Ugly, but VolumeContext isn't passed to DeleteVolume :-(
|
// Ugly, but VolumeContext isn't passed to DeleteVolume :-(
|
||||||
VolumeId: string(volumeIdJson),
|
VolumeId: string(volumeIdJson),
|
||||||
CapacityBytes: volSize,
|
CapacityBytes: volSize,
|
||||||
|
ContentSource: src,
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
@ -230,15 +247,19 @@ func (cs *ControllerServer) DeleteVolume(ctx context.Context, req *csi.DeleteVol
|
||||||
return nil, status.Error(codes.InvalidArgument, "request cannot be empty")
|
return nil, status.Error(codes.InvalidArgument, "request cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxVars := make(map[string]string)
|
volVars := make(map[string]string)
|
||||||
err := json.Unmarshal([]byte(req.VolumeId), &ctxVars)
|
err := json.Unmarshal([]byte(req.VolumeId), &volVars)
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
||||||
}
|
}
|
||||||
volName := ctxVars["name"]
|
volName := volVars["name"]
|
||||||
|
|
||||||
ctxVars, _, _ = GetConnectionParams(ctxVars)
|
ctxVars, err := GetConnectionParams(volVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
_, err = invokeCLI(ctxVars, []string{ "rm", volName })
|
_, err = invokeCLI(ctxVars, []string{ "rm", volName })
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
|
@ -344,6 +365,8 @@ func (cs *ControllerServer) ControllerGetCapabilities(ctx context.Context, req *
|
||||||
csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
|
csi.ControllerServiceCapability_RPC_LIST_VOLUMES,
|
||||||
csi.ControllerServiceCapability_RPC_EXPAND_VOLUME,
|
csi.ControllerServiceCapability_RPC_EXPAND_VOLUME,
|
||||||
csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
|
csi.ControllerServiceCapability_RPC_CREATE_DELETE_SNAPSHOT,
|
||||||
|
csi.ControllerServiceCapability_RPC_LIST_SNAPSHOTS,
|
||||||
|
// TODO: csi.ControllerServiceCapability_RPC_CLONE_VOLUME,
|
||||||
} {
|
} {
|
||||||
controllerServerCapabilities = append(controllerServerCapabilities, functionControllerServerCapabilities(capability))
|
controllerServerCapabilities = append(controllerServerCapabilities, functionControllerServerCapabilities(capability))
|
||||||
}
|
}
|
||||||
|
@ -353,28 +376,226 @@ func (cs *ControllerServer) ControllerGetCapabilities(ctx context.Context, req *
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func invokeList(ctxVars map[string]string, pattern string, expectExist bool) ([]InodeConfig, error)
|
||||||
|
{
|
||||||
|
stat, err := invokeCLI(ctxVars, []string{ "ls", "--json", pattern })
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var inodeCfg []InodeConfig
|
||||||
|
err = json.Unmarshal(stat, &inodeCfg)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.Internal, "Invalid JSON in vitastor-cli ls: "+err.Error())
|
||||||
|
}
|
||||||
|
if (expectExist && len(inodeCfg) == 0)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.Internal, "Can't find expected image "+pattern+" via vitastor-cli ls")
|
||||||
|
}
|
||||||
|
return inodeCfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
// CreateSnapshot create snapshot of an existing PV
|
// CreateSnapshot create snapshot of an existing PV
|
||||||
func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error)
|
func (cs *ControllerServer) CreateSnapshot(ctx context.Context, req *csi.CreateSnapshotRequest) (*csi.CreateSnapshotResponse, error)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Unimplemented, "")
|
klog.Infof("received controller create snapshot request %+v", protosanitizer.StripSecrets(req))
|
||||||
|
if (req == nil)
|
||||||
|
{
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "request cannot be empty")
|
||||||
|
}
|
||||||
|
if (req.SourceVolumeId == "" || req.Name == "")
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "source volume ID and snapshot name are required fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
// snapshot name
|
||||||
|
snapName := req.Name
|
||||||
|
|
||||||
|
// req.VolumeId is an ugly json string in our case :)
|
||||||
|
ctxVars := make(map[string]string)
|
||||||
|
err := json.Unmarshal([]byte(req.SourceVolumeId), &ctxVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
||||||
|
}
|
||||||
|
volName := ctxVars["name"]
|
||||||
|
|
||||||
|
// Create image using vitastor-cli
|
||||||
|
_, err = invokeCLI(ctxVars, []string{ "create", "--snapshot", snapName, volName })
|
||||||
|
if (err != nil && strings.Index(err.Error(), "already exists") <= 0)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check created snapshot
|
||||||
|
inodeCfg, err := invokeList(ctxVars, volName+"@"+snapName, true)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use ugly JSON snapshot ID again, DeleteSnapshot doesn't have context :-(
|
||||||
|
ctxVars["snapshot"] = snapName
|
||||||
|
snapIdJson, _ := json.Marshal(ctxVars)
|
||||||
|
return &csi.CreateSnapshotResponse{
|
||||||
|
Snapshot: &csi.Snapshot{
|
||||||
|
SizeBytes: int64(inodeCfg[0].Size),
|
||||||
|
SnapshotId: string(snapIdJson),
|
||||||
|
SourceVolumeId: req.SourceVolumeId,
|
||||||
|
CreationTime: ×tamppb.Timestamp{ Seconds: int64(inodeCfg[0].CreateTs) },
|
||||||
|
ReadyToUse: true,
|
||||||
|
},
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteSnapshot delete provided snapshot of a PV
|
// DeleteSnapshot delete provided snapshot of a PV
|
||||||
func (cs *ControllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error)
|
func (cs *ControllerServer) DeleteSnapshot(ctx context.Context, req *csi.DeleteSnapshotRequest) (*csi.DeleteSnapshotResponse, error)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Unimplemented, "")
|
klog.Infof("received controller delete snapshot request %+v", protosanitizer.StripSecrets(req))
|
||||||
|
if (req == nil)
|
||||||
|
{
|
||||||
|
return nil, status.Errorf(codes.InvalidArgument, "request cannot be empty")
|
||||||
|
}
|
||||||
|
if (req.SnapshotId == "")
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "snapshot ID is a required field")
|
||||||
|
}
|
||||||
|
|
||||||
|
volVars := make(map[string]string)
|
||||||
|
err := json.Unmarshal([]byte(req.SnapshotId), &volVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.Internal, "snapshot ID not in JSON format")
|
||||||
|
}
|
||||||
|
volName := volVars["name"]
|
||||||
|
snapName := volVars["snapshot"]
|
||||||
|
|
||||||
|
ctxVars, err := GetConnectionParams(volVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = invokeCLI(ctxVars, []string{ "rm", volName+"@"+snapName })
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &csi.DeleteSnapshotResponse{}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListSnapshots list the snapshots of a PV
|
// ListSnapshots list the snapshots of a PV
|
||||||
func (cs *ControllerServer) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error)
|
func (cs *ControllerServer) ListSnapshots(ctx context.Context, req *csi.ListSnapshotsRequest) (*csi.ListSnapshotsResponse, error)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Unimplemented, "")
|
klog.Infof("received controller list snapshots request %+v", protosanitizer.StripSecrets(req))
|
||||||
|
if (req == nil)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "request cannot be empty")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControllerExpandVolume resizes a volume
|
volVars := make(map[string]string)
|
||||||
|
err := json.Unmarshal([]byte(req.SourceVolumeId), &volVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
||||||
|
}
|
||||||
|
volName := volVars["name"]
|
||||||
|
ctxVars, err := GetConnectionParams(volVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
inodeCfg, err := invokeList(ctxVars, volName+"@*", false)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
resp := &csi.ListSnapshotsResponse{}
|
||||||
|
for _, ino := range inodeCfg
|
||||||
|
{
|
||||||
|
snapName := ino.Name[len(volName)+1:]
|
||||||
|
if (len(req.StartingToken) > 0 && snapName < req.StartingToken)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
else if (req.MaxEntries == 0 || len(resp.Entries) < int(req.MaxEntries))
|
||||||
|
{
|
||||||
|
volVars["snapshot"] = snapName
|
||||||
|
snapIdJson, _ := json.Marshal(volVars)
|
||||||
|
resp.Entries = append(resp.Entries, &csi.ListSnapshotsResponse_Entry{
|
||||||
|
Snapshot: &csi.Snapshot{
|
||||||
|
SizeBytes: int64(ino.Size),
|
||||||
|
SnapshotId: string(snapIdJson),
|
||||||
|
SourceVolumeId: req.SourceVolumeId,
|
||||||
|
CreationTime: ×tamppb.Timestamp{ Seconds: int64(ino.CreateTs) },
|
||||||
|
ReadyToUse: true,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
resp.NextToken = snapName
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return resp, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ControllerExpandVolume increases the size of a volume
|
||||||
func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error)
|
func (cs *ControllerServer) ControllerExpandVolume(ctx context.Context, req *csi.ControllerExpandVolumeRequest) (*csi.ControllerExpandVolumeResponse, error)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Unimplemented, "")
|
klog.Infof("received controller expand volume request %+v", protosanitizer.StripSecrets(req))
|
||||||
|
if (req == nil)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "request cannot be empty")
|
||||||
|
}
|
||||||
|
if (req.VolumeId == "" || req.CapacityRange == nil || req.CapacityRange.RequiredBytes == 0)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.InvalidArgument, "VolumeId, CapacityRange and RequiredBytes are required fields")
|
||||||
|
}
|
||||||
|
|
||||||
|
volVars := make(map[string]string)
|
||||||
|
err := json.Unmarshal([]byte(req.VolumeId), &volVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
||||||
|
}
|
||||||
|
volName := volVars["name"]
|
||||||
|
ctxVars, err := GetConnectionParams(volVars)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
inodeCfg, err := invokeList(ctxVars, volName, true)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if (req.CapacityRange.RequiredBytes > 0 && inodeCfg[0].Size < uint64(req.CapacityRange.RequiredBytes))
|
||||||
|
{
|
||||||
|
sz := ((req.CapacityRange.RequiredBytes+4095)/4096)*4096
|
||||||
|
_, err := invokeCLI(ctxVars, []string{ "modify", "--inc_size", "1", "--resize", fmt.Sprintf("%d", sz), volName })
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
inodeCfg, err = invokeList(ctxVars, volName, true)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &csi.ControllerExpandVolumeResponse{
|
||||||
|
CapacityBytes: int64(inodeCfg[0].Size),
|
||||||
|
NodeExpansionRequired: false,
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ControllerGetVolume get volume info
|
// ControllerGetVolume get volume info
|
||||||
|
|
|
@ -49,6 +49,13 @@ func (is *IdentityServer) GetPluginCapabilities(ctx context.Context, req *csi.Ge
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
Type: &csi.PluginCapability_VolumeExpansion_{
|
||||||
|
VolumeExpansion: &csi.PluginCapability_VolumeExpansion{
|
||||||
|
Type: csi.PluginCapability_VolumeExpansion_OFFLINE,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
},
|
},
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,11 +5,16 @@ package vitastor
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
|
"errors"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"encoding/json"
|
"path/filepath"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"bytes"
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
"google.golang.org/grpc/codes"
|
"google.golang.org/grpc/codes"
|
||||||
"google.golang.org/grpc/status"
|
"google.golang.org/grpc/status"
|
||||||
|
@ -25,16 +30,102 @@ import (
|
||||||
type NodeServer struct
|
type NodeServer struct
|
||||||
{
|
{
|
||||||
*Driver
|
*Driver
|
||||||
|
useVduse bool
|
||||||
|
stateDir string
|
||||||
mounter mount.Interface
|
mounter mount.Interface
|
||||||
|
restartInterval time.Duration
|
||||||
|
}
|
||||||
|
|
||||||
|
type DeviceState struct
|
||||||
|
{
|
||||||
|
ConfigPath string `json:"configPath"`
|
||||||
|
VdpaId string `json:"vdpaId"`
|
||||||
|
Image string `json:"image"`
|
||||||
|
Blockdev string `json:"blockdev"`
|
||||||
|
Readonly bool `json:"readonly"`
|
||||||
|
PidFile string `json:"pidFile"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewNodeServer create new instance node
|
// NewNodeServer create new instance node
|
||||||
func NewNodeServer(driver *Driver) *NodeServer
|
func NewNodeServer(driver *Driver) *NodeServer
|
||||||
{
|
{
|
||||||
return &NodeServer{
|
stateDir := os.Getenv("STATE_DIR")
|
||||||
|
if (stateDir == "")
|
||||||
|
{
|
||||||
|
stateDir = "/run/vitastor-csi"
|
||||||
|
}
|
||||||
|
if (stateDir[len(stateDir)-1] != '/')
|
||||||
|
{
|
||||||
|
stateDir += "/"
|
||||||
|
}
|
||||||
|
ns := &NodeServer{
|
||||||
Driver: driver,
|
Driver: driver,
|
||||||
|
useVduse: checkVduseSupport(),
|
||||||
|
stateDir: stateDir,
|
||||||
mounter: mount.New(""),
|
mounter: mount.New(""),
|
||||||
}
|
}
|
||||||
|
if (ns.useVduse)
|
||||||
|
{
|
||||||
|
ns.restoreVduseDaemons()
|
||||||
|
dur, err := time.ParseDuration(os.Getenv("RESTART_INTERVAL"))
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
dur = 10 * time.Second
|
||||||
|
}
|
||||||
|
ns.restartInterval = dur
|
||||||
|
if (ns.restartInterval != time.Duration(0))
|
||||||
|
{
|
||||||
|
go ns.restarter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ns
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkVduseSupport() bool
|
||||||
|
{
|
||||||
|
// Check VDUSE support (vdpa, vduse, virtio-vdpa kernel modules)
|
||||||
|
vduse := true
|
||||||
|
for _, mod := range []string{"vdpa", "vduse", "virtio-vdpa"}
|
||||||
|
{
|
||||||
|
_, err := os.Stat("/sys/module/"+mod)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
if (!errors.Is(err, os.ErrNotExist))
|
||||||
|
{
|
||||||
|
klog.Errorf("failed to check /sys/module/%s: %v", mod, err)
|
||||||
|
}
|
||||||
|
c := exec.Command("/sbin/modprobe", mod)
|
||||||
|
c.Stdout = os.Stderr
|
||||||
|
c.Stderr = os.Stderr
|
||||||
|
err := c.Run()
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("/sbin/modprobe %s failed: %v", mod, err)
|
||||||
|
vduse = false
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Check that vdpa tool functions
|
||||||
|
if (vduse)
|
||||||
|
{
|
||||||
|
c := exec.Command("/sbin/vdpa", "-j", "dev")
|
||||||
|
c.Stderr = os.Stderr
|
||||||
|
err := c.Run()
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("/sbin/vdpa -j dev failed: %v", err)
|
||||||
|
vduse = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!vduse)
|
||||||
|
{
|
||||||
|
klog.Errorf(
|
||||||
|
"Your host apparently has no VDUSE support. VDUSE support disabled, NBD will be used to map devices."+
|
||||||
|
" For VDUSE you need at least Linux 5.15 and the following kernel modules: vdpa, virtio-vdpa, vduse.",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
return vduse
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeStageVolume mounts the volume to a staging path on the node.
|
// NodeStageVolume mounts the volume to a staging path on the node.
|
||||||
|
@ -61,6 +152,318 @@ func Contains(list []string, s string) bool
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) mapNbd(volName string, ctxVars map[string]string, readonly bool) (string, error)
|
||||||
|
{
|
||||||
|
// Map NBD device
|
||||||
|
// FIXME: Check if already mapped
|
||||||
|
args := []string{
|
||||||
|
"map", "--image", volName,
|
||||||
|
}
|
||||||
|
if (ctxVars["configPath"] != "")
|
||||||
|
{
|
||||||
|
args = append(args, "--config_path", ctxVars["configPath"])
|
||||||
|
}
|
||||||
|
if (readonly)
|
||||||
|
{
|
||||||
|
args = append(args, "--readonly", "1")
|
||||||
|
}
|
||||||
|
stdout, stderr, err := system("/usr/bin/vitastor-nbd", args...)
|
||||||
|
dev := strings.TrimSpace(string(stdout))
|
||||||
|
if (dev == "")
|
||||||
|
{
|
||||||
|
return "", fmt.Errorf("vitastor-nbd did not return the name of NBD device. output: %s", stderr)
|
||||||
|
}
|
||||||
|
return dev, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) unmapNbd(devicePath string)
|
||||||
|
{
|
||||||
|
// unmap NBD device
|
||||||
|
unmapOut, unmapErr := exec.Command("/usr/bin/vitastor-nbd", "unmap", devicePath).CombinedOutput()
|
||||||
|
if (unmapErr != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("failed to unmap NBD device %s: %s, error: %v", devicePath, unmapOut, unmapErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func findByPidFile(pidFile string) (*os.Process, error)
|
||||||
|
{
|
||||||
|
pidBuf, err := os.ReadFile(pidFile)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
pid, err := strconv.ParseInt(strings.TrimSpace(string(pidBuf)), 0, 64)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
proc, err := os.FindProcess(int(pid))
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return proc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func killByPidFile(pidFile string) error
|
||||||
|
{
|
||||||
|
klog.Infof("killing process with PID from file %s", pidFile)
|
||||||
|
proc, err := findByPidFile(pidFile)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
return proc.Signal(syscall.SIGTERM)
|
||||||
|
}
|
||||||
|
|
||||||
|
func startStorageDaemon(vdpaId, volName, pidFile, configPath string, readonly bool) error
|
||||||
|
{
|
||||||
|
// Start qemu-storage-daemon
|
||||||
|
blockSpec := map[string]interface{}{
|
||||||
|
"node-name": "disk1",
|
||||||
|
"driver": "vitastor",
|
||||||
|
"image": volName,
|
||||||
|
"cache": map[string]bool{
|
||||||
|
"direct": true,
|
||||||
|
"no-flush": false,
|
||||||
|
},
|
||||||
|
"discard": "unmap",
|
||||||
|
}
|
||||||
|
if (configPath != "")
|
||||||
|
{
|
||||||
|
blockSpec["config-path"] = configPath
|
||||||
|
}
|
||||||
|
blockSpecJson, _ := json.Marshal(blockSpec)
|
||||||
|
writable := "true"
|
||||||
|
if (readonly)
|
||||||
|
{
|
||||||
|
writable = "false"
|
||||||
|
}
|
||||||
|
_, _, err := system(
|
||||||
|
"/usr/bin/qemu-storage-daemon", "--daemonize", "--pidfile", pidFile, "--blockdev", string(blockSpecJson),
|
||||||
|
"--export", "vduse-blk,id="+vdpaId+",node-name=disk1,name="+vdpaId+",num-queues=16,queue-size=128,writable="+writable,
|
||||||
|
)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) mapVduse(volName string, ctxVars map[string]string, readonly bool) (string, string, error)
|
||||||
|
{
|
||||||
|
// Generate state file
|
||||||
|
stateFd, err := os.CreateTemp(ns.stateDir, "vitastor-vduse-*.json")
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
stateFile := stateFd.Name()
|
||||||
|
stateFd.Close()
|
||||||
|
vdpaId := filepath.Base(stateFile)
|
||||||
|
vdpaId = vdpaId[0:len(vdpaId)-5] // remove ".json"
|
||||||
|
pidFile := ns.stateDir + vdpaId + ".pid"
|
||||||
|
// Map VDUSE device via qemu-storage-daemon
|
||||||
|
err = startStorageDaemon(vdpaId, volName, pidFile, ctxVars["configPath"], readonly)
|
||||||
|
if (err == nil)
|
||||||
|
{
|
||||||
|
// Add device to VDPA bus
|
||||||
|
_, _, err = system("/sbin/vdpa", "-j", "dev", "add", "name", vdpaId, "mgmtdev", "vduse")
|
||||||
|
if (err == nil)
|
||||||
|
{
|
||||||
|
// Find block device name
|
||||||
|
var matches []string
|
||||||
|
matches, err = filepath.Glob("/sys/bus/vdpa/devices/"+vdpaId+"/virtio*/block/*")
|
||||||
|
if (err == nil && len(matches) == 0)
|
||||||
|
{
|
||||||
|
err = errors.New("/sys/bus/vdpa/devices/"+vdpaId+"/virtio*/block/* is not found")
|
||||||
|
}
|
||||||
|
if (err == nil)
|
||||||
|
{
|
||||||
|
blockdev := "/dev/"+filepath.Base(matches[0])
|
||||||
|
_, err = os.Stat(blockdev)
|
||||||
|
if (err == nil)
|
||||||
|
{
|
||||||
|
// Generate state file
|
||||||
|
stateJSON, _ := json.Marshal(&DeviceState{
|
||||||
|
ConfigPath: ctxVars["configPath"],
|
||||||
|
VdpaId: vdpaId,
|
||||||
|
Image: volName,
|
||||||
|
Blockdev: blockdev,
|
||||||
|
Readonly: readonly,
|
||||||
|
PidFile: pidFile,
|
||||||
|
})
|
||||||
|
err = os.WriteFile(stateFile, stateJSON, 0600)
|
||||||
|
if (err == nil)
|
||||||
|
{
|
||||||
|
return blockdev, vdpaId, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
killErr := killByPidFile(pidFile)
|
||||||
|
if (killErr != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("Failed to kill started qemu-storage-daemon: %v", killErr)
|
||||||
|
}
|
||||||
|
os.Remove(stateFile)
|
||||||
|
os.Remove(pidFile)
|
||||||
|
}
|
||||||
|
return "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) unmapVduse(devicePath string)
|
||||||
|
{
|
||||||
|
if (len(devicePath) < 6 || devicePath[0:6] != "/dev/v")
|
||||||
|
{
|
||||||
|
klog.Errorf("%s does not start with /dev/v", devicePath)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vduseDev, err := os.Readlink("/sys/block/"+devicePath[5:])
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("%s is not a symbolic link to VDUSE device (../devices/virtual/vduse/xxx): %v", devicePath, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
vdpaId := ""
|
||||||
|
p := strings.Index(vduseDev, "/vduse/")
|
||||||
|
if (p >= 0)
|
||||||
|
{
|
||||||
|
vduseDev = vduseDev[p+7:]
|
||||||
|
p = strings.Index(vduseDev, "/")
|
||||||
|
if (p >= 0)
|
||||||
|
{
|
||||||
|
vdpaId = vduseDev[0:p]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (vdpaId == "")
|
||||||
|
{
|
||||||
|
klog.Errorf("%s is not a symbolic link to VDUSE device (../devices/virtual/vduse/xxx), but is %v", devicePath, vduseDev)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
ns.unmapVduseById(vdpaId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) unmapVduseById(vdpaId string)
|
||||||
|
{
|
||||||
|
_, err := os.Stat("/sys/bus/vdpa/devices/"+vdpaId)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("failed to stat /sys/bus/vdpa/devices/"+vdpaId+": %v", err)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_, _, _ = system("/sbin/vdpa", "-j", "dev", "del", vdpaId)
|
||||||
|
}
|
||||||
|
stateFile := ns.stateDir + vdpaId + ".json"
|
||||||
|
os.Remove(stateFile)
|
||||||
|
pidFile := ns.stateDir + vdpaId + ".pid"
|
||||||
|
_, err = os.Stat(pidFile)
|
||||||
|
if (os.IsNotExist(err))
|
||||||
|
{
|
||||||
|
// ok, already killed
|
||||||
|
}
|
||||||
|
else if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("Failed to stat %v: %v", pidFile, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
err = killByPidFile(pidFile)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("Failed to kill started qemu-storage-daemon: %v", err)
|
||||||
|
}
|
||||||
|
os.Remove(pidFile)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) restarter()
|
||||||
|
{
|
||||||
|
// Restart dead VDUSE daemons at regular intervals
|
||||||
|
// Otherwise volume I/O may hang in case of a qemu-storage-daemon crash
|
||||||
|
// Moreover, it may lead to a kernel panic of the kernel is configured to
|
||||||
|
// panic on hung tasks
|
||||||
|
ticker := time.NewTicker(ns.restartInterval)
|
||||||
|
defer ticker.Stop()
|
||||||
|
for
|
||||||
|
{
|
||||||
|
<-ticker.C
|
||||||
|
ns.restoreVduseDaemons()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (ns *NodeServer) restoreVduseDaemons()
|
||||||
|
{
|
||||||
|
pattern := ns.stateDir+"vitastor-vduse-*.json"
|
||||||
|
matches, err := filepath.Glob(pattern)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("failed to list %s: %v", pattern, err)
|
||||||
|
}
|
||||||
|
if (len(matches) == 0)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
devList := make(map[string]interface{})
|
||||||
|
// example output: {"dev":{"test1":{"type":"block","mgmtdev":"vduse","vendor_id":0,"max_vqs":16,"max_vq_size":128}}}
|
||||||
|
devListJSON, _, err := system("/sbin/vdpa", "-j", "dev", "list")
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return
|
||||||
|
}
|
||||||
|
err = json.Unmarshal(devListJSON, &devList)
|
||||||
|
devs, ok := devList["dev"].(map[string]interface{})
|
||||||
|
if (err != nil || !ok)
|
||||||
|
{
|
||||||
|
klog.Errorf("/sbin/vdpa -j dev list returned bad JSON (error %v): %v", err, string(devListJSON))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, stateFile := range matches
|
||||||
|
{
|
||||||
|
vdpaId := filepath.Base(stateFile)
|
||||||
|
vdpaId = vdpaId[0:len(vdpaId)-5]
|
||||||
|
// Check if VDPA device is still added to the bus
|
||||||
|
if (devs[vdpaId] != nil)
|
||||||
|
{
|
||||||
|
// Check if the storage daemon is still active
|
||||||
|
pidFile := ns.stateDir + vdpaId + ".pid"
|
||||||
|
exists := false
|
||||||
|
proc, err := findByPidFile(pidFile)
|
||||||
|
if (err == nil)
|
||||||
|
{
|
||||||
|
exists = proc.Signal(syscall.Signal(0)) == nil
|
||||||
|
}
|
||||||
|
if (!exists)
|
||||||
|
{
|
||||||
|
// Restart daemon
|
||||||
|
stateJSON, err := os.ReadFile(stateFile)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Warningf("error reading state file %v: %v", stateFile, err)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var state DeviceState
|
||||||
|
err := json.Unmarshal(stateJSON, &state)
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Warningf("state file %v contains invalid JSON (error %v): %v", stateFile, err, string(stateJSON))
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
klog.Warningf("restarting storage daemon for volume %v (VDPA ID %v)", state.Image, vdpaId)
|
||||||
|
_ = startStorageDaemon(vdpaId, state.Image, pidFile, state.ConfigPath, state.Readonly)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Unused, clean it up
|
||||||
|
ns.unmapVduseById(vdpaId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// NodePublishVolume mounts the volume mounted to the staging path to the target path
|
// NodePublishVolume mounts the volume mounted to the staging path to the target path
|
||||||
func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error)
|
func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublishVolumeRequest) (*csi.NodePublishVolumeResponse, error)
|
||||||
{
|
{
|
||||||
|
@ -70,10 +473,10 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
||||||
isBlock := req.GetVolumeCapability().GetBlock() != nil
|
isBlock := req.GetVolumeCapability().GetBlock() != nil
|
||||||
|
|
||||||
// Check that it's not already mounted
|
// Check that it's not already mounted
|
||||||
_, error := mount.IsNotMountPoint(ns.mounter, targetPath)
|
_, err := mount.IsNotMountPoint(ns.mounter, targetPath)
|
||||||
if (error != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
if (os.IsNotExist(error))
|
if (os.IsNotExist(err))
|
||||||
{
|
{
|
||||||
if (isBlock)
|
if (isBlock)
|
||||||
{
|
{
|
||||||
|
@ -81,13 +484,13 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
klog.Errorf("failed to create block device mount target %s with error: %v", targetPath, err)
|
klog.Errorf("failed to create block device mount target %s with error: %v", targetPath, err)
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
err = pathFile.Close()
|
err = pathFile.Close()
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
klog.Errorf("failed to close %s with error: %v", targetPath, err)
|
klog.Errorf("failed to close %s with error: %v", targetPath, err)
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -96,70 +499,57 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
klog.Errorf("failed to create fs mount target %s with error: %v", targetPath, err)
|
klog.Errorf("failed to create fs mount target %s with error: %v", targetPath, err)
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Internal, error.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ctxVars := make(map[string]string)
|
ctxVars := make(map[string]string)
|
||||||
err := json.Unmarshal([]byte(req.VolumeId), &ctxVars)
|
err = json.Unmarshal([]byte(req.VolumeId), &ctxVars)
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
return nil, status.Error(codes.Internal, "volume ID not in JSON format")
|
||||||
}
|
}
|
||||||
volName := ctxVars["name"]
|
volName := ctxVars["name"]
|
||||||
|
|
||||||
_, etcdUrl, etcdPrefix := GetConnectionParams(ctxVars)
|
_, err = GetConnectionParams(ctxVars)
|
||||||
if (len(etcdUrl) == 0)
|
|
||||||
{
|
|
||||||
return nil, status.Error(codes.InvalidArgument, "no etcdUrl in storage class configuration and no etcd_address in vitastor.conf")
|
|
||||||
}
|
|
||||||
|
|
||||||
// Map NBD device
|
|
||||||
// FIXME: Check if already mapped
|
|
||||||
args := []string{
|
|
||||||
"map", "--etcd_address", strings.Join(etcdUrl, ","),
|
|
||||||
"--etcd_prefix", etcdPrefix,
|
|
||||||
"--image", volName,
|
|
||||||
};
|
|
||||||
if (ctxVars["configPath"] != "")
|
|
||||||
{
|
|
||||||
args = append(args, "--config_path", ctxVars["configPath"])
|
|
||||||
}
|
|
||||||
if (req.GetReadonly())
|
|
||||||
{
|
|
||||||
args = append(args, "--readonly", "1")
|
|
||||||
}
|
|
||||||
c := exec.Command("/usr/bin/vitastor-nbd", args...)
|
|
||||||
var stdout, stderr bytes.Buffer
|
|
||||||
c.Stdout, c.Stderr = &stdout, &stderr
|
|
||||||
err = c.Run()
|
|
||||||
stdoutStr, stderrStr := string(stdout.Bytes()), string(stderr.Bytes())
|
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
klog.Errorf("vitastor-nbd map failed: %s, status %s\n", stdoutStr+stderrStr, err)
|
return nil, err
|
||||||
return nil, status.Error(codes.Internal, stdoutStr+stderrStr+" (status "+err.Error()+")")
|
}
|
||||||
|
|
||||||
|
var devicePath, vdpaId string
|
||||||
|
if (!ns.useVduse)
|
||||||
|
{
|
||||||
|
devicePath, err = ns.mapNbd(volName, ctxVars, req.GetReadonly())
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
devicePath, vdpaId, err = ns.mapVduse(volName, ctxVars, req.GetReadonly())
|
||||||
|
}
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
devicePath := strings.TrimSpace(stdoutStr)
|
|
||||||
|
|
||||||
// Check existing format
|
|
||||||
diskMounter := &mount.SafeFormatAndMount{Interface: ns.mounter, Exec: utilexec.New()}
|
diskMounter := &mount.SafeFormatAndMount{Interface: ns.mounter, Exec: utilexec.New()}
|
||||||
|
if (isBlock)
|
||||||
|
{
|
||||||
|
err = diskMounter.Mount(devicePath, targetPath, "", []string{"bind"})
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Check existing format
|
||||||
existingFormat, err := diskMounter.GetDiskFormat(devicePath)
|
existingFormat, err := diskMounter.GetDiskFormat(devicePath)
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
klog.Errorf("failed to get disk format for path %s, error: %v", err)
|
klog.Errorf("failed to get disk format for path %s, error: %v", err)
|
||||||
// unmap NBD device
|
goto unmap
|
||||||
unmapOut, unmapErr := exec.Command("/usr/bin/vitastor-nbd", "unmap", devicePath).CombinedOutput()
|
|
||||||
if (unmapErr != nil)
|
|
||||||
{
|
|
||||||
klog.Errorf("failed to unmap NBD device %s: %s, error: %v", devicePath, unmapOut, unmapErr)
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Format the device (ext4 or xfs)
|
// Format the device (ext4 or xfs)
|
||||||
|
@ -179,38 +569,42 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
||||||
readOnly := Contains(opt, "ro")
|
readOnly := Contains(opt, "ro")
|
||||||
if (existingFormat == "" && !readOnly)
|
if (existingFormat == "" && !readOnly)
|
||||||
{
|
{
|
||||||
args := []string{}
|
var cmdOut []byte
|
||||||
switch fsType
|
switch fsType
|
||||||
{
|
{
|
||||||
case "ext4":
|
case "ext4":
|
||||||
args = []string{"-m0", "-Enodiscard,lazy_itable_init=1,lazy_journal_init=1", devicePath}
|
args := []string{"-m0", "-Enodiscard,lazy_itable_init=1,lazy_journal_init=1", devicePath}
|
||||||
|
cmdOut, err = diskMounter.Exec.Command("mkfs.ext4", args...).CombinedOutput()
|
||||||
case "xfs":
|
case "xfs":
|
||||||
args = []string{"-K", devicePath}
|
cmdOut, err = diskMounter.Exec.Command("mkfs.xfs", "-K", devicePath).CombinedOutput()
|
||||||
}
|
}
|
||||||
if (len(args) > 0)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
cmdOut, cmdErr := diskMounter.Exec.Command("mkfs."+fsType, args...).CombinedOutput()
|
klog.Errorf("failed to run mkfs error: %v, output: %v", err, string(cmdOut))
|
||||||
if (cmdErr != nil)
|
goto unmap
|
||||||
{
|
|
||||||
klog.Errorf("failed to run mkfs error: %v, output: %v", cmdErr, string(cmdOut))
|
|
||||||
// unmap NBD device
|
|
||||||
unmapOut, unmapErr := exec.Command("/usr/bin/vitastor-nbd", "unmap", devicePath).CombinedOutput()
|
|
||||||
if (unmapErr != nil)
|
|
||||||
{
|
|
||||||
klog.Errorf("failed to unmap NBD device %s: %s, error: %v", devicePath, unmapOut, unmapErr)
|
|
||||||
}
|
|
||||||
return nil, status.Error(codes.Internal, cmdErr.Error())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (isBlock)
|
|
||||||
{
|
|
||||||
opt = append(opt, "bind")
|
|
||||||
err = diskMounter.Mount(devicePath, targetPath, fsType, opt)
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
err = diskMounter.FormatAndMount(devicePath, targetPath, fsType, opt)
|
err = diskMounter.FormatAndMount(devicePath, targetPath, fsType, opt)
|
||||||
|
|
||||||
|
// Try to run online resize on mount.
|
||||||
|
// FIXME: Implement online resize. It requires online resize support in vitastor-nbd.
|
||||||
|
if (err == nil && existingFormat != "" && !readOnly)
|
||||||
|
{
|
||||||
|
var cmdOut []byte
|
||||||
|
switch (fsType)
|
||||||
|
{
|
||||||
|
case "ext4":
|
||||||
|
cmdOut, err = diskMounter.Exec.Command("resize2fs", devicePath).CombinedOutput()
|
||||||
|
case "xfs":
|
||||||
|
cmdOut, err = diskMounter.Exec.Command("xfs_growfs", devicePath).CombinedOutput()
|
||||||
|
}
|
||||||
|
if (err != nil)
|
||||||
|
{
|
||||||
|
klog.Errorf("failed to run resizefs error: %v, output: %v", err, string(cmdOut))
|
||||||
|
goto unmap
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
|
@ -218,15 +612,20 @@ func (ns *NodeServer) NodePublishVolume(ctx context.Context, req *csi.NodePublis
|
||||||
"failed to mount device path (%s) to path (%s) for volume (%s) error: %s",
|
"failed to mount device path (%s) to path (%s) for volume (%s) error: %s",
|
||||||
devicePath, targetPath, volName, err,
|
devicePath, targetPath, volName, err,
|
||||||
)
|
)
|
||||||
// unmap NBD device
|
goto unmap
|
||||||
unmapOut, unmapErr := exec.Command("/usr/bin/vitastor-nbd", "unmap", devicePath).CombinedOutput()
|
|
||||||
if (unmapErr != nil)
|
|
||||||
{
|
|
||||||
klog.Errorf("failed to unmap NBD device %s: %s, error: %v", devicePath, unmapOut, unmapErr)
|
|
||||||
}
|
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
|
||||||
}
|
}
|
||||||
return &csi.NodePublishVolumeResponse{}, nil
|
return &csi.NodePublishVolumeResponse{}, nil
|
||||||
|
|
||||||
|
unmap:
|
||||||
|
if (!ns.useVduse || len(devicePath) >= 8 && devicePath[0:8] == "/dev/nbd")
|
||||||
|
{
|
||||||
|
ns.unmapNbd(devicePath)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ns.unmapVduseById(vdpaId)
|
||||||
|
}
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// NodeUnpublishVolume unmounts the volume from the target path
|
// NodeUnpublishVolume unmounts the volume from the target path
|
||||||
|
@ -241,25 +640,31 @@ func (ns *NodeServer) NodeUnpublishVolume(ctx context.Context, req *csi.NodeUnpu
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.NotFound, "Target path not found")
|
return nil, status.Error(codes.NotFound, "Target path not found")
|
||||||
}
|
}
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
if (devicePath == "")
|
if (devicePath == "")
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.NotFound, "Volume not mounted")
|
// volume not mounted
|
||||||
|
klog.Warningf("%s is not a mountpoint, deleting", targetPath)
|
||||||
|
os.Remove(targetPath)
|
||||||
|
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||||
}
|
}
|
||||||
// unmount
|
// unmount
|
||||||
err = mount.CleanupMountPoint(targetPath, ns.mounter, false)
|
err = mount.CleanupMountPoint(targetPath, ns.mounter, false)
|
||||||
if (err != nil)
|
if (err != nil)
|
||||||
{
|
{
|
||||||
return nil, status.Error(codes.Internal, err.Error())
|
return nil, err
|
||||||
}
|
}
|
||||||
// unmap NBD device
|
// unmap NBD device
|
||||||
if (refCount == 1)
|
if (refCount == 1)
|
||||||
{
|
{
|
||||||
unmapOut, unmapErr := exec.Command("/usr/bin/vitastor-nbd", "unmap", devicePath).CombinedOutput()
|
if (!ns.useVduse)
|
||||||
if (unmapErr != nil)
|
|
||||||
{
|
{
|
||||||
klog.Errorf("failed to unmap NBD device %s: %s, error: %v", devicePath, unmapOut, unmapErr)
|
ns.unmapNbd(devicePath)
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ns.unmapVduse(devicePath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return &csi.NodeUnpublishVolumeResponse{}, nil
|
return &csi.NodeUnpublishVolumeResponse{}, nil
|
||||||
|
|
|
@ -0,0 +1,58 @@
|
||||||
|
exit
|
||||||
|
|
||||||
|
git clone https://git.yourcmc.ru/vitalif/pve-qemu .
|
||||||
|
|
||||||
|
# bookworm
|
||||||
|
|
||||||
|
docker run -it -v `pwd`/pve-qemu:/root/pve-qemu --name pve-qemu-bullseye debian:bullseye bash
|
||||||
|
|
||||||
|
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/debian.sources
|
||||||
|
echo 'deb [arch=amd64] http://download.proxmox.com/debian/pve bookworm pve-no-subscription' >> /etc/apt/sources.list
|
||||||
|
echo 'deb https://vitastor.io/debian bookworm main' >> /etc/apt/sources.list
|
||||||
|
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf
|
||||||
|
echo 'ru_RU UTF-8' >> /etc/locale.gen
|
||||||
|
echo 'en_US UTF-8' >> /etc/locale.gen
|
||||||
|
apt-get update
|
||||||
|
apt-get install wget ca-certificates
|
||||||
|
wget https://enterprise.proxmox.com/debian/proxmox-release-bookworm.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bookworm.gpg
|
||||||
|
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg
|
||||||
|
apt-get update
|
||||||
|
apt-get install git devscripts equivs wget mc libjemalloc-dev vitastor-client-dev lintian locales
|
||||||
|
mk-build-deps --install ./control
|
||||||
|
|
||||||
|
# bullseye
|
||||||
|
|
||||||
|
docker run -it -v `pwd`/pve-qemu:/root/pve-qemu --name pve-qemu-bullseye debian:bullseye bash
|
||||||
|
|
||||||
|
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb /deb-src /' >> /etc/apt/sources.list
|
||||||
|
echo 'deb [arch=amd64] http://download.proxmox.com/debian/pve bullseye pve-no-subscription' >> /etc/apt/sources.list
|
||||||
|
echo 'deb https://vitastor.io/debian bullseye main' >> /etc/apt/sources.list
|
||||||
|
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf
|
||||||
|
echo 'ru_RU UTF-8' >> /etc/locale.gen
|
||||||
|
echo 'en_US UTF-8' >> /etc/locale.gen
|
||||||
|
apt-get update
|
||||||
|
apt-get install wget
|
||||||
|
wget https://enterprise.proxmox.com/debian/proxmox-release-bullseye.gpg -O /etc/apt/trusted.gpg.d/proxmox-release-bullseye.gpg
|
||||||
|
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg
|
||||||
|
apt-get update
|
||||||
|
apt-get install git devscripts equivs wget mc libjemalloc-dev vitastor-client-dev lintian locales
|
||||||
|
mk-build-deps --install ./control
|
||||||
|
|
||||||
|
# buster
|
||||||
|
|
||||||
|
docker run -it -v `pwd`/pve-qemu:/root/pve-qemu --name pve-qemu-buster debian:buster bash
|
||||||
|
|
||||||
|
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb /deb-src /' >> /etc/apt/sources.list
|
||||||
|
echo 'deb [arch=amd64] http://download.proxmox.com/debian/pve buster pve-no-subscription' >> /etc/apt/sources.list
|
||||||
|
echo 'deb https://vitastor.io/debian buster main' >> /etc/apt/sources.list
|
||||||
|
echo 'deb http://deb.debian.org/debian buster-backports main' >> /etc/apt/sources.list
|
||||||
|
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf
|
||||||
|
echo 'ru_RU UTF-8' >> /etc/locale.gen
|
||||||
|
echo 'en_US UTF-8' >> /etc/locale.gen
|
||||||
|
apt-get update
|
||||||
|
apt-get install wget ca-certificates
|
||||||
|
wget http://download.proxmox.com/debian/proxmox-ve-release-6.x.gpg -O /etc/apt/trusted.gpg.d/proxmox-ve-release-6.x.gpg
|
||||||
|
wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg
|
||||||
|
apt-get update
|
||||||
|
apt-get install git devscripts equivs wget mc libjemalloc-dev vitastor-client-dev lintian locales
|
||||||
|
mk-build-deps --install ./control
|
|
@ -0,0 +1,7 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
cat < vitastor.Dockerfile > ../Dockerfile
|
||||||
|
cd ..
|
||||||
|
mkdir -p packages
|
||||||
|
sudo podman build --build-arg REL=bookworm -v `pwd`/packages:/root/packages -f Dockerfile .
|
||||||
|
rm Dockerfile
|
|
@ -1,10 +1,10 @@
|
||||||
vitastor (0.8.9-1) unstable; urgency=medium
|
vitastor (1.4.4-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Bugfixes
|
* Bugfixes
|
||||||
|
|
||||||
-- Vitaliy Filippov <vitalif@yourcmc.ru> Fri, 03 Jun 2022 02:09:44 +0300
|
-- Vitaliy Filippov <vitalif@yourcmc.ru> Fri, 03 Jun 2022 02:09:44 +0300
|
||||||
|
|
||||||
vitastor (0.8.9-1) unstable; urgency=medium
|
vitastor (0.7.0-1) unstable; urgency=medium
|
||||||
|
|
||||||
* Implement NFS proxy
|
* Implement NFS proxy
|
||||||
* Add documentation
|
* Add documentation
|
||||||
|
|
|
@ -2,7 +2,7 @@ Source: vitastor
|
||||||
Section: admin
|
Section: admin
|
||||||
Priority: optional
|
Priority: optional
|
||||||
Maintainer: Vitaliy Filippov <vitalif@yourcmc.ru>
|
Maintainer: Vitaliy Filippov <vitalif@yourcmc.ru>
|
||||||
Build-Depends: debhelper, liburing-dev (>= 0.6), g++ (>= 8), libstdc++6 (>= 8), linux-libc-dev, libgoogle-perftools-dev, libjerasure-dev, libgf-complete-dev, libibverbs-dev, libisal-dev
|
Build-Depends: debhelper, liburing-dev (>= 0.6), g++ (>= 8), libstdc++6 (>= 8), linux-libc-dev, libgoogle-perftools-dev, libjerasure-dev, libgf-complete-dev, libibverbs-dev, libisal-dev, cmake, pkg-config
|
||||||
Standards-Version: 4.5.0
|
Standards-Version: 4.5.0
|
||||||
Homepage: https://vitastor.io/
|
Homepage: https://vitastor.io/
|
||||||
Rules-Requires-Root: no
|
Rules-Requires-Root: no
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Build patched QEMU for Debian Buster or Bullseye/Sid inside a container
|
# Build patched QEMU for Debian inside a container
|
||||||
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/patched-qemu.Dockerfile .
|
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/patched-qemu.Dockerfile .
|
||||||
|
|
||||||
ARG REL=
|
ARG REL=
|
||||||
|
@ -7,7 +7,7 @@ ARG REL=
|
||||||
|
|
||||||
WORKDIR /root
|
WORKDIR /root
|
||||||
|
|
||||||
RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" ]; then \
|
RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" -o "$REL" = "bookworm" ]; then \
|
||||||
echo "deb http://deb.debian.org/debian $REL-backports main" >> /etc/apt/sources.list; \
|
echo "deb http://deb.debian.org/debian $REL-backports main" >> /etc/apt/sources.list; \
|
||||||
echo >> /etc/apt/preferences; \
|
echo >> /etc/apt/preferences; \
|
||||||
echo 'Package: *' >> /etc/apt/preferences; \
|
echo 'Package: *' >> /etc/apt/preferences; \
|
||||||
|
@ -15,47 +15,47 @@ RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" ]; then \
|
||||||
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
||||||
fi; \
|
fi; \
|
||||||
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
||||||
|
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/debian.sources || true; \
|
||||||
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
|
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
|
||||||
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get -y install qemu fio liburing1 liburing-dev libgoogle-perftools-dev devscripts
|
RUN apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts
|
||||||
RUN apt-get -y build-dep qemu
|
RUN apt-get -y build-dep qemu
|
||||||
# To build a custom version
|
# To build a custom version
|
||||||
#RUN cp /root/packages/qemu-orig/* /root
|
#RUN cp /root/packages/qemu-orig/* /root
|
||||||
RUN apt-get --download-only source qemu
|
RUN apt-get --download-only source qemu
|
||||||
|
|
||||||
ADD patches/qemu-5.0-vitastor.patch patches/qemu-5.1-vitastor.patch patches/qemu-6.1-vitastor.patch src/qemu_driver.c /root/vitastor/patches/
|
ADD patches /root/vitastor/patches
|
||||||
|
ADD src/qemu_driver.c /root/vitastor/src/qemu_driver.c
|
||||||
|
|
||||||
|
#RUN set -e; \
|
||||||
|
# apt-get install -y wget; \
|
||||||
|
# wget -q -O /etc/apt/trusted.gpg.d/vitastor.gpg https://vitastor.io/debian/pubkey.gpg; \
|
||||||
|
# (echo deb http://vitastor.io/debian $REL main > /etc/apt/sources.list.d/vitastor.list); \
|
||||||
|
# (echo "APT::Install-Recommends false;" > /etc/apt/apt.conf) && \
|
||||||
|
# apt-get update; \
|
||||||
|
# apt-get install -y vitastor-client vitastor-client-dev quilt
|
||||||
|
|
||||||
RUN set -e; \
|
RUN set -e; \
|
||||||
apt-get install -y wget; \
|
dpkg -i /root/packages/vitastor-$REL/vitastor-client_*.deb /root/packages/vitastor-$REL/vitastor-client-dev_*.deb; \
|
||||||
wget -q -O /etc/apt/trusted.gpg.d/vitastor.gpg https://vitastor.io/debian/pubkey.gpg; \
|
|
||||||
(echo deb http://vitastor.io/debian $REL main > /etc/apt/sources.list.d/vitastor.list); \
|
|
||||||
(echo "APT::Install-Recommends false;" > /etc/apt/apt.conf) && \
|
|
||||||
apt-get update; \
|
apt-get update; \
|
||||||
apt-get install -y vitastor-client vitastor-client-dev quilt; \
|
apt-get install -y quilt; \
|
||||||
mkdir -p /root/packages/qemu-$REL; \
|
mkdir -p /root/packages/qemu-$REL; \
|
||||||
rm -rf /root/packages/qemu-$REL/*; \
|
rm -rf /root/packages/qemu-$REL/*; \
|
||||||
cd /root/packages/qemu-$REL; \
|
cd /root/packages/qemu-$REL; \
|
||||||
dpkg-source -x /root/qemu*.dsc; \
|
dpkg-source -x /root/qemu*.dsc; \
|
||||||
if ls -d /root/packages/qemu-$REL/qemu-5.0*; then \
|
QEMU_VER=$(ls -d qemu*/ | perl -pe 's!^.*?(\d+\.\d+).*!$1!'); \
|
||||||
D=$(ls -d /root/packages/qemu-$REL/qemu-5.0*); \
|
D=$(ls -d qemu*/); \
|
||||||
cp /root/vitastor/patches/qemu-5.0-vitastor.patch $D/debian/patches; \
|
cp /root/vitastor/patches/qemu-$QEMU_VER-vitastor.patch ./qemu-*/debian/patches; \
|
||||||
echo qemu-5.0-vitastor.patch >> $D/debian/patches/series; \
|
echo qemu-$QEMU_VER-vitastor.patch >> $D/debian/patches/series; \
|
||||||
elif ls /root/packages/qemu-$REL/qemu-6.1*; then \
|
|
||||||
D=$(ls -d /root/packages/qemu-$REL/qemu-6.1*); \
|
|
||||||
cp /root/vitastor/patches/qemu-6.1-vitastor.patch $D/debian/patches; \
|
|
||||||
echo qemu-6.1-vitastor.patch >> $D/debian/patches/series; \
|
|
||||||
else \
|
|
||||||
cp /root/vitastor/patches/qemu-5.1-vitastor.patch /root/packages/qemu-$REL/qemu-*/debian/patches; \
|
|
||||||
P=`ls -d /root/packages/qemu-$REL/qemu-*/debian/patches`; \
|
|
||||||
echo qemu-5.1-vitastor.patch >> $P/series; \
|
|
||||||
fi; \
|
|
||||||
cd /root/packages/qemu-$REL/qemu-*/; \
|
cd /root/packages/qemu-$REL/qemu-*/; \
|
||||||
quilt push -a; \
|
quilt push -a; \
|
||||||
quilt add block/vitastor.c; \
|
quilt add block/vitastor.c; \
|
||||||
cp /root/vitastor/patches/qemu_driver.c block/vitastor.c; \
|
cp /root/vitastor/src/qemu_driver.c block/vitastor.c; \
|
||||||
quilt refresh; \
|
quilt refresh; \
|
||||||
V=$(head -n1 debian/changelog | perl -pe 's/^.*\((.*?)(~bpo[\d\+]*)?\).*$/$1/')+vitastor1; \
|
V=$(head -n1 debian/changelog | perl -pe 's/5\.2\+dfsg-9/5.2+dfsg-11/; s/^.*\((.*?)(~bpo[\d\+]*)?\).*$/$1/')+vitastor4; \
|
||||||
|
if [ "$REL" = bullseye ]; then V=${V}bullseye; fi; \
|
||||||
DEBEMAIL="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v $V 'Plug Vitastor block driver'; \
|
DEBEMAIL="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v $V 'Plug Vitastor block driver'; \
|
||||||
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
|
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
|
||||||
rm -rf /root/packages/qemu-$REL/qemu-*/
|
rm -rf /root/packages/qemu-$REL/qemu-*/
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
# Build Vitastor packages for Debian Buster or Bullseye/Sid inside a container
|
# Build Vitastor packages for Debian inside a container
|
||||||
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/vitastor.Dockerfile .
|
# cd ..; podman build --build-arg REL=bullseye -v `pwd`/packages:/root/packages -f debian/vitastor.Dockerfile .
|
||||||
|
|
||||||
ARG REL=
|
ARG REL=
|
||||||
|
@ -15,11 +15,12 @@ RUN if [ "$REL" = "buster" -o "$REL" = "bullseye" ]; then \
|
||||||
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
echo 'Pin-Priority: 500' >> /etc/apt/preferences; \
|
||||||
fi; \
|
fi; \
|
||||||
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
grep '^deb ' /etc/apt/sources.list | perl -pe 's/^deb/deb-src/' >> /etc/apt/sources.list; \
|
||||||
|
perl -i -pe 's/Types: deb$/Types: deb deb-src/' /etc/apt/sources.list.d/debian.sources || true; \
|
||||||
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
|
echo 'APT::Install-Recommends false;' >> /etc/apt/apt.conf; \
|
||||||
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
echo 'APT::Install-Suggests false;' >> /etc/apt/apt.conf
|
||||||
|
|
||||||
RUN apt-get update
|
RUN apt-get update
|
||||||
RUN apt-get -y install fio liburing1 liburing-dev libgoogle-perftools-dev devscripts
|
RUN apt-get -y install fio liburing-dev libgoogle-perftools-dev devscripts
|
||||||
RUN apt-get -y build-dep fio
|
RUN apt-get -y build-dep fio
|
||||||
RUN apt-get --download-only source fio
|
RUN apt-get --download-only source fio
|
||||||
RUN apt-get update && apt-get -y install libjerasure-dev cmake libibverbs-dev libisal-dev
|
RUN apt-get update && apt-get -y install libjerasure-dev cmake libibverbs-dev libisal-dev
|
||||||
|
@ -34,8 +35,8 @@ RUN set -e -x; \
|
||||||
mkdir -p /root/packages/vitastor-$REL; \
|
mkdir -p /root/packages/vitastor-$REL; \
|
||||||
rm -rf /root/packages/vitastor-$REL/*; \
|
rm -rf /root/packages/vitastor-$REL/*; \
|
||||||
cd /root/packages/vitastor-$REL; \
|
cd /root/packages/vitastor-$REL; \
|
||||||
cp -r /root/vitastor vitastor-0.8.9; \
|
cp -r /root/vitastor vitastor-1.4.4; \
|
||||||
cd vitastor-0.8.9; \
|
cd vitastor-1.4.4; \
|
||||||
ln -s /root/fio-build/fio-*/ ./fio; \
|
ln -s /root/fio-build/fio-*/ ./fio; \
|
||||||
FIO=$(head -n1 fio/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
FIO=$(head -n1 fio/debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
||||||
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
ls /usr/include/linux/raw.h || cp ./debian/raw.h /usr/include/linux/raw.h; \
|
||||||
|
@ -48,8 +49,8 @@ RUN set -e -x; \
|
||||||
rm -rf a b; \
|
rm -rf a b; \
|
||||||
echo "dep:fio=$FIO" > debian/fio_version; \
|
echo "dep:fio=$FIO" > debian/fio_version; \
|
||||||
cd /root/packages/vitastor-$REL; \
|
cd /root/packages/vitastor-$REL; \
|
||||||
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_0.8.9.orig.tar.xz vitastor-0.8.9; \
|
tar --sort=name --mtime='2020-01-01' --owner=0 --group=0 --exclude=debian -cJf vitastor_1.4.4.orig.tar.xz vitastor-1.4.4; \
|
||||||
cd vitastor-0.8.9; \
|
cd vitastor-1.4.4; \
|
||||||
V=$(head -n1 debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
V=$(head -n1 debian/changelog | perl -pe 's/^.*\((.*?)\).*$/$1/'); \
|
||||||
DEBFULLNAME="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$V""$REL" "Rebuild for $REL"; \
|
DEBFULLNAME="Vitaliy Filippov <vitalif@yourcmc.ru>" dch -D $REL -v "$V""$REL" "Rebuild for $REL"; \
|
||||||
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
|
DEB_BUILD_OPTIONS=nocheck dpkg-buildpackage --jobs=auto -sa; \
|
||||||
|
|
|
@ -21,7 +21,7 @@ Configuration parameters can be set in 3 places:
|
||||||
mon, fio and QEMU options, OpenStack/Proxmox/etc configuration. The latter
|
mon, fio and QEMU options, OpenStack/Proxmox/etc configuration. The latter
|
||||||
doesn't allow to set all variables directly, but it allows to override the
|
doesn't allow to set all variables directly, but it allows to override the
|
||||||
configuration file and set everything you need inside it.
|
configuration file and set everything you need inside it.
|
||||||
- OSD superblocks created by [vitastor-disk](../usage/disk.en.md) contain
|
- OSD superblocks created by [vitastor-disk](usage/disk.en.md) contain
|
||||||
primarily disk layout parameters of specific OSDs. In fact, these parameters
|
primarily disk layout parameters of specific OSDs. In fact, these parameters
|
||||||
are automatically passed into the command line of vitastor-osd process, so
|
are automatically passed into the command line of vitastor-osd process, so
|
||||||
they have the same "status" as command-line parameters.
|
they have the same "status" as command-line parameters.
|
||||||
|
@ -33,6 +33,7 @@ In the future, additional configuration methods may be added:
|
||||||
|
|
||||||
- [Common](config/common.en.md)
|
- [Common](config/common.en.md)
|
||||||
- [Network](config/network.en.md)
|
- [Network](config/network.en.md)
|
||||||
|
- [Client](config/client.en.md)
|
||||||
- [Global Disk Layout](config/layout-cluster.en.md)
|
- [Global Disk Layout](config/layout-cluster.en.md)
|
||||||
- [OSD Disk Layout](config/layout-osd.en.md)
|
- [OSD Disk Layout](config/layout-osd.en.md)
|
||||||
- [OSD Runtime Parameters](config/osd.en.md)
|
- [OSD Runtime Parameters](config/osd.en.md)
|
||||||
|
|
|
@ -23,7 +23,7 @@
|
||||||
монитора, опциях fio и QEMU, настроек OpenStack, Proxmox и т.п. Последние,
|
монитора, опциях fio и QEMU, настроек OpenStack, Proxmox и т.п. Последние,
|
||||||
как правило, не включают полный набор параметров напрямую, но позволяют
|
как правило, не включают полный набор параметров напрямую, но позволяют
|
||||||
определить путь к файлу конфигурации и задать любые параметры в нём.
|
определить путь к файлу конфигурации и задать любые параметры в нём.
|
||||||
- В суперблоке OSD, записываемом [vitastor-disk](../usage/disk.ru.md) - параметры,
|
- В суперблоке OSD, записываемом [vitastor-disk](usage/disk.ru.md) - параметры,
|
||||||
связанные с дисковым форматом и с этим конкретным OSD. На самом деле,
|
связанные с дисковым форматом и с этим конкретным OSD. На самом деле,
|
||||||
при запуске OSD эти параметры автоматически передаются в командную строку
|
при запуске OSD эти параметры автоматически передаются в командную строку
|
||||||
процесса vitastor-osd, то есть по "статусу" они эквивалентны параметрам
|
процесса vitastor-osd, то есть по "статусу" они эквивалентны параметрам
|
||||||
|
@ -36,6 +36,7 @@
|
||||||
|
|
||||||
- [Общие](config/common.ru.md)
|
- [Общие](config/common.ru.md)
|
||||||
- [Сеть](config/network.ru.md)
|
- [Сеть](config/network.ru.md)
|
||||||
|
- [Клиентский код](config/client.ru.md)
|
||||||
- [Глобальные дисковые параметры](config/layout-cluster.ru.md)
|
- [Глобальные дисковые параметры](config/layout-cluster.ru.md)
|
||||||
- [Дисковые параметры OSD](config/layout-osd.ru.md)
|
- [Дисковые параметры OSD](config/layout-osd.ru.md)
|
||||||
- [Прочие параметры OSD](config/osd.ru.md)
|
- [Прочие параметры OSD](config/osd.ru.md)
|
||||||
|
|
|
@ -0,0 +1,137 @@
|
||||||
|
[Documentation](../../README.md#documentation) → [Configuration](../config.en.md) → Client Parameters
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
[Читать на русском](client.ru.md)
|
||||||
|
|
||||||
|
# Client Parameters
|
||||||
|
|
||||||
|
These parameters apply only to Vitastor clients (QEMU, fio, NBD and so on) and
|
||||||
|
affect their interaction with the cluster.
|
||||||
|
|
||||||
|
- [client_max_dirty_bytes](#client_max_dirty_bytes)
|
||||||
|
- [client_max_dirty_ops](#client_max_dirty_ops)
|
||||||
|
- [client_enable_writeback](#client_enable_writeback)
|
||||||
|
- [client_max_buffered_bytes](#client_max_buffered_bytes)
|
||||||
|
- [client_max_buffered_ops](#client_max_buffered_ops)
|
||||||
|
- [client_max_writeback_iodepth](#client_max_writeback_iodepth)
|
||||||
|
- [nbd_timeout](#nbd_timeout)
|
||||||
|
- [nbd_max_devices](#nbd_max_devices)
|
||||||
|
- [nbd_max_part](#nbd_max_part)
|
||||||
|
|
||||||
|
## client_max_dirty_bytes
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 33554432
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Without [immediate_commit](layout-cluster.en.md#immediate_commit)=all this parameter sets the limit of "dirty"
|
||||||
|
(not committed by fsync) data allowed by the client before forcing an
|
||||||
|
additional fsync and committing the data. Also note that the client always
|
||||||
|
holds a copy of uncommitted data in memory so this setting also affects
|
||||||
|
RAM usage of clients.
|
||||||
|
|
||||||
|
## client_max_dirty_ops
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 1024
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Same as client_max_dirty_bytes, but instead of total size, limits the number
|
||||||
|
of uncommitted write operations.
|
||||||
|
|
||||||
|
## client_enable_writeback
|
||||||
|
|
||||||
|
- Type: boolean
|
||||||
|
- Default: false
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
This parameter enables client-side write buffering. This means that write
|
||||||
|
requests are accumulated in memory for a short time before being sent to
|
||||||
|
a Vitastor cluster which allows to send them in parallel and increase
|
||||||
|
performance of some applications. Writes are buffered until client forces
|
||||||
|
a flush with fsync() or until the amount of buffered writes exceeds the
|
||||||
|
limit.
|
||||||
|
|
||||||
|
Write buffering significantly increases performance of some applications,
|
||||||
|
for example, CrystalDiskMark under Windows (LOL :-D), but also any other
|
||||||
|
applications if they do writes in one of two non-optimal ways: either if
|
||||||
|
they do a lot of small (4 kb or so) sequential writes, or if they do a lot
|
||||||
|
of small random writes, but without any parallelism or asynchrony, and also
|
||||||
|
without calling fsync().
|
||||||
|
|
||||||
|
With write buffering enabled, you can expect around 22000 T1Q1 random write
|
||||||
|
iops in QEMU more or less regardless of the quality of your SSDs, and this
|
||||||
|
number is in fact bound by QEMU itself rather than Vitastor (check it
|
||||||
|
yourself by adding a "driver=null-co" disk in QEMU). Without write
|
||||||
|
buffering, the current record is 9900 iops, but the number is usually
|
||||||
|
even lower with non-ideal hardware, for example, it may be 5000 iops.
|
||||||
|
|
||||||
|
Even when this parameter is enabled, write buffering isn't enabled until
|
||||||
|
the client explicitly allows it, because enabling it without the client
|
||||||
|
being aware of the fact that his writes may be buffered may lead to data
|
||||||
|
loss. Because of this, older versions of clients don't support write
|
||||||
|
buffering at all, newer versions of the QEMU driver allow write buffering
|
||||||
|
only if it's enabled in disk settings with `-blockdev cache.direct=false`,
|
||||||
|
and newer versions of FIO only allow write buffering if you don't specify
|
||||||
|
`-direct=1`. NBD and NFS drivers allow write buffering by default.
|
||||||
|
|
||||||
|
You can overcome this restriction too with the `client_writeback_allowed`
|
||||||
|
parameter, but you shouldn't do that unless you **really** know what you
|
||||||
|
are doing.
|
||||||
|
|
||||||
|
## client_max_buffered_bytes
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 33554432
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Maximum total size of buffered writes which triggers write-back when reached.
|
||||||
|
|
||||||
|
## client_max_buffered_ops
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 1024
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Maximum number of buffered writes which triggers write-back when reached.
|
||||||
|
Multiple consecutive modified data regions are counted as 1 write here.
|
||||||
|
|
||||||
|
## client_max_writeback_iodepth
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 256
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Maximum number of parallel writes when flushing buffered data to the server.
|
||||||
|
|
||||||
|
## nbd_timeout
|
||||||
|
|
||||||
|
- Type: seconds
|
||||||
|
- Default: 300
|
||||||
|
|
||||||
|
Timeout for I/O operations for [NBD](../usage/nbd.en.md). If an operation
|
||||||
|
executes for longer than this timeout, including when your cluster is just
|
||||||
|
temporarily down for more than timeout, the NBD device will detach by itself
|
||||||
|
(and possibly break the mounted file system).
|
||||||
|
|
||||||
|
You can set timeout to 0 to never detach, but in that case you won't be
|
||||||
|
able to remove the kernel device at all if the NBD process dies - you'll have
|
||||||
|
to reboot the host.
|
||||||
|
|
||||||
|
## nbd_max_devices
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 64
|
||||||
|
|
||||||
|
Maximum number of NBD devices in the system. This value is passed as
|
||||||
|
`nbds_max` parameter for the nbd kernel module when vitastor-nbd autoloads it.
|
||||||
|
|
||||||
|
## nbd_max_part
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 3
|
||||||
|
|
||||||
|
Maximum number of partitions per NBD device. This value is passed as
|
||||||
|
`max_part` parameter for the nbd kernel module when vitastor-nbd autoloads it.
|
||||||
|
Note that (nbds_max)*(1+max_part) usually can't exceed 256.
|
|
@ -0,0 +1,137 @@
|
||||||
|
[Документация](../../README-ru.md#документация) → [Конфигурация](../config.ru.md) → Параметры клиентского кода
|
||||||
|
|
||||||
|
-----
|
||||||
|
|
||||||
|
[Read in English](client.en.md)
|
||||||
|
|
||||||
|
# Параметры клиентского кода
|
||||||
|
|
||||||
|
Данные параметры применяются только к клиентам Vitastor (QEMU, fio, NBD и т.п.) и
|
||||||
|
затрагивают логику их работы с кластером.
|
||||||
|
|
||||||
|
- [client_max_dirty_bytes](#client_max_dirty_bytes)
|
||||||
|
- [client_max_dirty_ops](#client_max_dirty_ops)
|
||||||
|
- [client_enable_writeback](#client_enable_writeback)
|
||||||
|
- [client_max_buffered_bytes](#client_max_buffered_bytes)
|
||||||
|
- [client_max_buffered_ops](#client_max_buffered_ops)
|
||||||
|
- [client_max_writeback_iodepth](#client_max_writeback_iodepth)
|
||||||
|
- [nbd_timeout](#nbd_timeout)
|
||||||
|
- [nbd_max_devices](#nbd_max_devices)
|
||||||
|
- [nbd_max_part](#nbd_max_part)
|
||||||
|
|
||||||
|
## client_max_dirty_bytes
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 33554432
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
При работе без [immediate_commit](layout-cluster.ru.md#immediate_commit)=all - это лимит объёма "грязных" (не
|
||||||
|
зафиксированных fsync-ом) данных, при достижении которого клиент будет
|
||||||
|
принудительно вызывать fsync и фиксировать данные. Также стоит иметь в виду,
|
||||||
|
что в этом случае до момента fsync клиент хранит копию незафиксированных
|
||||||
|
данных в памяти, то есть, настройка влияет на потребление памяти клиентами.
|
||||||
|
|
||||||
|
## client_max_dirty_ops
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 1024
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Аналогично client_max_dirty_bytes, но ограничивает количество
|
||||||
|
незафиксированных операций записи вместо их общего объёма.
|
||||||
|
|
||||||
|
## client_enable_writeback
|
||||||
|
|
||||||
|
- Тип: булево (да/нет)
|
||||||
|
- Значение по умолчанию: false
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Данный параметр разрешает включать буферизацию записи в памяти. Буферизация
|
||||||
|
означает, что операции записи отправляются на кластер Vitastor не сразу, а
|
||||||
|
могут небольшое время накапливаться в памяти и сбрасываться сразу пакетами,
|
||||||
|
до тех пор, пока либо не будет превышен лимит неотправленных записей, либо
|
||||||
|
пока клиент не вызовет fsync.
|
||||||
|
|
||||||
|
Буферизация значительно повышает производительность некоторых приложений,
|
||||||
|
например, CrystalDiskMark в Windows (ха-ха :-D), но также и любых других,
|
||||||
|
которые пишут на диск неоптимально: либо последовательно, но мелкими блоками
|
||||||
|
(например, по 4 кб), либо случайно, но без параллелизма и без fsync - то
|
||||||
|
есть, например, отправляя 128 операций записи в разные места диска, но не
|
||||||
|
все сразу с помощью асинхронного I/O, а по одной.
|
||||||
|
|
||||||
|
В QEMU с буферизацией записи можно ожидать показателя примерно 22000
|
||||||
|
операций случайной записи в секунду в 1 поток и с глубиной очереди 1 (T1Q1)
|
||||||
|
без fsync, почти вне зависимости от того, насколько хороши ваши диски - эта
|
||||||
|
цифра упирается в сам QEMU. Без буферизации рекорд пока что - 9900 операций
|
||||||
|
в секунду, но на железе похуже может быть и поменьше, например, 5000 операций
|
||||||
|
в секунду.
|
||||||
|
|
||||||
|
При этом, даже если данный параметр включён, буферизация не включается, если
|
||||||
|
явно не разрешена клиентом, т.к. если клиент не знает, что запросы записи
|
||||||
|
буферизуются, это может приводить к потере данных. Поэтому в старых версиях
|
||||||
|
клиентских драйверов буферизация записи не включается вообще, в новых
|
||||||
|
версиях QEMU-драйвера включается, только если разрешена опцией диска
|
||||||
|
`-blockdev cache.direct=false`, а в fio - только если нет опции `-direct=1`.
|
||||||
|
В NBD и NFS драйверах буферизация записи разрешена по умолчанию.
|
||||||
|
|
||||||
|
Можно обойти и это ограничение с помощью параметра `client_writeback_allowed`,
|
||||||
|
но делать так не надо, если только вы не уверены в том, что делаете, на все
|
||||||
|
100%. :-)
|
||||||
|
|
||||||
|
## client_max_buffered_bytes
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 33554432
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Максимальный общий размер буферизованных записей, при достижении которого
|
||||||
|
начинается процесс сброса данных на сервер.
|
||||||
|
|
||||||
|
## client_max_buffered_ops
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 1024
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Максимальное количество буферизованных записей, при достижении которого
|
||||||
|
начинается процесс сброса данных на сервер. При этом несколько
|
||||||
|
последовательных изменённых областей здесь считаются 1 записью.
|
||||||
|
|
||||||
|
## client_max_writeback_iodepth
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 256
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Максимальное число параллельных операций записи при сбросе буферов на сервер.
|
||||||
|
|
||||||
|
## nbd_timeout
|
||||||
|
|
||||||
|
- Тип: секунды
|
||||||
|
- Значение по умолчанию: 300
|
||||||
|
|
||||||
|
Таймаут для операций чтения/записи через [NBD](../usage/nbd.ru.md). Если
|
||||||
|
операция выполняется дольше таймаута, включая временную недоступность
|
||||||
|
кластера на время, большее таймаута, NBD-устройство отключится само собой
|
||||||
|
(и, возможно, сломает примонтированную ФС).
|
||||||
|
|
||||||
|
Вы можете установить таймаут в 0, чтобы никогда не отключать устройство по
|
||||||
|
таймауту, но в этом случае вы вообще не сможете удалить устройство, если
|
||||||
|
процесс NBD умрёт - вам придётся перезагружать сервер.
|
||||||
|
|
||||||
|
## nbd_max_devices
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 64
|
||||||
|
|
||||||
|
Максимальное число NBD-устройств в системе. Данное значение передаётся
|
||||||
|
модулю ядра nbd как параметр `nbds_max`, когда его загружает vitastor-nbd.
|
||||||
|
|
||||||
|
## nbd_max_part
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 3
|
||||||
|
|
||||||
|
Максимальное число разделов на одном NBD-устройстве. Данное значение передаётся
|
||||||
|
модулю ядра nbd как параметр `max_part`, когда его загружает vitastor-nbd.
|
||||||
|
Имейте в виду, что (nbds_max)*(1+max_part) обычно не может превышать 256.
|
|
@ -25,11 +25,16 @@ running if required parameters are specified.
|
||||||
## etcd_address
|
## etcd_address
|
||||||
|
|
||||||
- Type: string or array of strings
|
- Type: string or array of strings
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
etcd connection endpoint(s). Multiple endpoints may be delimited by "," or
|
etcd connection endpoint(s). Multiple endpoints may be delimited by "," or
|
||||||
specified in a JSON array `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
specified in a JSON array `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
||||||
Note that https is not supported for etcd connections yet.
|
Note that https is not supported for etcd connections yet.
|
||||||
|
|
||||||
|
etcd connection endpoints can be changed online by updating global
|
||||||
|
configuration in etcd itself - this allows to switch the cluster to new
|
||||||
|
etcd addresses without downtime.
|
||||||
|
|
||||||
## etcd_prefix
|
## etcd_prefix
|
||||||
|
|
||||||
- Type: string
|
- Type: string
|
||||||
|
@ -42,5 +47,6 @@ example, use a single etcd cluster for multiple Vitastor clusters.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 0
|
- Default: 0
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Log level. Raise if you want more verbose output.
|
Log level. Raise if you want more verbose output.
|
||||||
|
|
|
@ -24,10 +24,14 @@
|
||||||
## etcd_address
|
## etcd_address
|
||||||
|
|
||||||
- Тип: строка или массив строк
|
- Тип: строка или массив строк
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Адрес(а) подключения к etcd. Несколько адресов могут разделяться запятой
|
Адрес(а) подключения к etcd. Несколько адресов могут разделяться запятой
|
||||||
или указываться в виде JSON-массива `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
или указываться в виде JSON-массива `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
||||||
|
|
||||||
|
Адреса подключения к etcd можно поменять на лету, обновив конфигурацию в
|
||||||
|
самом etcd - это позволяет переключить кластер на новые etcd без остановки.
|
||||||
|
|
||||||
## etcd_prefix
|
## etcd_prefix
|
||||||
|
|
||||||
- Тип: строка
|
- Тип: строка
|
||||||
|
@ -41,5 +45,6 @@
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 0
|
- Значение по умолчанию: 0
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Уровень логгирования. Повысьте, если хотите более подробный вывод.
|
Уровень логгирования. Повысьте, если хотите более подробный вывод.
|
||||||
|
|
|
@ -33,12 +33,13 @@ Size of objects (data blocks) into which all physical and virtual drives
|
||||||
in Vitastor, affects memory usage, write amplification and I/O load
|
in Vitastor, affects memory usage, write amplification and I/O load
|
||||||
distribution effectiveness.
|
distribution effectiveness.
|
||||||
|
|
||||||
Recommended default block size is 128 KB for SSD and 4 MB for HDD. In fact,
|
Recommended default block size is 128 KB for SSD and 1 MB for HDD. In fact,
|
||||||
it's possible to use 4 MB for SSD too - it will lower memory usage, but
|
it's possible to use 1 MB for SSD too - it will lower memory usage, but
|
||||||
may increase average WA and reduce linear performance.
|
may increase average WA and reduce linear performance.
|
||||||
|
|
||||||
OSD memory usage is roughly (SIZE / BLOCK * 68 bytes) which is roughly
|
OSD memory usage is roughly (SIZE / BLOCK * 68 bytes) which is roughly
|
||||||
544 MB per 1 TB of used disk space with the default 128 KB block size.
|
544 MB per 1 TB of used disk space with the default 128 KB block size.
|
||||||
|
With 1 MB it's 8 times lower.
|
||||||
|
|
||||||
## bitmap_granularity
|
## bitmap_granularity
|
||||||
|
|
||||||
|
@ -95,8 +96,9 @@ SSD cache or "media-cache" - for example, a lot of Seagate EXOS drives have
|
||||||
it (they have internal SSD cache even though it's not stated in datasheets).
|
it (they have internal SSD cache even though it's not stated in datasheets).
|
||||||
|
|
||||||
Setting this parameter to "all" or "small" in OSD parameters requires enabling
|
Setting this parameter to "all" or "small" in OSD parameters requires enabling
|
||||||
disable_journal_fsync and disable_meta_fsync, setting it to "all" also requires
|
[disable_journal_fsync](layout-osd.en.yml#disable_journal_fsync) and
|
||||||
enabling disable_data_fsync.
|
[disable_meta_fsync](layout-osd.en.yml#disable_meta_fsync), setting it to
|
||||||
|
"all" also requires enabling [disable_data_fsync](layout-osd.en.yml#disable_data_fsync).
|
||||||
|
|
||||||
TLDR: For optimal performance, set immediate_commit to "all" if you only use
|
TLDR: For optimal performance, set immediate_commit to "all" if you only use
|
||||||
SSDs with supercapacitor-based power loss protection (nonvolatile
|
SSDs with supercapacitor-based power loss protection (nonvolatile
|
||||||
|
|
|
@ -33,14 +33,14 @@ OSD) могут сосуществовать в одном кластере Vita
|
||||||
настроек, влияет на потребление памяти, объём избыточной записи (write
|
настроек, влияет на потребление памяти, объём избыточной записи (write
|
||||||
amplification) и эффективность распределения нагрузки по OSD.
|
amplification) и эффективность распределения нагрузки по OSD.
|
||||||
|
|
||||||
Рекомендуемые по умолчанию размеры блока - 128 килобайт для SSD и 4
|
Рекомендуемые по умолчанию размеры блока - 128 килобайт для SSD и 1 мегабайт
|
||||||
мегабайта для HDD. В принципе, для SSD можно тоже использовать 4 мегабайта,
|
для HDD. В принципе, для SSD можно тоже использовать блок размером 1 мегабайт,
|
||||||
это понизит использование памяти, но ухудшит распределение нагрузки и в
|
это понизит использование памяти, но ухудшит распределение нагрузки и в
|
||||||
среднем увеличит WA.
|
среднем увеличит WA.
|
||||||
|
|
||||||
Потребление памяти OSD составляет примерно (РАЗМЕР / БЛОК * 68 байт),
|
Потребление памяти OSD составляет примерно (РАЗМЕР / БЛОК * 68 байт),
|
||||||
т.е. примерно 544 МБ памяти на 1 ТБ занятого места на диске при
|
т.е. примерно 544 МБ памяти на 1 ТБ занятого места на диске при
|
||||||
стандартном 128 КБ блоке.
|
стандартном 128 КБ блоке. При 1 МБ блоке памяти нужно в 8 раз меньше.
|
||||||
|
|
||||||
## bitmap_granularity
|
## bitmap_granularity
|
||||||
|
|
||||||
|
@ -103,8 +103,9 @@ HDD-дисках с внутренним SSD или "медиа" кэшем - н
|
||||||
указано в спецификациях).
|
указано в спецификациях).
|
||||||
|
|
||||||
Указание "all" или "small" в настройках / командной строке OSD требует
|
Указание "all" или "small" в настройках / командной строке OSD требует
|
||||||
включения disable_journal_fsync и disable_meta_fsync, значение "all" также
|
включения [disable_journal_fsync](layout-osd.ru.yml#disable_journal_fsync) и
|
||||||
требует включения disable_data_fsync.
|
[disable_meta_fsync](layout-osd.ru.yml#disable_meta_fsync), значение "all"
|
||||||
|
также требует включения [disable_data_fsync](layout-osd.ru.yml#disable_data_fsync).
|
||||||
|
|
||||||
Итого, вкратце: для оптимальной производительности установите
|
Итого, вкратце: для оптимальной производительности установите
|
||||||
immediate_commit в значение "all", если вы используете в кластере только SSD
|
immediate_commit в значение "all", если вы используете в кластере только SSD
|
||||||
|
|
|
@ -24,6 +24,8 @@ initialization and can't be changed after it without losing data.
|
||||||
- [disable_journal_fsync](#disable_journal_fsync)
|
- [disable_journal_fsync](#disable_journal_fsync)
|
||||||
- [disable_device_lock](#disable_device_lock)
|
- [disable_device_lock](#disable_device_lock)
|
||||||
- [disk_alignment](#disk_alignment)
|
- [disk_alignment](#disk_alignment)
|
||||||
|
- [data_csum_type](#data_csum_type)
|
||||||
|
- [csum_block_size](#csum_block_size)
|
||||||
|
|
||||||
## data_device
|
## data_device
|
||||||
|
|
||||||
|
@ -174,3 +176,43 @@ Intel Optane (probably, not tested yet).
|
||||||
|
|
||||||
Clients don't need to be aware of disk_alignment, so it's not required to
|
Clients don't need to be aware of disk_alignment, so it's not required to
|
||||||
put a modified value into etcd key /vitastor/config/global.
|
put a modified value into etcd key /vitastor/config/global.
|
||||||
|
|
||||||
|
## data_csum_type
|
||||||
|
|
||||||
|
- Type: string
|
||||||
|
- Default: none
|
||||||
|
|
||||||
|
Data checksum type to use. May be "crc32c" or "none". Set to "crc32c" to
|
||||||
|
enable data checksums.
|
||||||
|
|
||||||
|
## csum_block_size
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 4096
|
||||||
|
|
||||||
|
Checksum calculation block size.
|
||||||
|
|
||||||
|
Must be equal or a multiple of [bitmap_granularity](layout-cluster.en.md#bitmap_granularity)
|
||||||
|
(which is usually 4 KB).
|
||||||
|
|
||||||
|
Checksums increase metadata size by 4 bytes per each csum_block_size of data.
|
||||||
|
|
||||||
|
Checksums are always a tradeoff:
|
||||||
|
1. You either sacrifice +1 GB RAM per 1 TB of data
|
||||||
|
2. Or you raise csum_block_size, for example, to 32k and sacrifice
|
||||||
|
50% random write iops due to checksum read-modify-write
|
||||||
|
3. Or you turn off [inmemory_metadata](osd.en.md#inmemory_metadata) and
|
||||||
|
sacrifice 50% random read iops due to checksum reads
|
||||||
|
|
||||||
|
All-flash clusters usually have enough RAM to use default csum_block_size,
|
||||||
|
which uses 1 GB RAM per 1 TB of data. HDD clusters usually don't.
|
||||||
|
|
||||||
|
Thus, recommended setups are:
|
||||||
|
1. All-flash, 1 GB RAM per 1 TB data: default (csum_block_size=4k)
|
||||||
|
2. All-flash, less RAM: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
3. Hybrid HDD+SSD: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
4. HDD-only, faster random read: csum_block_size=32k
|
||||||
|
5. HDD-only, faster random write: csum_block_size=4k +
|
||||||
|
inmemory_metadata=false + meta_io=cached
|
||||||
|
|
||||||
|
See also [meta_io](osd.en.md#meta_io).
|
||||||
|
|
|
@ -25,6 +25,8 @@
|
||||||
- [disable_journal_fsync](#disable_journal_fsync)
|
- [disable_journal_fsync](#disable_journal_fsync)
|
||||||
- [disable_device_lock](#disable_device_lock)
|
- [disable_device_lock](#disable_device_lock)
|
||||||
- [disk_alignment](#disk_alignment)
|
- [disk_alignment](#disk_alignment)
|
||||||
|
- [data_csum_type](#data_csum_type)
|
||||||
|
- [csum_block_size](#csum_block_size)
|
||||||
|
|
||||||
## data_device
|
## data_device
|
||||||
|
|
||||||
|
@ -183,3 +185,47 @@ journal_block_size и meta_block_size. Однако единственные SSD
|
||||||
|
|
||||||
Клиентам не обязательно знать про disk_alignment, так что помещать значение
|
Клиентам не обязательно знать про disk_alignment, так что помещать значение
|
||||||
этого параметра в etcd в /vitastor/config/global не нужно.
|
этого параметра в etcd в /vitastor/config/global не нужно.
|
||||||
|
|
||||||
|
## data_csum_type
|
||||||
|
|
||||||
|
- Тип: строка
|
||||||
|
- Значение по умолчанию: none
|
||||||
|
|
||||||
|
Тип используемых OSD контрольных сумм данных. Может быть "crc32c" или "none".
|
||||||
|
Установите в "crc32c", чтобы включить расчёт и проверку контрольных сумм данных.
|
||||||
|
|
||||||
|
Следует понимать, что контрольные суммы в зависимости от размера блока их
|
||||||
|
расчёта либо увеличивают потребление памяти, либо снижают производительность.
|
||||||
|
Подробнее смотрите в описании параметра [csum_block_size](#csum_block_size).
|
||||||
|
|
||||||
|
## csum_block_size
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 4096
|
||||||
|
|
||||||
|
Размер блока расчёта контрольных сумм.
|
||||||
|
|
||||||
|
Должен быть равен или кратен [bitmap_granularity](layout-cluster.ru.md#bitmap_granularity)
|
||||||
|
(который обычно равен 4 КБ).
|
||||||
|
|
||||||
|
Контрольные суммы увеличивают размер метаданных на 4 байта на каждые
|
||||||
|
csum_block_size данных.
|
||||||
|
|
||||||
|
Контрольные суммы - это всегда компромисс:
|
||||||
|
1. Вы либо жертвуете потреблением +1 ГБ памяти на 1 ТБ дискового пространства
|
||||||
|
2. Либо вы повышаете csum_block_size до, скажем, 32k и жертвуете 50%
|
||||||
|
скорости случайной записи из-за цикла чтения-изменения-записи для расчёта
|
||||||
|
новых контрольных сумм
|
||||||
|
3. Либо вы отключаете [inmemory_metadata](osd.ru.md#inmemory_metadata) и
|
||||||
|
жертвуете 50% скорости случайного чтения из-за чтения контрольных сумм
|
||||||
|
с диска
|
||||||
|
|
||||||
|
Таким образом, рекомендуются следующие варианты настроек:
|
||||||
|
1. All-flash, 1 ГБ памяти на 1 ТБ данных: по умолчанию (csum_block_size=4k)
|
||||||
|
2. All-flash, меньше памяти: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
3. Гибридные HDD+SSD: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
4. Только HDD, быстрее случайное чтение: csum_block_size=32k
|
||||||
|
5. Только HDD, быстрее случайная запись: csum_block_size=4k +
|
||||||
|
inmemory_metadata=false + meta_io=cached
|
||||||
|
|
||||||
|
Смотрите также [meta_io](osd.ru.md#meta_io).
|
||||||
|
|
|
@ -19,8 +19,8 @@ These parameters only apply to Monitors.
|
||||||
## etcd_mon_ttl
|
## etcd_mon_ttl
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 30
|
- Default: 1
|
||||||
- Minimum: 10
|
- Minimum: 5
|
||||||
|
|
||||||
Monitor etcd lease refresh interval in seconds
|
Monitor etcd lease refresh interval in seconds
|
||||||
|
|
||||||
|
|
|
@ -19,8 +19,8 @@
|
||||||
## etcd_mon_ttl
|
## etcd_mon_ttl
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 30
|
- Значение по умолчанию: 1
|
||||||
- Минимальное значение: 10
|
- Минимальное значение: 5
|
||||||
|
|
||||||
Интервал обновления etcd резервации (lease) монитором
|
Интервал обновления etcd резервации (lease) монитором
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ between clients, OSDs and etcd.
|
||||||
- [rdma_max_msg](#rdma_max_msg)
|
- [rdma_max_msg](#rdma_max_msg)
|
||||||
- [rdma_max_recv](#rdma_max_recv)
|
- [rdma_max_recv](#rdma_max_recv)
|
||||||
- [rdma_max_send](#rdma_max_send)
|
- [rdma_max_send](#rdma_max_send)
|
||||||
|
- [rdma_odp](#rdma_odp)
|
||||||
- [peer_connect_interval](#peer_connect_interval)
|
- [peer_connect_interval](#peer_connect_interval)
|
||||||
- [peer_connect_timeout](#peer_connect_timeout)
|
- [peer_connect_timeout](#peer_connect_timeout)
|
||||||
- [osd_idle_timeout](#osd_idle_timeout)
|
- [osd_idle_timeout](#osd_idle_timeout)
|
||||||
|
@ -30,7 +31,6 @@ between clients, OSDs and etcd.
|
||||||
- [etcd_slow_timeout](#etcd_slow_timeout)
|
- [etcd_slow_timeout](#etcd_slow_timeout)
|
||||||
- [etcd_keepalive_timeout](#etcd_keepalive_timeout)
|
- [etcd_keepalive_timeout](#etcd_keepalive_timeout)
|
||||||
- [etcd_ws_keepalive_timeout](#etcd_ws_keepalive_timeout)
|
- [etcd_ws_keepalive_timeout](#etcd_ws_keepalive_timeout)
|
||||||
- [client_dirty_limit](#client_dirty_limit)
|
|
||||||
|
|
||||||
## tcp_header_buffer_size
|
## tcp_header_buffer_size
|
||||||
|
|
||||||
|
@ -69,11 +69,14 @@ but they are not connected to the cluster.
|
||||||
- Type: string
|
- Type: string
|
||||||
|
|
||||||
RDMA device name to use for Vitastor OSD communications (for example,
|
RDMA device name to use for Vitastor OSD communications (for example,
|
||||||
"rocep5s0f0"). Please note that Vitastor RDMA requires Implicit On-Demand
|
"rocep5s0f0"). Now Vitastor supports all adapters, even ones without
|
||||||
Paging (Implicit ODP) and Scatter/Gather (SG) support from the RDMA device
|
ODP support, like Mellanox ConnectX-3 and non-Mellanox cards.
|
||||||
to work. For example, Mellanox ConnectX-3 and older adapters don't have
|
|
||||||
Implicit ODP, so they're unsupported by Vitastor. Run `ibv_devinfo -v` as
|
Versions up to Vitastor 1.2.0 required ODP which is only present in
|
||||||
root to list available RDMA devices and their features.
|
Mellanox ConnectX >= 4. See also [rdma_odp](#rdma_odp).
|
||||||
|
|
||||||
|
Run `ibv_devinfo -v` as root to list available RDMA devices and their
|
||||||
|
features.
|
||||||
|
|
||||||
Remember that you also have to configure your network switches if you use
|
Remember that you also have to configure your network switches if you use
|
||||||
RoCE/RoCEv2, otherwise you may experience unstable performance. Refer to
|
RoCE/RoCEv2, otherwise you may experience unstable performance. Refer to
|
||||||
|
@ -148,11 +151,34 @@ less than `rdma_max_recv` so the receiving side doesn't run out of buffers.
|
||||||
Doesn't affect memory usage - additional memory isn't allocated for send
|
Doesn't affect memory usage - additional memory isn't allocated for send
|
||||||
operations.
|
operations.
|
||||||
|
|
||||||
|
## rdma_odp
|
||||||
|
|
||||||
|
- Type: boolean
|
||||||
|
- Default: false
|
||||||
|
|
||||||
|
Use RDMA with On-Demand Paging. ODP is currently only available on Mellanox
|
||||||
|
ConnectX-4 and newer adapters. ODP allows to not register memory explicitly
|
||||||
|
for RDMA adapter to be able to use it. This, in turn, allows to skip memory
|
||||||
|
copying during sending. One would think this should improve performance, but
|
||||||
|
**in reality** RDMA performance with ODP is **drastically** worse. Example
|
||||||
|
3-node cluster with 8 NVMe in each node and 2*25 GBit/s ConnectX-6 RDMA network
|
||||||
|
without ODP pushes 3950000 read iops, but only 239000 iops with ODP...
|
||||||
|
|
||||||
|
This happens because Mellanox ODP implementation seems to be based on
|
||||||
|
message retransmissions when the adapter doesn't know about the buffer yet -
|
||||||
|
it likely uses standard "RNR retransmissions" (RNR = receiver not ready)
|
||||||
|
which is generally slow in RDMA/RoCE networks. Here's a presentation about
|
||||||
|
it from ISPASS-2021 conference: https://tkygtr6.github.io/pub/ISPASS21_slides.pdf
|
||||||
|
|
||||||
|
ODP support is retained in the code just in case a good ODP implementation
|
||||||
|
appears one day.
|
||||||
|
|
||||||
## peer_connect_interval
|
## peer_connect_interval
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 5
|
- Default: 5
|
||||||
- Minimum: 1
|
- Minimum: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Interval before attempting to reconnect to an unavailable OSD.
|
Interval before attempting to reconnect to an unavailable OSD.
|
||||||
|
|
||||||
|
@ -161,6 +187,7 @@ Interval before attempting to reconnect to an unavailable OSD.
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 5
|
- Default: 5
|
||||||
- Minimum: 1
|
- Minimum: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Timeout for OSD connection attempts.
|
Timeout for OSD connection attempts.
|
||||||
|
|
||||||
|
@ -169,6 +196,7 @@ Timeout for OSD connection attempts.
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 5
|
- Default: 5
|
||||||
- Minimum: 1
|
- Minimum: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
OSD connection inactivity time after which clients and other OSDs send
|
OSD connection inactivity time after which clients and other OSDs send
|
||||||
keepalive requests to check state of the connection.
|
keepalive requests to check state of the connection.
|
||||||
|
@ -178,6 +206,7 @@ keepalive requests to check state of the connection.
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 5
|
- Default: 5
|
||||||
- Minimum: 1
|
- Minimum: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Maximum time to wait for OSD keepalive responses. If an OSD doesn't respond
|
Maximum time to wait for OSD keepalive responses. If an OSD doesn't respond
|
||||||
within this time, the connection to it is dropped and a reconnection attempt
|
within this time, the connection to it is dropped and a reconnection attempt
|
||||||
|
@ -186,8 +215,9 @@ is scheduled.
|
||||||
## up_wait_retry_interval
|
## up_wait_retry_interval
|
||||||
|
|
||||||
- Type: milliseconds
|
- Type: milliseconds
|
||||||
- Default: 500
|
- Default: 50
|
||||||
- Minimum: 50
|
- Minimum: 10
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
OSDs respond to clients with a special error code when they receive I/O
|
OSDs respond to clients with a special error code when they receive I/O
|
||||||
requests for a PG that's not synchronized and started. This parameter sets
|
requests for a PG that's not synchronized and started. This parameter sets
|
||||||
|
@ -197,6 +227,7 @@ the time for the clients to wait before re-attempting such I/O requests.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 5
|
- Default: 5
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Maximum number of attempts for etcd requests which can't be retried
|
Maximum number of attempts for etcd requests which can't be retried
|
||||||
indefinitely.
|
indefinitely.
|
||||||
|
@ -205,6 +236,7 @@ indefinitely.
|
||||||
|
|
||||||
- Type: milliseconds
|
- Type: milliseconds
|
||||||
- Default: 1000
|
- Default: 1000
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Timeout for etcd requests which should complete quickly, like lease refresh.
|
Timeout for etcd requests which should complete quickly, like lease refresh.
|
||||||
|
|
||||||
|
@ -212,6 +244,7 @@ Timeout for etcd requests which should complete quickly, like lease refresh.
|
||||||
|
|
||||||
- Type: milliseconds
|
- Type: milliseconds
|
||||||
- Default: 5000
|
- Default: 5000
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Timeout for etcd requests which are allowed to wait for some time.
|
Timeout for etcd requests which are allowed to wait for some time.
|
||||||
|
|
||||||
|
@ -219,6 +252,7 @@ Timeout for etcd requests which are allowed to wait for some time.
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: max(30, etcd_report_interval*2)
|
- Default: max(30, etcd_report_interval*2)
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Timeout for etcd connection HTTP Keep-Alive. Should be higher than
|
Timeout for etcd connection HTTP Keep-Alive. Should be higher than
|
||||||
etcd_report_interval to guarantee that keepalive actually works.
|
etcd_report_interval to guarantee that keepalive actually works.
|
||||||
|
@ -227,19 +261,7 @@ etcd_report_interval to guarantee that keepalive actually works.
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 30
|
- Default: 30
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
etcd websocket ping interval required to keep the connection alive and
|
etcd websocket ping interval required to keep the connection alive and
|
||||||
detect disconnections quickly.
|
detect disconnections quickly.
|
||||||
|
|
||||||
## client_dirty_limit
|
|
||||||
|
|
||||||
- Type: integer
|
|
||||||
- Default: 33554432
|
|
||||||
|
|
||||||
Without immediate_commit=all this parameter sets the limit of "dirty"
|
|
||||||
(not committed by fsync) data allowed by the client before forcing an
|
|
||||||
additional fsync and committing the data. Also note that the client always
|
|
||||||
holds a copy of uncommitted data in memory so this setting also affects
|
|
||||||
RAM usage of clients.
|
|
||||||
|
|
||||||
This parameter doesn't affect OSDs themselves.
|
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
- [rdma_max_msg](#rdma_max_msg)
|
- [rdma_max_msg](#rdma_max_msg)
|
||||||
- [rdma_max_recv](#rdma_max_recv)
|
- [rdma_max_recv](#rdma_max_recv)
|
||||||
- [rdma_max_send](#rdma_max_send)
|
- [rdma_max_send](#rdma_max_send)
|
||||||
|
- [rdma_odp](#rdma_odp)
|
||||||
- [peer_connect_interval](#peer_connect_interval)
|
- [peer_connect_interval](#peer_connect_interval)
|
||||||
- [peer_connect_timeout](#peer_connect_timeout)
|
- [peer_connect_timeout](#peer_connect_timeout)
|
||||||
- [osd_idle_timeout](#osd_idle_timeout)
|
- [osd_idle_timeout](#osd_idle_timeout)
|
||||||
|
@ -30,7 +31,6 @@
|
||||||
- [etcd_slow_timeout](#etcd_slow_timeout)
|
- [etcd_slow_timeout](#etcd_slow_timeout)
|
||||||
- [etcd_keepalive_timeout](#etcd_keepalive_timeout)
|
- [etcd_keepalive_timeout](#etcd_keepalive_timeout)
|
||||||
- [etcd_ws_keepalive_timeout](#etcd_ws_keepalive_timeout)
|
- [etcd_ws_keepalive_timeout](#etcd_ws_keepalive_timeout)
|
||||||
- [client_dirty_limit](#client_dirty_limit)
|
|
||||||
|
|
||||||
## tcp_header_buffer_size
|
## tcp_header_buffer_size
|
||||||
|
|
||||||
|
@ -72,12 +72,15 @@ RDMA может быть нужно только если у клиентов е
|
||||||
- Тип: строка
|
- Тип: строка
|
||||||
|
|
||||||
Название RDMA-устройства для связи с Vitastor OSD (например, "rocep5s0f0").
|
Название RDMA-устройства для связи с Vitastor OSD (например, "rocep5s0f0").
|
||||||
Имейте в виду, что поддержка RDMA в Vitastor требует функций устройства
|
Сейчас Vitastor поддерживает все модели адаптеров, включая те, у которых
|
||||||
Implicit On-Demand Paging (Implicit ODP) и Scatter/Gather (SG). Например,
|
нет поддержки ODP, то есть вы можете использовать RDMA с ConnectX-3 и
|
||||||
адаптеры Mellanox ConnectX-3 и более старые не поддерживают Implicit ODP и
|
картами производства не Mellanox.
|
||||||
потому не поддерживаются в Vitastor. Запустите `ibv_devinfo -v` от имени
|
|
||||||
суперпользователя, чтобы посмотреть список доступных RDMA-устройств, их
|
Версии Vitastor до 1.2.0 включительно требовали ODP, который есть только
|
||||||
параметры и возможности.
|
на Mellanox ConnectX 4 и более новых. См. также [rdma_odp](#rdma_odp).
|
||||||
|
|
||||||
|
Запустите `ibv_devinfo -v` от имени суперпользователя, чтобы посмотреть
|
||||||
|
список доступных RDMA-устройств, их параметры и возможности.
|
||||||
|
|
||||||
Обратите внимание, что если вы используете RoCE/RoCEv2, вам также необходимо
|
Обратите внимание, что если вы используете RoCE/RoCEv2, вам также необходимо
|
||||||
правильно настроить для него коммутаторы, иначе вы можете столкнуться с
|
правильно настроить для него коммутаторы, иначе вы можете столкнуться с
|
||||||
|
@ -156,11 +159,35 @@ OSD в любом случае согласовывают реальное зн
|
||||||
Не влияет на потребление памяти - дополнительная память на операции отправки
|
Не влияет на потребление памяти - дополнительная память на операции отправки
|
||||||
не выделяется.
|
не выделяется.
|
||||||
|
|
||||||
|
## rdma_odp
|
||||||
|
|
||||||
|
- Тип: булево (да/нет)
|
||||||
|
- Значение по умолчанию: false
|
||||||
|
|
||||||
|
Использовать RDMA с On-Demand Paging. ODP - функция, доступная пока что
|
||||||
|
исключительно на адаптерах Mellanox ConnectX-4 и более новых. ODP позволяет
|
||||||
|
не регистрировать память для её использования RDMA-картой. Благодаря этому
|
||||||
|
можно не копировать данные при отправке их в сеть и, казалось бы, это должно
|
||||||
|
улучшать производительность - но **по факту** получается так, что
|
||||||
|
производительность только ухудшается, причём сильно. Пример - на 3-узловом
|
||||||
|
кластере с 8 NVMe в каждом узле и сетью 2*25 Гбит/с на чтение с RDMA без ODP
|
||||||
|
удаётся снять 3950000 iops, а с ODP - всего 239000 iops...
|
||||||
|
|
||||||
|
Это происходит из-за того, что реализация ODP у Mellanox неоптимальная и
|
||||||
|
основана на повторной передаче сообщений, когда карте не известен буфер -
|
||||||
|
вероятно, на стандартных "RNR retransmission" (RNR = receiver not ready).
|
||||||
|
А данные повторные передачи в RDMA/RoCE - всегда очень медленная штука.
|
||||||
|
Презентация на эту тему с конференции ISPASS-2021: https://tkygtr6.github.io/pub/ISPASS21_slides.pdf
|
||||||
|
|
||||||
|
Возможность использования ODP сохранена в коде на случай, если вдруг в один
|
||||||
|
прекрасный день появится хорошая реализация ODP.
|
||||||
|
|
||||||
## peer_connect_interval
|
## peer_connect_interval
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 5
|
- Значение по умолчанию: 5
|
||||||
- Минимальное значение: 1
|
- Минимальное значение: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Время ожидания перед повторной попыткой соединиться с недоступным OSD.
|
Время ожидания перед повторной попыткой соединиться с недоступным OSD.
|
||||||
|
|
||||||
|
@ -169,6 +196,7 @@ OSD в любом случае согласовывают реальное зн
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 5
|
- Значение по умолчанию: 5
|
||||||
- Минимальное значение: 1
|
- Минимальное значение: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное время ожидания попытки соединения с OSD.
|
Максимальное время ожидания попытки соединения с OSD.
|
||||||
|
|
||||||
|
@ -177,6 +205,7 @@ OSD в любом случае согласовывают реальное зн
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 5
|
- Значение по умолчанию: 5
|
||||||
- Минимальное значение: 1
|
- Минимальное значение: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Время неактивности соединения с OSD, после которого клиенты или другие OSD
|
Время неактивности соединения с OSD, после которого клиенты или другие OSD
|
||||||
посылают запрос проверки состояния соединения.
|
посылают запрос проверки состояния соединения.
|
||||||
|
@ -186,6 +215,7 @@ OSD в любом случае согласовывают реальное зн
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 5
|
- Значение по умолчанию: 5
|
||||||
- Минимальное значение: 1
|
- Минимальное значение: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное время ожидания ответа на запрос проверки состояния соединения.
|
Максимальное время ожидания ответа на запрос проверки состояния соединения.
|
||||||
Если OSD не отвечает за это время, соединение отключается и производится
|
Если OSD не отвечает за это время, соединение отключается и производится
|
||||||
|
@ -194,8 +224,9 @@ OSD в любом случае согласовывают реальное зн
|
||||||
## up_wait_retry_interval
|
## up_wait_retry_interval
|
||||||
|
|
||||||
- Тип: миллисекунды
|
- Тип: миллисекунды
|
||||||
- Значение по умолчанию: 500
|
- Значение по умолчанию: 50
|
||||||
- Минимальное значение: 50
|
- Минимальное значение: 10
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Когда OSD получают от клиентов запросы ввода-вывода, относящиеся к не
|
Когда OSD получают от клиентов запросы ввода-вывода, относящиеся к не
|
||||||
поднятым на данный момент на них PG, либо к PG в процессе синхронизации,
|
поднятым на данный момент на них PG, либо к PG в процессе синхронизации,
|
||||||
|
@ -207,6 +238,7 @@ OSD в любом случае согласовывают реальное зн
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 5
|
- Значение по умолчанию: 5
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное число попыток выполнения запросов к etcd для тех запросов,
|
Максимальное число попыток выполнения запросов к etcd для тех запросов,
|
||||||
которые нельзя повторять бесконечно.
|
которые нельзя повторять бесконечно.
|
||||||
|
@ -215,6 +247,7 @@ OSD в любом случае согласовывают реальное зн
|
||||||
|
|
||||||
- Тип: миллисекунды
|
- Тип: миллисекунды
|
||||||
- Значение по умолчанию: 1000
|
- Значение по умолчанию: 1000
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное время выполнения запросов к etcd, которые должны завершаться
|
Максимальное время выполнения запросов к etcd, которые должны завершаться
|
||||||
быстро, таких, как обновление резервации (lease).
|
быстро, таких, как обновление резервации (lease).
|
||||||
|
@ -223,6 +256,7 @@ OSD в любом случае согласовывают реальное зн
|
||||||
|
|
||||||
- Тип: миллисекунды
|
- Тип: миллисекунды
|
||||||
- Значение по умолчанию: 5000
|
- Значение по умолчанию: 5000
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное время выполнения запросов к etcd, для которых не обязательно
|
Максимальное время выполнения запросов к etcd, для которых не обязательно
|
||||||
гарантировать быстрое выполнение.
|
гарантировать быстрое выполнение.
|
||||||
|
@ -231,6 +265,7 @@ OSD в любом случае согласовывают реальное зн
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: max(30, etcd_report_interval*2)
|
- Значение по умолчанию: max(30, etcd_report_interval*2)
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Таймаут для HTTP Keep-Alive в соединениях к etcd. Должен быть больше, чем
|
Таймаут для HTTP Keep-Alive в соединениях к etcd. Должен быть больше, чем
|
||||||
etcd_report_interval, чтобы keepalive гарантированно работал.
|
etcd_report_interval, чтобы keepalive гарантированно работал.
|
||||||
|
@ -239,18 +274,6 @@ etcd_report_interval, чтобы keepalive гарантированно рабо
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 30
|
- Значение по умолчанию: 30
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Интервал проверки живости вебсокет-подключений к etcd.
|
Интервал проверки живости вебсокет-подключений к etcd.
|
||||||
|
|
||||||
## client_dirty_limit
|
|
||||||
|
|
||||||
- Тип: целое число
|
|
||||||
- Значение по умолчанию: 33554432
|
|
||||||
|
|
||||||
При работе без immediate_commit=all - это лимит объёма "грязных" (не
|
|
||||||
зафиксированных fsync-ом) данных, при достижении которого клиент будет
|
|
||||||
принудительно вызывать fsync и фиксировать данные. Также стоит иметь в виду,
|
|
||||||
что в этом случае до момента fsync клиент хранит копию незафиксированных
|
|
||||||
данных в памяти, то есть, настройка влияет на потребление памяти клиентами.
|
|
||||||
|
|
||||||
Параметр не влияет на сами OSD.
|
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
# Runtime OSD Parameters
|
# Runtime OSD Parameters
|
||||||
|
|
||||||
These parameters only apply to OSDs, are not fixed at the moment of OSD drive
|
These parameters only apply to OSDs, are not fixed at the moment of OSD drive
|
||||||
initialization and can be changed with an OSD restart.
|
initialization and can be changed - either with an OSD restart or, for some of
|
||||||
|
them, even without restarting by updating configuration in etcd.
|
||||||
|
|
||||||
- [etcd_report_interval](#etcd_report_interval)
|
- [etcd_report_interval](#etcd_report_interval)
|
||||||
|
- [etcd_stats_interval](#etcd_stats_interval)
|
||||||
- [run_primary](#run_primary)
|
- [run_primary](#run_primary)
|
||||||
- [osd_network](#osd_network)
|
- [osd_network](#osd_network)
|
||||||
- [bind_address](#bind_address)
|
- [bind_address](#bind_address)
|
||||||
|
@ -17,6 +19,7 @@ initialization and can be changed with an OSD restart.
|
||||||
- [autosync_interval](#autosync_interval)
|
- [autosync_interval](#autosync_interval)
|
||||||
- [autosync_writes](#autosync_writes)
|
- [autosync_writes](#autosync_writes)
|
||||||
- [recovery_queue_depth](#recovery_queue_depth)
|
- [recovery_queue_depth](#recovery_queue_depth)
|
||||||
|
- [recovery_sleep_us](#recovery_sleep_us)
|
||||||
- [recovery_pg_switch](#recovery_pg_switch)
|
- [recovery_pg_switch](#recovery_pg_switch)
|
||||||
- [recovery_sync_batch](#recovery_sync_batch)
|
- [recovery_sync_batch](#recovery_sync_batch)
|
||||||
- [readonly](#readonly)
|
- [readonly](#readonly)
|
||||||
|
@ -30,6 +33,9 @@ initialization and can be changed with an OSD restart.
|
||||||
- [max_flusher_count](#max_flusher_count)
|
- [max_flusher_count](#max_flusher_count)
|
||||||
- [inmemory_metadata](#inmemory_metadata)
|
- [inmemory_metadata](#inmemory_metadata)
|
||||||
- [inmemory_journal](#inmemory_journal)
|
- [inmemory_journal](#inmemory_journal)
|
||||||
|
- [data_io](#data_io)
|
||||||
|
- [meta_io](#meta_io)
|
||||||
|
- [journal_io](#journal_io)
|
||||||
- [journal_sector_buffer_count](#journal_sector_buffer_count)
|
- [journal_sector_buffer_count](#journal_sector_buffer_count)
|
||||||
- [journal_no_same_sector_overwrites](#journal_no_same_sector_overwrites)
|
- [journal_no_same_sector_overwrites](#journal_no_same_sector_overwrites)
|
||||||
- [throttle_small_writes](#throttle_small_writes)
|
- [throttle_small_writes](#throttle_small_writes)
|
||||||
|
@ -38,17 +44,43 @@ initialization and can be changed with an OSD restart.
|
||||||
- [throttle_target_parallelism](#throttle_target_parallelism)
|
- [throttle_target_parallelism](#throttle_target_parallelism)
|
||||||
- [throttle_threshold_us](#throttle_threshold_us)
|
- [throttle_threshold_us](#throttle_threshold_us)
|
||||||
- [osd_memlock](#osd_memlock)
|
- [osd_memlock](#osd_memlock)
|
||||||
|
- [auto_scrub](#auto_scrub)
|
||||||
|
- [no_scrub](#no_scrub)
|
||||||
|
- [scrub_interval](#scrub_interval)
|
||||||
|
- [scrub_queue_depth](#scrub_queue_depth)
|
||||||
|
- [scrub_sleep](#scrub_sleep)
|
||||||
|
- [scrub_list_limit](#scrub_list_limit)
|
||||||
|
- [scrub_find_best](#scrub_find_best)
|
||||||
|
- [scrub_ec_max_bruteforce](#scrub_ec_max_bruteforce)
|
||||||
|
- [recovery_tune_interval](#recovery_tune_interval)
|
||||||
|
- [recovery_tune_util_low](#recovery_tune_util_low)
|
||||||
|
- [recovery_tune_util_high](#recovery_tune_util_high)
|
||||||
|
- [recovery_tune_client_util_low](#recovery_tune_client_util_low)
|
||||||
|
- [recovery_tune_client_util_high](#recovery_tune_client_util_high)
|
||||||
|
- [recovery_tune_agg_interval](#recovery_tune_agg_interval)
|
||||||
|
- [recovery_tune_sleep_min_us](#recovery_tune_sleep_min_us)
|
||||||
|
- [recovery_tune_sleep_cutoff_us](#recovery_tune_sleep_cutoff_us)
|
||||||
|
|
||||||
## etcd_report_interval
|
## etcd_report_interval
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 5
|
- Default: 5
|
||||||
|
|
||||||
Interval at which OSDs report their state to etcd. Affects OSD lease time
|
Interval at which OSDs report their liveness to etcd. Affects OSD lease time
|
||||||
and thus the failover speed. Lease time is equal to this parameter value
|
and thus the failover speed. Lease time is equal to this parameter value
|
||||||
plus max_etcd_attempts * etcd_quick_timeout because it should be guaranteed
|
plus max_etcd_attempts * etcd_quick_timeout because it should be guaranteed
|
||||||
that every OSD always refreshes its lease in time.
|
that every OSD always refreshes its lease in time.
|
||||||
|
|
||||||
|
## etcd_stats_interval
|
||||||
|
|
||||||
|
- Type: seconds
|
||||||
|
- Default: 30
|
||||||
|
|
||||||
|
Interval at which OSDs report their statistics to etcd. Highly affects the
|
||||||
|
imposed load on etcd, because statistics include a key for every OSD and
|
||||||
|
for every PG. At the same time, low statistic intervals make `vitastor-cli`
|
||||||
|
statistics more responsive.
|
||||||
|
|
||||||
## run_primary
|
## run_primary
|
||||||
|
|
||||||
- Type: boolean
|
- Type: boolean
|
||||||
|
@ -91,6 +123,7 @@ OSD by hand.
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 5
|
- Default: 5
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Time interval at which automatic fsyncs/flushes are issued by each OSD when
|
Time interval at which automatic fsyncs/flushes are issued by each OSD when
|
||||||
the immediate_commit mode if disabled. fsyncs are required because without
|
the immediate_commit mode if disabled. fsyncs are required because without
|
||||||
|
@ -103,6 +136,7 @@ issue fsyncs at all.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 128
|
- Default: 128
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Same as autosync_interval, but sets the maximum number of uncommitted write
|
Same as autosync_interval, but sets the maximum number of uncommitted write
|
||||||
operations before issuing an fsync operation internally.
|
operations before issuing an fsync operation internally.
|
||||||
|
@ -110,16 +144,30 @@ operations before issuing an fsync operation internally.
|
||||||
## recovery_queue_depth
|
## recovery_queue_depth
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 4
|
- Default: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Maximum recovery operations per one primary OSD at any given moment of time.
|
Maximum recovery and rebalance operations initiated by each OSD in parallel.
|
||||||
Currently it's the only parameter available to tune the speed or recovery
|
Note that each OSD talks to a lot of other OSDs so actual number of parallel
|
||||||
and rebalancing, but it's planned to implement more.
|
recovery operations per each OSD is greater than just recovery_queue_depth.
|
||||||
|
Increasing this parameter can speedup recovery if [auto-tuning](#recovery_tune_interval)
|
||||||
|
allows it or if it is disabled.
|
||||||
|
|
||||||
|
## recovery_sleep_us
|
||||||
|
|
||||||
|
- Type: microseconds
|
||||||
|
- Default: 0
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Delay for all recovery- and rebalance- related operations. If non-zero,
|
||||||
|
such operations are artificially slowed down to reduce the impact on
|
||||||
|
client I/O.
|
||||||
|
|
||||||
## recovery_pg_switch
|
## recovery_pg_switch
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 128
|
- Default: 128
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Number of recovery operations before switching to recovery of the next PG.
|
Number of recovery operations before switching to recovery of the next PG.
|
||||||
The idea is to mix all PGs during recovery for more even space and load
|
The idea is to mix all PGs during recovery for more even space and load
|
||||||
|
@ -130,6 +178,7 @@ Degraded PGs are anyway scanned first.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 16
|
- Default: 16
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Maximum number of recovery operations before issuing an additional fsync.
|
Maximum number of recovery operations before issuing an additional fsync.
|
||||||
|
|
||||||
|
@ -145,6 +194,7 @@ the underlying device. This may be useful for recovery purposes.
|
||||||
|
|
||||||
- Type: boolean
|
- Type: boolean
|
||||||
- Default: false
|
- Default: false
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Disable automatic background recovery of objects. Note that it doesn't
|
Disable automatic background recovery of objects. Note that it doesn't
|
||||||
affect implicit recovery of objects happening during writes - a write is
|
affect implicit recovery of objects happening during writes - a write is
|
||||||
|
@ -154,6 +204,7 @@ always made to a full set of at least pg_minsize OSDs.
|
||||||
|
|
||||||
- Type: boolean
|
- Type: boolean
|
||||||
- Default: false
|
- Default: false
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Disable background movement of data between different OSDs. Disabling it
|
Disable background movement of data between different OSDs. Disabling it
|
||||||
means that PGs in the `has_misplaced` state will be left in it indefinitely.
|
means that PGs in the `has_misplaced` state will be left in it indefinitely.
|
||||||
|
@ -162,6 +213,7 @@ means that PGs in the `has_misplaced` state will be left in it indefinitely.
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 3
|
- Default: 3
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Time interval at which OSDs print simple human-readable operation
|
Time interval at which OSDs print simple human-readable operation
|
||||||
statistics on stdout.
|
statistics on stdout.
|
||||||
|
@ -170,6 +222,7 @@ statistics on stdout.
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 10
|
- Default: 10
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Time interval at which OSDs dump slow or stuck operations on stdout, if
|
Time interval at which OSDs dump slow or stuck operations on stdout, if
|
||||||
they're any. Also it's the time after which an operation is considered
|
they're any. Also it's the time after which an operation is considered
|
||||||
|
@ -179,6 +232,7 @@ they're any. Also it's the time after which an operation is considered
|
||||||
|
|
||||||
- Type: seconds
|
- Type: seconds
|
||||||
- Default: 60
|
- Default: 60
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Number of seconds after which a deleted inode is removed from OSD statistics.
|
Number of seconds after which a deleted inode is removed from OSD statistics.
|
||||||
|
|
||||||
|
@ -186,6 +240,7 @@ Number of seconds after which a deleted inode is removed from OSD statistics.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 128
|
- Default: 128
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Parallel client write operation limit per one OSD. Operations that exceed
|
Parallel client write operation limit per one OSD. Operations that exceed
|
||||||
this limit are pushed to a temporary queue instead of being executed
|
this limit are pushed to a temporary queue instead of being executed
|
||||||
|
@ -195,6 +250,7 @@ immediately.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 1
|
- Default: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Flusher is a micro-thread that moves data from the journal to the data
|
Flusher is a micro-thread that moves data from the journal to the data
|
||||||
area of the device. Their number is auto-tuned between minimum and maximum.
|
area of the device. Their number is auto-tuned between minimum and maximum.
|
||||||
|
@ -204,6 +260,7 @@ Minimum number is set by this parameter.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 256
|
- Default: 256
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Maximum number of journal flushers (see above min_flusher_count).
|
Maximum number of journal flushers (see above min_flusher_count).
|
||||||
|
|
||||||
|
@ -233,6 +290,60 @@ is typically very small because it's sufficient to have 16-32 MB journal
|
||||||
for SSD OSDs. However, in theory it's possible that you'll want to turn it
|
for SSD OSDs. However, in theory it's possible that you'll want to turn it
|
||||||
off for hybrid (HDD+SSD) OSDs with large journals on quick devices.
|
off for hybrid (HDD+SSD) OSDs with large journals on quick devices.
|
||||||
|
|
||||||
|
## data_io
|
||||||
|
|
||||||
|
- Type: string
|
||||||
|
- Default: direct
|
||||||
|
|
||||||
|
I/O mode for *data*. One of "direct", "cached" or "directsync". Corresponds
|
||||||
|
to O_DIRECT, O_SYNC and O_DIRECT|O_SYNC, respectively.
|
||||||
|
|
||||||
|
Choose "cached" to use Linux page cache. This may improve read performance
|
||||||
|
for hot data and slower disks - HDDs and maybe SATA SSDs - but will slightly
|
||||||
|
decrease write performance for fast disks because page cache is an overhead
|
||||||
|
itself.
|
||||||
|
|
||||||
|
Choose "directsync" to use [immediate_commit](layout-cluster.ru.md#immediate_commit)
|
||||||
|
(which requires disable_data_fsync) with drives having write-back cache
|
||||||
|
which can't be turned off, for example, Intel Optane. Also note that *some*
|
||||||
|
desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making
|
||||||
|
disable_data_fsync unsafe even with "directsync".
|
||||||
|
|
||||||
|
## meta_io
|
||||||
|
|
||||||
|
- Type: string
|
||||||
|
- Default: direct
|
||||||
|
|
||||||
|
I/O mode for *metadata*. One of "direct", "cached" or "directsync".
|
||||||
|
|
||||||
|
"cached" may improve read performance, but only under the following conditions:
|
||||||
|
1. your drives are relatively slow (HDD, SATA SSD), and
|
||||||
|
2. checksums are enabled, and
|
||||||
|
3. [inmemory_metadata](#inmemory_metadata) is disabled.
|
||||||
|
Under all these conditions, metadata blocks are read from disk on every
|
||||||
|
read request to verify checksums and caching them may reduce this extra
|
||||||
|
read load. Without (3) metadata is never read from the disk after starting,
|
||||||
|
and without (2) metadata blocks are read from disk only during journal
|
||||||
|
flushing.
|
||||||
|
|
||||||
|
"directsync" is the same as above.
|
||||||
|
|
||||||
|
If the same device is used for data and metadata, meta_io by default is set
|
||||||
|
to the same value as [data_io](#data_io).
|
||||||
|
|
||||||
|
## journal_io
|
||||||
|
|
||||||
|
- Type: string
|
||||||
|
- Default: direct
|
||||||
|
|
||||||
|
I/O mode for *journal*. One of "direct", "cached" or "directsync".
|
||||||
|
|
||||||
|
Here, "cached" may only improve read performance for recent writes and
|
||||||
|
only if [inmemory_journal](#inmemory_journal) is turned off.
|
||||||
|
|
||||||
|
If the same device is used for metadata and journal, journal_io by default
|
||||||
|
is set to the same value as [meta_io](#meta_io).
|
||||||
|
|
||||||
## journal_sector_buffer_count
|
## journal_sector_buffer_count
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
|
@ -260,6 +371,7 @@ Most (99%) other SSDs don't need this option.
|
||||||
|
|
||||||
- Type: boolean
|
- Type: boolean
|
||||||
- Default: false
|
- Default: false
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Enable soft throttling of small journaled writes. Useful for hybrid OSDs
|
Enable soft throttling of small journaled writes. Useful for hybrid OSDs
|
||||||
with fast journal/metadata devices and slow data devices. The idea is that
|
with fast journal/metadata devices and slow data devices. The idea is that
|
||||||
|
@ -277,6 +389,7 @@ fills up.
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 100
|
- Default: 100
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Target maximum number of throttled operations per second under the condition
|
Target maximum number of throttled operations per second under the condition
|
||||||
of full journal. Set it to approximate random write iops of your data devices
|
of full journal. Set it to approximate random write iops of your data devices
|
||||||
|
@ -286,6 +399,7 @@ of full journal. Set it to approximate random write iops of your data devices
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 100
|
- Default: 100
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Target maximum bandwidth in MB/s of throttled operations per second under
|
Target maximum bandwidth in MB/s of throttled operations per second under
|
||||||
the condition of full journal. Set it to approximate linear write
|
the condition of full journal. Set it to approximate linear write
|
||||||
|
@ -295,6 +409,7 @@ performance of your data devices (HDDs).
|
||||||
|
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 1
|
- Default: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Target maximum parallelism of throttled operations under the condition of
|
Target maximum parallelism of throttled operations under the condition of
|
||||||
full journal. Set it to approximate internal parallelism of your data
|
full journal. Set it to approximate internal parallelism of your data
|
||||||
|
@ -304,6 +419,7 @@ devices (1 for HDDs, 4-8 for SSDs).
|
||||||
|
|
||||||
- Type: microseconds
|
- Type: microseconds
|
||||||
- Default: 50
|
- Default: 50
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
Minimal computed delay to be applied to throttled operations. Usually
|
Minimal computed delay to be applied to throttled operations. Usually
|
||||||
doesn't need to be changed.
|
doesn't need to be changed.
|
||||||
|
@ -313,4 +429,190 @@ doesn't need to be changed.
|
||||||
- Type: boolean
|
- Type: boolean
|
||||||
- Default: false
|
- Default: false
|
||||||
|
|
||||||
Lock all OSD memory to prevent it from being unloaded into swap with mlockall(). Requires sufficient ulimit -l (max locked memory).
|
Lock all OSD memory to prevent it from being unloaded into swap with
|
||||||
|
mlockall(). Requires sufficient ulimit -l (max locked memory).
|
||||||
|
|
||||||
|
## auto_scrub
|
||||||
|
|
||||||
|
- Type: boolean
|
||||||
|
- Default: false
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Data scrubbing is the process of background verification of copies to find
|
||||||
|
and repair corrupted blocks. It's not run automatically by default since
|
||||||
|
it's a new feature. Set this parameter to true to enable automatic scrubs.
|
||||||
|
|
||||||
|
This parameter makes OSDs automatically schedule data scrubbing of clean PGs
|
||||||
|
every `scrub_interval` (see below). You can also start/schedule scrubbing
|
||||||
|
manually by setting `next_scrub` JSON key to the desired UNIX time of the
|
||||||
|
next scrub in `/pg/history/...` values in etcd.
|
||||||
|
|
||||||
|
## no_scrub
|
||||||
|
|
||||||
|
- Type: boolean
|
||||||
|
- Default: false
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Temporarily disable scrubbing and stop running scrubs.
|
||||||
|
|
||||||
|
## scrub_interval
|
||||||
|
|
||||||
|
- Type: string
|
||||||
|
- Default: 30d
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Default automatic scrubbing interval for all pools. Numbers without suffix
|
||||||
|
are treated as seconds, possible unit suffixes include 's' (seconds),
|
||||||
|
'm' (minutes), 'h' (hours), 'd' (days), 'M' (months) and 'y' (years).
|
||||||
|
|
||||||
|
## scrub_queue_depth
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Number of parallel scrubbing operations per one OSD.
|
||||||
|
|
||||||
|
## scrub_sleep
|
||||||
|
|
||||||
|
- Type: milliseconds
|
||||||
|
- Default: 0
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Additional interval between two consecutive scrubbing operations on one OSD.
|
||||||
|
Can be used to slow down scrubbing if it affects user load too much.
|
||||||
|
|
||||||
|
## scrub_list_limit
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 1000
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Number of objects to list in one listing operation during scrub.
|
||||||
|
|
||||||
|
## scrub_find_best
|
||||||
|
|
||||||
|
- Type: boolean
|
||||||
|
- Default: true
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Find and automatically restore best versions of objects with unmatched
|
||||||
|
copies. In replicated setups, the best version is the version with most
|
||||||
|
matching replicas. In EC setups, the best version is the subset of data
|
||||||
|
and parity chunks without mismatches.
|
||||||
|
|
||||||
|
The hypothetical situation where you might want to disable it is when
|
||||||
|
you have 3 replicas and you are paranoid that 2 HDDs out of 3 may silently
|
||||||
|
corrupt an object in the same way (for example, zero it out) and only
|
||||||
|
1 HDD will remain good. In this case disabling scrub_find_best may help
|
||||||
|
you to recover the data! See also scrub_ec_max_bruteforce below.
|
||||||
|
|
||||||
|
## scrub_ec_max_bruteforce
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 100
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Vitastor can locate corrupted chunks in EC setups with more than 1 parity
|
||||||
|
chunk by brute-forcing all possible error locations. This configuration
|
||||||
|
value limits the maximum number of checked combinations. You can try to
|
||||||
|
increase it if you have EC N+K setup with N and K large enough for
|
||||||
|
combination count `C(N+K-1, K-1) = (N+K-1)! / (K-1)! / N!` to be greater
|
||||||
|
than the default 100.
|
||||||
|
|
||||||
|
If there are too many possible combinations or if multiple combinations give
|
||||||
|
correct results then objects are marked inconsistent and aren't recovered
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
In replicated setups bruteforcing isn't needed, Vitastor just assumes that
|
||||||
|
the variant with most available equal copies is correct. For example, if
|
||||||
|
you have 3 replicas and 1 of them differs, this one is considered to be
|
||||||
|
corrupted. But if there is no "best" version with more copies than all
|
||||||
|
others have then the object is also marked as inconsistent.
|
||||||
|
|
||||||
|
## recovery_tune_interval
|
||||||
|
|
||||||
|
- Type: seconds
|
||||||
|
- Default: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Interval at which OSD re-considers client and recovery load and automatically
|
||||||
|
adjusts [recovery_sleep_us](#recovery_sleep_us). Recovery auto-tuning is
|
||||||
|
disabled if recovery_tune_interval is set to 0.
|
||||||
|
|
||||||
|
Auto-tuning targets utilization. Utilization is a measure of load and is
|
||||||
|
equal to the product of iops and average latency (so it may be greater
|
||||||
|
than 1). You set "low" and "high" client utilization thresholds and two
|
||||||
|
corresponding target recovery utilization levels. OSD calculates desired
|
||||||
|
recovery utilization from client utilization using linear interpolation
|
||||||
|
and auto-tunes recovery operation delay to make actual recovery utilization
|
||||||
|
match desired.
|
||||||
|
|
||||||
|
This allows to reduce recovery/rebalance impact on client operations. It is
|
||||||
|
of course impossible to remove it completely, but it should become adequate.
|
||||||
|
In some tests rebalance could earlier drop client write speed from 1.5 GB/s
|
||||||
|
to 50-100 MB/s, with default auto-tuning settings it now only reduces
|
||||||
|
to ~1 GB/s.
|
||||||
|
|
||||||
|
## recovery_tune_util_low
|
||||||
|
|
||||||
|
- Type: number
|
||||||
|
- Default: 0.1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Desired recovery/rebalance utilization when client load is high, i.e. when
|
||||||
|
it is at or above recovery_tune_client_util_high.
|
||||||
|
|
||||||
|
## recovery_tune_util_high
|
||||||
|
|
||||||
|
- Type: number
|
||||||
|
- Default: 1
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Desired recovery/rebalance utilization when client load is low, i.e. when
|
||||||
|
it is at or below recovery_tune_client_util_low.
|
||||||
|
|
||||||
|
## recovery_tune_client_util_low
|
||||||
|
|
||||||
|
- Type: number
|
||||||
|
- Default: 0
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Client utilization considered "low".
|
||||||
|
|
||||||
|
## recovery_tune_client_util_high
|
||||||
|
|
||||||
|
- Type: number
|
||||||
|
- Default: 0.5
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Client utilization considered "high".
|
||||||
|
|
||||||
|
## recovery_tune_agg_interval
|
||||||
|
|
||||||
|
- Type: integer
|
||||||
|
- Default: 10
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
The number of last auto-tuning iterations to use for calculating the
|
||||||
|
delay as average. Lower values result in quicker response to client
|
||||||
|
load change, higher values result in more stable delay. Default value of 10
|
||||||
|
is usually fine.
|
||||||
|
|
||||||
|
## recovery_tune_sleep_min_us
|
||||||
|
|
||||||
|
- Type: microseconds
|
||||||
|
- Default: 10
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Minimum possible value for auto-tuned recovery_sleep_us. Lower values
|
||||||
|
are changed to 0.
|
||||||
|
|
||||||
|
## recovery_tune_sleep_cutoff_us
|
||||||
|
|
||||||
|
- Type: microseconds
|
||||||
|
- Default: 10000000
|
||||||
|
- Can be changed online: yes
|
||||||
|
|
||||||
|
Maximum possible value for auto-tuned recovery_sleep_us. Higher values
|
||||||
|
are treated as outliers and ignored in aggregation.
|
||||||
|
|
|
@ -8,9 +8,11 @@
|
||||||
|
|
||||||
Данные параметры используются только OSD, но, в отличие от дисковых параметров,
|
Данные параметры используются только OSD, но, в отличие от дисковых параметров,
|
||||||
не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой
|
не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой
|
||||||
момент с перезапуском OSD.
|
момент с помощью перезапуска OSD, а некоторые и без перезапуска, с помощью
|
||||||
|
изменения конфигурации в etcd.
|
||||||
|
|
||||||
- [etcd_report_interval](#etcd_report_interval)
|
- [etcd_report_interval](#etcd_report_interval)
|
||||||
|
- [etcd_stats_interval](#etcd_stats_interval)
|
||||||
- [run_primary](#run_primary)
|
- [run_primary](#run_primary)
|
||||||
- [osd_network](#osd_network)
|
- [osd_network](#osd_network)
|
||||||
- [bind_address](#bind_address)
|
- [bind_address](#bind_address)
|
||||||
|
@ -18,6 +20,7 @@
|
||||||
- [autosync_interval](#autosync_interval)
|
- [autosync_interval](#autosync_interval)
|
||||||
- [autosync_writes](#autosync_writes)
|
- [autosync_writes](#autosync_writes)
|
||||||
- [recovery_queue_depth](#recovery_queue_depth)
|
- [recovery_queue_depth](#recovery_queue_depth)
|
||||||
|
- [recovery_sleep_us](#recovery_sleep_us)
|
||||||
- [recovery_pg_switch](#recovery_pg_switch)
|
- [recovery_pg_switch](#recovery_pg_switch)
|
||||||
- [recovery_sync_batch](#recovery_sync_batch)
|
- [recovery_sync_batch](#recovery_sync_batch)
|
||||||
- [readonly](#readonly)
|
- [readonly](#readonly)
|
||||||
|
@ -31,6 +34,9 @@
|
||||||
- [max_flusher_count](#max_flusher_count)
|
- [max_flusher_count](#max_flusher_count)
|
||||||
- [inmemory_metadata](#inmemory_metadata)
|
- [inmemory_metadata](#inmemory_metadata)
|
||||||
- [inmemory_journal](#inmemory_journal)
|
- [inmemory_journal](#inmemory_journal)
|
||||||
|
- [data_io](#data_io)
|
||||||
|
- [meta_io](#meta_io)
|
||||||
|
- [journal_io](#journal_io)
|
||||||
- [journal_sector_buffer_count](#journal_sector_buffer_count)
|
- [journal_sector_buffer_count](#journal_sector_buffer_count)
|
||||||
- [journal_no_same_sector_overwrites](#journal_no_same_sector_overwrites)
|
- [journal_no_same_sector_overwrites](#journal_no_same_sector_overwrites)
|
||||||
- [throttle_small_writes](#throttle_small_writes)
|
- [throttle_small_writes](#throttle_small_writes)
|
||||||
|
@ -39,17 +45,43 @@
|
||||||
- [throttle_target_parallelism](#throttle_target_parallelism)
|
- [throttle_target_parallelism](#throttle_target_parallelism)
|
||||||
- [throttle_threshold_us](#throttle_threshold_us)
|
- [throttle_threshold_us](#throttle_threshold_us)
|
||||||
- [osd_memlock](#osd_memlock)
|
- [osd_memlock](#osd_memlock)
|
||||||
|
- [auto_scrub](#auto_scrub)
|
||||||
|
- [no_scrub](#no_scrub)
|
||||||
|
- [scrub_interval](#scrub_interval)
|
||||||
|
- [scrub_queue_depth](#scrub_queue_depth)
|
||||||
|
- [scrub_sleep](#scrub_sleep)
|
||||||
|
- [scrub_list_limit](#scrub_list_limit)
|
||||||
|
- [scrub_find_best](#scrub_find_best)
|
||||||
|
- [scrub_ec_max_bruteforce](#scrub_ec_max_bruteforce)
|
||||||
|
- [recovery_tune_interval](#recovery_tune_interval)
|
||||||
|
- [recovery_tune_util_low](#recovery_tune_util_low)
|
||||||
|
- [recovery_tune_util_high](#recovery_tune_util_high)
|
||||||
|
- [recovery_tune_client_util_low](#recovery_tune_client_util_low)
|
||||||
|
- [recovery_tune_client_util_high](#recovery_tune_client_util_high)
|
||||||
|
- [recovery_tune_agg_interval](#recovery_tune_agg_interval)
|
||||||
|
- [recovery_tune_sleep_min_us](#recovery_tune_sleep_min_us)
|
||||||
|
- [recovery_tune_sleep_cutoff_us](#recovery_tune_sleep_cutoff_us)
|
||||||
|
|
||||||
## etcd_report_interval
|
## etcd_report_interval
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 5
|
- Значение по умолчанию: 5
|
||||||
|
|
||||||
Интервал, с которым OSD обновляет своё состояние в etcd. Значение параметра
|
Интервал, с которым OSD сообщает о том, что жив, в etcd. Значение параметра
|
||||||
влияет на время резервации (lease) OSD и поэтому на скорость переключения
|
влияет на время резервации (lease) OSD и поэтому - на скорость переключения
|
||||||
при падении OSD. Время lease равняется значению этого параметра плюс
|
при падении OSD. Время lease равняется значению этого параметра плюс
|
||||||
max_etcd_attempts * etcd_quick_timeout.
|
max_etcd_attempts * etcd_quick_timeout.
|
||||||
|
|
||||||
|
## etcd_stats_interval
|
||||||
|
|
||||||
|
- Тип: секунды
|
||||||
|
- Значение по умолчанию: 30
|
||||||
|
|
||||||
|
Интервал, с которым OSD обновляет свою статистику в etcd. Сильно влияет на
|
||||||
|
создаваемую нагрузку на etcd, потому что статистика содержит по ключу на
|
||||||
|
каждый OSD и на каждую PG. В то же время низкий интервал делает
|
||||||
|
статистику, печатаемую `vitastor-cli`, отзывчивей.
|
||||||
|
|
||||||
## run_primary
|
## run_primary
|
||||||
|
|
||||||
- Тип: булево (да/нет)
|
- Тип: булево (да/нет)
|
||||||
|
@ -93,6 +125,7 @@ RUNNING), подходящий под заданную маску. Также н
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 5
|
- Значение по умолчанию: 5
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Временной интервал отправки автоматических fsync-ов (операций очистки кэша)
|
Временной интервал отправки автоматических fsync-ов (операций очистки кэша)
|
||||||
каждым OSD для случая, когда режим immediate_commit отключён. fsync-и нужны
|
каждым OSD для случая, когда режим immediate_commit отключён. fsync-и нужны
|
||||||
|
@ -105,6 +138,7 @@ OSD, чтобы успевать очищать журнал - без них OSD
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 128
|
- Значение по умолчанию: 128
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Аналогично autosync_interval, но задаёт не временной интервал, а
|
Аналогично autosync_interval, но задаёт не временной интервал, а
|
||||||
максимальное количество незафиксированных операций записи перед
|
максимальное количество незафиксированных операций записи перед
|
||||||
|
@ -113,17 +147,31 @@ OSD, чтобы успевать очищать журнал - без них OSD
|
||||||
## recovery_queue_depth
|
## recovery_queue_depth
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 4
|
- Значение по умолчанию: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное число операций восстановления на одном первичном OSD в любой
|
Максимальное число параллельных операций восстановления, инициируемых одним
|
||||||
момент времени. На данный момент единственный параметр, который можно менять
|
OSD в любой момент времени. Имейте в виду, что каждый OSD обычно работает с
|
||||||
для ускорения или замедления восстановления и перебалансировки данных, но
|
многими другими OSD, так что на практике параллелизм восстановления больше,
|
||||||
в планах реализация других параметров.
|
чем просто recovery_queue_depth. Увеличение значения этого параметра может
|
||||||
|
ускорить восстановление если [автотюнинг скорости](#recovery_tune_interval)
|
||||||
|
разрешает это или если он отключён.
|
||||||
|
|
||||||
|
## recovery_sleep_us
|
||||||
|
|
||||||
|
- Тип: микросекунды
|
||||||
|
- Значение по умолчанию: 0
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Delay for all recovery- and rebalance- related operations. If non-zero,
|
||||||
|
such operations are artificially slowed down to reduce the impact on
|
||||||
|
client I/O.
|
||||||
|
|
||||||
## recovery_pg_switch
|
## recovery_pg_switch
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 128
|
- Значение по умолчанию: 128
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Число операций восстановления перед переключением на восстановление другой PG.
|
Число операций восстановления перед переключением на восстановление другой PG.
|
||||||
Идея заключается в том, чтобы восстанавливать все PG одновременно для более
|
Идея заключается в том, чтобы восстанавливать все PG одновременно для более
|
||||||
|
@ -135,6 +183,7 @@ OSD, чтобы успевать очищать журнал - без них OSD
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 16
|
- Значение по умолчанию: 16
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное число операций восстановления перед дополнительным fsync.
|
Максимальное число операций восстановления перед дополнительным fsync.
|
||||||
|
|
||||||
|
@ -150,6 +199,7 @@ OSD, чтобы успевать очищать журнал - без них OSD
|
||||||
|
|
||||||
- Тип: булево (да/нет)
|
- Тип: булево (да/нет)
|
||||||
- Значение по умолчанию: false
|
- Значение по умолчанию: false
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Отключить автоматическое фоновое восстановление объектов. Обратите внимание,
|
Отключить автоматическое фоновое восстановление объектов. Обратите внимание,
|
||||||
что эта опция не отключает восстановление объектов, происходящее при
|
что эта опция не отключает восстановление объектов, происходящее при
|
||||||
|
@ -160,6 +210,7 @@ OSD.
|
||||||
|
|
||||||
- Тип: булево (да/нет)
|
- Тип: булево (да/нет)
|
||||||
- Значение по умолчанию: false
|
- Значение по умолчанию: false
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Отключить фоновое перемещение объектов между разными OSD. Отключение
|
Отключить фоновое перемещение объектов между разными OSD. Отключение
|
||||||
означает, что PG, находящиеся в состоянии `has_misplaced`, будут оставлены
|
означает, что PG, находящиеся в состоянии `has_misplaced`, будут оставлены
|
||||||
|
@ -169,6 +220,7 @@ OSD.
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 3
|
- Значение по умолчанию: 3
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Временной интервал, с которым OSD печатают простую человекочитаемую
|
Временной интервал, с которым OSD печатают простую человекочитаемую
|
||||||
статистику выполнения операций в стандартный вывод.
|
статистику выполнения операций в стандартный вывод.
|
||||||
|
@ -177,6 +229,7 @@ OSD.
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 10
|
- Значение по умолчанию: 10
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Временной интервал, с которым OSD выводят в стандартный вывод список
|
Временной интервал, с которым OSD выводят в стандартный вывод список
|
||||||
медленных или зависших операций, если таковые имеются. Также время, при
|
медленных или зависших операций, если таковые имеются. Также время, при
|
||||||
|
@ -186,6 +239,7 @@ OSD.
|
||||||
|
|
||||||
- Тип: секунды
|
- Тип: секунды
|
||||||
- Значение по умолчанию: 60
|
- Значение по умолчанию: 60
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Число секунд, через которое удалённые инод удаляется и из статистики OSD.
|
Число секунд, через которое удалённые инод удаляется и из статистики OSD.
|
||||||
|
|
||||||
|
@ -193,6 +247,7 @@ OSD.
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 128
|
- Значение по умолчанию: 128
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное число одновременных клиентских операций записи на один OSD.
|
Максимальное число одновременных клиентских операций записи на один OSD.
|
||||||
Операции, превышающие этот лимит, не исполняются сразу, а сохраняются во
|
Операции, превышающие этот лимит, не исполняются сразу, а сохраняются во
|
||||||
|
@ -202,6 +257,7 @@ OSD.
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 1
|
- Значение по умолчанию: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Flusher - это микро-поток (корутина), которая копирует данные из журнала в
|
Flusher - это микро-поток (корутина), которая копирует данные из журнала в
|
||||||
основную область устройства данных. Их число настраивается динамически между
|
основную область устройства данных. Их число настраивается динамически между
|
||||||
|
@ -211,6 +267,7 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 256
|
- Значение по умолчанию: 256
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Максимальное число микро-потоков очистки журнала (см. выше min_flusher_count).
|
Максимальное число микро-потоков очистки журнала (см. выше min_flusher_count).
|
||||||
|
|
||||||
|
@ -241,6 +298,63 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
параметра может оказаться полезным для гибридных OSD (HDD+SSD) с большими
|
параметра может оказаться полезным для гибридных OSD (HDD+SSD) с большими
|
||||||
журналами, расположенными на быстром по сравнению с HDD устройстве.
|
журналами, расположенными на быстром по сравнению с HDD устройстве.
|
||||||
|
|
||||||
|
## data_io
|
||||||
|
|
||||||
|
- Тип: строка
|
||||||
|
- Значение по умолчанию: direct
|
||||||
|
|
||||||
|
Режим ввода-вывода для *данных*. Одно из значений "direct", "cached" или
|
||||||
|
"directsync", означающих O_DIRECT, O_SYNC и O_DIRECT|O_SYNC, соответственно.
|
||||||
|
|
||||||
|
Выберите "cached", чтобы использовать системный кэш Linux (page cache) при
|
||||||
|
чтении и записи. Это может улучшить скорость чтения горячих данных с
|
||||||
|
относительно медленных дисков - HDD и, возможно, SATA SSD - но немного
|
||||||
|
снижает производительность записи для быстрых дисков, так как кэш сам по
|
||||||
|
себе тоже добавляет накладные расходы.
|
||||||
|
|
||||||
|
Выберите "directsync", если хотите задействовать
|
||||||
|
[immediate_commit](layout-cluster.ru.md#immediate_commit) (требующий
|
||||||
|
включенияd disable_data_fsync) на дисках с неотключаемым кэшем. Пример таких
|
||||||
|
дисков - Intel Optane. При этом также стоит иметь в виду, что *некоторые*
|
||||||
|
настольные SSD (например, HP EX950) игнорируют флаг O_SYNC, делая отключение
|
||||||
|
fsync небезопасным даже с режимом "directsync".
|
||||||
|
|
||||||
|
## meta_io
|
||||||
|
|
||||||
|
- Тип: строка
|
||||||
|
- Значение по умолчанию: direct
|
||||||
|
|
||||||
|
Режим ввода-вывода для *метаданных*. Одно из значений "direct", "cached" или
|
||||||
|
"directsync".
|
||||||
|
|
||||||
|
"cached" может улучшить скорость чтения, если:
|
||||||
|
1. у вас медленные диски (HDD, SATA SSD)
|
||||||
|
2. контрольные суммы включены
|
||||||
|
3. параметр [inmemory_metadata](#inmemory_metadata) отключён.
|
||||||
|
При этих условиях блоки метаданных читаются с диска при каждом запросе чтения
|
||||||
|
для проверки контрольных сумм и их кэширование может снизить дополнительную
|
||||||
|
нагрузку на диск. Без (3) метаданные никогда не читаются с диска после
|
||||||
|
запуска OSD, а без (2) блоки метаданных читаются только при сбросе журнала.
|
||||||
|
|
||||||
|
Если одно и то же устройство используется для данных и метаданных, режим
|
||||||
|
ввода-вывода метаданных по умолчанию устанавливается равным [data_io](#data_io).
|
||||||
|
|
||||||
|
## journal_io
|
||||||
|
|
||||||
|
- Тип: строка
|
||||||
|
- Значение по умолчанию: direct
|
||||||
|
|
||||||
|
Режим ввода-вывода для *журнала*. Одно из значений "direct", "cached" или
|
||||||
|
"directsync".
|
||||||
|
|
||||||
|
Здесь "cached" может улучшить скорость чтения только недавно записанных
|
||||||
|
данных и только если параметр [inmemory_journal](#inmemory_journal)
|
||||||
|
отключён.
|
||||||
|
|
||||||
|
Если одно и то же устройство используется для метаданных и журнала,
|
||||||
|
режим ввода-вывода журнала по умолчанию устанавливается равным
|
||||||
|
[meta_io](#meta_io).
|
||||||
|
|
||||||
## journal_sector_buffer_count
|
## journal_sector_buffer_count
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
|
@ -270,6 +384,7 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
|
|
||||||
- Тип: булево (да/нет)
|
- Тип: булево (да/нет)
|
||||||
- Значение по умолчанию: false
|
- Значение по умолчанию: false
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Разрешить мягкое ограничение скорости журналируемой записи. Полезно для
|
Разрешить мягкое ограничение скорости журналируемой записи. Полезно для
|
||||||
гибридных OSD с быстрыми устройствами метаданных и медленными устройствами
|
гибридных OSD с быстрыми устройствами метаданных и медленными устройствами
|
||||||
|
@ -288,6 +403,7 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 100
|
- Значение по умолчанию: 100
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Расчётное максимальное число ограничиваемых операций в секунду при условии
|
Расчётное максимальное число ограничиваемых операций в секунду при условии
|
||||||
отсутствия свободного места в журнале. Устанавливайте приблизительно равным
|
отсутствия свободного места в журнале. Устанавливайте приблизительно равным
|
||||||
|
@ -298,6 +414,7 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 100
|
- Значение по умолчанию: 100
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Расчётный максимальный размер в МБ/с ограничиваемых операций в секунду при
|
Расчётный максимальный размер в МБ/с ограничиваемых операций в секунду при
|
||||||
условии отсутствия свободного места в журнале. Устанавливайте приблизительно
|
условии отсутствия свободного места в журнале. Устанавливайте приблизительно
|
||||||
|
@ -308,6 +425,7 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
|
|
||||||
- Тип: целое число
|
- Тип: целое число
|
||||||
- Значение по умолчанию: 1
|
- Значение по умолчанию: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Расчётный максимальный параллелизм ограничиваемых операций в секунду при
|
Расчётный максимальный параллелизм ограничиваемых операций в секунду при
|
||||||
условии отсутствия свободного места в журнале. Устанавливайте приблизительно
|
условии отсутствия свободного места в журнале. Устанавливайте приблизительно
|
||||||
|
@ -318,6 +436,7 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
|
|
||||||
- Тип: микросекунды
|
- Тип: микросекунды
|
||||||
- Значение по умолчанию: 50
|
- Значение по умолчанию: 50
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
Минимальная применимая к ограничиваемым операциям задержка. Обычно не
|
Минимальная применимая к ограничиваемым операциям задержка. Обычно не
|
||||||
требует изменений.
|
требует изменений.
|
||||||
|
@ -327,4 +446,203 @@ Flusher - это микро-поток (корутина), которая коп
|
||||||
- Тип: булево (да/нет)
|
- Тип: булево (да/нет)
|
||||||
- Значение по умолчанию: false
|
- Значение по умолчанию: false
|
||||||
|
|
||||||
Блокировать всю память OSD с помощью mlockall, чтобы запретить её выгрузку в пространство подкачки. Требует достаточного значения ulimit -l (лимита заблокированной памяти).
|
Блокировать всю память OSD с помощью mlockall, чтобы запретить её выгрузку
|
||||||
|
в пространство подкачки. Требует достаточного значения ulimit -l (лимита
|
||||||
|
заблокированной памяти).
|
||||||
|
|
||||||
|
## auto_scrub
|
||||||
|
|
||||||
|
- Тип: булево (да/нет)
|
||||||
|
- Значение по умолчанию: false
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Скраб - процесс фоновой проверки копий данных, предназначенный, чтобы
|
||||||
|
находить и исправлять повреждённые блоки. По умолчанию эти проверки ещё не
|
||||||
|
запускаются автоматически, так как являются новой функцией. Чтобы включить
|
||||||
|
автоматическое планирование скрабов, установите данный параметр в true.
|
||||||
|
|
||||||
|
Включённый параметр заставляет OSD автоматически планировать фоновую
|
||||||
|
проверку чистых PG раз в `scrub_interval` (см. ниже). Вы также можете
|
||||||
|
запустить или запланировать проверку вручную, установив значение ключа JSON
|
||||||
|
`next_scrub` внутри ключей etcd `/pg/history/...` в UNIX-время следующей
|
||||||
|
желаемой проверки.
|
||||||
|
|
||||||
|
## no_scrub
|
||||||
|
|
||||||
|
- Тип: булево (да/нет)
|
||||||
|
- Значение по умолчанию: false
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Временно отключить и остановить запущенные скрабы.
|
||||||
|
|
||||||
|
## scrub_interval
|
||||||
|
|
||||||
|
- Тип: строка
|
||||||
|
- Значение по умолчанию: 30d
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Интервал автоматической фоновой проверки по умолчанию для всех пулов.
|
||||||
|
Значения без указанной единицы измерения считаются в секундах, допустимые
|
||||||
|
символы единиц измерения в конце: 's' (секунды),
|
||||||
|
'm' (минуты), 'h' (часы), 'd' (дни), 'M' (месяца) или 'y' (годы).
|
||||||
|
|
||||||
|
## scrub_queue_depth
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Число параллельных операций фоновой проверки на один OSD.
|
||||||
|
|
||||||
|
## scrub_sleep
|
||||||
|
|
||||||
|
- Тип: миллисекунды
|
||||||
|
- Значение по умолчанию: 0
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Дополнительный интервал ожидания после фоновой проверки каждого объекта на
|
||||||
|
одном OSD. Может использоваться для замедления скраба, если он слишком
|
||||||
|
сильно влияет на пользовательскую нагрузку.
|
||||||
|
|
||||||
|
## scrub_list_limit
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 1000
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Размер загружаемых за одну операцию списков объектов в процессе фоновой
|
||||||
|
проверки.
|
||||||
|
|
||||||
|
## scrub_find_best
|
||||||
|
|
||||||
|
- Тип: булево (да/нет)
|
||||||
|
- Значение по умолчанию: true
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Находить и автоматически восстанавливать "лучшие версии" объектов с
|
||||||
|
несовпадающими копиями/частями. При использовании репликации "лучшая"
|
||||||
|
версия - версия, доступная в большем числе экземпляров, чем другие. При
|
||||||
|
использовании кодов коррекции ошибок "лучшая" версия - это подмножество
|
||||||
|
частей данных и чётности, полностью соответствующих друг другу.
|
||||||
|
|
||||||
|
Гипотетическая ситуация, в которой вы можете захотеть отключить этот
|
||||||
|
поиск - это если у вас 3 реплики и вы боитесь, что 2 диска из 3 могут
|
||||||
|
незаметно и одинаково повредить данные одного и того же объекта, например,
|
||||||
|
занулив его, и только 1 диск останется неповреждённым. В этой ситуации
|
||||||
|
отключение этого параметра поможет вам восстановить данные! Смотрите также
|
||||||
|
описание следующего параметра - scrub_ec_max_bruteforce.
|
||||||
|
|
||||||
|
## scrub_ec_max_bruteforce
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 100
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Vitastor старается определить повреждённые части объектов при использовании
|
||||||
|
EC (кодов коррекции ошибок) с более, чем 1 диском чётности, путём перебора
|
||||||
|
всех возможных комбинаций ошибочных частей. Данное значение конфигурации
|
||||||
|
ограничивает число перебираемых комбинаций. Вы можете попробовать поднять
|
||||||
|
его, если используете схему кодирования EC N+K с N и K, достаточно большими
|
||||||
|
для того, чтобы число сочетаний `C(N+K-1, K-1) = (N+K-1)! / (K-1)! / N!`
|
||||||
|
было больше, чем стандартное значение 100.
|
||||||
|
|
||||||
|
Если возможных комбинаций слишком много или если корректная комбинаций не
|
||||||
|
определяется однозначно, объекты помечаются неконсистентными (inconsistent)
|
||||||
|
и не восстанавливаются автоматически.
|
||||||
|
|
||||||
|
При использовании репликации перебор не нужен, Vitastor просто предполагает,
|
||||||
|
что вариант объекта с наибольшим количеством одинаковых копий корректен.
|
||||||
|
Например, если вы используете 3 реплики и 1 из них отличается, эта 1 копия
|
||||||
|
считается некорректной. Однако, если "лучшую" версию с числом доступных
|
||||||
|
копий большим, чем у всех других версий, найти невозможно, то объект тоже
|
||||||
|
маркируется неконсистентным.
|
||||||
|
|
||||||
|
## recovery_tune_interval
|
||||||
|
|
||||||
|
- Тип: секунды
|
||||||
|
- Значение по умолчанию: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Интервал, с которым OSD пересматривает клиентскую нагрузку и нагрузку
|
||||||
|
восстановления и автоматически подстраивает [recovery_sleep_us](#recovery_sleep_us).
|
||||||
|
Автотюнинг (автоподстройка) отключается, если recovery_tune_interval
|
||||||
|
устанавливается в значение 0.
|
||||||
|
|
||||||
|
Автотюнинг регулирует утилизацию. Утилизация является мерой нагрузки
|
||||||
|
и равна произведению числа операций в секунду и средней задержки
|
||||||
|
(то есть, она может быть выше 1). Вы задаёте два уровня клиентской
|
||||||
|
утилизации - "низкий" и "высокий" (low и high) и два соответствующих
|
||||||
|
целевых уровня утилизации операциями восстановления. OSD рассчитывает
|
||||||
|
желаемый уровень утилизации восстановления линейной интерполяцией от
|
||||||
|
клиентской утилизации и подстраивает задержку операций восстановления
|
||||||
|
так, чтобы фактическая утилизация восстановления совпадала с желаемой.
|
||||||
|
|
||||||
|
Это позволяет снизить влияние восстановления и ребаланса на клиентские
|
||||||
|
операции. Конечно, невозможно исключить такое влияние полностью, но оно
|
||||||
|
должно становиться адекватнее. В некоторых тестах перебалансировка могла
|
||||||
|
снижать клиентскую скорость записи с 1.5 ГБ/с до 50-100 МБ/с, а теперь, с
|
||||||
|
настройками автотюнинга по умолчанию, она снижается только до ~1 ГБ/с.
|
||||||
|
|
||||||
|
## recovery_tune_util_low
|
||||||
|
|
||||||
|
- Тип: число
|
||||||
|
- Значение по умолчанию: 0.1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Желаемая утилизация восстановления в моменты, когда клиентская нагрузка
|
||||||
|
высокая, то есть, находится на уровне или выше recovery_tune_client_util_high.
|
||||||
|
|
||||||
|
## recovery_tune_util_high
|
||||||
|
|
||||||
|
- Тип: число
|
||||||
|
- Значение по умолчанию: 1
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Желаемая утилизация восстановления в моменты, когда клиентская нагрузка
|
||||||
|
низкая, то есть, находится на уровне или ниже recovery_tune_client_util_low.
|
||||||
|
|
||||||
|
## recovery_tune_client_util_low
|
||||||
|
|
||||||
|
- Тип: число
|
||||||
|
- Значение по умолчанию: 0
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Клиентская утилизация, которая считается "низкой".
|
||||||
|
|
||||||
|
## recovery_tune_client_util_high
|
||||||
|
|
||||||
|
- Тип: число
|
||||||
|
- Значение по умолчанию: 0.5
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Клиентская утилизация, которая считается "высокой".
|
||||||
|
|
||||||
|
## recovery_tune_agg_interval
|
||||||
|
|
||||||
|
- Тип: целое число
|
||||||
|
- Значение по умолчанию: 10
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Число последних итераций автоподстройки для расчёта задержки как среднего
|
||||||
|
значения. Меньшие значения параметра ускоряют отклик на изменение нагрузки,
|
||||||
|
большие значения делают задержку стабильнее. Значение по умолчанию 10
|
||||||
|
обычно нормальное и не требует изменений.
|
||||||
|
|
||||||
|
## recovery_tune_sleep_min_us
|
||||||
|
|
||||||
|
- Тип: микросекунды
|
||||||
|
- Значение по умолчанию: 10
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Минимальное возможное значение авто-подстроенного recovery_sleep_us.
|
||||||
|
Меньшие значения заменяются на 0.
|
||||||
|
|
||||||
|
## recovery_tune_sleep_cutoff_us
|
||||||
|
|
||||||
|
- Тип: микросекунды
|
||||||
|
- Значение по умолчанию: 10000000
|
||||||
|
- Можно менять на лету: да
|
||||||
|
|
||||||
|
Максимальное возможное значение авто-подстроенного recovery_sleep_us.
|
||||||
|
Большие значения считаются случайными выбросами и игнорируются в
|
||||||
|
усреднении.
|
||||||
|
|
|
@ -40,6 +40,7 @@ Parameters:
|
||||||
- [root_node](#root_node)
|
- [root_node](#root_node)
|
||||||
- [osd_tags](#osd_tags)
|
- [osd_tags](#osd_tags)
|
||||||
- [primary_affinity_tags](#primary_affinity_tags)
|
- [primary_affinity_tags](#primary_affinity_tags)
|
||||||
|
- [scrub_interval](#scrub_interval)
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
|
@ -204,9 +205,8 @@ This parameter usually doesn't require to be changed.
|
||||||
- Default: 131072
|
- Default: 131072
|
||||||
|
|
||||||
Block size for this pool. The value from /vitastor/config/global is used when
|
Block size for this pool. The value from /vitastor/config/global is used when
|
||||||
unspecified. If your cluster has OSDs with different block sizes then pool must
|
unspecified. Only OSDs with matching block_size are used for each pool. If you
|
||||||
be restricted by [osd_tags](#osd_tags) to only include OSDs with matching block
|
want to further restrict OSDs for the pool, use [osd_tags](#osd_tags).
|
||||||
size.
|
|
||||||
|
|
||||||
Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-cluster.en.md#block_size).
|
Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-cluster.en.md#block_size).
|
||||||
|
|
||||||
|
@ -215,10 +215,9 @@ Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-c
|
||||||
- Type: integer
|
- Type: integer
|
||||||
- Default: 4096
|
- Default: 4096
|
||||||
|
|
||||||
"Sector" size of virtual disks in this pool. The value from
|
"Sector" size of virtual disks in this pool. The value from /vitastor/config/global
|
||||||
/vitastor/config/global is used when unspecified. Similar to block_size, the
|
is used when unspecified. Similarly to block_size, only OSDs with matching
|
||||||
pool must be restricted by [osd_tags](#osd_tags) to only include OSDs with
|
bitmap_granularity are used for each pool.
|
||||||
matching bitmap_granularity.
|
|
||||||
|
|
||||||
Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-cluster.en.md#bitmap_granularity).
|
Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-cluster.en.md#bitmap_granularity).
|
||||||
|
|
||||||
|
@ -228,10 +227,11 @@ Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-c
|
||||||
- Default: none
|
- Default: none
|
||||||
|
|
||||||
Immediate commit setting for this pool. The value from /vitastor/config/global
|
Immediate commit setting for this pool. The value from /vitastor/config/global
|
||||||
is used when unspecified. Similar to block_size, the pool must be restricted by
|
is used when unspecified. Similarly to block_size, only OSDs with compatible
|
||||||
[osd_tags](#osd_tags) to only include OSDs with compatible immediate_commit.
|
bitmap_granularity are used for each pool. "Compatible" means that a pool with
|
||||||
Compatible means that a pool with non-immediate commit will work with OSDs with
|
non-immediate commit will use OSDs with immediate commit enabled, but not vice
|
||||||
immediate commit enabled, but not vice versa.
|
versa. I.e., pools with "none" use all OSDs, pools with "small" only use OSDs
|
||||||
|
with "all" or "small", and pools with "all" only use OSDs with "all".
|
||||||
|
|
||||||
Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-cluster.en.md#immediate_commit).
|
Read more about this parameter in [Cluster-Wide Disk Layout Parameters](layout-cluster.en.md#immediate_commit).
|
||||||
|
|
||||||
|
@ -272,6 +272,13 @@ Specifies OSD tags to prefer putting primary OSDs in this pool to.
|
||||||
Note that for EC/XOR pools Vitastor always prefers to put primary OSD on one
|
Note that for EC/XOR pools Vitastor always prefers to put primary OSD on one
|
||||||
of the OSDs containing a data chunk for a PG.
|
of the OSDs containing a data chunk for a PG.
|
||||||
|
|
||||||
|
## scrub_interval
|
||||||
|
|
||||||
|
- Type: time interval (number + unit s/m/h/d/M/y)
|
||||||
|
|
||||||
|
Automatic scrubbing interval for this pool. Overrides
|
||||||
|
[global scrub_interval setting](osd.en.md#scrub_interval).
|
||||||
|
|
||||||
# Examples
|
# Examples
|
||||||
|
|
||||||
## Replicated pool
|
## Replicated pool
|
||||||
|
|
|
@ -39,6 +39,7 @@
|
||||||
- [root_node](#root_node)
|
- [root_node](#root_node)
|
||||||
- [osd_tags](#osd_tags)
|
- [osd_tags](#osd_tags)
|
||||||
- [primary_affinity_tags](#primary_affinity_tags)
|
- [primary_affinity_tags](#primary_affinity_tags)
|
||||||
|
- [scrub_interval](#scrub_interval)
|
||||||
|
|
||||||
Примеры:
|
Примеры:
|
||||||
|
|
||||||
|
@ -207,8 +208,9 @@ PG в Vitastor эферемерны, то есть вы можете менят
|
||||||
|
|
||||||
Размер блока для данного пула. Если не задан, используется значение из
|
Размер блока для данного пула. Если не задан, используется значение из
|
||||||
/vitastor/config/global. Если в вашем кластере есть OSD с разными размерами
|
/vitastor/config/global. Если в вашем кластере есть OSD с разными размерами
|
||||||
блока, пул должен быть ограничен только OSD, блок которых равен блоку пула,
|
блока, пул будет использовать только OSD с размером блока, равным размеру блока
|
||||||
с помощью [osd_tags](#osd_tags).
|
пула. Если вы хотите сильнее ограничить набор используемых для пула OSD -
|
||||||
|
используйте [osd_tags](#osd_tags).
|
||||||
|
|
||||||
О самом параметре читайте в разделе [Дисковые параметры уровня кластера](layout-cluster.ru.md#block_size).
|
О самом параметре читайте в разделе [Дисковые параметры уровня кластера](layout-cluster.ru.md#block_size).
|
||||||
|
|
||||||
|
@ -218,9 +220,8 @@ PG в Vitastor эферемерны, то есть вы можете менят
|
||||||
- По умолчанию: 4096
|
- По умолчанию: 4096
|
||||||
|
|
||||||
Размер "сектора" виртуальных дисков в данном пуле. Если не задан, используется
|
Размер "сектора" виртуальных дисков в данном пуле. Если не задан, используется
|
||||||
значение из /vitastor/config/global. Аналогично block_size, пул должен быть
|
значение из /vitastor/config/global. Аналогично block_size, каждый пул будет
|
||||||
ограничен OSD со значением bitmap_granularity, равным значению пула, с помощью
|
использовать только OSD с совпадающей с пулом настройкой bitmap_granularity.
|
||||||
[osd_tags](#osd_tags).
|
|
||||||
|
|
||||||
О самом параметре читайте в разделе [Дисковые параметры уровня кластера](layout-cluster.ru.md#bitmap_granularity).
|
О самом параметре читайте в разделе [Дисковые параметры уровня кластера](layout-cluster.ru.md#bitmap_granularity).
|
||||||
|
|
||||||
|
@ -230,11 +231,13 @@ PG в Vitastor эферемерны, то есть вы можете менят
|
||||||
- По умолчанию: none
|
- По умолчанию: none
|
||||||
|
|
||||||
Настройка мгновенного коммита для данного пула. Если не задана, используется
|
Настройка мгновенного коммита для данного пула. Если не задана, используется
|
||||||
значение из /vitastor/config/global. Аналогично block_size, пул должен быть
|
значение из /vitastor/config/global. Аналогично block_size, каждый пул будет
|
||||||
ограничен OSD со значением bitmap_granularity, совместимым со значением пула, с
|
использовать только OSD с *совместимыми* настройками immediate_commit.
|
||||||
помощью [osd_tags](#osd_tags). Совместимость означает, что пул с отключенным
|
"Совместимыми" означает, что пул с отключенным мгновенным коммитом будет
|
||||||
мгновенным коммитом может работать на OSD с включённым мгновенным коммитом, но
|
использовать OSD с включённым мгновенным коммитом, но не наоборот. То есть,
|
||||||
не наоборот.
|
пул со значением "none" будет использовать все OSD, пул со "small" будет
|
||||||
|
использовать OSD с "all" или "small", а пул с "all" будет использовать только
|
||||||
|
OSD с "all".
|
||||||
|
|
||||||
О самом параметре читайте в разделе [Дисковые параметры уровня кластера](layout-cluster.ru.md#immediate_commit).
|
О самом параметре читайте в разделе [Дисковые параметры уровня кластера](layout-cluster.ru.md#immediate_commit).
|
||||||
|
|
||||||
|
@ -276,6 +279,13 @@ PG в Vitastor эферемерны, то есть вы можете менят
|
||||||
для PG этого пула. Имейте в виду, что для EC-пулов Vitastor также всегда
|
для PG этого пула. Имейте в виду, что для EC-пулов Vitastor также всегда
|
||||||
предпочитает помещать первичный OSD на один из OSD с данными, а не с чётностью.
|
предпочитает помещать первичный OSD на один из OSD с данными, а не с чётностью.
|
||||||
|
|
||||||
|
## scrub_interval
|
||||||
|
|
||||||
|
- Тип: временной интервал (число + единица измерения s/m/h/d/M/y)
|
||||||
|
|
||||||
|
Интервал скраба, то есть, автоматической фоновой проверки данных для данного пула.
|
||||||
|
Переопределяет [глобальную настройку scrub_interval](osd.ru.md#scrub_interval).
|
||||||
|
|
||||||
# Примеры
|
# Примеры
|
||||||
|
|
||||||
## Реплицированный пул
|
## Реплицированный пул
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Client Parameters
|
||||||
|
|
||||||
|
These parameters apply only to Vitastor clients (QEMU, fio, NBD and so on) and
|
||||||
|
affect their interaction with the cluster.
|
|
@ -0,0 +1,4 @@
|
||||||
|
# Параметры клиентского кода
|
||||||
|
|
||||||
|
Данные параметры применяются только к клиентам Vitastor (QEMU, fio, NBD и т.п.) и
|
||||||
|
затрагивают логику их работы с кластером.
|
|
@ -0,0 +1,168 @@
|
||||||
|
- name: client_max_dirty_bytes
|
||||||
|
type: int
|
||||||
|
default: 33554432
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Without [immediate_commit](layout-cluster.en.md#immediate_commit)=all this parameter sets the limit of "dirty"
|
||||||
|
(not committed by fsync) data allowed by the client before forcing an
|
||||||
|
additional fsync and committing the data. Also note that the client always
|
||||||
|
holds a copy of uncommitted data in memory so this setting also affects
|
||||||
|
RAM usage of clients.
|
||||||
|
info_ru: |
|
||||||
|
При работе без [immediate_commit](layout-cluster.ru.md#immediate_commit)=all - это лимит объёма "грязных" (не
|
||||||
|
зафиксированных fsync-ом) данных, при достижении которого клиент будет
|
||||||
|
принудительно вызывать fsync и фиксировать данные. Также стоит иметь в виду,
|
||||||
|
что в этом случае до момента fsync клиент хранит копию незафиксированных
|
||||||
|
данных в памяти, то есть, настройка влияет на потребление памяти клиентами.
|
||||||
|
- name: client_max_dirty_ops
|
||||||
|
type: int
|
||||||
|
default: 1024
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Same as client_max_dirty_bytes, but instead of total size, limits the number
|
||||||
|
of uncommitted write operations.
|
||||||
|
info_ru: |
|
||||||
|
Аналогично client_max_dirty_bytes, но ограничивает количество
|
||||||
|
незафиксированных операций записи вместо их общего объёма.
|
||||||
|
- name: client_enable_writeback
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
This parameter enables client-side write buffering. This means that write
|
||||||
|
requests are accumulated in memory for a short time before being sent to
|
||||||
|
a Vitastor cluster which allows to send them in parallel and increase
|
||||||
|
performance of some applications. Writes are buffered until client forces
|
||||||
|
a flush with fsync() or until the amount of buffered writes exceeds the
|
||||||
|
limit.
|
||||||
|
|
||||||
|
Write buffering significantly increases performance of some applications,
|
||||||
|
for example, CrystalDiskMark under Windows (LOL :-D), but also any other
|
||||||
|
applications if they do writes in one of two non-optimal ways: either if
|
||||||
|
they do a lot of small (4 kb or so) sequential writes, or if they do a lot
|
||||||
|
of small random writes, but without any parallelism or asynchrony, and also
|
||||||
|
without calling fsync().
|
||||||
|
|
||||||
|
With write buffering enabled, you can expect around 22000 T1Q1 random write
|
||||||
|
iops in QEMU more or less regardless of the quality of your SSDs, and this
|
||||||
|
number is in fact bound by QEMU itself rather than Vitastor (check it
|
||||||
|
yourself by adding a "driver=null-co" disk in QEMU). Without write
|
||||||
|
buffering, the current record is 9900 iops, but the number is usually
|
||||||
|
even lower with non-ideal hardware, for example, it may be 5000 iops.
|
||||||
|
|
||||||
|
Even when this parameter is enabled, write buffering isn't enabled until
|
||||||
|
the client explicitly allows it, because enabling it without the client
|
||||||
|
being aware of the fact that his writes may be buffered may lead to data
|
||||||
|
loss. Because of this, older versions of clients don't support write
|
||||||
|
buffering at all, newer versions of the QEMU driver allow write buffering
|
||||||
|
only if it's enabled in disk settings with `-blockdev cache.direct=false`,
|
||||||
|
and newer versions of FIO only allow write buffering if you don't specify
|
||||||
|
`-direct=1`. NBD and NFS drivers allow write buffering by default.
|
||||||
|
|
||||||
|
You can overcome this restriction too with the `client_writeback_allowed`
|
||||||
|
parameter, but you shouldn't do that unless you **really** know what you
|
||||||
|
are doing.
|
||||||
|
info_ru: |
|
||||||
|
Данный параметр разрешает включать буферизацию записи в памяти. Буферизация
|
||||||
|
означает, что операции записи отправляются на кластер Vitastor не сразу, а
|
||||||
|
могут небольшое время накапливаться в памяти и сбрасываться сразу пакетами,
|
||||||
|
до тех пор, пока либо не будет превышен лимит неотправленных записей, либо
|
||||||
|
пока клиент не вызовет fsync.
|
||||||
|
|
||||||
|
Буферизация значительно повышает производительность некоторых приложений,
|
||||||
|
например, CrystalDiskMark в Windows (ха-ха :-D), но также и любых других,
|
||||||
|
которые пишут на диск неоптимально: либо последовательно, но мелкими блоками
|
||||||
|
(например, по 4 кб), либо случайно, но без параллелизма и без fsync - то
|
||||||
|
есть, например, отправляя 128 операций записи в разные места диска, но не
|
||||||
|
все сразу с помощью асинхронного I/O, а по одной.
|
||||||
|
|
||||||
|
В QEMU с буферизацией записи можно ожидать показателя примерно 22000
|
||||||
|
операций случайной записи в секунду в 1 поток и с глубиной очереди 1 (T1Q1)
|
||||||
|
без fsync, почти вне зависимости от того, насколько хороши ваши диски - эта
|
||||||
|
цифра упирается в сам QEMU. Без буферизации рекорд пока что - 9900 операций
|
||||||
|
в секунду, но на железе похуже может быть и поменьше, например, 5000 операций
|
||||||
|
в секунду.
|
||||||
|
|
||||||
|
При этом, даже если данный параметр включён, буферизация не включается, если
|
||||||
|
явно не разрешена клиентом, т.к. если клиент не знает, что запросы записи
|
||||||
|
буферизуются, это может приводить к потере данных. Поэтому в старых версиях
|
||||||
|
клиентских драйверов буферизация записи не включается вообще, в новых
|
||||||
|
версиях QEMU-драйвера включается, только если разрешена опцией диска
|
||||||
|
`-blockdev cache.direct=false`, а в fio - только если нет опции `-direct=1`.
|
||||||
|
В NBD и NFS драйверах буферизация записи разрешена по умолчанию.
|
||||||
|
|
||||||
|
Можно обойти и это ограничение с помощью параметра `client_writeback_allowed`,
|
||||||
|
но делать так не надо, если только вы не уверены в том, что делаете, на все
|
||||||
|
100%. :-)
|
||||||
|
- name: client_max_buffered_bytes
|
||||||
|
type: int
|
||||||
|
default: 33554432
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Maximum total size of buffered writes which triggers write-back when reached.
|
||||||
|
info_ru: |
|
||||||
|
Максимальный общий размер буферизованных записей, при достижении которого
|
||||||
|
начинается процесс сброса данных на сервер.
|
||||||
|
- name: client_max_buffered_ops
|
||||||
|
type: int
|
||||||
|
default: 1024
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Maximum number of buffered writes which triggers write-back when reached.
|
||||||
|
Multiple consecutive modified data regions are counted as 1 write here.
|
||||||
|
info_ru: |
|
||||||
|
Максимальное количество буферизованных записей, при достижении которого
|
||||||
|
начинается процесс сброса данных на сервер. При этом несколько
|
||||||
|
последовательных изменённых областей здесь считаются 1 записью.
|
||||||
|
- name: client_max_writeback_iodepth
|
||||||
|
type: int
|
||||||
|
default: 256
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Maximum number of parallel writes when flushing buffered data to the server.
|
||||||
|
info_ru: |
|
||||||
|
Максимальное число параллельных операций записи при сбросе буферов на сервер.
|
||||||
|
- name: nbd_timeout
|
||||||
|
type: sec
|
||||||
|
default: 300
|
||||||
|
online: false
|
||||||
|
info: |
|
||||||
|
Timeout for I/O operations for [NBD](../usage/nbd.en.md). If an operation
|
||||||
|
executes for longer than this timeout, including when your cluster is just
|
||||||
|
temporarily down for more than timeout, the NBD device will detach by itself
|
||||||
|
(and possibly break the mounted file system).
|
||||||
|
|
||||||
|
You can set timeout to 0 to never detach, but in that case you won't be
|
||||||
|
able to remove the kernel device at all if the NBD process dies - you'll have
|
||||||
|
to reboot the host.
|
||||||
|
info_ru: |
|
||||||
|
Таймаут для операций чтения/записи через [NBD](../usage/nbd.ru.md). Если
|
||||||
|
операция выполняется дольше таймаута, включая временную недоступность
|
||||||
|
кластера на время, большее таймаута, NBD-устройство отключится само собой
|
||||||
|
(и, возможно, сломает примонтированную ФС).
|
||||||
|
|
||||||
|
Вы можете установить таймаут в 0, чтобы никогда не отключать устройство по
|
||||||
|
таймауту, но в этом случае вы вообще не сможете удалить устройство, если
|
||||||
|
процесс NBD умрёт - вам придётся перезагружать сервер.
|
||||||
|
- name: nbd_max_devices
|
||||||
|
type: int
|
||||||
|
default: 64
|
||||||
|
online: false
|
||||||
|
info: |
|
||||||
|
Maximum number of NBD devices in the system. This value is passed as
|
||||||
|
`nbds_max` parameter for the nbd kernel module when vitastor-nbd autoloads it.
|
||||||
|
info_ru: |
|
||||||
|
Максимальное число NBD-устройств в системе. Данное значение передаётся
|
||||||
|
модулю ядра nbd как параметр `nbds_max`, когда его загружает vitastor-nbd.
|
||||||
|
- name: nbd_max_part
|
||||||
|
type: int
|
||||||
|
default: 3
|
||||||
|
online: false
|
||||||
|
info: |
|
||||||
|
Maximum number of partitions per NBD device. This value is passed as
|
||||||
|
`max_part` parameter for the nbd kernel module when vitastor-nbd autoloads it.
|
||||||
|
Note that (nbds_max)*(1+max_part) usually can't exceed 256.
|
||||||
|
info_ru: |
|
||||||
|
Максимальное число разделов на одном NBD-устройстве. Данное значение передаётся
|
||||||
|
модулю ядра nbd как параметр `max_part`, когда его загружает vitastor-nbd.
|
||||||
|
Имейте в виду, что (nbds_max)*(1+max_part) обычно не может превышать 256.
|
|
@ -11,13 +11,21 @@
|
||||||
- name: etcd_address
|
- name: etcd_address
|
||||||
type: string or array of strings
|
type: string or array of strings
|
||||||
type_ru: строка или массив строк
|
type_ru: строка или массив строк
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
etcd connection endpoint(s). Multiple endpoints may be delimited by "," or
|
etcd connection endpoint(s). Multiple endpoints may be delimited by "," or
|
||||||
specified in a JSON array `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
specified in a JSON array `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
||||||
Note that https is not supported for etcd connections yet.
|
Note that https is not supported for etcd connections yet.
|
||||||
|
|
||||||
|
etcd connection endpoints can be changed online by updating global
|
||||||
|
configuration in etcd itself - this allows to switch the cluster to new
|
||||||
|
etcd addresses without downtime.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Адрес(а) подключения к etcd. Несколько адресов могут разделяться запятой
|
Адрес(а) подключения к etcd. Несколько адресов могут разделяться запятой
|
||||||
или указываться в виде JSON-массива `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
или указываться в виде JSON-массива `["10.0.115.10:2379/v3","10.0.115.11:2379/v3"]`.
|
||||||
|
|
||||||
|
Адреса подключения к etcd можно поменять на лету, обновив конфигурацию в
|
||||||
|
самом etcd - это позволяет переключить кластер на новые etcd без остановки.
|
||||||
- name: etcd_prefix
|
- name: etcd_prefix
|
||||||
type: string
|
type: string
|
||||||
default: "/vitastor"
|
default: "/vitastor"
|
||||||
|
@ -31,5 +39,6 @@
|
||||||
- name: log_level
|
- name: log_level
|
||||||
type: int
|
type: int
|
||||||
default: 0
|
default: 0
|
||||||
|
online: true
|
||||||
info: Log level. Raise if you want more verbose output.
|
info: Log level. Raise if you want more verbose output.
|
||||||
info_ru: Уровень логгирования. Повысьте, если хотите более подробный вывод.
|
info_ru: Уровень логгирования. Повысьте, если хотите более подробный вывод.
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
#!/usr/bin/nodejs
|
||||||
|
|
||||||
|
const fsp = require('fs').promises;
|
||||||
|
|
||||||
|
run(process.argv).catch(console.error);
|
||||||
|
|
||||||
|
async function run(argv)
|
||||||
|
{
|
||||||
|
if (argv.length < 3)
|
||||||
|
{
|
||||||
|
console.log('Markdown preprocessor\nUSAGE: ./include.js file.md');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const index_file = await fsp.realpath(argv[2]);
|
||||||
|
const re = /(\{\{[\s\S]*?\}\}|\[[^\]]+\]\([^\)]+\)|(?:^|\n)#[^\n]+)/;
|
||||||
|
let text = await fsp.readFile(index_file, { encoding: 'utf-8' });
|
||||||
|
text = text.split(re);
|
||||||
|
let included = {};
|
||||||
|
let heading = 0, heading_name = '', m;
|
||||||
|
for (let i = 0; i < text.length; i++)
|
||||||
|
{
|
||||||
|
if (text[i].substr(0, 2) == '{{')
|
||||||
|
{
|
||||||
|
// Inclusion
|
||||||
|
let incfile = text[i].substr(2, text[i].length-4);
|
||||||
|
let section = null;
|
||||||
|
let indent = heading;
|
||||||
|
incfile = incfile.replace(/\s*\|\s*indent\s*=\s*(-?\d+)\s*$/, (m, m1) => { indent = parseInt(m1); return ''; });
|
||||||
|
incfile = incfile.replace(/\s*#\s*([^#]+)$/, (m, m1) => { section = m1; return ''; });
|
||||||
|
let inc_heading = section;
|
||||||
|
incfile = rel2abs(index_file, incfile);
|
||||||
|
let inc = await fsp.readFile(incfile, { encoding: 'utf-8' });
|
||||||
|
inc = inc.trim().replace(/^[\s\S]+?\n#/, '#'); // remove until the first header
|
||||||
|
inc = inc.split(re);
|
||||||
|
const indent_str = new Array(indent+1).join('#');
|
||||||
|
let section_start = -1, section_end = -1;
|
||||||
|
for (let j = 0; j < inc.length; j++)
|
||||||
|
{
|
||||||
|
if ((m = /^(\n?)(#+\s*)([\s\S]+)$/.exec(inc[j])))
|
||||||
|
{
|
||||||
|
if (!inc_heading)
|
||||||
|
{
|
||||||
|
inc_heading = m[3].trim();
|
||||||
|
}
|
||||||
|
if (section)
|
||||||
|
{
|
||||||
|
if (m[3].trim() == section)
|
||||||
|
section_start = j;
|
||||||
|
else if (section_start >= 0)
|
||||||
|
{
|
||||||
|
section_end = j;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
inc[j] = m[1] + indent_str + m[2] + m[3];
|
||||||
|
}
|
||||||
|
else if ((m = /^(\[[^\]]+\]\()([^\)]+)(\))$/.exec(inc[j])) && !/^https?:(\/\/)|^#/.exec(m[2]))
|
||||||
|
{
|
||||||
|
const abs_m2 = rel2abs(incfile, m[2]);
|
||||||
|
const rel_m = abs2rel(__filename, abs_m2);
|
||||||
|
if (rel_m.substr(0, 9) == '../../../') // outside docs
|
||||||
|
inc[j] = m[1] + 'https://git.yourcmc.ru/vitalif/vitastor/src/branch/master/'+rel2abs('docs/config/src/include.js', rel_m) + m[3];
|
||||||
|
else
|
||||||
|
inc[j] = m[1] + abs_m2 + m[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (section)
|
||||||
|
{
|
||||||
|
inc = section_start >= 0 ? inc.slice(section_start, section_end < 0 ? inc.length : section_end) : [];
|
||||||
|
}
|
||||||
|
if (inc.length)
|
||||||
|
{
|
||||||
|
if (!inc_heading)
|
||||||
|
inc_heading = heading_name||'';
|
||||||
|
included[incfile+(section ? '#'+section : '')] = '#'+inc_heading.toLowerCase().replace(/\P{L}+/ug, '-').replace(/^-|-$/g, '');
|
||||||
|
inc[0] = inc[0].replace(/^\s+/, '');
|
||||||
|
inc[inc.length-1] = inc[inc.length-1].replace(/\s+$/, '');
|
||||||
|
}
|
||||||
|
text.splice(i, 1, ...inc);
|
||||||
|
i = i + inc.length - 1;
|
||||||
|
}
|
||||||
|
else if ((m = /^\n?(#+)\s*([\s\S]+)$/.exec(text[i])))
|
||||||
|
{
|
||||||
|
// Heading
|
||||||
|
heading = m[1].length;
|
||||||
|
heading_name = m[2].trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (let i = 0; i < text.length; i++)
|
||||||
|
{
|
||||||
|
if ((m = /^(\[[^\]]+\]\()([^\)]+)(\))$/.exec(text[i])) && !/^https?:(\/\/)|^#/.exec(m[2]))
|
||||||
|
{
|
||||||
|
const p = m[2].indexOf('#');
|
||||||
|
if (included[m[2]])
|
||||||
|
{
|
||||||
|
text[i] = m[1]+included[m[2]]+m[3];
|
||||||
|
}
|
||||||
|
else if (p >= 0 && included[m[2].substr(0, p)])
|
||||||
|
{
|
||||||
|
text[i] = m[1]+m[2].substr(p)+m[3];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
console.log(text.join(''));
|
||||||
|
}
|
||||||
|
|
||||||
|
function rel2abs(ref, rel)
|
||||||
|
{
|
||||||
|
rel = [ ...ref.replace(/^(.*)\/[^\/]+$/, '$1').split(/\/+/), ...rel.split(/\/+/) ];
|
||||||
|
return killdots(rel).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
function abs2rel(ref, abs)
|
||||||
|
{
|
||||||
|
ref = ref.split(/\/+/);
|
||||||
|
abs = abs.split(/\/+/);
|
||||||
|
while (ref.length > 1 && ref[0] == abs[0])
|
||||||
|
{
|
||||||
|
ref.shift();
|
||||||
|
abs.shift();
|
||||||
|
}
|
||||||
|
for (let i = 1; i < ref.length; i++)
|
||||||
|
{
|
||||||
|
abs.unshift('..');
|
||||||
|
}
|
||||||
|
return killdots(abs).join('/');
|
||||||
|
}
|
||||||
|
|
||||||
|
function killdots(rel)
|
||||||
|
{
|
||||||
|
for (let i = 0; i < rel.length; i++)
|
||||||
|
{
|
||||||
|
if (rel[i] == '.')
|
||||||
|
{
|
||||||
|
rel.splice(i, 1);
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
else if (i >= 1 && rel[i] == '..' && rel[i-1] != '..')
|
||||||
|
{
|
||||||
|
rel.splice(i-1, 2);
|
||||||
|
i -= 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return rel;
|
||||||
|
}
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Vitastor
|
||||||
|
|
||||||
|
{{../../../README.md#The Idea}}
|
||||||
|
|
||||||
|
{{../../../README.md#Talks and presentations}}
|
||||||
|
|
||||||
|
{{../../intro/features.en.md}}
|
||||||
|
|
||||||
|
{{../../intro/quickstart.en.md}}
|
||||||
|
|
||||||
|
{{../../intro/architecture.en.md}}
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
{{../../installation/packages.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/proxmox.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/openstack.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/kubernetes.en.md}}
|
||||||
|
|
||||||
|
{{../../installation/source.en.md}}
|
||||||
|
|
||||||
|
{{../../config.en.md|indent=1}}
|
||||||
|
|
||||||
|
{{../../config/common.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/network.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/client.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-cluster.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-osd.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/osd.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/monitor.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/pool.en.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/inode.en.md|indent=2}}
|
||||||
|
|
||||||
|
## Usage
|
||||||
|
|
||||||
|
{{../../usage/cli.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/disk.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/fio.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/nbd.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/qemu.en.md}}
|
||||||
|
|
||||||
|
{{../../usage/nfs.en.md}}
|
||||||
|
|
||||||
|
## Performance
|
||||||
|
|
||||||
|
{{../../performance/understanding.en.md}}
|
||||||
|
|
||||||
|
{{../../performance/theoretical.en.md}}
|
||||||
|
|
||||||
|
{{../../performance/comparison1.en.md}}
|
||||||
|
|
||||||
|
{{../../intro/author.en.md|indent=1}}
|
|
@ -0,0 +1,67 @@
|
||||||
|
# Vitastor
|
||||||
|
|
||||||
|
{{../../../README-ru.md#Идея|indent=0}}
|
||||||
|
|
||||||
|
{{../../../README-ru.md#Презентации и записи докладов|indent=0}}
|
||||||
|
|
||||||
|
{{../../intro/features.ru.md}}
|
||||||
|
|
||||||
|
{{../../intro/quickstart.ru.md}}
|
||||||
|
|
||||||
|
{{../../intro/architecture.ru.md}}
|
||||||
|
|
||||||
|
## Установка
|
||||||
|
|
||||||
|
{{../../installation/packages.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/proxmox.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/openstack.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/kubernetes.ru.md}}
|
||||||
|
|
||||||
|
{{../../installation/source.ru.md}}
|
||||||
|
|
||||||
|
{{../../config.ru.md|indent=1}}
|
||||||
|
|
||||||
|
{{../../config/common.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/network.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/client.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-cluster.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/layout-osd.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/osd.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/monitor.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/pool.ru.md|indent=2}}
|
||||||
|
|
||||||
|
{{../../config/inode.ru.md|indent=2}}
|
||||||
|
|
||||||
|
## Использование
|
||||||
|
|
||||||
|
{{../../usage/cli.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/disk.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/fio.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/nbd.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/qemu.ru.md}}
|
||||||
|
|
||||||
|
{{../../usage/nfs.ru.md}}
|
||||||
|
|
||||||
|
## Производительность
|
||||||
|
|
||||||
|
{{../../performance/understanding.ru.md}}
|
||||||
|
|
||||||
|
{{../../performance/theoretical.ru.md}}
|
||||||
|
|
||||||
|
{{../../performance/comparison1.ru.md}}
|
||||||
|
|
||||||
|
{{../../intro/author.ru.md|indent=1}}
|
|
@ -7,26 +7,27 @@
|
||||||
in Vitastor, affects memory usage, write amplification and I/O load
|
in Vitastor, affects memory usage, write amplification and I/O load
|
||||||
distribution effectiveness.
|
distribution effectiveness.
|
||||||
|
|
||||||
Recommended default block size is 128 KB for SSD and 4 MB for HDD. In fact,
|
Recommended default block size is 128 KB for SSD and 1 MB for HDD. In fact,
|
||||||
it's possible to use 4 MB for SSD too - it will lower memory usage, but
|
it's possible to use 1 MB for SSD too - it will lower memory usage, but
|
||||||
may increase average WA and reduce linear performance.
|
may increase average WA and reduce linear performance.
|
||||||
|
|
||||||
OSD memory usage is roughly (SIZE / BLOCK * 68 bytes) which is roughly
|
OSD memory usage is roughly (SIZE / BLOCK * 68 bytes) which is roughly
|
||||||
544 MB per 1 TB of used disk space with the default 128 KB block size.
|
544 MB per 1 TB of used disk space with the default 128 KB block size.
|
||||||
|
With 1 MB it's 8 times lower.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Размер объектов (блоков данных), на которые делятся физические и виртуальные
|
Размер объектов (блоков данных), на которые делятся физические и виртуальные
|
||||||
диски в Vitastor (в рамках каждого пула). Одна из ключевых на данный момент
|
диски в Vitastor (в рамках каждого пула). Одна из ключевых на данный момент
|
||||||
настроек, влияет на потребление памяти, объём избыточной записи (write
|
настроек, влияет на потребление памяти, объём избыточной записи (write
|
||||||
amplification) и эффективность распределения нагрузки по OSD.
|
amplification) и эффективность распределения нагрузки по OSD.
|
||||||
|
|
||||||
Рекомендуемые по умолчанию размеры блока - 128 килобайт для SSD и 4
|
Рекомендуемые по умолчанию размеры блока - 128 килобайт для SSD и 1 мегабайт
|
||||||
мегабайта для HDD. В принципе, для SSD можно тоже использовать 4 мегабайта,
|
для HDD. В принципе, для SSD можно тоже использовать блок размером 1 мегабайт,
|
||||||
это понизит использование памяти, но ухудшит распределение нагрузки и в
|
это понизит использование памяти, но ухудшит распределение нагрузки и в
|
||||||
среднем увеличит WA.
|
среднем увеличит WA.
|
||||||
|
|
||||||
Потребление памяти OSD составляет примерно (РАЗМЕР / БЛОК * 68 байт),
|
Потребление памяти OSD составляет примерно (РАЗМЕР / БЛОК * 68 байт),
|
||||||
т.е. примерно 544 МБ памяти на 1 ТБ занятого места на диске при
|
т.е. примерно 544 МБ памяти на 1 ТБ занятого места на диске при
|
||||||
стандартном 128 КБ блоке.
|
стандартном 128 КБ блоке. При 1 МБ блоке памяти нужно в 8 раз меньше.
|
||||||
- name: bitmap_granularity
|
- name: bitmap_granularity
|
||||||
type: int
|
type: int
|
||||||
default: 4096
|
default: 4096
|
||||||
|
@ -86,8 +87,9 @@
|
||||||
it (they have internal SSD cache even though it's not stated in datasheets).
|
it (they have internal SSD cache even though it's not stated in datasheets).
|
||||||
|
|
||||||
Setting this parameter to "all" or "small" in OSD parameters requires enabling
|
Setting this parameter to "all" or "small" in OSD parameters requires enabling
|
||||||
disable_journal_fsync and disable_meta_fsync, setting it to "all" also requires
|
[disable_journal_fsync](layout-osd.en.yml#disable_journal_fsync) and
|
||||||
enabling disable_data_fsync.
|
[disable_meta_fsync](layout-osd.en.yml#disable_meta_fsync), setting it to
|
||||||
|
"all" also requires enabling [disable_data_fsync](layout-osd.en.yml#disable_data_fsync).
|
||||||
|
|
||||||
TLDR: For optimal performance, set immediate_commit to "all" if you only use
|
TLDR: For optimal performance, set immediate_commit to "all" if you only use
|
||||||
SSDs with supercapacitor-based power loss protection (nonvolatile
|
SSDs with supercapacitor-based power loss protection (nonvolatile
|
||||||
|
@ -139,8 +141,9 @@
|
||||||
указано в спецификациях).
|
указано в спецификациях).
|
||||||
|
|
||||||
Указание "all" или "small" в настройках / командной строке OSD требует
|
Указание "all" или "small" в настройках / командной строке OSD требует
|
||||||
включения disable_journal_fsync и disable_meta_fsync, значение "all" также
|
включения [disable_journal_fsync](layout-osd.ru.yml#disable_journal_fsync) и
|
||||||
требует включения disable_data_fsync.
|
[disable_meta_fsync](layout-osd.ru.yml#disable_meta_fsync), значение "all"
|
||||||
|
также требует включения [disable_data_fsync](layout-osd.ru.yml#disable_data_fsync).
|
||||||
|
|
||||||
Итого, вкратце: для оптимальной производительности установите
|
Итого, вкратце: для оптимальной производительности установите
|
||||||
immediate_commit в значение "all", если вы используете в кластере только SSD
|
immediate_commit в значение "all", если вы используете в кластере только SSD
|
||||||
|
|
|
@ -204,3 +204,73 @@
|
||||||
|
|
||||||
Клиентам не обязательно знать про disk_alignment, так что помещать значение
|
Клиентам не обязательно знать про disk_alignment, так что помещать значение
|
||||||
этого параметра в etcd в /vitastor/config/global не нужно.
|
этого параметра в etcd в /vitastor/config/global не нужно.
|
||||||
|
- name: data_csum_type
|
||||||
|
type: string
|
||||||
|
default: none
|
||||||
|
info: |
|
||||||
|
Data checksum type to use. May be "crc32c" or "none". Set to "crc32c" to
|
||||||
|
enable data checksums.
|
||||||
|
info_ru: |
|
||||||
|
Тип используемых OSD контрольных сумм данных. Может быть "crc32c" или "none".
|
||||||
|
Установите в "crc32c", чтобы включить расчёт и проверку контрольных сумм данных.
|
||||||
|
|
||||||
|
Следует понимать, что контрольные суммы в зависимости от размера блока их
|
||||||
|
расчёта либо увеличивают потребление памяти, либо снижают производительность.
|
||||||
|
Подробнее смотрите в описании параметра [csum_block_size](#csum_block_size).
|
||||||
|
- name: csum_block_size
|
||||||
|
type: int
|
||||||
|
default: 4096
|
||||||
|
info: |
|
||||||
|
Checksum calculation block size.
|
||||||
|
|
||||||
|
Must be equal or a multiple of [bitmap_granularity](layout-cluster.en.md#bitmap_granularity)
|
||||||
|
(which is usually 4 KB).
|
||||||
|
|
||||||
|
Checksums increase metadata size by 4 bytes per each csum_block_size of data.
|
||||||
|
|
||||||
|
Checksums are always a tradeoff:
|
||||||
|
1. You either sacrifice +1 GB RAM per 1 TB of data
|
||||||
|
2. Or you raise csum_block_size, for example, to 32k and sacrifice
|
||||||
|
50% random write iops due to checksum read-modify-write
|
||||||
|
3. Or you turn off [inmemory_metadata](osd.en.md#inmemory_metadata) and
|
||||||
|
sacrifice 50% random read iops due to checksum reads
|
||||||
|
|
||||||
|
All-flash clusters usually have enough RAM to use default csum_block_size,
|
||||||
|
which uses 1 GB RAM per 1 TB of data. HDD clusters usually don't.
|
||||||
|
|
||||||
|
Thus, recommended setups are:
|
||||||
|
1. All-flash, 1 GB RAM per 1 TB data: default (csum_block_size=4k)
|
||||||
|
2. All-flash, less RAM: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
3. Hybrid HDD+SSD: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
4. HDD-only, faster random read: csum_block_size=32k
|
||||||
|
5. HDD-only, faster random write: csum_block_size=4k +
|
||||||
|
inmemory_metadata=false + meta_io=cached
|
||||||
|
|
||||||
|
See also [meta_io](osd.en.md#meta_io).
|
||||||
|
info_ru: |
|
||||||
|
Размер блока расчёта контрольных сумм.
|
||||||
|
|
||||||
|
Должен быть равен или кратен [bitmap_granularity](layout-cluster.ru.md#bitmap_granularity)
|
||||||
|
(который обычно равен 4 КБ).
|
||||||
|
|
||||||
|
Контрольные суммы увеличивают размер метаданных на 4 байта на каждые
|
||||||
|
csum_block_size данных.
|
||||||
|
|
||||||
|
Контрольные суммы - это всегда компромисс:
|
||||||
|
1. Вы либо жертвуете потреблением +1 ГБ памяти на 1 ТБ дискового пространства
|
||||||
|
2. Либо вы повышаете csum_block_size до, скажем, 32k и жертвуете 50%
|
||||||
|
скорости случайной записи из-за цикла чтения-изменения-записи для расчёта
|
||||||
|
новых контрольных сумм
|
||||||
|
3. Либо вы отключаете [inmemory_metadata](osd.ru.md#inmemory_metadata) и
|
||||||
|
жертвуете 50% скорости случайного чтения из-за чтения контрольных сумм
|
||||||
|
с диска
|
||||||
|
|
||||||
|
Таким образом, рекомендуются следующие варианты настроек:
|
||||||
|
1. All-flash, 1 ГБ памяти на 1 ТБ данных: по умолчанию (csum_block_size=4k)
|
||||||
|
2. All-flash, меньше памяти: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
3. Гибридные HDD+SSD: csum_block_size=4k + inmemory_metadata=false
|
||||||
|
4. Только HDD, быстрее случайное чтение: csum_block_size=32k
|
||||||
|
5. Только HDD, быстрее случайная запись: csum_block_size=4k +
|
||||||
|
inmemory_metadata=false + meta_io=cached
|
||||||
|
|
||||||
|
Смотрите также [meta_io](osd.ru.md#meta_io).
|
||||||
|
|
|
@ -14,6 +14,7 @@ const L = {
|
||||||
toc_config: '[Configuration](../config.en.md)',
|
toc_config: '[Configuration](../config.en.md)',
|
||||||
toc_usage: 'Usage',
|
toc_usage: 'Usage',
|
||||||
toc_performance: 'Performance',
|
toc_performance: 'Performance',
|
||||||
|
online: 'Can be changed online: yes',
|
||||||
},
|
},
|
||||||
ru: {
|
ru: {
|
||||||
Documentation: 'Документация',
|
Documentation: 'Документация',
|
||||||
|
@ -28,6 +29,7 @@ const L = {
|
||||||
toc_config: '[Конфигурация](../config.ru.md)',
|
toc_config: '[Конфигурация](../config.ru.md)',
|
||||||
toc_usage: 'Использование',
|
toc_usage: 'Использование',
|
||||||
toc_performance: 'Производительность',
|
toc_performance: 'Производительность',
|
||||||
|
online: 'Можно менять на лету: да',
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
const types = {
|
const types = {
|
||||||
|
@ -36,6 +38,7 @@ const types = {
|
||||||
bool: 'boolean',
|
bool: 'boolean',
|
||||||
int: 'integer',
|
int: 'integer',
|
||||||
sec: 'seconds',
|
sec: 'seconds',
|
||||||
|
float: 'number',
|
||||||
ms: 'milliseconds',
|
ms: 'milliseconds',
|
||||||
us: 'microseconds',
|
us: 'microseconds',
|
||||||
},
|
},
|
||||||
|
@ -44,6 +47,7 @@ const types = {
|
||||||
bool: 'булево (да/нет)',
|
bool: 'булево (да/нет)',
|
||||||
int: 'целое число',
|
int: 'целое число',
|
||||||
sec: 'секунды',
|
sec: 'секунды',
|
||||||
|
float: 'число',
|
||||||
ms: 'миллисекунды',
|
ms: 'миллисекунды',
|
||||||
us: 'микросекунды',
|
us: 'микросекунды',
|
||||||
},
|
},
|
||||||
|
@ -70,6 +74,8 @@ for (const file of params_files)
|
||||||
out += `- ${L[lang]['Default'] || 'Default'}: ${c.default}\n`;
|
out += `- ${L[lang]['Default'] || 'Default'}: ${c.default}\n`;
|
||||||
if (c.min !== undefined)
|
if (c.min !== undefined)
|
||||||
out += `- ${L[lang]['Minimum'] || 'Minimum'}: ${c.min}\n`;
|
out += `- ${L[lang]['Minimum'] || 'Minimum'}: ${c.min}\n`;
|
||||||
|
if (c.online)
|
||||||
|
out += `- ${L[lang]['online'] || 'Can be changed online: yes'}\n`;
|
||||||
out += `\n`+(c["info_"+lang] || c["info"]).replace(/\s+$/, '');
|
out += `\n`+(c["info_"+lang] || c["info"]).replace(/\s+$/, '');
|
||||||
}
|
}
|
||||||
const head = fs.readFileSync(__dirname+'/'+file+'.'+lang+'.md', { encoding: 'utf-8' });
|
const head = fs.readFileSync(__dirname+'/'+file+'.'+lang+'.md', { encoding: 'utf-8' });
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
- name: etcd_mon_ttl
|
- name: etcd_mon_ttl
|
||||||
type: sec
|
type: sec
|
||||||
min: 10
|
min: 5
|
||||||
default: 30
|
default: 1
|
||||||
info: Monitor etcd lease refresh interval in seconds
|
info: Monitor etcd lease refresh interval in seconds
|
||||||
info_ru: Интервал обновления etcd резервации (lease) монитором
|
info_ru: Интервал обновления etcd резервации (lease) монитором
|
||||||
- name: etcd_mon_timeout
|
- name: etcd_mon_timeout
|
||||||
|
|
|
@ -48,11 +48,14 @@
|
||||||
type: string
|
type: string
|
||||||
info: |
|
info: |
|
||||||
RDMA device name to use for Vitastor OSD communications (for example,
|
RDMA device name to use for Vitastor OSD communications (for example,
|
||||||
"rocep5s0f0"). Please note that Vitastor RDMA requires Implicit On-Demand
|
"rocep5s0f0"). Now Vitastor supports all adapters, even ones without
|
||||||
Paging (Implicit ODP) and Scatter/Gather (SG) support from the RDMA device
|
ODP support, like Mellanox ConnectX-3 and non-Mellanox cards.
|
||||||
to work. For example, Mellanox ConnectX-3 and older adapters don't have
|
|
||||||
Implicit ODP, so they're unsupported by Vitastor. Run `ibv_devinfo -v` as
|
Versions up to Vitastor 1.2.0 required ODP which is only present in
|
||||||
root to list available RDMA devices and their features.
|
Mellanox ConnectX >= 4. See also [rdma_odp](#rdma_odp).
|
||||||
|
|
||||||
|
Run `ibv_devinfo -v` as root to list available RDMA devices and their
|
||||||
|
features.
|
||||||
|
|
||||||
Remember that you also have to configure your network switches if you use
|
Remember that you also have to configure your network switches if you use
|
||||||
RoCE/RoCEv2, otherwise you may experience unstable performance. Refer to
|
RoCE/RoCEv2, otherwise you may experience unstable performance. Refer to
|
||||||
|
@ -61,12 +64,15 @@
|
||||||
PFC (Priority Flow Control) and ECN (Explicit Congestion Notification).
|
PFC (Priority Flow Control) and ECN (Explicit Congestion Notification).
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Название RDMA-устройства для связи с Vitastor OSD (например, "rocep5s0f0").
|
Название RDMA-устройства для связи с Vitastor OSD (например, "rocep5s0f0").
|
||||||
Имейте в виду, что поддержка RDMA в Vitastor требует функций устройства
|
Сейчас Vitastor поддерживает все модели адаптеров, включая те, у которых
|
||||||
Implicit On-Demand Paging (Implicit ODP) и Scatter/Gather (SG). Например,
|
нет поддержки ODP, то есть вы можете использовать RDMA с ConnectX-3 и
|
||||||
адаптеры Mellanox ConnectX-3 и более старые не поддерживают Implicit ODP и
|
картами производства не Mellanox.
|
||||||
потому не поддерживаются в Vitastor. Запустите `ibv_devinfo -v` от имени
|
|
||||||
суперпользователя, чтобы посмотреть список доступных RDMA-устройств, их
|
Версии Vitastor до 1.2.0 включительно требовали ODP, который есть только
|
||||||
параметры и возможности.
|
на Mellanox ConnectX 4 и более новых. См. также [rdma_odp](#rdma_odp).
|
||||||
|
|
||||||
|
Запустите `ibv_devinfo -v` от имени суперпользователя, чтобы посмотреть
|
||||||
|
список доступных RDMA-устройств, их параметры и возможности.
|
||||||
|
|
||||||
Обратите внимание, что если вы используете RoCE/RoCEv2, вам также необходимо
|
Обратите внимание, что если вы используете RoCE/RoCEv2, вам также необходимо
|
||||||
правильно настроить для него коммутаторы, иначе вы можете столкнуться с
|
правильно настроить для него коммутаторы, иначе вы можете столкнуться с
|
||||||
|
@ -160,22 +166,64 @@
|
||||||
у принимающей стороны в процессе работы не заканчивались буферы на приём.
|
у принимающей стороны в процессе работы не заканчивались буферы на приём.
|
||||||
Не влияет на потребление памяти - дополнительная память на операции отправки
|
Не влияет на потребление памяти - дополнительная память на операции отправки
|
||||||
не выделяется.
|
не выделяется.
|
||||||
|
- name: rdma_odp
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
online: false
|
||||||
|
info: |
|
||||||
|
Use RDMA with On-Demand Paging. ODP is currently only available on Mellanox
|
||||||
|
ConnectX-4 and newer adapters. ODP allows to not register memory explicitly
|
||||||
|
for RDMA adapter to be able to use it. This, in turn, allows to skip memory
|
||||||
|
copying during sending. One would think this should improve performance, but
|
||||||
|
**in reality** RDMA performance with ODP is **drastically** worse. Example
|
||||||
|
3-node cluster with 8 NVMe in each node and 2*25 GBit/s ConnectX-6 RDMA network
|
||||||
|
without ODP pushes 3950000 read iops, but only 239000 iops with ODP...
|
||||||
|
|
||||||
|
This happens because Mellanox ODP implementation seems to be based on
|
||||||
|
message retransmissions when the adapter doesn't know about the buffer yet -
|
||||||
|
it likely uses standard "RNR retransmissions" (RNR = receiver not ready)
|
||||||
|
which is generally slow in RDMA/RoCE networks. Here's a presentation about
|
||||||
|
it from ISPASS-2021 conference: https://tkygtr6.github.io/pub/ISPASS21_slides.pdf
|
||||||
|
|
||||||
|
ODP support is retained in the code just in case a good ODP implementation
|
||||||
|
appears one day.
|
||||||
|
info_ru: |
|
||||||
|
Использовать RDMA с On-Demand Paging. ODP - функция, доступная пока что
|
||||||
|
исключительно на адаптерах Mellanox ConnectX-4 и более новых. ODP позволяет
|
||||||
|
не регистрировать память для её использования RDMA-картой. Благодаря этому
|
||||||
|
можно не копировать данные при отправке их в сеть и, казалось бы, это должно
|
||||||
|
улучшать производительность - но **по факту** получается так, что
|
||||||
|
производительность только ухудшается, причём сильно. Пример - на 3-узловом
|
||||||
|
кластере с 8 NVMe в каждом узле и сетью 2*25 Гбит/с на чтение с RDMA без ODP
|
||||||
|
удаётся снять 3950000 iops, а с ODP - всего 239000 iops...
|
||||||
|
|
||||||
|
Это происходит из-за того, что реализация ODP у Mellanox неоптимальная и
|
||||||
|
основана на повторной передаче сообщений, когда карте не известен буфер -
|
||||||
|
вероятно, на стандартных "RNR retransmission" (RNR = receiver not ready).
|
||||||
|
А данные повторные передачи в RDMA/RoCE - всегда очень медленная штука.
|
||||||
|
Презентация на эту тему с конференции ISPASS-2021: https://tkygtr6.github.io/pub/ISPASS21_slides.pdf
|
||||||
|
|
||||||
|
Возможность использования ODP сохранена в коде на случай, если вдруг в один
|
||||||
|
прекрасный день появится хорошая реализация ODP.
|
||||||
- name: peer_connect_interval
|
- name: peer_connect_interval
|
||||||
type: sec
|
type: sec
|
||||||
min: 1
|
min: 1
|
||||||
default: 5
|
default: 5
|
||||||
|
online: true
|
||||||
info: Interval before attempting to reconnect to an unavailable OSD.
|
info: Interval before attempting to reconnect to an unavailable OSD.
|
||||||
info_ru: Время ожидания перед повторной попыткой соединиться с недоступным OSD.
|
info_ru: Время ожидания перед повторной попыткой соединиться с недоступным OSD.
|
||||||
- name: peer_connect_timeout
|
- name: peer_connect_timeout
|
||||||
type: sec
|
type: sec
|
||||||
min: 1
|
min: 1
|
||||||
default: 5
|
default: 5
|
||||||
|
online: true
|
||||||
info: Timeout for OSD connection attempts.
|
info: Timeout for OSD connection attempts.
|
||||||
info_ru: Максимальное время ожидания попытки соединения с OSD.
|
info_ru: Максимальное время ожидания попытки соединения с OSD.
|
||||||
- name: osd_idle_timeout
|
- name: osd_idle_timeout
|
||||||
type: sec
|
type: sec
|
||||||
min: 1
|
min: 1
|
||||||
default: 5
|
default: 5
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
OSD connection inactivity time after which clients and other OSDs send
|
OSD connection inactivity time after which clients and other OSDs send
|
||||||
keepalive requests to check state of the connection.
|
keepalive requests to check state of the connection.
|
||||||
|
@ -186,6 +234,7 @@
|
||||||
type: sec
|
type: sec
|
||||||
min: 1
|
min: 1
|
||||||
default: 5
|
default: 5
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Maximum time to wait for OSD keepalive responses. If an OSD doesn't respond
|
Maximum time to wait for OSD keepalive responses. If an OSD doesn't respond
|
||||||
within this time, the connection to it is dropped and a reconnection attempt
|
within this time, the connection to it is dropped and a reconnection attempt
|
||||||
|
@ -196,8 +245,9 @@
|
||||||
повторная попытка соединения.
|
повторная попытка соединения.
|
||||||
- name: up_wait_retry_interval
|
- name: up_wait_retry_interval
|
||||||
type: ms
|
type: ms
|
||||||
min: 50
|
min: 10
|
||||||
default: 500
|
default: 50
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
OSDs respond to clients with a special error code when they receive I/O
|
OSDs respond to clients with a special error code when they receive I/O
|
||||||
requests for a PG that's not synchronized and started. This parameter sets
|
requests for a PG that's not synchronized and started. This parameter sets
|
||||||
|
@ -211,6 +261,7 @@
|
||||||
- name: max_etcd_attempts
|
- name: max_etcd_attempts
|
||||||
type: int
|
type: int
|
||||||
default: 5
|
default: 5
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Maximum number of attempts for etcd requests which can't be retried
|
Maximum number of attempts for etcd requests which can't be retried
|
||||||
indefinitely.
|
indefinitely.
|
||||||
|
@ -220,6 +271,7 @@
|
||||||
- name: etcd_quick_timeout
|
- name: etcd_quick_timeout
|
||||||
type: ms
|
type: ms
|
||||||
default: 1000
|
default: 1000
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Timeout for etcd requests which should complete quickly, like lease refresh.
|
Timeout for etcd requests which should complete quickly, like lease refresh.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
|
@ -228,6 +280,7 @@
|
||||||
- name: etcd_slow_timeout
|
- name: etcd_slow_timeout
|
||||||
type: ms
|
type: ms
|
||||||
default: 5000
|
default: 5000
|
||||||
|
online: true
|
||||||
info: Timeout for etcd requests which are allowed to wait for some time.
|
info: Timeout for etcd requests which are allowed to wait for some time.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Максимальное время выполнения запросов к etcd, для которых не обязательно
|
Максимальное время выполнения запросов к etcd, для которых не обязательно
|
||||||
|
@ -235,6 +288,7 @@
|
||||||
- name: etcd_keepalive_timeout
|
- name: etcd_keepalive_timeout
|
||||||
type: sec
|
type: sec
|
||||||
default: max(30, etcd_report_interval*2)
|
default: max(30, etcd_report_interval*2)
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Timeout for etcd connection HTTP Keep-Alive. Should be higher than
|
Timeout for etcd connection HTTP Keep-Alive. Should be higher than
|
||||||
etcd_report_interval to guarantee that keepalive actually works.
|
etcd_report_interval to guarantee that keepalive actually works.
|
||||||
|
@ -244,27 +298,9 @@
|
||||||
- name: etcd_ws_keepalive_timeout
|
- name: etcd_ws_keepalive_timeout
|
||||||
type: sec
|
type: sec
|
||||||
default: 30
|
default: 30
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
etcd websocket ping interval required to keep the connection alive and
|
etcd websocket ping interval required to keep the connection alive and
|
||||||
detect disconnections quickly.
|
detect disconnections quickly.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Интервал проверки живости вебсокет-подключений к etcd.
|
Интервал проверки живости вебсокет-подключений к etcd.
|
||||||
- name: client_dirty_limit
|
|
||||||
type: int
|
|
||||||
default: 33554432
|
|
||||||
info: |
|
|
||||||
Without immediate_commit=all this parameter sets the limit of "dirty"
|
|
||||||
(not committed by fsync) data allowed by the client before forcing an
|
|
||||||
additional fsync and committing the data. Also note that the client always
|
|
||||||
holds a copy of uncommitted data in memory so this setting also affects
|
|
||||||
RAM usage of clients.
|
|
||||||
|
|
||||||
This parameter doesn't affect OSDs themselves.
|
|
||||||
info_ru: |
|
|
||||||
При работе без immediate_commit=all - это лимит объёма "грязных" (не
|
|
||||||
зафиксированных fsync-ом) данных, при достижении которого клиент будет
|
|
||||||
принудительно вызывать fsync и фиксировать данные. Также стоит иметь в виду,
|
|
||||||
что в этом случае до момента fsync клиент хранит копию незафиксированных
|
|
||||||
данных в памяти, то есть, настройка влияет на потребление памяти клиентами.
|
|
||||||
|
|
||||||
Параметр не влияет на сами OSD.
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
# Runtime OSD Parameters
|
# Runtime OSD Parameters
|
||||||
|
|
||||||
These parameters only apply to OSDs, are not fixed at the moment of OSD drive
|
These parameters only apply to OSDs, are not fixed at the moment of OSD drive
|
||||||
initialization and can be changed with an OSD restart.
|
initialization and can be changed - either with an OSD restart or, for some of
|
||||||
|
them, even without restarting by updating configuration in etcd.
|
||||||
|
|
|
@ -2,4 +2,5 @@
|
||||||
|
|
||||||
Данные параметры используются только OSD, но, в отличие от дисковых параметров,
|
Данные параметры используются только OSD, но, в отличие от дисковых параметров,
|
||||||
не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой
|
не фиксируются в момент инициализации дисков OSD и могут быть изменены в любой
|
||||||
момент с перезапуском OSD.
|
момент с помощью перезапуска OSD, а некоторые и без перезапуска, с помощью
|
||||||
|
изменения конфигурации в etcd.
|
||||||
|
|
|
@ -2,15 +2,28 @@
|
||||||
type: sec
|
type: sec
|
||||||
default: 5
|
default: 5
|
||||||
info: |
|
info: |
|
||||||
Interval at which OSDs report their state to etcd. Affects OSD lease time
|
Interval at which OSDs report their liveness to etcd. Affects OSD lease time
|
||||||
and thus the failover speed. Lease time is equal to this parameter value
|
and thus the failover speed. Lease time is equal to this parameter value
|
||||||
plus max_etcd_attempts * etcd_quick_timeout because it should be guaranteed
|
plus max_etcd_attempts * etcd_quick_timeout because it should be guaranteed
|
||||||
that every OSD always refreshes its lease in time.
|
that every OSD always refreshes its lease in time.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Интервал, с которым OSD обновляет своё состояние в etcd. Значение параметра
|
Интервал, с которым OSD сообщает о том, что жив, в etcd. Значение параметра
|
||||||
влияет на время резервации (lease) OSD и поэтому на скорость переключения
|
влияет на время резервации (lease) OSD и поэтому - на скорость переключения
|
||||||
при падении OSD. Время lease равняется значению этого параметра плюс
|
при падении OSD. Время lease равняется значению этого параметра плюс
|
||||||
max_etcd_attempts * etcd_quick_timeout.
|
max_etcd_attempts * etcd_quick_timeout.
|
||||||
|
- name: etcd_stats_interval
|
||||||
|
type: sec
|
||||||
|
default: 30
|
||||||
|
info: |
|
||||||
|
Interval at which OSDs report their statistics to etcd. Highly affects the
|
||||||
|
imposed load on etcd, because statistics include a key for every OSD and
|
||||||
|
for every PG. At the same time, low statistic intervals make `vitastor-cli`
|
||||||
|
statistics more responsive.
|
||||||
|
info_ru: |
|
||||||
|
Интервал, с которым OSD обновляет свою статистику в etcd. Сильно влияет на
|
||||||
|
создаваемую нагрузку на etcd, потому что статистика содержит по ключу на
|
||||||
|
каждый OSD и на каждую PG. В то же время низкий интервал делает
|
||||||
|
статистику, печатаемую `vitastor-cli`, отзывчивей.
|
||||||
- name: run_primary
|
- name: run_primary
|
||||||
type: bool
|
type: bool
|
||||||
default: true
|
default: true
|
||||||
|
@ -66,6 +79,7 @@
|
||||||
- name: autosync_interval
|
- name: autosync_interval
|
||||||
type: sec
|
type: sec
|
||||||
default: 5
|
default: 5
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Time interval at which automatic fsyncs/flushes are issued by each OSD when
|
Time interval at which automatic fsyncs/flushes are issued by each OSD when
|
||||||
the immediate_commit mode if disabled. fsyncs are required because without
|
the immediate_commit mode if disabled. fsyncs are required because without
|
||||||
|
@ -83,6 +97,7 @@
|
||||||
- name: autosync_writes
|
- name: autosync_writes
|
||||||
type: int
|
type: int
|
||||||
default: 128
|
default: 128
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Same as autosync_interval, but sets the maximum number of uncommitted write
|
Same as autosync_interval, but sets the maximum number of uncommitted write
|
||||||
operations before issuing an fsync operation internally.
|
operations before issuing an fsync operation internally.
|
||||||
|
@ -92,19 +107,33 @@
|
||||||
принудительной отправкой fsync-а.
|
принудительной отправкой fsync-а.
|
||||||
- name: recovery_queue_depth
|
- name: recovery_queue_depth
|
||||||
type: int
|
type: int
|
||||||
default: 4
|
default: 1
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Maximum recovery operations per one primary OSD at any given moment of time.
|
Maximum recovery and rebalance operations initiated by each OSD in parallel.
|
||||||
Currently it's the only parameter available to tune the speed or recovery
|
Note that each OSD talks to a lot of other OSDs so actual number of parallel
|
||||||
and rebalancing, but it's planned to implement more.
|
recovery operations per each OSD is greater than just recovery_queue_depth.
|
||||||
|
Increasing this parameter can speedup recovery if [auto-tuning](#recovery_tune_interval)
|
||||||
|
allows it or if it is disabled.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
Максимальное число операций восстановления на одном первичном OSD в любой
|
Максимальное число параллельных операций восстановления, инициируемых одним
|
||||||
момент времени. На данный момент единственный параметр, который можно менять
|
OSD в любой момент времени. Имейте в виду, что каждый OSD обычно работает с
|
||||||
для ускорения или замедления восстановления и перебалансировки данных, но
|
многими другими OSD, так что на практике параллелизм восстановления больше,
|
||||||
в планах реализация других параметров.
|
чем просто recovery_queue_depth. Увеличение значения этого параметра может
|
||||||
|
ускорить восстановление если [автотюнинг скорости](#recovery_tune_interval)
|
||||||
|
разрешает это или если он отключён.
|
||||||
|
- name: recovery_sleep_us
|
||||||
|
type: us
|
||||||
|
default: 0
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Delay for all recovery- and rebalance- related operations. If non-zero,
|
||||||
|
such operations are artificially slowed down to reduce the impact on
|
||||||
|
client I/O.
|
||||||
- name: recovery_pg_switch
|
- name: recovery_pg_switch
|
||||||
type: int
|
type: int
|
||||||
default: 128
|
default: 128
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Number of recovery operations before switching to recovery of the next PG.
|
Number of recovery operations before switching to recovery of the next PG.
|
||||||
The idea is to mix all PGs during recovery for more even space and load
|
The idea is to mix all PGs during recovery for more even space and load
|
||||||
|
@ -119,6 +148,7 @@
|
||||||
- name: recovery_sync_batch
|
- name: recovery_sync_batch
|
||||||
type: int
|
type: int
|
||||||
default: 16
|
default: 16
|
||||||
|
online: true
|
||||||
info: Maximum number of recovery operations before issuing an additional fsync.
|
info: Maximum number of recovery operations before issuing an additional fsync.
|
||||||
info_ru: Максимальное число операций восстановления перед дополнительным fsync.
|
info_ru: Максимальное число операций восстановления перед дополнительным fsync.
|
||||||
- name: readonly
|
- name: readonly
|
||||||
|
@ -133,6 +163,7 @@
|
||||||
- name: no_recovery
|
- name: no_recovery
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Disable automatic background recovery of objects. Note that it doesn't
|
Disable automatic background recovery of objects. Note that it doesn't
|
||||||
affect implicit recovery of objects happening during writes - a write is
|
affect implicit recovery of objects happening during writes - a write is
|
||||||
|
@ -145,6 +176,7 @@
|
||||||
- name: no_rebalance
|
- name: no_rebalance
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Disable background movement of data between different OSDs. Disabling it
|
Disable background movement of data between different OSDs. Disabling it
|
||||||
means that PGs in the `has_misplaced` state will be left in it indefinitely.
|
means that PGs in the `has_misplaced` state will be left in it indefinitely.
|
||||||
|
@ -155,6 +187,7 @@
|
||||||
- name: print_stats_interval
|
- name: print_stats_interval
|
||||||
type: sec
|
type: sec
|
||||||
default: 3
|
default: 3
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Time interval at which OSDs print simple human-readable operation
|
Time interval at which OSDs print simple human-readable operation
|
||||||
statistics on stdout.
|
statistics on stdout.
|
||||||
|
@ -164,6 +197,7 @@
|
||||||
- name: slow_log_interval
|
- name: slow_log_interval
|
||||||
type: sec
|
type: sec
|
||||||
default: 10
|
default: 10
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Time interval at which OSDs dump slow or stuck operations on stdout, if
|
Time interval at which OSDs dump slow or stuck operations on stdout, if
|
||||||
they're any. Also it's the time after which an operation is considered
|
they're any. Also it's the time after which an operation is considered
|
||||||
|
@ -175,6 +209,7 @@
|
||||||
- name: inode_vanish_time
|
- name: inode_vanish_time
|
||||||
type: sec
|
type: sec
|
||||||
default: 60
|
default: 60
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Number of seconds after which a deleted inode is removed from OSD statistics.
|
Number of seconds after which a deleted inode is removed from OSD statistics.
|
||||||
info_ru: |
|
info_ru: |
|
||||||
|
@ -182,6 +217,7 @@
|
||||||
- name: max_write_iodepth
|
- name: max_write_iodepth
|
||||||
type: int
|
type: int
|
||||||
default: 128
|
default: 128
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Parallel client write operation limit per one OSD. Operations that exceed
|
Parallel client write operation limit per one OSD. Operations that exceed
|
||||||
this limit are pushed to a temporary queue instead of being executed
|
this limit are pushed to a temporary queue instead of being executed
|
||||||
|
@ -193,6 +229,7 @@
|
||||||
- name: min_flusher_count
|
- name: min_flusher_count
|
||||||
type: int
|
type: int
|
||||||
default: 1
|
default: 1
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Flusher is a micro-thread that moves data from the journal to the data
|
Flusher is a micro-thread that moves data from the journal to the data
|
||||||
area of the device. Their number is auto-tuned between minimum and maximum.
|
area of the device. Their number is auto-tuned between minimum and maximum.
|
||||||
|
@ -204,6 +241,7 @@
|
||||||
- name: max_flusher_count
|
- name: max_flusher_count
|
||||||
type: int
|
type: int
|
||||||
default: 256
|
default: 256
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Maximum number of journal flushers (see above min_flusher_count).
|
Maximum number of journal flushers (see above min_flusher_count).
|
||||||
info_ru: |
|
info_ru: |
|
||||||
|
@ -247,6 +285,96 @@
|
||||||
достаточно 16- или 32-мегабайтного журнала. Однако в теории отключение
|
достаточно 16- или 32-мегабайтного журнала. Однако в теории отключение
|
||||||
параметра может оказаться полезным для гибридных OSD (HDD+SSD) с большими
|
параметра может оказаться полезным для гибридных OSD (HDD+SSD) с большими
|
||||||
журналами, расположенными на быстром по сравнению с HDD устройстве.
|
журналами, расположенными на быстром по сравнению с HDD устройстве.
|
||||||
|
- name: data_io
|
||||||
|
type: string
|
||||||
|
default: direct
|
||||||
|
info: |
|
||||||
|
I/O mode for *data*. One of "direct", "cached" or "directsync". Corresponds
|
||||||
|
to O_DIRECT, O_SYNC and O_DIRECT|O_SYNC, respectively.
|
||||||
|
|
||||||
|
Choose "cached" to use Linux page cache. This may improve read performance
|
||||||
|
for hot data and slower disks - HDDs and maybe SATA SSDs - but will slightly
|
||||||
|
decrease write performance for fast disks because page cache is an overhead
|
||||||
|
itself.
|
||||||
|
|
||||||
|
Choose "directsync" to use [immediate_commit](layout-cluster.ru.md#immediate_commit)
|
||||||
|
(which requires disable_data_fsync) with drives having write-back cache
|
||||||
|
which can't be turned off, for example, Intel Optane. Also note that *some*
|
||||||
|
desktop SSDs (for example, HP EX950) may ignore O_SYNC thus making
|
||||||
|
disable_data_fsync unsafe even with "directsync".
|
||||||
|
info_ru: |
|
||||||
|
Режим ввода-вывода для *данных*. Одно из значений "direct", "cached" или
|
||||||
|
"directsync", означающих O_DIRECT, O_SYNC и O_DIRECT|O_SYNC, соответственно.
|
||||||
|
|
||||||
|
Выберите "cached", чтобы использовать системный кэш Linux (page cache) при
|
||||||
|
чтении и записи. Это может улучшить скорость чтения горячих данных с
|
||||||
|
относительно медленных дисков - HDD и, возможно, SATA SSD - но немного
|
||||||
|
снижает производительность записи для быстрых дисков, так как кэш сам по
|
||||||
|
себе тоже добавляет накладные расходы.
|
||||||
|
|
||||||
|
Выберите "directsync", если хотите задействовать
|
||||||
|
[immediate_commit](layout-cluster.ru.md#immediate_commit) (требующий
|
||||||
|
включенияd disable_data_fsync) на дисках с неотключаемым кэшем. Пример таких
|
||||||
|
дисков - Intel Optane. При этом также стоит иметь в виду, что *некоторые*
|
||||||
|
настольные SSD (например, HP EX950) игнорируют флаг O_SYNC, делая отключение
|
||||||
|
fsync небезопасным даже с режимом "directsync".
|
||||||
|
- name: meta_io
|
||||||
|
type: string
|
||||||
|
default: direct
|
||||||
|
info: |
|
||||||
|
I/O mode for *metadata*. One of "direct", "cached" or "directsync".
|
||||||
|
|
||||||
|
"cached" may improve read performance, but only under the following conditions:
|
||||||
|
1. your drives are relatively slow (HDD, SATA SSD), and
|
||||||
|
2. checksums are enabled, and
|
||||||
|
3. [inmemory_metadata](#inmemory_metadata) is disabled.
|
||||||
|
Under all these conditions, metadata blocks are read from disk on every
|
||||||
|
read request to verify checksums and caching them may reduce this extra
|
||||||
|
read load. Without (3) metadata is never read from the disk after starting,
|
||||||
|
and without (2) metadata blocks are read from disk only during journal
|
||||||
|
flushing.
|
||||||
|
|
||||||
|
"directsync" is the same as above.
|
||||||
|
|
||||||
|
If the same device is used for data and metadata, meta_io by default is set
|
||||||
|
to the same value as [data_io](#data_io).
|
||||||
|
info_ru: |
|
||||||
|
Режим ввода-вывода для *метаданных*. Одно из значений "direct", "cached" или
|
||||||
|
"directsync".
|
||||||
|
|
||||||
|
"cached" может улучшить скорость чтения, если:
|
||||||
|
1. у вас медленные диски (HDD, SATA SSD)
|
||||||
|
2. контрольные суммы включены
|
||||||
|
3. параметр [inmemory_metadata](#inmemory_metadata) отключён.
|
||||||
|
При этих условиях блоки метаданных читаются с диска при каждом запросе чтения
|
||||||
|
для проверки контрольных сумм и их кэширование может снизить дополнительную
|
||||||
|
нагрузку на диск. Без (3) метаданные никогда не читаются с диска после
|
||||||
|
запуска OSD, а без (2) блоки метаданных читаются только при сбросе журнала.
|
||||||
|
|
||||||
|
Если одно и то же устройство используется для данных и метаданных, режим
|
||||||
|
ввода-вывода метаданных по умолчанию устанавливается равным [data_io](#data_io).
|
||||||
|
- name: journal_io
|
||||||
|
type: string
|
||||||
|
default: direct
|
||||||
|
info: |
|
||||||
|
I/O mode for *journal*. One of "direct", "cached" or "directsync".
|
||||||
|
|
||||||
|
Here, "cached" may only improve read performance for recent writes and
|
||||||
|
only if [inmemory_journal](#inmemory_journal) is turned off.
|
||||||
|
|
||||||
|
If the same device is used for metadata and journal, journal_io by default
|
||||||
|
is set to the same value as [meta_io](#meta_io).
|
||||||
|
info_ru: |
|
||||||
|
Режим ввода-вывода для *журнала*. Одно из значений "direct", "cached" или
|
||||||
|
"directsync".
|
||||||
|
|
||||||
|
Здесь "cached" может улучшить скорость чтения только недавно записанных
|
||||||
|
данных и только если параметр [inmemory_journal](#inmemory_journal)
|
||||||
|
отключён.
|
||||||
|
|
||||||
|
Если одно и то же устройство используется для метаданных и журнала,
|
||||||
|
режим ввода-вывода журнала по умолчанию устанавливается равным
|
||||||
|
[meta_io](#meta_io).
|
||||||
- name: journal_sector_buffer_count
|
- name: journal_sector_buffer_count
|
||||||
type: int
|
type: int
|
||||||
default: 32
|
default: 32
|
||||||
|
@ -284,6 +412,7 @@
|
||||||
- name: throttle_small_writes
|
- name: throttle_small_writes
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Enable soft throttling of small journaled writes. Useful for hybrid OSDs
|
Enable soft throttling of small journaled writes. Useful for hybrid OSDs
|
||||||
with fast journal/metadata devices and slow data devices. The idea is that
|
with fast journal/metadata devices and slow data devices. The idea is that
|
||||||
|
@ -312,6 +441,7 @@
|
||||||
- name: throttle_target_iops
|
- name: throttle_target_iops
|
||||||
type: int
|
type: int
|
||||||
default: 100
|
default: 100
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Target maximum number of throttled operations per second under the condition
|
Target maximum number of throttled operations per second under the condition
|
||||||
of full journal. Set it to approximate random write iops of your data devices
|
of full journal. Set it to approximate random write iops of your data devices
|
||||||
|
@ -324,6 +454,7 @@
|
||||||
- name: throttle_target_mbs
|
- name: throttle_target_mbs
|
||||||
type: int
|
type: int
|
||||||
default: 100
|
default: 100
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Target maximum bandwidth in MB/s of throttled operations per second under
|
Target maximum bandwidth in MB/s of throttled operations per second under
|
||||||
the condition of full journal. Set it to approximate linear write
|
the condition of full journal. Set it to approximate linear write
|
||||||
|
@ -336,6 +467,7 @@
|
||||||
- name: throttle_target_parallelism
|
- name: throttle_target_parallelism
|
||||||
type: int
|
type: int
|
||||||
default: 1
|
default: 1
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Target maximum parallelism of throttled operations under the condition of
|
Target maximum parallelism of throttled operations under the condition of
|
||||||
full journal. Set it to approximate internal parallelism of your data
|
full journal. Set it to approximate internal parallelism of your data
|
||||||
|
@ -348,6 +480,7 @@
|
||||||
- name: throttle_threshold_us
|
- name: throttle_threshold_us
|
||||||
type: us
|
type: us
|
||||||
default: 50
|
default: 50
|
||||||
|
online: true
|
||||||
info: |
|
info: |
|
||||||
Minimal computed delay to be applied to throttled operations. Usually
|
Minimal computed delay to be applied to throttled operations. Usually
|
||||||
doesn't need to be changed.
|
doesn't need to be changed.
|
||||||
|
@ -357,10 +490,260 @@
|
||||||
- name: osd_memlock
|
- name: osd_memlock
|
||||||
type: bool
|
type: bool
|
||||||
default: false
|
default: false
|
||||||
info: >
|
info: |
|
||||||
Lock all OSD memory to prevent it from being unloaded into swap with
|
Lock all OSD memory to prevent it from being unloaded into swap with
|
||||||
mlockall(). Requires sufficient ulimit -l (max locked memory).
|
mlockall(). Requires sufficient ulimit -l (max locked memory).
|
||||||
info_ru: >
|
info_ru: |
|
||||||
Блокировать всю память OSD с помощью mlockall, чтобы запретить её выгрузку
|
Блокировать всю память OSD с помощью mlockall, чтобы запретить её выгрузку
|
||||||
в пространство подкачки. Требует достаточного значения ulimit -l (лимита
|
в пространство подкачки. Требует достаточного значения ulimit -l (лимита
|
||||||
заблокированной памяти).
|
заблокированной памяти).
|
||||||
|
- name: auto_scrub
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Data scrubbing is the process of background verification of copies to find
|
||||||
|
and repair corrupted blocks. It's not run automatically by default since
|
||||||
|
it's a new feature. Set this parameter to true to enable automatic scrubs.
|
||||||
|
|
||||||
|
This parameter makes OSDs automatically schedule data scrubbing of clean PGs
|
||||||
|
every `scrub_interval` (see below). You can also start/schedule scrubbing
|
||||||
|
manually by setting `next_scrub` JSON key to the desired UNIX time of the
|
||||||
|
next scrub in `/pg/history/...` values in etcd.
|
||||||
|
info_ru: |
|
||||||
|
Скраб - процесс фоновой проверки копий данных, предназначенный, чтобы
|
||||||
|
находить и исправлять повреждённые блоки. По умолчанию эти проверки ещё не
|
||||||
|
запускаются автоматически, так как являются новой функцией. Чтобы включить
|
||||||
|
автоматическое планирование скрабов, установите данный параметр в true.
|
||||||
|
|
||||||
|
Включённый параметр заставляет OSD автоматически планировать фоновую
|
||||||
|
проверку чистых PG раз в `scrub_interval` (см. ниже). Вы также можете
|
||||||
|
запустить или запланировать проверку вручную, установив значение ключа JSON
|
||||||
|
`next_scrub` внутри ключей etcd `/pg/history/...` в UNIX-время следующей
|
||||||
|
желаемой проверки.
|
||||||
|
- name: no_scrub
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Temporarily disable scrubbing and stop running scrubs.
|
||||||
|
info_ru: |
|
||||||
|
Временно отключить и остановить запущенные скрабы.
|
||||||
|
- name: scrub_interval
|
||||||
|
type: string
|
||||||
|
default: 30d
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Default automatic scrubbing interval for all pools. Numbers without suffix
|
||||||
|
are treated as seconds, possible unit suffixes include 's' (seconds),
|
||||||
|
'm' (minutes), 'h' (hours), 'd' (days), 'M' (months) and 'y' (years).
|
||||||
|
info_ru: |
|
||||||
|
Интервал автоматической фоновой проверки по умолчанию для всех пулов.
|
||||||
|
Значения без указанной единицы измерения считаются в секундах, допустимые
|
||||||
|
символы единиц измерения в конце: 's' (секунды),
|
||||||
|
'm' (минуты), 'h' (часы), 'd' (дни), 'M' (месяца) или 'y' (годы).
|
||||||
|
- name: scrub_queue_depth
|
||||||
|
type: int
|
||||||
|
default: 1
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Number of parallel scrubbing operations per one OSD.
|
||||||
|
info_ru: |
|
||||||
|
Число параллельных операций фоновой проверки на один OSD.
|
||||||
|
- name: scrub_sleep
|
||||||
|
type: ms
|
||||||
|
default: 0
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Additional interval between two consecutive scrubbing operations on one OSD.
|
||||||
|
Can be used to slow down scrubbing if it affects user load too much.
|
||||||
|
info_ru: |
|
||||||
|
Дополнительный интервал ожидания после фоновой проверки каждого объекта на
|
||||||
|
одном OSD. Может использоваться для замедления скраба, если он слишком
|
||||||
|
сильно влияет на пользовательскую нагрузку.
|
||||||
|
- name: scrub_list_limit
|
||||||
|
type: int
|
||||||
|
default: 1000
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Number of objects to list in one listing operation during scrub.
|
||||||
|
info_ru: |
|
||||||
|
Размер загружаемых за одну операцию списков объектов в процессе фоновой
|
||||||
|
проверки.
|
||||||
|
- name: scrub_find_best
|
||||||
|
type: bool
|
||||||
|
default: true
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Find and automatically restore best versions of objects with unmatched
|
||||||
|
copies. In replicated setups, the best version is the version with most
|
||||||
|
matching replicas. In EC setups, the best version is the subset of data
|
||||||
|
and parity chunks without mismatches.
|
||||||
|
|
||||||
|
The hypothetical situation where you might want to disable it is when
|
||||||
|
you have 3 replicas and you are paranoid that 2 HDDs out of 3 may silently
|
||||||
|
corrupt an object in the same way (for example, zero it out) and only
|
||||||
|
1 HDD will remain good. In this case disabling scrub_find_best may help
|
||||||
|
you to recover the data! See also scrub_ec_max_bruteforce below.
|
||||||
|
info_ru: |
|
||||||
|
Находить и автоматически восстанавливать "лучшие версии" объектов с
|
||||||
|
несовпадающими копиями/частями. При использовании репликации "лучшая"
|
||||||
|
версия - версия, доступная в большем числе экземпляров, чем другие. При
|
||||||
|
использовании кодов коррекции ошибок "лучшая" версия - это подмножество
|
||||||
|
частей данных и чётности, полностью соответствующих друг другу.
|
||||||
|
|
||||||
|
Гипотетическая ситуация, в которой вы можете захотеть отключить этот
|
||||||
|
поиск - это если у вас 3 реплики и вы боитесь, что 2 диска из 3 могут
|
||||||
|
незаметно и одинаково повредить данные одного и того же объекта, например,
|
||||||
|
занулив его, и только 1 диск останется неповреждённым. В этой ситуации
|
||||||
|
отключение этого параметра поможет вам восстановить данные! Смотрите также
|
||||||
|
описание следующего параметра - scrub_ec_max_bruteforce.
|
||||||
|
- name: scrub_ec_max_bruteforce
|
||||||
|
type: int
|
||||||
|
default: 100
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Vitastor can locate corrupted chunks in EC setups with more than 1 parity
|
||||||
|
chunk by brute-forcing all possible error locations. This configuration
|
||||||
|
value limits the maximum number of checked combinations. You can try to
|
||||||
|
increase it if you have EC N+K setup with N and K large enough for
|
||||||
|
combination count `C(N+K-1, K-1) = (N+K-1)! / (K-1)! / N!` to be greater
|
||||||
|
than the default 100.
|
||||||
|
|
||||||
|
If there are too many possible combinations or if multiple combinations give
|
||||||
|
correct results then objects are marked inconsistent and aren't recovered
|
||||||
|
automatically.
|
||||||
|
|
||||||
|
In replicated setups bruteforcing isn't needed, Vitastor just assumes that
|
||||||
|
the variant with most available equal copies is correct. For example, if
|
||||||
|
you have 3 replicas and 1 of them differs, this one is considered to be
|
||||||
|
corrupted. But if there is no "best" version with more copies than all
|
||||||
|
others have then the object is also marked as inconsistent.
|
||||||
|
info_ru: |
|
||||||
|
Vitastor старается определить повреждённые части объектов при использовании
|
||||||
|
EC (кодов коррекции ошибок) с более, чем 1 диском чётности, путём перебора
|
||||||
|
всех возможных комбинаций ошибочных частей. Данное значение конфигурации
|
||||||
|
ограничивает число перебираемых комбинаций. Вы можете попробовать поднять
|
||||||
|
его, если используете схему кодирования EC N+K с N и K, достаточно большими
|
||||||
|
для того, чтобы число сочетаний `C(N+K-1, K-1) = (N+K-1)! / (K-1)! / N!`
|
||||||
|
было больше, чем стандартное значение 100.
|
||||||
|
|
||||||
|
Если возможных комбинаций слишком много или если корректная комбинаций не
|
||||||
|
определяется однозначно, объекты помечаются неконсистентными (inconsistent)
|
||||||
|
и не восстанавливаются автоматически.
|
||||||
|
|
||||||
|
При использовании репликации перебор не нужен, Vitastor просто предполагает,
|
||||||
|
что вариант объекта с наибольшим количеством одинаковых копий корректен.
|
||||||
|
Например, если вы используете 3 реплики и 1 из них отличается, эта 1 копия
|
||||||
|
считается некорректной. Однако, если "лучшую" версию с числом доступных
|
||||||
|
копий большим, чем у всех других версий, найти невозможно, то объект тоже
|
||||||
|
маркируется неконсистентным.
|
||||||
|
- name: recovery_tune_interval
|
||||||
|
type: sec
|
||||||
|
default: 1
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Interval at which OSD re-considers client and recovery load and automatically
|
||||||
|
adjusts [recovery_sleep_us](#recovery_sleep_us). Recovery auto-tuning is
|
||||||
|
disabled if recovery_tune_interval is set to 0.
|
||||||
|
|
||||||
|
Auto-tuning targets utilization. Utilization is a measure of load and is
|
||||||
|
equal to the product of iops and average latency (so it may be greater
|
||||||
|
than 1). You set "low" and "high" client utilization thresholds and two
|
||||||
|
corresponding target recovery utilization levels. OSD calculates desired
|
||||||
|
recovery utilization from client utilization using linear interpolation
|
||||||
|
and auto-tunes recovery operation delay to make actual recovery utilization
|
||||||
|
match desired.
|
||||||
|
|
||||||
|
This allows to reduce recovery/rebalance impact on client operations. It is
|
||||||
|
of course impossible to remove it completely, but it should become adequate.
|
||||||
|
In some tests rebalance could earlier drop client write speed from 1.5 GB/s
|
||||||
|
to 50-100 MB/s, with default auto-tuning settings it now only reduces
|
||||||
|
to ~1 GB/s.
|
||||||
|
info_ru: |
|
||||||
|
Интервал, с которым OSD пересматривает клиентскую нагрузку и нагрузку
|
||||||
|
восстановления и автоматически подстраивает [recovery_sleep_us](#recovery_sleep_us).
|
||||||
|
Автотюнинг (автоподстройка) отключается, если recovery_tune_interval
|
||||||
|
устанавливается в значение 0.
|
||||||
|
|
||||||
|
Автотюнинг регулирует утилизацию. Утилизация является мерой нагрузки
|
||||||
|
и равна произведению числа операций в секунду и средней задержки
|
||||||
|
(то есть, она может быть выше 1). Вы задаёте два уровня клиентской
|
||||||
|
утилизации - "низкий" и "высокий" (low и high) и два соответствующих
|
||||||
|
целевых уровня утилизации операциями восстановления. OSD рассчитывает
|
||||||
|
желаемый уровень утилизации восстановления линейной интерполяцией от
|
||||||
|
клиентской утилизации и подстраивает задержку операций восстановления
|
||||||
|
так, чтобы фактическая утилизация восстановления совпадала с желаемой.
|
||||||
|
|
||||||
|
Это позволяет снизить влияние восстановления и ребаланса на клиентские
|
||||||
|
операции. Конечно, невозможно исключить такое влияние полностью, но оно
|
||||||
|
должно становиться адекватнее. В некоторых тестах перебалансировка могла
|
||||||
|
снижать клиентскую скорость записи с 1.5 ГБ/с до 50-100 МБ/с, а теперь, с
|
||||||
|
настройками автотюнинга по умолчанию, она снижается только до ~1 ГБ/с.
|
||||||
|
- name: recovery_tune_util_low
|
||||||
|
type: float
|
||||||
|
default: 0.1
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Desired recovery/rebalance utilization when client load is high, i.e. when
|
||||||
|
it is at or above recovery_tune_client_util_high.
|
||||||
|
info_ru: |
|
||||||
|
Желаемая утилизация восстановления в моменты, когда клиентская нагрузка
|
||||||
|
высокая, то есть, находится на уровне или выше recovery_tune_client_util_high.
|
||||||
|
- name: recovery_tune_util_high
|
||||||
|
type: float
|
||||||
|
default: 1
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Desired recovery/rebalance utilization when client load is low, i.e. when
|
||||||
|
it is at or below recovery_tune_client_util_low.
|
||||||
|
info_ru: |
|
||||||
|
Желаемая утилизация восстановления в моменты, когда клиентская нагрузка
|
||||||
|
низкая, то есть, находится на уровне или ниже recovery_tune_client_util_low.
|
||||||
|
- name: recovery_tune_client_util_low
|
||||||
|
type: float
|
||||||
|
default: 0
|
||||||
|
online: true
|
||||||
|
info: Client utilization considered "low".
|
||||||
|
info_ru: Клиентская утилизация, которая считается "низкой".
|
||||||
|
- name: recovery_tune_client_util_high
|
||||||
|
type: float
|
||||||
|
default: 0.5
|
||||||
|
online: true
|
||||||
|
info: Client utilization considered "high".
|
||||||
|
info_ru: Клиентская утилизация, которая считается "высокой".
|
||||||
|
- name: recovery_tune_agg_interval
|
||||||
|
type: int
|
||||||
|
default: 10
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
The number of last auto-tuning iterations to use for calculating the
|
||||||
|
delay as average. Lower values result in quicker response to client
|
||||||
|
load change, higher values result in more stable delay. Default value of 10
|
||||||
|
is usually fine.
|
||||||
|
info_ru: |
|
||||||
|
Число последних итераций автоподстройки для расчёта задержки как среднего
|
||||||
|
значения. Меньшие значения параметра ускоряют отклик на изменение нагрузки,
|
||||||
|
большие значения делают задержку стабильнее. Значение по умолчанию 10
|
||||||
|
обычно нормальное и не требует изменений.
|
||||||
|
- name: recovery_tune_sleep_min_us
|
||||||
|
type: us
|
||||||
|
default: 10
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Minimum possible value for auto-tuned recovery_sleep_us. Lower values
|
||||||
|
are changed to 0.
|
||||||
|
info_ru: |
|
||||||
|
Минимальное возможное значение авто-подстроенного recovery_sleep_us.
|
||||||
|
Меньшие значения заменяются на 0.
|
||||||
|
- name: recovery_tune_sleep_cutoff_us
|
||||||
|
type: us
|
||||||
|
default: 10000000
|
||||||
|
online: true
|
||||||
|
info: |
|
||||||
|
Maximum possible value for auto-tuned recovery_sleep_us. Higher values
|
||||||
|
are treated as outliers and ignored in aggregation.
|
||||||
|
info_ru: |
|
||||||
|
Максимальное возможное значение авто-подстроенного recovery_sleep_us.
|
||||||
|
Большие значения считаются случайными выбросами и игнорируются в
|
||||||
|
усреднении.
|
||||||
|
|
|
@ -17,4 +17,27 @@ and apply all `NNN-*.yaml` manifests to your Kubernetes installation:
|
||||||
for i in ./???-*.yaml; do kubectl apply -f $i; done
|
for i in ./???-*.yaml; do kubectl apply -f $i; done
|
||||||
```
|
```
|
||||||
|
|
||||||
After that you'll be able to create PersistentVolumes. See example in [csi/deploy/example-pvc.yaml](../../csi/deploy/example-pvc.yaml).
|
After that you'll be able to create PersistentVolumes.
|
||||||
|
|
||||||
|
**Important:** For best experience, use Linux kernel at least 5.15 with [VDUSE](../usage/qemu.en.md#vduse)
|
||||||
|
kernel modules enabled (vdpa, vduse, virtio-vdpa). If your distribution doesn't
|
||||||
|
have them pre-built - build them yourself ([instructions](../usage/qemu.en.md#vduse)),
|
||||||
|
I promise it's worth it :-). When VDUSE is unavailable, CSI driver uses [NBD](../usage/nbd.en.md)
|
||||||
|
to map Vitastor devices. NBD is slower and prone to timeout issues: if Vitastor
|
||||||
|
cluster becomes unresponsible for more than [nbd_timeout](../config/client.en.md#nbd_timeout),
|
||||||
|
the NBD device detaches and breaks pods using it.
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
Vitastor CSI supports:
|
||||||
|
- Kubernetes starting with 1.20 (or 1.17 for older vitastor-csi <= 1.1.0)
|
||||||
|
- Filesystem RWO (ReadWriteOnce) volumes. Example: [PVC](../../csi/deploy/example-pvc.yaml), [pod](../../csi/deploy/example-test-pod.yaml)
|
||||||
|
- Raw block RWX (ReadWriteMany) volumes. Example: [PVC](../../csi/deploy/example-pvc-block.yaml), [pod](../../csi/deploy/example-test-pod-block.yaml)
|
||||||
|
- Volume expansion
|
||||||
|
- Volume snapshots. Example: [snapshot class](../../csi/deploy/example-snapshot-class.yaml), [snapshot](../../csi/deploy/example-snapshot.yaml), [clone](../../csi/deploy/example-snapshot-clone.yaml)
|
||||||
|
- [VDUSE](../usage/qemu.en.md#vduse) (preferred) and [NBD](../usage/nbd.en.md) device mapping methods
|
||||||
|
- Upgrades with VDUSE - new handler processes are restarted when CSI pods are restarted themselves
|
||||||
|
- VDUSE daemon auto-restart - handler processes are automatically restarted if they crash due to a bug in Vitastor client code
|
||||||
|
- Multiple clusters by using multiple configuration files in ConfigMap.
|
||||||
|
|
||||||
|
Remember that to use snapshots with CSI you also have to install [Snapshot Controller and CRDs](https://kubernetes-csi.github.io/docs/snapshot-controller.html#deployment).
|
||||||
|
|
|
@ -8,13 +8,36 @@
|
||||||
|
|
||||||
У Vitastor есть CSI-плагин для Kubernetes, поддерживающий RWO, а также блочные RWX, тома.
|
У Vitastor есть CSI-плагин для Kubernetes, поддерживающий RWO, а также блочные RWX, тома.
|
||||||
|
|
||||||
Для установки возьмите манифесты из директории [csi/deploy/](../csi/deploy/), поместите
|
Для установки возьмите манифесты из директории [csi/deploy/](../../csi/deploy/), поместите
|
||||||
вашу конфигурацию подключения к Vitastor в [csi/deploy/001-csi-config-map.yaml](../csi/deploy/001-csi-config-map.yaml),
|
вашу конфигурацию подключения к Vitastor в [csi/deploy/001-csi-config-map.yaml](../../csi/deploy/001-csi-config-map.yaml),
|
||||||
настройте StorageClass в [csi/deploy/009-storage-class.yaml](../csi/deploy/009-storage-class.yaml)
|
настройте StorageClass в [csi/deploy/009-storage-class.yaml](../../csi/deploy/009-storage-class.yaml)
|
||||||
и примените все `NNN-*.yaml` к вашей инсталляции Kubernetes.
|
и примените все `NNN-*.yaml` к вашей инсталляции Kubernetes.
|
||||||
|
|
||||||
```
|
```
|
||||||
for i in ./???-*.yaml; do kubectl apply -f $i; done
|
for i in ./???-*.yaml; do kubectl apply -f $i; done
|
||||||
```
|
```
|
||||||
|
|
||||||
После этого вы сможете создавать PersistentVolume. Пример смотрите в файле [csi/deploy/example-pvc.yaml](../csi/deploy/example-pvc.yaml).
|
После этого вы сможете создавать PersistentVolume.
|
||||||
|
|
||||||
|
**Важно:** Лучше всего использовать ядро Linux версии не менее 5.15 с включёнными модулями
|
||||||
|
[VDUSE](../usage/qemu.ru.md#vduse) (vdpa, vduse, virtio-vdpa). Если в вашем дистрибутиве
|
||||||
|
они не собраны из коробки - соберите их сами, обещаю, что это стоит того ([инструкция](../usage/qemu.ru.md#vduse)) :-).
|
||||||
|
Когда VDUSE недоступно, CSI-плагин использует [NBD](../usage/nbd.ru.md) для подключения
|
||||||
|
дисков, а NBD медленнее и имеет проблему таймаута - если кластер остаётся недоступным
|
||||||
|
дольше, чем [nbd_timeout](../config/client.ru.md#nbd_timeout), NBD-устройство отключается
|
||||||
|
и ломает поды, использующие его.
|
||||||
|
|
||||||
|
## Возможности
|
||||||
|
|
||||||
|
CSI-плагин Vitastor поддерживает:
|
||||||
|
- Версии Kubernetes, начиная с 1.20 (или с 1.17 для более старых vitastor-csi <= 1.1.0)
|
||||||
|
- Файловые RWO (ReadWriteOnce) тома. Пример: [PVC](../../csi/deploy/example-pvc.yaml), [под](../../csi/deploy/example-test-pod.yaml)
|
||||||
|
- Сырые блочные RWX (ReadWriteMany) тома. Пример: [PVC](../../csi/deploy/example-pvc-block.yaml), [под](../../csi/deploy/example-test-pod-block.yaml)
|
||||||
|
- Расширение размера томов
|
||||||
|
- Снимки томов. Пример: [класс снимков](../../csi/deploy/example-snapshot-class.yaml), [снимок](../../csi/deploy/example-snapshot.yaml), [клон снимка](../../csi/deploy/example-snapshot-clone.yaml)
|
||||||
|
- Способы подключения устройств [VDUSE](../usage/qemu.ru.md#vduse) (предпочитаемый) и [NBD](../usage/nbd.ru.md)
|
||||||
|
- Обновление при использовании VDUSE - новые процессы-обработчики устройств успешно перезапускаются вместе с самими подами CSI
|
||||||
|
- Автоперезауск демонов VDUSE - процесс-обработчик автоматически перезапустится, если он внезапно упадёт из-за бага в коде клиента Vitastor
|
||||||
|
- Несколько кластеров через задание нескольких файлов конфигурации в ConfigMap.
|
||||||
|
|
||||||
|
Не забывайте, что для использования снимков нужно сначала установить [контроллер снимков и CRD](https://kubernetes-csi.github.io/docs/snapshot-controller.html#deployment).
|
||||||
|
|
|
@ -36,5 +36,5 @@ vitastor_pool_id = 1
|
||||||
image_upload_use_cinder_backend = True
|
image_upload_use_cinder_backend = True
|
||||||
```
|
```
|
||||||
|
|
||||||
To put Glance images in Vitastor, use [https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html](volume-backed images),
|
To put Glance images in Vitastor, use [volume-backed images](https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html),
|
||||||
although the support has not been verified yet.
|
although the support has not been verified yet.
|
||||||
|
|
|
@ -36,5 +36,5 @@ image_upload_use_cinder_backend = True
|
||||||
```
|
```
|
||||||
|
|
||||||
Чтобы помещать в Vitastor Glance-образы, нужно использовать
|
Чтобы помещать в Vitastor Glance-образы, нужно использовать
|
||||||
[https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html](образы на основе томов Cinder),
|
[образы на основе томов Cinder](https://docs.openstack.org/cinder/pike/admin/blockstorage-volume-backed-image.html),
|
||||||
однако, поддержка этой функции ещё не проверялась.
|
однако, поддержка этой функции ещё не проверялась.
|
||||||
|
|
|
@ -11,11 +11,14 @@
|
||||||
- Trust Vitastor package signing key:
|
- Trust Vitastor package signing key:
|
||||||
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
||||||
- Add Vitastor package repository to your /etc/apt/sources.list:
|
- Add Vitastor package repository to your /etc/apt/sources.list:
|
||||||
- Debian 11 (Bullseye/Sid): `deb https://vitastor.io/debian bullseye main`
|
- Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main`
|
||||||
|
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
|
||||||
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
||||||
|
- Add `-oldstable` to bookworm/bullseye/buster in this line to install the last
|
||||||
|
stable version from 0.9.x branch instead of 1.x
|
||||||
- For Debian 10 (Buster) also enable backports repository:
|
- For Debian 10 (Buster) also enable backports repository:
|
||||||
`deb http://deb.debian.org/debian buster-backports main`
|
`deb http://deb.debian.org/debian buster-backports main`
|
||||||
- Install packages: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu`
|
- Install packages: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`
|
||||||
|
|
||||||
## CentOS
|
## CentOS
|
||||||
|
|
||||||
|
@ -45,3 +48,10 @@
|
||||||
- etcd 3.4.15 or newer. Earlier versions won't work because of various bugs,
|
- etcd 3.4.15 or newer. Earlier versions won't work because of various bugs,
|
||||||
for example [#12402](https://github.com/etcd-io/etcd/pull/12402).
|
for example [#12402](https://github.com/etcd-io/etcd/pull/12402).
|
||||||
- node.js 10 or newer
|
- node.js 10 or newer
|
||||||
|
|
||||||
|
## Version archive
|
||||||
|
|
||||||
|
All previous Vitastor and other components (QEMU, etcd...) package builds
|
||||||
|
can be found here:
|
||||||
|
|
||||||
|
https://vitastor.io/archive/
|
||||||
|
|
|
@ -11,11 +11,14 @@
|
||||||
- Добавьте ключ репозитория Vitastor:
|
- Добавьте ключ репозитория Vitastor:
|
||||||
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
`wget https://vitastor.io/debian/pubkey.gpg -O /etc/apt/trusted.gpg.d/vitastor.gpg`
|
||||||
- Добавьте репозиторий Vitastor в /etc/apt/sources.list:
|
- Добавьте репозиторий Vitastor в /etc/apt/sources.list:
|
||||||
- Debian 11 (Bullseye/Sid): `deb https://vitastor.io/debian bullseye main`
|
- Debian 12 (Bookworm/Sid): `deb https://vitastor.io/debian bookworm main`
|
||||||
|
- Debian 11 (Bullseye): `deb https://vitastor.io/debian bullseye main`
|
||||||
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
- Debian 10 (Buster): `deb https://vitastor.io/debian buster main`
|
||||||
|
- Добавьте `-oldstable` к слову bookworm/bullseye/buster в этой строке, чтобы
|
||||||
|
установить последнюю стабильную версию из ветки 0.9.x вместо 1.x
|
||||||
- Для Debian 10 (Buster) также включите репозиторий backports:
|
- Для Debian 10 (Buster) также включите репозиторий backports:
|
||||||
`deb http://deb.debian.org/debian buster-backports main`
|
`deb http://deb.debian.org/debian buster-backports main`
|
||||||
- Установите пакеты: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu`
|
- Установите пакеты: `apt update; apt install vitastor lp-solve etcd linux-image-amd64 qemu-system-x86`
|
||||||
|
|
||||||
## CentOS
|
## CentOS
|
||||||
|
|
||||||
|
@ -44,3 +47,10 @@
|
||||||
- etcd 3.4.15 или новее. Более старые версии не будут работать из-за разных багов,
|
- etcd 3.4.15 или новее. Более старые версии не будут работать из-за разных багов,
|
||||||
например, [#12402](https://github.com/etcd-io/etcd/pull/12402).
|
например, [#12402](https://github.com/etcd-io/etcd/pull/12402).
|
||||||
- node.js 10 или новее
|
- node.js 10 или новее
|
||||||
|
|
||||||
|
## Архив предыдущих версий
|
||||||
|
|
||||||
|
Все предыдущие сборки пакетов Vitastor и других компонентов, таких, как QEMU
|
||||||
|
и etcd, можно скачать по следующей ссылке:
|
||||||
|
|
||||||
|
https://vitastor.io/archive/
|
||||||
|
|
|
@ -6,10 +6,10 @@
|
||||||
|
|
||||||
# Proxmox VE
|
# Proxmox VE
|
||||||
|
|
||||||
To enable Vitastor support in Proxmox Virtual Environment (6.4-7.4 are supported):
|
To enable Vitastor support in Proxmox Virtual Environment (6.4-8.1 are supported):
|
||||||
|
|
||||||
- Add the corresponding Vitastor Debian repository into sources.list on Proxmox hosts:
|
- Add the corresponding Vitastor Debian repository into sources.list on Proxmox hosts:
|
||||||
buster for 6.4, bullseye for 7.4, pve7.1 for 7.1, pve7.2 for 7.2, pve7.3 for 7.3
|
bookworm for 8.1, pve8.0 for 8.0, bullseye for 7.4, pve7.3 for 7.3, pve7.2 for 7.2, pve7.1 for 7.1, buster for 6.4
|
||||||
- Install vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* or see note) packages from Vitastor repository
|
- Install vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* or see note) packages from Vitastor repository
|
||||||
- Define storage in `/etc/pve/storage.cfg` (see below)
|
- Define storage in `/etc/pve/storage.cfg` (see below)
|
||||||
- Block network access from VMs to Vitastor network (to OSDs and etcd),
|
- Block network access from VMs to Vitastor network (to OSDs and etcd),
|
||||||
|
@ -25,7 +25,7 @@ vitastor: vitastor
|
||||||
vitastor_pool testpool
|
vitastor_pool testpool
|
||||||
# path to the configuration file
|
# path to the configuration file
|
||||||
vitastor_config_path /etc/vitastor/vitastor.conf
|
vitastor_config_path /etc/vitastor/vitastor.conf
|
||||||
# etcd address(es), required only if missing in the configuration file
|
# etcd address(es), OPTIONAL, required only if missing in the configuration file
|
||||||
vitastor_etcd_address 192.168.7.2:2379/v3
|
vitastor_etcd_address 192.168.7.2:2379/v3
|
||||||
# prefix for keys in etcd
|
# prefix for keys in etcd
|
||||||
vitastor_etcd_prefix /vitastor
|
vitastor_etcd_prefix /vitastor
|
||||||
|
@ -35,5 +35,5 @@ vitastor: vitastor
|
||||||
vitastor_nbd 0
|
vitastor_nbd 0
|
||||||
```
|
```
|
||||||
|
|
||||||
\* Note: you can also manually copy [patches/VitastorPlugin.pm](patches/VitastorPlugin.pm) to Proxmox hosts
|
\* Note: you can also manually copy [patches/VitastorPlugin.pm](../../patches/VitastorPlugin.pm) to Proxmox hosts
|
||||||
as `/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm` instead of installing pve-storage-vitastor.
|
as `/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm` instead of installing pve-storage-vitastor.
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
[Документация](../../README-ru.md#документация) → Установка → Proxmox
|
[Документация](../../README-ru.md#документация) → Установка → Proxmox VE
|
||||||
|
|
||||||
-----
|
-----
|
||||||
|
|
||||||
[Read in English](proxmox.en.md)
|
[Read in English](proxmox.en.md)
|
||||||
|
|
||||||
# Proxmox
|
# Proxmox VE
|
||||||
|
|
||||||
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-7.4):
|
Чтобы подключить Vitastor к Proxmox Virtual Environment (поддерживаются версии 6.4-8.1):
|
||||||
|
|
||||||
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
- Добавьте соответствующий Debian-репозиторий Vitastor в sources.list на хостах Proxmox:
|
||||||
buster для 6.4, bullseye для 7.4, pve7.1 для 7.1, pve7.2 для 7.2, pve7.3 для 7.3
|
bookworm для 8.1, pve8.0 для 8.0, bullseye для 7.4, pve7.3 для 7.3, pve7.2 для 7.2, pve7.1 для 7.1, buster для 6.4
|
||||||
- Установите пакеты vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* или см. сноску) из репозитория Vitastor
|
- Установите пакеты vitastor-client, pve-qemu-kvm, pve-storage-vitastor (* или см. сноску) из репозитория Vitastor
|
||||||
- Определите тип хранилища в `/etc/pve/storage.cfg` (см. ниже)
|
- Определите тип хранилища в `/etc/pve/storage.cfg` (см. ниже)
|
||||||
- Обязательно заблокируйте доступ от виртуальных машин к сети Vitastor (OSD и etcd), т.к. Vitastor (пока) не поддерживает аутентификацию
|
- Обязательно заблокируйте доступ от виртуальных машин к сети Vitastor (OSD и etcd), т.к. Vitastor (пока) не поддерживает аутентификацию
|
||||||
|
@ -24,7 +24,7 @@ vitastor: vitastor
|
||||||
vitastor_pool testpool
|
vitastor_pool testpool
|
||||||
# Путь к файлу конфигурации
|
# Путь к файлу конфигурации
|
||||||
vitastor_config_path /etc/vitastor/vitastor.conf
|
vitastor_config_path /etc/vitastor/vitastor.conf
|
||||||
# Адрес(а) etcd, нужны, только если не указаны в vitastor.conf
|
# Адрес(а) etcd, ОПЦИОНАЛЬНЫ, нужны, только если не указаны в vitastor.conf
|
||||||
vitastor_etcd_address 192.168.7.2:2379/v3
|
vitastor_etcd_address 192.168.7.2:2379/v3
|
||||||
# Префикс ключей метаданных в etcd
|
# Префикс ключей метаданных в etcd
|
||||||
vitastor_etcd_prefix /vitastor
|
vitastor_etcd_prefix /vitastor
|
||||||
|
@ -35,5 +35,5 @@ vitastor: vitastor
|
||||||
```
|
```
|
||||||
|
|
||||||
\* Примечание: вместо установки пакета pve-storage-vitastor вы можете вручную скопировать файл
|
\* Примечание: вместо установки пакета pve-storage-vitastor вы можете вручную скопировать файл
|
||||||
[patches/VitastorPlugin.pm](patches/VitastorPlugin.pm) на хосты Proxmox как
|
[patches/VitastorPlugin.pm](../../patches/VitastorPlugin.pm) на хосты Proxmox как
|
||||||
`/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm`.
|
`/usr/share/perl5/PVE/Storage/Custom/VitastorPlugin.pm`.
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
## Basic instructions
|
## Basic instructions
|
||||||
|
|
||||||
Download source, for example using git: `git clone --recurse-submodules https://yourcmc.ru/git/vitalif/vitastor/`
|
Download source, for example using git: `git clone --recurse-submodules https://git.yourcmc.ru/vitalif/vitastor/`
|
||||||
|
|
||||||
Get `fio` source and symlink it into `<vitastor>/fio`. If you don't want to build fio engine,
|
Get `fio` source and symlink it into `<vitastor>/fio`. If you don't want to build fio engine,
|
||||||
you can disable it by passing `-DWITH_FIO=no` to cmake.
|
you can disable it by passing `-DWITH_FIO=no` to cmake.
|
||||||
|
@ -41,7 +41,7 @@ It's recommended to build the QEMU driver (qemu_driver.c) in-tree, as a part of
|
||||||
QEMU build process. To do that:
|
QEMU build process. To do that:
|
||||||
- Install vitastor client library headers (from source or from vitastor-client-dev package)
|
- Install vitastor client library headers (from source or from vitastor-client-dev package)
|
||||||
- Take a corresponding patch from `patches/qemu-*-vitastor.patch` and apply it to QEMU source
|
- Take a corresponding patch from `patches/qemu-*-vitastor.patch` and apply it to QEMU source
|
||||||
- Copy `src/qemu_driver.c` to QEMU source directory as `block/block-vitastor.c`
|
- Copy `src/qemu_driver.c` to QEMU source directory as `block/vitastor.c`
|
||||||
- Build QEMU as usual
|
- Build QEMU as usual
|
||||||
|
|
||||||
But it is also possible to build it out-of-tree. To do that:
|
But it is also possible to build it out-of-tree. To do that:
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
|
|
||||||
## Базовая инструкция
|
## Базовая инструкция
|
||||||
|
|
||||||
Скачайте исходные коды, например, из git: `git clone --recurse-submodules https://yourcmc.ru/git/vitalif/vitastor/`
|
Скачайте исходные коды, например, из git: `git clone --recurse-submodules https://git.yourcmc.ru/vitalif/vitastor/`
|
||||||
|
|
||||||
Скачайте исходные коды пакета `fio`, распакуйте их и создайте символическую ссылку на них
|
Скачайте исходные коды пакета `fio`, распакуйте их и создайте символическую ссылку на них
|
||||||
в директории исходников Vitastor: `<vitastor>/fio`. Либо, если вы не хотите собирать плагин fio,
|
в директории исходников Vitastor: `<vitastor>/fio`. Либо, если вы не хотите собирать плагин fio,
|
||||||
|
@ -41,7 +41,7 @@ cmake .. && make -j8 install
|
||||||
Драйвер QEMU (qemu_driver.c) рекомендуется собирать вместе с самим QEMU. Для этого:
|
Драйвер QEMU (qemu_driver.c) рекомендуется собирать вместе с самим QEMU. Для этого:
|
||||||
- Установите заголовки клиентской библиотеки Vitastor (из исходников или из пакета vitastor-client-dev)
|
- Установите заголовки клиентской библиотеки Vitastor (из исходников или из пакета vitastor-client-dev)
|
||||||
- Возьмите соответствующий патч из `patches/qemu-*-vitastor.patch` и примените его к исходникам QEMU
|
- Возьмите соответствующий патч из `patches/qemu-*-vitastor.patch` и примените его к исходникам QEMU
|
||||||
- Скопируйте [src/qemu_driver.c](../../src/qemu_driver.c) в директорию исходников QEMU как `block/block-vitastor.c`
|
- Скопируйте [src/qemu_driver.c](../../src/qemu_driver.c) в директорию исходников QEMU как `block/vitastor.c`
|
||||||
- Соберите QEMU как обычно
|
- Соберите QEMU как обычно
|
||||||
|
|
||||||
Однако в целях отладки драйвер также можно собирать отдельно от QEMU. Для этого:
|
Однако в целях отладки драйвер также можно собирать отдельно от QEMU. Для этого:
|
||||||
|
@ -60,7 +60,7 @@ cmake .. && make -j8 install
|
||||||
* Для QEMU 2.0+: `<qemu>/qapi-types.h` → `<vitastor>/qemu/b/qemu/qapi-types.h`
|
* Для QEMU 2.0+: `<qemu>/qapi-types.h` → `<vitastor>/qemu/b/qemu/qapi-types.h`
|
||||||
- `config-host.h` и `qapi` нужны, т.к. в них содержатся автогенерируемые заголовки
|
- `config-host.h` и `qapi` нужны, т.к. в них содержатся автогенерируемые заголовки
|
||||||
- Сконфигурируйте cmake Vitastor с `WITH_QEMU=yes` (`cmake .. -DWITH_QEMU=yes`) и, если вы
|
- Сконфигурируйте cmake Vitastor с `WITH_QEMU=yes` (`cmake .. -DWITH_QEMU=yes`) и, если вы
|
||||||
используете RHEL-подобый дистрибутив, также с `QEMU_PLUGINDIR=qemu-kvm`.
|
используете RHEL-подобный дистрибутив, также с `QEMU_PLUGINDIR=qemu-kvm`.
|
||||||
- После этого в процессе сборки Vitastor также будет собираться подходящий для вашей
|
- После этого в процессе сборки Vitastor также будет собираться подходящий для вашей
|
||||||
версии QEMU `block-vitastor.so`.
|
версии QEMU `block-vitastor.so`.
|
||||||
- Таким образом можно использовать драйвер даже с немодифицированным QEMU, но в этом случае
|
- Таким образом можно использовать драйвер даже с немодифицированным QEMU, но в этом случае
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
depends linearly on drive capacity and data store block size which is 128 KB by default.
|
depends linearly on drive capacity and data store block size which is 128 KB by default.
|
||||||
With 128 KB blocks metadata takes around 512 MB per 1 TB (which is still less than Ceph wants).
|
With 128 KB blocks metadata takes around 512 MB per 1 TB (which is still less than Ceph wants).
|
||||||
Journal is also kept in memory by default, but in SSD-only clusters it's only 32 MB, and in SSD+HDD
|
Journal is also kept in memory by default, but in SSD-only clusters it's only 32 MB, and in SSD+HDD
|
||||||
clusters, where it's beneficial to increase it, [inmemory_journal](docs/config/osd.en.md#inmemory_journal) can be disabled.
|
clusters, where it's beneficial to increase it, [inmemory_journal](../config/osd.en.md#inmemory_journal) can be disabled.
|
||||||
- Vitastor storage layer doesn't have internal copy-on-write or redirect-write. I know that maybe
|
- Vitastor storage layer doesn't have internal copy-on-write or redirect-write. I know that maybe
|
||||||
it's possible to create a good copy-on-write storage, but it's much harder and makes performance
|
it's possible to create a good copy-on-write storage, but it's much harder and makes performance
|
||||||
less deterministic, so CoW isn't used in Vitastor.
|
less deterministic, so CoW isn't used in Vitastor.
|
||||||
|
|
|
@ -54,7 +54,8 @@
|
||||||
виртуальные диски, их снимки и клоны.
|
виртуальные диски, их снимки и клоны.
|
||||||
- **Драйвер QEMU** — подключаемый модуль QEMU, позволяющий QEMU/KVM виртуальным машинам работать
|
- **Драйвер QEMU** — подключаемый модуль QEMU, позволяющий QEMU/KVM виртуальным машинам работать
|
||||||
с виртуальными дисками Vitastor напрямую из пространства пользователя с помощью клиентской
|
с виртуальными дисками Vitastor напрямую из пространства пользователя с помощью клиентской
|
||||||
библиотеки, без необходимости отображения дисков в виде блочных устройств.
|
библиотеки, без необходимости отображения дисков в виде блочных устройств. Тот же драйвер
|
||||||
|
позволяет подключать диски в систему через [VDUSE](../usage/qemu.ru.md#vduse).
|
||||||
- **vitastor-nbd** — утилита, позволяющая монтировать образы Vitastor в виде блочных устройств
|
- **vitastor-nbd** — утилита, позволяющая монтировать образы Vitastor в виде блочных устройств
|
||||||
с помощью NBD (Network Block Device), на самом деле скорее работающего как "BUSE"
|
с помощью NBD (Network Block Device), на самом деле скорее работающего как "BUSE"
|
||||||
(Block Device In Userspace). Модуля ядра Linux для выполнения той же задачи в Vitastor нет
|
(Block Device In Userspace). Модуля ядра Linux для выполнения той же задачи в Vitastor нет
|
||||||
|
@ -156,7 +157,7 @@
|
||||||
блока хранилища (block_size, по умолчанию 128 КБ). С 128 КБ блоком потребление памяти
|
блока хранилища (block_size, по умолчанию 128 КБ). С 128 КБ блоком потребление памяти
|
||||||
составляет примерно 512 МБ на 1 ТБ данных. Журналы по умолчанию тоже хранятся в памяти,
|
составляет примерно 512 МБ на 1 ТБ данных. Журналы по умолчанию тоже хранятся в памяти,
|
||||||
но в SSD-кластерах нужный размер журнала составляет всего 32 МБ, а в гибридных (SSD+HDD)
|
но в SSD-кластерах нужный размер журнала составляет всего 32 МБ, а в гибридных (SSD+HDD)
|
||||||
кластерах, в которых есть смысл делать журналы больше, можно отключить [inmemory_journal](../docs/config/osd.ru.md#inmemory_journal).
|
кластерах, в которых есть смысл делать журналы больше, можно отключить [inmemory_journal](../config/osd.ru.md#inmemory_journal).
|
||||||
- В Vitastor нет внутреннего copy-on-write. Я считаю, что реализация CoW-хранилища гораздо сложнее,
|
- В Vitastor нет внутреннего copy-on-write. Я считаю, что реализация CoW-хранилища гораздо сложнее,
|
||||||
поэтому сложнее добиться устойчиво хороших результатов. Возможно, в один прекрасный день
|
поэтому сложнее добиться устойчиво хороших результатов. Возможно, в один прекрасный день
|
||||||
я придумаю красивый алгоритм для CoW-хранилища, но пока нет — внутреннего CoW в Vitastor не будет.
|
я придумаю красивый алгоритм для CoW-хранилища, но пока нет — внутреннего CoW в Vitastor не будет.
|
||||||
|
|
|
@ -29,12 +29,16 @@
|
||||||
- Snapshots and copy-on-write image clones
|
- Snapshots and copy-on-write image clones
|
||||||
- [Write throttling to smooth random write workloads in SSD+HDD configurations](../config/osd.en.md#throttle_small_writes)
|
- [Write throttling to smooth random write workloads in SSD+HDD configurations](../config/osd.en.md#throttle_small_writes)
|
||||||
- [RDMA/RoCEv2 support via libibverbs](../config/network.en.md#rdma_device)
|
- [RDMA/RoCEv2 support via libibverbs](../config/network.en.md#rdma_device)
|
||||||
|
- [Scrubbing](../config/osd.en.md#auto_scrub) (verification of copies)
|
||||||
|
- [Checksums](../config/layout-osd.en.md#data_csum_type)
|
||||||
|
- [Client write-back cache](../config/client.en.md#client_enable_writeback)
|
||||||
|
- [Intelligent recovery auto-tuning](../config/osd.en.md#recovery_tune_interval)
|
||||||
|
|
||||||
## Plugins and tools
|
## Plugins and tools
|
||||||
|
|
||||||
- [Debian and CentOS packages](../installation/packages.en.md)
|
- [Debian and CentOS packages](../installation/packages.en.md)
|
||||||
- [Image management CLI (vitastor-cli)](../usage/cli.en.md)
|
- [Image management CLI (vitastor-cli)](../usage/cli.en.md)
|
||||||
- [Disk management CLI (vitastor-disk)](docs/usage/disk.en.md)
|
- [Disk management CLI (vitastor-disk)](../usage/disk.en.md)
|
||||||
- Generic user-space client library
|
- Generic user-space client library
|
||||||
- [Native QEMU driver](../usage/qemu.en.md)
|
- [Native QEMU driver](../usage/qemu.en.md)
|
||||||
- [Loadable fio engine for benchmarks](../usage/fio.en.md)
|
- [Loadable fio engine for benchmarks](../usage/fio.en.md)
|
||||||
|
@ -48,15 +52,15 @@
|
||||||
|
|
||||||
The following features are planned for the future:
|
The following features are planned for the future:
|
||||||
|
|
||||||
|
- File system
|
||||||
|
- Control plane optimisation
|
||||||
- Other administrative tools
|
- Other administrative tools
|
||||||
- Web GUI
|
- Web GUI
|
||||||
- OpenNebula plugin
|
- OpenNebula plugin
|
||||||
- iSCSI proxy
|
- iSCSI and NVMeoF gateways
|
||||||
- Multi-threaded client
|
- Multi-threaded client
|
||||||
- Faster failover
|
- Faster failover
|
||||||
- Scrubbing without checksums (verification of replicas)
|
- S3
|
||||||
- Checksums
|
|
||||||
- Tiered storage (SSD caching)
|
- Tiered storage (SSD caching)
|
||||||
- NVDIMM support
|
- NVDIMM support
|
||||||
- Compression (possibly)
|
- Compression (possibly)
|
||||||
- Read caching using system page cache (possibly)
|
|
||||||
|
|
|
@ -13,7 +13,7 @@
|
||||||
## Серверные функции
|
## Серверные функции
|
||||||
|
|
||||||
- Базовая часть - надёжное кластерное блочное хранилище без единой точки отказа
|
- Базовая часть - надёжное кластерное блочное хранилище без единой точки отказа
|
||||||
- [Производительность](../comparison1.ru.md) ;-D
|
- [Производительность](../performance/comparison1.ru.md) ;-D
|
||||||
- [Несколько схем отказоустойчивости](../config/pool.ru.md#scheme): репликация, XOR n+1 (1 диск чётности), коды коррекции ошибок
|
- [Несколько схем отказоустойчивости](../config/pool.ru.md#scheme): репликация, XOR n+1 (1 диск чётности), коды коррекции ошибок
|
||||||
Рида-Соломона на основе библиотек jerasure и ISA-L с любым числом дисков данных и чётности в группе
|
Рида-Соломона на основе библиотек jerasure и ISA-L с любым числом дисков данных и чётности в группе
|
||||||
- Конфигурация через простые человекочитаемые JSON-структуры в etcd
|
- Конфигурация через простые человекочитаемые JSON-структуры в etcd
|
||||||
|
@ -31,12 +31,16 @@
|
||||||
- Снапшоты и copy-on-write клоны
|
- Снапшоты и copy-on-write клоны
|
||||||
- [Сглаживание производительности случайной записи в SSD+HDD конфигурациях](../config/osd.ru.md#throttle_small_writes)
|
- [Сглаживание производительности случайной записи в SSD+HDD конфигурациях](../config/osd.ru.md#throttle_small_writes)
|
||||||
- [Поддержка RDMA/RoCEv2 через libibverbs](../config/network.ru.md#rdma_device)
|
- [Поддержка RDMA/RoCEv2 через libibverbs](../config/network.ru.md#rdma_device)
|
||||||
|
- [Фоновая проверка целостности](../config/osd.ru.md#auto_scrub) (сверка копий)
|
||||||
|
- [Контрольные суммы](../config/layout-osd.ru.md#data_csum_type)
|
||||||
|
- [Буферизация записи на стороне клиента](../config/client.ru.md#client_enable_writeback)
|
||||||
|
- [Интеллектуальная автоподстройка скорости восстановления](../config/osd.ru.md#recovery_tune_interval)
|
||||||
|
|
||||||
## Драйверы и инструменты
|
## Драйверы и инструменты
|
||||||
|
|
||||||
- [Пакеты для Debian и CentOS](../installation/packages.ru.md)
|
- [Пакеты для Debian и CentOS](../installation/packages.ru.md)
|
||||||
- [Консольный интерфейс управления образами (vitastor-cli)](../usage/cli.ru.md)
|
- [Консольный интерфейс управления образами (vitastor-cli)](../usage/cli.ru.md)
|
||||||
- [Инструмент управления дисками (vitastor-disk)](docs/usage/disk.ru.md)
|
- [Инструмент управления дисками (vitastor-disk)](../usage/disk.ru.md)
|
||||||
- Общая пользовательская клиентская библиотека для работы с кластером
|
- Общая пользовательская клиентская библиотека для работы с кластером
|
||||||
- [Драйвер диска для QEMU](../usage/qemu.ru.md)
|
- [Драйвер диска для QEMU](../usage/qemu.ru.md)
|
||||||
- [Драйвер диска для утилиты тестирования производительности fio](../usage/fio.ru.md)
|
- [Драйвер диска для утилиты тестирования производительности fio](../usage/fio.ru.md)
|
||||||
|
@ -48,14 +52,15 @@
|
||||||
|
|
||||||
## Планы развития
|
## Планы развития
|
||||||
|
|
||||||
|
- Файловая система
|
||||||
|
- Оптимизация слоя управления
|
||||||
- Другие инструменты администрирования
|
- Другие инструменты администрирования
|
||||||
- Web-интерфейс
|
- Web-интерфейс
|
||||||
- Плагин для OpenNebula
|
- Плагин для OpenNebula
|
||||||
- iSCSI-прокси
|
- iSCSI и NVMeoF прокси
|
||||||
- Многопоточный клиент
|
- Многопоточный клиент
|
||||||
- Более быстрое переключение при отказах
|
- Более быстрое переключение при отказах
|
||||||
- Фоновая проверка целостности без контрольных сумм (сверка реплик)
|
- S3
|
||||||
- Контрольные суммы
|
|
||||||
- Поддержка SSD-кэширования (tiered storage)
|
- Поддержка SSD-кэширования (tiered storage)
|
||||||
- Поддержка NVDIMM
|
- Поддержка NVDIMM
|
||||||
- Возможно, сжатие
|
- Возможно, сжатие
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
# Quick Start
|
# Quick Start
|
||||||
|
|
||||||
- [Preparation](#preparation)
|
- [Preparation](#preparation)
|
||||||
|
- [Recommended drives](#recommended-drives)
|
||||||
- [Configure monitors](#configure-monitors)
|
- [Configure monitors](#configure-monitors)
|
||||||
- [Configure OSDs](#configure-osds)
|
- [Configure OSDs](#configure-osds)
|
||||||
- [Create a pool](#create-a-pool)
|
- [Create a pool](#create-a-pool)
|
||||||
|
@ -19,10 +20,20 @@
|
||||||
- Get some SATA or NVMe SSDs with capacitors (server-grade drives). You can use desktop SSDs
|
- Get some SATA or NVMe SSDs with capacitors (server-grade drives). You can use desktop SSDs
|
||||||
with lazy fsync, but prepare for inferior single-thread latency. Read more about capacitors
|
with lazy fsync, but prepare for inferior single-thread latency. Read more about capacitors
|
||||||
[here](../config/layout-cluster.en.md#immediate_commit).
|
[here](../config/layout-cluster.en.md#immediate_commit).
|
||||||
|
- If you want to use HDDs, get modern HDDs with Media Cache or SSD Cache: HGST Ultrastar,
|
||||||
|
Toshiba MG08, Seagate EXOS or something similar. If your drives don't have such cache then
|
||||||
|
you also need small SSDs for journal and metadata (even 2 GB per 1 TB of HDD space is enough).
|
||||||
- Get a fast network (at least 10 Gbit/s). Something like Mellanox ConnectX-4 with RoCEv2 is ideal.
|
- Get a fast network (at least 10 Gbit/s). Something like Mellanox ConnectX-4 with RoCEv2 is ideal.
|
||||||
- Disable CPU powersaving: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`.
|
- Disable CPU powersaving: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`.
|
||||||
- [Install Vitastor packages](../installation/packages.en.md).
|
- [Install Vitastor packages](../installation/packages.en.md).
|
||||||
|
|
||||||
|
## Recommended drives
|
||||||
|
|
||||||
|
- SATA SSD: Micron 5100/5200/5300/5400, Samsung PM863/PM883/PM893, Intel D3-S4510/4520/4610/4620, Kingston DC500M
|
||||||
|
- NVMe: Micron 9100/9200/9300/9400, Micron 7300/7450, Samsung PM983/PM9A3, Samsung PM1723/1735/1743,
|
||||||
|
Intel DC-P3700/P4500/P4600, Intel D7-P5500/P5600, Intel Optane, Kingston DC1000B/DC1500M
|
||||||
|
- HDD: HGST Ultrastar, Toshiba MG06/MG07/MG08, Seagate EXOS
|
||||||
|
|
||||||
## Configure monitors
|
## Configure monitors
|
||||||
|
|
||||||
On the monitor hosts:
|
On the monitor hosts:
|
||||||
|
@ -45,9 +56,10 @@ On the monitor hosts:
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- Initialize OSDs:
|
- Initialize OSDs:
|
||||||
- SSD-only: `vitastor-disk prepare /dev/sdXXX [/dev/sdYYY ...]`. You can add
|
- SSD-only or HDD-only: `vitastor-disk prepare /dev/sdXXX [/dev/sdYYY ...]`.
|
||||||
`--disable_data_fsync off` to leave disk cache enabled if you use desktop
|
Add `--disable_data_fsync off` to leave disk write cache enabled if you use
|
||||||
SSDs without capacitors.
|
desktop SSDs without capacitors. Do NOT add `--disable_data_fsync off` if you
|
||||||
|
use HDDs or SSD+HDD.
|
||||||
- Hybrid, SSD+HDD: `vitastor-disk prepare --hybrid /dev/sdXXX [/dev/sdYYY ...]`.
|
- Hybrid, SSD+HDD: `vitastor-disk prepare --hybrid /dev/sdXXX [/dev/sdYYY ...]`.
|
||||||
Pass all your devices (HDD and SSD) to this script — it will partition disks and initialize journals on its own.
|
Pass all your devices (HDD and SSD) to this script — it will partition disks and initialize journals on its own.
|
||||||
This script skips HDDs which are already partitioned so if you want to use non-empty disks for
|
This script skips HDDs which are already partitioned so if you want to use non-empty disks for
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
# Быстрый старт
|
# Быстрый старт
|
||||||
|
|
||||||
- [Подготовка](#подготовка)
|
- [Подготовка](#подготовка)
|
||||||
|
- [Рекомендуемые диски](#рекомендуемые-диски)
|
||||||
- [Настройте мониторы](#настройте-мониторы)
|
- [Настройте мониторы](#настройте-мониторы)
|
||||||
- [Настройте OSD](#настройте-osd)
|
- [Настройте OSD](#настройте-osd)
|
||||||
- [Создайте пул](#создайте-пул)
|
- [Создайте пул](#создайте-пул)
|
||||||
|
@ -19,10 +20,20 @@
|
||||||
- Возьмите серверы с SSD (SATA или NVMe), желательно с конденсаторами (серверные SSD). Можно
|
- Возьмите серверы с SSD (SATA или NVMe), желательно с конденсаторами (серверные SSD). Можно
|
||||||
использовать и десктопные SSD, включив режим отложенного fsync, но производительность будет хуже.
|
использовать и десктопные SSD, включив режим отложенного fsync, но производительность будет хуже.
|
||||||
О конденсаторах читайте [здесь](../config/layout-cluster.ru.md#immediate_commit).
|
О конденсаторах читайте [здесь](../config/layout-cluster.ru.md#immediate_commit).
|
||||||
|
- Если хотите использовать HDD, берите современные модели с Media или SSD кэшем - HGST Ultrastar,
|
||||||
|
Toshiba MG08, Seagate EXOS или что-то похожее. Если такого кэша у ваших дисков нет,
|
||||||
|
обязательно возьмите SSD под метаданные и журнал (маленькие, буквально 2 ГБ на 1 ТБ HDD-места).
|
||||||
- Возьмите быструю сеть, минимум 10 гбит/с. Идеал - что-то вроде Mellanox ConnectX-4 с RoCEv2.
|
- Возьмите быструю сеть, минимум 10 гбит/с. Идеал - что-то вроде Mellanox ConnectX-4 с RoCEv2.
|
||||||
- Для лучшей производительности отключите энергосбережение CPU: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`.
|
- Для лучшей производительности отключите энергосбережение CPU: `cpupower idle-set -D 0 && cpupower frequency-set -g performance`.
|
||||||
- [Установите пакеты Vitastor](../installation/packages.ru.md).
|
- [Установите пакеты Vitastor](../installation/packages.ru.md).
|
||||||
|
|
||||||
|
## Рекомендуемые диски
|
||||||
|
|
||||||
|
- SATA SSD: Micron 5100/5200/5300/5400, Samsung PM863/PM883/PM893, Intel D3-S4510/4520/4610/4620, Kingston DC500M
|
||||||
|
- NVMe: Micron 9100/9200/9300/9400, Micron 7300/7450, Samsung PM983/PM9A3, Samsung PM1723/1735/1743,
|
||||||
|
Intel DC-P3700/P4500/P4600, Intel D7-P5500/P5600, Intel Optane, Kingston DC1000B/DC1500M
|
||||||
|
- HDD: HGST Ultrastar, Toshiba MG06/MG07/MG08, Seagate EXOS
|
||||||
|
|
||||||
## Настройте мониторы
|
## Настройте мониторы
|
||||||
|
|
||||||
На хостах, выделенных под мониторы:
|
На хостах, выделенных под мониторы:
|
||||||
|
@ -45,9 +56,10 @@
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
- Инициализуйте OSD:
|
- Инициализуйте OSD:
|
||||||
- SSD: `vitastor-disk prepare /dev/sdXXX [/dev/sdYYY ...]`. Если вы используете
|
- Только SSD или только HDD: `vitastor-disk prepare /dev/sdXXX [/dev/sdYYY ...]`.
|
||||||
десктопные SSD без конденсаторов, можете оставить кэш включённым, добавив
|
Если вы используете десктопные SSD без конденсаторов, добавьте опцию `--disable_data_fsync off`,
|
||||||
опцию `--disable_data_fsync off`.
|
чтобы оставить кэш записи диска включённым. НЕ добавляйте эту опцию, если используете
|
||||||
|
жёсткие диски (HDD).
|
||||||
- Гибридные, SSD+HDD: `vitastor-disk prepare --hybrid /dev/sdXXX [/dev/sdYYY ...]`.
|
- Гибридные, SSD+HDD: `vitastor-disk prepare --hybrid /dev/sdXXX [/dev/sdYYY ...]`.
|
||||||
Передайте все ваши SSD и HDD скрипту в командной строке подряд, скрипт автоматически выделит
|
Передайте все ваши SSD и HDD скрипту в командной строке подряд, скрипт автоматически выделит
|
||||||
разделы под журналы на SSD и данные на HDD. Скрипт пропускает HDD, на которых уже есть разделы
|
разделы под журналы на SSD и данные на HDD. Скрипт пропускает HDD, на которых уже есть разделы
|
||||||
|
|
|
@ -11,19 +11,26 @@ Replicated setups:
|
||||||
- Single-threaded write+fsync latency:
|
- Single-threaded write+fsync latency:
|
||||||
- With immediate commit: 2 network roundtrips + 1 disk write.
|
- With immediate commit: 2 network roundtrips + 1 disk write.
|
||||||
- With lazy commit: 4 network roundtrips + 1 disk write + 1 disk flush.
|
- With lazy commit: 4 network roundtrips + 1 disk write + 1 disk flush.
|
||||||
- Saturated parallel read iops: min(network bandwidth, sum(disk read iops)).
|
- Linear read: `min(total network bandwidth, sum(disk read MB/s))`.
|
||||||
- Saturated parallel write iops: min(network bandwidth, sum(disk write iops / number of replicas / write amplification)).
|
- Linear write: `min(total network bandwidth, sum(disk write MB/s / number of replicas))`.
|
||||||
|
- Saturated parallel read iops: `min(total network bandwidth, sum(disk read iops))`.
|
||||||
|
- Saturated parallel write iops: `min(total network bandwidth / number of replicas, sum(disk write iops / number of replicas / (write amplification = 4)))`.
|
||||||
|
|
||||||
EC/XOR setups:
|
EC/XOR setups (EC N+K):
|
||||||
- Single-threaded (T1Q1) read latency: 1.5 network roundtrips + 1 disk read.
|
- Single-threaded (T1Q1) read latency: 1.5 network roundtrips + 1 disk read.
|
||||||
- Single-threaded write+fsync latency:
|
- Single-threaded write+fsync latency:
|
||||||
- With immediate commit: 3.5 network roundtrips + 1 disk read + 2 disk writes.
|
- With immediate commit: 3.5 network roundtrips + 1 disk read + 2 disk writes.
|
||||||
- With lazy commit: 5.5 network roundtrips + 1 disk read + 2 disk writes + 2 disk fsyncs.
|
- With lazy commit: 5.5 network roundtrips + 1 disk read + 2 disk writes + 2 disk fsyncs.
|
||||||
- 0.5 in actually (k-1)/k which means that an additional roundtrip doesn't happen when
|
- 0.5 in actually `(N-1)/N` which means that an additional roundtrip doesn't happen when
|
||||||
the read sub-operation can be served locally.
|
the read sub-operation can be served locally.
|
||||||
- Saturated parallel read iops: min(network bandwidth, sum(disk read iops)).
|
- Linear read: `min(total network bandwidth, sum(disk read MB/s))`.
|
||||||
- Saturated parallel write iops: min(network bandwidth, sum(disk write iops * number of data drives / (number of data + parity drives) / write amplification)).
|
- Linear write: `min(total network bandwidth, sum(disk write MB/s * N/(N+K)))`.
|
||||||
In fact, you should put disk write iops under the condition of ~10% reads / ~90% writes in this formula.
|
- Saturated parallel read iops: `min(total network bandwidth, sum(disk read iops))`.
|
||||||
|
- Saturated parallel write iops: roughly `total iops / (N+K) / WA`. More exactly,
|
||||||
|
`min(total network bandwidth * N/(N+K), sum(disk randrw iops / (N*4 + K*5 + 1)))` with
|
||||||
|
random read/write mix corresponding to `(N-1)/(N*4 + K*5 + 1)*100 % reads`.
|
||||||
|
- For example, with EC 2+1 it is: `(7% randrw iops) / 14`.
|
||||||
|
- With EC 6+3 it is: `(12.5% randrw iops) / 40`.
|
||||||
|
|
||||||
Write amplification for 4 KB blocks is usually 3-5 in Vitastor:
|
Write amplification for 4 KB blocks is usually 3-5 in Vitastor:
|
||||||
1. Journal block write
|
1. Journal block write
|
||||||
|
|
|
@ -11,20 +11,27 @@
|
||||||
- Запись+fsync в 1 поток:
|
- Запись+fsync в 1 поток:
|
||||||
- С мгновенным сбросом: 2 RTT + 1 запись.
|
- С мгновенным сбросом: 2 RTT + 1 запись.
|
||||||
- С отложенным ("ленивым") сбросом: 4 RTT + 1 запись + 1 fsync.
|
- С отложенным ("ленивым") сбросом: 4 RTT + 1 запись + 1 fsync.
|
||||||
- Параллельное чтение: сумма IOPS всех дисков либо производительность сети, если в сеть упрётся раньше.
|
- Линейное чтение: сумма МБ/с чтения всех дисков, либо общая производительность сети (сумма пропускной способности сети всех нод), если в сеть упрётся раньше.
|
||||||
- Параллельная запись: сумма IOPS всех дисков / число реплик / WA либо производительность сети, если в сеть упрётся раньше.
|
- Линейная запись: сумма МБ/с записи всех дисков / число реплик, либо производительность сети / число реплик, если в сеть упрётся раньше.
|
||||||
|
- Параллельное случайное мелкое чтение: сумма IOPS чтения всех дисков, либо производительность сети, если в сеть упрётся раньше.
|
||||||
|
- Параллельная случайная мелкая запись: сумма IOPS записи всех дисков / число реплик / WA, либо производительность сети / число реплик, если в сеть упрётся раньше.
|
||||||
|
|
||||||
При использовании кодов коррекции ошибок (EC):
|
При использовании кодов коррекции ошибок (EC N+K):
|
||||||
- Задержка чтения в 1 поток (T1Q1): 1.5 RTT + 1 чтение.
|
- Задержка чтения в 1 поток (T1Q1): 1.5 RTT + 1 чтение.
|
||||||
- Запись+fsync в 1 поток:
|
- Запись+fsync в 1 поток:
|
||||||
- С мгновенным сбросом: 3.5 RTT + 1 чтение + 2 записи.
|
- С мгновенным сбросом: 3.5 RTT + 1 чтение + 2 записи.
|
||||||
- С отложенным ("ленивым") сбросом: 5.5 RTT + 1 чтение + 2 записи + 2 fsync.
|
- С отложенным ("ленивым") сбросом: 5.5 RTT + 1 чтение + 2 записи + 2 fsync.
|
||||||
- Под 0.5 на самом деле подразумевается (k-1)/k, где k - число дисков данных,
|
- Под 0.5 на самом деле подразумевается (N-1)/N, где N - число дисков данных,
|
||||||
что означает, что дополнительное обращение по сети не нужно, когда операция
|
что означает, что дополнительное обращение по сети не нужно, когда операция
|
||||||
чтения обслуживается локально.
|
чтения обслуживается локально.
|
||||||
- Параллельное чтение: сумма IOPS всех дисков либо производительность сети, если в сеть упрётся раньше.
|
- Линейное чтение: сумма МБ/с чтения всех дисков, либо общая производительность сети, если в сеть упрётся раньше.
|
||||||
- Параллельная запись: сумма IOPS всех дисков / общее число дисков данных и чётности / WA либо производительность сети, если в сеть упрётся раньше.
|
- Линейная запись: сумма МБ/с записи всех дисков * N/(N+K), либо производительность сети * N / (N+K), если в сеть упрётся раньше.
|
||||||
Примечание: IOPS дисков в данном случае надо брать в смешанном режиме чтения/записи в пропорции, аналогичной формулам выше.
|
- Параллельное случайное мелкое чтение: сумма IOPS чтения всех дисков либо производительность сети, если в сеть упрётся раньше.
|
||||||
|
- Параллельная случайная мелкая запись: грубо `(сумма IOPS / (N+K) / WA)`. Если точнее, то:
|
||||||
|
сумма смешанного IOPS всех дисков при `(N-1)/(N*4 + K*5 + 1)*100 %` чтения, делённая на `(N*4 + K*5 + 1)`.
|
||||||
|
Либо, производительность сети * N/(N+K), если в сеть упрётся раньше.
|
||||||
|
- Например, при EC 2+1 это: `(сумма IOPS при 7% чтения) / 14`.
|
||||||
|
- При EC 6+3 это: `(сумма IOPS при 12.5% чтения) / 40`.
|
||||||
|
|
||||||
WA (мультипликатор записи) для 4 КБ блоков в Vitastor обычно составляет 3-5:
|
WA (мультипликатор записи) для 4 КБ блоков в Vitastor обычно составляет 3-5:
|
||||||
1. Запись метаданных в журнал
|
1. Запись метаданных в журнал
|
||||||
|
|
|
@ -20,13 +20,16 @@ It supports the following commands:
|
||||||
- [flatten](#flatten)
|
- [flatten](#flatten)
|
||||||
- [rm-data](#rm-data)
|
- [rm-data](#rm-data)
|
||||||
- [merge-data](#merge-data)
|
- [merge-data](#merge-data)
|
||||||
|
- [describe](#describe)
|
||||||
|
- [fix](#fix)
|
||||||
- [alloc-osd](#alloc-osd)
|
- [alloc-osd](#alloc-osd)
|
||||||
- [rm-osd](#rm-osd)
|
- [rm-osd](#rm-osd)
|
||||||
|
|
||||||
Global options:
|
Global options:
|
||||||
|
|
||||||
```
|
```
|
||||||
--etcd_address ADDR Etcd connection address
|
--config_file FILE Path to Vitastor configuration file
|
||||||
|
--etcd_address URL Etcd connection address
|
||||||
--iodepth N Send N operations in parallel to each OSD when possible (default 32)
|
--iodepth N Send N operations in parallel to each OSD when possible (default 32)
|
||||||
--parallel_osds M Work with M osds in parallel when possible (default 4)
|
--parallel_osds M Work with M osds in parallel when possible (default 4)
|
||||||
--progress 1|0 Report progress (default 1)
|
--progress 1|0 Report progress (default 1)
|
||||||
|
@ -174,6 +177,51 @@ Merge layer data without changing metadata. Merge `<from>`..`<to>` to `<target>`
|
||||||
`<to>` must be a child of `<from>` and `<target>` may be one of the layers between
|
`<to>` must be a child of `<from>` and `<target>` may be one of the layers between
|
||||||
`<from>` and `<to>`, including `<from>` and `<to>`.
|
`<from>` and `<to>`, including `<from>` and `<to>`.
|
||||||
|
|
||||||
|
## describe
|
||||||
|
|
||||||
|
`vitastor-cli describe [--osds <osds>] [--object-state <states>] [--pool <pool>]
|
||||||
|
[--inode <ino>] [--min-inode <ino>] [--max-inode <ino>]
|
||||||
|
[--min-offset <offset>] [--max-offset <offset>]`
|
||||||
|
|
||||||
|
Describe unclean object locations in the cluster.
|
||||||
|
|
||||||
|
```
|
||||||
|
--osds <osds>
|
||||||
|
Only list objects from primary OSD(s) <osds>.
|
||||||
|
--object-state <states>
|
||||||
|
Only list objects in given state(s). State(s) may include:
|
||||||
|
degraded, misplaced, incomplete, corrupted, inconsistent.
|
||||||
|
--pool <pool name or number>
|
||||||
|
Only list objects in the given pool.
|
||||||
|
--inode, --min-inode, --max-inode
|
||||||
|
Restrict listing to specific inode numbers.
|
||||||
|
--min-offset, --max-offset
|
||||||
|
Restrict listing to specific offsets inside inodes.
|
||||||
|
```
|
||||||
|
|
||||||
|
## fix
|
||||||
|
|
||||||
|
`vitastor-cli fix [--objects <objects>] [--bad-osds <osds>] [--part <part>] [--check no]`
|
||||||
|
|
||||||
|
Fix inconsistent objects in the cluster by deleting some copies.
|
||||||
|
|
||||||
|
```
|
||||||
|
--objects <objects>
|
||||||
|
Objects to fix, either in plain text or JSON format. If not specified,
|
||||||
|
object list will be read from STDIN in one of the same formats.
|
||||||
|
Plain text format: 0x<inode>:0x<stripe> <any delimiter> 0x<inode>:0x<stripe> ...
|
||||||
|
JSON format: [{"inode":"0x...","stripe":"0x..."},...]
|
||||||
|
--bad-osds <osds>
|
||||||
|
Remove inconsistent copies/parts of objects from these OSDs, effectively
|
||||||
|
marking them bad and allowing Vitastor to recover objects from other copies.
|
||||||
|
--part <number>
|
||||||
|
Only remove EC part <number> (from 0 to pg_size-1), required for extreme
|
||||||
|
edge cases where one OSD has multiple parts of a EC object.
|
||||||
|
--check no
|
||||||
|
Do not recheck that requested objects are actually inconsistent,
|
||||||
|
delete requested copies/parts anyway.
|
||||||
|
```
|
||||||
|
|
||||||
## alloc-osd
|
## alloc-osd
|
||||||
|
|
||||||
`vitastor-cli alloc-osd`
|
`vitastor-cli alloc-osd`
|
||||||
|
|
|
@ -27,7 +27,8 @@ vitastor-cli - интерфейс командной строки для адм
|
||||||
Глобальные опции:
|
Глобальные опции:
|
||||||
|
|
||||||
```
|
```
|
||||||
--etcd_address ADDR Адрес соединения с etcd
|
--config_file FILE Путь к файлу конфигурации Vitastor
|
||||||
|
--etcd_address URL Адрес соединения с etcd
|
||||||
--iodepth N Отправлять параллельно N операций на каждый OSD (по умолчанию 32)
|
--iodepth N Отправлять параллельно N операций на каждый OSD (по умолчанию 32)
|
||||||
--parallel_osds M Работать параллельно с M OSD (по умолчанию 4)
|
--parallel_osds M Работать параллельно с M OSD (по умолчанию 4)
|
||||||
--progress 1|0 Печатать прогресс выполнения (по умолчанию 1)
|
--progress 1|0 Печатать прогресс выполнения (по умолчанию 1)
|
||||||
|
@ -184,6 +185,59 @@ vitastor-cli snap-create [-p|--pool <id|name>] <image>@<snapshot>
|
||||||
в целевой образ `<target>`. `<to>` должен быть дочерним образом `<from>`, а `<target>`
|
в целевой образ `<target>`. `<to>` должен быть дочерним образом `<from>`, а `<target>`
|
||||||
должен быть одним из слоёв между `<from>` и `<to>`, включая сами `<from>` и `<to>`.
|
должен быть одним из слоёв между `<from>` и `<to>`, включая сами `<from>` и `<to>`.
|
||||||
|
|
||||||
|
## describe
|
||||||
|
|
||||||
|
`vitastor-cli describe [--osds <osds>] [--object-state <состояния>] [--pool <пул>]
|
||||||
|
[--inode <номер>] [--min-inode <номер>] [--max-inode <номер>]
|
||||||
|
[--min-offset <смещение>] [--max-offset <смещение>]`
|
||||||
|
|
||||||
|
Описать состояние "грязных" объектов в кластере, то есть таких объектов, копии
|
||||||
|
или части которых хранятся на наборе OSD, не равном целевому.
|
||||||
|
|
||||||
|
```
|
||||||
|
--osds <osds>
|
||||||
|
Перечислять только объекты с первичных OSD из списка <osds>.
|
||||||
|
--object-state <состояния>
|
||||||
|
Перечислять только объекты в указанных состояниях. Возможные состояния
|
||||||
|
объектов:
|
||||||
|
- degraded - деградированная избыточность
|
||||||
|
- misplaced - перемещённый
|
||||||
|
- incomplete - нечитаемый из-за потери большего числа частей, чем допустимо
|
||||||
|
- corrupted - с одной или более повреждённой частью
|
||||||
|
- inconsistent - неконсистентный, с неоднозначным расхождением копий/частей
|
||||||
|
--pool <имя или ID пула>
|
||||||
|
Перечислять только объекты из заданного пула.
|
||||||
|
--inode, --min-inode, --max-inode
|
||||||
|
Перечислять только объекты из указанных номеров инодов (образов).
|
||||||
|
--min-offset, --max-offset
|
||||||
|
Перечислять только объекты с заданных смещений внутри образов.
|
||||||
|
```
|
||||||
|
|
||||||
|
## fix
|
||||||
|
|
||||||
|
`vitastor-cli fix [--objects <объекты>] [--bad-osds <osds>] [--part <номер>] [--check no]`
|
||||||
|
|
||||||
|
Исправить неконсистентные (неоднозначные) объекты путём удаления части копий.
|
||||||
|
|
||||||
|
```
|
||||||
|
--objects <объекты>
|
||||||
|
Объекты для исправления - в простом текстовом или JSON формате. Если опция
|
||||||
|
не указана, список объектов читается со стандартного ввода в тех же форматах.
|
||||||
|
Простой формат: 0x<инод>:0x<смещение> <любой разделитель> 0x<инод>:0x<смещение> ...
|
||||||
|
Формат JSON: [{"inode":"0x<инод>","stripe":"0x<смещение>"},...]
|
||||||
|
--bad-osds <osds>
|
||||||
|
Удалить неконсистентные копии/части объектов с данных OSD, таким образом
|
||||||
|
признавая потерю этих копий и позволяя Vitastor-у восстановить объекты из
|
||||||
|
других копий.
|
||||||
|
--part <номер>
|
||||||
|
Удалить только части EC с заданным номером (от 0 до pg_size-1). Нужно только
|
||||||
|
в редких граничных случаях, когда один и тот же OSD содержит несколько частей
|
||||||
|
одного EC-объекта.
|
||||||
|
--check no
|
||||||
|
Не перепроверять, что заданные объекты действительно в неконсистентном
|
||||||
|
состоянии и просто удалять заданные части.
|
||||||
|
```
|
||||||
|
|
||||||
## alloc-osd
|
## alloc-osd
|
||||||
|
|
||||||
`vitastor-cli alloc-osd`
|
`vitastor-cli alloc-osd`
|
||||||
|
|
|
@ -17,6 +17,7 @@ It supports the following commands:
|
||||||
- [purge](#purge)
|
- [purge](#purge)
|
||||||
- [read-sb](#read-sb)
|
- [read-sb](#read-sb)
|
||||||
- [write-sb](#write-sb)
|
- [write-sb](#write-sb)
|
||||||
|
- [update-sb](#update-sb)
|
||||||
- [udev](#udev)
|
- [udev](#udev)
|
||||||
- [exec-osd](#exec-osd)
|
- [exec-osd](#exec-osd)
|
||||||
- [pre-exec](#pre-exec)
|
- [pre-exec](#pre-exec)
|
||||||
|
@ -86,6 +87,8 @@ Options (both modes):
|
||||||
--journal_size 1G/32M Set journal size (area or partition size)
|
--journal_size 1G/32M Set journal size (area or partition size)
|
||||||
--block_size 1M/128k Set blockstore object size
|
--block_size 1M/128k Set blockstore object size
|
||||||
--bitmap_granularity 4k Set bitmap granularity
|
--bitmap_granularity 4k Set bitmap granularity
|
||||||
|
--data_csum_type none Set data checksum type (crc32c or none)
|
||||||
|
--csum_block_size 4k Set data checksum block size
|
||||||
--data_device_block 4k Override data device block size
|
--data_device_block 4k Override data device block size
|
||||||
--meta_device_block 4k Override metadata device block size
|
--meta_device_block 4k Override metadata device block size
|
||||||
--journal_device_block 4k Override journal device block size
|
--journal_device_block 4k Override journal device block size
|
||||||
|
@ -100,8 +103,9 @@ checks the device cache status on start and tries to disable cache for SATA/SAS
|
||||||
If it doesn't succeed it issues a warning in the system log.
|
If it doesn't succeed it issues a warning in the system log.
|
||||||
|
|
||||||
You can also pass other OSD options here as arguments and they'll be persisted
|
You can also pass other OSD options here as arguments and they'll be persisted
|
||||||
to the superblock: max_write_iodepth, max_write_iodepth, min_flusher_count,
|
in the superblock: cached_io_data, cached_io_meta, cached_io_journal,
|
||||||
max_flusher_count, inmemory_metadata, inmemory_journal, journal_sector_buffer_count,
|
inmemory_metadata, inmemory_journal, max_write_iodepth,
|
||||||
|
min_flusher_count, max_flusher_count, journal_sector_buffer_count,
|
||||||
journal_no_same_sector_overwrites, throttle_small_writes, throttle_target_iops,
|
journal_no_same_sector_overwrites, throttle_small_writes, throttle_target_iops,
|
||||||
throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
||||||
See [Runtime OSD Parameters](../config/osd.en.md) for details.
|
See [Runtime OSD Parameters](../config/osd.en.md) for details.
|
||||||
|
@ -179,6 +183,14 @@ Try to read Vitastor OSD superblock from `<device>` and print it in JSON format.
|
||||||
|
|
||||||
Read JSON from STDIN and write it into Vitastor OSD superblock on `<device>`.
|
Read JSON from STDIN and write it into Vitastor OSD superblock on `<device>`.
|
||||||
|
|
||||||
|
## update-sb
|
||||||
|
|
||||||
|
`vitastor-disk update-sb <device> [--force] [--<parameter> <value>] [...]`
|
||||||
|
|
||||||
|
Read Vitastor OSD superblock from <device>, update parameters in it and write it back.
|
||||||
|
|
||||||
|
`--force` allows to ignore validation errors.
|
||||||
|
|
||||||
## udev
|
## udev
|
||||||
|
|
||||||
`vitastor-disk udev <device>`
|
`vitastor-disk udev <device>`
|
||||||
|
@ -249,7 +261,9 @@ Options (see also [Cluster-Wide Disk Layout Parameters](../config/layout-cluster
|
||||||
```
|
```
|
||||||
--object_size 128k Set blockstore block size
|
--object_size 128k Set blockstore block size
|
||||||
--bitmap_granularity 4k Set bitmap granularity
|
--bitmap_granularity 4k Set bitmap granularity
|
||||||
--journal_size 32M Set journal size
|
--journal_size 16M Set journal size
|
||||||
|
--data_csum_type none Set data checksum type (crc32c or none)
|
||||||
|
--csum_block_size 4k Set data checksum block size
|
||||||
--device_block_size 4k Set device block size
|
--device_block_size 4k Set device block size
|
||||||
--journal_offset 0 Set journal offset
|
--journal_offset 0 Set journal offset
|
||||||
--device_size 0 Set device size
|
--device_size 0 Set device size
|
||||||
|
|
|
@ -17,6 +17,7 @@ vitastor-disk - инструмент командной строки для уп
|
||||||
- [purge](#purge)
|
- [purge](#purge)
|
||||||
- [read-sb](#read-sb)
|
- [read-sb](#read-sb)
|
||||||
- [write-sb](#write-sb)
|
- [write-sb](#write-sb)
|
||||||
|
- [update-sb](#update-sb)
|
||||||
- [udev](#udev)
|
- [udev](#udev)
|
||||||
- [exec-osd](#exec-osd)
|
- [exec-osd](#exec-osd)
|
||||||
- [pre-exec](#pre-exec)
|
- [pre-exec](#pre-exec)
|
||||||
|
@ -87,6 +88,8 @@ vitastor-disk - инструмент командной строки для уп
|
||||||
--journal_size 1G/32M Задать размер журнала (области или раздела журнала)
|
--journal_size 1G/32M Задать размер журнала (области или раздела журнала)
|
||||||
--block_size 1M/128k Задать размер объекта хранилища
|
--block_size 1M/128k Задать размер объекта хранилища
|
||||||
--bitmap_granularity 4k Задать гранулярность битовых карт
|
--bitmap_granularity 4k Задать гранулярность битовых карт
|
||||||
|
--data_csum_type none Задать тип контрольных сумм (crc32c или none)
|
||||||
|
--csum_block_size 4k Задать размер блока расчёта контрольных сумм
|
||||||
--data_device_block 4k Задать размер блока устройства данных
|
--data_device_block 4k Задать размер блока устройства данных
|
||||||
--meta_device_block 4k Задать размер блока метаданных
|
--meta_device_block 4k Задать размер блока метаданных
|
||||||
--journal_device_block 4k Задать размер блока журнала
|
--journal_device_block 4k Задать размер блока журнала
|
||||||
|
@ -101,8 +104,9 @@ vitastor-disk - инструмент командной строки для уп
|
||||||
это не удаётся, в системный журнал выводится предупреждение.
|
это не удаётся, в системный журнал выводится предупреждение.
|
||||||
|
|
||||||
Вы можете передать данной команде и некоторые другие опции OSD в качестве аргументов
|
Вы можете передать данной команде и некоторые другие опции OSD в качестве аргументов
|
||||||
и они тоже будут сохранены в суперблок: max_write_iodepth, max_write_iodepth, min_flusher_count,
|
и они тоже будут сохранены в суперблок: cached_io_data, cached_io_meta,
|
||||||
max_flusher_count, inmemory_metadata, inmemory_journal, journal_sector_buffer_count,
|
cached_io_journal, inmemory_metadata, inmemory_journal, max_write_iodepth,
|
||||||
|
min_flusher_count, max_flusher_count, journal_sector_buffer_count,
|
||||||
journal_no_same_sector_overwrites, throttle_small_writes, throttle_target_iops,
|
journal_no_same_sector_overwrites, throttle_small_writes, throttle_target_iops,
|
||||||
throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
||||||
Читайте об этих параметрах подробнее в разделе [Изменяемые параметры OSD](../config/osd.ru.md).
|
Читайте об этих параметрах подробнее в разделе [Изменяемые параметры OSD](../config/osd.ru.md).
|
||||||
|
@ -184,6 +188,15 @@ throttle_target_mbs, throttle_target_parallelism, throttle_threshold_us.
|
||||||
|
|
||||||
Прочитать JSON со стандартного ввода и записать его в суперблок OSD на диск `<device>`.
|
Прочитать JSON со стандартного ввода и записать его в суперблок OSD на диск `<device>`.
|
||||||
|
|
||||||
|
## update-sb
|
||||||
|
|
||||||
|
`vitastor-disk update-sb <device> [--force] [--<параметр> <значение>] [...]`
|
||||||
|
|
||||||
|
Прочитать суперблок OSD с диска `<device>`, изменить в нём заданные параметры и записать обратно.
|
||||||
|
|
||||||
|
Опция `--force` позволяет читать суперблок, даже если он считается некорректным
|
||||||
|
из-за ошибок валидации.
|
||||||
|
|
||||||
## udev
|
## udev
|
||||||
|
|
||||||
`vitastor-disk udev <device>`
|
`vitastor-disk udev <device>`
|
||||||
|
@ -254,7 +267,9 @@ OSD отключены fsync-и.
|
||||||
```
|
```
|
||||||
--object_size 128k Размер блока хранилища
|
--object_size 128k Размер блока хранилища
|
||||||
--bitmap_granularity 4k Гранулярность битовых карт
|
--bitmap_granularity 4k Гранулярность битовых карт
|
||||||
--journal_size 32M Размер журнала
|
--journal_size 16M Размер журнала
|
||||||
|
--data_csum_type none Задать тип контрольных сумм (crc32c или none)
|
||||||
|
--csum_block_size 4k Задать размер блока расчёта контрольных сумм
|
||||||
--device_block_size 4k Размер блока устройства
|
--device_block_size 4k Размер блока устройства
|
||||||
--journal_offset 0 Смещение журнала
|
--journal_offset 0 Смещение журнала
|
||||||
--device_size 0 Размер устройства
|
--device_size 0 Размер устройства
|
||||||
|
|
|
@ -14,10 +14,13 @@ Vitastor has a fio driver which can be installed from the package vitastor-fio.
|
||||||
Use the following command as an example to run tests with fio against a Vitastor cluster:
|
Use the following command as an example to run tests with fio against a Vitastor cluster:
|
||||||
|
|
||||||
```
|
```
|
||||||
fio -thread -ioengine=libfio_vitastor.so -name=test -bs=4M -direct=1 -iodepth=16 -rw=write -etcd=10.115.0.10:2379/v3 -image=testimg
|
fio -thread -ioengine=libfio_vitastor.so -name=test -bs=4M -direct=1 -iodepth=16 -rw=write -image=testimg
|
||||||
```
|
```
|
||||||
|
|
||||||
If you don't want to access your image by name, you can specify pool number, inode number and size
|
If you don't want to access your image by name, you can specify pool number, inode number and size
|
||||||
(`-pool=1 -inode=1 -size=400G`) instead of the image name (`-image=testimg`).
|
(`-pool=1 -inode=1 -size=400G`) instead of the image name (`-image=testimg`).
|
||||||
|
|
||||||
See exact fio commands to use for benchmarking [here](../performance/understanding.en.md#команды-fio).
|
You can also specify etcd address(es) explicitly by adding `-etcd=10.115.0.10:2379/v3`, or you
|
||||||
|
can override configuration file path by adding `-conf=/etc/vitastor/vitastor.conf`.
|
||||||
|
|
||||||
|
See exact fio commands to use for benchmarking [here](../performance/understanding.en.md#fio-commands).
|
||||||
|
|
|
@ -14,10 +14,13 @@
|
||||||
Используйте следующую команду как пример для запуска тестов кластера Vitastor через fio:
|
Используйте следующую команду как пример для запуска тестов кластера Vitastor через fio:
|
||||||
|
|
||||||
```
|
```
|
||||||
fio -thread -ioengine=libfio_vitastor.so -name=test -bs=4M -direct=1 -iodepth=16 -rw=write -etcd=10.115.0.10:2379/v3 -image=testimg
|
fio -thread -ioengine=libfio_vitastor.so -name=test -bs=4M -direct=1 -iodepth=16 -rw=write -image=testimg
|
||||||
```
|
```
|
||||||
|
|
||||||
Вместо обращения к образу по имени (`-image=testimg`) можно указать номер пула, номер инода и размер:
|
Вместо обращения к образу по имени (`-image=testimg`) можно указать номер пула, номер инода и размер:
|
||||||
`-pool=1 -inode=1 -size=400G`.
|
`-pool=1 -inode=1 -size=400G`.
|
||||||
|
|
||||||
|
Вы также можете задать адрес(а) подключения к etcd явно, добавив `-etcd=10.115.0.10:2379/v3`,
|
||||||
|
или переопределить путь к файлу конфигурации, добавив `-conf=/etc/vitastor/vitastor.conf`.
|
||||||
|
|
||||||
Конкретные команды fio для тестирования производительности можно посмотреть [здесь](../performance/understanding.ru.md#команды-fio).
|
Конкретные команды fio для тестирования производительности можно посмотреть [здесь](../performance/understanding.ru.md#команды-fio).
|
||||||
|
|
|
@ -11,20 +11,42 @@ NBD stands for "Network Block Device", but in fact it also functions as "BUSE"
|
||||||
NBD slighly lowers the performance due to additional overhead, but performance still
|
NBD slighly lowers the performance due to additional overhead, but performance still
|
||||||
remains decent (see an example [here](../performance/comparison1.en.md#vitastor-0-4-0-nbd)).
|
remains decent (see an example [here](../performance/comparison1.en.md#vitastor-0-4-0-nbd)).
|
||||||
|
|
||||||
Vitastor Kubernetes CSI driver is based on NBD.
|
See also [VDUSE](qemu.en.md#vduse) as a better alternative to NBD.
|
||||||
|
|
||||||
|
Vitastor Kubernetes CSI driver uses NBD when VDUSE is unavailable.
|
||||||
|
|
||||||
## Map image
|
## Map image
|
||||||
|
|
||||||
To create a local block device for a Vitastor image run:
|
To create a local block device for a Vitastor image run:
|
||||||
|
|
||||||
```
|
```
|
||||||
vitastor-nbd map --etcd_address 10.115.0.10:2379/v3 --image testimg
|
vitastor-nbd map --image testimg
|
||||||
```
|
```
|
||||||
|
|
||||||
It will output a block device name like /dev/nbd0 which you can then use as a normal disk.
|
It will output a block device name like /dev/nbd0 which you can then use as a normal disk.
|
||||||
|
|
||||||
You can also use `--pool <POOL> --inode <INODE> --size <SIZE>` instead of `--image <IMAGE>` if you want.
|
You can also use `--pool <POOL> --inode <INODE> --size <SIZE>` instead of `--image <IMAGE>` if you want.
|
||||||
|
|
||||||
|
vitastor-nbd supports all usual Vitastor configuration options like `--config_file <path_to_config>` plus NBD-specific:
|
||||||
|
|
||||||
|
* `--nbd_timeout 300` \
|
||||||
|
Timeout for I/O operations in seconds after exceeding which the kernel stops
|
||||||
|
the device. You can set it to 0 to disable the timeout, but beware that you
|
||||||
|
won't be able to stop the device at all if vitastor-nbd process dies.
|
||||||
|
* `--nbd_max_devices 64 --nbd_max_part 3` \
|
||||||
|
Options for the `nbd` kernel module when modprobing it (`nbds_max` and `max_part`).
|
||||||
|
note that maximum allowed (nbds_max)*(1+max_part) is 256.
|
||||||
|
* `--logfile /path/to/log/file.txt` \
|
||||||
|
Write log messages to the specified file instead of dropping them (in background mode)
|
||||||
|
or printing them to the standard output (in foreground mode).
|
||||||
|
* `--dev_num N` \
|
||||||
|
Use the specified device /dev/nbdN instead of automatic selection.
|
||||||
|
* `--foreground 1` \
|
||||||
|
Stay in foreground, do not daemonize.
|
||||||
|
|
||||||
|
Note that `nbd_timeout`, `nbd_max_devices` and `nbd_max_part` options may also be specified
|
||||||
|
in `/etc/vitastor/vitastor.conf` or in other configuration file specified with `--config_file`.
|
||||||
|
|
||||||
## Unmap image
|
## Unmap image
|
||||||
|
|
||||||
To unmap the device run:
|
To unmap the device run:
|
||||||
|
@ -32,3 +54,27 @@ To unmap the device run:
|
||||||
```
|
```
|
||||||
vitastor-nbd unmap /dev/nbd0
|
vitastor-nbd unmap /dev/nbd0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## List mapped images
|
||||||
|
|
||||||
|
```
|
||||||
|
vitastor-nbd ls [--json]
|
||||||
|
```
|
||||||
|
|
||||||
|
Example output (normal format):
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev/nbd0
|
||||||
|
image: bench
|
||||||
|
pid: 584536
|
||||||
|
|
||||||
|
/dev/nbd1
|
||||||
|
image: bench1
|
||||||
|
pid: 584546
|
||||||
|
```
|
||||||
|
|
||||||
|
Example output (JSON format):
|
||||||
|
|
||||||
|
```
|
||||||
|
{"/dev/nbd0": {"image": "bench", "pid": 584536}, "/dev/nbd1": {"image": "bench1", "pid": 584546}}
|
||||||
|
```
|
||||||
|
|
|
@ -14,14 +14,16 @@ NBD на данный момент необходимо, чтобы монтир
|
||||||
NBD немного снижает производительность из-за дополнительных копирований памяти,
|
NBD немного снижает производительность из-за дополнительных копирований памяти,
|
||||||
но она всё равно остаётся на неплохом уровне (см. для примера [тест](../performance/comparison1.ru.md#vitastor-0-4-0-nbd)).
|
но она всё равно остаётся на неплохом уровне (см. для примера [тест](../performance/comparison1.ru.md#vitastor-0-4-0-nbd)).
|
||||||
|
|
||||||
CSI-драйвер Kubernetes Vitastor основан на NBD.
|
Смотрите также [VDUSE](qemu.ru.md#vduse), как лучшую альтернативу NBD.
|
||||||
|
|
||||||
|
CSI-драйвер Kubernetes Vitastor использует NBD, когда VDUSE недоступен.
|
||||||
|
|
||||||
## Подключить устройство
|
## Подключить устройство
|
||||||
|
|
||||||
Чтобы создать локальное блочное устройство для образа, выполните команду:
|
Чтобы создать локальное блочное устройство для образа, выполните команду:
|
||||||
|
|
||||||
```
|
```
|
||||||
vitastor-nbd map --etcd_address 10.115.0.10:2379/v3 --image testimg
|
vitastor-nbd map --image testimg
|
||||||
```
|
```
|
||||||
|
|
||||||
Команда напечатает название блочного устройства вида /dev/nbd0, которое потом можно
|
Команда напечатает название блочного устройства вида /dev/nbd0, которое потом можно
|
||||||
|
@ -30,6 +32,32 @@ vitastor-nbd map --etcd_address 10.115.0.10:2379/v3 --image testimg
|
||||||
Для обращения по номеру инода, аналогично другим командам, можно использовать опции
|
Для обращения по номеру инода, аналогично другим командам, можно использовать опции
|
||||||
`--pool <POOL> --inode <INODE> --size <SIZE>` вместо `--image testimg`.
|
`--pool <POOL> --inode <INODE> --size <SIZE>` вместо `--image testimg`.
|
||||||
|
|
||||||
|
vitastor-nbd поддерживает все обычные опции Vitastor, например, `--config_file <path_to_config>`,
|
||||||
|
плюс специфичные для NBD:
|
||||||
|
|
||||||
|
* `--nbd_timeout 30` \
|
||||||
|
Максимальное время выполнения любой операции чтения/записи в секундах, при
|
||||||
|
превышении которого ядро остановит NBD-устройство. Вы можете установить опцию
|
||||||
|
в 0, чтобы отключить ограничение времени, но имейте в виду, что в этом случае
|
||||||
|
вы вообще не сможете отключить NBD-устройство при нештатном завершении процесса
|
||||||
|
vitastor-nbd.
|
||||||
|
* `--nbd_max_devices 64 --nbd_max_part 3` \
|
||||||
|
Опции, передаваемые модулю ядра nbd, если его загружает vitastor-nbd
|
||||||
|
(`nbds_max` и `max_part`). Имейте в виду, что (nbds_max)*(1+max_part)
|
||||||
|
обычно не должно превышать 256.
|
||||||
|
* `--logfile /path/to/log/file.txt` \
|
||||||
|
Писать сообщения о процессе работы в заданный файл, вместо пропуска их
|
||||||
|
при фоновом режиме запуска или печати на стандартный вывод при запуске
|
||||||
|
в консоли с `--foreground 1`.
|
||||||
|
* `--dev_num N` \
|
||||||
|
Использовать заданное устройство `/dev/nbdN` вместо автоматического подбора.
|
||||||
|
* `--foreground 1` \
|
||||||
|
Не уводить процесс в фоновый режим.
|
||||||
|
|
||||||
|
Обратите внимание, что опции `nbd_timeout`, `nbd_max_devices` и `nbd_max_part` можно
|
||||||
|
также задавать в `/etc/vitastor/vitastor.conf` или в другом файле конфигурации,
|
||||||
|
заданном опцией `--config_file`.
|
||||||
|
|
||||||
## Отключить устройство
|
## Отключить устройство
|
||||||
|
|
||||||
Для отключения устройства выполните:
|
Для отключения устройства выполните:
|
||||||
|
@ -37,3 +65,27 @@ vitastor-nbd map --etcd_address 10.115.0.10:2379/v3 --image testimg
|
||||||
```
|
```
|
||||||
vitastor-nbd unmap /dev/nbd0
|
vitastor-nbd unmap /dev/nbd0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Вывести подключённые устройства
|
||||||
|
|
||||||
|
```
|
||||||
|
vitastor-nbd ls [--json]
|
||||||
|
```
|
||||||
|
|
||||||
|
Пример вывода в обычном формате:
|
||||||
|
|
||||||
|
```
|
||||||
|
/dev/nbd0
|
||||||
|
image: bench
|
||||||
|
pid: 584536
|
||||||
|
|
||||||
|
/dev/nbd1
|
||||||
|
image: bench1
|
||||||
|
pid: 584546
|
||||||
|
```
|
||||||
|
|
||||||
|
Пример вывода в JSON-формате:
|
||||||
|
|
||||||
|
```
|
||||||
|
{"/dev/nbd0": {"image": "bench", "pid": 584536}, "/dev/nbd1": {"image": "bench1", "pid": 584546}}
|
||||||
|
```
|
||||||
|
|
|
@ -23,7 +23,7 @@ balancer or any failover method you want to in that case.
|
||||||
vitastor-nfs usage:
|
vitastor-nfs usage:
|
||||||
|
|
||||||
```
|
```
|
||||||
vitastor-nfs [--etcd_address ADDR] [OTHER OPTIONS]
|
vitastor-nfs [STANDARD OPTIONS] [OTHER OPTIONS]
|
||||||
|
|
||||||
--subdir <DIR> export images prefixed <DIR>/ (default empty - export all images)
|
--subdir <DIR> export images prefixed <DIR>/ (default empty - export all images)
|
||||||
--portmap 0 do not listen on port 111 (portmap/rpcbind, requires root)
|
--portmap 0 do not listen on port 111 (portmap/rpcbind, requires root)
|
||||||
|
@ -34,7 +34,7 @@ vitastor-nfs [--etcd_address ADDR] [OTHER OPTIONS]
|
||||||
--foreground 1 stay in foreground, do not daemonize
|
--foreground 1 stay in foreground, do not daemonize
|
||||||
```
|
```
|
||||||
|
|
||||||
Example start and mount commands:
|
Example start and mount commands (etcd_address is optional):
|
||||||
|
|
||||||
```
|
```
|
||||||
vitastor-nfs --etcd_address 192.168.5.10:2379 --portmap 0 --port 2050 --pool testpool
|
vitastor-nfs --etcd_address 192.168.5.10:2379 --portmap 0 --port 2050 --pool testpool
|
||||||
|
|
|
@ -22,18 +22,18 @@
|
||||||
Использование vitastor-nfs:
|
Использование vitastor-nfs:
|
||||||
|
|
||||||
```
|
```
|
||||||
vitastor-nfs [--etcd_address ADDR] [ДРУГИЕ ОПЦИИ]
|
vitastor-nfs [СТАНДАРТНЫЕ ОПЦИИ] [ДРУГИЕ ОПЦИИ]
|
||||||
|
|
||||||
--subdir <DIR> экспортировать "поддиректорию" - образы с префиксом имени <DIR>/ (по умолчанию пусто - экспортировать все образы)
|
--subdir <DIR> экспортировать "поддиректорию" - образы с префиксом имени <DIR>/ (по умолчанию пусто - экспортировать все образы)
|
||||||
--portmap 0 отключить сервис portmap/rpcbind на порту 111 (по умолчанию включён и требует root привилегий)
|
--portmap 0 отключить сервис portmap/rpcbind на порту 111 (по умолчанию включён и требует root привилегий)
|
||||||
--bind <IP> принимать соединения по адресу <IP> (по умолчанию 0.0.0.0 - на всех)
|
--bind <IP> принимать соединения по адресу <IP> (по умолчанию 0.0.0.0 - на всех)
|
||||||
--nfspath <PATH> установить путь NFS-экспорта в <PATH> (по умолчанию /)
|
--nfspath <PATH> установить путь NFS-экспорта в <PATH> (по умолчанию /)
|
||||||
--port <PORT> использовать порт <PORT> для NFS-сервисов (по умолчанию 2049)
|
--port <PORT> использовать порт <PORT> для NFS-сервисов (по умолчанию 2049)
|
||||||
--pool <POOL> исползовать пул <POOL> для новых образов (обязательно, если пул в кластере не один)
|
--pool <POOL> использовать пул <POOL> для новых образов (обязательно, если пул в кластере не один)
|
||||||
--foreground 1 не уходить в фон после запуска
|
--foreground 1 не уходить в фон после запуска
|
||||||
```
|
```
|
||||||
|
|
||||||
Пример монтирования Vitastor через NFS:
|
Пример монтирования Vitastor через NFS (etcd_address необязателен):
|
||||||
|
|
||||||
```
|
```
|
||||||
vitastor-nfs --etcd_address 192.168.5.10:2379 --portmap 0 --port 2050 --pool testpool
|
vitastor-nfs --etcd_address 192.168.5.10:2379 --portmap 0 --port 2050 --pool testpool
|
||||||
|
|
|
@ -16,13 +16,16 @@ Old syntax (-drive):
|
||||||
|
|
||||||
```
|
```
|
||||||
qemu-system-x86_64 -enable-kvm -m 1024 \
|
qemu-system-x86_64 -enable-kvm -m 1024 \
|
||||||
-drive 'file=vitastor:etcd_host=192.168.7.2\:2379/v3:image=debian9',
|
-drive 'file=vitastor:image=debian9',
|
||||||
format=raw,if=none,id=drive-virtio-disk0,cache=none \
|
format=raw,if=none,id=drive-virtio-disk0,cache=none \
|
||||||
-device 'virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,
|
-device 'virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,
|
||||||
id=virtio-disk0,bootindex=1,write-cache=off' \
|
id=virtio-disk0,bootindex=1,write-cache=off' \
|
||||||
-vnc 0.0.0.0:0
|
-vnc 0.0.0.0:0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Etcd address may be specified explicitly by adding `:etcd_host=192.168.7.2\:2379/v3` to `file=`.
|
||||||
|
Configuration file path may be overriden by adding `:config_path=/etc/vitastor/vitastor.conf`.
|
||||||
|
|
||||||
New syntax (-blockdev):
|
New syntax (-blockdev):
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -34,14 +37,28 @@ qemu-system-x86_64 -enable-kvm -m 1024 \
|
||||||
-vnc 0.0.0.0:0
|
-vnc 0.0.0.0:0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
With a separate I/O thread:
|
||||||
|
|
||||||
|
```
|
||||||
|
qemu-system-x86_64 -enable-kvm -m 1024 \
|
||||||
|
-object iothread,id=vitastor1 \
|
||||||
|
-blockdev '{"node-name":"drive-virtio-disk0","driver":"vitastor","image":"debian9",
|
||||||
|
"cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \
|
||||||
|
-device 'virtio-blk-pci,iothread=vitastor1,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,
|
||||||
|
id=virtio-disk0,bootindex=1,write-cache=off' \
|
||||||
|
-vnc 0.0.0.0:0
|
||||||
|
```
|
||||||
|
|
||||||
|
You can also specify inode ID, pool and size manually instead of `:image=<IMAGE>` option: `:pool=<POOL>:inode=<INODE>:size=<SIZE>`.
|
||||||
|
|
||||||
## qemu-img
|
## qemu-img
|
||||||
|
|
||||||
For qemu-img, you should use `vitastor:etcd_host=<HOST>:image=<IMAGE>` as filename.
|
For qemu-img, you should use `vitastor:image=<IMAGE>[:etcd_host=<HOST>]` as filename.
|
||||||
|
|
||||||
For example, to upload a VM image into Vitastor, run:
|
For example, to upload a VM image into Vitastor, run:
|
||||||
|
|
||||||
```
|
```
|
||||||
qemu-img convert -f qcow2 debian10.qcow2 -p -O raw 'vitastor:etcd_host=192.168.7.2\:2379/v3:image=debian10'
|
qemu-img convert -f qcow2 debian10.qcow2 -p -O raw 'vitastor:image=debian10'
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also specify `:pool=<POOL>:inode=<INODE>:size=<SIZE>` instead of `:image=<IMAGE>`
|
You can also specify `:pool=<POOL>:inode=<INODE>:size=<SIZE>` instead of `:image=<IMAGE>`
|
||||||
|
@ -58,10 +75,10 @@ the snapshot separately using the following commands (key points are using `skip
|
||||||
`-B backing_file` option):
|
`-B backing_file` option):
|
||||||
|
|
||||||
```
|
```
|
||||||
qemu-img convert -f raw 'vitastor:etcd_host=192.168.7.2\:2379/v3:image=testimg@0' \
|
qemu-img convert -f raw 'vitastor:image=testimg@0' \
|
||||||
-O qcow2 testimg_0.qcow2
|
-O qcow2 testimg_0.qcow2
|
||||||
|
|
||||||
qemu-img convert -f raw 'vitastor:etcd_host=192.168.7.2\:2379/v3:image=testimg:skip-parents=1' \
|
qemu-img convert -f raw 'vitastor:image=testimg:skip-parents=1' \
|
||||||
-O qcow2 -o 'cluster_size=4k' -B testimg_0.qcow2 testimg.qcow2
|
-O qcow2 -o 'cluster_size=4k' -B testimg_0.qcow2 testimg.qcow2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -83,3 +100,94 @@ qemu-img rebase -u -b '' testimg.qcow2
|
||||||
This can be used for backups. Just note that exporting an image that is currently being written to
|
This can be used for backups. Just note that exporting an image that is currently being written to
|
||||||
is of course unsafe and doesn't produce a consistent result, so only export snapshots if you do this
|
is of course unsafe and doesn't produce a consistent result, so only export snapshots if you do this
|
||||||
on a live VM.
|
on a live VM.
|
||||||
|
|
||||||
|
## vhost-user-blk
|
||||||
|
|
||||||
|
QEMU, starting with 6.0, includes support for attaching disks via a separate
|
||||||
|
userspace worker process, called `vhost-user-blk`. It usually has slightly (20-30 us)
|
||||||
|
lower latency.
|
||||||
|
|
||||||
|
Example commands to use it with Vitastor:
|
||||||
|
|
||||||
|
```
|
||||||
|
qemu-storage-daemon \
|
||||||
|
--daemonize \
|
||||||
|
--blockdev '{"node-name":"drive-virtio-disk1","driver":"vitastor","image":"testosd1","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \
|
||||||
|
--export type=vhost-user-blk,id=vitastor1,node-name=drive-virtio-disk1,addr.type=unix,addr.path=/run/vitastor1-user-blk.sock,writable=on,num-queues=1
|
||||||
|
|
||||||
|
qemu-system-x86_64 -enable-kvm -m 2048 -M accel=kvm,memory-backend=mem \
|
||||||
|
-object memory-backend-memfd,id=mem,size=2G,share=on \
|
||||||
|
-chardev socket,id=vitastor1,reconnect=1,path=/run/vitastor1-user-blk.sock \
|
||||||
|
-device vhost-user-blk-pci,chardev=vitastor1,num-queues=1,config-wce=off \
|
||||||
|
-vnc 0.0.0.0:0
|
||||||
|
```
|
||||||
|
|
||||||
|
memfd memory-backend is crucial, vhost-user-blk does not work without it.
|
||||||
|
|
||||||
|
## VDUSE
|
||||||
|
|
||||||
|
Linux kernel, starting with version 5.15, supports a new interface for attaching virtual disks
|
||||||
|
to the host - VDUSE (vDPA Device in Userspace). QEMU, starting with 7.2, has support for
|
||||||
|
exporting QEMU block devices over this protocol using qemu-storage-daemon.
|
||||||
|
|
||||||
|
VDUSE is currently the best interface to attach Vitastor disks as kernel devices because:
|
||||||
|
- It avoids data copies and thus achieves much better performance than [NBD](nbd.en.md)
|
||||||
|
- It doesn't have NBD timeout problem - the device doesn't die if an operation executes for too long
|
||||||
|
- It doesn't have hung device problem - if the userspace process dies it can be restarted (!)
|
||||||
|
and block device will continue operation
|
||||||
|
- It doesn't seem to have the device number limit
|
||||||
|
|
||||||
|
Example performance comparison:
|
||||||
|
|
||||||
|
| | direct fio | NBD | VDUSE |
|
||||||
|
|----------------------|-------------|-------------|-------------|
|
||||||
|
| linear write | 3.85 GB/s | 1.12 GB/s | 3.85 GB/s |
|
||||||
|
| 4k random write Q128 | 240000 iops | 120000 iops | 178000 iops |
|
||||||
|
| 4k random write Q1 | 9500 iops | 7620 iops | 7640 iops |
|
||||||
|
| linear read | 4.3 GB/s | 1.8 GB/s | 2.85 GB/s |
|
||||||
|
| 4k random read Q128 | 287000 iops | 140000 iops | 189000 iops |
|
||||||
|
| 4k random read Q1 | 9600 iops | 7640 iops | 7780 iops |
|
||||||
|
|
||||||
|
To try VDUSE you need at least Linux 5.15, built with VDUSE support
|
||||||
|
(CONFIG_VDPA=m, CONFIG_VDPA_USER=m, CONFIG_VIRTIO_VDPA=m).
|
||||||
|
|
||||||
|
Debian Linux kernels have these options disabled by now, so if you want to try it on Debian,
|
||||||
|
use a kernel from Ubuntu [kernel-ppa/mainline](https://kernel.ubuntu.com/~kernel-ppa/mainline/), Proxmox,
|
||||||
|
or build modules for Debian kernel manually:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
apt-get install linux-headers-`uname -r`
|
||||||
|
apt-get build-dep linux-image-`uname -r`-unsigned
|
||||||
|
apt-get source linux-image-`uname -r`-unsigned
|
||||||
|
cd linux*/drivers/vdpa
|
||||||
|
make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install
|
||||||
|
cat Module.symvers >> /lib/modules/`uname -r`/build/Module.symvers
|
||||||
|
cd ../virtio
|
||||||
|
make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install
|
||||||
|
depmod -a
|
||||||
|
```
|
||||||
|
|
||||||
|
You also need `vdpa` tool from the `iproute2` package.
|
||||||
|
|
||||||
|
Commands to attach Vitastor image as a VDUSE device:
|
||||||
|
|
||||||
|
```
|
||||||
|
modprobe vduse
|
||||||
|
modprobe virtio-vdpa
|
||||||
|
qemu-storage-daemon --daemonize --blockdev '{"node-name":"test1","driver":"vitastor",\
|
||||||
|
"etcd-host":"192.168.7.2:2379/v3","image":"testosd1","cache":{"direct":true,"no-flush":false},"discard":"unmap"}' \
|
||||||
|
--export vduse-blk,id=test1,node-name=test1,name=test1,num-queues=16,queue-size=128,writable=true
|
||||||
|
vdpa dev add name test1 mgmtdev vduse
|
||||||
|
```
|
||||||
|
|
||||||
|
After running these commands, `/dev/vda` device will appear in the system and you'll be able to
|
||||||
|
use it as a normal disk.
|
||||||
|
|
||||||
|
To remove the device:
|
||||||
|
|
||||||
|
```
|
||||||
|
vdpa dev del test1
|
||||||
|
kill <qemu-storage-daemon_process_PID>
|
||||||
|
```
|
||||||
|
|
|
@ -18,13 +18,16 @@
|
||||||
|
|
||||||
```
|
```
|
||||||
qemu-system-x86_64 -enable-kvm -m 1024 \
|
qemu-system-x86_64 -enable-kvm -m 1024 \
|
||||||
-drive 'file=vitastor:etcd_host=192.168.7.2\:2379/v3:image=debian9',
|
-drive 'file=vitastor:image=debian9',
|
||||||
format=raw,if=none,id=drive-virtio-disk0,cache=none \
|
format=raw,if=none,id=drive-virtio-disk0,cache=none \
|
||||||
-device 'virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,
|
-device 'virtio-blk-pci,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,
|
||||||
id=virtio-disk0,bootindex=1,write-cache=off' \
|
id=virtio-disk0,bootindex=1,write-cache=off' \
|
||||||
-vnc 0.0.0.0:0
|
-vnc 0.0.0.0:0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Адрес подключения etcd можно задать явно, если добавить `:etcd_host=192.168.7.2\:2379/v3` к `file=`.
|
||||||
|
Путь к файлу конфигурации можно переопределить, добавив `:config_path=/etc/vitastor/vitastor.conf`.
|
||||||
|
|
||||||
Новый синтаксис (-blockdev):
|
Новый синтаксис (-blockdev):
|
||||||
|
|
||||||
```
|
```
|
||||||
|
@ -36,16 +39,28 @@ qemu-system-x86_64 -enable-kvm -m 1024 \
|
||||||
-vnc 0.0.0.0:0
|
-vnc 0.0.0.0:0
|
||||||
```
|
```
|
||||||
|
|
||||||
|
С отдельным потоком ввода-вывода:
|
||||||
|
|
||||||
|
```
|
||||||
|
qemu-system-x86_64 -enable-kvm -m 1024 \
|
||||||
|
-object iothread,id=vitastor1 \
|
||||||
|
-blockdev '{"node-name":"drive-virtio-disk0","driver":"vitastor","image":"debian9",
|
||||||
|
"cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \
|
||||||
|
-device 'virtio-blk-pci,iothread=vitastor1,scsi=off,bus=pci.0,addr=0x5,drive=drive-virtio-disk0,
|
||||||
|
id=virtio-disk0,bootindex=1,write-cache=off' \
|
||||||
|
-vnc 0.0.0.0:0
|
||||||
|
```
|
||||||
|
|
||||||
Вместо `:image=<IMAGE>` также можно указывать номер инода, пул и размер: `:pool=<POOL>:inode=<INODE>:size=<SIZE>`.
|
Вместо `:image=<IMAGE>` также можно указывать номер инода, пул и размер: `:pool=<POOL>:inode=<INODE>:size=<SIZE>`.
|
||||||
|
|
||||||
## qemu-img
|
## qemu-img
|
||||||
|
|
||||||
Для qemu-img используйте строку `vitastor:etcd_host=<HOST>:image=<IMAGE>` в качестве имени файла диска.
|
Для qemu-img используйте строку `vitastor:image=<IMAGE>[:etcd_host=<HOST>]` в качестве имени файла диска.
|
||||||
|
|
||||||
Например, чтобы загрузить образ диска в Vitastor:
|
Например, чтобы загрузить образ диска в Vitastor:
|
||||||
|
|
||||||
```
|
```
|
||||||
qemu-img convert -f qcow2 debian10.qcow2 -p -O raw 'vitastor:etcd_host=10.115.0.10\:2379/v3:image=testimg'
|
qemu-img convert -f qcow2 debian10.qcow2 -p -O raw 'vitastor:image=testimg'
|
||||||
```
|
```
|
||||||
|
|
||||||
Если вы не хотите обращаться к образу по имени, вместо `:image=<IMAGE>` можно указать номер пула, номер инода и размер:
|
Если вы не хотите обращаться к образу по имени, вместо `:image=<IMAGE>` можно указать номер пула, номер инода и размер:
|
||||||
|
@ -61,10 +76,10 @@ qemu-img convert -f qcow2 debian10.qcow2 -p -O raw 'vitastor:etcd_host=10.115.0.
|
||||||
с помощью следующих команд (ключевые моменты - использование `skip-parents=1` и опции `-B backing_file.qcow2`):
|
с помощью следующих команд (ключевые моменты - использование `skip-parents=1` и опции `-B backing_file.qcow2`):
|
||||||
|
|
||||||
```
|
```
|
||||||
qemu-img convert -f raw 'vitastor:etcd_host=192.168.7.2\:2379/v3:image=testimg@0' \
|
qemu-img convert -f raw 'vitastor:image=testimg@0' \
|
||||||
-O qcow2 testimg_0.qcow2
|
-O qcow2 testimg_0.qcow2
|
||||||
|
|
||||||
qemu-img convert -f raw 'vitastor:etcd_host=192.168.7.2\:2379/v3:image=testimg:skip-parents=1' \
|
qemu-img convert -f raw 'vitastor:image=testimg:skip-parents=1' \
|
||||||
-O qcow2 -o 'cluster_size=4k' -B testimg_0.qcow2 testimg.qcow2
|
-O qcow2 -o 'cluster_size=4k' -B testimg_0.qcow2 testimg.qcow2
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -87,3 +102,95 @@ qemu-img rebase -u -b '' testimg.qcow2
|
||||||
Это можно использовать для резервного копирования. Только помните, что экспортировать образ, в который
|
Это можно использовать для резервного копирования. Только помните, что экспортировать образ, в который
|
||||||
в то же время идёт запись, небезопасно - результат чтения не будет целостным. Так что если вы работаете
|
в то же время идёт запись, небезопасно - результат чтения не будет целостным. Так что если вы работаете
|
||||||
с активными виртуальными машинами, экспортируйте только их снимки, но не сам образ.
|
с активными виртуальными машинами, экспортируйте только их снимки, но не сам образ.
|
||||||
|
|
||||||
|
## vhost-user-blk
|
||||||
|
|
||||||
|
QEMU, начиная с 6.0, позволяет подключать диски через отдельный рабочий процесс.
|
||||||
|
Этот метод подключения называется `vhost-user-blk` и обычно имеет чуть меньшую
|
||||||
|
задержку (ниже на 20-30 микросекунд, чем при обычном методе).
|
||||||
|
|
||||||
|
Пример команд для использования vhost-user-blk с Vitastor:
|
||||||
|
|
||||||
|
```
|
||||||
|
qemu-storage-daemon \
|
||||||
|
--daemonize \
|
||||||
|
--blockdev '{"node-name":"drive-virtio-disk1","driver":"vitastor","image":"testosd1","cache":{"direct":true,"no-flush":false},"auto-read-only":true,"discard":"unmap"}' \
|
||||||
|
--export type=vhost-user-blk,id=vitastor1,node-name=drive-virtio-disk1,addr.type=unix,addr.path=/run/vitastor1-user-blk.sock,writable=on,num-queues=1
|
||||||
|
|
||||||
|
qemu-system-x86_64 -enable-kvm -m 2048 -M accel=kvm,memory-backend=mem \
|
||||||
|
-object memory-backend-memfd,id=mem,size=2G,share=on \
|
||||||
|
-chardev socket,id=vitastor1,reconnect=1,path=/run/vitastor1-user-blk.sock \
|
||||||
|
-device vhost-user-blk-pci,chardev=vitastor1,num-queues=1,config-wce=off \
|
||||||
|
-vnc 0.0.0.0:0
|
||||||
|
```
|
||||||
|
|
||||||
|
Здесь критична опция memory-backend-memfd, vhost-user-blk без неё не работает.
|
||||||
|
|
||||||
|
## VDUSE
|
||||||
|
|
||||||
|
В Linux, начиная с версии ядра 5.15, доступен новый интерфейс для подключения виртуальных дисков
|
||||||
|
к системе - VDUSE (vDPA Device in Userspace), а в QEMU, начиная с версии 7.2, есть поддержка
|
||||||
|
экспорта блочных устройств QEMU по этому протоколу через qemu-storage-daemon.
|
||||||
|
|
||||||
|
VDUSE - на данный момент лучший интерфейс для подключения дисков Vitastor в виде блочных
|
||||||
|
устройств на уровне ядра, ибо:
|
||||||
|
- VDUSE не копирует данные и поэтому достигает значительно лучшей производительности, чем [NBD](nbd.ru.md)
|
||||||
|
- Также оно не имеет проблемы NBD-таймаута - устройство не умирает, если операция выполняется слишком долго
|
||||||
|
- Также оно не имеет проблемы подвисающих устройств - если процесс-обработчик умирает, его можно
|
||||||
|
перезапустить (!) и блочное устройство продолжит работать
|
||||||
|
- По-видимому, у него нет предела числа подключаемых в систему устройств
|
||||||
|
|
||||||
|
Пример сравнения производительности:
|
||||||
|
|
||||||
|
| | Прямой fio | NBD | VDUSE |
|
||||||
|
|--------------------------|-------------|-------------|-------------|
|
||||||
|
| линейная запись | 3.85 GB/s | 1.12 GB/s | 3.85 GB/s |
|
||||||
|
| 4k случайная запись Q128 | 240000 iops | 120000 iops | 178000 iops |
|
||||||
|
| 4k случайная запись Q1 | 9500 iops | 7620 iops | 7640 iops |
|
||||||
|
| линейное чтение | 4.3 GB/s | 1.8 GB/s | 2.85 GB/s |
|
||||||
|
| 4k случайное чтение Q128 | 287000 iops | 140000 iops | 189000 iops |
|
||||||
|
| 4k случайное чтение Q1 | 9600 iops | 7640 iops | 7780 iops |
|
||||||
|
|
||||||
|
Чтобы попробовать VDUSE, вам нужно ядро Linux как минимум версии 5.15, собранное с поддержкой
|
||||||
|
VDUSE (CONFIG_VDPA=m, CONFIG_VDPA_USER=m, CONFIG_VIRTIO_VDPA=m).
|
||||||
|
|
||||||
|
В ядрах в Debian Linux поддержка пока отключена по умолчанию, так что чтобы попробовать VDUSE
|
||||||
|
на Debian, поставьте ядро из Ubuntu [kernel-ppa/mainline](https://kernel.ubuntu.com/~kernel-ppa/mainline/),
|
||||||
|
из Proxmox или соберите модули для ядра Debian вручную:
|
||||||
|
|
||||||
|
```
|
||||||
|
mkdir build
|
||||||
|
cd build
|
||||||
|
apt-get install linux-headers-`uname -r`
|
||||||
|
apt-get build-dep linux-image-`uname -r`-unsigned
|
||||||
|
apt-get source linux-image-`uname -r`-unsigned
|
||||||
|
cd linux*/drivers/vdpa
|
||||||
|
make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install
|
||||||
|
cat Module.symvers >> /lib/modules/`uname -r`/build/Module.symvers
|
||||||
|
cd ../virtio
|
||||||
|
make -C /lib/modules/`uname -r`/build M=$PWD CONFIG_VDPA=m CONFIG_VDPA_USER=m CONFIG_VIRTIO_VDPA=m -j8 modules modules_install
|
||||||
|
depmod -a
|
||||||
|
```
|
||||||
|
|
||||||
|
Также вам понадобится консольная утилита `vdpa` из пакета `iproute2`.
|
||||||
|
|
||||||
|
Команды для подключения виртуального диска через VDUSE:
|
||||||
|
|
||||||
|
```
|
||||||
|
modprobe vduse
|
||||||
|
modprobe virtio-vdpa
|
||||||
|
qemu-storage-daemon --daemonize --blockdev '{"node-name":"test1","driver":"vitastor",\
|
||||||
|
"etcd-host":"192.168.7.2:2379/v3","image":"testosd1","cache":{"direct":true,"no-flush":false},"discard":"unmap"}' \
|
||||||
|
--export vduse-blk,id=test1,node-name=test1,name=test1,num-queues=16,queue-size=128,writable=true
|
||||||
|
vdpa dev add name test1 mgmtdev vduse
|
||||||
|
```
|
||||||
|
|
||||||
|
После этого в системе появится устройство `/dev/vda`, которое можно будет использовать как
|
||||||
|
обычный диск.
|
||||||
|
|
||||||
|
Для удаления устройства из системы:
|
||||||
|
|
||||||
|
```
|
||||||
|
vdpa dev del test1
|
||||||
|
kill <PID_процесса_qemu-storage-daemon>
|
||||||
|
```
|
||||||
|
|
|
@ -3,5 +3,5 @@ SUBSYSTEM=="block", ENV{ID_PART_ENTRY_TYPE}=="e7009fac-a5a1-4d72-af72-53de130599
|
||||||
IMPORT{program}="/usr/bin/vitastor-disk udev $devnode", \
|
IMPORT{program}="/usr/bin/vitastor-disk udev $devnode", \
|
||||||
SYMLINK+="vitastor/$env{VITASTOR_ALIAS}"
|
SYMLINK+="vitastor/$env{VITASTOR_ALIAS}"
|
||||||
|
|
||||||
ENV{VITASTOR_OSD_NUM}!="", ACTION=="add", RUN{program}+="/usr/bin/systemctl enable --now vitastor-osd@$env{VITASTOR_OSD_NUM}"
|
ENV{VITASTOR_OSD_NUM}!="", ACTION=="add", RUN{program}+="/usr/bin/systemctl enable --now --no-block vitastor-osd@$env{VITASTOR_OSD_NUM}"
|
||||||
ENV{VITASTOR_OSD_NUM}!="", ACTION=="remove", RUN{program}+="/usr/bin/systemctl disable --now vitastor-osd@$env{VITASTOR_OSD_NUM}"
|
ENV{VITASTOR_OSD_NUM}!="", ACTION=="remove", RUN{program}+="/usr/bin/systemctl disable --now --no-block vitastor-osd@$env{VITASTOR_OSD_NUM}"
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
scale_pg_count,
|
scale_pg_count,
|
||||||
|
scale_pg_history,
|
||||||
};
|
};
|
||||||
|
|
||||||
function add_pg_history(new_pg_history, new_pg, prev_pgs, prev_pg_history, old_pg)
|
function add_pg_history(new_pg_history, new_pg, prev_pgs, prev_pg_history, old_pg)
|
||||||
|
@ -43,16 +44,18 @@ function finish_pg_history(merged_history)
|
||||||
merged_history.all_peers = Object.values(merged_history.all_peers);
|
merged_history.all_peers = Object.values(merged_history.all_peers);
|
||||||
}
|
}
|
||||||
|
|
||||||
function scale_pg_count(prev_pgs, real_prev_pgs, prev_pg_history, new_pg_history, new_pg_count)
|
function scale_pg_history(prev_pg_history, prev_pgs, new_pgs)
|
||||||
{
|
{
|
||||||
const old_pg_count = real_prev_pgs.length;
|
const new_pg_history = [];
|
||||||
|
const old_pg_count = prev_pgs.length;
|
||||||
|
const new_pg_count = new_pgs.length;
|
||||||
// Add all possibly intersecting PGs to the history of new PGs
|
// Add all possibly intersecting PGs to the history of new PGs
|
||||||
if (!(new_pg_count % old_pg_count))
|
if (!(new_pg_count % old_pg_count))
|
||||||
{
|
{
|
||||||
// New PG count is a multiple of old PG count
|
// New PG count is a multiple of old PG count
|
||||||
for (let i = 0; i < new_pg_count; i++)
|
for (let i = 0; i < new_pg_count; i++)
|
||||||
{
|
{
|
||||||
add_pg_history(new_pg_history, i, real_prev_pgs, prev_pg_history, i % old_pg_count);
|
add_pg_history(new_pg_history, i, prev_pgs, prev_pg_history, i % old_pg_count);
|
||||||
finish_pg_history(new_pg_history[i]);
|
finish_pg_history(new_pg_history[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -64,7 +67,7 @@ function scale_pg_count(prev_pgs, real_prev_pgs, prev_pg_history, new_pg_history
|
||||||
{
|
{
|
||||||
for (let j = 0; j < mul; j++)
|
for (let j = 0; j < mul; j++)
|
||||||
{
|
{
|
||||||
add_pg_history(new_pg_history, i, real_prev_pgs, prev_pg_history, i+j*new_pg_count);
|
add_pg_history(new_pg_history, i, prev_pgs, prev_pg_history, i+j*new_pg_count);
|
||||||
}
|
}
|
||||||
finish_pg_history(new_pg_history[i]);
|
finish_pg_history(new_pg_history[i]);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +79,7 @@ function scale_pg_count(prev_pgs, real_prev_pgs, prev_pg_history, new_pg_history
|
||||||
let merged_history = {};
|
let merged_history = {};
|
||||||
for (let i = 0; i < old_pg_count; i++)
|
for (let i = 0; i < old_pg_count; i++)
|
||||||
{
|
{
|
||||||
add_pg_history(merged_history, 1, real_prev_pgs, prev_pg_history, i);
|
add_pg_history(merged_history, 1, prev_pgs, prev_pg_history, i);
|
||||||
}
|
}
|
||||||
finish_pg_history(merged_history[1]);
|
finish_pg_history(merged_history[1]);
|
||||||
for (let i = 0; i < new_pg_count; i++)
|
for (let i = 0; i < new_pg_count; i++)
|
||||||
|
@ -89,6 +92,12 @@ function scale_pg_count(prev_pgs, real_prev_pgs, prev_pg_history, new_pg_history
|
||||||
{
|
{
|
||||||
new_pg_history[i] = null;
|
new_pg_history[i] = null;
|
||||||
}
|
}
|
||||||
|
return new_pg_history;
|
||||||
|
}
|
||||||
|
|
||||||
|
function scale_pg_count(prev_pgs, new_pg_count)
|
||||||
|
{
|
||||||
|
const old_pg_count = prev_pgs.length;
|
||||||
// Just for the lp_solve optimizer - pick a "previous" PG for each "new" one
|
// Just for the lp_solve optimizer - pick a "previous" PG for each "new" one
|
||||||
if (prev_pgs.length < new_pg_count)
|
if (prev_pgs.length < new_pg_count)
|
||||||
{
|
{
|
||||||
|
|
|
@ -50,8 +50,7 @@ async function lp_solve(text)
|
||||||
return { score, vars };
|
return { score, vars };
|
||||||
}
|
}
|
||||||
|
|
||||||
async function optimize_initial({ osd_tree, pg_count, pg_size = 3, pg_minsize = 2, hier_sizes = null,
|
async function optimize_initial({ osd_tree, pg_count, pg_size = 3, pg_minsize = 2, max_combinations = 10000, parity_space = 1, ordered = false })
|
||||||
max_combinations = 10000, parity_space = 1, ordered = false, seq_layout = false })
|
|
||||||
{
|
{
|
||||||
if (!pg_count || !osd_tree)
|
if (!pg_count || !osd_tree)
|
||||||
{
|
{
|
||||||
|
@ -59,7 +58,7 @@ async function optimize_initial({ osd_tree, pg_count, pg_size = 3, pg_minsize =
|
||||||
}
|
}
|
||||||
const all_weights = Object.assign({}, ...Object.values(osd_tree));
|
const all_weights = Object.assign({}, ...Object.values(osd_tree));
|
||||||
const total_weight = Object.values(all_weights).reduce((a, c) => Number(a) + Number(c), 0);
|
const total_weight = Object.values(all_weights).reduce((a, c) => Number(a) + Number(c), 0);
|
||||||
const all_pgs = Object.values(random_hier_combinations(osd_tree, hier_sizes || [ pg_size, 1 ], max_combinations, parity_space > 1, seq_layout));
|
const all_pgs = Object.values(random_combinations(osd_tree, pg_size, max_combinations, parity_space > 1));
|
||||||
const pg_per_osd = {};
|
const pg_per_osd = {};
|
||||||
for (const pg of all_pgs)
|
for (const pg of all_pgs)
|
||||||
{
|
{
|
||||||
|
@ -217,45 +216,39 @@ function calc_intersect_weights(old_pg_size, pg_size, pg_count, prev_weights, al
|
||||||
return move_weights;
|
return move_weights;
|
||||||
}
|
}
|
||||||
|
|
||||||
function build_parent_per_leaf(osd_tree, res = {}, parents = [])
|
function add_valid_previous(osd_tree, prev_weights, all_pgs)
|
||||||
{
|
|
||||||
for (const item in osd_tree)
|
|
||||||
{
|
|
||||||
if (osd_tree[item] instanceof Object)
|
|
||||||
build_parent_per_leaf(osd_tree[item], res, [ ...parents, item ]);
|
|
||||||
else
|
|
||||||
res[item] = parents;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
function add_valid_previous(osd_tree, prev_weights, all_pgs, hier_sizes)
|
|
||||||
{
|
{
|
||||||
// Add previous combinations that are still valid
|
// Add previous combinations that are still valid
|
||||||
const parent_per_osd = build_parent_per_leaf(osd_tree);
|
const hosts = Object.keys(osd_tree).sort();
|
||||||
|
const host_per_osd = {};
|
||||||
|
for (const host in osd_tree)
|
||||||
|
{
|
||||||
|
for (const osd in osd_tree[host])
|
||||||
|
{
|
||||||
|
host_per_osd[osd] = host;
|
||||||
|
}
|
||||||
|
}
|
||||||
skip_pg: for (const pg_name in prev_weights)
|
skip_pg: for (const pg_name in prev_weights)
|
||||||
{
|
{
|
||||||
const seen = [];
|
const seen_hosts = {};
|
||||||
const pg = pg_name.substr(3).split(/_/);
|
const pg = pg_name.substr(3).split(/_/);
|
||||||
for (const osd of pg)
|
for (const osd of pg)
|
||||||
{
|
{
|
||||||
if (!parent_per_osd[osd])
|
if (!host_per_osd[osd] || seen_hosts[host_per_osd[osd]])
|
||||||
continue skip_pg;
|
|
||||||
for (let i = 0; i < parent_per_osd[osd].length; i++)
|
|
||||||
{
|
{
|
||||||
seen[parent_per_osd[osd][i]]++;
|
|
||||||
if (seen[parent_per_osd[osd][i]] > hier_sizes[i])
|
|
||||||
continue skip_pg;
|
continue skip_pg;
|
||||||
}
|
}
|
||||||
|
seen_hosts[host_per_osd[osd]] = true;
|
||||||
}
|
}
|
||||||
if (!all_pgs[pg_name])
|
if (!all_pgs[pg_name])
|
||||||
|
{
|
||||||
all_pgs[pg_name] = pg;
|
all_pgs[pg_name] = pg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Try to minimize data movement
|
// Try to minimize data movement
|
||||||
async function optimize_change({ prev_pgs: prev_int_pgs, osd_tree, pg_size = 3, pg_minsize = 2,
|
async function optimize_change({ prev_pgs: prev_int_pgs, osd_tree, pg_size = 3, pg_minsize = 2, max_combinations = 10000, parity_space = 1, ordered = false })
|
||||||
hier_sizes = null, max_combinations = 10000, parity_space = 1, ordered = false, seq_layout = false })
|
|
||||||
{
|
{
|
||||||
if (!osd_tree)
|
if (!osd_tree)
|
||||||
{
|
{
|
||||||
|
@ -280,10 +273,10 @@ async function optimize_change({ prev_pgs: prev_int_pgs, osd_tree, pg_size = 3,
|
||||||
}
|
}
|
||||||
const old_pg_size = prev_int_pgs[0].length;
|
const old_pg_size = prev_int_pgs[0].length;
|
||||||
// Get all combinations
|
// Get all combinations
|
||||||
let all_pgs = random_hier_combinations(osd_tree, hier_sizes || [ pg_size, 1 ], max_combinations, parity_space > 1, seq_layout);
|
let all_pgs = random_combinations(osd_tree, pg_size, max_combinations, parity_space > 1);
|
||||||
if (old_pg_size == pg_size)
|
if (old_pg_size == pg_size)
|
||||||
{
|
{
|
||||||
add_valid_previous(osd_tree, prev_weights, all_pgs, hier_sizes || [ pg_size, 1 ]);
|
add_valid_previous(osd_tree, prev_weights, all_pgs);
|
||||||
}
|
}
|
||||||
all_pgs = Object.values(all_pgs);
|
all_pgs = Object.values(all_pgs);
|
||||||
const pg_per_osd = {};
|
const pg_per_osd = {};
|
||||||
|
@ -509,147 +502,41 @@ function put_aligned_pgs(aligned_pgs, int_pgs, prev_int_pgs, keygen)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Convert multi-level tree_node = { level: number|string, id?: string, size?: number, children?: tree_node[] }
|
// Convert multi-level osd_tree = { level: number|string, id?: string, size?: number, children?: osd_tree }[]
|
||||||
// levels = { string: number }
|
// levels = { string: number }
|
||||||
// to a multi-level OSD tree suitable for random_hier_combinations()
|
// to a two-level osd_tree suitable for all_combinations()
|
||||||
// (or in case of just 2 levels - for all_combinations() / random_combinations())
|
function flatten_tree(osd_tree, levels, failure_domain_level, osd_level, domains = {}, i = { i: 1 })
|
||||||
//
|
|
||||||
// Example:
|
|
||||||
// tree_node = { level: 'dc', children: [ { level: 'rack', children: [ { level: 'host', children: [ { level: 'osd', size: 10 } ] } ] } ] }
|
|
||||||
// extract_levels = [ 'rack', 'osd' ]
|
|
||||||
// level_defs = { dc: 1, rack: 2, host: 3, osd: 4 }
|
|
||||||
//
|
|
||||||
// Result:
|
|
||||||
// { rack0: { osd1: 10 } }
|
|
||||||
function extract_tree_levels(tree_node, extract_levels, level_defs, new_tree = { idx: 1, items: {} })
|
|
||||||
{
|
{
|
||||||
const next_level = Number(level_defs[extract_levels[0]] || extract_levels[0]) || 0;
|
osd_level = levels[osd_level] || osd_level;
|
||||||
const level_name = level_defs[extract_levels[0]] ? extract_levels[0] : 'l'+extract_levels[0]+'_';
|
failure_domain_level = levels[failure_domain_level] || failure_domain_level;
|
||||||
const is_leaf = extract_levels.length == 1;
|
for (const node of osd_tree)
|
||||||
if ((level_defs[tree_node.level] || tree_node.level) >= next_level)
|
|
||||||
{
|
{
|
||||||
if (!is_leaf)
|
if ((levels[node.level] || node.level) < failure_domain_level)
|
||||||
{
|
{
|
||||||
// Insert a (possibly fake) level
|
flatten_tree(node.children||[], levels, failure_domain_level, osd_level, domains, i);
|
||||||
const nt = { idx: 1, items: {} };
|
|
||||||
new_tree.items[level_name+(new_tree.idx++)] = nt.items;
|
|
||||||
extract_tree_levels(tree_node, extract_levels.slice(1), level_defs, nt);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Insert a leaf node
|
domains['dom'+(i.i++)] = extract_osds([ node ], levels, osd_level);
|
||||||
const leaf_id = tree_node.id || (level_name+(new_tree.idx++));
|
|
||||||
new_tree.items[leaf_id] = tree_node.size;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
return domains;
|
||||||
{
|
|
||||||
for (const child_node of tree_node.children||[])
|
|
||||||
{
|
|
||||||
extract_tree_levels(child_node, extract_levels, level_defs, new_tree);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return new_tree.items;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// generate random PGs with hierarchical failure domains, i.e. for example 3 DC each with 2 HOSTS
|
function extract_osds(osd_tree, levels, osd_level, osds = {})
|
||||||
// osd_tree = { level3_id: { level2_id: { level1_id: scalar_value } }, ... }
|
|
||||||
// osd_tree may contain arbitrary number of levels, but level count must be the same across the whole tree
|
|
||||||
// size_per_level = number of items to select on each level, for example [3, 2, 1].
|
|
||||||
// must have the same number of items as the osd_tree level count.
|
|
||||||
// count = PG count to generate
|
|
||||||
// ordered = don't treat (x,y) and (y,x) as equal
|
|
||||||
// seq_layout = true for the [DC1,DC1,DC2,DC2,DC3,DC3] layout, false for [DC1,DC2,DC3,DC1,DC2,DC3] layout
|
|
||||||
function random_hier_combinations(osd_tree, size_per_level, count, ordered, seq_layout)
|
|
||||||
{
|
{
|
||||||
let seed = 0x5f020e43;
|
for (const node of osd_tree)
|
||||||
const rng = () =>
|
|
||||||
{
|
{
|
||||||
seed ^= seed << 13;
|
if ((levels[node.level] || node.level) >= osd_level)
|
||||||
seed ^= seed >> 17;
|
|
||||||
seed ^= seed << 5;
|
|
||||||
return seed + 2147483648;
|
|
||||||
};
|
|
||||||
const get_max_level = (o) =>
|
|
||||||
{
|
{
|
||||||
let lvl = 0;
|
osds[node.id] = node.size;
|
||||||
while (o instanceof Object)
|
|
||||||
{
|
|
||||||
for (const k in o)
|
|
||||||
{
|
|
||||||
lvl++;
|
|
||||||
o = o[k];
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return lvl;
|
|
||||||
};
|
|
||||||
const max_level = get_max_level(osd_tree);
|
|
||||||
const gen_pg = (select) =>
|
|
||||||
{
|
|
||||||
let pg = [ osd_tree ];
|
|
||||||
for (let level = 0; level < max_level; level++)
|
|
||||||
{
|
|
||||||
let npg = [];
|
|
||||||
for (let i = 0; i < pg.length; i++)
|
|
||||||
{
|
|
||||||
const keys = pg[i] instanceof Object ? Object.keys(pg[i]) : [];
|
|
||||||
const max_keys = keys.length < size_per_level[level] ? keys.length : size_per_level[level];
|
|
||||||
for (let j = 0; j < max_keys; j++)
|
|
||||||
{
|
|
||||||
const r = select(level, i, j, (ordered ? keys.length : (keys.length - (max_keys - j - 1))));
|
|
||||||
const el = pg[i][keys[r]] instanceof Object ? pg[i][keys[r]] : keys[r];
|
|
||||||
npg[seq_layout ? i*size_per_level[level]+j : j*pg.length+i] = el;
|
|
||||||
keys.splice(ordered ? r : 0, ordered ? 1 : (r+1));
|
|
||||||
}
|
|
||||||
for (let j = max_keys; j < size_per_level[level]; j++)
|
|
||||||
npg[seq_layout ? i*size_per_level[level]+j : j*pg.length+i] = NO_OSD;
|
|
||||||
}
|
|
||||||
pg = npg;
|
|
||||||
}
|
|
||||||
return pg;
|
|
||||||
};
|
|
||||||
const r = {};
|
|
||||||
// Generate random combinations including each OSD at least once
|
|
||||||
let has_next = true;
|
|
||||||
let ctr = [];
|
|
||||||
while (has_next)
|
|
||||||
{
|
|
||||||
let pg = gen_pg((level, i, j, n) =>
|
|
||||||
{
|
|
||||||
if (i == 0 && j == 0)
|
|
||||||
{
|
|
||||||
// Select a pre-determined OSD in the first position on each level
|
|
||||||
const r = ctr[level] == null || ctr[level][1] != n ? 0 : ctr[level][0];
|
|
||||||
ctr[level] = [ r, n ];
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
return rng() % n;
|
|
||||||
});
|
|
||||||
for (let i = ctr.length-1; i >= 0; i--)
|
|
||||||
{
|
|
||||||
ctr[i][0]++;
|
|
||||||
if (ctr[i][0] < ctr[i][1])
|
|
||||||
break;
|
|
||||||
else
|
else
|
||||||
ctr[i] = null;
|
|
||||||
}
|
|
||||||
has_next = ctr[0] != null;
|
|
||||||
const cyclic_pgs = [ pg ];
|
|
||||||
if (ordered)
|
|
||||||
for (let i = 1; i < pg.size; i++)
|
|
||||||
cyclic_pgs.push([ ...pg.slice(i), ...pg.slice(0, i) ]);
|
|
||||||
for (const pg of cyclic_pgs)
|
|
||||||
r['pg_'+pg.join('_')] = pg;
|
|
||||||
}
|
|
||||||
// Generate purely random combinations
|
|
||||||
while (count > 0)
|
|
||||||
{
|
{
|
||||||
let pg = gen_pg((l, i, j, n) => rng() % n);
|
extract_osds(node.children||[], levels, osd_level, osds);
|
||||||
r['pg_'+pg.join('_')] = pg;
|
|
||||||
count--;
|
|
||||||
}
|
}
|
||||||
return r;
|
}
|
||||||
|
return osds;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ordered = don't treat (x,y) and (y,x) as equal
|
// ordered = don't treat (x,y) and (y,x) as equal
|
||||||
|
@ -865,12 +752,11 @@ module.exports = {
|
||||||
pg_weights_space_efficiency,
|
pg_weights_space_efficiency,
|
||||||
pg_list_space_efficiency,
|
pg_list_space_efficiency,
|
||||||
pg_per_osd_space_efficiency,
|
pg_per_osd_space_efficiency,
|
||||||
extract_tree_levels,
|
flatten_tree,
|
||||||
|
|
||||||
lp_solve,
|
lp_solve,
|
||||||
make_int_pgs,
|
make_int_pgs,
|
||||||
align_pgs,
|
align_pgs,
|
||||||
random_combinations,
|
random_combinations,
|
||||||
random_hier_combinations,
|
|
||||||
all_combinations,
|
all_combinations,
|
||||||
};
|
};
|
||||||
|
|
|
@ -63,8 +63,9 @@ Wants=network-online.target local-fs.target time-sync.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
Restart=always
|
Restart=always
|
||||||
ExecStart=/usr/local/bin/etcd -name etcd${num} --data-dir /var/lib/etcd${num}.etcd \\
|
Environment=GOGC=50
|
||||||
--advertise-client-urls http://${etcds[num]}:2379 --listen-client-urls http://${etcds[num]}:2379 \\
|
ExecStart=etcd -name etcd${num} --data-dir /var/lib/etcd${num}.etcd \\
|
||||||
|
--snapshot-count 10000 --advertise-client-urls http://${etcds[num]}:2379 --listen-client-urls http://${etcds[num]}:2379 \\
|
||||||
--initial-advertise-peer-urls http://${etcds[num]}:2380 --listen-peer-urls http://${etcds[num]}:2380 \\
|
--initial-advertise-peer-urls http://${etcds[num]}:2380 --listen-peer-urls http://${etcds[num]}:2380 \\
|
||||||
--initial-cluster-token vitastor-etcd-1 --initial-cluster ${etcd_cluster} \\
|
--initial-cluster-token vitastor-etcd-1 --initial-cluster ${etcd_cluster} \\
|
||||||
--initial-cluster-state new --max-txn-ops=100000 --max-request-bytes=104857600 \\
|
--initial-cluster-state new --max-txn-ops=100000 --max-request-bytes=104857600 \\
|
||||||
|
|
680
mon/mon.js
680
mon/mon.js
File diff suppressed because it is too large
Load Diff
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "vitastor-mon",
|
"name": "vitastor-mon",
|
||||||
"version": "1.0.0",
|
"version": "1.4.4",
|
||||||
"description": "Vitastor SDS monitor service",
|
"description": "Vitastor SDS monitor service",
|
||||||
"main": "mon-main.js",
|
"main": "mon-main.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
|
|
@ -36,7 +36,7 @@ const crush_tree = [
|
||||||
] },
|
] },
|
||||||
];
|
];
|
||||||
|
|
||||||
const osd_tree = LPOptimizer.extract_tree_levels({ level: -Infinity, children: crush_tree }, [ 1, 3 ], {});
|
const osd_tree = LPOptimizer.flatten_tree(crush_tree, {}, 1, 3);
|
||||||
console.log(osd_tree);
|
console.log(osd_tree);
|
||||||
|
|
||||||
async function run()
|
async function run()
|
||||||
|
@ -47,32 +47,32 @@ async function run()
|
||||||
LPOptimizer.print_change_stats(res, false);
|
LPOptimizer.print_change_stats(res, false);
|
||||||
assert(res.space == 0);
|
assert(res.space == 0);
|
||||||
console.log('\nAdding 1st failure domain:');
|
console.log('\nAdding 1st failure domain:');
|
||||||
cur_tree['l1_1'] = osd_tree['l1_1'];
|
cur_tree['dom1'] = osd_tree['dom1'];
|
||||||
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
||||||
LPOptimizer.print_change_stats(res, false);
|
LPOptimizer.print_change_stats(res, false);
|
||||||
assert(res.space == 12 && res.total_space == 12);
|
assert(res.space == 12 && res.total_space == 12);
|
||||||
console.log('\nAdding 2nd failure domain:');
|
console.log('\nAdding 2nd failure domain:');
|
||||||
cur_tree['l1_2'] = osd_tree['l1_2'];
|
cur_tree['dom2'] = osd_tree['dom2'];
|
||||||
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
||||||
LPOptimizer.print_change_stats(res, false);
|
LPOptimizer.print_change_stats(res, false);
|
||||||
assert(res.space == 24 && res.total_space == 24);
|
assert(res.space == 24 && res.total_space == 24);
|
||||||
console.log('\nAdding 3rd failure domain:');
|
console.log('\nAdding 3rd failure domain:');
|
||||||
cur_tree['l1_3'] = osd_tree['l1_3'];
|
cur_tree['dom3'] = osd_tree['dom3'];
|
||||||
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
||||||
LPOptimizer.print_change_stats(res, false);
|
LPOptimizer.print_change_stats(res, false);
|
||||||
assert(res.space == 36 && res.total_space == 36);
|
assert(res.space == 36 && res.total_space == 36);
|
||||||
console.log('\nRemoving 3rd failure domain:');
|
console.log('\nRemoving 3rd failure domain:');
|
||||||
delete cur_tree['l1_3'];
|
delete cur_tree['dom3'];
|
||||||
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
||||||
LPOptimizer.print_change_stats(res, false);
|
LPOptimizer.print_change_stats(res, false);
|
||||||
assert(res.space == 24 && res.total_space == 24);
|
assert(res.space == 24 && res.total_space == 24);
|
||||||
console.log('\nRemoving 2nd failure domain:');
|
console.log('\nRemoving 2nd failure domain:');
|
||||||
delete cur_tree['l1_2'];
|
delete cur_tree['dom2'];
|
||||||
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
||||||
LPOptimizer.print_change_stats(res, false);
|
LPOptimizer.print_change_stats(res, false);
|
||||||
assert(res.space == 12 && res.total_space == 12);
|
assert(res.space == 12 && res.total_space == 12);
|
||||||
console.log('\nRemoving 1st failure domain:');
|
console.log('\nRemoving 1st failure domain:');
|
||||||
delete cur_tree['l1_1'];
|
delete cur_tree['dom1'];
|
||||||
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
res = await LPOptimizer.optimize_change({ prev_pgs: res.int_pgs, osd_tree: cur_tree, pg_size: 3 });
|
||||||
LPOptimizer.print_change_stats(res, false);
|
LPOptimizer.print_change_stats(res, false);
|
||||||
assert(res.space == 0);
|
assert(res.space == 0);
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue