mirror of
https://github.com/kubesphere/website.git
synced 2025-12-26 00:12:48 +00:00
first version
This commit is contained in:
parent
975432336e
commit
da2b265add
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -1,103 +0,0 @@
|
|||
/* BEGIN Regular */
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-Regular.woff2") format("woff2"),
|
||||
url("./Roboto-Regular.woff") format("woff"),
|
||||
url('./Roboto-Regular.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-Regular.woff2") format("woff2"),
|
||||
url("./Roboto-Regular.woff") format("woff"),
|
||||
url('./Roboto-Regular.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* END Regular */
|
||||
|
||||
/* BEGIN Italic */
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-Italic.woff2") format("woff2"),
|
||||
url("./Roboto-Italic.woff") format("woff"),
|
||||
url('./Roboto-Italic.ttf') format('truetype');
|
||||
font-weight: 400;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-Italic.woff2") format("woff2"),
|
||||
url("./Roboto-Italic.woff") format("woff"),
|
||||
url('./Roboto-Italic.ttf') format('truetype');
|
||||
font-weight: normal;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* END Italic */
|
||||
|
||||
/* BEGIN Medium */
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-Medium.woff2") format("woff2"),
|
||||
url("./Roboto-Medium.woff") format("woff"),
|
||||
url('./Roboto-Medium.ttf') format('truetype');
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* END Medium */
|
||||
|
||||
/* BEGIN Medium Italic */
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-MediumItalic.woff2") format("woff2"),
|
||||
url("./Roboto-MediumItalic.woff") format("woff"),
|
||||
url('./Roboto-MediumItalic.ttf') format('truetype');
|
||||
font-weight: 500;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* END Medium Italic */
|
||||
|
||||
/* BEGIN Bold */
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-Bold.woff2") format("woff2"),
|
||||
url("./Roboto-Bold.woff") format("woff"),
|
||||
url('./Roboto-Bold.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: normal;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-Bold.woff2") format("woff2"),
|
||||
url("./Roboto-Bold.woff") format("woff"),
|
||||
url('./Roboto-Bold.ttf') format('truetype');
|
||||
font-weight: bold;
|
||||
font-style: normal;
|
||||
}
|
||||
|
||||
/* END Bold */
|
||||
|
||||
/* BEGIN Bold Italic */
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-BoldItalic.woff2") format("woff2"),
|
||||
url("./Roboto-BoldItalic.woff") format("woff"),
|
||||
url('./Roboto-BoldItalic.ttf') format('truetype');
|
||||
font-weight: 700;
|
||||
font-style: italic;
|
||||
}
|
||||
@font-face {
|
||||
font-family: Roboto;
|
||||
src: url("./Roboto-BoldItalic.woff2") format("woff2"),
|
||||
url("./Roboto-BoldItalic.woff") format("woff"),
|
||||
url('./Roboto-BoldItalic.ttf') format('truetype');
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
|
||||
/* END Bold Italic */
|
||||
|
|
@ -0,0 +1 @@
|
|||
@import 'open-source';
|
||||
|
|
@ -0,0 +1,156 @@
|
|||
@import 'variables';
|
||||
@import 'mixin';
|
||||
|
||||
.section-1 {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
min-width: 1160px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit:cover;
|
||||
}
|
||||
|
||||
.title-div {
|
||||
position: absolute;
|
||||
top: 138px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.11px;
|
||||
color: #ffffff;
|
||||
}
|
||||
p {
|
||||
margin-top: 12px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
letter-spacing: -0.04px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.section-2 {
|
||||
.cases-ul {
|
||||
display: flex;
|
||||
flex-wrap: wrap ;
|
||||
justify-content: space-between;
|
||||
position: relative;
|
||||
top: -60px;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
|
||||
li {
|
||||
width: 373px;
|
||||
height: 392px;
|
||||
margin-top: 20px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #ffffff;
|
||||
|
||||
img {
|
||||
display: block;
|
||||
width: 293px;
|
||||
height: 120px;
|
||||
margin: 24px auto;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
p {
|
||||
@include common-p-style;
|
||||
width: 293px;
|
||||
height: 128px;
|
||||
margin: 0 auto;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
div {
|
||||
width: 293px;
|
||||
height: 24px;
|
||||
margin: 25px auto 0;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
|
||||
a {
|
||||
color: #00a971;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-3 {
|
||||
background-image: url('/images/case/oval-4.svg');
|
||||
background-position: center top;
|
||||
background-repeat: no-repeat;
|
||||
padding-top: 80px;
|
||||
|
||||
h2 {
|
||||
margin-bottom: 40px;
|
||||
text-align: center;
|
||||
height: 52px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
& > div {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
#case-group {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100px;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 16px 0 rgba(7, 42, 68, 0.1);
|
||||
background-color: #ffffff;
|
||||
|
||||
li {
|
||||
margin-left: 60px;
|
||||
height: 24px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #36435c;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.active {
|
||||
padding: 8px 16px;
|
||||
border-radius: 20px;
|
||||
box-shadow: 0 8px 16px 0 rgba(101, 193, 148, 0.2), 0 0 50px 0 rgba(101, 193, 148, 0.1);
|
||||
background-color: #55bc8a;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
#case-children {
|
||||
display: flex;
|
||||
flex-wrap: wrap ;
|
||||
li {
|
||||
margin-top: 20px;
|
||||
margin-right: 21px;
|
||||
}
|
||||
|
||||
li:nth-child(4n) {
|
||||
margin-right: 0;
|
||||
}
|
||||
|
||||
img {
|
||||
width: 274px;
|
||||
height: 135px;
|
||||
object-fit: contain;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
@import 'reset';
|
||||
@import 'variables';
|
||||
@import 'header';
|
||||
@import 'footer';
|
||||
|
||||
body {
|
||||
font-family: $font-family-id;
|
||||
}
|
||||
|
||||
html {
|
||||
background-color: #f5f8f9;
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
@import 'open-source';
|
||||
|
||||
.tab-content {
|
||||
background-color: #fff;
|
||||
padding-top: 60px;
|
||||
padding-bottom: 100px;
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
|
||||
& > ul {
|
||||
|
||||
li:nth-child(1) {
|
||||
.top-div {
|
||||
background-image: linear-gradient(270deg, rgb(101, 193, 148), rgb(76, 169, 134))
|
||||
}
|
||||
}
|
||||
|
||||
li:nth-child(2) {
|
||||
.top-div {
|
||||
background-image: linear-gradient(to left, rgb(52, 197, 209), rgb(95, 182, 216))
|
||||
}
|
||||
}
|
||||
|
||||
& > li {
|
||||
.top-div {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
height: 158px;
|
||||
padding: 36px 48px;
|
||||
margin-bottom: 12px;
|
||||
border-radius: 4px;
|
||||
|
||||
.left-img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
h3 {
|
||||
font-size: 28px;
|
||||
font-weight: 600;
|
||||
line-height: 1.29;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-top: 8px;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.right-img {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 208px;
|
||||
transform: translate(50%, -50%);
|
||||
}
|
||||
}
|
||||
|
||||
ul {
|
||||
li {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
height: 354px;
|
||||
padding: 40px 593px 30px 40px;
|
||||
margin: 12px 0;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 15px 0 rgba(7,42,68,.1);
|
||||
background-color: #fff;
|
||||
|
||||
h4 {
|
||||
font-size: 20px;
|
||||
|
||||
a {
|
||||
color: #36435c;
|
||||
|
||||
&:hover {
|
||||
color: #55bc8a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.author {
|
||||
margin: 18px auto 22px;
|
||||
font-size: 16px;
|
||||
line-height: 1.75;
|
||||
color: #36435c;
|
||||
}
|
||||
|
||||
p {
|
||||
height: 84px;
|
||||
font-size: 14px;
|
||||
line-height: 2;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
.line {
|
||||
height: 0;
|
||||
margin-top: 19.5px;
|
||||
margin-bottom: 29.5px;
|
||||
opacity: 0.5;
|
||||
border: solid 1px #919aa3;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 111px;
|
||||
height: 36px;
|
||||
border-radius: 20px;
|
||||
border: solid 1px #ccd3db;
|
||||
background-color: #f5f8f9;
|
||||
font-size: 14px;
|
||||
color: #36435c;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
color: #4ca986;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 16px;
|
||||
right: 17px;
|
||||
width: 480px;
|
||||
height: 304px;
|
||||
border-radius: 3px;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,155 @@
|
|||
@import "markdown";
|
||||
|
||||
.main-section {
|
||||
padding-top: 93px;
|
||||
|
||||
& > div {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
|
||||
.breadcrumb {
|
||||
margin: 30px 0;
|
||||
}
|
||||
|
||||
.main-div {
|
||||
box-sizing: border-box;
|
||||
width: 880px;
|
||||
padding: 40px 60px;
|
||||
background-color: #fff;
|
||||
border-radius: 4px;
|
||||
|
||||
.author {
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
.date {
|
||||
font-size: 14px;
|
||||
line-height: 1.43;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin-top: 20px;
|
||||
margin-bottom: 40px;
|
||||
text-shadow: 0 8px 16px rgba(35,45,65,.1);
|
||||
font-size: 40px;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
.content {
|
||||
|
||||
.md-body {
|
||||
font-size: 14px;
|
||||
line-height: 2.29;
|
||||
color: #36435c;
|
||||
}
|
||||
|
||||
.md-body h2 {
|
||||
font-size: 24px;
|
||||
font-weight: 500;
|
||||
line-height: 64px;
|
||||
color: #171c34;
|
||||
text-shadow: none;
|
||||
text-align: left;
|
||||
margin-bottom: 20px;
|
||||
border-bottom: 1px solid #ccd3db;
|
||||
}
|
||||
|
||||
.md-body h3 {
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
.md-body img {
|
||||
max-width: 100%;
|
||||
box-sizing: content-box;
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: none;
|
||||
}
|
||||
|
||||
.md-body blockquote {
|
||||
padding: 4px 20px 4px 12px;
|
||||
border-radius: 4px;
|
||||
background-color: #ecf0f2;
|
||||
}
|
||||
|
||||
&-metadata {
|
||||
margin-bottom: 28px;
|
||||
|
||||
&-title {
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
&-time {
|
||||
font-size: 14px;
|
||||
line-height: 1.43;
|
||||
color: #919aa3;
|
||||
}
|
||||
}
|
||||
|
||||
&-title {
|
||||
text-shadow: 0 8px 16px rgba(35, 45, 65, 0.1);
|
||||
font-size: 40px;
|
||||
font-weight: 500;
|
||||
line-height: 1.4;
|
||||
color: #171c34;
|
||||
margin-bottom: 40px;
|
||||
|
||||
@media only screen and (max-width: $mobile-max-width) {
|
||||
font-size: 28px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.aside {
|
||||
position: fixed;
|
||||
top: 150px;
|
||||
left: 50%;
|
||||
width: 214px;
|
||||
transform: translateX(350px);
|
||||
|
||||
.title {
|
||||
height: 32px;
|
||||
font-size: 24px;
|
||||
line-height: 1.33;
|
||||
color: #36435c;
|
||||
padding-bottom: 10px;
|
||||
border-bottom: solid 1px #ccd3db;;
|
||||
}
|
||||
|
||||
.tabs {
|
||||
li {
|
||||
margin: 4px 0;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 2;
|
||||
color: #36435c;
|
||||
|
||||
a {
|
||||
display: block;
|
||||
width: 100%;
|
||||
height: 32px;
|
||||
color: #36435c;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
}
|
||||
li li {
|
||||
padding-left: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,481 @@
|
|||
@import 'variables';
|
||||
@import 'mixin';
|
||||
|
||||
|
||||
.section-1 {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
min-width: 1160px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit:cover;
|
||||
}
|
||||
|
||||
.title-div {
|
||||
position: absolute;
|
||||
top: 138px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.11px;
|
||||
color: #ffffff;
|
||||
}
|
||||
p {
|
||||
margin-top: 12px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
letter-spacing: -0.04px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.section-2 {
|
||||
background-image: url('/images/contribution/oval-4.svg');
|
||||
background-position: center bottom;
|
||||
background-repeat: no-repeat;
|
||||
& > div {
|
||||
@include common-content-div-style;
|
||||
& > ul {
|
||||
@include common-flex-style;
|
||||
position: relative;
|
||||
transform: translateY(-40px);
|
||||
& > li {
|
||||
position: relative;
|
||||
width: 373px;
|
||||
height: 392px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
& > .title {
|
||||
padding: 20px;
|
||||
text-align: center;
|
||||
img {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
}
|
||||
|
||||
& > .line {
|
||||
width: 360px;
|
||||
height: 1px;
|
||||
background-color: #d2e0d8;
|
||||
}
|
||||
|
||||
& > ul {
|
||||
margin-top: 40px;
|
||||
margin-left: 60px;
|
||||
|
||||
li {
|
||||
width: 216px;
|
||||
height: 24px;
|
||||
line-height: 24px;
|
||||
padding-bottom: 12px;
|
||||
margin-bottom: 11px;
|
||||
border-bottom: 1px solid #d2e0d8;
|
||||
a {
|
||||
font-size: 16px;
|
||||
color: #31383e;
|
||||
}
|
||||
a:hover {
|
||||
color: #00aa72;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-img {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
li:nth-child(2){
|
||||
.line {
|
||||
margin: 0 auto;
|
||||
}
|
||||
}
|
||||
|
||||
li:nth-child(3){
|
||||
.line {
|
||||
margin-left: 14px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.organization-div {
|
||||
margin-top: 60px;
|
||||
text-align: center;
|
||||
h2 {
|
||||
height: 52px;
|
||||
margin-bottom: 40px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 52px;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
height: 454px;
|
||||
.top-div {
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
margin: 0 auto;
|
||||
line-height: 50px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.23px;
|
||||
color: #ffffff;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #060845;
|
||||
}
|
||||
|
||||
& > ul {
|
||||
position: absolute;
|
||||
top: 100px;
|
||||
left: 50%;
|
||||
width: 896px;
|
||||
transform: translateX(-50%);
|
||||
@include common-flex-style;
|
||||
|
||||
& > li {
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.23px;
|
||||
line-height: 50px;
|
||||
color: #ffffff;
|
||||
border-radius: 3px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #7371df;
|
||||
|
||||
& > div {
|
||||
img, span {
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
width: 200px;
|
||||
height: 50px;
|
||||
margin-top: 31px;
|
||||
line-height: 50px;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.23px;
|
||||
color: #3d3e49;
|
||||
border-radius: 3px;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #ffffff;
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #f7b500;
|
||||
p {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
.left {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: -14px;
|
||||
width: 210px;
|
||||
transform: translate(-100%, -50%);
|
||||
padding: 20px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.23px;
|
||||
line-height: 16px;
|
||||
color: #ffffff;
|
||||
border-radius: 4px;
|
||||
opacity: 0.8;
|
||||
background-color: #060845;
|
||||
|
||||
&::after {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: -12px;
|
||||
transform: translateY(-50%);
|
||||
border: 6px solid transparent;
|
||||
border-left-color: #060845;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: -14px;
|
||||
width: 210px;
|
||||
transform: translate(100%, -50%);
|
||||
padding: 20px;
|
||||
font-size: 12px;
|
||||
letter-spacing: 0.23px;
|
||||
line-height: 16px;
|
||||
color: #ffffff;
|
||||
border-radius: 4px;
|
||||
opacity: 0.8;
|
||||
background-color: #060845;
|
||||
|
||||
&::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
left: -12px;
|
||||
transform: translateY(-50%);
|
||||
border: 6px solid transparent;
|
||||
border-right-color: #060845;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-3 {
|
||||
text-align: center;
|
||||
h2 {
|
||||
height: 52px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
}
|
||||
& > p {
|
||||
width: 964px;
|
||||
height: 64px;
|
||||
margin: 12px auto 0;
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
& > ul {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 30px;
|
||||
text-align: left;
|
||||
border-bottom: solid 2px #e5e5e5;
|
||||
|
||||
.active {
|
||||
background-image: linear-gradient(148deg, #4a499a 16%, #8552c3 85%);
|
||||
|
||||
&:hover {
|
||||
background-image: linear-gradient(148deg, #4a499a 16%, #8552c3 85%);
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-left: 84px;
|
||||
margin-top: 30px;
|
||||
margin-bottom: 28px;
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
border-radius: 50%;
|
||||
background-image: linear-gradient(38deg, #d5dee7 19%, #ffffff 113%);
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
background-image: linear-gradient(44deg, #dee0e6 19%, #b6c2cd 86%);
|
||||
}
|
||||
|
||||
img {
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
margin: 13px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 134px;
|
||||
height: 20px;
|
||||
position: absolute;
|
||||
bottom: -24px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
font-size: 14px;
|
||||
font-weight: 500;
|
||||
line-height: 20px;
|
||||
text-align: center;
|
||||
color: #3d3e49;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
li:nth-child(1), li:nth-child(10) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
& > div {
|
||||
position: relative;
|
||||
width: 160px;
|
||||
height: 160px;
|
||||
margin: 28px auto 30px;
|
||||
border-radius: 50%;
|
||||
background-image: linear-gradient(148deg, #4a499a 16%, #8552c3 85%);
|
||||
|
||||
img {
|
||||
width: 80px;
|
||||
height: 80px;
|
||||
margin: 40px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.btn-change {
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
transform: translateY(-50%) rotate(0.125turn);
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.btn-left {
|
||||
left: -100px;
|
||||
border-bottom: 4px solid #4f5362;
|
||||
border-left: 4px solid #4f5362;
|
||||
}
|
||||
|
||||
.btn-right {
|
||||
right: -100px;
|
||||
border-top: 4px solid #4f5362;
|
||||
border-right: 4px solid #4f5362;
|
||||
}
|
||||
}
|
||||
|
||||
& > a {
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
color: #00a971;
|
||||
}
|
||||
|
||||
& > p {
|
||||
height: 24px;
|
||||
margin-top: 4px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #31383e;
|
||||
}
|
||||
|
||||
& > ul {
|
||||
margin-top: 18px;
|
||||
margin-bottom: 83px;
|
||||
font-size: 0;
|
||||
li {
|
||||
display: inline-block;
|
||||
margin-left: 8px;
|
||||
img {
|
||||
width: 160px;
|
||||
height: 68px;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
li:nth-child(1) {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-4 {
|
||||
text-align: center;
|
||||
background-color: #ffffff;
|
||||
padding-top: 80px;
|
||||
padding-bottom: 93px;
|
||||
h2 {
|
||||
height: 52px;
|
||||
margin-bottom: 60px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
& > div {
|
||||
@include common-flex-style;
|
||||
width: 963px;
|
||||
margin: 0 auto;
|
||||
& > div {
|
||||
width: 471px;
|
||||
height: 565px;
|
||||
background-color: #f5f9fa;
|
||||
img {
|
||||
width: 168px;
|
||||
height: 168px;
|
||||
margin-top: 60px;
|
||||
border-radius: 50%;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
h3 {
|
||||
height: 29px;
|
||||
margin-top: 55px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
color: #31383e;
|
||||
}
|
||||
|
||||
p {
|
||||
height: 96px;
|
||||
margin: 13px auto 0;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #31383e;
|
||||
}
|
||||
|
||||
div {
|
||||
margin-top: 30px;
|
||||
height: 24px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.33;
|
||||
a {
|
||||
color: #00a971;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > div:nth-child(1) {
|
||||
p {
|
||||
width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
& > div:nth-child(2) {
|
||||
p {
|
||||
width: 384px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,10 +0,0 @@
|
|||
html {
|
||||
background-color: #f5f8f9;
|
||||
}
|
||||
|
||||
.bg-1 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
z-index: -1;
|
||||
}
|
||||
|
|
@ -17,6 +17,50 @@
|
|||
.foot-logo {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 360px;
|
||||
height: 44px;
|
||||
margin-top: 40px;
|
||||
font-size: 16px;
|
||||
line-height: 1.38;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
div {
|
||||
width: 360px;
|
||||
height: 48px;
|
||||
margin-top: 20px;
|
||||
border-radius: 24px;
|
||||
border: solid 1px #ccd3db;
|
||||
background-color: #f5f8f9;
|
||||
|
||||
input {
|
||||
width: 209px;
|
||||
height: 20px;
|
||||
font-size: 14px;
|
||||
margin-left: 17px;
|
||||
color: #ccd3db;
|
||||
border: none;
|
||||
background-color: #f5f8f9;
|
||||
}
|
||||
|
||||
button {
|
||||
width: 111px;
|
||||
height: 40px;
|
||||
margin: 4px 5px 4px 14px;
|
||||
border-radius: 20px;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 10px 50px 0 rgba(34, 43, 62, 0.1), 0 8px 16px 0 rgba(33, 43, 61, 0.2);
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1) 97%), linear-gradient(to bottom, #55bc8a, #55bc8a);
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.right-div {
|
||||
width: 720px;
|
||||
|
|
@ -48,5 +92,27 @@
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
.down-main {
|
||||
text-align: center;
|
||||
margin-top: 60px;
|
||||
|
||||
.img-div {
|
||||
font-size: 0;
|
||||
img {
|
||||
margin: 0 6px;
|
||||
}
|
||||
}
|
||||
|
||||
.p1 {
|
||||
height: 23px;
|
||||
margin-top: 6px;
|
||||
font-size: 14px;
|
||||
line-height: 23px;
|
||||
font-weight: 500;
|
||||
letter-spacing: 1.08px;
|
||||
color: #242e42;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -5,96 +5,248 @@
|
|||
top: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 100px;
|
||||
vertical-align: middle;
|
||||
opacity: .96;
|
||||
box-shadow: 0 4px 8px 0 rgba(36,46,66,.2);
|
||||
background-color: #f5f8f9!important;
|
||||
border-color: transparent!important;
|
||||
}
|
||||
height: 93px;
|
||||
color: #ffffff;
|
||||
border-bottom: 1px solid rgba($color: #e3e9ef, $alpha: 0.4);
|
||||
background-image: linear-gradient(to top, rgba(23, 188, 133, 0.18), rgba(0, 169, 113, 0.18));
|
||||
|
||||
.header-container {
|
||||
position: relative;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
.logo {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
padding: 34px 0;
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.nav {
|
||||
width: 800px;
|
||||
height: 100px;
|
||||
margin: 0 auto;
|
||||
line-height: 100px;
|
||||
text-align: center;
|
||||
& > li {
|
||||
display: inline-block;
|
||||
margin: 0 20px;
|
||||
.header-container {
|
||||
position: relative;
|
||||
color: #242e42;
|
||||
font-size: 16px;
|
||||
text-align: center;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
& > .active {
|
||||
a {
|
||||
color: #55bc8a;
|
||||
|
||||
.logo {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.nav {
|
||||
height:93px;
|
||||
margin-left: 200px;
|
||||
margin-right: 380px;
|
||||
line-height: 93px;
|
||||
& > li:first-child {
|
||||
margin-left: 0;
|
||||
}
|
||||
& > li {
|
||||
display: inline-block;
|
||||
margin-left: 20px;
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
line-height: 20px;
|
||||
cursor: pointer;
|
||||
& > a {
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
& > .active {
|
||||
a {
|
||||
// color: #55bc8a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-li {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
.menu-active {
|
||||
span {
|
||||
color: #55bc8a;
|
||||
}
|
||||
.active {
|
||||
a {
|
||||
color: #55bc8a;
|
||||
.menu-active {
|
||||
span {
|
||||
// color: #55bc8a;
|
||||
}
|
||||
.active {
|
||||
a {
|
||||
color: #55bc8a;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.menu-li:hover .dropdown-menu {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
display: none;
|
||||
position: absolute;
|
||||
width: 200px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
padding-left: 0;
|
||||
background: #ffffff;
|
||||
text-align: center;
|
||||
line-height: 30px;
|
||||
.active {
|
||||
a {
|
||||
color: #55bc8a;
|
||||
}
|
||||
.menu-li:hover {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.menu-span::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
margin-left: 5px;
|
||||
border-width: 4px 2px;
|
||||
border: solid transparent;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.language-menu {
|
||||
top: 40px;
|
||||
cursor: pointer;
|
||||
.dropdown-menu {
|
||||
width: 120px;
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
box-sizing: border-box;
|
||||
width: 306px;
|
||||
padding: 12px 30px 18px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
background: #ffffff;
|
||||
line-height: 30px;
|
||||
font-size: 0;
|
||||
border-radius: 6px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36,46,66,.06),0 8px 16px 0 rgba(36,46,66,.05);
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
padding-left: 20px;
|
||||
height: 32px;
|
||||
line-height: 32px;
|
||||
font-size: 12px;
|
||||
color: #36435c;
|
||||
|
||||
a {
|
||||
color: #36435c;
|
||||
|
||||
&:hover {
|
||||
color: #55bc8a;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
li:nth-child(2n) {
|
||||
margin-left: 6px;
|
||||
}
|
||||
|
||||
.active {
|
||||
a {
|
||||
color: #55bc8a;
|
||||
}
|
||||
}
|
||||
&::after {
|
||||
position: absolute;
|
||||
top: -20px;
|
||||
left: 50%;
|
||||
transform: translateX(-50%);
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 10px solid transparent;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
.right-menu {
|
||||
position: absolute;
|
||||
top: 28px;
|
||||
right: 0;
|
||||
|
||||
& > ul {
|
||||
& > li {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
.language-menu {
|
||||
position: relative;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
& > div {
|
||||
img, span {
|
||||
display: inline-block;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span::after {
|
||||
display: inline-block;
|
||||
content: '';
|
||||
margin-left: 5px;
|
||||
border-width: 4px 2px;
|
||||
border: solid transparent;
|
||||
border-top-color: #fff;
|
||||
}
|
||||
}
|
||||
.dropdown-menu {
|
||||
color: black;
|
||||
width: 120px;
|
||||
li {
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.btn-li {
|
||||
margin-left: 18px;
|
||||
margin-right: 4px;
|
||||
button {
|
||||
width: 112px;
|
||||
height: 36px;
|
||||
border-radius: 30px;
|
||||
border: none;
|
||||
font-size: 14px;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 10px 50px 0 rgba(34, 43, 62, 0.1), 0 8px 16px 0 rgba(33, 43, 61, 0.2);
|
||||
background-image: linear-gradient(to bottom, rgba(0, 0, 0, 0), rgba(0, 0, 0, 0.1) 97%), linear-gradient(to bottom, #242e42, #242e42);
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
&:hover {
|
||||
padding-bottom: 40px;
|
||||
}
|
||||
|
||||
.dropdown-menu {
|
||||
top: 60px
|
||||
}
|
||||
|
||||
ol {
|
||||
li {
|
||||
display: block;
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.link-li {
|
||||
a {
|
||||
display: inline-block;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
margin-left: 12px;
|
||||
background-position: center center;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
.link-1 {
|
||||
background-image: url('/images/header/slack.svg');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/images/header/slack-hover.svg');
|
||||
}
|
||||
}
|
||||
|
||||
.link-2 {
|
||||
background-image: url('/images/header/twitter.svg');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/images/header/twitter-hover.svg');
|
||||
}
|
||||
}
|
||||
|
||||
.link-3 {
|
||||
background-image: url('/images/header/github.svg');
|
||||
|
||||
&:hover {
|
||||
background-image: url('/images/header/github-hover.svg');
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.main-section {
|
||||
padding-top: 100px;
|
||||
.navigationScroll {
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-image: linear-gradient(to bottom, rgba(134, 219, 162, 0.9), rgba(0, 170, 114, 0.9));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,408 +0,0 @@
|
|||
@import 'reset';
|
||||
@import 'variables';
|
||||
@import 'else';
|
||||
@import 'header';
|
||||
@import 'footer';
|
||||
|
||||
.section-div-1 {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
.banner-title {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 460px;
|
||||
margin-top: 140px;
|
||||
margin-right: 25px;
|
||||
|
||||
.banner-activities {
|
||||
padding: 8px 12px;
|
||||
margin-bottom: 40px;
|
||||
border-radius: 22px;
|
||||
background-color: #e3e9ef;
|
||||
|
||||
.banner-tag {
|
||||
height: 24px;
|
||||
min-width: 58px;
|
||||
padding: 2px 12px;
|
||||
margin-right: 12px;
|
||||
border-radius: 4px;
|
||||
background-image: linear-gradient(152deg,#51b484,#329dce);
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
box-sizing: border-box;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
a {
|
||||
display: inline-block;
|
||||
font-family: $font-family-id;
|
||||
font-size: 14px;
|
||||
line-height: 24px;
|
||||
color: #36435c;
|
||||
word-break: keep-all;
|
||||
white-space: pre;
|
||||
}
|
||||
}
|
||||
|
||||
.h1 {
|
||||
font-family: $font-family-id;
|
||||
font-size: 30px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
color: #171c34;
|
||||
text-shadow: 0 8px 16px rgba(35,45,65,.16);
|
||||
margin-bottom: 16px;
|
||||
}
|
||||
|
||||
.banner-sub-title {
|
||||
margin-bottom: 16px;
|
||||
text-shadow: 0 8px 16px rgba(35,45,65,.16);
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
p {
|
||||
font-family: $font-family-id;
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #919aa3;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.install-button {
|
||||
margin-top: 20px;
|
||||
margin-right: 13px;
|
||||
padding: 7px 20px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
background-color: #242e42;
|
||||
box-shadow: 0 10px 50px 0 rgba(34,43,62,.1), 0 8px 16px 0 rgba(33,43,61,.2);
|
||||
height: 48px;
|
||||
border-radius: 30px;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
}
|
||||
}
|
||||
|
||||
.banner-snapshot {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 670px;
|
||||
height: 440px;
|
||||
margin-top: 40px;
|
||||
|
||||
.banner-snapshot-sub {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
left: 314px;
|
||||
width: 280px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-div-2 {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
padding-top: 120px;
|
||||
text-align: center;
|
||||
|
||||
.h1 {
|
||||
font-size: 32px;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
text-shadow: 0 4px 8px rgba(35,45,65,.1);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
& > p {
|
||||
width: 640px;
|
||||
font-size: 14px;
|
||||
margin: 0 auto 50px;
|
||||
line-height: 2;
|
||||
color: #485b7f;
|
||||
}
|
||||
|
||||
.feature-cards {
|
||||
font-size: 0;
|
||||
.feature-card + .feature-card {
|
||||
margin-left: 40px;
|
||||
}
|
||||
|
||||
.feature-card {
|
||||
display: inline-block;
|
||||
width: 280px;
|
||||
height: 280px;
|
||||
padding: 60px 40px;
|
||||
border-radius: 8px;
|
||||
background-color: #fff;
|
||||
vertical-align: top;
|
||||
|
||||
img {
|
||||
width: 60px;
|
||||
height: 60px;
|
||||
margin-bottom: 30px;
|
||||
}
|
||||
|
||||
.h2 {
|
||||
font-size: 24px;
|
||||
margin-bottom: 20px;
|
||||
line-height: 1.33;
|
||||
color: #4d5566;
|
||||
text-shadow: 0 4px 8px rgba(35,45,65,.1);
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.71;
|
||||
color: #8f94a1;
|
||||
font-size: 14px;
|
||||
a {
|
||||
color: #8f94a1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-div-3 {
|
||||
padding-bottom: 60px;
|
||||
padding-top: 120px;
|
||||
text-align: center;
|
||||
|
||||
.app-install-title {
|
||||
position: relative;
|
||||
padding: 80px 0;
|
||||
height: 268px;
|
||||
min-width: 1188px;
|
||||
text-align: center;
|
||||
background-image: linear-gradient(115deg,#4a499a,#8552c3);
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.right {
|
||||
position: absolute;
|
||||
top: 130px;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
div {
|
||||
font-family: $font-family-id;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
text-shadow: 0 8px 16px rgba(35,45,65,.16);
|
||||
font-size: 32px;
|
||||
font-weight: 600;
|
||||
line-height: 1.75;
|
||||
}
|
||||
|
||||
p {
|
||||
max-width: 752px;
|
||||
height: 64px;
|
||||
margin: 16px auto 0;
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
font-family: $font-family-id;
|
||||
text-align: center;
|
||||
color: #fff;
|
||||
}
|
||||
}
|
||||
.slider-wrapper {
|
||||
position: relative;
|
||||
margin: -132px auto 0;
|
||||
height: 612px;
|
||||
width: 1188px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px 0 rgba(36,46,66,.12);
|
||||
background-color: #fff;
|
||||
overflow: hidden;
|
||||
|
||||
.slider-repeat {
|
||||
position: relative;
|
||||
-webkit-animation: scrollUp 30s linear infinite;
|
||||
animation: scrollUp 30s linear infinite;
|
||||
font-size: 0;
|
||||
text-align: center;
|
||||
|
||||
.app {
|
||||
display: inline-block;
|
||||
width: 260px;
|
||||
height: 128px;
|
||||
padding: 0 6px;
|
||||
margin-right: 12px;
|
||||
margin-bottom: 12px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36,46,66,.06), 0 8px 16px 0 rgba(36,46,66,.12);
|
||||
background-color: #fff;
|
||||
text-align: left;
|
||||
vertical-align: top;
|
||||
|
||||
.app-header {
|
||||
display: flex;
|
||||
padding: 12px 6px;
|
||||
border-bottom: 1px solid #e3e9ef;
|
||||
|
||||
.app-icon {
|
||||
width: 40px;
|
||||
height: 40px;
|
||||
margin-right: 12px;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.app-title {
|
||||
display: inline;
|
||||
|
||||
.app-name {
|
||||
font-family: $font-family-id;
|
||||
font-size: 12px;
|
||||
font-weight: 600;
|
||||
line-height: 20px;
|
||||
color: #242e42;
|
||||
}
|
||||
|
||||
.app-version {
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
color: #79879c;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.app-desc {
|
||||
height: 30px;
|
||||
padding: 12px 6px;
|
||||
font-family: PingFang SC,Lantinghei SC,Helvetica Neue,Helvetica,Arial,Microsoft YaHei,微软雅黑,STHeitiSC-Light,simsun,宋体,WenQuanYi Zen Hei,WenQuanYi Micro Hei,sans-serif;
|
||||
overflow: hidden;
|
||||
font-size: 12px;
|
||||
font-weight: 400;
|
||||
line-height: 20px;
|
||||
color: #79879c;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scrollUp {
|
||||
0% {
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: translateY(-840px);
|
||||
transform: translateY(-840px);
|
||||
}
|
||||
}
|
||||
|
||||
.section-div-4 {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
padding-top: 120px;
|
||||
text-align: center;
|
||||
|
||||
.h1 {
|
||||
font-size: 32px;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
text-shadow: 0 4px 8px rgba(35,45,65,.1);
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
& > p {
|
||||
width: 640px;
|
||||
font-size: 16px;
|
||||
margin: 0 auto 50px;
|
||||
line-height: 2;
|
||||
color: #485b7f;
|
||||
}
|
||||
|
||||
.contribute-cards {
|
||||
width: 100%;
|
||||
max-width: 1188px;
|
||||
margin: 0 auto;
|
||||
|
||||
.contribute-card {
|
||||
width: 100%;
|
||||
padding: 40px;
|
||||
border-radius: 8px;
|
||||
margin-top: 24px;
|
||||
background-color: #fff;
|
||||
-webkit-transition: all .3s ease;
|
||||
transition: all .3s ease;
|
||||
text-align: left;
|
||||
|
||||
.contribute-title {
|
||||
margin-bottom: 12px;
|
||||
font-size: 18px;
|
||||
font-weight: 600;
|
||||
line-height: 1.56;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
p {
|
||||
line-height: 1.71;
|
||||
color: #485b7f;
|
||||
font-family: $font-family-id;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
font-family: $font-family-id;
|
||||
line-height: 2.14;
|
||||
color: #919aa3;
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
a {
|
||||
color: #55bc8a;
|
||||
}
|
||||
}
|
||||
|
||||
li:before {
|
||||
content: "";
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 14px;
|
||||
left: -18px;
|
||||
-webkit-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: #55bc8a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-div-5 {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
min-height: 120px;
|
||||
margin-top: 48px;
|
||||
padding: 30px 0;
|
||||
background-color: rgba(143,148,161,.06);
|
||||
text-align: center;
|
||||
|
||||
& > div {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #919aa3;
|
||||
|
||||
img {
|
||||
height: 60px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,787 @@
|
|||
@import 'variables';
|
||||
@import 'mixin';
|
||||
|
||||
section {
|
||||
min-width: 1160px;
|
||||
}
|
||||
|
||||
.section-1 {
|
||||
position: relative;
|
||||
height: 884px;
|
||||
background-image: linear-gradient(to left, #44bd93, #26a678);
|
||||
overflow: hidden;
|
||||
|
||||
& > .img1 {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
& > .img2 {
|
||||
position: absolute;
|
||||
top: 526px;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
& > .img3 {
|
||||
position: absolute;
|
||||
top: 387px;
|
||||
left: 50%;
|
||||
transform: translateX(510px)
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
padding-top: 256px;
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
}
|
||||
|
||||
.p1 {
|
||||
height: 24px;
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
letter-spacing: -0.04px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
h1 {
|
||||
width: 668px;
|
||||
height: 120px;
|
||||
margin-top: 12px;
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
font-size: 50px;
|
||||
font-weight: bold;
|
||||
line-height: 1.2;
|
||||
letter-spacing: -0.14px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
.p2 {
|
||||
width: 668px;
|
||||
height: 72px;
|
||||
margin-top: 12px;
|
||||
margin-bottom: 30px;
|
||||
text-shadow: 0 2px 8px rgba(0, 0, 0, 0.1);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
letter-spacing: -0.04px;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
button {
|
||||
height: 56px;
|
||||
line-height: 56px;
|
||||
border-radius: 28px;
|
||||
text-align: center;
|
||||
font-size: 16px;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
.btn1 {
|
||||
width: 211px;
|
||||
color: #ffffff;
|
||||
box-shadow: 0 10px 50px 0 rgba(34, 43, 62, 0.1), 0 8px 16px 0 rgba(33, 43, 61, 0.2), 0 10px 50px 0 rgba(76, 169, 134, 0.05);
|
||||
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 97%), linear-gradient(to bottom, #000000, #000000);
|
||||
|
||||
}
|
||||
|
||||
.btn2 {
|
||||
width: 195px;
|
||||
margin-left: 12px;
|
||||
color: #36435c;
|
||||
box-shadow: 0 10px 50px 0 rgba(34, 43, 62, 0.1), 0 8px 16px 0 rgba(33, 43, 61, 0.2), 0 10px 50px 0 rgba(76, 169, 134, 0.05);
|
||||
background-image: linear-gradient(to bottom, rgba(255, 255, 255, 0), rgba(255, 255, 255, 0.1) 97%), linear-gradient(to bottom, #ffffff, #ffffff);
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
.img1 {
|
||||
top: 231px;
|
||||
right: 0;
|
||||
z-index: 2;
|
||||
width: 480px;
|
||||
height: 297px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
.img2 {
|
||||
top: 507px;
|
||||
right: 454px;
|
||||
}
|
||||
|
||||
.img4 {
|
||||
top: 276px;
|
||||
left: -311px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
.section-2 {
|
||||
box-sizing: border-box;
|
||||
height: 1079px;
|
||||
position: relative;
|
||||
margin-top: -300px;
|
||||
margin-bottom: -300px;
|
||||
padding-top: 300px;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('/images/home/4.png');
|
||||
z-index: 2;
|
||||
|
||||
& > div {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
|
||||
& > h2 {
|
||||
height: 52px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
& > p {
|
||||
width: 964px;
|
||||
height: 72px;
|
||||
margin: 16px auto 50px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
& > ul {
|
||||
li {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 274px;
|
||||
height: 358px;
|
||||
|
||||
img {
|
||||
margin: 36px auto 20px;
|
||||
}
|
||||
|
||||
h3 {
|
||||
height: 32px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 24px;
|
||||
font-weight: bold;
|
||||
line-height: 1.33;
|
||||
color: #31383e;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 240px;
|
||||
font-size: 16px;
|
||||
margin: 20px auto 0;
|
||||
line-height: 1.5;
|
||||
color: #8f94a1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-3 {
|
||||
position: relative;
|
||||
padding-top: 300px;
|
||||
padding-bottom: 500px;
|
||||
background-color: #f5f8f9;
|
||||
& > div {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
|
||||
& > h2 {
|
||||
height: 52px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
& > p {
|
||||
width: 964px;
|
||||
margin: 16px auto 50px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
margin-top: 76px;
|
||||
padding-left: 214px;
|
||||
text-align: left;
|
||||
|
||||
& > ul {
|
||||
position: absolute;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
flex-direction: column;
|
||||
top: 50%;
|
||||
left: 0;
|
||||
width: 214px;
|
||||
height: 245px;
|
||||
transform: translateY(-50%);
|
||||
border-left: solid 1px #ccd3db;
|
||||
|
||||
& > li {
|
||||
height: 30px;
|
||||
line-height: 30px;
|
||||
padding-left: 24px;
|
||||
margin-left: -1px;
|
||||
font-size: 16px;
|
||||
color: #76808a;
|
||||
cursor: pointer;
|
||||
|
||||
&:hover {
|
||||
color: #31383e;
|
||||
}
|
||||
}
|
||||
|
||||
.active {
|
||||
font-size: 30px;
|
||||
color: #4ca986;
|
||||
border-left: 2px solid #4ca986;
|
||||
|
||||
&:hover {
|
||||
color: #4ca986;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
display: none;
|
||||
width: 919px;
|
||||
height: 436px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #ffffff;
|
||||
|
||||
& > .top {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
width: 643px;
|
||||
height: 132px;
|
||||
padding: 34px 40px;
|
||||
margin-left: 42px;
|
||||
transform: translateY(-36px);
|
||||
border-radius: 10px;
|
||||
color: #ffffff;
|
||||
background-image: linear-gradient(108deg, #4a499a 28%, #8552c3 81%);
|
||||
|
||||
& > h3 {
|
||||
font-size: 24px;
|
||||
line-height: 32px;
|
||||
}
|
||||
|
||||
& > p {
|
||||
font-size: 16px;
|
||||
line-height: 32px;
|
||||
}
|
||||
}
|
||||
|
||||
& > ul {
|
||||
margin-top: 4px;
|
||||
margin-left: 96px;
|
||||
width: 520px;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
font-size: 16px;
|
||||
color: #36435c;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
li::before {
|
||||
content: '';
|
||||
display: block;
|
||||
position: absolute;
|
||||
top: 6px;
|
||||
left: -16px;
|
||||
width: 6px;
|
||||
height: 6px;
|
||||
border-radius: 50%;
|
||||
background-color: #00a971;
|
||||
}
|
||||
}
|
||||
|
||||
& > img {
|
||||
position: absolute;
|
||||
bottom: -50px;
|
||||
right: -16px;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
& > div:nth-child(2) {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-4 {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
height: 1281px;
|
||||
margin-top: -300px;
|
||||
margin-bottom: -500px;
|
||||
padding-top: 350px;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('/images/home/5.png');
|
||||
overflow: hidden;
|
||||
|
||||
& > .bg-1 {
|
||||
position: absolute;
|
||||
top: 620px;
|
||||
right: 50%;
|
||||
transform: translateX(300px);
|
||||
}
|
||||
|
||||
& > .bg-2 {
|
||||
position: absolute;
|
||||
top: 430px;
|
||||
left: 50%;
|
||||
transform: translateX(540px);
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
|
||||
& > div {
|
||||
width: 471px;
|
||||
|
||||
h2 {
|
||||
height: 52px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #b3ffbd;
|
||||
}
|
||||
|
||||
& > p {
|
||||
height: 96px;
|
||||
opacity: 0.9;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
ul {
|
||||
margin-top: 60px;
|
||||
li {
|
||||
font-size: 0;
|
||||
margin-bottom: 30px;
|
||||
div {
|
||||
vertical-align: top;
|
||||
width: 414px;
|
||||
margin-left: 16px;
|
||||
display: inline-block;
|
||||
|
||||
h3 {
|
||||
height: 24px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
color: #ffffff;
|
||||
}
|
||||
|
||||
p {
|
||||
opacity: 0.9;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > ul {
|
||||
position: absolute;
|
||||
top: -350px;
|
||||
right: 0;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
width: 573px;
|
||||
height: 173px;
|
||||
margin-bottom: 10px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #ffffff;
|
||||
|
||||
.top-line {
|
||||
height: 6px;
|
||||
border-top-left-radius: 6px;
|
||||
border-top-right-radius: 6px;
|
||||
}
|
||||
|
||||
.grape {
|
||||
background-image: linear-gradient(to right, #6e56d8 3%, #ac6ef2 100%);
|
||||
}
|
||||
|
||||
.red {
|
||||
background-image: linear-gradient(91deg, #fa6400 18%, #fff8cb 96%);
|
||||
}
|
||||
|
||||
.green {
|
||||
background-image: linear-gradient(to bottom, #86dba2, #00a971);
|
||||
}
|
||||
|
||||
.orange {
|
||||
background-image: linear-gradient(to top, #ecaf24, #fff8cb);
|
||||
}
|
||||
|
||||
.img-span-div {
|
||||
margin-top: 23px;
|
||||
margin-left: 30px;
|
||||
img {
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
span {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
margin-left: 16px;
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
color: #31383e;
|
||||
vertical-align: middle;
|
||||
}
|
||||
}
|
||||
|
||||
p {
|
||||
width: 372px;
|
||||
margin-top: 10px;
|
||||
margin-left: 30px;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
color: #76808a;
|
||||
}
|
||||
|
||||
.middle-line {
|
||||
position: absolute;
|
||||
top: 18px;
|
||||
right: 146px;
|
||||
width: 2px;
|
||||
height: 114px;
|
||||
background-color: #e4edf6;
|
||||
|
||||
}
|
||||
|
||||
a {
|
||||
position: absolute;
|
||||
top: 71px;
|
||||
right: 35px;
|
||||
height: 24px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
line-height: 1.71;
|
||||
color: #00a971;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-5 {
|
||||
box-sizing: border-box;
|
||||
height: 1909px;
|
||||
padding-top: 700px;
|
||||
background-color: #f5f8f9;
|
||||
|
||||
& > div {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
|
||||
h2 {
|
||||
height: 52px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
margin-top: 64px;
|
||||
font-size: 0;
|
||||
|
||||
.front-div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 280px;
|
||||
text-align: center;
|
||||
|
||||
h3 {
|
||||
height: 24px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #31383e;
|
||||
}
|
||||
|
||||
p {
|
||||
width: 280px;
|
||||
height: 84px;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 12px;
|
||||
line-height: 84px;
|
||||
border-radius: 10px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #171c34;
|
||||
box-shadow: 0 6px 4px 0 rgba(0, 0, 0, 0.05);
|
||||
background-color: #ffffff;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
}
|
||||
|
||||
ul {
|
||||
padding: 24px 25px 29px 29px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 6px 4px 0 rgba(0, 0, 0, 0.05);
|
||||
background-color: #ffffff;
|
||||
li {
|
||||
margin-bottom: 24px;
|
||||
img {
|
||||
width: 229px;
|
||||
height: 160px;
|
||||
object-fit: contain;
|
||||
box-shadow: 0 6px 4px 0 rgba(0, 0, 0, 0.05);
|
||||
}
|
||||
}
|
||||
li:last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.back-div {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
width: 867px;
|
||||
margin-left: 13px;
|
||||
|
||||
h3 {
|
||||
height: 24px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 24px;
|
||||
font-weight: 600;
|
||||
color: #31383e;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
& > .group {
|
||||
box-sizing: border-box;
|
||||
height: 84px;
|
||||
margin-top: 24px;
|
||||
margin-bottom: 12px;
|
||||
padding: 24px 40px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 6px 4px 0 rgba(0, 0, 0, 0.05);
|
||||
background-color: #ffffff;
|
||||
|
||||
p {
|
||||
display: inline-block;
|
||||
height: 24px;
|
||||
margin-top: 6px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
ul {
|
||||
display: inline-block;
|
||||
margin-left: 30px;
|
||||
li {
|
||||
display: inline-block;
|
||||
height: 36px;
|
||||
padding: 0 20px;
|
||||
margin-left: 8px;
|
||||
border-radius: 4px;
|
||||
background-color: #fbf3dd;
|
||||
line-height: 36px;
|
||||
font-size: 14px;
|
||||
font-weight: 600;
|
||||
letter-spacing: 0.27px;
|
||||
color: #31383e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
& > .image {
|
||||
box-sizing: border-box;
|
||||
height: 581px;
|
||||
padding: 24px 38px;
|
||||
font-size: 12px;
|
||||
border-radius: 10px;
|
||||
box-shadow: 0 6px 4px 0 rgba(0, 0, 0, 0.05);
|
||||
background-color: #ffffff;
|
||||
overflow: hidden;
|
||||
font-size: 0;
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
width: 790px;
|
||||
height: 878px;
|
||||
object-fit: contain;
|
||||
-webkit-animation: scrollUp 30s linear infinite;
|
||||
animation: scrollUp 30s linear infinite;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@keyframes scrollUp {
|
||||
0% {
|
||||
-webkit-transform: translateY(0);
|
||||
transform: translateY(0);
|
||||
}
|
||||
|
||||
100% {
|
||||
-webkit-transform: translateY(-878px);
|
||||
transform: translateY(-878px);
|
||||
}
|
||||
}
|
||||
|
||||
.section-6 {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
height: 1100px;
|
||||
margin-top: -300px;
|
||||
padding-top: 300px;
|
||||
background-color: #f5f8f9;
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
background-image: url('/images/home/6.png');
|
||||
overflow-x: hidden;
|
||||
|
||||
.bg-1 {
|
||||
position: absolute;
|
||||
top: 430px;
|
||||
right: 50%;
|
||||
transform: translateX(-500px);
|
||||
}
|
||||
|
||||
.bg-2 {
|
||||
position: absolute;
|
||||
top: 580px;
|
||||
right: 50%;
|
||||
transform: translateX(650px);
|
||||
}
|
||||
|
||||
& > div {
|
||||
position: relative;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
text-align: center;
|
||||
z-index: 2;
|
||||
|
||||
h2 {
|
||||
height: 52px;
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-family: Roboto;
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
& > p {
|
||||
width: 965px;
|
||||
height: 64px;
|
||||
margin: 12px auto;
|
||||
white-space: pre;
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
ul {
|
||||
@include common-flex-style;
|
||||
margin-top: 59px;
|
||||
margin-bottom: 45px;
|
||||
li {
|
||||
margin-bottom: 16px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
}
|
||||
img {
|
||||
width: 210px;
|
||||
height: 100px;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
|
||||
button {
|
||||
width: 263px;
|
||||
height: 56px;
|
||||
border-radius: 28px;
|
||||
border: none;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
letter-spacing: -0.04px;
|
||||
color: #ffffff;
|
||||
cursor: pointer;
|
||||
box-shadow: 0 10px 50px 0 rgba(34, 43, 62, 0.1), 0 8px 16px 0 rgba(33, 43, 61, 0.2), 0 10px 50px 0 rgba(34, 43, 62, 0.1);
|
||||
background-image: linear-gradient(to bottom, rgba(85, 188, 138, 0), rgba(85, 188, 138, 0.1) 97%), linear-gradient(to bottom, #55bc8a, #55bc8a);
|
||||
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
}
|
||||
|
||||
& > .link-div {
|
||||
height: 24px;
|
||||
margin-top: 14px;
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
line-height: 1.5;
|
||||
letter-spacing: -0.04px;
|
||||
text-align: center;
|
||||
a {
|
||||
color: #31383e;
|
||||
text-decoration: underline;
|
||||
}
|
||||
}
|
||||
|
||||
.bottom-img {
|
||||
width: 639px;
|
||||
height: 72px;
|
||||
margin-top: 107px;
|
||||
object-fit: contain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,3 +1,4 @@
|
|||
@import "variables";
|
||||
$mobile-max-width: 768px;
|
||||
|
||||
.md-body {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
@mixin common-center-div-style {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
||||
@mixin common-p-style {
|
||||
font-size: 16px;
|
||||
line-height: 2;
|
||||
color: #919aa3;
|
||||
}
|
||||
|
||||
@mixin common-title-style {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 1.2;
|
||||
letter-spacing: -0.06px;
|
||||
color: #3e464c;
|
||||
}
|
||||
|
||||
@mixin common-h2-style {
|
||||
text-shadow: 0 4px 8px rgba(35, 45, 65, 0.1);
|
||||
font-size: 32px;
|
||||
font-weight: bold;
|
||||
line-height: 1.63;
|
||||
color: #171c34;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@mixin common-flex-style {
|
||||
display: flex;
|
||||
flex-wrap: wrap ;
|
||||
justify-content: space-between;
|
||||
}
|
||||
|
||||
@mixin common-content-div-style {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
}
|
||||
|
|
@ -0,0 +1,84 @@
|
|||
.open-source-header {
|
||||
text-align: center;
|
||||
margin-top: 93px;
|
||||
h1 {
|
||||
margin-bottom: 20px;
|
||||
font-size: 40px;
|
||||
font-weight: 600;
|
||||
line-height: 1.4;
|
||||
text-shadow: 0 8px 16px rgba(35,45,65,.16);
|
||||
color: #36435c;
|
||||
}
|
||||
p {
|
||||
max-width: 760px;
|
||||
margin: 0 auto 30px;
|
||||
font-size: 14px;
|
||||
line-height: 2.29;
|
||||
text-shadow: 0 8px 16px rgba(35,45,65,.16);
|
||||
color: #36435c;
|
||||
}
|
||||
button {
|
||||
height: 48px;
|
||||
border-radius: 30px;
|
||||
font-size: 16px;
|
||||
padding: 7px 20px;
|
||||
font-weight: 600;
|
||||
color: #fff;
|
||||
line-height: 1.5;
|
||||
text-align: center;
|
||||
border: none;
|
||||
cursor: pointer;
|
||||
-webkit-transition: all .3s ease;
|
||||
transition: all .3s ease;
|
||||
box-sizing: border-box;
|
||||
vertical-align: middle;
|
||||
background-color: #242e42;
|
||||
box-shadow: 0 10px 50px 0 rgba(34,43,62,.1),0 8px 16px 0 rgba(33,43,61,.2);
|
||||
&:hover {
|
||||
box-shadow: none;
|
||||
}
|
||||
svg {
|
||||
width: 21px;
|
||||
height: 21px;
|
||||
margin-right: 12px;
|
||||
vertical-align: text-top;
|
||||
}
|
||||
}
|
||||
ul {
|
||||
margin-top: 77px;
|
||||
li {
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
margin-bottom: 32px;
|
||||
font-size: 16px;
|
||||
font-weight: 600;
|
||||
color: #36435c;
|
||||
cursor: pointer;
|
||||
}
|
||||
li + li {
|
||||
margin-left: 40px;
|
||||
}
|
||||
a {
|
||||
color: rgb(48, 62, 90);
|
||||
&:hover {
|
||||
color: #4ca986;
|
||||
}
|
||||
}
|
||||
.active {
|
||||
color: #4ca986;
|
||||
&::after {
|
||||
position: absolute;
|
||||
bottom: -32px;
|
||||
left: 50%;
|
||||
-webkit-transform: translateX(-50%);
|
||||
transform: translateX(-50%);
|
||||
content: "";
|
||||
width: 0;
|
||||
height: 0;
|
||||
border: 1em solid transparent;
|
||||
border-bottom-color: #fff;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,227 @@
|
|||
@import 'variables';
|
||||
@import 'mixin';
|
||||
|
||||
.section-1 {
|
||||
position: relative;
|
||||
height: 300px;
|
||||
min-width: 1160px;
|
||||
|
||||
img {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
object-fit:cover;
|
||||
}
|
||||
|
||||
.title-div {
|
||||
position: absolute;
|
||||
top: 138px;
|
||||
left: 0;
|
||||
right: 0;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
h1 {
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
letter-spacing: -0.11px;
|
||||
color: #ffffff;
|
||||
}
|
||||
p {
|
||||
width: 1067px;
|
||||
margin: 12px auto 0;
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
letter-spacing: -0.04px;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
.section-2 {
|
||||
& > div {
|
||||
display: flex;
|
||||
position: relative;
|
||||
top: -40px;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06);
|
||||
.left-div {
|
||||
width: 470px;
|
||||
height: 298px;
|
||||
border-radius: 10px 0 0 10px;
|
||||
background-color: #ffffff;
|
||||
div {
|
||||
@include common-title-style;
|
||||
width: 351px;
|
||||
height: 48px;
|
||||
margin: 38px 80px 12px 40px;
|
||||
}
|
||||
p {
|
||||
@include common-p-style;
|
||||
width: 391px;
|
||||
height: 160px;
|
||||
margin-left: 40px;
|
||||
}
|
||||
}
|
||||
.right-div {
|
||||
position: relative;
|
||||
width: 690px;
|
||||
height: 298px;
|
||||
border-radius: 0 10px 10px 0;
|
||||
background-color: #3d3e49;
|
||||
|
||||
img {
|
||||
margin-top: 107px;
|
||||
margin-left: 45px;
|
||||
}
|
||||
|
||||
.btn-div {
|
||||
position: absolute;
|
||||
width: 92px;
|
||||
height: 27px;
|
||||
font-size: 14px;
|
||||
line-height: 27px;
|
||||
text-align: center;
|
||||
color: #ffffff;
|
||||
border-radius: 100px;
|
||||
box-shadow: 0 2px 8px 0 rgba(250, 164, 66, 0.5);
|
||||
background-image: linear-gradient(107deg, #fdba39 20%, #f2635e 99%);
|
||||
}
|
||||
|
||||
.div-1 {
|
||||
top: 116px;
|
||||
left: 85px;
|
||||
background-image: linear-gradient(107deg, #f2635e 20%, #fdba39 99%);
|
||||
}
|
||||
|
||||
.div-2 {
|
||||
top: 89px;
|
||||
left: 294px;
|
||||
}
|
||||
|
||||
.div-3 {
|
||||
top: 92px;
|
||||
right: 97px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-3 {
|
||||
padding-top: 54px;
|
||||
background-image: url('/images/partner/oval-4.svg');
|
||||
background-position: center top;
|
||||
background-repeat: no-repeat;
|
||||
|
||||
& > div {
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
h2 {
|
||||
@include common-h2-style;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul {
|
||||
@include common-flex-style;
|
||||
margin-top: 20px;
|
||||
|
||||
li {
|
||||
width: 570px;
|
||||
height: 309px;
|
||||
border-radius: 10px;
|
||||
margin-top: 20px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #ffffff;
|
||||
|
||||
h3 {
|
||||
margin: 40px 40px 20px;
|
||||
@include common-title-style;
|
||||
}
|
||||
|
||||
p {
|
||||
margin-left: 40px;
|
||||
margin-right: 40px;
|
||||
@include common-p-style;
|
||||
}
|
||||
|
||||
div {
|
||||
margin-left: 40px;
|
||||
margin-top: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 1.5;
|
||||
|
||||
a {
|
||||
color: #00a971;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.section-4 {
|
||||
& > div {
|
||||
@include common-center-div-style;
|
||||
margin-top: 80px;
|
||||
h2 {
|
||||
@include common-h2-style;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
ul {
|
||||
@include common-flex-style;
|
||||
margin-top: 20px;
|
||||
|
||||
.intro {
|
||||
background-image: radial-gradient(circle at -23% -21%, #cdf6d5, #089566 75%);
|
||||
|
||||
p {
|
||||
margin: 40px 30px;
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
color: #ffffff;
|
||||
}
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
width: 274px;
|
||||
height: 200px;
|
||||
margin-top: 20px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 8px 0 rgba(36, 46, 66, 0.06), 0 8px 16px 0 rgba(36, 46, 66, 0.05);
|
||||
background-color: #ffffff;
|
||||
|
||||
&:hover {
|
||||
div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
width: 200px;
|
||||
height: 100px;
|
||||
margin: 50px 37px;
|
||||
object-fit: contain;
|
||||
}
|
||||
|
||||
div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 0;
|
||||
width: 106px;
|
||||
height: 32px;
|
||||
object-fit: contain;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
font-size: 12px;
|
||||
color: #ffffff;
|
||||
border-radius: 16px 0 0 16px;
|
||||
box-shadow: 0 2px 8px 0 rgba(250, 164, 66, 0.5);
|
||||
background-image: linear-gradient(108deg, #fdba39 20%, #f2635e 99%);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,113 @@
|
|||
@import 'open-source';
|
||||
|
||||
|
||||
.tab-content {
|
||||
background-color: #fff;
|
||||
padding-top: 60px;
|
||||
padding-bottom: 100px;
|
||||
|
||||
.content {
|
||||
position: relative;
|
||||
min-height: 380px;
|
||||
width: 1160px;
|
||||
margin: 0 auto;
|
||||
padding-bottom: 20px;
|
||||
|
||||
.left {
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
width: 200px;
|
||||
padding: 0 30px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 15px 0 rgba(7,42,68,.1);
|
||||
background-color: #fff;
|
||||
|
||||
li:first-of-type {
|
||||
border-bottom: 1px solid rgba(181,193,204,.5);
|
||||
font-size: 16px;
|
||||
font-weight: 500;
|
||||
color: #36435c;
|
||||
line-height: 22px;
|
||||
padding: 20px 0;
|
||||
margin-bottom: 5px;
|
||||
}
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
padding: 15px 0;
|
||||
font-size: 14px;
|
||||
line-height: 20px;
|
||||
color: #36435c;
|
||||
-webkit-transition: all .2s ease-in-out;
|
||||
transition: all .2s ease-in-out;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
li:hover, li.active {
|
||||
color: #4ca986;
|
||||
}
|
||||
}
|
||||
|
||||
.right {
|
||||
padding-left: 300px;
|
||||
|
||||
li {
|
||||
position: relative;
|
||||
padding: 32px 157px 32px 120px;
|
||||
border-radius: 4px;
|
||||
box-shadow: 0 4px 15px 0 rgba(7,42,68,.1);
|
||||
background-color: #fff;
|
||||
|
||||
&:hover {
|
||||
div {
|
||||
display: block;
|
||||
}
|
||||
}
|
||||
|
||||
img {
|
||||
position: absolute;
|
||||
width: 64px;
|
||||
height: 64px;
|
||||
top: 50%;
|
||||
left: 28px;
|
||||
-webkit-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
& > a {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 1.6;
|
||||
margin-bottom: 8px;
|
||||
color: #36435c;
|
||||
}
|
||||
|
||||
p {
|
||||
font-size: 14px;
|
||||
line-height: 1.71;
|
||||
color: #8f94a1;
|
||||
}
|
||||
|
||||
div {
|
||||
display: none;
|
||||
position: absolute;
|
||||
top: 50%;
|
||||
right: 40px;
|
||||
-webkit-transform: translateY(-50%);
|
||||
transform: translateY(-50%);
|
||||
font-size: 16px;
|
||||
line-height: 1.5;
|
||||
|
||||
a {
|
||||
color: #55bc8a;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
li + li {
|
||||
margin-top: 12px;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1 @@
|
|||
@import 'open-source';
|
||||
236
config.toml
236
config.toml
|
|
@ -1,125 +1,251 @@
|
|||
baseURL = "http://example.org/"
|
||||
languageCode = "en-us"
|
||||
baseURL = "https://hugo-first.netlify.app"
|
||||
|
||||
[markup]
|
||||
[markup.tableOfContents]
|
||||
endLevel = 4
|
||||
ordered = false
|
||||
startLevel = 2
|
||||
|
||||
|
||||
[params]
|
||||
logo = "images/logo.svg"
|
||||
bg1 = "images/bg-1.svg"
|
||||
img1 = "images/1.svg"
|
||||
img2 = "images/2.png"
|
||||
left = "images/left.svg"
|
||||
right = "images/right.svg"
|
||||
cloud = "images/cloud-native1.png"
|
||||
certified = "images/certified.svg"
|
||||
|
||||
[languages.en]
|
||||
title = "KubeSphere | Enterprise container platform, built on Kubernetes"
|
||||
description = "KubeSphere is an open source container platform based on Kubernetes for enterprise app development and deployment, suppors installing anywhere from on-premise datacenter to any cloud to edge."
|
||||
languageName ="English"
|
||||
contentDir = "content/en"
|
||||
weight = 1
|
||||
languageCode = "en-US"
|
||||
languageName = "English"
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
weight = 1
|
||||
name = "Open Source"
|
||||
name = "Why KubeSphere"
|
||||
URL = "reason"
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
weight = 2
|
||||
name = "Scenario"
|
||||
hasChildren = true
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Open Source"
|
||||
parent = "Scenario"
|
||||
name = "Multi-cluster"
|
||||
URL = "multi-cluster"
|
||||
weight = 1
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "DevOps"
|
||||
URL = "devOps"
|
||||
weight = 2
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Network"
|
||||
URL = "network"
|
||||
weight = 3
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Service Mesh"
|
||||
URL = "service-mesh"
|
||||
weight = 4
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Storage"
|
||||
URL = "storage"
|
||||
weight = 5
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "AppStore"
|
||||
URL = "app-store"
|
||||
weight = 6
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Multi-tenancy"
|
||||
URL = "multi-tenancy"
|
||||
weight = 7
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Observability"
|
||||
URL = "observability"
|
||||
weight = 8
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
weight = 3
|
||||
name = "Resources"
|
||||
hasChildren = true
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Resources"
|
||||
name = "Open Source Projects"
|
||||
URL = "projects"
|
||||
weight = 1
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Open Source"
|
||||
parent = "Resources"
|
||||
name = "KubeCon & QCon"
|
||||
URL = "conferences"
|
||||
weight = 2
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Open Source"
|
||||
parent = "Resources"
|
||||
name = "Technology Blogs"
|
||||
URL = "blogs"
|
||||
weight = 3
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Open Source"
|
||||
parent = "Resources"
|
||||
name = "Video Resources"
|
||||
URL = "videos"
|
||||
weight = 4
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
name = "Quick Installation"
|
||||
URL = "install"
|
||||
weight = 2
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
weight = 3
|
||||
weight = 4
|
||||
name = "Documentation"
|
||||
URL = "docs"
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
weight = 4
|
||||
name = "Forum"
|
||||
URL = "forum"
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
weight = 5
|
||||
name = "News"
|
||||
URL = "trends"
|
||||
hasChildren = true
|
||||
name = "Community"
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Community"
|
||||
name = "Contribution"
|
||||
URL = "contribution"
|
||||
weight = 1
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Community"
|
||||
name = "Case Studies"
|
||||
URL = "case"
|
||||
weight = 2
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Community"
|
||||
name = "Partner"
|
||||
URL = "partner"
|
||||
weight = 3
|
||||
|
||||
[languages.zh]
|
||||
title = "KubeSphere-以应用为中心的开源容器平台"
|
||||
description = "KubeSphere 是在 Kubernetes 之上构建的以应用为中心的开源容器平台,支持部署和运行在任何基础设施之上,帮助企业轻松应对敏捷开发、自动化运维、应用快速交付、微服务治理、多租户管理、监控日志告警、服务与网络管理等业务场景"
|
||||
languageName = "简体中文"
|
||||
weight = 2
|
||||
contentDir = "content/zh"
|
||||
languageCode = "zh-CN"
|
||||
languageName = "简体中文"
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
weight = 1
|
||||
name = "开源社区"
|
||||
name = "Why KubeSphere"
|
||||
URL = "reason"
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
weight = 2
|
||||
name = "Scenario"
|
||||
hasChildren = true
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "开源社区"
|
||||
name = "开源项目"
|
||||
parent = "Scenario"
|
||||
name = "Multi-cluster"
|
||||
URL = "multi-cluster"
|
||||
weight = 1
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "DevOps"
|
||||
URL = "devOps"
|
||||
weight = 2
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Network"
|
||||
URL = "network"
|
||||
weight = 3
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Service Mesh"
|
||||
URL = "service-mesh"
|
||||
weight = 4
|
||||
|
||||
[[languages.en.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Storage"
|
||||
URL = "storage"
|
||||
weight = 5
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "AppStore"
|
||||
URL = "app-store"
|
||||
weight = 6
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Multi-tenancy"
|
||||
URL = "multi-tenancy"
|
||||
weight = 7
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Scenario"
|
||||
name = "Observability"
|
||||
URL = "observability"
|
||||
weight = 8
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
weight = 3
|
||||
name = "Resources"
|
||||
hasChildren = true
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Resources"
|
||||
name = "Open Source Projects"
|
||||
URL = "projects"
|
||||
weight = 1
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "开源社区"
|
||||
parent = "Resources"
|
||||
name = "KubeCon & QCon"
|
||||
URL = "conferences"
|
||||
weight = 2
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "开源社区"
|
||||
name = "技术博客"
|
||||
parent = "Resources"
|
||||
name = "Technology Blogs"
|
||||
URL = "blogs"
|
||||
weight = 3
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "开源社区"
|
||||
name = "视频资源"
|
||||
parent = "Resources"
|
||||
name = "Video Resources"
|
||||
URL = "videos"
|
||||
weight = 4
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
name = "快速安装"
|
||||
URL = "install"
|
||||
weight = 2
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
weight = 3
|
||||
name = "文档中心"
|
||||
weight = 4
|
||||
name = "Documentation"
|
||||
URL = "docs"
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
weight = 4
|
||||
name = "开发者社区"
|
||||
URL = "forum"
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
weight = 5
|
||||
name = "动态"
|
||||
URL = "trends"
|
||||
hasChildren = true
|
||||
name = "Community"
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Community"
|
||||
name = "Contribution"
|
||||
URL = "contribution"
|
||||
weight = 1
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Community"
|
||||
name = "Case Studies"
|
||||
URL = "case"
|
||||
weight = 2
|
||||
|
||||
[[languages.zh.menu.main]]
|
||||
parent = "Community"
|
||||
name = "Partner"
|
||||
URL = "partner"
|
||||
weight = 3
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
---
|
||||
title: KubeSphere | Enterprise container platform, built on Kubernetes
|
||||
description: KubeSphere is an open source container platform based on Kubernetes for enterprise app development and deployment, suppors installing anywhere from on-premise datacenter to any cloud to edge.
|
||||
|
||||
|
||||
css: scss/index.scss
|
||||
|
||||
section1:
|
||||
title: KubeSphere Container Platform
|
||||
topic: The Kubernetes Platform, tailored to the hybrid cloud
|
||||
content: KubeSphere is a distributed operating system providing cloud native stack with Kubernetes as its kernel, and aims to be plug-and-play architecture for third-party applications seamless integration to boost its ecosystem.
|
||||
btnContent1: Install on Kubernetes
|
||||
btnContent2: Install on Linux
|
||||
|
||||
section2:
|
||||
title: One Platform for full-stack solutions
|
||||
content: KubeSphere is also a multi-tenant enterprise-grade container platform with full-stack automated IT operation and streamlined DevOps workflows. It provides developer-friendly wizard web UI, helping enterprises to build out a more robust and feature-rich platform, which includes most common functionalities needed for enterprise Kubernetes strategy.,
|
||||
children:
|
||||
- name: Open Source
|
||||
icon: /images/home/open-source.svg
|
||||
content: A CNCF certified Kubernetes platform, 100% open source, built and improved by the community
|
||||
|
||||
- name: Easy to Run
|
||||
icon: /images/home/easy-to-run.svg
|
||||
content: Can be deployed on a Kubernetes cluster or Linux machines, supports online and air-gapped installation
|
||||
|
||||
- name: Feature-rich
|
||||
icon: /images/home/feature-rich.svg
|
||||
content: Delivers DevOps, service mesh, observability, application management, multi-tenancy, storage and networking management in an unified platform
|
||||
|
||||
- name: Modular & Pluggable
|
||||
icon: /images/home/modular-pluggable.svg
|
||||
content: These functionalities are loosely coupled with the platform since they are pluggable and optional. Other tools are easy to integrate and play
|
||||
|
||||
|
||||
|
||||
section3:
|
||||
title: Benefits to different teams
|
||||
content: Multi-tenancy makes different teams to securely deploy and maintain containerized applications from the cloud to the edge. It allows developers to deploy code via several clicks on intuitive console, brings centralized observability and powerful DevOps strategy for Ops team, helps Infra team to install and maintain Kubernetes cluster with flexible network and solution solutions, avoid locking team in to a single vendor eco-system.
|
||||
children:
|
||||
- name: Infra Team
|
||||
content: Automated installation, scaling, and upgrades from cloud to data center
|
||||
icon: /images/home/7.svg
|
||||
children:
|
||||
- content: Improve your environment utilization and reduce internal infrastructure costs
|
||||
- content: Support multi-cluster and multi-cloud Kubernetes management, avoiding vendor lock-in
|
||||
- content: Provides security enhancements, supports multiple storage and network solutions
|
||||
- content: Fully trusted, delivers a certified Kubernetes platform and distribution
|
||||
|
||||
- name: Developers
|
||||
content: Focus on your bussiness, others are run in automated tools
|
||||
icon: /images/home/74.png
|
||||
children:
|
||||
- content: Smooth user experience, reduce the learning curve of the cloud native stack
|
||||
- content: Provide toolkits and deployment automation tailored to any application environment
|
||||
- content: Out-of-box logging, monitoring and multi-tenancy, improving development efficiency
|
||||
- content: Support application lifecycle management, accelerating time to market
|
||||
|
||||
- name: Ops Team
|
||||
content: Building one-stop enterprise-grade DevOps framework
|
||||
icon: /images/home/71.svg
|
||||
children:
|
||||
- content: Centralized log collection, monitoring and alerting from infrastructure to applications.
|
||||
- content: Streamlined continuous deploy, test, release, upgrade and scale
|
||||
- content: Better track, route and optimize communications within Kubernetes for cloud native apps
|
||||
- content: Easy-to-use web terminal and graphical panel, satisfying the habits of different users
|
||||
|
||||
section4:
|
||||
title: Key Features
|
||||
content: If you want to use an open source project, but act like a commercial product, KubeSphere is your choice. <br>The Roadmap listed the planning features, you can raise a proposal to submit your ideas with us.
|
||||
children:
|
||||
- name: Provisioning Kubernetes
|
||||
icon: /images/home/provisioning-kubernetes.svg
|
||||
content: Deploy Kubernetes on any infrastructure out of box, including online and air-gapped installation, support add GPU node
|
||||
|
||||
- name: K8s Resource Management
|
||||
icon: /images/home/k-8-s-resource-management.svg
|
||||
content: Provide web console for creating and managing Kubernetes resources, with powerful observability
|
||||
|
||||
- name: Multi-tenant Management
|
||||
icon: /images/home/multi-tenant-management.svg
|
||||
content: Provide unified authentication with fine-grained roles and three-tier authorization system, supports AD/LDAP authentication
|
||||
|
||||
features:
|
||||
- name: Application Store
|
||||
icon: /images/home/store.svg
|
||||
content: Provide application store for Helm-based applications, and offers application lifecycle management
|
||||
color: grape
|
||||
|
||||
- name: Service Mesh (Istio-based)
|
||||
icon: /images/home/service.svg
|
||||
content: Provide fine-grained traffic management, observability and tracing, and offers visualization for traffic topology
|
||||
color: red
|
||||
|
||||
- name: Rich Observability
|
||||
icon: /images/home/rich.svg
|
||||
content: Multi-dimensional monitoring metrics, multi-tenant log query and collection, support alerting and notification
|
||||
color: green
|
||||
|
||||
- name: DevOps System
|
||||
icon: /images/home/dev-ops.svg
|
||||
content: Out-of-box CI/CD based on Jenkins, and offers automated workflow tools including S2I & B2I
|
||||
color: orange
|
||||
|
||||
- name: Multiple Storage Solutions
|
||||
icon: /images/home/multiple.svg
|
||||
content: Support GlusterFS, CephRBD, NFS, LocalPV solutions, provide CSI plugins to consume storage from multiple cloud providers
|
||||
color: grape
|
||||
|
||||
- name: Multiple Network Solutions
|
||||
icon: /images/home/network.svg
|
||||
content: Support Calico and Flannel, provides load balancer plug-in Porter for Kubernetes installed on physical machines
|
||||
color: green
|
||||
|
||||
- name: Multi-cluster management
|
||||
icon: /images/home/management.svg
|
||||
content: Distribute applications across multiple clusters and cloud providers, and provides the disaster recovery and cross-cluster discovery.
|
||||
color: orange
|
||||
|
||||
section5:
|
||||
title: KubeSphere with its cloud native architecture
|
||||
frontEnd:
|
||||
title: Front end
|
||||
project: KubeSphere Console
|
||||
children:
|
||||
- icon: /images/home/mobx.jpg
|
||||
- icon: /images/home/koa.jpg
|
||||
- icon: /images/home/react.png
|
||||
|
||||
backEnd:
|
||||
title: Back end (REST API)
|
||||
project: KubeSphere System
|
||||
group:
|
||||
- name: API Server
|
||||
- name: API Gateway
|
||||
- name: Controller Manager
|
||||
- name: Account Service
|
||||
|
||||
|
||||
section6:
|
||||
title: Who uses KubeSphere
|
||||
content: The Case Studies listed more detailed user cases and their cloud native transformation stories. </br>Various enterprises and organizations use KubeSphere Container Platform for research, production and commercial products.
|
||||
children:
|
||||
- icon: /images/home/section6-1.jpg
|
||||
- icon: /images/home/section6-2.jpg
|
||||
- icon: /images/home/section6-3.jpg
|
||||
- icon: /images/home/section6-4.jpg
|
||||
- icon: /images/home/section6-5.jpg
|
||||
- icon: /images/home/section6-6.jpg
|
||||
- icon: /images/home/section6-7.jpg
|
||||
- icon: /images/home/section6-8.jpg
|
||||
- icon: /images/home/section6-9.jpg
|
||||
- icon: /images/home/section6-10.jpg
|
||||
btnContent: Case Studies
|
||||
btnLink:
|
||||
link:
|
||||
linkContent: Want your logo up there? Just submit a pull request →
|
||||
image: /images/home/certification.jpg
|
||||
---
|
||||
|
|
@ -1,4 +1,5 @@
|
|||
---
|
||||
title: "page1"
|
||||
title: blogs
|
||||
|
||||
css: scss/blogs.scss
|
||||
---
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
title: "case"
|
||||
css: "scss/case.scss"
|
||||
|
||||
|
||||
section1:
|
||||
title: User Case Studies
|
||||
content: KubeSphere is trusted by various enterprises and organizations to the innovators driving the future of software.
|
||||
topImage: "images/case/case-top.jpg"
|
||||
|
||||
section2:
|
||||
tip: Read Case Study →
|
||||
caseList:
|
||||
- icon: "images/case/case1.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case2.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case3.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case4.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case5.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case6.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
section3:
|
||||
title: 'Various Industries are Powered by KubeSphere'
|
||||
tip: ALL
|
||||
caseType:
|
||||
- name: 'Financial'
|
||||
children:
|
||||
- name: 'sina'
|
||||
icon: 'images/case/v1.jpg'
|
||||
- name: 'benlai'
|
||||
icon: 'images/case/v2.jpg'
|
||||
|
||||
- name: 'T Service'
|
||||
children:
|
||||
- name: 'inaccel'
|
||||
icon: 'images/case/v3.jpg'
|
||||
- name: 'founder'
|
||||
icon: 'images/case/v4.jpg'
|
||||
|
||||
- name: 'E-Business'
|
||||
children:
|
||||
- name: 'huaxia'
|
||||
icon: 'images/case/v5.jpg'
|
||||
- name: 'aqara'
|
||||
icon: 'images/case/v6.jpg'
|
||||
|
||||
- name: 'Manufacture'
|
||||
children:
|
||||
- name: 'powersmart'
|
||||
icon: 'images/case/v7.jpg'
|
||||
- name: 'anchnet'
|
||||
icon: 'images/case/v8.jpg'
|
||||
---
|
||||
|
|
@ -1,4 +1,49 @@
|
|||
---
|
||||
title: "page1"
|
||||
|
||||
|
||||
css: "scss/conferences.scss"
|
||||
|
||||
viewDetail: View Details
|
||||
|
||||
list:
|
||||
- name: KubeCon
|
||||
content: KUBECON_DESC
|
||||
icon: images/conferences/kubecon.svg
|
||||
bg: images/conferences/kubecon-bg.svg
|
||||
children:
|
||||
- name: 'Multi-tenant Management: Creating Accounts, Roles, Workspaces, Projects and DevOps Projects'
|
||||
summary: ObjectiveIn this quickstart, as a cluster admin, you will learn how to create workspaces, roles and user accounts, and then invite new users…
|
||||
author: xxx
|
||||
link: admin-quick-start
|
||||
image:
|
||||
|
||||
- name: Managing Canary Release of Microservice Application on Kubernetes with Istio
|
||||
summary: Istio’s service mesh is able to manage traffic distribution with complete independence from deployment scaling, which enables a simpler, yet…
|
||||
author: xxx
|
||||
link: canary-release
|
||||
image:
|
||||
|
||||
- name: Deploying a Grafana Application to Kubernetes Using Application Template
|
||||
summary: ObjectiveThis tutorial shows you how to quickly deploy a Grafana application in KubeSphere via App Template, demonstrating the basic…
|
||||
author: xxx
|
||||
link: app-template
|
||||
image:
|
||||
|
||||
- name: QCon International Software Development Conference
|
||||
content: QCON_DESC
|
||||
icon: images/conferences/qcon.svg
|
||||
bg: images/conferences/qcon-bg.svg
|
||||
children:
|
||||
- name: Creating a CI/CD Pipeline to Deploy Spring Boot App to Kubernetes
|
||||
summary: ObjectiveThis tutorial shows you how to create a CI/CD Pipeline within DevOps project, which is intended for deploying a Spring Boot sample…
|
||||
author: xxx
|
||||
link: cicd-jenkinsfile
|
||||
image:
|
||||
|
||||
- name: Creating Horizontal Pod Autoscaler for Deployment
|
||||
summary: The Horizontal Pod Autoscaler automatically scales the number of pods in a deployment based on observed CPU utilization or Memory usage. The…
|
||||
author: xxx
|
||||
link: hpa
|
||||
image:
|
||||
---
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
---
|
||||
title: 'Multi-tenant Management: Creating Accounts, Roles, Workspaces, Projects and DevOps Projects'
|
||||
author: 'xxx'
|
||||
date: '2019-06-24'
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
In this quickstart, as a cluster admin, you will learn how to create workspaces, roles and user accounts, and then invite new users into the workspace to create their projects and DevOps projects. This tutorial is used to help beginners to become familiar with multi-tenant management.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You need to [install KubeSphere](https://kubesphere.io/en/install).
|
||||
- You need a default admin account.
|
||||
|
||||
## Hands-on Lab
|
||||
|
||||
Generally, the hierarchy relationship of Cluster, Workspace, Project and DevOps Project showing as the following graph, and there are common built-in roles existed in these orgnizations within each level.
|
||||
|
||||

|
||||
|
||||
### Cluster Admin
|
||||
|
||||
The role of cluster-admin is able to create accounts for other users and assign roles to them. There are three common roles in cluster level, it also supports customizing new roles.
|
||||
|
||||
| Built-in Roles | Responsibility |
|
||||
| ------------------ | ---------------------------------------------------------------------------------------------------------- |
|
||||
| cluster-admin | Have the highest privileges for the cluster, can manage any resources |
|
||||
| workspaces-manager | The workspace managers, can manage all of the resources, e.g. projects, DevOps projects, members and roles |
|
||||
| cluster-regular | The regular users in the cluster, they are not authorized until they have been invited to the workspace |
|
||||
|
||||
#### Step 1: Create roles and accounts
|
||||
|
||||
First, we will create a new role (user-manager), grants account management and role management authority to this role, then we will create an account and grant the user-manager role to this account.
|
||||
|
||||
| Account Name | Cluster Role | Responsibility |
|
||||
| ------------ | ------------ | --------------------------------- |
|
||||
| user-manager | user-manager | Manage cluster accounts and roles |
|
||||
|
||||
1.1 To get started, login KubeSphere with the `admin` account, click **Platform** and then navigate to **Platform Roles** page, click **Create** to create a role which is used to manage all accounts and roles.
|
||||
|
||||

|
||||
|
||||
1.2. Fill in the basic information and authority settings of the role, e.g. `Name : user-manager`.
|
||||
|
||||
1.3. Check all the boxes for both **Account Management** and **Role Management**, then click **Create**.
|
||||
|
||||

|
||||
|
||||
1.4. Click **Platform**, then navigate to **Accounts** page and click **Create** to create an account.
|
||||
|
||||

|
||||
|
||||
1.5. Fill in the basic information, notice that select `user-manger` as its role.
|
||||
|
||||

|
||||
|
||||
1.6. Log out and Sign in with the `user-manager` account, then navigate to **Account** and create 4 accounts according to the following table. Please reference the above steps to create these 4 accounts.
|
||||
|
||||
| Account Name | Cluster Role | Responsibility |
|
||||
| --------------- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
||||
| ws-manager | workspaces-manager | Create and manage all workspaces |
|
||||
| ws-admin | cluster-regular | Manage all resources under the specified workspace<br> (This example is used to invite new members to join the workspace.) |
|
||||
| project-admin | cluster-regular | Create and manage projects, DevOps projects, invite new members |
|
||||
| project-regular | cluster-regular | The regular user will be invited to the project and DevOps project by the project-admin, <br> we use this account to create workloads, pipelines and other resources under the specified project |
|
||||
|
||||
1.7. Verify the 4 accounts that we created in step 1.6.
|
||||
|
||||

|
||||
|
||||
### Workspace Admin
|
||||
|
||||
#### Step 2: Create a Workspace
|
||||
|
||||
Workspace is the base of implementing the multi-tenant mechanism, it's also the base unit for projects and DevOps projects managment.
|
||||
|
||||
2.1. Sign in with `ws-manager` that we created in Step 1, then click **Workspace** and click **Create Workspace**, name it as demo-workspace and appoint `ws-admin` as Workspace Manager, who has the highest administrative authority of the workspace.
|
||||
|
||||

|
||||
|
||||
2.2. Logout and sign in with `ws-admin` after `demo-workspace` has been created. Then click **View Workspace**, select **Worksapce Management → Members Management** and click **Invite Member**.
|
||||
|
||||

|
||||
|
||||
2.3. Invite both `project-admin` and `project-regular` and grant them `workspace-regular` accordingly, click **OK** to save it. Now there are 3 members in the `demo-workspace`.
|
||||
|
||||
| User Name | Role in the Workspace | Responsibility |
|
||||
| --------------- | --------------------- | ------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| ws-admin | workspace-admin | Manage all resources under the workspace<br> (We use this account to invite new members into the workspace) |
|
||||
| project-admin | workspace-regular | Create and manage projects, DevOps projects, and invite new members to join |
|
||||
| project-regular | workspace-viewer | Will be invited by project-admin to join the project and DevOps project. <br> we use this account to create workloads, pipelines, etc |
|
||||
|
||||

|
||||
|
||||
### Project Admin and DevOps Admin
|
||||
|
||||
#### Step 3: Create a Project
|
||||
|
||||
3.1. Sign in with `project-admin` that we created in Step 1, then click **Create** and select **Create a resource project**.
|
||||
|
||||

|
||||
|
||||
3.2. Name it as `demo-project` and keep the advanced settings as the default values, then click **Create**.
|
||||
|
||||
3.3. Choosing **Project Settings → Project Members** and click **Invite Member**.
|
||||
|
||||

|
||||
|
||||
3.4. Invite `project-regular` to this project and grant this user **operator** accordingly.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### Step 4: Set the Gateway
|
||||
|
||||
Before creating a route, you need to enable a gateway for this project.
|
||||
|
||||
4.1. We still use `project-admin`, Choose **Project Settings → Internet Access** and click **Set Gateway**.
|
||||
|
||||

|
||||
|
||||
4.2. Keep the access method as `NodePort` and click `Save`.
|
||||
|
||||

|
||||
|
||||
4.3. Now we are able to see the Gateway Address (192.168.0.88), the NodePort of http and https respectively.
|
||||
|
||||

|
||||
|
||||
#### Step 5: Create DevOps Project
|
||||
|
||||
5.1. In this step, click **Projects** and click `Create Project` button, then select **Create a DevOps project**.
|
||||
|
||||
5.2. Fill in the basic information, e.g. `demo-devops`, then click **Create** button, it will jump to `demo-devops` page.
|
||||
|
||||

|
||||
|
||||
5.3. Similarly, navigate to **Project Management → Project Members**, then click **Invite Member** and grant `project-regular` as the role of `maintainer`, which is used to create pipeline, credentials, etc.
|
||||
|
||||

|
||||
|
||||
<!-- ## Next Step
|
||||
|
||||
Tutorial 2 - [Expose your App: Create a Service and Ingress](ingress-demo.md). -->
|
||||
|
|
@ -0,0 +1,87 @@
|
|||
---
|
||||
title: 'Deploying a Grafana Application to Kubernetes Using Application Template'
|
||||
|
||||
author: 'xxx'
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
This tutorial shows you how to quickly deploy a [Grafana](https://grafana.com/) application in KubeSphere via App Template, demonstrating the basic functionality of the application repository, application templates, and application management.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
You've completed all steps in [Tutorial 1](admin-quick-start.md).
|
||||
|
||||
## Hands-on Lab
|
||||
|
||||
### Step 1: Add a Application Repository
|
||||
|
||||
> Note: The application repository can be either the Object Storage, e.g. [QingStor Object Storage](https://www.qingcloud.com/products/qingstor/), [AWS S3](https://aws.amazon.com/cn/what-is-cloud-object-storage/), or [GitHub Repository](https://github.com/). The packages are composed of Helm Chart template files of the applications. Therefore, before adding an application repository to KubeSphere, you need to create an object storage and upload Helm packages in advance. This tutorial prepares a demo repository based on QingStor Object Storage.
|
||||
|
||||
1.1. Sign in with `admin` account and navigate to **Platform → Platform Settings → App Repositories**, then Click **Add App Repository**.
|
||||
|
||||

|
||||
|
||||
1.2. Fill in the basic information, name it as demo-repo and input the URL with `https://helm-chart-repo.pek3a.qingstor.com/kubernetes-charts/`, you can validate if this URL is available, choose **OK** when you've done.
|
||||
|
||||

|
||||
|
||||
1.3. Click **App Templates** on the top of this page, it will automatically import all of the applications from the demo repository.
|
||||
|
||||

|
||||
|
||||
### Step 2: Deploy the Grafana Application
|
||||
|
||||
2.1. When you've already added the repository, you can logout and sign in with `project-regular` account. Then select **App Templates** on the top of this page, input "grafana" in the search box to find the application.
|
||||
|
||||

|
||||
|
||||
2.2. Click into grafana, **Deploy App** and fill in the basic information.
|
||||
|
||||

|
||||
|
||||
2.3. **Name** can be customized by yourself, choose the corresponding Workspace (e.g. `demo-workspace`) and Project (e.g. `demo-project`) as the environment. Then choose **Deploy** to deploy Grafana to KubeSphere.
|
||||
|
||||
2.4. Back to the `demo-project` and choose **Applications**, then you can see the application `grafana` showing `active` from the application list.
|
||||
|
||||

|
||||
|
||||
### Step 3: View App Details
|
||||
|
||||
3.1. Click into `grafana` application, you will be able to see its Services and Workloads in `Resource Status` page, as well as Environmental Variables and App Template information.
|
||||
|
||||

|
||||
|
||||
3.2. Next we are going to expose this service outside of the cluster via NodePort. Enter into its service e.g. `grafana-l47bmc`, then click **More → Edit Internet Access**.
|
||||
|
||||

|
||||
|
||||
3.3. Select `NodePort` from the drop down list.
|
||||
|
||||

|
||||
|
||||
3.4. Therefore it will generate a Node Port, for example, here is `31126` that we can access this service using `<$NodeIP>:<$NodePort>`.
|
||||
|
||||

|
||||
|
||||
### Step 4: Access the Grafana Service
|
||||
|
||||
At this point, you will be able to access the Nginx service via `${Node IP}:${NODEPORT}`, e.g. `http://192.168.0.88:31126`, or click the button **Click to visit** to access the Grafana dashboard.
|
||||
|
||||
4.1. Note that you have to obtain the account and password from the grafana secret in advance. Navigate to **Configuration Center → Secrets**, click into **grafana-l47bmc (Type: Default)**.
|
||||
|
||||

|
||||
|
||||
4.2. Click the button to display the secret information, then copy and paste the value of **admin-user** and **admin-password**.
|
||||
|
||||

|
||||
|
||||
4.3. Open the Grafana log in page, sign in with the **admin** account.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
## Next Step
|
||||
|
||||
Tutorial 7 - [Create Horizontal Pod Autoscaler for Deployment](hpa.md).
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
---
|
||||
title: 'Managing Canary Release of Microservice Application on Kubernetes with Istio'
|
||||
|
||||
author: 'xxx'
|
||||
---
|
||||
|
||||
Istio’s service mesh is able to manage traffic distribution with complete independence from deployment scaling, which enables a simpler, yet significantly more functional way to realize canary release and rollout. It allows users to introduce a new version of a service by first testing it using a small percentage of user traffic, and then if all goes well, increase, possibly gradually in increments, the percentage while simultaneously phasing out the old version.
|
||||
|
||||
KubeSphere provides three kind of grayscale strategies based on Istio, including blue-green deployment, canary release and traffic mirroring. Without modifying the source code, KubeSphere can realize grayscale, traffic governance, tracing, traffic monitoring and other service mesh features.
|
||||
|
||||
## What is Bookinfo Application
|
||||
|
||||
The Bookinfo application is broken into four separate microservices (There are 3 versions of the reviews microservice):
|
||||
|
||||
- productpage. The productpage microservice calls the details and reviews microservices to populate the page.
|
||||
- details. The details microservice contains book information.
|
||||
- reviews. The reviews microservice contains book reviews. It also calls the ratings microservice.
|
||||
- ratings. The ratings microservice contains book ranking information that accompanies a book review.
|
||||
|
||||
The end-to-end architecture of the application is shown below, see [Bookinfo Application](https://istio.io/docs/examples/bookinfo/) for more details.
|
||||
|
||||

|
||||
|
||||
## Objective
|
||||
|
||||
In this tutorial, we're going to deploy a Bookinfo sample application composed of four separate microservices used to demonstrate the canary release, tracing and traffic monitoring using Istio on KubeSphere.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You've completed all steps in [Tutorial 1](admin-quick-start.md).
|
||||
- You need to turn on the **Application Governance** to enable the tracing feature. (Choose **Project Settings → Internet Access → Edit Gateway → Turn it On**)
|
||||
|
||||
## Hands-on Lab
|
||||
|
||||
### Step 1: Deploy Bookinfo Application
|
||||
|
||||
1.1. Sign in with `project-regular` account and enter into the `demo-project`, navigate to **Application**, click on the **Deploy New Application** then choose **Deploy sample app Bookinfo**.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
1.2. Click **Create** in the pop-up window, then Bookinfo application has been deployed successfully, application components are listed in this following page, as well as the routes and hostname.
|
||||
|
||||

|
||||
|
||||
1.3. Next you can access the Bookinfo homepage as following screenshot via **Click to visit** button. Click on the **Normal user** to enter into the summary page.
|
||||
|
||||

|
||||
|
||||
1.4. Notice that at this point it only shows **- Reviewer1** and **- Reviewer2** without any stars at the Book Reviews section, this is the initial status of this section.
|
||||
|
||||

|
||||
|
||||
### Step 2: Create Canary Release for reviews service
|
||||
|
||||
2.1. Back to KubeSphere console, choose **Grayscale Release** and click on the **Create Canary Release Job**, then select **Canary Release** and click **Create Job**
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
2.2. Fill in the basic information, e.g. `canary-release`, click **Next** and select **reviews** as the canary service, then click **Next**.
|
||||
|
||||

|
||||
|
||||
2.3. Enter `v2` as **Grayscale Release Version Number** and fill in the new image blank with `kubesphere/examples-bookinfo-reviews-v2:1.13.0` (i.e. Modify v1 to v2), then click **Next**.
|
||||
|
||||

|
||||
|
||||
2.4. The canary release supports **Forward by traffic ratio** and **Forward by request content**, in this tutorial we choose adjust the traffic ratio to manage traffic distribution between v1 and v2. Drag the slider to adjust v2 takes up 30% traffic, and v2 takes up 70%.
|
||||
|
||||

|
||||
|
||||
2.5. Click **Create** when you've completed configuration, then you're able to see the `canary-release` has been created successfully.
|
||||
|
||||

|
||||
|
||||
### Step 3: Verify the Canary Release
|
||||
|
||||
When you visit the Bookinfo website again and refresh your browser repeatedly, you'll be able to see that the Bookinfo reviews section will switch between v1 and v2 at a random rate of about 30% and 70% respectively.
|
||||
|
||||

|
||||
|
||||
### Step 4: Inspect the Traffic Topology Graph
|
||||
|
||||
4.1. Connect to your SSH Client, use the following command to introduce real traffic to simulate the access to a bookinfo application every 0.5 seconds.
|
||||
|
||||
```
|
||||
$ curl http://productpage.demo-project.192.168.0.88.nip.io:32565/productpage?u=normal
|
||||
|
||||
% Total % Received % Xferd Average Speed Time Time Time Current
|
||||
Dload Upload Total Spent Left Speed
|
||||
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0< 74 5183 74 3842 0 0 73957 0 --:--:-- --:--:-- --:--:-- 73884<!DOCTYPE html>
|
||||
···
|
||||
```
|
||||
|
||||
4.2. From the traffic management diagram, you can easily see the service invocation and dependencies, health, performance between different microservices.
|
||||
|
||||

|
||||
|
||||
4.3. Click on the reviews card, the traffic monitoring graph will come out, including real-time data of **Success rate**, **Traffic** and **Duration**.
|
||||
|
||||

|
||||
|
||||
### Step 5: Inspect the Tracing Details
|
||||
|
||||
KubeSphere provides distributed tracing feature based on [Jaeger](https://www.jaegertracing.io/), which is used for monitoring and troubleshooting microservices-based distributed application.
|
||||
|
||||
5.1. Choose **Tracing** tab, you can clearly see all phases and internal calls of a request, as well as the period in each phase.
|
||||
|
||||

|
||||
|
||||
5.2. Click into any one item, you can even drill down to see the request details and this request is being processed by which machine (or container).
|
||||
|
||||

|
||||
|
||||
### Step 6: Take over all traffic
|
||||
|
||||
6.1. As mentioned previously, when the canary version (v2) is released, it could be used to send 70% of traffic to the canary version. Publishers can test the new version online and collect user feedback.
|
||||
|
||||
Switch to **Grayscale Release** tab, click into `canary-release`.
|
||||
|
||||

|
||||
|
||||
6.2. Click **···** and select **Take Over** at `reviews-v2`, then 100% of traffic will be sent to the new version (v2).
|
||||
|
||||
> Note: If anything goes wrong along the way, we can abort and rollback to the previous version (v1) in time.
|
||||
|
||||

|
||||
|
||||
6.3. Open the bookinfo page again and refresh the browsers several times, we can find that it only shows the v2 (ratings with black stars) in reviews module.
|
||||
|
||||

|
||||
|
||||
### Step 7: Take Down the Old Version
|
||||
|
||||
When the new version v2 jas been totally released online and takes over all the traffic, also the testing results and online users feedback are confirmed to be correct, you can take down the old version and remove the resources of v1.
|
||||
|
||||
Click on the **Job Offline** button to take down the old version,
|
||||
|
||||

|
||||
|
||||
> Notice: If take down a specific version of the component, the associated workloads and istio related configuration resources will be removed simultaneously, it turns out that v1 is being replaced by v2.
|
||||
|
||||

|
||||
|
|
@ -0,0 +1,37 @@
|
|||
---
|
||||
title: 'Creating a CI/CD Pipeline to Deploy Spring Boot App to Kubernetes'
|
||||
|
||||
author: 'xxx'
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
This tutorial shows you how to create a CI/CD Pipeline within DevOps project, which is intended for deploying a Spring Boot sample application to Kubernetes.
|
||||
|
||||
## Overview
|
||||
|
||||
Based on the existing Jenkinsfile in the sample GitHub repository, we can create a pipeline to build and complete the stages and steps (e.g. unit test, sonarqube analysis), which totally consists of eight stages as shown below.
|
||||
|
||||

|
||||
|
||||
## Prerequisites
|
||||
|
||||
You've completed all steps in [Tutorial 1](admin-quick-start.md).
|
||||
|
||||
## Hands-on Lab
|
||||
|
||||
### Step 1: Create Credentials
|
||||
|
||||
To get started, we need to create 3 credentials, i.e. DockerHub、GitHub and kubeconfig.
|
||||
|
||||
1.1. Sign in with `project-regular` account and enter into the `demo-devops`, navigate to **Credentials**, then click on the **Create Credentials**.
|
||||
|
||||

|
||||
|
||||
| Credential ID | Type | Username/Password/Secret | Content |
|
||||
| --------------- | ------------------- | -------------------------------------------------------------------- | ------- |
|
||||
| dockerhub-id | Account Credentials | Enter your personal DockerHub account information | \| |
|
||||
| github-id | Account Credentials | Enter your personal GitHub account information | \| |
|
||||
| kube-config |
|
||||
| demo-kubeconfig | kubeconfig | \|It will be automatically filled with the kubeconfig of the cluster |
|
||||
| sonar-token | secret_text | You can get secret by creating SonarQube token | \ |
|
||||
|
|
@ -0,0 +1,161 @@
|
|||
---
|
||||
title: 'Creating Horizontal Pod Autoscaler for Deployment'
|
||||
|
||||
author: 'xxx'
|
||||
---
|
||||
|
||||
The Horizontal Pod Autoscaler automatically scales the number of pods in a deployment based on observed CPU utilization or Memory usage. The controller periodically adjusts the number of replicas in a deployment to match the observed average CPU utilization to the target value specified by user.
|
||||
|
||||
## How does the HPA work
|
||||
|
||||
The Horizontal Pod Autoscaler is implemented as a control loop, with a period controlled by the controller manager’s HPA sync-period flag (with a default value of 15 seconds). For per-pod resource metrics (like CPU), the controller fetches the metrics from the resource metrics API for each pod targeted by the Horizontal Pod Autoscaler. See [Horizontal Pod Autoscaler](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/) for more details.
|
||||
|
||||

|
||||
|
||||
## Objective
|
||||
|
||||
This document walks you through an example of configuring Horizontal Pod Autoscaler for the hpa-example deployment.
|
||||
|
||||
We will create a deployment to send an infinite loop of queries to the hpa example application, demonstrating its autoscaling function and the HPA Principle.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You need to create a workspace and project, see the [Tutorial 1](admin-quick-start.md) if not yet.
|
||||
- You need to sign in with `project-regular` and enter into the corresponding project.
|
||||
|
||||
## Hands-on Lab
|
||||
|
||||
### Step 1: Create a Deployment
|
||||
|
||||
1.1. Enter into `demo-project`, then select **Workload → Deployments** and click **Create Deployment** button.
|
||||
|
||||

|
||||
|
||||
1.2. Fill in the basic information in the pop-up window. e.g. `Name: hpa-example`, then click **Next** when you've done.
|
||||
|
||||
### Step 2: Configure the HPA
|
||||
|
||||
2.1. Choose **Horizontal Pod Autoscaling**, and fill in the table as following:
|
||||
|
||||
- Min Replicas Number: 2
|
||||
- Max Replicas Number: 10
|
||||
- CPU Request Target(%): 50 (represents the percent of target CPU utilization)
|
||||
|
||||
Then click on the **Add Container** button.
|
||||
|
||||

|
||||
|
||||
2.2. Fill in the Pod Template with following values, then click **Save** to save these settings.
|
||||
|
||||
- Image: `mirrorgooglecontainers/hpa-example`
|
||||
- Service Settings
|
||||
- Name: port
|
||||
- port: 80 (TCP protocol by default)
|
||||
|
||||

|
||||
|
||||
2.3. Skip the Volume and Label Settings, click the **Create** button directly. Now the hpa-example deployment has been created successfully.
|
||||
|
||||

|
||||
|
||||
### Step 3: Create a Service
|
||||
|
||||
3.1. Choose **Network & Services → Services** on the left menu, then click on the **Create Service** button.
|
||||
|
||||

|
||||
|
||||
3.2. Fill in the basic information, e.g. `name : hpa-example`, then click **Next**.
|
||||
|
||||
3.3. Choose the first item `Virtual IP: Access the service through the internal IP of the cluster` for the service Settings.
|
||||
|
||||
3.4. In Selector blanks, click **Specify Workload** and select the `hpa-example` as the backend workload. Then choose **Save** and fill in the Ports blanks.
|
||||
|
||||
- Ports:
|
||||
- Name: port
|
||||
- Protocol: TCP
|
||||
- Port: 80
|
||||
- Target port: 80
|
||||
|
||||

|
||||
|
||||
Click **Next → Create** to complete the creation. Now the hpa-example service has been created successfully.
|
||||
|
||||

|
||||
|
||||
### Step 4: Create Load-generator
|
||||
|
||||
4.1. In the current project, redirect to **Workload → Deployments**. Click **Create** button and fill in the basic information in the pop-up window, e.g. `Name : load-generator`. Click **Next** when you've done.
|
||||
|
||||
4.2. Click on **Add Container** button, and fill in the Pod template as following:
|
||||
|
||||
- Image: busybox
|
||||
- Scroll down to **Start command**, add commands and parameters as following:
|
||||
|
||||
```
|
||||
# Commands
|
||||
sh
|
||||
-c
|
||||
|
||||
# Parameters (Note: the http service address like http://{$service name}.{$project name}.svc.cluster.local)
|
||||
while true; do wget -q -O- http://hpa-example.demo-project.svc.cluster.local; done
|
||||
```
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
Click on the **Save** button when you've done, then click **Next**.
|
||||
|
||||
4.3. Click **Next → Create** to complete creation.
|
||||
|
||||
So far, we've created 2 deployments (i.e. hpa-example and load-generator) and 1 service (i.e. hpa-example).
|
||||
|
||||

|
||||
|
||||
### Step 5: Verify the HPA
|
||||
|
||||
5.1. Click into `hpa-example` and inspect the changes, please pay attention to the HPA status and the CPU utilization, as well as the Pods monitoring graphs.
|
||||
|
||||

|
||||
|
||||
### Step 6: Verify the Auto Scaling
|
||||
|
||||
6.1. When all of the load-generator pods are successfully created and begin to access the hpe-example service, as shown in the following figure, the CPU utilization is significantly increased after refreshing the page, currently rising to `722%`, and the desired replicas and current replicas is rising to `10/10`.
|
||||
|
||||

|
||||
|
||||
> Note: Since the Horizontal Pod Autoscaler is working right now, the load-generator looply requests the hpa-example service to make the CPU utilization rised rapidly. After the HPA starts working, it makes the backend of the service increases fast to handle a large number of requests together. Also the replicas of hpa-example continues to increase follow with the CPU utilization increases, which demonstrates the working principle of HPA.
|
||||
|
||||
6.2. In the monitoring graph, it can be seen that the CPU usage of the first Pod that we originally created, showing a significant upward trend. When HPA started working, the CPU usage has a significant decreased trend, finally it tends to be smooth. Accordingly, the CPU usage is increasing on the newly created Pods.
|
||||
|
||||

|
||||
|
||||
### Step 7: Stop the Load Generation
|
||||
|
||||
7.1. Redirect to **Workload → Deployments** and delete `load-generator` to cease the load increasing.
|
||||
|
||||

|
||||
|
||||
7.2. Inspect the status of the `hpa-example` again, you'll find that its current CPU utilization has slowly dropped to 10% in a few minutes, eventually the HPA has reduced its deployment replicas to 1 (initial value). The trend reflected by the monitoring curve can also help us to further understand the working principle of HPA;
|
||||
|
||||

|
||||
|
||||
7.3. It enables user to inspect the monitoring graph of Deloyment, see the CPU utilization and Network inbound/outbound trend, they just match with the HPA example.
|
||||
|
||||

|
||||
|
||||
## Modify HPA Settings
|
||||
|
||||
If you need to modify the settings of the HPA, you can click into the deployment, and click **More → Horizontal Pod Autoscaler**.
|
||||
|
||||

|
||||
|
||||
## Cancel HPA
|
||||
|
||||
Click **···** button on the right and **Cancel** if you don't need HPA within this deployment.
|
||||
|
||||

|
||||
|
||||
## Next Step
|
||||
|
||||
Tutorial 8 - [Source-to-Image: Build Reproducible Images from Source Code](s2i.md).
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
---
|
||||
title: "contribution"
|
||||
|
||||
css: "scss/contribution.scss"
|
||||
|
||||
section1:
|
||||
title: 'Community is the Soul of KubeSphere'
|
||||
content: 'Join the community to get help, get involved, or to get updates and KubeSphere news!'
|
||||
topImage: "images/contribution/contribution-top.jpg"
|
||||
|
||||
section2:
|
||||
topType:
|
||||
- name: 'Download'
|
||||
icon1: 'images/contribution/download.svg'
|
||||
icon2: 'images/contribution/37.png'
|
||||
children:
|
||||
- content: 'Download KubeSphere'
|
||||
link: ''
|
||||
- content: 'Quickstart'
|
||||
link: ''
|
||||
- content: 'Tutorial Videos'
|
||||
link: ''
|
||||
|
||||
- name: 'Contribute'
|
||||
icon1: 'images/contribution/contribute.svg'
|
||||
icon2: 'images/contribution/38.png'
|
||||
children:
|
||||
- content: 'Join the SIGs and WGs'
|
||||
link: ''
|
||||
- content: 'Improve the Docs'
|
||||
link: ''
|
||||
- content: 'Submit a Bug or Suggestion'
|
||||
link: ''
|
||||
|
||||
- name: 'Get in Touch'
|
||||
icon1: 'images/contribution/business.svg'
|
||||
icon2: 'images/contribution/39.png'
|
||||
children:
|
||||
- content: 'Join KubeSphere Slack'
|
||||
link: ''
|
||||
- content: 'Join the Mailing List'
|
||||
link: ''
|
||||
- content: 'Follow us on Twitter'
|
||||
link: ''
|
||||
|
||||
organization:
|
||||
topic: 'Community Organization'
|
||||
name: 'KubeSphere Community'
|
||||
icon: 'images/contribution/28.svg'
|
||||
topIcon: 'images/contribution/8.svg'
|
||||
type:
|
||||
- name: 'TOC'
|
||||
icon: 'images/contribution/toc.svg'
|
||||
|
||||
- name: 'Developer Group'
|
||||
icon: 'images/contribution/developer-group.svg'
|
||||
children:
|
||||
- name: 'Owner / Lead'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'Member'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'Contributor'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'User Research Group'
|
||||
icon: 'images/contribution/user.svg'
|
||||
children:
|
||||
- name: 'Champion'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'Ambassador'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
|
||||
- name: 'Steering Committee'
|
||||
icon: 'images/contribution/steering.svg'
|
||||
|
||||
section3:
|
||||
interestGroup:
|
||||
title: 'Find Your Special Interest Group'
|
||||
content: 'SIGs are designed to let you can find everything you need in one place around a central topic. Find your commonality and join the SIG.'
|
||||
children:
|
||||
- name: 'Apps'
|
||||
icon: '/images/contribution/apps.svg'
|
||||
iconActive: '/images/contribution/apps-active.svg'
|
||||
content: 'App charts for the built-in App Store'
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Apps →'
|
||||
children:
|
||||
- icon: '/images/contribution/calicq1.jpg'
|
||||
- icon: '/images/contribution/calicq2.jpg'
|
||||
- icon: '/images/contribution/calicq3.jpg'
|
||||
|
||||
- name: 'App store'
|
||||
icon: '/images/contribution/app-store.svg'
|
||||
iconActive: '/images/contribution/app-store-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - App store →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Architecture'
|
||||
icon: '/images/contribution/architecture.svg'
|
||||
iconActive: '/images/contribution/architecture-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Architecture →'
|
||||
children:
|
||||
- icon: ''
|
||||
|
||||
- name: 'Cloud-Providers'
|
||||
icon: '/images/contribution/cloud-providers.svg'
|
||||
iconActive: '/images/contribution/cloud-providers-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Cloud-Providers →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Console (Front-end)'
|
||||
icon: '/images/contribution/console.svg'
|
||||
iconActive: '/images/contribution/console-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Console (Front-end) →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'DevOps'
|
||||
icon: '/images/contribution/dev-ops.svg'
|
||||
iconActive: '/images/contribution/dev-ops-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - DevOps →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: ' Docs'
|
||||
icon: '/images/contribution/docs.svg'
|
||||
iconActive: '/images/contribution/docs-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Docs →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Edge'
|
||||
icon: '/images/contribution/edge.svg'
|
||||
iconActive: '/images/contribution/edge-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Edge →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Installation'
|
||||
icon: '/images/contribution/installation.svg'
|
||||
iconActive: '/images/contribution/installation-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Installation →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Microservice'
|
||||
icon: '/images/contribution/microservice.svg'
|
||||
iconActive: '/images/contribution/microservice-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Microservice →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Multicluster'
|
||||
icon: '/images/contribution/multicluster.svg'
|
||||
iconActive: '/images/contribution/multicluster-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Multicluster →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Multitenancy'
|
||||
icon: '/images/contribution/multitenancy.svg'
|
||||
iconActive: '/images/contribution/multitenancy-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Multitenancy →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Network'
|
||||
icon: '/images/contribution/network.svg'
|
||||
iconActive: '/images/contribution/network-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Network →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Observability'
|
||||
icon: '/images/contribution/observability.svg'
|
||||
iconActive: '/images/contribution/observability-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Observability →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Release'
|
||||
icon: '/images/contribution/release.svg'
|
||||
iconActive: '/images/contribution/release-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Release →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Storage'
|
||||
icon: '/images/contribution/storage.svg'
|
||||
iconActive: '/images/contribution/storage-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Storage →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Testing'
|
||||
icon: '/images/contribution/testing.svg'
|
||||
iconActive: '/images/contribution/testing-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Testing →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
section4:
|
||||
involved:
|
||||
title: 'Get involved'
|
||||
children:
|
||||
- title: 'Be a Champion'
|
||||
icon: 'images/contribution/group-1.png'
|
||||
content: 'Join me tomorrow and start putting in the time to get your campaign ready with a landing page!'
|
||||
link: ''
|
||||
linkContent: 'Become a KubeSphere Champion →'
|
||||
|
||||
- title: 'Be a Member'
|
||||
icon: 'images/contribution/group-2.png'
|
||||
content: 'KubeSphere is 100% open source and driven by community,we appreciate contributions to our code and documentation!Significant contributions will earn you a contributor t-shirt.'
|
||||
link: ''
|
||||
linkContent: 'Become a KubeSphere Member →'
|
||||
---
|
||||
|
|
@ -3,116 +3,9 @@ title: "all-in-one"
|
|||
weight: 2
|
||||
---
|
||||
|
||||
## All-in-One Installation
|
||||
## test
|
||||
|
||||
For those who are new to KubeSphere and looking for a quick way to discover the platform, the all-in-one mode is your best choice to install it since it is one-click and hassle-free configuration installation with provisioning KubeSphere and Kubernetes on your machine.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
If your machine is behind a firewall, you need to open the ports by following the document [Ports Requirement](https://kubesphere.io/docs/v2.1/en/installation/port-firewall/) for more information.
|
||||
|
||||
## Step 1: Prepare Linux Machine
|
||||
|
||||
A Linux machine that is either a virtual machine or bare metal. This machine requires at a minimum:
|
||||
|
||||
- Hardware:
|
||||
|
||||
- CPU: 2 Cores for minimal, 8 Cores for complete setup
|
||||
- Memory: 4 GB for minimal, 16 GB for complete setup
|
||||
|
||||
- Operating Systems:
|
||||
|
||||
- CentOS 7.4 ~ 7.7 (`64-bit`)
|
||||
- Ubuntu 16.04/18.04 LTS (`64-bit`)
|
||||
- RHEL 7.4 (`64-bit`)
|
||||
- Debian Stretch 9.5 (`64-bit`)
|
||||
test
|
||||
|
||||
|
||||
> - For `Ubuntu 16.04` OS, it's recommended to select the latest `16.04.5`.
|
||||
> - If you are using Ubuntu 18.04, you need to use the root user to install.
|
||||
> - If the Debian system does not have the sudo command installed, you need to execute the `apt update && apt install sudo` command using root before installation.
|
||||
|
||||
## Step 2: Download Installer Package
|
||||
|
||||
Execute the following commands to download Installer 2.1.1 and unpack it.
|
||||
|
||||
```bash
|
||||
$ curl -L https://kubesphere.io/download/stable/latest > installer.tar.gz \
|
||||
&& tar -zxf installer.tar.gz && cd kubesphere-all-v2.1.1/scripts
|
||||
```
|
||||
|
||||
> Please note: the installer will be started with a default minimal installation only, if there are 8 Cores and 16 GB RAM available in your machine, please enable more pluggable components in `kubesphere-all-v2.1.1/conf/common.yaml`, see [Complete Installation](https://kubesphere.io/docs/v2.1/en/installation/complete-installation/)
|
||||
|
||||
## Step 3: Get Started with Installation
|
||||
|
||||
You should not do anything except executing one command as follows. The installer will complete all things for you automatically including install/update dependency packages, install Kubernetes (Defaults to 1.16.7), storage service and so on.
|
||||
|
||||
**Note:**
|
||||
|
||||
> - Generally speaking, do not modify any configuration.
|
||||
> - KubeSphere installs `calico` by default. If you would like to use a different network plugin, you are allowed to change the configuration in `conf/common.yaml`. You are also allowed to modify other configurations such as storage class, pluggable components, etc.
|
||||
> - The default storage class is [OpenEBS](https://openebs.io/) which is a kind of [Local Volume](https://kubernetes.io/docs/concepts/storage/volumes/#local) to provision persistence storage service. OpenEBS supports [dynamic provisioning PV](https://docs.openebs.io/docs/next/uglocalpv.html#Provision-OpenEBS-Local-PV-based-on-hostpath). It will be installed automatically for your testing environment.
|
||||
> - Please refer [storage configurations](https://kubesphere.io/docs/v2.1/en/installation/storage-configuration/) for supported storage class.
|
||||
> - Since the default subnet for Cluster IPs is 10.233.0.0/18, and the default subnet for Pod IPs is 10.233.64.0/18, the node IPs must not use the two IP range. You can modify the default subnets `kube_service_addresses` or `kube_pods_subnet` in the file `conf/common.yaml` to avoid conflicts.
|
||||
|
||||
|
||||
**1.** Execute the following command:
|
||||
|
||||
```
|
||||
$ ./install.sh
|
||||
```
|
||||
|
||||
**2.** Enter `1` to select `all-in-one` mode to start:
|
||||
|
||||
```bash
|
||||
################################################
|
||||
KubeSphere Installer Menu
|
||||
################################################
|
||||
* 1) All-in-one
|
||||
* 2) Multi-node
|
||||
* 3) Quit
|
||||
################################################
|
||||
https://kubesphere.io/ 2020-02-24
|
||||
################################################
|
||||
Please input an option: 1
|
||||
```
|
||||
|
||||
**3.** Verify if KubeSphere is installed successfully or not:
|
||||
|
||||
**(1).** If you see "Successful" returned after installation completed, it means your environment is ready to use. The console service is exposed through nodeport 30880 by default.
|
||||
|
||||
```bash
|
||||
successsful!
|
||||
#####################################################
|
||||
### Welcome to KubeSphere! ###
|
||||
#####################################################
|
||||
|
||||
Console: http://192.168.0.8:30880
|
||||
Account: admin
|
||||
Password: P@88w0rd
|
||||
|
||||
NOTE:Please modify the default password after login.
|
||||
#####################################################
|
||||
```
|
||||
|
||||
> Note: The information above is saved in a log file that you can view by following the [guide](https://kubesphere.io/docs/v2.1/en/installation/verify-components/).
|
||||
|
||||
|
||||
**(2).** You will be able to use default account and password to log in the console to take a tour of KubeSphere.
|
||||
|
||||
<font color=red>Note: After log in console, please verify the monitoring status of service components in the "Cluster Status". If any service is not ready, please wait patiently untill all components get running up.</font>
|
||||
|
||||

|
||||
|
||||
### Enable Pluggable Components
|
||||
|
||||
If you start with a default minimal installation, execute the following command to open the configmap in order to enable more pluggable components at your will. Make sure your cluster has enough CPU and memory, see [Enable Pluggable Components](https://kubesphere.io/docs/v2.1/en/installation/pluggable-components/).
|
||||
|
||||
```bash
|
||||
kubectl edit cm -n kubesphere-system ks-installer
|
||||
```
|
||||
|
||||
### FAQ
|
||||
|
||||
If you have further questions please do not hesitate to raise issues on [GitHub](https://github.com/kubesphere/kubesphere/issues).
|
||||
|
||||
|
|
|
|||
|
|
@ -4,22 +4,6 @@ weight: 1
|
|||
|
||||
---
|
||||
|
||||
# what-is-kubesphere
|
||||
## test
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
test
|
||||
|
|
@ -3,143 +3,6 @@ title: "quick-start-guide"
|
|||
weight: 1
|
||||
---
|
||||
|
||||
## Objective
|
||||
## test
|
||||
|
||||
In this quickstart, as a cluster admin, you will learn how to create workspaces, roles and user accounts, and then invite new users into the workspace to create their projects and DevOps projects. This tutorial is used to help beginners to become familiar with multi-tenant management.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
- You need to [install KubeSphere](https://kubesphere.io/en/install).
|
||||
- You need a default admin account.
|
||||
|
||||
## Hands-on Lab
|
||||
|
||||
Generally, the hierarchy relationship of Cluster, Workspace, Project and DevOps Project showing as the following graph, and there are common built-in roles existed in these orgnizations within each level.
|
||||
|
||||

|
||||
|
||||
### Cluster Admin
|
||||
|
||||
The role of cluster-admin is able to create accounts for other users and assign roles to them. There are three common roles in cluster level, it also supports customizing new roles.
|
||||
|
||||
|Built-in Roles|Responsibility|
|
||||
|---|---|
|
||||
|cluster-admin|Have the highest privileges for the cluster, can manage any resources|
|
||||
|workspaces-manager|The workspace managers, can manage all of the resources, e.g. projects, DevOps projects, members and roles |
|
||||
|cluster-regular| The regular users in the cluster, they are not authorized until they have been invited to the workspace|
|
||||
|
||||
|
||||
#### Step 1: Create roles and accounts
|
||||
|
||||
First, we will create a new role (user-manager), grants account management and role management authority to this role, then we will create an account and grant the user-manager role to this account.
|
||||
|
||||
|Account Name|Cluster Role|Responsibility|
|
||||
|---|---|---|
|
||||
|user-manager|user-manager|Manage cluster accounts and roles|
|
||||
|
||||
1.1 To get started, login KubeSphere with the `admin` account, click **Platform** and then navigate to **Platform Roles** page, click **Create** to create a role which is used to manage all accounts and roles.
|
||||
|
||||

|
||||
|
||||
1.2. Fill in the basic information and authority settings of the role, e.g. `Name : user-manager`.
|
||||
|
||||
1.3. Check all the boxes for both **Account Management** and **Role Management**, then click **Create**.
|
||||
|
||||

|
||||
|
||||
1.4. Click **Platform**, then navigate to **Accounts** page and click **Create** to create an account.
|
||||
|
||||

|
||||
|
||||
1.5. Fill in the basic information, notice that select `user-manger` as its role.
|
||||
|
||||

|
||||
|
||||
1.6. Log out and Sign in with the `user-manager` account, then navigate to **Account** and create 4 accounts according to the following table. Please reference the above steps to create these 4 accounts.
|
||||
|
||||
|Account Name|Cluster Role|Responsibility|
|
||||
|---|---|---|
|
||||
|ws-manager|workspaces-manager|Create and manage all workspaces|
|
||||
|ws-admin|cluster-regular|Manage all resources under the specified workspace<br> (This example is used to invite new members to join the workspace.)|
|
||||
|project-admin|cluster-regular|Create and manage projects, DevOps projects, invite new members|
|
||||
|project-regular|cluster-regular|The regular user will be invited to the project and DevOps project by the project-admin, <br> we use this account to create workloads, pipelines and other resources under the specified project|
|
||||
|
||||
1.7. Verify the 4 accounts that we created in step 1.6.
|
||||
|
||||

|
||||
|
||||
### Workspace Admin
|
||||
|
||||
#### Step 2: Create a Workspace
|
||||
|
||||
Workspace is the base of implementing the multi-tenant mechanism, it's also the base unit for projects and DevOps projects managment.
|
||||
|
||||
2.1. Sign in with `ws-manager` that we created in Step 1, then click **Workspace** and click **Create Workspace**, name it as demo-workspace and appoint `ws-admin` as Workspace Manager, who has the highest administrative authority of the workspace.
|
||||
|
||||

|
||||
|
||||
2.2. Logout and sign in with `ws-admin` after `demo-workspace` has been created. Then click **View Workspace**, select **Worksapce Management → Members Management** and click **Invite Member**.
|
||||
|
||||

|
||||
|
||||
2.3. Invite both `project-admin` and `project-regular` and grant them `workspace-regular` accordingly, click **OK** to save it. Now there are 3 members in the `demo-workspace`.
|
||||
|
||||
|User Name|Role in the Workspace|Responsibility|
|
||||
|---|---|---|
|
||||
|ws-admin|workspace-admin|Manage all resources under the workspace<br> (We use this account to invite new members into the workspace)|
|
||||
|project-admin|workspace-regular|Create and manage projects, DevOps projects, and invite new members to join|
|
||||
|project-regular|workspace-viewer|Will be invited by project-admin to join the project and DevOps project. <br> we use this account to create workloads, pipelines, etc|
|
||||
|
||||

|
||||
|
||||
### Project Admin and DevOps Admin
|
||||
|
||||
#### Step 3: Create a Project
|
||||
|
||||
3.1. Sign in with `project-admin` that we created in Step 1, then click **Create** and select **Create a resource project**.
|
||||
|
||||

|
||||
|
||||
3.2. Name it as `demo-project` and keep the advanced settings as the default values, then click **Create**.
|
||||
|
||||
3.3. Choosing **Project Settings → Project Members** and click **Invite Member**.
|
||||
|
||||

|
||||
|
||||
3.4. Invite `project-regular` to this project and grant this user **operator** accordingly.
|
||||
|
||||

|
||||
|
||||

|
||||
|
||||
#### Step 4: Set the Gateway
|
||||
|
||||
Before creating a route, you need to enable a gateway for this project.
|
||||
|
||||
4.1. We still use `project-admin`, Choose **Project Settings → Internet Access** and click **Set Gateway**.
|
||||
|
||||

|
||||
|
||||
4.2. Keep the access method as `NodePort` and click `Save`.
|
||||
|
||||

|
||||
|
||||
4.3. Now we are able to see the Gateway Address (192.168.0.88), the NodePort of http and https respectively.
|
||||
|
||||

|
||||
|
||||
#### Step 5: Create DevOps Project
|
||||
|
||||
5.1. In this step, click **Projects** and click `Create Project` button, then select **Create a DevOps project**.
|
||||
|
||||
5.2. Fill in the basic information, e.g. `demo-devops`, then click **Create** button, it will jump to `demo-devops` page.
|
||||
|
||||

|
||||
|
||||
5.3. Similarly, navigate to **Project Management → Project Members**, then click **Invite Member** and grant `project-regular` as the role of `maintainer`, which is used to create pipeline, credentials, etc.
|
||||
|
||||

|
||||
|
||||
## Next Step
|
||||
|
||||
Tutorial 2 - [Expose your App: Create a Service and Ingress](ingress-demo.md).
|
||||
test
|
||||
|
|
@ -4,18 +4,6 @@ weight: 2
|
|||
---
|
||||
|
||||
|
||||
## second
|
||||
## test
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
test
|
||||
|
|
@ -3,18 +3,6 @@ title: "aaaaaa"
|
|||
weight: 1
|
||||
---
|
||||
|
||||
## second
|
||||
## test
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
|
||||
## second
|
||||
|
||||
测试markdown
|
||||
test
|
||||
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
title: "page1"
|
||||
|
||||
css: "scss/partner.scss"
|
||||
|
||||
section1:
|
||||
title: 'Join the Revolution,Partner with KubeSphere'
|
||||
content: 'We look forward to your joining KubeSphere partner to improve the ecosystem of both, and grow your business. KubeSphere provide resources and rights for partners to help them increase their expertise, deliver open source technology, and resell product.'
|
||||
topImage: 'images/partner/partner-top.jpg'
|
||||
|
||||
section2:
|
||||
title: 'Together, build partnership for success all over the world'
|
||||
content: 'KubeSphere partners play a critical role in KubeSphere go-to-market strategy. KubeSphere partners are located all over the world, we are looking forward to the global cooperation, your success is our success.'
|
||||
name1: 'USA'
|
||||
name2: 'European'
|
||||
name3: 'China'
|
||||
mapImage: 'images/partner/map.svg'
|
||||
|
||||
section3:
|
||||
title: 'Partner Types'
|
||||
tip: Request now →
|
||||
partnerType:
|
||||
- title: "App Providers"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, KubeSphere bring your applications to tens of thousands of users, making them deploy your App to Kubernetes with one click."
|
||||
link: ""
|
||||
|
||||
- title: "Consulting"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, users can quickly deploy your application to Kubernetes using KubeSphere. Submit your application to KubeSphere Application Store now!"
|
||||
link: ""
|
||||
|
||||
- title: "Cloud Providers"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, users can quickly deploy your application to Kubernetes using KubeSphere. Submit your application to KubeSphere Application Store now!"
|
||||
link: ""
|
||||
|
||||
- title: "Go-To-Market"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, users can quickly deploy your application to Kubernetes using KubeSphere. Submit your application to KubeSphere Application Store now!"
|
||||
link: ""
|
||||
|
||||
section4:
|
||||
title: 'Featured Partners'
|
||||
content: 'KubeSphere is trusted by various enterprises and organizations to the innovators driving the future of software.'
|
||||
featuredPartnerList:
|
||||
- icon: "images/partner/partner1.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner2.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner3.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner4.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner5.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner6.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner7.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
---
|
||||
|
|
@ -1,4 +1,34 @@
|
|||
---
|
||||
title: "About"
|
||||
|
||||
|
||||
css: "scss/projects.scss"
|
||||
name: Open Source Projects
|
||||
groups:
|
||||
- name: Container Platform
|
||||
children:
|
||||
- title: KubeSphere
|
||||
icon: 'images/kubesphere.svg'
|
||||
link: ''
|
||||
description: 基于 Kubernetes 之上构建的以应用为中心的多租户容器平台,支持部署运行在任何基础设施之上,提供简单易用的操作界面以及向导式 UI,旨在解决 Kubernetes 的存储、网络、安全与易用性等痛点。
|
||||
|
||||
- name: App Management
|
||||
children:
|
||||
- title: OpenPitrix
|
||||
icon: ''
|
||||
link: ''
|
||||
description: 开源的多云应用管理平台,用来在多云环境下打包、部署和管理不同类型的应用,包括传统应用、微服务应用以及 Serverless 应用等,其中云平台包括 AWS、Kubernetes、QingCloud、VMWare。
|
||||
|
||||
- name: Storage Plugins
|
||||
children:
|
||||
- title: QingStor-CSI
|
||||
icon: ''
|
||||
link: ''
|
||||
description: QingStor CSI 插件实现 CSI 接口,使容器编排平台(如 Kubernetes)能够使用 NeonSAN 分布式存储的资源。目前,QingStor CSI 插件实现了存储卷管理和快照管理功能,并在 Kubernetes v1.12 环境中通过了 CSI Sanity 测试。
|
||||
|
||||
- title: QingCloud-CSI
|
||||
icon: ''
|
||||
link: ''
|
||||
description: QingCloud CSI 插件实现了 CSI 接口,并使容器管理平台能够使用 QingCloud 云平台的块存储资源。目前,QingCloud CSI 插件已经在 Kubernetes v1.14/v1.15 环境中通过了 CSI 测试。
|
||||
|
||||
---
|
||||
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
title: "reason"
|
||||
|
||||
---
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: "second"
|
||||
|
||||
---
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
title: "page1"
|
||||
|
||||
css: "scss/videos.scss"
|
||||
---
|
||||
|
|
@ -0,0 +1,159 @@
|
|||
---
|
||||
title: "KubeSphere-以应用为中心的开源容器平台"
|
||||
description: "KubeSphere 是在 Kubernetes 之上构建的以应用为中心的开源容器平台,支持部署和运行在任何基础设施之上,帮助企业轻松应对敏捷开发、自动化运维、应用快速交付、微服务治理、多租户管理、监控日志告警、服务与网络管理等业务场景"
|
||||
|
||||
|
||||
css: "scss/index.scss"
|
||||
|
||||
section1:
|
||||
title: KubeSphere Container Platform
|
||||
topic: The Kubernetes Platform, tailored to the hybrid cloud
|
||||
content: KubeSphere is a distributed operating system providing cloud native stack with Kubernetes as its kernel, and aims to be plug-and-play architecture for third-party applications seamless integration to boost its ecosystem.
|
||||
btnContent1: Install on Kubernetes
|
||||
btnContent2: Install on Linux
|
||||
|
||||
section2:
|
||||
title: One Platform for full-stack solutions
|
||||
content: KubeSphere is also a multi-tenant enterprise-grade container platform with full-stack automated IT operation and streamlined DevOps workflows. It provides developer-friendly wizard web UI, helping enterprises to build out a more robust and feature-rich platform, which includes most common functionalities needed for enterprise Kubernetes strategy.,
|
||||
children:
|
||||
- name: Open Source
|
||||
icon: /images/home/open-source.svg
|
||||
content: A CNCF certified Kubernetes platform, 100% open source, built and improved by the community
|
||||
|
||||
- name: Easy to Run
|
||||
icon: /images/home/easy-to-run.svg
|
||||
content: Can be deployed on a Kubernetes cluster or Linux machines, supports online and air-gapped installation
|
||||
|
||||
- name: Feature-rich
|
||||
icon: /images/home/feature-rich.svg
|
||||
content: Delivers DevOps, service mesh, observability, application management, multi-tenancy, storage and networking management in an unified platform
|
||||
|
||||
- name: Modular & Pluggable
|
||||
icon: /images/home/modular-pluggable.svg
|
||||
content: These functionalities are loosely coupled with the platform since they are pluggable and optional. Other tools are easy to integrate and play
|
||||
|
||||
|
||||
|
||||
section3:
|
||||
title: Benefits to different teams
|
||||
content: Multi-tenancy makes different teams to securely deploy and maintain containerized applications from the cloud to the edge. It allows developers to deploy code via several clicks on intuitive console, brings centralized observability and powerful DevOps strategy for Ops team, helps Infra team to install and maintain Kubernetes cluster with flexible network and solution solutions, avoid locking team in to a single vendor eco-system.
|
||||
children:
|
||||
- name: Infra Team
|
||||
content: Building one-stop enterprise-grade DevOps framework
|
||||
icon: /images/home/7.svg
|
||||
children:
|
||||
- content: Improve your environment utilization and reduce internal infrastructure costs
|
||||
- content: Support multi-cluster and multi-cloud Kubernetes management, avoiding vendor lock-in
|
||||
- content: Provides security enhancements, supports multiple storage and network solutions
|
||||
- content: Fully trusted, delivers a certified Kubernetes platform and distribution
|
||||
|
||||
- name: Developers
|
||||
content: Focus on your bussiness, others are run in automated tools
|
||||
icon: /images/home/74.png
|
||||
children:
|
||||
- content: Smooth user experience, reduce the learning curve of the cloud native stack
|
||||
- content: Provide toolkits and deployment automation tailored to any application environment
|
||||
- content: Out-of-box logging, monitoring and multi-tenancy, improving development efficiency
|
||||
- content: Support application lifecycle management, accelerating time to market
|
||||
|
||||
- name: Ops Team
|
||||
content: Building one-stop enterprise-grade DevOps framework
|
||||
icon: /images/home/71.svg
|
||||
children:
|
||||
- content: Centralized log collection, monitoring and alerting from infrastructure to applications.
|
||||
- content: Streamlined continuous deploy, test, release, upgrade and scale
|
||||
- content: Better track, route and optimize communications within Kubernetes for cloud native apps
|
||||
- content: Easy-to-use web terminal and graphical panel, satisfying the habits of different users
|
||||
|
||||
section4:
|
||||
title: Key Features
|
||||
content: If you want to use an open source project, but act like a commercial product, KubeSphere is your choice. The Roadmap listed the planning features, you can raise a proposal to submit your ideas with us.
|
||||
children:
|
||||
- name: Provisioning Kubernetes
|
||||
icon: /images/home/provisioning-kubernetes.svg
|
||||
content: Deploy Kubernetes on any infrastructure out of box, including online and air-gapped installation, support add GPU node
|
||||
|
||||
- name: K8s Resource Management
|
||||
icon: /images/home/k-8-s-resource-management.svg
|
||||
content: Provide web console for creating and managing Kubernetes resources, with powerful observability
|
||||
|
||||
- name: Multi-tenant Management
|
||||
icon: /images/home/multi-tenant-management.svg
|
||||
content: Provide unified authentication with fine-grained roles and three-tier authorization system, supports AD/LDAP authentication
|
||||
|
||||
features:
|
||||
- name: Application Store
|
||||
icon: /images/home/store.svg
|
||||
content: Provide application store for Helm-based applications, and offers application lifecycle management
|
||||
color: grape
|
||||
|
||||
- name: Service Mesh (Istio-based)
|
||||
icon: /images/home/service.svg
|
||||
content: Provide fine-grained traffic management, observability and tracing, and offers visualization for traffic topology
|
||||
color: red
|
||||
|
||||
- name: Rich Observability
|
||||
icon: /images/home/rich.svg
|
||||
content: Multi-dimensional monitoring metrics, multi-tenant log query and collection, support alerting and notification
|
||||
color: green
|
||||
|
||||
- name: DevOps System
|
||||
icon: /images/home/dev-ops.svg
|
||||
content: Out-of-box CI/CD based on Jenkins, and offers automated workflow tools including S2I & B2I
|
||||
color: orange
|
||||
|
||||
- name: Multiple Storage Solutions
|
||||
icon: /images/home/multiple.svg
|
||||
content: Support GlusterFS, CephRBD, NFS, LocalPV solutions, provide CSI plugins to consume storage from multiple cloud providers
|
||||
color: grape
|
||||
|
||||
- name: Multiple Network Solutions
|
||||
icon: /images/home/network.svg
|
||||
content: Support Calico and Flannel, provides load balancer plug-in Porter for Kubernetes installed on physical machines
|
||||
color: green
|
||||
|
||||
- name: Multi-cluster management
|
||||
icon: /images/home/management.svg
|
||||
content: Distribute applications across multiple clusters and cloud providers, and provides the disaster recovery and cross-cluster discovery.
|
||||
color: orange
|
||||
|
||||
section5:
|
||||
title: KubeSphere with its cloud native architecture
|
||||
frontEnd:
|
||||
title: Front end
|
||||
project: KubeSphere Console
|
||||
children:
|
||||
- icon: /images/home/mobx.jpg
|
||||
- icon: /images/home/koa.jpg
|
||||
- icon: /images/home/react.png
|
||||
|
||||
backEnd:
|
||||
title: Back end (REST API)
|
||||
project: KubeSphere System
|
||||
group:
|
||||
- name: API Server
|
||||
- name: API Gateway
|
||||
- name: Controller Manager
|
||||
- name: Account Service
|
||||
|
||||
|
||||
section6:
|
||||
title: Who uses KubeSphere
|
||||
content: The Case Studies listed more detailed user cases and their cloud native transformation stories. </br>Various enterprises and organizations use KubeSphere Container Platform for research, production and commercial products.
|
||||
children:
|
||||
- icon: /images/home/section6-1.jpg
|
||||
- icon: /images/home/section6-2.jpg
|
||||
- icon: /images/home/section6-3.jpg
|
||||
- icon: /images/home/section6-4.jpg
|
||||
- icon: /images/home/section6-5.jpg
|
||||
- icon: /images/home/section6-6.jpg
|
||||
- icon: /images/home/section6-7.jpg
|
||||
- icon: /images/home/section6-8.jpg
|
||||
- icon: /images/home/section6-9.jpg
|
||||
- icon: /images/home/section6-10.jpg
|
||||
btnContent: Case Studies
|
||||
btnLink:
|
||||
link:
|
||||
linkContent: Want your logo up there? Just submit a pull request →
|
||||
image: /images/home/certification.jpg
|
||||
---
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
title: "page1"
|
||||
|
||||
css: "scss/blogs.scss"
|
||||
---
|
||||
|
|
@ -0,0 +1,75 @@
|
|||
---
|
||||
title: "case"
|
||||
css: "scss/case.scss"
|
||||
|
||||
|
||||
section1:
|
||||
title: User Case Studies
|
||||
content: KubeSphere is trusted by various enterprises and organizations to the innovators driving the future of software.
|
||||
topImage: "images/case/case-top.jpg"
|
||||
|
||||
section2:
|
||||
tip: Read Case Study →
|
||||
caseList:
|
||||
- icon: "images/case/case1.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case2.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case3.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case4.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case5.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
- icon: "images/case/case6.jpg"
|
||||
content: "KubeSphere is trusted by various enterprises and organizations to the innovators driving the future
|
||||
of software."
|
||||
link: ""
|
||||
|
||||
section3:
|
||||
title: 'Various Industries are Powered by KubeSphere'
|
||||
tip: ALL
|
||||
caseType:
|
||||
- name: 'Financial'
|
||||
children:
|
||||
- name: 'sina'
|
||||
icon: 'images/case/v1.jpg'
|
||||
- name: 'benlai'
|
||||
icon: 'images/case/v2.jpg'
|
||||
|
||||
- name: 'T Service'
|
||||
children:
|
||||
- name: 'inaccel'
|
||||
icon: 'images/case/v3.jpg'
|
||||
- name: 'founder'
|
||||
icon: 'images/case/v4.jpg'
|
||||
|
||||
- name: 'E-Business'
|
||||
children:
|
||||
- name: 'huaxia'
|
||||
icon: 'images/case/v5.jpg'
|
||||
- name: 'aqara'
|
||||
icon: 'images/case/v6.jpg'
|
||||
|
||||
- name: 'Manufacture'
|
||||
children:
|
||||
- name: 'powersmart'
|
||||
icon: 'images/case/v7.jpg'
|
||||
- name: 'anchnet'
|
||||
icon: 'images/case/v8.jpg'
|
||||
---
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
title: "page1"
|
||||
|
||||
css: "scss/conferences.scss"
|
||||
---
|
||||
|
|
@ -0,0 +1,196 @@
|
|||
---
|
||||
title: '基于 CSI Kubernetes 存储插件的开发实践'
|
||||
type: 'QCon'
|
||||
author: '王欣'
|
||||
createTime: '2019-12-04'
|
||||
snapshot: 'https://pek3b.qingstor.com/kubesphere-docs/png/20190930112634.png'
|
||||
---
|
||||
|
||||
现在很多用户都会将自己的应用迁移到 Kubernetes 容器平台中。在 Kubernetes 容器平台中,存储是支撑用户应用的基石。随着用户不断的将自己的应用深度部署在 K8S 容器平台中,但是我们现有的 Kubernetes 存储插件无论从多样性还是存储的功能来说,都无法满足用户日益增长的需求。我们急需开发新的存储插件,将我们的存储服务和 Kubernetes 容器平台相对接。
|
||||
|
||||
## Kubernetes 存储插件分类
|
||||
|
||||
今天的主题是基于 CSI Kubernetes 存储插件的开发实践,我们会通过以下四部分为大家详细讲解 CSI 插件有什么功能,如何部署一个 CSI 插件,以及 CSI 的实践原理。
|
||||
|
||||
首先,我们会介绍 Kubernetes 存储插件的分类情况;然后为大家介绍如何开发一款 QingCloud 云平台 CSI 插件;之后,会介绍如何将 QingCloud 云平台 CSI 插件部署到 Kubernetes 容器平台中;最后,介绍如何对开发的 CSI 插件进行质量管理。
|
||||
|
||||

|
||||
|
||||
在 Kubernetes 容器平台中,Kubernetes 可以调用某类存储插件,对接后端存储服务,如调用 GCE 存储插件对接后端 GCE 存储服务。Kubernetes 里的存储插件可以分为 **In-tree 和 Out-of-tree** 这两大类。
|
||||
|
||||

|
||||
|
||||
首先,In-tree 存储插件的代码是在 Kubernetes 核心代码库里,In-tree 存储插件运行在 Kubernetes 核心组件里。Kubernetes 容器平台要使用后端某类存储服务,需要调用相应的 In-tree 存储插件,比如 Kubernetes 容器平台要使用后端 AWS 存储服务,需要调用 In-tree AWS 存储插件才能对接后端 AWS 存储服务。
|
||||
|
||||
另一类存储插件是 Out-of-tree 的存储插件,其代码和 Kubernetes 核心代码相独立。它的部署与 Kubernetes 核心组件的部署相独立,Kubernetes 核心组件可以通过调用某类 Out-of-tree 存储插件对接我们后端的存储服务,比如 Kubernetes 可以通过调用 GCE Out-of-tree 存储插件对接后端 GCE 存储服务。
|
||||
|
||||

|
||||
|
||||
**将 In-tree 存储插件和 Out-of-tree 存储插件进行比较:**
|
||||
|
||||
从功能性上来看,In-tree 存储插件支持的功能比较有限,比如存储管理基本功能:存储卷创建、删除、挂载、卸载等功能。
|
||||
而 Out-of-tree 存储插件在功能性上比较丰富,除了有存储卷管理的基本功能外,现在也有快照管理功能。比如我们可以创建基于某个存储卷的快照,删除快照或者从快照恢复创建一个存储卷。
|
||||
|
||||
从支持存储类型的种类来说,In-tree 的存储插件种类比较有限,用户需要准备 Kubernetes 原生支持的若干存储系统,这样会限制用户的选择。如果用户要在 Kubernetes 里选 In-tree 存储插件,必须有官网上列出的存储服务端才能对接。
|
||||
|
||||
而 Out-of-tree 存储插件支持的存储类型比较多样,存储厂商或者存储系统商开发相应的 Out-of-tree 存储插件,即可以与 Kubernetes 容器平台对接。这样不会限制用户的选择。
|
||||
|
||||
从易维护性上来说,In-tree 存储插件的代码在 K8S 核心代码仓库内,跟随 Kubernetes 打包发布。从维护性上来说并不是很好维护,In-tree 存储插件运行在 Kubernetes 核心组件内,如果 In-tree 存储插件出现问题,也会影响 Kubernetes 核心组件的正常运行。
|
||||
而 Out-of-tree 存储插件的代码独立于 Kubernetes,也可以独立构建发布,比较易于维护。今后的趋势是,尽量开发和使用 Out-of-tree 存储插件。
|
||||
|
||||
Out-of-tree 存储插件现在分为 FlexVolume 和 CSI 两大类。FlexVolume 插件是 Kubernetes1.2 开始支持的, QingCloud 云平台开发过相关的 FlexVolume 存储插件。FlexVolume 存储插件的部署相对 CSI 这种会复杂一些,FlexVolume 支持存储卷基本管理功能。
|
||||
|
||||

|
||||
|
||||
另一种比较新的存储方案是 CSI 方案,CSI 方案全称是 Container Storage Interface,它是容器平台里的一种工业标准。CSI 不仅仅是针对 Kubernetes 容器平台开发的,它是一种容器平台的通用解决方案。存储服务商或者存储厂商只要开发支持 CSI 标准的存储插件,就可以供各种容器平台使用。Kubernetes 从 1.9 开始支持 CSI 规范。
|
||||
|
||||
CSI 插件方案部署起来比较简单,可以支持容器化部署,在 Kubernetes 容器平台中,我们可以用 Kubernetes 的资源对象直接部署 CSI 插件。CSI 插件方案功能比较强大,除了存储卷管理功能外,还有快照管理功能。CSI 的存储标准方案在持续快速发展中,功能也会不断扩展。今后我们会尽量开发和使用基于 CSI 的存储插件方案。
|
||||
|
||||
## 如何开发一款 CSI 插件
|
||||
|
||||
接下来跟大家分享我在 QingCloud 云平台开发 CSI 插件的经验,并且告诉大家 QingCloud 云平台是如何开发一款 CSI 插件,如何把 CSI 插件部署在 Kubernetes 容器平台中,为用户提供相应的存储支持。
|
||||
|
||||

|
||||
|
||||
在谈到开发 CSI 插件之前,我们先了解一下 CSI 插件的基本原理:开发一款 CSI 插件要遵循 CSI 的标准实现相关的接口,在实现接口中,我们可以调用底层存储服务端的 API。在 QingCloud 云平台开发的 CSI 插件里,我们实现 CSI 接口是调用 QingCloud 云平台云平台 API 实现相关业务逻辑。
|
||||
|
||||
**CSI 插件在容器平台和存储资源体系结构中起到承上启下的作用。**
|
||||
|
||||
承上,容器平台可以通过 gRPC 调用 CSI 插件,对接 CSI 接口,支撑容器平台对于存储卷管理的功能,如创建、挂载、删除等操作。
|
||||
启下,CSI 插件实现 CSI 接口,是通过调用存储服务端 API 实现相关业务逻辑,可以充分挖掘我们存储资源的能力。
|
||||
|
||||

|
||||
|
||||
关于开发 CSI 插件,将会从以下三方面跟大家分享:
|
||||
|
||||
- 第一,CSI 接口规范。
|
||||
- 第二,分享开发 CSI 插件的经验。
|
||||
- 第三,开发 CSI 插件各个接口也要符合返回值规范。开发 CSI 插件的官方文档可以从 GitHub 上获取。
|
||||
|
||||
## CSI 接口规范
|
||||
|
||||
首先,开发一款 CSI 插件是要实现相关 CSI 的接口,作为开发者来说,CSI 规范将接口分为 Identity、Controller、Node 三大类。
|
||||
|
||||

|
||||
|
||||
首先是 **Identity 接口**,其功能主要描述插件的基本信息,我们可以通过 GetPluginInfo 的接口获得插件版本号或者插件所支持的 CSI 规范版本,像 Get Plugin Capabilities,我们可以找到插件的功能点,插件是否支持存储卷创建、删除等功能,是否支持存储卷挂载的功能。得到插件元数据信息。此外 Identity 接口可以检查插件的健康状态,开发者可以通过实现 Probe 接口对我们插件健康状况进行检查。
|
||||
|
||||
第二类开发者要实现的接口是 **Controller 类接口**,它主要从存储服务端的角度对存储资源和存储卷进行相关管理的接口,如存储卷的创建和删除,开发者需要实现 Controller 接口的 Create Volume 接口和 Delete Volume 接口,对存储卷进行创建和删除的操作。
|
||||
|
||||
如果我们要从存储服务端进行操作,比如将存储卷挂载在某台主机上,或者将存储卷从某台主机上卸载,开发者要实现 ControllerPublishVolume 和 ControllerUnpublishVolume 这两个接口。
|
||||
|
||||
最后一类需要开发者实现的接口称为 **Node 类接口**,主要对主机上的存储卷进行操作。像存储卷的分区和格式化,将存储卷挂载到指定目录上,或者将存储卷从指定目录上卸载。
|
||||
|
||||
比如存储卷分区格式化,我们会调用 NodeStageVolume 和 NodeUnstageVolume 来实现。存储卷挂载至某个路径或者将存储卷从某个容器路径中卸载,开发者要实现 NodePublishVolume 和 NodeUnpublishVolume 这两个接口。
|
||||
|
||||
以上就是开发者要实现的三类接口,对于部署的用户或者对于容器平台来说,可以将 CSI 插件分为两类服务:Controller 类服务和 Node 类服务。
|
||||
Controller 类服务主要调用 Controller 类接口,从存储服务端角度对存储卷进行管理和操作。Node类服务主要调用 Node 类接口,对主机上的存储卷进行相应的操作。
|
||||
|
||||
## CSI 插件开发经验
|
||||
|
||||

|
||||
|
||||
接下来以存储卷的生命周期为例为大家介绍 CSI 插件运行过程。在讲这个例子之前,我们想象一下个人在非容器化场景下如何使用存储卷。首先我们会打开云平台控制台,点击创建一个块存储卷,在控制台上把块存储卷挂载至某台主机,之后我们会登录主机,对主机里的存储卷进行分区格式化操作。再将已经分区格式化的存储卷挂载至某个路径下,才能让我们的应用使用这个存储卷。
|
||||
|
||||
在容器平台中流程也是相似的,接下来可以看到我们如何通过调用实现的各类 CSI 接口,完成我们对存储卷管理的过程。
|
||||
|
||||
当我们用户向容器平台发起创建存储卷的请求时,容器平台会调用 CSI 插件 Controller 服务的 CreateVolume 接口,发起创建存储卷的请求。
|
||||
CSI 插件实现 CreateVolume 接口会调用底层云平台 API,云平台会创建好一个块存储卷。将块存储卷的信息通过 CSI 插件反馈给容器平台,此时状态称之为 Create 状态,表明存储卷已经创建好,从容器平台中进行管理。就像我们刚才所说的在 Controller 里完成创建存储卷的操作。
|
||||
|
||||
之后存储卷要被用户的应用所使用,用户会起一个容器化的应用挂载存储卷。容器平台会调度容器到某台主机上,相应的容器平台会调用 CSI 插件的 ControllerPublishVolume 接口,将存储卷挂载至某台主机上。
|
||||
|
||||
CSI 插件实现的 ControllerPublishVolume 接口会调用底层云平台 API 实现相关操作。完成操作后,存储卷挂载这台主机上,可以在这台主机上看到存储卷为某个块设备后,这个状态称之为 Node Ready 状态。相当于我们刚刚所说的,在云平台 Controller 界面,把存储卷挂载至某台主机上。这两个功能都是通过 Controller 服务来做的。Controller 服务是从存储服务端的角度对存储卷进行全局的控制。
|
||||
|
||||
达到 Node Ready 状态后,此时我们的存储卷可以在主机内可见,我们容器平台会调用 CSI 插件的 Node Stage Volume 接口对存储卷进行分区格式化操作。在 CSI 插件里,相关实现逻辑会对存储卷进行分区格式化,完成之后状态称之为 Volume Ready 状态,表明存储卷此时已完成了分区格式化的操作。
|
||||
|
||||
接下来容器平台,希望把存储卷挂载至容器指定目录下,可以调用 CSI 插件 Node 服务的 NodePublishVolume 接口实现相应的操作。完成相关操作后,存储卷此时已挂载到容器指定目录中,这个状态称之为 Published 状态,完成存储卷挂载至容器中的过程。
|
||||
用户从非容器化情况下如何一步步挂载至主机目录,整个过程通过 CSI 插件和容器平台配合自动化完成。当用户应用运行结束后,需要卸载存储卷的过程和是刚才挂载存储卷的逆过程。
|
||||
|
||||
我们容器平台会依次调用 CSI 插件的 NodeUnpulishVolume、NodeUnstageVolume 这两个接口,将存储卷从主机内把指定的目录卸载。容器平台会调用 CSI 插件的 NodeUnpulishVolume,将存储卷从某台主机中卸载。此时状态回到 Created 状态,这时候 Created 状态存储卷在容器平台中来看是一个没有挂载到任何容器的存储卷资源。
|
||||
|
||||
此时在 Created 状态的存储卷,我们可以对其再进行一次挂载到容器中的操作,也可以对它进行删除操作。用户向容器平台发起删除存储卷请求后,容器平台会调用 CSI 插件的 DeleteVolume 接口,将存储卷删除。存储卷生命周期包括存储卷创建、挂载、卸载、删除等操作。
|
||||
|
||||
我们实现 CSI 插件仅仅简单的实现CSI接口所规定的字面意义是绝对不行的。例如:我们实现 CSI CreateVolume 接口直接调用底层云平台的创建存储卷 API 是远远不够的。其中需要开发者解决一个问题是,存储卷泄漏状况的发生。
|
||||
|
||||

|
||||
|
||||
当容器平台发起一个创建存储卷请求时,CSI 插件会调用底层云平台 API 创建存储卷。此时在云平台这边创建一个存储卷 A,存储卷 A 的信息通过 CSI 插件反馈到容器平台。当你将存储卷 A 的信息反馈到容器平台时,一些意外情况没有及时反馈容器平台或者没有成功的反馈到容器平台时,容器平台会重新以相同的请求参数,再次发起一个创建存储卷的请求。
|
||||
|
||||
这个请求又会通过 CSI 插件调用底层云平台创建存储卷 API,在底层云平台中又会创建一个新的存储卷。新创建的存储卷称之为存储卷 B,底层云平台将存储卷 B 的信息通过 CSI 插件反馈到容器平台中,这样才能完成一次存储卷创建。
|
||||
|
||||
此时在存储服务端中会有 A、B 这两个存储卷,都是由容器平台创建的。而实际上在容器平台这边,管理并发现存储卷 B,对于存储卷 A 来说,对于容器平台来说是不可知的。此时,存储卷 A 是无人管理的存储卷,造成存储卷泄漏的问题。存储卷泄漏问题十分严重,不仅会造成资源的浪费,还会造成其他影响。比如当我们配额或者资源不足时,会影响我们正常创建存储卷的请求,不能正常创建存储卷。我们要避免存储卷泄漏情况的发生。CSI 插件通过实现 CSI 插件接口的幂等性,避免存储卷泄漏情况的发生。所谓幂等性指的是以相同参数对某个接口调用一次和多次的结果是相同的。
|
||||
|
||||

|
||||
|
||||
就刚才的例子所说,我们要实现 CreateVolume 接口,创建一个存储卷时,不能简单的调用底层 API 创建存储卷。在创建存储卷之前,CSI 插件需要先到存储服务端查询是否有符合我们创建存储卷参数的存储卷存在,如果有,直接反馈存储卷信息。如果没有相应存储卷的存在,CSI 插件调用底层云平台 API 新建一个存储卷。
|
||||
|
||||
对于刚才的流程来说,首先看到容器平台发起创建存储卷的请求,插件成功调用底层云平台 API,成功创建存储卷 A 的信息。此时,存储卷 A 的信息并没有成功反馈到容器平台中,容器平台以相同的参数调用 CSI 的 CreateVolume API创建一个存储卷。我们有幂等性的插件会先到存储服务端检查是否有存储卷的存在,如果有符合参数存储卷的存在,直接将存储卷A的信息反馈到容器平台,避免存储卷泄漏问题的发生。
|
||||
|
||||
## CSI 返回值规范
|
||||
|
||||
我们开发 CSI 插件时也要符合 CSI 返回值的规范,CSI 对于存储插件的开发者来说,对 CSI 返回值有相关的规范。同时对于容器平台来说,要对不同返回值做相关的特殊处理。那么,我们在实际 Create Volume CSI 接口有怎样的返回值规范?
|
||||
|
||||

|
||||
|
||||
对于输入请求的参数,如果缺少必要的字段,实现 CSI 的接口需要立即返回,告诉容器平台你的请求缺少必要的字段。如果有的字段不支持也会返回给容器平台。
|
||||
|
||||
前面我们谈到如何开发 CSI 插件,我们开发 CSI 插件最重要的是实现 CSI 所规定的相关接口。我们 QingCloud 云平台开发了基于 QingCloud 云平台云平台的块存储 CSI 插件,也开发了基于 QingCloud 云平台 NeonSAN 的 CSI 插件。
|
||||
|
||||
## 如何部署 CSI 插件
|
||||
|
||||
我们将从通信、部署架构等多个方面,介绍我们如何将开发的 CSI 插件部署到 Kubernetes 容器平台中。我们使用的是 Kubernetes CSI 推荐的方式,可以从 GitHub 上获取。
|
||||
|
||||

|
||||
|
||||
首先,我们来看通信方面的用途,前面谈到 Kubernetes CSI 对接组件和CSI存储插件共同构成存储插件层,在 Kubernetes 和存储服务之间。对于 CSI Controller 服务,可以看到 K8S 和 CSI 对接组件是通过调用 K8S API,通过 HTTP 协议与 K8S API Server 进行相关的交互。
|
||||
|
||||

|
||||
|
||||
Kubernetes CSI 对接组件对于下层与 CSI 存储插件相通信,是通过 UDS 进行通信交互。CSI 存储插件收到调用 CSI 请求,调用底层云平台 API 也是通过 HTTP 协议实现的。
|
||||
|
||||
对于 Node 来说,K8S 核心组件是 Kubelet,通过 UDS 调用 CSI 存储插件所开发的 CSI 接口,CSI 存储插件实现了 CSI 接口,通过调用底层云平台 API,通过 HTTP 协议实现相关业务逻辑。这是我们 CSI 插件的通信流程。
|
||||
|
||||
那么如何部署CSI插件到K8S容器平台中呢,这是我们的部署架构图。
|
||||
|
||||

|
||||
|
||||
在部署架构图里可以看到 K8S Master 节点,下面划出了三个 K8S 的 Node 节点。灰色组件表明 K8S 核心组件。在 Master 节点上,我们划出 K8S API Server。在 Node 节点上,我们只划出了 K8S 核心组件的 Kubelet。深蓝色部分指的是 K8S 与 CSI 的对接组件,这是由 Kubernetes 团队维护的。绿色部分表明 QingCloud 云平台开发的 CSI 存储插件。
|
||||
|
||||
首先可以从 Controller 服务来看,CSI 插件在部署时分为 Controller 类服务和 Node 类服务,Controller 类服务是从存储服务端的角度对存储资源进行相应的操作。
|
||||
|
||||
Controller 服务相当于 CSI 插件大脑,只需要部署 Controller 服务的一个副本即可,所以我们使用 K8S StatefulSet Workload 部署 Controller 服务。在 Controller 服务里,我们封装了 K8S 和 CSI 的对接组件,包括 External Provisioner、External Attacher 和 QingCloud 云平台开发的 CSI 存储插件也封装在这个服务里。主要流程是通过 External Provisioner 和 External Attacher,他们会主动获取 K8S API Server 存储的相关资源信息,再调用 Controller 里的 CSI 存储插件所使实现的 CSI 接口,对存储服务端的存储资源进行相关操作。
|
||||
|
||||
在 Node 服务中,前面谈到 Node 服务是从主机的角度对主机上的存储卷进行相关的操作。Node 服务使用 K8S DaemonSet 进行创建,在 Node 服务里,我们会封装一个 Driver Registrar 这么一个 K8S 和 CSI 的对接组件。这个组件的主要功能是将 Node 服务注册到我们节点上。
|
||||
在 Node 服务中,也有个 CSI 存储插件的容器,在这个容器中,我们接收到本 Node 上 Kubelet 的调用,Kubelet 可以直接通过 UDS 调用 CSI 插件,Node 服务 CSI 存储插件的容器实现的相关 CSI 接口对主机上的存储卷进行操作,比如对主机上的存储卷进行分区格式化或者将存储卷挂载至某个容器的指定路径下,或者从某个容器的指定路径中进行卸载操作。
|
||||
|
||||
前面谈到 CSI 存储插件可以通过 Kubernetes 的资源对象进行部署,其优势是可支持容器化部署,并且部署简便。在部署 QingCloud 云平台 CSI 插件到 Kubernetes 平台中遵循了相关规范,我们使用了 Kubernetes 的 YAML 文件部署我们的 CSI 插件。可以看到我们部署的 CSI 插件会使用到 Config.yaml、RBAC 权限控制,Controller 使用 StatefulSet 部署,Node 服务通过 DaemonSet 部署。
|
||||
|
||||
Secret 密钥是为了拉取 CSI 插件的镜像所使用的资源对象。可以看到部署 CSI 插件到 Kubernetes 容器平台中,是使用 Kubernetes 已有的资源对象,完成部署过程。通过 Kubernetes 资源定义文件,我们可以很方便的让用户在不同的集群里快速部署标准化 CSI 插件。在 CSI 插件中需要对 Kubernetes 资源对象进行读写的操作。存储插件需要读写的权限,我们在读写权限使用 RBAC 进行权限控制。如图所示,我们在 attacher 这个功能点上赋予了 CSI 插件一些有限的权限,完成相关工作。
|
||||
|
||||
这里只让 CSI 插件有读写必要资源对象的权限,只能读取 Node 资源对象的权限或是读写 PersistentVolume, VolumeAttachement 等资源对象的权限。通过 RBAC 的权限控制可以维护集群安全,限制存储插件对于 Kubernetes 资源对象读写的权限,维护我们集群的安全。
|
||||
|
||||
## 如何对 CSI 插件进行质量管理
|
||||
|
||||
前面讲完我们如何开发一个 CSI 插件,以及如何将 CSI 插件部署到 Kubernetes 容器平台中。接下来我们看看在开发时,如何对 CSI 插件进行质量管控。
|
||||
|
||||

|
||||
|
||||
我们在开发 CSI 插件时引入了持续集成的概念,我们在开发相关 CSI 插件代码时会写相关单元测试,对 CSI 插件进行相关测试。我们开发完代码,每次提交会先运行单元测试,通过一键式 Makefile 构建程序,再通过 Dockerfile 和 Makefile 一键式制作我们的 CSI 插件镜像。构建镜像成功后,我们通过前面所说的 K8S Yaml 资源定义文件,持续部署我们 CSI 插件到 Kubernetes 容器平台中。当部署成功后,我们会进行 Kubernetes CSI Test 的过程,Kubernetes CSI Test 是 K8S CSI 官方开发的一个测试 CSI 插件的项目,我们需要通过这个测试。
|
||||
下一步是集成测试的阶段,在集成测试里我们会模拟用户使用情况创建资源对象,对我们 CSI 插件进行最后的测试。当集成测试成功后,才能顺利的完成提交过程。
|
||||
|
||||
从单元测试到持续集成过程中出现错误或过不去的情况,我们会返回开发代码阶段修复问题。引入持续集成开发 CSI 插件时,我们感觉到开发初期,有些问题快速暴露出来。我们快速定位问题并且解决,在开发 CSI 插件的后期可以顺利的进行 CSI 插件的版本发布等工作。
|
||||
|
||||

|
||||
|
||||
关于 Kubernetes CSI Test 项目,它是 K8S CSI 官方开发的开源项目,主要测试 CSI 插件是否符合 CSI 标准规范。左图是相关 CSI Test 的截图,右图是我们开发 CSI 插件运行 CSI Test 后的结果。可以看到 QingCloud 云平台开发的 CSI 插件要通过 CSI Test。
|
||||
|
||||

|
||||
|
||||
前面谈到 CSI 插件如何开发部署,并且谈到 CSI 的质量管理。接下来我们对 CSI 的发展进行简单的展望。我们知道 CSI 规范在不断快速发展中,昨天发布了 1.0 版本。下一步我们 CSI 规范会对快照功能进行完善,如快照保护等功能, QingCloud 云平台会持续跟进并且开发新 CSI 插件,支持最新的功能。
|
||||
|
||||
在 CSI 插件使用中,需要增加存储卷监控功能。用户使用存储卷挂载至容器中,我们需要知道存储卷已使用容量,存储卷监控是不可缺少的。当用户存储卷容量已经满或者将要满的时候,我们需要存储卷扩容的功能。Kubernetes CSI 官方逐渐将 K8S In-tree 的存储插件向 CSI 存储插件迁移,可以看到无论在开发和使用上,CSI 存储插件的确是大的趋势。
|
||||
|
||||

|
||||
|
||||
以上列出了相关资源,最上面是 CSI 的定义规范,下面是 QingCloud 云平台开发的基于 QingCloud 云平台云平台的 CSI 存储插件,还有基于 NeonSAN 的 CSI 存储插件,都可以在 GitHub 上获取。
|
||||
|
||||
|
|
@ -0,0 +1,172 @@
|
|||
---
|
||||
title: '基于 Kubernetes 的 Serverless Jenkins — Jenkins X'
|
||||
type: 'KubeCon'
|
||||
author: '夏润泽'
|
||||
createTime: '2019-06-24'
|
||||
snapshot: 'https://pek3b.qingstor.com/kubesphere-docs/png/20190930095450.png'
|
||||
---
|
||||
|
||||
在云原生时代,应用模块不断被拆分,使得模块的数量不断上涨并且关系也越加复杂。企业在落地云原生技术的时候同事也需要有强大的 DevOps 手段,没有 DevOps 的云原生不可能是成功的。Jenkins X 是 CDF(持续交付基金会)与 Jenkins 社区在云原生时代的 DevOps产品,本文我们将介绍 Jenkins X 以及 Jenkins X 背后的技术。
|
||||
|
||||
## 背景
|
||||
|
||||
Jenkins 在2004年诞生。根据官网的数据统计(截止2019年3月)有 250,000 的 Jenkins 服务器正在运行、15,000,000+ Jenkins 用户、1000+ Jenkins插件。Jenkins 在 DevOps 领域取得了巨大的成功,但随着技术的不断发展与用户数量的不断上升,传统 Jenkins 所暴露出来的问题也越来越多。在这里我们将介绍传统 Jenkins 所遇到的挑战。
|
||||
|
||||
### Jenkins 所遇到的挑战 - 单点故障
|
||||
|
||||
在传统的 Jenkins 当中,我们首先会遇到的问题就是 Jenkins 的单点故障问题。
|
||||
Jenkins 的历史非常悠久,在当时大多数程序都是单机程序,Jenkins也不例外。
|
||||
对比其他系统,Jenkins 的单点故障问题会更加凸显,熟悉 Jenkins 的用户都知道,它是一个基于插件的系统,而我们会经常安装插件,这时候我们就需要重启 Jenkins 服务器。这将导致共用这个平台的所有用户都无法使用。
|
||||
|
||||
### Jenkins 所遇到的挑战 - JVM消耗资源多
|
||||
|
||||
Jenkins 是 Java 系的程序,这使得 Jenkins 需要使用 JVM,而 JVM 将会消耗大量的内存。
|
||||
CI/CD 任务往往都是在代码提交时被触发,在非工作时间,这些资源消耗是可以大大降低的。
|
||||
|
||||
### Jenkins 所遇到的挑战 - Job 的调度方式使 CI/CD 变得困难
|
||||
|
||||
在 Jenkins 诞生的年代,机器资源并没有像现在一样丰富、可调度,导致 Jenkins 的调度模式使得不适合现代的环境。
|
||||
Jenkins 的调度模式是一种尽量能够节省资源的方式进行调度的。在一般的调度过程中 Jenkins 需要经历以下几个阶段:
|
||||
检查有没有可用的 agent -> 如果没有的可用的agent,计算是否有 agent 预计将要运行完任务 -> 等待一段时间-> 启动动态的 agent -> agent 与 master建立连接。
|
||||
这种方式使 CI/CD 任务被执行的太慢,我们往往都需要等待几十秒甚至更长时间来准备 CI/CD的执行环境。
|
||||
|
||||
## Jenkins X 的诞生与理念
|
||||
|
||||
Jenkins X 是起源于 Jenkins 的一个项目,在2018 年 2 月从 JEP(Jenkins Enhancement Proposals)中诞生。目前已经成为一个独立的项目,并且有了自己独立的 Logo。
|
||||
|
||||

|
||||
|
||||
Jenkins X 的设计目标是使用 Kubernetes 的力量来构建现代化的 CI/CD 平台,为用户提供自动化的 CI/CD。
|
||||
在现代化方面我认为主要有两个部分,其中一部分为用户体验的现代化,另外一部分则是架构方面的现代化。我们这里将首先介绍有关用户体验的现代化,稍后再介绍架构方面的现代化。
|
||||
|
||||
### 重新思考云原生时代的 CI/CD
|
||||
|
||||
用户在使用传统的 Jenkins 的 时候往往都在思考一个问题,我们应该怎样创建一个流水线来完成的工作。而用户想要的并不是如何创建一个流水线,而是想要:
|
||||
|
||||
* 更快的上市时间
|
||||
* 更高的部署频率
|
||||
* 更快的修复时间
|
||||
* 更低发布故障率
|
||||
* 更短的恢复时间
|
||||
|
||||
其实就是通过自动化「软件交付」和「架构变更」的流程,来使得构建、测试、发布软件能够更加地快捷、频繁和可靠。
|
||||
Jenkins X 在设计之初目标就在思考如何让用户如何落地云原生的 CI/CD,如何让用户成为“高性能” 的团队,在《加速度》一书当中 Jenkins X 团队总结出了一些高性能团队所有的特点:
|
||||
|
||||
* 版本化所有制品
|
||||
* 自动执行部署过程
|
||||
* 使用基于主干的开发
|
||||
* 实施持续集成
|
||||
* 实施持续交付
|
||||
* 使用松耦合架构
|
||||
* 让团队成员获得动力
|
||||
|
||||

|
||||
|
||||
于是 Jenkins X 团队将这些特性都融入到了 Jenkins X 当中,让用户更容易落地高性能的 DevOps。
|
||||
|
||||
### 以应用为视角的 CI/CD 产品
|
||||
|
||||
Jenkins X 与其他 CI/CD 产品的最大的不同,在于 Jenkins X 切换了用户在使用 CI/CD 产品时候的视角。在前面我们提到过在传统 Jenkins 当中,用户往往思考的是如何去创建一个流水线,而在全新的 Jenkins X 当中,用户是创建一个应用,而 Jenkins X 将自动的为这个应用创建CI/CD 流水线。
|
||||
为应用创建自动化的 CI/CD 流水线其中就包括 CD 也就是持续交付/部署过程,因此 Jenkins X当中拥有了环境管理的功能。
|
||||
在 Jenkins X 当中,所有操作将是 GitOps 的,GitOps 就是指将所有对基础设施的操作,全部转换为 Git 操作。
|
||||
|
||||

|
||||
|
||||
在上面的图中上面为用户的 Git 仓库,中间为 Jenkins X,最下方为 k8s 当中的 namespace,每一个 namespace都对应一个环境。当用户对我们的 Git 仓库操作时,Jenkins X 会将这些操作转换为对 k8s 集群的操作,以产生预览环境、预发布环境等。
|
||||
在 Jenkins X 当中创建一个应用,默认将拥有三个环境,也就是有三个 Git 仓库。其中第一个为应用的源代码仓库,它对应用户的预览环境,当用户创建一个PR(Pull Request)时,Jenkins X 将为这个 PR 生成一个预览环境,让用户更容易进行代码 review。同时这里还有 staging 和 production 仓库,在这两个仓库当中并没有应用的源代码,而是应用 helm chart 的索引信息。如果仓库当中拥有某一个版本 chart 的索引,那么 Jenkins X 就会把这些应用自动的部署到这个环境当中。
|
||||
环境管理与 GitOps 当中还有一个非常有意思的设计,那就是随时发布一个 release 版本。这里具体行为是这样的,当用户合并一个 PR 到应用的仓库的时候,这时候 Jenkins X 将会自动发布一个小版本的 release,并且自动创建并一个 PR 到 staging 环境的仓库当中,保持应用的 master 分支与 staging 环境当中的部署的应用是对应的。让用户习惯基于主干的开发和主干随时可发布的 DevOps 实践。
|
||||
|
||||
### Jenkins X 的演进
|
||||
|
||||

|
||||
|
||||
Jenkins X 在不断的迭代演进,在最初版本中 Jenkins X 使用传统 Jenkins 完成大部分工作。
|
||||
随后 Jenkins X 引入了 Prow 作为 webhook时间的接收者,来避免大量的仓库扫描,并且弥补传统仓库扫描描述信息不足的情况。
|
||||
之后 Jenkins X 开始使用一次性的 Jenkins Server 运行 CI/CD 任务。一次性的 Jenkins Server 实际上是对传统的 Jenkins 进行了改造,将传统的 Jenkins 打包成为一个可以执行 Jenkinsfile 的执行器。当需要执行 CI/CD 任务的时候去动态的启动 Jenkins Server 完成任务。这种方式虽然解决了长时间运行 Jenkins Server 所带来的资源消耗,但是这种方式还仍然使用 JVM,并且流水线启动的也很慢。
|
||||
后来 Jenkins X 就将底层的流水线引擎从 Jenkins 切换到了 Tekton。Tekton 谷歌开源的 CI/CD 流水线引擎,这部分我们在后面还会有更详细的介绍。
|
||||
在 2019 年 Jenkins X 引入了自己的流水线定义语言 Jenkins-x.yaml,让用户可以使用 yaml 的形式来定义自己的流水线。
|
||||
现在 Jenkins X 社区在努力开发自己的 webhook 响应器 lighthouse 以弥补 prow 只支持 github scm 的问题。
|
||||
|
||||
## Jenkins X 背后的技术
|
||||
|
||||
在上文当中,我们主要了解了 Jenkins X 的诞生以及全新的用户体验。在这一章当中我们将主要介绍 Jenkins X 背后的技术,这包括为了用户体验所使用的模块,也包括 Jenkins X 的现代化架构。
|
||||
|
||||
### 应用打包 Draft 与 Build Packs
|
||||
|
||||
在前面我们提到过 Jenkins X 将是以应用为视角的 CI/CD 平台。平台首先要解决的一个问题就是如何进行应用标准化打包的问题。Jenkins X 的应用打包借鉴了很多 Draft 的思想。
|
||||
|
||||
Draft 是云原生社区的一个项目,由 Azure 维护,目标是简化用户创建云原生应用的过程。
|
||||
我们在将应用云原生化的时候需要进行很多工作,包括但不仅限于以下步骤:编写 Dockerfile 将应用容器化->编写 k8s 相关的部署文件->以 Helm 的形式对应用进行打包->……
|
||||
|
||||
这个过程对大部分传统用户来说都拥有很高的学习成本,于是 Draft 诞生了。在使用 Draft 时用户不再需要去学习 Docker、Helm ……用户只需要输入 draft create 并且选择语言,那么 draft 就会自动创建好包括 Dockerfile、deploy.yaml、helm chart、项目基本结构 …… 当需要部署时用户只需要输入 draft up 就可以一键进行构建并且打包部署。
|
||||
|
||||

|
||||
|
||||
与 Draft 类似 Jenkins X 创建了自己的 buildpacks,其中包括 Dockerfile、Helm Chart、jenkins-x.yaml……用户只需要 jx create quickstart 就可以轻松的创建好这一系列的资源,并且 Jenkins X 还将在 scm 上创建好仓库,并且设置好完整的 CI/CD 流水线。这时用户可以根据项目生成的文件,直接开始编写自己的业务代码。
|
||||
|
||||
### 现代化架构初探
|
||||
|
||||
在上文当中我们介绍了有关 Jenkins X 产品方面的现代化,现在来介绍一下 Jenkins X 架构上面的现代化。在 Jenkins X 当中是采用的一种 Serverless 的服务架构。Serverless 是一种云计算执行模型,其中云提供商(k8s)运行服务器,并动态管理机器资源的分配(From WIKI)。
|
||||
|
||||
在以 CI/CD 为业务的 Serverless架构,我们将主要需要以下三个模块。
|
||||
|
||||
* Webhook响应器(类似API Gateway,可以动态其中服务)
|
||||
* 动态 CI/CD 引擎(类似 Func,支持动态加载执行)
|
||||
* 数据的持久化存储
|
||||
|
||||
### 可靠、高性能的流水线引擎 - Tekton
|
||||
|
||||
Tekton 是诞生于 Knative 的一个项目,Knavie 是 Google 开源的一个 Serverless 平台。在 Serverless 平台当中非常重要的一环就是将应用打包,于是 Knavie Build 项目诞生了。在 Knavie Build 诞生之后,大家发现以云原生的方式运行构建有很多优势,例如运行速度很快、可以轻松利用池化的资源。于是大家开始尝试用这种方式来做更多事情,例如执行测试、执行部署等,这个时候 Knavie Pipeline 项目也就诞生了。现在的 Tekton 的前身也就是 Knavie Pipeline,是一个纯正的云原生 CI/CD 引擎。
|
||||
|
||||

|
||||
|
||||
对 Jenkins X 来说 Tekton有非常大的优势就是避免了 JVM 的使用,并且可以动态的启动、高效利用资源,同时基于 CRD 开发的 Tekton也有非常易用的声明式 API。
|
||||
|
||||
### 高性能、高可用的事件响应器 - Prow
|
||||
|
||||
Prow 是诞生于 k8s 测试基础架构的一个组件。目前在 k8s 社区当中每天有上百个仓库的上千个PR/Issue 都通过一个Prow 来处理。
|
||||
Prow 是经过考验的高性能事件响应器,并且基于 k8s controller方式开发的 Prow 可以直接实现高可用,以保证我们事件入口随时可用。
|
||||
Prow 同时还提供了一个非常重要的功能就是 ChatOps,使用这种方式我们只需要在 Issue/PR 中进行回复就可以完成我们日常的大部分工作。
|
||||
插件模型的 Prow 也可以很容易的插入我们想要自定义的功能。
|
||||
|
||||

|
||||
### CRD + Controller 粘合各个模块
|
||||
CRD 是 k8s 当中的一等公民,是扩展 k8s 的标准方式。使用这种模式开发,我们可以容易的实现声明式 API 并且模块之间是松耦合的。k8s 的 watch 机制也可以让我们的请求被快速的响应,并且达到请求的最终一致性。这种开发模式同时拥有非常丰富的社区资源,我们可以利用社区资源很容易的实现例如高可用等特性。
|
||||
|
||||

|
||||
|
||||
这里简单介绍 Jenkins X 响应一个事件的流程
|
||||
1. 首先 SCM 会发送一个 WebHook 事件到 Prow,告诉 Prow 有一个事件发生(例如有人提交PR)
|
||||
2. Prow 在收到消息之后会在 k8s 的 apiserver 创建一个 ProwJob,将 WebHook 消息转换为CRD 资源。
|
||||
3. 这时 k8s apiserver 会通知正在 watch ProwJob 的 Jenkins X Controller
|
||||
4. Jenkins X Controller 获取 ProwJob 的详细信息,并且创建 Tekton 相关的 Pipeline 资源
|
||||
|
||||
这里我们利用 k8s apiserver 做到了非常好的解耦。
|
||||
|
||||

|
||||
|
||||
于是我们就可以得到一个相对完整的图,在上图当中
|
||||
1. SCM 会发送消息到 Prow。在 Prow 当中有多个模块,其中 Hook模块用于处理 WebHook 消息。
|
||||
2. Pipeline Operator(Jx Controller)发现有 ProwJob 被创建之后就会创建 Tekton 的一系列资源包括 Pipeline、Task、Pipeline Run 等。
|
||||
3. 在 Pipeline Run 当中会执行构建制品、推送制品以及部署制品到环境当中等工作
|
||||
### 环境清理与数据持久化
|
||||
在介绍完我们的工作流程之后,我们再来介绍以下 Jenkins X 的环境清理和数据持久化。
|
||||
在使用 Jenkins X 的过程中会产生一系列的资源,大量的资源被写入到 k8s 的 etcd,当数据量较大时就会影响我们 k8s 的正常使用。Jenkins X 利用 k8s 的核心资源 CronJob 来清理一些无用的数据,包括无用的 Preview环境、过期的Pod、过期的其他数据等等。
|
||||
|
||||

|
||||
|
||||
对于我们真正想要持久化的数据,Jenkins X 提供了外部对接的能力。我们可以去对接外部的存储,例如AWS的S3、青云的对象存储……这样我们就可以把想要持久化的数据很容易的保留下来。
|
||||
|
||||

|
||||
|
||||
在上面的图中就体现了这一点,对于 Artifacts、Secrets、Build logs……我们都可以借助云厂商的力量,进行数据的可靠存储,这种方式同样使我们的服务变得无状态、高可用、更稳定。
|
||||
|
||||
## 总结
|
||||
|
||||
Jenkins X 是一个非常现代化的产品,包括现代化的用户体验与现代化的架构设计。
|
||||
对于社区用户来说,现在可以开始尝试使用 Jenkins X (Jenkins X 对 Github的支持相对完善,并且相对传统 Jenkins 来说更节省资源、容易落地)
|
||||
大型企业落地仍然难度比较高,需要社区、用户以及企业的共同努力,建设下一代的 CI/CD 产品和社区。
|
||||
|
||||
大型企业落地 k8s 之上的 CI/CD,使用传统 Jenkins 仍然是首选方案。在使用这种方案时可以结合 kubernetes、kubernetes-cd、casc 等插件使传统 Jenkins 可以与 k8s 互相结合。
|
||||
|
||||
目前社区中的开源 k8s 发行版 KubeSphere 已经将这一方案集成到产品当中,使用户可以获得开箱即用的云原生 CI/CD 功能,有兴趣的同学可以快速安装使用。
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
---
|
||||
title: '云原生可观察性之日志管理'
|
||||
type: 'KubeCon'
|
||||
author: '霍秉杰,马丹'
|
||||
createTime: '2019-06-25'
|
||||
snapshot: 'https://pek3b.qingstor.com/kubesphere-docs/png/20190930095954.png'
|
||||
---
|
||||
|
||||
日志通常含有非常有价值的信息,日志管理是云原生可观察性的重要组成部分。不同于物理机或虚拟机,在容器与 Kubernetes 环境中,日志有标准的输出方式(stdout),这使得进行平台级统一的日志收集、分析与管理水到渠成,并体现出日志数据独特的价值。本文将介绍云原生领域比较主流的日志管理方案 EFK 、 KubeSphere 团队开发的 FluentBit Operator 以及 KubeSphere 在多租户日志管理方面的实践。此外还将介绍受 Prometheus 启发专为 Kubenetes 日志管理开发,具有低成本可扩展等特性的开源软件 Loki。
|
||||
|
||||
## 什么是可观察性
|
||||
|
||||
近年来随着以 Kubernetes 为代表的云原生技术的崛起,可观察性 ( Observability ) 作为一种新的理念逐渐走入人们的视野。云原生基金会 ( CNCF ) 在其 Landscape 里已经将可观察性单独列为一个分类,狭义上主要包含监控、日志和追踪等,广义上还包括告警、事件、审计等。在此领域陆续涌现出了众多新兴开源软件如 Prometheus, Grafana, Fluentd, Loki, Jaeger 等。
|
||||
|
||||

|
||||
|
||||
|
||||
日志作为可观察性的重要组成部分在开发、运维、测试、审计等过程中起着非常重要的作用。著名的应用开发十二要素中提到:“日志使得应用程序运行的动作变得透明,应用本身从不考虑存储自己的输出流。 不应该试图去写或者管理日志文件。每一个运行的进程都会直接输出到标准输出(stdout)。每个进程的输出流由运行环境截获,并将其他输出流整理在一起,然后一并发送给一个或多个最终的处理程序,用于查看或是长期存档。”
|
||||
|
||||
在物理机或者虚拟机的环境中,日志通常是输出到文件,并由用户自己管理,这使得日志的集中管理和分析变得困难和不便。而 Kubernetes 、docker 等容器技术直接将日志输出到 stdout,这使得日志的集中管理和分析变得更为便捷和水到渠成。
|
||||
|
||||
Kubernetes 官网文档给出的通用日志架构如下图所示,包含日志 Agent,后端服务和前端控制台等三个部分。无论是成熟的日志解决方案如 ELK/EFK , 还是云原生领域 2018 年开源的 Loki 都具有相似的架构,下面将分别介绍 ELK/EFK , [Loki](https://github.com/grafana/loki) 以及 [KubeSphere](https://github.com/kubesphere/kubesphere)) 在这方面的贡献。
|
||||
|
||||

|
||||
|
||||
## 新旧势力的联姻:从 ELK 到 EFK,从 Fluentd 到 Fluent Bit
|
||||
|
||||
ELK 是 Elasticsearch, Logstash, Kibana 的简称,是目前比较主流的开源日志解决方案。 而 2019 年 4 月从 CNCF 毕业用 C 和 Ruby 编写的 Fluentd 作为通用日志采集器,以其高效、灵活、易用的特性逐渐取代了用 Java 编写的 Logstash 成为新的日志解决方案 EFK 中的重要一员,并在云原生领域得到广泛认可与应用。Google 的云端日志服务 Stackdriver 也用修改后的 Fluentd 作为 Agent 。然而 Fluentd 开发团队并没有停滞不前,推出了更为轻量级的完全用 C 编写的产品 Fluent Bit,两者的对比如下图所示:
|
||||
|
||||

|
||||
|
||||
可以看到 Fluent Bit 比 Fluentd 占用资源更少,更适合作为日志收集器;而 Fluentd 插件非常多,更适合作为日志的聚合器。
|
||||
|
||||

|
||||
|
||||
## FluentBit Operator 及其在 KubeSphere 中的应用
|
||||
|
||||
Fluent Bit 虽然更加轻量和高效,但也有它的问题:配置文件变更后无法优雅的自动重新加载新的配置。详见官方 Github issue: [#PR 842](https://github.com/fluent/fluent-bit/pull/842) 和 [#issue 365](https://github.com/fluent/fluent-bit/issues/365)
|
||||
|
||||
为了解决上述问题,KubeSphere 团队开发了 [FluentBit Operator](https://github.com/kubesphere/fluentbit-operator) 并将其应用到 KubeSphere 中作为日志收集器。FluentBit Operator 架构及原理如下图所示:
|
||||
|
||||
1. 在 FluentBit Pod 的主 Container 里加入 FluentBit Controller 进程控制 FluentBit 主进程的启停;
|
||||
|
||||
2. 加入 ConfigMap Reload Sidecar Container 用于监控 FluentBit 配置文件所在 ConfigMap 的变化,并在监测到变化的时候调用 FluentBit Controller 的 reload 接口: [http://localhost:24444/api/config.reload](http://localhost:24444/api/config.reload)
|
||||
|
||||
3. 接下来 FluentBit Controller 将重启 FluentBit 主进程以达到加载新的配置文件的目的。
|
||||
|
||||

|
||||
|
||||
### FluentBit Operator 架构图
|
||||
|
||||
在 KubeSphere 中,选择 Elasticsearch 作为日志后端服务,使用 Fluent Bit 作为日志采集器,KubeSphere 日志控制台通过 FluentBit Operator 控制 FluentBit CRD 中的 Fluent Bit 配置 。(用户也可以通过 kubectl edit fluentbit fluent-bit 以 kubernetes 原生的方式来更改 FluentBit 的配置)
|
||||
|
||||

|
||||
|
||||
**KubeSphere 日志系统架构图**
|
||||
|
||||
通过 FluentBit Operator,KubeSphere 实现了通过控制台灵活的添加/删除/暂停/配置日志接收者
|
||||
|
||||

|
||||
|
||||
**KubeSphere 日志配置界面**
|
||||
|
||||

|
||||
|
||||
**KubeSphere 日志搜索界面**
|
||||
|
||||
## 多租户日志管理
|
||||
|
||||
多租户的特性目前在 Kubernetes 社区备受关注,实现方案多种多样,比如有软多租、硬多租等。具体到日志管理方面也是各有不同,Loki 支持的多租户是通过租户 ID ( Tenant ID) 实现了对多租户的支持;KubeSphere 通过 workspace 实现了租户间的隔离,下面我们简单了解一下 KubeSphere 日志管理在多租户方面的实践 (KubeSphere 即将发布的 v2.1 版对日志功能有显著增强,比如对中文日志检索更好的支持,自动注入收集落盘日志的 Sidecar 等)。
|
||||
|
||||
可以看到 KubeSphere 是基于 RBAC 的 3 层多租户架构,Cluster/Workspace/Project 三个层级均有不同级别的 Roles 与之对应。
|
||||
|
||||

|
||||
|
||||
在能访问到日志数据(或其他服务)之前,需要经过 API Gateway 的认证与授权。
|
||||
|
||||

|
||||
|
||||
|
||||
KubeSphere 完整的日志解决方案如下:
|
||||
|
||||

|
||||
|
||||
## 云原生的亲儿子 Loki : Like Prometheus, but for logs
|
||||
ELK/EFK 作为日志方案虽然流行,但是也有个众所周知的弱点:占用资源过多,无论是内存还是磁盘存储。究其原因是因为 Elasticsearch 对其中数据做了全文索引,以便于实现快速的全文搜索。对于日志数据来说,很多时候全文索引并不是必要的。除此之外,Elasticsearch 是由 Java 语言开发,相比云原生领域的开发语言 Go,无论是运行效率还是资源占用都处于下风。
|
||||
云原生领域一直期待有一款由 Go 开发的日志管理软件,Loki 应运而生。Loki 自 2018 年 12 月发布短短 10 个月的时间,Github 上的 Star 数已经达到了 7000+。Loki 由开发 Grafana 的 Grafana Labs 开发,Grafana Labs 中有著名云原生监控软件 Prometheus 的开发者并且提供了云端的 Prometheus 监控服务 Cortex , 而 Loki 正是受到 Prometheus 的启发而开发出来的。因此具有许多和 Prometheus 类似的特性比如:与 Kubernetes 紧密集成、与 Prometheus 共享 Label,与 Prometheus 有相似查询语法的查询语言 LogQL,与 Prometheus 类似的查询函数等,甚至同样可以在 Grafana 里直接查看检索 Loki 的日志数据。除此之外 Loki 的还与 Cortex 共享了很多组件,非常容易水平扩展。
|
||||
|
||||
Loki 最重要的特性是存储成本低,资源占用少。Loki 做到这点是在设计之初就有意解决 Elasticsearch 占用资源多的缺点,通过只对 Label 等元数据进行索引,对日志流数据进行压缩存储,并在用户搜索日志文本时通过索引的 Label 缩小查询范围后,实时解压并用类似 grep 一样的机制对日志流数据进行过滤。如下图所示,Loki 的组件包括收集数据的 Agent Promtail , 接收数据的 Distributor, 缓存数据以便批量写入的 Ingester,用于查询数据的 Querier ,这些组件均可以根据负载水平扩展并实现高可用。
|
||||
|
||||

|
||||
|
||||

|
||||
Loki 架构(来源于 Grafana Labs 官方博客)
|
||||
|
||||
如下图所示,Loki 的实现了索引和日志数据块分别用不同的存储介质存储,索引可以存到 Cassandra, BoltDB 等;日志数据块可以存到本地磁盘或者云端对象存储或者兼容 S3 协议的 Minio。 如此在实现海量日志数据的低成本存储的同时,还能够满足用户快速查询日志的需求。
|
||||
|
||||

|
||||
|
||||
Loki 存储(来源于 Grafana Labs 官方博客)
|
||||
|
||||
作为云原生时代出现的日志解决方案, Loki 以其低成本、可扩展和高可用以及与 Kubernetes, Prometheus 紧密集成等特性迅速获得了巨大关注,有望获得 Kubernetes 上如同 Prometheus 一样的地位,成为云原生领域日志管理的首选方案。
|
||||
|
||||
## 展望
|
||||
|
||||
Kubernetes 的架构为日志的集中管理提供了可能。而陆续涌现的优秀的日志管理方案使得用户可以更好的挖掘日志数据的价值,获得更好的可观察性。KubeSphere 作为开源的 Kubernetes 发行版,将在完善现有 Kubernetes 日志解决方案的基础上(比如多集群日志管理、日志告警等),持续关注受 Prometheus 启发而开发出来的 Loki 并将积极参与到其开发中,争取将业界最领先的日志管理技术集成到 KubeSphere 提供给用户使用。
|
||||
|
||||
## 相关资料
|
||||
|
||||
KubeSphere 多租户日志管理在 2019 年 6 月份上海的 KubeCon 上以 “[Effective Logging In Multi Tenant Kubernetes Environment](https://static.sched.com/hosted_files/kccncosschn19eng/39/Effective%20Logging%20in%20Multi-Tenant%20Kubernetes%20Environment.pdf)” 的主题进行过分享,相关的 PPT 资料大家可以在 [CNCF 官网](https://kccncosschn19eng.sched.com/event/NroE/effective-logging-in-multi-tenant-kubernetes-environment-benjamin-huo-dan-ma-beijing-yunify-technology-co-ltd) 找到。
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,128 @@
|
|||
---
|
||||
title: 'Porter-面向裸金属环境的 Kubernetes 开源负载均衡器'
|
||||
type: 'KubeCon'
|
||||
author: '宋雪涛'
|
||||
createTime: '2019-06-24'
|
||||
snapshot: 'https://pek3b.qingstor.com/kubesphere-docs/png/20190930095713.png'
|
||||
---
|
||||
|
||||
我们知道,在 Kubernetes 集群中可以使用 “LoadBalancer” 类型的服务将后端工作负载暴露在外部。云厂商通常为 Kubernetes 提供云上的 LB 插件,但这需要将集群部署在特定 IaaS 平台上。然而,许多企业用户通常都将 Kubernetes 集群部署在裸机上,尤其是用于生产环境时。而且对于本地裸机集群,Kubernetes 不提供 LB 实施。Porter 是一个专为裸金属 Kubernetes 集群环境而设计的开源的负载均衡器项目,可完美地解决此类问题。
|
||||
|
||||
## Kubernetes 服务介绍
|
||||
在 Kubernetes 集群中,网络是非常基础也非常重要的一部分。对于大规模的节点和容器来说,要保证网络的连通性、网络转发的高效,同时能做的 IP 和 Port 自动化分配和管理,并提供给用户非常直观和简单的方式来访问需要的应用,这是非常复杂且细致的设计。
|
||||
|
||||
Kubernetes 本身在这方面下了很大的功夫,它通过 CNI、Service、DNS、Ingress 等一系列概念,解决了服务发现、负载均衡的问题,也大大简化了用户的使用和配置。其中的 Service 是 Kubernetes 微服务的基础,Kubernetes 是通过 kube-proxy 这个组件来实现服务的。kube-proxy 运行在每个节点上,监听 API Server 中服务对象的变化,通过管理 iptables 来实现网络的转发。用户可以创建多种形式的 Service,比如基于 Label Selector 、Headless 或者 ExternalName 的 Service,kube-proxy 会为 Service 创建一个虚拟的 IP(即 Cluster IP),用于集群内部访问服务。
|
||||
## 暴露服务的三种方式
|
||||
如果需要从集群外部访问服务,即将服务暴露给用户使用,Kubernetes Service 本身提供了两种方式,一种是 NodePort,另外一种是 LoadBalancer。另外 Ingress 也是一种常用的暴露服务的方式。
|
||||
### NodePort
|
||||
如果将服务的类型设置为 NodePort,kube-proxy 就会为这个服务申请一个 30000 以上的端口号(默认情况下),然后在集群所有主机上配置 IPtables 规则,这样用户就能通过集群中的任意节点加上这个分配的端口号访问服务了,如下图
|
||||
|
||||

|
||||
|
||||
NodePort 是最方便的暴露服务的方式,缺点也很明显:
|
||||
|
||||
1. 基于 SNAT 进行访问,Pod 无法看到真正的 IP。
|
||||
2. NodePort 是将集群中的一个主机作为跳板访问后端服务,所有的流量都会经过跳板机,很容易造成性能瓶颈和单点故障,难以用于生产环境。
|
||||
3. NodePort 端口号一般都是用大端口,不容易记忆。
|
||||
|
||||
NodePort 设计之初就不是用于生产环境暴露服务的方式,所以默认端口都是一些大端口。
|
||||
### LoadBalancer
|
||||
LoadBalancer 是 Kubernetes 提倡的将服务暴露给外部的一种方式。但是这种方式需要借助于云厂商提供的负载均衡器才能实现,这也要求了 Kubernetes 集群必须在云厂商上部署。LoadBalancer 的原理如下:
|
||||
|
||||

|
||||
|
||||
LoadBalancer 通过云厂商的 LB 插件实现,LB 插件基于 Kubernetes.io/cloud-provider 这个包实现,这个包会自动选择合适的后端暴露给 LB 插件,然后 LB 插件由此创建对应的负载均衡器,网络流量在云服务端就会被分流,就能够避免 NodePort 方式的单点故障和性能瓶颈。LoadBalancer 是 Kubernetes 设计的对外暴露服务的推荐方式,但是这种方式仅仅限于云厂商提供的 Kubernetes 服务上,对于物理部署或者非云环境下部署的 Kubernetes 集群,这一机制就存在局限性而无法使用。
|
||||
### Ingress
|
||||
Ingress 并不是 Kubernetes 服务本身提供的暴露方式,而是借助于软件实现的同时暴露多个服务的一种类似路由器的插件。Ingress 通过域名来区分不同服务,并且通过 annotation 的方式控制服务对外暴露的方式。其原理如下图:
|
||||
|
||||

|
||||
|
||||
相比于 NodePort 和 LoadBalancer,Ingress 在企业业务场景中应该是使用的最多的,原因有:
|
||||
|
||||
1. 相比 kube-proxy 的负载均衡,Ingress controller 能够实现更多的功能,诸如流量控制,安全策略等。
|
||||
2. 基于域名区分服务,更加直观。也不需要用到 NodePort 中的大端口号。
|
||||
|
||||
但是在实际场景中,Ingress 也需要解决下面的一些问题:
|
||||
|
||||
1. Ingress 多用于 L7,对于 L4 的支持不多。
|
||||
2. 所有的流量都会经过 Ingress Controller,需要一个 LB 将 Ingress Controller 暴露出去。
|
||||
|
||||
第一个问题,Ingress 也可以用于 L4,但是对于 L4 的应用,Ingress 配置过于复杂,最好的实现就是直接用 LB 暴露出去。 第二个问题,测试环境可以用 NodePort 将 Ingress Controller 暴露出去或者直接 hostnetwork,但也不可避免有单点故障和性能瓶颈,也无法很好的使用 Ingress-controller 的 HA 特性。
|
||||
|
||||
## Porter 介绍
|
||||
|
||||
Porter 是 KubeSphere 团队研发的一款开源的基于 BGP 协议的云原生负载均衡器插件。它的主要特性有:
|
||||
|
||||
1. 基于路由器 ECMP 的负载均衡
|
||||
2. 基于 BGP 路由动态配置
|
||||
3. VIP 管理
|
||||
|
||||
Porter 的所有代码和文档已在 [GitHub](https://github.com/kubesphere/porter) 开源,欢迎大家关注(Star)和使用。
|
||||
## 如何快速部署使用
|
||||
|
||||
Porter 目前已在如下两种环境下进行过部署和测试,并将部署测试与使用步骤的详细文档记录在 GitHub,大家可以通过以下链接查看,建议大家动手部署实践一下。
|
||||
|
||||
- [在物理部署的 Kubernetes 集群上部署使用 Porter](https://github.com/kubesphere/porter/blob/master/doc/deploy_baremetal.md)
|
||||
- [在青云 QingCloud 云平台用模拟路由器的方式测试](https://github.com/kubesphere/porter/blob/master/doc/simulate_with_bird.md)
|
||||
|
||||
## 原理
|
||||
|
||||
### ECMP
|
||||
|
||||
ECMP(Equal-Cost Multi-Pathing,等价路由)即存在多条到达同一个目的地址的相同开销的路径。当设备支持等价路由时,发往该目的 IP 或者目的网段的三层转发流量就可以通过不同的路径分担,实现网络的负载均衡,并在其中某些路径出现故障时,由其它路径代替完成转发处理,实现路由冗余备份功能。如下图:
|
||||

|
||||
|
||||
借助于路由器(虚拟路由器),对于某一个IP(对应服务的VIP),ECMP能根据一定的Hash算法从已知的路由中来选择下一跳(Pod),从而实现负载均衡的目的。一般的路由器(虚拟路由器)都具备 ECMP 的能力,Porter 要做的就是查询 Kubernetes API Server,将一个服务对应的后端 Pod 信息通过路由的方式发送给路由器。
|
||||
|
||||
### BGP
|
||||
在Kubernetes中,Pod可能会漂移,对于路由器来说,一个服务VIP的下一跳是不固定的,等价路由的信息会经常更新。实际上我们参考 Calico,使用了 BGP(Border Gateway Protocol,边界网关协议)实现路由的广播。BGP 是互联网上一个核心的去中心化自治路由协议,在互联网领域用的比较多。BGP 不同于其他路由协议,BGP使用了L4来保证路由信息的安全更新。同时由于BGP的去中心化特性,很容易搭建一个高可用路由层,保证网络的持续性。
|
||||

|
||||
|
||||
上图简单描述了Porter中BGP的实现原理。图中左下是一个两节点的Kubernetes集群,集群上方是有两个路由器leaf1和leaf2,leaf连接了核心交换机层spine,也同样是两个。最右侧是用户,对应的路由器是border,border也连接了spine,用户和Kubernetes服务器三层是可达的。 Kubernetes集群中创建了Service,并且使用了Porter,Porter为其分配了一个1.1.1.1的vip(或者手工指定),Porter通过BGP告知leaf1和leaf2,访问1.1.1.1的下一跳可以是node1,也可以是node2。leaf一层也会将这个信息告知spine,spine的BGP经过计算得知访问1.1.1.1的下一跳是leaf1,leaf2。按照同样的逻辑,这个路由也会更新到border,这样用户访问1.1.1.1的完整路径就有了。同时,由于这个图中每一层都有HA,所以外界访问1.1.1.1的路径就有2*2*2*2=16条,流量能够在整个网络中被分流,并且任意一层一个路由器宕机都不会影响用户的访问。
|
||||
|
||||
## 架构
|
||||
|
||||

|
||||
|
||||
Porter有两个组件,一个核心控制器和一个部署在所有节点上的agent。核心控制器主要功能有:
|
||||
1. 监控集群中的Service以及对应的endpoints,获取pod漂移信息
|
||||
2. VIP存储与分配
|
||||
3. 与外界建立BGP协议,广播路由
|
||||
|
||||

|
||||
|
||||
上图展示了 Porter 核心控制器的工作原理。
|
||||
|
||||
agent 则是一个轻量级组件,用于监控VIP资源,增加Iptables规则让外部流量能够访问VIP,默认情况下外部流量访问VIP会被内核中的Forward表Drop掉
|
||||
|
||||
## 面向云原生的设计
|
||||
|
||||
Porter 中的所有资源都是 CRD,包括 VIP、BGPPeer、BGPConfig 等。对于习惯 Kubectl 的用户使用 Porter 将非常友好。对于想定制 Porter 的高级用户,也可以直接调用 Kubernetes API 来二次开发。Porter 的核心控制器很快就会支持 HA,保证 Porter 的高可用性。
|
||||
|
||||
## 使用注意事项
|
||||
|
||||
用户访问 VIP 的流量会通过 BGP 到达 Kubernetes 集群中的某一个节点,因为 Porter广播路由的路也是node而不是具体的podip,podip外部不可访问,后续node到pod的路由是由kube-proxy维护的。如下图:
|
||||
|
||||

|
||||
|
||||
流量被 SNAT 之后随机发送给某一个pod。由于Porter会根据Service Endpoints的变化动态调整路由,确保下一跳的node节点一定有pod存在,所以我们可以更改kube-proxy这一个默认行为。在Service上设置ExternalTrafficPolicy=local,达到下面的效果:
|
||||
|
||||

|
||||
|
||||
这样做有两个好处:
|
||||
|
||||
1. SourceIP不会NAT
|
||||
2. 流量直接走本地,网络路径少一跳
|
||||
|
||||
## 未来计划
|
||||
|
||||
1. 支持其他简单路由协议
|
||||
2. 更加方便的VIP管理
|
||||
3. BGP的policy支持
|
||||
4. 在Kubesphere集成,提供UI
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,285 @@
|
|||
---
|
||||
title: "contribution"
|
||||
|
||||
css: "scss/contribution.scss"
|
||||
|
||||
section1:
|
||||
title: 'Community is the Soul of KubeSphere'
|
||||
content: 'Join the community to get help, get involved, or to get updates and KubeSphere news!'
|
||||
topImage: "images/contribution/contribution-top.jpg"
|
||||
|
||||
section2:
|
||||
topType:
|
||||
- name: 'Download'
|
||||
icon1: 'images/contribution/download.svg'
|
||||
icon2: 'images/contribution/37.png'
|
||||
children:
|
||||
- content: 'Download KubeSphere'
|
||||
link: ''
|
||||
- content: 'Quickstart'
|
||||
link: ''
|
||||
- content: 'Tutorial Videos'
|
||||
link: ''
|
||||
|
||||
- name: 'Contribute'
|
||||
icon1: 'images/contribution/contribute.svg'
|
||||
icon2: 'images/contribution/38.png'
|
||||
children:
|
||||
- content: 'Join the SIGs and WGs'
|
||||
link: ''
|
||||
- content: 'Improve the Docs'
|
||||
link: ''
|
||||
- content: 'Submit a Bug or Suggestion'
|
||||
link: ''
|
||||
|
||||
- name: 'Get in Touch'
|
||||
icon1: 'images/contribution/business.svg'
|
||||
icon2: 'images/contribution/39.png'
|
||||
children:
|
||||
- content: 'Join KubeSphere Slack'
|
||||
link: ''
|
||||
- content: 'Join the Mailing List'
|
||||
link: ''
|
||||
- content: 'Follow us on Twitter'
|
||||
link: ''
|
||||
|
||||
organization:
|
||||
topic: 'Community Organization'
|
||||
name: 'KubeSphere Community'
|
||||
icon: 'images/contribution/28.svg'
|
||||
topIcon: 'images/contribution/8.svg'
|
||||
type:
|
||||
- name: 'TOC'
|
||||
icon: 'images/contribution/toc.svg'
|
||||
|
||||
- name: 'Developer Group'
|
||||
icon: 'images/contribution/developer-group.svg'
|
||||
children:
|
||||
- name: 'Owner / Lead'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'Member'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'Contributor'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'User Research Group'
|
||||
icon: 'images/contribution/user.svg'
|
||||
children:
|
||||
- name: 'Champion'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
- name: 'Ambassador'
|
||||
content: 'A lead is also the member of the project who is an experienced and acrive reciewer of the project.'
|
||||
|
||||
|
||||
- name: 'Steering Committee'
|
||||
icon: 'images/contribution/steering.svg'
|
||||
|
||||
section3:
|
||||
interestGroup:
|
||||
title: 'Find Your Special Interest Group'
|
||||
content: 'SIGs are designed to let you can find everything you need in one place around a central topic. Find your commonality and join the SIG.'
|
||||
children:
|
||||
- name: 'Apps'
|
||||
icon: '/images/contribution/apps.svg'
|
||||
iconActive: '/images/contribution/apps-active.svg'
|
||||
content: 'App charts for the built-in App Store'
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Apps →'
|
||||
children:
|
||||
- icon: '/images/contribution/calicq1.jpg'
|
||||
- icon: '/images/contribution/calicq2.jpg'
|
||||
- icon: '/images/contribution/calicq3.jpg'
|
||||
|
||||
- name: 'App store'
|
||||
icon: '/images/contribution/app-store.svg'
|
||||
iconActive: '/images/contribution/app-store-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - App store →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Architecture'
|
||||
icon: '/images/contribution/architecture.svg'
|
||||
iconActive: '/images/contribution/architecture-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Architecture →'
|
||||
children:
|
||||
- icon: ''
|
||||
|
||||
- name: 'Cloud-Providers'
|
||||
icon: '/images/contribution/cloud-providers.svg'
|
||||
iconActive: '/images/contribution/cloud-providers-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Cloud-Providers →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Console (Front-end)'
|
||||
icon: '/images/contribution/console.svg'
|
||||
iconActive: '/images/contribution/console-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Console (Front-end) →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'DevOps'
|
||||
icon: '/images/contribution/dev-ops.svg'
|
||||
iconActive: '/images/contribution/dev-ops-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - DevOps →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: ' Docs'
|
||||
icon: '/images/contribution/docs.svg'
|
||||
iconActive: '/images/contribution/docs-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Docs →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Edge'
|
||||
icon: '/images/contribution/edge.svg'
|
||||
iconActive: '/images/contribution/edge-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Edge →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Installation'
|
||||
icon: '/images/contribution/installation.svg'
|
||||
iconActive: '/images/contribution/installation-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Installation →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Microservice'
|
||||
icon: '/images/contribution/microservice.svg'
|
||||
iconActive: '/images/contribution/microservice-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Microservice →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Multicluster'
|
||||
icon: '/images/contribution/multicluster.svg'
|
||||
iconActive: '/images/contribution/multicluster-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Multicluster →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Multitenancy'
|
||||
icon: '/images/contribution/multitenancy.svg'
|
||||
iconActive: '/images/contribution/multitenancy-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Multitenancy →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Network'
|
||||
icon: '/images/contribution/network.svg'
|
||||
iconActive: '/images/contribution/network-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Network →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Observability'
|
||||
icon: '/images/contribution/observability.svg'
|
||||
iconActive: '/images/contribution/observability-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Observability →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Release'
|
||||
icon: '/images/contribution/release.svg'
|
||||
iconActive: '/images/contribution/release-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Release →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Storage'
|
||||
icon: '/images/contribution/storage.svg'
|
||||
iconActive: '/images/contribution/storage-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Storage →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
- name: 'Testing'
|
||||
icon: '/images/contribution/testing.svg'
|
||||
iconActive: '/images/contribution/testing-active.svg'
|
||||
content: ''
|
||||
link: ''
|
||||
linkContent: 'Join SIG - Testing →'
|
||||
children:
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
- icon: ''
|
||||
|
||||
section4:
|
||||
involved:
|
||||
title: 'Get involved'
|
||||
children:
|
||||
- title: 'Be a Champion'
|
||||
icon: 'images/contribution/group-1.png'
|
||||
content: 'Join me tomorrow and start putting in the time to get your campaign ready with a landing page!'
|
||||
link: ''
|
||||
linkContent: 'Become a KubeSphere Champion →'
|
||||
|
||||
- title: 'Be a Member'
|
||||
icon: 'images/contribution/group-2.png'
|
||||
content: 'KubeSphere is 100% open source and driven by community,we appreciate contributions to our code and documentation!Significant contributions will earn you a contributor t-shirt.'
|
||||
link: ''
|
||||
linkContent: 'Become a KubeSphere Member →'
|
||||
---
|
||||
|
|
@ -12,6 +12,11 @@ weight: 2
|
|||
> - 若在云平台使用在线安装,可在安装前 [配置镜像加速器](https://kubesphere.com.cn/forum/d/149-kubesphere-v2-1-0),或通过调高带宽的方式来加快安装速度。
|
||||
|
||||
|
||||
### 测试
|
||||
|
||||
测试h3
|
||||
|
||||
|
||||
## 前提条件
|
||||
|
||||
建议关闭机器的防火墙,若未关闭防火墙则需要开放相关端口,参考 [需开放的端口](https://kubesphere.io/docs/v2.1/zh-CN/installation/port-firewall/)。
|
||||
|
|
|
|||
|
|
@ -0,0 +1,63 @@
|
|||
---
|
||||
title: "page1"
|
||||
|
||||
css: "scss/partner.scss"
|
||||
|
||||
section1:
|
||||
title: 'Join the Revolution,Partner with KubeSphere'
|
||||
content: 'We look forward to your joining KubeSphere partner to improve the ecosystem of both, and grow your business. KubeSphere provide resources and rights for partners to help them increase their expertise, deliver open source technology, and resell product.'
|
||||
topImage: 'images/partner/partner-top.jpg'
|
||||
|
||||
section2:
|
||||
title: 'Together, build partnership for success all over the world'
|
||||
content: 'KubeSphere partners play a critical role in KubeSphere go-to-market strategy. KubeSphere partners are located all over the world, we are looking forward to the global cooperation, your success is our success.'
|
||||
name1: 'USA'
|
||||
name2: 'European'
|
||||
name3: 'China'
|
||||
mapImage: 'images/partner/map.svg'
|
||||
|
||||
section3:
|
||||
title: 'Partner Types'
|
||||
tip: Request now →
|
||||
partnerType:
|
||||
- title: "App Providers"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, users can quickly deploy your application to Kubernetes using KubeSphere. Submit your application to KubeSphere Application Store now!"
|
||||
link: ""
|
||||
|
||||
- title: "Consulting"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, users can quickly deploy your application to Kubernetes using KubeSphere. Submit your application to KubeSphere Application Store now!"
|
||||
link: ""
|
||||
|
||||
- title: "Cloud Providers"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, users can quickly deploy your application to Kubernetes using KubeSphere. Submit your application to KubeSphere Application Store now!"
|
||||
link: ""
|
||||
|
||||
- title: "Go-To-Market"
|
||||
content: "KubeSphere Application Store is a great place to showcase your application, users can quickly deploy your application to Kubernetes using KubeSphere. Submit your application to KubeSphere Application Store now!"
|
||||
link: ""
|
||||
|
||||
section4:
|
||||
title: 'Featured Partners'
|
||||
content: 'KubeSphere is trusted by various enterprises and organizations to the innovators driving the future of software.'
|
||||
featuredPartnerList:
|
||||
- icon: "images/partner/partner1.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner2.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner3.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner4.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner5.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner6.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
|
||||
- icon: "images/partner/partner7.jpg"
|
||||
partnerType: "Go-To-Market"
|
||||
---
|
||||
|
|
@ -1,4 +1,34 @@
|
|||
---
|
||||
title: "About"
|
||||
|
||||
|
||||
css: "scss/projects.scss"
|
||||
name: Open Source Projects
|
||||
groups:
|
||||
- name: Container Platform
|
||||
children:
|
||||
- title: KubeSphere
|
||||
icon: 'images/kubesphere.svg'
|
||||
link: ''
|
||||
description: 基于 Kubernetes 之上构建的以应用为中心的多租户容器平台,支持部署运行在任何基础设施之上,提供简单易用的操作界面以及向导式 UI,旨在解决 Kubernetes 的存储、网络、安全与易用性等痛点。
|
||||
|
||||
- name: App Management
|
||||
children:
|
||||
- title: OpenPitrix
|
||||
icon: ''
|
||||
link: ''
|
||||
description: 开源的多云应用管理平台,用来在多云环境下打包、部署和管理不同类型的应用,包括传统应用、微服务应用以及 Serverless 应用等,其中云平台包括 AWS、Kubernetes、QingCloud、VMWare。
|
||||
|
||||
- name: Storage Plugins
|
||||
children:
|
||||
- title: QingStor-CSI
|
||||
icon: ''
|
||||
link: ''
|
||||
description: QingStor CSI 插件实现 CSI 接口,使容器编排平台(如 Kubernetes)能够使用 NeonSAN 分布式存储的资源。目前,QingStor CSI 插件实现了存储卷管理和快照管理功能,并在 Kubernetes v1.12 环境中通过了 CSI Sanity 测试。
|
||||
|
||||
- title: QingCloud-CSI
|
||||
icon: ''
|
||||
link: ''
|
||||
description: QingCloud CSI 插件实现了 CSI 接口,并使容器管理平台能够使用 QingCloud 云平台的块存储资源。目前,QingCloud CSI 插件已经在 Kubernetes v1.14/v1.15 环境中通过了 CSI 测试。
|
||||
|
||||
---
|
||||
|
|
@ -1,4 +0,0 @@
|
|||
---
|
||||
title: "second"
|
||||
|
||||
---
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
---
|
||||
title: "page1"
|
||||
|
||||
css: "scss/videos.scss"
|
||||
---
|
||||
|
|
@ -2,37 +2,50 @@ footer:
|
|||
list:
|
||||
- title: Products
|
||||
list:
|
||||
- content: Community Edition
|
||||
link: /en
|
||||
- content: QKE
|
||||
link: https://appcenter.qingcloud.com/apps/app-cmgbd5k2/KubeSphere%C2%AE%EF%B8%8F%EF%BC%88QKE%EF%BC%89#Introduction
|
||||
- content: Commercial Service
|
||||
link: https://kubesphere.qingcloud.com/
|
||||
- title: Related Products
|
||||
list:
|
||||
- content: AppCenter
|
||||
link: https://appcenter.qingcloud.com/
|
||||
- content: NeonSAN
|
||||
link: https://www.qingcloud.com/products/qingstor-neonsan/
|
||||
- content: QingCloud
|
||||
link: https://www.qingcloud.com/products/qingstor-neonsan/
|
||||
- content: KubeSphere
|
||||
link: ''
|
||||
|
||||
- content: Porter
|
||||
link: ''
|
||||
|
||||
- content: OpenPitrix
|
||||
link: https://openpitrix.io/
|
||||
link: ''
|
||||
|
||||
- content: Fluentbit-Operator
|
||||
link: ''
|
||||
|
||||
- content: KubeKey
|
||||
link: ''
|
||||
|
||||
- content: Notification Manager
|
||||
link: ''
|
||||
- title: Resources
|
||||
list:
|
||||
- content: Projects
|
||||
link:
|
||||
- content: Blogs
|
||||
link:
|
||||
- content: KubeCon & QCon
|
||||
link:
|
||||
- content: Videos
|
||||
link:
|
||||
- title: KubeSphere Docs
|
||||
list:
|
||||
- content: Introduction
|
||||
link: https://kubesphere.io/docs/v2.1/zh-CN/introduction/intro/
|
||||
link: ''
|
||||
- content: Installation
|
||||
link: https://kubesphere.io/docs/v2.1/zh-CN/installation/intro/
|
||||
link: ''
|
||||
- content: Tutorial
|
||||
link: https://kubesphere.io/docs/v2.1/zh-CN/quick-start/quick-start-guide/
|
||||
link: ''
|
||||
- content: API Documentation
|
||||
link: https://kubesphere.io/docs/v2.1/zh-CN/api-reference/api-docs/
|
||||
- title: About
|
||||
link: ''
|
||||
- title: Community
|
||||
list:
|
||||
- content: News
|
||||
link: https://activity.qingcloud.com/event/kubesphere2019/
|
||||
- content: Contact
|
||||
link: https://www.qingcloud.com/contactus
|
||||
- content: Careers
|
||||
link: https://www.qingcloud.com/jobs
|
||||
- content: Contribution
|
||||
link:
|
||||
- content: Case Studies
|
||||
link:
|
||||
- content: Partners
|
||||
link:
|
||||
- content: Roadmap
|
||||
link:
|
||||
|
|
@ -1,113 +0,0 @@
|
|||
home:
|
||||
list:
|
||||
- icon: "images/easy.svg"
|
||||
title: "Easy"
|
||||
content: "A CNCF certified Kubernetes platform, 100% open source, built and improved by the community. KubeSphere can be deployed on a Kubernetes cluster or Linux machines, supports online and air-gapped installation"
|
||||
|
||||
- icon: "images/flexible.svg"
|
||||
title: "Flexible"
|
||||
content: "Delivers DevOps, service mesh, observability, application management, multi-tenancy, storage and networking management in an unified platform. These functionalities are loosely coupled with the platform since they are pluggable and optional. Other tools are easy to integrate and play"
|
||||
|
||||
- icon: "images/efficient.svg"
|
||||
title: "Efficient"
|
||||
content: "KubeSphere delivers consolidated views while integrating a wide breadth of ecosystem tools around Kubernetes and offers consistent user experience to reduce complexity, enabling teams to easily get started with cloud native stack"
|
||||
|
||||
appList:
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
|
||||
|
||||
|
|
@ -1,112 +0,0 @@
|
|||
home:
|
||||
list:
|
||||
- icon: "images/easy.svg"
|
||||
title: "易用"
|
||||
content: "面向开发、测试、运维友好的 UI,向导式用户体验,通过 KubeSphere 控制台将 Kubernetes 的能力以一种极简的方式输送给用户。"
|
||||
|
||||
- icon: "images/flexible.svg"
|
||||
title: "灵活"
|
||||
content: "支持开源的存储与网络插件,如用户对网络和存储有更高要求,可选用 <a href=\"//www.qingcloud.com\" target=\"_blank\" rel=\"noopener noreferrer\">青云 QingCloud</a> 作为底层平台,可以使用商业化的网络和存储解决方案。"
|
||||
|
||||
- icon: "images/efficient.svg"
|
||||
title: "高效"
|
||||
content: "无基础设施依赖,无 Kubernetes 依赖,支持跨物理机、虚拟机、云平台部署,可以纳管不同版本、不同厂商的 Kubernetes 集群。"
|
||||
|
||||
|
||||
appList:
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
- icon: "images/hadoop.svg"
|
||||
name: "hadoop"
|
||||
version: "1.0.7"
|
||||
content: "The Apache Hadoop software library is a framework that allows for the distributed processing of large data sets across clusters of computers using simple programming models."
|
||||
34
i18n/en.yaml
34
i18n/en.yaml
|
|
@ -1,33 +1,21 @@
|
|||
- id: home
|
||||
translation: Home
|
||||
- id: activities
|
||||
translation: Activities
|
||||
- id: meet
|
||||
translation: See a video for quick preview of KubeSphere
|
||||
- id: introduction1
|
||||
translation: The Kubernetes Platform,
|
||||
|
||||
- id: introduction2
|
||||
translation: tailored to the DevOps teams
|
||||
translation: KubeSphere®️ 2020 All Rights Reserved.
|
||||
- id: introduction3
|
||||
translation: —— KubeSphere Container Platform
|
||||
translation: Published at
|
||||
- id: introduction4
|
||||
translation: KubeSphere is a distributed operating system providing cloud native stack with Kubernetes as its kernel, and aims to be plug-and-play architecture for third-party applications seamless integration to boost its ecosystem.
|
||||
- id: install
|
||||
translation: Get KubeSphere
|
||||
- id: install
|
||||
translation: Get KubeSphere
|
||||
translation: KubeCon & QCon
|
||||
- id: introduction5
|
||||
translation: One Platform for full-stack solutions
|
||||
translation: Subscribe
|
||||
- id: introduction6
|
||||
translation: KubeSphere is also a multi-tenant enterprise-grade container platform with full-stack automated IT operation and streamlined DevOps workflows. It provides developer-friendly wizard web UI, helping enterprises to build out a more robust and feature-rich platform, which includes most common functionalities needed for enterprise Kubernetes strategy.
|
||||
- id: management
|
||||
translation: Complete application lifecycle management
|
||||
translation: Please enter your email address
|
||||
- id: introduction7
|
||||
translation: Based on OpenPitrix, it provides application-wide lifecycle management, including development, testing, release, upgrade, and off-the-shelf application-related operations, multi application repositories management, one-click deployment of applications, and advanced functions such as version control, billing, and auditing.
|
||||
translation: Receive the latest news, articles and updates from KubeSphere
|
||||
- id: introduction8
|
||||
translation: Welcome to the KubeSphere Documentation
|
||||
- id: introduction9
|
||||
translation: We will introduce the services and features of KubeSphere with clear and concise pictures and texts as far as possible.
|
||||
|
||||
|
||||
|
||||
- id: introduction10
|
||||
translation: Open Source Community
|
||||
- id: introduction11
|
||||
translation: KubeSphere is committed to the open source contribution of cloud native technology, enriching the ecology of the open source community
|
||||
|
|
|
|||
30
i18n/zh.yaml
30
i18n/zh.yaml
|
|
@ -1,28 +1,8 @@
|
|||
- id: home
|
||||
translation: 首页
|
||||
- id: activities
|
||||
translation: 动态
|
||||
- id: meet
|
||||
translation: 回顾 KubeSphere 社区年度 Meetup
|
||||
- id: introduction1
|
||||
translation: KubeSphere,
|
||||
- id: introduction2
|
||||
translation: 以应用为中心的容器平台
|
||||
- id: introduction3
|
||||
translation: 完全开源,加速企业云原生转型
|
||||
- id: introduction4
|
||||
translation: KubeSphere 帮助企业在云、虚拟化及物理机等任何环境中快速构建、部署和运维基于 Kubernetes 的容器架构,轻松实现微服务治理、多租户管理、DevOps 与 CI/CD、监控日志告警、应用商店、大数据、以及人工智能等业务场景。
|
||||
- id: install
|
||||
translation: 获取 KubeSphere
|
||||
- id: introduction5
|
||||
translation: 什么是 KubeSphere ?
|
||||
- id: introduction6
|
||||
translation: KubeSphere 是一款面向云原生设计的开源项目,在目前主流容器调度平台 Kubernetes 之上构建的分布式多租户容器管理平台,提供简单易用的操作界面以及向导式操作方式,在降低用户使用容器调度平台学习成本的同时,极大降低开发、测试、运维的日常工作的复杂度。
|
||||
- id: management
|
||||
translation: 完整的应用生命周期管理
|
||||
- id: introduction7
|
||||
translation: 基于 OpenPitrix 提供应用的全生命周期管理,包含开发、测试、发布、升级,下架等应用相关操作,多应用仓库管理,一键部署应用,并可实现版本控制、计费、审计等高级功能。
|
||||
- id: introduction8
|
||||
translation: 欢迎使用 KubeSphere 文档
|
||||
- id: introduction9
|
||||
translation: 欢迎阅读 KubeSphere 文档,我们尽可能以清晰简明的图文,介绍 KubeSphere 各项服务及使用方法。
|
||||
translation: 欢迎阅读 KubeSphere 文档,我们尽可能以清晰简明的图文,介绍 KubeSphere 各项服务及使用方法。
|
||||
- id: introduction10
|
||||
translation: 开源社区
|
||||
- id: introduction11
|
||||
translation: 分享云原生领域最前沿的技术干货与开发实践文章,以及 KubeSphere 产品最新的动态。
|
||||
|
|
|
|||
|
|
@ -0,0 +1,6 @@
|
|||
{{ define "main" }}
|
||||
|
||||
<section>
|
||||
<h2>页面不存在</h2>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -4,7 +4,6 @@
|
|||
|
||||
<body>
|
||||
{{- partial "header.html" . -}}
|
||||
<img src="{{ .Site.Params.bg1 | absURL }}" alt="bg" class="bg-1">
|
||||
<section class="main-section">
|
||||
{{- block "main" . }}{{- end }}
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
{{ define "main" }}
|
||||
|
||||
{{- partial "openSource.html" . -}}
|
||||
<section id="home">
|
||||
<h2>内容</h2>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -0,0 +1,70 @@
|
|||
{{ define "main" }}
|
||||
<section class="section-1">
|
||||
{{ with .Params.section1 }}
|
||||
<img src="{{ .topImage | absURL }}" alt="">
|
||||
<div class="title-div">
|
||||
<h1>{{ .title }}</h1>
|
||||
<p>{{ .content }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class="section-2">
|
||||
{{ with .Params.section2 }}
|
||||
{{ $tip := .tip }}
|
||||
<ul class="cases-ul">
|
||||
{{ range .caseList }}
|
||||
<li>
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
<p>{{ .content }}</p>
|
||||
<div>
|
||||
<a href="">{{ $tip }}</a>
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class="section-3">
|
||||
{{ with .Params.section3 }}
|
||||
<h2>{{ .title }}</h2>
|
||||
<div>
|
||||
<ul id="case-group">
|
||||
<li class="active">{{ .tip }}</li>
|
||||
{{ range .caseType }}
|
||||
<li data-name="{{ .name }}">{{ .name }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<ul id="case-children">
|
||||
{{ range .caseType }}
|
||||
{{ $name := .name }}
|
||||
{{ range .children }}
|
||||
<li data-name="{{ $name }}">
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
<script>
|
||||
$('#case-group li').click(function() {
|
||||
$("#case-group li").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
var name = $(this).data("name")
|
||||
if (name) {
|
||||
$("#case-children li").each(function(item) {
|
||||
if ($(this).data("name") !== name) {
|
||||
$(this).hide()
|
||||
} else {
|
||||
$(this).show()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
$("#case-children li").show()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{{ end }}
|
||||
|
|
@ -1,6 +1,34 @@
|
|||
{{ define "main" }}
|
||||
|
||||
<section id="home">
|
||||
<h2>内容</h2>
|
||||
{{- partial "openSource.html" . -}}
|
||||
<section>
|
||||
<div class="tab-content">
|
||||
<div class="content">
|
||||
<ul>
|
||||
{{ $viewDetail := .Params.viewDetail }}
|
||||
{{ range .Params.list }}
|
||||
<li>
|
||||
<div class='top-div'>
|
||||
<img class='left-img' src="{{ .bg | absURL }}" alt="">
|
||||
<h3>{{ .name }}</h3>
|
||||
<p>{{ .content }}</p>
|
||||
<img class='right-img' src="{{ .icon | absURL }}" alt="">
|
||||
</div>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>
|
||||
<h4><a href="{{ .link }}">{{ .name }}</a></h4>
|
||||
<div class='author'>{{ .author }}</div>
|
||||
<p>{{ .summary }}</p>
|
||||
<div class='line'></div>
|
||||
<a href="{{ .link }}"><button>{{ $viewDetail }}</button></a>
|
||||
<img src="{{ .image | absURL }}" alt="">
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<!DOCTYPE html>
|
||||
<html lang="{{ with .Site.LanguageCode }}{{ . }}{{ else }}en-US{{ end }}">
|
||||
{{- partial "head.html" . -}}
|
||||
|
||||
{{ $style := resources.Get "scss/content.scss" | toCSS | minify | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $style.Permalink }}">
|
||||
|
||||
{{ $style := resources.Get "scss/markdown.scss" | toCSS | minify | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $style.Permalink }}">
|
||||
|
||||
<body>
|
||||
{{- partial "header.html" . -}}
|
||||
<section class="main-section">
|
||||
<div>
|
||||
<div class='breadcrumb'>
|
||||
<span>{{ i18n "introduction4"}} ></span>
|
||||
<span>{{ .Title }}</span>
|
||||
</div>
|
||||
<div class='main-div'>
|
||||
<div class='author'>{{ .Params.author }}</div>
|
||||
<div class='date'>{{ i18n "introduction3" }}:{{ .Params.date }}</div>
|
||||
<h1>{{ .Title }}</h1>
|
||||
<div class='content'>
|
||||
<div class='md-body'>
|
||||
{{ .Content }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='aside'>
|
||||
<div class='title'>Table of Contents</div>
|
||||
<div class='tabs'>{{ .TableOfContents }}</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{- partial "footer.html" . -}}
|
||||
</body>
|
||||
|
||||
</html>
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
{{ define "main" }}
|
||||
|
||||
<section class="section-1">
|
||||
{{ with .Params.section1 }}
|
||||
<img src="{{ .topImage | absURL }}" alt="">
|
||||
<div class="title-div">
|
||||
<h1>{{ .title }}</h1>
|
||||
<p>{{ .content }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class="section-2">
|
||||
{{ with .Params.section2 }}
|
||||
<div>
|
||||
<ul>
|
||||
{{ range .topType }}
|
||||
<li>
|
||||
<div class='title'>
|
||||
<img src="{{ .icon1 | absURL }}" alt="">
|
||||
<p>{{ .name }}</p>
|
||||
</div>
|
||||
<div class='line'></div>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>
|
||||
<a href="{{ .link }}">{{ .content }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<img class='bottom-img' src="{{ .icon2 | absURL }}" alt="">
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<div class='organization-div'>
|
||||
{{ with .organization }}
|
||||
{{ $topIcon := .topIcon }}
|
||||
<h2>{{ .topic }}</h2>
|
||||
<div>
|
||||
<div class='top-div'>{{ .name }}</div>
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
<ul>
|
||||
{{ range $index, $element := .type }}
|
||||
<li>
|
||||
<div>
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
<span>{{ .name }}</span>
|
||||
</div>
|
||||
{{ if .children }}
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li class="">
|
||||
<img src="{{ $topIcon | absURL }}" alt="">
|
||||
<div>{{ .name }}</div>
|
||||
{{ if eq $index 1}}
|
||||
<p class='left'>{{ .content }}</p>
|
||||
{{ else if eq $index 2}}
|
||||
<p class='right'>{{ .content }}</p>
|
||||
{{ end }}
|
||||
<p></p>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class='section-3'>
|
||||
{{ with .Params.section3.interestGroup }}
|
||||
<h2>{{ .title }}</h2>
|
||||
<p>{{ .content }}</p>
|
||||
<ul class='interest-ul' data-index='0' data-length='{{ len .children }}'>
|
||||
{{ range $index, $element := .children }}
|
||||
{{ $active := "" }}
|
||||
{{ $icon := $element.icon }}
|
||||
{{ if eq $index 0 }}
|
||||
{{ $active = "active" }}
|
||||
{{ $icon = $element.iconActive }}
|
||||
{{ end }}
|
||||
<li class="{{ $active }}" data-info='{{ . | jsonify }}' data-index='{{ $index }}'>
|
||||
<img src="{{ $icon | absURL }}" alt="">
|
||||
<p>{{ $element.name }}</p>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<div class='bottom-div'>
|
||||
{{ with $first := index .children 0}}
|
||||
<div>
|
||||
<div class='btn-change btn-left' data-num='-1'></div>
|
||||
<img class='bottom-img' src="{{ .iconActive | absURL }}" alt="">
|
||||
<div class='btn-change btn-right' data-num='1'></div>
|
||||
</div>
|
||||
<a href="{{ .link }}">{{ .linkContent }}</a>
|
||||
<p>{{ .content }}</p>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class='section-4'>
|
||||
{{ with .Params.section4.involved }}
|
||||
<h2>{{ .title }}</h2>
|
||||
<div>
|
||||
{{ range .children}}
|
||||
<div>
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
<h3>{{ .title }}</h3>
|
||||
<p>{{ .content }}</p>
|
||||
<div>
|
||||
<a href="">{{ .linkContent }}</a>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<script>
|
||||
var bindChangeIcon = function() {
|
||||
var length = Number($('.interest-ul').data('length'))
|
||||
$('.btn-change').click(function(event) {
|
||||
var index = Number($('.interest-ul').data('index'))
|
||||
var count = Number($(this).data('num'))
|
||||
var nextIndex = (index + count + length) % length
|
||||
$('.interest-ul').data('index', nextIndex)
|
||||
changeByIndex(nextIndex)
|
||||
})
|
||||
}
|
||||
|
||||
var bindIconClick = function() {
|
||||
$('.interest-ul li').click(function(event) {
|
||||
var nextIndex = $(this).data('index')
|
||||
$('.interest-ul').data('index', nextIndex)
|
||||
changeByIndex(nextIndex)
|
||||
})
|
||||
}
|
||||
|
||||
var changeByIndex = function(index) {
|
||||
changeCurrentElement()
|
||||
var nextElement = $('.interest-ul li').eq(index)
|
||||
changeNextElement(nextElement)
|
||||
}
|
||||
|
||||
var changeCurrentElement = function() {
|
||||
var currentElement = $('.section-3 .active')
|
||||
var info = currentElement.data('info')
|
||||
var currentElementImage = currentElement.find('img')
|
||||
currentElementImage.attr({ src: info.icon })
|
||||
currentElement.removeClass('active')
|
||||
}
|
||||
|
||||
var changeNextElement = function(nextElement) {
|
||||
var info = nextElement.data('info')
|
||||
var nextElementImage = nextElement.find('img')
|
||||
nextElementImage.attr({ src: info.iconActive })
|
||||
nextElement.addClass('active')
|
||||
changeBottomContentByInfo(info)
|
||||
}
|
||||
|
||||
var changeBottomContentByInfo = function(info) {
|
||||
var bottomDiv = $('.section-3 .bottom-div')
|
||||
bottomDiv.find('.bottom-img').attr({ src: info.iconActive });
|
||||
bottomDiv.find('a').text(info.linkContent).attr({ href: info.link })
|
||||
bottomDiv.find('p').text(info.content);
|
||||
}
|
||||
|
||||
bindIconClick()
|
||||
bindChangeIcon()
|
||||
</script>
|
||||
{{ end }}
|
||||
|
|
@ -1,135 +1,189 @@
|
|||
{{ define "main" }}
|
||||
<section>
|
||||
<div class="section-div-1">
|
||||
<div class="banner-title">
|
||||
<div class="banner-activities">
|
||||
<span class="banner-tag">{{ i18n "activities" }}</span>
|
||||
<a href="https://kubesphere.io/docs/introduction/what-is-kubesphere/#video-on-youtube" target="_blank" rel="noopener noreferrer" title="See a video for quick preview of KubeSphere">{{ i18n "meet" }}</a>
|
||||
</div>
|
||||
<div class="h1">{{ i18n "introduction1" }}<br>{{ i18n "introduction2" }}</div>
|
||||
<div class="banner-sub-title">{{ i18n "introduction3" }}</div>
|
||||
<p>{{ i18n "introduction4" }}</p>
|
||||
<div class="banner-links">
|
||||
<a href="/install/">
|
||||
<button class="install-button">
|
||||
{{ i18n "install" }}
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<div class="banner-snapshot">
|
||||
<img src="{{ .Site.Params.img1 | absURL }}" alt="">
|
||||
<img src="{{ .Site.Params.img2 | absURL }}" alt="" class="banner-snapshot-sub">
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
{{ $data := index .Site.Data .Site.Language.Lang }}
|
||||
<section>
|
||||
<div class="section-div-2">
|
||||
<div class="h1">{{ i18n "introduction5" }}</div>
|
||||
<p>{{ i18n "introduction6" }}</p>
|
||||
<div class="feature-cards">
|
||||
{{ with $data.home.home }}
|
||||
{{ range .list }}
|
||||
<div class="feature-card">
|
||||
<img src="{{ .icon | relURL }}" alt="{{ .title }}">
|
||||
<div class="h2">{{ .title }}</div>
|
||||
<p>{{ .content | safeHTML }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
<section class='section-1'>
|
||||
{{ with .Params.section1 }}
|
||||
<img class='img1' src="images/home/52.svg" alt="">
|
||||
<img class='img2' src="/images/home/12-3.svg" alt="">
|
||||
<img class='img3' src="/images/home/2.svg" alt="">
|
||||
<div>
|
||||
<div>
|
||||
<p class='p1'>{{ .title }}</p>
|
||||
<h1>{{ .topic }}</h1>
|
||||
<p class='p2'>{{ .content }}</p>
|
||||
<button class='btn1'>{{ .btnContent1 }}</button>
|
||||
<button class='btn2'>{{ .btnContent2 }}</button>
|
||||
</div>
|
||||
<img class='img1' src="/images/home/53.jpg" alt="">
|
||||
<img class='img2' src="/images/home/left.svg" alt="">
|
||||
<img class='img4' src="/images/home/46.svg" alt="">
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
<section>
|
||||
<div class="section-div-3">
|
||||
<div class="app-install-title">
|
||||
<img class="left" src="{{ .Site.Params.left | absURL }}" alt="">
|
||||
<img class="right" src="{{ .Site.Params.right | absURL }}" alt="">
|
||||
<div>{{ i18n "management" }}</div>
|
||||
<p>{{ i18n "introduction7" }}</p>
|
||||
</div>
|
||||
<div class="slider-wrapper">
|
||||
<div class="slider-repeat">
|
||||
{{ with $data.home.home }}
|
||||
{{ range .appList }}
|
||||
<div class="app">
|
||||
<div class="app-header">
|
||||
<img class="app-icon" src="{{ .icon | relURL }}" alt="">
|
||||
<div class="app-title">
|
||||
<div class="app-name">{{ .name }}</div>
|
||||
<div class="app-version">{{ .version }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">{{ .content }}</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ range .appList }}
|
||||
<div class="app">
|
||||
<div class="app-header">
|
||||
<img class="app-icon" src="{{ .icon | relURL }}" alt="">
|
||||
<div class="app-title">
|
||||
<div class="app-name">{{ .name }}</div>
|
||||
<div class="app-version">{{ .version }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="app-desc">{{ .content }}</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</div>
|
||||
|
||||
<section class="section-2">
|
||||
{{ with .Params.section2 }}
|
||||
<div>
|
||||
<h2>{{ .title }}</h2>
|
||||
<p>{{ .content }}</p>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>
|
||||
<img src="{{ .icon }}" alt="">
|
||||
<h3>{{ .name }}</h3>
|
||||
<p>{{ .content }}</p>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class='section-3'>
|
||||
{{ with .Params.section3 }}
|
||||
<div>
|
||||
<h2>{{ .title }}</h2>
|
||||
<p>{{ .content }}</p>
|
||||
<div class='menu-div'>
|
||||
<ul>
|
||||
{{ range $index, $element := .children }}
|
||||
<li class='{{ if eq $index 0 }} active {{ end }} left-li' data-index='{{ $index }}'>{{ .name }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
{{ range .children }}
|
||||
<div class='right-div'>
|
||||
<div class='top'>
|
||||
<h3>💁🏼♂️{{ .name }}</h3>
|
||||
<p>{{ .content }}</p>
|
||||
</div>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>{{ .content }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
</div>
|
||||
{{ end }}
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
<section>
|
||||
<div class="section-div-4">
|
||||
<div class="h1">如何参与贡献</div>
|
||||
<p>积极参与到 KubeSphere 上游的开发中,了解项目进度,以及 Bug 提交,可以通过 GitHub 与 Slack 与我们保持联系。</p>
|
||||
<div class="contribute-cards">
|
||||
<div class="contribute-card">
|
||||
<div class="contribute-title">
|
||||
报告 Bug
|
||||
</div>
|
||||
<div>
|
||||
<p>KubeSphere 使用 GitHub issue 来管理 bug 跟踪</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contribute-card">
|
||||
<div class="contribute-title">
|
||||
参与开发和设计
|
||||
</div>
|
||||
<div>
|
||||
<ul class="list">
|
||||
<li>认真阅读 kubesphere <a href="//github.com/kubesphere/kubesphere/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">开发者指南</a></li>
|
||||
<li>fork 项目<!-- -->:<!-- --> <a href="https://github.com/kubesphere/kubesphere" target="_blank" rel="noopener noreferrer">https://github.com/kubesphere/kubesphere</a></li>
|
||||
<li><a href="/docs" target="_blank" rel="noopener noreferrer">阅读《KubeSphere 文档》</a></li>
|
||||
<li>参与到 KubeSphere 项目和上游项目如 Kubernetes、Docker、Istio 等</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<div class="contribute-card">
|
||||
<div class="contribute-title">
|
||||
日常沟通
|
||||
</div>
|
||||
<div>
|
||||
<ul class="list">
|
||||
<li>认真阅读 kubesphere <a href="//github.com/kubesphere/kubesphere/blob/master/CONTRIBUTING.md" target="_blank" rel="noopener noreferrer">开发者指南</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<section class='section-4'>
|
||||
{{ with .Params.section4 }}
|
||||
<img class='bg-1' src="/images/home/section4-left.svg" alt="">
|
||||
<img class='bg-2' src="/images/home/section4-right.svg" alt="">
|
||||
<div>
|
||||
<div>
|
||||
<h2>{{ .title }}</h2>
|
||||
<p>{{ .content | safeHTML }}</p>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>
|
||||
<img src="{{ .icon }}" alt="">
|
||||
<div>
|
||||
<h3>{{ .name }}</h3>
|
||||
<p>{{ .content}}</p>
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
<section>
|
||||
<div class="section-div-5">
|
||||
|
||||
<ul>
|
||||
{{ range .features}}
|
||||
<li>
|
||||
<div>
|
||||
<img src="{{ .Site.Params.cloud | absURL }}" alt="">
|
||||
<div>CNCF 云原生基金会会员</div>
|
||||
<div class='top-line {{ .color }}'></div>
|
||||
<div class='img-span-div'>
|
||||
<img src="{{ .icon }}" alt="">
|
||||
<span>{{ .name }}</span>
|
||||
</div>
|
||||
<p>{{ .content }}</p>
|
||||
</div>
|
||||
<div>
|
||||
<img src="{{ .Site.Params.certified | absURL }}" alt="">
|
||||
<div>CNCF 云原生基金会会员</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class='middle-line'></div>
|
||||
<a href="">Read More →</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class='section-5'>
|
||||
{{ with .Params.section5 }}
|
||||
<div>
|
||||
<h2>{{ .title }}</h2>
|
||||
<div>
|
||||
{{ with .frontEnd }}
|
||||
<div class='front-div'>
|
||||
<h3>{{ .title }}</h3>
|
||||
<p>{{ .project }}</p>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>
|
||||
<img src="{{ .icon }}" alt="">
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
{{ with .backEnd }}
|
||||
<div class='back-div'>
|
||||
<h3>{{ .title}}</h3>
|
||||
<div class='group'>
|
||||
<p>{{ .project }}</p>
|
||||
<ul>
|
||||
{{ range .group }}
|
||||
<li>{{ .name }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
<div class='image'>
|
||||
<img src="/images/home/applications.jpg" alt="">
|
||||
<img src="/images/home/applications.jpg" alt="">
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class='section-6'>
|
||||
{{ with .Params.section6 }}
|
||||
<div>
|
||||
<h2>{{ .title }}</h2>
|
||||
<p>{{ .content | safeHTML }}</p>
|
||||
<ul>
|
||||
{{ range .children }}
|
||||
<li>
|
||||
<img src="{{ .icon }}" alt="">
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
<div>
|
||||
<button>{{ .btnContent }}</button>
|
||||
</div>
|
||||
<div class='link-div'>
|
||||
<a href="{{ .link }}">{{ .linkContent }}</a>
|
||||
</div>
|
||||
<img class='bottom-img' src="{{ .image }}" alt="">
|
||||
</div>
|
||||
<img class='bg-1' src="/images/home/section6-left.svg" alt="">
|
||||
<img class='bg-2' src="/images/home/section6-right.svg" alt="">
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<script>
|
||||
var bindMouseLeftLi = function() {
|
||||
$('.left-li').mouseenter(function() {
|
||||
var index = Number($(this).data('index'))
|
||||
$('.left-li').removeClass('active')
|
||||
$(this).addClass('active')
|
||||
$('.right-div').hide().eq(index).show()
|
||||
})
|
||||
}
|
||||
bindMouseLeftLi()
|
||||
</script>
|
||||
{{ end }}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
{{ define "main" }}
|
||||
|
||||
<section id="home">
|
||||
<section>
|
||||
<h2>内容</h2>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -1,2 +1,5 @@
|
|||
{{ $style := resources.Get "scss/home.scss" | toCSS | minify | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $style.Permalink }}">
|
||||
{{ if .Params.css}}
|
||||
{{ $style := resources.Get .Params.css | toCSS | minify | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $style.Permalink }}">
|
||||
{{ end }}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,6 +5,11 @@
|
|||
<div class="up-main">
|
||||
<div class="left-div">
|
||||
<img src="{{ .Site.Params.logo | absURL }}" alt="{{ .Site.Title }}" class="foot-logo">
|
||||
<p>{{ i18n "introduction7" }}</p>
|
||||
<div>
|
||||
<input type="text" placeholder='{{ i18n "introduction6" }}'>
|
||||
<button>{{ i18n "introduction5" }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="right-div">
|
||||
<ul>
|
||||
|
|
@ -22,7 +27,14 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="down-main">
|
||||
|
||||
<div class='img-div'>
|
||||
<img src="/images/footer/facebook.svg" alt="">
|
||||
<img src="/images/footer/youtube.svg" alt="">
|
||||
<img src="/images/footer/slack.svg" alt="">
|
||||
<img src="/images/footer/twitter.svg" alt="">
|
||||
<img src="/images/footer/github.svg" alt="">
|
||||
</div>
|
||||
<p class='p1'>{{ i18n "introduction2" }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -7,6 +7,11 @@
|
|||
|
||||
<link rel="stylesheet" href="/fonts/Roboto/stylesheet.css">
|
||||
|
||||
{{ $style := resources.Get "scss/home.scss" | resources.ToCSS }}
|
||||
<link rel="stylesheet" href="{{ $style.Permalink }}">
|
||||
{{ $common := resources.Get "scss/common.scss" | toCSS | minify | fingerprint }}
|
||||
<link rel="stylesheet" href="{{ $common.Permalink }}">
|
||||
|
||||
{{- partial "css.html" . -}}
|
||||
|
||||
<script src="{{ "js/jquery-3.5.0.min.js" | relURL }}"></script>
|
||||
|
||||
</head>
|
||||
|
|
@ -1,10 +1,12 @@
|
|||
<!-- Header Start -->
|
||||
<header class="navigation">
|
||||
<div class="header-container">
|
||||
<img src="{{ .Site.Params.logo | absURL }}" alt="{{ .Site.Title }}" class="logo">
|
||||
<a href="{{ site.Home.RelPermalink }}">
|
||||
<img src="/images/header/logo.svg" alt="{{ .Site.Title }}" class="logo">
|
||||
</a>
|
||||
|
||||
<ul class="nav">
|
||||
{{ $section := .Page.Section }}
|
||||
<li {{ if .Page.IsHome }} class="active" {{ end}}><a href="{{ site.Home.RelPermalink }}">{{ i18n "home" }}</a></li>
|
||||
{{ range .Site.Menus.main }}
|
||||
{{ if .HasChildren }}
|
||||
|
||||
|
|
@ -16,7 +18,7 @@
|
|||
{{ end }}
|
||||
|
||||
<li {{ if $active }} class="menu-li menu-active" {{ else }} class="menu-li" {{ end}}>
|
||||
<span>{{ .Name }}</span>
|
||||
<span class='menu-span'>{{ .Name }}</span>
|
||||
<ul class="dropdown-menu">
|
||||
{{ range .Children }}
|
||||
<li {{ if eq $section .URL }} class="active"{{ end}}><a href="{{ .URL | absLangURL }}">{{ .Name }}</a></li>
|
||||
|
|
@ -30,13 +32,71 @@
|
|||
{{ end }}
|
||||
|
||||
</ul>
|
||||
<div class="menu-li language-menu">
|
||||
<span>{{ .Site.Language.LanguageName }}</span>
|
||||
<ul class="dropdown-menu">
|
||||
{{ range .Page.AllTranslations }}
|
||||
<li onclick="location = '{{ .Permalink }}'">{{ .Language.LanguageName }}</li>
|
||||
{{ end }}
|
||||
<div class="right-menu">
|
||||
<ul>
|
||||
<li class="language-menu">
|
||||
<div>
|
||||
<img src="/images/header/black.svg" alt="">
|
||||
<span>{{ .Site.Language.LanguageName }}</span>
|
||||
</div>
|
||||
<ul class="dropdown-menu">
|
||||
{{ range .Page.AllTranslations }}
|
||||
<li onclick="location = '{{ .Permalink }}'">{{ .Language.LanguageName }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</li>
|
||||
<li class='btn-li'>
|
||||
<button>Demo →</button>
|
||||
<ol class="dropdown-menu">
|
||||
<li>1.aaa</li>
|
||||
<li>2.bbb</li>
|
||||
<li>3.ccc</li>
|
||||
</ol>
|
||||
</li>
|
||||
<li class='link-li'>
|
||||
<a class='link-1' href=""></a>
|
||||
<a class='link-2' href=""></a>
|
||||
<a class='link-3' href=""></a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</header>
|
||||
<script>
|
||||
var bindNavMouseEvent = function(selector) {
|
||||
var flag = false
|
||||
$(selector).mouseenter(function() {
|
||||
if (flag) {
|
||||
return false
|
||||
}
|
||||
flag = true
|
||||
$(this).find('.dropdown-menu').fadeIn(300, function() {
|
||||
flag = false
|
||||
})
|
||||
});
|
||||
$(selector).mouseleave(function() {
|
||||
$(this).find('.dropdown-menu').fadeOut(300)
|
||||
});
|
||||
}
|
||||
|
||||
var bindScrollChangeHeader = function() {
|
||||
var check = 100
|
||||
var header = $('header')
|
||||
window.addEventListener('scroll', function() {
|
||||
var scrollY = window.scrollY;
|
||||
if (scrollY > 100) {
|
||||
header.addClass('navigationScroll')
|
||||
} else {
|
||||
header.removeClass('navigationScroll')
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
bindScrollChangeHeader()
|
||||
|
||||
bindNavMouseEvent('.navigation .menu-li')
|
||||
bindNavMouseEvent('.navigation .language-menu')
|
||||
bindNavMouseEvent('.navigation .btn-li')
|
||||
|
||||
|
||||
</script>
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
<section>
|
||||
<div class='open-source-header'>
|
||||
<h1>{{ i18n "introduction10" }}</h1>
|
||||
<p>{{ i18n "introduction11" }}</p>
|
||||
<div>
|
||||
<a href="https://github.com/kubesphere" target="_blank" rel="noopener noreferrer">
|
||||
<button class="index-module--button--217nv index-module--control--3r7PJ index-module--large--3KWUF">
|
||||
<svg width="1em" height="1em" viewBox="0 0 21 20">
|
||||
<path d="M10.252.003C4.59.003 0 4.593 0 10.255c0 4.53 2.937 8.372 7.011 9.728.513.095.701-.223.701-.493 0-.245-.01-1.053-.014-1.909-2.853.62-3.454-1.21-3.454-1.21-.466-1.185-1.138-1.5-1.138-1.5-.93-.637.07-.623.07-.623 1.03.072 1.572 1.056 1.572 1.056.915 1.567 2.4 1.114 2.983.852.093-.662.358-1.115.651-1.371-2.277-.259-4.67-1.138-4.67-5.067 0-1.119.4-2.034 1.055-2.752-.106-.258-.457-1.3.099-2.713 0 0 .861-.275 2.82 1.051a9.834 9.834 0 0 1 2.566-.344 9.86 9.86 0 0 1 2.568.344c1.957-1.326 2.817-1.05 2.817-1.05.558 1.412.208 2.455.101 2.712.658.718 1.055 1.633 1.055 2.752 0 3.938-2.399 4.804-4.681 5.058.368.318.696.942.696 1.898 0 1.371-.012 2.476-.012 2.813 0 .273.185.592.705.492a10.253 10.253 0 0 0 7.005-9.727C20.506 4.59 15.916 0 10.254 0l-.002.003z" fill="currentColor" fill-rule="nonzero"></path>
|
||||
</svg>
|
||||
前往 Github
|
||||
</button>
|
||||
</a>
|
||||
</div>
|
||||
<ul class="tabs">
|
||||
{{ $section := .Page.Section }}
|
||||
{{ $menus := (index .Site.Menus.main 2).Children }}
|
||||
{{ range $menus }}
|
||||
<li class="">
|
||||
<a {{ if eq $section .URL }} class="active"{{ end }} href="{{ .URL | absLangURL }}">{{ .Name }}</a>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</section>
|
||||
|
|
@ -34,7 +34,6 @@
|
|||
{{ end }}
|
||||
<script>
|
||||
$('.list-title').click(function() {
|
||||
console.log('click')
|
||||
$(this).find('svg').toggleClass('arrow-open')
|
||||
$(this).next().toggleClass('ul-active')
|
||||
})
|
||||
|
|
|
|||
|
|
@ -0,0 +1,68 @@
|
|||
{{ define "main" }}
|
||||
|
||||
<section class="section-1">
|
||||
{{ with .Params.section1 }}
|
||||
<img src="{{ .topImage | absURL }}" alt="">
|
||||
<div class="title-div">
|
||||
<h1>{{ .title }}</h1>
|
||||
<p>{{ .content }}</p>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class="section-2">
|
||||
{{ with .Params.section2 }}
|
||||
<div>
|
||||
<div class="left-div">
|
||||
<div>{{ .title }}</div>
|
||||
<p>{{ .content }}</p>
|
||||
</div>
|
||||
<div class="right-div">
|
||||
<img src="{{ .mapImage | absURL }}" alt="">
|
||||
<div class='btn-div div-1'>{{ .name1 }}</div>
|
||||
<div class='btn-div div-2'>{{ .name2 }}</div>
|
||||
<div class='btn-div div-3'>{{ .name3 }}</div>
|
||||
</div>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class="section-3">
|
||||
{{ with .Params.section3 }}
|
||||
{{ $tip := .tip }}
|
||||
<div>
|
||||
<h2>{{ .title }}</h2>
|
||||
<ul class="partner-ul">
|
||||
{{ range .partnerType }}
|
||||
<li>
|
||||
<h3>{{ .title }}</h3>
|
||||
<p>{{ .content }}</p>
|
||||
<div>
|
||||
<a href="">{{ $tip }}</a>
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
|
||||
<section class="section-4">
|
||||
{{ with .Params.section4 }}
|
||||
<div>
|
||||
<h2>{{ .title }}</h2>
|
||||
<ul class="partner-ul">
|
||||
<li class="intro">
|
||||
<p>{{ .content }}</p>
|
||||
</li>
|
||||
{{ range .featuredPartnerList }}
|
||||
<li>
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
<div>{{ .partnerType }}</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
{{ end }}
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -1,6 +1,51 @@
|
|||
{{ define "main" }}
|
||||
{{- partial "openSource.html" . -}}
|
||||
|
||||
<section id="home">
|
||||
<h2>内容</h2>
|
||||
<section>
|
||||
<div class="tab-content">
|
||||
<div class="content">
|
||||
<div class="left">
|
||||
<ul id="objects-group">
|
||||
<li class="active">{{ .Params.name }}</li>
|
||||
{{ range .Params.groups }}
|
||||
<li data-name="{{ .name }}">{{ .name }}</li>
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
<ul id="objects-item" class="right">
|
||||
{{ range .Params.groups }}
|
||||
{{ $name := .name }}
|
||||
{{ range .children }}
|
||||
<li data-name="{{ $name }}">
|
||||
<img src="{{ .icon | absURL }}" alt="">
|
||||
<a href="{{ .link }}">{{ .title }}</a>
|
||||
<p>{{ .description }}</p>
|
||||
<div>
|
||||
<a href="{{ .link }}">Github</a>
|
||||
</div>
|
||||
</li>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
<script>
|
||||
$('#objects-group li').click(function() {
|
||||
$("#objects-group li").removeClass("active");
|
||||
$(this).addClass("active");
|
||||
var name = $(this).data("name")
|
||||
if (name) {
|
||||
$("#objects-item li").each(function(item) {
|
||||
if ($(this).data("name") !== name) {
|
||||
$(this).hide()
|
||||
} else {
|
||||
$(this).show()
|
||||
}
|
||||
})
|
||||
} else {
|
||||
$("#objects-item li").show()
|
||||
}
|
||||
})
|
||||
</script>
|
||||
{{ end }}
|
||||
|
|
@ -0,0 +1,6 @@
|
|||
{{ define "main" }}
|
||||
|
||||
<section>
|
||||
<h2>内容</h2>
|
||||
</section>
|
||||
{{ end }}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
{{ define "main" }}
|
||||
|
||||
{{- partial "openSource.html" . -}}
|
||||
<section id="home">
|
||||
<h2>内容</h2>
|
||||
</section>
|
||||
|
|
|
|||
|
|
@ -1,8 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="608" height="636" viewBox="0 0 608 636">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#E4EBF1" d="M307.083 475.619l20.78-297.156a13 13 0 0 1 6.013-10.076L595.985 2.41a3 3 0 0 1 4.605 2.501l4.405 396.354-297.912 74.353z"/>
|
||||
<path fill="#F5F7FA" d="M.192 635.372c1.411.404 2.648.49 3.709.26 1.06-.23 72.692-16.054 214.894-47.471l4.494-1.817 359.973-189.652-276.545 78.84L.192 635.373z"/>
|
||||
<path fill="#E4EBF1" d="M164.081 556.666c1.08.31 2.027.375 2.84.199.812-.176 55.65-12.295 164.516-36.355l3.44-1.391 178.318-95.249-201.44 57.052-147.674 75.744z"/>
|
||||
<path fill="#C6D1DC" d="M.26 634.395l3.293 1.293a3 3 0 0 0 1.686.149l212.225-42.491a40 40 0 0 0 9.646-3.252l372.3-181.12a15 15 0 0 0 8.436-13.712L602.03 4.484a3.756 3.756 0 0 0-5.098-3.452 2.922 2.922 0 0 1 2.737 2.948l-4.172 390.345a6.543 6.543 0 0 1-12.872 1.586l-359.71 189.008a35 35 0 0 1-8.878 3.225L.26 634.394z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 972 B |
Binary file not shown.
|
Before Width: | Height: | Size: 262 KiB |
|
|
@ -1,6 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="359" height="574" viewBox="0 0 359 574">
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<path fill="#EFF4F9" d="M558.573-177.67l-99.09 193.112-117.629-181.134 216.719-11.977zM189.268-66.704a60 60 0 0 1 20.761-23.04c27.791-18.048 64.951-10.15 82.999 17.641L393.18 82.12a60 60 0 0 1 3.12 59.959l-30.658 60.055a58.843 58.843 0 0 0-6.35 29.879c1.725 32.452 29.432 57.361 61.884 55.636l67.333-3.58a60 60 0 0 1 53.506 27.237l100.15 154.218a60 60 0 0 1 9.596 29.491c1.76 33.09-23.638 61.342-56.728 63.103L309.57 573.304a60 60 0 0 1-53.508-27.237L62.41 247.872a60 60 0 0 1-3.12-59.958L189.268-66.705zm382.994 257.453a60 60 0 0 1-30.55-6.494c-29.503-15.088-41.188-51.237-26.1-80.74L614.04-88.942a60 60 0 0 1 20.741-23c27.792-18.048 64.951-10.15 82.999 17.641l117.425 180.82a60 60 0 0 1 9.593 29.448c1.784 33.089-23.593 61.359-56.682 63.143l-215.854 11.639z" opacity=".9"/>
|
||||
<path fill="#E3E9EF" fill-rule="nonzero" d="M118.746 128.981L45.722 87.356c-14.394-8.205-32.714-3.187-40.92 11.207a30 30 0 0 0-3.936 14.856v83.254c0 16.568 13.431 30 30 30a30 30 0 0 0 14.857-3.938l73.024-41.628c14.394-8.206 19.41-26.526 11.205-40.92a30 30 0 0 0-11.206-11.206z" opacity=".6"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB |
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue