diff --git a/docs/404.html b/docs/404.html index 4485572..3381154 100644 --- a/docs/404.html +++ b/docs/404.html @@ -3,9 +3,9 @@ -Kosmos - - +Kosmos + +
Skip to main content

Page Not Found

We could not find what you were looking for.

Please contact the owner of the site that linked you to the original URL and let them know their link is broken.

diff --git a/docs/assets/css/styles.20bcec04.css b/docs/assets/css/styles.b815901c.css similarity index 70% rename from docs/assets/css/styles.20bcec04.css rename to docs/assets/css/styles.b815901c.css index ef51428..d421406 100644 --- a/docs/assets/css/styles.20bcec04.css +++ b/docs/assets/css/styles.b815901c.css @@ -1 +1 @@ -.col,.container{padding:0 var(--ifm-spacing-horizontal)}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#3b54e0;--ifm-color-primary-dark:#0598ea;--ifm-color-primary-darker:#0590dd;--ifm-color-primary-darkest:#0476b6;--ifm-color-primary-light:#2ab0fb;--ifm-color-primary-lighter:#37b5fb;--ifm-color-primary-lightest:#5ec3fc;--ifm-code-font-size:95%;--ifm-font-size-base:16px;--hero-border-color:#0000001a;--docusaurus-announcement-bar-height:"auto"!important;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}*{box-sizing:border-box}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none,.tabItem_LNqP{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width);width:100%}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal);color:#c8254e}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul,.tabList__CuJ{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_Gvgb,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_BuS1>:last-child,.collapsibleContent_i85q p:last-child,.details_lb9f>summary>p:last-child,.footer__items,.tabItem_Ymn6>:last-child{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;visibility:hidden;top:0;left:0}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter);content:""}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid,.sm-hidden{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);position:fixed;transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;position:fixed;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.code-block-primary-line,.code-block-warning-line{margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.z-input,.z-input:focus,.z-textarea,.z-textarea:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-inset:inset;--tw-ring-opacity:1}.container{width:100%}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.absolute{position:absolute}.isolate{isolation:isolate}.block,.tocCollapsibleContent_vkbj a{display:block}.table{display:table}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.code-block-primary-line{background-color:#e0f2fe;display:block}.code-block-primary-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module{background-color:#e0f2fe;border-left:3px solid #60a5fa}.code-block-warning-line{background-color:#fef9c3;display:block}.code-block-warning-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module{background-color:#fef9c3;border-left:3px solid #facc15}[data-theme=dark] .code-block-primary-line,[data-theme=dark] .code-block-primary-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module,[data-theme=dark] .code-block-warning-line,[data-theme=dark] .code-block-warning-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module{background-color:#0009}.tabs-container{border-radius:.5rem;box-shadow:0 0 12px #0000002e;padding:.5rem}.theme-code-block:hover .buttonGroup_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Content-styles-module button{opacity:.75!important}.divider{background:linear-gradient(-45deg,#94a3b8 30%,#f1f4ff 0,#f1f4ff 50%,#f1f4ff 0,#f1f4ff 80%,#f1f4ff 0);background-size:1.5rem 1.5rem;border:1px dashed #0000}.header-github-link:hover{opacity:.6}.header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;content:"";display:flex}[data-theme=dark] .header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat}.z-input,.z-textarea{--tw-text-opacity:1;--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity));border-width:0;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:rgb(17 24 39/var(--tw-text-opacity));display:block;padding-bottom:.375rem;padding-top:.375rem;width:100%}.z-input::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.z-input:focus,.z-textarea:focus{--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgb(79 70 229/var(--tw-ring-opacity));box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.z-button{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity));color:rgb(255 255 255/var(--tw-text-opacity));font-weight:700;padding:.5rem 1rem;width:9rem}.z-button:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity))}.z-textarea::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.navbar--fixed-top{height:70px}.navbar--fixed-top .navbar__logo{height:44px;margin-right:11px;padding-left:5px}.navbar--fixed-top .navbar__title{font-size:28px}.navbar__link{font-size:16px}.header-github-link:before{height:35px;width:35px}.navbar__title{font-size:30px;font-weight:700}.hero--primary,.mdxPageWrapper_j9I6{justify-content:center}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_YfHR,.sidebarLogo_isFc,.themedComponent_mlkZ,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedComponent--dark_xIcU,[data-theme=light] .themedComponent--light_NVdE,html:not([data-theme]) .themedComponent--light_NVdE{display:initial}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.iconExternalLink_nPIU{margin-left:.3rem}.docMainContainer_TBSr,.docRoot_UBD9{display:flex;width:100%}.docsWrapper_hBAB{display:flex;flex:1 0 auto}.dropdownNavbarItemMobile_S0Fm{cursor:pointer}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}@supports selector(:has(*)){.navbarSearchContainer_Bca1:not(:has(>*)){display:none}}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.errorBoundaryFallback_VBag{color:red;padding:.55rem}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.container_bfhl{align-items:center;background-image:url(/website/assets/images/top-bg-907106b795294aa3d5e4cbb0e9c2bad5.svg);background-position:50%;background-size:cover;display:flex;flex:1;height:690px!important;margin:0 80px;max-width:1800px;padding:0!important;width:100%}.heroBanner_qdFl{background-color:#f8f9fc;margin-bottom:100px;overflow:hidden;position:relative;text-align:center}.button1_OX1t{background-color:#3b54e0;border:none;border-radius:25px;color:#fff!important;margin-bottom:65px}.iconStar_WCul{border-radius:0!important;border-right:1px solid #d1d5d7}.starNum_QxJd{color:#000;display:inline-block;font-size:14px;text-align:center;width:55px}.heroTitle_qg2I{color:#000;font-size:50px;margin-bottom:20px}.heroText_ryRM{color:#626262;font-size:16px;font-weight:700;margin-bottom:40px;width:475px}.headerLeft_DBKD{height:613px;padding:130px 70px 30px 0;text-align:left;width:50%}.topImg_oKWx{display:block;max-height:530px;max-width:100%}.headerDes_Qvmc{color:#414141;font-size:16px}.featureTitle_Xf3m,.featureTitle__pTw{font-size:40px;color:#333;font-family:PingFangSC-Semibold;font-weight:600}.headerDesInfo_x7U0{margin-bottom:10px}.mainContainer_mA9m{display:flex;flex-direction:column;justify-content:space-between}.star_elzc{margin-bottom:5px}.featuresText_eVJS{display:flex;height:535px;justify-content:space-between;margin:0 80px;max-width:1800px;width:100%}.rigthInfo_KVv9{display:flex;flex-direction:column;justify-content:center;margin-right:30px;width:50%}.leftInfo_cdZ5{margin-right:150px;width:50%}.containerView_M7QC,.features_xdhU{display:flex;justify-content:center}.featureTitle__pTw{margin-bottom:20px}.featuresDes_VkbC{max-width:415px}.featuresContainer_wvSy{margin:80px 80px 40px;max-width:1800px;width:100%}.featureTitle_Xf3m{margin-bottom:40px;position:relative}.titleBg_pq9t{height:100px;left:170px;position:absolute;top:0;z-index:-1}.featureText_v8dk{display:flex;flex-direction:column;height:100px;justify-content:flex-end;margin-bottom:10px;width:270px}.line_gRrf{border-bottom:5px solid #3355e9;margin:0 0 20px 5px;width:55px}.featureItemLeft_j4hF{align-items:flex-start;background-color:#f9fbff;border-radius:30px;display:flex;justify-content:space-between;margin-bottom:85px;position:relative;width:100%}.featureItemRight_HONX{flex-direction:row-reverse}.featureDes_FHkX{align-items:left;display:flex;flex:1;flex-direction:column;justify-content:center;margin-bottom:30px;margin-left:45px;padding-top:30px;z-index:1}.featureItemRight_HONX .featureDes_FHkX{align-items:flex-end;margin-right:45px}.featureItemRight_HONX .featureDesTitle_NLsR{width:55%}.featureArrangeImg_KtM9{height:400px;position:absolute;right:0;top:50%;transform:translateY(-50%)}.featureDispatchImg_eSBL{left:0}.featureDispatchImg_eSBL,.featureNetworkImg_Z2mW{height:440px;position:absolute;top:50%;transform:translateY(-50%)}.featureNetworkImg_Z2mW{right:0}.featureImg_IxXR{height:100%;width:100%}.featureDesTitle_NLsR{color:#333;font-size:32px;margin-bottom:5px}.featureDesInfo_ytRY,.featureDesTitle_NLsR{font-family:PingFangSC-Semibold;font-weight:600}.featureDesInfo_ytRY{color:#626262;line-height:22px}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.featureDesDetails_Zud9,.featureDesInfo_ytRY{font-size:16px;max-width:55%}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.img_ev3q{height:auto}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.admonition_xJq3{margin-bottom:1em}.admonitionHeading_Gvgb{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family)}.admonitionHeading_Gvgb:not(:last-child){margin-bottom:.3rem}.admonitionHeading_Gvgb code{text-transform:none}.admonitionIcon_Rf37{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_Rf37 svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}@media (min-width:640px){.container{max-width:640px}.sm-hidden{display:none!important}.z-input,.z-textarea{font-size:.875rem;line-height:1.5rem}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_TmdG{background-color:var(--docusaurus-collapse-button-bg)}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_i1dp,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_TmdG:focus,.expandButton_TmdG:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_TmdG{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_i1dp{transform:rotate(180deg)}.docSidebarContainer_YfHR{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_DPk8{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_aRkj{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_TBSr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_lQrH{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_JWYK{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.navbarSearchContainer_Bca1{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.docItemCol_VOVn{max-width:75%!important}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (min-width:1536px){.container{max-width:1536px}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.navbarSearchContainer_Bca1{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file +.col,.container{padding:0 var(--ifm-spacing-horizontal)}.markdown>h2,.markdown>h3,.markdown>h4,.markdown>h5,.markdown>h6{margin-bottom:calc(var(--ifm-heading-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown li,body{word-wrap:break-word}body,ol ol,ol ul,ul ol,ul ul{margin:0}pre,table{overflow:auto}blockquote,pre{margin:0 0 var(--ifm-spacing-vertical)}.breadcrumbs__link,.button{transition-timing-function:var(--ifm-transition-timing-default)}.button,code{vertical-align:middle}.button--outline.button--active,.button--outline:active,.button--outline:hover,:root{--ifm-button-color:var(--ifm-font-color-base-inverse)}.menu__link:hover,a{transition:color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.navbar--dark,:root{--ifm-navbar-link-hover-color:var(--ifm-color-primary)}.menu,.navbar-sidebar{overflow-x:hidden}:root,html[data-theme=dark]{--ifm-color-emphasis-500:var(--ifm-color-gray-500)}.toggleButton_gllP,html{-webkit-tap-highlight-color:transparent}.clean-list,.containsTaskList_mC6p,.details_lb9f>summary,.dropdown__menu,.menu__list{list-style:none}:root{--ifm-color-scheme:light;--ifm-dark-value:10%;--ifm-darker-value:15%;--ifm-darkest-value:30%;--ifm-light-value:15%;--ifm-lighter-value:30%;--ifm-lightest-value:50%;--ifm-contrast-background-value:90%;--ifm-contrast-foreground-value:70%;--ifm-contrast-background-dark-value:70%;--ifm-contrast-foreground-dark-value:90%;--ifm-color-primary:#3578e5;--ifm-color-secondary:#ebedf0;--ifm-color-success:#00a400;--ifm-color-info:#54c7ec;--ifm-color-warning:#ffba00;--ifm-color-danger:#fa383e;--ifm-color-primary-dark:#306cce;--ifm-color-primary-darker:#2d66c3;--ifm-color-primary-darkest:#2554a0;--ifm-color-primary-light:#538ce9;--ifm-color-primary-lighter:#72a1ed;--ifm-color-primary-lightest:#9abcf2;--ifm-color-primary-contrast-background:#ebf2fc;--ifm-color-primary-contrast-foreground:#102445;--ifm-color-secondary-dark:#d4d5d8;--ifm-color-secondary-darker:#c8c9cc;--ifm-color-secondary-darkest:#a4a6a8;--ifm-color-secondary-light:#eef0f2;--ifm-color-secondary-lighter:#f1f2f5;--ifm-color-secondary-lightest:#f5f6f8;--ifm-color-secondary-contrast-background:#fdfdfe;--ifm-color-secondary-contrast-foreground:#474748;--ifm-color-success-dark:#009400;--ifm-color-success-darker:#008b00;--ifm-color-success-darkest:#007300;--ifm-color-success-light:#26b226;--ifm-color-success-lighter:#4dbf4d;--ifm-color-success-lightest:#80d280;--ifm-color-success-contrast-background:#e6f6e6;--ifm-color-success-contrast-foreground:#003100;--ifm-color-info-dark:#4cb3d4;--ifm-color-info-darker:#47a9c9;--ifm-color-info-darkest:#3b8ba5;--ifm-color-info-light:#6ecfef;--ifm-color-info-lighter:#87d8f2;--ifm-color-info-lightest:#aae3f6;--ifm-color-info-contrast-background:#eef9fd;--ifm-color-info-contrast-foreground:#193c47;--ifm-color-warning-dark:#e6a700;--ifm-color-warning-darker:#d99e00;--ifm-color-warning-darkest:#b38200;--ifm-color-warning-light:#ffc426;--ifm-color-warning-lighter:#ffcf4d;--ifm-color-warning-lightest:#ffdd80;--ifm-color-warning-contrast-background:#fff8e6;--ifm-color-warning-contrast-foreground:#4d3800;--ifm-color-danger-dark:#e13238;--ifm-color-danger-darker:#d53035;--ifm-color-danger-darkest:#af272b;--ifm-color-danger-light:#fb565b;--ifm-color-danger-lighter:#fb7478;--ifm-color-danger-lightest:#fd9c9f;--ifm-color-danger-contrast-background:#ffebec;--ifm-color-danger-contrast-foreground:#4b1113;--ifm-color-white:#fff;--ifm-color-black:#000;--ifm-color-gray-0:var(--ifm-color-white);--ifm-color-gray-100:#f5f6f7;--ifm-color-gray-200:#ebedf0;--ifm-color-gray-300:#dadde1;--ifm-color-gray-400:#ccd0d5;--ifm-color-gray-500:#bec3c9;--ifm-color-gray-600:#8d949e;--ifm-color-gray-700:#606770;--ifm-color-gray-800:#444950;--ifm-color-gray-900:#1c1e21;--ifm-color-gray-1000:var(--ifm-color-black);--ifm-color-emphasis-0:var(--ifm-color-gray-0);--ifm-color-emphasis-100:var(--ifm-color-gray-100);--ifm-color-emphasis-200:var(--ifm-color-gray-200);--ifm-color-emphasis-300:var(--ifm-color-gray-300);--ifm-color-emphasis-400:var(--ifm-color-gray-400);--ifm-color-emphasis-600:var(--ifm-color-gray-600);--ifm-color-emphasis-700:var(--ifm-color-gray-700);--ifm-color-emphasis-800:var(--ifm-color-gray-800);--ifm-color-emphasis-900:var(--ifm-color-gray-900);--ifm-color-emphasis-1000:var(--ifm-color-gray-1000);--ifm-color-content:var(--ifm-color-emphasis-900);--ifm-color-content-inverse:var(--ifm-color-emphasis-0);--ifm-color-content-secondary:#525860;--ifm-background-color:#0000;--ifm-background-surface-color:var(--ifm-color-content-inverse);--ifm-global-border-width:1px;--ifm-global-radius:0.4rem;--ifm-hover-overlay:#0000000d;--ifm-font-color-base:var(--ifm-color-content);--ifm-font-color-base-inverse:var(--ifm-color-content-inverse);--ifm-font-color-secondary:var(--ifm-color-content-secondary);--ifm-font-family-base:system-ui,-apple-system,Segoe UI,Roboto,Ubuntu,Cantarell,Noto Sans,sans-serif,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif,"Apple Color Emoji","Segoe UI Emoji","Segoe UI Symbol";--ifm-font-family-monospace:SFMono-Regular,Menlo,Monaco,Consolas,"Liberation Mono","Courier New",monospace;--ifm-font-size-base:100%;--ifm-font-weight-light:300;--ifm-font-weight-normal:400;--ifm-font-weight-semibold:500;--ifm-font-weight-bold:700;--ifm-font-weight-base:var(--ifm-font-weight-normal);--ifm-line-height-base:1.65;--ifm-global-spacing:1rem;--ifm-spacing-vertical:var(--ifm-global-spacing);--ifm-spacing-horizontal:var(--ifm-global-spacing);--ifm-transition-fast:200ms;--ifm-transition-slow:400ms;--ifm-transition-timing-default:cubic-bezier(0.08,0.52,0.52,1);--ifm-global-shadow-lw:0 1px 2px 0 #0000001a;--ifm-global-shadow-md:0 5px 40px #0003;--ifm-global-shadow-tl:0 12px 28px 0 #0003,0 2px 4px 0 #0000001a;--ifm-z-index-dropdown:100;--ifm-z-index-fixed:200;--ifm-z-index-overlay:400;--ifm-container-width:1140px;--ifm-container-width-xl:1320px;--ifm-code-background:#f6f7f8;--ifm-code-border-radius:var(--ifm-global-radius);--ifm-code-font-size:90%;--ifm-code-padding-horizontal:0.1rem;--ifm-code-padding-vertical:0.1rem;--ifm-pre-background:var(--ifm-code-background);--ifm-pre-border-radius:var(--ifm-code-border-radius);--ifm-pre-color:inherit;--ifm-pre-line-height:1.45;--ifm-pre-padding:1rem;--ifm-heading-color:inherit;--ifm-heading-margin-top:0;--ifm-heading-margin-bottom:var(--ifm-spacing-vertical);--ifm-heading-font-family:var(--ifm-font-family-base);--ifm-heading-font-weight:var(--ifm-font-weight-bold);--ifm-heading-line-height:1.25;--ifm-h1-font-size:2rem;--ifm-h2-font-size:1.5rem;--ifm-h3-font-size:1.25rem;--ifm-h4-font-size:1rem;--ifm-h5-font-size:0.875rem;--ifm-h6-font-size:0.85rem;--ifm-image-alignment-padding:1.25rem;--ifm-leading-desktop:1.25;--ifm-leading:calc(var(--ifm-leading-desktop)*1rem);--ifm-list-left-padding:2rem;--ifm-list-margin:1rem;--ifm-list-item-margin:0.25rem;--ifm-list-paragraph-margin:1rem;--ifm-table-cell-padding:0.75rem;--ifm-table-background:#0000;--ifm-table-stripe-background:#00000008;--ifm-table-border-width:1px;--ifm-table-border-color:var(--ifm-color-emphasis-300);--ifm-table-head-background:inherit;--ifm-table-head-color:inherit;--ifm-table-head-font-weight:var(--ifm-font-weight-bold);--ifm-table-cell-color:inherit;--ifm-link-color:var(--ifm-color-primary);--ifm-link-decoration:none;--ifm-link-hover-color:var(--ifm-link-color);--ifm-link-hover-decoration:underline;--ifm-paragraph-margin-bottom:var(--ifm-leading);--ifm-blockquote-font-size:var(--ifm-font-size-base);--ifm-blockquote-border-left-width:2px;--ifm-blockquote-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-blockquote-padding-vertical:0;--ifm-blockquote-shadow:none;--ifm-blockquote-color:var(--ifm-color-emphasis-800);--ifm-blockquote-border-color:var(--ifm-color-emphasis-300);--ifm-hr-background-color:var(--ifm-color-emphasis-500);--ifm-hr-height:1px;--ifm-hr-margin-vertical:1.5rem;--ifm-scrollbar-size:7px;--ifm-scrollbar-track-background-color:#f1f1f1;--ifm-scrollbar-thumb-background-color:silver;--ifm-scrollbar-thumb-hover-background-color:#a7a7a7;--ifm-alert-background-color:inherit;--ifm-alert-border-color:inherit;--ifm-alert-border-radius:var(--ifm-global-radius);--ifm-alert-border-width:0px;--ifm-alert-border-left-width:5px;--ifm-alert-color:var(--ifm-font-color-base);--ifm-alert-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-alert-padding-vertical:var(--ifm-spacing-vertical);--ifm-alert-shadow:var(--ifm-global-shadow-lw);--ifm-avatar-intro-margin:1rem;--ifm-avatar-intro-alignment:inherit;--ifm-avatar-photo-size:3rem;--ifm-badge-background-color:inherit;--ifm-badge-border-color:inherit;--ifm-badge-border-radius:var(--ifm-global-radius);--ifm-badge-border-width:var(--ifm-global-border-width);--ifm-badge-color:var(--ifm-color-white);--ifm-badge-padding-horizontal:calc(var(--ifm-spacing-horizontal)*0.5);--ifm-badge-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-breadcrumb-border-radius:1.5rem;--ifm-breadcrumb-spacing:0.5rem;--ifm-breadcrumb-color-active:var(--ifm-color-primary);--ifm-breadcrumb-item-background-active:var(--ifm-hover-overlay);--ifm-breadcrumb-padding-horizontal:0.8rem;--ifm-breadcrumb-padding-vertical:0.4rem;--ifm-breadcrumb-size-multiplier:1;--ifm-breadcrumb-separator:url('data:image/svg+xml;utf8,');--ifm-breadcrumb-separator-filter:none;--ifm-breadcrumb-separator-size:0.5rem;--ifm-breadcrumb-separator-size-multiplier:1.25;--ifm-button-background-color:inherit;--ifm-button-border-color:var(--ifm-button-background-color);--ifm-button-border-width:var(--ifm-global-border-width);--ifm-button-font-weight:var(--ifm-font-weight-bold);--ifm-button-padding-horizontal:1.5rem;--ifm-button-padding-vertical:0.375rem;--ifm-button-size-multiplier:1;--ifm-button-transition-duration:var(--ifm-transition-fast);--ifm-button-border-radius:calc(var(--ifm-global-radius)*var(--ifm-button-size-multiplier));--ifm-button-group-spacing:2px;--ifm-card-background-color:var(--ifm-background-surface-color);--ifm-card-border-radius:calc(var(--ifm-global-radius)*2);--ifm-card-horizontal-spacing:var(--ifm-global-spacing);--ifm-card-vertical-spacing:var(--ifm-global-spacing);--ifm-toc-border-color:var(--ifm-color-emphasis-300);--ifm-toc-link-color:var(--ifm-color-content-secondary);--ifm-toc-padding-vertical:0.5rem;--ifm-toc-padding-horizontal:0.5rem;--ifm-dropdown-background-color:var(--ifm-background-surface-color);--ifm-dropdown-font-weight:var(--ifm-font-weight-semibold);--ifm-dropdown-link-color:var(--ifm-font-color-base);--ifm-dropdown-hover-background-color:var(--ifm-hover-overlay);--ifm-footer-background-color:var(--ifm-color-emphasis-100);--ifm-footer-color:inherit;--ifm-footer-link-color:var(--ifm-color-emphasis-700);--ifm-footer-link-hover-color:var(--ifm-color-primary);--ifm-footer-link-horizontal-spacing:0.5rem;--ifm-footer-padding-horizontal:calc(var(--ifm-spacing-horizontal)*2);--ifm-footer-padding-vertical:calc(var(--ifm-spacing-vertical)*2);--ifm-footer-title-color:inherit;--ifm-footer-logo-max-width:min(30rem,90vw);--ifm-hero-background-color:var(--ifm-background-surface-color);--ifm-hero-text-color:var(--ifm-color-emphasis-800);--ifm-menu-color:var(--ifm-color-emphasis-700);--ifm-menu-color-active:var(--ifm-color-primary);--ifm-menu-color-background-active:var(--ifm-hover-overlay);--ifm-menu-color-background-hover:var(--ifm-hover-overlay);--ifm-menu-link-padding-horizontal:0.75rem;--ifm-menu-link-padding-vertical:0.375rem;--ifm-menu-link-sublist-icon:url('data:image/svg+xml;utf8,');--ifm-menu-link-sublist-icon-filter:none;--ifm-navbar-background-color:var(--ifm-background-surface-color);--ifm-navbar-height:3.75rem;--ifm-navbar-item-padding-horizontal:0.75rem;--ifm-navbar-item-padding-vertical:0.25rem;--ifm-navbar-link-color:var(--ifm-font-color-base);--ifm-navbar-link-active-color:var(--ifm-link-color);--ifm-navbar-padding-horizontal:var(--ifm-spacing-horizontal);--ifm-navbar-padding-vertical:calc(var(--ifm-spacing-vertical)*0.5);--ifm-navbar-shadow:var(--ifm-global-shadow-lw);--ifm-navbar-search-input-background-color:var(--ifm-color-emphasis-200);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-800);--ifm-navbar-search-input-placeholder-color:var(--ifm-color-emphasis-500);--ifm-navbar-search-input-icon:url('data:image/svg+xml;utf8,');--ifm-navbar-sidebar-width:83vw;--ifm-pagination-border-radius:var(--ifm-global-radius);--ifm-pagination-color-active:var(--ifm-color-primary);--ifm-pagination-font-size:1rem;--ifm-pagination-item-active-background:var(--ifm-hover-overlay);--ifm-pagination-page-spacing:0.2em;--ifm-pagination-padding-horizontal:calc(var(--ifm-spacing-horizontal)*1);--ifm-pagination-padding-vertical:calc(var(--ifm-spacing-vertical)*0.25);--ifm-pagination-nav-border-radius:var(--ifm-global-radius);--ifm-pagination-nav-color-hover:var(--ifm-color-primary);--ifm-pills-color-active:var(--ifm-color-primary);--ifm-pills-color-background-active:var(--ifm-hover-overlay);--ifm-pills-spacing:0.125rem;--ifm-tabs-color:var(--ifm-font-color-secondary);--ifm-tabs-color-active:var(--ifm-color-primary);--ifm-tabs-color-active-border:var(--ifm-tabs-color-active);--ifm-tabs-padding-horizontal:1rem;--ifm-tabs-padding-vertical:1rem;--docusaurus-progress-bar-color:var(--ifm-color-primary);--ifm-color-primary:#3b54e0;--ifm-color-primary-dark:#0598ea;--ifm-color-primary-darker:#0590dd;--ifm-color-primary-darkest:#0476b6;--ifm-color-primary-light:#2ab0fb;--ifm-color-primary-lighter:#37b5fb;--ifm-color-primary-lightest:#5ec3fc;--ifm-code-font-size:95%;--ifm-font-size-base:16px;--hero-border-color:#0000001a;--docusaurus-announcement-bar-height:"auto"!important;--docusaurus-tag-list-border:var(--ifm-color-emphasis-300);--docusaurus-announcement-bar-height:auto;--docusaurus-collapse-button-bg:#0000;--docusaurus-collapse-button-bg-hover:#0000001a;--doc-sidebar-width:300px;--doc-sidebar-hidden-width:30px}.badge--danger,.badge--info,.badge--primary,.badge--secondary,.badge--success,.badge--warning{--ifm-badge-border-color:var(--ifm-badge-background-color)}.button--link,.button--outline{--ifm-button-background-color:#0000}*{box-sizing:border-box}html{-webkit-font-smoothing:antialiased;-webkit-text-size-adjust:100%;text-size-adjust:100%;background-color:var(--ifm-background-color);color:var(--ifm-font-color-base);color-scheme:var(--ifm-color-scheme);font:var(--ifm-font-size-base)/var(--ifm-line-height-base) var(--ifm-font-family-base);text-rendering:optimizelegibility}iframe{border:0;color-scheme:auto}.container{margin:0 auto;max-width:var(--ifm-container-width)}.container--fluid{max-width:inherit}.row{display:flex;flex-wrap:wrap;margin:0 calc(var(--ifm-spacing-horizontal)*-1)}.margin-bottom--none,.margin-vert--none,.markdown>:last-child{margin-bottom:0!important}.margin-top--none,.margin-vert--none,.tabItem_LNqP{margin-top:0!important}.row--no-gutters{margin-left:0;margin-right:0}.margin-horiz--none,.margin-right--none{margin-right:0!important}.row--no-gutters>.col{padding-left:0;padding-right:0}.row--align-top{align-items:flex-start}.row--align-bottom{align-items:flex-end}.menuExternalLink_NmtK,.row--align-center{align-items:center}.row--align-stretch{align-items:stretch}.row--align-baseline{align-items:baseline}.col{--ifm-col-width:100%;flex:1 0;margin-left:0;max-width:var(--ifm-col-width);width:100%}.padding-bottom--none,.padding-vert--none{padding-bottom:0!important}.padding-top--none,.padding-vert--none{padding-top:0!important}.padding-horiz--none,.padding-left--none{padding-left:0!important}.padding-horiz--none,.padding-right--none{padding-right:0!important}.col[class*=col--]{flex:0 0 var(--ifm-col-width)}.col--1{--ifm-col-width:8.33333%}.col--offset-1{margin-left:8.33333%}.col--2{--ifm-col-width:16.66667%}.col--offset-2{margin-left:16.66667%}.col--3{--ifm-col-width:25%}.col--offset-3{margin-left:25%}.col--4{--ifm-col-width:33.33333%}.col--offset-4{margin-left:33.33333%}.col--5{--ifm-col-width:41.66667%}.col--offset-5{margin-left:41.66667%}.col--6{--ifm-col-width:50%}.col--offset-6{margin-left:50%}.col--7{--ifm-col-width:58.33333%}.col--offset-7{margin-left:58.33333%}.col--8{--ifm-col-width:66.66667%}.col--offset-8{margin-left:66.66667%}.col--9{--ifm-col-width:75%}.col--offset-9{margin-left:75%}.col--10{--ifm-col-width:83.33333%}.col--offset-10{margin-left:83.33333%}.col--11{--ifm-col-width:91.66667%}.col--offset-11{margin-left:91.66667%}.col--12{--ifm-col-width:100%}.col--offset-12{margin-left:100%}.margin-horiz--none,.margin-left--none{margin-left:0!important}.margin--none{margin:0!important}.margin-bottom--xs,.margin-vert--xs{margin-bottom:.25rem!important}.margin-top--xs,.margin-vert--xs{margin-top:.25rem!important}.margin-horiz--xs,.margin-left--xs{margin-left:.25rem!important}.margin-horiz--xs,.margin-right--xs{margin-right:.25rem!important}.margin--xs{margin:.25rem!important}.margin-bottom--sm,.margin-vert--sm{margin-bottom:.5rem!important}.margin-top--sm,.margin-vert--sm{margin-top:.5rem!important}.margin-horiz--sm,.margin-left--sm{margin-left:.5rem!important}.margin-horiz--sm,.margin-right--sm{margin-right:.5rem!important}.margin--sm{margin:.5rem!important}.margin-bottom--md,.margin-vert--md{margin-bottom:1rem!important}.margin-top--md,.margin-vert--md{margin-top:1rem!important}.margin-horiz--md,.margin-left--md{margin-left:1rem!important}.margin-horiz--md,.margin-right--md{margin-right:1rem!important}.margin--md{margin:1rem!important}.margin-bottom--lg,.margin-vert--lg{margin-bottom:2rem!important}.margin-top--lg,.margin-vert--lg{margin-top:2rem!important}.margin-horiz--lg,.margin-left--lg{margin-left:2rem!important}.margin-horiz--lg,.margin-right--lg{margin-right:2rem!important}.margin--lg{margin:2rem!important}.margin-bottom--xl,.margin-vert--xl{margin-bottom:5rem!important}.margin-top--xl,.margin-vert--xl{margin-top:5rem!important}.margin-horiz--xl,.margin-left--xl{margin-left:5rem!important}.margin-horiz--xl,.margin-right--xl{margin-right:5rem!important}.margin--xl{margin:5rem!important}.padding--none{padding:0!important}.padding-bottom--xs,.padding-vert--xs{padding-bottom:.25rem!important}.padding-top--xs,.padding-vert--xs{padding-top:.25rem!important}.padding-horiz--xs,.padding-left--xs{padding-left:.25rem!important}.padding-horiz--xs,.padding-right--xs{padding-right:.25rem!important}.padding--xs{padding:.25rem!important}.padding-bottom--sm,.padding-vert--sm{padding-bottom:.5rem!important}.padding-top--sm,.padding-vert--sm{padding-top:.5rem!important}.padding-horiz--sm,.padding-left--sm{padding-left:.5rem!important}.padding-horiz--sm,.padding-right--sm{padding-right:.5rem!important}.padding--sm{padding:.5rem!important}.padding-bottom--md,.padding-vert--md{padding-bottom:1rem!important}.padding-top--md,.padding-vert--md{padding-top:1rem!important}.padding-horiz--md,.padding-left--md{padding-left:1rem!important}.padding-horiz--md,.padding-right--md{padding-right:1rem!important}.padding--md{padding:1rem!important}.padding-bottom--lg,.padding-vert--lg{padding-bottom:2rem!important}.padding-top--lg,.padding-vert--lg{padding-top:2rem!important}.padding-horiz--lg,.padding-left--lg{padding-left:2rem!important}.padding-horiz--lg,.padding-right--lg{padding-right:2rem!important}.padding--lg{padding:2rem!important}.padding-bottom--xl,.padding-vert--xl{padding-bottom:5rem!important}.padding-top--xl,.padding-vert--xl{padding-top:5rem!important}.padding-horiz--xl,.padding-left--xl{padding-left:5rem!important}.padding-horiz--xl,.padding-right--xl{padding-right:5rem!important}.padding--xl{padding:5rem!important}code{background-color:var(--ifm-code-background);border:.1rem solid #0000001a;border-radius:var(--ifm-code-border-radius);font-family:var(--ifm-font-family-monospace);font-size:var(--ifm-code-font-size);padding:var(--ifm-code-padding-vertical) var(--ifm-code-padding-horizontal);color:#c8254e}a code{color:inherit}pre{background-color:var(--ifm-pre-background);border-radius:var(--ifm-pre-border-radius);color:var(--ifm-pre-color);font:var(--ifm-code-font-size)/var(--ifm-pre-line-height) var(--ifm-font-family-monospace);padding:var(--ifm-pre-padding)}pre code{background-color:initial;border:none;font-size:100%;line-height:inherit;padding:0}kbd{background-color:var(--ifm-color-emphasis-0);border:1px solid var(--ifm-color-emphasis-400);border-radius:.2rem;box-shadow:inset 0 -1px 0 var(--ifm-color-emphasis-400);color:var(--ifm-color-emphasis-800);font:80% var(--ifm-font-family-monospace);padding:.15rem .3rem}h1,h2,h3,h4,h5,h6{color:var(--ifm-heading-color);font-family:var(--ifm-heading-font-family);font-weight:var(--ifm-heading-font-weight);line-height:var(--ifm-heading-line-height);margin:var(--ifm-heading-margin-top) 0 var(--ifm-heading-margin-bottom) 0}h1{font-size:var(--ifm-h1-font-size)}h2{font-size:var(--ifm-h2-font-size)}h3{font-size:var(--ifm-h3-font-size)}h4{font-size:var(--ifm-h4-font-size)}h5{font-size:var(--ifm-h5-font-size)}h6{font-size:var(--ifm-h6-font-size)}img{max-width:100%}img[align=right]{padding-left:var(--image-alignment-padding)}img[align=left]{padding-right:var(--image-alignment-padding)}.markdown{--ifm-h1-vertical-rhythm-top:3;--ifm-h2-vertical-rhythm-top:2;--ifm-h3-vertical-rhythm-top:1.5;--ifm-heading-vertical-rhythm-top:1.25;--ifm-h1-vertical-rhythm-bottom:1.25;--ifm-heading-vertical-rhythm-bottom:1}.markdown:after,.markdown:before{content:"";display:table}.markdown:after{clear:both}.markdown h1:first-child{--ifm-h1-font-size:3rem;margin-bottom:calc(var(--ifm-h1-vertical-rhythm-bottom)*var(--ifm-leading))}.markdown>h2{--ifm-h2-font-size:2rem;margin-top:calc(var(--ifm-h2-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h3{--ifm-h3-font-size:1.5rem;margin-top:calc(var(--ifm-h3-vertical-rhythm-top)*var(--ifm-leading))}.markdown>h4,.markdown>h5,.markdown>h6{margin-top:calc(var(--ifm-heading-vertical-rhythm-top)*var(--ifm-leading))}.markdown>p,.markdown>pre,.markdown>ul,.tabList__CuJ{margin-bottom:var(--ifm-leading)}.markdown li>p{margin-top:var(--ifm-list-paragraph-margin)}.markdown li+li{margin-top:var(--ifm-list-item-margin)}ol,ul{margin:0 0 var(--ifm-list-margin);padding-left:var(--ifm-list-left-padding)}ol ol,ul ol{list-style-type:lower-roman}ol ol ol,ol ul ol,ul ol ol,ul ul ol{list-style-type:lower-alpha}table{border-collapse:collapse;display:block;margin-bottom:var(--ifm-spacing-vertical)}table thead tr{border-bottom:2px solid var(--ifm-table-border-color)}table thead,table tr:nth-child(2n){background-color:var(--ifm-table-stripe-background)}table tr{background-color:var(--ifm-table-background);border-top:var(--ifm-table-border-width) solid var(--ifm-table-border-color)}table td,table th{border:var(--ifm-table-border-width) solid var(--ifm-table-border-color);padding:var(--ifm-table-cell-padding)}table th{background-color:var(--ifm-table-head-background);color:var(--ifm-table-head-color);font-weight:var(--ifm-table-head-font-weight)}table td{color:var(--ifm-table-cell-color)}strong{font-weight:var(--ifm-font-weight-bold)}a{color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}a:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button:hover,.text--no-decoration,.text--no-decoration:hover,a:not([href]){text-decoration:none}p{margin:0 0 var(--ifm-paragraph-margin-bottom)}blockquote{border-left:var(--ifm-blockquote-border-left-width) solid var(--ifm-blockquote-border-color);box-shadow:var(--ifm-blockquote-shadow);color:var(--ifm-blockquote-color);font-size:var(--ifm-blockquote-font-size);padding:var(--ifm-blockquote-padding-vertical) var(--ifm-blockquote-padding-horizontal)}blockquote>:first-child{margin-top:0}blockquote>:last-child{margin-bottom:0}hr{background-color:var(--ifm-hr-background-color);border:0;height:var(--ifm-hr-height);margin:var(--ifm-hr-margin-vertical) 0}.shadow--lw{box-shadow:var(--ifm-global-shadow-lw)!important}.shadow--md{box-shadow:var(--ifm-global-shadow-md)!important}.shadow--tl{box-shadow:var(--ifm-global-shadow-tl)!important}.text--primary,.wordWrapButtonEnabled_EoeP .wordWrapButtonIcon_Bwma{color:var(--ifm-color-primary)}.text--secondary{color:var(--ifm-color-secondary)}.text--success{color:var(--ifm-color-success)}.text--info{color:var(--ifm-color-info)}.text--warning{color:var(--ifm-color-warning)}.text--danger{color:var(--ifm-color-danger)}.text--center{text-align:center}.text--left{text-align:left}.text--justify{text-align:justify}.text--right{text-align:right}.text--capitalize{text-transform:capitalize}.text--lowercase{text-transform:lowercase}.admonitionHeading_Gvgb,.alert__heading,.text--uppercase{text-transform:uppercase}.text--light{font-weight:var(--ifm-font-weight-light)}.text--normal{font-weight:var(--ifm-font-weight-normal)}.text--semibold{font-weight:var(--ifm-font-weight-semibold)}.text--bold{font-weight:var(--ifm-font-weight-bold)}.text--italic{font-style:italic}.text--truncate{overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.text--break{word-wrap:break-word!important;word-break:break-word!important}.clean-btn{background:none;border:none;color:inherit;cursor:pointer;font-family:inherit;padding:0}.alert,.alert .close{color:var(--ifm-alert-foreground-color)}.clean-list{padding-left:0}.alert--primary{--ifm-alert-background-color:var(--ifm-color-primary-contrast-background);--ifm-alert-background-color-highlight:#3578e526;--ifm-alert-foreground-color:var(--ifm-color-primary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-primary-dark)}.alert--secondary{--ifm-alert-background-color:var(--ifm-color-secondary-contrast-background);--ifm-alert-background-color-highlight:#ebedf026;--ifm-alert-foreground-color:var(--ifm-color-secondary-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-secondary-dark)}.alert--success{--ifm-alert-background-color:var(--ifm-color-success-contrast-background);--ifm-alert-background-color-highlight:#00a40026;--ifm-alert-foreground-color:var(--ifm-color-success-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-success-dark)}.alert--info{--ifm-alert-background-color:var(--ifm-color-info-contrast-background);--ifm-alert-background-color-highlight:#54c7ec26;--ifm-alert-foreground-color:var(--ifm-color-info-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-info-dark)}.alert--warning{--ifm-alert-background-color:var(--ifm-color-warning-contrast-background);--ifm-alert-background-color-highlight:#ffba0026;--ifm-alert-foreground-color:var(--ifm-color-warning-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-warning-dark)}.alert--danger{--ifm-alert-background-color:var(--ifm-color-danger-contrast-background);--ifm-alert-background-color-highlight:#fa383e26;--ifm-alert-foreground-color:var(--ifm-color-danger-contrast-foreground);--ifm-alert-border-color:var(--ifm-color-danger-dark)}.alert{--ifm-code-background:var(--ifm-alert-background-color-highlight);--ifm-link-color:var(--ifm-alert-foreground-color);--ifm-link-hover-color:var(--ifm-alert-foreground-color);--ifm-link-decoration:underline;--ifm-tabs-color:var(--ifm-alert-foreground-color);--ifm-tabs-color-active:var(--ifm-alert-foreground-color);--ifm-tabs-color-active-border:var(--ifm-alert-border-color);background-color:var(--ifm-alert-background-color);border:var(--ifm-alert-border-width) solid var(--ifm-alert-border-color);border-left-width:var(--ifm-alert-border-left-width);border-radius:var(--ifm-alert-border-radius);box-shadow:var(--ifm-alert-shadow);padding:var(--ifm-alert-padding-vertical) var(--ifm-alert-padding-horizontal)}.alert__heading{align-items:center;display:flex;font:700 var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family);margin-bottom:.5rem}.alert__icon{display:inline-flex;margin-right:.4em}.alert__icon svg{fill:var(--ifm-alert-foreground-color);stroke:var(--ifm-alert-foreground-color);stroke-width:0}.alert .close{margin:calc(var(--ifm-alert-padding-vertical)*-1) calc(var(--ifm-alert-padding-horizontal)*-1) 0 0;opacity:.75}.alert .close:focus,.alert .close:hover{opacity:1}.alert a{text-decoration-color:var(--ifm-alert-border-color)}.alert a:hover{text-decoration-thickness:2px}.avatar{column-gap:var(--ifm-avatar-intro-margin);display:flex}.avatar__photo{border-radius:50%;display:block;height:var(--ifm-avatar-photo-size);overflow:hidden;width:var(--ifm-avatar-photo-size)}.card--full-height,.navbar__logo img,body,html{height:100%}.avatar__photo--sm{--ifm-avatar-photo-size:2rem}.avatar__photo--lg{--ifm-avatar-photo-size:4rem}.avatar__photo--xl{--ifm-avatar-photo-size:6rem}.avatar__intro{display:flex;flex:1 1;flex-direction:column;justify-content:center;text-align:var(--ifm-avatar-intro-alignment)}.badge,.breadcrumbs__item,.breadcrumbs__link,.button,.dropdown>.navbar__link:after{display:inline-block}.avatar__name{font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base)}.avatar__subtitle{margin-top:.25rem}.avatar--vertical{--ifm-avatar-intro-alignment:center;--ifm-avatar-intro-margin:0.5rem;align-items:center;flex-direction:column}.badge{background-color:var(--ifm-badge-background-color);border:var(--ifm-badge-border-width) solid var(--ifm-badge-border-color);border-radius:var(--ifm-badge-border-radius);color:var(--ifm-badge-color);font-size:75%;font-weight:var(--ifm-font-weight-bold);line-height:1;padding:var(--ifm-badge-padding-vertical) var(--ifm-badge-padding-horizontal)}.badge--primary{--ifm-badge-background-color:var(--ifm-color-primary)}.badge--secondary{--ifm-badge-background-color:var(--ifm-color-secondary);color:var(--ifm-color-black)}.breadcrumbs__link,.button.button--secondary.button--outline:not(.button--active):not(:hover){color:var(--ifm-font-color-base)}.badge--success{--ifm-badge-background-color:var(--ifm-color-success)}.badge--info{--ifm-badge-background-color:var(--ifm-color-info)}.badge--warning{--ifm-badge-background-color:var(--ifm-color-warning)}.badge--danger{--ifm-badge-background-color:var(--ifm-color-danger)}.breadcrumbs{margin-bottom:0;padding-left:0}.breadcrumbs__item:not(:last-child):after{background:var(--ifm-breadcrumb-separator) center;content:" ";display:inline-block;filter:var(--ifm-breadcrumb-separator-filter);height:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier));margin:0 var(--ifm-breadcrumb-spacing);opacity:.5;width:calc(var(--ifm-breadcrumb-separator-size)*var(--ifm-breadcrumb-size-multiplier)*var(--ifm-breadcrumb-separator-size-multiplier))}.breadcrumbs__item--active .breadcrumbs__link{background:var(--ifm-breadcrumb-item-background-active);color:var(--ifm-breadcrumb-color-active)}.breadcrumbs__link{border-radius:var(--ifm-breadcrumb-border-radius);font-size:calc(1rem*var(--ifm-breadcrumb-size-multiplier));padding:calc(var(--ifm-breadcrumb-padding-vertical)*var(--ifm-breadcrumb-size-multiplier)) calc(var(--ifm-breadcrumb-padding-horizontal)*var(--ifm-breadcrumb-size-multiplier));transition-duration:var(--ifm-transition-fast);transition-property:background,color}.breadcrumbs__link:any-link:hover,.breadcrumbs__link:link:hover,.breadcrumbs__link:visited:hover,area[href].breadcrumbs__link:hover{background:var(--ifm-breadcrumb-item-background-active);text-decoration:none}.breadcrumbs--sm{--ifm-breadcrumb-size-multiplier:0.8}.breadcrumbs--lg{--ifm-breadcrumb-size-multiplier:1.2}.button{background-color:var(--ifm-button-background-color);border:var(--ifm-button-border-width) solid var(--ifm-button-border-color);border-radius:var(--ifm-button-border-radius);cursor:pointer;font-size:calc(.875rem*var(--ifm-button-size-multiplier));font-weight:var(--ifm-button-font-weight);line-height:1.5;padding:calc(var(--ifm-button-padding-vertical)*var(--ifm-button-size-multiplier)) calc(var(--ifm-button-padding-horizontal)*var(--ifm-button-size-multiplier));text-align:center;transition-duration:var(--ifm-button-transition-duration);transition-property:color,background,border-color;-webkit-user-select:none;user-select:none;white-space:nowrap}.button,.button:hover{color:var(--ifm-button-color)}.button--outline{--ifm-button-color:var(--ifm-button-border-color)}.button--outline:hover{--ifm-button-background-color:var(--ifm-button-border-color)}.button--link{--ifm-button-border-color:#0000;color:var(--ifm-link-color);text-decoration:var(--ifm-link-decoration)}.button--link.button--active,.button--link:active,.button--link:hover{color:var(--ifm-link-hover-color);text-decoration:var(--ifm-link-hover-decoration)}.button.disabled,.button:disabled,.button[disabled]{opacity:.65;pointer-events:none}.button--sm{--ifm-button-size-multiplier:0.8}.button--lg{--ifm-button-size-multiplier:1.35}.button--block{display:block;width:100%}.button.button--secondary{color:var(--ifm-color-gray-900)}:where(.button--primary){--ifm-button-background-color:var(--ifm-color-primary);--ifm-button-border-color:var(--ifm-color-primary)}:where(.button--primary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-primary-dark);--ifm-button-border-color:var(--ifm-color-primary-dark)}.button--primary.button--active,.button--primary:active{--ifm-button-background-color:var(--ifm-color-primary-darker);--ifm-button-border-color:var(--ifm-color-primary-darker)}:where(.button--secondary){--ifm-button-background-color:var(--ifm-color-secondary);--ifm-button-border-color:var(--ifm-color-secondary)}:where(.button--secondary):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-secondary-dark);--ifm-button-border-color:var(--ifm-color-secondary-dark)}.button--secondary.button--active,.button--secondary:active{--ifm-button-background-color:var(--ifm-color-secondary-darker);--ifm-button-border-color:var(--ifm-color-secondary-darker)}:where(.button--success){--ifm-button-background-color:var(--ifm-color-success);--ifm-button-border-color:var(--ifm-color-success)}:where(.button--success):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-success-dark);--ifm-button-border-color:var(--ifm-color-success-dark)}.button--success.button--active,.button--success:active{--ifm-button-background-color:var(--ifm-color-success-darker);--ifm-button-border-color:var(--ifm-color-success-darker)}:where(.button--info){--ifm-button-background-color:var(--ifm-color-info);--ifm-button-border-color:var(--ifm-color-info)}:where(.button--info):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-info-dark);--ifm-button-border-color:var(--ifm-color-info-dark)}.button--info.button--active,.button--info:active{--ifm-button-background-color:var(--ifm-color-info-darker);--ifm-button-border-color:var(--ifm-color-info-darker)}:where(.button--warning){--ifm-button-background-color:var(--ifm-color-warning);--ifm-button-border-color:var(--ifm-color-warning)}:where(.button--warning):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-warning-dark);--ifm-button-border-color:var(--ifm-color-warning-dark)}.button--warning.button--active,.button--warning:active{--ifm-button-background-color:var(--ifm-color-warning-darker);--ifm-button-border-color:var(--ifm-color-warning-darker)}:where(.button--danger){--ifm-button-background-color:var(--ifm-color-danger);--ifm-button-border-color:var(--ifm-color-danger)}:where(.button--danger):not(.button--outline):hover{--ifm-button-background-color:var(--ifm-color-danger-dark);--ifm-button-border-color:var(--ifm-color-danger-dark)}.button--danger.button--active,.button--danger:active{--ifm-button-background-color:var(--ifm-color-danger-darker);--ifm-button-border-color:var(--ifm-color-danger-darker)}.button-group{display:inline-flex;gap:var(--ifm-button-group-spacing)}.button-group>.button:not(:first-child){border-bottom-left-radius:0;border-top-left-radius:0}.button-group>.button:not(:last-child){border-bottom-right-radius:0;border-top-right-radius:0}.button-group--block{display:flex;justify-content:stretch}.button-group--block>.button{flex-grow:1}.card{background-color:var(--ifm-card-background-color);border-radius:var(--ifm-card-border-radius);box-shadow:var(--ifm-global-shadow-lw);display:flex;flex-direction:column;overflow:hidden}.card__image{padding-top:var(--ifm-card-vertical-spacing)}.card__image:first-child{padding-top:0}.card__body,.card__footer,.card__header{padding:var(--ifm-card-vertical-spacing) var(--ifm-card-horizontal-spacing)}.card__body:not(:last-child),.card__footer:not(:last-child),.card__header:not(:last-child){padding-bottom:0}.card__body>:last-child,.card__footer>:last-child,.card__header>:last-child{margin-bottom:0}.card__footer{margin-top:auto}.table-of-contents{font-size:.8rem;margin-bottom:0;padding:var(--ifm-toc-padding-vertical) 0}.table-of-contents,.table-of-contents ul{list-style:none;padding-left:var(--ifm-toc-padding-horizontal)}.table-of-contents li{margin:var(--ifm-toc-padding-vertical) var(--ifm-toc-padding-horizontal)}.table-of-contents__left-border{border-left:1px solid var(--ifm-toc-border-color)}.table-of-contents__link{color:var(--ifm-toc-link-color);display:block}.table-of-contents__link--active,.table-of-contents__link--active code,.table-of-contents__link:hover,.table-of-contents__link:hover code{color:var(--ifm-color-primary);text-decoration:none}.close{color:var(--ifm-color-black);float:right;font-size:1.5rem;font-weight:var(--ifm-font-weight-bold);line-height:1;opacity:.5;padding:1rem;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.close:hover{opacity:.7}.close:focus,.theme-code-block-highlighted-line .codeLineNumber_Tfdd:before{opacity:.8}.dropdown{display:inline-flex;font-weight:var(--ifm-dropdown-font-weight);position:relative;vertical-align:top}.dropdown--hoverable:hover .dropdown__menu,.dropdown--show .dropdown__menu{opacity:1;pointer-events:all;transform:translateY(-1px);visibility:visible}#nprogress,.dropdown__menu,.navbar__item.dropdown .navbar__link:not([href]){pointer-events:none}.dropdown--right .dropdown__menu{left:inherit;right:0}.dropdown--nocaret .navbar__link:after{content:none!important}.dropdown__menu{background-color:var(--ifm-dropdown-background-color);border-radius:var(--ifm-global-radius);box-shadow:var(--ifm-global-shadow-md);left:0;max-height:80vh;min-width:10rem;opacity:0;overflow-y:auto;padding:.5rem;position:absolute;top:calc(100% - var(--ifm-navbar-item-padding-vertical) + .3rem);transform:translateY(-.625rem);transition-duration:var(--ifm-transition-fast);transition-property:opacity,transform,visibility;transition-timing-function:var(--ifm-transition-timing-default);visibility:hidden;z-index:var(--ifm-z-index-dropdown)}.menu__caret,.menu__link,.menu__list-item-collapsible{border-radius:.25rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.dropdown__link{border-radius:.25rem;color:var(--ifm-dropdown-link-color);display:block;font-size:.875rem;margin-top:.2rem;padding:.25rem .5rem;white-space:nowrap}.dropdown__link--active,.dropdown__link:hover{background-color:var(--ifm-dropdown-hover-background-color);color:var(--ifm-dropdown-link-color);text-decoration:none}.dropdown__link--active,.dropdown__link--active:hover{--ifm-dropdown-link-color:var(--ifm-link-color)}.dropdown>.navbar__link:after{border-color:currentcolor #0000;border-style:solid;border-width:.4em .4em 0;content:"";margin-left:.3em;position:relative;top:2px;transform:translateY(-50%)}.footer{background-color:var(--ifm-footer-background-color);color:var(--ifm-footer-color);padding:var(--ifm-footer-padding-vertical) var(--ifm-footer-padding-horizontal)}.footer--dark{--ifm-footer-background-color:#303846;--ifm-footer-color:var(--ifm-footer-link-color);--ifm-footer-link-color:var(--ifm-color-secondary);--ifm-footer-title-color:var(--ifm-color-white)}.footer__links{margin-bottom:1rem}.footer__link-item{color:var(--ifm-footer-link-color);line-height:2}.footer__link-item:hover{color:var(--ifm-footer-link-hover-color)}.footer__link-separator{margin:0 var(--ifm-footer-link-horizontal-spacing)}.footer__logo{margin-top:1rem;max-width:var(--ifm-footer-logo-max-width)}.footer__title{color:var(--ifm-footer-title-color);font:700 var(--ifm-h4-font-size)/var(--ifm-heading-line-height) var(--ifm-font-family-base);margin-bottom:var(--ifm-heading-margin-bottom)}.menu,.navbar__link{font-weight:var(--ifm-font-weight-semibold)}.docItemContainer_Djhp article>:first-child,.docItemContainer_Djhp header+*,.footer__item{margin-top:0}.admonitionContent_BuS1>:last-child,.collapsibleContent_i85q p:last-child,.details_lb9f>summary>p:last-child,.footer__items,.tabItem_Ymn6>:last-child{margin-bottom:0}.codeBlockStandalone_MEMb,[type=checkbox]{padding:0}.hero{align-items:center;background-color:var(--ifm-hero-background-color);color:var(--ifm-hero-text-color);display:flex;padding:4rem 2rem}.hero--primary{--ifm-hero-background-color:var(--ifm-color-primary);--ifm-hero-text-color:var(--ifm-font-color-base-inverse)}.hero--dark{--ifm-hero-background-color:#303846;--ifm-hero-text-color:var(--ifm-color-white)}.hero__title{font-size:3rem}.hero__subtitle{font-size:1.5rem}.menu__list{margin:0;padding-left:0}.menu__caret,.menu__link{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu__list .menu__list{flex:0 0 100%;margin-top:.25rem;padding-left:var(--ifm-menu-link-padding-horizontal)}.menu__list-item:not(:first-child){margin-top:.25rem}.menu__list-item--collapsed .menu__list{height:0;overflow:hidden}.details_lb9f[data-collapsed=false].isBrowser_bmU9>summary:before,.details_lb9f[open]:not(.isBrowser_bmU9)>summary:before,.menu__list-item--collapsed .menu__caret:before,.menu__list-item--collapsed .menu__link--sublist:after{transform:rotate(90deg)}.menu__list-item-collapsible{display:flex;flex-wrap:wrap;position:relative}.menu__caret:hover,.menu__link:hover,.menu__list-item-collapsible--active,.menu__list-item-collapsible:hover{background:var(--ifm-menu-color-background-hover)}.menu__list-item-collapsible .menu__link--active,.menu__list-item-collapsible .menu__link:hover{background:none!important}.menu__caret,.menu__link{align-items:center;display:flex}.navbar-sidebar,.navbar-sidebar__backdrop{bottom:0;opacity:0;transition-duration:var(--ifm-transition-fast);transition-timing-function:ease-in-out;visibility:hidden;top:0;left:0}.menu__link{color:var(--ifm-menu-color);flex:1;line-height:1.25}.menu__link:hover{color:var(--ifm-menu-color);text-decoration:none}.menu__caret:before,.menu__link--sublist-caret:after{height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast) linear;width:1.25rem;filter:var(--ifm-menu-link-sublist-icon-filter);content:""}.menu__link--sublist-caret:after{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem;margin-left:auto;min-width:1.25rem}.menu__link--active,.menu__link--active:hover{color:var(--ifm-menu-color-active)}.navbar__brand,.navbar__link{color:var(--ifm-navbar-link-color)}.menu__link--active:not(.menu__link--sublist){background-color:var(--ifm-menu-color-background-active)}.menu__caret:before{background:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem}.navbar--dark,html[data-theme=dark]{--ifm-menu-link-sublist-icon-filter:invert(100%) sepia(94%) saturate(17%) hue-rotate(223deg) brightness(104%) contrast(98%)}.navbar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-navbar-shadow);height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar,.navbar>.container,.navbar>.container-fluid,.sm-hidden{display:flex}.navbar--fixed-top{position:sticky;top:0;z-index:var(--ifm-z-index-fixed)}.navbar__inner{display:flex;flex-wrap:wrap;justify-content:space-between;width:100%}.navbar__brand{align-items:center;display:flex;margin-right:1rem;min-width:0}.navbar__brand:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.announcementBarContent_xLdY,.navbar__title{flex:1 1 auto}.navbar__toggle{display:none;margin-right:.5rem}.navbar__logo{flex:0 0 auto;height:2rem;margin-right:.5rem}.navbar__items{align-items:center;display:flex;flex:1;min-width:0}.navbar__items--center{flex:0 0 auto}.navbar__items--center .navbar__brand{margin:0}.navbar__items--center+.navbar__items--right{flex:1}.navbar__items--right{flex:0 0 auto;justify-content:flex-end}.navbar__items--right>:last-child{padding-right:0}.navbar__item{display:inline-block;padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.navbar__link--active,.navbar__link:hover{color:var(--ifm-navbar-link-hover-color);text-decoration:none}.navbar--dark,.navbar--primary{--ifm-menu-color:var(--ifm-color-gray-300);--ifm-navbar-link-color:var(--ifm-color-gray-100);--ifm-navbar-search-input-background-color:#ffffff1a;--ifm-navbar-search-input-placeholder-color:#ffffff80;color:var(--ifm-color-white)}.navbar--dark{--ifm-navbar-background-color:#242526;--ifm-menu-color-background-active:#ffffff0d;--ifm-navbar-search-input-color:var(--ifm-color-white)}.navbar--primary{--ifm-navbar-background-color:var(--ifm-color-primary);--ifm-navbar-link-hover-color:var(--ifm-color-white);--ifm-menu-color-active:var(--ifm-color-white);--ifm-navbar-search-input-color:var(--ifm-color-emphasis-500)}.navbar__search-input{-webkit-appearance:none;appearance:none;background:var(--ifm-navbar-search-input-background-color) var(--ifm-navbar-search-input-icon) no-repeat .75rem center/1rem 1rem;border:none;border-radius:2rem;color:var(--ifm-navbar-search-input-color);cursor:text;display:inline-block;font-size:.9rem;height:2rem;padding:0 .5rem 0 2.25rem;width:12.5rem}.navbar__search-input::placeholder{color:var(--ifm-navbar-search-input-placeholder-color)}.navbar-sidebar{background-color:var(--ifm-navbar-background-color);box-shadow:var(--ifm-global-shadow-md);position:fixed;transform:translate3d(-100%,0,0);transition-property:opacity,visibility,transform;width:var(--ifm-navbar-sidebar-width)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar__items{transform:translateZ(0)}.navbar-sidebar--show .navbar-sidebar,.navbar-sidebar--show .navbar-sidebar__backdrop{opacity:1;visibility:visible}.navbar-sidebar__backdrop{background-color:#0009;position:fixed;right:0;transition-property:opacity,visibility}.navbar-sidebar__brand{align-items:center;box-shadow:var(--ifm-navbar-shadow);display:flex;flex:1;height:var(--ifm-navbar-height);padding:var(--ifm-navbar-padding-vertical) var(--ifm-navbar-padding-horizontal)}.navbar-sidebar__items{display:flex;height:calc(100% - var(--ifm-navbar-height));transition:transform var(--ifm-transition-fast) ease-in-out}.navbar-sidebar__items--show-secondary{transform:translate3d(calc((var(--ifm-navbar-sidebar-width))*-1),0,0)}.navbar-sidebar__item{flex-shrink:0;padding:.5rem;width:calc(var(--ifm-navbar-sidebar-width))}.navbar-sidebar__back{background:var(--ifm-menu-color-background-active);font-size:15px;font-weight:var(--ifm-button-font-weight);margin:0 0 .2rem -.5rem;padding:.6rem 1.5rem;position:relative;text-align:left;top:-.5rem;width:calc(100% + 1rem)}.navbar-sidebar__close{display:flex;margin-left:auto}.pagination{column-gap:var(--ifm-pagination-page-spacing);display:flex;font-size:var(--ifm-pagination-font-size);padding-left:0}.pagination--sm{--ifm-pagination-font-size:0.8rem;--ifm-pagination-padding-horizontal:0.8rem;--ifm-pagination-padding-vertical:0.2rem}.pagination--lg{--ifm-pagination-font-size:1.2rem;--ifm-pagination-padding-horizontal:1.2rem;--ifm-pagination-padding-vertical:0.3rem}.pagination__item{display:inline-flex}.pagination__item>span{padding:var(--ifm-pagination-padding-vertical)}.pagination__item--active .pagination__link{color:var(--ifm-pagination-color-active)}.pagination__item--active .pagination__link,.pagination__item:not(.pagination__item--active):hover .pagination__link{background:var(--ifm-pagination-item-active-background)}.pagination__item--disabled,.pagination__item[disabled]{opacity:.25;pointer-events:none}.pagination__link{border-radius:var(--ifm-pagination-border-radius);color:var(--ifm-font-color-base);display:inline-block;padding:var(--ifm-pagination-padding-vertical) var(--ifm-pagination-padding-horizontal);transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination__link:hover{text-decoration:none}.pagination-nav{grid-gap:var(--ifm-spacing-horizontal);display:grid;gap:var(--ifm-spacing-horizontal);grid-template-columns:repeat(2,1fr)}.pagination-nav__link{border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-pagination-nav-border-radius);display:block;height:100%;line-height:var(--ifm-heading-line-height);padding:var(--ifm-global-spacing);transition:border-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.pagination-nav__link:hover{border-color:var(--ifm-pagination-nav-color-hover);text-decoration:none}.pagination-nav__link--next{grid-column:2/3;text-align:right}.pagination-nav__label{font-size:var(--ifm-h4-font-size);font-weight:var(--ifm-heading-font-weight);word-break:break-word}.pagination-nav__link--prev .pagination-nav__label:before{content:"« "}.pagination-nav__link--next .pagination-nav__label:after{content:" »"}.pagination-nav__sublabel{color:var(--ifm-color-content-secondary);font-size:var(--ifm-h5-font-size);font-weight:var(--ifm-font-weight-semibold);margin-bottom:.25rem}.pills__item,.tabs{font-weight:var(--ifm-font-weight-bold)}.pills{display:flex;gap:var(--ifm-pills-spacing);padding-left:0}.pills__item{border-radius:.5rem;cursor:pointer;display:inline-block;padding:.25rem 1rem;transition:background var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.tabs,:not(.containsTaskList_mC6p>li)>.containsTaskList_mC6p{padding-left:0}.pills__item--active{color:var(--ifm-pills-color-active)}.pills__item--active,.pills__item:not(.pills__item--active):hover{background:var(--ifm-pills-color-background-active)}.pills--block{justify-content:stretch}.pills--block .pills__item{flex-grow:1;text-align:center}.tabs{color:var(--ifm-tabs-color);display:flex;margin-bottom:0;overflow-x:auto}.tabs__item{border-bottom:3px solid #0000;border-radius:var(--ifm-global-radius);cursor:pointer;display:inline-flex;padding:var(--ifm-tabs-padding-vertical) var(--ifm-tabs-padding-horizontal);transition:background-color var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.code-block-primary-line,.code-block-warning-line{margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.tabs__item--active{border-bottom-color:var(--ifm-tabs-color-active-border);border-bottom-left-radius:0;border-bottom-right-radius:0;color:var(--ifm-tabs-color-active)}.tabs__item:hover{background-color:var(--ifm-hover-overlay)}.tabs--block{justify-content:stretch}.tabs--block .tabs__item{flex-grow:1;justify-content:center}html[data-theme=dark]{--ifm-color-scheme:dark;--ifm-color-emphasis-0:var(--ifm-color-gray-1000);--ifm-color-emphasis-100:var(--ifm-color-gray-900);--ifm-color-emphasis-200:var(--ifm-color-gray-800);--ifm-color-emphasis-300:var(--ifm-color-gray-700);--ifm-color-emphasis-400:var(--ifm-color-gray-600);--ifm-color-emphasis-600:var(--ifm-color-gray-400);--ifm-color-emphasis-700:var(--ifm-color-gray-300);--ifm-color-emphasis-800:var(--ifm-color-gray-200);--ifm-color-emphasis-900:var(--ifm-color-gray-100);--ifm-color-emphasis-1000:var(--ifm-color-gray-0);--ifm-background-color:#1b1b1d;--ifm-background-surface-color:#242526;--ifm-hover-overlay:#ffffff0d;--ifm-color-content:#e3e3e3;--ifm-color-content-secondary:#fff;--ifm-breadcrumb-separator-filter:invert(64%) sepia(11%) saturate(0%) hue-rotate(149deg) brightness(99%) contrast(95%);--ifm-code-background:#ffffff1a;--ifm-scrollbar-track-background-color:#444;--ifm-scrollbar-thumb-background-color:#686868;--ifm-scrollbar-thumb-hover-background-color:#7a7a7a;--ifm-table-stripe-background:#ffffff12;--ifm-toc-border-color:var(--ifm-color-emphasis-200);--ifm-color-primary-contrast-background:#102445;--ifm-color-primary-contrast-foreground:#ebf2fc;--ifm-color-secondary-contrast-background:#474748;--ifm-color-secondary-contrast-foreground:#fdfdfe;--ifm-color-success-contrast-background:#003100;--ifm-color-success-contrast-foreground:#e6f6e6;--ifm-color-info-contrast-background:#193c47;--ifm-color-info-contrast-foreground:#eef9fd;--ifm-color-warning-contrast-background:#4d3800;--ifm-color-warning-contrast-foreground:#fff8e6;--ifm-color-danger-contrast-background:#4b1113;--ifm-color-danger-contrast-foreground:#ffebec}#nprogress .bar{background:var(--docusaurus-progress-bar-color);height:2px;left:0;position:fixed;top:0;width:100%;z-index:1031}#nprogress .peg{box-shadow:0 0 10px var(--docusaurus-progress-bar-color),0 0 5px var(--docusaurus-progress-bar-color);height:100%;opacity:1;position:absolute;right:0;transform:rotate(3deg) translateY(-4px);width:100px}*,::backdrop,:after,:before{--tw-border-spacing-x:0;--tw-border-spacing-y:0;--tw-translate-x:0;--tw-translate-y:0;--tw-rotate:0;--tw-skew-x:0;--tw-skew-y:0;--tw-scale-x:1;--tw-scale-y:1;--tw-pan-x: ;--tw-pan-y: ;--tw-pinch-zoom: ;--tw-scroll-snap-strictness:proximity;--tw-gradient-from-position: ;--tw-gradient-via-position: ;--tw-gradient-to-position: ;--tw-ordinal: ;--tw-slashed-zero: ;--tw-numeric-figure: ;--tw-numeric-spacing: ;--tw-numeric-fraction: ;--tw-ring-inset: ;--tw-ring-offset-width:0px;--tw-ring-offset-color:#fff;--tw-ring-color:#3b82f680;--tw-ring-offset-shadow:0 0 #0000;--tw-ring-shadow:0 0 #0000;--tw-shadow:0 0 #0000;--tw-shadow-colored:0 0 #0000;--tw-blur: ;--tw-brightness: ;--tw-contrast: ;--tw-grayscale: ;--tw-hue-rotate: ;--tw-invert: ;--tw-saturate: ;--tw-sepia: ;--tw-drop-shadow: ;--tw-backdrop-blur: ;--tw-backdrop-brightness: ;--tw-backdrop-contrast: ;--tw-backdrop-grayscale: ;--tw-backdrop-hue-rotate: ;--tw-backdrop-invert: ;--tw-backdrop-opacity: ;--tw-backdrop-saturate: ;--tw-backdrop-sepia: }.z-input,.z-input:focus,.z-textarea,.z-textarea:focus{--tw-ring-offset-shadow:var(--tw-ring-inset) 0 0 0 var(--tw-ring-offset-width) var(--tw-ring-offset-color);--tw-ring-inset:inset;--tw-ring-opacity:1}.container{width:100%}.visible{visibility:visible}.invisible{visibility:hidden}.static{position:static}.absolute{position:absolute}.isolate{isolation:isolate}.table{display:table}.filter{filter:var(--tw-blur) var(--tw-brightness) var(--tw-contrast) var(--tw-grayscale) var(--tw-hue-rotate) var(--tw-invert) var(--tw-saturate) var(--tw-sepia) var(--tw-drop-shadow)}.code-block-primary-line{background-color:#e0f2fe;display:block}.code-block-primary-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module{background-color:#e0f2fe;border-left:3px solid #60a5fa}.code-block-warning-line{background-color:#fef9c3;display:block}.code-block-warning-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module{background-color:#fef9c3;border-left:3px solid #facc15}[data-theme=dark] .code-block-primary-line,[data-theme=dark] .code-block-primary-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module,[data-theme=dark] .code-block-warning-line,[data-theme=dark] .code-block-warning-line .codeLineNumber_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Line-styles-module{background-color:#0009}.tabs-container{border-radius:.5rem;box-shadow:0 0 12px #0000002e;padding:.5rem}.theme-code-block:hover .buttonGroup_node_modules-\@docusaurus-theme-classic-lib-theme-CodeBlock-Content-styles-module button{opacity:.75!important}.divider{background:linear-gradient(-45deg,#94a3b8 30%,#f1f4ff 0,#f1f4ff 50%,#f1f4ff 0,#f1f4ff 80%,#f1f4ff 0);background-size:1.5rem 1.5rem;border:1px dashed #0000}.header-github-link:hover{opacity:.6}.header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat;content:"";display:flex}[data-theme=dark] .header-github-link:before{background:url("data:image/svg+xml;charset=utf-8,%3Csvg viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Cpath fill='%23fff' d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E") no-repeat}.z-input,.z-textarea{--tw-text-opacity:1;--tw-shadow:0 1px 2px 0 #0000000d;--tw-shadow-colored:0 1px 2px 0 var(--tw-shadow-color);--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(1px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgb(209 213 219/var(--tw-ring-opacity));border-width:0;box-shadow:var(--tw-ring-offset-shadow,0 0 #0000),var(--tw-ring-shadow,0 0 #0000),var(--tw-shadow);box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000);color:rgb(17 24 39/var(--tw-text-opacity));display:block;padding-bottom:.375rem;padding-top:.375rem;width:100%}.z-input::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.z-input:focus,.z-textarea:focus{--tw-ring-shadow:var(--tw-ring-inset) 0 0 0 calc(2px + var(--tw-ring-offset-width)) var(--tw-ring-color);--tw-ring-color:rgb(79 70 229/var(--tw-ring-opacity));box-shadow:var(--tw-ring-offset-shadow),var(--tw-ring-shadow),var(--tw-shadow,0 0 #0000)}.z-button{--tw-bg-opacity:1;--tw-text-opacity:1;background-color:rgb(59 130 246/var(--tw-bg-opacity));color:rgb(255 255 255/var(--tw-text-opacity));font-weight:700;padding:.5rem 1rem;width:9rem}.z-button:hover{--tw-bg-opacity:1;background-color:rgb(37 99 235/var(--tw-bg-opacity))}.z-textarea::placeholder{--tw-text-opacity:1;color:rgb(156 163 175/var(--tw-text-opacity))}.navbar--fixed-top{height:70px}.navbar--fixed-top .navbar__logo{height:44px;margin-right:11px;padding-left:5px}.navbar--fixed-top .navbar__title{font-size:28px}.navbar__link{font-size:16px}.header-github-link:before{height:35px;width:35px}.navbar__title{font-size:30px;font-weight:700}.hero--primary,.mdxPageWrapper_j9I6{justify-content:center}.iconEdit_Z9Sw{margin-right:.3em;vertical-align:sub}.tag_zVej{border:1px solid var(--docusaurus-tag-list-border);transition:border var(--ifm-transition-fast)}.tag_zVej:hover{--docusaurus-tag-list-border:var(--ifm-link-color);text-decoration:none}.tagRegular_sFm0{border-radius:var(--ifm-global-radius);font-size:90%;padding:.2rem .5rem .3rem}.tagWithCount_h2kH{align-items:center;border-left:0;display:flex;padding:0 .5rem 0 1rem;position:relative}.tagWithCount_h2kH:after,.tagWithCount_h2kH:before{border:1px solid var(--docusaurus-tag-list-border);content:"";position:absolute;top:50%;transition:inherit}.tagWithCount_h2kH:before{border-bottom:0;border-right:0;height:1.18rem;right:100%;transform:translate(50%,-50%) rotate(-45deg);width:1.18rem}.tagWithCount_h2kH:after{border-radius:50%;height:.5rem;left:0;transform:translateY(-50%);width:.5rem}.tagWithCount_h2kH span{background:var(--ifm-color-secondary);border-radius:var(--ifm-global-radius);color:var(--ifm-color-black);font-size:.7rem;line-height:1.2;margin-left:.3rem;padding:.1rem .4rem}.tags_jXut{display:inline}.tag_QGVx{display:inline-block;margin:0 .4rem .5rem 0}.lastUpdated_vwxv{font-size:smaller;font-style:italic;margin-top:.2rem}.tocCollapsibleButton_TO0P{align-items:center;display:flex;font-size:inherit;justify-content:space-between;padding:.4rem .8rem;width:100%}.tocCollapsibleButton_TO0P:after{background:var(--ifm-menu-link-sublist-icon) 50% 50%/2rem 2rem no-repeat;content:"";filter:var(--ifm-menu-link-sublist-icon-filter);height:1.25rem;transform:rotate(180deg);transition:transform var(--ifm-transition-fast);width:1.25rem}.tocCollapsibleButtonExpanded_MG3E:after,.tocCollapsibleExpanded_sAul{transform:none}.tocCollapsible_ETCw{background-color:var(--ifm-menu-color-background-active);border-radius:var(--ifm-global-radius);margin:1rem 0}.tocCollapsibleContent_vkbj>ul{border-left:none;border-top:1px solid var(--ifm-color-emphasis-300);font-size:15px;padding:.2rem 0}.tocCollapsibleContent_vkbj ul li{margin:.4rem .8rem}.tocCollapsibleContent_vkbj a{display:block}.backToTopButton_sjWU{background-color:var(--ifm-color-emphasis-200);border-radius:50%;bottom:1.3rem;box-shadow:var(--ifm-global-shadow-lw);height:3rem;opacity:0;position:fixed;right:1.3rem;transform:scale(0);transition:all var(--ifm-transition-fast) var(--ifm-transition-timing-default);visibility:hidden;width:3rem;z-index:calc(var(--ifm-z-index-fixed) - 1)}.backToTopButton_sjWU:after{background-color:var(--ifm-color-emphasis-1000);content:" ";display:inline-block;height:100%;-webkit-mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;mask:var(--ifm-menu-link-sublist-icon) 50%/2rem 2rem no-repeat;width:100%}.backToTopButtonShow_xfvO{opacity:1;transform:scale(1);visibility:visible}.skipToContent_fXgn{background-color:var(--ifm-background-surface-color);color:var(--ifm-color-emphasis-900);left:100%;padding:calc(var(--ifm-global-spacing)/2) var(--ifm-global-spacing);position:fixed;top:1rem;z-index:calc(var(--ifm-z-index-fixed) + 1)}.skipToContent_fXgn:focus{box-shadow:var(--ifm-global-shadow-md);left:1rem}.closeButton_CVFx{line-height:0;padding:0}.content_knG7{font-size:85%;padding:5px 0;text-align:center}.content_knG7 a{color:inherit;text-decoration:underline}.announcementBar_mb4j{align-items:center;background-color:var(--ifm-color-white);border-bottom:1px solid var(--ifm-color-emphasis-100);color:var(--ifm-color-black);display:flex;height:var(--docusaurus-announcement-bar-height)}#__docusaurus-base-url-issue-banner-container,.docSidebarContainer_YfHR,.sidebarLogo_isFc,.themedComponent_mlkZ,[data-theme=dark] .lightToggleIcon_pyhR,[data-theme=light] .darkToggleIcon_wfgR,html[data-announcement-bar-initially-dismissed=true] .announcementBar_mb4j{display:none}.announcementBarPlaceholder_vyr4{flex:0 0 10px}.announcementBarClose_gvF7{align-self:stretch;flex:0 0 30px}.toggle_vylO{height:2rem;width:2rem}.toggleButton_gllP{align-items:center;border-radius:50%;display:flex;height:100%;justify-content:center;transition:background var(--ifm-transition-fast);width:100%}.toggleButton_gllP:hover{background:var(--ifm-color-emphasis-200)}.toggleButtonDisabled_aARS{cursor:not-allowed}.darkNavbarColorModeToggle_X3D1:hover{background:var(--ifm-color-gray-800)}[data-theme=dark] .themedComponent--dark_xIcU,[data-theme=light] .themedComponent--light_NVdE,html:not([data-theme]) .themedComponent--light_NVdE{display:initial}[data-theme=dark]:root{--docusaurus-collapse-button-bg:#ffffff0d;--docusaurus-collapse-button-bg-hover:#ffffff1a}.collapseSidebarButton_PEFL{display:none;margin:0}.iconExternalLink_nPIU{margin-left:.3rem}.docMainContainer_TBSr,.docRoot_UBD9{display:flex;width:100%}.docsWrapper_hBAB{display:flex;flex:1 0 auto}.dropdownNavbarItemMobile_S0Fm{cursor:pointer}.iconLanguage_nlXk{margin-right:5px;vertical-align:text-bottom}@supports selector(:has(*)){.navbarSearchContainer_Bca1:not(:has(>*)){display:none}}.navbarHideable_m1mJ{transition:transform var(--ifm-transition-fast) ease}.navbarHidden_jGov{transform:translate3d(0,calc(-100% - 2px),0)}.errorBoundaryError_a6uf{color:red;white-space:pre-wrap}.errorBoundaryFallback_VBag{color:red;padding:.55rem}.footerLogoLink_BH7S{opacity:.5;transition:opacity var(--ifm-transition-fast) var(--ifm-transition-timing-default)}.footerLogoLink_BH7S:hover,.hash-link:focus,:hover>.hash-link{opacity:1}body:not(.navigation-with-keyboard) :not(input):focus{outline:0}.anchorWithStickyNavbar_LWe7{scroll-margin-top:calc(var(--ifm-navbar-height) + .5rem)}.anchorWithHideOnScrollNavbar_WYt5{scroll-margin-top:.5rem}.hash-link{opacity:0;padding-left:.5rem;transition:opacity var(--ifm-transition-fast);-webkit-user-select:none;user-select:none}.hash-link:before{content:"#"}.mainWrapper_z2l0{display:flex;flex:1 0 auto;flex-direction:column}.docusaurus-mt-lg{margin-top:3rem}#__docusaurus{display:flex;flex-direction:column;min-height:100%}.container_bfhl{align-items:center;background-image:url(/website/assets/images/top-bg-907106b795294aa3d5e4cbb0e9c2bad5.svg);background-position:50%;background-size:cover;display:flex;flex:1;height:690px!important;margin:0 80px;max-width:1800px;padding:0!important;width:100%}.heroBanner_qdFl{background-color:#f8f9fc;margin-bottom:100px;overflow:hidden;position:relative;text-align:center}.button1_OX1t{background-color:#3b54e0;border:none;border-radius:25px;color:#fff!important;margin-bottom:65px}.iconStar_WCul{border-radius:0!important;border-right:1px solid #d1d5d7}.starNum_QxJd{color:#000;display:inline-block;font-size:14px;text-align:center;width:55px}.heroTitle_qg2I{color:#000;font-size:50px;margin-bottom:20px}.heroText_ryRM{color:#626262;font-size:16px;font-weight:700;margin-bottom:40px;width:475px}.headerLeft_DBKD{height:613px;padding:130px 70px 30px 0;text-align:left;width:50%}.topImg_oKWx{display:block;max-height:530px;max-width:100%}.headerDes_Qvmc{color:#414141;font-size:16px}.featureTitle_Xf3m,.featureTitle__pTw{font-size:40px;color:#333;font-family:PingFangSC-Semibold;font-weight:600}.headerDesInfo_x7U0{margin-bottom:10px}.mainContainer_mA9m{display:flex;flex-direction:column;justify-content:space-between}.star_elzc{margin-bottom:5px}.featuresText_eVJS{display:flex;height:535px;justify-content:space-between;margin:0 80px;max-width:1800px;width:100%}.rigthInfo_KVv9{display:flex;flex-direction:column;justify-content:center;margin-right:30px;width:50%}.leftInfo_cdZ5{margin-right:150px;width:50%}.containerView_M7QC,.features_xdhU{display:flex;justify-content:center}.featureTitle__pTw{margin-bottom:20px}.featuresDes_VkbC{max-width:415px}.featuresContainer_wvSy{margin:80px 80px 40px;max-width:1800px;width:100%}.featureTitle_Xf3m{margin-bottom:40px;position:relative}.titleBg_pq9t{height:100px;left:170px;position:absolute;top:0;z-index:-1}.featureText_v8dk{display:flex;flex-direction:column;height:100px;justify-content:flex-end;margin-bottom:10px;width:270px}.line_gRrf{border-bottom:5px solid #3355e9;margin:0 0 20px 5px;width:55px}.featureItemLeft_j4hF{align-items:flex-start;background-color:#f9fbff;border-radius:30px;display:flex;justify-content:space-between;margin-bottom:85px;position:relative;width:100%}.featureItemRight_HONX{flex-direction:row-reverse}.featureDes_FHkX{align-items:left;display:flex;flex:1;flex-direction:column;justify-content:center;margin-bottom:30px;margin-left:45px;padding-top:30px;z-index:1}.featureItemRight_HONX .featureDes_FHkX{align-items:flex-end;margin-right:45px}.featureItemRight_HONX .featureDesTitle_NLsR{width:55%}.featureArrangeImg_KtM9{height:400px;position:absolute;right:0;top:50%;transform:translateY(-50%)}.featureDispatchImg_eSBL{left:0}.featureDispatchImg_eSBL,.featureNetworkImg_Z2mW{height:440px;position:absolute;top:50%;transform:translateY(-50%)}.featureNetworkImg_Z2mW{right:0}.featureImg_IxXR{height:100%;width:100%}.featureDesTitle_NLsR{color:#333;font-size:32px;margin-bottom:5px}.featureDesInfo_ytRY,.featureDesTitle_NLsR{font-family:PingFangSC-Semibold;font-weight:600}.featureDesInfo_ytRY{color:#626262;line-height:22px}.buttonGroup__atx button,.codeBlockContainer_Ckt0{background:var(--prism-background-color);color:var(--prism-color)}.featureDesDetails_Zud9,.featureDesInfo_ytRY{font-size:16px;max-width:55%}.codeBlockContainer_Ckt0{border-radius:var(--ifm-code-border-radius);box-shadow:var(--ifm-global-shadow-lw);margin-bottom:var(--ifm-leading)}.codeBlockContent_biex{border-radius:inherit;direction:ltr;position:relative}.codeBlockTitle_Ktv7{border-bottom:1px solid var(--ifm-color-emphasis-300);border-top-left-radius:inherit;border-top-right-radius:inherit;font-size:var(--ifm-code-font-size);font-weight:500;padding:.75rem var(--ifm-pre-padding)}.codeBlock_bY9V{--ifm-pre-background:var(--prism-background-color);margin:0;padding:0}.codeBlockTitle_Ktv7+.codeBlockContent_biex .codeBlock_bY9V{border-top-left-radius:0;border-top-right-radius:0}.codeBlockLines_e6Vv{float:left;font:inherit;min-width:100%;padding:var(--ifm-pre-padding)}.codeBlockLinesWithNumbering_o6Pm{display:table;padding:var(--ifm-pre-padding) 0}.buttonGroup__atx{column-gap:.2rem;display:flex;position:absolute;right:calc(var(--ifm-pre-padding)/2);top:calc(var(--ifm-pre-padding)/2)}.buttonGroup__atx button{align-items:center;border:1px solid var(--ifm-color-emphasis-300);border-radius:var(--ifm-global-radius);display:flex;line-height:0;opacity:0;padding:.4rem;transition:opacity var(--ifm-transition-fast) ease-in-out}.buttonGroup__atx button:focus-visible,.buttonGroup__atx button:hover{opacity:1!important}.theme-code-block:hover .buttonGroup__atx button{opacity:.4}:where(:root){--docusaurus-highlighted-code-line-bg:#484d5b}:where([data-theme=dark]){--docusaurus-highlighted-code-line-bg:#646464}.theme-code-block-highlighted-line{background-color:var(--docusaurus-highlighted-code-line-bg);display:block;margin:0 calc(var(--ifm-pre-padding)*-1);padding:0 var(--ifm-pre-padding)}.codeLine_lJS_{counter-increment:a;display:table-row}.codeLineNumber_Tfdd{background:var(--ifm-pre-background);display:table-cell;left:0;overflow-wrap:normal;padding:0 var(--ifm-pre-padding);position:sticky;text-align:right;width:1%}.codeLineNumber_Tfdd:before{content:counter(a);opacity:.4}.codeLineContent_feaV{padding-right:var(--ifm-pre-padding)}.theme-code-block:hover .copyButtonCopied_obH4{opacity:1!important}.copyButtonIcons_eSgA{height:1.125rem;position:relative;width:1.125rem}.copyButtonIcon_y97N,.copyButtonSuccessIcon_LjdS{fill:currentColor;height:inherit;left:0;opacity:inherit;position:absolute;top:0;transition:all var(--ifm-transition-fast) ease;width:inherit}.copyButtonSuccessIcon_LjdS{color:#00d600;left:50%;opacity:0;top:50%;transform:translate(-50%,-50%) scale(.33)}.copyButtonCopied_obH4 .copyButtonIcon_y97N{opacity:0;transform:scale(.33)}.copyButtonCopied_obH4 .copyButtonSuccessIcon_LjdS{opacity:1;transform:translate(-50%,-50%) scale(1);transition-delay:75ms}.wordWrapButtonIcon_Bwma{height:1.2rem;width:1.2rem}.details_lb9f{--docusaurus-details-summary-arrow-size:0.38rem;--docusaurus-details-transition:transform 200ms ease;--docusaurus-details-decoration-color:grey}.details_lb9f>summary{cursor:pointer;padding-left:1rem;position:relative}.details_lb9f>summary::-webkit-details-marker{display:none}.details_lb9f>summary:before{border-color:#0000 #0000 #0000 var(--docusaurus-details-decoration-color);border-style:solid;border-width:var(--docusaurus-details-summary-arrow-size);content:"";left:0;position:absolute;top:.45rem;transform:rotate(0);transform-origin:calc(var(--docusaurus-details-summary-arrow-size)/2) 50%;transition:var(--docusaurus-details-transition)}.collapsibleContent_i85q{border-top:1px solid var(--docusaurus-details-decoration-color);margin-top:1rem;padding-top:1rem}.details_b_Ee{--docusaurus-details-decoration-color:var(--ifm-alert-border-color);--docusaurus-details-transition:transform var(--ifm-transition-fast) ease;border:1px solid var(--ifm-alert-border-color);margin:0 0 var(--ifm-spacing-vertical)}.img_ev3q{height:auto}.tableOfContents_bqdL{max-height:calc(100vh - var(--ifm-navbar-height) - 2rem);overflow-y:auto;position:sticky;top:calc(var(--ifm-navbar-height) + 1rem)}.admonition_xJq3{margin-bottom:1em}.admonitionHeading_Gvgb{font:var(--ifm-heading-font-weight) var(--ifm-h5-font-size)/var(--ifm-heading-line-height) var(--ifm-heading-font-family)}.admonitionHeading_Gvgb:not(:last-child){margin-bottom:.3rem}.admonitionHeading_Gvgb code{text-transform:none}.admonitionIcon_Rf37{display:inline-block;margin-right:.4em;vertical-align:middle}.admonitionIcon_Rf37 svg{fill:var(--ifm-alert-foreground-color);display:inline-block;height:1.6em;width:1.6em}.breadcrumbHomeIcon_YNFT{height:1.1rem;position:relative;top:1px;vertical-align:top;width:1.1rem}.breadcrumbsContainer_Z_bl{--ifm-breadcrumb-size-multiplier:0.8;margin-bottom:.8rem}@media (min-width:640px){.container{max-width:640px}.sm-hidden{display:none!important}.z-input,.z-textarea{font-size:.875rem;line-height:1.5rem}}@media (min-width:768px){.container{max-width:768px}}@media (min-width:997px){.collapseSidebarButton_PEFL,.expandButton_TmdG{background-color:var(--docusaurus-collapse-button-bg)}.lastUpdated_vwxv{text-align:right}.tocMobile_ITEo{display:none}:root{--docusaurus-announcement-bar-height:30px}.announcementBarClose_gvF7,.announcementBarPlaceholder_vyr4{flex-basis:50px}.collapseSidebarButton_PEFL{border:1px solid var(--ifm-toc-border-color);border-radius:0;bottom:0;display:block!important;height:40px;position:sticky}.collapseSidebarButtonIcon_kv0_{margin-top:4px;transform:rotate(180deg)}.expandButtonIcon_i1dp,[dir=rtl] .collapseSidebarButtonIcon_kv0_{transform:rotate(0)}.collapseSidebarButton_PEFL:focus,.collapseSidebarButton_PEFL:hover,.expandButton_TmdG:focus,.expandButton_TmdG:hover{background-color:var(--docusaurus-collapse-button-bg-hover)}.menuHtmlItem_M9Kj{padding:var(--ifm-menu-link-padding-vertical) var(--ifm-menu-link-padding-horizontal)}.menu_SIkG{flex-grow:1;padding:.5rem}@supports (scrollbar-gutter:stable){.menu_SIkG{padding:.5rem 0 .5rem .5rem;scrollbar-gutter:stable}}.menuWithAnnouncementBar_GW3s{margin-bottom:var(--docusaurus-announcement-bar-height)}.sidebar_njMd{display:flex;flex-direction:column;height:100%;padding-top:var(--ifm-navbar-height);width:var(--doc-sidebar-width)}.sidebarWithHideableNavbar_wUlq{padding-top:0}.sidebarHidden_VK0M{opacity:0;visibility:hidden}.sidebarLogo_isFc{align-items:center;color:inherit!important;display:flex!important;margin:0 var(--ifm-navbar-padding-horizontal);max-height:var(--ifm-navbar-height);min-height:var(--ifm-navbar-height);text-decoration:none!important}.sidebarLogo_isFc img{height:2rem;margin-right:.5rem}.expandButton_TmdG{align-items:center;display:flex;height:100%;justify-content:center;position:absolute;right:0;top:0;transition:background-color var(--ifm-transition-fast) ease;width:100%}[dir=rtl] .expandButtonIcon_i1dp{transform:rotate(180deg)}.docSidebarContainer_YfHR{border-right:1px solid var(--ifm-toc-border-color);-webkit-clip-path:inset(0);clip-path:inset(0);display:block;margin-top:calc(var(--ifm-navbar-height)*-1);transition:width var(--ifm-transition-fast) ease;width:var(--doc-sidebar-width);will-change:width}.docSidebarContainerHidden_DPk8{cursor:pointer;width:var(--doc-sidebar-hidden-width)}.sidebarViewport_aRkj{height:100%;max-height:100vh;position:sticky;top:0}.docMainContainer_TBSr{flex-grow:1;max-width:calc(100% - var(--doc-sidebar-width))}.docMainContainerEnhanced_lQrH{max-width:calc(100% - var(--doc-sidebar-hidden-width))}.docItemWrapperEnhanced_JWYK{max-width:calc(var(--ifm-container-width) + var(--doc-sidebar-width))!important}.navbarSearchContainer_Bca1{padding:var(--ifm-navbar-item-padding-vertical) var(--ifm-navbar-item-padding-horizontal)}.docItemCol_VOVn{max-width:75%!important}}@media (min-width:1024px){.container{max-width:1024px}}@media (min-width:1280px){.container{max-width:1280px}}@media (min-width:1440px){.container{max-width:var(--ifm-container-width-xl)}}@media (min-width:1536px){.container{max-width:1536px}}@media (max-width:996px){.col{--ifm-col-width:100%;flex-basis:var(--ifm-col-width);margin-left:0}.footer{--ifm-footer-padding-horizontal:0}.colorModeToggle_DEke,.footer__link-separator,.navbar__item,.tableOfContents_bqdL{display:none}.footer__col{margin-bottom:calc(var(--ifm-spacing-vertical)*3)}.footer__link-item{display:block}.hero{padding-left:0;padding-right:0}.navbar>.container,.navbar>.container-fluid{padding:0}.navbar__toggle{display:inherit}.navbar__search-input{width:9rem}.pills--block,.tabs--block{flex-direction:column}.navbarSearchContainer_Bca1{position:absolute;right:var(--ifm-navbar-padding-horizontal)}.docItemContainer_F8PC{padding:0 .3rem}}@media (max-width:576px){.markdown h1:first-child{--ifm-h1-font-size:2rem}.markdown>h2{--ifm-h2-font-size:1.5rem}.markdown>h3{--ifm-h3-font-size:1.25rem}}@media (hover:hover){.backToTopButton_sjWU:hover{background-color:var(--ifm-color-emphasis-300)}}@media (pointer:fine){.thin-scrollbar{scrollbar-width:thin}.thin-scrollbar::-webkit-scrollbar{height:var(--ifm-scrollbar-size);width:var(--ifm-scrollbar-size)}.thin-scrollbar::-webkit-scrollbar-track{background:var(--ifm-scrollbar-track-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb{background:var(--ifm-scrollbar-thumb-background-color);border-radius:10px}.thin-scrollbar::-webkit-scrollbar-thumb:hover{background:var(--ifm-scrollbar-thumb-hover-background-color)}}@media (prefers-reduced-motion:reduce){:root{--ifm-transition-fast:0ms;--ifm-transition-slow:0ms}}@media print{.announcementBar_mb4j,.footer,.menu,.navbar,.pagination-nav,.table-of-contents,.tocMobile_ITEo{display:none}.tabs{page-break-inside:avoid}.codeBlockLines_e6Vv{white-space:pre-wrap}} \ No newline at end of file diff --git a/docs/assets/images/Kosmos_Admission_Webhook-6f617f75916da415e7547e6a4d827971.png b/docs/assets/images/Kosmos_Admission_Webhook-6f617f75916da415e7547e6a4d827971.png new file mode 100644 index 0000000..356d1ac Binary files /dev/null and b/docs/assets/images/Kosmos_Admission_Webhook-6f617f75916da415e7547e6a4d827971.png differ diff --git a/docs/assets/images/Kubenest-Architecture-f1051d9ace44d72e36fd9cc4320ea472.png b/docs/assets/images/Kubenest-Architecture-f1051d9ace44d72e36fd9cc4320ea472.png deleted file mode 100644 index 585a586..0000000 Binary files a/docs/assets/images/Kubenest-Architecture-f1051d9ace44d72e36fd9cc4320ea472.png and /dev/null differ diff --git a/docs/assets/images/Kubenest-CR-89640795b8f4fc975d23979a6001e026.png b/docs/assets/images/Kubenest-CR-89640795b8f4fc975d23979a6001e026.png deleted file mode 100644 index 8dec916..0000000 Binary files a/docs/assets/images/Kubenest-CR-89640795b8f4fc975d23979a6001e026.png and /dev/null differ diff --git a/docs/assets/images/Kubenest-NodeAgent-Flowchart-7466545901ee24ebd28263f70d88b3b7.png b/docs/assets/images/Kubenest-NodeAgent-Flowchart-7466545901ee24ebd28263f70d88b3b7.png deleted file mode 100644 index e9c637a..0000000 Binary files a/docs/assets/images/Kubenest-NodeAgent-Flowchart-7466545901ee24ebd28263f70d88b3b7.png and /dev/null differ diff --git a/docs/assets/images/Kubenest-Solution-Overview-58deb68e8e2ff8482b98a2e65a43eb2e.png b/docs/assets/images/Kubenest-Solution-Overview-58deb68e8e2ff8482b98a2e65a43eb2e.png deleted file mode 100644 index 9252b53..0000000 Binary files a/docs/assets/images/Kubenest-Solution-Overview-58deb68e8e2ff8482b98a2e65a43eb2e.png and /dev/null differ diff --git a/docs/assets/images/cluster-deploy-90f1f30f5decda82585865e924e8a598.jpg b/docs/assets/images/cluster-deploy-90f1f30f5decda82585865e924e8a598.jpg deleted file mode 100644 index e32e7a8..0000000 Binary files a/docs/assets/images/cluster-deploy-90f1f30f5decda82585865e924e8a598.jpg and /dev/null differ diff --git a/docs/assets/images/mutaing_api_latency-748ec7f610d0c8c7cf2b6e180f3505f0.jpg b/docs/assets/images/mutaing_api_latency-748ec7f610d0c8c7cf2b6e180f3505f0.jpg deleted file mode 100644 index 7a9c702..0000000 Binary files a/docs/assets/images/mutaing_api_latency-748ec7f610d0c8c7cf2b6e180f3505f0.jpg and /dev/null differ diff --git a/docs/assets/images/readonly_api_latency-f224e93b2e2060c911df88a18aa39a46.jpg b/docs/assets/images/readonly_api_latency-f224e93b2e2060c911df88a18aa39a46.jpg deleted file mode 100644 index ba3274d..0000000 Binary files a/docs/assets/images/readonly_api_latency-f224e93b2e2060c911df88a18aa39a46.jpg and /dev/null differ diff --git a/docs/assets/images/readonly_api_latency30-cc2f0ae0beea51845ecc79fd8b1b420b.jpg b/docs/assets/images/readonly_api_latency30-cc2f0ae0beea51845ecc79fd8b1b420b.jpg deleted file mode 100644 index ba29ff8..0000000 Binary files a/docs/assets/images/readonly_api_latency30-cc2f0ae0beea51845ecc79fd8b1b420b.jpg and /dev/null differ diff --git a/docs/assets/images/readonly_api_latency5-0b671cdc723d4d232c034de05f6f5284.jpg b/docs/assets/images/readonly_api_latency5-0b671cdc723d4d232c034de05f6f5284.jpg deleted file mode 100644 index 4bb463e..0000000 Binary files a/docs/assets/images/readonly_api_latency5-0b671cdc723d4d232c034de05f6f5284.jpg and /dev/null differ diff --git a/docs/assets/js/1f271e39.15ae0175.js b/docs/assets/js/1f271e39.15ae0175.js deleted file mode 100644 index 68bd70c..0000000 --- a/docs/assets/js/1f271e39.15ae0175.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[192],{3224:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>c,default:()=>m,frontMatter:()=>l,metadata:()=>i,toc:()=>t});var s=r(7624),o=r(2172);const l={id:"mc-scheduler_zh",title:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668"},c="\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668",i={id:"i18n/zh/v0.2.0/mc-scheduler_zh",title:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668",description:"\u5f53 Kosmos \u52a0\u5165\u4e00\u4e2a\u6210\u5458\u96c6\u7fa4\u540e\uff0c\u5b83\u4f1a\u6620\u5c04\u4e00\u4e2a\u5e26\u6709 kosmos.io/node=true:Noschedule \u6c61\u70b9\u7684\u865a\u62df\u8282\u70b9\uff0c\u56e0\u6b64 Kubernetes \u9ed8\u8ba4\u8c03\u5ea6\u5668\u65e0\u6cd5\u5c06 Pod \u8c03\u5ea6\u5230\u8be5\u865a\u62df\u8282\u70b9\uff08\u5373\u6210\u5458\u96c6\u7fa4\uff09\u4e0a\u3002",source:"@site/docs/i18n/zh/v0.2.0/multi-cluster-scheduler_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/mc-scheduler_zh",permalink:"/website/i18n/zh/v0.2.0/mc-scheduler_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/multi-cluster-scheduler_zh.md",tags:[],version:"current",frontMatter:{id:"mc-scheduler_zh",title:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668"}},d={},t=[{value:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668\u89e3\u51b3\u65b9\u6848",id:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668\u89e3\u51b3\u65b9\u6848",level:2},{value:"\u7b80\u4ecb",id:"\u7b80\u4ecb",level:3},{value:"\u5148\u51b3\u6761\u4ef6",id:"\u5148\u51b3\u6761\u4ef6",level:3},{value:"\u5b89\u88c5 Kosmos",id:"\u5b89\u88c5-kosmos",level:4},{value:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4",id:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4",level:4},{value:"\u90e8\u7f72 Kosmos-scheduler",id:"\u90e8\u7f72-kosmos-scheduler",level:3},{value:"\u793a\u4f8b",id:"\u793a\u4f8b",level:4},{value:"\u7ed3\u8bba",id:"\u7ed3\u8bba",level:3}];function a(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,o.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668",children:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668"}),"\n",(0,s.jsxs)(n.p,{children:["\u5f53 Kosmos \u52a0\u5165\u4e00\u4e2a\u6210\u5458\u96c6\u7fa4\u540e\uff0c\u5b83\u4f1a\u6620\u5c04\u4e00\u4e2a\u5e26\u6709 ",(0,s.jsx)(n.code,{children:"kosmos.io/node=true:Noschedule"})," \u6c61\u70b9\u7684\u865a\u62df\u8282\u70b9\uff0c\u56e0\u6b64 Kubernetes \u9ed8\u8ba4\u8c03\u5ea6\u5668\u65e0\u6cd5\u5c06 Pod \u8c03\u5ea6\u5230\u8be5\u865a\u62df\u8282\u70b9\uff08\u5373\u6210\u5458\u96c6\u7fa4\uff09\u4e0a\u3002\r\n\u90e8\u7f72 kosmos-scheduler \u540e\uff0c\u7528\u6237\u53ef\u4ee5\u901a\u8fc7 kosmos-scheduler \u4e2d\u7684 ",(0,s.jsx)(n.code,{children:"LeafNodeTaintToleration"})," \u8c03\u5ea6\u63d2\u4ef6\u5bb9\u5fcd ",(0,s.jsx)(n.code,{children:"kosmos.io/node=true:Noschedule"})," \u6c61\u70b9\uff0c\u4ece\u800c\u5b9e\u73b0\u6210\u5458\u96c6\u7fa4\u548c\u4e3b\u673a\u96c6\u7fa4\u8282\u70b9\u4e4b\u95f4\u7684\u6df7\u5408\u8c03\u5ea6\u6548\u679c\u3002"]}),"\n",(0,s.jsxs)(n.p,{children:["\u5bf9\u4e8e\u5e26\u6709 PV/PVC \u7684 Pod\uff0c\u8fd8\u9700\u5728 kosmos-scheduler \u4e2d\u914d\u7f6e ",(0,s.jsx)(n.code,{children:"LeafNodeVolumeBinding"})," \u8c03\u5ea6\u63d2\u4ef6\uff0c\u4ee5\u5728\u5b58\u50a8\u5377\u7ed1\u5b9a\u8fc7\u7a0b\u4e2d\u76f4\u63a5\u4f7f\u7528\u5e26\u6709 ",(0,s.jsx)(n.code,{children:"kosmos.io/node=true:Noschedule"})," \u6c61\u70b9\u7684\u865a\u62df\u8282\u70b9\u3002"]}),"\n",(0,s.jsxs)(n.p,{children:["\u9700\u8981\u6ce8\u610f\u7684\u662f\uff0c\u5bf9\u4e8e\u4e0d\u540c\u7248\u672c\u7684 Kubernetes\uff0c\u53d1\u5e03\u7684\u9ed8\u8ba4\u8c03\u5ea6\u5668\u6240\u4f9d\u8d56\u7684\u8c03\u5ea6\u6a21\u5757\uff08\u8c03\u5ea6\u6846\u67b6\uff09\u4e5f\u4f1a\u968f\u7248\u672c\u53d8\u5316\u800c\u53d8\u5316\u3002\u76ee\u524d\uff0cKosmos \u5df2\u9002\u914d\u4e86\u4e24\u4e2a\u7248\u672c\uff08",(0,s.jsx)(n.code,{children:"release-1.21.5"})," \u548c ",(0,s.jsx)(n.code,{children:"release-1.26.3"}),"\uff09\u3002\u4ee5\u4e0b\u9a8c\u8bc1\u90e8\u5206\u5c06\u4f7f\u7528 ",(0,s.jsx)(n.code,{children:"release-1.21.5"})," \u8fdb\u884c\u90e8\u7f72\u548c\u6d4b\u8bd5\u3002"]}),"\n",(0,s.jsx)(n.h2,{id:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668\u89e3\u51b3\u65b9\u6848",children:"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668\u89e3\u51b3\u65b9\u6848"}),"\n",(0,s.jsx)(n.h3,{id:"\u7b80\u4ecb",children:"\u7b80\u4ecb"}),"\n",(0,s.jsxs)(n.p,{children:["\u8c03\u5ea6\u5668\u6846\u67b6\u6700\u521d\u901a\u8fc7 Kubernetes \u589e\u5f3a\u63d0\u6848\u4e2d\u7684 ",(0,s.jsx)(n.a,{href:"https://link.zhihu.com/?target=https%3A//github.com/kubernetes/enhancements/tree/master/keps/sig-scheduling/624-scheduling-framework",children:"624-scheduling-framework"})," \u63d0\u6848\u5f15\u5165\uff0c\u4e3b\u8981\u5b9e\u73b0\u4ee5\u4e0b\u76ee\u6807\uff1a"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\u4f7f\u8c03\u5ea6\u5668\u66f4\u52a0\u53ef\u6269\u5c55\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u901a\u8fc7\u5c06\u4e00\u4e9b\u529f\u80fd\u79fb\u81f3\u63d2\u4ef6\uff0c\u4f7f\u8c03\u5ea6\u5668\u6838\u5fc3\u66f4\u7b80\u5355\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5728\u6846\u67b6\u4e2d\u63d0\u51fa\u6269\u5c55\u70b9\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u63d0\u51fa\u6839\u636e\u6536\u5230\u7684\u7ed3\u679c\u7ee7\u7eed\u6216\u4e2d\u6b62\u7684\u63d2\u4ef6\u7ed3\u679c\u63a5\u6536\u673a\u5236\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u63d0\u51fa\u5904\u7406\u9519\u8bef\u5e76\u5c06\u5176\u4e0e\u63d2\u4ef6\u901a\u4fe1\u7684\u673a\u5236\u3002"}),"\n"]}),"\n",(0,s.jsxs)(n.p,{children:["\u4e3a\u6b64\uff0c\u8c03\u5ea6\u5668\u6846\u67b6\u5b9a\u4e49\u4e86\u591a\u4e2a\u6269\u5c55\u70b9\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a\r\n",(0,s.jsx)(n.img,{alt:"MC_Scheduler.png",src:r(5900).c+"",width:"1366",height:"613"})]}),"\n",(0,s.jsxs)(n.p,{children:["kosmos-scheduler \u4e2d\u7684 ",(0,s.jsx)(n.code,{children:"LeafNodeTaintToleration"})," \u548c ",(0,s.jsx)(n.code,{children:"LeafNodeVolumeBinding"})," \u8c03\u5ea6\u63d2\u4ef6\u4e3b\u8981\u662f\u57fa\u4e8e Kubernetes \u9ed8\u8ba4\u8c03\u5ea6\u5668\u7684 ",(0,s.jsx)(n.code,{children:"NodeTaintToleration"})," \u548c ",(0,s.jsx)(n.code,{children:"NodeVolumeBinding"})," \u8c03\u5ea6\u63d2\u4ef6\u8fdb\u884c\u4f18\u5316\u7684\u3002\r\n",(0,s.jsx)(n.code,{children:"LeafNodeTaintToleration"})," \u63d2\u4ef6\u4e3b\u8981\u5728 ",(0,s.jsx)(n.code,{children:"Filter"})," \u6269\u5c55\u70b9\u4e2d\u4e3a\u865a\u62df\u8282\u70b9\u4e0a\u7684 ",(0,s.jsx)(n.code,{children:"kosmos.io/node=true:Noschedule"})," \u6c61\u70b9\u6dfb\u52a0\u5bb9\u5fcd\u3002\r\n",(0,s.jsx)(n.code,{children:"LeafNodeVolumeBinding"})," \u63d2\u4ef6\u4e3b\u8981\u5728 ",(0,s.jsx)(n.code,{children:"Filter"}),"\u3001",(0,s.jsx)(n.code,{children:"Reserve"}),"\u3001",(0,s.jsx)(n.code,{children:"Unreserved"})," \u548c ",(0,s.jsx)(n.code,{children:"PreBind"})," \u6269\u5c55\u70b9\u4e0a\u8d77\u4f5c\u7528\uff0c\u5e76\u76f4\u63a5\u4f20\u9012\u5e26\u6709 ",(0,s.jsx)(n.code,{children:"kosmos.io/node=true:Noschedule"})," \u6c61\u70b9\u7684\u865a\u62df\u8282\u70b9\u3002"]}),"\n",(0,s.jsx)(n.h3,{id:"\u5148\u51b3\u6761\u4ef6",children:"\u5148\u51b3\u6761\u4ef6"}),"\n",(0,s.jsx)(n.h4,{id:"\u5b89\u88c5-kosmos",children:"\u5b89\u88c5 Kosmos"}),"\n",(0,s.jsxs)(n.p,{children:["\u53c2\u8003 Kosmos \u5feb\u901f\u5165\u95e8\u6587\u6863 ",(0,s.jsx)(n.a,{href:"https://github.com/kosmos-io/kosmos",children:"https://github.com/kosmos-io/kosmos"})," \u5e76\u4e3a\u591a\u96c6\u7fa4\u7f51\u7edc\u542f\u7528 ClusterLink \u6a21\u5757\u3002\u4f7f\u7528 kosmosctl \u5de5\u5177\uff1a"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"kosmosctl install --cni calico --default-nic eth0 // \u6211\u4eec\u57fa\u4e8e\u4f20\u9012\u7684\u7f51\u7edc\u63a5\u53e3\u503c\u6784\u5efa\u7f51\u7edc\u96a7\u9053\n"})}),"\n",(0,s.jsx)(n.admonition,{title:"\u63d0\u793a",type:"info",children:(0,s.jsx)(n.p,{children:"\u81f3\u5c11\u90e8\u7f72 clustertree \u6a21\u5757\u5e76\u6b63\u786e\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4\u3002"})}),"\n",(0,s.jsx)(n.h4,{id:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4",children:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"kosmosctl join cluster --name cluster1 --kubeconfig ~/kubeconfig/cluster1-kubeconfig --cni calico --default-nic eth0 --enable-link\n"})}),"\n",(0,s.jsx)(n.h3,{id:"\u90e8\u7f72-kosmos-scheduler",children:"\u90e8\u7f72 Kosmos-scheduler"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"\u914d\u7f6e\u8c03\u5ea6\u5668\u548c\u8c03\u5ea6\u7b56\u7565\uff1a"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:'---\r\n# kosmos-scheduler \u8c03\u5ea6\u7b56\u7565\r\napiVersion: v1\r\nkind: ConfigMap\r\nmetadata:\r\n name: scheduler-config\r\n namespace: kosmos-system\r\ndata:\r\n scheduler-config.yaml: |\r\n apiVersion: kubescheduler.config.k8s.io/v1beta1\r\n kind: KubeSchedulerConfiguration\r\n leaderElection:\r\n leaderElect: true\r\n resourceName: kosmos-scheduler\r\n resourceNamespace: kosmos-system\r\n profiles:\r\n - schedulerName: kosmos-scheduler\r\n plugins:\r\n preFilter:\r\n disabled:\r\n - name: "VolumeBinding"\r\n enabled:\r\n - name: "LeafNodeVolumeBinding"\r\n filter:\r\n disabled:\r\n - name: "VolumeBinding"\r\n - name: "TaintToleration"\r\n enabled:\r\n - name: "LeafNodeTaintToleration"\r\n - name: "LeafNodeVolumeBinding"\r\n score:\r\n disabled:\r\n - name: "VolumeBinding"\r\n reserve:\r\n disabled:\r\n - name: "VolumeBinding"\r\n enabled:\r\n - name: "LeafNodeVolumeBinding"\r\n preBind:\r\n disabled:\r\n - name: "VolumeBinding"\r\n enabled:\r\n - name: "LeafNodeVolumeBinding"\r\n pluginConfig:\r\n - name: LeafNodeVolumeBinding\r\n args:\r\n bindTimeoutSeconds: 5\r\n---\r\n# \u8c03\u5ea6\u5668\u914d\u7f6e\r\napiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: kosmos-scheduler\r\n namespace: kosmos-system\r\n labels:\r\n component: scheduler\r\nspec:\r\n replicas: 1\r\n selector:\r\n matchLabels:\r\n component: scheduler\r\n template:\r\n metadata:\r\n labels:\r\n component: scheduler\r\n spec:\r\n volumes:\r\n - name: scheduler-config\r\n configMap:\r\n name: scheduler-config\r\n defaultMode: 420\r\n containers:\r\n - name: kosmos-scheduler\r\n image: ghcr.io/kosmos-io/scheduler:0.0.2\r\n command:\r\n - scheduler\r\n - --config=/etc/kubernetes/kube-scheduler/scheduler-config.yaml\r\n resources:\r\n requests:\r\n cpu: 200m\r\n volumeMounts:\r\n - name: scheduler-config\r\n readOnly: true\r\n mountPath: /etc/kubernetes/kube-scheduler\r\n livenessProbe:\r\n httpGet:\r\n path: /healthz\r\n port: 10259\r\n scheme: HTTPS\r\n initialDelaySeconds: 15\r\n periodSeconds: 10\r\n failureThreshold: 3\r\n readinessProbe:\r\n httpGet:\r\n path: /healthz\r\n port: 10259\r\n scheme: HTTPS\r\n restartPolicy: Always\r\n dnsPolicy: ClusterFirst\r\n serviceAccountName: kosmos-scheduler\r\n serviceAccount: kosmos-scheduler\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"2",children:["\n",(0,s.jsx)(n.li,{children:"\u9a8c\u8bc1 kosmos-scheduler \u670d\u52a1\uff1a"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# \u521b\u5efa kosmos-scheduler\r\nkubectl -n kosmos-system get pod\r\nNAME READY STATUS RESTARTS AGE\r\nkosmos-scheduler-8f96d87d7-ssxrx 1/1 Running 0 24s\n"})}),"\n",(0,s.jsx)(n.h4,{id:"\u793a\u4f8b",children:"\u793a\u4f8b"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"\u5728\u6d4b\u8bd5\u96c6\u7fa4\u4e0a\u90e8\u7f72 openebs"}),"\n"]}),"\n",(0,s.jsxs)(n.li,{children:["\n",(0,s.jsx)(n.p,{children:"\u4f7f\u7528\u6848\u4f8b yaml\uff08mysql-cluster.yaml\uff09"}),"\n"]}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:'apiVersion: v1\r\nkind: Secret\r\nmetadata:\r\n namespace: test-mysql\r\n name: my-secret\r\ntype: Opaque\r\ndata:\r\n # \u9700\u8981\u6307\u5b9a root \u5bc6\u7801\r\n ROOT_PASSWORD: ${your_password}\r\n ## \u5728\u96c6\u7fa4\u542f\u52a8\u65f6\u521b\u5efa\u7684\u5e94\u7528\u51ed\u636e\r\n # DATABASE:\r\n # USER:\r\n # PASSWORD:\r\n---\r\nkind: MysqlCluster\r\nmetadata:\r\n name: test-mysql-cluster\r\n namespace: test-mysql\r\nspec:\r\n replicas: 2\r\n secretName: my-secret\r\n image: docker.io/percona:5.7\r\n mysqlVersion: "5.7"\r\n podSpec:\r\n affinity: \r\n podAntiAffinity:\r\n requiredDuringSchedulingIgnoredDuringExecution:\r\n - labelSelector:\r\n matchLabels:\r\n mysql.presslabs.org/cluster: test-mysql-cluster\r\n topologyKey: kubernetes.io/hostname\r\n volumeSpec:\r\n persistentVolumeClaim:\r\n storageClassName: openebs-hostpath\r\n accessModes:\r\n - ReadWriteOnce\r\n resources:\r\n requests:\r\n storage: 1Gi\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"3",children:["\n",(0,s.jsx)(n.li,{children:"\u64cd\u4f5c\u8bf4\u660e"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# \u663e\u793a\u4e3b\u673a\u96c6\u7fa4\u4e2d\u7684\u6240\u6709\u8282\u70b9\r\nkubectl get node\r\nNAME STATUS ROLES AGE VERSION\r\nkosmoscluster1-1 Ready control-plane,master,node 21d v1.21.5-eki.0\r\nkosmoscluster1-2 Ready node\r\n\r\n 21d v1.21.5-eki.0\r\nkosmos-member2-cluster-1 Ready agent 24m v1.21.5-eki.0\r\nkosmos-member2-cluster-2 Ready agent 24m v1.21.5-eki.0\r\n \r\n# \u663e\u793a\u865a\u62df\u8282\u70b9\u4e0a\u7684\u6c61\u70b9\u4fe1\u606f\r\nkubectl describe node kosmos-member2-cluster-1 |grep Tai\r\nTaints: node.kubernetes.io/unreachable:NoExecute\r\n \r\nkubectl describe node kosmos-member2-cluster-2 |grep Tai\r\nTaints: node.kubernetes.io/unreachable:NoExecute\r\n \r\n# \u4f7f\u7528 kosmos-scheduler \u8fdb\u884c\uff08\u6df7\u5408\uff09\u8c03\u5ea6\r\nkubectl apply -f mysql-cluster.yaml\r\n \r\n# \u5728\u4e3b\u673a\u96c6\u7fa4\u4e2d\u663e\u793a\u5b9e\u4f8b\uff08\u6df7\u5408\uff09\u8c03\u5ea6\u7ed3\u679c\r\nkubectl get pod -owide -n test-mysql\r\nNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES\r\ntest-mysql-cluster-mysql-0 4/4 Running 0 3m 2409:xxxxx:8ac kosmoscluster1-2 \r\ntest-mysql-cluster-mysql-1 4/4 Running 0 2m 2409:xxxxx:8ae kosmos-member2-cluster-1 \r\n\r\n# \u5728\u6210\u5458\u96c6\u7fa4\u4e2d\u663e\u793a\u5b9e\u4f8b\uff08\u6df7\u5408\uff09\u8c03\u5ea6\u7ed3\u679c\r\nkubectl get pod -owide -n test-mysql\r\nNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES\r\ntest-mysql-cluster-mysql-1 4/4 Running 0 2m 2409:xxxxx:8ae kosmos-member2-cluster-1 \n"})}),"\n",(0,s.jsx)(n.h3,{id:"\u7ed3\u8bba",children:"\u7ed3\u8bba"}),"\n",(0,s.jsx)(n.p,{children:"\u53ef\u4ee5\u770b\u5230\uff0ckosmos-scheduler \u6210\u529f\u5c06\u7528\u6237\u5b9e\u4f8b\u7684 Pod \u8c03\u5ea6\u5230\u4e86\u4e3b\u673a\u96c6\u7fa4\u548c\u6210\u5458\u96c6\u7fa4\u4e2d\u3002"})]})}function m(e={}){const{wrapper:n}={...(0,o.M)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},5900:(e,n,r)=>{r.d(n,{c:()=>s});const s=r.p+"assets/images/MC_Scheduler-4e0d264782f68e38b5d41dc36731c7fe.png"},2172:(e,n,r)=>{r.d(n,{I:()=>i,M:()=>c});var s=r(1504);const o={},l=s.createContext(o);function c(e){const n=s.useContext(l);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function i(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/32d4be63.69eecc3a.js b/docs/assets/js/32d4be63.69eecc3a.js deleted file mode 100644 index 5f004bb..0000000 --- a/docs/assets/js/32d4be63.69eecc3a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[428],{5480:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>d,contentTitle:()=>l,default:()=>h,frontMatter:()=>i,metadata:()=>c,toc:()=>o});var n=t(7624),r=t(2172);const i={id:"performance-testing",title:"Kosmos Performance Testing"},l="Kosmos Performance Testing",c={id:"v0.2.0/proposals/performance-testing",title:"Kosmos Performance Testing",description:"Network Performance Testing",source:"@site/docs/v0.2.0/proposals/performance_testing.md",sourceDirName:"v0.2.0/proposals",slug:"/v0.2.0/proposals/performance-testing",permalink:"/website/v0.2.0/proposals/performance-testing",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/proposals/performance_testing.md",tags:[],version:"current",frontMatter:{id:"performance-testing",title:"Kosmos Performance Testing"},sidebar:"tutorialSidebar",previous:{title:"Leaf Node Generate Rules",permalink:"/website/v0.2.0/proposals/leaf-node-generate-rules"}},d={},o=[{value:"Network Performance Testing",id:"network-performance-testing",level:2},{value:"Large scale cluster performance testing",id:"large-scale-cluster-performance-testing",level:2},{value:"Performance indicators",id:"performance-indicators",level:4},{value:"Testing tools and test cases",id:"testing-tools-and-test-cases",level:4},{value:"1. ClusterLoader2",id:"1-clusterloader2",level:5},{value:"2. Kwok",id:"2-kwok",level:5},{value:"3. Test cases",id:"3-test-cases",level:5},{value:"4. Test clusters deploy architecture",id:"4-test-clusters-deploy-architecture",level:5},{value:"Testing environment detail",id:"testing-environment-detail",level:4},{value:"1. OS version",id:"1-os-version",level:5},{value:"2. Master node",id:"2-master-node",level:5},{value:"3. Component configuration",id:"3-component-configuration",level:5},{value:"Test Results",id:"test-results",level:4},{value:"2. Pod Startup Latency",id:"2-pod-startup-latency",level:5},{value:"Conclusion and Analysis",id:"conclusion-and-analysis",level:4}];function a(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h4:"h4",h5:"h5",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",ul:"ul",...(0,r.M)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"kosmos-performance-testing",children:"Kosmos Performance Testing"}),"\n",(0,n.jsx)(s.h2,{id:"network-performance-testing",children:"Network Performance Testing"}),"\n",(0,n.jsx)(s.p,{children:"The target of Kosmos networking is to establish connectivity between multiple Kubernetes clusters. This module can be deployed and used independently. In this document, we do performance testing on cross-cluster pod."}),"\n",(0,n.jsx)(s.p,{children:"Bandwidth and latency are two import performance metrics. For bandwidth, we used iperf3 for testing, while ping was used to measure latency."}),"\n",(0,n.jsx)(s.p,{children:"The test environment consisted of three physical machines. Among these physical machines, two nodes on same subnet were deployed as a k8s cluster, and the other node on another subnet was separately deployed a k8s cluster. We established overley pod network connectivity between the two clusters using Kosmos."}),"\n",(0,n.jsx)(s.p,{children:"environment\uff1a"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["\n",(0,n.jsxs)(s.p,{children:["kubernetes: ",(0,n.jsx)(s.code,{children:"v1.21.5"})]}),"\n"]}),"\n",(0,n.jsxs)(s.li,{children:["\n",(0,n.jsxs)(s.p,{children:["OS: ",(0,n.jsx)(s.code,{children:"BigCloud Enterprise Linux For Euler release 21.10 (LTS-SP2)"})]}),"\n"]}),"\n",(0,n.jsxs)(s.li,{children:["\n",(0,n.jsxs)(s.p,{children:["kernel: ",(0,n.jsx)(s.code,{children:"4.19.90-2107.6.0.0192.8.oe1.bclinux.x86_64"})]}),"\n"]}),"\n",(0,n.jsxs)(s.li,{children:["\n",(0,n.jsxs)(s.p,{children:["calico: ",(0,n.jsx)(s.code,{children:"v3.23.2"})]}),"\n"]}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:"result\uff1a"}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Test scenario"}),(0,n.jsx)(s.th,{children:"bandwidth"}),(0,n.jsx)(s.th,{children:"latency"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"physical machines in same cluster"}),(0,n.jsx)(s.td,{children:"9.37 Gbits/sec"}),(0,n.jsx)(s.td,{children:"0.091550ms"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"kubernetes overlay network\uff08calico bgp)"}),(0,n.jsx)(s.td,{children:"8.15 Gbits/sec"}),(0,n.jsx)(s.td,{children:"0.128268ms"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"kubernetes overlay network\uff08calico tunl0\uff09"}),(0,n.jsx)(s.td,{children:"6.34 Gbits/sec"}),(0,n.jsx)(s.td,{children:"0.170805ms"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"kubernetes overlay network\uff08calico vxlan\uff09"}),(0,n.jsx)(s.td,{children:"6.25 Gbits/sec"}),(0,n.jsx)(s.td,{children:"0.193439ms"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"physical machines in different cluster"}),(0,n.jsx)(s.td,{children:"9.35 Gbits/sec"}),(0,n.jsx)(s.td,{children:"0.108512ms"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"cross-cluster overlay network\uff08kosmos gateway\uff09"}),(0,n.jsx)(s.td,{children:"6.22 Gbits/sec"}),(0,n.jsx)(s.td,{children:"0.332878ms"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"cross-cluster overlay network\uff08kosmos p2p\uff09"}),(0,n.jsx)(s.td,{children:"6.26 Gbits/sec"}),(0,n.jsx)(s.td,{children:"0.218075ms"})]})]})]}),"\n",(0,n.jsx)(s.p,{children:"It can be observed that the transmission through overlay container networks incurs certain losses compared to the transmission through underlay physical machine networks. It is also evident that the performance of our Kosmos network is essentially consistent with the network transmission performance within the Calico cluster."}),"\n",(0,n.jsx)(s.p,{children:"By the way, when using kosmos to connect multiple Kubernetes clusters, network performance is better in p2p mode compared to gateway mode."}),"\n",(0,n.jsx)(s.h2,{id:"large-scale-cluster-performance-testing",children:"Large scale cluster performance testing"}),"\n",(0,n.jsx)(s.p,{children:"Based on the standard configuration of Kubernetes large-scale clusters and user production implementation practices, the usage scenario of Kosmos managing 100000 nodes and 200000 Pods simultaneously was tested. Due to limitations in testing environment and tools, we have not pursued the upper limit of testing Kosmos multi cluster systems."}),"\n",(0,n.jsx)(s.h4,{id:"performance-indicators",children:"Performance indicators"}),"\n",(0,n.jsx)(s.p,{children:"How to determine if Kubernetes supports 100000+nodes? Is it supported even if 100000 nodes can be successfully registered in the cluster? Or what conditions?"}),"\n",(0,n.jsxs)(s.p,{children:["The Kubernetes community has provided a series of SLIs (Service Level Indicator)/SLOs (service level objective) indicators to measure the quality of cluster services based on the judgment criteria. In a cluster, when the SLO of these SLIs is met, we say that the current Kubernetes cluster supports this performance metric.",(0,n.jsx)(s.a,{href:"https://github.com/kubernetes/community/blob/master/sig-scalability/slos/slos.md",children:"https://github.com/kubernetes/community/blob/master/sig-scalability/slos/slos.md"})]}),"\n",(0,n.jsx)(s.p,{children:"There are currently three official SLIs:"}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"API Call Latency"})}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:(0,n.jsx)(s.strong,{children:"Status"})}),(0,n.jsx)(s.th,{children:(0,n.jsx)(s.strong,{children:"SLI"})}),(0,n.jsx)(s.th,{children:(0,n.jsx)(s.strong,{children:"SLO"})})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Official"}),(0,n.jsx)(s.td,{children:"Single Object Mutating API P99 latency in the last 5 minutes"}),(0,n.jsx)(s.td,{children:"Except for aggregation API and CRD, P99 < 1s"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Official"}),(0,n.jsx)(s.td,{children:"Non streaming read only API P99 latency in the last 5 minutes"}),(0,n.jsx)(s.td,{children:"Except for aggregation API and CRD, P99 < 30s"})]})]})]}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"Pod Startup Latency"})}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Status"}),(0,n.jsx)(s.th,{children:(0,n.jsx)(s.strong,{children:"SLI"})}),(0,n.jsx)(s.th,{children:"SLO"})]})}),(0,n.jsx)(s.tbody,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Official"}),(0,n.jsx)(s.td,{children:"Stateless Pod startup time (excluding mirror removal and InitContainer), reporting startup time from Pod createTimestamp to all containers, and P99 time observed by the watch"}),(0,n.jsx)(s.td,{children:"P99 < 5s"})]})})]}),"\n",(0,n.jsx)(s.h4,{id:"testing-tools-and-test-cases",children:"Testing tools and test cases"}),"\n",(0,n.jsx)(s.h5,{id:"1-clusterloader2",children:"1. ClusterLoader2"}),"\n",(0,n.jsx)(s.p,{children:"ClusterLoader2 is an official open-source cluster load testing tool provided by Kubernetes, which can test the SLIs/SLOs indicators defined by Kubernetes to verify whether the cluster meets various service quality standards. In addition, Clusterloader2 provides visual data for cluster problem localization and cluster performance optimization. ClusterLoader2 will ultimately output a Kubernetes cluster performance report, displaying a series of performance indicator test results."}),"\n",(0,n.jsx)(s.h5,{id:"2-kwok",children:"2. Kwok"}),"\n",(0,n.jsx)(s.p,{children:"Kwok is a simulation testing toolkit officially released by Kubernetes, which allows users to create clusters with thousands of nodes in low resource simulation within seconds, and conduct large-scale testing of Kubernetes controllers without occupying a large amount of infrastructure. This report used the Kwok tool to simulate the creation of 20 Kubernetes clusters, each with 5000 nodes."}),"\n",(0,n.jsx)(s.h5,{id:"3-test-cases",children:"3. Test cases"}),"\n",(0,n.jsxs)(s.p,{children:["Use the Density test cases provided by ClusterLoader2( ",(0,n.jsx)(s.a,{href:"https://github.com/kubernetes/perf-tests/blob/master/clusterloader2/testing/density/config.yaml)%E3%80%82The",children:"https://github.com/kubernetes/perf-tests/blob/master/clusterloader2/testing/density/config.yaml)\u3002The"})," detailed configuration of this report is shown in the table below:"]}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:"Type"}),(0,n.jsx)(s.th,{children:"Value"})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Number of Nodes"}),(0,n.jsx)(s.td,{children:"100,000"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Number of Pods"}),(0,n.jsx)(s.td,{children:"200,000"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Number of Pods per node"}),(0,n.jsx)(s.td,{children:"2"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Number of Namespaces"}),(0,n.jsx)(s.td,{children:"200"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"Number of Pods per Namespace"}),(0,n.jsx)(s.td,{children:"1000"})]})]})]}),"\n",(0,n.jsx)(s.h5,{id:"4-test-clusters-deploy-architecture",children:"4. Test clusters deploy architecture"}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.img,{alt:"img",src:t(3244).c+"",width:"554",height:"431"})}),"\n",(0,n.jsx)(s.h4,{id:"testing-environment-detail",children:"Testing environment detail"}),"\n",(0,n.jsx)(s.p,{children:"The host Kubernetes is deployed using a single master, with Etcd, Kube apiserver, Kube Schedule, and Kube Controller all deployed as single instances."}),"\n",(0,n.jsx)(s.h5,{id:"1-os-version",children:"1. OS version"}),"\n",(0,n.jsx)(s.p,{children:"BigCloud Enterprise Linux For LDK release 7.6.1906 (Core)"}),"\n",(0,n.jsx)(s.p,{children:"kernel versions: 4.19.0-240.23.19.el7_6.bclinux.x86_64"}),"\n",(0,n.jsx)(s.p,{children:"Kubernetes version"}),"\n",(0,n.jsx)(s.p,{children:'Major:"1",Minor:"21+",GitVersion:"v1.21.5-eki.0",GitCommit:"83c85a6e50757c6bbb81c6ceaac60234c1161817",GitTreeState:"clean",BuildDate:"2021-10-19T08:28:00Z",GoVersion:"go1.16.8",Compiler:"gc", Platform:"linux/amd64"'}),"\n",(0,n.jsx)(s.h5,{id:"2-master-node",children:"2. Master node"}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"CPU"})}),"\n",(0,n.jsx)(s.p,{children:"Architecture: x86_64"}),"\n",(0,n.jsx)(s.p,{children:"CPU op-mode(s): 32-bit, 64-bit"}),"\n",(0,n.jsx)(s.p,{children:"Byte Order: Little Endian"}),"\n",(0,n.jsx)(s.p,{children:"CPU(s): 48"}),"\n",(0,n.jsx)(s.p,{children:"On-line CPU(s) list: 0-47"}),"\n",(0,n.jsx)(s.p,{children:"Thread(s) per core: 2"}),"\n",(0,n.jsx)(s.p,{children:"Core(s) per socket: 12"}),"\n",(0,n.jsx)(s.p,{children:"Socket(s): 2"}),"\n",(0,n.jsx)(s.p,{children:"NUMA node(s): 2"}),"\n",(0,n.jsx)(s.p,{children:"Vendor ID: GenuineIntel"}),"\n",(0,n.jsx)(s.p,{children:"CPU family: 6"}),"\n",(0,n.jsx)(s.p,{children:"Model: 85"}),"\n",(0,n.jsx)(s.p,{children:"Model name: Intel(R) Xeon(R) Silver 4214 CPU @ 2.20GHz"}),"\n",(0,n.jsx)(s.p,{children:"Stepping: 7"}),"\n",(0,n.jsx)(s.p,{children:"CPU MHz: 2482.416"}),"\n",(0,n.jsxs)(s.p,{children:[(0,n.jsx)(s.strong,{children:"MEMORY"}),"\uff1a 187GB"]}),"\n",(0,n.jsx)(s.h5,{id:"3-component-configuration",children:"3. Component configuration"}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"kube-apiserver"})}),"\n",(0,n.jsx)(s.p,{children:"--max-requests-inflight=1000"}),"\n",(0,n.jsx)(s.p,{children:"--max-mutating-requests-inflight=1000"}),"\n",(0,n.jsx)(s.p,{children:"**kube-controller-manager **"}),"\n",(0,n.jsx)(s.p,{children:"--kube-api-qps=100"}),"\n",(0,n.jsx)(s.p,{children:"--kube-api-burst=100"}),"\n",(0,n.jsx)(s.p,{children:"**kube-scheduler **"}),"\n",(0,n.jsx)(s.p,{children:"--kube-api-qps=100"}),"\n",(0,n.jsx)(s.p,{children:"--kube-api-burst=200"}),"\n",(0,n.jsx)(s.p,{children:"**etcd **"}),"\n",(0,n.jsx)(s.p,{children:"--auto-compaction-retention=4"}),"\n",(0,n.jsx)(s.p,{children:"--quota-backend-bytes=8589934592"}),"\n",(0,n.jsx)(s.h4,{id:"test-results",children:"Test Results"}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.strong,{children:"API Call Latency"})}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsx)(s.li,{children:"mutating API latency\uff08threshold=1s\uff09"}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.img,{alt:"img",src:t(1068).c+"",width:"553",height:"213"})}),"\n",(0,n.jsxs)(s.ol,{start:"2",children:["\n",(0,n.jsx)(s.li,{children:"Read-only API call latency(scope=resource, threshold=1s)"}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.img,{alt:"img",src:t(8604).c+"",width:"554",height:"231"})}),"\n",(0,n.jsxs)(s.ol,{start:"3",children:["\n",(0,n.jsx)(s.li,{children:"Read-only API call latency(scope=namespace, threshold=5s)"}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.img,{alt:"img",src:t(3119).c+"",width:"553",height:"244"})}),"\n",(0,n.jsxs)(s.ol,{start:"4",children:["\n",(0,n.jsx)(s.li,{children:"Read-only API call latency(scope=cluster, threshold=30s)"}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.img,{alt:"img",src:t(796).c+"",width:"554",height:"230"})}),"\n",(0,n.jsxs)(s.h5,{id:"2-pod-startup-latency",children:["2. ",(0,n.jsx)(s.strong,{children:"Pod Startup Latency"})]}),"\n",(0,n.jsxs)(s.table,{children:[(0,n.jsx)(s.thead,{children:(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.th,{children:(0,n.jsx)(s.strong,{children:"metric"})}),(0,n.jsx)(s.th,{children:"p50(ms)"}),(0,n.jsx)(s.th,{children:"p90(ms)"}),(0,n.jsx)(s.th,{children:"p99(ms)"}),(0,n.jsx)(s.th,{children:(0,n.jsx)(s.strong,{children:"SLO(ms)"})})]})}),(0,n.jsxs)(s.tbody,{children:[(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"pod_startup"}),(0,n.jsx)(s.td,{children:"780"}),(0,n.jsx)(s.td,{children:"1189"}),(0,n.jsx)(s.td,{children:"1403"}),(0,n.jsx)(s.td,{children:"5000"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"create_to_schedule"}),(0,n.jsx)(s.td,{children:"0"}),(0,n.jsx)(s.td,{children:"0"}),(0,n.jsx)(s.td,{children:"1000"}),(0,n.jsx)(s.td,{children:"N/A"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"schedule_to_run"}),(0,n.jsx)(s.td,{children:"0"}),(0,n.jsx)(s.td,{children:"0"}),(0,n.jsx)(s.td,{children:"1000"}),(0,n.jsx)(s.td,{children:"N/A"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"run_to_watch"}),(0,n.jsx)(s.td,{children:"899"}),(0,n.jsx)(s.td,{children:"1375"}),(0,n.jsx)(s.td,{children:"1512"}),(0,n.jsx)(s.td,{children:"N/A"})]}),(0,n.jsxs)(s.tr,{children:[(0,n.jsx)(s.td,{children:"schedule_to_watch"}),(0,n.jsx)(s.td,{children:"764"}),(0,n.jsx)(s.td,{children:"1176"}),(0,n.jsx)(s.td,{children:"1376"}),(0,n.jsx)(s.td,{children:"N/A"})]})]})]}),"\n",(0,n.jsx)(s.p,{children:"Note: In cases where the delay is relatively small, due to accuracy loss, certain values recorded by ClusterLoader2 are 0."}),"\n",(0,n.jsx)(s.h4,{id:"conclusion-and-analysis",children:(0,n.jsx)(s.strong,{children:"Conclusion and Analysis"})}),"\n",(0,n.jsx)(s.p,{children:"In the above test results, both API Call Latency and Pod Startup Latency meet the SLIs/SLOs metrics defined by the Kubernetes community. Therefore, a multi cluster system with Kosmos as its core can stably support 100000 nodes online simultaneously and manage over 200000 pods."})]})}function h(e={}){const{wrapper:s}={...(0,r.M)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},3244:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/cluster-deploy-90f1f30f5decda82585865e924e8a598.jpg"},1068:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/mutaing_api_latency-748ec7f610d0c8c7cf2b6e180f3505f0.jpg"},8604:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/readonly_api_latency-f224e93b2e2060c911df88a18aa39a46.jpg"},796:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/readonly_api_latency30-cc2f0ae0beea51845ecc79fd8b1b420b.jpg"},3119:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/readonly_api_latency5-0b671cdc723d4d232c034de05f6f5284.jpg"},2172:(e,s,t)=>{t.d(s,{I:()=>c,M:()=>l});var n=t(1504);const r={},i=n.createContext(r);function l(e){const s=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function c(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:l(e.components),n.createElement(i.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4b29c545.3c7ed13e.js b/docs/assets/js/4b29c545.3c7ed13e.js new file mode 100644 index 0000000..d697eee --- /dev/null +++ b/docs/assets/js/4b29c545.3c7ed13e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[588],{2020:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var i=t(7624),s=t(2172);const r={id:"application-migration",title:"Application Migration"},a="Application Migration",o={id:"v0.2.0/tutorials/application-migration",title:"Application Migration",description:"Kosmos provides application migration functionality to help users migrate existing applications from subclusters to the Kosmos control plane cluster.",source:"@site/docs/v0.2.0/tutorials/application-migration.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/application-migration",permalink:"/website/v0.2.0/tutorials/application-migration",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/application-migration.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1710244580,formattedLastUpdatedAt:"Mar 12, 2024",frontMatter:{id:"application-migration",title:"Application Migration"},sidebar:"tutorialSidebar",previous:{title:"IPsec Cross-cluster Network",permalink:"/website/v0.2.0/tutorials/ipsec-network"},next:{title:"Kubernetes in Kubernetes",permalink:"/website/v0.2.0/proposals/k8s-in-k8s"}},l={},c=[{value:"Application Migration Solution",id:"application-migration-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Design Details",id:"design-details",level:3},{value:"Application Backup",id:"application-backup",level:4},{value:"Deletion of Owner Objects",id:"deletion-of-owner-objects",level:4},{value:"Rebuilding Applications in the Control Plane",id:"rebuilding-applications-in-the-control-plane",level:4},{value:"CRD API",id:"crd-api",level:4},{value:"Rollback",id:"rollback",level:4},{value:"Test Plans",id:"test-plans",level:3},{value:"Preparation",id:"preparation",level:4},{value:"Create an Existing Application in the Subcluster",id:"create-an-existing-application-in-the-subcluster",level:4},{value:"Create a Migration Policy",id:"create-a-migration-policy",level:4},{value:"Check the Migration Result",id:"check-the-migration-result",level:4},{value:"Rollback",id:"rollback-1",level:4}];function p(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"application-migration",children:"Application Migration"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos provides application migration functionality to help users migrate existing applications from subclusters to the Kosmos control plane cluster."}),"\n",(0,i.jsx)(n.h2,{id:"application-migration-solution",children:"Application Migration Solution"}),"\n",(0,i.jsx)(n.h3,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"In the Kosmos multi-cluster design architecture, users can interact with the kube-apiserver of the control plane cluster using tools such as kubectl and client-go to create deployments or statefulset applications, etc.\r\nThe actual Pod instances are running in the subclusters."}),"\n",(0,i.jsx)(n.p,{children:"However, for existing applications in the subclusters that were not created through the Kosmos control plane, these applications cannot be viewed and managed in the control plane cluster."}),"\n",(0,i.jsx)(n.p,{children:"Kosmos provides application migration functionality to support the migration of applications in a namespace to the control plane cluster.\r\nThe entire process does not require restarting the application Pod instances, ensuring minimal impact on business operations."}),"\n",(0,i.jsx)(n.h3,{id:"design-details",children:"Design Details"}),"\n",(0,i.jsx)(n.p,{children:"Application migration mainly consists of three processes: application backup -> deletion of owner objects -> rebuilding applications in the control plane."}),"\n",(0,i.jsx)(n.h4,{id:"application-backup",children:"Application Backup"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos first backs up all namespaced-level resources in the target namespace, as well as the dependent cluster-level resources, such as cluster roles, cluster role bindings, persistent volumes, etc.\r\nThe backup files are stored in PVCs in Kosmos."}),"\n",(0,i.jsx)(n.h4,{id:"deletion-of-owner-objects",children:"Deletion of Owner Objects"}),"\n",(0,i.jsx)(n.p,{children:"The subclusters in Kosmos only run Pods, and their owner StatefulSets or ReplicaSets need to be deleted and rebuilt in the Kosmos control plane.\r\nSimilarly, the owner Deployment of a ReplicaSet, as well as the owner StatefulSet and Deployment, need to be deleted and rebuilt in the Kosmos control plane."}),"\n",(0,i.jsx)(n.p,{children:"By using a top-down cascading deletion of owner objects (e.g., deleting the Deployment first and then the ReplicaSet), the Pods are not affected and remain in a running state."}),"\n",(0,i.jsx)(n.h4,{id:"rebuilding-applications-in-the-control-plane",children:"Rebuilding Applications in the Control Plane"}),"\n",(0,i.jsx)(n.p,{children:"Based on the backup resources, the control plane cluster creates all the migrated resources, including namespaces, pods, deployments, config maps, service accounts, etc.\r\nIn order to maintain consistency with the subcluster Pods and keep them in a running state, the applications are rebuilt using a bottom-up approach (e.g., creating the Pod first and then the ReplicaSet)."}),"\n",(0,i.jsx)(n.h4,{id:"crd-api",children:"CRD API"}),"\n",(0,i.jsx)(n.p,{children:"The PromotePolicy CRD API is provided for configuring the migration policy.\r\nPromotePolicy is a cluster-wide CRD API. Here is an example of how to use it:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-sample\r\nspec:\r\n includedNamespaces:\r\n - namespace1\r\n - namespace2\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: member-cluster1\n"})}),"\n",(0,i.jsx)(n.p,{children:"where:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"includedNamespaces: The namespaces to be migrated."}),"\n",(0,i.jsx)(n.li,{children:"excludedNamespaceScopedResources: The namespace-level resources that should not be migrated.\r\nIt is recommended to keep the example configuration and add additional configurations as needed based on actual requirements."}),"\n",(0,i.jsx)(n.li,{children:"clusterName: The name of the Kosmos subcluster."}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"rollback",children:"Rollback"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos supports rollback functionality for migrations.\r\nAfter a successful migration, the existing applications in the subcluster can be restored to their initial state.\r\nSimply edit the PromotePolicy YAML file and add the configuration 'rollback'=true."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:'apiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-sample\r\nspec:\r\n rollback: "true"\r\n includedNamespaces:\r\n - namespace1\r\n - namespace2\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: member-cluster1\n'})}),"\n",(0,i.jsx)(n.h3,{id:"test-plans",children:"Test Plans"}),"\n",(0,i.jsx)(n.h4,{id:"preparation",children:"Preparation"}),"\n",(0,i.jsxs)(n.p,{children:["First, you need to deploy ",(0,i.jsx)(n.a,{href:"https://github.com/kosmos-io/kosmos",children:"Kosmos"})," (the clustertree module must be installed) and add a subcluster."]}),"\n",(0,i.jsx)(n.h4,{id:"create-an-existing-application-in-the-subcluster",children:"Create an Existing Application in the Subcluster"}),"\n",(0,i.jsx)(n.p,{children:"Deploy an nginx application in the subcluster as an example."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: nginx\r\n namespace: nginx-test\r\nspec:\r\n selector:\r\n matchLabels:\r\n app: nginx\r\n replicas: 1\r\n template:\r\n metadata:\r\n labels:\r\n app: nginx\r\n deletionGracePeriodSeconds: 30\r\n spec:\r\n containers:\r\n - name: nginx\r\n image: nginx:1.14-alpine\r\n ports:\r\n - containerPort: 80\r\n\r\n---\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n name: nginx-service\r\n namespace: nginx-test\r\nspec:\r\n selector:\r\n app: nginx\r\n ports:\r\n - protocol: TCP\r\n port: 80\r\n targetPort: 80\r\n type: ClusterIP\n"})}),"\n",(0,i.jsx)(n.h4,{id:"create-a-migration-policy",children:"Create a Migration Policy"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl apply -f promote-nginx.yaml\r\napiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-example\r\nspec:\r\n includedNamespaces:\r\n - nginx-test\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: cluster-36-28\n"})}),"\n",(0,i.jsx)(n.h4,{id:"check-the-migration-result",children:"Check the Migration Result"}),"\n",(0,i.jsx)(n.p,{children:"Check the progress of the migration:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl describe promotepolicy promote-policy-example\r\nName: promote-policy-example\r\nNamespace: default\r\nLabels: \r\nAnnotations: \r\nAPI Version: kosmos.io/v1alpha1\r\nKind: PromotePolicy\r\nMetadata:\r\n Creation Timestamp: 2024-03-11T10:57:47Z\r\n Generation: 3\r\n Resource Version: 405947183\r\n UID: 0e32dd93-c370-4874-b9a7-37a6894cd373\r\nSpec:\r\n Cluster Name: cluster-36-28\r\n Excluded Namespace Scoped Resources:\r\n events\r\n events.events.k8s.io\r\n endpoints\r\n endpointslices.discovery.k8s.io\r\n controllerrevisions.apps\r\n Included Namespaces:\r\n nginx-test\r\nStatus:\r\n Backedup File: /data/backup/promote-policy-sample20240311-104907\r\n Phase: Completed\r\nEvents: \n"})}),"\n",(0,i.jsx)(n.p,{children:"When Status.Phase is 'Completed', it means the migration is successful. At this point, you can view and manage all applications in the nginx-test namespace in the control plane cluster."}),"\n",(0,i.jsx)(n.h4,{id:"rollback-1",children:"Rollback"}),"\n",(0,i.jsx)(n.p,{children:"Edit the promote-nginx.yml file and add the configuration \u2018rollback\u2019=true:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:'# kubectl apply -f promote-nginx.yaml\r\napiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-example\r\nspec:\r\n rollback: "true"\r\n includedNamespaces:\r\n - nginx-test\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: cluster-36-28\n'})}),"\n",(0,i.jsx)(n.p,{children:"Check the rollback result:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl describe promotepolicy promote-policy-example\r\nName: promote-policy-example\r\nNamespace: default\r\nLabels: \r\nAnnotations: \r\nAPI Version: kosmos.io/v1alpha1\r\nKind: PromotePolicy\r\nMetadata:\r\n Creation Timestamp: 2024-03-11T10:57:47Z\r\n Generation: 5\r\n Resource Version: 405953692\r\n UID: 0e32dd93-c370-4874-b9a7-37a6894cd373\r\nSpec:\r\n Cluster Name: cluster-36-28\r\n Excluded Namespace Scoped Resources:\r\n events\r\n events.events.k8s.io\r\n endpoints\r\n endpointslices.discovery.k8s.io\r\n controllerrevisions.apps\r\n Included Namespaces:\r\n nginx-test\r\nStatus:\r\n Backedup File: /data/backup/promote-policy-sample20240311-104907\r\n Phase: RolledBack\r\nEvents: \n"})}),"\n",(0,i.jsx)(n.p,{children:"When Status.Phase is 'RolledBack', it means the rollback is successful.\r\nAt this point, the applications in the nginx-test namespace cannot be queried in the control plane cluster."})]})}function d(e={}){const{wrapper:n}={...(0,s.M)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>o,M:()=>a});var i=t(1504);const s={},r=i.createContext(s);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4b29c545.441b3353.js b/docs/assets/js/4b29c545.441b3353.js deleted file mode 100644 index 07966be..0000000 --- a/docs/assets/js/4b29c545.441b3353.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[588],{2020:(e,n,t)=>{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>a,default:()=>d,frontMatter:()=>r,metadata:()=>o,toc:()=>c});var i=t(7624),s=t(2172);const r={id:"application-migration",title:"Application Migration"},a="Application Migration",o={id:"v0.2.0/tutorials/application-migration",title:"Application Migration",description:"Kosmos provides application migration functionality to help users migrate existing applications from subclusters to the Kosmos control plane cluster.",source:"@site/docs/v0.2.0/tutorials/application-migration.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/application-migration",permalink:"/website/v0.2.0/tutorials/application-migration",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/application-migration.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1710244580,formattedLastUpdatedAt:"Mar 12, 2024",frontMatter:{id:"application-migration",title:"Application Migration"},sidebar:"tutorialSidebar",previous:{title:"IPsec Cross-cluster Network",permalink:"/website/v0.2.0/tutorials/ipsec-network"},next:{title:"kubenest",permalink:"/website/v0.2.0/tutorials/kubenest"}},l={},c=[{value:"Application Migration Solution",id:"application-migration-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Design Details",id:"design-details",level:3},{value:"Application Backup",id:"application-backup",level:4},{value:"Deletion of Owner Objects",id:"deletion-of-owner-objects",level:4},{value:"Rebuilding Applications in the Control Plane",id:"rebuilding-applications-in-the-control-plane",level:4},{value:"CRD API",id:"crd-api",level:4},{value:"Rollback",id:"rollback",level:4},{value:"Test Plans",id:"test-plans",level:3},{value:"Preparation",id:"preparation",level:4},{value:"Create an Existing Application in the Subcluster",id:"create-an-existing-application-in-the-subcluster",level:4},{value:"Create a Migration Policy",id:"create-a-migration-policy",level:4},{value:"Check the Migration Result",id:"check-the-migration-result",level:4},{value:"Rollback",id:"rollback-1",level:4}];function p(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,s.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"application-migration",children:"Application Migration"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos provides application migration functionality to help users migrate existing applications from subclusters to the Kosmos control plane cluster."}),"\n",(0,i.jsx)(n.h2,{id:"application-migration-solution",children:"Application Migration Solution"}),"\n",(0,i.jsx)(n.h3,{id:"introduction",children:"Introduction"}),"\n",(0,i.jsx)(n.p,{children:"In the Kosmos multi-cluster design architecture, users can interact with the kube-apiserver of the control plane cluster using tools such as kubectl and client-go to create deployments or statefulset applications, etc.\r\nThe actual Pod instances are running in the subclusters."}),"\n",(0,i.jsx)(n.p,{children:"However, for existing applications in the subclusters that were not created through the Kosmos control plane, these applications cannot be viewed and managed in the control plane cluster."}),"\n",(0,i.jsx)(n.p,{children:"Kosmos provides application migration functionality to support the migration of applications in a namespace to the control plane cluster.\r\nThe entire process does not require restarting the application Pod instances, ensuring minimal impact on business operations."}),"\n",(0,i.jsx)(n.h3,{id:"design-details",children:"Design Details"}),"\n",(0,i.jsx)(n.p,{children:"Application migration mainly consists of three processes: application backup -> deletion of owner objects -> rebuilding applications in the control plane."}),"\n",(0,i.jsx)(n.h4,{id:"application-backup",children:"Application Backup"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos first backs up all namespaced-level resources in the target namespace, as well as the dependent cluster-level resources, such as cluster roles, cluster role bindings, persistent volumes, etc.\r\nThe backup files are stored in PVCs in Kosmos."}),"\n",(0,i.jsx)(n.h4,{id:"deletion-of-owner-objects",children:"Deletion of Owner Objects"}),"\n",(0,i.jsx)(n.p,{children:"The subclusters in Kosmos only run Pods, and their owner StatefulSets or ReplicaSets need to be deleted and rebuilt in the Kosmos control plane.\r\nSimilarly, the owner Deployment of a ReplicaSet, as well as the owner StatefulSet and Deployment, need to be deleted and rebuilt in the Kosmos control plane."}),"\n",(0,i.jsx)(n.p,{children:"By using a top-down cascading deletion of owner objects (e.g., deleting the Deployment first and then the ReplicaSet), the Pods are not affected and remain in a running state."}),"\n",(0,i.jsx)(n.h4,{id:"rebuilding-applications-in-the-control-plane",children:"Rebuilding Applications in the Control Plane"}),"\n",(0,i.jsx)(n.p,{children:"Based on the backup resources, the control plane cluster creates all the migrated resources, including namespaces, pods, deployments, config maps, service accounts, etc.\r\nIn order to maintain consistency with the subcluster Pods and keep them in a running state, the applications are rebuilt using a bottom-up approach (e.g., creating the Pod first and then the ReplicaSet)."}),"\n",(0,i.jsx)(n.h4,{id:"crd-api",children:"CRD API"}),"\n",(0,i.jsx)(n.p,{children:"The PromotePolicy CRD API is provided for configuring the migration policy.\r\nPromotePolicy is a cluster-wide CRD API. Here is an example of how to use it:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-sample\r\nspec:\r\n includedNamespaces:\r\n - namespace1\r\n - namespace2\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: member-cluster1\n"})}),"\n",(0,i.jsx)(n.p,{children:"where:"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"includedNamespaces: The namespaces to be migrated."}),"\n",(0,i.jsx)(n.li,{children:"excludedNamespaceScopedResources: The namespace-level resources that should not be migrated.\r\nIt is recommended to keep the example configuration and add additional configurations as needed based on actual requirements."}),"\n",(0,i.jsx)(n.li,{children:"clusterName: The name of the Kosmos subcluster."}),"\n"]}),"\n",(0,i.jsx)(n.h4,{id:"rollback",children:"Rollback"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos supports rollback functionality for migrations.\r\nAfter a successful migration, the existing applications in the subcluster can be restored to their initial state.\r\nSimply edit the PromotePolicy YAML file and add the configuration 'rollback'=true."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:'apiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-sample\r\nspec:\r\n rollback: "true"\r\n includedNamespaces:\r\n - namespace1\r\n - namespace2\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: member-cluster1\n'})}),"\n",(0,i.jsx)(n.h3,{id:"test-plans",children:"Test Plans"}),"\n",(0,i.jsx)(n.h4,{id:"preparation",children:"Preparation"}),"\n",(0,i.jsxs)(n.p,{children:["First, you need to deploy ",(0,i.jsx)(n.a,{href:"https://github.com/kosmos-io/kosmos",children:"Kosmos"})," (the clustertree module must be installed) and add a subcluster."]}),"\n",(0,i.jsx)(n.h4,{id:"create-an-existing-application-in-the-subcluster",children:"Create an Existing Application in the Subcluster"}),"\n",(0,i.jsx)(n.p,{children:"Deploy an nginx application in the subcluster as an example."}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: nginx\r\n namespace: nginx-test\r\nspec:\r\n selector:\r\n matchLabels:\r\n app: nginx\r\n replicas: 1\r\n template:\r\n metadata:\r\n labels:\r\n app: nginx\r\n deletionGracePeriodSeconds: 30\r\n spec:\r\n containers:\r\n - name: nginx\r\n image: nginx:1.14-alpine\r\n ports:\r\n - containerPort: 80\r\n\r\n---\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n name: nginx-service\r\n namespace: nginx-test\r\nspec:\r\n selector:\r\n app: nginx\r\n ports:\r\n - protocol: TCP\r\n port: 80\r\n targetPort: 80\r\n type: ClusterIP\n"})}),"\n",(0,i.jsx)(n.h4,{id:"create-a-migration-policy",children:"Create a Migration Policy"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl apply -f promote-nginx.yaml\r\napiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-example\r\nspec:\r\n includedNamespaces:\r\n - nginx-test\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: cluster-36-28\n"})}),"\n",(0,i.jsx)(n.h4,{id:"check-the-migration-result",children:"Check the Migration Result"}),"\n",(0,i.jsx)(n.p,{children:"Check the progress of the migration:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl describe promotepolicy promote-policy-example\r\nName: promote-policy-example\r\nNamespace: default\r\nLabels: \r\nAnnotations: \r\nAPI Version: kosmos.io/v1alpha1\r\nKind: PromotePolicy\r\nMetadata:\r\n Creation Timestamp: 2024-03-11T10:57:47Z\r\n Generation: 3\r\n Resource Version: 405947183\r\n UID: 0e32dd93-c370-4874-b9a7-37a6894cd373\r\nSpec:\r\n Cluster Name: cluster-36-28\r\n Excluded Namespace Scoped Resources:\r\n events\r\n events.events.k8s.io\r\n endpoints\r\n endpointslices.discovery.k8s.io\r\n controllerrevisions.apps\r\n Included Namespaces:\r\n nginx-test\r\nStatus:\r\n Backedup File: /data/backup/promote-policy-sample20240311-104907\r\n Phase: Completed\r\nEvents: \n"})}),"\n",(0,i.jsx)(n.p,{children:"When Status.Phase is 'Completed', it means the migration is successful. At this point, you can view and manage all applications in the nginx-test namespace in the control plane cluster."}),"\n",(0,i.jsx)(n.h4,{id:"rollback-1",children:"Rollback"}),"\n",(0,i.jsx)(n.p,{children:"Edit the promote-nginx.yml file and add the configuration \u2018rollback\u2019=true:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:'# kubectl apply -f promote-nginx.yaml\r\napiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-example\r\nspec:\r\n rollback: "true"\r\n includedNamespaces:\r\n - nginx-test\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: cluster-36-28\n'})}),"\n",(0,i.jsx)(n.p,{children:"Check the rollback result:"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl describe promotepolicy promote-policy-example\r\nName: promote-policy-example\r\nNamespace: default\r\nLabels: \r\nAnnotations: \r\nAPI Version: kosmos.io/v1alpha1\r\nKind: PromotePolicy\r\nMetadata:\r\n Creation Timestamp: 2024-03-11T10:57:47Z\r\n Generation: 5\r\n Resource Version: 405953692\r\n UID: 0e32dd93-c370-4874-b9a7-37a6894cd373\r\nSpec:\r\n Cluster Name: cluster-36-28\r\n Excluded Namespace Scoped Resources:\r\n events\r\n events.events.k8s.io\r\n endpoints\r\n endpointslices.discovery.k8s.io\r\n controllerrevisions.apps\r\n Included Namespaces:\r\n nginx-test\r\nStatus:\r\n Backedup File: /data/backup/promote-policy-sample20240311-104907\r\n Phase: RolledBack\r\nEvents: \n"})}),"\n",(0,i.jsx)(n.p,{children:"When Status.Phase is 'RolledBack', it means the rollback is successful.\r\nAt this point, the applications in the nginx-test namespace cannot be queried in the control plane cluster."})]})}function d(e={}){const{wrapper:n}={...(0,s.M)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(p,{...e})}):p(e)}},2172:(e,n,t)=>{t.d(n,{I:()=>o,M:()=>a});var i=t(1504);const s={},r=i.createContext(s);function a(e){const n=i.useContext(r);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:a(e.components),i.createElement(r.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/4df3a098.4609b1d5.js b/docs/assets/js/4df3a098.4609b1d5.js deleted file mode 100644 index 40f85a2..0000000 --- a/docs/assets/js/4df3a098.4609b1d5.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[80],{7348:(e,s,o)=>{o.r(s),o.d(s,{assets:()=>c,contentTitle:()=>d,default:()=>u,frontMatter:()=>t,metadata:()=>l,toc:()=>a});var n=o(7624),r=o(2172);const t={id:"node-not-ready_zh",title:"Kosmos \u8282\u70b9 NotReady"},d="Kosmos \u8282\u70b9 NotReady",l={id:"i18n/zh/v0.2.0/node-not-ready_zh",title:"Kosmos \u8282\u70b9 NotReady",description:"Kosmos \u8282\u70b9 NotReady \u89e3\u51b3\u65b9\u6848",source:"@site/docs/i18n/zh/v0.2.0/node-not-ready_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/node-not-ready_zh",permalink:"/website/i18n/zh/v0.2.0/node-not-ready_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/node-not-ready_zh.md",tags:[],version:"current",frontMatter:{id:"node-not-ready_zh",title:"Kosmos \u8282\u70b9 NotReady"}},c={},a=[{value:"Kosmos \u8282\u70b9 NotReady \u89e3\u51b3\u65b9\u6848",id:"kosmos-\u8282\u70b9-notready-\u89e3\u51b3\u65b9\u6848",level:2},{value:"\u7b80\u4ecb",id:"\u7b80\u4ecb",level:3},{value:"\u89e3\u51b3\u65b9\u6848\uff1a\u96c6\u6210 Kyverno \u89e3\u51b3 Kosmos \u8282\u70b9 NotReady \u7684\u95ee\u9898",id:"\u89e3\u51b3\u65b9\u6848\u96c6\u6210-kyverno-\u89e3\u51b3-kosmos-\u8282\u70b9-notready-\u7684\u95ee\u9898",level:3},{value:"\u4ec0\u4e48\u662f\u51c6\u5165 Webhook\uff1f",id:"\u4ec0\u4e48\u662f\u51c6\u5165-webhook",level:4},{value:"\u89e3\u51b3\u65b9\u6848",id:"\u89e3\u51b3\u65b9\u6848",level:4},{value:"\u5b89\u88c5 Kyverno",id:"\u5b89\u88c5-kyverno",level:5},{value:"\u914d\u7f6e ClusterPolicy",id:"\u914d\u7f6e-clusterpolicy",level:5}];function i(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,r.M)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"kosmos-\u8282\u70b9-notready",children:"Kosmos \u8282\u70b9 NotReady"}),"\n",(0,n.jsx)(s.h2,{id:"kosmos-\u8282\u70b9-notready-\u89e3\u51b3\u65b9\u6848",children:"Kosmos \u8282\u70b9 NotReady \u89e3\u51b3\u65b9\u6848"}),"\n",(0,n.jsx)(s.h3,{id:"\u7b80\u4ecb",children:"\u7b80\u4ecb"}),"\n",(0,n.jsxs)(s.p,{children:["\u5047\u8bbe\u6211\u4eec\u5df2\u7ecf\u5728\u4e3b\u96c6\u7fa4\u4e0a\u6ce8\u518c\u4e86\u96c6\u7fa4 ",(0,n.jsx)(s.code,{children:"cluster7"}),"\uff1a"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-shell",metastring:"script",children:"$ kubectl get node\r\nNAME STATUS ROLES AGE VERSION\r\necs-54004033-001 Ready worker 50d v1.21.5\r\necs-54004033-002 Ready control-plane,master,worker 50d v1.21.5\r\nkosmos-cluster7 Ready agent 5d22h v1.21.5\n"})}),"\n",(0,n.jsxs)(s.p,{children:["Kosmos \u7684 clustertree-cluster-manager \u5c06\u6301\u7eed\u76d1\u89c6 ",(0,n.jsx)(s.code,{children:"cluster7"})," \u96c6\u7fa4\u7684\u8d44\u6e90\u4f7f\u7528\u60c5\u51b5\u548c\u96c6\u7fa4\u72b6\u6001\uff0c\u5e76\u5c06\u5176\u66f4\u65b0\u5230\u4e3b\u96c6\u7fa4\u4e0a\u7684\u53f6\u8282\u70b9 ",(0,n.jsx)(s.code,{children:"kosmos-cluster7"}),"\u3002"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-shell",metastring:"script",children:"$ kubectl get deploy -nkosmos-system\r\nNAME READY UP-TO-DATE AVAILABLE AGE\r\nclusterlink-controller-manager 1/1 1 1 5d22h\r\nclusterlink-elector 2/2 2 2 5d22h\r\nclusterlink-network-manager 1/1 1 1 5d22h\r\nclustertree-cluster-manager 1/1 1 1 5d22h\r\nkosmos-operator 1/1 1 1 5d22h\r\nkosmos-webhook 1/1 1 1 11\n"})}),"\n",(0,n.jsxs)(s.p,{children:["\u5982\u679c\u4e3b\u96c6\u7fa4\u4e0e ",(0,n.jsx)(s.code,{children:"cluster7"})," \u96c6\u7fa4\u4e4b\u95f4\u5b58\u5728\u7f51\u7edc\u6ce2\u52a8\uff0cKosmos \u5c06\u68c0\u6d4b\u5230\u6b64\u5f02\u5e38\uff0c\u5e76\u5c06\u4e3b\u96c6\u7fa4\u4e0a\u53f6\u8282\u70b9 ",(0,n.jsx)(s.code,{children:"kosmos-cluster7"}),' \u7684\u72b6\u6001\u8bbe\u7f6e\u4e3a "NotReady"\u3002\r\n\u8fd9\u5c06\u89e6\u53d1 Kubernetes \u7684 Pod \u9a71\u9010\u884c\u4e3a\uff0c\u610f\u5473\u7740\u5728 "NotReady" \u8282\u70b9\u4e0a\u7684 Pod \u5c06\u88ab\u9a71\u9010\u5230\u5176\u4ed6 Ready \u8282\u70b9\u3002']}),"\n",(0,n.jsxs)(s.p,{children:["\u7136\u800c\uff0c\u7531\u4e8e\u7f51\u7edc\u6ce2\u52a8\uff0c",(0,n.jsx)(s.code,{children:"kosmos-cluster7"}),' \u7684\u72b6\u6001\u5728\u9a71\u9010\u8fc7\u7a0b\u4e2d\u53ef\u80fd\u4f1a\u518d\u6b21\u53d8\u4e3a "Ready"\u3002\r\n\u4f46\u6700\u521d\u9a71\u9010\u7684 Pod \u7684\u4e8b\u4ef6\u4ecd\u5c06\u53d1\u9001\u5230 "cluster7" \u96c6\u7fa4\uff0c\u5bfc\u81f4\u5728 "cluster7" \u96c6\u7fa4\u4e0a\u7684\u6b63\u5e38\u8fd0\u884c\u7684 Pod \u88ab\u5220\u9664\u6216\u91cd\u65b0\u542f\u52a8\uff0c\u4ece\u800c\u5f71\u54cd\u4e1a\u52a1\u3002']}),"\n",(0,n.jsx)(s.h3,{id:"\u89e3\u51b3\u65b9\u6848\u96c6\u6210-kyverno-\u89e3\u51b3-kosmos-\u8282\u70b9-notready-\u7684\u95ee\u9898",children:"\u89e3\u51b3\u65b9\u6848\uff1a\u96c6\u6210 Kyverno \u89e3\u51b3 Kosmos \u8282\u70b9 NotReady \u7684\u95ee\u9898"}),"\n",(0,n.jsxs)(s.p,{children:[(0,n.jsx)(s.a,{href:"https://kyverno.io/",children:"Kyverno"})," \u901a\u8fc7 Kubernetes \u51c6\u5165 Webhook\u3001\u540e\u53f0\u626b\u63cf\u548c\u6e90\u4ee3\u7801\u5e93\u626b\u63cf\u6765\u9a8c\u8bc1\u3001\u53d8\u66f4\u3001\u751f\u6210\u548c\u6e05\u7406\u914d\u7f6e\u3002\r\nKyverno \u7b56\u7565\u53ef\u4ee5\u4f5c\u4e3a Kubernetes \u8d44\u6e90\u8fdb\u884c\u7ba1\u7406\u3002"]}),"\n",(0,n.jsx)(s.p,{children:"\u5b83\u7684\u4e3b\u8981\u529f\u80fd\u5982\u4e0b\uff1a"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsx)(s.li,{children:"\u9a8c\u8bc1\u3001\u53d8\u66f4\u3001\u751f\u6210\u6216\u6e05\u7406\uff08\u5220\u9664\uff09\u4efb\u4f55\u8d44\u6e90"}),"\n",(0,n.jsx)(s.li,{children:"\u9a8c\u8bc1\u5bb9\u5668\u955c\u50cf\u4ee5\u7528\u4e8e\u8f6f\u4ef6\u4f9b\u5e94\u94fe\u5b89\u5168\u6027"}),"\n",(0,n.jsx)(s.li,{children:"\u4f7f\u7528\u6807\u7b7e\u9009\u62e9\u5668\u548c\u901a\u914d\u7b26\u5339\u914d\u8d44\u6e90"}),"\n",(0,n.jsx)(s.li,{children:"\u5728\u547d\u540d\u7a7a\u95f4\u95f4\u540c\u6b65\u914d\u7f6e"}),"\n",(0,n.jsx)(s.li,{children:"\u4f7f\u7528\u51c6\u5165\u63a7\u5236\u963b\u6b62\u975e\u7b26\u5408\u8d44\u6e90\uff0c\u6216\u62a5\u544a\u7b56\u7565\u8fdd\u89c4"}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:"\u672c\u6587\u5c06\u89e3\u91ca\u5982\u4f55\u4f7f\u7528 Kyverno \u7684\u51c6\u5165 Webhook \u6765\u9632\u6b62 Kosmos \u8282\u70b9 NotReady \u65f6\u7684 Pod \u9a71\u9010\u3002"}),"\n",(0,n.jsx)(s.h4,{id:"\u4ec0\u4e48\u662f\u51c6\u5165-webhook",children:"\u4ec0\u4e48\u662f\u51c6\u5165 Webhook\uff1f"}),"\n",(0,n.jsx)(s.p,{children:"\u51c6\u5165 Webhook \u662f\u4e00\u6bb5\u4ee3\u7801\uff0c\u5728\u5bf9\u8c61\u6301\u4e45\u5316\u5230 Kubernetes API \u670d\u52a1\u5668\u4e4b\u524d\u62e6\u622a\u8bf7\u6c42\u3002\r\n\u5b83\u5141\u8bb8\u8bf7\u6c42\u901a\u8fc7\u8ba4\u8bc1\u548c\u6388\u6743\u540e\u624d\u80fd\u901a\u8fc7\u3002\u51c6\u5165\u63a7\u5236\u5668\u53ef\u4ee5\u6267\u884c\u9a8c\u8bc1\u3001\u53d8\u66f4\u6216\u4e24\u8005\u90fd\u6267\u884c\u3002\r\n\u53d8\u66f4\u63a7\u5236\u5668\u4fee\u6539\u5b83\u4eec\u5904\u7406\u7684\u8d44\u6e90\u5bf9\u8c61\uff0c\u800c\u9a8c\u8bc1\u63a7\u5236\u5668\u4e0d\u4f1a\u3002\u5982\u679c\u4efb\u4f55\u63a7\u5236\u5668\u5728\u4efb\u4f55\u9636\u6bb5\u62d2\u7edd\u8bf7\u6c42\uff0c\u6574\u4e2a\u8bf7\u6c42\u5c06\u7acb\u5373\u88ab\u62d2\u7edd\uff0c\u5e76\u5c06\u9519\u8bef\u8fd4\u56de\u7ed9\u6700\u7ec8\u7528\u6237\u3002"}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.img,{alt:"K8s_Admission_Webhook.png",src:o(4928).c+"",width:"2401",height:"721"})}),"\n",(0,n.jsx)(s.h4,{id:"\u89e3\u51b3\u65b9\u6848",children:"\u89e3\u51b3\u65b9\u6848"}),"\n",(0,n.jsx)(s.h5,{id:"\u5b89\u88c5-kyverno",children:"\u5b89\u88c5 Kyverno"}),"\n",(0,n.jsx)(s.p,{children:(0,n.jsx)(s.a,{href:"https://kyverno.io/docs/installation/methods/",children:"\u5b89\u88c5 Kyverno"})}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-shell",metastring:"script",children:"kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.10.0/install.yaml\n"})}),"\n",(0,n.jsx)(s.h5,{id:"\u914d\u7f6e-clusterpolicy",children:"\u914d\u7f6e ClusterPolicy"}),"\n",(0,n.jsx)(s.p,{children:"\u4ee5\u4e0b\u662f\u56db\u79cd\u60c5\u51b5\u4e0b K8s \u9a71\u9010 Pod\uff1a"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"\u7528\u6237\u53d1\u8d77"}),"\uff1a\u7531 API \u53d1\u8d77\u7684\u9a71\u9010\u8bf7\u6c42\u3002\u4f8b\u5982\uff0c\u8282\u70b9\u7ef4\u62a4\u671f\u95f4\uff0c\u4e3a\u4e86\u907f\u514d\u8282\u70b9\u7a81\u7136\u4e0b\u7ebf\u5bf9\u670d\u52a1\u9020\u6210\u7684\u5f71\u54cd\uff0c\u4f1a\u9a71\u9010\u8282\u70b9\u4e0a\u7684\u6240\u6709 Pod\u3002"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Kubelet \u53d1\u8d77"}),"\uff1a\u5b9a\u671f\u68c0\u67e5\u8282\u70b9\u8d44\u6e90\u3002\u5f53\u8d44\u6e90\u4e0d\u8db3\u65f6\uff0c\u57fa\u4e8e\u4f18\u5148\u7ea7\uff0c\u5c06\u9a71\u9010\u4e00\u4e9b Pod\u3002"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"kube-controller-manager \u53d1\u8d77"}),"\uff1a\u5b9a\u671f\u68c0\u6d4b\u6240\u6709\u8282\u70b9\u3002\u5f53\u8282\u70b9\u7684 NotReady \u72b6\u6001\u8d85\u8fc7\u4e00\u6bb5\u65f6\u95f4\u65f6\uff0c\u5c06\u9a71\u9010\u8282\u70b9\u4e0a\u7684\u6240\u6709 Pod\uff0c\u4ee5\u4fbf\u5c06\u5176\u91cd\u65b0\u8c03\u5ea6\u5230\u5176\u4ed6\u6b63\u5e38\u8282\u70b9\u4e0a\u8fd0\u884c\u3002\u542f\u7528\u6c61\u70b9\u9a71\u9010\u65f6\uff0c\u5728\u8282\u70b9\u4e0a\u51fa\u73b0 ",(0,n.jsx)(s.code,{children:"NoExecute"})," \u6c61\u70b9\u540e\uff0c\u65e0\u6cd5\u5bb9\u5fcd\u6c61\u70b9\u7684 Pod \u5c06\u7acb\u5373\u88ab\u9a71\u9010\u3002\u5bf9\u4e8e\u53ef\u4ee5\u5bb9\u5fcd\u6c61\u70b9\u7684 Pod\uff0c\u5728 Pod \u4e0a\u914d\u7f6e\u7684\u6700\u5c0f\u6c61\u70b9\u5bb9\u5fcd\u65f6\u95f4\u540e\uff0c\u5c06\u88ab\u9a71\u9010\u3002"]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"kube-scheduler \u53d1\u8d77"}),"\uff1a\u5f53\u5b9e\u73b0\u62a2\u5360\u8c03\u5ea6\u65f6\uff0c\u4f4e\u4f18\u5148\u7ea7 Pod \u53ef\u80fd\u4f1a\u88ab\u9a71\u9010\uff0c\u4ee5\u4e3a\u9ad8\u4f18\u5148\u7ea7\u548c\u62a2\u5360 Pod \u817e\u51fa\u4f4d\u7f6e\uff0c\u4ece\u800c\u4f7f\u9ad8\u4f18\u5148\u7ea7 Pod \u53ef\u4ee5\u6b63\u5e38\u8c03\u5ea6\u3002"]}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:"\u4f7f\u7528\u4ee5\u4e0b\u914d\u7f6e\uff0c\u6211\u4eec\u5c06\u4ec5\u963b\u6b62\u7b26\u5408\u4ee5\u4e0b\u4e09\u4e2a\u6761\u4ef6\u7684 Pod \u5220\u9664\u4e8b\u4ef6\uff1a"}),"\n",(0,n.jsx)(s.p,{children:"(1) \u8282\u70b9\u72b6\u6001\u4e3a NotReady"}),"\n",(0,n.jsx)(s.p,{children:"(2) \u8282\u70b9\u662f KosmosNode"}),"\n",(0,n.jsxs)(s.p,{children:["(3) \u7528\u6237\u540d\u4e3a system:serviceaccount:kube-system",":node-controller","\uff08\u5c5e\u4e8e node-controller \u7684 kube-controller-manager\uff09"]}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-yaml",children:'apiVersion: kyverno.io/v1\r\nkind: ClusterPolicy\r\nmetadata:\r\n name: kosmos-node-not-ready\r\nspec:\r\n validationFailureAction: Enforce\r\n background: false\r\n rules:\r\n - match:\r\n any:\r\n - resources:\r\n kinds:\r\n - Pod\r\n operations:\r\n - DELETE\r\n name: kosmos-node-not-read\r\n context:\r\n - name: nodeStatus\r\n apiCall:\r\n urlPath: /api/v1/nodes/{{request.oldObject.spec.nodeName}}\r\n jmesPath: status.conditions[?type==\'Ready\'].status | [0]\r\n - name: isKosmosNode\r\n apiCall:\r\n urlPath: /api/v1/nodes/{{request.oldObject.spec.nodeName}}\r\n jmesPath: metadata.labels."kosmos.io/node"\r\n preconditions:\r\n all:\r\n - key: "{{ request.userInfo.username }}"\r\n operator: Equals\r\n value: "system:serviceaccount:kube-system:node-controller"\r\n - key: "{{ nodeStatus }}"\r\n operator: NotEquals\r\n value: "True" \r\n - key: "{{ length(isKosmosNode) }}"\r\n operator: GreaterThan\r\n value: 0\r\n validate:\r\n message: "{{ request.userInfo.username }} \u4e0d\u5141\u8bb8\u5220\u9664 NotReady Kosmos {{request.oldObject.spec.nodeName}} \u8282\u70b9\u4e0a\u7684 Pod {{request.oldObject.metadata.name}}\u3002"\r\n deny: {}\n'})}),"\n",(0,n.jsx)(s.p,{children:"\u5f53 Kosmos \u8282\u70b9\u72b6\u6001\u4e3a NotReady \u65f6\uff0c\u5c06\u963b\u6b62\u5728\u6b64\u7c7b\u8282\u70b9\u4e0a\u7684 Pod\u3002\u60a8\u53ef\u4ee5\u901a\u8fc7\u67e5\u770b kyverno-admission-controller \u6765\u67e5\u770b\u4ee5\u4e0b\u65e5\u5fd7\u3002"}),"\n",(0,n.jsx)(s.pre,{children:(0,n.jsx)(s.code,{className:"language-shell",metastring:"script",children:'handlers.go:139] webhooks/resource/validate "msg"="admission request denied" "clusterroles"=["system:basic-user","system:controller:node-controller","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"","version":"v1","kind":"Pod"} "gvr"={"group":"","version":"v1","resource":"pods"} "kind"="Pod" "name"="example-deployment-6cc4fd9bd7-kkm8z" "namespace"="default" "operation"="DELETE" "resource.gvk"={"Group":"","Version":"v1","Kind":"Pod"} "roles\r\n\r\n"=null "uid"="7f25ee88-4522-45fd-a6ba-38733122b443" "user"={"username":"system:serviceaccount:kube-system:node-controller","uid":"5a13be66-71fd-40e3-9553-00eb0825fbb0","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"]}\r\nevent.go:307] "Event occurred" object="kosmos-node-not-ready" fieldPath="" kind="ClusterPolicy" apiVersion="kyverno.io/v1" type="Warning" reason="PolicyViolation" message="Pod default/example-deployment-6cc4fd9bd7-kkm8z: [kosmos-node-not-ready] fail (blocked); system:serviceaccount:kube-system:node-controller delete pod example-deployment-6cc4fd9bd7-kkm8z of NotReady Kosmos kosmos-cluster2 Node is not allowed. "\r\nvalidation.go:103] webhooks/resource/validate "msg"="validation failed" "action"="Enforce" "clusterroles"=["system:basic-user","system:controller:node-controller","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "failed rules"=["kosmos-node-not-ready"] "gvk"={"group":"","version":"v1","kind":"Pod"} "gvr"={"group":"","version":"v1","resource":"pods"} "kind"="Pod" "name"="example-deployment-6cc4fd9bd7-sb7m7" "namespace"="default" "operation"="DELETE" "policy"="kosmos-node-not-ready" "resource"="default/Pod/example-deployment-6cc4fd9bd7-sb7m7" "resource.gvk"={"Group":"","Version":"v1","Kind":"Pod"} "roles"=null "uid"="251f1877-4f2c-40ec-9bca-8ceb7c9c845f" "user"={"username":"system:serviceaccount:kube-system:node-controller","uid":"5a13be66-71fd-40e3-9553-00eb0825fbb0","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"]}\n'})})]})}function u(e={}){const{wrapper:s}={...(0,r.M)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(i,{...e})}):i(e)}},4928:(e,s,o)=>{o.d(s,{c:()=>n});const n=o.p+"assets/images/K8s_Admission_Webhook-d80e6ba8089fbf07bf3bf24a5302860a.png"},2172:(e,s,o)=>{o.d(s,{I:()=>l,M:()=>d});var n=o(1504);const r={},t=n.createContext(r);function d(e){const s=n.useContext(t);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:d(e.components),n.createElement(t.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/551e372e.d8870a63.js b/docs/assets/js/551e372e.38a74c14.js similarity index 99% rename from docs/assets/js/551e372e.d8870a63.js rename to docs/assets/js/551e372e.38a74c14.js index ea302f3..4f30b7f 100644 --- a/docs/assets/js/551e372e.d8870a63.js +++ b/docs/assets/js/551e372e.38a74c14.js @@ -1 +1 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[811],{7140:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>l,toc:()=>a});var r=n(7624),s=n(2172);const o={id:"mcn-connectivity",title:"Multi-cluster Network Connectivity"},i="Multi-cluster Network Connectivity",l={id:"v0.2.0/tutorials/mcn-connectivity",title:"Multi-cluster Network Connectivity",description:"The Clusterlink design of the Kosmos multi-cluster solution aims to interconnect the nodes and resources of multiple Kubernetes clusters, forming a unified resource pool.",source:"@site/docs/v0.2.0/tutorials/multi-cluster-network.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/mcn-connectivity",permalink:"/website/v0.2.0/tutorials/mcn-connectivity",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/multi-cluster-network.md",tags:[],version:"current",lastUpdatedBy:"renxiangyu",lastUpdatedAt:1710063238,formattedLastUpdatedAt:"Mar 10, 2024",frontMatter:{id:"mcn-connectivity",title:"Multi-cluster Network Connectivity"},sidebar:"tutorialSidebar",previous:{title:"Multi-cluster Scheduler",permalink:"/website/v0.2.0/tutorials/mc-scheduler"},next:{title:"Multi-cluster PV/PVC Dynamic Storage",permalink:"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage"}},c={},a=[{value:"Multi-cluster Container Network Solution",id:"multi-cluster-container-network-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Design",id:"design",level:3},{value:"Prerequisites",id:"prerequisites",level:3},{value:"Install Kosmos",id:"install-kosmos",level:4},{value:"Join the Leaf Cluster",id:"join-the-leaf-cluster",level:4},{value:"Across Cluster L3 Network Connectivity",id:"across-cluster-l3-network-connectivity",level:3},{value:"Gateway Mode",id:"gateway-mode",level:4},{value:"P2P Mode",id:"p2p-mode",level:4},{value:"Starting ClusterLink",id:"starting-clusterlink",level:3},{value:"Using P2P Mode",id:"using-p2p-mode",level:4},{value:"Create Test Pods",id:"create-test-pods",level:4},{value:"One-Click Diagnostic for Cluster Connectivity",id:"one-click-diagnostic-for-cluster-connectivity",level:3}];function u(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",p:"p",pre:"pre",...(0,s.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"multi-cluster-network-connectivity",children:"Multi-cluster Network Connectivity"}),"\n",(0,r.jsx)(t.p,{children:"The Clusterlink design of the Kosmos multi-cluster solution aims to interconnect the nodes and resources of multiple Kubernetes clusters, forming a unified resource pool.\r\nOne of the foundations for achieving this is the need to build a multi-cluster network architecture to meet the communication requirements between different clusters."}),"\n",(0,r.jsx)(t.h2,{id:"multi-cluster-container-network-solution",children:"Multi-cluster Container Network Solution"}),"\n",(0,r.jsx)(t.h3,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsx)(t.p,{children:"Clusterlink includes two network modes: Gateway and P2P. In the Gateway mode, when a data packet is sent by a Pod on the left, it first goes through the vx-local tunnel within the cluster to reach the Gateway node of that cluster.\r\nIt then traverses the cross-cluster tunnel to reach the counterpart cluster.\r\nOnce the data packet arrives at the counterpart cluster, it is handled by the CNI and follows the single-cluster network to reach the target Pod.\r\nThis mode has its advantages and disadvantages.\r\nThe advantage is that each cluster only needs one node (or two for high availability) to provide external access, making it suitable for multi-cloud and hybrid cloud scenarios.\r\nThe disadvantage is that due to the longer network path, there is a certain performance loss.\r\nTo address this issue, Clusterlink provides the P2P mode, which is suitable for scenarios with higher network performance requirements.\r\nIn this mode, the data packets are directly sent to the node where the counterpart Pod is located.\r\nAdditionally, the P2P and Gateway modes can be used in combination."}),"\n",(0,r.jsx)(t.h3,{id:"design",children:"Design"}),"\n",(0,r.jsx)(t.p,{children:"The architecture of the Kosmos multi-cluster network Gateway solution is as follows:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"MCN GW_Architecture.png",src:n(208).c+"",width:"1019",height:"287"})}),"\n",(0,r.jsx)(t.admonition,{title:"NOTE",type:"info",children:(0,r.jsx)(t.p,{children:"It provides strong compatibility, requiring only one node per cluster (or two for high availability) to provide external access, making it suitable for cross-cloud scenarios."})}),"\n",(0,r.jsx)(t.p,{children:"The architecture of the Kosmos multi-cluster network P2P solution is as follows:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"MCN P2P_Architecture.png",src:n(4032).c+"",width:"1019",height:"310"})}),"\n",(0,r.jsx)(t.admonition,{title:"NOTE",type:"info",children:(0,r.jsx)(t.p,{children:"It has shorter network paths and better performance, making it suitable for fully interconnected Underlay scenarios."})}),"\n",(0,r.jsx)(t.h3,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,r.jsx)(t.h4,{id:"install-kosmos",children:"Install Kosmos"}),"\n",(0,r.jsxs)(t.p,{children:["Refer to the Kosmos Quick Start documentation ",(0,r.jsx)(t.a,{href:"https://github.com/kosmos-io/kosmos",children:"https://github.com/kosmos-io/kosmos"})," and enable the ClusterLink module for multi-cluster networking. Using the kosmosctl tool:"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:'kosmosctl install --cni calico --default-nic eth0 (We build a network tunnel based on the network interface value passed by the arg "default-nic")\n'})}),"\n",(0,r.jsx)(t.h4,{id:"join-the-leaf-cluster",children:"Join the Leaf Cluster"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"kosmosctl join cluster --name cluster1 --kubeconfig ~/kubeconfig/cluster1-kubeconfig --cni calico --default-nic eth0 --enable-link\n"})}),"\n",(0,r.jsx)(t.h3,{id:"across-cluster-l3-network-connectivity",children:"Across Cluster L3 Network Connectivity"}),"\n",(0,r.jsx)(t.p,{children:"To achieve cross-cluster L3 network connectivity in Kosmos, at least two different cluster nodes from each cluster need to be able to communicate with each other at the host machine network level, and the clusters must be correctly deployed and support VXLAN or IPSec technologies."}),"\n",(0,r.jsx)(t.h4,{id:"gateway-mode",children:"Gateway Mode"}),"\n",(0,r.jsx)(t.p,{children:"In each Kubernetes cluster within the Kosmos federation, one node is elected as the Gateway (GW) node using the Elector module.\r\nThe GW nodes of the two clusters communicate through the vx-bridge tunnel (created by Kosmos) to establish connectivity.\r\nWithin each cluster, routing is handled by the GW node.\r\nCompared to the P2P mode, the GW mode has slightly lower network performance due to the additional packet encapsulation and decapsulation at the GW node.\r\nHowever, the advantage is that the routing table and FDB table of the cluster nodes can remain almost the same as before.\r\nTherefore, the GW mode is suitable for larger-scale multi-cluster scenarios where network performance is not critical."}),"\n",(0,r.jsx)(t.h4,{id:"p2p-mode",children:"P2P Mode"}),"\n",(0,r.jsx)(t.p,{children:"In the P2P mode, there is no need to use the Elector module.\r\nKosmos creates vx-bridge interfaces on all nodes of each cluster to achieve direct container network communication between nodes of different clusters.\r\nThe network performance in this mode is almost the same as in a single Kubernetes cluster.\r\nHowever, in the P2P mode, every node in the cluster needs to configure access rules for all nodes in the Kosmos federation, resulting in larger routing and FDB table sizes.\r\nTherefore, the P2P mode is suitable for scenarios that require higher network performance but have a smaller number of nodes in each cluster."}),"\n",(0,r.jsx)(t.h3,{id:"starting-clusterlink",children:"Starting ClusterLink"}),"\n",(0,r.jsx)(t.h4,{id:"using-p2p-mode",children:"Using P2P Mode"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"# Complete the steps in sections 'Install Kosmos' & 'Join the Leaf Cluster'\r\n# Check if the clusters resource has been created correctly\r\n[root@kosmos-control-cluster yaml]# kubectl --kubeconfig config-14 get clusters.kosmos.io\r\nNAME NETWORK_TYPE IP_FAMILY\r\ncluster38 p2p all\r\nkosmos-control-cluster p2p all\r\n\r\n# Check if the clusternodes resource has been created correctly\r\n[root@kosmos-control-cluster yaml]# kubectl get clusternodes.kosmos.io\r\nNAME ROLES INTERFACE IP\r\ncluster38-001 bond0.1820 10.*.*.38\r\ncluster38-002 bond0.1820 10.*.*.39\r\ncluster38-003 bond0.1830 10.*.*.94\r\ncluster38-004 [\"gateway\"] bond0.1830 10.*.*.95\r\nkosmos-control-cluster-001 bond0.1820 10.*.*.14\r\nkosmos-control-cluster-002 bond0.1820 10.*.*.15\r\nkosmos-control-cluster-003 [\"gateway\"] bond0.1565 10.*.*.38\r\nkosmos-control-cluster-004 bond0.1565 10.*.*.31\r\nkosmos-control-cluster-005 bond0.1565 10.*.*.32\r\nkosmos-control-cluster-006 bond0.1565 10.*.*.33\r\nkosmos-control-cluster-007 bond0.1565 10.*.*.37\r\n\r\n# Check if the nodeconfigs resource has been created correctly\r\n[root@kosmos-control-cluster yaml]# kubectl get nodeconfigs.kosmos.io\r\nNAME AGE\r\ncluster38-001 14d\r\ncluster38-002 14d\r\ncluster38-003 14d\r\ncluster38-004 14d\r\nkosmos-control-cluster-001 48d\r\nkosmos-control-cluster-002 48d\r\nkosmos-control-cluster-003 49d\r\nkosmos-control-cluster-004 49d\r\nkosmos-control-cluster-005 45d\r\nkosmos-control-cluster-006 45d\r\nkosmos-control-cluster-007 45d\n"})}),"\n",(0,r.jsx)(t.h4,{id:"create-test-pods",children:"Create Test Pods"}),"\n",(0,r.jsx)(t.p,{children:"Verify the cross-cluster container network connectivity by creating Pods in the kosmos-control-cluster and cluster38 clusters.\r\nTo ensure the containers have common network utilities such as Ping and Curl, use the clusterlink-floater image.\r\nMore details about the Floater feature will be provided in subsequent sections. Here is a sample YAML to create the Pods:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:'---\r\napiVersion: v1\r\nkind: ServiceAccount\r\nmetadata:\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\n---\r\napiVersion: rbac.authorization.k8s.io/v1\r\nkind: ClusterRole\r\nmetadata:\r\n name: clusterlink-floater\r\nrules:\r\n - apiGroups: [\'*\']\r\n resources: [\'*\']\r\n verbs: ["*"]\r\n - nonResourceURLs: [\'*\']\r\n verbs: ["get"]\r\n---\r\napiVersion: rbac.authorization.k8s.io/v1\r\nkind: ClusterRoleBinding\r\nmetadata:\r\n name: clusterlink-floater\r\nroleRef:\r\n apiGroup: rbac.authorization.k8s.io\r\n kind: ClusterRole\r\n name: clusterlink-floater\r\nsubjects:\r\n - kind: ServiceAccount\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\n---\r\napiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\nspec:\r\n replicas: 1\r\n selector:\r\n matchLabels:\r\n app: clusterlink-floater\r\n template:\r\n metadata:\r\n labels:\r\n app: clusterlink-floater\r\n spec:\r\n hostNetwork: false\r\n serviceAccountName: clusterlink-floater\r\n containers:\r\n - name: floater\r\n image: ghcr.io/kosmos-io/clusterlink-floater:v0.2.0-lts\r\n imagePullPolicy: IfNotPresent\r\n command:\r\n - clusterlink-floater\r\n securityContext:\r\n privileged: true\r\n env:\r\n - name: "PORT"\r\n value: "8889"\r\n - name: "ENABLE_ANALYSIS"\r\n value: "false"\r\n affinity:\r\n nodeAffinity:\r\n requiredDuringSchedulingIgnoredDuringExecution:\r\n nodeSelectorTerms:\r\n - matchExpressions:\r\n - key: kosmos.io/exclude\r\n operator: DoesNotExist\r\n tolerations:\r\n - effect: NoSchedule\r\n operator: Exists\r\n - key: CriticalAddonsOnly\r\n operator: Exists\r\n - effect: NoExecute\r\n operator: Exists\n'})}),"\n",(0,r.jsx)(t.admonition,{title:"NOTE",type:"info",children:(0,r.jsx)(t.p,{children:"The provided test case in this section can only check the container network connectivity between nodes in two clusters.\r\nTo quickly test all nodes in the cluster, please refer to section 5."})}),"\n",(0,r.jsx)(t.p,{children:"Make sure the Pods are running successfully in the kosmos-control-cluster and cluster38 clusters:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"[root@kosmos-control-cluster yaml]# kubectl -n kosmos-system get pod\r\nNAME READY STATUS RESTARTS AGE\r\nclusterlink-agent-6qq4v 1/1 Running 0 15d\r\nclusterlink-agent-6v9jm 1/1 Running 0 15d\r\nclusterlink-agent-7zpf5 1/1 Running 0 15d\r\nclusterlink-agent-84d68 1/1 Running 0 15d\r\nclusterlink-agent-dj9q2 1/1 Running 0 26h\r\nclusterlink-agent-r2zj4 1/1 Running 0 15d\r\nclusterlink-agent-vlh2x 1/1 Running 0 3d3h\r\nclusterlink-controller-manager-6774ddd58b-bcn7s 1/1 Running 0 15d\r\nclusterlink-elector-6b597b44f7-jrbg6 1/1 Running 0 15d\r\nclusterlink-elector-6b597b44f7-mj882 1/1 Running 0 15d\r\nclusterlink-floater-7dcb47579-lddgc 1/1 Running 0 77s\r\nclusterlink-network-manager-6489597986-h74m4 1/1 Running 0 15d\r\nclustertree-cluster-manager-6778bd7b6c-mwhpj 1/1 Running 0 5h45m\r\nkosmos-operator-c88898f66-b8mjl 1/1 Running 0 15d\r\nkosmos-scheduler-7dcfd94bf7-2km8m 1/1 Running 0 8d\r\n\r\n[root@cluster38 yaml]# kubectl -n kosmos-system get pod\r\nNAME READY STATUS RESTARTS AGE\r\nclusterlink-agent-jsv2b 1/1 Running 0 14d\r\nclusterlink-agent-qncxt 1/1 Running 0 14d\r\nclusterlink-agent-rzngm 1/1 Running 0 14d\r\nclusterlink-agent-s252r 1/1 Running 0 14d\r\nclusterlink-controller-manager-77fbbd9f78-bz47t 1/1 Running 0 14d\r\nclusterlink-elector-86b49775b5-x4gsp 1/1 Running 0 14d\r\nclusterlink-elector-86b49775b5-z4lb5 1/1 Running 0 14d\r\nclusterlink-floater-7dcb47579-jx85c 1/1 Running 0 16s\n"})}),"\n",(0,r.jsx)(t.p,{children:"Get the IP addresses of the two Pods and enter the container of either Pod to execute the Ping command to verify the inter-cluster container network connectivity.\r\nHere is an example:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"[root@cluster38 yaml]# kubectl -n kosmos-system get pod clusterlink-floater-7dcb47579-jx85c -oyaml |grep ip\r\n - ip: 10.*.*.253\r\n - ip: fd11:1111:*:*:*:*:4573:f17d\r\n\r\n[root@kosmos-control-cluster yaml]# kubectl -n kosmos-system exec -it clusterlink-floater-7dcb47579-lddgc -- sh\r\n/ # ping 10.*.*.253\r\nPING 10.*.*.253 (10.*.*.253): 56 data bytes\r\n64 bytes from 10.*.*.253: seq=0 ttl=62 time=0.592 ms\r\n64 bytes from 10.*.*.253: seq=1 ttl=62 time=0.362 ms\r\n64 bytes from 10.*.*.253: seq=2 ttl=62 time=0.388 ms\r\n64 bytes from 10.*.*.253: seq=3 ttl=62 time=0.373 ms\r\n^C\r\n--- 10.*.*.253 ping statistics ---\r\n4 packets transmitted, 4 packets received, 0% packet loss\r\nround-trip min/avg/max = 0.362/0.428/0.592 ms\r\n/ # ping -6 fd11:1111:*:*:*:*:4573:f17d\r\nPING fd11:1111:*:*:*:*:4573:f17d (fd11:1111:*:*:*:*:4573:f17d): 56 data bytes\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=0 ttl=62 time=0.679 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=1 ttl=62 time=0.492 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=2 ttl=62 time=0.406 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=3 ttl=62 time=1.488 ms\r\n^C\r\n--- fd11:1111:*:*:*:*:4573:f17d ping statistics ---\r\n4 packets transmitted, 4 packets received, 0% packet loss\r\nround-trip min/avg/max = 0.406/0.766/1.488 ms\n"})}),"\n",(0,r.jsx)(t.h3,{id:"one-click-diagnostic-for-cluster-connectivity",children:"One-Click Diagnostic for Cluster Connectivity"}),"\n",(0,r.jsx)(t.p,{children:"The Cluster Connectivity Diagnostic (Floater) feature was developed to address the challenge of continuously checking the network connectivity between multiple Kubernetes clusters when using Kosmos.\r\nWhen the number of clusters is small, such as only two clusters, this task may not be difficult.\r\nHowever, when the number of clusters reaches 5000 or even more, even the most enthusiastic operations personnel would find it nearly impossible to complete this task."}),"\n",(0,r.jsx)(t.p,{children:"To address this, we designed the Floater feature, which floats on every node in a cluster.\r\nThrough the kosmosctl tool, you can diagnose the network connectivity between multiple Kubernetes clusters with just one command.\r\nThe architecture of the ClusterLink Floater is as follows:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"MCN Floater_Flow.png",src:n(8940).c+"",width:"1261",height:"836"})}),"\n",(0,r.jsx)(t.p,{children:'The kosmosctl command line tool provides a one-click diagnostic command "dr" to easily validate the network connectivity between multiple Kubernetes clusters, including but not limited to host network, container network, and native cluster network.\r\nHere is an example:'}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"# Verify cross-cluster host network\r\nkosmosctl dr -r ghcr.io/kosmos-io/komos --src-kubeconfig root-config --dst-kubeconfig cluster38-config --host-network\r\n\r\n# Verify cross-cluster container network\r\nkosmosctl dr -r ghcr.io/kosmos-io/komos --src-kubeconfig root-config --dst-kubeconfig cluster38-config\n"})})]})}function d(e={}){const{wrapper:t}={...(0,s.M)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},8940:(e,t,n)=>{n.d(t,{c:()=>r});const r=n.p+"assets/images/MCN_Floater_Flow-5eacf7d674beab610c33fa93723b0c35.png"},208:(e,t,n)=>{n.d(t,{c:()=>r});const r=n.p+"assets/images/MCN_GW_Architecture-ad8eb15c31035ee0af215d29bceb17cf.png"},4032:(e,t,n)=>{n.d(t,{c:()=>r});const r=n.p+"assets/images/MCN_P2P_Architecture-9554e1fd1efbac70fe5576731eb95ed3.png"},2172:(e,t,n)=>{n.d(t,{I:()=>l,M:()=>i});var r=n(1504);const s={},o=r.createContext(s);function i(e){const t=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[192],{7140:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>d,frontMatter:()=>o,metadata:()=>l,toc:()=>a});var r=n(7624),s=n(2172);const o={id:"mcn-connectivity",title:"Multi-cluster Network Connectivity"},i="Multi-cluster Network Connectivity",l={id:"v0.2.0/tutorials/mcn-connectivity",title:"Multi-cluster Network Connectivity",description:"The Clusterlink design of the Kosmos multi-cluster solution aims to interconnect the nodes and resources of multiple Kubernetes clusters, forming a unified resource pool.",source:"@site/docs/v0.2.0/tutorials/multi-cluster-network.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/mcn-connectivity",permalink:"/website/v0.2.0/tutorials/mcn-connectivity",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/multi-cluster-network.md",tags:[],version:"current",lastUpdatedBy:"renxiangyu",lastUpdatedAt:1710063238,formattedLastUpdatedAt:"Mar 10, 2024",frontMatter:{id:"mcn-connectivity",title:"Multi-cluster Network Connectivity"},sidebar:"tutorialSidebar",previous:{title:"Multi-cluster Scheduler",permalink:"/website/v0.2.0/tutorials/mc-scheduler"},next:{title:"Multi-cluster PV/PVC Dynamic Storage",permalink:"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage"}},c={},a=[{value:"Multi-cluster Container Network Solution",id:"multi-cluster-container-network-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Design",id:"design",level:3},{value:"Prerequisites",id:"prerequisites",level:3},{value:"Install Kosmos",id:"install-kosmos",level:4},{value:"Join the Leaf Cluster",id:"join-the-leaf-cluster",level:4},{value:"Across Cluster L3 Network Connectivity",id:"across-cluster-l3-network-connectivity",level:3},{value:"Gateway Mode",id:"gateway-mode",level:4},{value:"P2P Mode",id:"p2p-mode",level:4},{value:"Starting ClusterLink",id:"starting-clusterlink",level:3},{value:"Using P2P Mode",id:"using-p2p-mode",level:4},{value:"Create Test Pods",id:"create-test-pods",level:4},{value:"One-Click Diagnostic for Cluster Connectivity",id:"one-click-diagnostic-for-cluster-connectivity",level:3}];function u(e){const t={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",p:"p",pre:"pre",...(0,s.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"multi-cluster-network-connectivity",children:"Multi-cluster Network Connectivity"}),"\n",(0,r.jsx)(t.p,{children:"The Clusterlink design of the Kosmos multi-cluster solution aims to interconnect the nodes and resources of multiple Kubernetes clusters, forming a unified resource pool.\r\nOne of the foundations for achieving this is the need to build a multi-cluster network architecture to meet the communication requirements between different clusters."}),"\n",(0,r.jsx)(t.h2,{id:"multi-cluster-container-network-solution",children:"Multi-cluster Container Network Solution"}),"\n",(0,r.jsx)(t.h3,{id:"introduction",children:"Introduction"}),"\n",(0,r.jsx)(t.p,{children:"Clusterlink includes two network modes: Gateway and P2P. In the Gateway mode, when a data packet is sent by a Pod on the left, it first goes through the vx-local tunnel within the cluster to reach the Gateway node of that cluster.\r\nIt then traverses the cross-cluster tunnel to reach the counterpart cluster.\r\nOnce the data packet arrives at the counterpart cluster, it is handled by the CNI and follows the single-cluster network to reach the target Pod.\r\nThis mode has its advantages and disadvantages.\r\nThe advantage is that each cluster only needs one node (or two for high availability) to provide external access, making it suitable for multi-cloud and hybrid cloud scenarios.\r\nThe disadvantage is that due to the longer network path, there is a certain performance loss.\r\nTo address this issue, Clusterlink provides the P2P mode, which is suitable for scenarios with higher network performance requirements.\r\nIn this mode, the data packets are directly sent to the node where the counterpart Pod is located.\r\nAdditionally, the P2P and Gateway modes can be used in combination."}),"\n",(0,r.jsx)(t.h3,{id:"design",children:"Design"}),"\n",(0,r.jsx)(t.p,{children:"The architecture of the Kosmos multi-cluster network Gateway solution is as follows:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"MCN GW_Architecture.png",src:n(208).c+"",width:"1019",height:"287"})}),"\n",(0,r.jsx)(t.admonition,{title:"NOTE",type:"info",children:(0,r.jsx)(t.p,{children:"It provides strong compatibility, requiring only one node per cluster (or two for high availability) to provide external access, making it suitable for cross-cloud scenarios."})}),"\n",(0,r.jsx)(t.p,{children:"The architecture of the Kosmos multi-cluster network P2P solution is as follows:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"MCN P2P_Architecture.png",src:n(4032).c+"",width:"1019",height:"310"})}),"\n",(0,r.jsx)(t.admonition,{title:"NOTE",type:"info",children:(0,r.jsx)(t.p,{children:"It has shorter network paths and better performance, making it suitable for fully interconnected Underlay scenarios."})}),"\n",(0,r.jsx)(t.h3,{id:"prerequisites",children:"Prerequisites"}),"\n",(0,r.jsx)(t.h4,{id:"install-kosmos",children:"Install Kosmos"}),"\n",(0,r.jsxs)(t.p,{children:["Refer to the Kosmos Quick Start documentation ",(0,r.jsx)(t.a,{href:"https://github.com/kosmos-io/kosmos",children:"https://github.com/kosmos-io/kosmos"})," and enable the ClusterLink module for multi-cluster networking. Using the kosmosctl tool:"]}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:'kosmosctl install --cni calico --default-nic eth0 (We build a network tunnel based on the network interface value passed by the arg "default-nic")\n'})}),"\n",(0,r.jsx)(t.h4,{id:"join-the-leaf-cluster",children:"Join the Leaf Cluster"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"kosmosctl join cluster --name cluster1 --kubeconfig ~/kubeconfig/cluster1-kubeconfig --cni calico --default-nic eth0 --enable-link\n"})}),"\n",(0,r.jsx)(t.h3,{id:"across-cluster-l3-network-connectivity",children:"Across Cluster L3 Network Connectivity"}),"\n",(0,r.jsx)(t.p,{children:"To achieve cross-cluster L3 network connectivity in Kosmos, at least two different cluster nodes from each cluster need to be able to communicate with each other at the host machine network level, and the clusters must be correctly deployed and support VXLAN or IPSec technologies."}),"\n",(0,r.jsx)(t.h4,{id:"gateway-mode",children:"Gateway Mode"}),"\n",(0,r.jsx)(t.p,{children:"In each Kubernetes cluster within the Kosmos federation, one node is elected as the Gateway (GW) node using the Elector module.\r\nThe GW nodes of the two clusters communicate through the vx-bridge tunnel (created by Kosmos) to establish connectivity.\r\nWithin each cluster, routing is handled by the GW node.\r\nCompared to the P2P mode, the GW mode has slightly lower network performance due to the additional packet encapsulation and decapsulation at the GW node.\r\nHowever, the advantage is that the routing table and FDB table of the cluster nodes can remain almost the same as before.\r\nTherefore, the GW mode is suitable for larger-scale multi-cluster scenarios where network performance is not critical."}),"\n",(0,r.jsx)(t.h4,{id:"p2p-mode",children:"P2P Mode"}),"\n",(0,r.jsx)(t.p,{children:"In the P2P mode, there is no need to use the Elector module.\r\nKosmos creates vx-bridge interfaces on all nodes of each cluster to achieve direct container network communication between nodes of different clusters.\r\nThe network performance in this mode is almost the same as in a single Kubernetes cluster.\r\nHowever, in the P2P mode, every node in the cluster needs to configure access rules for all nodes in the Kosmos federation, resulting in larger routing and FDB table sizes.\r\nTherefore, the P2P mode is suitable for scenarios that require higher network performance but have a smaller number of nodes in each cluster."}),"\n",(0,r.jsx)(t.h3,{id:"starting-clusterlink",children:"Starting ClusterLink"}),"\n",(0,r.jsx)(t.h4,{id:"using-p2p-mode",children:"Using P2P Mode"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"# Complete the steps in sections 'Install Kosmos' & 'Join the Leaf Cluster'\r\n# Check if the clusters resource has been created correctly\r\n[root@kosmos-control-cluster yaml]# kubectl --kubeconfig config-14 get clusters.kosmos.io\r\nNAME NETWORK_TYPE IP_FAMILY\r\ncluster38 p2p all\r\nkosmos-control-cluster p2p all\r\n\r\n# Check if the clusternodes resource has been created correctly\r\n[root@kosmos-control-cluster yaml]# kubectl get clusternodes.kosmos.io\r\nNAME ROLES INTERFACE IP\r\ncluster38-001 bond0.1820 10.*.*.38\r\ncluster38-002 bond0.1820 10.*.*.39\r\ncluster38-003 bond0.1830 10.*.*.94\r\ncluster38-004 [\"gateway\"] bond0.1830 10.*.*.95\r\nkosmos-control-cluster-001 bond0.1820 10.*.*.14\r\nkosmos-control-cluster-002 bond0.1820 10.*.*.15\r\nkosmos-control-cluster-003 [\"gateway\"] bond0.1565 10.*.*.38\r\nkosmos-control-cluster-004 bond0.1565 10.*.*.31\r\nkosmos-control-cluster-005 bond0.1565 10.*.*.32\r\nkosmos-control-cluster-006 bond0.1565 10.*.*.33\r\nkosmos-control-cluster-007 bond0.1565 10.*.*.37\r\n\r\n# Check if the nodeconfigs resource has been created correctly\r\n[root@kosmos-control-cluster yaml]# kubectl get nodeconfigs.kosmos.io\r\nNAME AGE\r\ncluster38-001 14d\r\ncluster38-002 14d\r\ncluster38-003 14d\r\ncluster38-004 14d\r\nkosmos-control-cluster-001 48d\r\nkosmos-control-cluster-002 48d\r\nkosmos-control-cluster-003 49d\r\nkosmos-control-cluster-004 49d\r\nkosmos-control-cluster-005 45d\r\nkosmos-control-cluster-006 45d\r\nkosmos-control-cluster-007 45d\n"})}),"\n",(0,r.jsx)(t.h4,{id:"create-test-pods",children:"Create Test Pods"}),"\n",(0,r.jsx)(t.p,{children:"Verify the cross-cluster container network connectivity by creating Pods in the kosmos-control-cluster and cluster38 clusters.\r\nTo ensure the containers have common network utilities such as Ping and Curl, use the clusterlink-floater image.\r\nMore details about the Floater feature will be provided in subsequent sections. Here is a sample YAML to create the Pods:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:'---\r\napiVersion: v1\r\nkind: ServiceAccount\r\nmetadata:\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\n---\r\napiVersion: rbac.authorization.k8s.io/v1\r\nkind: ClusterRole\r\nmetadata:\r\n name: clusterlink-floater\r\nrules:\r\n - apiGroups: [\'*\']\r\n resources: [\'*\']\r\n verbs: ["*"]\r\n - nonResourceURLs: [\'*\']\r\n verbs: ["get"]\r\n---\r\napiVersion: rbac.authorization.k8s.io/v1\r\nkind: ClusterRoleBinding\r\nmetadata:\r\n name: clusterlink-floater\r\nroleRef:\r\n apiGroup: rbac.authorization.k8s.io\r\n kind: ClusterRole\r\n name: clusterlink-floater\r\nsubjects:\r\n - kind: ServiceAccount\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\n---\r\napiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\nspec:\r\n replicas: 1\r\n selector:\r\n matchLabels:\r\n app: clusterlink-floater\r\n template:\r\n metadata:\r\n labels:\r\n app: clusterlink-floater\r\n spec:\r\n hostNetwork: false\r\n serviceAccountName: clusterlink-floater\r\n containers:\r\n - name: floater\r\n image: ghcr.io/kosmos-io/clusterlink-floater:v0.2.0-lts\r\n imagePullPolicy: IfNotPresent\r\n command:\r\n - clusterlink-floater\r\n securityContext:\r\n privileged: true\r\n env:\r\n - name: "PORT"\r\n value: "8889"\r\n - name: "ENABLE_ANALYSIS"\r\n value: "false"\r\n affinity:\r\n nodeAffinity:\r\n requiredDuringSchedulingIgnoredDuringExecution:\r\n nodeSelectorTerms:\r\n - matchExpressions:\r\n - key: kosmos.io/exclude\r\n operator: DoesNotExist\r\n tolerations:\r\n - effect: NoSchedule\r\n operator: Exists\r\n - key: CriticalAddonsOnly\r\n operator: Exists\r\n - effect: NoExecute\r\n operator: Exists\n'})}),"\n",(0,r.jsx)(t.admonition,{title:"NOTE",type:"info",children:(0,r.jsx)(t.p,{children:"The provided test case in this section can only check the container network connectivity between nodes in two clusters.\r\nTo quickly test all nodes in the cluster, please refer to section 5."})}),"\n",(0,r.jsx)(t.p,{children:"Make sure the Pods are running successfully in the kosmos-control-cluster and cluster38 clusters:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"[root@kosmos-control-cluster yaml]# kubectl -n kosmos-system get pod\r\nNAME READY STATUS RESTARTS AGE\r\nclusterlink-agent-6qq4v 1/1 Running 0 15d\r\nclusterlink-agent-6v9jm 1/1 Running 0 15d\r\nclusterlink-agent-7zpf5 1/1 Running 0 15d\r\nclusterlink-agent-84d68 1/1 Running 0 15d\r\nclusterlink-agent-dj9q2 1/1 Running 0 26h\r\nclusterlink-agent-r2zj4 1/1 Running 0 15d\r\nclusterlink-agent-vlh2x 1/1 Running 0 3d3h\r\nclusterlink-controller-manager-6774ddd58b-bcn7s 1/1 Running 0 15d\r\nclusterlink-elector-6b597b44f7-jrbg6 1/1 Running 0 15d\r\nclusterlink-elector-6b597b44f7-mj882 1/1 Running 0 15d\r\nclusterlink-floater-7dcb47579-lddgc 1/1 Running 0 77s\r\nclusterlink-network-manager-6489597986-h74m4 1/1 Running 0 15d\r\nclustertree-cluster-manager-6778bd7b6c-mwhpj 1/1 Running 0 5h45m\r\nkosmos-operator-c88898f66-b8mjl 1/1 Running 0 15d\r\nkosmos-scheduler-7dcfd94bf7-2km8m 1/1 Running 0 8d\r\n\r\n[root@cluster38 yaml]# kubectl -n kosmos-system get pod\r\nNAME READY STATUS RESTARTS AGE\r\nclusterlink-agent-jsv2b 1/1 Running 0 14d\r\nclusterlink-agent-qncxt 1/1 Running 0 14d\r\nclusterlink-agent-rzngm 1/1 Running 0 14d\r\nclusterlink-agent-s252r 1/1 Running 0 14d\r\nclusterlink-controller-manager-77fbbd9f78-bz47t 1/1 Running 0 14d\r\nclusterlink-elector-86b49775b5-x4gsp 1/1 Running 0 14d\r\nclusterlink-elector-86b49775b5-z4lb5 1/1 Running 0 14d\r\nclusterlink-floater-7dcb47579-jx85c 1/1 Running 0 16s\n"})}),"\n",(0,r.jsx)(t.p,{children:"Get the IP addresses of the two Pods and enter the container of either Pod to execute the Ping command to verify the inter-cluster container network connectivity.\r\nHere is an example:"}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"[root@cluster38 yaml]# kubectl -n kosmos-system get pod clusterlink-floater-7dcb47579-jx85c -oyaml |grep ip\r\n - ip: 10.*.*.253\r\n - ip: fd11:1111:*:*:*:*:4573:f17d\r\n\r\n[root@kosmos-control-cluster yaml]# kubectl -n kosmos-system exec -it clusterlink-floater-7dcb47579-lddgc -- sh\r\n/ # ping 10.*.*.253\r\nPING 10.*.*.253 (10.*.*.253): 56 data bytes\r\n64 bytes from 10.*.*.253: seq=0 ttl=62 time=0.592 ms\r\n64 bytes from 10.*.*.253: seq=1 ttl=62 time=0.362 ms\r\n64 bytes from 10.*.*.253: seq=2 ttl=62 time=0.388 ms\r\n64 bytes from 10.*.*.253: seq=3 ttl=62 time=0.373 ms\r\n^C\r\n--- 10.*.*.253 ping statistics ---\r\n4 packets transmitted, 4 packets received, 0% packet loss\r\nround-trip min/avg/max = 0.362/0.428/0.592 ms\r\n/ # ping -6 fd11:1111:*:*:*:*:4573:f17d\r\nPING fd11:1111:*:*:*:*:4573:f17d (fd11:1111:*:*:*:*:4573:f17d): 56 data bytes\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=0 ttl=62 time=0.679 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=1 ttl=62 time=0.492 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=2 ttl=62 time=0.406 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=3 ttl=62 time=1.488 ms\r\n^C\r\n--- fd11:1111:*:*:*:*:4573:f17d ping statistics ---\r\n4 packets transmitted, 4 packets received, 0% packet loss\r\nround-trip min/avg/max = 0.406/0.766/1.488 ms\n"})}),"\n",(0,r.jsx)(t.h3,{id:"one-click-diagnostic-for-cluster-connectivity",children:"One-Click Diagnostic for Cluster Connectivity"}),"\n",(0,r.jsx)(t.p,{children:"The Cluster Connectivity Diagnostic (Floater) feature was developed to address the challenge of continuously checking the network connectivity between multiple Kubernetes clusters when using Kosmos.\r\nWhen the number of clusters is small, such as only two clusters, this task may not be difficult.\r\nHowever, when the number of clusters reaches 5000 or even more, even the most enthusiastic operations personnel would find it nearly impossible to complete this task."}),"\n",(0,r.jsx)(t.p,{children:"To address this, we designed the Floater feature, which floats on every node in a cluster.\r\nThrough the kosmosctl tool, you can diagnose the network connectivity between multiple Kubernetes clusters with just one command.\r\nThe architecture of the ClusterLink Floater is as follows:"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"MCN Floater_Flow.png",src:n(8940).c+"",width:"1261",height:"836"})}),"\n",(0,r.jsx)(t.p,{children:'The kosmosctl command line tool provides a one-click diagnostic command "dr" to easily validate the network connectivity between multiple Kubernetes clusters, including but not limited to host network, container network, and native cluster network.\r\nHere is an example:'}),"\n",(0,r.jsx)(t.pre,{children:(0,r.jsx)(t.code,{className:"language-shell",metastring:"script",children:"# Verify cross-cluster host network\r\nkosmosctl dr -r ghcr.io/kosmos-io/komos --src-kubeconfig root-config --dst-kubeconfig cluster38-config --host-network\r\n\r\n# Verify cross-cluster container network\r\nkosmosctl dr -r ghcr.io/kosmos-io/komos --src-kubeconfig root-config --dst-kubeconfig cluster38-config\n"})})]})}function d(e={}){const{wrapper:t}={...(0,s.M)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(u,{...e})}):u(e)}},8940:(e,t,n)=>{n.d(t,{c:()=>r});const r=n.p+"assets/images/MCN_Floater_Flow-5eacf7d674beab610c33fa93723b0c35.png"},208:(e,t,n)=>{n.d(t,{c:()=>r});const r=n.p+"assets/images/MCN_GW_Architecture-ad8eb15c31035ee0af215d29bceb17cf.png"},4032:(e,t,n)=>{n.d(t,{c:()=>r});const r=n.p+"assets/images/MCN_P2P_Architecture-9554e1fd1efbac70fe5576731eb95ed3.png"},2172:(e,t,n)=>{n.d(t,{I:()=>l,M:()=>i});var r=n(1504);const s={},o=r.createContext(s);function i(e){const t=r.useContext(o);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:i(e.components),r.createElement(o.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/63590f5d.862d8a8e.js b/docs/assets/js/63590f5d.b5f4d1d6.js similarity index 84% rename from docs/assets/js/63590f5d.862d8a8e.js rename to docs/assets/js/63590f5d.b5f4d1d6.js index d77ce6b..5910ea9 100644 --- a/docs/assets/js/63590f5d.862d8a8e.js +++ b/docs/assets/js/63590f5d.b5f4d1d6.js @@ -1 +1 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[372],{2088:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>d});var n=t(7624),i=t(2172);const o={id:"introduction",title:"Introduction"},r="Introduction",l={id:"v0.2.0/getting-started/introduction",title:"Introduction",description:"What is Kosmos?",source:"@site/docs/v0.2.0/getting-started/introduction.md",sourceDirName:"v0.2.0/getting-started",slug:"/v0.2.0/getting-started/introduction",permalink:"/website/v0.2.0/getting-started/introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/getting-started/introduction.md",tags:[],version:"current",lastUpdatedBy:"duanmengkk",lastUpdatedAt:1710293310,formattedLastUpdatedAt:"Mar 13, 2024",frontMatter:{id:"introduction",title:"Introduction"},sidebar:"tutorialSidebar",next:{title:"Quick Start",permalink:"/website/v0.2.0/quick-start"}},c={},d=[{value:"What is Kosmos?",id:"what-is-kosmos",level:2},{value:"ClusterLink",id:"clusterlink",level:2},{value:"Network Architecture",id:"network-architecture",level:3},{value:"ClusterTree",id:"clustertree",level:2},{value:"Scheduler",id:"scheduler",level:2},{value:"What's Next",id:"whats-next",level:2}];function a(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(s.h2,{id:"what-is-kosmos",children:"What is Kosmos?"}),"\n",(0,n.jsx)(s.p,{children:"Kosmos is an open-source, all-in-one distributed cloud-native solution. The name \"kosmos\" combines 'k' representing Kubernetes and 'cosmos' which means universe in Greek, symbolizing the limitless expansion of Kubernetes."}),"\n",(0,n.jsxs)(s.p,{children:["Currently, Kosmos primarily consists of three major modules: ",(0,n.jsx)(s.code,{children:"ClusterLink"}),", ",(0,n.jsx)(s.code,{children:"ClusterTree"})," and ",(0,n.jsx)(s.code,{children:"Scheduler"}),"."]}),"\n",(0,n.jsx)(s.h2,{id:"clusterlink",children:"ClusterLink"}),"\n",(0,n.jsxs)(s.p,{children:["The target of ClusterLink is to establish connectivity between multiple Kubernetes clusters. This module can be deployed and used independently. ClusterLink enables ",(0,n.jsx)(s.code,{children:"Pods"})," to access ",(0,n.jsx)(s.code,{children:"Pods"})," and ",(0,n.jsx)(s.code,{children:"Services"})," across clusters, as if they were in the single cluster. Currently, this module primarily offers the following ability:"]}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Cross-cluster PodIP and ServiceIP communication"}),": L3 network connections across multiple Kubernetes clusters, based on tunneling technologies such as VxLAN and IPsec. This allows users to conduct ",(0,n.jsx)(s.code,{children:"Pod-to-Pod"})," and ",(0,n.jsx)(s.code,{children:"Pod-to-Service"})," communication within the global clusters scope."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Multi-Mode Support"}),": When join clusters, you can choose ",(0,n.jsx)(s.code,{children:"P2P"})," or ",(0,n.jsx)(s.code,{children:"Gateway"})," mode. The P2P model provides a second-layer network interconnection at the overlay level, offering shorter network paths and superior performance. When selecting the ",(0,n.jsx)(s.code,{children:"Gateway"})," mode, it demonstrates superior compatibility, which is well-suited for hybrid and multi-cloud scenarios."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Support for Global IP Allocation"}),": ClusterLink allows for the presence of two or more clusters within the global clusters to use the same ",(0,n.jsx)(s.code,{children:"Pod/Service"})," network segments, making it convenient for users to manage subnet. ClusterLink supports configuring the mapping relationship between ",(0,n.jsx)(s.code,{children:"PodCIDR/ServiceCIDR"})," and ",(0,n.jsx)(s.code,{children:"GlobalCIDR"}),". ",(0,n.jsx)(s.code,{children:"GlobalIP"})," is globally unique, enabling cross-cluster communication for services with conflicting network segments through ",(0,n.jsx)(s.code,{children:"GlobalIP"}),"."]}),"\n",(0,n.jsx)(s.li,{children:(0,n.jsx)(s.strong,{children:"IPv6/IPv4 Dual-Stack Support"})}),"\n"]}),"\n",(0,n.jsx)(s.h3,{id:"network-architecture",children:"Network Architecture"}),"\n",(0,n.jsxs)(s.p,{children:["The Kosmos ClusterLink module currently includes the following key components:\r\n",(0,n.jsx)(s.img,{alt:"ClusterLink_Architecture.png",src:t(4052).c+"",width:"2000",height:"1066"})]}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Controller-Manager"}),"\uff1aCollect network information of the current cluster and monitors changes in network settings."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Network-manager"}),"\uff1aCalculates the network configurations required for each node."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Agent"}),"\uff1aA DaemonSet used for configuring the host network, including tasks such as tunnel creation, routing, NAT, and so on."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Multi-Cluster-Coredns"}),"\uff1aImplements multi-cluster service discovery."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Elector"}),"\uff1aElects the gateway node."]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"clustertree",children:"ClusterTree"}),"\n",(0,n.jsxs)(s.p,{children:["The Kosmos clustertree module realizes the tree-like scaling of Kubernetes and achieves cross-cluster orchestration of applications.This is the technological foundation for Kosmos to achieve boundless of Kubernetes.\r\n",(0,n.jsx)(s.img,{alt:"ClusterTree_Architecture.png",src:t(4503).c+"",width:"1920",height:"1496"})]}),"\n",(0,n.jsx)(s.p,{children:"Currently, it primarily supports the following ability:"}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Full Compatibility with k8s API"}),": Users can interact with the host cluster's ",(0,n.jsx)(s.code,{children:"kube-apiserver"})," using tools like ",(0,n.jsx)(s.code,{children:"kubectl"}),", ",(0,n.jsx)(s.code,{children:"client-go"}),", and others just like they normally would. However, the ",(0,n.jsx)(s.code,{children:"Pods"})," are actually distributed across the entire multi-cloud, multi-cluster environment."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Support for Stateful and k8s-native Applications"}),": In addition to stateless applications, Kosmos also facilitates the orchestration of stateful applications and k8s-native applications (interacting with ",(0,n.jsx)(s.code,{children:"kube-apiserver"}),"). Kosmos will automatically detect the storage and permission resources that ",(0,n.jsx)(s.code,{children:"Pods"})," depend on, such as pv/pvc, sa, etc., and perform bidirectional synchronization between control plane clusters and data plane clusters."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Diverse Pod Topology Constraints"}),": Users can easily control the distribution of Pods within the global clusters, such as by region, availability zone, cluster, or node. This helps achieve high availability and improve resource utilization."]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"scheduler",children:"Scheduler"}),"\n",(0,n.jsx)(s.p,{children:"The Kosmos scheduling module is an extension developed on top of the Kubernetes scheduling framework, aiming to meet the container management needs in mixed-node and sub-cluster environments. It provides the following core features to enhance the flexibility and efficiency of container management:"}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Flexible Node and Cluster Hybrid Scheduling"}),": The Kosmos scheduling module allows users to intelligently schedule workloads between real nodes and sub-clusters based on custom configurations. This enables users to make optimal use of resources across different nodes, ensuring the best performance and availability of workloads. Based on this capability, Kosmos enables workloads to achieve flexible cross-cloud and cross-cluster deployments."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Fine-grained Container Distribution Strategy"}),": By introducing Custom Resource Definitions (CRD), users can exert precise control over the distribution of workloads. The configuration of CRD allows users to explicitly specify the number of pods for the workload in different clusters and adjust the distribution ratio as needed."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Fine-grained Fragmented Resource Handling"}),": The Kosmos scheduling module intelligently detects fragmented resources within sub-clusters, effectively avoiding situations where pod deployment encounters insufficient resources in the sub-cluster. This helps ensure a more balanced allocation of resources across different nodes, enhancing system stability and performance."]}),"\n"]}),"\n",(0,n.jsx)(s.p,{children:"Whether building a hybrid cloud environment or requiring flexible deployment of workloads across different clusters, the Kosmos scheduling module serves as a reliable solution, assisting users in managing containerized applications more efficiently."}),"\n",(0,n.jsx)(s.h2,{id:"whats-next",children:"What's Next"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Start to ",(0,n.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/quick-start",children:"install Kosmos"}),"."]}),"\n",(0,n.jsxs)(s.li,{children:["Learn Kosmos's ",(0,n.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/tutorials/mcs-discovery",children:"tutorials"}),"."]}),"\n",(0,n.jsxs)(s.li,{children:["Learn Kosmos's ",(0,n.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/proposals/k8s-in-k8s",children:"proposals"}),"."]}),"\n"]})]})}function u(e={}){const{wrapper:s}={...(0,i.M)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},4052:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/ClusterLink_Architecture-156348f81f4d7537d0c514541c0978c9.png"},4503:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/ClusterTree_Architecture-ec1f02d3c150b9cc505a94e9e7b70abe.png"},2172:(e,s,t)=>{t.d(s,{I:()=>l,M:()=>r});var n=t(1504);const i={},o=n.createContext(i);function r(e){const s=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[372],{2088:(e,s,t)=>{t.r(s),t.d(s,{assets:()=>c,contentTitle:()=>r,default:()=>u,frontMatter:()=>o,metadata:()=>l,toc:()=>d});var n=t(7624),i=t(2172);const o={id:"introduction",title:"Introduction"},r="Introduction",l={id:"v0.2.0/getting-started/introduction",title:"Introduction",description:"What is Kosmos?",source:"@site/docs/v0.2.0/getting-started/introduction.md",sourceDirName:"v0.2.0/getting-started",slug:"/v0.2.0/getting-started/introduction",permalink:"/website/v0.2.0/getting-started/introduction",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/getting-started/introduction.md",tags:[],version:"current",lastUpdatedBy:"duanmengkk",lastUpdatedAt:1710293310,formattedLastUpdatedAt:"Mar 13, 2024",frontMatter:{id:"introduction",title:"Introduction"},sidebar:"tutorialSidebar",next:{title:"Quick Start",permalink:"/website/v0.2.0/quick-start"}},c={},d=[{value:"What is Kosmos?",id:"what-is-kosmos",level:2},{value:"ClusterLink",id:"clusterlink",level:2},{value:"Network Architecture",id:"network-architecture",level:3},{value:"ClusterTree",id:"clustertree",level:2},{value:"Scheduler",id:"scheduler",level:2},{value:"What's Next",id:"whats-next",level:2}];function a(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(s.h1,{id:"introduction",children:"Introduction"}),"\n",(0,n.jsx)(s.h2,{id:"what-is-kosmos",children:"What is Kosmos?"}),"\n",(0,n.jsx)(s.p,{children:"Kosmos is an open-source, all-in-one distributed cloud-native solution. The name \"kosmos\" combines 'k' representing Kubernetes and 'cosmos' which means universe in Greek, symbolizing the limitless expansion of Kubernetes."}),"\n",(0,n.jsxs)(s.p,{children:["Currently, Kosmos primarily consists of three major modules: ",(0,n.jsx)(s.code,{children:"ClusterLink"}),", ",(0,n.jsx)(s.code,{children:"ClusterTree"})," and ",(0,n.jsx)(s.code,{children:"Scheduler"}),"."]}),"\n",(0,n.jsx)(s.h2,{id:"clusterlink",children:"ClusterLink"}),"\n",(0,n.jsxs)(s.p,{children:["The target of ClusterLink is to establish connectivity between multiple Kubernetes clusters. This module can be deployed and used independently. ClusterLink enables ",(0,n.jsx)(s.code,{children:"Pods"})," to access ",(0,n.jsx)(s.code,{children:"Pods"})," and ",(0,n.jsx)(s.code,{children:"Services"})," across clusters, as if they were in the single cluster. Currently, this module primarily offers the following ability:"]}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Cross-cluster PodIP and ServiceIP communication"}),": L3 network connections across multiple Kubernetes clusters, based on tunneling technologies such as VxLAN and IPsec. This allows users to conduct ",(0,n.jsx)(s.code,{children:"Pod-to-Pod"})," and ",(0,n.jsx)(s.code,{children:"Pod-to-Service"})," communication within the global clusters scope."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Multi-Mode Support"}),": When join clusters, you can choose ",(0,n.jsx)(s.code,{children:"P2P"})," or ",(0,n.jsx)(s.code,{children:"Gateway"})," mode. The P2P model provides a second-layer network interconnection at the overlay level, offering shorter network paths and superior performance. When selecting the ",(0,n.jsx)(s.code,{children:"Gateway"})," mode, it demonstrates superior compatibility, which is well-suited for hybrid and multi-cloud scenarios."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Support for Global IP Allocation"}),": ClusterLink allows for the presence of two or more clusters within the global clusters to use the same ",(0,n.jsx)(s.code,{children:"Pod/Service"})," network segments, making it convenient for users to manage subnet. ClusterLink supports configuring the mapping relationship between ",(0,n.jsx)(s.code,{children:"PodCIDR/ServiceCIDR"})," and ",(0,n.jsx)(s.code,{children:"GlobalCIDR"}),". ",(0,n.jsx)(s.code,{children:"GlobalIP"})," is globally unique, enabling cross-cluster communication for services with conflicting network segments through ",(0,n.jsx)(s.code,{children:"GlobalIP"}),"."]}),"\n",(0,n.jsx)(s.li,{children:(0,n.jsx)(s.strong,{children:"IPv6/IPv4 Dual-Stack Support"})}),"\n"]}),"\n",(0,n.jsx)(s.h3,{id:"network-architecture",children:"Network Architecture"}),"\n",(0,n.jsxs)(s.p,{children:["The Kosmos ClusterLink module currently includes the following key components:\r\n",(0,n.jsx)(s.img,{alt:"ClusterLink_Architecture.png",src:t(4052).c+"",width:"2000",height:"1066"})]}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Controller-Manager"}),"\uff1aCollect network information of the current cluster and monitors changes in network settings."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Network-manager"}),"\uff1aCalculates the network configurations required for each node."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Agent"}),"\uff1aA DaemonSet used for configuring the host network, including tasks such as tunnel creation, routing, NAT, and so on."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Multi-Cluster-Coredns"}),"\uff1aImplements multi-cluster service discovery."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.code,{children:"Elector"}),"\uff1aElects the gateway node."]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"clustertree",children:"ClusterTree"}),"\n",(0,n.jsxs)(s.p,{children:["The Kosmos clustertree module realizes the tree-like scaling of Kubernetes and achieves cross-cluster orchestration of applications.This is the technological foundation for Kosmos to achieve boundless of Kubernetes.\r\n",(0,n.jsx)(s.img,{alt:"ClusterTree_Architecture.png",src:t(4503).c+"",width:"1920",height:"1496"})]}),"\n",(0,n.jsx)(s.p,{children:"Currently, it primarily supports the following ability:"}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Full Compatibility with k8s API"}),": Users can interact with the host cluster's ",(0,n.jsx)(s.code,{children:"kube-apiserver"})," using tools like ",(0,n.jsx)(s.code,{children:"kubectl"}),", ",(0,n.jsx)(s.code,{children:"client-go"}),", and others just like they normally would. However, the ",(0,n.jsx)(s.code,{children:"Pods"})," are actually distributed across the entire multi-cloud, multi-cluster environment."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Support for Stateful and k8s-native Applications"}),": In addition to stateless applications, Kosmos also facilitates the orchestration of stateful applications and k8s-native applications (interacting with ",(0,n.jsx)(s.code,{children:"kube-apiserver"}),"). Kosmos will automatically detect the storage and permission resources that ",(0,n.jsx)(s.code,{children:"Pods"})," depend on, such as pv/pvc, sa, etc., and perform bidirectional synchronization between control plane clusters and data plane clusters."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Diverse Pod Topology Constraints"}),": Users can easily control the distribution of Pods within the global clusters, such as by region, availability zone, cluster, or node. This helps achieve high availability and improve resource utilization."]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"scheduler",children:"Scheduler"}),"\n",(0,n.jsx)(s.p,{children:"The Kosmos scheduling module is an extension developed on top of the Kubernetes scheduling framework, aiming to meet the container management needs in mixed-node and sub-cluster environments. It provides the following core features to enhance the flexibility and efficiency of container management:"}),"\n",(0,n.jsxs)(s.ol,{children:["\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Flexible Node and Cluster Hybrid Scheduling"}),": The Kosmos scheduling module allows users to intelligently schedule workloads between real nodes and sub-clusters based on custom configurations. This enables users to make optimal use of resources across different nodes, ensuring the best performance and availability of workloads. Based on this capability, Kosmos enables workloads to achieve flexible cross-cloud and cross-cluster deployments."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Fine-grained Container Distribution Strategy"}),": By introducing Custom Resource Definitions (CRD), users can exert precise control over the distribution of workloads. The configuration of CRD allows users to explicitly specify the number of pods for the workload in different clusters and adjust the distribution ratio as needed."]}),"\n",(0,n.jsxs)(s.li,{children:[(0,n.jsx)(s.strong,{children:"Fine-grained Fragmented Resource Handling"}),": The Kosmos scheduling module intelligently detects fragmented resources within sub-clusters, effectively avoiding situations where pod deployment encounters insufficient resources in the sub-cluster. This helps ensure a more balanced allocation of resources across different nodes, enhancing system stability and performance.\r\nWhether building a hybrid cloud environment or requiring flexible deployment of workloads across different clusters, the Kosmos scheduling module serves as a reliable solution, assisting users in managing containerized applications more efficiently."]}),"\n"]}),"\n",(0,n.jsx)(s.h2,{id:"whats-next",children:"What's Next"}),"\n",(0,n.jsxs)(s.ul,{children:["\n",(0,n.jsxs)(s.li,{children:["Start to ",(0,n.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/quick-start",children:"install Kosmos"}),"."]}),"\n",(0,n.jsxs)(s.li,{children:["Learn Kosmos's ",(0,n.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/tutorials/mcs-discovery",children:"tutorials"}),"."]}),"\n",(0,n.jsxs)(s.li,{children:["Learn Kosmos's ",(0,n.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/proposals/k8s-in-k8s",children:"proposals"}),"."]}),"\n"]})]})}function u(e={}){const{wrapper:s}={...(0,i.M)(),...e.components};return s?(0,n.jsx)(s,{...e,children:(0,n.jsx)(a,{...e})}):a(e)}},4052:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/ClusterLink_Architecture-156348f81f4d7537d0c514541c0978c9.png"},4503:(e,s,t)=>{t.d(s,{c:()=>n});const n=t.p+"assets/images/ClusterTree_Architecture-ec1f02d3c150b9cc505a94e9e7b70abe.png"},2172:(e,s,t)=>{t.d(s,{I:()=>l,M:()=>r});var n=t(1504);const i={},o=n.createContext(i);function r(e){const s=n.useContext(o);return n.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:r(e.components),n.createElement(o.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/825101dc.218280ab.js b/docs/assets/js/825101dc.218280ab.js deleted file mode 100644 index 751b46a..0000000 --- a/docs/assets/js/825101dc.218280ab.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[412],{1672:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>t,contentTitle:()=>a,default:()=>p,frontMatter:()=>o,metadata:()=>l,toc:()=>c});var s=r(7624),i=r(2172);const o={id:"application-migration_zh",title:"\u5e94\u7528\u8fc1\u79fb"},a="\u5e94\u7528\u8fc1\u79fb",l={id:"i18n/zh/v0.2.0/application-migration_zh",title:"\u5e94\u7528\u8fc1\u79fb",description:"Kosmos \u63d0\u4f9b\u5e94\u7528\u8fc1\u79fb\u529f\u80fd\uff0c\u5e2e\u52a9\u7528\u6237\u5c06\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f\u4ece\u5b50\u96c6\u7fa4\u8fc1\u79fb\u5230 Kosmos \u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u3002",source:"@site/docs/i18n/zh/v0.2.0/application-migration_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/application-migration_zh",permalink:"/website/i18n/zh/v0.2.0/application-migration_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/application-migration_zh.md",tags:[],version:"current",frontMatter:{id:"application-migration_zh",title:"\u5e94\u7528\u8fc1\u79fb"}},t={},c=[{value:"\u5e94\u7528\u8fc1\u79fb\u89e3\u51b3\u65b9\u6848",id:"\u5e94\u7528\u8fc1\u79fb\u89e3\u51b3\u65b9\u6848",level:2},{value:"\u7b80\u4ecb",id:"\u7b80\u4ecb",level:3},{value:"\u8bbe\u8ba1\u7ec6\u8282",id:"\u8bbe\u8ba1\u7ec6\u8282",level:3},{value:"\u5e94\u7528\u5907\u4efd",id:"\u5e94\u7528\u5907\u4efd",level:4},{value:"\u5220\u9664\u6240\u6709\u8005\u5bf9\u8c61",id:"\u5220\u9664\u6240\u6709\u8005\u5bf9\u8c61",level:4},{value:"\u5728\u63a7\u5236\u5e73\u9762\u4e2d\u91cd\u5efa\u5e94\u7528\u7a0b\u5e8f",id:"\u5728\u63a7\u5236\u5e73\u9762\u4e2d\u91cd\u5efa\u5e94\u7528\u7a0b\u5e8f",level:4},{value:"CRD API",id:"crd-api",level:4},{value:"\u56de\u6eda",id:"\u56de\u6eda",level:4},{value:"\u6d4b\u8bd5\u8ba1\u5212",id:"\u6d4b\u8bd5\u8ba1\u5212",level:3},{value:"\u51c6\u5907\u5de5\u4f5c",id:"\u51c6\u5907\u5de5\u4f5c",level:4},{value:"\u5728\u5b50\u96c6\u7fa4\u4e2d\u521b\u5efa\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f",id:"\u5728\u5b50\u96c6\u7fa4\u4e2d\u521b\u5efa\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f",level:4},{value:"\u521b\u5efa\u8fc1\u79fb\u7b56\u7565",id:"\u521b\u5efa\u8fc1\u79fb\u7b56\u7565",level:4},{value:"\u68c0\u67e5\u8fc1\u79fb\u7ed3\u679c",id:"\u68c0\u67e5\u8fc1\u79fb\u7ed3\u679c",level:4},{value:"\u56de\u6eda",id:"\u56de\u6eda-1",level:4}];function d(e){const n={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",li:"li",p:"p",pre:"pre",ul:"ul",...(0,i.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"\u5e94\u7528\u8fc1\u79fb",children:"\u5e94\u7528\u8fc1\u79fb"}),"\n",(0,s.jsx)(n.p,{children:"Kosmos \u63d0\u4f9b\u5e94\u7528\u8fc1\u79fb\u529f\u80fd\uff0c\u5e2e\u52a9\u7528\u6237\u5c06\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f\u4ece\u5b50\u96c6\u7fa4\u8fc1\u79fb\u5230 Kosmos \u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u3002"}),"\n",(0,s.jsx)(n.h2,{id:"\u5e94\u7528\u8fc1\u79fb\u89e3\u51b3\u65b9\u6848",children:"\u5e94\u7528\u8fc1\u79fb\u89e3\u51b3\u65b9\u6848"}),"\n",(0,s.jsx)(n.h3,{id:"\u7b80\u4ecb",children:"\u7b80\u4ecb"}),"\n",(0,s.jsx)(n.p,{children:"\u5728 Kosmos \u591a\u96c6\u7fa4\u8bbe\u8ba1\u67b6\u6784\u4e2d\uff0c\u7528\u6237\u53ef\u4ee5\u4f7f\u7528 kubectl\u3001client-go \u7b49\u5de5\u5177\u4e0e\u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u7684 kube-apiserver \u4ea4\u4e92\uff0c\u521b\u5efa\u90e8\u7f72\u6216\u6709\u72b6\u6001\u7684\u5e94\u7528\u7a0b\u5e8f\u7b49\u3002\r\n\u5b9e\u9645\u7684 Pod \u5b9e\u4f8b\u5728\u5b50\u96c6\u7fa4\u4e2d\u8fd0\u884c\u3002"}),"\n",(0,s.jsx)(n.p,{children:"\u7136\u800c\uff0c\u5bf9\u4e8e\u5728\u5b50\u96c6\u7fa4\u4e2d\u672a\u901a\u8fc7 Kosmos \u63a7\u5236\u5e73\u9762\u521b\u5efa\u7684\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f\uff0c\u8fd9\u4e9b\u5e94\u7528\u7a0b\u5e8f\u65e0\u6cd5\u5728\u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u4e2d\u67e5\u770b\u548c\u7ba1\u7406\u3002"}),"\n",(0,s.jsx)(n.p,{children:"Kosmos \u63d0\u4f9b\u5e94\u7528\u8fc1\u79fb\u529f\u80fd\uff0c\u652f\u6301\u5c06\u547d\u540d\u7a7a\u95f4\u4e2d\u7684\u5e94\u7528\u7a0b\u5e8f\u8fc1\u79fb\u5230\u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u3002\r\n\u6574\u4e2a\u8fc7\u7a0b\u65e0\u9700\u91cd\u65b0\u542f\u52a8\u5e94\u7528\u7a0b\u5e8f Pod \u5b9e\u4f8b\uff0c\u786e\u4fdd\u5bf9\u4e1a\u52a1\u8fd0\u8425\u7684\u6700\u5c0f\u5f71\u54cd\u3002"}),"\n",(0,s.jsx)(n.h3,{id:"\u8bbe\u8ba1\u7ec6\u8282",children:"\u8bbe\u8ba1\u7ec6\u8282"}),"\n",(0,s.jsx)(n.p,{children:"\u5e94\u7528\u8fc1\u79fb\u4e3b\u8981\u5305\u62ec\u4e09\u4e2a\u8fc7\u7a0b\uff1a\u5e94\u7528\u5907\u4efd -> \u5220\u9664\u6240\u6709\u8005\u5bf9\u8c61 -> \u5728\u63a7\u5236\u5e73\u9762\u4e2d\u91cd\u5efa\u5e94\u7528\u7a0b\u5e8f\u3002"}),"\n",(0,s.jsx)(n.h4,{id:"\u5e94\u7528\u5907\u4efd",children:"\u5e94\u7528\u5907\u4efd"}),"\n",(0,s.jsx)(n.p,{children:"Kosmos \u9996\u5148\u5907\u4efd\u76ee\u6807\u547d\u540d\u7a7a\u95f4\u4e2d\u7684\u6240\u6709\u547d\u540d\u7a7a\u95f4\u7ea7\u522b\u8d44\u6e90\uff0c\u4ee5\u53ca\u4f9d\u8d56\u7684\u96c6\u7fa4\u7ea7\u522b\u8d44\u6e90\uff0c\u5982\u96c6\u7fa4\u89d2\u8272\u3001\u96c6\u7fa4\u89d2\u8272\u7ed1\u5b9a\u3001\u6301\u4e45\u5377\u7b49\u3002\r\n\u5907\u4efd\u6587\u4ef6\u5b58\u50a8\u5728 Kosmos \u7684 PVC \u4e2d\u3002"}),"\n",(0,s.jsx)(n.h4,{id:"\u5220\u9664\u6240\u6709\u8005\u5bf9\u8c61",children:"\u5220\u9664\u6240\u6709\u8005\u5bf9\u8c61"}),"\n",(0,s.jsx)(n.p,{children:"Kosmos \u5b50\u96c6\u7fa4\u4ec5\u8fd0\u884c Pod\uff0c\u5b83\u4eec\u7684\u6240\u6709\u8005 StatefulSet \u6216 ReplicaSet \u9700\u8981\u5728 Kosmos \u63a7\u5236\u5e73\u9762\u4e2d\u5220\u9664\u5e76\u91cd\u5efa\u3002\r\n\u7c7b\u4f3c\u5730\uff0cReplicaSet \u7684\u6240\u6709\u8005 Deployment\uff0c\u4ee5\u53ca StatefulSet \u548c Deployment \u7684\u6240\u6709\u8005\uff0c\u9700\u8981\u5728 Kosmos \u63a7\u5236\u5e73\u9762\u4e2d\u5220\u9664\u5e76\u91cd\u5efa\u3002"}),"\n",(0,s.jsx)(n.p,{children:"\u901a\u8fc7\u4f7f\u7528\u81ea\u4e0a\u800c\u4e0b\u7684\u7ea7\u8054\u5220\u9664\u6240\u6709\u8005\u5bf9\u8c61\uff08\u4f8b\u5982\uff0c\u9996\u5148\u5220\u9664 Deployment\uff0c\u7136\u540e\u5220\u9664 ReplicaSet\uff09\uff0cPod \u4e0d\u53d7\u5f71\u54cd\u5e76\u4fdd\u6301\u8fd0\u884c\u72b6\u6001\u3002"}),"\n",(0,s.jsx)(n.h4,{id:"\u5728\u63a7\u5236\u5e73\u9762\u4e2d\u91cd\u5efa\u5e94\u7528\u7a0b\u5e8f",children:"\u5728\u63a7\u5236\u5e73\u9762\u4e2d\u91cd\u5efa\u5e94\u7528\u7a0b\u5e8f"}),"\n",(0,s.jsx)(n.p,{children:"\u57fa\u4e8e\u5907\u4efd\u8d44\u6e90\uff0c\u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u521b\u5efa\u6240\u6709\u8fc1\u79fb\u540e\u7684\u8d44\u6e90\uff0c\u5305\u62ec\u547d\u540d\u7a7a\u95f4\u3001Pod\u3001\u90e8\u7f72\u3001\u914d\u7f6e\u6620\u5c04\u3001\u670d\u52a1\u8d26\u6237\u7b49\u3002\r\n\u4e3a\u4e86\u4e0e\u5b50\u96c6\u7fa4\u4e2d\u7684 Pod \u4fdd\u6301\u4e00\u81f4\u5e76\u4fdd\u6301\u5176\u8fd0\u884c\u72b6\u6001\uff0c\u5e94\u7528\u7a0b\u5e8f\u4f7f\u7528\u81ea\u4e0b\u800c\u4e0a\u7684\u65b9\u6cd5\u8fdb\u884c\u91cd\u5efa\uff08\u4f8b\u5982\uff0c\u9996\u5148\u521b\u5efa Pod\uff0c\u7136\u540e\u521b\u5efa ReplicaSet\uff09\u3002"}),"\n",(0,s.jsx)(n.h4,{id:"crd-api",children:"CRD API"}),"\n",(0,s.jsx)(n.p,{children:"\u63d0\u4f9b PromotePolicy CRD API \u7528\u4e8e\u914d\u7f6e\u8fc1\u79fb\u7b56\u7565\u3002\r\nPromotePolicy \u662f\u4e00\u4e2a\u96c6\u7fa4\u8303\u56f4\u7684 CRD API\u3002\u4ee5\u4e0b\u662f\u5982\u4f55\u4f7f\u7528\u5b83\u7684\u793a\u4f8b\uff1a"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-sample\r\nspec:\r\n includedNamespaces:\r\n - namespace1\r\n - namespace2\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: member-cluster1\n"})}),"\n",(0,s.jsx)(n.p,{children:"\u5176\u4e2d\uff1a"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"includedNamespaces: \u8981\u8fc1\u79fb\u7684\u547d\u540d\u7a7a\u95f4\u3002"}),"\n",(0,s.jsx)(n.li,{children:"excludedNamespaceScopedResources: \u4e0d\u5e94\u8fc1\u79fb\u7684\u547d\u540d\u7a7a\u95f4\u7ea7\u8d44\u6e90\u3002\r\n\u5efa\u8bae\u4fdd\u7559\u793a\u4f8b\u914d\u7f6e\uff0c\u5e76\u6839\u636e\u5b9e\u9645\u9700\u6c42\u6dfb\u52a0\u5176\u4ed6\u914d\u7f6e\u3002"}),"\n",(0,s.jsx)(n.li,{children:"clusterName: Kosmos \u5b50\u96c6\u7fa4\u7684\u540d\u79f0\u3002"}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"\u56de\u6eda",children:"\u56de\u6eda"}),"\n",(0,s.jsx)(n.p,{children:"Kosmos \u652f\u6301\u8fc1\u79fb\u7684\u56de\u6eda\u529f\u80fd\u3002\r\n\u6210\u529f\u8fc1\u79fb\u540e\uff0c\u53ef\u4ee5\u5c06\u5b50\u96c6\u7fa4\u4e2d\u73b0\u6709\u7684\u5e94\u7528\u7a0b\u5e8f\u6062\u590d\u5230\u5176\u521d\u59cb\u72b6\u6001\u3002\r\n\u53ea\u9700\u7f16\u8f91 PromotePolicy YAML \u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0\u914d\u7f6e 'rollback'=true\u3002"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:'apiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-sample\r\nspec:\r\n rollback: "true"\r\n includedNamespaces:\r\n - namespace1\r\n - namespace2\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: member-cluster1\n'})}),"\n",(0,s.jsx)(n.h3,{id:"\u6d4b\u8bd5\u8ba1\u5212",children:"\u6d4b\u8bd5\u8ba1\u5212"}),"\n",(0,s.jsx)(n.h4,{id:"\u51c6\u5907\u5de5\u4f5c",children:"\u51c6\u5907\u5de5\u4f5c"}),"\n",(0,s.jsxs)(n.p,{children:["\u9996\u5148\uff0c\u9700\u8981\u90e8\u7f72 ",(0,s.jsx)(n.a,{href:"https://github.com/kosmos-io/kosmos",children:"Kosmos"}),"\uff08\u5fc5\u987b\u5b89\u88c5 clustertree \u6a21\u5757\uff09\u5e76\u6dfb\u52a0\u4e00\u4e2a\u5b50\u96c6\u7fa4\u3002"]}),"\n",(0,s.jsx)(n.h4,{id:"\u5728\u5b50\u96c6\u7fa4\u4e2d\u521b\u5efa\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f",children:"\u5728\u5b50\u96c6\u7fa4\u4e2d\u521b\u5efa\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f"}),"\n",(0,s.jsx)(n.p,{children:"\u4ee5\u5728\u5b50\u96c6\u7fa4\u4e2d\u90e8\u7f72 nginx \u5e94\u7528\u7a0b\u5e8f\u4e3a\u4f8b\u3002"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: nginx\r\n namespace: nginx-test\r\nspec:\r\n selector:\r\n matchLabels:\r\n app: nginx\r\n replicas: 1\r\n template:\r\n metadata:\r\n labels:\r\n app: nginx\r\n spec:\r\n containers:\r\n - name: nginx\r\n image: nginx:1.14-alpine\r\n ports:\r\n - containerPort: 80\r\n\r\n---\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n name: nginx-service\r\n namespace: nginx-test\r\nspec:\r\n selector:\r\n app: nginx\r\n ports:\r\n - protocol: TCP\r\n port: 80\r\n targetPort: 80\r\n type: ClusterIP\n"})}),"\n",(0,s.jsx)(n.h4,{id:"\u521b\u5efa\u8fc1\u79fb\u7b56\u7565",children:"\u521b\u5efa\u8fc1\u79fb\u7b56\u7565"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl apply -f promote-nginx.yaml\r\napiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-example\r\nspec:\r\n includedNamespaces:\r\n - nginx-test\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: cluster-36-28\n"})}),"\n",(0,s.jsx)(n.h4,{id:"\u68c0\u67e5\u8fc1\u79fb\u7ed3\u679c",children:"\u68c0\u67e5\u8fc1\u79fb\u7ed3\u679c"}),"\n",(0,s.jsx)(n.p,{children:"\u68c0\u67e5\u8fc1\u79fb\u8fdb\u5ea6\uff1a"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl describe promotepolicy promote-policy-example\r\nName: promote-policy-example\r\nNamespace: default\r\nLabels: \r\nAnnotations: \r\nAPI Version: kosmos.io/v1alpha1\r\nKind: PromotePolicy\r\nMetadata:\r\n Creation Timestamp: 2024-03-11T10:57:47Z\r\n Generation: 3\r\n Resource Version: 405947183\r\n UID: 0e32dd93-c370-4874-b9a7-37a6894cd373\r\nSpec:\r\n Cluster Name: cluster-36-28\r\n Excluded Namespace Scoped Resources:\r\n events\r\n events.events.k8s.io\r\n endpoints\r\n endpointslices.discovery.k8s.io\r\n controllerrevisions.apps\r\n Included Namespaces:\r\n nginx-test\r\nStatus:\r\n Backedup File: /data/backup/promote-policy-sample20240311-104907\r\n Phase: Completed\r\nEvents: \n"})}),"\n",(0,s.jsx)(n.p,{children:"\u5f53 Status.Phase \u4e3a 'Completed' \u65f6\uff0c\u8868\u793a\u8fc1\u79fb\u6210\u529f\u3002\r\n\u6b64\u65f6\uff0c\u53ef\u4ee5\u5728\u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u4e2d\u67e5\u770b\u548c\u7ba1\u7406 nginx-test \u547d\u540d\u7a7a\u95f4\u4e2d\u7684\u6240\u6709\u5e94\u7528\u7a0b\u5e8f\u3002"}),"\n",(0,s.jsx)(n.h4,{id:"\u56de\u6eda-1",children:"\u56de\u6eda"}),"\n",(0,s.jsx)(n.p,{children:"\u7f16\u8f91 promote-nginx.yml \u6587\u4ef6\uff0c\u5e76\u6dfb\u52a0\u914d\u7f6e 'rollback'=true\uff1a"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:'# kubectl apply -f promote-nginx.yaml\r\napiVersion: kosmos.io/v1alpha1\r\nkind: PromotePolicy\r\nmetadata:\r\n name: promote-policy-example\r\nspec:\r\n rollback: "true"\r\n includedNamespaces:\r\n - nginx-test\r\n excludedNamespaceScopedResources:\r\n - events\r\n - events.events.k8s.io\r\n - endpoints\r\n - endpointslices.discovery.k8s.io\r\n clusterName: cluster-36-28\n'})}),"\n",(0,s.jsx)(n.p,{children:"\u56de\u6eda\u7ed3\u679c\u68c0\u67e5\uff1a"}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# kubectl describe promotepolicy promote-policy-example\r\nName: promote-policy-example\r\nNamespace: default\r\nLabels: \r\nAnnotations: \r\nAPI Version: kosmos.io/v1alpha1\r\nKind: PromotePolicy\r\nMetadata:\r\n Creation Timestamp: 2024-03-11T10:57:47Z\r\n Generation: 5\r\n Resource Version: 405953692\r\n UID: 0e32dd93-c370-4874-b9a7-37a6894cd373\r\nSpec:\r\n Cluster Name: cluster-36-28\r\n Excluded Namespace Scoped Resources:\r\n events\r\n events.events.k8s.io\r\n endpoints\r\n endpointslices.discovery.k8s.io\r\n controllerrevisions.apps\r\n Included Namespaces:\r\n nginx-test\r\nStatus:\r\n Backedup File: /data/backup/promote-policy-sample20240311-104907\r\n Phase: RolledBack\r\nEvents: \n"})}),"\n",(0,s.jsxs)(n.p,{children:["\u5f53 ",(0,s.jsx)(n.code,{children:"Status.Phase"})," \u4e3a 'RolledBack' \u65f6\uff0c\u8868\u793a\u56de\u6eda\u6210\u529f\u3002\r\n\u6b64\u65f6\uff0cnginx-test \u547d\u540d\u7a7a\u95f4\u4e2d\u7684\u5e94\u7528\u7a0b\u5e8f\u5728\u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u4e2d\u65e0\u6cd5\u67e5\u8be2\u5230\u3002"]})]})}function p(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},2172:(e,n,r)=>{r.d(n,{I:()=>l,M:()=>a});var s=r(1504);const i={},o=s.createContext(i);function a(e){const n=s.useContext(o);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function l(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:a(e.components),s.createElement(o.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/935f2afb.44094366.js b/docs/assets/js/935f2afb.44094366.js new file mode 100644 index 0000000..27f478a --- /dev/null +++ b/docs/assets/js/935f2afb.44094366.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[696],{5988:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"category","label":"Getting Started","collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/website/v0.2.0/getting-started/introduction","docId":"v0.2.0/getting-started/introduction","unlisted":false},{"type":"link","label":"Quick Start","href":"/website/v0.2.0/quick-start","docId":"v0.2.0/quick-start","unlisted":false}],"collapsible":true},{"type":"category","label":"Tutorials","collapsed":false,"items":[{"type":"link","label":"Multi-cluster Service Discovery","href":"/website/v0.2.0/tutorials/mcs-discovery","docId":"v0.2.0/tutorials/mcs-discovery","unlisted":false},{"type":"link","label":"Multi-cluster Scheduler","href":"/website/v0.2.0/tutorials/mc-scheduler","docId":"v0.2.0/tutorials/mc-scheduler","unlisted":false},{"type":"link","label":"Multi-cluster Network Connectivity","href":"/website/v0.2.0/tutorials/mcn-connectivity","docId":"v0.2.0/tutorials/mcn-connectivity","unlisted":false},{"type":"link","label":"Multi-cluster PV/PVC Dynamic Storage","href":"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage","docId":"v0.2.0/tutorials/pv-pvc-dynamic-storage","unlisted":false},{"type":"link","label":"Design of EXEC and Log in Kosmos","href":"/website/v0.2.0/tutorials/exe-and-log","docId":"v0.2.0/tutorials/exe-and-log","unlisted":false},{"type":"link","label":"Kosmos Node NotReady","href":"/website/v0.2.0/tutorials/node-not-ready","docId":"v0.2.0/tutorials/node-not-ready","unlisted":false},{"type":"link","label":"IPsec Cross-cluster Network","href":"/website/v0.2.0/tutorials/ipsec-network","docId":"v0.2.0/tutorials/ipsec-network","unlisted":false},{"type":"link","label":"Application Migration","href":"/website/v0.2.0/tutorials/application-migration","docId":"v0.2.0/tutorials/application-migration","unlisted":false}],"collapsible":true},{"type":"category","label":"Proposals","collapsed":false,"items":[{"type":"link","label":"Kubernetes in Kubernetes","href":"/website/v0.2.0/proposals/k8s-in-k8s","docId":"v0.2.0/proposals/k8s-in-k8s","unlisted":false},{"type":"link","label":"Distribution Policy","href":"/website/v0.2.0/proposals/distribution-policy","docId":"v0.2.0/proposals/distribution-policy","unlisted":false},{"type":"link","label":"Leaf Node Generate Rules","href":"/website/v0.2.0/proposals/leaf-node-generate-rules","docId":"v0.2.0/proposals/leaf-node-generate-rules","unlisted":false}],"collapsible":true}]},"docs":{"example/describe2":{"id":"example/describe2","title":"md/mdx\u6587\u4ef6\u5199\u6cd5\u4ecb\u7ecd","description":"1.\u5e38\u89c1markdown\u5199\u6cd5"},"example/list1/test1":{"id":"example/list1/test1","title":"test1","description":"\u6d4b\u8bd5\u76ee\u5f55\u4e0b\u7684\u6587\u6863"},"example/list2/test2":{"id":"example/list2/test2","title":"test2","description":""},"example/list3/list3Content":{"id":"example/list3/list3Content","title":"list3","description":"\u6211\u662f\u6807\u9898\u5bf9\u5e94\u7684\u5185\u5bb9\u533a\u57df"},"example/list3/test3":{"id":"example/list3/test3","title":"test3","description":""},"v0.2.0/getting-started/introduction":{"id":"v0.2.0/getting-started/introduction","title":"Introduction","description":"What is Kosmos?","sidebar":"tutorialSidebar"},"v0.2.0/proposals/distribution-policy":{"id":"v0.2.0/proposals/distribution-policy","title":"Distribution Policy","description":"Summary","sidebar":"tutorialSidebar"},"v0.2.0/proposals/k8s-in-k8s":{"id":"v0.2.0/proposals/k8s-in-k8s","title":"Kubernetes in Kubernetes","description":"Summary","sidebar":"tutorialSidebar"},"v0.2.0/proposals/leaf-node-generate-rules":{"id":"v0.2.0/proposals/leaf-node-generate-rules","title":"Leaf Node Generate Rules","description":"Summary","sidebar":"tutorialSidebar"},"v0.2.0/quick-start":{"id":"v0.2.0/quick-start","title":"Quick Start","description":"This guide will cover:","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/application-migration":{"id":"v0.2.0/tutorials/application-migration","title":"Application Migration","description":"Kosmos provides application migration functionality to help users migrate existing applications from subclusters to the Kosmos control plane cluster.","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/exe-and-log":{"id":"v0.2.0/tutorials/exe-and-log","title":"Design of EXEC and Log in Kosmos","description":"Kosmos EXEC and Log Solution","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/ipsec-network":{"id":"v0.2.0/tutorials/ipsec-network","title":"IPsec Cross-cluster Network","description":"Using IPsec Tunnels for Cross-Cluster Container Network Communication over Public IP","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/mc-scheduler":{"id":"v0.2.0/tutorials/mc-scheduler","title":"Multi-cluster Scheduler","description":"After Kosmos join a member cluster, it will map a virtual node with the kosmos.io/node=true:Noschedule taint, so the Kubernetes default scheduler cannot schedule Pods to the virtual node (i.e, the member cluster).","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/mcn-connectivity":{"id":"v0.2.0/tutorials/mcn-connectivity","title":"Multi-cluster Network Connectivity","description":"The Clusterlink design of the Kosmos multi-cluster solution aims to interconnect the nodes and resources of multiple Kubernetes clusters, forming a unified resource pool.","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/mcs-discovery":{"id":"v0.2.0/tutorials/mcs-discovery","title":"Multi-cluster Service Discovery","description":"Kosmos provides two capabilities for multi-cluster service discovery:","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/node-not-ready":{"id":"v0.2.0/tutorials/node-not-ready","title":"Kosmos Node NotReady","description":"Kosmos Node NotReady Solution","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/pv-pvc-dynamic-storage":{"id":"v0.2.0/tutorials/pv-pvc-dynamic-storage","title":"Multi-cluster PV/PVC Dynamic Storage","description":"Multi-cluster PV/PVC Dynamic Storage Implementation","sidebar":"tutorialSidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/935f2afb.55e6ec9a.js b/docs/assets/js/935f2afb.55e6ec9a.js deleted file mode 100644 index ca69233..0000000 --- a/docs/assets/js/935f2afb.55e6ec9a.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[696],{5988:e=>{e.exports=JSON.parse('{"pluginId":"default","version":"current","label":"Next","banner":null,"badge":false,"noIndex":false,"className":"docs-version-current","isLast":true,"docsSidebars":{"tutorialSidebar":[{"type":"category","label":"Getting Started","collapsed":false,"items":[{"type":"link","label":"Introduction","href":"/website/v0.2.0/getting-started/introduction","docId":"v0.2.0/getting-started/introduction","unlisted":false},{"type":"link","label":"Quick Start","href":"/website/v0.2.0/quick-start","docId":"v0.2.0/quick-start","unlisted":false}],"collapsible":true},{"type":"category","label":"Tutorials","collapsed":false,"items":[{"type":"link","label":"Multi-cluster Service Discovery","href":"/website/v0.2.0/tutorials/mcs-discovery","docId":"v0.2.0/tutorials/mcs-discovery","unlisted":false},{"type":"link","label":"Multi-cluster Scheduler","href":"/website/v0.2.0/tutorials/mc-scheduler","docId":"v0.2.0/tutorials/mc-scheduler","unlisted":false},{"type":"link","label":"Multi-cluster Network Connectivity","href":"/website/v0.2.0/tutorials/mcn-connectivity","docId":"v0.2.0/tutorials/mcn-connectivity","unlisted":false},{"type":"link","label":"Multi-cluster PV/PVC Dynamic Storage","href":"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage","docId":"v0.2.0/tutorials/pv-pvc-dynamic-storage","unlisted":false},{"type":"link","label":"Design of EXEC and Log in Kosmos","href":"/website/v0.2.0/tutorials/exe-and-log","docId":"v0.2.0/tutorials/exe-and-log","unlisted":false},{"type":"link","label":"Kosmos Node NotReady","href":"/website/v0.2.0/tutorials/node-not-ready","docId":"v0.2.0/tutorials/node-not-ready","unlisted":false},{"type":"link","label":"IPsec Cross-cluster Network","href":"/website/v0.2.0/tutorials/ipsec-network","docId":"v0.2.0/tutorials/ipsec-network","unlisted":false},{"type":"link","label":"Application Migration","href":"/website/v0.2.0/tutorials/application-migration","docId":"v0.2.0/tutorials/application-migration","unlisted":false},{"type":"link","label":"kubenest","href":"/website/v0.2.0/tutorials/kubenest","docId":"v0.2.0/tutorials/kubenest","unlisted":false}],"collapsible":true},{"type":"category","label":"Proposals","collapsed":false,"items":[{"type":"link","label":"Kubernetes in Kubernetes","href":"/website/v0.2.0/proposals/k8s-in-k8s","docId":"v0.2.0/proposals/k8s-in-k8s","unlisted":false},{"type":"link","label":"Distribution Policy","href":"/website/v0.2.0/proposals/distribution-policy","docId":"v0.2.0/proposals/distribution-policy","unlisted":false},{"type":"link","label":"Leaf Node Generate Rules","href":"/website/v0.2.0/proposals/leaf-node-generate-rules","docId":"v0.2.0/proposals/leaf-node-generate-rules","unlisted":false},{"type":"link","label":"Kosmos Performance Testing","href":"/website/v0.2.0/proposals/performance-testing","docId":"v0.2.0/proposals/performance-testing","unlisted":false}],"collapsible":true}]},"docs":{"example/describe2":{"id":"example/describe2","title":"md/mdx\u6587\u4ef6\u5199\u6cd5\u4ecb\u7ecd","description":"1.\u5e38\u89c1markdown\u5199\u6cd5"},"example/list1/test1":{"id":"example/list1/test1","title":"test1","description":"\u6d4b\u8bd5\u76ee\u5f55\u4e0b\u7684\u6587\u6863"},"example/list2/test2":{"id":"example/list2/test2","title":"test2","description":""},"example/list3/list3Content":{"id":"example/list3/list3Content","title":"list3","description":"\u6211\u662f\u6807\u9898\u5bf9\u5e94\u7684\u5185\u5bb9\u533a\u57df"},"example/list3/test3":{"id":"example/list3/test3","title":"test3","description":""},"i18n/zh/v0.2.0/application-migration_zh":{"id":"i18n/zh/v0.2.0/application-migration_zh","title":"\u5e94\u7528\u8fc1\u79fb","description":"Kosmos \u63d0\u4f9b\u5e94\u7528\u8fc1\u79fb\u529f\u80fd\uff0c\u5e2e\u52a9\u7528\u6237\u5c06\u73b0\u6709\u5e94\u7528\u7a0b\u5e8f\u4ece\u5b50\u96c6\u7fa4\u8fc1\u79fb\u5230 Kosmos \u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u3002"},"i18n/zh/v0.2.0/exe-and-log_zh":{"id":"i18n/zh/v0.2.0/exe-and-log_zh","title":"Kosmos \u4e2d\u7684 EXEC \u548c Log \u8bbe\u8ba1","description":"Kosmos \u7684 EXEC \u548c Log \u89e3\u51b3\u65b9\u6848"},"i18n/zh/v0.2.0/introduction_zh":{"id":"i18n/zh/v0.2.0/introduction_zh","title":"\u7b80\u4ecb","description":"\u4ec0\u4e48\u662f Kosmos\uff1f"},"i18n/zh/v0.2.0/ipsec-network_zh":{"id":"i18n/zh/v0.2.0/ipsec-network_zh","title":"IPsec\u8de8\u96c6\u7fa4\u7f51\u7edc","description":"\u4f7f\u7528IPsec\u96a7\u9053\u5728\u516c\u5171IP\u4e0a\u8fdb\u884c\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1"},"i18n/zh/v0.2.0/mc-scheduler_zh":{"id":"i18n/zh/v0.2.0/mc-scheduler_zh","title":"\u591a\u96c6\u7fa4\u8c03\u5ea6\u5668","description":"\u5f53 Kosmos \u52a0\u5165\u4e00\u4e2a\u6210\u5458\u96c6\u7fa4\u540e\uff0c\u5b83\u4f1a\u6620\u5c04\u4e00\u4e2a\u5e26\u6709 kosmos.io/node=true:Noschedule \u6c61\u70b9\u7684\u865a\u62df\u8282\u70b9\uff0c\u56e0\u6b64 Kubernetes \u9ed8\u8ba4\u8c03\u5ea6\u5668\u65e0\u6cd5\u5c06 Pod \u8c03\u5ea6\u5230\u8be5\u865a\u62df\u8282\u70b9\uff08\u5373\u6210\u5458\u96c6\u7fa4\uff09\u4e0a\u3002"},"i18n/zh/v0.2.0/mcn-connectivity_zh":{"id":"i18n/zh/v0.2.0/mcn-connectivity_zh","title":"\u591a\u96c6\u7fa4\u7f51\u7edc\u8054\u901a","description":"Kosmos \u591a\u96c6\u7fa4\u89e3\u51b3\u65b9\u6848\u7684 Clusterlink \u8bbe\u8ba1\u65e8\u5728\u4e92\u8fde\u591a\u4e2a Kubernetes \u96c6\u7fa4\u7684\u8282\u70b9\u548c\u8d44\u6e90\uff0c\u5f62\u6210\u7edf\u4e00\u7684\u8d44\u6e90\u6c60\u3002"},"i18n/zh/v0.2.0/mcs-discovery_zh":{"id":"i18n/zh/v0.2.0/mcs-discovery_zh","title":"\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0","description":"Kosmos\u63d0\u4f9b\u4e86\u4e24\u79cd\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0\u7684\u80fd\u529b\uff1a"},"i18n/zh/v0.2.0/node-not-ready_zh":{"id":"i18n/zh/v0.2.0/node-not-ready_zh","title":"Kosmos \u8282\u70b9 NotReady","description":"Kosmos \u8282\u70b9 NotReady \u89e3\u51b3\u65b9\u6848"},"i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh":{"id":"i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh","title":"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8","description":"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8\u5b9e\u73b0"},"v0.2.0/getting-started/introduction":{"id":"v0.2.0/getting-started/introduction","title":"Introduction","description":"What is Kosmos?","sidebar":"tutorialSidebar"},"v0.2.0/proposals/distribution-policy":{"id":"v0.2.0/proposals/distribution-policy","title":"Distribution Policy","description":"Summary","sidebar":"tutorialSidebar"},"v0.2.0/proposals/k8s-in-k8s":{"id":"v0.2.0/proposals/k8s-in-k8s","title":"Kubernetes in Kubernetes","description":"Summary","sidebar":"tutorialSidebar"},"v0.2.0/proposals/leaf-node-generate-rules":{"id":"v0.2.0/proposals/leaf-node-generate-rules","title":"Leaf Node Generate Rules","description":"Summary","sidebar":"tutorialSidebar"},"v0.2.0/proposals/performance-testing":{"id":"v0.2.0/proposals/performance-testing","title":"Kosmos Performance Testing","description":"Network Performance Testing","sidebar":"tutorialSidebar"},"v0.2.0/quick-start":{"id":"v0.2.0/quick-start","title":"Quick Start","description":"This guide will cover:","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/application-migration":{"id":"v0.2.0/tutorials/application-migration","title":"Application Migration","description":"Kosmos provides application migration functionality to help users migrate existing applications from subclusters to the Kosmos control plane cluster.","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/exe-and-log":{"id":"v0.2.0/tutorials/exe-and-log","title":"Design of EXEC and Log in Kosmos","description":"Kosmos EXEC and Log Solution","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/ipsec-network":{"id":"v0.2.0/tutorials/ipsec-network","title":"IPsec Cross-cluster Network","description":"Using IPsec Tunnels for Cross-Cluster Container Network Communication over Public IP","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/kubenest":{"id":"v0.2.0/tutorials/kubenest","title":"kubenest","description":"Introduction","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/mc-scheduler":{"id":"v0.2.0/tutorials/mc-scheduler","title":"Multi-cluster Scheduler","description":"After Kosmos join a member cluster, it will map a virtual node with the kosmos.io/node=true:Noschedule taint, so the Kubernetes default scheduler cannot schedule Pods to the virtual node (i.e, the member cluster).","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/mcn-connectivity":{"id":"v0.2.0/tutorials/mcn-connectivity","title":"Multi-cluster Network Connectivity","description":"The Clusterlink design of the Kosmos multi-cluster solution aims to interconnect the nodes and resources of multiple Kubernetes clusters, forming a unified resource pool.","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/mcs-discovery":{"id":"v0.2.0/tutorials/mcs-discovery","title":"Multi-cluster Service Discovery","description":"Kosmos provides two capabilities for multi-cluster service discovery:","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/node-not-ready":{"id":"v0.2.0/tutorials/node-not-ready","title":"Kosmos Node NotReady","description":"Kosmos Node NotReady Solution","sidebar":"tutorialSidebar"},"v0.2.0/tutorials/pv-pvc-dynamic-storage":{"id":"v0.2.0/tutorials/pv-pvc-dynamic-storage","title":"Multi-cluster PV/PVC Dynamic Storage","description":"Multi-cluster PV/PVC Dynamic Storage Implementation","sidebar":"tutorialSidebar"}}}')}}]); \ No newline at end of file diff --git a/docs/assets/js/9882b082.82ff8854.js b/docs/assets/js/9882b082.82ff8854.js deleted file mode 100644 index 0c0441f..0000000 --- a/docs/assets/js/9882b082.82ff8854.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[786],{1076:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var t=r(7624),o=r(2172);const s={id:"exe-and-log",title:"Design of EXEC and Log in Kosmos"},i="Design of EXEC and Log in Kosmos",a={id:"v0.2.0/tutorials/exe-and-log",title:"Design of EXEC and Log in Kosmos",description:"Kosmos EXEC and Log Solution",source:"@site/docs/v0.2.0/tutorials/design-of-exec-and-log.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/exe-and-log",permalink:"/website/v0.2.0/tutorials/exe-and-log",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/design-of-exec-and-log.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1711021616,formattedLastUpdatedAt:"Mar 21, 2024",frontMatter:{id:"exe-and-log",title:"Design of EXEC and Log in Kosmos"},sidebar:"tutorialSidebar",previous:{title:"Multi-cluster PV/PVC Dynamic Storage",permalink:"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage"},next:{title:"Kosmos Node NotReady",permalink:"/website/v0.2.0/tutorials/node-not-ready"}},d={},c=[{value:"Kosmos EXEC and Log Solution",id:"kosmos-exec-and-log-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Background Knowledge",id:"background-knowledge",level:3},{value:"Implementation in Kosmos",id:"implementation-in-kosmos",level:3},{value:"Customization",id:"customization",level:3},{value:"Conclusion",id:"conclusion",level:3}];function l(e){const n={code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.M)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"design-of-exec-and-log-in-kosmos",children:"Design of EXEC and Log in Kosmos"}),"\n",(0,t.jsx)(n.h2,{id:"kosmos-exec-and-log-solution",children:"Kosmos EXEC and Log Solution"}),"\n",(0,t.jsx)(n.h3,{id:"introduction",children:"Introduction"}),"\n",(0,t.jsxs)(n.p,{children:["In Kosmos, the pods scheduled to kosmos-node also support the ",(0,t.jsx)(n.code,{children:"kubectl exec"})," and ",(0,t.jsx)(n.code,{children:"kubectl log"})," functions.\r\nSince the overall architecture of ",(0,t.jsx)(n.code,{children:"kubectl exec"})," and ",(0,t.jsx)(n.code,{children:"kubectl log"})," is the same, we will use ",(0,t.jsx)(n.code,{children:"kubectl exec"})," as a sample to introduce the overall architecture.\r\nThe following diagram illustrates the overall design architecture."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"EXE Log_Arch.png",src:r(4252).c+"",width:"1110",height:"863"})}),"\n",(0,t.jsx)(n.h3,{id:"background-knowledge",children:"Background Knowledge"}),"\n",(0,t.jsxs)(n.p,{children:["First, let's explore how to implement ",(0,t.jsx)(n.code,{children:"kubectl exec"})," in Kubernetes.\r\nThe ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"leaf-cluster"})})," part of the architecture diagram is a representation of the ",(0,t.jsx)(n.code,{children:"kubectl exec"})," function of a native cluster.\r\nThe kubectl exec request initiated by the user is processed by apiserver.\r\nAfter receiving the exec request, apiserver needs to forward the request to the node where the pod is allocated, so it needs to query the information of the node where the pod is allocated.\r\nIn the Kubernetes source code, apiserver will call the ",(0,t.jsx)(n.code,{children:"ExecLocation"})," method to obtain the exec url of the pod.\r\nThe code is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'// ExecLocation returns the exec URL for a pod container. If opts.Container is blank\r\n// and only one container is present in the pod, that container is used.\r\nfunc ExecLocation(\r\n ctx context.Context,\r\n getter ResourceGetter,\r\n connInfo client.ConnectionInfoGetter,\r\n name string,\r\n opts *api.PodExecOptions,\r\n) (*url.URL, http.RoundTripper, error) {\r\n return streamLocation(ctx, getter, connInfo, name, opts, opts.Container, "exec")\r\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ExecLocation"})," calls the ",(0,t.jsx)(n.code,{children:"streamLocation"})," method, and streamLocation obtains pod information through the pod name."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'func streamLocation(\r\n ctx context.Context,\r\n getter ResourceGetter,\r\n connInfo client.ConnectionInfoGetter,\r\n name string,\r\n opts runtime.Object,\r\n container,\r\n path string,\r\n) (*url.URL, http.RoundTripper, error) {\r\n pod, err := getPod(ctx, getter, name)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n \r\n // Try to figure out a container\r\n // If a container was provided, it must be valid\r\n container, err = validateContainer(container, pod)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n \r\n nodeName := types.NodeName(pod.Spec.NodeName)\r\n if len(nodeName) == 0 {\r\n // If pod has not been assigned a host, return an empty location\r\n return nil, nil, errors.NewBadRequest(fmt.Sprintf("pod %s does not have a host assigned", name))\r\n }\r\n nodeInfo, err := connInfo.GetConnectionInfo(ctx, nodeName)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n params := url.Values{}\r\n if err := streamParams(params, opts); err != nil {\r\n return nil, nil, err\r\n }\r\n loc := &url.URL{\r\n Scheme: nodeInfo.Scheme,\r\n Host: net.JoinHostPort(nodeInfo.Hostname, nodeInfo.Port),\r\n Path: fmt.Sprintf("/%s/%s/%s/%s", path, pod.Namespace, pod.Name, container),\r\n RawQuery: params.Encode(),\r\n }\r\n return loc, nodeInfo.Transport, nil\r\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Then the node name where the pod is allocated is obtained through ",(0,t.jsx)(n.code,{children:"pod.Spec.NodeName"}),", and then a key method ",(0,t.jsx)(n.code,{children:"GetConnectionInfo"})," is called. The code is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:"// GetConnectionInfo retrieves connection info from the status of a Node API object.\r\nfunc (k *NodeConnectionInfoGetter) GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error) {\r\n node, err := k.nodes.Get(ctx, string(nodeName), metav1.GetOptions{})\r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n // Find a kubelet-reported address, using preferred address type\r\n host, err := nodeutil.GetPreferredNodeAddress(node, k.preferredAddressTypes)\r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n // Use the kubelet-reported port, if present\r\n port := int(node.Status.DaemonEndpoints.KubeletEndpoint.Port)\r\n if port <= 0 {\r\n port = k.defaultPort\r\n }\r\n \r\n return &ConnectionInfo{\r\n Scheme: k.scheme,\r\n Hostname: host,\r\n Port: strconv.Itoa(port),\r\n Transport: k.transport,\r\n InsecureSkipTLSVerifyTransport: k.insecureSkipTLSVerifyTransport,\r\n }, nil\r\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"GetConnectionInfo"})," obtains the node information through the node name, then uses ",(0,t.jsx)(n.code,{children:"GetPreferredNodeAddress"})," to select a suitable host, and then through the ",(0,t.jsx)(n.code,{children:"streamLocation"})," processing, an exec request URL is pieced together.\r\nThe apiserver will know which node to forward the exec request to.\r\nThe kubelet service running on the node will capture the exec request and then establish a link with the pod."]}),"\n",(0,t.jsx)(n.p,{children:"The above briefly introduces the process of establishing kubectl exec."}),"\n",(0,t.jsx)(n.h3,{id:"implementation-in-kosmos",children:"Implementation in Kosmos"}),"\n",(0,t.jsxs)(n.p,{children:["Next, let's take a look at the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"root-cluster"})})," in the overall architecture diagram.\r\nIn order for the exec request to be passed to the leaf cluster, the exec request needs to be forwarded."]}),"\n",(0,t.jsxs)(n.p,{children:["First, we need to tell apiserver that the ip address of kosmos-node is the podIP of our ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})}),", which will cause apiserver to forward the exec request to ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})}),".\r\nWhen we synchronize the node information of kosmos-node, we read it from the environment variable ",(0,t.jsx)(n.code,{children:"LEAF_NODE_IP"}),".\r\nThis environment variable is configured when starting the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service.\r\nThe key configuration fragment is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:"spec:\r\n serviceAccountName: clustertree\r\n containers:\r\n - name: clustertree-cluster-manager\r\n image: ghcr.io/kosmos-io/clustertree-cluster-manager:__VERSION__\r\n imagePullPolicy: IfNotPresent\r\n env:\r\n - name: APISERVER_CERT_LOCATION\r\n value: /etc/cluster-tree/cert/cert.pem\r\n - name: APISERVER_KEY_LOCATION\r\n value: /etc/cluster-tree/cert/key.pem\r\n - name: LEAF_NODE_IP\r\n valueFrom:\r\n fieldRef:\r\n fieldPath: status.podIP\r\n - name: PREFERRED-ADDRESS-TYPE\r\n value: InternalDNS\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Then we need to start a service similar to kubelet that listens to exec.\r\nIn the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service, we start a nodeserver service.\r\nThe code snippet is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'nodeServer := nodeserver.NodeServer{\r\n RootClient: mgr.GetClient(),\r\n GlobalLeafManager: globalleafManager,\r\n}\r\ngo func() {\r\n if err := nodeServer.Start(ctx, opts); err != nil {\r\n klog.Errorf("failed to start node server: %v", err)\r\n }\r\n}()\n'})}),"\n",(0,t.jsx)(n.p,{children:"This service monitors exec and log requests, and will act as a proxy to forward the monitored requests to the corresponding leaf cluster.\r\nThe source code is as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'func (s *NodeServer) AttachRoutes(m *http.ServeMux) {\r\n r := mux.NewRouter()\r\n r.StrictSlash(true)\r\n \r\n r.HandleFunc(\r\n "/containerLogs/{namespace}/{pod}/{container}",\r\n api.ContainerLogsHandler(s.getClient),\r\n ).Methods("GET")\r\n \r\n r.HandleFunc(\r\n "/exec/{namespace}/{pod}/{container}",\r\n api.ContainerExecHandler(\r\n api.ContainerExecOptions{\r\n StreamIdleTimeout: 30 * time.Second,\r\n StreamCreationTimeout: 30 * time.Second,\r\n },\r\n s.getClient,\r\n ),\r\n ).Methods("POST", "GET")\r\n \r\n r.NotFoundHandler = http.HandlerFunc(api.NotFound)\r\n \r\n m.Handle("/", r)\r\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["With the forwarding part completed, we need to make the API server in the root cluster recognize the communication address of the kosmos-node as the address of the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service.\r\nTherefore, when maintaining the status of kosmos-node, we synchronize the podIP of ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," to kosmos-node.\r\nThe complete process is as follows:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"The user initiates an exec request."}),"\n",(0,t.jsx)(n.li,{children:"The API server in the root cluster receives the exec request and queries the node information based on the pod information."}),"\n",(0,t.jsx)(n.li,{children:"The queried node host is the podIP of clustertree-cluster-manager."}),"\n",(0,t.jsx)(n.li,{children:"The API server in the root cluster establishes an exec connection with clustertree-cluster-manager."}),"\n",(0,t.jsx)(n.li,{children:"clustertree-cluster-manager receives the exec connection request, queries the pod information, and proxies the exec request to the leaf cluster.\r\nWith this process, Kosmos implements the exec functionality, and the log functionality works in the same way."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"customization",children:"Customization"}),"\n",(0,t.jsxs)(n.p,{children:["When connecting with es products, there is a customized requirement.\r\nThe above design will cause the IPs of all kosmos-node to be the podIPs of ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manage"})}),".\r\nIn the product design of es, nodeIP is used as the primary key, which causes the product to fail to be stored in the warehouse.\r\nFor this purpose, kosmos has made a special design.\r\nThe ip address in the node information obtained through kubectl get node -owide is of the InternalIP type."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"sudo kubectl get nodes -owide\r\nNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME\r\nkosmos-control-1 Ready control-plane,master,node 65d v1.21.5 192.xx.xx.1 BigCloud Enterprise Linux For Euler 21.10 LTS 4.19.90-2107.6.0.0192.8.oe1.bclinux.x86_64 containerd://1.5.7\r\nkosmos-control-2 Ready node 65d v1.21.5 192.xx.xx.2 BigCloud Enterprise Linux For Euler 21.10 LTS 4.19.90-2107.6.0.0192.8.oe1.bclinux.x86_64 containerd://1.5.7\r\nkosmos-cluster1 Ready agent 20d v1.21.5 192.xx.xx.3 \n"})}),"\n",(0,t.jsxs)(n.p,{children:["The function GetPreferredNodeAddress used by the apiserver mentioned above when querying the host of the node will select one from the Address list according to the priority, so in es, we set the podIP of ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manage"})})," as other priority higher than the InternalIP category address, as shown below, you can specify the type of ip and the value of ip."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'func GetAddress(ctx context.Context, rootClient kubernetes.Interface, originAddress []corev1.NodeAddress) ([]corev1.NodeAddress, error) {\r\n preferredAddressType := corev1.NodeAddressType(os.Getenv("PREFERRED-ADDRESS-TYPE"))\r\n \r\n if len(preferredAddressType) == 0 {\r\n preferredAddressType = corev1.NodeInternalDNS\r\n }\r\n \r\n prefixAddress := []corev1.NodeAddress{\r\n {Type: preferredAddressType, Address: os.Getenv("LEAF_NODE_IP")},\r\n }\r\n \r\n address, err := SortAddress(ctx, rootClient, originAddress)\r\n \r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n return append(prefixAddress, address...), nil\r\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"How to check address priority? By looking at the startup parameter of api-server - kubelet-preferred-address-types, the GetPreferredNodeAddress function is set here to obtain the priority of the host.\r\nBy default, InternalDNS has the highest priority."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:"- --kubelet-preferred-address-types=InternalDNS,InternalIP,Hostname,ExternaLDNS,ExternalIP\n"})}),"\n",(0,t.jsx)(n.h3,{id:"conclusion",children:"Conclusion"}),"\n",(0,t.jsxs)(n.p,{children:["In Kosmos, both ",(0,t.jsx)(n.code,{children:"kubectl exec"})," and ",(0,t.jsx)(n.code,{children:"kubectl log"}),' are "tricked" by the API server and redirected to our own ',(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service.\r\nThis allows us to implement customized features in subsequent steps."]})]})}function h(e={}){const{wrapper:n}={...(0,o.M)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},4252:(e,n,r)=>{r.d(n,{c:()=>t});const t=r.p+"assets/images/EXEC_Log_Arch-55169f06d1b0071b36b0ddb300a3e3fd.png"},2172:(e,n,r)=>{r.d(n,{I:()=>a,M:()=>i});var t=r(1504);const o={},s=t.createContext(o);function i(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/9882b082.85523005.js b/docs/assets/js/9882b082.85523005.js new file mode 100644 index 0000000..2707d56 --- /dev/null +++ b/docs/assets/js/9882b082.85523005.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[786],{1076:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>d,contentTitle:()=>i,default:()=>h,frontMatter:()=>s,metadata:()=>a,toc:()=>c});var t=r(7624),o=r(2172);const s={id:"exe-and-log",title:"Design of EXEC and Log in Kosmos"},i="Design of EXEC and Log in Kosmos",a={id:"v0.2.0/tutorials/exe-and-log",title:"Design of EXEC and Log in Kosmos",description:"Kosmos EXEC and Log Solution",source:"@site/docs/v0.2.0/tutorials/design-of-exec-and-log.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/exe-and-log",permalink:"/website/v0.2.0/tutorials/exe-and-log",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/design-of-exec-and-log.md",tags:[],version:"current",lastUpdatedBy:"qiuming520",lastUpdatedAt:1710846733,formattedLastUpdatedAt:"Mar 19, 2024",frontMatter:{id:"exe-and-log",title:"Design of EXEC and Log in Kosmos"},sidebar:"tutorialSidebar",previous:{title:"Multi-cluster PV/PVC Dynamic Storage",permalink:"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage"},next:{title:"Kosmos Node NotReady",permalink:"/website/v0.2.0/tutorials/node-not-ready"}},d={},c=[{value:"Kosmos EXEC and Log Solution",id:"kosmos-exec-and-log-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Background Knowledge",id:"background-knowledge",level:3},{value:"Implementation in Kosmos",id:"implementation-in-kosmos",level:3},{value:"Customization",id:"customization",level:3},{value:"Conclusion",id:"conclusion",level:3}];function l(e){const n={code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.M)(),...e.components};return(0,t.jsxs)(t.Fragment,{children:[(0,t.jsx)(n.h1,{id:"design-of-exec-and-log-in-kosmos",children:"Design of EXEC and Log in Kosmos"}),"\n",(0,t.jsx)(n.h2,{id:"kosmos-exec-and-log-solution",children:"Kosmos EXEC and Log Solution"}),"\n",(0,t.jsx)(n.h3,{id:"introduction",children:"Introduction"}),"\n",(0,t.jsxs)(n.p,{children:["In Kosmos, the pods scheduled to kosmos-node also support the ",(0,t.jsx)(n.code,{children:"kubectl exec"})," and ",(0,t.jsx)(n.code,{children:"kubectl log"})," functions.\r\nSince the overall architecture of ",(0,t.jsx)(n.code,{children:"kubectl exec"})," and ",(0,t.jsx)(n.code,{children:"kubectl log"})," is the same, we will use ",(0,t.jsx)(n.code,{children:"kubectl exec"})," as a sample to introduce the overall architecture.\r\nThe following diagram illustrates the overall design architecture."]}),"\n",(0,t.jsx)(n.p,{children:(0,t.jsx)(n.img,{alt:"EXE Log_Arch.png",src:r(4252).c+"",width:"1110",height:"863"})}),"\n",(0,t.jsx)(n.h3,{id:"background-knowledge",children:"Background Knowledge"}),"\n",(0,t.jsxs)(n.p,{children:["First, let's explore how to implement ",(0,t.jsx)(n.code,{children:"kubectl exec"})," in Kubernetes.\r\nThe ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"leaf-cluster"})})," part of the architecture diagram is a representation of the ",(0,t.jsx)(n.code,{children:"kubectl exec"})," function of a native cluster.\r\nThe kubectl exec request initiated by the user is processed by apiserver.\r\nAfter receiving the exec request, apiserver needs to forward the request to the node where the pod is allocated, so it needs to query the information of the node where the pod is allocated.\r\nIn the Kubernetes source code, apiserver will call the ",(0,t.jsx)(n.code,{children:"ExecLocation"})," method to obtain the exec url of the pod.\r\nThe code is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'// ExecLocation returns the exec URL for a pod container. If opts.Container is blank\r\n// and only one container is present in the pod, that container is used.\r\nfunc ExecLocation(\r\n ctx context.Context,\r\n getter ResourceGetter,\r\n connInfo client.ConnectionInfoGetter,\r\n name string,\r\n opts *api.PodExecOptions,\r\n) (*url.URL, http.RoundTripper, error) {\r\n return streamLocation(ctx, getter, connInfo, name, opts, opts.Container, "exec")\r\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"ExecLocation"})," calls the ",(0,t.jsx)(n.code,{children:"streamLocation"})," method, and streamLocation obtains pod information through the pod name."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'func streamLocation(\r\n ctx context.Context,\r\n getter ResourceGetter,\r\n connInfo client.ConnectionInfoGetter,\r\n name string,\r\n opts runtime.Object,\r\n container,\r\n path string,\r\n) (*url.URL, http.RoundTripper, error) {\r\n pod, err := getPod(ctx, getter, name)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n \r\n // Try to figure out a container\r\n // If a container was provided, it must be valid\r\n container, err = validateContainer(container, pod)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n \r\n nodeName := types.NodeName(pod.Spec.NodeName)\r\n if len(nodeName) == 0 {\r\n // If pod has not been assigned a host, return an empty location\r\n return nil, nil, errors.NewBadRequest(fmt.Sprintf("pod %s does not have a host assigned", name))\r\n }\r\n nodeInfo, err := connInfo.GetConnectionInfo(ctx, nodeName)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n params := url.Values{}\r\n if err := streamParams(params, opts); err != nil {\r\n return nil, nil, err\r\n }\r\n loc := &url.URL{\r\n Scheme: nodeInfo.Scheme,\r\n Host: net.JoinHostPort(nodeInfo.Hostname, nodeInfo.Port),\r\n Path: fmt.Sprintf("/%s/%s/%s/%s", path, pod.Namespace, pod.Name, container),\r\n RawQuery: params.Encode(),\r\n }\r\n return loc, nodeInfo.Transport, nil\r\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["Then the node name where the pod is allocated is obtained through ",(0,t.jsx)(n.code,{children:"pod.Spec.NodeName"}),", and then a key method ",(0,t.jsx)(n.code,{children:"GetConnectionInfo"})," is called. The code is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:"// GetConnectionInfo retrieves connection info from the status of a Node API object.\r\nfunc (k *NodeConnectionInfoGetter) GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error) {\r\n node, err := k.nodes.Get(ctx, string(nodeName), metav1.GetOptions{})\r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n // Find a kubelet-reported address, using preferred address type\r\n host, err := nodeutil.GetPreferredNodeAddress(node, k.preferredAddressTypes)\r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n // Use the kubelet-reported port, if present\r\n port := int(node.Status.DaemonEndpoints.KubeletEndpoint.Port)\r\n if port <= 0 {\r\n port = k.defaultPort\r\n }\r\n \r\n return &ConnectionInfo{\r\n Scheme: k.scheme,\r\n Hostname: host,\r\n Port: strconv.Itoa(port),\r\n Transport: k.transport,\r\n InsecureSkipTLSVerifyTransport: k.insecureSkipTLSVerifyTransport,\r\n }, nil\r\n}\n"})}),"\n",(0,t.jsxs)(n.p,{children:[(0,t.jsx)(n.code,{children:"GetConnectionInfo"})," obtains the node information through the node name, then uses ",(0,t.jsx)(n.code,{children:"GetPreferredNodeAddress"})," to select a suitable host, and then through the ",(0,t.jsx)(n.code,{children:"streamLocation"})," processing, an exec request URL is pieced together.\r\nThe apiserver will know which node to forward the exec request to.\r\nThe kubelet service running on the node will capture the exec request and then establish a link with the pod."]}),"\n",(0,t.jsx)(n.p,{children:"The above briefly introduces the process of establishing kubectl exec."}),"\n",(0,t.jsx)(n.h3,{id:"implementation-in-kosmos",children:"Implementation in Kosmos"}),"\n",(0,t.jsxs)(n.p,{children:["Next, let's take a look at the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"root-cluster"})})," in the overall architecture diagram.\r\nIn order for the exec request to be passed to the leaf cluster, the exec request needs to be forwarded."]}),"\n",(0,t.jsxs)(n.p,{children:["First, we need to tell apiserver that the ip address of kosmos-node is the podIP of our ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})}),", which will cause apiserver to forward the exec request to ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})}),".\r\nWhen we synchronize the node information of kosmos-node, we read it from the environment variable ",(0,t.jsx)(n.code,{children:"LEAF_NODE_IP"}),".\r\nThis environment variable is configured when starting the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service.\r\nThe key configuration fragment is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:"spec:\r\n serviceAccountName: clustertree\r\n containers:\r\n - name: clustertree-cluster-manager\r\n image: ghcr.io/kosmos-io/clustertree-cluster-manager:__VERSION__\r\n imagePullPolicy: IfNotPresent\r\n env:\r\n - name: APISERVER_CERT_LOCATION\r\n value: /etc/cluster-tree/cert/cert.pem\r\n - name: APISERVER_KEY_LOCATION\r\n value: /etc/cluster-tree/cert/key.pem\r\n - name: LEAF_NODE_IP\r\n valueFrom:\r\n fieldRef:\r\n fieldPath: status.podIP\r\n - name: PREFERRED-ADDRESS-TYPE\r\n value: InternalDNS\n"})}),"\n",(0,t.jsxs)(n.p,{children:["Then we need to start a service similar to kubelet that listens to exec.\r\nIn the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service, we start a nodeserver service.\r\nThe code snippet is as follows:"]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'nodeServer := nodeserver.NodeServer{\r\n RootClient: mgr.GetClient(),\r\n GlobalLeafManager: globalleafManager,\r\n}\r\ngo func() {\r\n if err := nodeServer.Start(ctx, opts); err != nil {\r\n klog.Errorf("failed to start node server: %v", err)\r\n }\r\n}()\n'})}),"\n",(0,t.jsx)(n.p,{children:"This service monitors exec and log requests, and will act as a proxy to forward the monitored requests to the corresponding leaf cluster.\r\nThe source code is as follows:"}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'func (s *NodeServer) AttachRoutes(m *http.ServeMux) {\r\n r := mux.NewRouter()\r\n r.StrictSlash(true)\r\n \r\n r.HandleFunc(\r\n "/containerLogs/{namespace}/{pod}/{container}",\r\n api.ContainerLogsHandler(s.getClient),\r\n ).Methods("GET")\r\n \r\n r.HandleFunc(\r\n "/exec/{namespace}/{pod}/{container}",\r\n api.ContainerExecHandler(\r\n api.ContainerExecOptions{\r\n StreamIdleTimeout: 30 * time.Second,\r\n StreamCreationTimeout: 30 * time.Second,\r\n },\r\n s.getClient,\r\n ),\r\n ).Methods("POST", "GET")\r\n \r\n r.NotFoundHandler = http.HandlerFunc(api.NotFound)\r\n \r\n m.Handle("/", r)\r\n}\n'})}),"\n",(0,t.jsxs)(n.p,{children:["With the forwarding part completed, we need to make the API server in the root cluster recognize the communication address of the kosmos-node as the address of the ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service.\r\nTherefore, when maintaining the status of kosmos-node, we synchronize the podIP of ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," to kosmos-node.\r\nThe complete process is as follows:"]}),"\n",(0,t.jsxs)(n.ul,{children:["\n",(0,t.jsx)(n.li,{children:"The user initiates an exec request."}),"\n",(0,t.jsx)(n.li,{children:"The API server in the root cluster receives the exec request and queries the node information based on the pod information."}),"\n",(0,t.jsx)(n.li,{children:"The queried node host is the podIP of clustertree-cluster-manager."}),"\n",(0,t.jsx)(n.li,{children:"The API server in the root cluster establishes an exec connection with clustertree-cluster-manager."}),"\n",(0,t.jsx)(n.li,{children:"clustertree-cluster-manager receives the exec connection request, queries the pod information, and proxies the exec request to the leaf cluster.\r\nWith this process, Kosmos implements the exec functionality, and the log functionality works in the same way."}),"\n"]}),"\n",(0,t.jsx)(n.h3,{id:"customization",children:"Customization"}),"\n",(0,t.jsxs)(n.p,{children:["When connecting with es products, there is a customized requirement.\r\nThe above design will cause the IPs of all kosmos-node to be the podIPs of ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manage"})}),".\r\nIn the product design of es, nodeIP is used as the primary key, which causes the product to fail to be stored in the warehouse.\r\nFor this purpose, kosmos has made a special design.\r\nThe ip address in the node information obtained through kubectl get node -owide is of the InternalIP type."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"sudo kubectl get nodes -owide\r\nNAME STATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME\r\nkosmos-control-1 Ready control-plane,master,node 65d v1.21.5 192.xx.xx.1 BigCloud Enterprise Linux For Euler 21.10 LTS 4.19.90-2107.6.0.0192.8.oe1.bclinux.x86_64 containerd://1.5.7\r\nkosmos-control-2 Ready node 65d v1.21.5 192.xx.xx.2 BigCloud Enterprise Linux For Euler 21.10 LTS 4.19.90-2107.6.0.0192.8.oe1.bclinux.x86_64 containerd://1.5.7\r\nkosmos-cluster1 Ready agent 20d v1.21.5 192.xx.xx.3 \n"})}),"\n",(0,t.jsxs)(n.p,{children:["The function GetPreferredNodeAddress used by the apiserver mentioned above when querying the host of the node will select one from the Address list according to the priority, so in es, we set the podIP of ",(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manage"})})," as other priority higher than the InternalIP category address, as shown below, you can specify the type of ip and the value of ip."]}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",metastring:"script",children:'func GetAddress(ctx context.Context, rootClient kubernetes.Interface, originAddress []corev1.NodeAddress) ([]corev1.NodeAddress, error) {\r\n preferredAddressType := corev1.NodeAddressType(os.Getenv("PREFERRED-ADDRESS-TYPE"))\r\n \r\n if len(preferredAddressType) == 0 {\r\n preferredAddressType = corev1.NodeInternalDNS\r\n }\r\n \r\n prefixAddress := []corev1.NodeAddress{\r\n {Type: preferredAddressType, Address: os.Getenv("LEAF_NODE_IP")},\r\n }\r\n \r\n address, err := SortAddress(ctx, rootClient, originAddress)\r\n \r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n return append(prefixAddress, address...), nil\r\n}\n'})}),"\n",(0,t.jsx)(n.p,{children:"How to check address priority? By looking at the startup parameter of api-server - kubelet-preferred-address-types, the GetPreferredNodeAddress function is set here to obtain the priority of the host.\r\nBy default, InternalDNS has the highest priority."}),"\n",(0,t.jsx)(n.pre,{children:(0,t.jsx)(n.code,{className:"language-shell",children:"- --kubelet-preferred-address-types=InternalDNS,InternalIP,Hostname,ExternaLDNS,ExternalIP\n"})}),"\n",(0,t.jsx)(n.h3,{id:"conclusion",children:"Conclusion"}),"\n",(0,t.jsxs)(n.p,{children:["In Kosmos, both ",(0,t.jsx)(n.code,{children:"kubectl exec"})," and ",(0,t.jsx)(n.code,{children:"kubectl log"}),' are "tricked" by the API server and redirected to our own ',(0,t.jsx)(n.em,{children:(0,t.jsx)(n.strong,{children:"clustertree-cluster-manager"})})," service.\r\nThis allows us to implement customized features in subsequent steps."]})]})}function h(e={}){const{wrapper:n}={...(0,o.M)(),...e.components};return n?(0,t.jsx)(n,{...e,children:(0,t.jsx)(l,{...e})}):l(e)}},4252:(e,n,r)=>{r.d(n,{c:()=>t});const t=r.p+"assets/images/EXEC_Log_Arch-55169f06d1b0071b36b0ddb300a3e3fd.png"},2172:(e,n,r)=>{r.d(n,{I:()=>a,M:()=>i});var t=r(1504);const o={},s=t.createContext(o);function i(e){const n=t.useContext(s);return t.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function a(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:i(e.components),t.createElement(s.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b4ae384a.878dcfab.js b/docs/assets/js/b4ae384a.878dcfab.js deleted file mode 100644 index 540987e..0000000 --- a/docs/assets/js/b4ae384a.878dcfab.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[20],{1184:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var n=s(7624),r=s(2172);const i={id:"k8s-in-k8s",title:"Kubernetes in Kubernetes"},o="Kubernetes in Kubernetes",l={id:"v0.2.0/proposals/k8s-in-k8s",title:"Kubernetes in Kubernetes",description:"Summary",source:"@site/docs/v0.2.0/proposals/k8s-in-k8s.md",sourceDirName:"v0.2.0/proposals",slug:"/v0.2.0/proposals/k8s-in-k8s",permalink:"/website/v0.2.0/proposals/k8s-in-k8s",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/proposals/k8s-in-k8s.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1708679400,formattedLastUpdatedAt:"Feb 23, 2024",frontMatter:{id:"k8s-in-k8s",title:"Kubernetes in Kubernetes"},sidebar:"tutorialSidebar",previous:{title:"kubenest",permalink:"/website/v0.2.0/tutorials/kubenest"},next:{title:"Distribution Policy",permalink:"/website/v0.2.0/proposals/distribution-policy"}},a={},c=[{value:"Summary",id:"summary",level:2},{value:"Motivation",id:"motivation",level:2},{value:"Goals",id:"goals",level:3},{value:"Non-Goals",id:"non-goals",level:3},{value:"Proposal",id:"proposal",level:2},{value:"Function Overview",id:"function-overview",level:3},{value:"User Stories (Optional)",id:"user-stories-optional",level:3},{value:"Story 1",id:"story-1",level:4},{value:"Design Details",id:"design-details",level:2},{value:"Overall Architecture",id:"overall-architecture",level:3},{value:"CRD Design",id:"crd-design",level:3},{value:"Overall Process",id:"overall-process",level:3},{value:"Test Plan",id:"test-plan",level:2},{value:"Unit Test",id:"unit-test",level:3},{value:"E2E Test",id:"e2e-test",level:3}];function d(e){const t={code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.M)(),...e.components};return(0,n.jsxs)(n.Fragment,{children:[(0,n.jsx)(t.h1,{id:"kubernetes-in-kubernetes",children:"Kubernetes in Kubernetes"}),"\n",(0,n.jsx)(t.h2,{id:"summary",children:"Summary"}),"\n",(0,n.jsx)(t.p,{children:"Kosmos now supports the management of different Kubernetes (k8s) clusters, offering a unified control plane view for resource management and scheduling. This proposal introduces a method to achieve Kubernetes within Kubernetes (k8s in k8s) using Kosmos."}),"\n",(0,n.jsx)(t.p,{children:"The approach involves creating different Kubernetes control plane services within a single k8s cluster and deploying Kosmos' ClusterTree service. The ClusterTree listens to the kube-apiserver address of the created k8s control plane and incorporates the current cluster as a node into the dynamically created control plane. Each control plane has its exclusive etcd, ensuring the isolation of permissions and data for different tenants."}),"\n",(0,n.jsx)(t.h2,{id:"motivation",children:"Motivation"}),"\n",(0,n.jsx)(t.p,{children:"In some cases, cloud providers offer a large k8s cluster as infrastructure to different tenants, providing computational resources like CPU and GPU. Therefore, a k8s in k8s solution is required to isolate permissions and data for different tenants."}),"\n",(0,n.jsx)(t.h3,{id:"goals",children:"Goals"}),"\n",(0,n.jsx)(t.p,{children:"Divide the computational power of a single k8s cluster into multiple distinct k8s clusters, achieving permission and data isolation for different tenants."}),"\n",(0,n.jsx)(t.h3,{id:"non-goals",children:"Non-Goals"}),"\n",(0,n.jsx)(t.h2,{id:"proposal",children:"Proposal"}),"\n",(0,n.jsx)(t.p,{children:"Implement a k8s in k8s solution with Kosmos, allocating a single cluster's computational resources to different tenants."}),"\n",(0,n.jsx)(t.h3,{id:"function-overview",children:"Function Overview"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"Enable splitting a single cluster into different smaller clusters through Kosmos."}),"\n",(0,n.jsx)(t.li,{children:"Provide tenants with exclusive etcd and k8s control planes to ensure complete isolation of permissions and resources."}),"\n",(0,n.jsx)(t.li,{children:"Ensure tenants' control planes offer the same functionalities as a single k8s control plane, without changing the user experience."}),"\n"]}),"\n",(0,n.jsx)(t.h3,{id:"user-stories-optional",children:"User Stories (Optional)"}),"\n",(0,n.jsx)(t.h4,{id:"story-1",children:"Story 1"}),"\n",(0,n.jsx)(t.p,{children:"Imagine a supercluster with tens of thousands of nodes, hosting many different tenants. These tenants do not require all the computational resources of the entire k8s cluster, and for security reasons, it's crucial to ensure complete permission isolation between tenants. The native RBAC permission isolation solution in k8s might be insufficient, and k8s's reliance on namespaces for resource isolation could alter the user experience, restricting operations to the namespace level, which could be user-unfriendly."}),"\n",(0,n.jsx)(t.h2,{id:"design-details",children:"Design Details"}),"\n",(0,n.jsx)(t.h3,{id:"overall-architecture",children:"Overall Architecture"}),"\n",(0,n.jsx)(t.p,{children:(0,n.jsx)(t.img,{alt:"Kubernetes_in_Kubernetes.svg",src:s(8380).c+"",width:"1071",height:"828"})}),"\n",(0,n.jsx)(t.p,{children:"As shown in the figure, each tenant has a separate k8s control plane and etcd. Each tenant's k8s control plane uses Kosmos to manage the nodes of the current cluster as virtual nodes for the control plane. The CRD configuration determines the number of nodes from the current cluster each control plane should manage."}),"\n",(0,n.jsx)(t.h3,{id:"crd-design",children:"CRD Design"}),"\n",(0,n.jsx)(t.pre,{children:(0,n.jsx)(t.code,{className:"language-shell",metastring:"script",children:"apiVersion: kosmos.io/v1alpha1\r\nkind: VirtualCluster\r\nmetadata:\r\n name: tenant1-cluster\r\nspec:\r\n kubeconfig: XXXXXX\r\n promoteResources:\r\n nodes:\r\n - node1\r\n - node2\r\n resources:\r\n cpu: 10\r\n memory: 100Gi\r\nstatus:\r\n phase: Initialized\n"})}),"\n",(0,n.jsx)(t.h3,{id:"overall-process",children:"Overall Process"}),"\n",(0,n.jsxs)(t.ol,{children:["\n",(0,n.jsx)(t.li,{children:"A cluster administrator creates a VirtualCluster CR resource."}),"\n",(0,n.jsx)(t.li,{children:"The Kosmos-operator listens for the creation of the VirtualCluster, starts the creation of the Kubernetes control plane services including the kube-apiserver, kube-controller-manager, kube-scheduler, and etcd. Once the Kubernetes control plane services are setup, the VirtualCluster's status.phase will be set to Initialized, and the spec.kubeconfig field will be populated."}),"\n",(0,n.jsx)(t.li,{children:"After the control plane is set up, the Kosmos-operator creates the Kosmos clusterTree service and configures the clusterTree's apiserver address to the current control plane using the kubeconfig value from the VirtualCluster."}),"\n",(0,n.jsx)(t.li,{children:"Once the clusterTree is ready, the Kosmos-operator manages the tenant's required node resources or computational resources like CPU and memory into the tenant's control plane based on the VirtualCluster's promoteResource configuration. Tenants can then manage resources in the control plane using the spec.kubeconfig."}),"\n"]}),"\n",(0,n.jsx)(t.h2,{id:"test-plan",children:"Test Plan"}),"\n",(0,n.jsx)(t.h3,{id:"unit-test",children:"Unit Test"}),"\n",(0,n.jsx)(t.h3,{id:"e2e-test",children:"E2E Test"}),"\n",(0,n.jsxs)(t.table,{children:[(0,n.jsx)(t.thead,{children:(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.th,{children:"Test Case"}),(0,n.jsx)(t.th,{children:"Case Description"})]})}),(0,n.jsxs)(t.tbody,{children:[(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Virtual Control Plane Creation"}),(0,n.jsx)(t.td,{children:"Test the creation of a virtual control plane through the VirtualCluster CRD"})]}),(0,n.jsxs)(t.tr,{children:[(0,n.jsx)(t.td,{children:"Service Creation in Virtual Control Plane"}),(0,n.jsx)(t.td,{children:"Test the creation of services in the virtual control plane and their external functionality"})]})]})]})]})}function u(e={}){const{wrapper:t}={...(0,r.M)(),...e.components};return t?(0,n.jsx)(t,{...e,children:(0,n.jsx)(d,{...e})}):d(e)}},8380:(e,t,s)=>{s.d(t,{c:()=>n});const n=s.p+"assets/images/Kubernetes_in_Kubernetes-68a4983b483a83a8793f2fb6aea57bcc.svg"},2172:(e,t,s)=>{s.d(t,{I:()=>l,M:()=>o});var n=s(1504);const r={},i=n.createContext(r);function o(e){const t=n.useContext(i);return n.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),n.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b4ae384a.8ec3beec.js b/docs/assets/js/b4ae384a.8ec3beec.js new file mode 100644 index 0000000..5d11c3e --- /dev/null +++ b/docs/assets/js/b4ae384a.8ec3beec.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[20],{1184:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>a,contentTitle:()=>o,default:()=>u,frontMatter:()=>i,metadata:()=>l,toc:()=>c});var s=n(7624),r=n(2172);const i={id:"k8s-in-k8s",title:"Kubernetes in Kubernetes"},o="Kubernetes in Kubernetes",l={id:"v0.2.0/proposals/k8s-in-k8s",title:"Kubernetes in Kubernetes",description:"Summary",source:"@site/docs/v0.2.0/proposals/k8s-in-k8s.md",sourceDirName:"v0.2.0/proposals",slug:"/v0.2.0/proposals/k8s-in-k8s",permalink:"/website/v0.2.0/proposals/k8s-in-k8s",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/proposals/k8s-in-k8s.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1708679400,formattedLastUpdatedAt:"Feb 23, 2024",frontMatter:{id:"k8s-in-k8s",title:"Kubernetes in Kubernetes"},sidebar:"tutorialSidebar",previous:{title:"Application Migration",permalink:"/website/v0.2.0/tutorials/application-migration"},next:{title:"Distribution Policy",permalink:"/website/v0.2.0/proposals/distribution-policy"}},a={},c=[{value:"Summary",id:"summary",level:2},{value:"Motivation",id:"motivation",level:2},{value:"Goals",id:"goals",level:3},{value:"Non-Goals",id:"non-goals",level:3},{value:"Proposal",id:"proposal",level:2},{value:"Function Overview",id:"function-overview",level:3},{value:"User Stories (Optional)",id:"user-stories-optional",level:3},{value:"Story 1",id:"story-1",level:4},{value:"Design Details",id:"design-details",level:2},{value:"Overall Architecture",id:"overall-architecture",level:3},{value:"CRD Design",id:"crd-design",level:3},{value:"Overall Process",id:"overall-process",level:3},{value:"Test Plan",id:"test-plan",level:2},{value:"Unit Test",id:"unit-test",level:3},{value:"E2E Test",id:"e2e-test",level:3}];function d(e){const t={code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",table:"table",tbody:"tbody",td:"td",th:"th",thead:"thead",tr:"tr",...(0,r.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"kubernetes-in-kubernetes",children:"Kubernetes in Kubernetes"}),"\n",(0,s.jsx)(t.h2,{id:"summary",children:"Summary"}),"\n",(0,s.jsx)(t.p,{children:"Kosmos now supports the management of different Kubernetes (k8s) clusters, offering a unified control plane view for resource management and scheduling. This proposal introduces a method to achieve Kubernetes within Kubernetes (k8s in k8s) using Kosmos."}),"\n",(0,s.jsx)(t.p,{children:"The approach involves creating different Kubernetes control plane services within a single k8s cluster and deploying Kosmos' ClusterTree service. The ClusterTree listens to the kube-apiserver address of the created k8s control plane and incorporates the current cluster as a node into the dynamically created control plane. Each control plane has its exclusive etcd, ensuring the isolation of permissions and data for different tenants."}),"\n",(0,s.jsx)(t.h2,{id:"motivation",children:"Motivation"}),"\n",(0,s.jsx)(t.p,{children:"In some cases, cloud providers offer a large k8s cluster as infrastructure to different tenants, providing computational resources like CPU and GPU. Therefore, a k8s in k8s solution is required to isolate permissions and data for different tenants."}),"\n",(0,s.jsx)(t.h3,{id:"goals",children:"Goals"}),"\n",(0,s.jsx)(t.p,{children:"Divide the computational power of a single k8s cluster into multiple distinct k8s clusters, achieving permission and data isolation for different tenants."}),"\n",(0,s.jsx)(t.h3,{id:"non-goals",children:"Non-Goals"}),"\n",(0,s.jsx)(t.h2,{id:"proposal",children:"Proposal"}),"\n",(0,s.jsx)(t.p,{children:"Implement a k8s in k8s solution with Kosmos, allocating a single cluster's computational resources to different tenants."}),"\n",(0,s.jsx)(t.h3,{id:"function-overview",children:"Function Overview"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"Enable splitting a single cluster into different smaller clusters through Kosmos."}),"\n",(0,s.jsx)(t.li,{children:"Provide tenants with exclusive etcd and k8s control planes to ensure complete isolation of permissions and resources."}),"\n",(0,s.jsx)(t.li,{children:"Ensure tenants' control planes offer the same functionalities as a single k8s control plane, without changing the user experience."}),"\n"]}),"\n",(0,s.jsx)(t.h3,{id:"user-stories-optional",children:"User Stories (Optional)"}),"\n",(0,s.jsx)(t.h4,{id:"story-1",children:"Story 1"}),"\n",(0,s.jsx)(t.p,{children:"Imagine a supercluster with tens of thousands of nodes, hosting many different tenants. These tenants do not require all the computational resources of the entire k8s cluster, and for security reasons, it's crucial to ensure complete permission isolation between tenants. The native RBAC permission isolation solution in k8s might be insufficient, and k8s's reliance on namespaces for resource isolation could alter the user experience, restricting operations to the namespace level, which could be user-unfriendly."}),"\n",(0,s.jsx)(t.h2,{id:"design-details",children:"Design Details"}),"\n",(0,s.jsx)(t.h3,{id:"overall-architecture",children:"Overall Architecture"}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Kubernetes_in_Kubernetes.svg",src:n(8380).c+"",width:"1071",height:"828"})}),"\n",(0,s.jsx)(t.p,{children:"As shown in the figure, each tenant has a separate k8s control plane and etcd. Each tenant's k8s control plane uses Kosmos to manage the nodes of the current cluster as virtual nodes for the control plane. The CRD configuration determines the number of nodes from the current cluster each control plane should manage."}),"\n",(0,s.jsx)(t.h3,{id:"crd-design",children:"CRD Design"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-shell",metastring:"script",children:"apiVersion: kosmos.io/v1alpha1\r\nkind: VirtualCluster\r\nmetadata:\r\n name: tenant1-cluster\r\nspec:\r\n kubeconfig: XXXXXX\r\n promoteResources:\r\n nodes:\r\n - node1\r\n - node2\r\n resources:\r\n cpu: 10\r\n memory: 100Gi\r\nstatus:\r\n phase: Initialized\n"})}),"\n",(0,s.jsx)(t.h3,{id:"overall-process",children:"Overall Process"}),"\n",(0,s.jsxs)(t.ol,{children:["\n",(0,s.jsx)(t.li,{children:"A cluster administrator creates a VirtualCluster CR resource."}),"\n",(0,s.jsx)(t.li,{children:"The Kosmos-operator listens for the creation of the VirtualCluster, starts the creation of the Kubernetes control plane services including the kube-apiserver, kube-controller-manager, kube-scheduler, and etcd. Once the Kubernetes control plane services are setup, the VirtualCluster's status.phase will be set to Initialized, and the spec.kubeconfig field will be populated."}),"\n",(0,s.jsx)(t.li,{children:"After the control plane is set up, the Kosmos-operator creates the Kosmos clusterTree service and configures the clusterTree's apiserver address to the current control plane using the kubeconfig value from the VirtualCluster."}),"\n",(0,s.jsx)(t.li,{children:"Once the clusterTree is ready, the Kosmos-operator manages the tenant's required node resources or computational resources like CPU and memory into the tenant's control plane based on the VirtualCluster's promoteResource configuration. Tenants can then manage resources in the control plane using the spec.kubeconfig."}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"test-plan",children:"Test Plan"}),"\n",(0,s.jsx)(t.h3,{id:"unit-test",children:"Unit Test"}),"\n",(0,s.jsx)(t.h3,{id:"e2e-test",children:"E2E Test"}),"\n",(0,s.jsxs)(t.table,{children:[(0,s.jsx)(t.thead,{children:(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.th,{children:"Test Case"}),(0,s.jsx)(t.th,{children:"Case Description"})]})}),(0,s.jsxs)(t.tbody,{children:[(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Virtual Control Plane Creation"}),(0,s.jsx)(t.td,{children:"Test the creation of a virtual control plane through the VirtualCluster CRD"})]}),(0,s.jsxs)(t.tr,{children:[(0,s.jsx)(t.td,{children:"Service Creation in Virtual Control Plane"}),(0,s.jsx)(t.td,{children:"Test the creation of services in the virtual control plane and their external functionality"})]})]})]})]})}function u(e={}){const{wrapper:t}={...(0,r.M)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},8380:(e,t,n)=>{n.d(t,{c:()=>s});const s=n.p+"assets/images/Kubernetes_in_Kubernetes-68a4983b483a83a8793f2fb6aea57bcc.svg"},2172:(e,t,n)=>{n.d(t,{I:()=>l,M:()=>o});var s=n(1504);const r={},i=s.createContext(r);function o(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function l(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(r):e.components||r:o(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/b9ed296f.d7b9631b.js b/docs/assets/js/b9ed296f.d7b9631b.js deleted file mode 100644 index 59e7a8c..0000000 --- a/docs/assets/js/b9ed296f.d7b9631b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[762],{4476:(e,n,s)=>{s.r(n),s.d(n,{assets:()=>d,contentTitle:()=>t,default:()=>h,frontMatter:()=>l,metadata:()=>c,toc:()=>o});var r=s(7624),i=s(2172);const l={id:"ipsec-network_zh",title:"IPsec\u8de8\u96c6\u7fa4\u7f51\u7edc"},t="IPsec\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u89e3\u51b3\u65b9\u6848",c={id:"i18n/zh/v0.2.0/ipsec-network_zh",title:"IPsec\u8de8\u96c6\u7fa4\u7f51\u7edc",description:"\u4f7f\u7528IPsec\u96a7\u9053\u5728\u516c\u5171IP\u4e0a\u8fdb\u884c\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1",source:"@site/docs/i18n/zh/v0.2.0/ccn-ipsec-tunnel_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/ipsec-network_zh",permalink:"/website/i18n/zh/v0.2.0/ipsec-network_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/ccn-ipsec-tunnel_zh.md",tags:[],version:"current",frontMatter:{id:"ipsec-network_zh",title:"IPsec\u8de8\u96c6\u7fa4\u7f51\u7edc"}},d={},o=[{value:"\u4f7f\u7528IPsec\u96a7\u9053\u5728\u516c\u5171IP\u4e0a\u8fdb\u884c\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1",id:"\u4f7f\u7528ipsec\u96a7\u9053\u5728\u516c\u5171ip\u4e0a\u8fdb\u884c\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1",level:2},{value:"\u7b80\u4ecb",id:"\u7b80\u4ecb",level:3},{value:"\u52a8\u673a",id:"\u52a8\u673a",level:3},{value:"\u76ee\u6807",id:"\u76ee\u6807",level:3},{value:"\u8bbe\u8ba1\u7ec6\u8282",id:"\u8bbe\u8ba1\u7ec6\u8282",level:2},{value:"API\u53d8\u66f4",id:"api\u53d8\u66f4",level:3},{value:"Cluster API\u53d8\u66f4",id:"cluster-api\u53d8\u66f4",level:4},{value:"Clusternode API\u53d8\u66f4",id:"clusternode-api\u53d8\u66f4",level:4},{value:"Nodeconfig API\u53d8\u66f4",id:"nodeconfig-api\u53d8\u66f4",level:4},{value:"\u7ec4\u4ef6\u4fee\u6539",id:"\u7ec4\u4ef6\u4fee\u6539",level:3},{value:"Clusterlink-controller-manager",id:"clusterlink-controller-manager",level:4},{value:"Clusterlink-elector",id:"clusterlink-elector",level:4},{value:"Clusterlink-network-manager",id:"clusterlink-network-manager",level:4},{value:"clusterlink-agent",id:"clusterlink-agent",level:4},{value:"kosmosctl",id:"kosmosctl",level:4}];function a(e){const n={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,i.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(n.h1,{id:"ipsec\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u89e3\u51b3\u65b9\u6848",children:"IPsec\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u89e3\u51b3\u65b9\u6848"}),"\n",(0,r.jsx)(n.h2,{id:"\u4f7f\u7528ipsec\u96a7\u9053\u5728\u516c\u5171ip\u4e0a\u8fdb\u884c\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1",children:"\u4f7f\u7528IPsec\u96a7\u9053\u5728\u516c\u5171IP\u4e0a\u8fdb\u884c\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1"}),"\n",(0,r.jsx)(n.h3,{id:"\u7b80\u4ecb",children:"\u7b80\u4ecb"}),"\n",(0,r.jsx)(n.p,{children:"Kosmos\u662f\u4e00\u4e2a\u591a\u96c6\u7fa4\u89e3\u51b3\u65b9\u6848\uff0c\u7f51\u7edc\u662f\u5176\u91cd\u8981\u7ec4\u6210\u90e8\u5206\u3002\r\n\u6709\u65f6\u5019\uff0c\u9700\u8981\u5728\u4e0d\u540c\u7f51\u7edc\u7684Kubernetes\u96c6\u7fa4\u4e4b\u95f4\u8fdb\u884c\u901a\u4fe1\u3002\r\n\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0c\u4e24\u4e2a\u6216\u591a\u4e2a\u96c6\u7fa4\u53ea\u80fd\u901a\u8fc7\u516c\u5171\u4e92\u8054\u7f51\u8fdb\u884c\u901a\u4fe1\u3002\r\n\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0cKosmos\u5b9e\u73b0\u4e86\u57fa\u4e8eIPsec\u96a7\u9053\u7684\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1\u89e3\u51b3\u65b9\u6848\u3002"}),"\n",(0,r.jsx)(n.h3,{id:"\u52a8\u673a",children:"\u52a8\u673a"}),"\n",(0,r.jsx)(n.p,{children:"\u51fa\u4e8e\u707e\u96be\u6062\u590d\u7684\u8003\u8651\uff0c\u5e94\u7528\u90e8\u7f72\u53ef\u80fd\u9700\u8981\u5728\u591a\u4e91\u591a\u96c6\u7fa4\u73af\u5883\u7684\u4e0d\u540c\u533a\u57df\uff08\u8de8VPC\uff09\u4e4b\u95f4\u8fdb\u884c\u901a\u4fe1\u3002\r\n\u5728\u8fd9\u79cd\u60c5\u51b5\u4e0b\uff0c\u7531\u4e8e\u673a\u5668\u7684\u5185\u90e8IP\u5730\u5740\u901a\u5e38\u65e0\u6cd5\u76f4\u63a5\u8bbf\u95ee\u800c\u6ca1\u6709\u4e13\u7528\u7f51\u7edc\u8fde\u63a5\uff0c\u5bb9\u5668\u901a\u4fe1\u53d8\u5f97\u5177\u6709\u6311\u6218\u6027\u3002\r\n\u5e38\u89c1\u7684CNI\u96a7\u9053\u6280\u672f\u5982VxLAN\u6216IPIP\u5728\u516c\u5171\u4e92\u8054\u7f51\u73af\u5883\u4e0b\u53ef\u80fd\u65e0\u6cd5\u6709\u6548\u5de5\u4f5c\u3002\r\n\u4e3a\u89e3\u51b3\u6b64\u95ee\u9898\uff0cKosmos\u5b9e\u73b0\u4e86\u57fa\u4e8eIPsec\u96a7\u9053\u7684\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1\u89e3\u51b3\u65b9\u6848\uff0c\u7528\u4e8e\u901a\u8fc7\u516c\u5171\u4e92\u8054\u7f51\u8fdb\u884c\u8de8\u4e91\u901a\u4fe1\u3002\r\n\u8be5\u89e3\u51b3\u65b9\u6848\u65e8\u5728\u6ee1\u8db3\u5728\u516c\u5171\u7f51\u7edc\u4e2d\u8fdb\u884c\u901a\u4fe1\u7684\u9700\u6c42\uff0c\u5e76\u8003\u8651\u6570\u636e\u4f20\u8f93\u7684\u5b89\u5168\u6027\u3002"}),"\n",(0,r.jsx)(n.h3,{id:"\u76ee\u6807",children:"\u76ee\u6807"}),"\n",(0,r.jsx)(n.p,{children:"\u76ee\u6807\u662f\u4f7f\u7528\u5f39\u6027\u516c\u5171IP\u5730\u5740\u4f7f\u4e24\u4e2a\u96c6\u7fa4\u4e2d\u7684Pod\u80fd\u591f\u901a\u4fe1\u3002\u4e0b\u56fe\u5c55\u793a\u4e86\u6d41\u91cf\u7684\u6d41\u5411\uff1a"}),"\n",(0,r.jsx)(n.p,{children:(0,r.jsx)(n.img,{alt:"IPsec_Tunnel",src:s(4040).c+"",width:"1301",height:"331"})}),"\n",(0,r.jsx)(n.admonition,{title:"NOTE",type:"info",children:(0,r.jsx)(n.p,{children:"\u6b64\u89e3\u51b3\u65b9\u6848\u4e0d\u6d89\u53ca\u96c6\u7fa4\u5185\u4e3b\u673a\u7f51\u7edc\u6a21\u5f0f\u4e0b\u7684\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1\u3002\r\n\u4ec5\u5173\u6ce8IPv4\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1\uff0c\u5e76\u4e0d\u6db5\u76d6IPv6\u5bb9\u5668\u7f51\u7edc\u3002"})}),"\n",(0,r.jsx)(n.h2,{id:"\u8bbe\u8ba1\u7ec6\u8282",children:"\u8bbe\u8ba1\u7ec6\u8282"}),"\n",(0,r.jsx)(n.h3,{id:"api\u53d8\u66f4",children:"API\u53d8\u66f4"}),"\n",(0,r.jsx)(n.h4,{id:"cluster-api\u53d8\u66f4",children:"Cluster API\u53d8\u66f4"}),"\n",(0,r.jsxs)(n.p,{children:["\u6b64\u89e3\u51b3\u65b9\u6848\u5411 ",(0,r.jsx)(n.code,{children:".spec.ClusterLinkOptions"})," \u6dfb\u52a0\u4e86\u4e09\u4e2a\u5b57\u6bb5\uff1a",(0,r.jsx)(n.code,{children:"NodeElasticIPMap"}),"\u3001",(0,r.jsx)(n.code,{children:"ClusterPodCIDRs"})," \u548c ",(0,r.jsx)(n.code,{children:"UseExternalApiserver"}),"\u3002"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",metastring:"script",children:'type ClusterLinkOptions struct {\r\n ...\r\n // NodeElasticIPMap\u8868\u793aKubernetes\u4e2d\u8282\u70b9\u540d\u79f0\u4e0e\u6302\u8f7d\u5728\u8282\u70b9\u4e0a\u7684\u5f39\u6027IP\u4e4b\u95f4\u7684\u6620\u5c04\u5173\u7cfb\r\n // +optional\r\n NodeElasticIPMap map[string]string `json:"nodeElasticIPMap,omitempty"`\r\n // +optional\r\n ClusterPodCIDRs []string `json:"clusterpodCIDRs,omitempty"`\r\n // +optional\r\n UseExternalApiserver bool `json:"useexternalapiserver,omitempty"`\r\n}\n'})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"NodeElasticIPMap"})," \u5b57\u6bb5\u8868\u793aKubernetes\u4e2d\u8282\u70b9\u540d\u79f0\u4e0e\u6302\u8f7d\u5728\u8282\u70b9\u4e0a\u7684\u5f39\u6027\u516c\u5171IP\u4e4b\u95f4\u7684\u6620\u5c04\u5173\u7cfb\u3002"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ClusterPodCIDRs"})," \u5b57\u6bb5\u7528\u4e8e\u8f93\u5165Pod CIDR\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u67d0\u4e9bCNI\u63d2\u4ef6\u6765\u8bf4\u83b7\u53d6Pod CIDR\u5e76\u4e0d\u603b\u662f\u5bb9\u6613\u7684\u3002"]}),"\n"]}),"\n",(0,r.jsxs)(n.p,{children:["\u901a\u5e38\u60c5\u51b5\u4e0b\uff0cKosmos\u901a\u8fc7kube-apiserver\u53c2\u6570\u83b7\u53d6\u670d\u52a1CIDR\u3002\r\n\u7136\u800c\uff0c\u5728\u67d0\u4e9b\u60c5\u51b5\u4e0b\uff0ckube-apiserver\u4e0d\u662f\u96c6\u7fa4\u5185\u7684\u4e00\u4e2aPod\u3002\r\n\u56e0\u6b64\uff0c\u6dfb\u52a0\u4e86 ",(0,r.jsx)(n.code,{children:"UseExternalApiserver"})," \u5b57\u6bb5\u4ee5\u5904\u7406\u8fd9\u79cd\u60c5\u51b5\u3002"]}),"\n",(0,r.jsx)(n.h4,{id:"clusternode-api\u53d8\u66f4",children:"Clusternode API\u53d8\u66f4"}),"\n",(0,r.jsxs)(n.p,{children:["\u6b64\u89e3\u51b3\u65b9\u6848\u5411 ",(0,r.jsx)(n.code,{children:".spec"})," \u6dfb\u52a0\u4e86\u4e00\u4e2a\u65b0\u5b57\u6bb5 ",(0,r.jsx)(n.code,{children:"ElasticIP"}),"\uff0c\u5e76\u5411 ",(0,r.jsx)(n.code,{children:".status"})," \u6dfb\u52a0\u4e86\u4e00\u4e2a\u65b0\u5b57\u6bb5 ",(0,r.jsx)(n.code,{children:"NodeStatus"}),"\u3002"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",metastring:"script",children:'type ClusterNodeSpec struct {\r\n ...\r\n // +optional\r\n ElasticIP string `json:"elasticip,omitempty"`\r\n}\r\n\r\ntype ClusterNodeStatus struct {\r\n // +optional\r\n NodeStatus string `json:"nodeStatus,omitempty"`\r\n}\n'})}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"ElasticIP"})," \u5b57\u6bb5\u63cf\u8ff0\u4e86\u6302\u8f7d\u5728\u8282\u70b9\u4e0a\u7684\u5f39\u6027\u516c\u5171IP\u3002"]}),"\n",(0,r.jsxs)(n.li,{children:[(0,r.jsx)(n.code,{children:"NodeStatus"}),' \u5b57\u6bb5\u63cf\u8ff0\u4e86\u8282\u70b9\u7684\u72b6\u6001\uff0c\u53ef\u4ee5\u662f "Ready" \u6216 "NotReady"\u3002']}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"nodeconfig-api\u53d8\u66f4",children:"Nodeconfig API\u53d8\u66f4"}),"\n",(0,r.jsxs)(n.p,{children:["\u6b64\u89e3\u51b3\u65b9\u6848\u5411 ",(0,r.jsx)(n.code,{children:".spec"})," \u6dfb\u52a0\u4e86\u4e24\u4e2a\u65b0\u5b57\u6bb5 ",(0,r.jsx)(n.code,{children:"XfrmPoliciesXfrmStates"})," \u548c ",(0,r.jsx)(n.code,{children:"IPsetsAvoidMasqs"}),"\u3002"]}),"\n",(0,r.jsx)(n.pre,{children:(0,r.jsx)(n.code,{className:"language-shell",metastring:"script",children:'type NodeConfigSpec struct {\r\n XfrmPolicies []XfrmPolicy `json:"xfrmpolicies,omitempty"`\r\n XfrmStates []XfrmState `json:"xfrmstates,omitempty"`\r\n IPsetsAvoidMasqs []IPset `json:"ipsetsavoidmasq,omitempty"`\r\n}\r\n\r\ntype XfrmPolicy struct {\r\n LeftIP string `json:"leftip"`\r\n LeftNet string `json:"leftnet"`\r\n RightIP string `json:"rightip"`\r\n RightNet string `json:"rightnet"`\r\n ReqID int `json:"reqid"`\r\n Dir int `json:"dir"`\r\n}\r\n\r\ntype XfrmState struct {\r\n LeftIP string `json:"leftip"`\r\n RightIP string `json:"rightip"`\r\n ReqID int `json:"reqid"`\r\n SPI uint32 `json:"spi"`\r\n PSK string `json:"PSK"`\r\n}\r\n\r\ntype IPset struct {\r\n CIDR string `json:"cidr"`\r\n Name string `json:"name"`\r\n}\n'})}),"\n",(0,r.jsxs)(n.p,{children:["\u65b0\u7684 ",(0,r.jsx)(n.code,{children:"XfrmPolicies"})," \u548c ",(0,r.jsx)(n.code,{children:"XfrmStates"})," \u5b57\u6bb5\u5b9a\u4e49\u4e86Kosmos\u521b\u5efa\u7684\u4e0eIPsec\u76f8\u5173\u7684\u89c4\u5219\u3002"]}),"\n",(0,r.jsxs)(n.p,{children:[(0,r.jsx)(n.code,{children:"IPsetsAvoidMasqs"})," \u5b57\u6bb5\u63cf\u8ff0\u4e86\u9700\u8981\u907f\u514d\u4f2a\u88c5\u7684\u7f51\u7edc\u6bb5\uff0c\u5141\u8bb8\u5bb9\u5668\u7684\u51fa\u7ad9\u6d41\u91cf\u4fdd\u7559\u5176\u5bb9\u5668IP\u5730\u5740\u3002"]}),"\n",(0,r.jsx)(n.h3,{id:"\u7ec4\u4ef6\u4fee\u6539",children:"\u7ec4\u4ef6\u4fee\u6539"}),"\n",(0,r.jsx)(n.h4,{id:"clusterlink-controller-manager",children:"Clusterlink-controller-manager"}),"\n",(0,r.jsx)(n.p,{children:"\u5904\u7406kube-apiserver\u4e0d\u5728\u96c6\u7fa4\u5185\u7684\u60c5\u51b5\uff1a"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\u96c6\u7fa4\u63a7\u5236\u5668\u901a\u8fc7 ",(0,r.jsx)(n.code,{children:"GetSvcByCreateInvalidSvc"})," \u51fd\u6570\u4f18\u5316\u670d\u52a1CIDR\u7684\u83b7\u53d6\u3002"]}),"\n"]}),"\n",(0,r.jsx)(n.p,{children:"\u8282\u70b9\u72b6\u6001\u540c\u6b65\uff1a"}),"\n",(0,r.jsxs)(n.ul,{children:["\n",(0,r.jsxs)(n.li,{children:["\u8282\u70b9\u63a7\u5236\u5668\u57fa\u4e8e ",(0,r.jsx)(n.code,{children:"Cluster"})," \u5bf9\u8c61\u7684 ",(0,r.jsx)(n.code,{children:"NodeElasticIPMap"})," \u5b57\u6bb5\u503c\uff0c\u540c\u6b65 ",(0,r.jsx)(n.code,{children:"clusternode"})," \u5bf9\u8c61\u7684 ",(0,r.jsx)(n.code,{children:"ElasticIP"})," \u5b57\u6bb5\u3002"]}),"\n",(0,r.jsxs)(n.li,{children:['\u8282\u70b9\u63a7\u5236\u5668\u73b0\u5728\u6839\u636e\u8282\u70b9\u7684\u72b6\u6001\uff08"Ready" \u6216 "NotReady"\uff09\u66f4\u65b0 ',(0,r.jsx)(n.code,{children:"clusternode"})," \u5bf9\u8c61\u7684 ",(0,r.jsx)(n.code,{children:".Status.NodeStatus"})," \u5b57\u6bb5\u3002"]}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"clusterlink-elector",children:"Clusterlink-elector"}),"\n",(0,r.jsx)(n.p,{children:'\u9009\u4e3e\u6a21\u5757\u7528\u4e8e\u5728\u7f51\u5173\u6a21\u5f0f\u4e2d\u9009\u62e9\u7f51\u5173\u3002\u73b0\u5728\uff0c\u5b83\u53ef\u4ee5\u4ece\u5904\u4e8e "Ready" \u72b6\u6001\u7684\u8282\u70b9\u4e2d\u9009\u62e9\u4e00\u4e2a\u7f51\u5173\u3002'}),"\n",(0,r.jsx)(n.h4,{id:"clusterlink-network-manager",children:"Clusterlink-network-manager"}),"\n",(0,r.jsxs)(n.ol,{children:["\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsx)(n.p,{children:"\u6dfb\u52a0\u5bf9\u67d0\u4e9bCNI\u63d2\u4ef6\u7684\u652f\u6301\r\n\u5bf9\u4e8e\u67d0\u4e9bCNI\u63d2\u4ef6\uff0c\u6dfb\u52a0\u4e86iptables\u89c4\u5219\u4ee5\u907f\u514d\u4f2a\u88c5\uff0c\u5141\u8bb8\u5bb9\u5668\u7684\u51fa\u7ad9\u6d41\u91cf\u4fdd\u7559\u5176\u5bb9\u5668IP\u5730\u5740\u3002"}),"\n"]}),"\n",(0,r.jsxs)(n.li,{children:["\n",(0,r.jsxs)(n.p,{children:["\u6784\u5efaIPsec\u89c4\u5219\r\n\u901a\u5e38\u60c5\u51b5\u4e0b\uff0cKosmos\u521b\u5efa\u8def\u7531\u4ee5\u5b9e\u73b0\u5bb9\u5668\u901a\u4fe1\u3002\u5728IPsec\u96a7\u9053\u6a21\u5f0f\u4e0b\uff0c\u5982\u679c ",(0,r.jsx)(n.code,{children:"clusternode"})," \u7684 ",(0,r.jsx)(n.code,{children:"ElasticIP"})," \u5b57\u6bb5\u4e0d\u4e3a\u7a7a\uff0cKosmos\u4f1a\u521b\u5efa ",(0,r.jsx)(n.code,{children:"ip xfrm state"})," \u548c ",(0,r.jsx)(n.code,{children:"ip xfrm policy"})," \u89c4\u5219\u3002"]}),"\n"]}),"\n"]}),"\n",(0,r.jsx)(n.h4,{id:"clusterlink-agent",children:"clusterlink-agent"}),"\n",(0,r.jsxs)(n.p,{children:["\u6dfb\u52a0\u4e86\u6267\u884c\u7279\u5b9a\u64cd\u4f5c\u7684\u51fd\u6570\uff0c\u76f8\u5f53\u4e8e\u5728\u64cd\u4f5c\u7cfb\u7edf\u4e0a\u6267\u884c ",(0,r.jsx)(n.code,{children:"ip xfrm state add/del"})," \u548c ",(0,r.jsx)(n.code,{children:"ip xfrm policy add/del"})," \u547d\u4ee4\u3002"]}),"\n",(0,r.jsxs)(n.p,{children:["\u4e3a\u4e86\u907f\u514d\u4f2a\u88c5\uff0c\u6dfb\u52a0\u4e86\u6267\u884c ",(0,r.jsx)(n.code,{children:"ipset"})," \u547d\u4ee4\u548c\u521b\u5efaiptables\u89c4\u5219\u7684\u51fd\u6570\u3002"]}),"\n",(0,r.jsx)(n.h4,{id:"kosmosctl",children:"kosmosctl"}),"\n",(0,r.jsxs)(n.p,{children:["\u6dfb\u52a0\u4e86 ",(0,r.jsx)(n.code,{children:"NodeElasticIP"}),"\u3001",(0,r.jsx)(n.code,{children:"UseExternalApiserver"})," \u548c ",(0,r.jsx)(n.code,{children:"ClusterPodCIDRs"})," \u8f93\u5165\u53c2\u6570\uff0c\u7528\u4e8e\u586b\u5145 ",(0,r.jsx)(n.code,{children:"Cluster"})," CRD \u4e2d\u7684\u65b0\u5b57\u6bb5 ",(0,r.jsx)(n.code,{children:"NodeElasticIPMap"}),"\u3001",(0,r.jsx)(n.code,{children:"UseExternalApiserver"})," \u548c ",(0,r.jsx)(n.code,{children:"ClusterPodCIDRs"}),"\u3002"]})]})}function h(e={}){const{wrapper:n}={...(0,i.M)(),...e.components};return n?(0,r.jsx)(n,{...e,children:(0,r.jsx)(a,{...e})}):a(e)}},4040:(e,n,s)=>{s.d(n,{c:()=>r});const r=s.p+"assets/images/IPsec_Tunnel-9f261fc88ef5a03937ab257a45539388.jpeg"},2172:(e,n,s)=>{s.d(n,{I:()=>c,M:()=>t});var r=s(1504);const i={},l=r.createContext(i);function t(e){const n=r.useContext(l);return r.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function c(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:t(e.components),r.createElement(l.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/be2a6898.0572920c.js b/docs/assets/js/be2a6898.0572920c.js deleted file mode 100644 index 04618be..0000000 --- a/docs/assets/js/be2a6898.0572920c.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[584],{4884:(e,t,n)=>{n.r(t),n.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>c,frontMatter:()=>i,metadata:()=>r,toc:()=>d});var s=n(7624),o=n(2172);const i={},a="kubenest",r={id:"v0.2.0/tutorials/kubenest",title:"kubenest",description:"Introduction",source:"@site/docs/v0.2.0/tutorials/kubenest.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/kubenest",permalink:"/website/v0.2.0/tutorials/kubenest",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/kubenest.md",tags:[],version:"current",lastUpdatedBy:"qiuwei",lastUpdatedAt:1718274099,formattedLastUpdatedAt:"Jun 13, 2024",frontMatter:{},sidebar:"tutorialSidebar",previous:{title:"Application Migration",permalink:"/website/v0.2.0/tutorials/application-migration"},next:{title:"Kubernetes in Kubernetes",permalink:"/website/v0.2.0/proposals/k8s-in-k8s"}},l={},d=[{value:"Introduction",id:"introduction",level:2},{value:"What is kubenest?",id:"what-is-kubenest",level:3},{value:"Why do you need kubenest?",id:"why-do-you-need-kubenest",level:3},{value:"Solution",id:"solution",level:2},{value:"Overview",id:"overview",level:3},{value:"Architecture Diagram",id:"architecture-diagram",level:3},{value:"Virtual Cluster Custom Resource",id:"virtual-cluster-custom-resource",level:4},{value:"Virtual Cluster Controller",id:"virtual-cluster-controller",level:4},{value:"Node-agent",id:"node-agent",level:4},{value:"How to use",id:"how-to-use",level:2},{value:"Technical advantages",id:"technical-advantages",level:2},{value:"Differences from standard k8s",id:"differences-from-standard-k8s",level:2}];function h(e){const t={br:"br",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",p:"p",pre:"pre",ul:"ul",...(0,o.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"kubenest",children:"kubenest"}),"\n",(0,s.jsx)(t.h2,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsx)(t.h3,{id:"what-is-kubenest",children:"What is kubenest?"}),"\n",(0,s.jsx)(t.p,{children:"Kubenest is a solution that virtualizes multiple k8s clusters in a k8s cluster. The cluster that is virtualized with multiple k8s clusters is called host-k8s,\nand the virtualized cluster is called virtual-k8s, as shown in the figure below."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"kubenest",src:n(6159).c+"",width:"1050",height:"460"})}),"\n",(0,s.jsx)(t.h3,{id:"why-do-you-need-kubenest",children:"Why do you need kubenest?"}),"\n",(0,s.jsx)(t.p,{children:"In some cases, cloud vendors will provide a large k8s cluster as infrastructure at the bottom layer to provide computing resources such as CPU and GPU to different tenants.\nIn order to achieve the isolation of permissions and data of different tenants, multiple small k8s clusters need to be virtualized in the large k8s cluster for tenants to use.\nTenants do not perceive the existence of the large k8s cluster or other tenants, and use the virtualized k8s cluster like a normal k8s cluster.\nBased on this background, we designed kubenest."}),"\n",(0,s.jsx)(t.h2,{id:"solution",children:"Solution"}),"\n",(0,s.jsx)(t.h3,{id:"overview",children:"Overview"}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"kubenest",src:n(4759).c+"",width:"1632",height:"1020"})}),"\n",(0,s.jsxs)(t.p,{children:["As shown in the above figure, when a tenant accesses a virtual cluster, they first access the api-server in the virtual control plane on the hosted large cluster (Host k8s),\nexpose the network externally through nodeport, and then interact with the virtual-k8s cluster created by the api-server in the virtual control plane.\nUsers can deploy their own services in Virtual k8s. The nodes in Virtual k8s are separated from the hosted large cluster and then joined to virtual-k8s.\nBecause all control plane services of k8s are installed in the control plane, metadata and network are completely isolated for tenants,\nensuring the security of their data. At the same time, due to the automated disassembly and assembly of nodes,\ntenants are provided with the ability to scale elastically in seconds on demand.",(0,s.jsx)(t.br,{}),"\n",'In order to virtualize a virtual-k8s cluster in a host-k8s cluster, first, virtual-k8s needs a control plane, in which api-server,\ncontroller-manager, etcd, scheduler, and core-dns components need to be installed. The control plane of this virtual-k8s needs to be installed on the master node of host-k8s.\nThen, in virtual-k8s, components such as calico and kube-proxy need to be installed. Among them, api-server, controller-manager, etcd, scheduler,\nand core-dns are installed under a namespace in the host-k8s cluster, which is specified by the tenant in CustomResource when creating a virtualcluster.\nCustomResource is an entry point for the virtual control plane controller. After the control plane of virtual-k8s is installed,\nit is necessary to install the worker node of virtual-k8s. Here we consider removing the worker node in the host-k8s cluster and installing it in the virtual-k8s cluster.\nThis also explains why the control plane of virtual-k8s should be installed on the master node of host-k8s, because if it is installed in the worker node,\nthe subsequent disassembly and installation of the node may use this worker node. In this way, the node in virtual-k8s is actually a node in host-k8s.\nOnce it is removed and installed in virtual-k8s, the get node in host-k8s cannot get the removed node. Therefore, we need a place to "store" the node information in host-k8s.\nWe designed the Custom Resource Definition globalnode to synchronize label changes on host-k8s, and also store node status (such as whether it belongs to a shared cluster node and whether it is already occupied by virtual-k8s).\nWhen creating virtual-k8s, the controller will select nodes based on CR and globalnode.']}),"\n",(0,s.jsx)(t.h3,{id:"architecture-diagram",children:"Architecture Diagram"}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Architecture Diagram",src:n(1732).c+"",width:"1664",height:"1450"})}),"\n",(0,s.jsx)(t.h4,{id:"virtual-cluster-custom-resource",children:"Virtual Cluster Custom Resource"}),"\n",(0,s.jsx)(t.p,{children:"Virtual cluster CR is the API of the virtual control plane operator, which is the entrance to create a virtual control plane.\nAfter the upper-level service creates this CR, the virtual cluster controller performs a series of operations such as creating\na virtual control plane, disassembling nodes, and installing components. The following information needs to be paid attention to in the CR:"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Metadata.namespace: the ns of the virtual-k8s created. This ns is the ns in host-k8s, used to create the virtual-k8s control plane in this ns"}),"\n",(0,s.jsx)(t.li,{children:"metadata.name: Name of virtual-k8s created"}),"\n",(0,s.jsx)(t.li,{children:"Spec.externalIP: This IP will be added to the certificate of virtual-k8s kubeconfig, and the api-server of virtual-k8s\ncan be accessed externally through this IP"}),"\n",(0,s.jsx)(t.li,{children:"promotePolicies' labelSelector: Select the label of the worker node in host-k8s, and select the node based on the node label"}),"\n",(0,s.jsx)(t.li,{children:"promotePolicies.nodeCount: The number of selected nodes"}),"\n",(0,s.jsx)(t.li,{children:"Spec.kubeconfig: virtual-k8s' kubeconfig, encrypted with base64. No need to fill in on the client side, backfill to CR\nafter the virtual-k8s virtual control plane is created"}),"\n",(0,s.jsx)(t.li,{children:"Status.phase: The state created by the virtual control plane that does not need to be filled in on the client side.\nIt is also the state monitored by the two controllers of the virtual control plane and the disassembly node, and the corresponding\nlogic is processed according to this state"}),"\n"]}),"\n",(0,s.jsx)(t.p,{children:"An example of CR is as follows:"}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-yaml",children:'apiVersion: kosmos.io/v1alpha1\nkind: VirtualCluster\nmetadata:\n namespace: test-521-8\n name: test-521-8\nspec:\n externalIP: "192.168.0.1" #dummy ip\n promotePolicies:\n - labelSelector:\n matchLabels:\n kubernetes.io/hostname: kc-aaaaa-s-x6fn2\n nodeCount: 1\n'})}),"\n",(0,s.jsx)(t.h4,{id:"virtual-cluster-controller",children:"Virtual Cluster Controller"}),"\n",(0,s.jsx)(t.p,{children:"The virtual cluster controller is used to listen to the virtual cluster CR, create a virtual control plane for virtual-k8s,\ndisassemble worker nodes, install components in virtual-k8s, and perform a series of operations.\nThis controller is divided into three specific controllers based on its functions."}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"GlobalNodeController: Used to listen to the node node and update the label value on the node. At the same time,\nmaintain the disassembled state of the node. This information is needed in the CR created by the upper layer service"}),"\n",(0,s.jsx)(t.li,{children:"VirtualClusterInitController: Create a virtual control plane. After creating the virtual control plane,\nwait for the node to be added to the virtual cluster, and then start installing the components"}),"\n",(0,s.jsx)(t.li,{children:"NodeController: listens to the virtual cluster CR, and performs the operation of disassembling and assembling nodes\nwhen the virtual control plane is ready."}),"\n"]}),"\n",(0,s.jsx)(t.h4,{id:"node-agent",children:"Node-agent"}),"\n",(0,s.jsx)(t.p,{children:"In order to automate node disassembly and provide on-demand second-level elastic scalability,\nwe have developed a node-agent that can operate nodes through websocket without logging in to the node through ansible or ssh.\nWe will install an agent on the node, which is a remote operator executor.\nThe Virtual Cluster Controller implements some operations on the worker-node by calling the agent's interface,\ndeploys the systemd service through daemonset, and needs to escape to the host user to execute the installation command.\nThe flowchart of the node joining virtual-k8s is shown in the figure below. The dotted line part is the capability provided\nby the node-agent."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"flowchart",src:n(8496).c+"",width:"1190",height:"1896"})}),"\n",(0,s.jsx)(t.h2,{id:"how-to-use",children:"How to use"}),"\n",(0,s.jsx)(t.p,{children:"We defined the Virtual Cluster through the k8s CRD. Therefore, from a usage perspective, we only need to issue a CR,\nand the controller will create virtual-k8s based on the issued CR. At the same time, after the control plane is successfully installed,\nthe kubeconfig file will be rewritten back to the CR. After the user obtains the kubeconfig,\nthey can access the virtual-k8s cluster through base64 decryption. A complete CR is shown in the following figure."}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"CR",src:n(8256).c+"",width:"2924",height:"1638"})}),"\n",(0,s.jsx)(t.h2,{id:"technical-advantages",children:"Technical advantages"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Security isolation: tenant metadata and network are completely isolated to ensure tenant security"}),"\n",(0,s.jsx)(t.li,{children:"Second-level elastic expansion: quickly pull up the tenant control surface, providing node on-demand second-level elastic expansion"}),"\n",(0,s.jsx)(t.li,{children:"Efficient operation and maintenance: Create control surfaces through Cloud Native CRE to ensure that management does not interfere with existing resources"}),"\n"]}),"\n",(0,s.jsx)(t.h2,{id:"differences-from-standard-k8s",children:"Differences from standard k8s"}),"\n",(0,s.jsxs)(t.ul,{children:["\n",(0,s.jsx)(t.li,{children:"Because the virtual-k8s control plane is hosted in host-k8s, the tenant cannot change the configuration of the k8s system service"}),"\n",(0,s.jsx)(t.li,{children:"The tenant's k8s control plane service is deployed in a k8s cluster mixed with other tenants, and is isolated by an exclusive etcd at the logical level"}),"\n",(0,s.jsx)(t.li,{children:"Control plane services are isolated from container networks on tenant nodes"}),"\n",(0,s.jsx)(t.li,{children:"The control plane service is exposed through the nodeport of host-k8s, and the tenant service is exposed through the nodeport of the node on virtual-k8s"}),"\n"]})]})}function c(e={}){const{wrapper:t}={...(0,o.M)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(h,{...e})}):h(e)}},1732:(e,t,n)=>{n.d(t,{c:()=>s});const s=n.p+"assets/images/Kubenest-Architecture-f1051d9ace44d72e36fd9cc4320ea472.png"},8256:(e,t,n)=>{n.d(t,{c:()=>s});const s=n.p+"assets/images/Kubenest-CR-89640795b8f4fc975d23979a6001e026.png"},6159:(e,t,n)=>{n.d(t,{c:()=>s});const s="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABBoAAAHMCAMAAABMXTv4AAAAkFBMVEXw9Pz///8AAAAfIypVVVafoaeeoKb9/f07PD6Hi5O8wMe2uL9TV18EBAQDAwN5en61t768wMggJCmGi5NTV15TWF+7wMc8PT+zt716e3/Exs7i5e2XmZ3T1d1pam4ODg9LTE7R1dxbXF8tLi8fHyBqa26lp66ztbthYmN0dXcdHh/29vbb29usrK2WlpfQ09uYOuZKAAAV5ElEQVR42uzZ3U4iMQCA0dl2XW0z7oW3mF0WTZD4s+//dk4RiGiFZDAR6jmJcZqZ6R0fpe1+ALwjDYA0ANIASAMgDcA2aQAqpAGokAagQhqACmkAKqQBqJAGoEIagAppACqkAaiQBqBCGoAKaQAqpAGokAagQhqACmkAKqQBqPiaNEzOFrOfQBNmi7PJp6RhPg1AU6b54DTc3wWgOXf3h6Xh4SYADbp5OCQNk6uXSRbXv4AmXC9uQnE1OSAN0zC4mHdAQ+YXYTAdn4anMJh1QGNmYfA0Og23pSwd0Jzyi+B2bBoew+BfBzTnfxg8jkxDObf80wENKh/vu5FpKPuYtiChSfNy9jgyDZfDu5MOaNAkhPB3XBrOh1cvO6BJv0MI59IASAMgDYA0ANIAbEgDUCENQIU0ABXSAFS0n4acO+DLHVsaUowd8OU+Lw0p5er14WlIvZUE7HG8aYix31z35Xq/lPanIfWxUAfYqak0xJj3paFMm3IfY+qAj323NKTVTLYgYLdvloZ+9UiybICdTi4NOS3PIyvjHONwnT9IQ7lTHnmXjOR8E945tTSkuJS6rXGfy9VKrqRhM8X61byaMZXX7DzAWyeWhrQMQflb34h9KuM9aSgP5u1xXi004vJ9CwfYdlJpSC9f8JsThlw+02WcN6P6XkNa38plibH892rinKwa4I0jTkPs19aZiK9WD2l7D2JHGjaPF7nMuy5FtlyADxxzGp7ZuZudCGEwDKMmrNr0/q9XR8snZV6d7TQ5ZyOUn51PoCVTZhLakob68zIN/XrauLx1dLMMkL1zGkY7fW3XhEEdnS8Y/XUaxvJu0lq14XHH5rkBnr11Gmp7VBp+R46almz3NPTxrc00jOWUOTqHho+mIdopDTVU84pLHPoyVs8V13z0Y9zWPLo4QLRRGp6fGmrZYn1qmM5K9MvXDf1sRF3fLV7Cs53SULOOy9EarzSU6kbFo4Jw3qqmN4GLTdPQ59EppSEtZfRrW5offIG/7JWGj6NeDNYKzL36d49fQy5n9J/9Pm/nqQFutkrDfD2o2YUxbl8/jx7SsC5NtP7YHT+7sxTmGmC1WRo+2jG139WFGYp5dIwW0lAb7bzi6OfS5ThMNcCzrdLwqEGVoVLRWp33ZaQ0XGYi64q63fBJJNy8bxr+0nvLu7X3+gZ+jR7+t2EagA1JAyANgDQA0gBIA7CSBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQBiCQhk926kAAAAAAQJC/9QIjFETAUAMw1AAMNQBDDcBQAzDUAAw1AEMNwFADMNQADDUAQw3AUAMw1AAMNQBDDcBQAzDUAAw1AEMNwFADMNQADDUAQw3AUAMw1AAMNQBDDcBQA7FTBwIAAAAAgvytFxihIIKhBmCoARhqAIYagKEGYKgBGGoAhhqAoQZgqAEYagCGGoChBmCoAYgdO2hxEAaiADy8U6QHeyuN2qQx9dD//wM3C7pQEFrodNM35LuNB4WJeWbc0aKhaZodFqNhOmxkxVZ/wNCasuOwGdYLnqxmUj8aRvyRFVutb2pN2RGwOa5XHFnNpH40eP5dcDkPoizQN2VM6k1x9NFwPXlhUT8ahD4aJiB70eXYmyIZYRFdPX00JOAsJL4gGqLbyIqsTgCCF1WXb23K6cV6RDGKqmXeHuK3NnHVVxRJOHxBNNALKALjn6YPirQz9gd1+NUJhXrRsPBMXU9MDkUUBcdFjBguKPKgcSuaM/iL2cDx5teLhswzdT2VtL6QCdHM6WNE0avsp5ljM73ABwBRGFSLhhGAEyOGu86CT6Ymkwggy/uypcmkQzEJgWrRkAH0YsWCuVNY72QpL+WK+83L20ZTeSn3kDimxmrRgMLOesskGhwAjvfmH5vSA7iJGRQnhprR4AHM0jwKtvJSR7SVlzRqRcPR1NFZCwppHjlLvxqItGj4YedeVhsHgjCMCnolEbDnxowhm7z/S46WklXgyTgJf7fOtzQkoCI6JqJVQRkKL3NCQ1CGgoacnIaUhAZJaPjKrrfbzbOyu97WobxO2rcOpYtzwGj4mC5DneD6oP6sQ/k9qc9nJ2hAwyY0lKEBDWhAQxEa0IAGNBShAQ1oQEMRGhx5eo4GR54KGk5zK412PWhAwzY0VKEBDf/d9XK5XNGw720dyutpbqV/bR1KF/96oiEoQzkDDb2EhqAMBQ05oSEoQ0FDTmgIylDQkBMagjIUNOTkyJMkNEhCw8PsazhmX0OVfQ1o8A5F3GnI0erl2Qka0LAJDWVoQAMa0FCEBjSgAQ1FaEADGtBQhAZHnryUnUdDL7fSaNeDBjRsQ0MVGtBgX8NkX0OVfQ1oeHfeoTh2ym/Z0UJDUIaChpzQEJShoCEnNARlKGjICQ1BGQoacnLkSRIaJKHhYfY1HLOvocq+BjR4hyLuNORo9fLsBA1o2ISGMjSgAQ1oKEIDGtCAhiI0oAENaChCgyNPXsrOo6GXW2m060EDGrahoQoNaLCvYbKvocq+BjS8O+9QHDvlt+xooSEoQ0FDTmgIylDQkBMagjIUNOSEhqAMBQ05OfIkCQ2S0PAw+xqO2ddQZV8DGrxDEXcacrR6eXaCBjRsQkMZGtCABjQUoWEgGpZlmfYdPjghDcvyaEwnpGH5dv/B4RM0RNEwz8/81b60l2nX0tr97+uRhqeGMrc27WttnnZ1ScP8zK38o32/+/Gf7dd0CA05R55aa59Nw/yXvbNbbhSGoTAz5+podJPy8/6PutsIyHHRmLKlJGTRtBOELcBq9GHL4LrZNxDlTit28GkvZTvAX0YD6etOMbr3t1Q9/qXsFuAvo8EYzasLWTrl7pULDUegwWj7ocGIT1mLA+IuLKzsWWhgBjj+EA3bndIWThkQ0t9eBw3kLmjQ5lb6EuoGlkbghYa9o8DIxS74DmjQG7A5sBZNpD1u1riLPWu9BvPEKdgPDQRo0dyVWOTQARw1kC2A/sj1GuociHjfBw2DNLdKBr/X6kObjMBrvYbff12AO6FBI4rVP7gBLA5H0teyFoc5ZX80AFZxisZOBFV88OvN+/lj8z3R0IFjxbpTPm7ihWkEgr9W55T/Fg0O/8YxCSys7X3RMHfLqsccIghm6ymypNvwTmgompuLlnbg4vCnlNdBg1m5aWaynxbhbDYVJmak2ToawlaGCJNNmOeEAfgMNGjrouGlUyzSDxa6OMVKp9TREBbaXJfkit2W90dhQbK/+V00mN3KzdDHT/IW926bChMzMpQKGsJCewtt6hQFSNK5GC40/DQKKKk+QL6mwL0QhhAp1DglQmwNDYwNAuXAIkvAGR5o8GegoXCKPa7aYeEUR4gUihkZhVxDAwFqBUewps3yi0AvLDgeDUCvm3P0teDfX8BbjMK5UCN+LOYaGgaA40fsj4phL1Yynlgeb7gGFDtGgcMLNJgDjqaKBgBwBwDW0UCA+mnzaUAHQhMjzknL49GgweyA6A4S8BU0GACnA2AFDdrOL07pAGcH9IvQzKKgO2JAEafVW7KiYQDQWxUNw72gA8AKGvQT+FA0tKNTQlMuKlD0YOeU13nkiYCEnqLBQWGGbmnEM9Q6GjTYp9OYnN2YGEm57DxEqN2gAg2+6AokvYb4MAfqaAC86Ls5KJ3hYdFroKCh3H+IAJS4EzQATmGGbGmkR9s6fNTQoP2A6De1k304xbkwWrqB3WnHEy+EBgMoXXxBQ2zU0aCAqaDBpFvggJsLSpbCZ6OhEadY0Tx4s4oGbUYFDdp4AiDByh1Pww48clStYShRKmiIjToa5OIraJD90yilr40QsESDR9fkrPI6aGj0hl+iodmEBqugQXcTgOQSkKNBzGXzqPUaFHWlCltHg1K3ggYCljqlBZijQcw1og5Yr0FHFMMCDWzqaFCpo0HbPkhyQQqyo+l5wuhar2G3KDDASjTw+2iwOhrKIKAVw3C3H6Bh93coctQpKb6NBmMVDaVT+nhMR3vSKnnYSYgd8g4FQAnCuIwgxvfRwFHP0TAAlJZZi9kXAFhDA6bzGNl9Wl1PQ+70Bzeg+Sc0GB1AEUrmIWNFag8kTubChoDDbMVkQHEwGtQp9k9oMBJAiQYPsaho8lVnjN19+na3k+ls1YfRAg0RS0ehoUUvDy9sRwPvDSvQQL8Lx4ooeyA6XBm6wIQ45ZYOKKaUxoWGH4vLwHczGggApJVoQEhszhMYoX7NfnrAYbbyZIbieDRQZmS2oiGc4rQSDQgJNPj9Rx4U0ukbhUMYfWRpyCBD3xyIhg8Z9W9DQ4S2cyh7DR3uEmjwDnjYxcYMP4UDgKiZzFCIugMaFIs3UUTjZ9F7ooGABN42NBCgLYcjFjLFOykJDQGSwIFqpWjw49GgORLbiAZxiurilHnOd3bxMId3q91pdcrty3MNNyHDUWiIBkWsb0fDME1jKBq0eU13R2AHKi/1+AGHXqwUDYtZzV3R0EE7NKpEbuM90dAAjCn1jWjQ6Y1KrgGU2JJOtBeVGhVJUx6PBnXKdjToRVdyDfAYN0mwSBQoAVRfzOVHlcPQ0KKPmN2IBm1kJdfwuasFKLwUNybZSDlMm3hrBzQoDEDlxEdZdHo0pK8LEBxjNkcDFzN2goZmFQ1eRA2VMpr1W32H4tiXsgm//34LDZYkKKpoiCqOfvEsUd4nLqoBvZLhgPUaJPTna8zRAKYPQQRQcjQoCqNAj6qU0cbrGfOJkH5nNGhaQwY+7XujAQ1gKRryKDDIfL8U1J+GzNiiWv5EwJFoUAHG8USOBltEgTlALanOUMgtsJUwqj2wAFD3RywdioYGYIc+Q0PIEg0d0Ks+1GYoxHL4wpZb/f3M5stjYsNuaEhmRFvlxBBF74mGBiC8SdCQRIHbmGYrR9MzGpChISyjogtDTLRkQRkqje3g9RqIaEyOBnWQP5xCqcXQtVuhthJV01eL4wPIfYRcsrQJ5UvfAZRR9yHrNbRgpAdzNETA68V2EBTE7jn3wBQNYRkGYtipFqK1u9mTJvMa+63X0Eb869hHi3j+XEMaBRHZCRoUmY4ojeR6MxowdPChe44GApwM3AHYQhOx6bih4iHWVGRvp3iGBi0fWxFiDs4lDnDUDXBL0KB3SMBbFFpyK+oA74QMITtmwdbvshHZFTQAHairLU2EQ1y86kzQoMAEfEZJN9oLL/WUOsMJyRnuJ8aa8s5oaCposDkozUevh/pXd9GDHVZ5HWI+AmNnaKA1Knqi49GgCYEKGuQKOW45+ChyNgTzpSV1kpLxjQ6LEN5Vsponx1PQ0FXRoH3t2Lo1rU5egrPe5mgINlJG8VMnJXOKnkirgWd9heLF0LAuZqZbZVGuqtQsVNt0pKf/p+yaU5ioVbFbRf3BHeroFZjNbkkb6vr6wdRg3Xd2Wi6cEA1vLZdTzrw4+7vJhYYXksspFxpeR17qkadLLrnkVeRCwyWXXHKhYTfJ12u4JFmv4ZJrvYb/Wc7x73A3yXn+5+W55Cy5kwsNFxpELjSkcqHhQsMfdu4gBUIYCKKo9z/1zDKQAhU3leT9G9jgG0aSRgMaQmhAAxrQEEIDGtCAhhAaHHn6RoMjT4GGY16l3Z4HDWgYQ0MKDWh4Wt7XgIZr3tdwzKv0tP9QlvjriYaiDOUEGlYJDUUZChp6QkNRhoKGntBQlKGgoSc0FGUoaOjJkSdJaJCEhtvsa5izryFlXwMa3KGoOw25W6t8O0EDGobQEEMDGtCAhhAa0IAGNITQgAY0oCGEBkeeXMruo2GVV2m350EDGsbQkEIDGuxruOxrSNnXgIbXuUMxd+Sv7G6hoShDQUNPaCjKUNDQExqKMhQ09ISGogwFDT058iQJDZLQ8GPnDlIAhIEgCPr/V3sNZEC8TTbVP3DBEiTZz+xr2LOvIWVfAxrcoag7DTmtU/6doAENS2iIoQENaEBDCA1oQAMaQmhAAxrQEEKDI08uZffRcMqrNO150ICGNTSk0IAG+xoe+xpS9jWg4XfuUOxd+ZWdFhqKMhQ09ISGogwFDT2hoShDQUNPaCjKUNDQkyNPkl527lhHYRgGA7D1T60YyhaIk+ZoS4e+/wMeKAwgTuKEDIkjf5sXJED+65oSiwZjjEXDS3ZewzM7r+Evdl6DRYP9h6K6pyFbo2V3YtFg0fAxK4AfMg8YQCIFLBpkdADshsLysqFRyqJBBCcAkcwDB2Al85SXZ1KgYDTwcaJWDGJTYnBMjTjgwou8kvPUCE4AelKgWDTwMSn5iP4hJqHRuV8aujtfhFYNqwOWVgJzgpY3U25q6HDRysUgABsJGHHRyu99PgFRaJuJVibM06zlCy4XDXtcnVUE6Gv7tIqNm3CNbC1O8yC248XSyJaXJxVLyKK7hoCrRJnfZay0jmJX2rtpKu6ySDprZpLAG676W7XLPOmqI90oCf6C0UAj7m5GO2R7pbWUcJ+XA7JBaZ1JBWbMxQGZI521FiWjgdYEhEpau5ZoID8DYyWtXUs0EHfAXElrWzR8IRooDhtV0trv1j1J47D5Slr73XoiccH1lbT2u/VCulTzyNPYZV5ZHeiDwi+7dYwCIAxFQdBbCPbe/4rapBAWxCKFYaZ7pPjdknFk7t7f3j/t27lNdIwjP9t+DcACpAGQBkAaAGkApAF4kgYgSAMQpAEI0gAEaQCCNABBGoAgDUCQBiBIAxCkAQjSAARpAII0AEEagCANQJAGIEgDEKQBCNIABGkAgjQAQRq42KkDAQAAAABB/tYLjFAQwVADMNQADDUAQw3AUAMw1AAMNQBDDcBQAzDUAAw1AEMNwFADMNQADDUAQw3AUAMw1AAMNQBDDcBQAzDUAAw1AEMNwFADMNQADDUAQw3AUAMw1AAMNQBDDcBQAzDUAAw1AEMNwFADMNQADDUAQw3AUAMw1AAMNQBDDcBQAzDUAAw1AEMNwFADMNQADDUAQw3AUAMw1AAMNQBDDcBQAzDUQO3YvUokQRiF4a6PHTDZxLRdt5kWegb/7v/uLDODg0oFIsXz5Cd9gwOBNACBNACBNACBNACBNACBNACBNACBNACBNACBNACBNACBNACBNACBNACBNACBNACBNADBL0pD+9un6wJMaK2q/20sDXvfHgswoaOq9sE0XPr2fgEmdF9Vl8E0PFf3bwGm81rd82Aa2kMfbwswna2qHtpoGl6quyzAZM7VvQynoW3V3bgiYSrHTXVbG0/Delvv9uvdCZjC3XWvd7frcBq6p72ACe1PbTwN3eO5gOlcHtv305AdWwFT2Y4WhDR8bj1dz3+AKZyvp7V9aWkA0gBIAyANgDQAH0kDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgDEEgD8BPeANlaR5bEs7wEAAAAAElFTkSuQmCC"},8496:(e,t,n)=>{n.d(t,{c:()=>s});const s=n.p+"assets/images/Kubenest-NodeAgent-Flowchart-7466545901ee24ebd28263f70d88b3b7.png"},4759:(e,t,n)=>{n.d(t,{c:()=>s});const s=n.p+"assets/images/Kubenest-Solution-Overview-58deb68e8e2ff8482b98a2e65a43eb2e.png"},2172:(e,t,n)=>{n.d(t,{I:()=>r,M:()=>a});var s=n(1504);const o={},i=s.createContext(o);function a(e){const t=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function r(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),s.createElement(i.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/bfb97598.757001a3.js b/docs/assets/js/bfb97598.757001a3.js deleted file mode 100644 index 6d5a873..0000000 --- a/docs/assets/js/bfb97598.757001a3.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[152],{8804:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>l,contentTitle:()=>t,default:()=>p,frontMatter:()=>c,metadata:()=>o,toc:()=>d});var i=r(7624),s=r(2172);const c={id:"mcs-discovery_zh",title:"\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0"},t="\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0",o={id:"i18n/zh/v0.2.0/mcs-discovery_zh",title:"\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0",description:"Kosmos\u63d0\u4f9b\u4e86\u4e24\u79cd\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0\u7684\u80fd\u529b\uff1a",source:"@site/docs/i18n/zh/v0.2.0/multi-cluster-svc-discovery_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/mcs-discovery_zh",permalink:"/website/i18n/zh/v0.2.0/mcs-discovery_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/multi-cluster-svc-discovery_zh.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1712828974,formattedLastUpdatedAt:"Apr 11, 2024",frontMatter:{id:"mcs-discovery_zh",title:"\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0"}},l={},d=[{value:"\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4Service\u65b9\u6848",id:"\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4service\u65b9\u6848",level:2},{value:"\u4ecb\u7ecd",id:"\u4ecb\u7ecd",level:3},{value:"\u524d\u63d0\u51c6\u5907",id:"\u524d\u63d0\u51c6\u5907",level:3},{value:"\u5b89\u88c5Kosmos",id:"\u5b89\u88c5kosmos",level:4},{value:"\u6ce8\u518c\u53f6\u5b50\u96c6\u7fa4",id:"\u6ce8\u518c\u53f6\u5b50\u96c6\u7fa4",level:4},{value:"\u4f7f\u7528\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4Service",id:"\u4f7f\u7528\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4service",level:3},{value:"\u624b\u52a8\u5bfc\u51fa\u548c\u5bfc\u51faService",id:"\u624b\u52a8\u5bfc\u51fa\u548c\u5bfc\u51faservice",level:4},{value:"\u81ea\u52a8\u5bfc\u51fa\u5bfc\u5165Service\u5230\u6240\u6709\u6570\u636e\u9762\u96c6\u7fa4",id:"\u81ea\u52a8\u5bfc\u51fa\u5bfc\u5165service\u5230\u6240\u6709\u6570\u636e\u9762\u96c6\u7fa4",level:3},{value:"\u901a\u8fc7\u63a7\u5236\u9762Service\u7684\u6ce8\u89e3\u8bc6\u522b\u65b9\u5f0f",id:"\u901a\u8fc7\u63a7\u5236\u9762service\u7684\u6ce8\u89e3\u8bc6\u522b\u65b9\u5f0f",level:4},{value:"\u901a\u8fc7\u5168\u5c40\u542f\u52a8\u53c2\u6570",id:"\u901a\u8fc7\u5168\u5c40\u542f\u52a8\u53c2\u6570",level:4},{value:"Service\u8de8\u96c6\u7fa4\u7f51\u7edc\u8fde\u901a\u6821\u9a8c",id:"service\u8de8\u96c6\u7fa4\u7f51\u7edc\u8fde\u901a\u6821\u9a8c",level:3},{value:"\u5168\u5c40\u4e2d\u5fc3core-dns\u65b9\u6848",id:"\u5168\u5c40\u4e2d\u5fc3core-dns\u65b9\u6848",level:2},{value:"\u4ecb\u7ecd",id:"\u4ecb\u7ecd-1",level:3}];function a(e){const n={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,s.M)(),...e.components};return(0,i.jsxs)(i.Fragment,{children:[(0,i.jsx)(n.h1,{id:"\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0",children:"\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos\u63d0\u4f9b\u4e86\u4e24\u79cd\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0\u7684\u80fd\u529b\uff1a"}),"\n",(0,i.jsxs)(n.ul,{children:["\n",(0,i.jsx)(n.li,{children:"\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4Service\u65b9\u6848"}),"\n",(0,i.jsx)(n.li,{children:"\u5168\u5c40\u4e2d\u5fc3core-dns\u65b9\u6848\u3002 \u5176\u4e2d\u5728\u751f\u4ea7\u73af\u5883\u4e2d\uff0c\u6211\u4eec\u66f4\u63a8\u8350\u53bb\u4e2d\u5fc3\u5316\u7684\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4Service\u65b9\u6848"}),"\n"]}),"\n",(0,i.jsx)(n.h2,{id:"\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4service\u65b9\u6848",children:"\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4Service\u65b9\u6848"}),"\n",(0,i.jsx)(n.h3,{id:"\u4ecb\u7ecd",children:"\u4ecb\u7ecd"}),"\n",(0,i.jsx)(n.p,{children:"Kosmos\u57fa\u4e8e\u591a\u96c6\u7fa4\u670d\u52a1API\u5b9e\u73b0\u4e86\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0\u529f\u80fd\u3002\u7528\u6237\u53ef\u4ee5\u5c06\u63a7\u5236\u9762\u96c6\u7fa4\u751f\u6210\u7684Service\u5bfc\u51fa\u5230\u6210\u5458\u96c6\u7fa4\uff0c\u4ece\u800c\u5728\u6210\u5458\u96c6\u7fa4\u5bf9\u5916\u63d0\u4f9b\u670d\u52a1\u3002"}),"\n",(0,i.jsx)(n.admonition,{title:"NOTE",type:"info",children:(0,i.jsx)(n.p,{children:"\u4f7f\u7528\u8be5\u7279\u6027\uff0c\u9700\u8981\u4fdd\u8bc1\u63a7\u5236\u9762\u96c6\u7fa4\u548c\u6210\u5458\u96c6\u7fa4\u7684\u7248\u672c\u4e0d\u4f4e\u4e8ev1.21\uff0c\u5e76\u4e14\u96c6\u7fa4\u5185core-dns\u7684\u7248\u672c\u4e0d\u4f4e\u4e8ev1.84."})}),"\n",(0,i.jsx)(n.p,{children:"Kosmos\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4Service\u7684\u65b9\u6848\u67b6\u6784\u5982\u4e0b\uff1a"}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"MCS Architecture.svg",src:r(8616).c+"",width:"1185",height:"671"})}),"\n",(0,i.jsx)(n.p,{children:"Kosmos\u7684\u63a7\u5236\u5668\u4f1a\u76d1\u542c\u63a7\u5236\u9762\u7684ServiceExport\u548c\u6570\u636e\u9762\u7684ServiceImport\u8d44\u6e90\uff0c\u5e76\u57fa\u4e8e\u8fd9\u4e24\u4e2aMCS\u7684\u8d44\u6e90\u7684\u914d\u7f6e\u5c06\u63a7\u5236\u9762\u7684Service\u548cEndpointSlice\u540c\u6b65\u5230\u6570\u636e\u9762\u96c6\u7fa4\u3002\r\n\u5728\u4efb\u610f\u4e00\u4e2a\u6570\u636e\u9762\u96c6\u7fa4\uff0c\u90fd\u53ef\u4ee5\u901a\u8fc7Service\u5bf9\u5916\u66b4\u9732\u670d\u52a1\uff0c\u6bcf\u4e2a\u96c6\u7fa4\u7684EndpointSlice\u90fd\u4f1a\u5305\u542b\u63a7\u5236\u9762\u96c6\u7fa4\u7684\u5de5\u4f5c\u8d1f\u8f7d\u7684\u6240\u6709\u7684Pod IP\uff0c\u4ece\u800c\u5b9e\u73b0\u4e86\u670d\u52a1\u7684\u7684\u5f02\u5730\u8de8\u96c6\u7fa4\u591a\u6d3b\u3002"}),"\n",(0,i.jsx)(n.h3,{id:"\u524d\u63d0\u51c6\u5907",children:"\u524d\u63d0\u51c6\u5907"}),"\n",(0,i.jsx)(n.h4,{id:"\u5b89\u88c5kosmos",children:"\u5b89\u88c5Kosmos"}),"\n",(0,i.jsxs)(n.p,{children:["\u53ef\u4ee5\u53c2\u8003 ",(0,i.jsx)(n.a,{href:"https://github.com/kosmos-io/kosmos",children:"https://github.com/kosmos-io/kosmos"})," \u5e76\u5f00\u542f\u591a\u96c6\u7fa4\u7f51\u7edc\u6a21\u5757\u3002 \u4f7f\u7528",(0,i.jsx)(n.code,{children:"kosmosctl"}),"\u5de5\u5177\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"# \u53c2\u6570 default-nic \u4e3a\u53ef\u9009\u53c2\u6570\uff0c\u7528\u4e8e\u6307\u5b9a\u9ed8\u8ba4\u7f51\u5361\r\nkosmosctl install --cni calico --default-nic eth0\n"})}),"\n",(0,i.jsx)(n.h4,{id:"\u6ce8\u518c\u53f6\u5b50\u96c6\u7fa4",children:"\u6ce8\u518c\u53f6\u5b50\u96c6\u7fa4"}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"kosmosctl join cluster --name cluster1 --kubeconfig ~/kubeconfig/cluster1-kubeconfig --cni calico --default-nic eth0 --enable-link\n"})}),"\n",(0,i.jsx)(n.h3,{id:"\u4f7f\u7528\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4service",children:"\u4f7f\u7528\u5206\u5e03\u5f0f\u591a\u96c6\u7fa4Service"}),"\n",(0,i.jsx)(n.h4,{id:"\u624b\u52a8\u5bfc\u51fa\u548c\u5bfc\u51faservice",children:"\u624b\u52a8\u5bfc\u51fa\u548c\u5bfc\u51faService"}),"\n",(0,i.jsx)(n.p,{children:"\u7528\u6237\u53ef\u4ee5\u901a\u8fc7\u624b\u52a8\u521b\u5efaServiceExport\u548cServiceImport\u7684\u65b9\u5f0f\u5c06Service\u4e0b\u53d1\u5230\u6570\u636e\u9762\u96c6\u7fa4\u3002"}),"\n",(0,i.jsxs)(n.ol,{children:["\n",(0,i.jsx)(n.li,{children:"\u5728\u6570\u636e\u9762\u96c6\u7fa4\u521b\u5efa\u5de5\u4f5c\u8d1f\u8f7dnginx\uff0cnginx\u7684yaml\u5982\u4e0b\uff1a"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:'apiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: nginx\r\nspec:\r\n replicas: 2\r\n selector:\r\n matchLabels:\r\n app: nginx\r\n template:\r\n metadata:\r\n labels:\r\n app: nginx\r\n spec:\r\n tolerations:\r\n - key: "kosmos.io/node"\r\n operator: "Equal"\r\n value: "true"\r\n effect: "NoSchedule"\r\n podAntiAffinity:\r\n requiredDuringSchedulingIgnoredDuringExecution:\r\n - labelSelector:\r\n matchLabels:\r\n app: nginx\r\n topologyKey: kubernetes.io/hostname\r\n containers:\r\n - name: nginx\r\n image: nginx:latest\r\n ports:\r\n - containerPort: 80\r\n---\r\napiVersion: v1\r\nkind: Service\r\nmetadata:\r\n name: nginx\r\nspec:\r\n selector:\r\n app: nginx\r\n ports:\r\n - protocol: TCP\r\n port: 80\r\n targetPort: 80\r\n nodePort: 31444\r\n type: NodePort\n'})}),"\n",(0,i.jsx)(n.admonition,{title:"NOTE",type:"info",children:(0,i.jsx)(n.p,{children:"\u53ef\u4ee5\u901a\u8fc7\u5728yaml\u4e2d\u6307\u5b9a\u8282\u70b9\u4eb2\u548c\u6027\u5c06\u5de5\u4f5c\u8d1f\u8f7d\u7684pod\u8c03\u5ea6\u5230Kosmos\u7684leaf\u8282\u70b9\u4e0a\u3002"})}),"\n",(0,i.jsxs)(n.ol,{start:"2",children:["\n",(0,i.jsx)(n.li,{children:"\u5728\u63a7\u5236\u9762\u4e0a\u521b\u5efaServiceExport\u5c06\u4e0a\u9762\u7684nginx\u7684Service\u5bfc\u51fa\uff1a"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: multicluster.x-k8s.io/v1alpha1\r\nkind: ServiceExport\r\nmetadata:\r\n name: nginx\n"})}),"\n",(0,i.jsxs)(n.ol,{start:"3",children:["\n",(0,i.jsx)(n.li,{children:"\u5728\u6570\u636e\u9762\u96c6\u7fa41\u4e2d\u521b\u5efaServiceImport\u5c06\u5bfc\u51fa\u7684Service\u521b\u5efa\u5230\u6570\u636e\u9762\u96c6\u7fa41\u4e2d\uff1a"}),"\n"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"apiVersion: multicluster.x-k8s.io/v1alpha1\r\nkind: ServiceImport\r\nmetadata:\r\n name: nginx\r\nspec:\r\n type: ClusterSetIP\r\n ports:\r\n - protocol: TCP\r\n port: 80\n"})}),"\n",(0,i.jsx)(n.p,{children:"\u6b64\u65f6\u5c31\u53ef\u4ee5\u5728\u6570\u636e\u9762\u96c6\u7fa41\u901a\u8fc7\u76f8\u540c\u7684Service\u5bf9\u5916\u66b4\u9732\u670d\u52a1\u3002"}),"\n",(0,i.jsx)(n.h3,{id:"\u81ea\u52a8\u5bfc\u51fa\u5bfc\u5165service\u5230\u6240\u6709\u6570\u636e\u9762\u96c6\u7fa4",children:"\u81ea\u52a8\u5bfc\u51fa\u5bfc\u5165Service\u5230\u6240\u6709\u6570\u636e\u9762\u96c6\u7fa4"}),"\n",(0,i.jsx)(n.p,{children:"\u5728\u67d0\u4e9b\u573a\u666f\u4e0b\uff0c\u7528\u6237\u9700\u8981\u81ea\u52a8\u7684\u5c06\u63a7\u5236\u9762\u7684Service\u540c\u6b65\u5230\u6240\u6709\u7684\u6570\u636e\u9762\u96c6\u7fa4\uff0c\u800c\u4e0d\u60f3\u624b\u52a8\u7684\u521b\u5efaServiceExport\u548cServiceImport\u3002\r\nKosmos\u63d0\u4f9b\u4e86\u4e24\u79cd\u81ea\u52a8\u5316\u5bfc\u51fa\u548c\u5bfc\u5165Service\u7684\u65b9\u5f0f\u3002"}),"\n",(0,i.jsx)(n.h4,{id:"\u901a\u8fc7\u63a7\u5236\u9762service\u7684\u6ce8\u89e3\u8bc6\u522b\u65b9\u5f0f",children:"\u901a\u8fc7\u63a7\u5236\u9762Service\u7684\u6ce8\u89e3\u8bc6\u522b\u65b9\u5f0f"}),"\n",(0,i.jsxs)(n.p,{children:["\u5bf9\u4e8e\u9700\u8981\u81ea\u52a8\u5bfc\u51fa\u4e0b\u53d1\u5230\u6240\u6709\u6570\u636e\u9762\u96c6\u7fa4\u7684Service\uff0c\u7528\u6237\u53ef\u4ee5\u624b\u52a8\u7684\u7ed9Service\u6dfb\u52a0\u6ce8\u89e3\u3002",(0,i.jsx)(n.code,{children:'kosmos.io/auto-create-mcs: "true"'}),"\uff0cservice\u7684\u6837\u4f8byaml\u5982\u4e0b\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:'apiVersion: v1\r\nkind: Service\r\nmetadata:\r\n name: nginx\r\n annotations:\r\n kosmos.io/auto-create-mcs: "true"\r\nspec:\r\n selector:\r\n app: nginx\r\n ports:\r\n - protocol: TCP\r\n port: 80\r\n targetPort: 80\r\n nodePort: 31444\r\n type: NodePort\n'})}),"\n",(0,i.jsx)(n.h4,{id:"\u901a\u8fc7\u5168\u5c40\u542f\u52a8\u53c2\u6570",children:"\u901a\u8fc7\u5168\u5c40\u542f\u52a8\u53c2\u6570"}),"\n",(0,i.jsxs)(n.p,{children:["\u5bf9\u4e8e\u4e00\u4e9b\u4e0d\u60f3\u6d89\u53ca\u5230\u81ea\u8eab\u4ee3\u7801\u6539\u52a8\u7684\u60c5\u51b5\u4e0b\uff0cKosmos\u4e5f\u652f\u6301\u901a\u8fc7\u914d\u7f6e\u542f\u52a8\u53c2\u6570\u7684\u65b9\u5f0f\u81ea\u52a8\u4e0b\u53d1Service\u3002\r\n\u5728ClusterTree\u7684\u542f\u52a8\u670d\u52a1\u4e2d\u589e\u52a0\u53c2\u6570",(0,i.jsx)(n.code,{children:"--auto-mcs-prefix"}),"\uff0c\u5982\u914d\u7f6e",(0,i.jsx)(n.code,{children:"--auto-mcs-prefix=test"}),"\uff0ckosmos\uff0c\u5219\u6240\u6709test\u548ckosmos\u524d\u7f00\u7684Namespace\u4e0b\u9762\u7684Service\uff0c\u5c06\u4f1a\u88ab\u81ea\u52a8\u5bfc\u51fa\u4e0b\u53d1\u5230\u6240\u6709\u7684\u6570\u636e\u9762\u96c6\u7fa4\u3002"]}),"\n",(0,i.jsx)(n.h3,{id:"service\u8de8\u96c6\u7fa4\u7f51\u7edc\u8fde\u901a\u6821\u9a8c",children:"Service\u8de8\u96c6\u7fa4\u7f51\u7edc\u8fde\u901a\u6821\u9a8c"}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"eps-probe-plugin"})," \u662f\u4e00\u4e2a\u8de8\u96c6\u7fa4Service\u7f51\u7edc\u6821\u9a8c\u63d2\u4ef6\u3002\r\n\u5982\u4e0a\u6240\u8bf4\uff0cKosmos\u7684\u63a7\u5236\u5668\u4f1a\u5c06\u63a7\u5236\u96c6\u7fa4\u7684Service\u548cEndpointSlice\u540c\u6b65\u5230\u6570\u636e\u9762\u96c6\u7fa4\u3002\r\n\u5f53\u8de8\u96c6\u7fa4\u7684\u7f51\u7edc\u8fde\u901a\u51fa\u73b0\u6545\u969c\u65f6\uff0c\u5c31\u4f1a\u5bfc\u81f4EndpointSlice\u4e2d\u7684endpoint\u662f\u4e0d\u53ef\u7528\u7684\uff0c\u4ece\u800c\u5f15\u53d1\u6545\u969c\u3002"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"eps-probe-plugin"})," \u901a\u8fc7\u5b9a\u65f6\u7684\u68c0\u67e5endpoint\u4e2d\u7684pod-ip\u662f\u5426\u53ef\u8fbe\uff0c\u5c06\u4e0d\u53ef\u8fbe\u7684endpoint\u7684\u5730\u5740\u66f4\u65b0\u5230serviceImport\u7684",(0,i.jsx)(n.code,{children:"kosmos.io/disconnected-address"}),"\u4e2d\uff0cKosmos\u7684\u63a7\u5236\u5668\u4f1a\u5c06\u5bfc\u51fa\u7684Service\u5bf9\u5e94\u7684EndpointSlice\u4e2d\u4e0d\u53ef\u8fbe\u7684endpoint\u5220\u9664\u3002"]}),"\n",(0,i.jsxs)(n.p,{children:[(0,i.jsx)(n.code,{children:"eps-probe-plugin"})," \u53ef\u901a\u8fc7\u5982\u4e0b\u7684\u65b9\u5f0f\u5b89\u88c5\uff1a"]}),"\n",(0,i.jsx)(n.pre,{children:(0,i.jsx)(n.code,{className:"language-shell",metastring:"script",children:"kubectl apply -f https://raw.githubusercontent.com/kosmos-io/eps-probe-plugin/main/deploy/eps-probe-plugin.yaml\n"})}),"\n",(0,i.jsx)(n.h2,{id:"\u5168\u5c40\u4e2d\u5fc3core-dns\u65b9\u6848",children:"\u5168\u5c40\u4e2d\u5fc3core-dns\u65b9\u6848"}),"\n",(0,i.jsx)(n.h3,{id:"\u4ecb\u7ecd-1",children:"\u4ecb\u7ecd"}),"\n",(0,i.jsx)(n.p,{children:"\u5168\u5c40\u4e2d\u5fc3core-dns\u65b9\u6848\u5982\u4e0b\u56fe\u6240\u793a\uff0c\u6240\u6709\u7684\u901a\u8fc7Kosmos\u4e0b\u53d1\u7684pod\u90fd\u901a\u8fc7\u63a7\u5236\u9762\u96c6\u7fa4\u7684core-dns\u89e3\u6790\u57df\u540d\u8bf7\u6c42\uff0c\u8fd9\u79cd\u65b9\u5f0f\u53ea\u9002\u5408\u5728\u6d4b\u8bd5\u73af\u5883\u4f7f\u7528\uff0c\u5728\u751f\u4ea7\u73af\u5883\u4e2d\uff0c\u53ef\u80fd\u5bfc\u81f4\u63a7\u5236\u9762\u96c6\u7fa4\u7684core-dns\u7684\u8bf7\u6c42\u538b\u529b\u8fc7\u5927\u3002"}),"\n",(0,i.jsxs)(n.p,{children:["\u8981\u5f00\u542f\u5168\u5c40\u4e2d\u5fc3\u7684core-dns\u65b9\u6848\uff0c\u53ea\u9700\u8981\u5c06clusterTree\u670d\u52a1\u7684\u542f\u52a8\u53c2\u6570\u4fee\u6539\u4e3a ",(0,i.jsx)(n.code,{children:"--multi-cluster-service=false"}),"."]}),"\n",(0,i.jsx)(n.p,{children:(0,i.jsx)(n.img,{alt:"CoreDNS_Centralized_Architecture.svg",src:r(1296).c+"",width:"1073",height:"672"})})]})}function p(e={}){const{wrapper:n}={...(0,s.M)(),...e.components};return n?(0,i.jsx)(n,{...e,children:(0,i.jsx)(a,{...e})}):a(e)}},1296:(e,n,r)=>{r.d(n,{c:()=>i});const i=r.p+"assets/images/CoreDNS_Centralized_Architecture-5d5c0d8887c8ff26ae63bcc7d10a7fe8.svg"},8616:(e,n,r)=>{r.d(n,{c:()=>i});const i=r.p+"assets/images/MCS_Architecture-9279013ec1847fc33c86d989475a809e.svg"},2172:(e,n,r)=>{r.d(n,{I:()=>o,M:()=>t});var i=r(1504);const s={},c=i.createContext(s);function t(e){const n=i.useContext(c);return i.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(s):e.components||s:t(e.components),i.createElement(c.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/ce926f5d.d3089b6b.js b/docs/assets/js/ce926f5d.d3089b6b.js deleted file mode 100644 index 6a943be..0000000 --- a/docs/assets/js/ce926f5d.d3089b6b.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[568],{820:(e,s,n)=>{n.r(s),n.d(s,{assets:()=>d,contentTitle:()=>o,default:()=>u,frontMatter:()=>c,metadata:()=>l,toc:()=>t});var r=n(7624),i=n(2172);const c={id:"introduction_zh",title:"\u7b80\u4ecb"},o="\u7b80\u4ecb",l={id:"i18n/zh/v0.2.0/introduction_zh",title:"\u7b80\u4ecb",description:"\u4ec0\u4e48\u662f Kosmos\uff1f",source:"@site/docs/i18n/zh/v0.2.0/introduction_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/introduction_zh",permalink:"/website/i18n/zh/v0.2.0/introduction_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/introduction_zh.md",tags:[],version:"current",frontMatter:{id:"introduction_zh",title:"\u7b80\u4ecb"}},d={},t=[{value:"\u4ec0\u4e48\u662f Kosmos\uff1f",id:"\u4ec0\u4e48\u662f-kosmos",level:2},{value:"ClusterLink",id:"clusterlink",level:2},{value:"\u7f51\u7edc\u67b6\u6784",id:"\u7f51\u7edc\u67b6\u6784",level:3},{value:"ClusterTree",id:"clustertree",level:2},{value:"Scheduler",id:"scheduler",level:2},{value:"\u4e0b\u4e00\u6b65\u662f\u4ec0\u4e48",id:"\u4e0b\u4e00\u6b65\u662f\u4ec0\u4e48",level:2}];function h(e){const s={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",ol:"ol",p:"p",strong:"strong",ul:"ul",...(0,i.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(s.h1,{id:"\u7b80\u4ecb",children:"\u7b80\u4ecb"}),"\n",(0,r.jsx)(s.h2,{id:"\u4ec0\u4e48\u662f-kosmos",children:"\u4ec0\u4e48\u662f Kosmos\uff1f"}),"\n",(0,r.jsx)(s.p,{children:"Kosmos \u662f\u4e00\u4e2a\u5f00\u6e90\u7684\u3001\u4e00\u4f53\u5316\u7684\u5206\u5e03\u5f0f\u4e91\u539f\u751f\u89e3\u51b3\u65b9\u6848\u3002\r\n\u540d\u79f0\u201ckosmos\u201d\u7ed3\u5408\u4e86\u4ee3\u8868 Kubernetes \u7684 'k' \u548c\u5728\u5e0c\u814a\u8bed\u4e2d\u610f\u4e3a\u5b87\u5b99\u7684 'cosmos'\uff0c\u8c61\u5f81\u7740 Kubernetes \u7684\u65e0\u9650\u6269\u5c55\u3002"}),"\n",(0,r.jsxs)(s.p,{children:["\u76ee\u524d\uff0cKosmos \u4e3b\u8981\u5305\u62ec\u4e09\u4e2a\u4e3b\u8981\u6a21\u5757\uff1a",(0,r.jsx)(s.code,{children:"ClusterLink"}),"\u3001",(0,r.jsx)(s.code,{children:"ClusterTree"})," \u548c ",(0,r.jsx)(s.code,{children:"Scheduler"}),"\u3002"]}),"\n",(0,r.jsx)(s.h2,{id:"clusterlink",children:"ClusterLink"}),"\n",(0,r.jsxs)(s.p,{children:["ClusterLink \u7684\u76ee\u6807\u662f\u5efa\u7acb\u591a\u4e2a Kubernetes \u96c6\u7fa4\u4e4b\u95f4\u7684\u8fde\u63a5\u3002\r\n\u6b64\u6a21\u5757\u53ef\u4ee5\u72ec\u7acb\u90e8\u7f72\u548c\u4f7f\u7528\u3002\r\nClusterLink \u4f7f ",(0,r.jsx)(s.code,{children:"Pods"})," \u80fd\u591f\u8bbf\u95ee\u8de8\u96c6\u7fa4\u7684 ",(0,r.jsx)(s.code,{children:"Pods"})," \u548c ",(0,r.jsx)(s.code,{children:"Services"}),"\uff0c\u5c31\u50cf\u5b83\u4eec\u5728\u540c\u4e00\u4e2a\u96c6\u7fa4\u4e2d\u4e00\u6837\u3002\r\n\u76ee\u524d\uff0c\u6b64\u6a21\u5757\u4e3b\u8981\u63d0\u4f9b\u4ee5\u4e0b\u529f\u80fd\uff1a"]}),"\n",(0,r.jsxs)(s.ol,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u8de8\u96c6\u7fa4 PodIP \u548c ServiceIP \u901a\u4fe1"}),"\uff1a\u57fa\u4e8e VxLAN \u548c IPsec \u7b49\u96a7\u9053\u6280\u672f\u7684\u591a Kubernetes \u96c6\u7fa4\u4e4b\u95f4\u7684 L3 \u7f51\u7edc\u8fde\u63a5\u3002\r\n\u8fd9\u4f7f\u7528\u6237\u80fd\u591f\u5728\u5168\u7403\u96c6\u7fa4\u8303\u56f4\u5185\u8fdb\u884c ",(0,r.jsx)(s.code,{children:"Pod-to-Pod"})," \u548c ",(0,r.jsx)(s.code,{children:"Pod-to-Service"})," \u901a\u4fe1\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u591a\u6a21\u5f0f\u652f\u6301"}),"\uff1a\u5728\u52a0\u5165\u96c6\u7fa4\u65f6\uff0c\u53ef\u4ee5\u9009\u62e9 ",(0,r.jsx)(s.code,{children:"P2P"})," \u6216 ",(0,r.jsx)(s.code,{children:"Gateway"})," \u6a21\u5f0f\u3002\r\nP2P \u6a21\u5f0f\u5728\u8986\u76d6\u5c42\u63d0\u4f9b\u7b2c\u4e8c\u5c42\u7f51\u7edc\u4e92\u8fde\uff0c\u63d0\u4f9b\u66f4\u77ed\u7684\u7f51\u7edc\u8def\u5f84\u548c\u66f4\u4f18\u7684\u6027\u80fd\u3002\r\n\u9009\u62e9 ",(0,r.jsx)(s.code,{children:"Gateway"})," \u6a21\u5f0f\u65f6\uff0c\u5b83\u8868\u73b0\u51fa\u66f4\u597d\u7684\u517c\u5bb9\u6027\uff0c\u975e\u5e38\u9002\u5408\u6df7\u5408\u548c\u591a\u4e91\u573a\u666f\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u652f\u6301\u5168\u5c40 IP \u5206\u914d"}),"\uff1aClusterLink \u5141\u8bb8\u5168\u5c40\u96c6\u7fa4\u4e2d\u5b58\u5728\u4e24\u4e2a\u6216\u591a\u4e2a\u96c6\u7fa4\u4f7f\u7528\u76f8\u540c\u7684 ",(0,r.jsx)(s.code,{children:"Pod/Service"})," \u7f51\u7edc\u6bb5\uff0c\u65b9\u4fbf\u7528\u6237\u7ba1\u7406\u5b50\u7f51\u3002\r\nClusterLink \u652f\u6301\u914d\u7f6e ",(0,r.jsx)(s.code,{children:"PodCIDR/ServiceCIDR"})," \u548c ",(0,r.jsx)(s.code,{children:"GlobalCIDR"})," \u4e4b\u95f4\u7684\u6620\u5c04\u5173\u7cfb\u3002\r\n",(0,r.jsx)(s.code,{children:"GlobalIP"})," \u662f\u5168\u7403\u552f\u4e00\u7684\uff0c\u901a\u8fc7 ",(0,r.jsx)(s.code,{children:"GlobalIP"})," \u4f7f\u51b2\u7a81\u7f51\u7edc\u6bb5\u7684\u670d\u52a1\u8fdb\u884c\u8de8\u96c6\u7fa4\u901a\u4fe1\u3002"]}),"\n",(0,r.jsx)(s.li,{children:(0,r.jsx)(s.strong,{children:"\u652f\u6301 IPv6/IPv4 \u53cc\u6808"})}),"\n"]}),"\n",(0,r.jsx)(s.h3,{id:"\u7f51\u7edc\u67b6\u6784",children:"\u7f51\u7edc\u67b6\u6784"}),"\n",(0,r.jsxs)(s.p,{children:["\u76ee\u524d\uff0cKosmos ClusterLink \u6a21\u5757\u5305\u62ec\u4ee5\u4e0b\u5173\u952e\u7ec4\u4ef6\uff1a\r\n",(0,r.jsx)(s.img,{alt:"ClusterLink_Architecture.png",src:n(9233).c+"",width:"2000",height:"1066"})]}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.code,{children:"Controller-Manager"}),"\uff1a\u6536\u96c6\u5f53\u524d\u96c6\u7fa4\u7684\u7f51\u7edc\u4fe1\u606f\u5e76\u76d1\u63a7\u7f51\u7edc\u8bbe\u7f6e\u7684\u53d8\u5316\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.code,{children:"Network-manager"}),"\uff1a\u8ba1\u7b97\u6bcf\u4e2a\u8282\u70b9\u6240\u9700\u7684\u7f51\u7edc\u914d\u7f6e\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.code,{children:"Agent"}),"\uff1a\u4e00\u4e2a DaemonSet \u7528\u4e8e\u914d\u7f6e\u4e3b\u673a\u7f51\u7edc\uff0c\u5305\u62ec\u96a7\u9053\u521b\u5efa\u3001\u8def\u7531\u3001NAT \u7b49\u4efb\u52a1\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.code,{children:"Multi-Cluster-Coredns"}),"\uff1a\u5b9e\u73b0\u591a\u96c6\u7fa4\u670d\u52a1\u53d1\u73b0\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.code,{children:"Elector"}),"\uff1a\u9009\u4e3e\u7f51\u5173\u8282\u70b9\u3002"]}),"\n"]}),"\n",(0,r.jsx)(s.h2,{id:"clustertree",children:"ClusterTree"}),"\n",(0,r.jsxs)(s.p,{children:["Kosmos clustertree \u6a21\u5757\u5b9e\u73b0\u4e86 Kubernetes \u7684\u6811\u72b6\u6269\u5c55\uff0c\u5e76\u5b9e\u73b0\u4e86\u8de8\u96c6\u7fa4\u7684\u5e94\u7528\u7f16\u6392\u3002\r\n\u8fd9\u662f Kosmos \u5b9e\u73b0 Kubernetes \u65e0\u9650\u6269\u5c55\u7684\u6280\u672f\u57fa\u7840\u3002\r\n",(0,r.jsx)(s.img,{alt:"ClusterTree_Architecture.png",src:n(2736).c+"",width:"1920",height:"1496"})]}),"\n",(0,r.jsx)(s.p,{children:"\u76ee\u524d\uff0c\u5b83\u4e3b\u8981\u652f\u6301\u4ee5\u4e0b\u529f\u80fd\uff1a"}),"\n",(0,r.jsxs)(s.ol,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u5b8c\u5168\u517c\u5bb9 k8s API"}),"\uff1a\u7528\u6237\u53ef\u4ee5\u50cf\u5e73\u5e38\u4e00\u6837\u4f7f\u7528 ",(0,r.jsx)(s.code,{children:"kubectl"}),"\u3001",(0,r.jsx)(s.code,{children:"client-go"})," \u7b49\u5de5\u5177\u4e0e\u4e3b\u96c6\u7fa4\u7684 ",(0,r.jsx)(s.code,{children:"kube-apiserver"})," \u8fdb\u884c\u4ea4\u4e92\u3002\u7136\u800c\uff0c",(0,r.jsx)(s.code,{children:"Pods"})," \u5b9e\u9645\u4e0a\u5206\u5e03\u5728\u6574\u4e2a\u591a\u4e91\u3001\u591a\u96c6\u7fa4\u73af\u5883\u4e2d\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u652f\u6301\u6709\u72b6\u6001\u548c k8s \u539f\u751f\u5e94\u7528\u7a0b\u5e8f"}),"\uff1a\u9664\u4e86\u65e0\u72b6\u6001\u5e94\u7528\u7a0b\u5e8f\u5916\uff0cKosmos \u8fd8\u4fc3\u8fdb\u4e86\u6709\u72b6\u6001\u5e94\u7528\u7a0b\u5e8f\u548c k8s \u539f\u751f\u5e94\u7528\u7a0b\u5e8f\uff08\u4e0e ",(0,r.jsx)(s.code,{children:"kube-apiserver"})," \u4ea4\u4e92\uff09\u7684\u7f16\u6392\u3002\r\nKosmos \u5c06\u81ea\u52a8\u68c0\u6d4b ",(0,r.jsx)(s.code,{children:"Pods"})," \u6240\u4f9d\u8d56\u7684\u5b58\u50a8\u548c\u6743\u9650\u8d44\u6e90\uff0c\u5982 pv/pvc\u3001sa \u7b49\uff0c\u5e76\u5728\u63a7\u5236\u5e73\u9762\u96c6\u7fa4\u548c\u6570\u636e\u5e73\u9762\u96c6\u7fa4\u4e4b\u95f4\u8fdb\u884c\u53cc\u5411\u540c\u6b65\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u591a\u6837\u7684 Pod \u62d3\u6251\u7ea6\u675f"}),"\uff1a\u7528\u6237\u53ef\u4ee5\u8f7b\u677e\u63a7\u5236\u5168\u7403\u96c6\u7fa4\u5185 Pods \u7684\u5206\u5e03\uff0c\u5982\u6309\u5730\u533a\u3001\u53ef\u7528\u533a\u3001\u96c6\u7fa4\u6216\u8282\u70b9\u3002\r\n\u8fd9\u6709\u52a9\u4e8e\u5b9e\u73b0\u9ad8\u53ef\u7528\u6027\u5e76\u63d0\u9ad8\u8d44\u6e90\u5229\u7528\u7387\u3002"]}),"\n"]}),"\n",(0,r.jsx)(s.h2,{id:"scheduler",children:"Scheduler"}),"\n",(0,r.jsx)(s.p,{children:"Kosmos \u8c03\u5ea6\u6a21\u5757\u662f\u5728 Kubernetes \u8c03\u5ea6\u6846\u67b6\u4e4b\u4e0a\u5f00\u53d1\u7684\u6269\u5c55\uff0c\u65e8\u5728\u6ee1\u8db3\u6df7\u5408\u8282\u70b9\u548c\u5b50\u96c6\u7fa4\u73af\u5883\u4e2d\u7684\u5bb9\u5668\u7ba1\u7406\u9700\u6c42\u3002\r\n\u5b83\u63d0\u4f9b\u4ee5\u4e0b\u6838\u5fc3\u529f\u80fd\uff0c\u4ee5\u63d0\u9ad8\u5bb9\u5668\u7ba1\u7406\u7684\u7075\u6d3b\u6027\u548c\u6548\u7387\uff1a"}),"\n",(0,r.jsxs)(s.ol,{children:["\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u7075\u6d3b\u7684\u8282\u70b9\u548c\u96c6\u7fa4\u6df7\u5408\u8c03\u5ea6"}),"\uff1aKosmos \u8c03\u5ea6\u6a21\u5757\u5141\u8bb8\u7528\u6237\u6839\u636e\u81ea\u5b9a\u4e49\u914d\u7f6e\u5728\u771f\u5b9e\u8282\u70b9\u548c\u5b50\u96c6\u7fa4\u4e4b\u95f4\u667a\u80fd\u8c03\u5ea6\u5de5\u4f5c\u8d1f\u8f7d\u3002\r\n\u8fd9\u4f7f\u7528\u6237\u80fd\u591f\u6700\u4f73\u5229\u7528\u4e0d\u540c\u8282\u70b9\u4e0a\u7684\u8d44\u6e90\uff0c\u786e\u4fdd\u5de5\u4f5c\u8d1f\u8f7d\u7684\u6700\u4f73\u6027\u80fd\u548c\u53ef\u7528\u6027\u3002\r\n\u57fa\u4e8e\u6b64\u529f\u80fd\uff0cKosmos \u4f7f\u5de5\u4f5c\u8d1f\u8f7d\u80fd\u591f\u5b9e\u73b0\u7075\u6d3b\u7684\u8de8\u4e91\u548c\u8de8\u96c6\u7fa4\u90e8\u7f72\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u7ec6\u7c92\u5ea6\u7684\u5bb9\u5668\u5206\u5e03\u7b56\u7565"}),"\uff1a\u901a\u8fc7\u5f15\u5165\u81ea\u5b9a\u4e49\u8d44\u6e90\u5b9a\u4e49 (CRD)\uff0c\u7528\u6237\u53ef\u4ee5\u5bf9\u5de5\u4f5c\u8d1f\u8f7d\u7684\u5206\u5e03\u8fdb\u884c\u7cbe\u786e\u63a7\u5236\u3002\r\nCRD \u7684\u914d\u7f6e\u5141\u8bb8\u7528\u6237\u660e\u786e\u6307\u5b9a\u4e0d\u540c\u96c6\u7fa4\u4e2d\u5de5\u4f5c\u8d1f\u8f7d\u7684 pod \u6570\u91cf\uff0c\u5e76\u6839\u636e\u9700\u8981\u8c03\u6574\u5206\u5e03\u6bd4\u4f8b\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:[(0,r.jsx)(s.strong,{children:"\u7ec6\u7c92\u5ea6\u7684\u788e\u7247\u5316\u8d44\u6e90\u5904\u7406"}),"\uff1aKosmos \u8c03\u5ea6\u6a21\u5757\u667a\u80fd\u68c0\u6d4b\u5b50\u96c6\u7fa4\u5185\u7684\u788e\u7247\u5316\u8d44\u6e90\uff0c\u6709\u6548\u907f\u514d pod \u90e8\u7f72\u9047\u5230\u5b50\u96c6\u7fa4\u5185\u8d44\u6e90\u4e0d\u8db3\u7684\u60c5\u51b5\u3002\r\n\u8fd9\u6709\u52a9\u4e8e\u5728\u4e0d\u540c\u8282\u70b9\u95f4\u5b9e\u73b0\u66f4\u5747\u8861\u7684\u8d44\u6e90\u5206\u914d\uff0c\u589e\u5f3a\u7cfb\u7edf\u7a33\u5b9a\u6027\u548c\u6027\u80fd\u3002"]}),"\n"]}),"\n",(0,r.jsx)(s.p,{children:"\u65e0\u8bba\u662f\u6784\u5efa\u6df7\u5408\u4e91\u73af\u5883\u8fd8\u662f\u9700\u8981\u7075\u6d3b\u5730\u8de8\u96c6\u7fa4\u90e8\u7f72\u5de5\u4f5c\u8d1f\u8f7d\uff0cKosmos \u8c03\u5ea6\u6a21\u5757\u90fd\u662f\u4e00\u4e2a\u53ef\u9760\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u5e2e\u52a9\u7528\u6237\u66f4\u9ad8\u6548\u5730\u7ba1\u7406\u5bb9\u5668\u5316\u5e94\u7528\u3002"}),"\n",(0,r.jsx)(s.h2,{id:"\u4e0b\u4e00\u6b65\u662f\u4ec0\u4e48",children:"\u4e0b\u4e00\u6b65\u662f\u4ec0\u4e48"}),"\n",(0,r.jsxs)(s.ul,{children:["\n",(0,r.jsxs)(s.li,{children:["\u5f00\u59cb ",(0,r.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/quick-start",children:"\u5b89\u88c5 Kosmos"}),"\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:["\u5b66\u4e60 Kosmos \u7684 ",(0,r.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/tutorials/mcs-discovery",children:"\u6559\u7a0b"}),"\u3002"]}),"\n",(0,r.jsxs)(s.li,{children:["\u5b66\u4e60 Kosmos \u7684 ",(0,r.jsx)(s.a,{href:"https://kosmos-io.github.io/website/v0.2.0/proposals/k8s-in-k8s",children:"\u63d0\u6848"}),"\u3002"]}),"\n"]})]})}function u(e={}){const{wrapper:s}={...(0,i.M)(),...e.components};return s?(0,r.jsx)(s,{...e,children:(0,r.jsx)(h,{...e})}):h(e)}},9233:(e,s,n)=>{n.d(s,{c:()=>r});const r=n.p+"assets/images/ClusterLink_Architecture-156348f81f4d7537d0c514541c0978c9.png"},2736:(e,s,n)=>{n.d(s,{c:()=>r});const r=n.p+"assets/images/ClusterTree_Architecture-ec1f02d3c150b9cc505a94e9e7b70abe.png"},2172:(e,s,n)=>{n.d(s,{I:()=>l,M:()=>o});var r=n(1504);const i={},c=r.createContext(i);function o(e){const s=r.useContext(c);return r.useMemo((function(){return"function"==typeof e?e(s):{...s,...e}}),[s,e])}function l(e){let s;return s=e.disableParentContext?"function"==typeof e.components?e.components(i):e.components||i:o(e.components),r.createElement(c.Provider,{value:s},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/d5d7ecfb.0982280e.js b/docs/assets/js/d5d7ecfb.0982280e.js deleted file mode 100644 index 6f5429d..0000000 --- a/docs/assets/js/d5d7ecfb.0982280e.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[528],{3767:(e,n,r)=>{r.r(n),r.d(n,{assets:()=>c,contentTitle:()=>t,default:()=>h,frontMatter:()=>i,metadata:()=>o,toc:()=>a});var s=r(7624),l=r(2172);const i={id:"pv-pvc-dynamic-storage_zh",title:"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8"},t="\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8\u89e3\u51b3\u65b9\u6848",o={id:"i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh",title:"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8",description:"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8\u5b9e\u73b0",source:"@site/docs/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh",permalink:"/website/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh.md",tags:[],version:"current",frontMatter:{id:"pv-pvc-dynamic-storage_zh",title:"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8"}},c={},a=[{value:"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8\u5b9e\u73b0",id:"\u591a\u96c6\u7fa4-pvpvc-\u52a8\u6001\u5b58\u50a8\u5b9e\u73b0",level:2},{value:"\u4ecb\u7ecd",id:"\u4ecb\u7ecd",level:3},{value:"\u65b9\u6cd5",id:"\u65b9\u6cd5",level:3},{value:"\u5355\u4e2a Kubernetes \u96c6\u7fa4\u4e2d PVC\u3001PV \u548c SC \u7684\u89d2\u8272",id:"\u5355\u4e2a-kubernetes-\u96c6\u7fa4\u4e2d-pvcpv-\u548c-sc-\u7684\u89d2\u8272",level:4},{value:"\u5355\u4e2a Kubernetes \u96c6\u7fa4\u4e2d PVC\u3001PV \u548c StorageClass \u7684\u5b9e\u73b0\u8fc7\u7a0b",id:"\u5355\u4e2a-kubernetes-\u96c6\u7fa4\u4e2d-pvcpv-\u548c-storageclass-\u7684\u5b9e\u73b0\u8fc7\u7a0b",level:4},{value:"StorageClass \u5377\u7ed1\u5b9a\u6a21\u5f0f",id:"storageclass-\u5377\u7ed1\u5b9a\u6a21\u5f0f",level:4},{value:"CSI\uff08\u52a8\u6001\u5377\u914d\u7f6e\uff09\u76f8\u5173\u8fc7\u7a0b",id:"csi\u52a8\u6001\u5377\u914d\u7f6e\u76f8\u5173\u8fc7\u7a0b",level:4},{value:"\u8de8\u96c6\u7fa4\u5b9e\u73b0",id:"\u8de8\u96c6\u7fa4\u5b9e\u73b0",level:4},{value:"\u6d41\u7a0b",id:"\u6d41\u7a0b",level:3},{value:"\u76f8\u5173",id:"\u76f8\u5173",level:3},{value:"\u8c03\u5ea6\u6a21\u5757\uff08\u4e3b\u96c6\u7fa4\uff09",id:"\u8c03\u5ea6\u6a21\u5757\u4e3b\u96c6\u7fa4",level:4},{value:"\u7f16\u6392\u6a21\u5757",id:"\u7f16\u6392\u6a21\u5757",level:4},{value:"\u793a\u4f8b",id:"\u793a\u4f8b",level:3},{value:"\u7ed3\u8bba",id:"\u7ed3\u8bba",level:3}];function d(e){const n={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",li:"li",ol:"ol",p:"p",pre:"pre",ul:"ul",...(0,l.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(n.h1,{id:"\u591a\u96c6\u7fa4-pvpvc-\u52a8\u6001\u5b58\u50a8\u89e3\u51b3\u65b9\u6848",children:"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8\u89e3\u51b3\u65b9\u6848"}),"\n",(0,s.jsx)(n.h2,{id:"\u591a\u96c6\u7fa4-pvpvc-\u52a8\u6001\u5b58\u50a8\u5b9e\u73b0",children:"\u591a\u96c6\u7fa4 PV/PVC \u52a8\u6001\u5b58\u50a8\u5b9e\u73b0"}),"\n",(0,s.jsx)(n.h3,{id:"\u4ecb\u7ecd",children:"\u4ecb\u7ecd"}),"\n",(0,s.jsx)(n.p,{children:"\u672c\u6587\u4e3b\u8981\u4ecb\u7ecd\u5728 Kosmos \u8de8\u96c6\u7fa4\u4e2d\uff0c\u4e3a\u6709\u72b6\u6001\u670d\u52a1\u76f8\u5173\u7684 Pod \u5b9e\u73b0 PV/PVC \u5b58\u50a8\u7ba1\u7406\u3002\r\n\u8be6\u7ec6\u8bf4\u660e\u4e86\u521b\u5efa\u3001\u66f4\u65b0\u548c\u7ed1\u5b9a Pod \u7684 PV \u548c PVC \u7684\u8fc7\u7a0b\u3002\r\n\u901a\u8fc7\u672c\u6587\uff0c\u60a8\u53ef\u4ee5\u5168\u9762\u4e86\u89e3\u5728 Kosmos \u4e2d\u7ba1\u7406\u6709\u72b6\u6001\u670d\u52a1\u7684\u7ec6\u8282\u3002"}),"\n",(0,s.jsx)(n.admonition,{title:"\u63d0\u793a",type:"info",children:(0,s.jsx)(n.p,{children:"\u76ee\u524d\u7684\u5b9e\u73b0\u662f\u4e00\u4e2a\u4e2d\u95f4\u7248\u672c\uff0c\u672a\u6765\u4f1a\u5bf9\u5168\u7403\u5b58\u50a8\u8fdb\u884c\u8fdb\u4e00\u6b65\u4f18\u5316\u3002"})}),"\n",(0,s.jsx)(n.h3,{id:"\u65b9\u6cd5",children:"\u65b9\u6cd5"}),"\n",(0,s.jsx)(n.h4,{id:"\u5355\u4e2a-kubernetes-\u96c6\u7fa4\u4e2d-pvcpv-\u548c-sc-\u7684\u89d2\u8272",children:"\u5355\u4e2a Kubernetes \u96c6\u7fa4\u4e2d PVC\u3001PV \u548c SC \u7684\u89d2\u8272"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"\u6301\u4e45\u5377 (Persistent Volume, PV):"}),"\n"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"PV \u662f Kubernetes \u96c6\u7fa4\u4e2d\u7684\u5b58\u50a8\u5377\u8d44\u6e90\uff0c\u5c06\u5176\u4e0e\u5b9e\u9645\u7684\u5b58\u50a8\u540e\u7aef\u62bd\u8c61\u548c\u5206\u79bb\u5f00\u6765\u3002"}),"\n",(0,s.jsx)(n.li,{children:"PV \u53ef\u4ee5\u662f\u4efb\u4f55\u5f62\u5f0f\u7684\u5b58\u50a8\uff0c\u5982\u7f51\u7edc\u5b58\u50a8\u3001\u672c\u5730\u5b58\u50a8\u3001\u4e91\u5b58\u50a8\u7b49\u3002"}),"\n",(0,s.jsx)(n.li,{children:"PV \u53ef\u4ee5\u7531 PV \u7ba1\u7406\u5458\u6216\u96c6\u7fa4\u4e2d\u7684\u52a8\u6001\u5b58\u50a8\u63d2\u4ef6\u9884\u5148\u521b\u5efa\uff0c\u4e5f\u53ef\u4ee5\u6839\u636e PVC \u7684\u8981\u6c42\u52a8\u6001\u521b\u5efa\u3002"}),"\n",(0,s.jsx)(n.li,{children:"PV \u63cf\u8ff0\u4e86\u5b58\u50a8\u5c5e\u6027\uff0c\u5982\u5bb9\u91cf\u3001\u8bbf\u95ee\u6a21\u5f0f\uff08\u4f8b\u5982\uff0c\u8bfb/\u5199\uff09\u548c\u56de\u6536\u7b56\u7565\u3002"}),"\n"]}),"\n",(0,s.jsxs)(n.ol,{start:"2",children:["\n",(0,s.jsx)(n.li,{children:"\u6301\u4e45\u5377\u58f0\u660e (Persistent Volume Claim, PVC):"}),"\n"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"PVC \u662f\u5e94\u7528\u7a0b\u5e8f\u5bf9\u5b58\u50a8\u8d44\u6e90\u7684\u8bf7\u6c42\uff0c\u5b83\u5728 Pod \u4e2d\u6307\u5b9a\u6240\u9700\u7684\u5b58\u50a8\u5bb9\u91cf\u548c\u5176\u4ed6\u5c5e\u6027\uff0c\u5982\u8bbf\u95ee\u6a21\u5f0f\u548c\u5377\u6a21\u5f0f\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5e94\u7528\u7a0b\u5e8f\u4f7f\u7528 PVC \u58f0\u660e\u5176\u5b58\u50a8\u9700\u6c42\uff0c\u800c\u65e0\u9700\u6307\u5b9a\u5b9e\u9645\u7684\u5b58\u50a8\u4f4d\u7f6e\u6216\u7c7b\u578b\u3002Kubernetes \u4f1a\u6839\u636e PVC \u7684\u9700\u6c42\u5339\u914d\u96c6\u7fa4\u4e2d\u7684\u53ef\u7528 PV \u4ee5\u6ee1\u8db3 PVC \u7684\u9700\u6c42\u3002"}),"\n",(0,s.jsx)(n.li,{children:"PVC \u53ef\u4ee5\u8bf7\u6c42\u52a8\u6001\u914d\u7f6e\u7684\u5339\u914d PV \u6216\u624b\u52a8\u9009\u62e9\u7279\u5b9a\u7684 PV \u5bf9\u8c61\u3002"}),"\n"]}),"\n",(0,s.jsxs)(n.ol,{start:"3",children:["\n",(0,s.jsx)(n.li,{children:"\u5b58\u50a8\u7c7b (StorageClass, SC):"}),"\n"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"SC \u5b9a\u4e49\u4e86 PV \u7684\u52a8\u6001\u914d\u7f6e\u7b56\u7565\uff0c\u6307\u5b9a\u4e86\u5982\u4f55\u6839\u636e PVC \u7684\u9700\u6c42\u81ea\u52a8\u521b\u5efa PV\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5f53 PVC \u8bf7\u6c42\u7279\u5b9a\u7684 StorageClass \u65f6\uff0cKubernetes \u4f1a\u6839\u636e StorageClass \u4e2d\u5b9a\u4e49\u7684\u89c4\u5219\u521b\u5efa PV \u5e76\u81ea\u52a8\u5c06 PV \u7ed1\u5b9a\u5230 PVC\u3002"}),"\n",(0,s.jsx)(n.li,{children:"StorageClass \u5141\u8bb8\u5b9a\u4e49\u4e0d\u540c\u7c7b\u578b\u7684\u5b58\u50a8\uff0c\u4e3a\u4e0d\u540c\u7684\u5e94\u7528\u7a0b\u5e8f\u63d0\u4f9b\u4e0d\u540c\u7684\u5b58\u50a8\u9009\u9879\u3002"}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"\u5355\u4e2a-kubernetes-\u96c6\u7fa4\u4e2d-pvcpv-\u548c-storageclass-\u7684\u5b9e\u73b0\u8fc7\u7a0b",children:"\u5355\u4e2a Kubernetes \u96c6\u7fa4\u4e2d PVC\u3001PV \u548c StorageClass \u7684\u5b9e\u73b0\u8fc7\u7a0b"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\u5f53\u5e94\u7528\u7a0b\u5e8f\u4e2d\u7684 Pod \u9700\u8981\u8bbf\u95ee\u6301\u4e45\u5b58\u50a8\u65f6\uff0c\u4f1a\u521b\u5efa\u4e00\u4e2a PVC \u5bf9\u8c61\u6765\u58f0\u660e\u6240\u9700\u7684\u5b58\u50a8\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u6839\u636e PVC \u4e2d\u5b9a\u4e49\u7684\u9700\u6c42\uff0cKubernetes \u4f1a\u901a\u8fc7 StorageClass \u5339\u914d\u9002\u5408\u7684 PV \u5e76\u8fdb\u884c\u7ed1\u5b9a\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5728 PV \u548c PVC \u6210\u529f\u7ed1\u5b9a\u540e\uff0c\u5e94\u7528\u7a0b\u5e8f\u53ef\u4ee5\u76f4\u63a5\u4f7f\u7528 PVC \u63d0\u4f9b\u7684\u5b58\u50a8\u5e76\u5728 Pod \u4e2d\u6302\u8f7d\u5b58\u50a8\u8def\u5f84\u3002"}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"storageclass-\u5377\u7ed1\u5b9a\u6a21\u5f0f",children:"StorageClass \u5377\u7ed1\u5b9a\u6a21\u5f0f"}),"\n",(0,s.jsx)(n.p,{children:"\u5728 StorageClass \u5b9a\u4e49\u4e2d\uff0c'volumeBindingMode' \u5b57\u6bb5\u6307\u5b9a\u4e86\u52a8\u6001\u914d\u7f6e\u5668\u5982\u4f55\u7ed1\u5b9a PVC \u548c PV\u3002\u4ee5\u4e0b\u662f\u51e0\u79cd\u5e38\u89c1\u7684\u5377\u7ed1\u5b9a\u6a21\u5f0f\uff1a"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"Immediate: \u5728\u8fd9\u79cd\u6a21\u5f0f\u4e0b\uff0c\u914d\u7f6e\u5668\u4f1a\u7acb\u5373\u5c06\u53ef\u7528\u7684 PV \u7ed1\u5b9a\u5230 PVC\u3002\u5982\u679c\u6ca1\u6709\u53ef\u7528\u7684 PV \u6ee1\u8db3 PVC \u7684\u8981\u6c42\uff0cPVC \u5c06\u4fdd\u6301\u5728 Pending \u72b6\u6001\u3002"}),"\n",(0,s.jsx)(n.li,{children:"WaitForFirstConsumer: \u5728\u8fd9\u79cd\u6a21\u5f0f\u4e0b\uff0c\u914d\u7f6e\u5668\u4f1a\u7b49\u5f85\u5f15\u7528 PVC \u7684 Pod \u5c1d\u8bd5\u6302\u8f7d\u5377\u540e\u518d\u5206\u914d PV\u3002\u5f53 Pod \u4f7f\u7528 PVC \u65f6\uff0cPV \u4f1a\u88ab\u52a8\u6001\u7ed1\u5b9a\u3002"}),"\n",(0,s.jsx)(n.li,{children:"Cluster: \u8fd9\u662f\u9ed8\u8ba4\u7684\u7ed1\u5b9a\u6a21\u5f0f\u3002PV \u4f1a\u7acb\u5373\u5206\u914d\u7ed9 PVC\u3002\u8fd9\u79cd\u6a21\u5f0f\u7c7b\u4f3c\u4e8e 'Immediate'\uff0c\u4f46\u5141\u8bb8\u96c6\u7fa4\u7ba1\u7406\u5458\u8986\u76d6 StorageClass \u7684\u9ed8\u8ba4\u7ed1\u5b9a\u6a21\u5f0f\u3002\r\n\u6bcf\u4e2a StorageClass \u53ea\u80fd\u6709\u4e00\u79cd\u7ed1\u5b9a\u6a21\u5f0f\uff0c\u5e76\u4e14\u4e00\u65e6\u8bbe\u7f6e\u540e\u4e0d\u80fd\u66f4\u6539\u3002"}),"\n"]}),"\n",(0,s.jsx)(n.p,{children:"\u6839\u636e\u9700\u6c42\u548c\u73af\u5883\u914d\u7f6e\u9009\u62e9\u9002\u5f53\u5f97\u7ed1\u5b9a\u6a21\u5f0f\u3002"}),"\n",(0,s.jsx)(n.h4,{id:"csi\u52a8\u6001\u5377\u914d\u7f6e\u76f8\u5173\u8fc7\u7a0b",children:"CSI\uff08\u52a8\u6001\u5377\u914d\u7f6e\uff09\u76f8\u5173\u8fc7\u7a0b"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"\u7528\u6237\u521b\u5efa\u4e00\u4e2a Pod \u548c PVC\u3002"}),"\n",(0,s.jsx)(n.li,{children:"VolumeController \u7684 PersistentVolumeController \u63a7\u5236\u5faa\u73af\u68c0\u6d4b\u5230 PVC \u7684\u521b\u5efa\u5e76\u8df3\u8fc7\u5b83\uff0c\u56e0\u4e3a\u5b83\u4f7f\u7528\u7684\u662f Out-of-Tree \u6a21\u5f0f\u3002\r\n\u8be5\u63a7\u5236\u5faa\u73af\u4e3b\u8981\u5904\u7406 In-Tree \u6a21\u5f0f\u4e0b\u7684 PV \u548c PVC \u7ed1\u5b9a\u3002"}),"\n",(0,s.jsx)(n.li,{children:"External-provisioner \u68c0\u6d4b\u5230 PVC \u7684\u521b\u5efa\uff1a"}),"\n"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\u8c03\u7528 Controller Service \u7684 'CreateVolume' \u65b9\u6cd5\u521b\u5efa\u5e95\u5c42\u5b58\u50a8\u5377\u3002\u6b64\u65f6\uff0c\u5377\u5904\u4e8e CREATED \u72b6\u6001\uff0c\u4ec5\u5728\u5b58\u50a8\u7cfb\u7edf\u4e2d\u5b58\u5728\uff0c\u5bf9\u4efb\u4f55\u8282\u70b9\u6216\u5bb9\u5668\u4e0d\u53ef\u89c1\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u521b\u5efa PV\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5c06 PV \u7ed1\u5b9a\u5230 PVC\uff08\u7ed1\u5b9a\uff1a\u5728 PVC \u5bf9\u8c61\u7684 spec.volumeName \u5b57\u6bb5\u4e2d\u586b\u5199\u8be5 PV \u5bf9\u8c61\u7684\u540d\u79f0\uff09\u3002"}),"\n"]}),"\n",(0,s.jsxs)(n.ol,{start:"4",children:["\n",(0,s.jsx)(n.li,{children:"VolumeController \u7684 AttachDetachController \u63a7\u5236\u5faa\u73af\u68c0\u6d4b\u5230\u5377\u672a\u9644\u52a0\u5230\u4e3b\u673a\uff0c\u9700\u8981\u6267\u884c Attach \u64cd\u4f5c\u3002\u5b83\u521b\u5efa 'VolumeAttachment' \u5bf9\u8c61\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5f53 external-attacher \u68c0\u6d4b\u5230 'VolumeAttachment' \u8d44\u6e90\u7684\u521b\u5efa\u65f6\uff0c\u5b83\u8c03\u7528 Controller Service \u7684 'ControllerPublishVolume' \u65b9\u6cd5\u3002\r\n\u6b64\u65f6\uff0c\u5377\u5904\u4e8e NODE_READY \u72b6\u6001\uff0c\u610f\u5473\u7740\u8282\u70b9\u53ef\u4ee5\u68c0\u6d4b\u5230\u5377\uff0c\u4f46\u5728\u5bb9\u5668\u5185\u90e8\u4ecd\u4e0d\u53ef\u89c1\u3002"}),"\n",(0,s.jsx)(n.li,{children:"Kubelet \u7684 VolumeManagerReconciler \u63a7\u5236\u5faa\u73af\uff1a"}),"\n"]}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\u8c03\u7528 Node Service \u7684 'NodeStageVolume' \u65b9\u6cd5\u6267\u884c MountDevice \u64cd\u4f5c\u3002\u8be5\u65b9\u6cd5\u4e3b\u8981\u5904\u7406\u683c\u5f0f\u5316\u5377\u5e76\u5c06\u5176\u6302\u8f7d\u5230\u4e34\u65f6\u76ee\u5f55\uff08Staging \u76ee\u5f55\uff09\u3002\r\n\u6b64\u64cd\u4f5c\u540e\uff0c\u5377\u8fdb\u5165 VOL_READY \u72b6\u6001\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u8c03\u7528 Node Service \u7684 'NodePublishVolume' \u65b9\u6cd5\u6267\u884c SetUp \u64cd\u4f5c\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5b83\u7ed1\u5b9a Staging \u76ee\u5f55\u5e76\u5c06\u5176\u6302\u8f7d\u5230\u5377\u7684\u76f8\u5e94\u4e3b\u673a\u76ee\u5f55\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5377\u8fdb\u5165 PUBLISHED \u72b6\u6001\uff0c\u7528\u6237\u73b0\u5728\u53ef\u4ee5\u6b63\u5e38\u4f7f\u7528\u5b83\u3002"}),"\n"]}),"\n",(0,s.jsx)(n.h4,{id:"\u8de8\u96c6\u7fa4\u5b9e\u73b0",children:"\u8de8\u96c6\u7fa4\u5b9e\u73b0"}),"\n",(0,s.jsx)(n.p,{children:"\u57fa\u4e8e\u5355\u4e2a Kubernetes \u96c6\u7fa4\u4e2d PVC\u3001PV \u548c StorageClass \u7684\u903b\u8f91\uff0c\u5e76\u7ed3\u5408 Kosmos \u4e2d\u8de8\u96c6\u7fa4\u521b\u5efa Pod \u5b9e\u4f8b\u7684\u903b\u8f91\uff0c\u8de8\u96c6\u7fa4\u5b9e\u73b0 PV/PVC \u7684\u65b9\u6cd5\u5982\u4e0b\uff1a"}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\u5728\u4e3b\u96c6\u7fa4\uff08Host-Cluster\uff09\u4e2d\uff0cStorageClass \u7684 volumeBindingMode \u8bbe\u7f6e\u4e3a WaitForFirstConsumer\uff0c\u786e\u4fdd\u5ef6\u8fdf\u7ed1\u5b9a\u548c\u914d\u7f6e PV\uff08\u7b49\u5f85\u4e0e\u6210\u5458\u96c6\u7fa4\u540c\u6b65\uff09\u76f4\u5230\u521b\u5efa\u4f7f\u7528 PersistentVolumeClaim \u7684 Pod\u3002\r\nPersistentVolumes \u5c06\u6839\u636e Pod \u4e2d\u6307\u5b9a\u7684\u8c03\u5ea6\u7ea6\u675f\uff08\u5305\u62ec\u8d44\u6e90\u8981\u6c42\u3001\u8282\u70b9\u9009\u62e9\u5668\u3001Pod \u4eb2\u548c\u6027\u548c\u53cd\u4eb2\u548c\u6027\u3001\u6c61\u70b9\u548c\u5bb9\u5fcd\u5ea6\uff09\u8fdb\u884c\u9009\u62e9\u6216\u914d\u7f6e\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u4e3b\u96c6\u7fa4\uff08Host-Cluster\uff09\u4e2d\u7684 PVC \u548c PV \u7ed1\u5b9a\u5e94\u4e0e Kosmos \u4e2d\u8de8\u96c6\u7fa4\u521b\u5efa Pod \u7684\u8fc7\u7a0b\u4e00\u81f4\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u4e3b\u96c6\u7fa4\uff08Host-Cluster\uff09\u4e2d\u7684 PV \u63a7\u5236\u5668\u4ec5\u5904\u7406 PV \u5220\u9664\u4e8b\u4ef6\uff0c\u521b\u5efa\u548c\u66f4\u65b0\u64cd\u4f5c\u7531\u6210\u5458\u96c6\u7fa4\u4e2d\u7684 PV \u63a7\u5236\u5668\u6267\u884c\u3002"}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"\u6d41\u7a0b",children:"\u6d41\u7a0b"}),"\n",(0,s.jsx)(n.p,{children:"Kosmos PV/PVC \u7684\u5b9e\u73b0\u6d41\u7a0b\u5982\u4e0b\uff1a"}),"\n",(0,s.jsx)(n.p,{children:(0,s.jsx)(n.img,{alt:"PV_PVC_Dynamic_Storage.png",src:r(7244).c+"",width:"1590",height:"1652"})}),"\n",(0,s.jsxs)(n.ul,{children:["\n",(0,s.jsx)(n.li,{children:"\u5f53\u5728\u4e3b\u96c6\u7fa4\uff08Host-Cluster\uff09\u4e2d\u521b\u5efa Pod \u5e76\u6709\u76f8\u5173\u7684 PVC \u8bf7\u6c42\u65f6\uff0cKosmos \u5c06\u6839\u636e Pod \u521b\u5efa\u4e8b\u4ef6\u5728\u6210\u5458\u96c6\u7fa4\u4e2d\u521b\u5efa\u76f8\u5e94\u7684 PVC\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5728\u6210\u5458\u96c6\u7fa4\uff08Member-Cluster\uff09\u4e2d\u521b\u5efa PVC \u540e\uff0c\u6d41\u7a0b\u4e0e\u5355\u4e2a Kubernetes \u96c6\u7fa4\u4e2d\u7684\u6d41\u7a0b\u76f8\u540c\uff0c\u5305\u62ec Pod \u521b\u5efa\u3001PVC \u521b\u5efa\u3001PV \u521b\u5efa\u548c PVC-PV \u7ed1\u5b9a\u7684\u5b8c\u6210\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5f53\u5728\u6210\u5458\u96c6\u7fa4\uff08Member-Cluster\uff09\u4e2d\u521b\u5efa PV \u65f6\uff0c\u76f8\u5e94\u7684 PV \u63a7\u5236\u5668\u5c06\u6839\u636e PV \u521b\u5efa\u4e8b\u4ef6\u5728\u4e3b\u96c6\u7fa4\uff08Host-Cluster\uff09\u4e2d\u521b\u5efa PV\u3002"}),"\n",(0,s.jsx)(n.li,{children:"\u5728\u6210\u5458\u96c6\u7fa4\uff08Member-Cluster\uff09\u4e2d\u6210\u529f\u8c03\u5ea6\u5e76\u7ed1\u5b9a PVC \u548c PV \u540e\uff0c\u4e3b\u96c6\u7fa4\uff08Host-Cluster\uff09\u4e2d\u7684 PV \u521b\u5efa\u5c06\u5b8c\u6210 PVC \u548c PV \u7684\u7ed1\u5b9a\u3002"}),"\n"]}),"\n",(0,s.jsx)(n.h3,{id:"\u76f8\u5173",children:"\u76f8\u5173"}),"\n",(0,s.jsx)(n.h4,{id:"\u8c03\u5ea6\u6a21\u5757\u4e3b\u96c6\u7fa4",children:"\u8c03\u5ea6\u6a21\u5757\uff08\u4e3b\u96c6\u7fa4\uff09"}),"\n",(0,s.jsxs)(n.p,{children:['\u6b64\u6a21\u5757\u53ef\u4ee5\u901a\u8fc7\u6269\u5c55 Kosmos \u8c03\u5ea6\u5668\u4e2d\u7684 VolumeBinding \u63d2\u4ef6\u5b9e\u73b0\u3002\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528\u5e26\u6709 "kosmos.io/node=true',":NoSchedule",'" \u6c61\u70b9\u7684\u865a\u62df\u8282\u70b9\u6765\u5b9e\u73b0\u3002']}),"\n",(0,s.jsx)(n.h4,{id:"\u7f16\u6392\u6a21\u5757",children:"\u7f16\u6392\u6a21\u5757"}),"\n",(0,s.jsx)(n.p,{children:"\u6b64\u6a21\u5757\u7684\u5b9e\u73b0\u4e3b\u8981\u57fa\u4e8e\u7b2c 3 \u8282\u4e2d\u63cf\u8ff0\u7684\u6b65\u9aa4\uff0c\u5305\u62ec Kosmos \u96c6\u7fa4\u7ba1\u7406\u5668\u4e2d\u7684 root_pod_controller.go\u3001root_pvc_controller.go\u3001leaf_pvc_controller.go\u3001root_pv_controller.go \u548c leaf_pv_controller.go\u3002"}),"\n",(0,s.jsx)(n.h3,{id:"\u793a\u4f8b",children:"\u793a\u4f8b"}),"\n",(0,s.jsxs)(n.ol,{children:["\n",(0,s.jsx)(n.li,{children:"YAML \u793a\u4f8b:"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:'apiVersion: v1\r\nkind: PersistentVolumeClaim\r\nmetadata:\r\n name: nginx-pvc\r\n namespace: test-new\r\nspec:\r\n accessModes:\r\n - ReadWriteOnce\r\n resources:\r\n requests:\r\n storage: 1Gi\r\n storageClassName: openebs-hostpath\r\n---\r\napiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: nginx-new\r\n namespace: test-new\r\nspec:\r\n selector:\r\n matchLabels:\r\n app: nginx\r\n replicas: 1\r\n template:\r\n metadata:\r\n labels:\r\n app: nginx\r\n deletionGracePeriodSeconds: 30\r\n spec:\r\n affinity:\r\n nodeAffinity:\r\n requiredDuringSchedulingIgnoredDuringExecution:\r\n nodeSelectorTerms:\r\n - matchExpressions:\r\n - key: kubernetes.io/hostname\r\n operator: In\r\n values:\r\n - kosmos-cluster38\r\n tolerations:\r\n - key: "kosmos.io/node"\r\n operator: "Equal"\r\n value: "true"\r\n effect: "NoSchedule"\r\n containers:\r\n - name: nginx\r\n image: registry.paas/cnp/nginx:1.14-alpine\r\n ports:\r\n - containerPort: 80\r\n volumeMounts:\r\n - name: data\r\n mountPath: /data\r\n volumes:\r\n - name: data\r\n persistentVolumeClaim:\r\n claimName: "nginx-pvc"\n'})}),"\n",(0,s.jsxs)(n.ol,{start:"2",children:["\n",(0,s.jsx)(n.li,{children:"\u5728\u4e3b\u96c6\u7fa4\u4e2d\u6267\u884c\u521b\u5efa\u64cd\u4f5c:"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"[root@kosmos-control-cluster ylc]# kubectl apply -f test.yaml\r\npersistentvolumeclaim/nginx-pvc created\r\ndeployment.apps/nginx-new\r\n\r\n created\r\n[root@kosmos-control-cluster ylc]# kubectl get all -n test-new\r\nNAME READY STATUS RESTARTS AGE\r\npod/nginx-new-5677468b6c-ns9k2 0/1 Pending 0 5s\r\n\r\nNAME READY UP-TO-DATE AVAILABLE AGE\r\ndeployment.apps/nginx-new 0/1 1 0 5s\r\n\r\nNAME DESIRED CURRENT READY AGE\r\nreplicaset.apps/nginx-new-5677468b6c 1 1 0 5s\r\n[root@kosmos-control-cluster ylc]# kubectl get all -n test-new -owide\r\nNAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES\r\npod/nginx-new-5677468b6c-ns9k2 1/1 Running 0 11s 10.*.*.252 kosmos-cluster38 \r\n\r\nNAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR\r\ndeployment.apps/nginx-new 1/1 1 1 11s nginx nginx:1.14-alpine app=nginx\r\n\r\nNAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR\r\nreplicaset.apps/nginx-new-5677468b6c 1 1 1 11s nginx nginx:1.14-alpine app=nginx,pod-template-hash=56774\r\n[root@kosmos-control-cluster ylc]# kubectl get pvc -n test-new\r\nNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE\r\nnginx-pvc Bound pvc-ad86ef86-23c1-407e-a8e7-0b3e44d36254 1Gi RWO openebs-hostpath 21s\n"})}),"\n",(0,s.jsxs)(n.ol,{start:"3",children:["\n",(0,s.jsx)(n.li,{children:"\u67e5\u8be2\u6210\u5458\u96c6\u7fa4\u4e2d\u7684\u72b6\u6001:"}),"\n"]}),"\n",(0,s.jsx)(n.pre,{children:(0,s.jsx)(n.code,{className:"language-shell",metastring:"script",children:"[root@cluster38 ~]# kubectl get all -n test-new\r\nNAME READY STATUS RESTARTS AGE\r\npod/nginx-new-5677468b6c-ns9k2 1/1 Running 0 2m36s\r\n[root@cluster38 ~]# kubectl get pvc -n test-new\r\nNAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE\r\nnginx-pvc Bound pvc-ad86ef86-23c1-407e-a8e7-0b3e44d36254 1Gi RWO openebs-hostpath 2m41s\n"})}),"\n",(0,s.jsx)(n.h3,{id:"\u7ed3\u8bba",children:"\u7ed3\u8bba"}),"\n",(0,s.jsx)(n.p,{children:"Kosmos \u4e2d PV/PVC \u7684\u52a8\u6001\u5b58\u50a8\u5b9e\u73b0\u9700\u8981\u6269\u5c55\u4ee5\u652f\u6301\u5168\u7403\u5b58\u50a8\u3002\u76ee\u524d\u7684\u5b9e\u73b0\u7c92\u5ea6\u8f83\u5c0f\uff0c\u4ecd\u9700\u8fdb\u4e00\u6b65\u6539\u8fdb\u548c\u6f14\u8fdb\u3002"})]})}function h(e={}){const{wrapper:n}={...(0,l.M)(),...e.components};return n?(0,s.jsx)(n,{...e,children:(0,s.jsx)(d,{...e})}):d(e)}},7244:(e,n,r)=>{r.d(n,{c:()=>s});const s=r.p+"assets/images/PV_PVC_Dynamic_Storage-0b5e75726205965064b4fb0aedbe8233.png"},2172:(e,n,r)=>{r.d(n,{I:()=>o,M:()=>t});var s=r(1504);const l={},i=s.createContext(l);function t(e){const n=s.useContext(i);return s.useMemo((function(){return"function"==typeof e?e(n):{...n,...e}}),[n,e])}function o(e){let n;return n=e.disableParentContext?"function"==typeof e.components?e.components(l):e.components||l:t(e.components),s.createElement(i.Provider,{value:n},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e5ba6994.c60deed7.js b/docs/assets/js/e5ba6994.c60deed7.js deleted file mode 100644 index 67d2549..0000000 --- a/docs/assets/js/e5ba6994.c60deed7.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[92],{8952:(e,r,n)=>{n.r(r),n.d(r,{assets:()=>l,contentTitle:()=>c,default:()=>x,frontMatter:()=>t,metadata:()=>d,toc:()=>i});var s=n(7624),o=n(2172);const t={id:"exe-and-log_zh",title:"Kosmos \u4e2d\u7684 EXEC \u548c Log \u8bbe\u8ba1"},c="Kosmos \u4e2d\u7684 EXEC \u548c Log \u8bbe\u8ba1",d={id:"i18n/zh/v0.2.0/exe-and-log_zh",title:"Kosmos \u4e2d\u7684 EXEC \u548c Log \u8bbe\u8ba1",description:"Kosmos \u7684 EXEC \u548c Log \u89e3\u51b3\u65b9\u6848",source:"@site/docs/i18n/zh/v0.2.0/design-of-exec-and-log_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/exe-and-log_zh",permalink:"/website/i18n/zh/v0.2.0/exe-and-log_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/design-of-exec-and-log_zh.md",tags:[],version:"current",frontMatter:{id:"exe-and-log_zh",title:"Kosmos \u4e2d\u7684 EXEC \u548c Log \u8bbe\u8ba1"}},l={},i=[{value:"Kosmos \u7684 EXEC \u548c Log \u89e3\u51b3\u65b9\u6848",id:"kosmos-\u7684-exec-\u548c-log-\u89e3\u51b3\u65b9\u6848",level:2},{value:"\u7b80\u4ecb",id:"\u7b80\u4ecb",level:3},{value:"\u80cc\u666f\u77e5\u8bc6",id:"\u80cc\u666f\u77e5\u8bc6",level:3},{value:"\u5728 Kosmos \u4e2d\u7684\u5b9e\u73b0",id:"\u5728-kosmos-\u4e2d\u7684\u5b9e\u73b0",level:3},{value:"\u5b9a\u5236\u5316",id:"\u5b9a\u5236\u5316",level:3},{value:"\u7ed3\u8bba",id:"\u7ed3\u8bba",level:3}];function a(e){const r={code:"code",em:"em",h1:"h1",h2:"h2",h3:"h3",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,o.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(r.h1,{id:"kosmos-\u4e2d\u7684-exec-\u548c-log-\u8bbe\u8ba1",children:"Kosmos \u4e2d\u7684 EXEC \u548c Log \u8bbe\u8ba1"}),"\n",(0,s.jsx)(r.h2,{id:"kosmos-\u7684-exec-\u548c-log-\u89e3\u51b3\u65b9\u6848",children:"Kosmos \u7684 EXEC \u548c Log \u89e3\u51b3\u65b9\u6848"}),"\n",(0,s.jsx)(r.h3,{id:"\u7b80\u4ecb",children:"\u7b80\u4ecb"}),"\n",(0,s.jsxs)(r.p,{children:["\u5728 Kosmos \u4e2d\uff0c\u8c03\u5ea6\u5230 kosmos-node \u7684 pod \u4e5f\u652f\u6301 ",(0,s.jsx)(r.code,{children:"kubectl exec"})," \u548c ",(0,s.jsx)(r.code,{children:"kubectl log"})," \u529f\u80fd\u3002\r\n\u7531\u4e8e ",(0,s.jsx)(r.code,{children:"kubectl exec"})," \u548c ",(0,s.jsx)(r.code,{children:"kubectl log"})," \u7684\u6574\u4f53\u67b6\u6784\u662f\u76f8\u540c\u7684\uff0c\u6211\u4eec\u5c06\u4f7f\u7528 ",(0,s.jsx)(r.code,{children:"kubectl exec"})," \u4f5c\u4e3a\u793a\u4f8b\u6765\u4ecb\u7ecd\u6574\u4f53\u67b6\u6784\u3002\r\n\u4e0b\u56fe\u5c55\u793a\u4e86\u6574\u4f53\u8bbe\u8ba1\u67b6\u6784\u3002"]}),"\n",(0,s.jsx)(r.p,{children:(0,s.jsx)(r.img,{alt:"EXE Log_Arch.png",src:n(4780).c+"",width:"1110",height:"863"})}),"\n",(0,s.jsx)(r.h3,{id:"\u80cc\u666f\u77e5\u8bc6",children:"\u80cc\u666f\u77e5\u8bc6"}),"\n",(0,s.jsxs)(r.p,{children:["\u9996\u5148\uff0c\u8ba9\u6211\u4eec\u63a2\u8ba8\u5728 Kubernetes \u4e2d\u5982\u4f55\u5b9e\u73b0 ",(0,s.jsx)(r.code,{children:"kubectl exec"}),"\u3002\r\n\u67b6\u6784\u56fe\u4e2d\u7684 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"leaf-cluster"})})," \u90e8\u5206\u662f\u539f\u751f\u96c6\u7fa4\u7684 ",(0,s.jsx)(r.code,{children:"kubectl exec"})," \u529f\u80fd\u7684\u4ee3\u8868\u3002\r\n\u7528\u6237\u53d1\u8d77\u7684 kubectl exec \u8bf7\u6c42\u7531 apiserver \u5904\u7406\u3002\r\napiserver \u5728\u63a5\u6536\u5230 exec \u8bf7\u6c42\u540e\uff0c\u9700\u8981\u5c06\u8bf7\u6c42\u8f6c\u53d1\u5230 pod \u6240\u5728\u7684\u8282\u70b9\uff0c\u56e0\u6b64\u9700\u8981\u67e5\u8be2\u5206\u914d\u4e86 pod \u7684\u8282\u70b9\u4fe1\u606f\u3002\r\n\u5728 Kubernetes \u6e90\u4ee3\u7801\u4e2d\uff0capiserver \u4f1a\u8c03\u7528 ",(0,s.jsx)(r.code,{children:"ExecLocation"})," \u65b9\u6cd5\u4ee5\u83b7\u53d6 pod \u7684 exec url\u3002\r\n\u4ee3\u7801\u5982\u4e0b\uff1a"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:'// ExecLocation \u8fd4\u56de pod \u5bb9\u5668\u7684 exec URL\r\n// \u5982\u679c opts.Container \u4e3a\u7a7a\u4e14 pod \u4e2d\u53ea\u6709\u4e00\u4e2a\u5bb9\u5668, \u5219\u4f7f\u7528\u8be5\u5bb9\u5668\r\nfunc ExecLocation(\r\n ctx context.Context,\r\n getter ResourceGetter,\r\n connInfo client.ConnectionInfoGetter,\r\n name string,\r\n opts *api.PodExecOptions,\r\n) (*url.URL, http.RoundTripper, error) {\r\n return streamLocation(ctx, getter, connInfo, name, opts, opts.Container, "exec")\r\n}\n'})}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)(r.code,{children:"ExecLocation"})," \u8c03\u7528\u4e86 ",(0,s.jsx)(r.code,{children:"streamLocation"})," \u65b9\u6cd5\uff0cstreamLocation \u901a\u8fc7 pod \u540d\u79f0\u83b7\u53d6 pod \u4fe1\u606f\u3002"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:'func streamLocation(\r\n ctx context.Context,\r\n getter ResourceGetter,\r\n connInfo client.ConnectionInfoGetter,\r\n name string,\r\n opts runtime.Object,\r\n container,\r\n path string,\r\n) (*url.URL, http.RoundTripper, error) {\r\n pod, err := getPod(ctx, getter, name)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n \r\n // \u5c1d\u8bd5\u786e\u5b9a\u4e00\u4e2a\u5bb9\u5668\r\n // \u5982\u679c\u63d0\u4f9b\u4e86\u4e00\u4e2a\u5bb9\u5668, \u5219\u5b83\u5fc5\u987b\u662f\u6709\u6548\u7684\r\n container, err = validateContainer(container, pod)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n \r\n nodeName := types.NodeName(pod.Spec.NodeName)\r\n if len(nodeName) == 0 {\r\n // \u5982\u679c pod \u5c1a\u672a\u5206\u914d\u4e3b\u673a, \u5219\u8fd4\u56de\u7a7a\u4f4d\u7f6e\r\n return nil, nil, errors.NewBadRequest(fmt.Sprintf("pod %s \u5c1a\u672a\u5206\u914d\u4e3b\u673a", name))\r\n }\r\n nodeInfo, err := connInfo.GetConnectionInfo(ctx, nodeName)\r\n if err != nil {\r\n return nil, nil, err\r\n }\r\n params := url.Values{}\r\n if err := streamParams(params, opts); err != nil {\r\n return nil, nil, err\r\n }\r\n loc := &url.URL{\r\n Scheme: nodeInfo.Scheme,\r\n Host: net.JoinHostPort(nodeInfo.Hostname, nodeInfo.Port),\r\n Path: fmt.Sprintf("/%s/%s/%s/%s", path, pod.Namespace, pod.Name, container),\r\n RawQuery: params.Encode(),\r\n }\r\n return loc, nodeInfo.Transport, nil\r\n}\n'})}),"\n",(0,s.jsxs)(r.p,{children:["\u7136\u540e\u901a\u8fc7 ",(0,s.jsx)(r.code,{children:"pod.Spec.NodeName"})," \u83b7\u53d6\u5206\u914d pod \u7684\u8282\u70b9\u540d\u79f0\uff0c\u518d\u8c03\u7528\u4e00\u4e2a\u5173\u952e\u65b9\u6cd5 ",(0,s.jsx)(r.code,{children:"GetConnectionInfo"}),"\u3002\r\n\u4ee3\u7801\u5982\u4e0b\uff1a"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:"// GetConnectionInfo \u4ece Node API \u5bf9\u8c61\u7684\u72b6\u6001\u4e2d\u68c0\u7d22\u8fde\u63a5\u4fe1\u606f\r\nfunc (k *NodeConnectionInfoGetter) GetConnectionInfo(ctx context.Context, nodeName types.NodeName) (*ConnectionInfo, error) {\r\n node, err := k.nodes.Get(ctx, string(nodeName), metav1.GetOptions{})\r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n // \u67e5\u627e kubelet \u62a5\u544a\u7684\u5730\u5740, \u4f7f\u7528\u9996\u9009\u5730\u5740\u7c7b\u578b\r\n host, err := nodeutil.GetPreferredNodeAddress(node, k.preferredAddressTypes)\r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n // \u4f7f\u7528 kubelet \u62a5\u544a\u7684\u7aef\u53e3, \u5982\u679c\u5b58\u5728\r\n port := int(node.Status.DaemonEndpoints.KubeletEndpoint.Port)\r\n if port <= 0 {\r\n port = k.defaultPort\r\n }\r\n \r\n return &ConnectionInfo{\r\n Scheme: k.scheme,\r\n Hostname: host,\r\n Port: strconv.Itoa(port),\r\n Transport: k.transport,\r\n InsecureSkipTLSVerifyTransport: k.insecureSkipTLSVerifyTransport,\r\n }, nil\r\n}\n"})}),"\n",(0,s.jsxs)(r.p,{children:[(0,s.jsx)(r.code,{children:"GetConnectionInfo"})," \u901a\u8fc7\u8282\u70b9\u540d\u79f0\u83b7\u53d6\u8282\u70b9\u4fe1\u606f\uff0c\u7136\u540e\u4f7f\u7528 ",(0,s.jsx)(r.code,{children:"GetPreferredNodeAddress"})," \u9009\u62e9\u4e00\u4e2a\u5408\u9002\u7684\u4e3b\u673a\uff0c\u901a\u8fc7 ",(0,s.jsx)(r.code,{children:"streamLocation"})," \u5904\u7406\u540e\uff0c\u62fc\u63a5\u4e00\u4e2a exec \u8bf7\u6c42 URL\u3002\r\napiserver \u5c06\u77e5\u9053\u5e94\u5c06 exec \u8bf7\u6c42\u8f6c\u53d1\u5230\u54ea\u4e2a\u8282\u70b9\u3002\r\n\u8fd0\u884c\u5728\u8282\u70b9\u4e0a\u7684 kubelet \u670d\u52a1\u5c06\u6355\u83b7 exec \u8bf7\u6c42\uff0c\u7136\u540e\u4e0e pod \u5efa\u7acb\u94fe\u63a5\u3002"]}),"\n",(0,s.jsx)(r.p,{children:"\u4ee5\u4e0a\u7b80\u8981\u4ecb\u7ecd\u4e86\u5efa\u7acb kubectl exec \u7684\u8fc7\u7a0b\u3002"}),"\n",(0,s.jsx)(r.h3,{id:"\u5728-kosmos-\u4e2d\u7684\u5b9e\u73b0",children:"\u5728 Kosmos \u4e2d\u7684\u5b9e\u73b0"}),"\n",(0,s.jsxs)(r.p,{children:["\u63a5\u4e0b\u6765\uff0c\u8ba9\u6211\u4eec\u770b\u770b\u6574\u4f53\u67b6\u6784\u56fe\u4e2d\u7684 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"root-cluster"})}),"\u3002\r\n\u4e3a\u4e86\u5c06 exec \u8bf7\u6c42\u4f20\u9012\u5230 leaf \u96c6\u7fa4\uff0c\u9700\u8981\u5bf9 exec \u8bf7\u6c42\u8fdb\u884c\u8f6c\u53d1\u3002"]}),"\n",(0,s.jsxs)(r.p,{children:["\u9996\u5148\uff0c\u6211\u4eec\u9700\u8981\u544a\u8bc9 apiserver\uff0ckosmos-node \u7684 IP \u5730\u5740\u662f ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u7684 podIP\uff0c\u8fd9\u5c06\u5bfc\u81f4 apiserver \u5c06 exec \u8bf7\u6c42\u8f6c\u53d1\u5230 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})}),"\u3002\r\n\u5f53\u6211\u4eec\u540c\u6b65 kosmos-node \u7684\u8282\u70b9\u4fe1\u606f\u65f6\uff0c\u6211\u4eec\u4ece\u73af\u5883\u53d8\u91cf ",(0,s.jsx)(r.code,{children:"LEAF_NODE_IP"})," \u4e2d\u8bfb\u53d6\u8be5\u4fe1\u606f\u3002\r\n\u542f\u52a8 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u670d\u52a1\u65f6\u914d\u7f6e\u4e86\u6b64\u73af\u5883\u53d8\u91cf\u3002\r\n\u5173\u952e\u914d\u7f6e\u7247\u6bb5\u5982\u4e0b\uff1a"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:"spec:\r\n serviceAccountName: clustertree\r\n containers:\r\n - name: clustertree-cluster-manager\r\n image: ghcr.io/kosmos-io/clustertree-cluster-manager:__VERSION__\r\n imagePullPolicy: IfNotPresent\r\n env:\r\n - name: APISERVER_CERT_LOCATION\r\n value: /etc/cluster-tree/cert/cert.pem\r\n - name: APISERVER_KEY_LOCATION\r\n value: /etc/cluster-tree/cert/key.pem\r\n - name: LEAF_NODE_IP\r\n valueFrom:\r\n fieldRef:\r\n fieldPath: status.podIP\r\n - name: PREFERRED-ADDRESS-TYPE\r\n value: InternalDNS\n"})}),"\n",(0,s.jsxs)(r.p,{children:["\u7136\u540e\u6211\u4eec\u9700\u8981\u542f\u52a8\u4e00\u4e2a\u7c7b\u4f3c\u4e8e kubelet \u7684\u670d\u52a1\u6765\u76d1\u542c exec\u3002\r\n\u5728 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u670d\u52a1\u4e2d\uff0c\u6211\u4eec\u542f\u52a8\u4e86\u4e00\u4e2a nodeserver \u670d\u52a1\u3002\r\n\u4ee3\u7801\u7247\u6bb5\u5982\u4e0b\uff1a"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:'nodeServer := nodeserver.NodeServer{\r\n RootClient: mgr.GetClient(),\r\n GlobalLeafManager: globalleafManager,\r\n}\r\ngo func() {\r\n if err := nodeServer.Start(ctx, opts); err != nil {\r\n klog.Errorf("failed to start node server: %v", err)\r\n }\r\n}()\n'})}),"\n",(0,s.jsx)(r.p,{children:"\u6b64\u670d\u52a1\u76d1\u89c6 exec \u548c log \u8bf7\u6c42\uff0c\u5e76\u5c06\u76d1\u89c6\u5230\u7684\u8bf7\u6c42\u4ee3\u7406\u8f6c\u53d1\u5230\u76f8\u5e94\u7684 leaf \u96c6\u7fa4\u3002\r\n\u6e90\u4ee3\u7801\u5982\u4e0b\uff1a"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:'func (s *NodeServer) AttachRoutes(m *http.ServeMux) {\r\n r := mux.NewRouter()\r\n r.StrictSlash(true)\r\n \r\n r.HandleFunc(\r\n "/containerLogs/{namespace}/{pod}/{container}",\r\n api.ContainerLogsHandler(s.getClient),\r\n ).Methods("GET")\r\n \r\n r.HandleFunc(\r\n "/exec/{namespace}/{pod}/{container}",\r\n api.ContainerExecHandler(\r\n api.ContainerExecOptions{\r\n StreamIdleTimeout: 30 * time.Second,\r\n StreamCreationTimeout: 30 * time.Second,\r\n },\r\n s.getClient,\r\n ),\r\n ).Methods("POST", "GET")\r\n \r\n r.NotFoundHandler = http.HandlerFunc(api.NotFound)\r\n \r\n m.Handle("/", r)\r\n}\n'})}),"\n",(0,s.jsxs)(r.p,{children:["\u5b8c\u6210\u8f6c\u53d1\u90e8\u5206\u540e\uff0c\u6211\u4eec\u9700\u8981\u8ba9\u6839\u96c6\u7fa4\u4e2d\u7684 API server \u8bc6\u522b kosmos-node \u7684\u901a\u4fe1\u5730\u5740\u4e3a ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u670d\u52a1\u7684\u5730\u5740\u3002\r\n\u56e0\u6b64\uff0c\u5728\u7ef4\u62a4 kosmos-node \u7684\u72b6\u6001\u65f6\uff0c\u6211\u4eec\u5c06 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u7684 podIP \u540c\u6b65\u5230 kosmos-node\u3002\r\n\u5b8c\u6574\u7684\u8fc7\u7a0b\u5982\u4e0b\uff1a"]}),"\n",(0,s.jsxs)(r.ul,{children:["\n",(0,s.jsx)(r.li,{children:"\u7528\u6237\u53d1\u8d77 exec \u8bf7\u6c42\u3002"}),"\n",(0,s.jsx)(r.li,{children:"\u6839\u96c6\u7fa4\u4e2d\u7684 API server \u63a5\u6536\u5230 exec \u8bf7\u6c42\uff0c\u5e76\u6839\u636e pod \u4fe1\u606f\u67e5\u8be2\u8282\u70b9\u4fe1\u606f\u3002"}),"\n",(0,s.jsxs)(r.li,{children:["\u67e5\u8be2\u5230\u7684\u8282\u70b9\u4e3b\u673a\u662f ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u7684 podIP\u3002"]}),"\n",(0,s.jsxs)(r.li,{children:["\u6839\u96c6\u7fa4\u4e2d\u7684 API server \u4e0e ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u5efa\u7acb exec \u8fde\u63a5\u3002"]}),"\n",(0,s.jsxs)(r.li,{children:[(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u63a5\u6536\u5230 exec \u8fde\u63a5\u8bf7\u6c42\uff0c\u67e5\u8be2 pod \u4fe1\u606f\uff0c\u5e76\u5c06 exec \u8bf7\u6c42\u4ee3\u7406\u5230 leaf \u96c6\u7fa4\u3002\r\n\u901a\u8fc7\u8fd9\u4e2a\u8fc7\u7a0b\uff0cKosmos \u5b9e\u73b0\u4e86 exec \u529f\u80fd\uff0clog \u529f\u80fd\u7684\u5de5\u4f5c\u65b9\u5f0f\u4e5f\u662f\u76f8\u540c\u7684\u3002"]}),"\n"]}),"\n",(0,s.jsx)(r.h3,{id:"\u5b9a\u5236\u5316",children:"\u5b9a\u5236\u5316"}),"\n",(0,s.jsxs)(r.p,{children:["\u5728\u4e0e es \u4ea7\u54c1\u5bf9\u63a5\u65f6\uff0c\u6709\u4e00\u4e2a\u5b9a\u5236\u5316\u9700\u6c42\u3002\r\n\u4e0a\u8ff0\u8bbe\u8ba1\u5c06\u5bfc\u81f4\u6240\u6709 kosmos-node \u7684 IP \u90fd\u662f ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u7684 podIP\u3002\r\n\u5728 es \u7684\u4ea7\u54c1\u8bbe\u8ba1\u4e2d\uff0cnodeIP \u7528\u4f5c\u4e3b\u952e\uff0c\u8fd9\u4f1a\u5bfc\u81f4\u4ea7\u54c1\u65e0\u6cd5\u5b58\u50a8\u5230\u4ed3\u5e93\u4e2d\u3002\u4e3a\u6b64\uff0ckosmos \u8fdb\u884c\u4e86\u7279\u6b8a\u8bbe\u8ba1\u3002\r\n\u5728\u901a\u8fc7 kubectl get node -owide \u83b7\u53d6\u7684\u8282\u70b9\u4fe1\u606f\u4e2d\uff0cip \u5730\u5740\u5c5e\u4e8e InternalIP \u7c7b\u578b\u3002"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",children:"sudo kubectl get nodes -owide\r\nNAME STATUS ROLES AGE VERSION INTERNAL-IP\r\n\r\n EXTERNAL-IP OS-IMAGE KERNEL-VERSION CONTAINER-RUNTIME\r\nkosmos-control-1 Ready control-plane,master,node 65d v1.21.5 192.xx.xx.1 BigCloud Enterprise Linux For Euler 21.10 LTS 4.19.90-2107.6.0.0192.8.oe1.bclinux.x86_64 containerd://1.5.7\r\nkosmos-control-2 Ready node 65d v1.21.5 192.xx.xx.2 BigCloud Enterprise Linux For Euler 21.10 LTS 4.19.90-2107.6.0.0192.8.oe1.bclinux.x86_64 containerd://1.5.7\r\nkosmos-cluster1 Ready agent 20d v1.21.5 192.xx.xx.3 \n"})}),"\n",(0,s.jsxs)(r.p,{children:["\u5728\u67e5\u8be2\u8282\u70b9\u4e3b\u673a\u65f6\uff0c\u4e0a\u6587\u63d0\u5230\u7684 GetPreferredNodeAddress \u51fd\u6570\u5c06\u6839\u636e\u4f18\u5148\u7ea7\u4ece Address \u5217\u8868\u4e2d\u9009\u62e9\u4e00\u4e2a\uff0c\u56e0\u6b64\u5728 es \u4e2d\uff0c\u6211\u4eec\u5c06 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u7684 podIP \u8bbe\u7f6e\u4e3a\u6bd4 InternalIP \u7c7b\u522b\u5730\u5740\u66f4\u9ad8\u7684\u4f18\u5148\u7ea7\uff0c\u5982\u4e0b\u6240\u793a\uff0c\u53ef\u4ee5\u6307\u5b9a ip \u7684\u7c7b\u578b\u548c\u503c\u3002"]}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:'func GetAddress(ctx context.Context, rootClient kubernetes.Interface, originAddress []corev1.NodeAddress) ([]corev1.NodeAddress, error) {\r\n preferredAddressType := corev1.NodeAddressType(os.Getenv("PREFERRED-ADDRESS-TYPE"))\r\n \r\n if len(preferredAddressType) == 0 {\r\n preferredAddressType = corev1.NodeInternalDNS\r\n }\r\n \r\n prefixAddress := []corev1.NodeAddress{\r\n {Type: preferredAddressType, Address: os.Getenv("LEAF_NODE_IP")},\r\n }\r\n \r\n address, err := SortAddress(ctx, rootClient, originAddress)\r\n \r\n if err != nil {\r\n return nil, err\r\n }\r\n \r\n return append(prefixAddress, address...), nil\r\n}\n'})}),"\n",(0,s.jsx)(r.p,{children:"\u5982\u4f55\u67e5\u770b\u5730\u5740\u4f18\u5148\u7ea7\uff1f\u901a\u8fc7\u67e5\u770b api-server \u7684\u542f\u52a8\u53c2\u6570 - kubelet-preferred-address-types\uff0c\u6b64\u5904\u8bbe\u7f6e\u4e86 GetPreferredNodeAddress \u51fd\u6570\u4ee5\u83b7\u53d6\u4e3b\u673a\u7684\u4f18\u5148\u7ea7\u3002\r\n\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cInternalDNS \u5177\u6709\u6700\u9ad8\u4f18\u5148\u7ea7\u3002"}),"\n",(0,s.jsx)(r.pre,{children:(0,s.jsx)(r.code,{className:"language-shell",metastring:"script",children:"- --kubelet-preferred-address-types=InternalDNS,InternalIP,Hostname,ExternaLDNS,ExternalIP\n"})}),"\n",(0,s.jsx)(r.h3,{id:"\u7ed3\u8bba",children:"\u7ed3\u8bba"}),"\n",(0,s.jsxs)(r.p,{children:["\u5728 Kosmos \u4e2d\uff0c",(0,s.jsx)(r.code,{children:"kubectl exec"})," \u548c ",(0,s.jsx)(r.code,{children:"kubectl log"})," \u90fd\u901a\u8fc7 API server \u88ab\u201c\u6b3a\u9a97\u201d\u5e76\u91cd\u5b9a\u5411\u5230\u6211\u4eec\u81ea\u5df1\u7684 ",(0,s.jsx)(r.em,{children:(0,s.jsx)(r.strong,{children:"clustertree-cluster-manager"})})," \u670d\u52a1\u3002\r\n\u8fd9\u4f7f\u5f97\u6211\u4eec\u53ef\u4ee5\u5728\u540e\u7eed\u6b65\u9aa4\u4e2d\u5b9e\u73b0\u5b9a\u5236\u5316\u529f\u80fd\u3002"]})]})}function x(e={}){const{wrapper:r}={...(0,o.M)(),...e.components};return r?(0,s.jsx)(r,{...e,children:(0,s.jsx)(a,{...e})}):a(e)}},4780:(e,r,n)=>{n.d(r,{c:()=>s});const s=n.p+"assets/images/EXEC_Log_Arch-55169f06d1b0071b36b0ddb300a3e3fd.png"},2172:(e,r,n)=>{n.d(r,{I:()=>d,M:()=>c});var s=n(1504);const o={},t=s.createContext(o);function c(e){const r=s.useContext(t);return s.useMemo((function(){return"function"==typeof e?e(r):{...r,...e}}),[r,e])}function d(e){let r;return r=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:c(e.components),s.createElement(t.Provider,{value:r},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/e723d4d1.340863ed.js b/docs/assets/js/e723d4d1.340863ed.js deleted file mode 100644 index 21edd0e..0000000 --- a/docs/assets/js/e723d4d1.340863ed.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[980],{7384:(n,e,r)=>{r.r(e),r.d(e,{assets:()=>i,contentTitle:()=>l,default:()=>u,frontMatter:()=>o,metadata:()=>c,toc:()=>a});var s=r(7624),t=r(2172);const o={id:"mcn-connectivity_zh",title:"\u591a\u96c6\u7fa4\u7f51\u7edc\u8054\u901a"},l="\u591a\u96c6\u7fa4\u7f51\u7edc\u8054\u901a",c={id:"i18n/zh/v0.2.0/mcn-connectivity_zh",title:"\u591a\u96c6\u7fa4\u7f51\u7edc\u8054\u901a",description:"Kosmos \u591a\u96c6\u7fa4\u89e3\u51b3\u65b9\u6848\u7684 Clusterlink \u8bbe\u8ba1\u65e8\u5728\u4e92\u8fde\u591a\u4e2a Kubernetes \u96c6\u7fa4\u7684\u8282\u70b9\u548c\u8d44\u6e90\uff0c\u5f62\u6210\u7edf\u4e00\u7684\u8d44\u6e90\u6c60\u3002",source:"@site/docs/i18n/zh/v0.2.0/multi-cluster-network_zh.md",sourceDirName:"i18n/zh/v0.2.0",slug:"/i18n/zh/v0.2.0/mcn-connectivity_zh",permalink:"/website/i18n/zh/v0.2.0/mcn-connectivity_zh",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/i18n/zh/v0.2.0/multi-cluster-network_zh.md",tags:[],version:"current",frontMatter:{id:"mcn-connectivity_zh",title:"\u591a\u96c6\u7fa4\u7f51\u7edc\u8054\u901a"}},i={},a=[{value:"\u591a\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u89e3\u51b3\u65b9\u6848",id:"\u591a\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u89e3\u51b3\u65b9\u6848",level:2},{value:"\u4ecb\u7ecd",id:"\u4ecb\u7ecd",level:3},{value:"\u8bbe\u8ba1",id:"\u8bbe\u8ba1",level:3},{value:"\u5148\u51b3\u6761\u4ef6",id:"\u5148\u51b3\u6761\u4ef6",level:3},{value:"\u5b89\u88c5 Kosmos",id:"\u5b89\u88c5-kosmos",level:4},{value:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4",id:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4",level:4},{value:"\u8de8\u96c6\u7fa4 L3 \u7f51\u7edc\u8fde\u63a5\u6027",id:"\u8de8\u96c6\u7fa4-l3-\u7f51\u7edc\u8fde\u63a5\u6027",level:3},{value:"Gateway \u6a21\u5f0f",id:"gateway-\u6a21\u5f0f",level:4},{value:"P2P \u6a21\u5f0f",id:"p2p-\u6a21\u5f0f",level:4},{value:"\u542f\u52a8 ClusterLink",id:"\u542f\u52a8-clusterlink",level:3},{value:"\u4f7f\u7528 P2P \u6a21\u5f0f",id:"\u4f7f\u7528-p2p-\u6a21\u5f0f",level:4},{value:"\u521b\u5efa\u6d4b\u8bd5 Pods",id:"\u521b\u5efa\u6d4b\u8bd5-pods",level:4},{value:"\u4e00\u952e\u8bca\u65ad\u96c6\u7fa4\u8fde\u63a5",id:"\u4e00\u952e\u8bca\u65ad\u96c6\u7fa4\u8fde\u63a5",level:3}];function d(n){const e={a:"a",admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",p:"p",pre:"pre",...(0,t.M)(),...n.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(e.h1,{id:"\u591a\u96c6\u7fa4\u7f51\u7edc\u8054\u901a",children:"\u591a\u96c6\u7fa4\u7f51\u7edc\u8054\u901a"}),"\n",(0,s.jsx)(e.p,{children:"Kosmos \u591a\u96c6\u7fa4\u89e3\u51b3\u65b9\u6848\u7684 Clusterlink \u8bbe\u8ba1\u65e8\u5728\u4e92\u8fde\u591a\u4e2a Kubernetes \u96c6\u7fa4\u7684\u8282\u70b9\u548c\u8d44\u6e90\uff0c\u5f62\u6210\u7edf\u4e00\u7684\u8d44\u6e90\u6c60\u3002\r\n\u5b9e\u73b0\u8fd9\u4e00\u76ee\u6807\u7684\u57fa\u7840\u4e4b\u4e00\u662f\u6784\u5efa\u591a\u96c6\u7fa4\u7f51\u7edc\u67b6\u6784\uff0c\u4ee5\u6ee1\u8db3\u4e0d\u540c\u96c6\u7fa4\u4e4b\u95f4\u7684\u901a\u4fe1\u9700\u6c42\u3002"}),"\n",(0,s.jsx)(e.h2,{id:"\u591a\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u89e3\u51b3\u65b9\u6848",children:"\u591a\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u89e3\u51b3\u65b9\u6848"}),"\n",(0,s.jsx)(e.h3,{id:"\u4ecb\u7ecd",children:"\u4ecb\u7ecd"}),"\n",(0,s.jsx)(e.p,{children:"Clusterlink \u5305\u542b\u4e24\u79cd\u7f51\u7edc\u6a21\u5f0f\uff1aGateway \u548c P2P\u3002\r\n\u5728 Gateway \u6a21\u5f0f\u4e0b\uff0c\u5f53 Pod \u53d1\u9001\u6570\u636e\u5305\u65f6\uff0c\u9996\u5148\u901a\u8fc7\u96c6\u7fa4\u5185\u7684 vx-local \u96a7\u9053\u5230\u8fbe\u8be5\u96c6\u7fa4\u7684 Gateway \u8282\u70b9\uff0c\u7136\u540e\u7a7f\u8fc7\u8de8\u96c6\u7fa4\u96a7\u9053\u5230\u8fbe\u5bf9\u7aef\u96c6\u7fa4\u3002\r\n\u4e00\u65e6\u6570\u636e\u5305\u5230\u8fbe\u5bf9\u7aef\u96c6\u7fa4\uff0c\u7531 CNI \u5904\u7406\u5e76\u901a\u8fc7\u5355\u96c6\u7fa4\u7f51\u7edc\u5230\u8fbe\u76ee\u6807 Pod\u3002\r\n\u8fd9\u79cd\u6a21\u5f0f\u7684\u4f18\u70b9\u662f\u6bcf\u4e2a\u96c6\u7fa4\u53ea\u9700\u8981\u4e00\u4e2a\u8282\u70b9\uff08\u6216\u4e24\u4e2a\u7528\u4e8e\u9ad8\u53ef\u7528\u6027\uff09\u63d0\u4f9b\u5916\u90e8\u8bbf\u95ee\uff0c\u9002\u7528\u4e8e\u591a\u4e91\u548c\u6df7\u5408\u4e91\u573a\u666f\u3002\r\n\u7f3a\u70b9\u662f\u7531\u4e8e\u8f83\u957f\u7684\u7f51\u7edc\u8def\u5f84\uff0c\u5b58\u5728\u4e00\u5b9a\u7684\u6027\u80fd\u635f\u5931\u3002\u4e3a\u4e86\u5e94\u5bf9\u8fd9\u4e00\u95ee\u9898\uff0cClusterlink \u63d0\u4f9b\u4e86 P2P \u6a21\u5f0f\uff0c\u9002\u7528\u4e8e\u5bf9\u7f51\u7edc\u6027\u80fd\u8981\u6c42\u8f83\u9ad8\u7684\u573a\u666f\u3002\r\n\u5728\u6b64\u6a21\u5f0f\u4e0b\uff0c\u6570\u636e\u5305\u76f4\u63a5\u53d1\u9001\u5230\u76ee\u6807 Pod \u6240\u5728\u7684\u8282\u70b9\u3002\r\n\u6b64\u5916\uff0cP2P \u548c Gateway \u6a21\u5f0f\u53ef\u4ee5\u7ec4\u5408\u4f7f\u7528\u3002"}),"\n",(0,s.jsx)(e.h3,{id:"\u8bbe\u8ba1",children:"\u8bbe\u8ba1"}),"\n",(0,s.jsx)(e.p,{children:"Kosmos \u591a\u96c6\u7fa4\u7f51\u7edc Gateway \u89e3\u51b3\u65b9\u6848\u7684\u67b6\u6784\u5982\u4e0b\uff1a"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"MCN GW_Architecture.png",src:r(1728).c+"",width:"1019",height:"287"})}),"\n",(0,s.jsx)(e.admonition,{title:"\u6ce8\u610f",type:"info",children:(0,s.jsx)(e.p,{children:"\u63d0\u4f9b\u4e86\u5f88\u5f3a\u7684\u517c\u5bb9\u6027\uff0c\u6bcf\u4e2a\u96c6\u7fa4\u53ea\u9700\u8981\u4e00\u4e2a\u8282\u70b9\uff08\u6216\u4e24\u4e2a\u7528\u4e8e\u9ad8\u53ef\u7528\u6027\uff09\u63d0\u4f9b\u5916\u90e8\u8bbf\u95ee\uff0c\u9002\u7528\u4e8e\u8de8\u4e91\u573a\u666f\u3002"})}),"\n",(0,s.jsx)(e.p,{children:"Kosmos \u591a\u96c6\u7fa4\u7f51\u7edc P2P \u89e3\u51b3\u65b9\u6848\u7684\u67b6\u6784\u5982\u4e0b\uff1a"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"MCN P2P_Architecture.png",src:r(9296).c+"",width:"1019",height:"310"})}),"\n",(0,s.jsx)(e.admonition,{title:"\u6ce8\u610f",type:"info",children:(0,s.jsx)(e.p,{children:"\u5177\u6709\u8f83\u77ed\u7684\u7f51\u7edc\u8def\u5f84\u548c\u66f4\u597d\u7684\u6027\u80fd\uff0c\u9002\u7528\u4e8e\u5b8c\u5168\u4e92\u8054\u7684 Underlay \u573a\u666f\u3002"})}),"\n",(0,s.jsx)(e.h3,{id:"\u5148\u51b3\u6761\u4ef6",children:"\u5148\u51b3\u6761\u4ef6"}),"\n",(0,s.jsx)(e.h4,{id:"\u5b89\u88c5-kosmos",children:"\u5b89\u88c5 Kosmos"}),"\n",(0,s.jsxs)(e.p,{children:["\u53c2\u8003 Kosmos \u5feb\u901f\u5165\u95e8\u6587\u6863 ",(0,s.jsx)(e.a,{href:"https://github.com/kosmos-io/kosmos",children:"https://github.com/kosmos-io/kosmos"})," \u5e76\u542f\u7528 ClusterLink \u6a21\u5757\u4ee5\u8fdb\u884c\u591a\u96c6\u7fa4\u7f51\u7edc\u914d\u7f6e\u3002\r\n\u4f7f\u7528 kosmosctl \u5de5\u5177\uff1a"]}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",metastring:"script",children:"kosmosctl install --cni calico --default-nic eth0 // \u6211\u4eec\u6839\u636e\u53c2\u6570 default-nic \u4f20\u9012\u7684\u7f51\u7edc\u63a5\u53e3\u503c\u5efa\u7acb\u7f51\u7edc\u96a7\u9053\n"})}),"\n",(0,s.jsx)(e.h4,{id:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4",children:"\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",metastring:"script",children:"kosmosctl join cluster --name cluster1 --kubeconfig ~/kubeconfig/cluster1-kubeconfig --cni calico --default-nic eth0 --enable-link\n"})}),"\n",(0,s.jsx)(e.h3,{id:"\u8de8\u96c6\u7fa4-l3-\u7f51\u7edc\u8fde\u63a5\u6027",children:"\u8de8\u96c6\u7fa4 L3 \u7f51\u7edc\u8fde\u63a5\u6027"}),"\n",(0,s.jsx)(e.p,{children:"\u4e3a\u4e86\u5b9e\u73b0 Kosmos \u4e2d\u7684\u8de8\u96c6\u7fa4 L3 \u7f51\u7edc\u8fde\u63a5\u6027\uff0c\u9700\u8981\u81f3\u5c11\u4e24\u4e2a\u4e0d\u540c\u96c6\u7fa4\u7684\u8282\u70b9\u5728\u4e3b\u673a\u7f51\u7edc\u5c42\u80fd\u591f\u76f8\u4e92\u901a\u4fe1\uff0c\u5e76\u4e14\u96c6\u7fa4\u5fc5\u987b\u6b63\u786e\u90e8\u7f72\u5e76\u652f\u6301 VXLAN \u6216 IPSec \u6280\u672f\u3002"}),"\n",(0,s.jsx)(e.h4,{id:"gateway-\u6a21\u5f0f",children:"Gateway \u6a21\u5f0f"}),"\n",(0,s.jsx)(e.p,{children:"\u5728 Kosmos \u8054\u90a6\u4e2d\u7684\u6bcf\u4e2a Kubernetes \u96c6\u7fa4\u4e2d\uff0c\u4f7f\u7528 Elector \u6a21\u5757\u9009\u4e3e\u4e00\u4e2a\u8282\u70b9\u4f5c\u4e3a Gateway\uff08GW\uff09\u8282\u70b9\u3002\r\n\u4e24\u4e2a\u96c6\u7fa4\u7684 GW \u8282\u70b9\u901a\u8fc7 vx-bridge \u96a7\u9053\uff08\u7531 Kosmos \u521b\u5efa\uff09\u8fdb\u884c\u901a\u4fe1\u4ee5\u5efa\u7acb\u8fde\u63a5\u3002\r\n\u5728\u6bcf\u4e2a\u96c6\u7fa4\u5185\uff0c\u8def\u7531\u7531 GW \u8282\u70b9\u5904\u7406\u3002\r\n\u76f8\u6bd4 P2P \u6a21\u5f0f\uff0cGW \u6a21\u5f0f\u7531\u4e8e GW \u8282\u70b9\u7684\u989d\u5916\u6570\u636e\u5305\u5c01\u88c5\u548c\u89e3\u5c01\u88c5\uff0c\u7f51\u7edc\u6027\u80fd\u7565\u4f4e\u3002\r\n\u7136\u800c\uff0c\u5176\u4f18\u52bf\u5728\u4e8e\u96c6\u7fa4\u8282\u70b9\u7684\u8def\u7531\u8868\u548c FDB \u8868\u51e0\u4e4e\u53ef\u4ee5\u4fdd\u6301\u4e0d\u53d8\u3002\r\n\u56e0\u6b64\uff0cGW \u6a21\u5f0f\u9002\u7528\u4e8e\u5bf9\u7f51\u7edc\u6027\u80fd\u8981\u6c42\u4e0d\u9ad8\u7684\u66f4\u5927\u89c4\u6a21\u591a\u96c6\u7fa4\u573a\u666f\u3002"}),"\n",(0,s.jsx)(e.h4,{id:"p2p-\u6a21\u5f0f",children:"P2P \u6a21\u5f0f"}),"\n",(0,s.jsx)(e.p,{children:"\u5728 P2P \u6a21\u5f0f\u4e0b\uff0c\u4e0d\u9700\u8981\u4f7f\u7528 Elector \u6a21\u5757\u3002\r\nKosmos \u5728\u6bcf\u4e2a\u96c6\u7fa4\u7684\u6240\u6709\u8282\u70b9\u4e0a\u521b\u5efa vx-bridge \u63a5\u53e3\uff0c\u5b9e\u73b0\u4e0d\u540c\u96c6\u7fa4\u8282\u70b9\u4e4b\u95f4\u7684\u76f4\u63a5\u5bb9\u5668\u7f51\u7edc\u901a\u4fe1\u3002\r\n\u6b64\u6a21\u5f0f\u4e0b\u7684\u7f51\u7edc\u6027\u80fd\u51e0\u4e4e\u4e0e\u5355\u4e2a Kubernetes \u96c6\u7fa4\u76f8\u540c\u3002\r\n\u7136\u800c\uff0c\u5728 P2P \u6a21\u5f0f\u4e0b\uff0c\u6bcf\u4e2a\u96c6\u7fa4\u7684\u6bcf\u4e2a\u8282\u70b9\u9700\u8981\u4e3a Kosmos \u8054\u90a6\u4e2d\u7684\u6240\u6709\u8282\u70b9\u914d\u7f6e\u8bbf\u95ee\u89c4\u5219\uff0c\u5bfc\u81f4\u8f83\u5927\u7684\u8def\u7531\u548c FDB \u8868\u5927\u5c0f\u3002\r\n\u56e0\u6b64\uff0cP2P \u6a21\u5f0f\u9002\u7528\u4e8e\u5bf9\u7f51\u7edc\u6027\u80fd\u8981\u6c42\u8f83\u9ad8\u4f46\u6bcf\u4e2a\u96c6\u7fa4\u8282\u70b9\u6570\u91cf\u8f83\u5c11\u7684\u573a\u666f\u3002"}),"\n",(0,s.jsx)(e.h3,{id:"\u542f\u52a8-clusterlink",children:"\u542f\u52a8 ClusterLink"}),"\n",(0,s.jsx)(e.h4,{id:"\u4f7f\u7528-p2p-\u6a21\u5f0f",children:"\u4f7f\u7528 P2P \u6a21\u5f0f"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",metastring:"script",children:'# \u5b8c\u6210\u201c\u5b89\u88c5 Kosmos\u201d\u548c\u201c\u52a0\u5165\u53f6\u5b50\u96c6\u7fa4\u201d\u90e8\u5206\u7684\u6b65\u9aa4\r\n# \u68c0\u67e5\u96c6\u7fa4\u8d44\u6e90\u662f\u5426\u6b63\u786e\u521b\u5efa\r\n[root@kosmos-control-cluster yaml]# kubectl --kubeconfig config-14 get clusters.kosmos.io\r\nNAME NETWORK_TYPE IP_FAMILY\r\ncluster38 p2p all\r\nkosmos-control-cluster p2p all\r\n\r\n# \u68c0\u67e5 clusternodes \u8d44\u6e90\u662f\u5426\u6b63\u786e\u521b\u5efa\r\n[root@kosmos-control-cluster yaml]# kubectl get clusternodes.kosmos.io\r\nNAME ROLES INTERFACE IP\r\ncluster38-001 bond0.1820 10.*.*.38\r\ncluster38-002 bond0.1820 10.*.*.39\r\ncluster38-003 bond0.1830 10.*.*.94\r\ncluster38-004 ["gateway"] bond0.1830 10.*.*.95\r\nkosmos-control-cluster-001 bond0.1820 10.*.*.14\r\nkosmos-control-cluster-002 bond0.1820 10.*.*.15\r\nkosmos-control-cluster-003 ["gateway"] bond0.1565 10.*.*.38\r\nkosmos-control-cluster-004 bond0.1565 10.*.*.31\r\nkosmos-control-cluster-005 bond0.1565 10.*.*.32\r\nkosmos-control-cluster-006 bond0.1565 10.*.*.33\r\nkosmos-control-cluster-007 bond0.1565 10.*.*.37\r\n\r\n# \u68c0\u67e5 nodeconfigs \u8d44\u6e90\u662f\u5426\u6b63\u786e\u521b\u5efa\r\n[root@kosmos-control-cluster yaml]# kubectl get nodeconfigs.kosmos.io\r\nNAME AGE\r\ncluster38-001 14d\r\ncluster38-002 14d\r\ncluster38-003 14d\r\ncluster38-004 14d\r\nkosmos-control-cluster-001 48d\r\nkosmos-control-cluster-002 48d\r\nkosmos-control-cluster-003 49d\r\nkosmos-control-cluster-004 49d\r\nkosmos-control-cluster-005 45d\r\nkosmos-control-cluster-006 45d\r\nkosmos-control-cluster-007 45d\n'})}),"\n",(0,s.jsx)(e.h4,{id:"\u521b\u5efa\u6d4b\u8bd5-pods",children:"\u521b\u5efa\u6d4b\u8bd5 Pods"}),"\n",(0,s.jsx)(e.p,{children:"\u901a\u8fc7\u5728 kosmos-control-cluster \u548c cluster38 \u96c6\u7fa4\u4e2d\u521b\u5efa Pod \u9a8c\u8bc1\u8de8\u96c6\u7fa4\u5bb9\u5668\u7f51\u7edc\u8fde\u63a5\u6027\u3002\r\n\u4e3a\u4e86\u786e\u4fdd\u5bb9\u5668\u5177\u6709\u5e38\u89c1\u7684\u7f51\u7edc\u5de5\u5177\uff08\u5982 Ping \u548c Curl\uff09\uff0c\u4f7f\u7528 clusterlink-floater \u955c\u50cf\u3002\r\n\u4ee5\u4e0b\u662f\u521b\u5efa Pods \u7684\u793a\u4f8b YAML\uff1a"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-yaml",children:'---\r\napiVersion: v1\r\nkind: ServiceAccount\r\nmetadata:\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\n---\r\napiVersion: rbac.authorization.k8s.io/v1\r\nkind: ClusterRole\r\nmetadata:\r\n name: clusterlink-floater\r\nrules:\r\n - apiGroups: [\'*\']\r\n resources: [\'*\']\r\n verbs: ["*"]\r\n - nonResourceURLs: [\'*\']\r\n verbs: ["get"]\r\n---\r\napiVersion: rbac.authorization.k8s.io/v1\r\nkind: ClusterRoleBinding\r\nmetadata:\r\n name: clusterlink-floater\r\nroleRef:\r\n apiGroup: rbac.authorization.k8s.io\r\n kind: ClusterRole\r\n name: clusterlink-floater\r\nsubjects:\r\n - kind: ServiceAccount\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\n---\r\napiVersion: apps/v1\r\nkind: Deployment\r\nmetadata:\r\n name: clusterlink-floater\r\n namespace: kosmos-system\r\nspec:\r\n replicas: 1\r\n selector:\r\n matchLabels:\r\n app: clusterlink-floater\r\n template:\r\n metadata:\r\n labels:\r\n app: clusterlink-floater\r\n spec:\r\n hostNetwork: false\r\n serviceAccountName: clusterlink-floater\r\n containers:\r\n - name: floater\r\n image: ghcr.io/kosmos-io/clusterlink-floater:v0.2.0-lts\r\n imagePullPolicy: IfNotPresent\r\n command:\r\n - clusterlink-floater\r\n securityContext:\r\n privileged: true\r\n env:\r\n - name: "PORT"\r\n value: "8889"\r\n - name: "ENABLE_ANALYSIS"\r\n value: "false"\r\n affinity:\r\n nodeAffinity:\r\n requiredDuringSchedulingIgnoredDuringExecution:\r\n nodeSelectorTerms:\r\n - matchExpressions:\r\n - key: kosmos.io/exclude\r\n operator: DoesNotExist\r\n tolerations:\r\n - effect: NoSchedule\r\n operator: Exists\r\n - key: CriticalAddonsOnly\r\n operator: Exists\r\n - effect: NoExecute\r\n operator: Exists\n'})}),"\n",(0,s.jsx)(e.admonition,{title:"NOTE",type:"info",children:(0,s.jsx)(e.p,{children:"\u672c\u8282\u63d0\u4f9b\u7684\u6d4b\u8bd5\u7528\u4f8b\u53ea\u80fd\u68c0\u67e5\u4e24\u4e2a\u96c6\u7fa4\u4e2d\u8282\u70b9\u4e4b\u95f4\u7684\u5bb9\u5668\u7f51\u7edc\u8fde\u63a5\u6027\u3002\r\n\u8981\u5feb\u901f\u6d4b\u8bd5\u96c6\u7fa4\u4e2d\u7684\u6240\u6709\u8282\u70b9\uff0c\u8bf7\u53c2\u9605\u7b2c 5 \u8282\u3002"})}),"\n",(0,s.jsx)(e.p,{children:"\u786e\u4fdd Pods \u5728 kosmos-control-cluster \u548c cluster38 \u96c6\u7fa4\u4e2d\u6210\u529f\u8fd0\u884c\uff1a"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",metastring:"script",children:"[root@kosmos-control-cluster yaml]# kubectl -n kosmos-system get pod\r\nNAME READY STATUS RESTARTS AGE\r\nclusterlink-agent-6qq4v 1/1 Running 0 15d\r\nclusterlink-agent-6v9jm 1/1 Running 0 15d\r\nclusterlink-agent-7zpf5 1/1 Running 0 15d\r\nclusterlink-agent-84d68 1/1 Running 0 15d\r\nclusterlink-agent-dj9q2 1/1 Running 0 26h\r\nclusterlink-agent-r2zj4 1/1 Running 0 15d\r\nclusterlink-agent-vlh2x 1/1 Running 0 3d3h\r\nclusterlink-controller-manager-6774ddd58b-bcn7s 1/1 Running 0 15d\r\nclusterlink-elector-6b597b44f7-jrbg6 1/1 Running 0 15d\r\nclusterlink-elector-6b597b44f7-mj882 1/1 Running 0 15d\r\nclusterlink-floater-7dcb47579-lddgc 1/1 Running 0 77s\r\nclusterlink-network-manager-6489597986-h74m4 1/1 Running 0 15d\r\nclustertree-cluster-manager-6778bd7b6c-mwhpj 1/1 Running 0 5h45m\r\nkosmos-operator-c88898f66-b8mjl 1/1 Running 0 15d\r\nkosmos-scheduler-7dcfd94bf7-2km8m 1/1 Running 0 8d\r\n\r\n[root@cluster38 yaml]# kubectl -n kosmos-system get pod\r\nNAME READY STATUS RESTARTS AGE\r\nclusterlink-agent-jsv2b 1/1 Running 0 14d\r\nclusterlink-agent-qncxt 1/1 Running 0 14d\r\nclusterlink-agent-rzngm 1/1 Running 0 14d\r\nclusterlink-agent-s252r 1/1 Running 0 14d\r\nclusterlink-controller-manager-77fbbd9f78-bz47t 1/1 Running 0 14d\r\nclusterlink-elector-86b49775b5-x4gsp 1/1 Running 0 14d\r\nclusterlink-elector-86b49775b5-z4lb5 1/1 Running 0 14d\r\nclusterlink-floater-7dcb47579-jx85c 1/1 Running 0 16s\n"})}),"\n",(0,s.jsx)(e.p,{children:"\u83b7\u53d6\u4e24\u4e2a Pod \u7684 IP \u5730\u5740\uff0c\u5e76\u8fdb\u5165\u5176\u4e2d\u4e00\u4e2a Pod \u7684\u5bb9\u5668\u6267\u884c Ping \u547d\u4ee4\uff0c\u4ee5\u9a8c\u8bc1\u8de8\u96c6\u7fa4\u7684\u5bb9\u5668\u7f51\u7edc\u8fde\u63a5\u3002\u793a\u4f8b\u5982\u4e0b\uff1a"}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",metastring:"script",children:"[root@cluster38 yaml]# kubectl -n kosmos-system get pod clusterlink-floater-7dcb47579-jx85c -oyaml |grep ip\r\n - ip: 10.*.*.253\r\n - ip: fd11:1111:*:*:*:*:4573:f17d\r\n\r\n[root@kosmos-control-cluster yaml]# kubectl -n kosmos-system exec -it clusterlink-floater-7dcb47579-lddgc -- sh\r\n/ # ping 10.*.*.253\r\nPING 10.*.*.253 (10.*.*.253): 56 data bytes\r\n64 bytes from 10.*.*.253: seq=0 ttl=62 time=0.592 ms\r\n64 bytes from 10.*.*.253: seq=1 ttl=62 time=0.362 ms\r\n64 bytes from 10.*.*.253: seq=2 ttl=62 time=0.388 ms\r\n64 bytes from 10.*.*.253: seq=3 ttl=62 time=0.373 ms\r\n^C\r\n--- 10.*.*.253 ping statistics ---\r\n4 packets transmitted, 4 packets received, 0% packet loss\r\nround-trip min/avg/max = 0.362/0.428/0.592 ms\r\n/ # ping -6 fd11:1111:*:*:*:*:4573:f17d\r\nPING fd11:1111:*:*:*:*:4573:f17d (fd11:1111:*:*:*:*:4573:f17d): 56 data bytes\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=0 ttl=62 time=0.679 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=1 ttl=62 time=0.492 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=2 ttl=62 time=0.406 ms\r\n64 bytes from fd11:1111:*:*:*:*:4573:f17d: seq=3 ttl=62 time=1.488 ms\r\n^C\r\n--- fd11:1111:*:*:*:*:4573:f17d ping statistics ---\r\n4 packets transmitted, 4 packets received, 0% packet loss\r\nround-trip min/avg/max = 0.406/0.766/1.488 ms\n"})}),"\n",(0,s.jsx)(e.h3,{id:"\u4e00\u952e\u8bca\u65ad\u96c6\u7fa4\u8fde\u63a5",children:"\u4e00\u952e\u8bca\u65ad\u96c6\u7fa4\u8fde\u63a5"}),"\n",(0,s.jsx)(e.p,{children:"\u96c6\u7fa4\u8fde\u63a5\u8bca\u65ad (Floater) \u529f\u80fd\u65e8\u5728\u89e3\u51b3\u4f7f\u7528 Kosmos \u65f6\u6301\u7eed\u68c0\u67e5\u591a\u4e2a Kubernetes \u96c6\u7fa4\u4e4b\u95f4\u7f51\u7edc\u8fde\u63a5\u7684\u6311\u6218\u3002\u5f53\u96c6\u7fa4\u6570\u91cf\u8f83\u5c11\u65f6\uff0c\u4f8b\u5982\u53ea\u6709\u4e24\u4e2a\u96c6\u7fa4\uff0c\u8fd9\u9879\u4efb\u52a1\u53ef\u80fd\u5e76\u4e0d\u56f0\u96be\u3002\u7136\u800c\uff0c\u5f53\u96c6\u7fa4\u6570\u91cf\u8fbe\u5230 5000 \u6216\u66f4\u591a\u65f6\uff0c\u5373\u4f7f\u662f\u6700\u70ed\u60c5\u7684\u8fd0\u7ef4\u4eba\u5458\u4e5f\u4f1a\u53d1\u73b0\u51e0\u4e4e\u4e0d\u53ef\u80fd\u5b8c\u6210\u8fd9\u9879\u4efb\u52a1\u3002"}),"\n",(0,s.jsx)(e.p,{children:"\u4e3a\u4e86\u89e3\u51b3\u8fd9\u4e2a\u95ee\u9898\uff0c\u6211\u4eec\u8bbe\u8ba1\u4e86 Floater \u529f\u80fd\uff0c\u5b83\u53ef\u4ee5\u5728\u96c6\u7fa4\u4e2d\u7684\u6bcf\u4e2a\u8282\u70b9\u4e0a\u6f02\u6d6e\u3002\u901a\u8fc7 kosmosctl \u5de5\u5177\uff0c\u60a8\u53ef\u4ee5\u4f7f\u7528\u4e00\u4e2a\u547d\u4ee4\u8bca\u65ad\u591a\u4e2a Kubernetes \u96c6\u7fa4\u4e4b\u95f4\u7684\u7f51\u7edc\u8fde\u63a5\u3002\r\nClusterLink Floater \u7684\u67b6\u6784\u5982\u4e0b\uff1a"}),"\n",(0,s.jsx)(e.p,{children:(0,s.jsx)(e.img,{alt:"MCN Floater_Flow.png",src:r(5855).c+"",width:"1261",height:"836"})}),"\n",(0,s.jsx)(e.p,{children:'kosmosctl \u547d\u4ee4\u884c\u5de5\u5177\u63d0\u4f9b\u4e86\u4e00\u952e\u8bca\u65ad\u547d\u4ee4 "dr"\uff0c\u53ef\u4ee5\u8f7b\u677e\u9a8c\u8bc1\u591a\u4e2a Kubernetes \u96c6\u7fa4\u4e4b\u95f4\u7684\u7f51\u7edc\u8fde\u63a5\uff0c\u5305\u62ec\u4f46\u4e0d\u9650\u4e8e\u4e3b\u673a\u7f51\u7edc\u3001\u5bb9\u5668\u7f51\u7edc\u548c\u539f\u751f\u96c6\u7fa4\u7f51\u7edc\u3002\u793a\u4f8b\u5982\u4e0b\uff1a'}),"\n",(0,s.jsx)(e.pre,{children:(0,s.jsx)(e.code,{className:"language-shell",metastring:"script",children:"# \u9a8c\u8bc1\u8de8\u96c6\u7fa4\u7684\u4e3b\u673a\u7f51\u7edc\r\nkosmosctl dr -r ghcr.io/kosmos-io/komos --src-kubeconfig root-config --dst-kubeconfig cluster38-config --host-network\r\n\r\n# \u9a8c\u8bc1\u8de8\u96c6\u7fa4\u7684\u5bb9\u5668\u7f51\u7edc\r\nkosmosctl dr -r ghcr.io/kosmos-io/komos --src-kubeconfig root-config --dst-kubeconfig cluster38-config\n"})})]})}function u(n={}){const{wrapper:e}={...(0,t.M)(),...n.components};return e?(0,s.jsx)(e,{...n,children:(0,s.jsx)(d,{...n})}):d(n)}},5855:(n,e,r)=>{r.d(e,{c:()=>s});const s=r.p+"assets/images/MCN_Floater_Flow-5eacf7d674beab610c33fa93723b0c35.png"},1728:(n,e,r)=>{r.d(e,{c:()=>s});const s=r.p+"assets/images/MCN_GW_Architecture-ad8eb15c31035ee0af215d29bceb17cf.png"},9296:(n,e,r)=>{r.d(e,{c:()=>s});const s=r.p+"assets/images/MCN_P2P_Architecture-9554e1fd1efbac70fe5576731eb95ed3.png"},2172:(n,e,r)=>{r.d(e,{I:()=>c,M:()=>l});var s=r(1504);const t={},o=s.createContext(t);function l(n){const e=s.useContext(o);return s.useMemo((function(){return"function"==typeof n?n(e):{...e,...n}}),[e,n])}function c(n){let e;return e=n.disableParentContext?"function"==typeof n.components?n.components(t):n.components||t:l(n.components),s.createElement(o.Provider,{value:e},n.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/ea929182.4baac7e8.js b/docs/assets/js/ea929182.4baac7e8.js new file mode 100644 index 0000000..680b96c --- /dev/null +++ b/docs/assets/js/ea929182.4baac7e8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[620],{2692:(e,t,o)=>{o.r(t),o.d(t,{assets:()=>a,contentTitle:()=>i,default:()=>h,frontMatter:()=>r,metadata:()=>d,toc:()=>l});var s=o(7624),n=o(2172);const r={id:"node-not-ready",title:"Kosmos Node NotReady"},i="Kosmos Node NotReady",d={id:"v0.2.0/tutorials/node-not-ready",title:"Kosmos Node NotReady",description:"Kosmos Node NotReady Solution",source:"@site/docs/v0.2.0/tutorials/node-not-ready.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/node-not-ready",permalink:"/website/v0.2.0/tutorials/node-not-ready",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/node-not-ready.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1709174921,formattedLastUpdatedAt:"Feb 29, 2024",frontMatter:{id:"node-not-ready",title:"Kosmos Node NotReady"},sidebar:"tutorialSidebar",previous:{title:"Design of EXEC and Log in Kosmos",permalink:"/website/v0.2.0/tutorials/exe-and-log"},next:{title:"IPsec Cross-cluster Network",permalink:"/website/v0.2.0/tutorials/ipsec-network"}},a={},l=[{value:"Kosmos Node NotReady Solution",id:"kosmos-node-notready-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Solution",id:"solution",level:3},{value:"What is an admission webhook?",id:"what-is-an-admission-webhook",level:4},{value:"Kosmos Solution",id:"kosmos-solution",level:4}];function c(e){const t={admonition:"admonition",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",img:"img",p:"p",pre:"pre",...(0,n.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(t.h1,{id:"kosmos-node-notready",children:"Kosmos Node NotReady"}),"\n",(0,s.jsx)(t.h2,{id:"kosmos-node-notready-solution",children:"Kosmos Node NotReady Solution"}),"\n",(0,s.jsx)(t.h3,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsxs)(t.p,{children:["Assuming that we have registered the cluster ",(0,s.jsx)(t.code,{children:"cluster7"})," on the master cluster:"]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-shell",metastring:"script",children:"$ kubectl get node\r\nNAME STATUS ROLES AGE VERSION\r\necs-54004033-001 Ready worker 50d v1.21.5\r\necs-54004033-002 Ready control-plane,master,worker 50d v1.21.5\r\nkosmos-cluster7 Ready agent 5d22h v1.21.5\n"})}),"\n",(0,s.jsxs)(t.p,{children:["The clustertree-cluster-manager of Kosmos will continuously monitor the resource usage and cluster status of the ",(0,s.jsx)(t.code,{children:"cluster7"})," cluster, and update it to the leaf node ",(0,s.jsx)(t.code,{children:"kosmos-cluster7"})," on the master cluster."]}),"\n",(0,s.jsx)(t.pre,{children:(0,s.jsx)(t.code,{className:"language-shell",metastring:"script",children:"$ kubectl get deploy -nkosmos-system\r\nNAME READY UP-TO-DATE AVAILABLE AGE\r\nclusterlink-controller-manager 1/1 1 1 5d22h\r\nclusterlink-elector 2/2 2 2 5d22h\r\nclusterlink-network-manager 1/1 1 1 5d22h\r\nclustertree-cluster-manager 1/1 1 1 5d22h\r\nkosmos-operator 1/1 1 1 5d22h\r\nkosmos-webhook 1/1 1 1 11\n"})}),"\n",(0,s.jsxs)(t.p,{children:["If there is a network fluctuation between the master cluster and the ",(0,s.jsx)(t.code,{children:"cluster7"})," cluster, Kosmos will detect this anomaly and set the status of the leaf node ",(0,s.jsx)(t.code,{children:"kosmos-cluster7"}),' on the master cluster to "not ready". This will trigger the pod eviction behavior in Kubernetes, meaning that the pods on the "not ready" node will be evicted to other ready nodes.']}),"\n",(0,s.jsxs)(t.p,{children:["However, due to network fluctuations, the status of ",(0,s.jsx)(t.code,{children:"kosmos-cluster7"}),' may become "ready" again during the eviction process. But the events of the originally evicted pods will still be sent to the "cluster7" cluster, causing normal running pods on the "cluster7" cluster to be deleted or restarted, thus affecting the business.']}),"\n",(0,s.jsx)(t.h3,{id:"solution",children:"Solution"}),"\n",(0,s.jsx)(t.h4,{id:"what-is-an-admission-webhook",children:"What is an admission webhook?"}),"\n",(0,s.jsx)(t.p,{children:'An "admission webhook" is a piece of code that intercepts requests to the Kubernetes API Server before object persistence. It allows requests to pass through after authentication and authorization. Admission controllers can perform validation, mutation, or both. Mutating controllers modify the resource objects they handle, while Validating controllers do not. If any controller in any phase rejects a request, the entire request will be immediately rejected, and the error will be returned to the end user.'}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"K8s_Admission_Webhook.png",src:o(9140).c+"",width:"2401",height:"721"})}),"\n",(0,s.jsx)(t.h4,{id:"kosmos-solution",children:"Kosmos Solution"}),"\n",(0,s.jsx)(t.p,{children:'We will create a ValidatingAdmissionWebhook controller specifically for the "DELETE Pod" event and when the nodeName is the Kosmos leaf node. When this node becomes "Not Ready," this controller will intercept the request, thereby stopping the pod eviction behavior of the API Server.'}),"\n",(0,s.jsx)(t.p,{children:(0,s.jsx)(t.img,{alt:"Kosmos_Admission_Webhook.png",src:o(6544).c+"",width:"1614",height:"748"})}),"\n",(0,s.jsx)(t.admonition,{title:"Note",type:"info",children:(0,s.jsx)(t.p,{children:"kosmos-webhook will be deployed as a separate controller in the master cluster."})})]})}function h(e={}){const{wrapper:t}={...(0,n.M)(),...e.components};return t?(0,s.jsx)(t,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},9140:(e,t,o)=>{o.d(t,{c:()=>s});const s=o.p+"assets/images/K8s_Admission_Webhook-d80e6ba8089fbf07bf3bf24a5302860a.png"},6544:(e,t,o)=>{o.d(t,{c:()=>s});const s=o.p+"assets/images/Kosmos_Admission_Webhook-6f617f75916da415e7547e6a4d827971.png"},2172:(e,t,o)=>{o.d(t,{I:()=>d,M:()=>i});var s=o(1504);const n={},r=s.createContext(n);function i(e){const t=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function d(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(n):e.components||n:i(e.components),s.createElement(r.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/ea929182.d73b5844.js b/docs/assets/js/ea929182.d73b5844.js deleted file mode 100644 index e3693ba..0000000 --- a/docs/assets/js/ea929182.d73b5844.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[620],{2692:(e,o,n)=>{n.r(o),n.d(o,{assets:()=>l,contentTitle:()=>i,default:()=>u,frontMatter:()=>r,metadata:()=>a,toc:()=>d});var s=n(7624),t=n(2172);const r={id:"node-not-ready",title:"Kosmos Node NotReady"},i="Kosmos Node NotReady",a={id:"v0.2.0/tutorials/node-not-ready",title:"Kosmos Node NotReady",description:"Kosmos Node NotReady Solution",source:"@site/docs/v0.2.0/tutorials/node-not-ready.md",sourceDirName:"v0.2.0/tutorials",slug:"/v0.2.0/tutorials/node-not-ready",permalink:"/website/v0.2.0/tutorials/node-not-ready",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/tutorials/node-not-ready.md",tags:[],version:"current",lastUpdatedBy:"renxiangyu",lastUpdatedAt:1711014110,formattedLastUpdatedAt:"Mar 21, 2024",frontMatter:{id:"node-not-ready",title:"Kosmos Node NotReady"},sidebar:"tutorialSidebar",previous:{title:"Design of EXEC and Log in Kosmos",permalink:"/website/v0.2.0/tutorials/exe-and-log"},next:{title:"IPsec Cross-cluster Network",permalink:"/website/v0.2.0/tutorials/ipsec-network"}},l={},d=[{value:"Kosmos Node NotReady Solution",id:"kosmos-node-notready-solution",level:2},{value:"Introduction",id:"introduction",level:3},{value:"Solution: Integrating Kyverno to solve the kosmos node is not ready",id:"solution-integrating-kyverno-to-solve-the-kosmos-node-is-not-ready",level:3},{value:"What is an admission webhook?",id:"what-is-an-admission-webhook",level:4},{value:"Solution",id:"solution",level:4},{value:"install Kyverno",id:"install-kyverno",level:5},{value:"Configuring clusterpolicy",id:"configuring-clusterpolicy",level:4}];function c(e){const o={a:"a",code:"code",h1:"h1",h2:"h2",h3:"h3",h4:"h4",h5:"h5",img:"img",li:"li",p:"p",pre:"pre",strong:"strong",ul:"ul",...(0,t.M)(),...e.components};return(0,s.jsxs)(s.Fragment,{children:[(0,s.jsx)(o.h1,{id:"kosmos-node-notready",children:"Kosmos Node NotReady"}),"\n",(0,s.jsx)(o.h2,{id:"kosmos-node-notready-solution",children:"Kosmos Node NotReady Solution"}),"\n",(0,s.jsx)(o.h3,{id:"introduction",children:"Introduction"}),"\n",(0,s.jsxs)(o.p,{children:["Assuming that we have registered the cluster ",(0,s.jsx)(o.code,{children:"cluster7"})," on the master cluster:"]}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-shell",metastring:"script",children:"$ kubectl get node\r\nNAME STATUS ROLES AGE VERSION\r\necs-54004033-001 Ready worker 50d v1.21.5\r\necs-54004033-002 Ready control-plane,master,worker 50d v1.21.5\r\nkosmos-cluster7 Ready agent 5d22h v1.21.5\n"})}),"\n",(0,s.jsxs)(o.p,{children:["The clustertree-cluster-manager of Kosmos will continuously monitor the resource usage and cluster status of the ",(0,s.jsx)(o.code,{children:"cluster7"})," cluster, and update it to the leaf node ",(0,s.jsx)(o.code,{children:"kosmos-cluster7"})," on the master cluster."]}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-shell",metastring:"script",children:"$ kubectl get deploy -nkosmos-system\r\nNAME READY UP-TO-DATE AVAILABLE AGE\r\nclusterlink-controller-manager 1/1 1 1 5d22h\r\nclusterlink-elector 2/2 2 2 5d22h\r\nclusterlink-network-manager 1/1 1 1 5d22h\r\nclustertree-cluster-manager 1/1 1 1 5d22h\r\nkosmos-operator 1/1 1 1 5d22h\r\nkosmos-webhook 1/1 1 1 11\n"})}),"\n",(0,s.jsxs)(o.p,{children:["If there is a network fluctuation between the master cluster and the ",(0,s.jsx)(o.code,{children:"cluster7"})," cluster, Kosmos will detect this anomaly and set the status of the leaf node ",(0,s.jsx)(o.code,{children:"kosmos-cluster7"}),' on the master cluster to "not ready". This will trigger the pod eviction behavior in Kubernetes, meaning that the pods on the "not ready" node will be evicted to other ready nodes.']}),"\n",(0,s.jsxs)(o.p,{children:["However, due to network fluctuations, the status of ",(0,s.jsx)(o.code,{children:"kosmos-cluster7"}),' may become "ready" again during the eviction process. But the events of the originally evicted pods will still be sent to the "cluster7" cluster, causing normal running pods on the "cluster7" cluster to be deleted or restarted, thus affecting the business.']}),"\n",(0,s.jsx)(o.h3,{id:"solution-integrating-kyverno-to-solve-the-kosmos-node-is-not-ready",children:"Solution: Integrating Kyverno to solve the kosmos node is not ready"}),"\n",(0,s.jsxs)(o.p,{children:[(0,s.jsx)(o.a,{href:"https://kyverno.io/",children:"Kyverno"})," validate, mutate, generate, and cleanup configurations using Kubernetes admission webhook, background scans, and source code repository scans. Kyverno policies can be managed as Kubernetes resources."]}),"\n",(0,s.jsx)(o.p,{children:"Its main functions are as follows:"}),"\n",(0,s.jsxs)(o.ul,{children:["\n",(0,s.jsx)(o.li,{children:"validate, mutate, generate, or cleanup (remove) any resource"}),"\n",(0,s.jsx)(o.li,{children:"verify container images for software supply chain security"}),"\n",(0,s.jsx)(o.li,{children:"match resources using label selectors and wildcards"}),"\n",(0,s.jsx)(o.li,{children:"synchronize configurations across Namespaces"}),"\n",(0,s.jsx)(o.li,{children:"block non-conformant resources using admission controls, or report policy violations"}),"\n"]}),"\n",(0,s.jsx)(o.p,{children:"This article explains how to use Kyverno's admission webhook to prevent pod expulsion when the kosmos node is not ready."}),"\n",(0,s.jsx)(o.h4,{id:"what-is-an-admission-webhook",children:"What is an admission webhook?"}),"\n",(0,s.jsx)(o.p,{children:'An "admission webhook" is a piece of code that intercepts requests to the Kubernetes API Server before object persistence. It allows requests to pass through after authentication and authorization. Admission controllers can perform validation, mutation, or both. Mutating controllers modify the resource objects they handle, while Validating controllers do not. If any controller in any phase rejects a request, the entire request will be immediately rejected, and the error will be returned to the end user.'}),"\n",(0,s.jsx)(o.p,{children:(0,s.jsx)(o.img,{alt:"K8s_Admission_Webhook.png",src:n(9140).c+"",width:"2401",height:"721"})}),"\n",(0,s.jsx)(o.h4,{id:"solution",children:"Solution"}),"\n",(0,s.jsx)(o.h5,{id:"install-kyverno",children:"install Kyverno"}),"\n",(0,s.jsx)(o.p,{children:(0,s.jsx)(o.a,{href:"https://kyverno.io/docs/installation/methods/",children:"Install Kyverno"})}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-shell",metastring:"script",children:"kubectl create -f https://github.com/kyverno/kyverno/releases/download/v1.10.0/install.yaml\n"})}),"\n",(0,s.jsx)(o.h4,{id:"configuring-clusterpolicy",children:"Configuring clusterpolicy"}),"\n",(0,s.jsx)(o.p,{children:"There are four scenarios in which k8s evicts the pod:"}),"\n",(0,s.jsxs)(o.ul,{children:["\n",(0,s.jsxs)(o.li,{children:[(0,s.jsx)(o.strong,{children:"User initiated"})," : The user initiates the evict request initiated by the API. For example, all Pods on the node are evicted during node maintenance to avoid the impact on services caused by the node going offline suddenly."]}),"\n",(0,s.jsxs)(o.li,{children:[(0,s.jsx)(o.strong,{children:"Kubelet initiated"})," : Periodically checks the resources of the node. When the resources are insufficient, some Pods are evicted based on the priority."]}),"\n",(0,s.jsxs)(o.li,{children:[(0,s.jsx)(o.strong,{children:"kube-controller-manager Initiate"})," : Periodically detects all nodes. When a node is in the NotReady state for more than a period of time, all Pods on the node are evicted so that they are scheduled to other normal nodes for re-running. When taint evict is enabled, the pod that cannot tolerate the taint is exicted immediately after there is a 'NoExecute' taint on node. For the pod that can tolerate the taint, the pod will be evicted after the minimum taint tolerance time configured on the pod."]}),"\n",(0,s.jsxs)(o.li,{children:[(0,s.jsx)(o.strong,{children:"kube-scheduler Initiating"})," : When preemptive scheduling is implemented, the low-priority Pod may be evicted to make room for the high-priority & preemptive Pod, so that the high-priority Pod can be scheduled normally"]}),"\n"]}),"\n",(0,s.jsx)(o.p,{children:"With the following profile, we will only block pod deletion events that meet the following three conditions:"}),"\n",(0,s.jsx)(o.p,{children:"(1) Node status is NotReady"}),"\n",(0,s.jsx)(o.p,{children:"(2) Node is a KosmosNode"}),"\n",(0,s.jsxs)(o.p,{children:["(3) the Username is system: serviceaccount: kube-system",":node-controller"," (belong to kube-controller-manager of node-controller )"]}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-yaml",children:'apiVersion: kyverno.io/v1\r\nkind: ClusterPolicy\r\nmetadata:\r\n name: kosmos-node-not-ready\r\nspec:\r\n validationFailureAction: Enforce\r\n background: false\r\n rules:\r\n - match:\r\n any:\r\n - resources:\r\n kinds:\r\n - Pod\r\n operations:\r\n - DELETE\r\n name: kosmos-node-not-read\r\n context:\r\n - name: nodeStatus\r\n apiCall:\r\n urlPath: /api/v1/nodes/{{request.oldObject.spec.nodeName}}\r\n jmesPath: status.conditions[?type==\'Ready\'].status | [0]\r\n - name: isKosmosNode\r\n apiCall:\r\n urlPath: /api/v1/nodes/{{request.oldObject.spec.nodeName}}\r\n jmesPath: metadata.labels."kosmos.io/node"\r\n preconditions:\r\n all:\r\n - key: "{{ request.userInfo.username }}"\r\n operator: Equals\r\n value: "system:serviceaccount:kube-system:node-controller"\r\n - key: "{{ nodeStatus }}"\r\n operator: NotEquals\r\n value: "True" \r\n - key: "{{ length(isKosmosNode) }}"\r\n operator: GreaterThan\r\n value: 0\r\n validate:\r\n message: " {{ request.userInfo.username }} delete pod {{request.oldObject.metadata.name}} of NotReady Kosmos {{request.oldObject.spec.nodeName}} Node is not allowed. "\r\n deny: {}\n'})}),"\n",(0,s.jsx)(o.p,{children:"When the status of Kosmos node is notready, the Pods on this node are blocked. You can view the following logs by viewing the kyverno-admission-controller"}),"\n",(0,s.jsx)(o.pre,{children:(0,s.jsx)(o.code,{className:"language-shell",metastring:"script",children:'handlers.go:139] webhooks/resource/validate "msg"="admission request denied" "clusterroles"=["system:basic-user","system:controller:node-controller","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "gvk"={"group":"","version":"v1","kind":"Pod"} "gvr"={"group":"","version":"v1","resource":"pods"} "kind"="Pod" "name"="example-deployment-6cc4fd9bd7-kkm8z" "namespace"="default" "operation"="DELETE" "resource.gvk"={"Group":"","Version":"v1","Kind":"Pod"} "roles"=null "uid"="7f25ee88-4522-45fd-a6ba-38733122b443" "user"={"username":"system:serviceaccount:kube-system:node-controller","uid":"5a13be66-71fd-40e3-9553-00eb0825fbb0","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"]}\r\nevent.go:307] "Event occurred" object="kosmos-node-not-ready" fieldPath="" kind="ClusterPolicy" apiVersion="kyverno.io/v1" type="Warning" reason="PolicyViolation" message="Pod default/example-deployment-6cc4fd9bd7-kkm8z: [kosmos-node-not-ready] fail (blocked); system:serviceaccount:kube-system:node-controller delete pod example-deployment-6cc4fd9bd7-kkm8z of NotReady Kosmos kosmos-cluster2 Node is not allowed. "\r\nvalidation.go:103] webhooks/resource/validate "msg"="validation failed" "action"="Enforce" "clusterroles"=["system:basic-user","system:controller:node-controller","system:discovery","system:public-info-viewer","system:service-account-issuer-discovery"] "failed rules"=["kosmos-node-not-ready"] "gvk"={"group":"","version":"v1","kind":"Pod"} "gvr"={"group":"","version":"v1","resource":"pods"} "kind"="Pod" "name"="example-deployment-6cc4fd9bd7-sb7m7" "namespace"="default" "operation"="DELETE" "policy"="kosmos-node-not-ready" "resource"="default/Pod/example-deployment-6cc4fd9bd7-sb7m7" "resource.gvk"={"Group":"","Version":"v1","Kind":"Pod"} "roles"=null "uid"="251f1877-4f2c-40ec-9bca-8ceb7c9c845f" "user"={"username":"system:serviceaccount:kube-system:node-controller","uid":"5a13be66-71fd-40e3-9553-00eb0825fbb0","groups":["system:serviceaccounts","system:serviceaccounts:kube-system","system:authenticated"]}\n'})})]})}function u(e={}){const{wrapper:o}={...(0,t.M)(),...e.components};return o?(0,s.jsx)(o,{...e,children:(0,s.jsx)(c,{...e})}):c(e)}},9140:(e,o,n)=>{n.d(o,{c:()=>s});const s=n.p+"assets/images/K8s_Admission_Webhook-d80e6ba8089fbf07bf3bf24a5302860a.png"},2172:(e,o,n)=>{n.d(o,{I:()=>a,M:()=>i});var s=n(1504);const t={},r=s.createContext(t);function i(e){const o=s.useContext(r);return s.useMemo((function(){return"function"==typeof e?e(o):{...o,...e}}),[o,e])}function a(e){let o;return o=e.disableParentContext?"function"==typeof e.components?e.components(t):e.components||t:i(e.components),s.createElement(r.Provider,{value:o},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/eecb3c4a.77b63ad1.js b/docs/assets/js/eecb3c4a.77b63ad1.js new file mode 100644 index 0000000..3ed5376 --- /dev/null +++ b/docs/assets/js/eecb3c4a.77b63ad1.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[456],{9296:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>n,metadata:()=>i,toc:()=>d});var r=s(7624),o=s(2172);const n={id:"leaf-node-generate-rules",title:"Leaf Node Generate Rules"},a="Leaf Node Generate Rules",i={id:"v0.2.0/proposals/leaf-node-generate-rules",title:"Leaf Node Generate Rules",description:"Summary",source:"@site/docs/v0.2.0/proposals/leaf-node-gen.md",sourceDirName:"v0.2.0/proposals",slug:"/v0.2.0/proposals/leaf-node-generate-rules",permalink:"/website/v0.2.0/proposals/leaf-node-generate-rules",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/proposals/leaf-node-gen.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1708679400,formattedLastUpdatedAt:"Feb 23, 2024",frontMatter:{id:"leaf-node-generate-rules",title:"Leaf Node Generate Rules"},sidebar:"tutorialSidebar",previous:{title:"Distribution Policy",permalink:"/website/v0.2.0/proposals/distribution-policy"}},l={},d=[{value:"Summary",id:"summary",level:2},{value:"Motivation & User Stories",id:"motivation--user-stories",level:2},{value:"Design Details",id:"design-details",level:2},{value:"Architecture",id:"architecture",level:3}];function c(e){const t={h1:"h1",h2:"h2",h3:"h3",img:"img",p:"p",...(0,o.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"leaf-node-generate-rules",children:"Leaf Node Generate Rules"}),"\n",(0,r.jsx)(t.h2,{id:"summary",children:"Summary"}),"\n",(0,r.jsx)(t.p,{children:"Provide a member cluster to pretend one or more Leaf Nodes in clusterTree by some rules like Node labelSelector"}),"\n",(0,r.jsx)(t.h2,{id:"motivation--user-stories",children:"Motivation & User Stories"}),"\n",(0,r.jsx)(t.p,{children:"1\u3001Some products can provide idle Nodes to join Kosmos\r\n2\u3001Some products want an easy way to make a second level pod schedule in their member clusters."}),"\n",(0,r.jsx)(t.h2,{id:"design-details",children:"Design Details"}),"\n",(0,r.jsx)(t.h3,{id:"architecture",children:"Architecture"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"leaf_node_rules",src:s(1904).c+"",width:"1762",height:"758"})})]})}function u(e={}){const{wrapper:t}={...(0,o.M)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},1904:(e,t,s)=>{s.d(t,{c:()=>r});const r=s.p+"assets/images/Leaf_Nodes-0deb9c286724d4458edaa11c9af9c5f1.png"},2172:(e,t,s)=>{s.d(t,{I:()=>i,M:()=>a});var r=s(1504);const o={},n=r.createContext(o);function a(e){const t=r.useContext(n);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/eecb3c4a.8cf0d3e6.js b/docs/assets/js/eecb3c4a.8cf0d3e6.js deleted file mode 100644 index e862603..0000000 --- a/docs/assets/js/eecb3c4a.8cf0d3e6.js +++ /dev/null @@ -1 +0,0 @@ -"use strict";(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[456],{6916:(e,t,s)=>{s.r(t),s.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>u,frontMatter:()=>n,metadata:()=>i,toc:()=>d});var r=s(7624),o=s(2172);const n={id:"leaf-node-generate-rules",title:"Leaf Node Generate Rules"},a="Leaf Node Generate Rules",i={id:"v0.2.0/proposals/leaf-node-generate-rules",title:"Leaf Node Generate Rules",description:"Summary",source:"@site/docs/v0.2.0/proposals/leaf-node-gen.md",sourceDirName:"v0.2.0/proposals",slug:"/v0.2.0/proposals/leaf-node-generate-rules",permalink:"/website/v0.2.0/proposals/leaf-node-generate-rules",draft:!1,unlisted:!1,editUrl:"https://github.com/facebook/docusaurus/tree/main/packages/create-docusaurus/templates/shared/docs/v0.2.0/proposals/leaf-node-gen.md",tags:[],version:"current",lastUpdatedBy:"ONE7live",lastUpdatedAt:1708679400,formattedLastUpdatedAt:"Feb 23, 2024",frontMatter:{id:"leaf-node-generate-rules",title:"Leaf Node Generate Rules"},sidebar:"tutorialSidebar",previous:{title:"Distribution Policy",permalink:"/website/v0.2.0/proposals/distribution-policy"},next:{title:"Kosmos Performance Testing",permalink:"/website/v0.2.0/proposals/performance-testing"}},l={},d=[{value:"Summary",id:"summary",level:2},{value:"Motivation & User Stories",id:"motivation--user-stories",level:2},{value:"Design Details",id:"design-details",level:2},{value:"Architecture",id:"architecture",level:3}];function c(e){const t={h1:"h1",h2:"h2",h3:"h3",img:"img",p:"p",...(0,o.M)(),...e.components};return(0,r.jsxs)(r.Fragment,{children:[(0,r.jsx)(t.h1,{id:"leaf-node-generate-rules",children:"Leaf Node Generate Rules"}),"\n",(0,r.jsx)(t.h2,{id:"summary",children:"Summary"}),"\n",(0,r.jsx)(t.p,{children:"Provide a member cluster to pretend one or more Leaf Nodes in clusterTree by some rules like Node labelSelector"}),"\n",(0,r.jsx)(t.h2,{id:"motivation--user-stories",children:"Motivation & User Stories"}),"\n",(0,r.jsx)(t.p,{children:"1\u3001Some products can provide idle Nodes to join Kosmos\r\n2\u3001Some products want an easy way to make a second level pod schedule in their member clusters."}),"\n",(0,r.jsx)(t.h2,{id:"design-details",children:"Design Details"}),"\n",(0,r.jsx)(t.h3,{id:"architecture",children:"Architecture"}),"\n",(0,r.jsx)(t.p,{children:(0,r.jsx)(t.img,{alt:"leaf_node_rules",src:s(1904).c+"",width:"1762",height:"758"})})]})}function u(e={}){const{wrapper:t}={...(0,o.M)(),...e.components};return t?(0,r.jsx)(t,{...e,children:(0,r.jsx)(c,{...e})}):c(e)}},1904:(e,t,s)=>{s.d(t,{c:()=>r});const r=s.p+"assets/images/Leaf_Nodes-0deb9c286724d4458edaa11c9af9c5f1.png"},2172:(e,t,s)=>{s.d(t,{I:()=>i,M:()=>a});var r=s(1504);const o={},n=r.createContext(o);function a(e){const t=r.useContext(n);return r.useMemo((function(){return"function"==typeof e?e(t):{...t,...e}}),[t,e])}function i(e){let t;return t=e.disableParentContext?"function"==typeof e.components?e.components(o):e.components||o:a(e.components),r.createElement(n.Provider,{value:t},e.children)}}}]); \ No newline at end of file diff --git a/docs/assets/js/main.0db9ee29.js b/docs/assets/js/main.0db9ee29.js deleted file mode 100644 index 5564670..0000000 --- a/docs/assets/js/main.0db9ee29.js +++ /dev/null @@ -1,2 +0,0 @@ -/*! For license information please see main.0db9ee29.js.LICENSE.txt */ -(self.webpackChunkzfile_docs=self.webpackChunkzfile_docs||[]).push([[590],{628:(e,t,n)=>{"use strict";n.d(t,{c:()=>f});n(1504);var r=n(8852),o=n.n(r),a=n(4504);const i={"04f08363":[()=>n.e(112).then(n.bind(n,8756)),"@site/docs/example/list1/test1.md",8756],"135c4066":[()=>n.e(808).then(n.bind(n,6712)),"@site/docs/v0.2.0/tutorials/ccn-ipsec-tunnel.md",6712],17896441:[()=>Promise.all([n.e(176),n.e(40),n.e(752)]).then(n.bind(n,7552)),"@theme/DocItem",7552],"1f271e39":[()=>n.e(192).then(n.bind(n,3224)),"@site/docs/i18n/zh/v0.2.0/multi-cluster-scheduler_zh.md",3224],"1f391b9e":[()=>Promise.all([n.e(176),n.e(40),n.e(204)]).then(n.bind(n,6728)),"@theme/MDXPage",6728],"20fc52ba":[()=>n.e(724).then(n.bind(n,2592)),"@site/docs/v0.2.0/quickstart.md",2592],"32d4be63":[()=>n.e(428).then(n.bind(n,5480)),"@site/docs/v0.2.0/proposals/performance_testing.md",5480],"393be207":[()=>n.e(652).then(n.bind(n,6084)),"@site/src/pages/markdown-page.md",6084],"4b29c545":[()=>n.e(588).then(n.bind(n,2020)),"@site/docs/v0.2.0/tutorials/application-migration.md",2020],"4df3a098":[()=>n.e(80).then(n.bind(n,7348)),"@site/docs/i18n/zh/v0.2.0/node-not-ready_zh.md",7348],"551e372e":[()=>n.e(811).then(n.bind(n,7140)),"@site/docs/v0.2.0/tutorials/multi-cluster-network.md",7140],"5e3c255f":[()=>n.e(474).then(n.bind(n,1884)),"@site/docs/example/list2/test2.md",1884],"5e95c892":[()=>n.e(304).then(n.bind(n,3564)),"@theme/DocsRoot",3564],"5e9f5e1a":[()=>Promise.resolve().then(n.bind(n,7768)),"@generated/docusaurus.config",7768],"63590f5d":[()=>n.e(372).then(n.bind(n,2088)),"@site/docs/v0.2.0/getting-started/introduction.md",2088],"69307a23":[()=>Promise.all([n.e(176),n.e(8)]).then(n.bind(n,4046)),"@site/docs/example/\u6587\u6863\u5199\u6cd5\u4ecb\u7ecd.md",4046],"69fd573f":[()=>n.e(614).then(n.bind(n,5236)),"@site/docs/v0.2.0/tutorials/pv-pvc-dynamic-storage.md",5236],"71f627e1":[()=>n.e(996).then(n.bind(n,7500)),"@site/docs/example/list3/list3\u5185\u5bb9.md",7500],"7e40eb73":[()=>n.e(720).then(n.bind(n,428)),"@site/docs/v0.2.0/proposals/distribution-policy.md",428],"825101dc":[()=>n.e(412).then(n.bind(n,1672)),"@site/docs/i18n/zh/v0.2.0/application-migration_zh.md",1672],"92fa710f":[()=>n.e(56).then(n.bind(n,9424)),"@site/docs/v0.2.0/tutorials/multi-cluster-svc-discovery.md",9424],"935f2afb":[()=>n.e(696).then(n.t.bind(n,5988,19)),"~docs/default/version-current-metadata-prop-751.json",5988],"9882b082":[()=>n.e(786).then(n.bind(n,1076)),"@site/docs/v0.2.0/tutorials/design-of-exec-and-log.md",1076],a7bd4aaa:[()=>n.e(500).then(n.bind(n,2e3)),"@theme/DocVersionRoot",2e3],a94703ab:[()=>Promise.all([n.e(176),n.e(666)]).then(n.bind(n,996)),"@theme/DocRoot",996],b4ae384a:[()=>n.e(20).then(n.bind(n,1184)),"@site/docs/v0.2.0/proposals/k8s-in-k8s.md",1184],b9ed296f:[()=>n.e(762).then(n.bind(n,4476)),"@site/docs/i18n/zh/v0.2.0/ccn-ipsec-tunnel_zh.md",4476],bdda2101:[()=>n.e(820).then(n.t.bind(n,590,19)),"D:\\code\\go\\src\\kosmos\\website\\kosmos\\.docusaurus\\docusaurus-plugin-content-pages\\default\\plugin-route-context-module-100.json",590],be2a6898:[()=>n.e(584).then(n.bind(n,4884)),"@site/docs/v0.2.0/tutorials/kubenest.md",4884],bfb97598:[()=>n.e(152).then(n.bind(n,8804)),"@site/docs/i18n/zh/v0.2.0/multi-cluster-svc-discovery_zh.md",8804],c4f5d8e4:[()=>Promise.all([n.e(176),n.e(632)]).then(n.bind(n,7276)),"@site/src/pages/index.js",7276],ce926f5d:[()=>n.e(568).then(n.bind(n,820)),"@site/docs/i18n/zh/v0.2.0/introduction_zh.md",820],d222d3f8:[()=>n.e(968).then(n.bind(n,148)),"@site/docs/example/list3/test3.md",148],d271270a:[()=>n.e(320).then(n.t.bind(n,2080,19)),"D:\\code\\go\\src\\kosmos\\website\\kosmos\\.docusaurus\\docusaurus-plugin-content-docs\\default\\plugin-route-context-module-100.json",2080],d5d7ecfb:[()=>n.e(528).then(n.bind(n,3767)),"@site/docs/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh.md",3767],d951913e:[()=>n.e(692).then(n.bind(n,2176)),"@site/docs/v0.2.0/tutorials/multi-cluster-scheduler.md",2176],e5ba6994:[()=>n.e(92).then(n.bind(n,8952)),"@site/docs/i18n/zh/v0.2.0/design-of-exec-and-log_zh.md",8952],e723d4d1:[()=>n.e(980).then(n.bind(n,7384)),"@site/docs/i18n/zh/v0.2.0/multi-cluster-network_zh.md",7384],ea929182:[()=>n.e(620).then(n.bind(n,2692)),"@site/docs/v0.2.0/tutorials/node-not-ready.md",2692],eecb3c4a:[()=>n.e(456).then(n.bind(n,6916)),"@site/docs/v0.2.0/proposals/leaf-node-gen.md",6916]};var l=n(7624);function s(e){let{error:t,retry:n,pastDelay:r}=e;return t?(0,l.jsxs)("div",{style:{textAlign:"center",color:"#fff",backgroundColor:"#fa383e",borderColor:"#fa383e",borderStyle:"solid",borderRadius:"0.25rem",borderWidth:"1px",boxSizing:"border-box",display:"block",padding:"1rem",flex:"0 0 50%",marginLeft:"25%",marginRight:"25%",marginTop:"5rem",maxWidth:"50%",width:"100%"},children:[(0,l.jsx)("p",{children:String(t)}),(0,l.jsx)("div",{children:(0,l.jsx)("button",{type:"button",onClick:n,children:"Retry"})})]}):r?(0,l.jsx)("div",{style:{display:"flex",justifyContent:"center",alignItems:"center",height:"100vh"},children:(0,l.jsx)("svg",{id:"loader",style:{width:128,height:110,position:"absolute",top:"calc(100vh - 64%)"},viewBox:"0 0 45 45",xmlns:"http://www.w3.org/2000/svg",stroke:"#61dafb",children:(0,l.jsxs)("g",{fill:"none",fillRule:"evenodd",transform:"translate(1 1)",strokeWidth:"2",children:[(0,l.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,l.jsx)("animate",{attributeName:"r",begin:"1.5s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-opacity",begin:"1.5s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-width",begin:"1.5s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,l.jsxs)("circle",{cx:"22",cy:"22",r:"6",strokeOpacity:"0",children:[(0,l.jsx)("animate",{attributeName:"r",begin:"3s",dur:"3s",values:"6;22",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-opacity",begin:"3s",dur:"3s",values:"1;0",calcMode:"linear",repeatCount:"indefinite"}),(0,l.jsx)("animate",{attributeName:"stroke-width",begin:"3s",dur:"3s",values:"2;0",calcMode:"linear",repeatCount:"indefinite"})]}),(0,l.jsx)("circle",{cx:"22",cy:"22",r:"8",children:(0,l.jsx)("animate",{attributeName:"r",begin:"0s",dur:"1.5s",values:"6;1;2;3;4;5;6",calcMode:"linear",repeatCount:"indefinite"})})]})})}):null}var c=n(8120),u=n(5548);function d(e,t){if("*"===e)return o()({loading:s,loader:()=>n.e(552).then(n.bind(n,4552)),modules:["@theme/NotFound"],webpack:()=>[4552],render(e,t){const n=e.default;return(0,l.jsx)(u.Y,{value:{plugin:{name:"native",id:"default"}},children:(0,l.jsx)(n,{...t})})}});const r=a[`${e}-${t}`],d={},f=[],p=[],m=(0,c.c)(r);return Object.entries(m).forEach((e=>{let[t,n]=e;const r=i[n];r&&(d[t]=r[0],f.push(r[1]),p.push(r[2]))})),o().Map({loading:s,loader:d,modules:f,webpack:()=>p,render(t,n){const o=JSON.parse(JSON.stringify(r));Object.entries(t).forEach((t=>{let[n,r]=t;const a=r.default;if(!a)throw new Error(`The page component at ${e} doesn't have a default export. This makes it impossible to render anything. Consider default-exporting a React component.`);"object"!=typeof a&&"function"!=typeof a||Object.keys(r).filter((e=>"default"!==e)).forEach((e=>{a[e]=r[e]}));let i=o;const l=n.split(".");l.slice(0,-1).forEach((e=>{i=i[e]})),i[l[l.length-1]]=a}));const a=o.__comp;delete o.__comp;const i=o.__context;return delete o.__context,(0,l.jsx)(u.Y,{value:i,children:(0,l.jsx)(a,{...o,...n})})}})}const f=[{path:"/website/markdown-page",component:d("/website/markdown-page","5d8"),exact:!0},{path:"/website/",component:d("/website/","a82"),exact:!0},{path:"/website/",component:d("/website/","572"),routes:[{path:"/website/",component:d("/website/","316"),routes:[{path:"/website/",component:d("/website/","313"),routes:[{path:"/website/example/describe2",component:d("/website/example/describe2","08f"),exact:!0},{path:"/website/example/list1/test1",component:d("/website/example/list1/test1","065"),exact:!0},{path:"/website/example/list2/test2",component:d("/website/example/list2/test2","1d8"),exact:!0},{path:"/website/example/list3/list3Content",component:d("/website/example/list3/list3Content","e42"),exact:!0},{path:"/website/example/list3/test3",component:d("/website/example/list3/test3","614"),exact:!0},{path:"/website/i18n/zh/v0.2.0/application-migration_zh",component:d("/website/i18n/zh/v0.2.0/application-migration_zh","5c3"),exact:!0},{path:"/website/i18n/zh/v0.2.0/exe-and-log_zh",component:d("/website/i18n/zh/v0.2.0/exe-and-log_zh","072"),exact:!0},{path:"/website/i18n/zh/v0.2.0/introduction_zh",component:d("/website/i18n/zh/v0.2.0/introduction_zh","fab"),exact:!0},{path:"/website/i18n/zh/v0.2.0/ipsec-network_zh",component:d("/website/i18n/zh/v0.2.0/ipsec-network_zh","160"),exact:!0},{path:"/website/i18n/zh/v0.2.0/mc-scheduler_zh",component:d("/website/i18n/zh/v0.2.0/mc-scheduler_zh","753"),exact:!0},{path:"/website/i18n/zh/v0.2.0/mcn-connectivity_zh",component:d("/website/i18n/zh/v0.2.0/mcn-connectivity_zh","6e8"),exact:!0},{path:"/website/i18n/zh/v0.2.0/mcs-discovery_zh",component:d("/website/i18n/zh/v0.2.0/mcs-discovery_zh","90a"),exact:!0},{path:"/website/i18n/zh/v0.2.0/node-not-ready_zh",component:d("/website/i18n/zh/v0.2.0/node-not-ready_zh","6ed"),exact:!0},{path:"/website/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh",component:d("/website/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh","477"),exact:!0},{path:"/website/v0.2.0/getting-started/introduction",component:d("/website/v0.2.0/getting-started/introduction","437"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/proposals/distribution-policy",component:d("/website/v0.2.0/proposals/distribution-policy","9f9"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/proposals/k8s-in-k8s",component:d("/website/v0.2.0/proposals/k8s-in-k8s","e81"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/proposals/leaf-node-generate-rules",component:d("/website/v0.2.0/proposals/leaf-node-generate-rules","b09"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/proposals/performance-testing",component:d("/website/v0.2.0/proposals/performance-testing","cae"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/quick-start",component:d("/website/v0.2.0/quick-start","320"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/application-migration",component:d("/website/v0.2.0/tutorials/application-migration","d8b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/exe-and-log",component:d("/website/v0.2.0/tutorials/exe-and-log","34d"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/ipsec-network",component:d("/website/v0.2.0/tutorials/ipsec-network","91b"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/kubenest",component:d("/website/v0.2.0/tutorials/kubenest","966"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/mc-scheduler",component:d("/website/v0.2.0/tutorials/mc-scheduler","b64"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/mcn-connectivity",component:d("/website/v0.2.0/tutorials/mcn-connectivity","b3e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/mcs-discovery",component:d("/website/v0.2.0/tutorials/mcs-discovery","186"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/node-not-ready",component:d("/website/v0.2.0/tutorials/node-not-ready","23e"),exact:!0,sidebar:"tutorialSidebar"},{path:"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage",component:d("/website/v0.2.0/tutorials/pv-pvc-dynamic-storage","04c"),exact:!0,sidebar:"tutorialSidebar"}]}]}]},{path:"*",component:d("*")}]},240:(e,t,n)=>{"use strict";n.d(t,{e:()=>a,g:()=>i});var r=n(1504),o=n(7624);const a=r.createContext(!1);function i(e){let{children:t}=e;const[n,i]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{i(!0)}),[]),(0,o.jsx)(a.Provider,{value:n,children:t})}},8808:(e,t,n)=>{"use strict";var r=n(1504),o=n(8352),a=n(440),i=n(2160),l=n(8684);const s=[n(1462),n(5396),n(1976),n(1496),n(6564)];var c=n(628),u=n(5592),d=n(5464),f=n(7624);function p(e){let{children:t}=e;return(0,f.jsx)(f.Fragment,{children:t})}var m=n(6952),h=n(8264),g=n(964),y=n(1824),b=n(5756),v=n(1616),w=n(204),k=n(4456),x=n(5684),S=n(8712);function E(){const{i18n:{currentLocale:e,defaultLocale:t,localeConfigs:n}}=(0,h.c)(),r=(0,v.D)(),o=n[e].htmlLang,a=e=>e.replace("-","_");return(0,f.jsxs)(m.c,{children:[Object.entries(n).map((e=>{let[t,{htmlLang:n}]=e;return(0,f.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:n},t)})),(0,f.jsx)("link",{rel:"alternate",href:r.createUrl({locale:t,fullyQualified:!0}),hrefLang:"x-default"}),(0,f.jsx)("meta",{property:"og:locale",content:a(o)}),Object.values(n).filter((e=>o!==e.htmlLang)).map((e=>(0,f.jsx)("meta",{property:"og:locale:alternate",content:a(e.htmlLang)},`meta-og-${e.htmlLang}`)))]})}function _(e){let{permalink:t}=e;const{siteConfig:{url:n}}=(0,h.c)(),r=function(){const{siteConfig:{url:e,baseUrl:t,trailingSlash:n}}=(0,h.c)(),{pathname:r}=(0,u.IT)();return e+(0,x.applyTrailingSlash)((0,g.c)(r),{trailingSlash:n,baseUrl:t})}(),o=t?`${n}${t}`:r;return(0,f.jsxs)(m.c,{children:[(0,f.jsx)("meta",{property:"og:url",content:o}),(0,f.jsx)("link",{rel:"canonical",href:o})]})}function C(){const{i18n:{currentLocale:e}}=(0,h.c)(),{metadata:t,image:n}=(0,y.y)();return(0,f.jsxs)(f.Fragment,{children:[(0,f.jsxs)(m.c,{children:[(0,f.jsx)("meta",{name:"twitter:card",content:"summary_large_image"}),(0,f.jsx)("body",{className:w.m})]}),n&&(0,f.jsx)(b.U7,{image:n}),(0,f.jsx)(_,{}),(0,f.jsx)(E,{}),(0,f.jsx)(S.c,{tag:k.e6,locale:e}),(0,f.jsx)(m.c,{children:t.map(((e,t)=>(0,f.jsx)("meta",{...e},t)))})]})}const T=new Map;function N(e){if(T.has(e.pathname))return{...e,pathname:T.get(e.pathname)};if((0,d.C)(c.c,e.pathname).some((e=>{let{route:t}=e;return!0===t.exact})))return T.set(e.pathname,e.pathname),e;const t=e.pathname.trim().replace(/(?:\/index)?\.html$/,"")||"/";return T.set(e.pathname,t),{...e,pathname:t}}var A=n(240),L=n(136),j=n(5288);function O(e){for(var t=arguments.length,n=new Array(t>1?t-1:0),r=1;r{const r=t.default?.[e]??t[e];return r?.(...n)}));return()=>o.forEach((e=>e?.()))}const P=function(e){let{children:t,location:n,previousLocation:r}=e;return(0,j.c)((()=>{r!==n&&(!function(e){let{location:t,previousLocation:n}=e;if(!n)return;const r=t.pathname===n.pathname,o=t.hash===n.hash,a=t.search===n.search;if(r&&o&&!a)return;const{hash:i}=t;if(i){const e=decodeURIComponent(i.substring(1)),t=document.getElementById(e);t?.scrollIntoView()}else window.scrollTo(0,0)}({location:n,previousLocation:r}),O("onRouteDidUpdate",{previousLocation:r,location:n}))}),[r,n]),t};function z(e){const t=Array.from(new Set([e,decodeURI(e)])).map((e=>(0,d.C)(c.c,e))).flat();return Promise.all(t.map((e=>e.route.component.preload?.())))}class R extends r.Component{previousLocation;routeUpdateCleanupCb;constructor(e){super(e),this.previousLocation=null,this.routeUpdateCleanupCb=l.c.canUseDOM?O("onRouteUpdate",{previousLocation:null,location:this.props.location}):()=>{},this.state={nextRouteHasLoaded:!0}}shouldComponentUpdate(e,t){if(e.location===this.props.location)return t.nextRouteHasLoaded;const n=e.location;return this.previousLocation=this.props.location,this.setState({nextRouteHasLoaded:!1}),this.routeUpdateCleanupCb=O("onRouteUpdate",{previousLocation:this.previousLocation,location:n}),z(n.pathname).then((()=>{this.routeUpdateCleanupCb(),this.setState({nextRouteHasLoaded:!0})})).catch((e=>{console.warn(e),window.location.reload()})),!1}render(){const{children:e,location:t}=this.props;return(0,f.jsx)(P,{previousLocation:this.previousLocation,location:t,children:(0,f.jsx)(u.kX,{location:t,render:()=>e})})}}const I=R,F="__docusaurus-base-url-issue-banner-container",M="__docusaurus-base-url-issue-banner",D="__docusaurus-base-url-issue-banner-suggestion-container";function B(e){return`\ndocument.addEventListener('DOMContentLoaded', function maybeInsertBanner() {\n var shouldInsert = typeof window['docusaurus'] === 'undefined';\n shouldInsert && insertBanner();\n});\n\nfunction insertBanner() {\n var bannerContainer = document.createElement('div');\n bannerContainer.id = '${F}';\n var bannerHtml = ${JSON.stringify(function(e){return`\n
\n

Your Docusaurus site did not load properly.

\n

A very common reason is a wrong site baseUrl configuration.

\n

Current configured baseUrl = ${e} ${"/"===e?" (default value)":""}

\n

We suggest trying baseUrl =

\n
\n`}(e)).replace(/{if("undefined"==typeof document)return void n();const r=document.createElement("link");r.setAttribute("rel","prefetch"),r.setAttribute("href",e),r.onload=()=>t(),r.onerror=()=>n();const o=document.getElementsByTagName("head")[0]??document.getElementsByName("script")[0]?.parentNode;o?.appendChild(r)}))}:function(e){return new Promise(((t,n)=>{const r=new XMLHttpRequest;r.open("GET",e,!0),r.withCredentials=!0,r.onload=()=>{200===r.status?t():n()},r.send(null)}))};var K=n(8120);const Z=new Set,X=new Set,J=()=>navigator.connection?.effectiveType.includes("2g")||navigator.connection?.saveData,ee={prefetch(e){if(!(e=>!J()&&!X.has(e)&&!Z.has(e))(e))return!1;Z.add(e);const t=(0,d.C)(c.c,e).flatMap((e=>{return t=e.route.path,Object.entries(Y).filter((e=>{let[n]=e;return n.replace(/-[^-]+$/,"")===t})).flatMap((e=>{let[,t]=e;return Object.values((0,K.c)(t))}));var t}));return Promise.all(t.map((e=>{const t=n.gca(e);return t&&!t.includes("undefined")?Q(t).catch((()=>{})):Promise.resolve()})))},preload:e=>!!(e=>!J()&&!X.has(e))(e)&&(X.add(e),z(e))},te=Object.freeze(ee),ne=Boolean(!0);if(l.c.canUseDOM){window.docusaurus=te;const e=document.getElementById("__docusaurus"),t=(0,f.jsx)(i.EN,{children:(0,f.jsx)(a.kn,{children:(0,f.jsx)(G,{})})}),n=(e,t)=>{console.error("Docusaurus React Root onRecoverableError:",e,t)},l=()=>{if(ne)r.startTransition((()=>{o.hydrateRoot(e,t,{onRecoverableError:n})}));else{const a=o.createRoot(e,{onRecoverableError:n});r.startTransition((()=>{a.render(t)}))}};z(window.location.pathname).then(l)}},136:(e,t,n)=>{"use strict";n.d(t,{e:()=>d,y:()=>f});var r=n(1504),o=n(7768);const a=JSON.parse('{"docusaurus-plugin-content-docs":{"default":{"path":"/website/","versions":[{"name":"current","label":"Next","isLast":true,"path":"/website/","mainDocId":"v0.2.0/getting-started/introduction","docs":[{"id":"example/describe2","path":"/website/example/describe2"},{"id":"example/list1/test1","path":"/website/example/list1/test1"},{"id":"example/list2/test2","path":"/website/example/list2/test2"},{"id":"example/list3/list3Content","path":"/website/example/list3/list3Content"},{"id":"example/list3/test3","path":"/website/example/list3/test3"},{"id":"i18n/zh/v0.2.0/application-migration_zh","path":"/website/i18n/zh/v0.2.0/application-migration_zh"},{"id":"i18n/zh/v0.2.0/exe-and-log_zh","path":"/website/i18n/zh/v0.2.0/exe-and-log_zh"},{"id":"i18n/zh/v0.2.0/introduction_zh","path":"/website/i18n/zh/v0.2.0/introduction_zh"},{"id":"i18n/zh/v0.2.0/ipsec-network_zh","path":"/website/i18n/zh/v0.2.0/ipsec-network_zh"},{"id":"i18n/zh/v0.2.0/mc-scheduler_zh","path":"/website/i18n/zh/v0.2.0/mc-scheduler_zh"},{"id":"i18n/zh/v0.2.0/mcn-connectivity_zh","path":"/website/i18n/zh/v0.2.0/mcn-connectivity_zh"},{"id":"i18n/zh/v0.2.0/mcs-discovery_zh","path":"/website/i18n/zh/v0.2.0/mcs-discovery_zh"},{"id":"i18n/zh/v0.2.0/node-not-ready_zh","path":"/website/i18n/zh/v0.2.0/node-not-ready_zh"},{"id":"i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh","path":"/website/i18n/zh/v0.2.0/pv-pvc-dynamic-storage_zh"},{"id":"v0.2.0/getting-started/introduction","path":"/website/v0.2.0/getting-started/introduction","sidebar":"tutorialSidebar"},{"id":"v0.2.0/proposals/distribution-policy","path":"/website/v0.2.0/proposals/distribution-policy","sidebar":"tutorialSidebar"},{"id":"v0.2.0/proposals/k8s-in-k8s","path":"/website/v0.2.0/proposals/k8s-in-k8s","sidebar":"tutorialSidebar"},{"id":"v0.2.0/proposals/leaf-node-generate-rules","path":"/website/v0.2.0/proposals/leaf-node-generate-rules","sidebar":"tutorialSidebar"},{"id":"v0.2.0/proposals/performance-testing","path":"/website/v0.2.0/proposals/performance-testing","sidebar":"tutorialSidebar"},{"id":"v0.2.0/quick-start","path":"/website/v0.2.0/quick-start","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/application-migration","path":"/website/v0.2.0/tutorials/application-migration","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/exe-and-log","path":"/website/v0.2.0/tutorials/exe-and-log","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/ipsec-network","path":"/website/v0.2.0/tutorials/ipsec-network","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/kubenest","path":"/website/v0.2.0/tutorials/kubenest","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/mc-scheduler","path":"/website/v0.2.0/tutorials/mc-scheduler","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/mcn-connectivity","path":"/website/v0.2.0/tutorials/mcn-connectivity","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/mcs-discovery","path":"/website/v0.2.0/tutorials/mcs-discovery","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/node-not-ready","path":"/website/v0.2.0/tutorials/node-not-ready","sidebar":"tutorialSidebar"},{"id":"v0.2.0/tutorials/pv-pvc-dynamic-storage","path":"/website/v0.2.0/tutorials/pv-pvc-dynamic-storage","sidebar":"tutorialSidebar"}],"draftIds":[],"sidebars":{"tutorialSidebar":{"link":{"path":"/website/v0.2.0/getting-started/introduction","label":"v0.2.0/getting-started/introduction"}}}}],"breadcrumbs":true}}}'),i=JSON.parse('{"defaultLocale":"en","locales":["en"],"path":"i18n","currentLocale":"en","localeConfigs":{"en":{"label":"English","direction":"ltr","htmlLang":"en","calendar":"gregory","path":"en"}}}');var l=n(144);const s=JSON.parse('{"docusaurusVersion":"3.1.1","siteVersion":"0.0.0","pluginVersions":{"docusaurus-plugin-content-docs":{"type":"package","name":"@docusaurus/plugin-content-docs","version":"3.1.1"},"docusaurus-plugin-content-blog":{"type":"package","name":"@docusaurus/plugin-content-blog","version":"3.1.1"},"docusaurus-plugin-content-pages":{"type":"package","name":"@docusaurus/plugin-content-pages","version":"3.1.1"},"docusaurus-plugin-sitemap":{"type":"package","name":"@docusaurus/plugin-sitemap","version":"3.1.1"},"docusaurus-theme-classic":{"type":"package","name":"@docusaurus/theme-classic","version":"3.1.1"},"postcss-tailwindcss-loader":{"type":"project"},"docusaurus-plugin-image-zoom":{"type":"package","name":"docusaurus-plugin-image-zoom","version":"2.0.0"}}}');var c=n(7624);const u={siteConfig:o.default,siteMetadata:s,globalData:a,i18n:i,codeTranslations:l},d=r.createContext(u);function f(e){let{children:t}=e;return(0,c.jsx)(d.Provider,{value:u,children:t})}},5852:(e,t,n)=>{"use strict";n.d(t,{c:()=>p});var r=n(1504),o=n(8684),a=n(6952),i=n(5684),l=n(9012),s=n(7624);function c(e){let{error:t,tryAgain:n}=e;return(0,s.jsxs)("div",{style:{display:"flex",flexDirection:"column",justifyContent:"center",alignItems:"flex-start",minHeight:"100vh",width:"100%",maxWidth:"80ch",fontSize:"20px",margin:"0 auto",padding:"1rem"},children:[(0,s.jsx)("h1",{style:{fontSize:"3rem"},children:"This page crashed"}),(0,s.jsx)("button",{type:"button",onClick:n,style:{margin:"1rem 0",fontSize:"2rem",cursor:"pointer",borderRadius:20,padding:"1rem"},children:"Try again"}),(0,s.jsx)(u,{error:t})]})}function u(e){let{error:t}=e;const n=(0,i.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,s.jsx)("p",{style:{whiteSpace:"pre-wrap"},children:n})}function d(e){let{error:t,tryAgain:n}=e;return(0,s.jsxs)(p,{fallback:()=>(0,s.jsx)(c,{error:t,tryAgain:n}),children:[(0,s.jsx)(a.c,{children:(0,s.jsx)("title",{children:"Page Error"})}),(0,s.jsx)(l.c,{children:(0,s.jsx)(c,{error:t,tryAgain:n})})]})}const f=e=>(0,s.jsx)(d,{...e});class p extends r.Component{constructor(e){super(e),this.state={error:null}}componentDidCatch(e){o.c.canUseDOM&&this.setState({error:e})}render(){const{children:e}=this.props,{error:t}=this.state;if(t){const e={error:t,tryAgain:()=>this.setState({error:null})};return(this.props.fallback??f)(e)}return e??null}}},8684:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});const r="undefined"!=typeof window&&"document"in window&&"createElement"in window.document,o={canUseDOM:r,canUseEventListeners:r&&("addEventListener"in window||"attachEvent"in window),canUseIntersectionObserver:r&&"IntersectionObserver"in window,canUseViewport:r&&"screen"in window}},6952:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);var r=n(2160),o=n(7624);function a(e){return(0,o.jsx)(r.So,{...e})}},867:(e,t,n)=>{"use strict";n.d(t,{c:()=>p});var r=n(1504),o=n(440),a=n(5684),i=n(8264),l=n(8136),s=n(8684),c=n(5976),u=n(964),d=n(7624);function f(e,t){let{isNavLink:n,to:f,href:p,activeClassName:m,isActive:h,"data-noBrokenLinkCheck":g,autoAddBaseUrl:y=!0,...b}=e;const{siteConfig:{trailingSlash:v,baseUrl:w}}=(0,i.c)(),{withBaseUrl:k}=(0,u.E)(),x=(0,c.c)(),S=(0,r.useRef)(null);(0,r.useImperativeHandle)(t,(()=>S.current));const E=f||p;const _=(0,l.c)(E),C=E?.replace("pathname://","");let T=void 0!==C?(N=C,y&&(e=>e.startsWith("/"))(N)?k(N):N):void 0;var N;T&&_&&(T=(0,a.applyTrailingSlash)(T,{trailingSlash:v,baseUrl:w}));const A=(0,r.useRef)(!1),L=n?o.Af:o.cH,j=s.c.canUseIntersectionObserver,O=(0,r.useRef)(),P=()=>{A.current||null==T||(window.docusaurus.preload(T),A.current=!0)};(0,r.useEffect)((()=>(!j&&_&&null!=T&&window.docusaurus.prefetch(T),()=>{j&&O.current&&O.current.disconnect()})),[O,T,j,_]);const z=T?.startsWith("#")??!1,R=!b.target||"_self"===b.target,I=!T||!_||!R||z;return g||!z&&I||x.collectLink(T),b.id&&x.collectAnchor(b.id),I?(0,d.jsx)("a",{ref:S,href:T,...E&&!_&&{target:"_blank",rel:"noopener noreferrer"},...b}):(0,d.jsx)(L,{...b,onMouseEnter:P,onTouchStart:P,innerRef:e=>{S.current=e,j&&e&&_&&(O.current=new window.IntersectionObserver((t=>{t.forEach((t=>{e===t.target&&(t.isIntersecting||t.intersectionRatio>0)&&(O.current.unobserve(e),O.current.disconnect(),null!=T&&window.docusaurus.prefetch(T))}))})),O.current.observe(e))},to:T,...n&&{isActive:h,activeClassName:m}})}const p=r.forwardRef(f)},2944:(e,t,n)=>{"use strict";n.d(t,{c:()=>r});const r=()=>null},4357:(e,t,n)=>{"use strict";n.d(t,{c:()=>c,G:()=>s});var r=n(1504),o=n(7624);function a(e,t){const n=e.split(/(\{\w+\})/).map(((e,n)=>{if(n%2==1){const n=t?.[e.slice(1,-1)];if(void 0!==n)return n}return e}));return n.some((e=>(0,r.isValidElement)(e)))?n.map(((e,t)=>(0,r.isValidElement)(e)?r.cloneElement(e,{key:t}):e)).filter((e=>""!==e)):n.join("")}var i=n(144);function l(e){let{id:t,message:n}=e;if(void 0===t&&void 0===n)throw new Error("Docusaurus translation declarations must have at least a translation id or a default translation message");return i[t??n]??n??t}function s(e,t){let{message:n,id:r}=e;return a(l({message:n,id:r}),t)}function c(e){let{children:t,id:n,values:r}=e;if(t&&"string"!=typeof t)throw console.warn("Illegal children",t),new Error("The Docusaurus component only accept simple string values");const i=l({message:t,id:n});return(0,o.jsx)(o.Fragment,{children:a(i,r)})}},2488:(e,t,n)=>{"use strict";n.d(t,{M:()=>r});const r="default"},8136:(e,t,n)=>{"use strict";function r(e){return/^(?:\w*:|\/\/)/.test(e)}function o(e){return void 0!==e&&!r(e)}n.d(t,{_:()=>r,c:()=>o})},964:(e,t,n)=>{"use strict";n.d(t,{E:()=>i,c:()=>l});var r=n(1504),o=n(8264),a=n(8136);function i(){const{siteConfig:{baseUrl:e,url:t}}=(0,o.c)(),n=(0,r.useCallback)(((n,r)=>function(e,t,n,r){let{forcePrependBaseUrl:o=!1,absolute:i=!1}=void 0===r?{}:r;if(!n||n.startsWith("#")||(0,a._)(n))return n;if(o)return t+n.replace(/^\//,"");if(n===t.replace(/\/$/,""))return t;const l=n.startsWith(t)?n:t+n.replace(/^\//,"");return i?e+l:l}(t,e,n,r)),[t,e]);return{withBaseUrl:n}}function l(e,t){void 0===t&&(t={});const{withBaseUrl:n}=i();return n(e,t)}},5976:(e,t,n)=>{"use strict";n.d(t,{c:()=>i});var r=n(1504);n(7624);const o=r.createContext({collectAnchor:()=>{},collectLink:()=>{}}),a=()=>(0,r.useContext)(o);function i(){return a()}},8264:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});var r=n(1504),o=n(136);function a(){return(0,r.useContext)(o.e)}},3664:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});var r=n(1504),o=n(240);function a(){return(0,r.useContext)(o.e)}},5288:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});var r=n(1504);const o=n(8684).c.canUseDOM?r.useLayoutEffect:r.useEffect},8120:(e,t,n)=>{"use strict";n.d(t,{c:()=>o});const r=e=>"object"==typeof e&&!!e&&Object.keys(e).length>0;function o(e){const t={};return function e(n,o){Object.entries(n).forEach((n=>{let[a,i]=n;const l=o?`${o}.${a}`:a;r(i)?e(i,l):t[l]=i}))}(e),t}},5548:(e,t,n)=>{"use strict";n.d(t,{Y:()=>i,e:()=>a});var r=n(1504),o=n(7624);const a=r.createContext(null);function i(e){let{children:t,value:n}=e;const i=r.useContext(a),l=(0,r.useMemo)((()=>function(e){let{parent:t,value:n}=e;if(!t){if(!n)throw new Error("Unexpected: no Docusaurus route context found");if(!("plugin"in n))throw new Error("Unexpected: Docusaurus topmost route context has no `plugin` attribute");return n}const r={...t.data,...n?.data};return{plugin:t.plugin,data:r}}({parent:i,value:n})),[i,n]);return(0,o.jsx)(a.Provider,{value:l,children:t})}},2840:(e,t,n)=>{"use strict";n.d(t,{wB:()=>h,UF:()=>f,L0:()=>u,i8:()=>g,OK:()=>d,aA:()=>m,gN:()=>p});var r=n(5592),o=n(8264),a=n(2488);function i(e,t){void 0===t&&(t={});const n=function(){const{globalData:e}=(0,o.c)();return e}()[e];if(!n&&t.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin.`);return n}const l=e=>e.versions.find((e=>e.isLast));function s(e,t){const n=function(e,t){const n=l(e);return[...e.versions.filter((e=>e!==n)),n].find((e=>!!(0,r.ot)(t,{path:e.path,exact:!1,strict:!1})))}(e,t),o=n?.docs.find((e=>!!(0,r.ot)(t,{path:e.path,exact:!0,strict:!1})));return{activeVersion:n,activeDoc:o,alternateDocVersions:o?function(t){const n={};return e.versions.forEach((e=>{e.docs.forEach((r=>{r.id===t&&(n[e.name]=r)}))})),n}(o.id):{}}}const c={},u=()=>i("docusaurus-plugin-content-docs")??c,d=e=>function(e,t,n){void 0===t&&(t=a.M),void 0===n&&(n={});const r=i(e),o=r?.[t];if(!o&&n.failfast)throw new Error(`Docusaurus plugin global data not found for "${e}" plugin with id "${t}".`);return o}("docusaurus-plugin-content-docs",e,{failfast:!0});function f(e){void 0===e&&(e={});const t=u(),{pathname:n}=(0,r.IT)();return function(e,t,n){void 0===n&&(n={});const o=Object.entries(e).sort(((e,t)=>t[1].path.localeCompare(e[1].path))).find((e=>{let[,n]=e;return!!(0,r.ot)(t,{path:n.path,exact:!1,strict:!1})})),a=o?{pluginId:o[0],pluginData:o[1]}:void 0;if(!a&&n.failfast)throw new Error(`Can't find active docs plugin for "${t}" pathname, while it was expected to be found. Maybe you tried to use a docs feature that can only be used on a docs-related page? Existing docs plugin paths are: ${Object.values(e).map((e=>e.path)).join(", ")}`);return a}(t,n,e)}function p(e){return d(e).versions}function m(e){const t=d(e);return l(t)}function h(e){const t=d(e),{pathname:n}=(0,r.IT)();return s(t,n)}function g(e){const t=d(e),{pathname:n}=(0,r.IT)();return function(e,t){const n=l(e);return{latestDocSuggestion:s(e,t).alternateDocVersions[n.name],latestVersionSuggestion:n}}(t,n)}},1976:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>a});var r=n(2272),o=n.n(r);o().configure({showSpinner:!1});const a={onRouteUpdate(e){let{location:t,previousLocation:n}=e;if(n&&t.pathname!==n.pathname){const e=window.setTimeout((()=>{o().start()}),200);return()=>window.clearTimeout(e)}},onRouteDidUpdate(){o().done()}}},5396:(e,t,n)=>{"use strict";n.r(t);var r=n(5720),o=n(7768);!function(e){const{themeConfig:{prism:t}}=o.default,{additionalLanguages:r}=t;globalThis.Prism=e,r.forEach((e=>{"php"===e&&n(1808),n(464)(`./prism-${e}`)})),delete globalThis.Prism}(r.sp)},6448:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});n(1504);var r=n(5456),o=n(4357),a=n(1824),i=n(867),l=n(5976);const s={anchorWithStickyNavbar:"anchorWithStickyNavbar_LWe7",anchorWithHideOnScrollNavbar:"anchorWithHideOnScrollNavbar_WYt5"};var c=n(7624);function u(e){let{as:t,id:n,...u}=e;const d=(0,l.c)(),{navbar:{hideOnScroll:f}}=(0,a.y)();if("h1"===t||!n)return(0,c.jsx)(t,{...u,id:void 0});d.collectAnchor(n);const p=(0,o.G)({id:"theme.common.headingLinkTitle",message:"Direct link to {heading}",description:"Title for link to heading"},{heading:"string"==typeof u.children?u.children:n});return(0,c.jsxs)(t,{...u,className:(0,r.c)("anchor",f?s.anchorWithHideOnScrollNavbar:s.anchorWithStickyNavbar,u.className),id:n,children:[u.children,(0,c.jsx)(i.c,{className:"hash-link",to:`#${n}`,"aria-label":p,title:p,children:"\u200b"})]})}},3232:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);const r={iconExternalLink:"iconExternalLink_nPIU"};var o=n(7624);function a(e){let{width:t=13.5,height:n=13.5}=e;return(0,o.jsx)("svg",{width:t,height:n,"aria-hidden":"true",viewBox:"0 0 24 24",className:r.iconExternalLink,children:(0,o.jsx)("path",{fill:"currentColor",d:"M21 13v10h-21v-19h12v2h-10v15h17v-8h2zm3-12h-10.988l4.035 4-6.977 7.07 2.828 2.828 6.977-7.07 4.125 4.172v-11z"})})}},9012:(e,t,n)=>{"use strict";n.d(t,{c:()=>pt});var r=n(1504),o=n(5456),a=n(5852),i=n(5756),l=n(5592),s=n(4357),c=n(7124),u=n(7624);const d="__docusaurus_skipToContent_fallback";function f(e){e.setAttribute("tabindex","-1"),e.focus(),e.removeAttribute("tabindex")}function p(){const e=(0,r.useRef)(null),{action:t}=(0,l.Uz)(),n=(0,r.useCallback)((e=>{e.preventDefault();const t=document.querySelector("main:first-of-type")??document.getElementById(d);t&&f(t)}),[]);return(0,c.c)((n=>{let{location:r}=n;e.current&&!r.hash&&"PUSH"===t&&f(e.current)})),{containerRef:e,onClick:n}}const m=(0,s.G)({id:"theme.common.skipToMainContent",description:"The skip to content label used for accessibility, allowing to rapidly navigate to main content with keyboard tab/enter navigation",message:"Skip to main content"});function h(e){const t=e.children??m,{containerRef:n,onClick:r}=p();return(0,u.jsx)("div",{ref:n,role:"region","aria-label":m,children:(0,u.jsx)("a",{...e,href:`#${d}`,onClick:r,children:t})})}var g=n(5864),y=n(204);const b={skipToContent:"skipToContent_fXgn"};function v(){return(0,u.jsx)(h,{className:b.skipToContent})}var w=n(1824),k=n(3868);function x(e){let{width:t=21,height:n=21,color:r="currentColor",strokeWidth:o=1.2,className:a,...i}=e;return(0,u.jsx)("svg",{viewBox:"0 0 15 15",width:t,height:n,...i,children:(0,u.jsx)("g",{stroke:r,strokeWidth:o,children:(0,u.jsx)("path",{d:"M.75.75l13.5 13.5M14.25.75L.75 14.25"})})})}const S={closeButton:"closeButton_CVFx"};function E(e){return(0,u.jsx)("button",{type:"button","aria-label":(0,s.G)({id:"theme.AnnouncementBar.closeButtonAriaLabel",message:"Close",description:"The ARIA label for close button of announcement bar"}),...e,className:(0,o.c)("clean-btn close",S.closeButton,e.className),children:(0,u.jsx)(x,{width:14,height:14,strokeWidth:3.1})})}const _={content:"content_knG7"};function C(e){const{announcementBar:t}=(0,w.y)(),{content:n}=t;return(0,u.jsx)("div",{...e,className:(0,o.c)(_.content,e.className),dangerouslySetInnerHTML:{__html:n}})}const T={announcementBar:"announcementBar_mb4j",announcementBarPlaceholder:"announcementBarPlaceholder_vyr4",announcementBarClose:"announcementBarClose_gvF7",announcementBarContent:"announcementBarContent_xLdY"};function N(){const{announcementBar:e}=(0,w.y)(),{isActive:t,close:n}=(0,k.el)();if(!t)return null;const{backgroundColor:r,textColor:o,isCloseable:a}=e;return(0,u.jsxs)("div",{className:T.announcementBar,style:{backgroundColor:r,color:o},role:"banner",children:[a&&(0,u.jsx)("div",{className:T.announcementBarPlaceholder}),(0,u.jsx)(C,{className:T.announcementBarContent}),a&&(0,u.jsx)(E,{onClick:n,className:T.announcementBarClose})]})}var A=n(8200),L=n(3943);var j=n(1100),O=n(5168);const P=r.createContext(null);function z(e){let{children:t}=e;const n=function(){const e=(0,A.q)(),t=(0,O.MF)(),[n,o]=(0,r.useState)(!1),a=null!==t.component,i=(0,j.i0)(a);return(0,r.useEffect)((()=>{a&&!i&&o(!0)}),[a,i]),(0,r.useEffect)((()=>{a?e.shown||o(!0):o(!1)}),[e.shown,a]),(0,r.useMemo)((()=>[n,o]),[n])}();return(0,u.jsx)(P.Provider,{value:n,children:t})}function R(e){if(e.component){const t=e.component;return(0,u.jsx)(t,{...e.props})}}function I(){const e=(0,r.useContext)(P);if(!e)throw new j.AH("NavbarSecondaryMenuDisplayProvider");const[t,n]=e,o=(0,r.useCallback)((()=>n(!1)),[n]),a=(0,O.MF)();return(0,r.useMemo)((()=>({shown:t,hide:o,content:R(a)})),[o,a,t])}function F(e){let{header:t,primaryMenu:n,secondaryMenu:r}=e;const{shown:a}=I();return(0,u.jsxs)("div",{className:"navbar-sidebar",children:[t,(0,u.jsxs)("div",{className:(0,o.c)("navbar-sidebar__items",{"navbar-sidebar__items--show-secondary":a}),children:[(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:n}),(0,u.jsx)("div",{className:"navbar-sidebar__item menu",children:r})]})]})}var M=n(6528),D=n(3664);function B(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12,9c1.65,0,3,1.35,3,3s-1.35,3-3,3s-3-1.35-3-3S10.35,9,12,9 M12,7c-2.76,0-5,2.24-5,5s2.24,5,5,5s5-2.24,5-5 S14.76,7,12,7L12,7z M2,13l2,0c0.55,0,1-0.45,1-1s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S1.45,13,2,13z M20,13l2,0c0.55,0,1-0.45,1-1 s-0.45-1-1-1l-2,0c-0.55,0-1,0.45-1,1S19.45,13,20,13z M11,2v2c0,0.55,0.45,1,1,1s1-0.45,1-1V2c0-0.55-0.45-1-1-1S11,1.45,11,2z M11,20v2c0,0.55,0.45,1,1,1s1-0.45,1-1v-2c0-0.55-0.45-1-1-1C11.45,19,11,19.45,11,20z M5.99,4.58c-0.39-0.39-1.03-0.39-1.41,0 c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0s0.39-1.03,0-1.41L5.99,4.58z M18.36,16.95 c-0.39-0.39-1.03-0.39-1.41,0c-0.39,0.39-0.39,1.03,0,1.41l1.06,1.06c0.39,0.39,1.03,0.39,1.41,0c0.39-0.39,0.39-1.03,0-1.41 L18.36,16.95z M19.42,5.99c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06c-0.39,0.39-0.39,1.03,0,1.41 s1.03,0.39,1.41,0L19.42,5.99z M7.05,18.36c0.39-0.39,0.39-1.03,0-1.41c-0.39-0.39-1.03-0.39-1.41,0l-1.06,1.06 c-0.39,0.39-0.39,1.03,0,1.41s1.03,0.39,1.41,0L7.05,18.36z"})})}function $(e){return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:24,height:24,...e,children:(0,u.jsx)("path",{fill:"currentColor",d:"M9.37,5.51C9.19,6.15,9.1,6.82,9.1,7.5c0,4.08,3.32,7.4,7.4,7.4c0.68,0,1.35-0.09,1.99-0.27C17.45,17.19,14.93,19,12,19 c-3.86,0-7-3.14-7-7C5,9.07,6.81,6.55,9.37,5.51z M12,3c-4.97,0-9,4.03-9,9s4.03,9,9,9s9-4.03,9-9c0-0.46-0.04-0.92-0.1-1.36 c-0.98,1.37-2.58,2.26-4.4,2.26c-2.98,0-5.4-2.42-5.4-5.4c0-1.81,0.89-3.42,2.26-4.4C12.92,3.04,12.46,3,12,3L12,3z"})})}const U={toggle:"toggle_vylO",toggleButton:"toggleButton_gllP",darkToggleIcon:"darkToggleIcon_wfgR",lightToggleIcon:"lightToggleIcon_pyhR",toggleButtonDisabled:"toggleButtonDisabled_aARS"};function H(e){let{className:t,buttonClassName:n,value:r,onChange:a}=e;const i=(0,D.c)(),l=(0,s.G)({message:"Switch between dark and light mode (currently {mode})",id:"theme.colorToggle.ariaLabel",description:"The ARIA label for the navbar color mode toggle"},{mode:"dark"===r?(0,s.G)({message:"dark mode",id:"theme.colorToggle.ariaLabel.mode.dark",description:"The name for the dark color mode"}):(0,s.G)({message:"light mode",id:"theme.colorToggle.ariaLabel.mode.light",description:"The name for the light color mode"})});return(0,u.jsx)("div",{className:(0,o.c)(U.toggle,t),children:(0,u.jsxs)("button",{className:(0,o.c)("clean-btn",U.toggleButton,!i&&U.toggleButtonDisabled,n),type:"button",onClick:()=>a("dark"===r?"light":"dark"),disabled:!i,title:l,"aria-label":l,"aria-live":"polite",children:[(0,u.jsx)(B,{className:(0,o.c)(U.toggleIcon,U.lightToggleIcon)}),(0,u.jsx)($,{className:(0,o.c)(U.toggleIcon,U.darkToggleIcon)})]})})}const W=r.memo(H),V={darkNavbarColorModeToggle:"darkNavbarColorModeToggle_X3D1"};function q(e){let{className:t}=e;const n=(0,w.y)().navbar.style,r=(0,w.y)().colorMode.disableSwitch,{colorMode:o,setColorMode:a}=(0,M.U)();return r?null:(0,u.jsx)(W,{className:t,buttonClassName:"dark"===n?V.darkNavbarColorModeToggle:void 0,value:o,onChange:a})}var G=n(8164);function Y(){return(0,u.jsx)(G.c,{className:"navbar__brand",imageClassName:"navbar__logo",titleClassName:"navbar__title text--truncate"})}function Q(){const e=(0,A.q)();return(0,u.jsx)("button",{type:"button","aria-label":(0,s.G)({id:"theme.docs.sidebar.closeSidebarButtonAriaLabel",message:"Close navigation bar",description:"The ARIA label for close button of mobile sidebar"}),className:"clean-btn navbar-sidebar__close",onClick:()=>e.toggle(),children:(0,u.jsx)(x,{color:"var(--ifm-color-emphasis-600)"})})}function K(){return(0,u.jsxs)("div",{className:"navbar-sidebar__brand",children:[(0,u.jsx)(Y,{}),(0,u.jsx)(q,{className:"margin-right--md"}),(0,u.jsx)(Q,{})]})}var Z=n(867),X=n(964),J=n(8136);function ee(e,t){return void 0!==e&&void 0!==t&&new RegExp(e,"gi").test(t)}var te=n(3232);function ne(e){let{activeBasePath:t,activeBaseRegex:n,to:r,href:o,label:a,html:i,isDropdownLink:l,prependBaseUrlToHref:s,...c}=e;const d=(0,X.c)(r),f=(0,X.c)(t),p=(0,X.c)(o,{forcePrependBaseUrl:!0}),m=a&&o&&!(0,J.c)(o),h=i?{dangerouslySetInnerHTML:{__html:i}}:{children:(0,u.jsxs)(u.Fragment,{children:[a,m&&(0,u.jsx)(te.c,{...l&&{width:12,height:12}})]})};return o?(0,u.jsx)(Z.c,{href:s?p:o,...c,...h}):(0,u.jsx)(Z.c,{to:d,isNavLink:!0,...(t||n)&&{isActive:(e,t)=>n?ee(n,t.pathname):t.pathname.startsWith(f)},...c,...h})}function re(e){let{className:t,isDropdownItem:n=!1,...r}=e;const a=(0,u.jsx)(ne,{className:(0,o.c)(n?"dropdown__link":"navbar__item navbar__link",t),isDropdownLink:n,...r});return n?(0,u.jsx)("li",{children:a}):a}function oe(e){let{className:t,isDropdownItem:n,...r}=e;return(0,u.jsx)("li",{className:"menu__list-item",children:(0,u.jsx)(ne,{className:(0,o.c)("menu__link",t),...r})})}function ae(e){let{mobile:t=!1,position:n,...r}=e;const o=t?oe:re;return(0,u.jsx)(o,{...r,activeClassName:r.activeClassName??(t?"menu__link--active":"navbar__link--active")})}var ie=n(8448),le=n(3376),se=n(8264);const ce={dropdownNavbarItemMobile:"dropdownNavbarItemMobile_S0Fm"};function ue(e,t){return e.some((e=>function(e,t){return!!(0,le.Sc)(e.to,t)||!!ee(e.activeBaseRegex,t)||!(!e.activeBasePath||!t.startsWith(e.activeBasePath))}(e,t)))}function de(e){let{items:t,position:n,className:a,onClick:i,...l}=e;const s=(0,r.useRef)(null),[c,d]=(0,r.useState)(!1);return(0,r.useEffect)((()=>{const e=e=>{s.current&&!s.current.contains(e.target)&&d(!1)};return document.addEventListener("mousedown",e),document.addEventListener("touchstart",e),document.addEventListener("focusin",e),()=>{document.removeEventListener("mousedown",e),document.removeEventListener("touchstart",e),document.removeEventListener("focusin",e)}}),[s]),(0,u.jsxs)("div",{ref:s,className:(0,o.c)("navbar__item","dropdown","dropdown--hoverable",{"dropdown--right":"right"===n,"dropdown--show":c}),children:[(0,u.jsx)(ne,{"aria-haspopup":"true","aria-expanded":c,role:"button",href:l.to?void 0:"#",className:(0,o.c)("navbar__link",a),...l,onClick:l.to?void 0:e=>e.preventDefault(),onKeyDown:e=>{"Enter"===e.key&&(e.preventDefault(),d(!c))},children:l.children??l.label}),(0,u.jsx)("ul",{className:"dropdown__menu",children:t.map(((e,t)=>(0,r.createElement)(_e,{isDropdownItem:!0,activeClassName:"dropdown__link--active",...e,key:t})))})]})}function fe(e){let{items:t,className:n,position:a,onClick:i,...s}=e;const c=function(){const{siteConfig:{baseUrl:e}}=(0,se.c)(),{pathname:t}=(0,l.IT)();return t.replace(e,"/")}(),d=ue(t,c),{collapsed:f,toggleCollapsed:p,setCollapsed:m}=(0,ie.a)({initialState:()=>!d});return(0,r.useEffect)((()=>{d&&m(!d)}),[c,d,m]),(0,u.jsxs)("li",{className:(0,o.c)("menu__list-item",{"menu__list-item--collapsed":f}),children:[(0,u.jsx)(ne,{role:"button",className:(0,o.c)(ce.dropdownNavbarItemMobile,"menu__link menu__link--sublist menu__link--sublist-caret",n),...s,onClick:e=>{e.preventDefault(),p()},children:s.children??s.label}),(0,u.jsx)(ie.U,{lazy:!0,as:"ul",className:"menu__list",collapsed:f,children:t.map(((e,t)=>(0,r.createElement)(_e,{mobile:!0,isDropdownItem:!0,onClick:i,activeClassName:"menu__link--active",...e,key:t})))})]})}function pe(e){let{mobile:t=!1,...n}=e;const r=t?fe:de;return(0,u.jsx)(r,{...n})}var me=n(1616);function he(e){let{width:t=20,height:n=20,...r}=e;return(0,u.jsx)("svg",{viewBox:"0 0 24 24",width:t,height:n,"aria-hidden":!0,...r,children:(0,u.jsx)("path",{fill:"currentColor",d:"M12.87 15.07l-2.54-2.51.03-.03c1.74-1.94 2.98-4.17 3.71-6.53H17V4h-7V2H8v2H1v1.99h11.17C11.5 7.92 10.44 9.75 9 11.35 8.07 10.32 7.3 9.19 6.69 8h-2c.73 1.63 1.73 3.17 2.98 4.56l-5.09 5.02L4 19l5-5 3.11 3.11.76-2.04zM18.5 10h-2L12 22h2l1.12-3h4.75L21 22h2l-4.5-12zm-2.62 7l1.62-4.33L19.12 17h-3.24z"})})}const ge="iconLanguage_nlXk";var ye=n(2944);const be={navbarSearchContainer:"navbarSearchContainer_Bca1"};function ve(e){let{children:t,className:n}=e;return(0,u.jsx)("div",{className:(0,o.c)(n,be.navbarSearchContainer),children:t})}var we=n(2840),ke=n(5492);var xe=n(4592);const Se=e=>e.docs.find((t=>t.id===e.mainDocId));const Ee={default:ae,localeDropdown:function(e){let{mobile:t,dropdownItemsBefore:n,dropdownItemsAfter:r,queryString:o="",...a}=e;const{i18n:{currentLocale:i,locales:c,localeConfigs:d}}=(0,se.c)(),f=(0,me.D)(),{search:p,hash:m}=(0,l.IT)(),h=[...n,...c.map((e=>{const n=`${`pathname://${f.createUrl({locale:e,fullyQualified:!1})}`}${p}${m}${o}`;return{label:d[e].label,lang:d[e].htmlLang,to:n,target:"_self",autoAddBaseUrl:!1,className:e===i?t?"menu__link--active":"dropdown__link--active":""}})),...r],g=t?(0,s.G)({message:"Languages",id:"theme.navbar.mobileLanguageDropdown.label",description:"The label for the mobile language switcher dropdown"}):d[i].label;return(0,u.jsx)(pe,{...a,mobile:t,label:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(he,{className:ge}),g]}),items:h})},search:function(e){let{mobile:t,className:n}=e;return t?null:(0,u.jsx)(ve,{className:n,children:(0,u.jsx)(ye.c,{})})},dropdown:pe,html:function(e){let{value:t,className:n,mobile:r=!1,isDropdownItem:a=!1}=e;const i=a?"li":"div";return(0,u.jsx)(i,{className:(0,o.c)({navbar__item:!r&&!a,"menu__list-item":r},n),dangerouslySetInnerHTML:{__html:t}})},doc:function(e){let{docId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,we.wB)(r),i=(0,ke.Qf)(t,r),l=a?.path===i?.path;return null===i||i.unlisted&&!l?null:(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>l||!!a?.sidebar&&a.sidebar===i.sidebar,label:n??i.id,to:i.path})},docSidebar:function(e){let{sidebarId:t,label:n,docsPluginId:r,...o}=e;const{activeDoc:a}=(0,we.wB)(r),i=(0,ke.Ab)(t,r).link;if(!i)throw new Error(`DocSidebarNavbarItem: Sidebar with ID "${t}" doesn't have anything to be linked to.`);return(0,u.jsx)(ae,{exact:!0,...o,isActive:()=>a?.sidebar===t,label:n??i.label,to:i.path})},docsVersion:function(e){let{label:t,to:n,docsPluginId:r,...o}=e;const a=(0,ke.b7)(r)[0],i=t??a.label,l=n??(e=>e.docs.find((t=>t.id===e.mainDocId)))(a).path;return(0,u.jsx)(ae,{...o,label:i,to:l})},docsVersionDropdown:function(e){let{mobile:t,docsPluginId:n,dropdownActiveClassDisabled:r,dropdownItemsBefore:o,dropdownItemsAfter:a,...i}=e;const{search:c,hash:d}=(0,l.IT)(),f=(0,we.wB)(n),p=(0,we.gN)(n),{savePreferredVersionName:m}=(0,xe.iy)(n),h=[...o,...p.map((e=>{const t=f.alternateDocVersions[e.name]??Se(e);return{label:e.label,to:`${t.path}${c}${d}`,isActive:()=>e===f.activeVersion,onClick:()=>m(e.name)}})),...a],g=(0,ke.b7)(n)[0],y=t&&h.length>1?(0,s.G)({id:"theme.navbar.mobileVersionsDropdown.label",message:"Versions",description:"The label for the navbar versions dropdown on mobile view"}):g.label,b=t&&h.length>1?void 0:Se(g).path;return h.length<=1?(0,u.jsx)(ae,{...i,mobile:t,label:y,to:b,isActive:r?()=>!1:void 0}):(0,u.jsx)(pe,{...i,mobile:t,label:y,to:b,items:h,isActive:r?()=>!1:void 0})}};function _e(e){let{type:t,...n}=e;const r=function(e,t){return e&&"default"!==e?e:"items"in t?"dropdown":"default"}(t,n),o=Ee[r];if(!o)throw new Error(`No NavbarItem component found for type "${t}".`);return(0,u.jsx)(o,{...n})}function Ce(){const e=(0,A.q)(),t=(0,w.y)().navbar.items;return(0,u.jsx)("ul",{className:"menu__list",children:t.map(((t,n)=>(0,r.createElement)(_e,{mobile:!0,...t,onClick:()=>e.toggle(),key:n})))})}function Te(e){return(0,u.jsx)("button",{...e,type:"button",className:"clean-btn navbar-sidebar__back",children:(0,u.jsx)(s.c,{id:"theme.navbar.mobileSidebarSecondaryMenu.backButtonLabel",description:"The label of the back button to return to main menu, inside the mobile navbar sidebar secondary menu (notably used to display the docs sidebar)",children:"\u2190 Back to main menu"})})}function Ne(){const e=0===(0,w.y)().navbar.items.length,t=I();return(0,u.jsxs)(u.Fragment,{children:[!e&&(0,u.jsx)(Te,{onClick:()=>t.hide()}),t.content]})}function Ae(){const e=(0,A.q)();var t;return void 0===(t=e.shown)&&(t=!0),(0,r.useEffect)((()=>(document.body.style.overflow=t?"hidden":"visible",()=>{document.body.style.overflow="visible"})),[t]),e.shouldRender?(0,u.jsx)(F,{header:(0,u.jsx)(K,{}),primaryMenu:(0,u.jsx)(Ce,{}),secondaryMenu:(0,u.jsx)(Ne,{})}):null}const Le={navbarHideable:"navbarHideable_m1mJ",navbarHidden:"navbarHidden_jGov"};function je(e){return(0,u.jsx)("div",{role:"presentation",...e,className:(0,o.c)("navbar-sidebar__backdrop",e.className)})}function Oe(e){let{children:t}=e;const{navbar:{hideOnScroll:n,style:a}}=(0,w.y)(),i=(0,A.q)(),{navbarRef:l,isNavbarVisible:d}=function(e){const[t,n]=(0,r.useState)(e),o=(0,r.useRef)(!1),a=(0,r.useRef)(0),i=(0,r.useCallback)((e=>{null!==e&&(a.current=e.getBoundingClientRect().height)}),[]);return(0,L.SM)(((t,r)=>{let{scrollY:i}=t;if(!e)return;if(i=l?n(!1):i+c{if(!e)return;const r=t.location.hash;if(r?document.getElementById(r.substring(1)):void 0)return o.current=!0,void n(!1);n(!0)})),{navbarRef:i,isNavbarVisible:t}}(n);return(0,u.jsxs)("nav",{ref:l,"aria-label":(0,s.G)({id:"theme.NavBar.navAriaLabel",message:"Main",description:"The ARIA label for the main navigation"}),className:(0,o.c)("navbar","navbar--fixed-top",n&&[Le.navbarHideable,!d&&Le.navbarHidden],{"navbar--dark":"dark"===a,"navbar--primary":"primary"===a,"navbar-sidebar--show":i.shown}),children:[t,(0,u.jsx)(je,{onClick:i.toggle}),(0,u.jsx)(Ae,{})]})}var Pe=n(5684);const ze={errorBoundaryError:"errorBoundaryError_a6uf",errorBoundaryFallback:"errorBoundaryFallback_VBag"};function Re(e){return(0,u.jsx)("button",{type:"button",...e,children:(0,u.jsx)(s.c,{id:"theme.ErrorPageContent.tryAgain",description:"The label of the button to try again rendering when the React error boundary captures an error",children:"Try again"})})}function Ie(e){let{error:t}=e;const n=(0,Pe.getErrorCausalChain)(t).map((e=>e.message)).join("\n\nCause:\n");return(0,u.jsx)("p",{className:ze.errorBoundaryError,children:n})}class Fe extends r.Component{componentDidCatch(e,t){throw this.props.onError(e,t)}render(){return this.props.children}}const Me="right";function De(e){let{width:t=30,height:n=30,className:r,...o}=e;return(0,u.jsx)("svg",{className:r,width:t,height:n,viewBox:"0 0 30 30","aria-hidden":"true",...o,children:(0,u.jsx)("path",{stroke:"currentColor",strokeLinecap:"round",strokeMiterlimit:"10",strokeWidth:"2",d:"M4 7h22M4 15h22M4 23h22"})})}function Be(){const{toggle:e,shown:t}=(0,A.q)();return(0,u.jsx)("button",{onClick:e,"aria-label":(0,s.G)({id:"theme.docs.sidebar.toggleSidebarButtonAriaLabel",message:"Toggle navigation bar",description:"The ARIA label for hamburger menu button of mobile navigation"}),"aria-expanded":t,className:"navbar__toggle clean-btn",type:"button",children:(0,u.jsx)(De,{})})}const $e={colorModeToggle:"colorModeToggle_DEke"};function Ue(e){let{items:t}=e;return(0,u.jsx)(u.Fragment,{children:t.map(((e,t)=>(0,u.jsx)(Fe,{onError:t=>new Error(`A theme navbar item failed to render.\nPlease double-check the following navbar item (themeConfig.navbar.items) of your Docusaurus config:\n${JSON.stringify(e,null,2)}`,{cause:t}),children:(0,u.jsx)(_e,{...e})},t)))})}function He(e){let{left:t,right:n}=e;return(0,u.jsxs)("div",{className:"navbar__inner",children:[(0,u.jsx)("div",{className:"navbar__items",children:t}),(0,u.jsx)("div",{className:"navbar__items navbar__items--right",children:n})]})}function We(){const e=(0,A.q)(),t=(0,w.y)().navbar.items,[n,r]=function(e){function t(e){return"left"===(e.position??Me)}return[e.filter(t),e.filter((e=>!t(e)))]}(t),o=t.find((e=>"search"===e.type));return(0,u.jsx)(He,{left:(0,u.jsxs)(u.Fragment,{children:[!e.disabled&&(0,u.jsx)(Be,{}),(0,u.jsx)(Y,{}),(0,u.jsx)(Ue,{items:n})]}),right:(0,u.jsxs)(u.Fragment,{children:[(0,u.jsx)(Ue,{items:r}),(0,u.jsx)(q,{className:$e.colorModeToggle}),!o&&(0,u.jsx)(ve,{children:(0,u.jsx)(ye.c,{})})]})})}function Ve(){return(0,u.jsx)(Oe,{children:(0,u.jsx)(We,{})})}function qe(e){let{item:t}=e;const{to:n,href:r,label:o,prependBaseUrlToHref:a,...i}=t,l=(0,X.c)(n),s=(0,X.c)(r,{forcePrependBaseUrl:!0});return(0,u.jsxs)(Z.c,{className:"footer__link-item",...r?{href:a?s:r}:{to:l},...i,children:[o,r&&!(0,J.c)(r)&&(0,u.jsx)(te.c,{})]})}function Ge(e){let{item:t}=e;return t.html?(0,u.jsx)("li",{className:"footer__item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)("li",{className:"footer__item",children:(0,u.jsx)(qe,{item:t})},t.href??t.to)}function Ye(e){let{column:t}=e;return(0,u.jsxs)("div",{className:"col footer__col",children:[(0,u.jsx)("div",{className:"footer__title",children:t.title}),(0,u.jsx)("ul",{className:"footer__items clean-list",children:t.items.map(((e,t)=>(0,u.jsx)(Ge,{item:e},t)))})]})}function Qe(e){let{columns:t}=e;return(0,u.jsx)("div",{className:"row footer__links",children:t.map(((e,t)=>(0,u.jsx)(Ye,{column:e},t)))})}function Ke(){return(0,u.jsx)("span",{className:"footer__link-separator",children:"\xb7"})}function Ze(e){let{item:t}=e;return t.html?(0,u.jsx)("span",{className:"footer__link-item",dangerouslySetInnerHTML:{__html:t.html}}):(0,u.jsx)(qe,{item:t})}function Xe(e){let{links:t}=e;return(0,u.jsx)("div",{className:"footer__links text--center",children:(0,u.jsx)("div",{className:"footer__links",children:t.map(((e,n)=>(0,u.jsxs)(r.Fragment,{children:[(0,u.jsx)(Ze,{item:e}),t.length!==n+1&&(0,u.jsx)(Ke,{})]},n)))})})}function Je(e){let{links:t}=e;return function(e){return"title"in e[0]}(t)?(0,u.jsx)(Qe,{columns:t}):(0,u.jsx)(Xe,{links:t})}var et=n(1964);const tt={footerLogoLink:"footerLogoLink_BH7S"};function nt(e){let{logo:t}=e;const{withBaseUrl:n}=(0,X.E)(),r={light:n(t.src),dark:n(t.srcDark??t.src)};return(0,u.jsx)(et.c,{className:(0,o.c)("footer__logo",t.className),alt:t.alt,sources:r,width:t.width,height:t.height,style:t.style})}function rt(e){let{logo:t}=e;return t.href?(0,u.jsx)(Z.c,{href:t.href,className:tt.footerLogoLink,target:t.target,children:(0,u.jsx)(nt,{logo:t})}):(0,u.jsx)(nt,{logo:t})}function ot(e){let{copyright:t}=e;return(0,u.jsx)("div",{className:"footer__copyright",dangerouslySetInnerHTML:{__html:t}})}function at(e){let{style:t,links:n,logo:r,copyright:a}=e;return(0,u.jsx)("footer",{className:(0,o.c)("footer",{"footer--dark":"dark"===t}),children:(0,u.jsxs)("div",{className:"container container-fluid",children:[n,(r||a)&&(0,u.jsxs)("div",{className:"footer__bottom text--center",children:[r&&(0,u.jsx)("div",{className:"margin-bottom--sm",children:r}),a]})]})})}function it(){const{footer:e}=(0,w.y)();if(!e)return null;const{copyright:t,links:n,logo:r,style:o}=e;return(0,u.jsx)(at,{style:o,links:n&&n.length>0&&(0,u.jsx)(Je,{links:n}),logo:r&&(0,u.jsx)(rt,{logo:r}),copyright:t&&(0,u.jsx)(ot,{copyright:t})})}const lt=r.memo(it),st=(0,j.qY)([M.C,k.qu,L.S2,xe.gc,i.w7,function(e){let{children:t}=e;return(0,u.jsx)(O.Ub,{children:(0,u.jsx)(A.y,{children:(0,u.jsx)(z,{children:t})})})}]);function ct(e){let{children:t}=e;return(0,u.jsx)(st,{children:t})}var ut=n(6448);function dt(e){let{error:t,tryAgain:n}=e;return(0,u.jsx)("main",{className:"container margin-vert--xl",children:(0,u.jsx)("div",{className:"row",children:(0,u.jsxs)("div",{className:"col col--6 col--offset-3",children:[(0,u.jsx)(ut.c,{as:"h1",className:"hero__title",children:(0,u.jsx)(s.c,{id:"theme.ErrorPageContent.title",description:"The title of the fallback page when the page crashed",children:"This page crashed."})}),(0,u.jsx)("div",{className:"margin-vert--lg",children:(0,u.jsx)(Re,{onClick:n,className:"button button--primary shadow--lw"})}),(0,u.jsx)("hr",{}),(0,u.jsx)("div",{className:"margin-vert--md",children:(0,u.jsx)(Ie,{error:t})})]})})})}const ft={mainWrapper:"mainWrapper_z2l0"};function pt(e){const{children:t,noFooter:n,wrapperClassName:r,title:l,description:s}=e;return(0,y.W)(),(0,u.jsxs)(ct,{children:[(0,u.jsx)(i.U7,{title:l,description:s}),(0,u.jsx)(v,{}),(0,u.jsx)(N,{}),(0,u.jsx)(Ve,{}),(0,u.jsx)("div",{id:d,className:(0,o.c)(g.W.wrapper.main,ft.mainWrapper,r),children:(0,u.jsx)(a.c,{fallback:e=>(0,u.jsx)(dt,{...e}),children:t})}),!n&&(0,u.jsx)(lt,{})]})}},8164:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});n(1504);var r=n(867),o=n(964),a=n(8264),i=n(1824),l=n(1964),s=n(7624);function c(e){let{logo:t,alt:n,imageClassName:r}=e;const a={light:(0,o.c)(t.src),dark:(0,o.c)(t.srcDark||t.src)},i=(0,s.jsx)(l.c,{className:t.className,sources:a,height:t.height,width:t.width,alt:n,style:t.style});return r?(0,s.jsx)("div",{className:r,children:i}):i}function u(e){const{siteConfig:{title:t}}=(0,a.c)(),{navbar:{title:n,logo:l}}=(0,i.y)(),{imageClassName:u,titleClassName:d,...f}=e,p=(0,o.c)(l?.href||"/"),m=n?"":t,h=l?.alt??m;return(0,s.jsxs)(r.c,{to:p,...f,...l?.target&&{target:l.target},children:[l&&(0,s.jsx)(c,{logo:l,alt:h,imageClassName:u}),null!=n&&(0,s.jsx)("b",{className:d,children:n})]})}},8712:(e,t,n)=>{"use strict";n.d(t,{c:()=>a});n(1504);var r=n(6952),o=n(7624);function a(e){let{locale:t,version:n,tag:a}=e;const i=t;return(0,o.jsxs)(r.c,{children:[t&&(0,o.jsx)("meta",{name:"docusaurus_locale",content:t}),n&&(0,o.jsx)("meta",{name:"docusaurus_version",content:n}),a&&(0,o.jsx)("meta",{name:"docusaurus_tag",content:a}),i&&(0,o.jsx)("meta",{name:"docsearch:language",content:i}),n&&(0,o.jsx)("meta",{name:"docsearch:version",content:n}),a&&(0,o.jsx)("meta",{name:"docsearch:docusaurus_tag",content:a})]})}},1964:(e,t,n)=>{"use strict";n.d(t,{c:()=>u});var r=n(1504),o=n(5456),a=n(3664),i=n(6528);const l={themedComponent:"themedComponent_mlkZ","themedComponent--light":"themedComponent--light_NVdE","themedComponent--dark":"themedComponent--dark_xIcU"};var s=n(7624);function c(e){let{className:t,children:n}=e;const c=(0,a.c)(),{colorMode:u}=(0,i.U)();return(0,s.jsx)(s.Fragment,{children:(c?"dark"===u?["dark"]:["light"]:["light","dark"]).map((e=>{const a=n({theme:e,className:(0,o.c)(t,l.themedComponent,l[`themedComponent--${e}`])});return(0,s.jsx)(r.Fragment,{children:a},e)}))})}function u(e){const{sources:t,className:n,alt:r,...o}=e;return(0,s.jsx)(c,{className:n,children:e=>{let{theme:n,className:a}=e;return(0,s.jsx)("img",{src:t[n],alt:r,className:a,...o})}})}},8448:(e,t,n)=>{"use strict";n.d(t,{U:()=>y,a:()=>c});var r=n(1504),o=n(8684),a=n(5288),i=n(3856),l=n(7624);const s="ease-in-out";function c(e){let{initialState:t}=e;const[n,o]=(0,r.useState)(t??!1),a=(0,r.useCallback)((()=>{o((e=>!e))}),[]);return{collapsed:n,setCollapsed:o,toggleCollapsed:a}}const u={display:"none",overflow:"hidden",height:"0px"},d={display:"block",overflow:"visible",height:"auto"};function f(e,t){const n=t?u:d;e.style.display=n.display,e.style.overflow=n.overflow,e.style.height=n.height}function p(e){let{collapsibleRef:t,collapsed:n,animation:o}=e;const a=(0,r.useRef)(!1);(0,r.useEffect)((()=>{const e=t.current;function r(){const t=e.scrollHeight,n=o?.duration??function(e){if((0,i.I)())return 1;const t=e/36;return Math.round(10*(4+15*t**.25+t/5))}(t);return{transition:`height ${n}ms ${o?.easing??s}`,height:`${t}px`}}function l(){const t=r();e.style.transition=t.transition,e.style.height=t.height}if(!a.current)return f(e,n),void(a.current=!0);return e.style.willChange="height",function(){const t=requestAnimationFrame((()=>{n?(l(),requestAnimationFrame((()=>{e.style.height=u.height,e.style.overflow=u.overflow}))):(e.style.display="block",requestAnimationFrame((()=>{l()})))}));return()=>cancelAnimationFrame(t)}()}),[t,n,o])}function m(e){if(!o.c.canUseDOM)return e?u:d}function h(e){let{as:t="div",collapsed:n,children:o,animation:a,onCollapseTransitionEnd:i,className:s,disableSSRStyle:c}=e;const u=(0,r.useRef)(null);return p({collapsibleRef:u,collapsed:n,animation:a}),(0,l.jsx)(t,{ref:u,style:c?void 0:m(n),onTransitionEnd:e=>{"height"===e.propertyName&&(f(u.current,n),i?.(n))},className:s,children:o})}function g(e){let{collapsed:t,...n}=e;const[o,i]=(0,r.useState)(!t),[s,c]=(0,r.useState)(t);return(0,a.c)((()=>{t||i(!0)}),[t]),(0,a.c)((()=>{o&&c(t)}),[o,t]),o?(0,l.jsx)(h,{...n,collapsed:s}):null}function y(e){let{lazy:t,...n}=e;const r=t?g:h;return(0,l.jsx)(r,{...n})}},3868:(e,t,n)=>{"use strict";n.d(t,{el:()=>h,qu:()=>m});var r=n(1504),o=n(3664),a=n(1148),i=n(1100),l=n(1824),s=n(7624);const c=(0,a.GS)("docusaurus.announcement.dismiss"),u=(0,a.GS)("docusaurus.announcement.id"),d=()=>"true"===c.get(),f=e=>c.set(String(e)),p=r.createContext(null);function m(e){let{children:t}=e;const n=function(){const{announcementBar:e}=(0,l.y)(),t=(0,o.c)(),[n,a]=(0,r.useState)((()=>!!t&&d()));(0,r.useEffect)((()=>{a(d())}),[]);const i=(0,r.useCallback)((()=>{f(!0),a(!0)}),[]);return(0,r.useEffect)((()=>{if(!e)return;const{id:t}=e;let n=u.get();"annoucement-bar"===n&&(n="announcement-bar");const r=t!==n;u.set(t),r&&f(!1),!r&&d()||a(!1)}),[e]),(0,r.useMemo)((()=>({isActive:!!e&&!n,close:i})),[e,n,i])}();return(0,s.jsx)(p.Provider,{value:n,children:t})}function h(){const e=(0,r.useContext)(p);if(!e)throw new i.AH("AnnouncementBarProvider");return e}},6528:(e,t,n)=>{"use strict";n.d(t,{C:()=>g,U:()=>y});var r=n(1504),o=n(8684),a=n(1100),i=n(1148),l=n(1824),s=n(7624);const c=r.createContext(void 0),u="theme",d=(0,i.GS)(u),f={light:"light",dark:"dark"},p=e=>e===f.dark?f.dark:f.light,m=e=>o.c.canUseDOM?p(document.documentElement.getAttribute("data-theme")):p(e),h=e=>{d.set(p(e))};function g(e){let{children:t}=e;const n=function(){const{colorMode:{defaultMode:e,disableSwitch:t,respectPrefersColorScheme:n}}=(0,l.y)(),[o,a]=(0,r.useState)(m(e));(0,r.useEffect)((()=>{t&&d.del()}),[t]);const i=(0,r.useCallback)((function(t,r){void 0===r&&(r={});const{persist:o=!0}=r;t?(a(t),o&&h(t)):(a(n?window.matchMedia("(prefers-color-scheme: dark)").matches?f.dark:f.light:e),d.del())}),[n,e]);(0,r.useEffect)((()=>{document.documentElement.setAttribute("data-theme",p(o))}),[o]),(0,r.useEffect)((()=>{if(t)return;const e=e=>{if(e.key!==u)return;const t=d.get();null!==t&&i(p(t))};return window.addEventListener("storage",e),()=>window.removeEventListener("storage",e)}),[t,i]);const s=(0,r.useRef)(!1);return(0,r.useEffect)((()=>{if(t&&!n)return;const e=window.matchMedia("(prefers-color-scheme: dark)"),r=()=>{window.matchMedia("print").matches||s.current?s.current=window.matchMedia("print").matches:i(null)};return e.addListener(r),()=>e.removeListener(r)}),[i,t,n]),(0,r.useMemo)((()=>({colorMode:o,setColorMode:i,get isDarkTheme(){return o===f.dark},setLightTheme(){i(f.light)},setDarkTheme(){i(f.dark)}})),[o,i])}();return(0,s.jsx)(c.Provider,{value:n,children:t})}function y(){const e=(0,r.useContext)(c);if(null==e)throw new a.AH("ColorModeProvider","Please see https://docusaurus.io/docs/api/themes/configuration#use-color-mode.");return e}},4592:(e,t,n)=>{"use strict";n.d(t,{gc:()=>y,iy:()=>v});var r=n(1504),o=n(2840),a=n(2488),i=n(1824),l=n(5492),s=n(1100),c=n(1148),u=n(7624);const d=e=>`docs-preferred-version-${e}`,f={save:(e,t,n)=>{(0,c.GS)(d(e),{persistence:t}).set(n)},read:(e,t)=>(0,c.GS)(d(e),{persistence:t}).get(),clear:(e,t)=>{(0,c.GS)(d(e),{persistence:t}).del()}},p=e=>Object.fromEntries(e.map((e=>[e,{preferredVersionName:null}])));const m=r.createContext(null);function h(){const e=(0,o.L0)(),t=(0,i.y)().docs.versionPersistence,n=(0,r.useMemo)((()=>Object.keys(e)),[e]),[a,l]=(0,r.useState)((()=>p(n)));(0,r.useEffect)((()=>{l(function(e){let{pluginIds:t,versionPersistence:n,allDocsData:r}=e;function o(e){const t=f.read(e,n);return r[e].versions.some((e=>e.name===t))?{preferredVersionName:t}:(f.clear(e,n),{preferredVersionName:null})}return Object.fromEntries(t.map((e=>[e,o(e)])))}({allDocsData:e,versionPersistence:t,pluginIds:n}))}),[e,t,n]);return[a,(0,r.useMemo)((()=>({savePreferredVersion:function(e,n){f.save(e,t,n),l((t=>({...t,[e]:{preferredVersionName:n}})))}})),[t])]}function g(e){let{children:t}=e;const n=h();return(0,u.jsx)(m.Provider,{value:n,children:t})}function y(e){let{children:t}=e;return l.c1?(0,u.jsx)(g,{children:t}):(0,u.jsx)(u.Fragment,{children:t})}function b(){const e=(0,r.useContext)(m);if(!e)throw new s.AH("DocsPreferredVersionContextProvider");return e}function v(e){void 0===e&&(e=a.M);const t=(0,o.OK)(e),[n,i]=b(),{preferredVersionName:l}=n[e];return{preferredVersion:t.versions.find((e=>e.name===l))??null,savePreferredVersionName:(0,r.useCallback)((t=>{i.savePreferredVersion(e,t)}),[i,e])}}},6192:(e,t,n)=>{"use strict";n.d(t,{m:()=>c,y:()=>s});var r=n(1504),o=n(1100),a=n(7624);const i=Symbol("EmptyContext"),l=r.createContext(i);function s(e){let{children:t,name:n,items:o}=e;const i=(0,r.useMemo)((()=>n&&o?{name:n,items:o}:null),[n,o]);return(0,a.jsx)(l.Provider,{value:i,children:t})}function c(){const e=(0,r.useContext)(l);if(e===i)throw new o.AH("DocsSidebarProvider");return e}},9920:(e,t,n)=>{"use strict";n.d(t,{E:()=>s,Q:()=>l});var r=n(1504),o=n(1100),a=n(7624);const i=r.createContext(null);function l(e){let{children:t,version:n}=e;return(0,a.jsx)(i.Provider,{value:n,children:t})}function s(){const e=(0,r.useContext)(i);if(null===e)throw new o.AH("DocsVersionProvider");return e}},8200:(e,t,n)=>{"use strict";n.d(t,{q:()=>p,y:()=>f});var r=n(1504),o=n(5168),a=n(1432),i=n(632),l=n(1824),s=n(1100),c=n(7624);const u=r.createContext(void 0);function d(){const e=function(){const e=(0,o.MF)(),{items:t}=(0,l.y)().navbar;return 0===t.length&&!e.component}(),t=(0,a.U)(),n=!e&&"mobile"===t,[s,c]=(0,r.useState)(!1);(0,i.a4)((()=>{if(s)return c(!1),!1}));const u=(0,r.useCallback)((()=>{c((e=>!e))}),[]);return(0,r.useEffect)((()=>{"desktop"===t&&c(!1)}),[t]),(0,r.useMemo)((()=>({disabled:e,shouldRender:n,toggle:u,shown:s})),[e,n,u,s])}function f(e){let{children:t}=e;const n=d();return(0,c.jsx)(u.Provider,{value:n,children:t})}function p(){const e=r.useContext(u);if(void 0===e)throw new s.AH("NavbarMobileSidebarProvider");return e}},5168:(e,t,n)=>{"use strict";n.d(t,{MF:()=>s,Mx:()=>c,Ub:()=>l});var r=n(1504),o=n(1100),a=n(7624);const i=r.createContext(null);function l(e){let{children:t}=e;const n=(0,r.useState)({component:null,props:null});return(0,a.jsx)(i.Provider,{value:n,children:t})}function s(){const e=(0,r.useContext)(i);if(!e)throw new o.AH("NavbarSecondaryMenuContentProvider");return e[0]}function c(e){let{component:t,props:n}=e;const a=(0,r.useContext)(i);if(!a)throw new o.AH("NavbarSecondaryMenuContentProvider");const[,l]=a,s=(0,o.Mh)(n);return(0,r.useEffect)((()=>{l({component:t,props:s})}),[l,t,s]),(0,r.useEffect)((()=>()=>l({component:null,props:null})),[l]),null}},204:(e,t,n)=>{"use strict";n.d(t,{m:()=>o,W:()=>a});var r=n(1504);const o="navigation-with-keyboard";function a(){(0,r.useEffect)((()=>{function e(e){"keydown"===e.type&&"Tab"===e.key&&document.body.classList.add(o),"mousedown"===e.type&&document.body.classList.remove(o)}return document.addEventListener("keydown",e),document.addEventListener("mousedown",e),()=>{document.body.classList.remove(o),document.removeEventListener("keydown",e),document.removeEventListener("mousedown",e)}}),[])}},1432:(e,t,n)=>{"use strict";n.d(t,{U:()=>l});var r=n(1504),o=n(8684);const a={desktop:"desktop",mobile:"mobile",ssr:"ssr"},i=996;function l(e){let{desktopBreakpoint:t=i}=void 0===e?{}:e;const[n,l]=(0,r.useState)((()=>"ssr"));return(0,r.useEffect)((()=>{function e(){l(function(e){if(!o.c.canUseDOM)throw new Error("getWindowSize() should only be called after React hydration");return window.innerWidth>e?a.desktop:a.mobile}(t))}return e(),window.addEventListener("resize",e),()=>{window.removeEventListener("resize",e)}}),[t]),n}},5864:(e,t,n)=>{"use strict";n.d(t,{W:()=>r});const r={page:{blogListPage:"blog-list-page",blogPostPage:"blog-post-page",blogTagsListPage:"blog-tags-list-page",blogTagPostListPage:"blog-tags-post-list-page",docsDocPage:"docs-doc-page",docsTagsListPage:"docs-tags-list-page",docsTagDocListPage:"docs-tags-doc-list-page",mdxPage:"mdx-page"},wrapper:{main:"main-wrapper",blogPages:"blog-wrapper",docsPages:"docs-wrapper",mdxPages:"mdx-wrapper"},common:{editThisPage:"theme-edit-this-page",lastUpdated:"theme-last-updated",backToTopButton:"theme-back-to-top-button",codeBlock:"theme-code-block",admonition:"theme-admonition",unlistedBanner:"theme-unlisted-banner",admonitionType:e=>`theme-admonition-${e}`},layout:{},docs:{docVersionBanner:"theme-doc-version-banner",docVersionBadge:"theme-doc-version-badge",docBreadcrumbs:"theme-doc-breadcrumbs",docMarkdown:"theme-doc-markdown",docTocMobile:"theme-doc-toc-mobile",docTocDesktop:"theme-doc-toc-desktop",docFooter:"theme-doc-footer",docFooterTagsRow:"theme-doc-footer-tags-row",docFooterEditMetaRow:"theme-doc-footer-edit-meta-row",docSidebarContainer:"theme-doc-sidebar-container",docSidebarMenu:"theme-doc-sidebar-menu",docSidebarItemCategory:"theme-doc-sidebar-item-category",docSidebarItemLink:"theme-doc-sidebar-item-link",docSidebarItemCategoryLevel:e=>`theme-doc-sidebar-item-category-level-${e}`,docSidebarItemLinkLevel:e=>`theme-doc-sidebar-item-link-level-${e}`},blog:{}}},3856:(e,t,n)=>{"use strict";function r(){return window.matchMedia("(prefers-reduced-motion: reduce)").matches}n.d(t,{I:()=>r})},5492:(e,t,n)=>{"use strict";n.d(t,{Ab:()=>x,Gw:()=>p,Md:()=>g,Qf:()=>S,Uj:()=>E,b7:()=>k,c1:()=>f,js:()=>w,mg:()=>b});var r=n(1504),o=n(5592),a=n(5464),i=n(2840),l=n(4592),s=n(9920),c=n(6192),u=n(7128),d=n(3376);const f=!!i.L0;function p(e){return"link"!==e.type||e.unlisted?"category"===e.type?function(e){if(e.href&&!e.linkUnlisted)return e.href;for(const t of e.items){const e=p(t);if(e)return e}}(e):void 0:e.href}const m=(e,t)=>void 0!==e&&(0,d.Sc)(e,t),h=(e,t)=>e.some((e=>g(e,t)));function g(e,t){return"link"===e.type?m(e.href,t):"category"===e.type&&(m(e.href,t)||h(e.items,t))}function y(e,t){switch(e.type){case"category":return g(e,t)||e.items.some((e=>y(e,t)));case"link":return!e.unlisted||g(e,t);default:return!0}}function b(e,t){return(0,r.useMemo)((()=>e.filter((e=>y(e,t)))),[e,t])}function v(e){let{sidebarItems:t,pathname:n,onlyCategories:r=!1}=e;const o=[];return function e(t){for(const a of t)if("category"===a.type&&((0,d.Sc)(a.href,n)||e(a.items))||"link"===a.type&&(0,d.Sc)(a.href,n)){return r&&"category"!==a.type||o.unshift(a),!0}return!1}(t),o}function w(){const e=(0,c.m)(),{pathname:t}=(0,o.IT)(),n=(0,i.UF)()?.pluginData.breadcrumbs;return!1!==n&&e?v({sidebarItems:e.items,pathname:t}):null}function k(e){const{activeVersion:t}=(0,i.wB)(e),{preferredVersion:n}=(0,l.iy)(e),o=(0,i.aA)(e);return(0,r.useMemo)((()=>(0,u.U)([t,n,o].filter(Boolean))),[t,n,o])}function x(e,t){const n=k(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.sidebars?Object.entries(e.sidebars):[])),r=t.find((t=>t[0]===e));if(!r)throw new Error(`Can't find any sidebar with id "${e}" in version${n.length>1?"s":""} ${n.map((e=>e.name)).join(", ")}".\nAvailable sidebar ids are:\n- ${t.map((e=>e[0])).join("\n- ")}`);return r[1]}),[e,n])}function S(e,t){const n=k(t);return(0,r.useMemo)((()=>{const t=n.flatMap((e=>e.docs)),r=t.find((t=>t.id===e));if(!r){if(n.flatMap((e=>e.draftIds)).includes(e))return null;throw new Error(`Couldn't find any doc with id "${e}" in version${n.length>1?"s":""} "${n.map((e=>e.name)).join(", ")}".\nAvailable doc ids are:\n- ${(0,u.U)(t.map((e=>e.id))).join("\n- ")}`)}return r}),[e,n])}function E(e){let{route:t}=e;const n=(0,o.IT)(),r=(0,s.E)(),i=t.routes,l=i.find((e=>(0,o.ot)(n.pathname,e)));if(!l)return null;const c=l.sidebar,u=c?r.docsSidebars[c]:void 0;return{docElement:(0,a.k)(i),sidebarName:c,sidebarItems:u}}},632:(e,t,n)=>{"use strict";n.d(t,{_M:()=>l,a4:()=>i});var r=n(1504),o=n(5592),a=n(1100);function i(e){!function(e){const t=(0,o.Uz)(),n=(0,a.yA)(e);(0,r.useEffect)((()=>t.block(((e,t)=>n(e,t)))),[t,n])}(((t,n)=>{if("POP"===n)return e(t,n)}))}function l(e){return function(e){const t=(0,o.Uz)();return(0,r.useSyncExternalStore)(t.listen,(()=>e(t)),(()=>e(t)))}((t=>null===e?null:new URLSearchParams(t.location.search).get(e)))}},7128:(e,t,n)=>{"use strict";function r(e,t){return void 0===t&&(t=(e,t)=>e===t),e.filter(((n,r)=>e.findIndex((e=>t(e,n)))!==r))}function o(e){return Array.from(new Set(e))}n.d(t,{U:()=>o,w:()=>r})},5756:(e,t,n)=>{"use strict";n.d(t,{cr:()=>p,U7:()=>d,w7:()=>m});var r=n(1504),o=n(5456),a=n(6952),i=n(5548);function l(){const e=r.useContext(i.e);if(!e)throw new Error("Unexpected: no Docusaurus route context found");return e}var s=n(964),c=n(8264);var u=n(7624);function d(e){let{title:t,description:n,keywords:r,image:o,children:i}=e;const l=function(e){const{siteConfig:t}=(0,c.c)(),{title:n,titleDelimiter:r}=t;return e?.trim().length?`${e.trim()} ${r} ${n}`:n}(t),{withBaseUrl:d}=(0,s.E)(),f=o?d(o,{absolute:!0}):void 0;return(0,u.jsxs)(a.c,{children:[t&&(0,u.jsx)("title",{children:l}),t&&(0,u.jsx)("meta",{property:"og:title",content:l}),n&&(0,u.jsx)("meta",{name:"description",content:n}),n&&(0,u.jsx)("meta",{property:"og:description",content:n}),r&&(0,u.jsx)("meta",{name:"keywords",content:Array.isArray(r)?r.join(","):r}),f&&(0,u.jsx)("meta",{property:"og:image",content:f}),f&&(0,u.jsx)("meta",{name:"twitter:image",content:f}),i]})}const f=r.createContext(void 0);function p(e){let{className:t,children:n}=e;const i=r.useContext(f),l=(0,o.c)(i,t);return(0,u.jsxs)(f.Provider,{value:l,children:[(0,u.jsx)(a.c,{children:(0,u.jsx)("html",{className:l})}),n]})}function m(e){let{children:t}=e;const n=l(),r=`plugin-${n.plugin.name.replace(/docusaurus-(?:plugin|theme)-(?:content-)?/gi,"")}`;const a=`plugin-id-${n.plugin.id}`;return(0,u.jsx)(p,{className:(0,o.c)(r,a),children:t})}},1100:(e,t,n)=>{"use strict";n.d(t,{AH:()=>s,Mh:()=>c,i0:()=>l,qY:()=>u,yA:()=>i});var r=n(1504),o=n(5288),a=n(7624);function i(e){const t=(0,r.useRef)(e);return(0,o.c)((()=>{t.current=e}),[e]),(0,r.useCallback)((function(){return t.current(...arguments)}),[])}function l(e){const t=(0,r.useRef)();return(0,o.c)((()=>{t.current=e})),t.current}class s extends Error{constructor(e,t){super(),this.name="ReactContextError",this.message=`Hook ${this.stack?.split("\n")[1]?.match(/at (?:\w+\.)?(?\w+)/)?.groups.name??""} is called outside the <${e}>. ${t??""}`}}function c(e){const t=Object.entries(e);return t.sort(((e,t)=>e[0].localeCompare(t[0]))),(0,r.useMemo)((()=>e),t.flat())}function u(e){return t=>{let{children:n}=t;return(0,a.jsx)(a.Fragment,{children:e.reduceRight(((e,t)=>(0,a.jsx)(t,{children:e})),n)})}}},3376:(e,t,n)=>{"use strict";n.d(t,{Sc:()=>i,Y5:()=>l});var r=n(1504),o=n(628),a=n(8264);function i(e,t){const n=e=>(!e||e.endsWith("/")?e:`${e}/`)?.toLowerCase();return n(e)===n(t)}function l(){const{baseUrl:e}=(0,a.c)().siteConfig;return(0,r.useMemo)((()=>function(e){let{baseUrl:t,routes:n}=e;function r(e){return e.path===t&&!0===e.exact}function o(e){return e.path===t&&!e.exact}return function e(t){if(0===t.length)return;return t.find(r)||e(t.filter(o).flatMap((e=>e.routes??[])))}(n)}({routes:o.c,baseUrl:e})),[e])}},3943:(e,t,n)=>{"use strict";n.d(t,{MV:()=>m,S2:()=>u,SM:()=>p,yI:()=>h});var r=n(1504),o=n(8684),a=n(3664),i=n(5288),l=n(1100),s=n(7624);const c=r.createContext(void 0);function u(e){let{children:t}=e;const n=function(){const e=(0,r.useRef)(!0);return(0,r.useMemo)((()=>({scrollEventsEnabledRef:e,enableScrollEvents:()=>{e.current=!0},disableScrollEvents:()=>{e.current=!1}})),[])}();return(0,s.jsx)(c.Provider,{value:n,children:t})}function d(){const e=(0,r.useContext)(c);if(null==e)throw new l.AH("ScrollControllerProvider");return e}const f=()=>o.c.canUseDOM?{scrollX:window.pageXOffset,scrollY:window.pageYOffset}:null;function p(e,t){void 0===t&&(t=[]);const{scrollEventsEnabledRef:n}=d(),o=(0,r.useRef)(f()),a=(0,l.yA)(e);(0,r.useEffect)((()=>{const e=()=>{if(!n.current)return;const e=f();a(e,o.current),o.current=e},t={passive:!0};return e(),window.addEventListener("scroll",e,t),()=>window.removeEventListener("scroll",e,t)}),[a,n,...t])}function m(){const e=d(),t=function(){const e=(0,r.useRef)({elem:null,top:0}),t=(0,r.useCallback)((t=>{e.current={elem:t,top:t.getBoundingClientRect().top}}),[]),n=(0,r.useCallback)((()=>{const{current:{elem:t,top:n}}=e;if(!t)return{restored:!1};const r=t.getBoundingClientRect().top-n;return r&&window.scrollBy({left:0,top:r}),e.current={elem:null,top:0},{restored:0!==r}}),[]);return(0,r.useMemo)((()=>({save:t,restore:n})),[n,t])}(),n=(0,r.useRef)(void 0),o=(0,r.useCallback)((r=>{t.save(r),e.disableScrollEvents(),n.current=()=>{const{restored:r}=t.restore();if(n.current=void 0,r){const t=()=>{e.enableScrollEvents(),window.removeEventListener("scroll",t)};window.addEventListener("scroll",t)}else e.enableScrollEvents()}}),[e,t]);return(0,i.c)((()=>{queueMicrotask((()=>n.current?.()))})),{blockElementScrollPositionUntilNextRender:o}}function h(){const e=(0,r.useRef)(null),t=(0,a.c)()&&"smooth"===getComputedStyle(document.documentElement).scrollBehavior;return{startScroll:n=>{e.current=t?function(e){return window.scrollTo({top:e,behavior:"smooth"}),()=>{}}(n):function(e){let t=null;const n=document.documentElement.scrollTop>e;return function r(){const o=document.documentElement.scrollTop;(n&&o>e||!n&&ot&&cancelAnimationFrame(t)}(n)},cancelScroll:()=>e.current?.()}}},4456:(e,t,n)=>{"use strict";n.d(t,{SE:()=>o,e6:()=>r});n(8264);const r="default";function o(e,t){return`docs-${e}-${t}`}},1148:(e,t,n)=>{"use strict";n.d(t,{GS:()=>c,IN:()=>u});var r=n(1504);const o="localStorage";function a(e){let{key:t,oldValue:n,newValue:r,storage:o}=e;if(n===r)return;const a=document.createEvent("StorageEvent");a.initStorageEvent("storage",!1,!1,t,n,r,window.location.href,o),window.dispatchEvent(a)}function i(e){if(void 0===e&&(e=o),"undefined"==typeof window)throw new Error("Browser storage is not available on Node.js/Docusaurus SSR process.");if("none"===e)return null;try{return window[e]}catch(n){return t=n,l||(console.warn("Docusaurus browser storage is not available.\nPossible reasons: running Docusaurus in an iframe, in an incognito browser session, or using too strict browser privacy settings.",t),l=!0),null}var t}let l=!1;const s={get:()=>null,set:()=>{},del:()=>{},listen:()=>()=>{}};function c(e,t){if("undefined"==typeof window)return function(e){function t(){throw new Error(`Illegal storage API usage for storage key "${e}".\nDocusaurus storage APIs are not supposed to be called on the server-rendering process.\nPlease only call storage APIs in effects and event handlers.`)}return{get:t,set:t,del:t,listen:t}}(e);const n=i(t?.persistence);return null===n?s:{get:()=>{try{return n.getItem(e)}catch(t){return console.error(`Docusaurus storage error, can't get key=${e}`,t),null}},set:t=>{try{const r=n.getItem(e);n.setItem(e,t),a({key:e,oldValue:r,newValue:t,storage:n})}catch(r){console.error(`Docusaurus storage error, can't set ${e}=${t}`,r)}},del:()=>{try{const t=n.getItem(e);n.removeItem(e),a({key:e,oldValue:t,newValue:null,storage:n})}catch(t){console.error(`Docusaurus storage error, can't delete key=${e}`,t)}},listen:t=>{try{const r=r=>{r.storageArea===n&&r.key===e&&t(r)};return window.addEventListener("storage",r),()=>window.removeEventListener("storage",r)}catch(r){return console.error(`Docusaurus storage error, can't listen for changes of key=${e}`,r),()=>{}}}}}function u(e,t){const n=(0,r.useRef)((()=>null===e?s:c(e,t))).current(),o=(0,r.useCallback)((e=>"undefined"==typeof window?()=>{}:n.listen(e)),[n]);return[(0,r.useSyncExternalStore)(o,(()=>"undefined"==typeof window?null:n.get()),(()=>null)),n]}},1616:(e,t,n)=>{"use strict";n.d(t,{D:()=>i});var r=n(8264),o=n(5592),a=n(5684);function i(){const{siteConfig:{baseUrl:e,url:t,trailingSlash:n},i18n:{defaultLocale:i,currentLocale:l}}=(0,r.c)(),{pathname:s}=(0,o.IT)(),c=(0,a.applyTrailingSlash)(s,{trailingSlash:n,baseUrl:e}),u=l===i?e:e.replace(`/${l}/`,"/"),d=c.replace(e,"");return{createUrl:function(e){let{locale:n,fullyQualified:r}=e;return`${r?t:""}${function(e){return e===i?`${u}`:`${u}${e}/`}(n)}${d}`}}}},7124:(e,t,n)=>{"use strict";n.d(t,{c:()=>i});var r=n(1504),o=n(5592),a=n(1100);function i(e){const t=(0,o.IT)(),n=(0,a.i0)(t),i=(0,a.yA)(e);(0,r.useEffect)((()=>{n&&t!==n&&i({location:t,previousLocation:n})}),[i,t,n])}},1824:(e,t,n)=>{"use strict";n.d(t,{y:()=>o});var r=n(8264);function o(){return(0,r.c)().siteConfig.themeConfig}},1600:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.default=function(e,t){const{trailingSlash:n,baseUrl:r}=t;if(e.startsWith("#"))return e;if(void 0===n)return e;const[o]=e.split(/[#?]/),a="/"===o||o===r?o:(i=o,n?function(e){return e.endsWith("/")?e:`${e}/`}(i):function(e){return e.endsWith("/")?e.slice(0,-1):e}(i));var i;return e.replace(o,a)}},4292:(e,t)=>{"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=void 0,t.getErrorCausalChain=function e(t){return t.cause?[t,...e(t.cause)]:[t]}},5684:function(e,t,n){"use strict";var r=this&&this.__importDefault||function(e){return e&&e.__esModule?e:{default:e}};Object.defineProperty(t,"__esModule",{value:!0}),t.getErrorCausalChain=t.applyTrailingSlash=t.blogPostContainerID=void 0,t.blogPostContainerID="__blog-post-container";var o=n(1600);Object.defineProperty(t,"applyTrailingSlash",{enumerable:!0,get:function(){return r(o).default}});var a=n(4292);Object.defineProperty(t,"getErrorCausalChain",{enumerable:!0,get:function(){return a.getErrorCausalChain}})},6564:(e,t,n)=>{"use strict";n.r(t),n.d(t,{default:()=>p});var r=n(7768),o=Object.assign||function(e){for(var t=1;t1&&void 0!==arguments[1]?arguments[1]:{},r=window.Promise||function(e){function t(){}e(t,t)},a=function(){for(var e=arguments.length,t=Array(e),n=0;n0&&void 0!==arguments[0]?arguments[0]:{}).target,t=function(){var e={width:document.documentElement.clientWidth,height:document.documentElement.clientHeight,left:0,top:0,right:0,bottom:0},t=void 0,n=void 0;if(y.container)if(y.container instanceof Object)t=(e=o({},e,y.container)).width-e.left-e.right-2*y.margin,n=e.height-e.top-e.bottom-2*y.margin;else{var r=(i(y.container)?y.container:document.querySelector(y.container)).getBoundingClientRect(),a=r.width,s=r.height,c=r.left,u=r.top;e=o({},e,{width:a,height:s,left:c,top:u})}t=t||e.width-2*y.margin,n=n||e.height-2*y.margin;var d=b.zoomedHd||b.original,f=l(d)?t:d.naturalWidth||t,p=l(d)?n:d.naturalHeight||n,m=d.getBoundingClientRect(),h=m.top,g=m.left,v=m.width,w=m.height,k=Math.min(Math.max(v,f),t)/v,x=Math.min(Math.max(w,p),n)/w,S=Math.min(k,x),E="scale("+S+") translate3d("+((t-v)/2-g+y.margin+e.left)/S+"px, "+((n-w)/2-h+y.margin+e.top)/S+"px, 0)";b.zoomed.style.transform=E,b.zoomedHd&&(b.zoomedHd.style.transform=E)};return new r((function(n){if(e&&-1===p.indexOf(e))n(w);else{if(b.zoomed)n(w);else{if(e)b.original=e;else{if(!(p.length>0))return void n(w);var r=p;b.original=r[0]}if(b.original.dispatchEvent(c("medium-zoom:open",{detail:{zoom:w}})),g=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,h=!0,b.zoomed=function(e){var t=e.getBoundingClientRect(),n=t.top,r=t.left,o=t.width,a=t.height,i=e.cloneNode(),l=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0,s=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;return i.removeAttribute("id"),i.style.position="absolute",i.style.top=n+l+"px",i.style.left=r+s+"px",i.style.width=o+"px",i.style.height=a+"px",i.style.transform="",i}(b.original),document.body.appendChild(v),y.template){var o=i(y.template)?y.template:document.querySelector(y.template);b.template=document.createElement("div"),b.template.appendChild(o.content.cloneNode(!0)),document.body.appendChild(b.template)}if(b.original.parentElement&&"PICTURE"===b.original.parentElement.tagName&&b.original.currentSrc&&(b.zoomed.src=b.original.currentSrc),document.body.appendChild(b.zoomed),window.requestAnimationFrame((function(){document.body.classList.add("medium-zoom--opened")})),b.original.classList.add("medium-zoom-image--hidden"),b.zoomed.classList.add("medium-zoom-image--opened"),b.zoomed.addEventListener("click",d),b.zoomed.addEventListener("transitionend",(function e(){h=!1,b.zoomed.removeEventListener("transitionend",e),b.original.dispatchEvent(c("medium-zoom:opened",{detail:{zoom:w}})),n(w)})),b.original.getAttribute("data-zoom-src")){b.zoomedHd=b.zoomed.cloneNode(),b.zoomedHd.removeAttribute("srcset"),b.zoomedHd.removeAttribute("sizes"),b.zoomedHd.removeAttribute("loading"),b.zoomedHd.src=b.zoomed.getAttribute("data-zoom-src"),b.zoomedHd.onerror=function(){clearInterval(a),console.warn("Unable to reach the zoom image target "+b.zoomedHd.src),b.zoomedHd=null,t()};var a=setInterval((function(){b.zoomedHd.complete&&(clearInterval(a),b.zoomedHd.classList.add("medium-zoom-image--opened"),b.zoomedHd.addEventListener("click",d),document.body.appendChild(b.zoomedHd),t())}),10)}else if(b.original.hasAttribute("srcset")){b.zoomedHd=b.zoomed.cloneNode(),b.zoomedHd.removeAttribute("sizes"),b.zoomedHd.removeAttribute("loading");var l=b.zoomedHd.addEventListener("load",(function(){b.zoomedHd.removeEventListener("load",l),b.zoomedHd.classList.add("medium-zoom-image--opened"),b.zoomedHd.addEventListener("click",d),document.body.appendChild(b.zoomedHd),t()}))}else t()}}}))},d=function(){return new r((function(e){if(!h&&b.original){h=!0,document.body.classList.remove("medium-zoom--opened"),b.zoomed.style.transform="",b.zoomedHd&&(b.zoomedHd.style.transform=""),b.template&&(b.template.style.transition="opacity 150ms",b.template.style.opacity=0),b.original.dispatchEvent(c("medium-zoom:close",{detail:{zoom:w}})),b.zoomed.addEventListener("transitionend",(function t(){b.original.classList.remove("medium-zoom-image--hidden"),document.body.removeChild(b.zoomed),b.zoomedHd&&document.body.removeChild(b.zoomedHd),document.body.removeChild(v),b.zoomed.classList.remove("medium-zoom-image--opened"),b.template&&document.body.removeChild(b.template),h=!1,b.zoomed.removeEventListener("transitionend",t),b.original.dispatchEvent(c("medium-zoom:closed",{detail:{zoom:w}})),b.original=null,b.zoomed=null,b.zoomedHd=null,b.template=null,e(w)}))}else e(w)}))},f=function(){var e=(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}).target;return b.original?d():u({target:e})},p=[],m=[],h=!1,g=0,y=n,b={original:null,zoomed:null,zoomedHd:null,template:null};"[object Object]"===Object.prototype.toString.call(t)?y=t:(t||"string"==typeof t)&&a(t);var v=function(e){var t=document.createElement("div");return t.classList.add("medium-zoom-overlay"),t.style.background=e,t}((y=o({margin:0,background:"#fff",scrollOffset:40,container:null,template:null},y)).background);document.addEventListener("click",(function(e){var t=e.target;t!==v?-1!==p.indexOf(t)&&f({target:t}):d()})),document.addEventListener("keyup",(function(e){var t=e.key||e.keyCode;"Escape"!==t&&"Esc"!==t&&27!==t||d()})),document.addEventListener("scroll",(function(){if(!h&&b.original){var e=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;Math.abs(g-e)>y.scrollOffset&&setTimeout(d,150)}})),window.addEventListener("resize",d);var w={open:u,close:d,toggle:f,update:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},t=e;if(e.background&&(v.style.background=e.background),e.container&&e.container instanceof Object&&(t.container=o({},y.container,e.container)),e.template){var n=i(e.template)?e.template:document.querySelector(e.template);t.template=n}return y=o({},y,t),p.forEach((function(e){e.dispatchEvent(c("medium-zoom:update",{detail:{zoom:w}}))})),w},clone:function(){return e(o({},y,arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}))},attach:a,detach:function(){for(var e=arguments.length,t=Array(e),n=0;n0?t.reduce((function(e,t){return[].concat(e,s(t))}),[]):p;return r.forEach((function(e){e.classList.remove("medium-zoom-image"),e.dispatchEvent(c("medium-zoom:detach",{detail:{zoom:w}}))})),p=p.filter((function(e){return-1===r.indexOf(e)})),w},on:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return p.forEach((function(r){r.addEventListener("medium-zoom:"+e,t,n)})),m.push({type:"medium-zoom:"+e,listener:t,options:n}),w},off:function(e,t){var n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};return p.forEach((function(r){r.removeEventListener("medium-zoom:"+e,t,n)})),m=m.filter((function(n){return!(n.type==="medium-zoom:"+e&&n.listener.toString()===t.toString())})),w},getOptions:function(){return y},getImages:function(){return p},getZoomedImage:function(){return b.original}};return w},{themeConfig:d}=r.default;function f(e){var t,n;return document.querySelector('html[data-theme="dark"]')?(null===(t=e.background)||void 0===t?void 0:t.dark)||"rgb(50, 50, 50)":(null===(n=e.background)||void 0===n?void 0:n.light)||"rgb(255, 255, 255)"}const p=function(){if("undefined"==typeof window)return null;let e;const{zoom:t}=d,{selector:n=".markdown img",config:r={}}=t||{};if(!t)return null;r.background=f(t);var o=new MutationObserver((function(){e&&e.update({background:f(t)})}));const a=document.querySelector("html");return o.observe(a,{attributes:!0,attributeFilter:["data-theme"]}),setTimeout((()=>{e&&e.detach(),e=u(n,r)}),1e3),{onRouteUpdate(){setTimeout((()=>{e&&e.detach(),e=u(n,r)}),1e3)}}}()},8064:(e,t,n)=>{"use strict";n.d(t,{iU:()=>w,Yf:()=>C,gh:()=>p,Wi:()=>N,Ep:()=>f});var r=n(5072);function o(e){return"/"===e.charAt(0)}function a(e,t){for(var n=t,r=n+1,o=e.length;r=0;f--){var p=i[f];"."===p?a(i,f):".."===p?(a(i,f),d++):d&&(a(i,f),d--)}if(!c)for(;d--;d)i.unshift("..");!c||""===i[0]||i[0]&&o(i[0])||i.unshift("");var m=i.join("/");return n&&"/"!==m.substr(-1)&&(m+="/"),m};var l=n(4812);function s(e){return"/"===e.charAt(0)?e:"/"+e}function c(e){return"/"===e.charAt(0)?e.substr(1):e}function u(e,t){return function(e,t){return 0===e.toLowerCase().indexOf(t.toLowerCase())&&-1!=="/?#".indexOf(e.charAt(t.length))}(e,t)?e.substr(t.length):e}function d(e){return"/"===e.charAt(e.length-1)?e.slice(0,-1):e}function f(e){var t=e.pathname,n=e.search,r=e.hash,o=t||"/";return n&&"?"!==n&&(o+="?"===n.charAt(0)?n:"?"+n),r&&"#"!==r&&(o+="#"===r.charAt(0)?r:"#"+r),o}function p(e,t,n,o){var a;"string"==typeof e?(a=function(e){var t=e||"/",n="",r="",o=t.indexOf("#");-1!==o&&(r=t.substr(o),t=t.substr(0,o));var a=t.indexOf("?");return-1!==a&&(n=t.substr(a),t=t.substr(0,a)),{pathname:t,search:"?"===n?"":n,hash:"#"===r?"":r}}(e),a.state=t):(void 0===(a=(0,r.c)({},e)).pathname&&(a.pathname=""),a.search?"?"!==a.search.charAt(0)&&(a.search="?"+a.search):a.search="",a.hash?"#"!==a.hash.charAt(0)&&(a.hash="#"+a.hash):a.hash="",void 0!==t&&void 0===a.state&&(a.state=t));try{a.pathname=decodeURI(a.pathname)}catch(l){throw l instanceof URIError?new URIError('Pathname "'+a.pathname+'" could not be decoded. This is likely caused by an invalid percent-encoding.'):l}return n&&(a.key=n),o?a.pathname?"/"!==a.pathname.charAt(0)&&(a.pathname=i(a.pathname,o.pathname)):a.pathname=o.pathname:a.pathname||(a.pathname="/"),a}function m(){var e=null;var t=[];return{setPrompt:function(t){return e=t,function(){e===t&&(e=null)}},confirmTransitionTo:function(t,n,r,o){if(null!=e){var a="function"==typeof e?e(t,n):e;"string"==typeof a?"function"==typeof r?r(a,o):o(!0):o(!1!==a)}else o(!0)},appendListener:function(e){var n=!0;function r(){n&&e.apply(void 0,arguments)}return t.push(r),function(){n=!1,t=t.filter((function(e){return e!==r}))}},notifyListeners:function(){for(var e=arguments.length,n=new Array(e),r=0;rt?n.splice(t,n.length-t,o):n.push(o),d({action:r,location:o,index:t,entries:n})}}))},replace:function(e,t){var r="REPLACE",o=p(e,t,h(),w.location);u.confirmTransitionTo(o,r,n,(function(e){e&&(w.entries[w.index]=o,d({action:r,location:o}))}))},go:v,goBack:function(){v(-1)},goForward:function(){v(1)},canGo:function(e){var t=w.index+e;return t>=0&&t{"use strict";var r=n(2168),o={childContextTypes:!0,contextType:!0,contextTypes:!0,defaultProps:!0,displayName:!0,getDefaultProps:!0,getDerivedStateFromError:!0,getDerivedStateFromProps:!0,mixins:!0,propTypes:!0,type:!0},a={name:!0,length:!0,prototype:!0,caller:!0,callee:!0,arguments:!0,arity:!0},i={$$typeof:!0,compare:!0,defaultProps:!0,displayName:!0,propTypes:!0,type:!0},l={};function s(e){return r.isMemo(e)?i:l[e.$$typeof]||o}l[r.ForwardRef]={$$typeof:!0,render:!0,defaultProps:!0,displayName:!0,propTypes:!0},l[r.Memo]=i;var c=Object.defineProperty,u=Object.getOwnPropertyNames,d=Object.getOwnPropertySymbols,f=Object.getOwnPropertyDescriptor,p=Object.getPrototypeOf,m=Object.prototype;e.exports=function e(t,n,r){if("string"!=typeof n){if(m){var o=p(n);o&&o!==m&&e(t,o,r)}var i=u(n);d&&(i=i.concat(d(n)));for(var l=s(t),h=s(n),g=0;g{"use strict";e.exports=function(e,t,n,r,o,a,i,l){if(!e){var s;if(void 0===t)s=new Error("Minified exception occurred; use the non-minified dev environment for the full error message and additional helpful warnings.");else{var c=[n,r,o,a,i,l],u=0;(s=new Error(t.replace(/%s/g,(function(){return c[u++]})))).name="Invariant Violation"}throw s.framesToPop=1,s}}},9600:e=>{e.exports=Array.isArray||function(e){return"[object Array]"==Object.prototype.toString.call(e)}},1462:(e,t,n)=>{"use strict";n.r(t)},1496:(e,t,n)=>{"use strict";n.r(t)},2272:function(e,t,n){var r,o;r=function(){var e,t,n={version:"0.2.0"},r=n.settings={minimum:.08,easing:"ease",positionUsing:"",speed:200,trickle:!0,trickleRate:.02,trickleSpeed:800,showSpinner:!0,barSelector:'[role="bar"]',spinnerSelector:'[role="spinner"]',parent:"body",template:'
'};function o(e,t,n){return en?n:e}function a(e){return 100*(-1+e)}function i(e,t,n){var o;return(o="translate3d"===r.positionUsing?{transform:"translate3d("+a(e)+"%,0,0)"}:"translate"===r.positionUsing?{transform:"translate("+a(e)+"%,0)"}:{"margin-left":a(e)+"%"}).transition="all "+t+"ms "+n,o}n.configure=function(e){var t,n;for(t in e)void 0!==(n=e[t])&&e.hasOwnProperty(t)&&(r[t]=n);return this},n.status=null,n.set=function(e){var t=n.isStarted();e=o(e,r.minimum,1),n.status=1===e?null:e;var a=n.render(!t),c=a.querySelector(r.barSelector),u=r.speed,d=r.easing;return a.offsetWidth,l((function(t){""===r.positionUsing&&(r.positionUsing=n.getPositioningCSS()),s(c,i(e,u,d)),1===e?(s(a,{transition:"none",opacity:1}),a.offsetWidth,setTimeout((function(){s(a,{transition:"all "+u+"ms linear",opacity:0}),setTimeout((function(){n.remove(),t()}),u)}),u)):setTimeout(t,u)})),this},n.isStarted=function(){return"number"==typeof n.status},n.start=function(){n.status||n.set(0);var e=function(){setTimeout((function(){n.status&&(n.trickle(),e())}),r.trickleSpeed)};return r.trickle&&e(),this},n.done=function(e){return e||n.status?n.inc(.3+.5*Math.random()).set(1):this},n.inc=function(e){var t=n.status;return t?("number"!=typeof e&&(e=(1-t)*o(Math.random()*t,.1,.95)),t=o(t+e,0,.994),n.set(t)):n.start()},n.trickle=function(){return n.inc(Math.random()*r.trickleRate)},e=0,t=0,n.promise=function(r){return r&&"resolved"!==r.state()?(0===t&&n.start(),e++,t++,r.always((function(){0==--t?(e=0,n.done()):n.set((e-t)/e)})),this):this},n.render=function(e){if(n.isRendered())return document.getElementById("nprogress");u(document.documentElement,"nprogress-busy");var t=document.createElement("div");t.id="nprogress",t.innerHTML=r.template;var o,i=t.querySelector(r.barSelector),l=e?"-100":a(n.status||0),c=document.querySelector(r.parent);return s(i,{transition:"all 0 linear",transform:"translate3d("+l+"%,0,0)"}),r.showSpinner||(o=t.querySelector(r.spinnerSelector))&&p(o),c!=document.body&&u(c,"nprogress-custom-parent"),c.appendChild(t),t},n.remove=function(){d(document.documentElement,"nprogress-busy"),d(document.querySelector(r.parent),"nprogress-custom-parent");var e=document.getElementById("nprogress");e&&p(e)},n.isRendered=function(){return!!document.getElementById("nprogress")},n.getPositioningCSS=function(){var e=document.body.style,t="WebkitTransform"in e?"Webkit":"MozTransform"in e?"Moz":"msTransform"in e?"ms":"OTransform"in e?"O":"";return t+"Perspective"in e?"translate3d":t+"Transform"in e?"translate":"margin"};var l=function(){var e=[];function t(){var n=e.shift();n&&n(t)}return function(n){e.push(n),1==e.length&&t()}}(),s=function(){var e=["Webkit","O","Moz","ms"],t={};function n(e){return e.replace(/^-ms-/,"ms-").replace(/-([\da-z])/gi,(function(e,t){return t.toUpperCase()}))}function r(t){var n=document.body.style;if(t in n)return t;for(var r,o=e.length,a=t.charAt(0).toUpperCase()+t.slice(1);o--;)if((r=e[o]+a)in n)return r;return t}function o(e){return e=n(e),t[e]||(t[e]=r(e))}function a(e,t,n){t=o(t),e.style[t]=n}return function(e,t){var n,r,o=arguments;if(2==o.length)for(n in t)void 0!==(r=t[n])&&t.hasOwnProperty(n)&&a(e,n,r);else a(e,o[1],o[2])}}();function c(e,t){return("string"==typeof e?e:f(e)).indexOf(" "+t+" ")>=0}function u(e,t){var n=f(e),r=n+t;c(n,t)||(e.className=r.substring(1))}function d(e,t){var n,r=f(e);c(e,t)&&(n=r.replace(" "+t+" "," "),e.className=n.substring(1,n.length-1))}function f(e){return(" "+(e.className||"")+" ").replace(/\s+/gi," ")}function p(e){e&&e.parentNode&&e.parentNode.removeChild(e)}return n},void 0===(o="function"==typeof r?r.call(t,n,t,e):r)||(e.exports=o)},6872:(e,t,n)=>{var r=n(9600);e.exports=p,e.exports.parse=a,e.exports.compile=function(e,t){return l(a(e,t),t)},e.exports.tokensToFunction=l,e.exports.tokensToRegExp=f;var o=new RegExp(["(\\\\.)","([\\/.])?(?:(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?|(\\*))"].join("|"),"g");function a(e,t){for(var n,r=[],a=0,i=0,l="",u=t&&t.delimiter||"/";null!=(n=o.exec(e));){var d=n[0],f=n[1],p=n.index;if(l+=e.slice(i,p),i=p+d.length,f)l+=f[1];else{var m=e[i],h=n[2],g=n[3],y=n[4],b=n[5],v=n[6],w=n[7];l&&(r.push(l),l="");var k=null!=h&&null!=m&&m!==h,x="+"===v||"*"===v,S="?"===v||"*"===v,E=n[2]||u,_=y||b;r.push({name:g||a++,prefix:h||"",delimiter:E,optional:S,repeat:x,partial:k,asterisk:!!w,pattern:_?c(_):w?".*":"[^"+s(E)+"]+?"})}}return i{!function(e){var t="(?:"+(/"""(?:[^\\"]|"(?!""\2)|)*"""/.source+"|"+/'''(?:[^\\']|'(?!''\2)|)*'''/.source+"|"+/"(?:[^\\\r\n"]|"(?!\2)|)*"/.source+"|"+/'(?:[^\\\r\n']|'(?!\2)|)*'/.source).replace(//g,/\\(?:(?!\2)|\2(?:[^()\r\n]|\([^()]*\)))/.source)+")";e.languages.cue={comment:{pattern:/\/\/.*/,greedy:!0},"string-literal":{pattern:RegExp(/(^|[^#"'\\])(#*)/.source+t+/(?!["'])\2/.source),lookbehind:!0,greedy:!0,inside:{escape:{pattern:/(?=[\s\S]*["'](#*)$)\\\1(?:U[a-fA-F0-9]{1,8}|u[a-fA-F0-9]{1,4}|x[a-fA-F0-9]{1,2}|\d{2,3}|[^(])/,greedy:!0,alias:"string"},interpolation:{pattern:/(?=[\s\S]*["'](#*)$)\\\1\([^()]*\)/,greedy:!0,inside:{punctuation:/^\\#*\(|\)$/,expression:{pattern:/[\s\S]+/,inside:null}}},string:/[\s\S]+/}},keyword:{pattern:/(^|[^\w$])(?:for|if|import|in|let|null|package)(?![\w$])/,lookbehind:!0},boolean:{pattern:/(^|[^\w$])(?:false|true)(?![\w$])/,lookbehind:!0},builtin:{pattern:/(^|[^\w$])(?:bool|bytes|float|float(?:32|64)|u?int(?:8|16|32|64|128)?|number|rune|string)(?![\w$])/,lookbehind:!0},attribute:{pattern:/@[\w$]+(?=\s*\()/,alias:"function"},function:{pattern:/(^|[^\w$])[a-z_$][\w$]*(?=\s*\()/i,lookbehind:!0},number:{pattern:/(^|[^\w$.])(?:0b[01]+(?:_[01]+)*|0o[0-7]+(?:_[0-7]+)*|0[xX][0-9A-Fa-f]+(?:_[0-9A-Fa-f]+)*|(?:\d+(?:_\d+)*(?:\.(?:\d+(?:_\d+)*)?)?|\.\d+(?:_\d+)*)(?:[eE][+-]?\d+(?:_\d+)*)?(?:[KMGTP]i?)?)(?![\w$])/,lookbehind:!0},operator:/\.{3}|_\|_|&&?|\|\|?|[=!]~|[<>=!]=?|[+\-*/?]/,punctuation:/[()[\]{},.:]/},e.languages.cue["string-literal"].inside.interpolation.inside.expression.inside=e.languages.cue}(Prism)},1808:()=>{!function(e){function t(e,t){return"___"+e.toUpperCase()+t+"___"}Object.defineProperties(e.languages["markup-templating"]={},{buildPlaceholders:{value:function(n,r,o,a){if(n.language===r){var i=n.tokenStack=[];n.code=n.code.replace(o,(function(e){if("function"==typeof a&&!a(e))return e;for(var o,l=i.length;-1!==n.code.indexOf(o=t(r,l));)++l;return i[l]=e,o})),n.grammar=e.languages.markup}}},tokenizePlaceholders:{value:function(n,r){if(n.language===r&&n.tokenStack){n.grammar=e.languages[r];var o=0,a=Object.keys(n.tokenStack);!function i(l){for(var s=0;s=a.length);s++){var c=l[s];if("string"==typeof c||c.content&&"string"==typeof c.content){var u=a[o],d=n.tokenStack[u],f="string"==typeof c?c:c.content,p=t(r,u),m=f.indexOf(p);if(m>-1){++o;var h=f.substring(0,m),g=new e.Token(r,e.tokenize(d,n.grammar),"language-"+r,d),y=f.substring(m+p.length),b=[];h&&b.push.apply(b,i([h])),b.push(g),y&&b.push.apply(b,i([y])),"string"==typeof c?l.splice.apply(l,[s,1].concat(b)):c.content=b}}else c.content&&i(c.content)}return l}(n.tokens)}}}})}(Prism)},1880:()=>{!function(e){var t=e.languages.powershell={comment:[{pattern:/(^|[^`])<#[\s\S]*?#>/,lookbehind:!0},{pattern:/(^|[^`])#.*/,lookbehind:!0}],string:[{pattern:/"(?:`[\s\S]|[^`"])*"/,greedy:!0,inside:null},{pattern:/'(?:[^']|'')*'/,greedy:!0}],namespace:/\[[a-z](?:\[(?:\[[^\]]*\]|[^\[\]])*\]|[^\[\]])*\]/i,boolean:/\$(?:false|true)\b/i,variable:/\$\w+\b/,function:[/\b(?:Add|Approve|Assert|Backup|Block|Checkpoint|Clear|Close|Compare|Complete|Compress|Confirm|Connect|Convert|ConvertFrom|ConvertTo|Copy|Debug|Deny|Disable|Disconnect|Dismount|Edit|Enable|Enter|Exit|Expand|Export|Find|ForEach|Format|Get|Grant|Group|Hide|Import|Initialize|Install|Invoke|Join|Limit|Lock|Measure|Merge|Move|New|Open|Optimize|Out|Ping|Pop|Protect|Publish|Push|Read|Receive|Redo|Register|Remove|Rename|Repair|Request|Reset|Resize|Resolve|Restart|Restore|Resume|Revoke|Save|Search|Select|Send|Set|Show|Skip|Sort|Split|Start|Step|Stop|Submit|Suspend|Switch|Sync|Tee|Test|Trace|Unblock|Undo|Uninstall|Unlock|Unprotect|Unpublish|Unregister|Update|Use|Wait|Watch|Where|Write)-[a-z]+\b/i,/\b(?:ac|cat|chdir|clc|cli|clp|clv|compare|copy|cp|cpi|cpp|cvpa|dbp|del|diff|dir|ebp|echo|epal|epcsv|epsn|erase|fc|fl|ft|fw|gal|gbp|gc|gci|gcs|gdr|gi|gl|gm|gp|gps|group|gsv|gu|gv|gwmi|iex|ii|ipal|ipcsv|ipsn|irm|iwmi|iwr|kill|lp|ls|measure|mi|mount|move|mp|mv|nal|ndr|ni|nv|ogv|popd|ps|pushd|pwd|rbp|rd|rdr|ren|ri|rm|rmdir|rni|rnp|rp|rv|rvpa|rwmi|sal|saps|sasv|sbp|sc|select|set|shcm|si|sl|sleep|sls|sort|sp|spps|spsv|start|sv|swmi|tee|trcm|type|write)\b/i],keyword:/\b(?:Begin|Break|Catch|Class|Continue|Data|Define|Do|DynamicParam|Else|ElseIf|End|Exit|Filter|Finally|For|ForEach|From|Function|If|InlineScript|Parallel|Param|Process|Return|Sequence|Switch|Throw|Trap|Try|Until|Using|Var|While|Workflow)\b/i,operator:{pattern:/(^|\W)(?:!|-(?:b?(?:and|x?or)|as|(?:Not)?(?:Contains|In|Like|Match)|eq|ge|gt|is(?:Not)?|Join|le|lt|ne|not|Replace|sh[lr])\b|-[-=]?|\+[+=]?|[*\/%]=?)/i,lookbehind:!0},punctuation:/[|{}[\];(),.]/};t.string[0].inside={function:{pattern:/(^|[^`])\$\((?:\$\([^\r\n()]*\)|(?!\$\()[^\r\n)])*\)/,lookbehind:!0,inside:t},boolean:t.boolean,variable:t.variable}}(Prism)},464:(e,t,n)=>{var r={"./prism-cue":5376,"./prism-powershell":1880};function o(e){var t=a(e);return n(t)}function a(e){if(!n.o(r,e)){var t=new Error("Cannot find module '"+e+"'");throw t.code="MODULE_NOT_FOUND",t}return r[e]}o.keys=function(){return Object.keys(r)},o.resolve=a,e.exports=o,o.id=464},9776:(e,t,n)=>{"use strict";var r=n(9143);function o(){}function a(){}a.resetWarningCache=o,e.exports=function(){function e(e,t,n,o,a,i){if(i!==r){var l=new Error("Calling PropTypes validators directly is not supported by the `prop-types` package. Use PropTypes.checkPropTypes() to call them. Read more at http://fb.me/use-check-prop-types");throw l.name="Invariant Violation",l}}function t(){return e}e.isRequired=e;var n={array:e,bigint:e,bool:e,func:e,number:e,object:e,string:e,symbol:e,any:e,arrayOf:t,element:e,elementType:e,instanceOf:t,node:e,objectOf:t,oneOf:t,oneOfType:t,shape:t,exact:t,checkPropTypes:a,resetWarningCache:o};return n.PropTypes=n,n}},3268:(e,t,n)=>{e.exports=n(9776)()},9143:e=>{"use strict";e.exports="SECRET_DO_NOT_PASS_THIS_OR_YOU_WILL_BE_FIRED"},9516:(e,t,n)=>{"use strict";var r=n(1504),o=n(4712);function a(e){for(var t="https://reactjs.org/docs/error-decoder.html?invariant="+e,n=1;n