diff --git a/404.html b/404.html index 7c633f32f2..67c6a567d5 100644 --- a/404.html +++ b/404.html @@ -14,13 +14,13 @@ - +
Skip to main content

Page Not Found

We could not find what you were looking for.

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

- + \ No newline at end of file diff --git a/assets/js/0a4e8755.afeaff60.js b/assets/js/0a4e8755.afeaff60.js new file mode 100644 index 0000000000..f42b2d2bcd --- /dev/null +++ b/assets/js/0a4e8755.afeaff60.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[5482],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),s=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=s(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),u=s(r),m=o,g=u["".concat(l,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},p),{},{components:r})):n.createElement(g,i({ref:t},p))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[u]="string"==typeof e?e:o,i[1]=c;for(var s=2;s{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/higress",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/higress.md",source:"@site/blog/higress.md",title:"higress",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"first-meetup",permalink:"/blog/first-meetup"},nextItem:{title:"nacos",permalink:"/blog/nacos"}},l={authorsImageUrls:[]},s=[],p={toc:s},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/0a74bc50.9913a08f.js b/assets/js/0a74bc50.9913a08f.js new file mode 100644 index 0000000000..a9f68688e8 --- /dev/null +++ b/assets/js/0a74bc50.9913a08f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[4424],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/first-meetup",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/first-meetup.md",source:"@site/blog/first-meetup.md",title:"first-meetup",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"configmap",permalink:"/blog/configmap"},nextItem:{title:"higress",permalink:"/blog/higress"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/0b0fed00.ca4958ed.js b/assets/js/0b0fed00.ca4958ed.js new file mode 100644 index 0000000000..063e49b612 --- /dev/null +++ b/assets/js/0b0fed00.ca4958ed.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3269],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>g});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function i(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),p=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):i(i({},r),e)),t},u=function(e){var r=p(e.components);return n.createElement(c.Provider,{value:r},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(t),m=o,g=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return t?n.createElement(g,i(i({ref:r},u),{},{components:t})):n.createElement(g,i({ref:r},u))}));function g(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=m;var l={};for(var c in r)hasOwnProperty.call(r,c)&&(l[c]=r[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const a={},i=void 0,l={permalink:"/blog/plugin-transformer",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/plugin-transformer.md",source:"@site/blog/plugin-transformer.md",title:"plugin-transformer",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"ospp-2023",permalink:"/blog/ospp-2023"},nextItem:{title:"release-070",permalink:"/blog/release-070"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(s,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/1ad4371e.00e9ce0e.js b/assets/js/1ad4371e.00e9ce0e.js new file mode 100644 index 0000000000..4cc02ede28 --- /dev/null +++ b/assets/js/1ad4371e.00e9ce0e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6478],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(l,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,c(c({ref:t},s),{},{components:r})):n.createElement(b,c({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,c=new Array(a);c[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[u]="string"==typeof e?e:o,c[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},c=void 0,i={permalink:"/blog/nacos",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/nacos.md",source:"@site/blog/nacos.md",title:"nacos",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"higress",permalink:"/blog/higress"},nextItem:{title:"ospp-2023",permalink:"/blog/ospp-2023"}},l={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/208b2359.c8fa702c.js b/assets/js/208b2359.c8fa702c.js new file mode 100644 index 0000000000..c16859d48d --- /dev/null +++ b/assets/js/208b2359.c8fa702c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[1141],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(l,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,c(c({ref:t},s),{},{components:r})):n.createElement(b,c({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,c=new Array(a);c[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[u]="string"==typeof e?e:o,c[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},c=void 0,i={permalink:"/blog/nacos",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/nacos.md",source:"@site/blog/nacos.md",title:"nacos",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"higress",permalink:"/blog/higress"},nextItem:{title:"ospp-2023",permalink:"/blog/ospp-2023"}},l={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/32f852b2.b32a722e.js b/assets/js/32f852b2.b32a722e.js new file mode 100644 index 0000000000..7fc44b2ad3 --- /dev/null +++ b/assets/js/32f852b2.b32a722e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2338],{3905:(e,r,t)=>{t.d(r,{Zo:()=>s,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),p=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},s=function(e){var r=p(e.components);return n.createElement(c.Provider,{value:r},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(t),m=o,b=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return t?n.createElement(b,l(l({ref:r},s),{},{components:t})):n.createElement(b,l({ref:r},s))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,l=new Array(a);l[0]=m;var i={};for(var c in r)hasOwnProperty.call(r,c)&&(i[c]=r[c]);i.originalType=e,i[u]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const a={},l=void 0,i={permalink:"/blog/release-070",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-070.md",source:"@site/blog/release-070.md",title:"release-070",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"plugin-transformer",permalink:"/blog/plugin-transformer"},nextItem:{title:"release-1.3",permalink:"/blog/release-1.3"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(u,(0,n.Z)({},s,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/34064e98.9d53ddc3.js b/assets/js/34064e98.9d53ddc3.js new file mode 100644 index 0000000000..67f21c2018 --- /dev/null +++ b/assets/js/34064e98.9d53ddc3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7833],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>g});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function i(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),p=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):i(i({},r),e)),t},u=function(e){var r=p(e.components);return n.createElement(c.Provider,{value:r},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(t),m=o,g=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return t?n.createElement(g,i(i({ref:r},u),{},{components:t})):n.createElement(g,i({ref:r},u))}));function g(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=m;var l={};for(var c in r)hasOwnProperty.call(r,c)&&(l[c]=r[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const a={},i=void 0,l={permalink:"/blog/plugin-transformer",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/plugin-transformer.md",source:"@site/blog/plugin-transformer.md",title:"plugin-transformer",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"ospp-2023",permalink:"/blog/ospp-2023"},nextItem:{title:"release-070",permalink:"/blog/release-070"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(s,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/4fced428.42c2f25d.js b/assets/js/4fced428.42c2f25d.js new file mode 100644 index 0000000000..33d29a6ce2 --- /dev/null +++ b/assets/js/4fced428.42c2f25d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2957],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(l,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},s),{},{components:r})):n.createElement(b,i({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[u]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/ospp-2023",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/ospp-2023.md",source:"@site/blog/ospp-2023.md",title:"ospp-2023",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"nacos",permalink:"/blog/nacos"},nextItem:{title:"plugin-transformer",permalink:"/blog/plugin-transformer"}},l={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/58bc8fb4.1b0dec37.js b/assets/js/58bc8fb4.1b0dec37.js new file mode 100644 index 0000000000..97cab13427 --- /dev/null +++ b/assets/js/58bc8fb4.1b0dec37.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[5577],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),u=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),s=u(r),m=o,b=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(b,c(c({ref:t},p),{},{components:r})):n.createElement(b,c({ref:t},p))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,c=new Array(a);c[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[s]="string"==typeof e?e:o,c[1]=i;for(var u=2;u{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={},c=void 0,i={permalink:"/blog/2023-kubecon",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/2023-kubecon.md",source:"@site/blog/2023-kubecon.md",title:"2023-kubecon",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},nextItem:{title:"30-line-wasm",permalink:"/blog/30-line-wasm"}},l={authorsImageUrls:[]},u=[],p={toc:u},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/624571fc.89a8ed4a.js b/assets/js/624571fc.89a8ed4a.js new file mode 100644 index 0000000000..b482a0cc9a --- /dev/null +++ b/assets/js/624571fc.89a8ed4a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3919],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,s=c(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(l,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},s),{},{components:r})):n.createElement(b,i({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[u]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/ospp-2023",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/ospp-2023.md",source:"@site/blog/ospp-2023.md",title:"ospp-2023",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"nacos",permalink:"/blog/nacos"},nextItem:{title:"plugin-transformer",permalink:"/blog/plugin-transformer"}},l={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/754257ee.50c6de29.js b/assets/js/754257ee.50c6de29.js new file mode 100644 index 0000000000..8a61dc56fc --- /dev/null +++ b/assets/js/754257ee.50c6de29.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[8666],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,b=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},u),{},{components:r})):n.createElement(b,i({ref:t},u))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/30-line-wasm",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/30-line-wasm.md",source:"@site/blog/30-line-wasm.md",title:"30-line-wasm",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"2023-kubecon",permalink:"/blog/2023-kubecon"},nextItem:{title:"DeployOnWindows",permalink:"/blog/DeployOnWindows"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8128b5c2.0bda2485.js b/assets/js/8128b5c2.0bda2485.js new file mode 100644 index 0000000000..db17e5f3fd --- /dev/null +++ b/assets/js/8128b5c2.0bda2485.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2606],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function u(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var i=n.createContext({}),l=function(e){var r=n.useContext(i),t=r;return e&&(t="function"==typeof e?e(r):u(u({},r),e)),t},p=function(e){var r=l(e.components);return n.createElement(i.Provider,{value:r},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,i=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),s=l(t),m=o,b=s["".concat(i,".").concat(m)]||s[m]||f[m]||a;return t?n.createElement(b,u(u({ref:r},p),{},{components:t})):n.createElement(b,u({ref:r},p))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,u=new Array(a);u[0]=m;var c={};for(var i in r)hasOwnProperty.call(r,i)&&(c[i]=r[i]);c.originalType=e,c[s]="string"==typeof e?e:o,u[1]=c;for(var l=2;l{t.r(r),t.d(r,{assets:()=>i,contentTitle:()=>u,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>l});var n=t(7462),o=(t(7294),t(3905));const a={},u=void 0,c={permalink:"/blog/user-uu",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/user-uu.md",source:"@site/blog/user-uu.md",title:"user-uu",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"user-mq",permalink:"/blog/user-mq"}},i={authorsImageUrls:[]},l=[],p={toc:l},s="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(s,(0,n.Z)({},p,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8395dadb.927ecca0.js b/assets/js/8395dadb.927ecca0.js new file mode 100644 index 0000000000..df8123b719 --- /dev/null +++ b/assets/js/8395dadb.927ecca0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3197],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/first-meetup",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/first-meetup.md",source:"@site/blog/first-meetup.md",title:"first-meetup",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"configmap",permalink:"/blog/configmap"},nextItem:{title:"higress",permalink:"/blog/higress"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/845e9851.265adf69.js b/assets/js/845e9851.265adf69.js new file mode 100644 index 0000000000..7be38fa3d7 --- /dev/null +++ b/assets/js/845e9851.265adf69.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[1382],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>y});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,y=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(y,i(i({ref:t},u),{},{components:r})):n.createElement(y,i({ref:t},u))}));function y(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/DeployOnWindows",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/DeployOnWindows.md",source:"@site/blog/DeployOnWindows.md",title:"DeployOnWindows",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"30-line-wasm",permalink:"/blog/30-line-wasm"},nextItem:{title:"ai_plugin",permalink:"/blog/ai_plugin"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/8d5cf564.7334e05b.js b/assets/js/8d5cf564.7334e05b.js new file mode 100644 index 0000000000..3f0421289e --- /dev/null +++ b/assets/js/8d5cf564.7334e05b.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3072],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,l(l({ref:t},s),{},{components:r})):n.createElement(b,l({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},l=void 0,i={permalink:"/blog/release-1.3",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-1.3.md",source:"@site/blog/release-1.3.md",title:"release-1.3",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-070",permalink:"/blog/release-070"},nextItem:{title:"release-100",permalink:"/blog/release-100"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/99708c2c.885bf99e.js b/assets/js/99708c2c.885bf99e.js new file mode 100644 index 0000000000..5dc5fa995f --- /dev/null +++ b/assets/js/99708c2c.885bf99e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[4953],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/configmap",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/configmap.md",source:"@site/blog/configmap.md",title:"configmap",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"config-with-file",permalink:"/blog/config-with-file"},nextItem:{title:"first-meetup",permalink:"/blog/first-meetup"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/9d0fb5fa.a3b20e8c.js b/assets/js/9d0fb5fa.a3b20e8c.js new file mode 100644 index 0000000000..34c62a0f5d --- /dev/null +++ b/assets/js/9d0fb5fa.a3b20e8c.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7732],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,l(l({ref:t},s),{},{components:r})):n.createElement(b,l({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},l=void 0,i={permalink:"/blog/release-1.3",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-1.3.md",source:"@site/blog/release-1.3.md",title:"release-1.3",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-070",permalink:"/blog/release-070"},nextItem:{title:"release-100",permalink:"/blog/release-100"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/9ef98e71.a1498b92.js b/assets/js/9ef98e71.a1498b92.js new file mode 100644 index 0000000000..64f710e46d --- /dev/null +++ b/assets/js/9ef98e71.a1498b92.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[1434],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},f="mdxType",s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),f=p(r),m=o,g=f["".concat(l,".").concat(m)]||f[m]||s[m]||i;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[f]="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>s,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,c={permalink:"/blog/config-with-file",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/config-with-file.md",source:"@site/blog/config-with-file.md",title:"config-with-file",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"ai_plugin",permalink:"/blog/ai_plugin"},nextItem:{title:"configmap",permalink:"/blog/configmap"}},l={authorsImageUrls:[]},p=[],u={toc:p},f="wrapper";function s(e){let{components:t,...r}=e;return(0,o.kt)(f,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/a68b5a4c.73f7ff43.js b/assets/js/a68b5a4c.73f7ff43.js new file mode 100644 index 0000000000..3047db6206 --- /dev/null +++ b/assets/js/a68b5a4c.73f7ff43.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[9533],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,l(l({ref:t},s),{},{components:r})):n.createElement(b,l({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},l=void 0,i={permalink:"/blog/release-100",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-100.md",source:"@site/blog/release-100.md",title:"release-100",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-1.3",permalink:"/blog/release-1.3"},nextItem:{title:"skywalking",permalink:"/blog/skywalking"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/aa0335fa.b389efb0.js b/assets/js/aa0335fa.b389efb0.js new file mode 100644 index 0000000000..d67444797e --- /dev/null +++ b/assets/js/aa0335fa.b389efb0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7662],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),u=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),s=u(r),m=o,b=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},p),{},{components:r})):n.createElement(b,i({ref:t},p))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var u=2;u{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/user-mq",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/user-mq.md",source:"@site/blog/user-mq.md",title:"user-mq",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"skywalking",permalink:"/blog/skywalking"},nextItem:{title:"user-uu",permalink:"/blog/user-uu"}},c={authorsImageUrls:[]},u=[],p={toc:u},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/b2f554cd.22910a69.js b/assets/js/b2f554cd.22910a69.js new file mode 100644 index 0000000000..3b2d99a314 --- /dev/null +++ b/assets/js/b2f554cd.22910a69.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[1477],{10:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"/2023-kubecon","metadata":{"permalink":"/blog/2023-kubecon","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/2023-kubecon.md","source":"@site/blog/2023-kubecon.md","title":"2023-kubecon","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"nextItem":{"title":"30-line-wasm","permalink":"/blog/30-line-wasm"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/30-line-wasm","metadata":{"permalink":"/blog/30-line-wasm","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/30-line-wasm.md","source":"@site/blog/30-line-wasm.md","title":"30-line-wasm","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"2023-kubecon","permalink":"/blog/2023-kubecon"},"nextItem":{"title":"DeployOnWindows","permalink":"/blog/DeployOnWindows"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/DeployOnWindows","metadata":{"permalink":"/blog/DeployOnWindows","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/DeployOnWindows.md","source":"@site/blog/DeployOnWindows.md","title":"DeployOnWindows","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"30-line-wasm","permalink":"/blog/30-line-wasm"},"nextItem":{"title":"ai_plugin","permalink":"/blog/ai_plugin"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/ai_plugin","metadata":{"permalink":"/blog/ai_plugin","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/ai_plugin.md","source":"@site/blog/ai_plugin.md","title":"ai_plugin","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"DeployOnWindows","permalink":"/blog/DeployOnWindows"},"nextItem":{"title":"config-with-file","permalink":"/blog/config-with-file"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/config-with-file","metadata":{"permalink":"/blog/config-with-file","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/config-with-file.md","source":"@site/blog/config-with-file.md","title":"config-with-file","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"ai_plugin","permalink":"/blog/ai_plugin"},"nextItem":{"title":"configmap","permalink":"/blog/configmap"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/configmap","metadata":{"permalink":"/blog/configmap","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/configmap.md","source":"@site/blog/configmap.md","title":"configmap","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"config-with-file","permalink":"/blog/config-with-file"},"nextItem":{"title":"first-meetup","permalink":"/blog/first-meetup"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/first-meetup","metadata":{"permalink":"/blog/first-meetup","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/first-meetup.md","source":"@site/blog/first-meetup.md","title":"first-meetup","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"configmap","permalink":"/blog/configmap"},"nextItem":{"title":"higress","permalink":"/blog/higress"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/higress","metadata":{"permalink":"/blog/higress","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/higress.md","source":"@site/blog/higress.md","title":"higress","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"first-meetup","permalink":"/blog/first-meetup"},"nextItem":{"title":"nacos","permalink":"/blog/nacos"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/nacos","metadata":{"permalink":"/blog/nacos","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/nacos.md","source":"@site/blog/nacos.md","title":"nacos","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"higress","permalink":"/blog/higress"},"nextItem":{"title":"ospp-2023","permalink":"/blog/ospp-2023"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/ospp-2023","metadata":{"permalink":"/blog/ospp-2023","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/ospp-2023.md","source":"@site/blog/ospp-2023.md","title":"ospp-2023","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"nacos","permalink":"/blog/nacos"},"nextItem":{"title":"plugin-transformer","permalink":"/blog/plugin-transformer"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/plugin-transformer","metadata":{"permalink":"/blog/plugin-transformer","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/plugin-transformer.md","source":"@site/blog/plugin-transformer.md","title":"plugin-transformer","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"ospp-2023","permalink":"/blog/ospp-2023"},"nextItem":{"title":"release-070","permalink":"/blog/release-070"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/release-070","metadata":{"permalink":"/blog/release-070","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-070.md","source":"@site/blog/release-070.md","title":"release-070","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"plugin-transformer","permalink":"/blog/plugin-transformer"},"nextItem":{"title":"release-1.3","permalink":"/blog/release-1.3"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/release-1.3","metadata":{"permalink":"/blog/release-1.3","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-1.3.md","source":"@site/blog/release-1.3.md","title":"release-1.3","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"release-070","permalink":"/blog/release-070"},"nextItem":{"title":"release-100","permalink":"/blog/release-100"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/release-100","metadata":{"permalink":"/blog/release-100","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-100.md","source":"@site/blog/release-100.md","title":"release-100","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"release-1.3","permalink":"/blog/release-1.3"},"nextItem":{"title":"skywalking","permalink":"/blog/skywalking"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/skywalking","metadata":{"permalink":"/blog/skywalking","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/skywalking.md","source":"@site/blog/skywalking.md","title":"skywalking","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"release-100","permalink":"/blog/release-100"},"nextItem":{"title":"user-mq","permalink":"/blog/user-mq"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/user-mq","metadata":{"permalink":"/blog/user-mq","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/user-mq.md","source":"@site/blog/user-mq.md","title":"user-mq","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"skywalking","permalink":"/blog/skywalking"},"nextItem":{"title":"user-uu","permalink":"/blog/user-uu"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/user-uu","metadata":{"permalink":"/blog/user-uu","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/user-uu.md","source":"@site/blog/user-uu.md","title":"user-uu","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"user-mq","permalink":"/blog/user-mq"}},"content":"Placeholder. DO NOT DELETE."}]}')}}]); \ No newline at end of file diff --git a/assets/js/b4e8a740.560d6e31.js b/assets/js/b4e8a740.560d6e31.js new file mode 100644 index 0000000000..958197e553 --- /dev/null +++ b/assets/js/b4e8a740.560d6e31.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2272],{3905:(e,r,t)=>{t.d(r,{Zo:()=>s,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),p=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},s=function(e){var r=p(e.components);return n.createElement(c.Provider,{value:r},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(t),m=o,b=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return t?n.createElement(b,l(l({ref:r},s),{},{components:t})):n.createElement(b,l({ref:r},s))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,l=new Array(a);l[0]=m;var i={};for(var c in r)hasOwnProperty.call(r,c)&&(i[c]=r[c]);i.originalType=e,i[u]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const a={},l=void 0,i={permalink:"/blog/release-070",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-070.md",source:"@site/blog/release-070.md",title:"release-070",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"plugin-transformer",permalink:"/blog/plugin-transformer"},nextItem:{title:"release-1.3",permalink:"/blog/release-1.3"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(u,(0,n.Z)({},s,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/ccb98be5.4613d37f.js b/assets/js/ccb98be5.4613d37f.js new file mode 100644 index 0000000000..c13c5222a5 --- /dev/null +++ b/assets/js/ccb98be5.4613d37f.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7211],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),u=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),s=u(r),m=o,b=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(b,c(c({ref:t},p),{},{components:r})):n.createElement(b,c({ref:t},p))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,c=new Array(a);c[0]=m;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[s]="string"==typeof e?e:o,c[1]=i;for(var u=2;u{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={},c=void 0,i={permalink:"/blog/2023-kubecon",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/2023-kubecon.md",source:"@site/blog/2023-kubecon.md",title:"2023-kubecon",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},nextItem:{title:"30-line-wasm",permalink:"/blog/30-line-wasm"}},l={authorsImageUrls:[]},u=[],p={toc:u},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/cd655862.d464c447.js b/assets/js/cd655862.d464c447.js new file mode 100644 index 0000000000..7d01cc3946 --- /dev/null +++ b/assets/js/cd655862.d464c447.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[5858],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,b=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},u),{},{components:r})):n.createElement(b,i({ref:t},u))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/30-line-wasm",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/30-line-wasm.md",source:"@site/blog/30-line-wasm.md",title:"30-line-wasm",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"2023-kubecon",permalink:"/blog/2023-kubecon"},nextItem:{title:"DeployOnWindows",permalink:"/blog/DeployOnWindows"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/dbd65e5e.25fd00e9.js b/assets/js/dbd65e5e.25fd00e9.js new file mode 100644 index 0000000000..2630804a6f --- /dev/null +++ b/assets/js/dbd65e5e.25fd00e9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6446],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},f="mdxType",s={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),f=p(r),m=o,g=f["".concat(l,".").concat(m)]||f[m]||s[m]||i;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[f]="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>s,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,c={permalink:"/blog/config-with-file",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/config-with-file.md",source:"@site/blog/config-with-file.md",title:"config-with-file",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"ai_plugin",permalink:"/blog/ai_plugin"},nextItem:{title:"configmap",permalink:"/blog/configmap"}},l={authorsImageUrls:[]},p=[],u={toc:p},f="wrapper";function s(e){let{components:t,...r}=e;return(0,o.kt)(f,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}s.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/de9c39ca.77e0252e.js b/assets/js/de9c39ca.77e0252e.js new file mode 100644 index 0000000000..6bb4f46cc3 --- /dev/null +++ b/assets/js/de9c39ca.77e0252e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6642],{3905:(e,r,t)=>{t.d(r,{Zo:()=>p,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function u(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var i=n.createContext({}),l=function(e){var r=n.useContext(i),t=r;return e&&(t="function"==typeof e?e(r):u(u({},r),e)),t},p=function(e){var r=l(e.components);return n.createElement(i.Provider,{value:r},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,i=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),s=l(t),m=o,b=s["".concat(i,".").concat(m)]||s[m]||f[m]||a;return t?n.createElement(b,u(u({ref:r},p),{},{components:t})):n.createElement(b,u({ref:r},p))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,u=new Array(a);u[0]=m;var c={};for(var i in r)hasOwnProperty.call(r,i)&&(c[i]=r[i]);c.originalType=e,c[s]="string"==typeof e?e:o,u[1]=c;for(var l=2;l{t.r(r),t.d(r,{assets:()=>i,contentTitle:()=>u,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>l});var n=t(7462),o=(t(7294),t(3905));const a={},u=void 0,c={permalink:"/blog/user-uu",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/user-uu.md",source:"@site/blog/user-uu.md",title:"user-uu",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"user-mq",permalink:"/blog/user-mq"}},i={authorsImageUrls:[]},l=[],p={toc:l},s="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(s,(0,n.Z)({},p,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e053fdff.675f107e.js b/assets/js/e053fdff.675f107e.js new file mode 100644 index 0000000000..9da63c4863 --- /dev/null +++ b/assets/js/e053fdff.675f107e.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3304],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(c,".").concat(m)]||s[m]||f[m]||i;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,a[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>f,frontMatter:()=>i,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,l={permalink:"/blog/ai_plugin",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/ai_plugin.md",source:"@site/blog/ai_plugin.md",title:"ai_plugin",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"DeployOnWindows",permalink:"/blog/DeployOnWindows"},nextItem:{title:"config-with-file",permalink:"/blog/config-with-file"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e0d5e815.d8dc4404.js b/assets/js/e0d5e815.d8dc4404.js new file mode 100644 index 0000000000..9ed5d729f7 --- /dev/null +++ b/assets/js/e0d5e815.d8dc4404.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[4319],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/configmap",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/configmap.md",source:"@site/blog/configmap.md",title:"configmap",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"config-with-file",permalink:"/blog/config-with-file"},nextItem:{title:"first-meetup",permalink:"/blog/first-meetup"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e6214f62.2914ffa5.js b/assets/js/e6214f62.2914ffa5.js new file mode 100644 index 0000000000..411b9a1421 --- /dev/null +++ b/assets/js/e6214f62.2914ffa5.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6541],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),u=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,p=l(e,["components","mdxType","originalType","parentName"]),s=u(r),m=o,b=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},p),{},{components:r})):n.createElement(b,i({ref:t},p))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var u=2;u{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/user-mq",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/user-mq.md",source:"@site/blog/user-mq.md",title:"user-mq",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"skywalking",permalink:"/blog/skywalking"},nextItem:{title:"user-uu",permalink:"/blog/user-uu"}},c={authorsImageUrls:[]},u=[],p={toc:u},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e6448491.abf79420.js b/assets/js/e6448491.abf79420.js new file mode 100644 index 0000000000..03663b2370 --- /dev/null +++ b/assets/js/e6448491.abf79420.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[5746],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(c,".").concat(m)]||s[m]||f[m]||i;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,a[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>a,default:()=>f,frontMatter:()=>i,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,l={permalink:"/blog/ai_plugin",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/ai_plugin.md",source:"@site/blog/ai_plugin.md",title:"ai_plugin",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"DeployOnWindows",permalink:"/blog/DeployOnWindows"},nextItem:{title:"config-with-file",permalink:"/blog/config-with-file"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/e7597a90.7d19e5f8.js b/assets/js/e7597a90.7d19e5f8.js new file mode 100644 index 0000000000..d286d37f66 --- /dev/null +++ b/assets/js/e7597a90.7d19e5f8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2131],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,g=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},s),{},{components:r})):n.createElement(g,i({ref:t},s))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[u]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/skywalking",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/skywalking.md",source:"@site/blog/skywalking.md",title:"skywalking",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-100",permalink:"/blog/release-100"},nextItem:{title:"user-mq",permalink:"/blog/user-mq"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/eee51acf.b0b1cd02.js b/assets/js/eee51acf.b0b1cd02.js new file mode 100644 index 0000000000..f2b12d9d4c --- /dev/null +++ b/assets/js/eee51acf.b0b1cd02.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[9341],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>y});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,y=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(y,i(i({ref:t},u),{},{components:r})):n.createElement(y,i({ref:t},u))}));function y(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/DeployOnWindows",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/DeployOnWindows.md",source:"@site/blog/DeployOnWindows.md",title:"DeployOnWindows",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"30-line-wasm",permalink:"/blog/30-line-wasm"},nextItem:{title:"ai_plugin",permalink:"/blog/ai_plugin"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f01d234c.a5a84db9.js b/assets/js/f01d234c.a5a84db9.js new file mode 100644 index 0000000000..6cb794c8dd --- /dev/null +++ b/assets/js/f01d234c.a5a84db9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[696],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=l(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,g=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},s),{},{components:r})):n.createElement(g,i({ref:t},s))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[u]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/blog/skywalking",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/skywalking.md",source:"@site/blog/skywalking.md",title:"skywalking",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-100",permalink:"/blog/release-100"},nextItem:{title:"user-mq",permalink:"/blog/user-mq"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/f1fb6c08.20886404.js b/assets/js/f1fb6c08.20886404.js new file mode 100644 index 0000000000..590f5b96c8 --- /dev/null +++ b/assets/js/f1fb6c08.20886404.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2439],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),s=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},p=function(e){var t=s(e.components);return n.createElement(l.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=c(e,["components","mdxType","originalType","parentName"]),u=s(r),m=o,g=u["".concat(l,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},p),{},{components:r})):n.createElement(g,i({ref:t},p))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[u]="string"==typeof e?e:o,i[1]=c;for(var s=2;s{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/blog/higress",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/higress.md",source:"@site/blog/higress.md",title:"higress",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"first-meetup",permalink:"/blog/first-meetup"},nextItem:{title:"nacos",permalink:"/blog/nacos"}},l={authorsImageUrls:[]},s=[],p={toc:s},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/feedb3b4.179d3638.js b/assets/js/feedb3b4.179d3638.js new file mode 100644 index 0000000000..a64de782f5 --- /dev/null +++ b/assets/js/feedb3b4.179d3638.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6388],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),p=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},s=function(e){var t=p(e.components);return n.createElement(c.Provider,{value:t},e.children)},u="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=i(e,["components","mdxType","originalType","parentName"]),u=p(r),m=o,b=u["".concat(c,".").concat(m)]||u[m]||f[m]||a;return r?n.createElement(b,l(l({ref:t},s),{},{components:r})):n.createElement(b,l({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[u]="string"==typeof e?e:o,l[1]=i;for(var p=2;p{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},l=void 0,i={permalink:"/blog/release-100",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/default/docusaurus-plugin-content-blog/release-100.md",source:"@site/blog/release-100.md",title:"release-100",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-1.3",permalink:"/blog/release-1.3"},nextItem:{title:"skywalking",permalink:"/blog/skywalking"}},c={authorsImageUrls:[]},p=[],s={toc:p},u="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(u,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/assets/js/runtime~main.d2bd931d.js b/assets/js/runtime~main.d2bd931d.js new file mode 100644 index 0000000000..0bd8c8930a --- /dev/null +++ b/assets/js/runtime~main.d2bd931d.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,a,d,f,c,b={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var d=t[e]={id:e,loaded:!1,exports:{}};return b[e].call(d.exports,d,d.exports,r),d.loaded=!0,d.exports}r.m=b,r.c=t,e=[],r.O=(a,d,f,c)=>{if(!d){var b=1/0;for(i=0;i=c)&&Object.keys(r.O).every((e=>r.O[e](d[o])))?d.splice(o--,1):(t=!1,c0&&e[i-1][2]>c;i--)e[i]=e[i-1];e[i]=[d,f,c]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},d=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var c=Object.create(null);r.r(c);var b={};a=a||[null,d({}),d([]),d(d)];for(var t=2&f&&e;"object"==typeof t&&!~a.indexOf(t);t=d(t))Object.getOwnPropertyNames(t).forEach((a=>b[a]=()=>e[a]));return b.default=()=>e,r.d(c,b),c},r.d=(e,a)=>{for(var d in a)r.o(a,d)&&!r.o(e,d)&&Object.defineProperty(e,d,{enumerable:!0,get:a[d]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,d)=>(r.f[d](e,a),a)),[])),r.u=e=>"assets/js/"+({1:"8eb4e46b",53:"935f2afb",106:"703e454d",136:"7893cef3",286:"b72e39f9",353:"98685493",360:"3a84ea56",443:"841233fa",533:"b2b675dd",565:"043d71ad",590:"e6e760b3",647:"568610b2",696:"f01d234c",799:"2d27d23c",801:"914e0e0b",1141:"208b2359",1208:"3f59e662",1249:"44e19575",1382:"845e9851",1434:"9ef98e71",1477:"b2f554cd",1492:"beb5e9ee",1519:"af45db24",1595:"573517bf",1775:"4d9cbf1c",1791:"4becae2f",1840:"b03f1728",1927:"2dc40880",1960:"bcaff976",2131:"e7597a90",2169:"432e4ad2",2272:"b4e8a740",2338:"32f852b2",2439:"f1fb6c08",2464:"77dd0ed0",2535:"814f3328",2606:"8128b5c2",2698:"d90649c7",2957:"4fced428",2972:"3794dc3b",3072:"8d5cf564",3085:"1f391b9e",3089:"a6aa9e1f",3114:"7c708217",3127:"8a882891",3140:"984e32b5",3197:"8395dadb",3237:"1df93b7f",3248:"002ed870",3269:"0b0fed00",3304:"e053fdff",3397:"e34f3602",3591:"3d8abcf7",3608:"9e4087bc",3808:"3eb9a485",3865:"19fc5a4c",3919:"624571fc",4016:"b7d5369b",4319:"e0d5e815",4424:"0a74bc50",4666:"29c0fea4",4953:"99708c2c",4970:"33b08622",5039:"24868bd5",5292:"c557ece2",5342:"3525307a",5375:"afb509df",5482:"0a4e8755",5577:"58bc8fb4",5707:"c8858931",5746:"e6448491",5858:"cd655862",5862:"5d73b5ae",5941:"3ef9205c",6103:"ccc49370",6303:"17dfea31",6388:"feedb3b4",6446:"dbd65e5e",6478:"1ad4371e",6541:"e6214f62",6604:"6a1ae202",6642:"de9c39ca",6697:"d7d92410",6811:"4ceb2517",7211:"ccb98be5",7318:"bb332f99",7414:"393be207",7662:"aa0335fa",7732:"9d0fb5fa",7833:"34064e98",7903:"5d067262",7918:"17896441",8017:"f706fd0f",8122:"647ae0a3",8283:"caf0b7bb",8576:"f8be80dd",8666:"754257ee",8982:"35dffc23",9003:"4c19e3d2",9077:"3caa656d",9171:"6a170313",9250:"d97b4169",9327:"ca296d7a",9341:"eee51acf",9439:"265f8c6c",9514:"1be78505",9533:"a68b5a4c",9775:"b672a4ca",9962:"4e3c9368",9987:"94c19817"}[e]||e)+"."+{1:"a41b11cb",53:"6acffe3b",106:"d0ac9bda",136:"4b5d27c3",210:"7b457f2b",286:"bc477af8",353:"8af03921",360:"6c9b2aae",412:"c211d18d",443:"00256d13",533:"4ee28bcb",565:"698ccba8",590:"69ecc827",647:"061b71e5",696:"a5a84db9",799:"17afcaf8",801:"1a9049d8",1141:"c8fa702c",1208:"71a1bd12",1249:"be4afab3",1382:"265adf69",1434:"a1498b92",1477:"22910a69",1492:"5385e4d3",1519:"a257312f",1595:"73120264",1775:"c70d2281",1791:"cfbcefec",1840:"453d80ff",1927:"1188d6da",1960:"58169b38",2131:"7d19e5f8",2169:"ff07ec21",2272:"560d6e31",2338:"b32a722e",2439:"20886404",2464:"05fc0cee",2535:"6d41c96f",2606:"0bda2485",2698:"9cd25e5e",2957:"42c2f25d",2972:"e2e2a610",3072:"7334e05b",3085:"5dd43995",3089:"04e59258",3114:"5de8cbee",3127:"71422bcc",3140:"10ca6685",3197:"927ecca0",3237:"b211faaa",3248:"1ea36195",3269:"ca4958ed",3304:"675f107e",3397:"a5f33862",3591:"1c0cc073",3608:"d4b4fa21",3808:"d4eccbeb",3865:"56c54bb6",3919:"89a8ed4a",4016:"09ffb822",4319:"d8dc4404",4424:"9913a08f",4666:"38fabd02",4953:"885bf99e",4970:"dd2929ea",4972:"453b6fac",5039:"357629ca",5292:"46e2f392",5342:"b2e7d8b1",5375:"483bf097",5482:"afeaff60",5577:"1b0dec37",5707:"48a403b2",5746:"abf79420",5858:"d464c447",5862:"25089025",5941:"947d6ac0",6103:"f9d66d0a",6303:"9d41b7ee",6388:"179d3638",6446:"25fd00e9",6478:"00e9ce0e",6541:"2914ffa5",6604:"af192488",6642:"77e0252e",6697:"8c7c1964",6811:"91511ebf",7211:"4613d37f",7318:"eb18e1c9",7414:"ec26ee40",7662:"b389efb0",7732:"a3b20e8c",7833:"9d53ddc3",7903:"d5bd7919",7918:"0980fa4a",8017:"04c906f1",8122:"8cc0db52",8283:"06321d6e",8576:"86690e3d",8666:"50c6de29",8982:"0bbf502e",9003:"49669259",9077:"fddd1251",9171:"33105e8f",9250:"3bbf021e",9327:"05192077",9341:"b0b1cd02",9439:"2bf55669",9514:"7cc3593d",9533:"73f7ff43",9775:"3c2cdcf0",9962:"d4bcdf2a",9987:"c1528435"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),f={},c="higress-website:",r.l=(e,a,d,b)=>{if(f[e])f[e].push(a);else{var t,o;if(void 0!==d)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(l);var c=f[e];if(delete f[e],t.parentNode&&t.parentNode.removeChild(t),c&&c.forEach((e=>e(d))),a)return a(d)},l=setTimeout(s.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=s.bind(null,t.onerror),t.onload=s.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/",r.gca=function(e){return e={17896441:"7918",98685493:"353","8eb4e46b":"1","935f2afb":"53","703e454d":"106","7893cef3":"136",b72e39f9:"286","3a84ea56":"360","841233fa":"443",b2b675dd:"533","043d71ad":"565",e6e760b3:"590","568610b2":"647",f01d234c:"696","2d27d23c":"799","914e0e0b":"801","208b2359":"1141","3f59e662":"1208","44e19575":"1249","845e9851":"1382","9ef98e71":"1434",b2f554cd:"1477",beb5e9ee:"1492",af45db24:"1519","573517bf":"1595","4d9cbf1c":"1775","4becae2f":"1791",b03f1728:"1840","2dc40880":"1927",bcaff976:"1960",e7597a90:"2131","432e4ad2":"2169",b4e8a740:"2272","32f852b2":"2338",f1fb6c08:"2439","77dd0ed0":"2464","814f3328":"2535","8128b5c2":"2606",d90649c7:"2698","4fced428":"2957","3794dc3b":"2972","8d5cf564":"3072","1f391b9e":"3085",a6aa9e1f:"3089","7c708217":"3114","8a882891":"3127","984e32b5":"3140","8395dadb":"3197","1df93b7f":"3237","002ed870":"3248","0b0fed00":"3269",e053fdff:"3304",e34f3602:"3397","3d8abcf7":"3591","9e4087bc":"3608","3eb9a485":"3808","19fc5a4c":"3865","624571fc":"3919",b7d5369b:"4016",e0d5e815:"4319","0a74bc50":"4424","29c0fea4":"4666","99708c2c":"4953","33b08622":"4970","24868bd5":"5039",c557ece2:"5292","3525307a":"5342",afb509df:"5375","0a4e8755":"5482","58bc8fb4":"5577",c8858931:"5707",e6448491:"5746",cd655862:"5858","5d73b5ae":"5862","3ef9205c":"5941",ccc49370:"6103","17dfea31":"6303",feedb3b4:"6388",dbd65e5e:"6446","1ad4371e":"6478",e6214f62:"6541","6a1ae202":"6604",de9c39ca:"6642",d7d92410:"6697","4ceb2517":"6811",ccb98be5:"7211",bb332f99:"7318","393be207":"7414",aa0335fa:"7662","9d0fb5fa":"7732","34064e98":"7833","5d067262":"7903",f706fd0f:"8017","647ae0a3":"8122",caf0b7bb:"8283",f8be80dd:"8576","754257ee":"8666","35dffc23":"8982","4c19e3d2":"9003","3caa656d":"9077","6a170313":"9171",d97b4169:"9250",ca296d7a:"9327",eee51acf:"9341","265f8c6c":"9439","1be78505":"9514",a68b5a4c:"9533",b672a4ca:"9775","4e3c9368":"9962","94c19817":"9987"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,d)=>{var f=r.o(e,a)?e[a]:void 0;if(0!==f)if(f)d.push(f[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var c=new Promise(((d,c)=>f=e[a]=[d,c]));d.push(f[2]=c);var b=r.p+r.u(a),t=new Error;r.l(b,(d=>{if(r.o(e,a)&&(0!==(f=e[a])&&(e[a]=void 0),f)){var c=d&&("load"===d.type?"missing":d.type),b=d&&d.target&&d.target.src;t.message="Loading chunk "+a+" failed.\n("+c+": "+b+")",t.name="ChunkLoadError",t.type=c,t.request=b,f[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,d)=>{var f,c,b=d[0],t=d[1],o=d[2],n=0;if(b.some((a=>0!==e[a]))){for(f in t)r.o(t,f)&&(r.m[f]=t[f]);if(o)var i=o(r)}for(a&&a(d);n -2023-kubecon | Higress +2023-kubecon | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/30-line-wasm/index.html b/blog/30-line-wasm/index.html index b1a017e600..d3b61fd4e3 100644 --- a/blog/30-line-wasm/index.html +++ b/blog/30-line-wasm/index.html @@ -3,7 +3,7 @@ -30-line-wasm | Higress +30-line-wasm | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/DeployOnWindows/index.html b/blog/DeployOnWindows/index.html index 4425be4b8a..63c9ddc2c1 100644 --- a/blog/DeployOnWindows/index.html +++ b/blog/DeployOnWindows/index.html @@ -3,7 +3,7 @@ -DeployOnWindows | Higress +DeployOnWindows | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/ai_plugin/index.html b/blog/ai_plugin/index.html index a223fb5cc3..4e82dcf836 100644 --- a/blog/ai_plugin/index.html +++ b/blog/ai_plugin/index.html @@ -3,7 +3,7 @@ -ai_plugin | Higress +ai_plugin | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/archive/index.html b/blog/archive/index.html index 3848f22e6e..2e929639db 100644 --- a/blog/archive/index.html +++ b/blog/archive/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/blog/atom.xml b/blog/atom.xml index 1d262b2de7..43d6f8d665 100644 --- a/blog/atom.xml +++ b/blog/atom.xml @@ -2,7 +2,7 @@ https://higress.io/blog Higress Blog - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z https://github.com/jpmonette/feed Higress Blog @@ -11,7 +11,7 @@ <![CDATA[2023-kubecon]]> https://higress.io/blog/2023-kubecon - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -19,7 +19,7 @@ <![CDATA[30-line-wasm]]> https://higress.io/blog/30-line-wasm - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -27,7 +27,7 @@ <![CDATA[DeployOnWindows]]> https://higress.io/blog/DeployOnWindows - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -35,7 +35,7 @@ <![CDATA[ai_plugin]]> https://higress.io/blog/ai_plugin - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -43,7 +43,7 @@ <![CDATA[config-with-file]]> https://higress.io/blog/config-with-file - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -51,7 +51,7 @@ <![CDATA[configmap]]> https://higress.io/blog/configmap - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -59,7 +59,7 @@ <![CDATA[first-meetup]]> https://higress.io/blog/first-meetup - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -67,7 +67,7 @@ <![CDATA[higress]]> https://higress.io/blog/higress - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -75,7 +75,7 @@ <![CDATA[nacos]]> https://higress.io/blog/nacos - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -83,7 +83,7 @@ <![CDATA[ospp-2023]]> https://higress.io/blog/ospp-2023 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -91,7 +91,7 @@ <![CDATA[plugin-transformer]]> https://higress.io/blog/plugin-transformer - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -99,7 +99,7 @@ <![CDATA[release-070]]> https://higress.io/blog/release-070 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -107,7 +107,7 @@ <![CDATA[release-1.3]]> https://higress.io/blog/release-1.3 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -115,7 +115,7 @@ <![CDATA[release-100]]> https://higress.io/blog/release-100 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -123,7 +123,7 @@ <![CDATA[skywalking]]> https://higress.io/blog/skywalking - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -131,7 +131,7 @@ <![CDATA[user-mq]]> https://higress.io/blog/user-mq - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -139,7 +139,7 @@ <![CDATA[user-uu]]> https://higress.io/blog/user-uu - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
diff --git a/blog/config-with-file/index.html b/blog/config-with-file/index.html index 959e5f6676..ed91636d4f 100644 --- a/blog/config-with-file/index.html +++ b/blog/config-with-file/index.html @@ -3,7 +3,7 @@ -config-with-file | Higress +config-with-file | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/configmap/index.html b/blog/configmap/index.html index c17754608b..5ed1c75769 100644 --- a/blog/configmap/index.html +++ b/blog/configmap/index.html @@ -3,7 +3,7 @@ -configmap | Higress +configmap | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/first-meetup/index.html b/blog/first-meetup/index.html index 90e3837366..bceef6faec 100644 --- a/blog/first-meetup/index.html +++ b/blog/first-meetup/index.html @@ -3,7 +3,7 @@ -first-meetup | Higress +first-meetup | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/higress/index.html b/blog/higress/index.html index e7848d4ea8..1f95de5f7a 100644 --- a/blog/higress/index.html +++ b/blog/higress/index.html @@ -3,7 +3,7 @@ -higress | Higress +higress | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/index.html b/blog/index.html index 728ffc90c3..ca6a616e2b 100644 --- a/blog/index.html +++ b/blog/index.html @@ -14,13 +14,13 @@ - +
-

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

- +

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

+ \ No newline at end of file diff --git a/blog/nacos/index.html b/blog/nacos/index.html index 9a226f54b1..f82e564e75 100644 --- a/blog/nacos/index.html +++ b/blog/nacos/index.html @@ -3,7 +3,7 @@ -nacos | Higress +nacos | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/ospp-2023/index.html b/blog/ospp-2023/index.html index 3aa15c66ad..9ffa9cfe28 100644 --- a/blog/ospp-2023/index.html +++ b/blog/ospp-2023/index.html @@ -3,7 +3,7 @@ -ospp-2023 | Higress +ospp-2023 | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/page/2/index.html b/blog/page/2/index.html index 2aeac889d3..be43739511 100644 --- a/blog/page/2/index.html +++ b/blog/page/2/index.html @@ -14,13 +14,13 @@ - +
-

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

- +

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

+ \ No newline at end of file diff --git a/blog/plugin-transformer/index.html b/blog/plugin-transformer/index.html index b34e73cb83..47821257ba 100644 --- a/blog/plugin-transformer/index.html +++ b/blog/plugin-transformer/index.html @@ -3,7 +3,7 @@ -plugin-transformer | Higress +plugin-transformer | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/release-070/index.html b/blog/release-070/index.html index 013e35b4e9..dc7b5825cd 100644 --- a/blog/release-070/index.html +++ b/blog/release-070/index.html @@ -3,7 +3,7 @@ -release-070 | Higress +release-070 | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/release-1.3/index.html b/blog/release-1.3/index.html index 8a00f5bdc4..bc542282c6 100644 --- a/blog/release-1.3/index.html +++ b/blog/release-1.3/index.html @@ -3,7 +3,7 @@ -release-1.3 | Higress +release-1.3 | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/release-100/index.html b/blog/release-100/index.html index 0fedb5cb29..0dce2f6088 100644 --- a/blog/release-100/index.html +++ b/blog/release-100/index.html @@ -3,7 +3,7 @@ -release-100 | Higress +release-100 | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/rss.xml b/blog/rss.xml index 10a210a245..be54a84ba4 100644 --- a/blog/rss.xml +++ b/blog/rss.xml @@ -4,7 +4,7 @@ Higress Blog https://higress.io/blog Higress Blog - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed default @@ -12,7 +12,7 @@ <![CDATA[2023-kubecon]]> https://higress.io/blog/2023-kubecon https://higress.io/blog/2023-kubecon - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -20,7 +20,7 @@ <![CDATA[30-line-wasm]]> https://higress.io/blog/30-line-wasm https://higress.io/blog/30-line-wasm - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -28,7 +28,7 @@ <![CDATA[DeployOnWindows]]> https://higress.io/blog/DeployOnWindows https://higress.io/blog/DeployOnWindows - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -36,7 +36,7 @@ <![CDATA[ai_plugin]]> https://higress.io/blog/ai_plugin https://higress.io/blog/ai_plugin - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -44,7 +44,7 @@ <![CDATA[config-with-file]]> https://higress.io/blog/config-with-file https://higress.io/blog/config-with-file - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -52,7 +52,7 @@ <![CDATA[configmap]]> https://higress.io/blog/configmap https://higress.io/blog/configmap - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -60,7 +60,7 @@ <![CDATA[first-meetup]]> https://higress.io/blog/first-meetup https://higress.io/blog/first-meetup - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -68,7 +68,7 @@ <![CDATA[higress]]> https://higress.io/blog/higress https://higress.io/blog/higress - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -76,7 +76,7 @@ <![CDATA[nacos]]> https://higress.io/blog/nacos https://higress.io/blog/nacos - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -84,7 +84,7 @@ <![CDATA[ospp-2023]]> https://higress.io/blog/ospp-2023 https://higress.io/blog/ospp-2023 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -92,7 +92,7 @@ <![CDATA[plugin-transformer]]> https://higress.io/blog/plugin-transformer https://higress.io/blog/plugin-transformer - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -100,7 +100,7 @@ <![CDATA[release-070]]> https://higress.io/blog/release-070 https://higress.io/blog/release-070 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -108,7 +108,7 @@ <![CDATA[release-1.3]]> https://higress.io/blog/release-1.3 https://higress.io/blog/release-1.3 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -116,7 +116,7 @@ <![CDATA[release-100]]> https://higress.io/blog/release-100 https://higress.io/blog/release-100 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -124,7 +124,7 @@ <![CDATA[skywalking]]> https://higress.io/blog/skywalking https://higress.io/blog/skywalking - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -132,7 +132,7 @@ <![CDATA[user-mq]]> https://higress.io/blog/user-mq https://higress.io/blog/user-mq - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -140,7 +140,7 @@ <![CDATA[user-uu]]> https://higress.io/blog/user-uu https://higress.io/blog/user-uu - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
diff --git a/blog/skywalking/index.html b/blog/skywalking/index.html index 9c0294bb85..c85e937c7b 100644 --- a/blog/skywalking/index.html +++ b/blog/skywalking/index.html @@ -3,7 +3,7 @@ -skywalking | Higress +skywalking | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/user-mq/index.html b/blog/user-mq/index.html index 94c476a8ad..92a3b5ca82 100644 --- a/blog/user-mq/index.html +++ b/blog/user-mq/index.html @@ -3,7 +3,7 @@ -user-mq | Higress +user-mq | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/blog/user-uu/index.html b/blog/user-uu/index.html index bd4952115c..c99ebdee22 100644 --- a/blog/user-uu/index.html +++ b/blog/user-uu/index.html @@ -3,7 +3,7 @@ -user-uu | Higress +user-uu | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/community/contactItem/index.html b/community/contactItem/index.html index 5ac7fb7cf6..e75d86adf3 100644 --- a/community/contactItem/index.html +++ b/community/contactItem/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/community/contributorItem/index.html b/community/contributorItem/index.html index cce75b05cd..34f9b56739 100644 --- a/community/contributorItem/index.html +++ b/community/contributorItem/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/community/eventCard/index.html b/community/eventCard/index.html index c62a7b95f5..bc74d408a5 100644 --- a/community/eventCard/index.html +++ b/community/eventCard/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/community/index.html b/community/index.html index e7085747dc..aa259c7a66 100644 --- a/community/index.html +++ b/community/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/docs/dev/CustomResourceDefinition/index.html b/docs/dev/CustomResourceDefinition/index.html index 2debcb6d22..d66155b70e 100644 --- a/docs/dev/CustomResourceDefinition/index.html +++ b/docs/dev/CustomResourceDefinition/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/dev/architecture/index.html b/docs/dev/architecture/index.html index 0835a009b6..99a4264f59 100644 --- a/docs/dev/architecture/index.html +++ b/docs/dev/architecture/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/dev/code/index.html b/docs/dev/code/index.html index 8692196c60..c76db91c04 100644 --- a/docs/dev/code/index.html +++ b/docs/dev/code/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/committer-guide/label-an-issue-guide_dev/index.html b/docs/developers/committer-guide/label-an-issue-guide_dev/index.html index 13c4dbf23b..5a3828c567 100644 --- a/docs/developers/committer-guide/label-an-issue-guide_dev/index.html +++ b/docs/developers/committer-guide/label-an-issue-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/committer-guide/release-guide_dev/index.html b/docs/developers/committer-guide/release-guide_dev/index.html index 54ed619d03..8d6fd44c52 100644 --- a/docs/developers/committer-guide/release-guide_dev/index.html +++ b/docs/developers/committer-guide/release-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/committer-guide/website-guide_dev/index.html b/docs/developers/committer-guide/website-guide_dev/index.html index d9e97e4353..26c2824eea 100644 --- a/docs/developers/committer-guide/website-guide_dev/index.html +++ b/docs/developers/committer-guide/website-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/contributor-guide/new-contributor-guide_dev/index.html b/docs/developers/contributor-guide/new-contributor-guide_dev/index.html index b83f026fc4..a570f6526f 100644 --- a/docs/developers/contributor-guide/new-contributor-guide_dev/index.html +++ b/docs/developers/contributor-guide/new-contributor-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/contributor-guide/reporting-security-issues_dev/index.html b/docs/developers/contributor-guide/reporting-security-issues_dev/index.html index 586f6456a9..cbfdcb98f3 100644 --- a/docs/developers/contributor-guide/reporting-security-issues_dev/index.html +++ b/docs/developers/contributor-guide/reporting-security-issues_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/contributor-guide/test-coverage-guide_dev/index.html b/docs/developers/contributor-guide/test-coverage-guide_dev/index.html index 74aa04826b..b20e302d50 100644 --- a/docs/developers/contributor-guide/test-coverage-guide_dev/index.html +++ b/docs/developers/contributor-guide/test-coverage-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/developers_dev/index.html b/docs/developers/developers_dev/index.html index f4e6757279..7df93419d0 100644 --- a/docs/developers/developers_dev/index.html +++ b/docs/developers/developers_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/developers/guide_dev/index.html b/docs/developers/guide_dev/index.html index fb54f1a762..8606cebdfa 100644 --- a/docs/developers/guide_dev/index.html +++ b/docs/developers/guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/ops/deploy-by-docker-compose/index.html b/docs/ops/deploy-by-docker-compose/index.html index 1b93b6d64c..344ef66039 100644 --- a/docs/ops/deploy-by-docker-compose/index.html +++ b/docs/ops/deploy-by-docker-compose/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/ops/deploy-by-helm/index.html b/docs/ops/deploy-by-helm/index.html index a39642fd95..e124da8a24 100644 --- a/docs/ops/deploy-by-helm/index.html +++ b/docs/ops/deploy-by-helm/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/ops/hgctl/index.html b/docs/ops/hgctl/index.html index d0a635a151..82c3873dc0 100644 --- a/docs/ops/hgctl/index.html +++ b/docs/ops/hgctl/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/ops/log/index.html b/docs/ops/log/index.html index 1f7dc389eb..5752ed1cb1 100644 --- a/docs/ops/log/index.html +++ b/docs/ops/log/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/ops/upgrade/index.html b/docs/ops/upgrade/index.html index e190301557..71bc04aafc 100644 --- a/docs/ops/upgrade/index.html +++ b/docs/ops/upgrade/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/overview/faq/index.html b/docs/overview/faq/index.html index 0f3228ef04..5702a05077 100644 --- a/docs/overview/faq/index.html +++ b/docs/overview/faq/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/overview/roadmap/index.html b/docs/overview/roadmap/index.html index d317f5383e..ab2930b72a 100644 --- a/docs/overview/roadmap/index.html +++ b/docs/overview/roadmap/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/overview/terminology/index.html b/docs/overview/terminology/index.html index 81a88e91dc..88e6ead369 100644 --- a/docs/overview/terminology/index.html +++ b/docs/overview/terminology/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/overview/what-is-higress/index.html b/docs/overview/what-is-higress/index.html index f357a7046b..c90c23bf6f 100644 --- a/docs/overview/what-is-higress/index.html +++ b/docs/overview/what-is-higress/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/basic-auth/index.html b/docs/plugins/basic-auth/index.html index 2207da4354..e616f43c9f 100644 --- a/docs/plugins/basic-auth/index.html +++ b/docs/plugins/basic-auth/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/bot-detect/index.html b/docs/plugins/bot-detect/index.html index 3777b7e23b..2a71b04f27 100644 --- a/docs/plugins/bot-detect/index.html +++ b/docs/plugins/bot-detect/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/custom-response/index.html b/docs/plugins/custom-response/index.html index 16235187ce..a4b68f4e7f 100644 --- a/docs/plugins/custom-response/index.html +++ b/docs/plugins/custom-response/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/custom/index.html b/docs/plugins/custom/index.html index 749ce64f30..82ca110af7 100644 --- a/docs/plugins/custom/index.html +++ b/docs/plugins/custom/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/hmac-auth/index.html b/docs/plugins/hmac-auth/index.html index 7d36d64c8b..a082a58958 100644 --- a/docs/plugins/hmac-auth/index.html +++ b/docs/plugins/hmac-auth/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/intro/index.html b/docs/plugins/intro/index.html index d19f3ae264..5f5ded0277 100644 --- a/docs/plugins/intro/index.html +++ b/docs/plugins/intro/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/jwt-auth/index.html b/docs/plugins/jwt-auth/index.html index c2d9620d01..41e05f0e63 100644 --- a/docs/plugins/jwt-auth/index.html +++ b/docs/plugins/jwt-auth/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/key-auth/index.html b/docs/plugins/key-auth/index.html index ab7dba0545..128ce1969b 100644 --- a/docs/plugins/key-auth/index.html +++ b/docs/plugins/key-auth/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/key-rate-limit/index.html b/docs/plugins/key-rate-limit/index.html index 755a78765b..86a1066312 100644 --- a/docs/plugins/key-rate-limit/index.html +++ b/docs/plugins/key-rate-limit/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/request-block/index.html b/docs/plugins/request-block/index.html index d5cbcc9e0e..8f150656a9 100644 --- a/docs/plugins/request-block/index.html +++ b/docs/plugins/request-block/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/plugins/waf/index.html b/docs/plugins/waf/index.html index 1d1f0f2d9e..be9cf511c6 100644 --- a/docs/plugins/waf/index.html +++ b/docs/plugins/waf/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/annotation-use-case/index.html b/docs/user/annotation-use-case/index.html index 1a1722429b..71b282a932 100644 --- a/docs/user/annotation-use-case/index.html +++ b/docs/user/annotation-use-case/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/annotation/index.html b/docs/user/annotation/index.html index 8e8b6e8929..d2f124824f 100644 --- a/docs/user/annotation/index.html +++ b/docs/user/annotation/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/configmap/index.html b/docs/user/configmap/index.html index 026d1f3575..7ced87771e 100644 --- a/docs/user/configmap/index.html +++ b/docs/user/configmap/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/configurations/index.html b/docs/user/configurations/index.html index 53e4bcbf65..d3395f74ac 100644 --- a/docs/user/configurations/index.html +++ b/docs/user/configurations/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/dubbo-http2rpc/index.html b/docs/user/dubbo-http2rpc/index.html index f6f6525ec3..fcc8dbcfbb 100644 --- a/docs/user/dubbo-http2rpc/index.html +++ b/docs/user/dubbo-http2rpc/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/dubbo/index.html b/docs/user/dubbo/index.html index 4283edf894..a17643ca7c 100644 --- a/docs/user/dubbo/index.html +++ b/docs/user/dubbo/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/kruise-rollout/index.html b/docs/user/kruise-rollout/index.html index e7e8e849de..2ead57aece 100644 --- a/docs/user/kruise-rollout/index.html +++ b/docs/user/kruise-rollout/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/mcp-bridge/index.html b/docs/user/mcp-bridge/index.html index 336db1ca99..8d8a8f9095 100644 --- a/docs/user/mcp-bridge/index.html +++ b/docs/user/mcp-bridge/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/nacos-route/index.html b/docs/user/nacos-route/index.html index 22eb3bf7a5..a7dd6cc23f 100644 --- a/docs/user/nacos-route/index.html +++ b/docs/user/nacos-route/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/nginx-ingress-migrate/index.html b/docs/user/nginx-ingress-migrate/index.html index f1d4d8ea2e..3985158ce0 100644 --- a/docs/user/nginx-ingress-migrate/index.html +++ b/docs/user/nginx-ingress-migrate/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/docs/user/nginx-ingress/index.html b/docs/user/nginx-ingress/index.html index 5f636be550..b898c3f5c9 100644 --- a/docs/user/nginx-ingress/index.html +++ b/docs/user/nginx-ingress/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/opensergo-gray/index.html b/docs/user/opensergo-gray/index.html index a6acf75adc..b06783773a 100644 --- a/docs/user/opensergo-gray/index.html +++ b/docs/user/opensergo-gray/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/prometheus/index.html b/docs/user/prometheus/index.html index 8672d0baec..f99a22d74e 100644 --- a/docs/user/prometheus/index.html +++ b/docs/user/prometheus/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/quickstart/index.html b/docs/user/quickstart/index.html index 085800391e..a00a0c8138 100644 --- a/docs/user/quickstart/index.html +++ b/docs/user/quickstart/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/sentinel/index.html b/docs/user/sentinel/index.html index 6a3a754111..e8fb163e86 100644 --- a/docs/user/sentinel/index.html +++ b/docs/user/sentinel/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/spring-cloud/index.html b/docs/user/spring-cloud/index.html index 89f6f19679..4e530b5d21 100644 --- a/docs/user/spring-cloud/index.html +++ b/docs/user/spring-cloud/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/waf/index.html b/docs/user/waf/index.html index 649a6e0f1e..7b2756cb13 100644 --- a/docs/user/waf/index.html +++ b/docs/user/waf/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/wasm-go/index.html b/docs/user/wasm-go/index.html index 3f6f764366..4a60e225d1 100644 --- a/docs/user/wasm-go/index.html +++ b/docs/user/wasm-go/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/docs/user/wasm-image-spec/index.html b/docs/user/wasm-image-spec/index.html index 4fb8c90a3c..5f8928f785 100644 --- a/docs/user/wasm-image-spec/index.html +++ b/docs/user/wasm-image-spec/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/404.html b/en-us/404.html index c4a164dd7f..a7595d93aa 100644 --- a/en-us/404.html +++ b/en-us/404.html @@ -14,13 +14,13 @@ - +

Page Not Found

We could not find what you were looking for.

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

- + \ No newline at end of file diff --git a/en-us/assets/js/0b0fed00.f50761c0.js b/en-us/assets/js/0b0fed00.f50761c0.js new file mode 100644 index 0000000000..4cb8ddddea --- /dev/null +++ b/en-us/assets/js/0b0fed00.f50761c0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3269],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>g});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function i(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),p=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):i(i({},r),e)),t},u=function(e){var r=p(e.components);return n.createElement(c.Provider,{value:r},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(t),m=o,g=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return t?n.createElement(g,i(i({ref:r},u),{},{components:t})):n.createElement(g,i({ref:r},u))}));function g(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=m;var l={};for(var c in r)hasOwnProperty.call(r,c)&&(l[c]=r[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const a={},i=void 0,l={permalink:"/en-us/blog/plugin-transformer",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/plugin-transformer.md",source:"@site/blog/plugin-transformer.md",title:"plugin-transformer",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"ospp-2023",permalink:"/en-us/blog/ospp-2023"},nextItem:{title:"release-070",permalink:"/en-us/blog/release-070"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(s,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/32f852b2.20b07853.js b/en-us/assets/js/32f852b2.20b07853.js new file mode 100644 index 0000000000..af0e0aa5aa --- /dev/null +++ b/en-us/assets/js/32f852b2.20b07853.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2338],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),s=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},u=function(e){var r=s(e.components);return n.createElement(c.Provider,{value:r},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=s(t),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return t?n.createElement(b,l(l({ref:r},u),{},{components:t})):n.createElement(b,l({ref:r},u))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,l=new Array(a);l[0]=m;var i={};for(var c in r)hasOwnProperty.call(r,c)&&(i[c]=r[c]);i.originalType=e,i[p]="string"==typeof e?e:o,l[1]=i;for(var s=2;s{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>s});var n=t(7462),o=(t(7294),t(3905));const a={},l=void 0,i={permalink:"/en-us/blog/release-070",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-070.md",source:"@site/blog/release-070.md",title:"release-070",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"plugin-transformer",permalink:"/en-us/blog/plugin-transformer"},nextItem:{title:"release-1.3",permalink:"/en-us/blog/release-1.3"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(p,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/34064e98.61fffd2a.js b/en-us/assets/js/34064e98.61fffd2a.js new file mode 100644 index 0000000000..2f9a9c05be --- /dev/null +++ b/en-us/assets/js/34064e98.61fffd2a.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7833],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>g});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function i(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),p=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):i(i({},r),e)),t},u=function(e){var r=p(e.components);return n.createElement(c.Provider,{value:r},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),s=p(t),m=o,g=s["".concat(c,".").concat(m)]||s[m]||f[m]||a;return t?n.createElement(g,i(i({ref:r},u),{},{components:t})):n.createElement(g,i({ref:r},u))}));function g(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,i=new Array(a);i[0]=m;var l={};for(var c in r)hasOwnProperty.call(r,c)&&(l[c]=r[c]);l.originalType=e,l[s]="string"==typeof e?e:o,i[1]=l;for(var p=2;p{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>p});var n=t(7462),o=(t(7294),t(3905));const a={},i=void 0,l={permalink:"/en-us/blog/plugin-transformer",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/plugin-transformer.md",source:"@site/blog/plugin-transformer.md",title:"plugin-transformer",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"ospp-2023",permalink:"/en-us/blog/ospp-2023"},nextItem:{title:"release-070",permalink:"/en-us/blog/release-070"}},c={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(s,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/452368c1.fcf440dd.js b/en-us/assets/js/452368c1.fcf440dd.js new file mode 100644 index 0000000000..1a8fc0d544 --- /dev/null +++ b/en-us/assets/js/452368c1.fcf440dd.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[165],{4755:e=>{e.exports=JSON.parse('{"blogPosts":[{"id":"/2023-kubecon","metadata":{"permalink":"/en-us/blog/2023-kubecon","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/2023-kubecon.md","source":"@site/blog/2023-kubecon.md","title":"2023-kubecon","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"nextItem":{"title":"DeployOnWindows","permalink":"/en-us/blog/DeployOnWindows"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/DeployOnWindows","metadata":{"permalink":"/en-us/blog/DeployOnWindows","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/DeployOnWindows.md","source":"@site/blog/DeployOnWindows.md","title":"DeployOnWindows","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"2023-kubecon","permalink":"/en-us/blog/2023-kubecon"},"nextItem":{"title":"config-with-file","permalink":"/en-us/blog/config-with-file"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/config-with-file","metadata":{"permalink":"/en-us/blog/config-with-file","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/config-with-file.md","source":"@site/blog/config-with-file.md","title":"config-with-file","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"DeployOnWindows","permalink":"/en-us/blog/DeployOnWindows"},"nextItem":{"title":"configmap","permalink":"/en-us/blog/configmap"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/configmap","metadata":{"permalink":"/en-us/blog/configmap","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/configmap.md","source":"@site/blog/configmap.md","title":"configmap","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"config-with-file","permalink":"/en-us/blog/config-with-file"},"nextItem":{"title":"ospp-2023","permalink":"/en-us/blog/ospp-2023"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/ospp-2023","metadata":{"permalink":"/en-us/blog/ospp-2023","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/ospp-2023.md","source":"@site/blog/ospp-2023.md","title":"ospp-2023","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"configmap","permalink":"/en-us/blog/configmap"},"nextItem":{"title":"plugin-transformer","permalink":"/en-us/blog/plugin-transformer"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/plugin-transformer","metadata":{"permalink":"/en-us/blog/plugin-transformer","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/plugin-transformer.md","source":"@site/blog/plugin-transformer.md","title":"plugin-transformer","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"ospp-2023","permalink":"/en-us/blog/ospp-2023"},"nextItem":{"title":"release-070","permalink":"/en-us/blog/release-070"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/release-070","metadata":{"permalink":"/en-us/blog/release-070","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-070.md","source":"@site/blog/release-070.md","title":"release-070","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"plugin-transformer","permalink":"/en-us/blog/plugin-transformer"},"nextItem":{"title":"release-1.3","permalink":"/en-us/blog/release-1.3"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/release-1.3","metadata":{"permalink":"/en-us/blog/release-1.3","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-1.3.md","source":"@site/blog/release-1.3.md","title":"release-1.3","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"release-070","permalink":"/en-us/blog/release-070"},"nextItem":{"title":"release-100","permalink":"/en-us/blog/release-100"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/release-100","metadata":{"permalink":"/en-us/blog/release-100","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-100.md","source":"@site/blog/release-100.md","title":"release-100","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"release-1.3","permalink":"/en-us/blog/release-1.3"},"nextItem":{"title":"skywalking","permalink":"/en-us/blog/skywalking"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/skywalking","metadata":{"permalink":"/en-us/blog/skywalking","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/skywalking.md","source":"@site/blog/skywalking.md","title":"skywalking","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"release-100","permalink":"/en-us/blog/release-100"},"nextItem":{"title":"user-mq","permalink":"/en-us/blog/user-mq"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/user-mq","metadata":{"permalink":"/en-us/blog/user-mq","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/user-mq.md","source":"@site/blog/user-mq.md","title":"user-mq","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"skywalking","permalink":"/en-us/blog/skywalking"},"nextItem":{"title":"user-uu","permalink":"/en-us/blog/user-uu"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/user-uu","metadata":{"permalink":"/en-us/blog/user-uu","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/user-uu.md","source":"@site/blog/user-uu.md","title":"user-uu","description":"Placeholder. DO NOT DELETE.","date":"2023-11-16T06:51:43.000Z","formattedDate":"November 16, 2023","tags":[],"readingTime":0.02,"hasTruncateMarker":false,"authors":[],"frontMatter":{},"prevItem":{"title":"user-mq","permalink":"/en-us/blog/user-mq"},"nextItem":{"title":"AIGC OpenAPI Cost Reduction via Higress","permalink":"/en-us/blog/ai_plugin"}},"content":"Placeholder. DO NOT DELETE."},{"id":"/ai_plugin","metadata":{"permalink":"/en-us/blog/ai_plugin","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/ai_plugin.md","source":"@site/i18n/en-us/docusaurus-plugin-content-blog/ai_plugin.md","title":"AIGC OpenAPI Cost Reduction via Higress","description":"This paper introduces the usage of higress in AIGC application.","date":"2023-07-12T00:00:00.000Z","formattedDate":"July 12, 2023","tags":[],"readingTime":8.465,"hasTruncateMarker":false,"authors":[{"name":"Weiji Zhao"}],"frontMatter":{"title":"AIGC OpenAPI Cost Reduction via Higress","keywords":["Higress","AIGC","AI plugin"],"description":"This paper introduces the usage of higress in AIGC application.","author":"Weiji Zhao","date":"2023-07-12T00:00:00.000Z","custom_edit_url":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en/docusaurus-plugin-content-blog/ai_plugin.md"},"prevItem":{"title":"user-uu","permalink":"/en-us/blog/user-uu"},"nextItem":{"title":"Higress + Nacos Microservice Gateway Best Practices","permalink":"/en-us/blog/nacos"}},"content":"AIGC applications represented by ChatGPT have brought great changes to enterprise production and greatly improved people\'s production efficiency. Large AI models can help to complete various complex tasks, such as helping developers write, debug and record codes, researchers quickly understand scientific research fields, marketers write product descriptions, etc. More and more enterprises have begun to attach importance to AIGC application development. How to manage the API of large AI models through the gateway has become a concern. \\n \\n[Higress](https://github.com/alibaba/higress/blob/main/README_EN.md) is a next-generation cloud-native gateway based on Alibaba\'s internal gateway practices. Powered by [Istio](https://github.com/istio/istio) and [Envoy](https://github.com/envoyproxy/envoy), Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway, and security gateway, thereby greatly reducing the costs of deployment, operation, and maintenance. Based on the rich capabilities provided by Higress, enterprises can greatly reduce the cost of using large AI models.\\n\\n# How does Higress reduce the cost of using AI models?\\n\\nTaking OpenAI as an example, OpenAI\'s APIs are priced not based on the number of requests or subscription time but based on the usage of each request. For large AI models, tokens are the standard billing strategy for OpenAI API as a measure of the complexity of inference tasks. The cost for tokens varies based on the model. Generally, more complex models give better results at a higher cost. API Keys are distributed to consumers for authentication and charging. \\n\\n![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/103456511/1688523788955-ef30f3fa-9916-48cf-baf7-dcdc9d733a8a.png#clientId=u000cf9ed-697b-4&from=paste&height=303&id=VzJLA&originHeight=1436&originWidth=3392&originalType=binary&ratio=2&rotation=0&showTitle=false&size=3514703&status=done&style=none&taskId=uf85155a3-3c08-4964-a503-f0274c5869f&title=&width=715.9957275390625)\\n \\nIt is unrealistic for an organization to apply for an API Key for each member. Scattered API keys will not be conducive to the organization\'s calculation, management, and payment of API usage, thereby increasing the cost of using large AI models. For organizations, the selection and access rights of AI models, the frequency of use of AI models and access permissions, and the management and protection of data exposed to AI models are all important API management. \\n \\nBased on rich plugin capabilities, Higress provides functions such as authentication, request filtering, traffic control, usage monitoring, and security protection, helping organizations interact with large AI model APIs more securely, reliably, and observably. Based on the **authentication** provided by Higress, organizations can implement multi-tenant authentication and grant different AI model access rights to team members; based on the **traffic control** capability, organizations can set differentiated access rate limits for different models and users, effectively reducing the cost of using AI model; based on the **request interception** capability, organizations can effectively filter access requests containing sensitive information, and protect some internal site resources from being exposed to the outside world, effectively ensuring data security. Based on the index query and log system capabilities provided by [Commercial Higress](https://www.aliyun.com/product/aliware/mse?spm=higress-website.topbar.0.0.0), organizations can **observe** and **analyze** the usage of AI model calls by different users to formulate more reasonable AI model usage strategies. \\n\\n![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/103456511/1689125555906-388e3f46-4070-414e-9f67-293bfc8c49e2.png#clientId=u7d7dc920-d9bf-4&from=paste&height=373&id=u5c1bba9d&originHeight=820&originWidth=2302&originalType=binary&ratio=2.200000047683716&rotation=0&showTitle=false&size=1205356&status=done&style=none&taskId=u6a5fcf97-095d-4300-9831-749a537703c&title=&width=1046.3636136843159)\\n\\n# Manage OpenAI API with Higress\\n\\nWe will take Higress connecting to the OpenAI API as an example to introduce how Higress seamlessly connects to the large AI model. The overall solution is shown in Fig.3. We have extended the Higress plugin based on WASM to proxy requests to the OpenAI language model. Based on authentication plugins such as Key Auth, we implement multi-tenant authentication under a unified OpenAI API-Key. Based on the Request-Block plugin, we implement the interception of requests with sensitive information and ensure data protection.\\n\\n![](https://intranetproxy.alipay.com/skylark/lark/0/2023/jpeg/103456511/1689043915532-1c902ce8-9d12-4b5b-8577-5f9b8711b272.jpeg)\\n \\n## Prerequisites\\n\\n1. Install Higress. Please refer to [Deploy Higress by Helm](https://higress.io/en-us/docs/ops/deploy-by-helm/).\\n2. Prepare the development environment for WASM plugins with Golang. Please refer to [Developing a WASM plugin with Golang | Higress](https://higress.io/en-us/docs/user/wasm-go/).\\n\\n## AI Proxy WASM Plugin \\n\\nThe following will give the AI proxy plugin implementation based on Higress and WASM. Higress supports scalability externally based on WASM. The multi-language ecology and hot-swapping mechanism provided by the WASM facilitate the implementation and deployment of the plugin. Higress also supports requesting external services in the plugin, which provides an efficient solution path for the implementation of the AI proxy plugin.\\n\\n### Code Implementation\\n\\nThe following code implements the request proxy to OPENAI-API based on HTTP. For details, please refer to the [AI proxy plugin](https://github.com/alibaba/higress/tree/main/plugins/wasm-go/extensions/chatgpt-proxy). The specific implementation steps are as follows:\\n\\n1. Create a new HTTP client, specify the OpenAI API host through the RouteCluster method, and determine the request proxy path.\\n\\n```go\\nfunc parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {\\n\\t//The default forwarding path is OpenAI API. \\n //Users can adjust through configuration.\\n chatgptUri := json.Get(\\"chatgptUri\\").String()\\n\\tvar chatgptHost string\\n\\tif chatgptUri == \\"\\" {\\n\\t\\tconfig.ChatgptPath = \\"/v1/completions\\"\\n\\t\\tchatgptHost = \\"api.openai.com\\"\\n\\t}\\n ...\\n //Specify the specific request proxy host through RouteCluster.\\n\\tconfig.client = wrapper.NewClusterClient(wrapper.RouteCluster{\\n\\t\\tHost: chatgptHost,\\n\\t}) \\n ...\\n}\\n \\n```\\n\\n2. Encapsulate the request in the OpenAI-API format, send requests and receive responses through the HTTP Client, and send responses to the user.\\n\\n```go\\n//OPENAI API request body template. Please refer to https://platform.openai.com/docs/api-reference/chat\\nconst bodyTemplate string = `\\n{\\n\\"model\\":\\"%s\\",\\n\\"prompt\\":\\"%s\\",\\n\\"temperature\\":0.9,\\n\\"max_tokens\\": 150,\\n\\"top_p\\": 1,\\n\\"frequency_penalty\\": 0.0,\\n\\"presence_penalty\\": 0.6,\\n\\"stop\\": [\\"%s\\", \\"%s\\"]\\n}\\n`\\nfunc onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {\\n ...\\n //Encapsulate the OPENAI API request body according to the user\'s request content.\\n\\tbody := fmt.Sprintf(bodyTemplate, config.Model, prompt[0], config.HumanId, config.AIId)\\n\\t//Post request via HTTP client.\\n err = config.client.Post(config.ChatgptPath, [][2]string{\\n\\t\\t{\\"Content-Type\\", \\"application/json\\"},\\n\\t\\t{\\"Authorization\\", \\"Bearer \\" + config.ApiKey},\\n\\t}, []byte(body),\\n\\t\\tfunc(statusCode int, responseHeaders http.Header, responseBody []byte) {\\n\\t\\t\\tvar headers [][2]string\\n\\t\\t\\tfor key, value := range responseHeaders {\\n\\t\\t\\t\\theaders = append(headers, [2]string{key, value[0]})\\n\\t\\t\\t}\\n //Receive the response from the OPENAI API and send it to user\\n\\t\\t\\tproxywasm.SendHttpResponse(uint32(statusCode), headers, responseBody, -1)\\n\\t\\t}, 10000)\\n ...\\n}\\n```\\n\\nEnable the custom AI-Proxy-Wasm plugin in Higress as follows:\\n\\n![](https://intranetproxy.alipay.com/skylark/lark/0/2023/jpeg/103456511/1689128762997-2b14f1b5-8120-427a-b503-dab6e286de53.jpeg)\\n \\nThis example provides the compiled AI-proxy-plugin WASM file and completes the construction and push of the docker image. The recommended configuration is as follows:\\n\\n| **Name** | **Recommended configuration** |\\n| --- | --- |\\n| Image URL | oci://registry.cn-hangzhou.aliyuncs.com/zwj_test/chatgpt-proxy:1.0.0 |\\n| Plugin Execution Phase | Authz |\\n| Plugin Execution Priority | 1 |\\n\\n### Plugin configuration instructions\\n\\nAI-Proxy-Plugin is easy to configure and supports proxy forwarding at the global/domain name level/routing level. Route-level configuration is recommended: **route config**-**strategy**-**enable plugin**. An example configuration is as follows\uff1a\\n\\n```yaml\\napiKey: \\"xxxxxxxxxxxxxxxxxx\\"\\nmodel: \\"curie\\"\\npromptParam: \\"text\\"\\n```\\n\\nAccording to this configuration, the gateway proxies to the Curie model in OpenAI, and the user enters prompts in the URL through the keyword \\"text\\".\\n\\n```shell\\ncurl \\"http://{GatewayIP}/?text=Say,hello\\"\\n```\\n\\nResponse from Curie model in OpenAI:\\n\\n![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/103456511/1688630702128-6060fad6-4e47-4223-bc02-d9a240db9263.png#clientId=u743d3343-6ab1-4&from=paste&height=137&id=FIkxG&originHeight=520&originWidth=3170&originalType=binary&ratio=1.100000023841858&rotation=0&showTitle=false&size=1213836&status=done&style=none&taskId=u38ba4744-5835-4092-8291-ddfede62f55&title=&width=833.178955078125)\\n\\n## Multi-tenant authentication based on Key Auth\\n\\nDifferent from the form of issuing AI-API keys for each member, enterprises can utilize internal authorization (such as Key Auth, etc.) and rely on the unified AI-API key for request proxy to achieve unified management of API usage. \\n\\nKey Auth implements the authentication based on the Gateway level API Key. Key Auth supports parsing the API Key from the URL parameter or request header of the HTTP requests and verifies whether the API has permission to access. \\n\\n![](https://intranetproxy.alipay.com/skylark/lark/0/2023/jpeg/103456511/1689140841602-01d8dd1d-7b9f-42a1-a951-d149e922ebac.jpeg)\\n \\n```yaml\\nconsumers:\\n- credential: \\"xxxxxx\\"\\n name: \\"consumer1\\"\\n- credential: \\"yyyyyy\\"\\n name: \\"consumer2\\"\\nglobal_auth: false\\nin_header: true\\nkeys:\\n- \\"apikey\\"\\n```\\n\\n![](https://intranetproxy.alipay.com/skylark/lark/0/2023/jpeg/103456511/1689130328559-c542f754-04ab-4c89-93b6-f6e511c9f0e2.jpeg)\\n \\n```yaml\\nallow: [consumer1]\\n```\\n\\nThe above configuration defines consumers, and only consumer1 has the access right to the AI model service under the current route.\\n\\n```yaml\\ncurl \\"http://{GatewayIP}/?text=Say,hello\\"\\n#The request does not provide an API Key, return 401\\n\\ncurl \\"http://{GatewayIP}/?text=Say,hello\\" -H \\"apikey:zzzzzz\\"\\n#The API Key provided by the request is not authorized to access, return 401\\n\\ncurl \\"http://{GatewayIP}/?text=Say,hello\\" -H \\"apikey:yyyyyy\\"\\n#The caller matched according to the API Key provided in the request has no access rights, return 403\\n\\ncurl \\"http://{GatewayIP}/?text=Say,hello\\" -H \\"apikey:xxxxxx\\"\\n#The caller has access to the AI model service, the request will be proxied to the AI model, and the response from the OpenAI API will be received normally\\n```\\n\\nIn addition to providing gateway-level multi-tenant authentication, Higress provides traffic control and other capabilities. The Key Rate Limit plugin can limit the user\'s application rate based on the user\'s membership in the consumption group. \\n\\n## Data protection based on Request Block\\n\\nFor AIGC applications, especially LLM services, a good return often requires users to provide enough prompts as model input. Users face the risk of data leakage in the process of providing prompts. Ensuring data security in the process of using the AIGC application is also an important issue for API callers. \\n\\nProtecting data security involves stringent control over the API calling channels. One method involves confirming specifically approved models with their published API. Another way is to intercept user requests containing sensitive information. These can be achieved by setting specific request interception at the gateway level. Higress provides request interception based on the request block plugin, which can prevent unauthorized models from accessing user information and prevent user requests containing sensitive information from being exposed to the external network.\\n![](https://intranetproxy.alipay.com/skylark/lark/0/2023/jpeg/103456511/1689131852975-b35f7a0d-8e4d-4fd0-b805-fa168159f94f.jpeg)\\n \\n```yaml\\nblocked_code: 404\\nblock_urls:\\n- password\\n- pw\\ncase_sensitive: false\\n```\\n\\nThe above configuration defines URL-based shielding fields under the current route, in which requests containing sensitive information such as \\"password\\" and \\"pw\\" will be blocked\u3002\\n\\n```yaml\\ncurl \\"http://{GatewayIP}/?text=Mypassword=xxxxxx\\" -H \\"apikey:xxxxxx\\"\\ncurl \\"http://{GatewayIP}/?text=pw=xxxxxx\\" -H \\"apikey:xxxxxx\\"\\n#The above request will be forbidden and return 404\\n```\\n## Usage observation and analysis\\n\\nFor organizations, observing and analyzing the usage of large AI model calls for each user helps to understand their usage and costs. It is also necessary for individual users to understand their own call volume and overhead. [Commercial Higress](https://www.aliyun.com/product/aliware/mse?spm=higress-website.topbar.0.0.0) is deeply integrated with various metrics and log systems and provides an out-of-the-box usage observation and analysis report construction mechanism, which can view the usage of various APIs in real time and filter according to various parameters.\\n\\nTaking the observation of each user\'s usage of the OPENAI-Curie model as an example, the administrator can set the observability parameter in the request header\uff1ax-mse-consumer, to distinguish users through **MSE console** - **Cloud native Gateway** - **Gateway instance** - **Parameter Configurator**- **Custom Format**. After adding the observability parameters, enter the **Observation Analysis **-** Log Center** to set the use statistics chart function to complete the observation and analysis of API usage. As shown in the figure below, the amount of calls to the OPENAI-Curie model of user consumer1 and user consumer2 is presented in the form of a pie chart.\\n\\n![image.png](https://intranetproxy.alipay.com/skylark/lark/0/2023/png/103456511/1689133126041-96a120ea-34b3-488a-8d75-8a296ac41b12.png#clientId=uaea7149c-f4cc-4&from=paste&height=400&id=u56e5ce08&originHeight=879&originWidth=2334&originalType=binary&ratio=2.200000047683716&rotation=0&showTitle=false&size=1418178&status=done&style=none&taskId=u99bdb280-d7e5-4c5c-acc8-dff0c104c03&title=&width=1060.909067914506)\\n\\n# Join the Higress community\\nJoin Higress Slack: [https://join.slack.com/t/w1689142780-euk177225/shared_invite/zt-1zbjm9d34-4nptVXPpNvnuKEKZ7V3MIg](https://join.slack.com/t/w1689142780-euk177225/shared_invite/zt-1zbjm9d34-4nptVXPpNvnuKEKZ7V3MIg)\\n\\nTo get invited: [https://communityinviter.com/apps/w1689142780-euk177225/higress](https://communityinviter.com/apps/w1689142780-euk177225/higress)\\n\\nIf you find Higress helpful, welcome to [Higress](https://github.com/alibaba/higress) to star us!"},{"id":"/nacos","metadata":{"permalink":"/en-us/blog/nacos","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/nacos.md","source":"@site/i18n/en-us/docusaurus-plugin-content-blog/nacos.md","title":"Higress + Nacos Microservice Gateway Best Practices","description":"Higress\uff1a the best partner of Nacos","date":"2023-01-10T00:00:00.000Z","formattedDate":"January 10, 2023","tags":[],"readingTime":0.005,"hasTruncateMarker":false,"authors":[{"name":"\u6f84\u6f6d"}],"frontMatter":{"title":"Higress + Nacos Microservice Gateway Best Practices","keywords":["higress","wasm"],"description":"Higress\uff1a the best partner of Nacos","author":"\u6f84\u6f6d","date":"2023-01-10T00:00:00.000Z","custom_edit_url":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en/docusaurus-plugin-content-blog/nacos.md"},"prevItem":{"title":"AIGC OpenAPI Cost Reduction via Higress","permalink":"/en-us/blog/ai_plugin"},"nextItem":{"title":"30 lines of code to write a Wasm Go plugin","permalink":"/en-us/blog/30-line-wasm"}},"content":"TBD"},{"id":"/30-line-wasm","metadata":{"permalink":"/en-us/blog/30-line-wasm","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/30-line-wasm.md","source":"@site/i18n/en-us/docusaurus-plugin-content-blog/30-line-wasm.md","title":"30 lines of code to write a Wasm Go plugin","description":"30 lines of code to write a Wasm Go plugin","date":"2022-11-22T00:00:00.000Z","formattedDate":"November 22, 2022","tags":[],"readingTime":0.005,"hasTruncateMarker":false,"authors":[{"name":"\u6f84\u6f6d"}],"frontMatter":{"title":"30 lines of code to write a Wasm Go plugin","keywords":["higress","wasm"],"description":"30 lines of code to write a Wasm Go plugin","author":"\u6f84\u6f6d","date":"2022-11-22T00:00:00.000Z","custom_edit_url":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en/docusaurus-plugin-content-blog/30-line-wasm.md"},"prevItem":{"title":"Higress + Nacos Microservice Gateway Best Practices","permalink":"/en-us/blog/nacos"},"nextItem":{"title":"Welcome to sign up for Higress\' first offline meetup","permalink":"/en-us/blog/first-meetup"}},"content":"TBD"},{"id":"/first-meetup","metadata":{"permalink":"/en-us/blog/first-meetup","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/first-meetup.md","source":"@site/i18n/en-us/docusaurus-plugin-content-blog/first-meetup.md","title":"Welcome to sign up for Higress\' first offline meetup","description":"Offline Meetup registration","date":"2022-11-22T00:00:00.000Z","formattedDate":"November 22, 2022","tags":[],"readingTime":0.01,"hasTruncateMarker":true,"authors":[{"name":"\u6f84\u6f6d"}],"frontMatter":{"title":"Welcome to sign up for Higress\' first offline meetup","keywords":["higress","meetup"],"description":"Offline Meetup registration","author":"\u6f84\u6f6d","date":"2022-11-22T00:00:00.000Z","custom_edit_url":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en/docusaurus-plugin-content-blog/first-meetup.md"},"prevItem":{"title":"30 lines of code to write a Wasm Go plugin","permalink":"/en-us/blog/30-line-wasm"},"nextItem":{"title":"Alibaba Open Source Cloud Native Gateway\uff1a Higress","permalink":"/en-us/blog/higress"}},"content":"\x3c!--truncate--\x3e\\n![](https://img.alicdn.com/imgextra/i4/O1CN013pqDug1iTf1wdYIat_!!6000000004414-2-tps-800-8358.png)"},{"id":"/higress","metadata":{"permalink":"/en-us/blog/higress","editUrl":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/higress.md","source":"@site/i18n/en-us/docusaurus-plugin-content-blog/higress.md","title":"Alibaba Open Source Cloud Native Gateway\uff1a Higress","description":"This paper introduces the background and development stages of Higress","date":"2022-11-04T00:00:00.000Z","formattedDate":"November 4, 2022","tags":[],"readingTime":0,"hasTruncateMarker":false,"authors":[{"name":"gengleilei"}],"frontMatter":{"title":"Alibaba Open Source Cloud Native Gateway\uff1a Higress","keywords":["higress"],"description":"This paper introduces the background and development stages of Higress","author":"gengleilei","date":"2022-11-04T00:00:00.000Z","custom_edit_url":"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en/docusaurus-plugin-content-blog/higress.md"},"prevItem":{"title":"Welcome to sign up for Higress\' first offline meetup","permalink":"/en-us/blog/first-meetup"}},"content":""}]}')}}]); \ No newline at end of file diff --git a/en-us/assets/js/4fced428.920060e4.js b/en-us/assets/js/4fced428.920060e4.js new file mode 100644 index 0000000000..e6bf6af651 --- /dev/null +++ b/en-us/assets/js/4fced428.920060e4.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2957],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),l=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(p.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=l(r),m=o,g=s["".concat(p,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var l=2;l{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/en-us/blog/ospp-2023",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/ospp-2023.md",source:"@site/blog/ospp-2023.md",title:"ospp-2023",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"configmap",permalink:"/en-us/blog/configmap"},nextItem:{title:"plugin-transformer",permalink:"/en-us/blog/plugin-transformer"}},p={authorsImageUrls:[]},l=[],u={toc:l},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/58bc8fb4.825c60c8.js b/en-us/assets/js/58bc8fb4.825c60c8.js new file mode 100644 index 0000000000..3290cc773c --- /dev/null +++ b/en-us/assets/js/58bc8fb4.825c60c8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[5577],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),u=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},b=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),s=u(r),b=o,m=s["".concat(l,".").concat(b)]||s[b]||f[b]||a;return r?n.createElement(m,c(c({ref:t},p),{},{components:r})):n.createElement(m,c({ref:t},p))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,c=new Array(a);c[0]=b;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[s]="string"==typeof e?e:o,c[1]=i;for(var u=2;u{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={},c=void 0,i={permalink:"/en-us/blog/2023-kubecon",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/2023-kubecon.md",source:"@site/blog/2023-kubecon.md",title:"2023-kubecon",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},nextItem:{title:"DeployOnWindows",permalink:"/en-us/blog/DeployOnWindows"}},l={authorsImageUrls:[]},u=[],p={toc:u},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/624571fc.072bcdb0.js b/en-us/assets/js/624571fc.072bcdb0.js new file mode 100644 index 0000000000..6fe487faca --- /dev/null +++ b/en-us/assets/js/624571fc.072bcdb0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3919],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var p=n.createContext({}),l=function(e){var t=n.useContext(p),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=l(e.components);return n.createElement(p.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,p=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=l(r),m=o,g=s["".concat(p,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var p in t)hasOwnProperty.call(t,p)&&(c[p]=t[p]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var l=2;l{r.r(t),r.d(t,{assets:()=>p,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/en-us/blog/ospp-2023",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/ospp-2023.md",source:"@site/blog/ospp-2023.md",title:"ospp-2023",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"configmap",permalink:"/en-us/blog/configmap"},nextItem:{title:"plugin-transformer",permalink:"/en-us/blog/plugin-transformer"}},p={authorsImageUrls:[]},l=[],u={toc:l},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/8128b5c2.eb93d317.js b/en-us/assets/js/8128b5c2.eb93d317.js new file mode 100644 index 0000000000..2770d298e7 --- /dev/null +++ b/en-us/assets/js/8128b5c2.eb93d317.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2606],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=u(e,["components","mdxType","originalType","parentName"]),p=l(r),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},s),{},{components:r})):n.createElement(b,i({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u[p]="string"==typeof e?e:o,i[1]=u;for(var l=2;l{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>u,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,u={permalink:"/en-us/blog/user-uu",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/user-uu.md",source:"@site/blog/user-uu.md",title:"user-uu",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"user-mq",permalink:"/en-us/blog/user-mq"},nextItem:{title:"AIGC OpenAPI Cost Reduction via Higress",permalink:"/en-us/blog/ai_plugin"}},c={authorsImageUrls:[]},l=[],s={toc:l},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/845e9851.c252d7ed.js b/en-us/assets/js/845e9851.c252d7ed.js new file mode 100644 index 0000000000..2ccb417476 --- /dev/null +++ b/en-us/assets/js/845e9851.c252d7ed.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[1382],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,b=s["".concat(l,".").concat(m)]||s[m]||f[m]||i;return r?n.createElement(b,a(a({ref:t},u),{},{components:r})):n.createElement(b,a({ref:t},u))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>f,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,c={permalink:"/en-us/blog/DeployOnWindows",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/DeployOnWindows.md",source:"@site/blog/DeployOnWindows.md",title:"DeployOnWindows",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"2023-kubecon",permalink:"/en-us/blog/2023-kubecon"},nextItem:{title:"config-with-file",permalink:"/en-us/blog/config-with-file"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/8d5cf564.816d8c84.js b/en-us/assets/js/8d5cf564.816d8c84.js new file mode 100644 index 0000000000..8e31edd9be --- /dev/null +++ b/en-us/assets/js/8d5cf564.816d8c84.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[3072],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),s=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},u=function(e){var r=s(e.components);return n.createElement(c.Provider,{value:r},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=s(t),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return t?n.createElement(b,l(l({ref:r},u),{},{components:t})):n.createElement(b,l({ref:r},u))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,l=new Array(a);l[0]=m;var i={};for(var c in r)hasOwnProperty.call(r,c)&&(i[c]=r[c]);i.originalType=e,i[p]="string"==typeof e?e:o,l[1]=i;for(var s=2;s{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>s});var n=t(7462),o=(t(7294),t(3905));const a={},l=void 0,i={permalink:"/en-us/blog/release-1.3",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-1.3.md",source:"@site/blog/release-1.3.md",title:"release-1.3",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-070",permalink:"/en-us/blog/release-070"},nextItem:{title:"release-100",permalink:"/en-us/blog/release-100"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(p,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/99708c2c.6be998a3.js b/en-us/assets/js/99708c2c.6be998a3.js new file mode 100644 index 0000000000..36df3f0a9a --- /dev/null +++ b/en-us/assets/js/99708c2c.6be998a3.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[4953],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/en-us/blog/configmap",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/configmap.md",source:"@site/blog/configmap.md",title:"configmap",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"config-with-file",permalink:"/en-us/blog/config-with-file"},nextItem:{title:"ospp-2023",permalink:"/en-us/blog/ospp-2023"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/9d0fb5fa.6749965d.js b/en-us/assets/js/9d0fb5fa.6749965d.js new file mode 100644 index 0000000000..167b5bbc88 --- /dev/null +++ b/en-us/assets/js/9d0fb5fa.6749965d.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7732],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),s=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},u=function(e){var r=s(e.components);return n.createElement(c.Provider,{value:r},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=s(t),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return t?n.createElement(b,l(l({ref:r},u),{},{components:t})):n.createElement(b,l({ref:r},u))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,l=new Array(a);l[0]=m;var i={};for(var c in r)hasOwnProperty.call(r,c)&&(i[c]=r[c]);i.originalType=e,i[p]="string"==typeof e?e:o,l[1]=i;for(var s=2;s{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>s});var n=t(7462),o=(t(7294),t(3905));const a={},l=void 0,i={permalink:"/en-us/blog/release-1.3",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-1.3.md",source:"@site/blog/release-1.3.md",title:"release-1.3",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-070",permalink:"/en-us/blog/release-070"},nextItem:{title:"release-100",permalink:"/en-us/blog/release-100"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(p,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/9ef98e71.25fce2c0.js b/en-us/assets/js/9ef98e71.25fce2c0.js new file mode 100644 index 0000000000..2a6b5d7276 --- /dev/null +++ b/en-us/assets/js/9ef98e71.25fce2c0.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[1434],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||i;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>f,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,c={permalink:"/en-us/blog/config-with-file",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/config-with-file.md",source:"@site/blog/config-with-file.md",title:"config-with-file",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"DeployOnWindows",permalink:"/en-us/blog/DeployOnWindows"},nextItem:{title:"configmap",permalink:"/en-us/blog/configmap"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/a68b5a4c.d560b6ac.js b/en-us/assets/js/a68b5a4c.d560b6ac.js new file mode 100644 index 0000000000..b632057c09 --- /dev/null +++ b/en-us/assets/js/a68b5a4c.d560b6ac.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[9533],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=s(r),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return r?n.createElement(b,l(l({ref:t},u),{},{components:r})):n.createElement(b,l({ref:t},u))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[p]="string"==typeof e?e:o,l[1]=i;for(var s=2;s{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={},l=void 0,i={permalink:"/en-us/blog/release-100",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-100.md",source:"@site/blog/release-100.md",title:"release-100",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-1.3",permalink:"/en-us/blog/release-1.3"},nextItem:{title:"skywalking",permalink:"/en-us/blog/skywalking"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/aa0335fa.77ae2940.js b/en-us/assets/js/aa0335fa.77ae2940.js new file mode 100644 index 0000000000..cd1d27333e --- /dev/null +++ b/en-us/assets/js/aa0335fa.77ae2940.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7662],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=u(e,["components","mdxType","originalType","parentName"]),p=l(r),f=o,b=p["".concat(c,".").concat(f)]||p[f]||m[f]||a;return r?n.createElement(b,i(i({ref:t},s),{},{components:r})):n.createElement(b,i({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u[p]="string"==typeof e?e:o,i[1]=u;for(var l=2;l{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>u,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,u={permalink:"/en-us/blog/user-mq",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/user-mq.md",source:"@site/blog/user-mq.md",title:"user-mq",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"skywalking",permalink:"/en-us/blog/skywalking"},nextItem:{title:"user-uu",permalink:"/en-us/blog/user-uu"}},c={authorsImageUrls:[]},l=[],s={toc:l},p="wrapper";function m(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/b4e8a740.dd0f1de8.js b/en-us/assets/js/b4e8a740.dd0f1de8.js new file mode 100644 index 0000000000..731c0d66fb --- /dev/null +++ b/en-us/assets/js/b4e8a740.dd0f1de8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2272],{3905:(e,r,t)=>{t.d(r,{Zo:()=>u,kt:()=>b});var n=t(7294);function o(e,r,t){return r in e?Object.defineProperty(e,r,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[r]=t,e}function a(e,r){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);r&&(n=n.filter((function(r){return Object.getOwnPropertyDescriptor(e,r).enumerable}))),t.push.apply(t,n)}return t}function l(e){for(var r=1;r=0||(o[t]=e[t]);return o}(e,r);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(o[t]=e[t])}return o}var c=n.createContext({}),s=function(e){var r=n.useContext(c),t=r;return e&&(t="function"==typeof e?e(r):l(l({},r),e)),t},u=function(e){var r=s(e.components);return n.createElement(c.Provider,{value:r},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var r=e.children;return n.createElement(n.Fragment,{},r)}},m=n.forwardRef((function(e,r){var t=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=s(t),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return t?n.createElement(b,l(l({ref:r},u),{},{components:t})):n.createElement(b,l({ref:r},u))}));function b(e,r){var t=arguments,o=r&&r.mdxType;if("string"==typeof e||o){var a=t.length,l=new Array(a);l[0]=m;var i={};for(var c in r)hasOwnProperty.call(r,c)&&(i[c]=r[c]);i.originalType=e,i[p]="string"==typeof e?e:o,l[1]=i;for(var s=2;s{t.r(r),t.d(r,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>s});var n=t(7462),o=(t(7294),t(3905));const a={},l=void 0,i={permalink:"/en-us/blog/release-070",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-070.md",source:"@site/blog/release-070.md",title:"release-070",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"plugin-transformer",permalink:"/en-us/blog/plugin-transformer"},nextItem:{title:"release-1.3",permalink:"/en-us/blog/release-1.3"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:r,...t}=e;return(0,o.kt)(p,(0,n.Z)({},u,t,{components:r,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/ccb98be5.5945a078.js b/en-us/assets/js/ccb98be5.5945a078.js new file mode 100644 index 0000000000..590523c1e8 --- /dev/null +++ b/en-us/assets/js/ccb98be5.5945a078.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[7211],{3905:(e,t,r)=>{r.d(t,{Zo:()=>p,kt:()=>m});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function c(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),u=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):c(c({},t),e)),r},p=function(e){var t=u(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},b=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,p=i(e,["components","mdxType","originalType","parentName"]),s=u(r),b=o,m=s["".concat(l,".").concat(b)]||s[b]||f[b]||a;return r?n.createElement(m,c(c({ref:t},p),{},{components:r})):n.createElement(m,c({ref:t},p))}));function m(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,c=new Array(a);c[0]=b;var i={};for(var l in t)hasOwnProperty.call(t,l)&&(i[l]=t[l]);i.originalType=e,i[s]="string"==typeof e?e:o,c[1]=i;for(var u=2;u{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>c,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>u});var n=r(7462),o=(r(7294),r(3905));const a={},c=void 0,i={permalink:"/en-us/blog/2023-kubecon",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/2023-kubecon.md",source:"@site/blog/2023-kubecon.md",title:"2023-kubecon",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},nextItem:{title:"DeployOnWindows",permalink:"/en-us/blog/DeployOnWindows"}},l={authorsImageUrls:[]},u=[],p={toc:u},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},p,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/dbd65e5e.a3b07da7.js b/en-us/assets/js/dbd65e5e.a3b07da7.js new file mode 100644 index 0000000000..b5aa8009bb --- /dev/null +++ b/en-us/assets/js/dbd65e5e.a3b07da7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6446],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||i;return r?n.createElement(g,a(a({ref:t},u),{},{components:r})):n.createElement(g,a({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>f,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,c={permalink:"/en-us/blog/config-with-file",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/config-with-file.md",source:"@site/blog/config-with-file.md",title:"config-with-file",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"DeployOnWindows",permalink:"/en-us/blog/DeployOnWindows"},nextItem:{title:"configmap",permalink:"/en-us/blog/configmap"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/de9c39ca.5c3d1aa9.js b/en-us/assets/js/de9c39ca.5c3d1aa9.js new file mode 100644 index 0000000000..729ed8b930 --- /dev/null +++ b/en-us/assets/js/de9c39ca.5c3d1aa9.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6642],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=u(e,["components","mdxType","originalType","parentName"]),p=l(r),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return r?n.createElement(b,i(i({ref:t},s),{},{components:r})):n.createElement(b,i({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u[p]="string"==typeof e?e:o,i[1]=u;for(var l=2;l{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>u,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,u={permalink:"/en-us/blog/user-uu",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/user-uu.md",source:"@site/blog/user-uu.md",title:"user-uu",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"user-mq",permalink:"/en-us/blog/user-mq"},nextItem:{title:"AIGC OpenAPI Cost Reduction via Higress",permalink:"/en-us/blog/ai_plugin"}},c={authorsImageUrls:[]},l=[],s={toc:l},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/e0d5e815.ef9ad5d2.js b/en-us/assets/js/e0d5e815.ef9ad5d2.js new file mode 100644 index 0000000000..1c45f5aed1 --- /dev/null +++ b/en-us/assets/js/e0d5e815.ef9ad5d2.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[4319],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,g=s["".concat(l,".").concat(m)]||s[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,i[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,c={permalink:"/en-us/blog/configmap",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/configmap.md",source:"@site/blog/configmap.md",title:"configmap",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"config-with-file",permalink:"/en-us/blog/config-with-file"},nextItem:{title:"ospp-2023",permalink:"/en-us/blog/ospp-2023"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/e6214f62.564cb0e8.js b/en-us/assets/js/e6214f62.564cb0e8.js new file mode 100644 index 0000000000..f43b8f2498 --- /dev/null +++ b/en-us/assets/js/e6214f62.564cb0e8.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6541],{3905:(e,t,r)=>{r.d(t,{Zo:()=>s,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),l=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},s=function(e){var t=l(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",m={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},f=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,s=u(e,["components","mdxType","originalType","parentName"]),p=l(r),f=o,b=p["".concat(c,".").concat(f)]||p[f]||m[f]||a;return r?n.createElement(b,i(i({ref:t},s),{},{components:r})):n.createElement(b,i({ref:t},s))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=f;var u={};for(var c in t)hasOwnProperty.call(t,c)&&(u[c]=t[c]);u.originalType=e,u[p]="string"==typeof e?e:o,i[1]=u;for(var l=2;l{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>m,frontMatter:()=>a,metadata:()=>u,toc:()=>l});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,u={permalink:"/en-us/blog/user-mq",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/user-mq.md",source:"@site/blog/user-mq.md",title:"user-mq",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"skywalking",permalink:"/en-us/blog/skywalking"},nextItem:{title:"user-uu",permalink:"/en-us/blog/user-uu"}},c={authorsImageUrls:[]},l=[],s={toc:l},p="wrapper";function m(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},s,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}m.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/e7597a90.19978962.js b/en-us/assets/js/e7597a90.19978962.js new file mode 100644 index 0000000000..845f338f18 --- /dev/null +++ b/en-us/assets/js/e7597a90.19978962.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[2131],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=s(r),m=o,g=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[p]="string"==typeof e?e:o,i[1]=l;for(var s=2;s{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/en-us/blog/skywalking",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/skywalking.md",source:"@site/blog/skywalking.md",title:"skywalking",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-100",permalink:"/en-us/blog/release-100"},nextItem:{title:"user-mq",permalink:"/en-us/blog/user-mq"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/eee51acf.80e2b958.js b/en-us/assets/js/eee51acf.80e2b958.js new file mode 100644 index 0000000000..07c50bd116 --- /dev/null +++ b/en-us/assets/js/eee51acf.80e2b958.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[9341],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function i(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function a(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var l=n.createContext({}),p=function(e){var t=n.useContext(l),r=t;return e&&(r="function"==typeof e?e(t):a(a({},t),e)),r},u=function(e){var t=p(e.components);return n.createElement(l.Provider,{value:t},e.children)},s="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,i=e.originalType,l=e.parentName,u=c(e,["components","mdxType","originalType","parentName"]),s=p(r),m=o,b=s["".concat(l,".").concat(m)]||s[m]||f[m]||i;return r?n.createElement(b,a(a({ref:t},u),{},{components:r})):n.createElement(b,a({ref:t},u))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var i=r.length,a=new Array(i);a[0]=m;var c={};for(var l in t)hasOwnProperty.call(t,l)&&(c[l]=t[l]);c.originalType=e,c[s]="string"==typeof e?e:o,a[1]=c;for(var p=2;p{r.r(t),r.d(t,{assets:()=>l,contentTitle:()=>a,default:()=>f,frontMatter:()=>i,metadata:()=>c,toc:()=>p});var n=r(7462),o=(r(7294),r(3905));const i={},a=void 0,c={permalink:"/en-us/blog/DeployOnWindows",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/DeployOnWindows.md",source:"@site/blog/DeployOnWindows.md",title:"DeployOnWindows",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"2023-kubecon",permalink:"/en-us/blog/2023-kubecon"},nextItem:{title:"config-with-file",permalink:"/en-us/blog/config-with-file"}},l={authorsImageUrls:[]},p=[],u={toc:p},s="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(s,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/f01d234c.4e1ac777.js b/en-us/assets/js/f01d234c.4e1ac777.js new file mode 100644 index 0000000000..3f1c78d0b6 --- /dev/null +++ b/en-us/assets/js/f01d234c.4e1ac777.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[696],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>g});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function i(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):i(i({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=l(e,["components","mdxType","originalType","parentName"]),p=s(r),m=o,g=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return r?n.createElement(g,i(i({ref:t},u),{},{components:r})):n.createElement(g,i({ref:t},u))}));function g(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,i=new Array(a);i[0]=m;var l={};for(var c in t)hasOwnProperty.call(t,c)&&(l[c]=t[c]);l.originalType=e,l[p]="string"==typeof e?e:o,i[1]=l;for(var s=2;s{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>i,default:()=>f,frontMatter:()=>a,metadata:()=>l,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={},i=void 0,l={permalink:"/en-us/blog/skywalking",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/skywalking.md",source:"@site/blog/skywalking.md",title:"skywalking",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-100",permalink:"/en-us/blog/release-100"},nextItem:{title:"user-mq",permalink:"/en-us/blog/user-mq"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/feedb3b4.9cdc7100.js b/en-us/assets/js/feedb3b4.9cdc7100.js new file mode 100644 index 0000000000..0250bc7a43 --- /dev/null +++ b/en-us/assets/js/feedb3b4.9cdc7100.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6388],{3905:(e,t,r)=>{r.d(t,{Zo:()=>u,kt:()=>b});var n=r(7294);function o(e,t,r){return t in e?Object.defineProperty(e,t,{value:r,enumerable:!0,configurable:!0,writable:!0}):e[t]=r,e}function a(e,t){var r=Object.keys(e);if(Object.getOwnPropertySymbols){var n=Object.getOwnPropertySymbols(e);t&&(n=n.filter((function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable}))),r.push.apply(r,n)}return r}function l(e){for(var t=1;t=0||(o[r]=e[r]);return o}(e,t);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);for(n=0;n=0||Object.prototype.propertyIsEnumerable.call(e,r)&&(o[r]=e[r])}return o}var c=n.createContext({}),s=function(e){var t=n.useContext(c),r=t;return e&&(r="function"==typeof e?e(t):l(l({},t),e)),r},u=function(e){var t=s(e.components);return n.createElement(c.Provider,{value:t},e.children)},p="mdxType",f={inlineCode:"code",wrapper:function(e){var t=e.children;return n.createElement(n.Fragment,{},t)}},m=n.forwardRef((function(e,t){var r=e.components,o=e.mdxType,a=e.originalType,c=e.parentName,u=i(e,["components","mdxType","originalType","parentName"]),p=s(r),m=o,b=p["".concat(c,".").concat(m)]||p[m]||f[m]||a;return r?n.createElement(b,l(l({ref:t},u),{},{components:r})):n.createElement(b,l({ref:t},u))}));function b(e,t){var r=arguments,o=t&&t.mdxType;if("string"==typeof e||o){var a=r.length,l=new Array(a);l[0]=m;var i={};for(var c in t)hasOwnProperty.call(t,c)&&(i[c]=t[c]);i.originalType=e,i[p]="string"==typeof e?e:o,l[1]=i;for(var s=2;s{r.r(t),r.d(t,{assets:()=>c,contentTitle:()=>l,default:()=>f,frontMatter:()=>a,metadata:()=>i,toc:()=>s});var n=r(7462),o=(r(7294),r(3905));const a={},l=void 0,i={permalink:"/en-us/blog/release-100",editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/en-us/docusaurus-plugin-content-blog/release-100.md",source:"@site/blog/release-100.md",title:"release-100",description:"Placeholder. DO NOT DELETE.",date:"2023-11-16T06:51:43.000Z",formattedDate:"November 16, 2023",tags:[],readingTime:.02,hasTruncateMarker:!1,authors:[],frontMatter:{},prevItem:{title:"release-1.3",permalink:"/en-us/blog/release-1.3"},nextItem:{title:"skywalking",permalink:"/en-us/blog/skywalking"}},c={authorsImageUrls:[]},s=[],u={toc:s},p="wrapper";function f(e){let{components:t,...r}=e;return(0,o.kt)(p,(0,n.Z)({},u,r,{components:t,mdxType:"MDXLayout"}),(0,o.kt)("p",null,"Placeholder. DO NOT DELETE."))}f.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/en-us/assets/js/runtime~main.2830f15a.js b/en-us/assets/js/runtime~main.2830f15a.js new file mode 100644 index 0000000000..c6023414f8 --- /dev/null +++ b/en-us/assets/js/runtime~main.2830f15a.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,c,b,f,a,d={},t={};function r(e){var c=t[e];if(void 0!==c)return c.exports;var b=t[e]={id:e,loaded:!1,exports:{}};return d[e].call(b.exports,b,b.exports,r),b.loaded=!0,b.exports}r.m=d,r.c=t,e=[],r.O=(c,b,f,a)=>{if(!b){var d=1/0;for(i=0;i=a)&&Object.keys(r.O).every((e=>r.O[e](b[o])))?b.splice(o--,1):(t=!1,a0&&e[i-1][2]>a;i--)e[i]=e[i-1];e[i]=[b,f,a]},r.n=e=>{var c=e&&e.__esModule?()=>e.default:()=>e;return r.d(c,{a:c}),c},b=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,f){if(1&f&&(e=this(e)),8&f)return e;if("object"==typeof e&&e){if(4&f&&e.__esModule)return e;if(16&f&&"function"==typeof e.then)return e}var a=Object.create(null);r.r(a);var d={};c=c||[null,b({}),b([]),b(b)];for(var t=2&f&&e;"object"==typeof t&&!~c.indexOf(t);t=b(t))Object.getOwnPropertyNames(t).forEach((c=>d[c]=()=>e[c]));return d.default=()=>e,r.d(a,d),a},r.d=(e,c)=>{for(var b in c)r.o(c,b)&&!r.o(e,b)&&Object.defineProperty(e,b,{enumerable:!0,get:c[b]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((c,b)=>(r.f[b](e,c),c)),[])),r.u=e=>"assets/js/"+({53:"935f2afb",123:"59a4c5e3",136:"7893cef3",165:"452368c1",252:"11c936d8",286:"b72e39f9",590:"e6e760b3",647:"568610b2",696:"f01d234c",799:"2d27d23c",801:"914e0e0b",943:"1ea5e911",1092:"c178a1d0",1162:"e58c4451",1249:"44e19575",1329:"30616e31",1382:"845e9851",1434:"9ef98e71",1492:"beb5e9ee",1519:"af45db24",1874:"c3080676",2069:"3d978fec",2131:"e7597a90",2224:"f920f5b4",2272:"b4e8a740",2338:"32f852b2",2352:"78520b88",2535:"814f3328",2592:"aded1fcd",2606:"8128b5c2",2619:"2e1d296f",2729:"661b5bb5",2957:"4fced428",2972:"3794dc3b",3072:"8d5cf564",3085:"1f391b9e",3089:"a6aa9e1f",3099:"f61b6d7f",3218:"688b78c4",3237:"1df93b7f",3269:"0b0fed00",3388:"7ba87912",3443:"0241a5fb",3591:"3d8abcf7",3608:"9e4087bc",3663:"cb5ac88b",3812:"68d86171",3905:"9f719182",3919:"624571fc",4319:"e0d5e815",4358:"9ab73039",4404:"6fd65bc4",4598:"0f9ae43c",4856:"910cd5d0",4872:"372cb0b9",4953:"99708c2c",4970:"33b08622",5096:"a39ffcaa",5124:"5f26e4d8",5189:"112fa8ff",5275:"db57f5f2",5292:"c557ece2",5454:"4776e42b",5484:"44124c81",5577:"58bc8fb4",5643:"d735d603",5688:"cb385ac5",5707:"c8858931",5792:"058e5a18",5825:"28f6e2c7",6103:"ccc49370",6162:"389417be",6388:"feedb3b4",6401:"3b55c56b",6446:"dbd65e5e",6487:"2c354a3f",6503:"9ebe65ca",6541:"e6214f62",6589:"7e045136",6604:"6a1ae202",6642:"de9c39ca",7047:"c63d2a83",7065:"36100489",7147:"485656d5",7211:"ccb98be5",7256:"d53cb142",7318:"bb332f99",7414:"393be207",7662:"aa0335fa",7732:"9d0fb5fa",7833:"34064e98",7918:"17896441",8009:"9bcd7609",8119:"64fdbea0",8197:"cfcce438",8373:"bae9b49c",8565:"6d6f3fbb",8571:"a7b4b059",8854:"2a133e97",8927:"b9dea8e8",8956:"5edd1287",9010:"c83c74b9",9269:"1d0c03a0",9341:"eee51acf",9439:"265f8c6c",9491:"c6215efd",9514:"1be78505",9533:"a68b5a4c",9791:"b0ba0782",9871:"899b9fc2"}[e]||e)+"."+{53:"c0634d10",123:"e6623ba6",136:"4b5d27c3",165:"fcf440dd",210:"7b457f2b",252:"22d21365",286:"bc477af8",412:"c211d18d",590:"69ecc827",647:"a79add55",696:"4e1ac777",799:"17afcaf8",801:"1a9049d8",943:"fbfb6867",1092:"61130079",1162:"fce1283b",1249:"ae5692e5",1329:"10f925bf",1382:"c252d7ed",1434:"25fce2c0",1492:"5385e4d3",1519:"a257312f",1874:"97fe9918",2069:"d7136a44",2131:"19978962",2224:"1f35a12b",2272:"dd0f1de8",2338:"20b07853",2352:"6b4b5aba",2535:"d4dd2677",2592:"e9808ad1",2606:"eb93d317",2619:"9c71b308",2729:"d777fe2d",2957:"920060e4",2972:"e2e2a610",3072:"816d8c84",3085:"5dd43995",3089:"04e59258",3099:"a81c18e1",3218:"488f13ed",3237:"b211faaa",3269:"f50761c0",3388:"f5442359",3443:"5697b9cc",3591:"1c0cc073",3608:"d4b4fa21",3663:"755a9638",3812:"317b51bf",3905:"2c1ed745",3919:"072bcdb0",4319:"ef9ad5d2",4358:"07208875",4404:"4f3fd1d3",4598:"25a70c7c",4856:"46e108ec",4872:"51a822d8",4953:"6be998a3",4970:"999fdc38",4972:"453b6fac",5096:"6c1fe07c",5124:"ba247263",5189:"d4e5af95",5275:"2dfc00da",5292:"46e2f392",5454:"510be36f",5484:"a28f15b5",5577:"825c60c8",5643:"40001728",5688:"ea2154a3",5707:"48a403b2",5792:"e7d172cc",5825:"85a13092",6103:"f9d66d0a",6162:"4dae02d6",6388:"9cdc7100",6401:"d0220cc4",6446:"a3b07da7",6487:"7fca1448",6503:"9d35b9ff",6541:"564cb0e8",6589:"bbf40747",6604:"af192488",6642:"5c3d1aa9",7047:"167d4d37",7065:"f00be223",7147:"c99ed771",7211:"5945a078",7256:"a9c4981c",7318:"0cb840aa",7414:"817017f4",7662:"77ae2940",7732:"6749965d",7833:"61fffd2a",7918:"0980fa4a",8009:"9b12c8d8",8119:"f627b34d",8197:"8089a161",8373:"39ee4252",8565:"5dbfaa6a",8571:"48fe19c7",8854:"03c9b601",8927:"0cb86141",8956:"7a267d8e",9010:"047de3f8",9269:"9af81cf7",9341:"80e2b958",9439:"2bf55669",9491:"47f2a5dc",9514:"7cc3593d",9533:"d560b6ac",9791:"983bfd77",9871:"b37e91c4"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,c)=>Object.prototype.hasOwnProperty.call(e,c),f={},a="higress-website:",r.l=(e,c,b,d)=>{if(f[e])f[e].push(c);else{var t,o;if(void 0!==b)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(l);var a=f[e];if(delete f[e],t.parentNode&&t.parentNode.removeChild(t),a&&a.forEach((e=>e(b))),c)return c(b)},l=setTimeout(s.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=s.bind(null,t.onerror),t.onload=s.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/en-us/",r.gca=function(e){return e={17896441:"7918",36100489:"7065","935f2afb":"53","59a4c5e3":"123","7893cef3":"136","452368c1":"165","11c936d8":"252",b72e39f9:"286",e6e760b3:"590","568610b2":"647",f01d234c:"696","2d27d23c":"799","914e0e0b":"801","1ea5e911":"943",c178a1d0:"1092",e58c4451:"1162","44e19575":"1249","30616e31":"1329","845e9851":"1382","9ef98e71":"1434",beb5e9ee:"1492",af45db24:"1519",c3080676:"1874","3d978fec":"2069",e7597a90:"2131",f920f5b4:"2224",b4e8a740:"2272","32f852b2":"2338","78520b88":"2352","814f3328":"2535",aded1fcd:"2592","8128b5c2":"2606","2e1d296f":"2619","661b5bb5":"2729","4fced428":"2957","3794dc3b":"2972","8d5cf564":"3072","1f391b9e":"3085",a6aa9e1f:"3089",f61b6d7f:"3099","688b78c4":"3218","1df93b7f":"3237","0b0fed00":"3269","7ba87912":"3388","0241a5fb":"3443","3d8abcf7":"3591","9e4087bc":"3608",cb5ac88b:"3663","68d86171":"3812","9f719182":"3905","624571fc":"3919",e0d5e815:"4319","9ab73039":"4358","6fd65bc4":"4404","0f9ae43c":"4598","910cd5d0":"4856","372cb0b9":"4872","99708c2c":"4953","33b08622":"4970",a39ffcaa:"5096","5f26e4d8":"5124","112fa8ff":"5189",db57f5f2:"5275",c557ece2:"5292","4776e42b":"5454","44124c81":"5484","58bc8fb4":"5577",d735d603:"5643",cb385ac5:"5688",c8858931:"5707","058e5a18":"5792","28f6e2c7":"5825",ccc49370:"6103","389417be":"6162",feedb3b4:"6388","3b55c56b":"6401",dbd65e5e:"6446","2c354a3f":"6487","9ebe65ca":"6503",e6214f62:"6541","7e045136":"6589","6a1ae202":"6604",de9c39ca:"6642",c63d2a83:"7047","485656d5":"7147",ccb98be5:"7211",d53cb142:"7256",bb332f99:"7318","393be207":"7414",aa0335fa:"7662","9d0fb5fa":"7732","34064e98":"7833","9bcd7609":"8009","64fdbea0":"8119",cfcce438:"8197",bae9b49c:"8373","6d6f3fbb":"8565",a7b4b059:"8571","2a133e97":"8854",b9dea8e8:"8927","5edd1287":"8956",c83c74b9:"9010","1d0c03a0":"9269",eee51acf:"9341","265f8c6c":"9439",c6215efd:"9491","1be78505":"9514",a68b5a4c:"9533",b0ba0782:"9791","899b9fc2":"9871"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(c,b)=>{var f=r.o(e,c)?e[c]:void 0;if(0!==f)if(f)b.push(f[2]);else if(/^(1303|532)$/.test(c))e[c]=0;else{var a=new Promise(((b,a)=>f=e[c]=[b,a]));b.push(f[2]=a);var d=r.p+r.u(c),t=new Error;r.l(d,(b=>{if(r.o(e,c)&&(0!==(f=e[c])&&(e[c]=void 0),f)){var a=b&&("load"===b.type?"missing":b.type),d=b&&b.target&&b.target.src;t.message="Loading chunk "+c+" failed.\n("+a+": "+d+")",t.name="ChunkLoadError",t.type=a,t.request=d,f[1](t)}}),"chunk-"+c,c)}},r.O.j=c=>0===e[c];var c=(c,b)=>{var f,a,d=b[0],t=b[1],o=b[2],n=0;if(d.some((c=>0!==e[c]))){for(f in t)r.o(t,f)&&(r.m[f]=t[f]);if(o)var i=o(r)}for(c&&c(b);n -2023-kubecon | Higress +2023-kubecon | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/blog/30-line-wasm/index.html b/en-us/blog/30-line-wasm/index.html index 58bb2ee1fc..866c3bab48 100644 --- a/en-us/blog/30-line-wasm/index.html +++ b/en-us/blog/30-line-wasm/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/blog/DeployOnWindows/index.html b/en-us/blog/DeployOnWindows/index.html index d8b66ad003..6fdef3e776 100644 --- a/en-us/blog/DeployOnWindows/index.html +++ b/en-us/blog/DeployOnWindows/index.html @@ -3,7 +3,7 @@ -DeployOnWindows | Higress +DeployOnWindows | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/blog/ai_plugin/index.html b/en-us/blog/ai_plugin/index.html index a657d75f8a..b87219d7b0 100644 --- a/en-us/blog/ai_plugin/index.html +++ b/en-us/blog/ai_plugin/index.html @@ -14,14 +14,14 @@ - +

AIGC OpenAPI Cost Reduction via Higress

· 9 mins read

AIGC applications represented by ChatGPT have brought great changes to enterprise production and greatly improved people's production efficiency. Large AI models can help to complete various complex tasks, such as helping developers write, debug and record codes, researchers quickly understand scientific research fields, marketers write product descriptions, etc. More and more enterprises have begun to attach importance to AIGC application development. How to manage the API of large AI models through the gateway has become a concern.

Higress is a next-generation cloud-native gateway based on Alibaba's internal gateway practices. Powered by Istio and Envoy, Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway, and security gateway, thereby greatly reducing the costs of deployment, operation, and maintenance. Based on the rich capabilities provided by Higress, enterprises can greatly reduce the cost of using large AI models.

How does Higress reduce the cost of using AI models?

Taking OpenAI as an example, OpenAI's APIs are priced not based on the number of requests or subscription time but based on the usage of each request. For large AI models, tokens are the standard billing strategy for OpenAI API as a measure of the complexity of inference tasks. The cost for tokens varies based on the model. Generally, more complex models give better results at a higher cost. API Keys are distributed to consumers for authentication and charging.

image.png

It is unrealistic for an organization to apply for an API Key for each member. Scattered API keys will not be conducive to the organization's calculation, management, and payment of API usage, thereby increasing the cost of using large AI models. For organizations, the selection and access rights of AI models, the frequency of use of AI models and access permissions, and the management and protection of data exposed to AI models are all important API management.

Based on rich plugin capabilities, Higress provides functions such as authentication, request filtering, traffic control, usage monitoring, and security protection, helping organizations interact with large AI model APIs more securely, reliably, and observably. Based on the authentication provided by Higress, organizations can implement multi-tenant authentication and grant different AI model access rights to team members; based on the traffic control capability, organizations can set differentiated access rate limits for different models and users, effectively reducing the cost of using AI model; based on the request interception capability, organizations can effectively filter access requests containing sensitive information, and protect some internal site resources from being exposed to the outside world, effectively ensuring data security. Based on the index query and log system capabilities provided by Commercial Higress, organizations can observe and analyze the usage of AI model calls by different users to formulate more reasonable AI model usage strategies.

image.png

Manage OpenAI API with Higress

We will take Higress connecting to the OpenAI API as an example to introduce how Higress seamlessly connects to the large AI model. The overall solution is shown in Fig.3. We have extended the Higress plugin based on WASM to proxy requests to the OpenAI language model. Based on authentication plugins such as Key Auth, we implement multi-tenant authentication under a unified OpenAI API-Key. Based on the Request-Block plugin, we implement the interception of requests with sensitive information and ensure data protection.

Prerequisites

  1. Install Higress. Please refer to Deploy Higress by Helm.
  2. Prepare the development environment for WASM plugins with Golang. Please refer to Developing a WASM plugin with Golang | Higress.

AI Proxy WASM Plugin

The following will give the AI proxy plugin implementation based on Higress and WASM. Higress supports scalability externally based on WASM. The multi-language ecology and hot-swapping mechanism provided by the WASM facilitate the implementation and deployment of the plugin. Higress also supports requesting external services in the plugin, which provides an efficient solution path for the implementation of the AI proxy plugin.

Code Implementation

The following code implements the request proxy to OPENAI-API based on HTTP. For details, please refer to the AI proxy plugin. The specific implementation steps are as follows:

  1. Create a new HTTP client, specify the OpenAI API host through the RouteCluster method, and determine the request proxy path.
func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
//The default forwarding path is OpenAI API.
//Users can adjust through configuration.
chatgptUri := json.Get("chatgptUri").String()
var chatgptHost string
if chatgptUri == "" {
config.ChatgptPath = "/v1/completions"
chatgptHost = "api.openai.com"
}
...
//Specify the specific request proxy host through RouteCluster.
config.client = wrapper.NewClusterClient(wrapper.RouteCluster{
Host: chatgptHost,
})
...
}

  1. Encapsulate the request in the OpenAI-API format, send requests and receive responses through the HTTP Client, and send responses to the user.
//OPENAI API request body template. Please refer to https://platform.openai.com/docs/api-reference/chat
const bodyTemplate string = `
{
"model":"%s",
"prompt":"%s",
"temperature":0.9,
"max_tokens": 150,
"top_p": 1,
"frequency_penalty": 0.0,
"presence_penalty": 0.6,
"stop": ["%s", "%s"]
}
`
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
...
//Encapsulate the OPENAI API request body according to the user's request content.
body := fmt.Sprintf(bodyTemplate, config.Model, prompt[0], config.HumanId, config.AIId)
//Post request via HTTP client.
err = config.client.Post(config.ChatgptPath, [][2]string{
{"Content-Type", "application/json"},
{"Authorization", "Bearer " + config.ApiKey},
}, []byte(body),
func(statusCode int, responseHeaders http.Header, responseBody []byte) {
var headers [][2]string
for key, value := range responseHeaders {
headers = append(headers, [2]string{key, value[0]})
}
//Receive the response from the OPENAI API and send it to user
proxywasm.SendHttpResponse(uint32(statusCode), headers, responseBody, -1)
}, 10000)
...
}

Enable the custom AI-Proxy-Wasm plugin in Higress as follows:

This example provides the compiled AI-proxy-plugin WASM file and completes the construction and push of the docker image. The recommended configuration is as follows:

NameRecommended configuration
Image URLoci://registry.cn-hangzhou.aliyuncs.com/zwj_test/chatgpt-proxy:1.0.0
Plugin Execution PhaseAuthz
Plugin Execution Priority1

Plugin configuration instructions

AI-Proxy-Plugin is easy to configure and supports proxy forwarding at the global/domain name level/routing level. Route-level configuration is recommended: route config-strategy-enable plugin. An example configuration is as follows:

apiKey: "xxxxxxxxxxxxxxxxxx"
model: "curie"
promptParam: "text"

According to this configuration, the gateway proxies to the Curie model in OpenAI, and the user enters prompts in the URL through the keyword "text".

curl "http://{GatewayIP}/?text=Say,hello"

Response from Curie model in OpenAI:

image.png

Multi-tenant authentication based on Key Auth

Different from the form of issuing AI-API keys for each member, enterprises can utilize internal authorization (such as Key Auth, etc.) and rely on the unified AI-API key for request proxy to achieve unified management of API usage.

Key Auth implements the authentication based on the Gateway level API Key. Key Auth supports parsing the API Key from the URL parameter or request header of the HTTP requests and verifies whether the API has permission to access.

consumers:
- credential: "xxxxxx"
name: "consumer1"
- credential: "yyyyyy"
name: "consumer2"
global_auth: false
in_header: true
keys:
- "apikey"

allow: [consumer1]

The above configuration defines consumers, and only consumer1 has the access right to the AI model service under the current route.

curl "http://{GatewayIP}/?text=Say,hello"
#The request does not provide an API Key, return 401

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:zzzzzz"
#The API Key provided by the request is not authorized to access, return 401

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:yyyyyy"
#The caller matched according to the API Key provided in the request has no access rights, return 403

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:xxxxxx"
#The caller has access to the AI model service, the request will be proxied to the AI model, and the response from the OpenAI API will be received normally

In addition to providing gateway-level multi-tenant authentication, Higress provides traffic control and other capabilities. The Key Rate Limit plugin can limit the user's application rate based on the user's membership in the consumption group.

Data protection based on Request Block

For AIGC applications, especially LLM services, a good return often requires users to provide enough prompts as model input. Users face the risk of data leakage in the process of providing prompts. Ensuring data security in the process of using the AIGC application is also an important issue for API callers.

Protecting data security involves stringent control over the API calling channels. One method involves confirming specifically approved models with their published API. Another way is to intercept user requests containing sensitive information. These can be achieved by setting specific request interception at the gateway level. Higress provides request interception based on the request block plugin, which can prevent unauthorized models from accessing user information and prevent user requests containing sensitive information from being exposed to the external network.

blocked_code: 404
block_urls:
- password
- pw
case_sensitive: false

The above configuration defines URL-based shielding fields under the current route, in which requests containing sensitive information such as "password" and "pw" will be blocked。

curl "http://{GatewayIP}/?text=Mypassword=xxxxxx" -H "apikey:xxxxxx"
curl "http://{GatewayIP}/?text=pw=xxxxxx" -H "apikey:xxxxxx"
#The above request will be forbidden and return 404

Usage observation and analysis

For organizations, observing and analyzing the usage of large AI model calls for each user helps to understand their usage and costs. It is also necessary for individual users to understand their own call volume and overhead. Commercial Higress is deeply integrated with various metrics and log systems and provides an out-of-the-box usage observation and analysis report construction mechanism, which can view the usage of various APIs in real time and filter according to various parameters.

Taking the observation of each user's usage of the OPENAI-Curie model as an example, the administrator can set the observability parameter in the request header:x-mse-consumer, to distinguish users through MSE console - Cloud native Gateway - Gateway instance - Parameter Configurator- Custom Format. After adding the observability parameters, enter the Observation Analysis - Log Center to set the use statistics chart function to complete the observation and analysis of API usage. As shown in the figure below, the amount of calls to the OPENAI-Curie model of user consumer1 and user consumer2 is presented in the form of a pie chart.

image.png

Join the Higress community

Join Higress Slack: https://join.slack.com/t/w1689142780-euk177225/shared_invite/zt-1zbjm9d34-4nptVXPpNvnuKEKZ7V3MIg

To get invited: https://communityinviter.com/apps/w1689142780-euk177225/higress

If you find Higress helpful, welcome to Higress to star us!

- + \ No newline at end of file diff --git a/en-us/blog/archive/index.html b/en-us/blog/archive/index.html index 64a53e11b5..dbf93513bb 100644 --- a/en-us/blog/archive/index.html +++ b/en-us/blog/archive/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/blog/atom.xml b/en-us/blog/atom.xml index 35ce75e15b..b000f54b7f 100644 --- a/en-us/blog/atom.xml +++ b/en-us/blog/atom.xml @@ -2,7 +2,7 @@ https://higress.io/en-us/blog Higress Blog - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z https://github.com/jpmonette/feed Higress Blog @@ -11,7 +11,7 @@ <![CDATA[2023-kubecon]]> https://higress.io/en-us/blog/2023-kubecon - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -19,7 +19,7 @@ <![CDATA[DeployOnWindows]]> https://higress.io/en-us/blog/DeployOnWindows - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -27,7 +27,7 @@ <![CDATA[config-with-file]]> https://higress.io/en-us/blog/config-with-file - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -35,7 +35,7 @@ <![CDATA[configmap]]> https://higress.io/en-us/blog/configmap - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -43,7 +43,7 @@ <![CDATA[ospp-2023]]> https://higress.io/en-us/blog/ospp-2023 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -51,7 +51,7 @@ <![CDATA[plugin-transformer]]> https://higress.io/en-us/blog/plugin-transformer - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -59,7 +59,7 @@ <![CDATA[release-070]]> https://higress.io/en-us/blog/release-070 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -67,7 +67,7 @@ <![CDATA[release-1.3]]> https://higress.io/en-us/blog/release-1.3 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -75,7 +75,7 @@ <![CDATA[release-100]]> https://higress.io/en-us/blog/release-100 - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -83,7 +83,7 @@ <![CDATA[skywalking]]> https://higress.io/en-us/blog/skywalking - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -91,7 +91,7 @@ <![CDATA[user-mq]]> https://higress.io/en-us/blog/user-mq - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
@@ -99,7 +99,7 @@ <![CDATA[user-uu]]> https://higress.io/en-us/blog/user-uu - 2023-11-16T06:41:18.000Z + 2023-11-16T06:51:43.000Z Placeholder. DO NOT DELETE.

]]>
diff --git a/en-us/blog/config-with-file/index.html b/en-us/blog/config-with-file/index.html index ac35fdd2a7..4a5dfb30bf 100644 --- a/en-us/blog/config-with-file/index.html +++ b/en-us/blog/config-with-file/index.html @@ -3,7 +3,7 @@ -config-with-file | Higress +config-with-file | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/blog/configmap/index.html b/en-us/blog/configmap/index.html index 604e275af5..05915f9d2c 100644 --- a/en-us/blog/configmap/index.html +++ b/en-us/blog/configmap/index.html @@ -3,7 +3,7 @@ -configmap | Higress +configmap | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/blog/first-meetup/index.html b/en-us/blog/first-meetup/index.html index 6479ebc291..fbc08f67d2 100644 --- a/en-us/blog/first-meetup/index.html +++ b/en-us/blog/first-meetup/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/blog/higress/index.html b/en-us/blog/higress/index.html index 0ccdfb4c5c..ed464b5fcc 100644 --- a/en-us/blog/higress/index.html +++ b/en-us/blog/higress/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/blog/index.html b/en-us/blog/index.html index 7e304e140a..b64c218675 100644 --- a/en-us/blog/index.html +++ b/en-us/blog/index.html @@ -14,13 +14,13 @@ - +
-

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

- +

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

+ \ No newline at end of file diff --git a/en-us/blog/nacos/index.html b/en-us/blog/nacos/index.html index 02b721452c..dbadce021f 100644 --- a/en-us/blog/nacos/index.html +++ b/en-us/blog/nacos/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/blog/ospp-2023/index.html b/en-us/blog/ospp-2023/index.html index f17ddff5e8..c3e717cd98 100644 --- a/en-us/blog/ospp-2023/index.html +++ b/en-us/blog/ospp-2023/index.html @@ -3,7 +3,7 @@ -ospp-2023 | Higress +ospp-2023 | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/blog/page/2/index.html b/en-us/blog/page/2/index.html index cc23ae08c5..15b1c93348 100644 --- a/en-us/blog/page/2/index.html +++ b/en-us/blog/page/2/index.html @@ -14,14 +14,14 @@ - +
-

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· 9 mins read

AIGC applications represented by ChatGPT have brought great changes to enterprise production and greatly improved people's production efficiency. Large AI models can help to complete various complex tasks, such as helping developers write, debug and record codes, researchers quickly understand scientific research fields, marketers write product descriptions, etc. More and more enterprises have begun to attach importance to AIGC application development. How to manage the API of large AI models through the gateway has become a concern.

Higress is a next-generation cloud-native gateway based on Alibaba's internal gateway practices. Powered by Istio and Envoy, Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway, and security gateway, thereby greatly reducing the costs of deployment, operation, and maintenance. Based on the rich capabilities provided by Higress, enterprises can greatly reduce the cost of using large AI models.

How does Higress reduce the cost of using AI models?

Taking OpenAI as an example, OpenAI's APIs are priced not based on the number of requests or subscription time but based on the usage of each request. For large AI models, tokens are the standard billing strategy for OpenAI API as a measure of the complexity of inference tasks. The cost for tokens varies based on the model. Generally, more complex models give better results at a higher cost. API Keys are distributed to consumers for authentication and charging.

image.png

It is unrealistic for an organization to apply for an API Key for each member. Scattered API keys will not be conducive to the organization's calculation, management, and payment of API usage, thereby increasing the cost of using large AI models. For organizations, the selection and access rights of AI models, the frequency of use of AI models and access permissions, and the management and protection of data exposed to AI models are all important API management.

Based on rich plugin capabilities, Higress provides functions such as authentication, request filtering, traffic control, usage monitoring, and security protection, helping organizations interact with large AI model APIs more securely, reliably, and observably. Based on the authentication provided by Higress, organizations can implement multi-tenant authentication and grant different AI model access rights to team members; based on the traffic control capability, organizations can set differentiated access rate limits for different models and users, effectively reducing the cost of using AI model; based on the request interception capability, organizations can effectively filter access requests containing sensitive information, and protect some internal site resources from being exposed to the outside world, effectively ensuring data security. Based on the index query and log system capabilities provided by Commercial Higress, organizations can observe and analyze the usage of AI model calls by different users to formulate more reasonable AI model usage strategies.

image.png

Manage OpenAI API with Higress

We will take Higress connecting to the OpenAI API as an example to introduce how Higress seamlessly connects to the large AI model. The overall solution is shown in Fig.3. We have extended the Higress plugin based on WASM to proxy requests to the OpenAI language model. Based on authentication plugins such as Key Auth, we implement multi-tenant authentication under a unified OpenAI API-Key. Based on the Request-Block plugin, we implement the interception of requests with sensitive information and ensure data protection.

Prerequisites

  1. Install Higress. Please refer to Deploy Higress by Helm.
  2. Prepare the development environment for WASM plugins with Golang. Please refer to Developing a WASM plugin with Golang | Higress.

AI Proxy WASM Plugin

The following will give the AI proxy plugin implementation based on Higress and WASM. Higress supports scalability externally based on WASM. The multi-language ecology and hot-swapping mechanism provided by the WASM facilitate the implementation and deployment of the plugin. Higress also supports requesting external services in the plugin, which provides an efficient solution path for the implementation of the AI proxy plugin.

Code Implementation

The following code implements the request proxy to OPENAI-API based on HTTP. For details, please refer to the AI proxy plugin. The specific implementation steps are as follows:

  1. Create a new HTTP client, specify the OpenAI API host through the RouteCluster method, and determine the request proxy path.
func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
//The default forwarding path is OpenAI API.
//Users can adjust through configuration.
chatgptUri := json.Get("chatgptUri").String()
var chatgptHost string
if chatgptUri == "" {
config.ChatgptPath = "/v1/completions"
chatgptHost = "api.openai.com"
}
...
//Specify the specific request proxy host through RouteCluster.
config.client = wrapper.NewClusterClient(wrapper.RouteCluster{
Host: chatgptHost,
})
...
}

  1. Encapsulate the request in the OpenAI-API format, send requests and receive responses through the HTTP Client, and send responses to the user.
//OPENAI API request body template. Please refer to https://platform.openai.com/docs/api-reference/chat
const bodyTemplate string = `
{
"model":"%s",
"prompt":"%s",
"temperature":0.9,
"max_tokens": 150,
"top_p": 1,
"frequency_penalty": 0.0,
"presence_penalty": 0.6,
"stop": ["%s", "%s"]
}
`
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
...
//Encapsulate the OPENAI API request body according to the user's request content.
body := fmt.Sprintf(bodyTemplate, config.Model, prompt[0], config.HumanId, config.AIId)
//Post request via HTTP client.
err = config.client.Post(config.ChatgptPath, [][2]string{
{"Content-Type", "application/json"},
{"Authorization", "Bearer " + config.ApiKey},
}, []byte(body),
func(statusCode int, responseHeaders http.Header, responseBody []byte) {
var headers [][2]string
for key, value := range responseHeaders {
headers = append(headers, [2]string{key, value[0]})
}
//Receive the response from the OPENAI API and send it to user
proxywasm.SendHttpResponse(uint32(statusCode), headers, responseBody, -1)
}, 10000)
...
}

Enable the custom AI-Proxy-Wasm plugin in Higress as follows:

This example provides the compiled AI-proxy-plugin WASM file and completes the construction and push of the docker image. The recommended configuration is as follows:

NameRecommended configuration
Image URLoci://registry.cn-hangzhou.aliyuncs.com/zwj_test/chatgpt-proxy:1.0.0
Plugin Execution PhaseAuthz
Plugin Execution Priority1

Plugin configuration instructions

AI-Proxy-Plugin is easy to configure and supports proxy forwarding at the global/domain name level/routing level. Route-level configuration is recommended: route config-strategy-enable plugin. An example configuration is as follows:

apiKey: "xxxxxxxxxxxxxxxxxx"
model: "curie"
promptParam: "text"

According to this configuration, the gateway proxies to the Curie model in OpenAI, and the user enters prompts in the URL through the keyword "text".

curl "http://{GatewayIP}/?text=Say,hello"

Response from Curie model in OpenAI:

image.png

Multi-tenant authentication based on Key Auth

Different from the form of issuing AI-API keys for each member, enterprises can utilize internal authorization (such as Key Auth, etc.) and rely on the unified AI-API key for request proxy to achieve unified management of API usage.

Key Auth implements the authentication based on the Gateway level API Key. Key Auth supports parsing the API Key from the URL parameter or request header of the HTTP requests and verifies whether the API has permission to access.

consumers:
- credential: "xxxxxx"
name: "consumer1"
- credential: "yyyyyy"
name: "consumer2"
global_auth: false
in_header: true
keys:
- "apikey"

allow: [consumer1]

The above configuration defines consumers, and only consumer1 has the access right to the AI model service under the current route.

curl "http://{GatewayIP}/?text=Say,hello"
#The request does not provide an API Key, return 401

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:zzzzzz"
#The API Key provided by the request is not authorized to access, return 401

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:yyyyyy"
#The caller matched according to the API Key provided in the request has no access rights, return 403

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:xxxxxx"
#The caller has access to the AI model service, the request will be proxied to the AI model, and the response from the OpenAI API will be received normally

In addition to providing gateway-level multi-tenant authentication, Higress provides traffic control and other capabilities. The Key Rate Limit plugin can limit the user's application rate based on the user's membership in the consumption group.

Data protection based on Request Block

For AIGC applications, especially LLM services, a good return often requires users to provide enough prompts as model input. Users face the risk of data leakage in the process of providing prompts. Ensuring data security in the process of using the AIGC application is also an important issue for API callers.

Protecting data security involves stringent control over the API calling channels. One method involves confirming specifically approved models with their published API. Another way is to intercept user requests containing sensitive information. These can be achieved by setting specific request interception at the gateway level. Higress provides request interception based on the request block plugin, which can prevent unauthorized models from accessing user information and prevent user requests containing sensitive information from being exposed to the external network. +

· One min read

Placeholder. DO NOT DELETE.

· One min read

Placeholder. DO NOT DELETE.

· 9 mins read

AIGC applications represented by ChatGPT have brought great changes to enterprise production and greatly improved people's production efficiency. Large AI models can help to complete various complex tasks, such as helping developers write, debug and record codes, researchers quickly understand scientific research fields, marketers write product descriptions, etc. More and more enterprises have begun to attach importance to AIGC application development. How to manage the API of large AI models through the gateway has become a concern.

Higress is a next-generation cloud-native gateway based on Alibaba's internal gateway practices. Powered by Istio and Envoy, Higress realizes the integration of the triple gateway architecture of traffic gateway, microservice gateway, and security gateway, thereby greatly reducing the costs of deployment, operation, and maintenance. Based on the rich capabilities provided by Higress, enterprises can greatly reduce the cost of using large AI models.

How does Higress reduce the cost of using AI models?

Taking OpenAI as an example, OpenAI's APIs are priced not based on the number of requests or subscription time but based on the usage of each request. For large AI models, tokens are the standard billing strategy for OpenAI API as a measure of the complexity of inference tasks. The cost for tokens varies based on the model. Generally, more complex models give better results at a higher cost. API Keys are distributed to consumers for authentication and charging.

image.png

It is unrealistic for an organization to apply for an API Key for each member. Scattered API keys will not be conducive to the organization's calculation, management, and payment of API usage, thereby increasing the cost of using large AI models. For organizations, the selection and access rights of AI models, the frequency of use of AI models and access permissions, and the management and protection of data exposed to AI models are all important API management.

Based on rich plugin capabilities, Higress provides functions such as authentication, request filtering, traffic control, usage monitoring, and security protection, helping organizations interact with large AI model APIs more securely, reliably, and observably. Based on the authentication provided by Higress, organizations can implement multi-tenant authentication and grant different AI model access rights to team members; based on the traffic control capability, organizations can set differentiated access rate limits for different models and users, effectively reducing the cost of using AI model; based on the request interception capability, organizations can effectively filter access requests containing sensitive information, and protect some internal site resources from being exposed to the outside world, effectively ensuring data security. Based on the index query and log system capabilities provided by Commercial Higress, organizations can observe and analyze the usage of AI model calls by different users to formulate more reasonable AI model usage strategies.

image.png

Manage OpenAI API with Higress

We will take Higress connecting to the OpenAI API as an example to introduce how Higress seamlessly connects to the large AI model. The overall solution is shown in Fig.3. We have extended the Higress plugin based on WASM to proxy requests to the OpenAI language model. Based on authentication plugins such as Key Auth, we implement multi-tenant authentication under a unified OpenAI API-Key. Based on the Request-Block plugin, we implement the interception of requests with sensitive information and ensure data protection.

Prerequisites

  1. Install Higress. Please refer to Deploy Higress by Helm.
  2. Prepare the development environment for WASM plugins with Golang. Please refer to Developing a WASM plugin with Golang | Higress.

AI Proxy WASM Plugin

The following will give the AI proxy plugin implementation based on Higress and WASM. Higress supports scalability externally based on WASM. The multi-language ecology and hot-swapping mechanism provided by the WASM facilitate the implementation and deployment of the plugin. Higress also supports requesting external services in the plugin, which provides an efficient solution path for the implementation of the AI proxy plugin.

Code Implementation

The following code implements the request proxy to OPENAI-API based on HTTP. For details, please refer to the AI proxy plugin. The specific implementation steps are as follows:

  1. Create a new HTTP client, specify the OpenAI API host through the RouteCluster method, and determine the request proxy path.
func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
//The default forwarding path is OpenAI API.
//Users can adjust through configuration.
chatgptUri := json.Get("chatgptUri").String()
var chatgptHost string
if chatgptUri == "" {
config.ChatgptPath = "/v1/completions"
chatgptHost = "api.openai.com"
}
...
//Specify the specific request proxy host through RouteCluster.
config.client = wrapper.NewClusterClient(wrapper.RouteCluster{
Host: chatgptHost,
})
...
}

  1. Encapsulate the request in the OpenAI-API format, send requests and receive responses through the HTTP Client, and send responses to the user.
//OPENAI API request body template. Please refer to https://platform.openai.com/docs/api-reference/chat
const bodyTemplate string = `
{
"model":"%s",
"prompt":"%s",
"temperature":0.9,
"max_tokens": 150,
"top_p": 1,
"frequency_penalty": 0.0,
"presence_penalty": 0.6,
"stop": ["%s", "%s"]
}
`
func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
...
//Encapsulate the OPENAI API request body according to the user's request content.
body := fmt.Sprintf(bodyTemplate, config.Model, prompt[0], config.HumanId, config.AIId)
//Post request via HTTP client.
err = config.client.Post(config.ChatgptPath, [][2]string{
{"Content-Type", "application/json"},
{"Authorization", "Bearer " + config.ApiKey},
}, []byte(body),
func(statusCode int, responseHeaders http.Header, responseBody []byte) {
var headers [][2]string
for key, value := range responseHeaders {
headers = append(headers, [2]string{key, value[0]})
}
//Receive the response from the OPENAI API and send it to user
proxywasm.SendHttpResponse(uint32(statusCode), headers, responseBody, -1)
}, 10000)
...
}

Enable the custom AI-Proxy-Wasm plugin in Higress as follows:

This example provides the compiled AI-proxy-plugin WASM file and completes the construction and push of the docker image. The recommended configuration is as follows:

NameRecommended configuration
Image URLoci://registry.cn-hangzhou.aliyuncs.com/zwj_test/chatgpt-proxy:1.0.0
Plugin Execution PhaseAuthz
Plugin Execution Priority1

Plugin configuration instructions

AI-Proxy-Plugin is easy to configure and supports proxy forwarding at the global/domain name level/routing level. Route-level configuration is recommended: route config-strategy-enable plugin. An example configuration is as follows:

apiKey: "xxxxxxxxxxxxxxxxxx"
model: "curie"
promptParam: "text"

According to this configuration, the gateway proxies to the Curie model in OpenAI, and the user enters prompts in the URL through the keyword "text".

curl "http://{GatewayIP}/?text=Say,hello"

Response from Curie model in OpenAI:

image.png

Multi-tenant authentication based on Key Auth

Different from the form of issuing AI-API keys for each member, enterprises can utilize internal authorization (such as Key Auth, etc.) and rely on the unified AI-API key for request proxy to achieve unified management of API usage.

Key Auth implements the authentication based on the Gateway level API Key. Key Auth supports parsing the API Key from the URL parameter or request header of the HTTP requests and verifies whether the API has permission to access.

consumers:
- credential: "xxxxxx"
name: "consumer1"
- credential: "yyyyyy"
name: "consumer2"
global_auth: false
in_header: true
keys:
- "apikey"

allow: [consumer1]

The above configuration defines consumers, and only consumer1 has the access right to the AI model service under the current route.

curl "http://{GatewayIP}/?text=Say,hello"
#The request does not provide an API Key, return 401

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:zzzzzz"
#The API Key provided by the request is not authorized to access, return 401

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:yyyyyy"
#The caller matched according to the API Key provided in the request has no access rights, return 403

curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:xxxxxx"
#The caller has access to the AI model service, the request will be proxied to the AI model, and the response from the OpenAI API will be received normally

In addition to providing gateway-level multi-tenant authentication, Higress provides traffic control and other capabilities. The Key Rate Limit plugin can limit the user's application rate based on the user's membership in the consumption group.

Data protection based on Request Block

For AIGC applications, especially LLM services, a good return often requires users to provide enough prompts as model input. Users face the risk of data leakage in the process of providing prompts. Ensuring data security in the process of using the AIGC application is also an important issue for API callers.

Protecting data security involves stringent control over the API calling channels. One method involves confirming specifically approved models with their published API. Another way is to intercept user requests containing sensitive information. These can be achieved by setting specific request interception at the gateway level. Higress provides request interception based on the request block plugin, which can prevent unauthorized models from accessing user information and prevent user requests containing sensitive information from being exposed to the external network.

blocked_code: 404
block_urls:
- password
- pw
case_sensitive: false

The above configuration defines URL-based shielding fields under the current route, in which requests containing sensitive information such as "password" and "pw" will be blocked。

curl "http://{GatewayIP}/?text=Mypassword=xxxxxx" -H "apikey:xxxxxx"
curl "http://{GatewayIP}/?text=pw=xxxxxx" -H "apikey:xxxxxx"
#The above request will be forbidden and return 404

Usage observation and analysis

For organizations, observing and analyzing the usage of large AI model calls for each user helps to understand their usage and costs. It is also necessary for individual users to understand their own call volume and overhead. Commercial Higress is deeply integrated with various metrics and log systems and provides an out-of-the-box usage observation and analysis report construction mechanism, which can view the usage of various APIs in real time and filter according to various parameters.

Taking the observation of each user's usage of the OPENAI-Curie model as an example, the administrator can set the observability parameter in the request header:x-mse-consumer, to distinguish users through MSE console - Cloud native Gateway - Gateway instance - Parameter Configurator- Custom Format. After adding the observability parameters, enter the Observation Analysis - Log Center to set the use statistics chart function to complete the observation and analysis of API usage. As shown in the figure below, the amount of calls to the OPENAI-Curie model of user consumer1 and user consumer2 is presented in the form of a pie chart.

image.png

Join the Higress community

Join Higress Slack: https://join.slack.com/t/w1689142780-euk177225/shared_invite/zt-1zbjm9d34-4nptVXPpNvnuKEKZ7V3MIg

To get invited: https://communityinviter.com/apps/w1689142780-euk177225/higress

If you find Higress helpful, welcome to Higress to star us!

- + \ No newline at end of file diff --git a/en-us/blog/plugin-transformer/index.html b/en-us/blog/plugin-transformer/index.html index d4efdf90b8..7af26bce5c 100644 --- a/en-us/blog/plugin-transformer/index.html +++ b/en-us/blog/plugin-transformer/index.html @@ -3,7 +3,7 @@ -plugin-transformer | Higress +plugin-transformer | Higress @@ -14,13 +14,13 @@ - + - +
+ \ No newline at end of file diff --git a/en-us/blog/release-070/index.html b/en-us/blog/release-070/index.html index 0a88c609ad..cf8631dd1a 100644 --- a/en-us/blog/release-070/index.html +++ b/en-us/blog/release-070/index.html @@ -3,7 +3,7 @@ -release-070 | Higress +release-070 | Higress @@ -14,13 +14,13 @@ - + - +
+ \ No newline at end of file diff --git a/en-us/blog/release-1.3/index.html b/en-us/blog/release-1.3/index.html index 4ca2e72c23..13a1851660 100644 --- a/en-us/blog/release-1.3/index.html +++ b/en-us/blog/release-1.3/index.html @@ -3,7 +3,7 @@ -release-1.3 | Higress +release-1.3 | Higress @@ -14,13 +14,13 @@ - + - +
+ \ No newline at end of file diff --git a/en-us/blog/release-100/index.html b/en-us/blog/release-100/index.html index d9858580cf..45e213ddf7 100644 --- a/en-us/blog/release-100/index.html +++ b/en-us/blog/release-100/index.html @@ -3,7 +3,7 @@ -release-100 | Higress +release-100 | Higress @@ -14,13 +14,13 @@ - + - +
+ \ No newline at end of file diff --git a/en-us/blog/rss.xml b/en-us/blog/rss.xml index 53f21a2be7..bd3c831c96 100644 --- a/en-us/blog/rss.xml +++ b/en-us/blog/rss.xml @@ -4,7 +4,7 @@ Higress Blog https://higress.io/en-us/blog Higress Blog - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT https://validator.w3.org/feed/docs/rss2.html https://github.com/jpmonette/feed en-us @@ -12,7 +12,7 @@ <![CDATA[2023-kubecon]]> https://higress.io/en-us/blog/2023-kubecon https://higress.io/en-us/blog/2023-kubecon - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -20,7 +20,7 @@ <![CDATA[DeployOnWindows]]> https://higress.io/en-us/blog/DeployOnWindows https://higress.io/en-us/blog/DeployOnWindows - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -28,7 +28,7 @@ <![CDATA[config-with-file]]> https://higress.io/en-us/blog/config-with-file https://higress.io/en-us/blog/config-with-file - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -36,7 +36,7 @@ <![CDATA[configmap]]> https://higress.io/en-us/blog/configmap https://higress.io/en-us/blog/configmap - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -44,7 +44,7 @@ <![CDATA[ospp-2023]]> https://higress.io/en-us/blog/ospp-2023 https://higress.io/en-us/blog/ospp-2023 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -52,7 +52,7 @@ <![CDATA[plugin-transformer]]> https://higress.io/en-us/blog/plugin-transformer https://higress.io/en-us/blog/plugin-transformer - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -60,7 +60,7 @@ <![CDATA[release-070]]> https://higress.io/en-us/blog/release-070 https://higress.io/en-us/blog/release-070 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -68,7 +68,7 @@ <![CDATA[release-1.3]]> https://higress.io/en-us/blog/release-1.3 https://higress.io/en-us/blog/release-1.3 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -76,7 +76,7 @@ <![CDATA[release-100]]> https://higress.io/en-us/blog/release-100 https://higress.io/en-us/blog/release-100 - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -84,7 +84,7 @@ <![CDATA[skywalking]]> https://higress.io/en-us/blog/skywalking https://higress.io/en-us/blog/skywalking - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -92,7 +92,7 @@ <![CDATA[user-mq]]> https://higress.io/en-us/blog/user-mq https://higress.io/en-us/blog/user-mq - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
@@ -100,7 +100,7 @@ <![CDATA[user-uu]]> https://higress.io/en-us/blog/user-uu https://higress.io/en-us/blog/user-uu - Thu, 16 Nov 2023 06:41:18 GMT + Thu, 16 Nov 2023 06:51:43 GMT Placeholder. DO NOT DELETE.

]]>
diff --git a/en-us/blog/skywalking/index.html b/en-us/blog/skywalking/index.html index 8ed279c460..4288cb5a46 100644 --- a/en-us/blog/skywalking/index.html +++ b/en-us/blog/skywalking/index.html @@ -3,7 +3,7 @@ -skywalking | Higress +skywalking | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/blog/user-mq/index.html b/en-us/blog/user-mq/index.html index 5b307474e3..0fc1c04bc3 100644 --- a/en-us/blog/user-mq/index.html +++ b/en-us/blog/user-mq/index.html @@ -3,7 +3,7 @@ -user-mq | Higress +user-mq | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/blog/user-uu/index.html b/en-us/blog/user-uu/index.html index 61bb1d19f1..472cde6968 100644 --- a/en-us/blog/user-uu/index.html +++ b/en-us/blog/user-uu/index.html @@ -3,7 +3,7 @@ -user-uu | Higress +user-uu | Higress @@ -14,13 +14,13 @@ - + - + + \ No newline at end of file diff --git a/en-us/community/contactItem/index.html b/en-us/community/contactItem/index.html index 53f73d67a9..0f9ae6a40c 100644 --- a/en-us/community/contactItem/index.html +++ b/en-us/community/contactItem/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/en-us/community/contributorItem/index.html b/en-us/community/contributorItem/index.html index 64d95eb537..77656de18f 100644 --- a/en-us/community/contributorItem/index.html +++ b/en-us/community/contributorItem/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/en-us/community/eventCard/index.html b/en-us/community/eventCard/index.html index f63379d3d6..20177a4302 100644 --- a/en-us/community/eventCard/index.html +++ b/en-us/community/eventCard/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/en-us/community/index.html b/en-us/community/index.html index 84b3b2ff25..8901407b35 100644 --- a/en-us/community/index.html +++ b/en-us/community/index.html @@ -14,13 +14,13 @@ - +
- + \ No newline at end of file diff --git a/en-us/docs/dev/CustomResourceDefinition/index.html b/en-us/docs/dev/CustomResourceDefinition/index.html index 338e9bac48..ecd2096d85 100644 --- a/en-us/docs/dev/CustomResourceDefinition/index.html +++ b/en-us/docs/dev/CustomResourceDefinition/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/dev/architecture/index.html b/en-us/docs/dev/architecture/index.html index 77dcb852a6..0b4cbc028d 100644 --- a/en-us/docs/dev/architecture/index.html +++ b/en-us/docs/dev/architecture/index.html @@ -14,13 +14,13 @@ - +

Component Compilation Instructions

Higress Controller

The Higress controller is a control plane that connects to Istio to generate Istio API objects and sends them to Istio using the xDS protocol.

To compile the binary that can run in the local environment, execute make build in the higress repository directory.

If need to compile the Docker image, please execute make docker-build .

Higress Gateway

The Higress gateway is a data plane that implements gateway routing and forwarding capabilities.

Executing make build-gateway in the higress repository directory will compile the Higress Gateway image.

- + \ No newline at end of file diff --git a/en-us/docs/dev/code/index.html b/en-us/docs/dev/code/index.html index 77fc062cc6..cbbb5116fc 100644 --- a/en-us/docs/dev/code/index.html +++ b/en-us/docs/dev/code/index.html @@ -14,13 +14,13 @@ - +

Code Reading Instructions

If you would like to constribute source code for Higress, please check out the Contribute Guide

Code base structure descriptions:

  • cmd: Containing functions of parsing command-line arguments, etc.

  • pkg/ingress: Containing functions of converting Ingress resources to Istio resources.

  • pkg/bootstrap: Containing functions of starting gRPC/xDS/HTTP servers.

  • registry: Implementations of various service registries.

  • envoy: Containing the referred official envoy codebase and corresponding patches.

  • istio: Containing the referred official istio codebase and corresponding patches.

  • plugins: Higress plugin SDK and official built-in plugins.

  • tools: Building related scripts.

  • docker: Docker image building related scripts.

During compilation, make prebuild will be executed automatically, generating an external folder, which contains all the external dependencies, including envoy and istios, with all the patches applied.

If you would like to modify the source code of envoy or istio, you can do it directly in the external folder, then execute the prebuild command and generate the patch file with diff later. For example:

mv external/envoy external/envoy_new
make prebuild
diff -Naur external/envoy external/envoy_new > envoy/1.20/patches/envoy/$(date +%Y%m%d)-what-changed.patch

Please be aware that patches will be applied in the order of file names. So please use timestamp as a prefix when naming a new patch file.

- + \ No newline at end of file diff --git a/en-us/docs/developers/committer-guide/label-an-issue-guide_dev/index.html b/en-us/docs/developers/committer-guide/label-an-issue-guide_dev/index.html index 918779ec76..1c0833165a 100644 --- a/en-us/docs/developers/committer-guide/label-an-issue-guide_dev/index.html +++ b/en-us/docs/developers/committer-guide/label-an-issue-guide_dev/index.html @@ -14,13 +14,13 @@ - +

Label an Issue

If you are handling an issue, remember to mark the issue clearly with one or more labels whenever you think it's meaningful. With labels on, other developers can easily recognize problems, classify them or track progress.

For issues or pull requests that need coding and further version release to fix, you should always mark it with a milestone.

Some frequently used labels:

  • Help Wanted

    • help wanted
    • good first issue
  • Priority

    • priority/blocker
    • priority/high
    • priority/low
    • priority/normal
  • Status

    • status/need-triage
    • status/DO-NOT-MERGE
    • status/READY-TO-MERGE
    • status/invalid
    • status/wontfix
  • Type

    • type/bug
    • type/documentation
    • type/enhancement
    • type/feature
- + \ No newline at end of file diff --git a/en-us/docs/developers/committer-guide/release-guide_dev/index.html b/en-us/docs/developers/committer-guide/release-guide_dev/index.html index 43c431a2fa..d5f538cdd3 100644 --- a/en-us/docs/developers/committer-guide/release-guide_dev/index.html +++ b/en-us/docs/developers/committer-guide/release-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/developers/committer-guide/website-guide_dev/index.html b/en-us/docs/developers/committer-guide/website-guide_dev/index.html index 97065c6a81..32ce499b94 100644 --- a/en-us/docs/developers/committer-guide/website-guide_dev/index.html +++ b/en-us/docs/developers/committer-guide/website-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/developers/contributor-guide/new-contributor-guide_dev/index.html b/en-us/docs/developers/contributor-guide/new-contributor-guide_dev/index.html index e9025fb3d6..b9bad38778 100644 --- a/en-us/docs/developers/contributor-guide/new-contributor-guide_dev/index.html +++ b/en-us/docs/developers/contributor-guide/new-contributor-guide_dev/index.html @@ -14,13 +14,13 @@ - +

New contributor guide

This is a guide for new contributor who wants to contribute to Higress.

Subscribe to the mailing list

TBD

Reporting issue

You can always reporting an issue to Higress via Github Issues.

If you are reporting bugs, please refer to the issue report template.

If you are reporting feature, please refer to the issue report template.

If you are reporting regular issues, like raise an question, you can open an regular issue.

Sending pull request

  • Follow the checklist in the pull request template
  • Before you sending out the pull request, please sync your forked repository with remote repository, this will make your pull request simple and clear. See guide below:
git remote add upstream git@github.com:alibaba/higress.git
git fetch upstream
git rebase upstream/main
git checkout -b your_awesome_patch
... add some work
git push origin your_awesome_patch

Code convention

Please check the CONTRIBUTING.md for code convention.

- + \ No newline at end of file diff --git a/en-us/docs/developers/contributor-guide/reporting-security-issues_dev/index.html b/en-us/docs/developers/contributor-guide/reporting-security-issues_dev/index.html index 0bbbec019a..1e675d94e8 100644 --- a/en-us/docs/developers/contributor-guide/reporting-security-issues_dev/index.html +++ b/en-us/docs/developers/contributor-guide/reporting-security-issues_dev/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

Reporting Security Issues

The Higress Group takes a rigorous standpoint in annihilating the security issues in its software projects. Higress is highly sensitive and forthcoming to issues pertaining to its features and functionality.

REPORTING VULNERABILITY

If you have apprehensions regarding Higress's security or you discover vulnerability or potential threat, don’t hesitate to get in touch with the Higress Security Team by dropping a mail at [higress@googlegroups.com] (mailto:higress@googlegroups.com). In the mail, specify the description of the issue or potential threat. You are also urged to recommend the way to reproduce and replicate the issue. The Higress community will get back to you after assessing and analysing the findings.

PLEASE PAY ATTENTION to report the security issue on the security email before disclosing it on public domain.

VULNERABILITY HANDLING

An overview of the vulnerability handling process is:

  • The reporter reports the vulnerability privately to Apache.
  • The appropriate project's security team works privately with the reporter to resolve the vulnerability.
  • A new release of the Apache product concerned is made that includes the fix.
  • The vulnerability is publically announced.
- + \ No newline at end of file diff --git a/en-us/docs/developers/contributor-guide/test-coverage-guide_dev/index.html b/en-us/docs/developers/contributor-guide/test-coverage-guide_dev/index.html index 74ab7d69c8..6d3daab913 100644 --- a/en-us/docs/developers/contributor-guide/test-coverage-guide_dev/index.html +++ b/en-us/docs/developers/contributor-guide/test-coverage-guide_dev/index.html @@ -14,14 +14,14 @@ - +

Test coverage guide

How to divide test granularity

How to divide test granularity is a big problem. Chris Richardson has divided unit test, integration test, component test and end-to-end test for services test in "[Descending the Testing Pyramid: Effective Testing Strategies for Microservices](https://microservices.io/microservices/testing/2019/09/20/oracle-code-one-testing.html)". We can use it for reference in the process of designing test cases.

Unit Test

1.The benefits of unit testing

  • Unit test code can help everyone to go into details and understand the function of the code.
  • We can find bugs by test case, and then enhance the robustness of the code.
  • Test case code is also the demo usage of the core code.

2.Some design principle of unit test case

  • Steps, fine-grained and combination conditions should be well designed.
  • Attention to boundary condition test
  • Test code should also be designed without writing useless code.
  • When you find a method that is hard to write unit test, if you can be sure the method is "smelly code", then refactor it with the committer.
  • The mock framework in higress is: mockito. Some tutorials:[mockito tutorial](http://www. baeldung.com/bdd-mockito),mockito refcard
  • TDD(optional):When you start a new issue, you can try to write test case at first

3.The specified value of the test coverage

  • In the stage, the test coverage specified value of delta changed codes is :>=80%. The higher, the better.
  • We can see the coverage report in this page: https://codecov.io/gh/alibaba/higress

4.Project agreement

  • The unit test cases of the Higress project are distributed in each sub module of the project, and the test assertion class ends with Test.

Integration test

Project agreement

  • Integration test in this project generally refers to the test above unit test level.
  • This project use github actionsjiblib maven pluginfabric maven plugintestContainers to build Docker images,and build integration test environment
  • Different from unit test, if a test case needs to rely on the third-party middleware, you can use the above tools to build the docker environment and test without mock. But also pay attention to the granularity of building components. For an overly complex environment, you can: the middleware on which the core test depends can be built by docker, and the middleware on which the core test depends can be mocked
  • The integration test cases of the Higress project are uniformly placed in the integration-test sub module, and the test assertion class ends with IT.
  • Junit5 is used here
  • In the process of parallel running of test cases, pay attention to the isolation state of common middleware, plan the test data and prevent conflicts.
- + \ No newline at end of file diff --git a/en-us/docs/developers/developers_dev/index.html b/en-us/docs/developers/developers_dev/index.html index d7823dfe6f..017c0d7e25 100644 --- a/en-us/docs/developers/developers_dev/index.html +++ b/en-us/docs/developers/developers_dev/index.html @@ -14,13 +14,13 @@ - +

Developers

Higress Team

This page shows Higress developers and continues to expand. The list is not prioritized.

Higress Committer List

namegithubcompany
Tianyi ZhangjohnlanniAlibaba
Leilei GenggengleileiAlibaba
Yang FanSpecialYangAlibaba
Bingkun ZhaosjtuzbkAlibaba
Yiqun LingLynskylatePdd Holdings Inc
Xunzhuo LiuXunzhuoTencent
Yiquan DongCH3CHOTrip.com
Qianglin LiCharlie17LiZJU-SEL
Pengyuan SongsongpengyuanOkki.com
YaTao TianHinstenyAnt

Higress Developer Roles

Higress developers include three roles: Maintainer, Committer, and Contributor. The standard definitions for each role are as follows.

Maintainer

Maintainer is an individual who has made a significant contribution to the evolution and development of the Higress project, including projects under the Higress group. Specifically includes the following criteria:

  • Completing the design and development of multiple key modules or projects, is an core developer of the project.
  • Continuous investment and passion, can actively participate in the maintenance of related matters such as community, official website, issue, PR, etc.
  • Has a visible influence in the community and is able to represent Higress in important community meetings and events.
  • Have the consciousness and ability to cultivate Committer and Contributor.

Committer

Committer is an individual with write access to the Higress repository and includes the following criteria:

  • An individual who can contribute to the issue and PR continuously for a long time.
  • Participate in the maintenance of the issue list and discussion of important features.
  • Participate in code review.

Contributor

Contributor is an individual who contributes to the Higress project. The standard is:

  • Submitted a PR that is merged.
- + \ No newline at end of file diff --git a/en-us/docs/developers/guide_dev/index.html b/en-us/docs/developers/guide_dev/index.html index 4c48c4afc7..8d2f19ad39 100644 --- a/en-us/docs/developers/guide_dev/index.html +++ b/en-us/docs/developers/guide_dev/index.html @@ -14,7 +14,7 @@ - + @@ -28,7 +28,7 @@ clone repository to your local machine. Then you can create new branches to finish the change you wish to make.

  • Set Remote upstream to be git@github.com:alibaba/higress.git using the following two commands:

  • git remote add upstream git@github.com:alibaba/higress.git
    git remote set-url --push upstream no-pushing

    With this remote setting, you can check your git remote configuration like this:

    $ git remote -v
    origin git@github.com:<your-username>/higress.git (fetch)
    origin git@github.com:<your-username>/higress.git (push)
    upstream git@github.com:alibaba/higress.git (fetch)
    upstream no-pushing (push)

    Adding this, we can easily synchronize local branches with upstream branches.

    Branch Definition

    Right now we assume every contribution via pull request is for [branch main](https://github. com/alibaba/higress/tree/main) in Higress. Before contributing, be aware of branch definition would help a lot.

    As a contributor, keep in mind again that every contribution via pull request is for branch main. While in project Higress, there are several other branches, we generally call them release branches (such as 0.6.0,0.6.1), feature branches, hotfix branches.

    When officially releasing a version, there will be a release branch and named with the version number.

    After the release, we will merge the commit of the release branch into the main branch.

    When we find that there is a bug in a certain version, we will decide to fix it in a later version or fix it in a specific hotfix version. When we decide to fix the hotfix version, we will checkout the hotfix branch based on the corresponding release branch, perform code repair and verification, and merge it into the main branch.

    For larger features, we will pull out the feature branch for development and verification.

    Commit Rules

    Actually in Higress, we take two rules serious when committing:

    Commit Message

    Commit message could help reviewers better understand what is the purpose of submitted PR. It could help accelerate the code review procedure as well. We encourage contributors to use EXPLICIT commit message rather than ambiguous message. In general, we advocate the following commit message type:

    • docs: xxxx. For example, "docs: add docs about Higress cluster installation".
    • feature: xxxx.For example, "feature: support oracle in AT mode".
    • bugfix: xxxx. For example, "bugfix: fix panic when input nil parameter".
    • refactor: xxxx. For example, "refactor: simplify to make codes more readable".
    • test: xxx. For example, "test: add unit test case for func InsertIntoArray".
    • other readable and explicit expression ways.

    On the other side, we discourage contributors from committing message like the following ways:

    • fix bug
    • update
    • add doc

    If you get lost, please see How to Write a Git Commit Message for a start.

    Commit Content

    Commit content represents all content changes included in one commit. We had better include things in one single commit which could support reviewer's complete review without any other commits' help. In another word, contents in one single commit can pass the CI to avoid code mess. In brief, there are three minor rules for us to keep in mind:

    • avoid very large change in a commit;
    • complete and reviewable for each commit.
    • check git config(user.name, user.email) when committing to ensure that it is associated with your github ID.

    In addition, in the code change part, we suggest that all contributors should read the code style of Higress.

    No matter commit message, or commit content, we do take more emphasis on code review.

    PR Description

    PR is the only way to make change to Higress project files. To help reviewers better get your purpose, PR description could not be too detailed. We encourage contributors to follow the PR template to finish the pull request.

    Test case contribution

    Any test case would be welcomed. Currently, Higress function test cases are high priority.

    • For unit test, you need to create a test file named xxxTest.java in the test directory of the same module. Recommend you to use the junit5 UT framework

    • For integration test, you can put the integration test in the test directory or the higress-test module. It is recommended to use the mockito test framework.

    Engage to help anything

    We choose GitHub as the primary place for Higress to collaborate. So the latest updates of Higress are always here. Although contributions via PR is an explicit way to help, we still call for any other ways.

    • reply to other's issues if you could;
    • help solve other user's problems;
    • help review other's PR design;
    • help review other's codes in PR;
    • discuss about Higress to make things clearer;
    • advocate Higress technology beyond GitHub;
    • write blogs on Higress and so on.

    Code Style

    Higress code style Comply with Alibaba Java Coding Guidelines.

    Guidelines

    Alibaba-Java-Coding-Guidelines

    IDE Plugin Install(not necessary)

    It is not necessary to install, if you want to find a problem when you are coding.

    idea IDE

    p3c-idea-plugin-install

    eclipse IDE

    p3c-eclipse-plugin-install

    In a word, ANY HELP IS CONTRIBUTION.

    - + \ No newline at end of file diff --git a/en-us/docs/ops/deploy-by-docker-compose/index.html b/en-us/docs/ops/deploy-by-docker-compose/index.html index 0ced1281ca..7c9c3a489f 100644 --- a/en-us/docs/ops/deploy-by-docker-compose/index.html +++ b/en-us/docs/ops/deploy-by-docker-compose/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/ops/deploy-by-helm/index.html b/en-us/docs/ops/deploy-by-helm/index.html index edde53b837..bac1c1586b 100644 --- a/en-us/docs/ops/deploy-by-helm/index.html +++ b/en-us/docs/ops/deploy-by-helm/index.html @@ -14,13 +14,13 @@ - +

    Deploy Higress by Helm

    Helm is a package manager for Kubernetes used in software management and deployment. You can use Helm to perform a quick install of Higress Gateway in your Kubernetes cluster.

    Install Higress

    Higress Gateway consists of a control plane component higress-controller and a data plane component higress-gateway. It uses Istio to management API configurations of the data plane, and higress-controller to manage API configurations of the control plane.

    Helm Installation Command

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress higress.io/higress -n higress-system --create-namespace

    Installation Parameters

    ParameterDescriptionDefault
    Global Parameters
    global.localSet to true if installing to a local K8s cluster (e.g.: Kind, Rancher Desktop, etc.)false
    global.ingressClassIngressClass which is used to filter Ingress resources Higress Controller watches.
    If there are multiple gateway instances deployed in the cluster, this parameter can be used to distinguish the scope of each gateway instance.
    There are some special cases for special IngressClass values:
    1. If set to "nginx", Higress Controller will watch Ingress resources with the nginx IngressClass or without any Ingress class.
    2. If set to empty, Higress Controller will watch all Ingress resources in the K8s cluster.
    higress
    global.watchNamespaceIf not empty, Higress Controller will only watch resources in the specified namespace. When isolating different business systems using K8s namespace, if each namespace requires a standalone gateway instance, this parameter can be used to confine the Ingress watching of Higress within the given namespace.""
    global.disableAlpnH2Whether to disable HTTP/2 in ALPNtrue
    global.enableStatusIf true, Higress Controller will update the status field of Ingress resources.
    When migrating from Nginx Ingress, in order to avoid status field of Ingress objects being overwritten, this parameter needs to be set to false, so Higress won't write the entry IP to the status field of the corresponding Ingress object.
    true
    global.enableIstioAPIIf true, Higress Controller will monitor istio resources as wellfalse
    global.istioNamespaceThe namespace istio is installed toistio-system
    Core Paramters
    higress-core.gateway.replicasNumber of Higress Gateway pods2
    higress-core.controller.replicasNumber of Higress Controller pods1
    Console Paramters
    higress-console.replicaCountNumber of Higress Console pods1
    higress-console.service.typeK8s service type used by Higress ConsoleClusterIP
    higress-console.domainDomain used to access Higress Consoleconsole.higress.io
    higress-console.tlsSecretNameName of Secret resource used by TLS connections.""
    higress-console.web.login.promptPrompt message to be displayed on the login page""
    higress-console.admin.passwordIf not empty, the admin password will be configured to the specified value.""
    higress-console.o11y.enabledIf true, o11y suite (Grafana + Promethues) will be installed.false
    higress-console.pvc.rwxSupportedSet to false when installing to a standard K8s cluster and the target cluster doesn't support the ReadWriteMany access mode of PersistentVolumeClaim.true

    Support Istio CRD

    The CRD of Istio needs to be installed in advance in the cluster. If you do not want to install Istio, you can also install only the CRD of Istio:

    helm repo add istio https://istio-release.storage.googleapis.com/charts
    helm install istio-base istio/base -n istio-system

    In this mode, you need to update the deployment parameters of Higress:

    helm upgrade higress -n higress-system --set global.enableIstioAPI=true higress.io/higress
    - + \ No newline at end of file diff --git a/en-us/docs/ops/hgctl/index.html b/en-us/docs/ops/hgctl/index.html index be00ab2a17..be28bfcff7 100644 --- a/en-us/docs/ops/hgctl/index.html +++ b/en-us/docs/ops/hgctl/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/ops/log/index.html b/en-us/docs/ops/log/index.html index d39849bc63..9f6cd9a2d9 100644 --- a/en-us/docs/ops/log/index.html +++ b/en-us/docs/ops/log/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/ops/upgrade/index.html b/en-us/docs/ops/upgrade/index.html index 3920f1ef8d..8a31ada453 100644 --- a/en-us/docs/ops/upgrade/index.html +++ b/en-us/docs/ops/upgrade/index.html @@ -14,13 +14,13 @@ - +

    Upgrade

    Cloud-Native Deployment

    Upgrade via Helm

    # Sample value of ${higress_version} : v1.1.0
    kubectl apply -f https://github.com/alibaba/higress/releases/download/${higress_version}/customresourcedefinitions.gen.yaml
    helm repo update
    helm upgrade higress -n higress-system higress.io/higress

    Standalone Deployment

    # ${higress_dir} is the path of Higress' installation directory
    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- "${higress_dir}" -u
    - + \ No newline at end of file diff --git a/en-us/docs/overview/faq/index.html b/en-us/docs/overview/faq/index.html index 95dfb8cd32..38d8065685 100644 --- a/en-us/docs/overview/faq/index.html +++ b/en-us/docs/overview/faq/index.html @@ -14,7 +14,7 @@ - + @@ -23,7 +23,7 @@ It is recommended to upgrade to v1.0.0 and above

    For details, please refer to our Roadmap


    Q: What is the difference between Higress and Envoy Gateway?

    A: Higress is implemented and extended based on Envoy, and follows the Gateway API standard like Envoy Gateway. The difference is that it also provides:

    • Waf protection, authentication and authentication and other security plug-in capabilities
    • Service management plug-in capabilities such as multiple registries, protocol conversion, and current limiting and downgrading. For example, for microservice users who traditionally use Dubbo, they want to use native RPC to expose external services, but usually the services that provide external access mainly use HTTP. To help Dubbo users reduce the development cost of service exposure, Higress provides the HTTP-to-Dubbo protocol function, and provides users with a white-screen configuration method through the Console. After using it, a customer reported that "this is the industry's most complete HTTP-to-Dubbo protocol." Function.
    • Support WASM, Lua and other custom plug-ins, such as Nginx users, we will also support out-of-process plug-ins to meet the demands of multi-language users, especially Java users who want to expand the gateway because the Java community's support for WebAssembly is not perfect at this stage demands.

    Q: What are the differences between Higress and Tengine, another open source gateway of Alibaba?

    A:

    Tengine is implemented based on Nginx, extended by Lua, and Higress is based on istio + Envoy, extended by WASM. The technical architecture is different, and developers can choose according to business scenarios. Higress already supports the ability of smooth migration of Nginx Ingress annotations, which meets the needs of some users who expect to migrate to Higress but do not want to reconfigure the gateway. Higress can be used as a unified access gateway while enjoying the bonus of Ingress.


    Q: What is the relationship between the MSE cloud-native gateway on Higress Alibaba Cloud? Is it an open source project incubated based on this?

    A:

    The MSE cloud-native gateway is a commercial version of Higress, with differences in capabilities, mainly reflected in performance, stability, ease of use, and security, because these are very dependent on the infrastructure capabilities on the cloud, and detailed resources are still available. After sorting, it will be displayed on the product page and document page of MSE in the future, which is convenient for everyone to choose. Of course, Higress is in the process of evolution. We will define with the community which capabilities on the MSE cloud-native gateway are open sourced, and we will also plan a plug-in market for open source.


    Q: Higress combines traffic gateway, microservice gateway, and security gateway into one. Is this practice common in the industry? Is it a trend?

    A:

    Traffic gateways, microservice gateways, and security gateways have always been used in the industry. Most of the deployment forms use independent cluster deployments. In the context of K8s-led containerization, K8s standardized ingress gateways through Ingress. Traditional traffic gateways, microservices The independent deployment mode of gateway and security gateway appears to be high in deployment cost and complicated in operation and maintenance under K8s. From the perspective of users, only a highly integrated gateway with rich functions is enough. Based on this, we judge that highly integrated gateway will be a future development trend.


    Q: Higress has customized the upstream. Is there a problem of not being able to enjoy community benefits and being burdened with ecological follow-up?

    A:

    The Higress core code basically adopts pluggable Filter extensions, and new functions also follow the principle of scalability as much as possible. In order to maintain its own stability in the upstream follow-up, it will not immediately follow up with the latest version. For example, APISIX and Kong kernels are based on Nginx , but they are still developing very well, and the facts also show that upstream follow-up will not become an obstacle to project development.


    Q: Higress supports Nacos service discovery, is there any plan to support Consul?

    A:

    Expected to be available in version 1.2.0


    Q: Does Higress have an offline deployment version?

    A:

    There is no existing one, you need to build it yourself. Currently, all Docker images are provided and can be pulled and used by yourself.


    Q: Can Higress be separated from the istio environment and run only based on Docker?

    A:

    Already supported, you can see it here: https://higress.io/en-us/docs/user/quickstart#environment-2-use-in-docker-compose-without-k8s


    Q: In addition to running on K8s, does Higress support running on virtual machines and physical machines?

    A:

    Not yet supported, open source will use Nacos for configuration management to support this requirement.

    You can also consider using [Higress Enterprise Edition] (https://www.aliyun.com/product/aliware/mse?spm=higress-website.topbar.0.0.0), this mode Higress is fully managed, no need to care about Higress Deployment and operation and maintenance, can directly connect to the back-end services deployed on virtual machines and physical machines.


    Q: Will Higress Dashboard be open source?

    A:

    Already open source: https://github.com/higress-group/higress-console


    Q: Does the current open source version support the Waf function, and is there any relevant best practice?

    A:

    Supported, you can read this document: https://higress.io/zh-cn/docs/user/waf/


    Q: Does Higress support auto-scaling, and is the gateway stateless?

    A:

    Higress is based on K8s HPA and supports elastic scaling. The gateway is stateless and is a deployment.


    Q: Does Higress have a roadmap?

    A:

    Please refer to Roadmap


    Q: How to join the Higress community to contribute, I can't wait

    A:

    We welcome everyone to participate in the construction of our project in various forms, including but not limited to:

    • Architecture design
    • Modular design
    • Code
    • Bug Fixes
    • Demo sample
    • Documentation, websites and translations

    For details on how to participate, please refer to Developer Guide on our official website or contact higress@googlegroups.com. In fact, we are not limited to the form of contribution. Every issue raised by a developer, whether it is a Bug Report, improvement suggestion or even a question consultation, represents attention and help to the project. I hope that the Higress project will grow healthily with the community and become an excellent solution in the field of cloud-native gateways.


    - + \ No newline at end of file diff --git a/en-us/docs/overview/roadmap/index.html b/en-us/docs/overview/roadmap/index.html index 81c65d7842..69c297ccc7 100644 --- a/en-us/docs/overview/roadmap/index.html +++ b/en-us/docs/overview/roadmap/index.html @@ -14,13 +14,13 @@ - +

    Roadmap

    Version numberCore goalEstimated release time
    v0.6.0The black screen operation (kubectl) under K8s has reached GA status; the preview version of the console is released to improve the ease of installation and deployment2023-01
    v0.7.0The official version of the console is released, integrating observables out of the box2023-02
    v1.0.0Overall reached GA status2023-05
    v1.1.0Enhance the microservice gateway related capabilities in the console function; support installation and deployment under non-K8s2023-07
    v1.2.0Supports use as the network layer of Knative; supports ARM architecture deployment; supports docking with Consul2023-08
    v1.3.0Fully support GatewayAPI; support Operator mode deployment2023-09
    v1.4.0Launched WASM Plugin Marketplace2023-10
    - + \ No newline at end of file diff --git a/en-us/docs/overview/terminology/index.html b/en-us/docs/overview/terminology/index.html index cbed54b5d4..c29f598dc7 100644 --- a/en-us/docs/overview/terminology/index.html +++ b/en-us/docs/overview/terminology/index.html @@ -14,13 +14,13 @@ - +

    Higress Terminology

    #Higress Terminology

    Ingress Annotation (Annotation)

    The annotation (Annotation) field in the Ingress resource is a kv dictionary structure, which can implement various routing strategies in a declarative manner. As shown below, annotations are used to enable cross-domain access permission for the Ingress route:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: ingress-example
    annotations:
    higress.io/enable-cors: "true"
    spec:
    ingressClassName: nginx-example
    rules:
    - http:
    paths:
    - path: /test
    pathType: Prefix
    backend:
    service:
    name: test
    port:
    number: 80

    For other annotation configuration methods supported by Higress, please refer to Ingress Annotation Configuration Instructions

    Downstream

    Downstream refers to the source where Higress receives the request, usually a client such as a browser

    Upstream

    Upstream refers to the target backend service that Higress forwards the request to

    - + \ No newline at end of file diff --git a/en-us/docs/overview/what-is-higress/index.html b/en-us/docs/overview/what-is-higress/index.html index c2b0152902..36425e7aae 100644 --- a/en-us/docs/overview/what-is-higress/index.html +++ b/en-us/docs/overview/what-is-higress/index.html @@ -14,13 +14,13 @@ - +

    What Is Higress?

    Higress is a next-generation cloud-native gateway built on the core of open-source Istio + Envoy based on Alibaba's internal Envoy Gateway practice. It realizes the high integration capability of three-in-one traffic gateway + microservice gateway + security gateway, and deeply integrates Dubbo and Nacos , Sentinel and other micro-service technology stacks can help users greatly reduce the cost of gateway deployment and operation and maintenance without compromising capabilities; fully support Ingress and Gateway APIs in terms of standards, and actively embrace the standard API specifications under cloud native; at the same time, Higress The Controller also supports smooth migration of Nginx Ingress, helping users quickly migrate to Higress at zero cost.

    image

    Classification of traditional gateways

    In the industry, gateways are usually divided into two categories: traffic gateways and business gateways. Traffic gateways mainly provide global policy configurations that have nothing to do with back-end business. For example, Ali’s internal unified access gateway Tengine is a typical traffic gateway. ; As the name suggests, the business gateway mainly provides independent business domain-level, tightly coupled policy configuration with the back-end business. With the evolution of the application architecture model from a single body to the current distributed micro-service, the business gateway also has a new name - micro-service gateway ( Illustrations are shown below). In the current cloud-native era dominated by container technology and K8s, is the next-generation gateway model still the same?

    Positioning

    Under the microservice architecture in the virtualization era, the business usually adopts a two-tier architecture of traffic gateway + microservice gateway. The traffic gateway is responsible for north-south traffic scheduling and security protection, and the microservice gateway is responsible for east-west traffic scheduling and service governance. In the cloud-native era dominated by K8s, Ingress has become the gateway standard of the K8s ecosystem, endowing the gateway with a new mission and making it possible to combine traffic gateway + microservice gateway into one.

    As a north-south public network gateway, it is a common requirement to use Waf to protect abnormal traffic. As the Internet environment becomes more and more complex, users' demands for protection continue to increase. The conventional method is to access the traffic first. The Waf security gateway, after filtering, forwards the traffic to the traffic gateway, and finally reaches the microservice gateway; Higress hopes that through the built-in Waf module, the user's request link can be simultaneously completed Waf protection, traffic distribution, and microservice governance only through Higress. It can improve the link RT and reduce the operation and maintenance complexity of the gateway. Therefore, Higress realizes the high integration capability of three-in-one traffic gateway + microservice gateway + security gateway.

    Why did Higress choose Envoy/Istio as the engine

    In the context of containerized cloud native, Kubernetes has become a standard interface between infrastructure and upper-layer applications. The natural internal and external network isolation environment of Kubernetes clusters requires external traffic to enter the Kubernetes cluster through an ingress gateway. Therefore, Kubernetes is standardized through Ingress The definition and standard of the ingress gateway. Although the Ingress standard has some shortcomings such as weak routing expression ability, the community has been actively promoting the definition of the Gateway API standard to solve it. However, it is undeniable that the Ingress standard still occupies the mainstream. CNCF annual report The usage of Ingress Provider (the implementers of the Ingress standard are collectively referred to as Ingress Provider) is also counted separately.

    Although Nginx Ingress still occupies the top spot of K8s Ingress Provider, Envoy has the fastest growth, from less than 20% in 2019 to 37% in 2020, and only after Nginx Ingress , the growth momentum is very rapid, which shows that choosing Envoy as the core is in line with the development trend of cloud native; and as Service Mesh is gradually recognized by the public, the system of Istio + Envoy can cover both the Mesh and Ingress fields at the same time, realizing a set of technical architecture The goal of dispatching east-west and north-south global traffic is also very meaningful to users.

    Higress practise inside Alibaba

    Higress was incubated from Alibaba's internal "Local Life Campaign" in May 2020. It was originally built to meet the demands of Alibaba Group and Ant Group to directly use RPC to request mutual visits, and the project also successfully incubated Dubbo 3.0's Triple Therefore, Higress is also the first internal application that supports the Triple protocol. In the same year, Higress also successfully supported major promotional activities such as Double 11 and Double 12. With the expansion of business scope, Higress has already supported Youku, DingTalk, For businesses such as Dharma Academy and Ant, the business scenarios have also been extended to global traffic scheduling in east-west and north-south directions.

    - + \ No newline at end of file diff --git a/en-us/docs/plugins/basic-auth/index.html b/en-us/docs/plugins/basic-auth/index.html index 80464c39bf..cc1abd1164 100644 --- a/en-us/docs/plugins/basic-auth/index.html +++ b/en-us/docs/plugins/basic-auth/index.html @@ -14,13 +14,13 @@ - +

    Basic Auth

    Description

    basic-auth plugin implements the function of authentication based on the HTTP Basic Auth standard.

    Configuration Fields

    NameTypeRequirementDefault ValueDescription
    consumersarray of objectRequired-Caller of the service for authentication of requests
    _rules_array of objectOptional-Configure access permission list for specific routes or domains to authenticate requests

    Filed descriptions of consumers items:

    NameTypeRequirementDefault ValueDescription
    credentialstringRequired-Credential for this consumer's access
    namestringRequired-Name of this consumer

    Configuration field descriptions for each item in _rules_ are as follows:

    Field NameData TypeRequirementDefaultDescription
    _match_route_array of stringOne of _match_route_ or _match_domain_-Configure the routes to match for request authorization
    _match_domain_array of stringOne of _match_route_ , _match_domain_-Configure the domains to match for request authorization
    allowarray of stringRequired-Configure the consumer names allowed to access requests that match the match condition

    Note:

    • If the _rules_ field is not configured, authentication is enabled for all routes of the current gateway instance by default;
    • For authenticated requests, X-Mse-Consumer field will be added to the request header to identify the name of the caller.

    Configuration Samples

    Enable Authentication and Authorization for specific routes or domains

    The following configuration will enable Basic Auth authentication and authorization for specific routes or domains of the gateway. Note that the username and password in the credential information are separated by a ":", and the credential field cannot be repeated.

    # use the _rules_ field for fine-grained rule configuration.
    consumers:
    - credential: 'admin:123456'
    name: consumer1
    - credential: 'guest:abc'
    name: consumer2
    _rules_:
    # rule 1: match by the route name.
    - _match_route_:
    - route-a
    - route-b
    allow:
    - consumer1
    # rule 2: match by the domain.
    - _match_domain_:
    - "*.example.com"
    - test.com
    allow:
    - consumer2

    In this sample, route-a and route-b specified in _match_route_ are the route names filled in when creating gateway routes. When these two routes are matched, the caller with name as consumer1 is allowed to access, and other callers are not allowed to access.

    The *.example.com and test.com specified in _match_domain_ are used to match the domain name of the request. When the domain name is matched, the caller with name as consumer2 is allowed to access, and other callers are not allowed to access.

    According to this configuration, the following requests are allowed:

    Requests with specified username and password

    # Assuming the following request will match with route-a
    # Use -u option of curl to specify the credentials
    curl -u admin:123456 http://xxx.hello.com/test
    # Or specify the Authorization request header directly with the credentials in base64 encoding
    curl -H 'Authorization: Basic YWRtaW46MTIzNDU2' http://xxx.hello.com/test

    A X-Mse-Consumer field will be added to the headers of the request, and its value in this example is consumer1, used to identify the name of the caller when passed authentication and authorization.

    The following requests will be denied:

    Requests without providing username and password, returning 401

    curl  http://xxx.hello.com/test

    Requests with incorrect username or password, returning 401

    curl -u admin:abc  http://xxx.hello.com/test

    Requests matched with a caller who has no access permission, returning 403

    # consumer2 is not in the allow list of route-a
    curl -u guest:abc http://xxx.hello.com/test

    Enable basic auth for gateway instance

    The following configuration does not specify the _rules_ field, so Basic Auth authentication will be effective for the whole gateway instance.

    consumers:
    - credential: 'admin:123456'
    name: consumer1
    - credential: 'guest:abc'
    name: consumer2

    Error Codes

    HTTP Status CodeError InfoReason
    401Request denied by Basic Auth check. No Basic Authentication information found.Credentials not provided in the request
    401Request denied by Basic Auth check. Invalid username and/or passwordInvalid username and/or password
    403Request denied by Basic Auth check. Unauthorized consumerUnauthorized consumer
    - + \ No newline at end of file diff --git a/en-us/docs/plugins/bot-detect/index.html b/en-us/docs/plugins/bot-detect/index.html index 84e462d3a2..d53619cdf6 100644 --- a/en-us/docs/plugins/bot-detect/index.html +++ b/en-us/docs/plugins/bot-detect/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    Robot Detect

    Description

    bot-detect plugin can be used to identify and prevent web crawlers from crawling websites.

    Configuration Fields

    NameTypeRequirementDefault ValueDescription
    allowarray of stringOptional-A regular expression to match the User-Agent request header and will allow access if the match hits
    denyarray of stringOptional-A regular expression to match the User-Agent request header and will block the request if the match hits
    blocked_codenumberOptional403The HTTP status code returned when a request is blocked
    blocked_messagestringOptional-The HTTP response Body returned when a request is blocked

    If field allow and field deny are not configured at the same time, the default logic to identify crawlers will be executed. By configuring the allow field, requests that would otherwise hit the default logic can be allowed. The judgement can be extended by configuring the deny field

    The default set of crawler judgment regular expressions is as follows:

    # Bots General matcher 'name/0.0'
    (?:\/[A-Za-z0-9\.]+|) {0,5}([A-Za-z0-9 \-_\!\[\]:]{0,50}(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]{0,50}))[/ ](\d+)(?:\.(\d+)(?:\.(\d+)|)|)
    # Bots General matcher 'name 0.0'
    (?:\/[A-Za-z0-9\.]+|) {0,5}([A-Za-z0-9 \-_\!\[\]:]{0,50}(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]{0,50})) (\d+)(?:\.(\d+)(?:\.(\d+)|)|)
    # Bots containing spider|scrape|bot(but not CUBOT)|Crawl
    ((?:[A-z0-9]{1,50}|[A-z\-]{1,50} ?|)(?: the |)(?:[Ss][Pp][Ii][Dd][Ee][Rr]|[Ss]crape|[Cc][Rr][Aa][Ww][Ll])[A-z0-9]{0,50})(?:(?:[ /]| v)(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)
    # Bots Pattern '/name-0.0'
    /((?:Ant-)?Nutch|[A-z]+[Bb]ot|[A-z]+[Ss]pider|Axtaris|fetchurl|Isara|ShopSalad|Tailsweep)[ \-](\d+)(?:\.(\d+)(?:\.(\d+))?)?
    # Bots Pattern 'name/0.0'
    \b(008|Altresium|Argus|BaiduMobaider|BoardReader|DNSGroup|DataparkSearch|EDI|Goodzer|Grub|INGRID|Infohelfer|LinkedInBot|LOOQ|Nutch|OgScrper|PathDefender|Peew|PostPost|Steeler|Twitterbot|VSE|WebCrunch|WebZIP|Y!J-BR[A-Z]|YahooSeeker|envolk|sproose|wminer)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)
    # More bots
    (CSimpleSpider|Cityreview Robot|CrawlDaddy|CrawlFire|Finderbots|Index crawler|Job Roboter|KiwiStatus Spider|Lijit Crawler|QuerySeekerSpider|ScollSpider|Trends Crawler|USyd-NLP-Spider|SiteCat Webbot|BotName\/\$BotVersion|123metaspider-Bot|1470\.net crawler|50\.nu|8bo Crawler Bot|Aboundex|Accoona-[A-z]{1,30}-Agent|AdsBot-Google(?:-[a-z]{1,30}|)|altavista|AppEngine-Google|archive.{0,30}\.org_bot|archiver|Ask Jeeves|[Bb]ai[Dd]u[Ss]pider(?:-[A-Za-z]{1,30})(?:-[A-Za-z]{1,30}|)|bingbot|BingPreview|blitzbot|BlogBridge|Bloglovin|BoardReader Blog Indexer|BoardReader Favicon Fetcher|boitho.com-dc|BotSeer|BUbiNG|\b\w{0,30}favicon\w{0,30}\b|\bYeti(?:-[a-z]{1,30}|)|Catchpoint(?: bot|)|[Cc]harlotte|Checklinks|clumboot|Comodo HTTP\(S\) Crawler|Comodo-Webinspector-Crawler|ConveraCrawler|CRAWL-E|CrawlConvera|Daumoa(?:-feedfetcher|)|Feed Seeker Bot|Feedbin|findlinks|Flamingo_SearchEngine|FollowSite Bot|furlbot|Genieo|gigabot|GomezAgent|gonzo1|(?:[a-zA-Z]{1,30}-|)Googlebot(?:-[a-zA-Z]{1,30}|)|Google SketchUp|grub-client|gsa-crawler|heritrix|HiddenMarket|holmes|HooWWWer|htdig|ia_archiver|ICC-Crawler|Icarus6j|ichiro(?:/mobile|)|IconSurf|IlTrovatore(?:-Setaccio|)|InfuzApp|Innovazion Crawler|InternetArchive|IP2[a-z]{1,30}Bot|jbot\b|KaloogaBot|Kraken|Kurzor|larbin|LEIA|LesnikBot|Linguee Bot|LinkAider|LinkedInBot|Lite Bot|Llaut|lycos|Mail\.RU_Bot|masscan|masidani_bot|Mediapartners-Google|Microsoft .{0,30} Bot|mogimogi|mozDex|MJ12bot|msnbot(?:-media {0,2}|)|msrbot|Mtps Feed Aggregation System|netresearch|Netvibes|NewsGator[^/]{0,30}|^NING|Nutch[^/]{0,30}|Nymesis|ObjectsSearch|OgScrper|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo Screenshot Bot|PlantyNet_WebRobot|Pompos|Qwantify|Read%20Later|Reaper|RedCarpet|Retreiver|Riddler|Rival IQ|scooter|Scrapy|Scrubby|searchsight|seekbot|semanticdiscovery|SemrushBot|Simpy|SimplePie|SEOstats|SimpleRSS|SiteCon|Slackbot-LinkExpanding|Slack-ImgProxy|Slurp|snappy|Speedy Spider|Squrl Java|Stringer|TheUsefulbot|ThumbShotsBot|Thumbshots\.ru|Tiny Tiny RSS|Twitterbot|WhatsApp|URL2PNG|Vagabondo|VoilaBot|^vortex|Votay bot|^voyager|WASALive.Bot|Web-sniffer|WebThumb|WeSEE:[A-z]{1,30}|WhatWeb|WIRE|WordPress|Wotbox|www\.almaden\.ibm\.com|Xenu(?:.s|) Link Sleuth|Xerka [A-z]{1,30}Bot|yacy(?:bot|)|YahooSeeker|Yahoo! Slurp|Yandex\w{1,30}|YodaoBot(?:-[A-z]{1,30}|)|YottaaMonitor|Yowedo|^Zao|^Zao-Crawler|ZeBot_www\.ze\.bz|ZooShot|ZyBorg)(?:[ /]v?(\d+)(?:\.(\d+)(?:\.(\d+)|)|)|)

    Configuration Samples

    Release Requests that would otherwise Hit the Crawler Rules

    allow:
    - ".*Go-http-client.*"

    Without this configuration, the default Golang web library request will be treated as a crawler and access will be denied.

    Add Crawler Judgement

    deny:
    - "spd-tools.*"

    According to this configuration, the following requests will be denied:

    curl http://example.com -H 'User-Agent: spd-tools/1.1'
    curl http://exmaple.com -H 'User-Agent: spd-tools'

    Only Enabled for Specific Routes or Domains

    # Use _rules_ field for fine-grained rule configurations 
    _rules_:
    # Rule 1: Match by route name
    - _match_route_:
    - route-a
    - route-b
    # Rule 2: Match by domain
    - _match_domain_:
    - "*.example.com"
    - test.com
    allow:
    - ".*Go-http-client.*"

    In the rule sample of _match_route_, route-a and route-b are the route names provided when creating a new gateway route. When the current route names matches the configuration, the rule following shall be applied. In the rule sample of _match_domain_, *.example.com and test.com are the domain names used for request matching. When the current domain name matches the configuration, the rule following shall be applied. All rules shall be checked following the order of items in the _rules_ field, The first matched rule will be applied. All remained will be ignored.

    - + \ No newline at end of file diff --git a/en-us/docs/plugins/custom-response/index.html b/en-us/docs/plugins/custom-response/index.html index e8312c29dc..02e9c6eb44 100644 --- a/en-us/docs/plugins/custom-response/index.html +++ b/en-us/docs/plugins/custom-response/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    Custom response

    Description

    custom-response plugin implements a function of sending custom responses, including custom HTTP response status codes, HTTP response headers and HTTP response body, which can be used in the scenarios of response mocking and sending a custom response for specific status codes, such as customizing the response for rate-limited requests.

    Configuration Fields

    NameTypeRequirementDefault ValueDescription
    status_codenumberOptional200Custom HTTP response status code
    headersarray of stringOptional-Custom HTTP response header. Key and value shall be separated using =.
    bodystringOptional-Custom HTTP response body
    enable_on_statusarray of numberOptional-The original response status code to match. Generate the custom response only the actual status code matches the configuration. Ignore the status code match if left unconfigured.

    Configuration Samples

    Mock Responses

    status_code: 200
    headers:
    - Content-Type=application/json
    - Hello=World
    body: "{\"hello\":\"world\"}"

    According to the configuration above, all the requests will get the following custom response:

    HTTP/1.1 200 OK
    Content-Type: application/json
    Hello: World
    Content-Length: 17

    {"hello":"world"}

    Send a Custom Response when Rate-Limited

    enable_on_status: 
    - 429
    status_code: 302
    headers:
    - Location=https://example.com

    When rate-limited, normally gateway will return a status code of 429 . Now, rate-limited requests will get the following custom response:

    HTTP/1.1 302 Found
    Location: https://example.com

    So based on the 302 redirecting mechanism provided by browsers, this can redirect rate-limited users to other pages, for example, a static page hosted on CDN.

    If you'd like to send other responses when rate-limited, please add other fields into the configuration, referring to the Mock Responses scenario.

    Only Enabled for Specific Routes or Domains

    # Use _rules_ field for fine-grained rule configurations 
    _rules_:
    # Rule 1: Match by route name
    - _match_route_:
    - route-a
    - route-b
    body: "{\"hello\":\"world\"}"
    # Rule 2: Match by domain
    - _match_domain_:
    - "*.example.com"
    - test.com
    enable_on_status:
    - 429
    status_code: 200
    headers:
    - Content-Type=application/json
    body: "{\"errmsg\": \"rate limited\"}"

    In the rule sample of _match_route_, route-a and route-b are the route names provided when creating a new gateway route. When the current route names matches the configuration, the rule following shall be applied. In the rule sample of _match_domain_, *.example.com and test.com are the domain names used for request matching. When the current domain name matches the configuration, the rule following shall be applied. All rules shall be checked following the order of items in the _rules_ field, The first matched rule will be applied. All remained will be ignored.

    - + \ No newline at end of file diff --git a/en-us/docs/plugins/custom/index.html b/en-us/docs/plugins/custom/index.html index 145adb168d..f1cdcf509a 100644 --- a/en-us/docs/plugins/custom/index.html +++ b/en-us/docs/plugins/custom/index.html @@ -14,14 +14,14 @@ - +

    Custom Plugin

    Edit the Wasm file

    1. SDK for developing Higress' Wasm plugin in Go language
    2. Example of plug-in development

    Build the Wasm image

    You can also choose to build the wasm locally first, and then copy it to the Docker image. This requires you to build the build environment locally first.

    The compilation environment requirements are as follows:

    • Go version: >= 1.18 (need to support generic features)

    • TinyGo version: 0.28.1 (0.28.1 recommended)

    The following is an example of local steps to build the request-block plugin.

    step1. Compile wasm

    tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags='custommalloc nottinygc_finalizer' ./main.go

    step2. Build and push the docker image of the plugin

    Use this simple Dockerfile

    FROM scratch
    COPY main.wasm plugin.wasm
    docker build -t <your_registry_hub>/request-block:1.0.0 -f <your_dockerfile> .
    docker push <your_registry_hub>/request-block:1.0.0

    Enable Wasm plugin

    Using the Higress console

    Click the Create button to create a custom plug-in in the plug-in market, and fill in the Wasm mirror address built above in the mirror address column;

    After the creation is complete, click the configuration button of the plug-in card, fill in the configuration of the plug-in (if any), and turn on the switch to take effect.

    If the plug-in logic changes, you can build a new image with a different image tag, click the "Edit" button in the upper right menu of the plug-in card, and change the address of the Wasm image to the address of the new version.

    Using CRDs

    Write the WasmPlugin resource as follows:

    apiVersion: extensions.higress.io/v1alpha1
    kind: WasmPlugin
    metadata:
    name: request-block
    namespace: higress-system
    spec:
    defaultConfig:
    block_urls:
    - "swagger.html"
    url: oci://<your_registry_hub>/request-block:1.0.0 # The address of the image built and pushed before

    Use kubectl apply -f <your-wasm-plugin-yaml> to apply the resources. After the resource takes effect, if the request url carries swagger.html, the request will be rejected, for example:

    curl <your_gateway_address>/api/user/swagger.html
    HTTP/1.1 403 Forbidden
    date: Wed, 09 Nov 2022 12:12:32 GMT
    server: istio-envoy
    content-length: 0
    - + \ No newline at end of file diff --git a/en-us/docs/plugins/hmac-auth/index.html b/en-us/docs/plugins/hmac-auth/index.html index de8afbd09f..cc72aa7826 100644 --- a/en-us/docs/plugins/hmac-auth/index.html +++ b/en-us/docs/plugins/hmac-auth/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    HMAC authentication

    Function Description

    The hmac-auth plugin implements the generation of tamper-proof signatures for HTTP requests based on HMAC algorithm, and uses the signature for identity authentication and authorization.

    Configuration Fields

    NameData TypeRequiredDefaultDescription
    consumersarray of objectRequired-Configures the caller of the service to authenticate the request.
    date_offsetnumberOptional-Configures the maximum allowed time deviation of the client, in seconds. It is used to parse the client's UTC time from the Date header of the request, and can be used to prevent replay attacks. If not configured, no validation is performed.
    _rules_array of objectOptional-Configures the access control list for specific routes or domains, used for authorization of requests.

    The configuration fields for each item in consumers are as follows :

    NameData TypeRequiredDefaultDescription
    keystringRequired-Configures the key extracted from the x-ca-key header of the request.
    secretstringRequired-Configures the secret used to generate the signature.
    namestringRequired-Configures the name of the consumer.

    The configuration fields for each item in _rules_ are as follows:

    NameData TypeRequiredDefaultDescription
    _match_route_array of stringOptional, either _match_route_ or _match_domain_ must be provided-Configures the name of the route to match.
    _match_domain_array of stringOptional, either _match_route_ or _match_domain_ must be provided-Configures the name of the domain to match.
    allowarray of stringRequired-Configures the name of the consumer to allow for requests that match the specified route or domain.

    Note:

    • If _rules_ is not configured, authentication is enabled for all routes on the current gateway instance by default ;
    • For requests that pass authentication and authorization, a X-Mse-Consumer header will be added to the request headers to identify the name of the consumer.

    Configuration Example

    The following configuration enables Hmac Auth authentication and authorization for specific routes or domains on the gateway. Note that the key field should not be duplicated.

    Enabling for specific routes or domains

    consumers: 
    - key: appKey-example-1
    secret: appSecret-example-1
    name: consumer-1
    - key: appKey-example-2
    secret: appSecret-example-2
    name: consumer-2
    # Configuring Fine-Grained Rules using _rules_ Field
    _rules_:
    # Rule 1: Matching by route name.
    - _match_route_:
    - route-a
    - route-b
    allow:
    - consumer-1
    # Rule 2: Applies based on domain name matching.
    - _match_domain_:
    - "*.example.com"
    - test.com
    allow:
    - consumer-2

    The allow field under each matching rule specifies the list of callers allowed to access under that matching condition;

    In this example, route-a and route-b specified in _match_route_ are the route names filled in when creating the gateway route. When either of these routes is matched, it will allow access to the caller named consumer-1, while denying access to other callers;

    In _match_domain_, *.example.com and test.com are used to match the requested domain name. When a match is found, it will allow access to the caller named consumer-2, while denying access to other callers;

    Upon successful authentication, the X-Mse-Consumer field will be added to the request header with the value set to the caller's name, such as consumer-1.。

    Enable at the Gateway Instance Level

    The following configuration enables HMAC authentication at the gateway instance level.

    consumers: 
    - key: appKey-example-1
    secret: appSecret-example-1
    name: consumer-1
    - key: appKey-example-2
    secret: appSecret-example-2
    name: consumer-2

    Description of Signing Mechanism

    Configuration Preparation

    As mentioned in the guide above, configure the credential settings required for generating and validating signatures in the plugin configuration.

    • key: Used for setting in the request header x-ca-key.
    • secret: Used for generating the request signature.

    Client Signature Generation Method

    Overview of the Process

    The process for generating a signature on the client side consists of three steps:

    1. Extracting key data from the original request to obtain a string to be signed.

    2. Using encryption algorithms and the configured secret to encrypt the key data signing string and obtain a signature.

    3. Adding all headers related to the signature to the original HTTP request to obtain the final HTTP request.

    As shown below :

    Process for Extracting Signing String

    To generate a signature, the client needs to extract key data from the HTTP request and combine it into a signing string. The format of the generated signing string is as follows:

    HTTPMethod
    Accept
    Content-MD5
    Content-Type
    Date
    Headers
    PathAndParameters

    The signing string consists of the above 7 fields separated by \n. If Headers is empty, no \n is needed. If other fields are empty, the \n should still be retained. The signature is case-sensitive. Below are the rules for extracting each field:

    • HTTPMethod: The HTTP method used in the request, in all capital letters, such as POST.

    • Accept: The value of the Accept header in the request, which can be empty. It is recommended to explicitly set the Accept header. When Accept is empty, some HTTP clients will set the default value of */*, which may cause signature verification to fail.

    • Content-MD5: The value of the Content-MD5 header in the request, which can be empty. It is only calculated when there is a non-form body in the request. The following is a reference calculation method for Content-MD5 values in :

    String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
    • Content-Type: The value of the Content-Type header in the request, which can be empty.

    • Date: The value of the Date header in the request. When the date_offset configuration is not enabled, it can be empty. Otherwise, it will be used for time offset verification.

    • Headers: Users can select specific headers to participate in the signature. There are the following rules for concatenating the signature string with headers:

      • The keys of the headers participating in the signature calculation are sorted in alphabetical order and concatenated as follows:
        HeaderKey1 + ":" + HeaderValue1 + "\n"\+
        HeaderKey2 + ":" + HeaderValue2 + "\n"\+
        ...
        HeaderKeyN + ":" + HeaderValueN + "\n"
      • If the value of a header is empty, it will participate in the signature with the HeaderKey+":"+"\n" only, and the key and english colon should be retained.
      • The set of keys for all headers participating in the signature is separated by a comma and placed in the X-Ca-Signature-Headers header.
      • The following headers are not included in the header signature calculation: X-Ca-Signature, X-Ca-Signature-Headers, Accept, Content-MD5, Content-Type, Date.
    • PathAndParameters: This field contains all parameters in the path, query, and form. The specific format is as follows:

    Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN

    Notes:

    1. The keys of the query and form parameter pairs are sorted alphabetically, and the same format as above is used for concatenation.
    2. If there are no query and form parameters, use the path directly without adding ? .
    3. If the value of a parameter is empty, only the key will be included in the signature. The equal sign should not be included in the signature.
    4. If there are array parameters in the query or form (parameters with the same key but different values), only the first value should be included in the signature calculation.

    Example of Extracting Signing String

    The initial HTTP request :

    POST /http2test/test?param1=test HTTP/1.1
    host:api.aliyun.com
    accept:application/json; charset=utf-8
    ca_version:1
    content-type:application/x-www-form-urlencoded; charset=utf-8
    x-ca-timestamp:1525872629832
    date:Wed, 09 May 2018 13:30:29 GMT+00:00
    user-agent:ALIYUN-ANDROID-DEMO
    x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
    content-length:33
    username=xiaoming&password=123456789

    The correct generated signature string is :

    POST
    application/json; charset=utf-8
    application/x-www-form-urlencoded; charset=utf-8
    Wed, 09 May 2018 13:30:29 GMT+00:00
    x-ca-key:203753385
    x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
    x-ca-signature-method:HmacSHA256
    x-ca-timestamp:1525872629832
    /http2test/test?param1=test&password=123456789&username=xiaoming

    Signature Calculation Process

    After extracting the key data from the HTTP request and assembling it into a signature string, the client needs to encrypt and encode the signature string to form the final signature.

    The specific encryption format is as follows, where stringToSign is the extracted signature string, secret is the one filled in the plugin configuration, and sign is the final generated signature:

    Mac hmacSha256 = Mac.getInstance("HmacSHA256");
    byte[] secretBytes = secret.getBytes("UTF-8");
    hmacSha256.init(new SecretKeySpec(secretBytes, 0, secretBytes.length, "HmacSHA256"));
    byte[] result = hmacSha256.doFinal(stringToSign.getBytes("UTF-8"));
    String sign = Base64.encodeBase64String(result);

    In summary, the stringToSign is decoded using UTF-8 to obtain a Byte array. Then, an encryption algorithm is used to encrypt the Byte array, and finally, the Base64 algorithm is used to encode the encrypted data, resulting in the final signature.

    The Process of Adding a Signature

    The client needs to include the following four headers in the HTTP request to be transmitted to the API gateway for signature verification:

    • x-ca-key: The value is the APP Key and is required.

    • x-ca-signature-method: The signature algorithm, the value can be HmacSHA256 or HmacSHA1, optional. The default value is HmacSHA256.

    • x-ca-signature-headers: The collection of keys for all signature headers, separated by commas. Optional.

    • x-ca-signature: The signature and it is required.

    Here is an example of a complete HTTP request with a signature :

    POST /http2test/test?param1=test HTTP/1.1
    host:api.aliyun.com
    accept:application/json; charset=utf-8
    ca_version:1
    content-type:application/x-www-form-urlencoded; charset=utf-8
    x-ca-timestamp:1525872629832
    date:Wed, 09 May 2018 13:30:29 GMT+00:00
    user-agent:ALIYUN-ANDROID-DEMO
    x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
    x-ca-key:203753385
    x-ca-signature-method:HmacSHA256
    x-ca-signature-headers:x-ca-timestamp,x-ca-key,x-ca-nonce,x-ca-signature-method
    x-ca-signature:xfX+bZxY2yl7EB/qdoDy9v/uscw3Nnj1pgoU+Bm6xdM=
    content-length:33
    username=xiaoming&password=123456789

    Server-side Signature Verification Method

    Overview of the Process

    The server-side signature verification of the client's request involves four steps :

    1. Extract crucial data from the received request to obtain a string for signing.

    2. Retrieve the key from the received request and use it to query its corresponding secret.

    3. Encrypt the string for signing using the encryption algorithm and secret.

    4. Retrieve the client's signature from the received request, and compare the consistency of the server-side signature with the client's signature.

    As shown below :

    Troubleshooting Signature Errors

    When the gateway signature verification fails, the server-side signing string (StringToSign) will be returned to the client in the HTTP Response Header. The key is X-Ca-Error-Message. Users only need to compare the locally calculated signing string with the server-side signing string returned to locate the problem;

    If the StringToSign on the server side is consistent with that on the client side, please check whether the APP Secret used for signature calculation is correct;

    Because line breaks cannot be represented in HTTP headers, all line breaks in the StringToSign are replaced with #, as shown below:

    X-Ca-Error-Message:  Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`

    HTTP Status CodeError MessageReason
    401Invalid KeyThe x-ca-key request header is not provided or is invalid.
    401Empty SignatureThe x-ca-signature request header does not contain a signature.
    400Invalid SignatureThe x-ca-signature request header contains a signature that does not match the server-calculated signature.
    400Invalid Content-MD5The content-md5 request header is incorrect.
    400Invalid DateThe time offset calculated based on the date request header exceeds the configured date_offset.
    413Request Body Too LargeThe request body exceeds the size limit of 32 MB.
    413Payload Too LargeThe request body exceeds the DownstreamConnectionBufferLimits global configuration.
    403Unauthorized ConsumerThe requesting party does not have access permission.
    - + \ No newline at end of file diff --git a/en-us/docs/plugins/intro/index.html b/en-us/docs/plugins/intro/index.html index b522e3db1f..a4cbee9c39 100644 --- a/en-us/docs/plugins/intro/index.html +++ b/en-us/docs/plugins/intro/index.html @@ -14,13 +14,13 @@ - +

    Introduction to the use of Wasm plugins

    Configure through the Higress console

    The Higress console provides 3 entries for plug-in configuration:

    1. Global configuration: plug-in market -> select plug-in to configure
    2. Domain-level configuration: domain name management->select domain name->click policy->select plug-in to configure
    3. Routing-level configuration: Routing configuration->select routing->click policy->select plug-in to configure

    The effective priority of these three configurations is: route level > domain name level > global

    That is, the global configuration will only take effect for requests that do not match a specific route or domain name

    For general plugins, including custom plugins, the routing/domain name level configuration fields are exactly the same as the global configuration fields;

    For authentication plug-ins (Key authentication, HMAC authentication, Basic authentication, JWT authentication, etc.), it is different. The global configuration only configures the Consumer credential and whether to enable global authentication, and configures the allowed access through the allow field at the routing/domain name level. Consumer list, for details, please refer to Configuration Instructions of Key Authentication

    Configuration via Higress WasmPlugin CRD

    The Higress WasmPlugin CRD extends the Istio WasmPlugin CRD, adding the following configuration fields:

    Field NameData TypeFilling RequirementsDescription
    defaultConfigobjectOptionalThe default configuration of the plugin, which takes effect globally for requests that do not match specific domain names and routing configurations
    matchRulesarray of objectoptionalconfigurations that match domain names or routes to take effect

    Description of configuration fields for each item in matchRules:

    Field NameData TypeFilling RequirementsConfiguration ExampleDescription
    ingressarray of stringone of ingress and domain is required["default/foo","default/bar"]Matching ingress resource object, the matching format is: namespace/ingress name
    domainarray of stringone of ingress and domain is required["example.com","*.test.com"]match domain name, support generic domain name
    configobjectoptional-plug-in configuration that takes effect after matching

    Take the Request Blocking plugin as an example, if you want the following configuration of the plugin to take effect globally (please refer to the Request Blocking document for configuration field descriptions):

    block_urls:
    - swagger.html
    - foo=bar
    case_sensitive: false

    Then the corresponding WasmPlugin needs to be configured as follows:

    apiVersion: extensions.higress.io/v1alpha1
    kind: WasmPlugin
    metadata:
    name: request-block
    namespace: higress-system
    spec:
    defaultConfig:
    block_urls:
    - swagger.html
    - foo=bar
    case_sensitive: false
    url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/request-block:1.0.0

    The following requests will be blocked immediately after configuration:

    curl http://example.com?foo=Bar
    curl http://exmaple.com/foo/Swagger.html

    If you want to apply the following configuration to the Ingress named foo under the default namespace (matching requests whose path prefix is /foo):

    block_headers:
    - example-key
    - example-value

    Then the corresponding WasmPlugin needs to be configured as follows:

    apiVersion: extensions.higress.io/v1alpha1
    kind: WasmPlugin
    metadata:
    name: request-block
    namespace: higress-system
    spec:
    defaultConfig:
    block_urls:
    - swagger.html
    - foo=bar
    case_sensitive: false
    matchRules:
    # Route-level effective configuration
    - ingress:
    - default/foo
    # The ingress named foo under the default namespace will execute the following configuration
    config:
    block_headers:
    - example-key
    - example-value
    url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/request-block:1.0.0

    After configuration, the following request will not match a specific ingress, so it still hits the global default configuration and is denied access:

    curl http://example.com?foo=Bar

    Since the following request matches the Ingress of foo, the routing-level configuration is not affected by the default configuration and will not be denied access:

    curl http://exmaple.com/foo/Swagger.html

    Because the route-level configuration blocks requests with example-key characters in the request header, the following request will be denied access:

    curl http://exmaple.com/foo -H 'exmaple-key: 123'

    When there are multiple rules in matchRules, they will be matched according to the order of the rules. It is recommended to place the ingress matching configuration before the domain matching, which is also the practice of the Higress console

    Official plugin mirror address

    Plugin nameMirror address
    Key authenticationhigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/key-auth:1.0.0
    Basic authenticationhigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/basic-auth:1.0.0
    HMAC authenticationhigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/hmac-auth:1.0.0
    JWT authenticationhigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/jwt-auth:1.0.0
    Bot detectionhigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/bot-detect:1.0.0
    Custom Responsehigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/custom-response:1.0.0
    request blockhigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/request-block:1.0.0
    Key-based rate limithigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/key-rate-limit:1.0.0
    WAF Protectionhigress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/waf:1.0.0

    Wasm plugin principle introduction

    What is Wasm

    // TODO...

    Plug-in effective process

    // TODO...

    Plug-in execution sequence arrangement

    // TODO...

    How does the Wasm plugin achieve lossless traffic when changing

    // TODO...

    - + \ No newline at end of file diff --git a/en-us/docs/plugins/jwt-auth/index.html b/en-us/docs/plugins/jwt-auth/index.html index 6f1de979c0..4f9106ac1e 100644 --- a/en-us/docs/plugins/jwt-auth/index.html +++ b/en-us/docs/plugins/jwt-auth/index.html @@ -14,13 +14,13 @@ - +

    JWT authentication

    Description

    The jwt-auth plugin implements authentication and authorization based on JWT (JSON Web Token), supports parsing JWTs from URL parameters, request headers, and Cookie fields from HTTP requests, and verifies whether the token has permission to access.

    The difference between this plugin and the JWT authentication in Security Capabilities->Authentication and Authorization is that it provides additional capabilities for identifying the caller's identity, supporting the configuration of different JWT credentials for different callers.

    Detailed Description

    1. Token-based authentication

    1.1 Introduction

    Many open APIs need to identify the identity of the caller and determine whether the requested resource can be returned to the caller based on this identity. Token is a mechanism used for identity verification. Based on this mechanism, the application does not need to retain the user's authentication information or session information on the server, which can realize stateless and distributed web application authorization and provide convenience for application extension.

    1.2 Process Description

    The above figure is the business process sequence diagram when the gateway uses JWT for authentication, and the following we will describe the steps marked in the figure in detail in words:

    1. The client initiates an authentication request to the API gateway, usually carrying the end user's username and password in the request;

    2. The gateway forwards the request directly to the backend service;

    3. The backend service reads the authentication information (such as the username and password) in the request for verification. After the verification is passed, it uses the private key to generate a standard token and returns it to the gateway;

    4. The gateway returns the response with the token to the client, and the client needs to cache this token locally;

    5. The client sends a business request to the API gateway, carrying the token in the request;

    6. The gateway uses the public key set by the user to verify the token in the request. After the verification is passed, the request is passed through to the backend service;

    7. The backend service processes the business and responds;

    8. The gateway returns the business response to the client.

    In this entire process, the gateway uses the token authentication mechanism to realize the ability of users to use their own user system to authorize their API. Next, we will introduce the structured token JSON Web Token (JWT) used by the gateway to implement token authentication.

    1.3 JWT

    1.3.1 Introduction

    JSON Web Token (JWT) is an open standard RFC7519 based on JSON for executing a type of claim to pass between network applications. JWT can generally be used as an independent identity verification token, which can contain user identification, user roles, and permissions information, making it easier to obtain resources from the resource server, and can also add some other necessary declarative information for other business logic, especially suitable for the login scenario of distributed sites.

    1.3.2 Composition of JWT

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

    As shown in the example above, JWT is a string consisting of three parts:

    • Header
    • Payload
    • Signature

    Header

    The header of the JWT carries two pieces of information:

    • The type of the token, which is JWT
    • The algorithm used for encryption

    The gateway supports the following encryption algorithms:

    ES256, ES384, ES512,
    HS256, HS384, HS512,
    RS256, RS384, RS512,
    PS256, PS384, PS512,
    EdDSA

    The complete header looks like the following JSON:

    {
    'typ': 'JWT',
    'alg': 'HS256'
    }

    The header is then Base64-encoded (this encoding can be symmetrically decoded), forming the first part:

    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

    Payload

    The payload is where the actual information is stored. The details are defined below:

    iss: The issuer of the token. This indicates who created the token and is a string value.
    sub: The subject identifier. This is the unique identifier for the end user provided by the issuer, and is no longer than 255 ASCII characters, and is case-sensitive within the issuer's scope.
    aud: The audience(s) of the token, which is an array of case-sensitive strings.
    exp: The expiration time of the token, after which the token will be invalidated, is an integer declaration representing the Unix timestamp in seconds.
    iat: The issuance time of the token, is an integer declaration representing the Unix timestamp in seconds.
    jti: The unique identifier of the token, and the value is unique for every token created by the issuer. It is usually a cryptographically random value to prevent conflicts. This component adds a random entropy that an attacker cannot obtain to the structured token, making it more difficult for the token to be guessed or replayed.

    Custom fields for a user feature can also be added, such as the example below adding a "name" field for the user's nickname:

    {
    "sub": "1234567890",
    "name": "John Doe"
    }

    The payload is then Base64-encoded, forming the second part of the JWT:

    JTdCJTBBJTIwJTIwJTIyc3ViJTIyJTNBJTIwJTIyMTIzNDU2Nzg5MCUyMiUyQyUwQSUyMCUyMCUyMm5hbWUlMjIlM0ElMjAlMjJKb2huJTIwRG9lJTIyJTBBJTdE

    Signature

    This part is a string that consists of the Base64-encoded header and Base64-encoded payload concatenated with a period, followed by the encryption of the resulting string using the algorithm specified in the header (where $secret represents the user's private key).

    var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
    var signature = HMACSHA256(encodedString, '$secret');

    These three parts are then concatenated using periods to form the complete JWT string as shown in the example at the beginning of this section.

    1.3.3 Time validity

    The gateway will verify the exp field in the token. Once this field has expired, the gateway will consider the token invalid and reject the request directly. The expiration time value must be set.

    1.3.4 Several Characteristics of JWT
    1. By default, JWT is not encrypted and cannot write secret data into JWT.
    2. JWT can not only be used for authentication but also for exchanging information. Using JWT effectively can reduce the number of times servers query the database.
    3. The biggest drawback of JWT is that the server cannot invalidate a token during use, or change the token's permission, because the server does not keep the session state. That is, once JWT is issued, it will always be valid before it expires, unless the server deploys additional logic.
    4. JWT contains authentication information itself. Once leaked, anyone can obtain all permissions of the token. To reduce theft, the expiration time of JWT should be set relatively short. For some more important permissions, users should be authenticated again when using them.
    5. To reduce theft, JWT should not be transmitted in plaintext using the HTTP protocol, and the HTTPS protocol should be used for transmission.

    2. How to apply the JWT plugin to protect the API of the user system

    2.1 Generate a pair of JWK (JSON Web Key)

    Method 1: Generate online

    Users can generate the private and public keys used for token generation and verification on this website https://mkjwk.org. The private key is used for the authorization service to issue JWT, and the public key is configured into the JWT plugin for the gateway to verify the signature of the request. Note that the JWKs format configuration used by the gateway requires the public key in the figure below to be placed in the keys structure, such as: {"keys":[{"kty":"RSA","e":"AQAB",...}]}

    Method 2: Generate locally

    This article uses a Java example to illustrate, and users of other languages can also find relevant tools to generate key pairs. Create a new Maven project and add the following dependencies:

    <dependency>
    <groupId>org.bitbucket.b_c</groupId>
    <artifactId>jose4j</artifactId>
    <version>0.7.0</version>
    </dependency>

    Use the following code to generate a pair of RSA keys:

    RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
    final String publicKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY);
    final String privateKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);

    2.2 Implement the token issuance authentication service using the private key in JWK

    The Keypair JSON string generated online in Section 2.1 (the first of the three boxes) or privateKeyString JSON string generated locally needs to be used as the private key to issue tokens for trusted users to access protected APIs. The specific implementation can refer to the following example. The form of issuing tokens to customers is determined by the user according to the specific business scenario. The function of issuing tokens can be deployed in the production environment and configured as a normal API for visitors to obtain through username and password, or tokens can be generated directly in the local environment and copied to designated users for use.

    import java.security.PrivateKey; 
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jwk.RsaJsonWebKey;
    import org.jose4j.jwk.RsaJwkGenerator;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.lang.JoseException;
    public class GenerateJwtDemo {
    public static void main(String[] args) throws JoseException {
    String keyId = "uniq_key";
    //Use the Keypair generated in section 2.1 of this article
    String privateKeyJson = "{\n"
    + " \"kty\": \"RSA\",\n"
    + " \"d\": "
    +
    "\"O9MJSOgcjjiVMNJ4jmBAh0mRHF_TlaVva70Imghtlgwxl8BLfcf1S8ueN1PD7xV6Cnq8YenSKsfiNOhC6yZ_fjW1syn5raWfj68eR7cjHWjLOvKjwVY33GBPNOvspNhVAFzeqfWneRTBbga53Agb6jjN0SUcZdJgnelzz5JNdOGaLzhacjH6YPJKpbuzCQYPkWtoZHDqWTzCSb4mJ3n0NRTsWy7Pm8LwG_Fd3pACl7JIY38IanPQDLoighFfo-Lriv5z3IdlhwbPnx0tk9sBwQBTRdZ8JkqqYkxUiB06phwr7mAnKEpQJ6HvhZBQ1cCnYZ_nIlrX9-I7qomrlE1UoQ\",\n"
    + " \"e\": \"AQAB\",\n"
    + " \"alg\": \"RS256\",\n"
    + " \"n\": \"vCuB8MgwPZfziMSytEbBoOEwxsG7XI3MaVMoocziP4SjzU4IuWuE_DodbOHQwb_thUru57_Efe"
    +
    "--sfATHEa0Odv5ny3QbByqsvjyeHk6ZE4mSAV9BsHYa6GWAgEZtnDceeeDc0y76utXK2XHhC1Pysi2KG8KAzqDa099Yh7s31AyoueoMnrYTmWfEyDsQL_OAIiwgXakkS5U8QyXmWicCwXntDzkIMh8MjfPskesyli0XQD1AmCXVV3h2Opm1Amx0ggSOOiINUR5YRD6mKo49_cN-nrJWjtwSouqDdxHYP-4c7epuTcdS6kQHiQERBd1ejdpAxV4c0t0FHF7MOy9kw\"\n"
    + "}";
    JwtClaims claims = new JwtClaims();
    claims.setGeneratedJwtId();
    claims.setIssuedAtToNow();
    //Expiration time must be set
    NumericDate date = NumericDate.now();
    date.addSeconds(120*60);
    claims.setExpirationTime(date);
    claims.setNotBeforeMinutesInThePast(1);
    claims.setSubject("YOUR_SUBJECT");
    claims.setAudience("YOUR_AUDIENCE");
    //Add custom parameters, use String type for all values
    claims.setClaim("userId", "1213234");
    claims.setClaim("email", "userEmail@youapp.com");
    JsonWebSignature jws = new JsonWebSignature();
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    jws.setKeyIdHeaderValue(keyId);
    jws.setPayload(claims.toJson());
    PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyJson)).getPrivateKey();

    jws.setKey(privateKey);
    String jwtResult = jws.getCompactSerialization();
    System.out.println("Generate Json Web token , result is " + jwtResult);
    }
    }

    Plugin Configuration Guide

    Configuration Fields

    NameData TypeRequiredDefaultDescription
    consumersarray of objectYes-Configures callers of the service for authenticating requests
    _rules_array of objectOptional-Configures access control lists for specific routes or domains for authorizing requests

    The configuration field descriptions for each item in consumers are as follows:

    NameData TypeRequiredDefaultDescription
    namestringYes-Configures the name of this consumer
    jwksstringYes-Specifies a JSON Web Key Set, as defined in https://www.rfc-editor.org/rfc/rfc7517, consisting of public keys (or symmetric keys) used to verify the signature of JWT
    issuerstringYes-The issuer of the JWT, which should be consistent with the iss field in the payload
    claims_to_headersarray of objectOptional-Extracts the specified fields from the JWT's payload and sets them to the specified request headers for forwarding to the backend
    from_headersarray of objectOptional{"name":"Authorization","value_prefix":"Bearer "}Extracts the JWT from the specified request headers
    from_paramsarray of stringOptionalaccess_tokenExtracts the JWT from the specified URL parameters
    from_cookiesarray of stringOptional-Extracts the JWT from the specified cookie(s)
    clock_skew_secondsnumberOptional60The amount of clock skew, in seconds, that is allowed when verifying the exp and iat fields of the JWT
    keep_tokenboolOptionaltrueWhether to keep the JWT when forwarding it to the backend

    Note:

    • The default value is used only if neither from_headers, from_params, nor from_cookies are configured.

    The configuration field descriptions for each item in from_headers are as follows:

    NameData TypeRequiredDefaultDescription
    namestringYes-Specifies the request header to extract the JWT from
    value_prefixstringYes-Removes the specified prefix from the request header's value, leaving the rest as the JWT

    The configuration field descriptions for each item in claims_to_headers are as follows:

    NameData TypeRequiredDefaultDescription
    claimstringYes-The name of the field in the JWT payload, which must be a string or unsigned integer
    headerstringYes-Sets the value of the specified request header to the value of the specified field in the payload, for forwarding to the backend
    overrideboolOptionaltrueIf true, overrides an existing header with the same name; if false, appends the header to the existing headers

    The configuration field descriptions for each item in _rules_ are as follows:

    NameData TypeRequiredDefaultDescription
    _match_route_array of stringOptional, select either _match_route_ or _match_domain_-Configures the route names to match
    _match_domain_array of stringOptional, select either _match_route_ or _match_domain_-Configures the domains to match
    allowarray of stringRequired-Configures the consumer names allowed to access the matched requests

    Note:

    • If the _rules_ field is not configured, authentication and authorization are enabled for all routes of the current gateway instance by default;
    • For authenticated and authorized requests, a X-Mse-Consumer field is added to the request header to identify the caller's name.

    Configuration Example

    Enable for Specific Routes or Domains

    The following configuration enables Jwt Auth authentication and authorization for specific routes or domains of the gateway. If a JWT can match multiple jwks, the first matching consumer is hit according to the configuration order.

    consumers:
    - name: consumer1
    issuer: abcd
    jwks: |
    {
    "keys": [
    {
    "kty": "oct",
    "kid": "123",
    "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
    "alg": "HS256"
    }
    ]
    }
    - name: consumer2
    issuer: abc
    jwks: |
    {
    "keys": [
    {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "123",
    "alg": "RS256",
    "n": "i0B67f1jggT9QJlZ_8QL9QQ56LfurrqDhpuu8BxtVcfxrYmaXaCtqTn7OfCuca7cGHdrJIjq99rz890NmYFZuvhaZ-LMt2iyiSb9LZJAeJmHf7ecguXS_-4x3hvbsrgUDi9tlg7xxbqGYcrco3anmalAFxsbswtu2PAXLtTnUo6aYwZsWA6ksq4FL3-anPNL5oZUgIp3HGyhhLTLdlQcC83jzxbguOim-0OEz-N4fniTYRivK7MlibHKrJfO3xa_6whBS07HW4Ydc37ZN3Rx9Ov3ZyV0idFblU519nUdqp_inXj1eEpynlxH60Ys_aTU2POGZh_25KXGdF_ZC_MSRw"
    }
    ]
    }
    # Use the _rules_ field for fine-grained rule configuration
    _rules_:
    # Rule 1: Effective when matched by route name
    - _match_route_:
    - route-a
    - route-b
    allow:
    - consumer1
    # Rule 2: Effective when matched by domain name
    - _match_domain_:
    - "*.example.com"
    - test.com
    allow:
    - consumer2

    In this example, the route-a and route-b specified in _match_route_ are the names of the routes filled in when creating the gateway route. When these two routes are matched, access will be allowed for the caller with the name of consumer1, and other callers will not be allowed to access.

    The *.example.com and test.com specified in _match_domain_ are used to match the domain names of the requests. When a domain name match is found, access will be allowed for the caller with the name of consumer2, and other callers will not be allowed to access.

    According to this configuration, the following requests are allowed:

    Assuming the following requests will match the route-a route:

    JWT is set in URL parameter

    curl  'http://xxx.hello.com/test?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

    JWT is set in HTTP request header

    curl  http://xxx.hello.com/test -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

    After authentication and authorization, a X-Mse-Consumer field will be added in the request header with a value of consumer1 in this example, to identify the name of the caller.

    The following requests will be denied:

    Request without JWT provided, returns 401

    curl  http://xxx.hello.com/test

    The consumer matched by the provided JWT in the request does not have access, returns 403

    # consumer1 is not in the allow list of *.example.com
    curl 'http://xxx.example.com/test' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

    Enabling at Gateway Instance Level

    The following configuration does not specify the _rules_ field, so JWT authentication will be enabled at the gateway instance level:

    consumers:
    - name: consumer1
    issuer: abcd
    jwks: |
    {
    "keys": [
    {
    "kty": "oct",
    "kid": "123",
    "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
    "alg": "HS256"
    }
    ]
    }
    - name: consumer2
    issuer: abc
    jwks: |
    {
    "keys": [
    {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "123",
    "alg": "RS256",
    "n": "i0B67f1jggT9QJlZ_8QL9QQ56LfurrqDhpuu8BxtVcfxrYmaXaCtqTn7OfCuca7cGHdrJIjq99rz890NmYFZuvhaZ-LMt2iyiSb9LZJAeJmHf7ecguXS_-4x3hvbsrgUDi9tlg7xxbqGYcrco3anmalAFxsbswtu2PAXLtTnUo6aYwZsWA6ksq4FL3-anPNL5oZUgIp3HGyhhLTLdlQcC83jzxbguOim-0OEz-N4fniTYRivK7MlibHKrJfO3xa_6whBS07HW4Ydc37ZN3Rx9Ov3ZyV0idFblU519nUdqp_inXj1eEpynlxH60Ys_aTU2POGZh_25KXGdF_ZC_MSRw"
    }
    ]
    }

    Common Error Codes

    HTTP Status CodeError MessageReason Description
    401JWT missingThe JWT is not provided in the request header.
    401JWT expiredThe JWT has expired.
    401JWT verification failsThe JWT payload verification failed, such as the iss mismatch.
    403Access deniedAccess to the current route is denied.
    - + \ No newline at end of file diff --git a/en-us/docs/plugins/key-auth/index.html b/en-us/docs/plugins/key-auth/index.html index cda14e9a0e..84393cf6a6 100644 --- a/en-us/docs/plugins/key-auth/index.html +++ b/en-us/docs/plugins/key-auth/index.html @@ -14,13 +14,13 @@ - +

    Key Authentication

    Features

    The key-auth plug-in implements the authentication function based on the API Key, supports parsing the API Key from the URL parameter or request header of the HTTP request, and verifies whether the API Key has permission to access.

    Configuration field

    NameData TypeParameter requirementsDefaultDescription
    consumersarray of objectRequired-Configure the caller of the service to authenticate the request.
    keysarray of stringRequired-The name of the source field of the API Key, which can be a URL parameter or an HTTP request header name.
    in_queryboolAt least one of in_query and in_header must be true.trueWhen configured true, the gateway will try to parse the API Key from the URL parameters.
    in_headerboolThe same as above.trueThe same as above.
    _rules_array of objectOptional-Configure the access list of a specific route or domain name for authenticating requests.

    The configuration fields of each item in consumers are described as follows:

    NameData TypeParameter requirementsDefaultDescription
    credentialstringRequired-Configure the consumer's access credentials.
    namestringRequired-Configure the name of the consumer.

    The configuration fields of each item in _rules_ are described as follows:

    NameData TypeParameter requirementsDefaultDescription
    _match_route_array of stringOptional,Optionally fill in one of _match_route_, _match_domain_.-Configure the route name to match.
    _match_domain_array of stringOptional,Optionally fill in one of _match_route_, _match_domain_.-Configure the domain name to match.
    allowarray of stringRequired-For requests that meet the matching conditions, configure the name of the consumer that is allowed to access.

    Warning:

    • If the _rules_ field is not configured, authentication will be enabled for all routes of the current gateway instance by default;
    • For a request that passes authentication, an X-Mse-Consumer field will be added to the request header to identify the name of the caller.

    Example configuration

    Enabled for specific routes or domains

    The following configuration will enable Key Auth authentication and authentication for gateway-specific routes or domain names. Note that the credential field can not be repeated.

    consumers:
    - credential: 2bda943c-ba2b-11ec-ba07-00163e1250b5
    name: consumer1
    - credential: c8c8e9ca-558e-4a2d-bb62-e700dcc40e35
    name: consumer2
    keys:
    - apikey
    in_query: true
    # Use the _rules_ field for fine-grained rule configuration
    _rules_:
    # Rule 1: Match by route name to take effect
    - _match_route_:
    - route-a
    - route-b
    allow:
    - consumer1
    # Rule 2: Take effect by domain name matching
    - _match_domain_:
    - "*.example.com"
    - test.com
    allow:
    - consumer2

    The route-a and route-b specified in _match_route_ in this example are the route names filled in when creating the gateway route. When these two routes are matched, calls whose name is consumer1 will be allowed Access by callers, other callers are not allowed to access;

    *.example.com and test.com specified in _match_domain_ in this example are used to match the domain name of the request. When the domain name matches, the caller whose name is consumer2 will be allowed to access, and other calls access is not allowed.

    Depending on this configuration, the following requests would allow access:

    Assume that the following request will match the route-a route:

    Set the API Key in the url parameter

    curl  http://xxx.hello.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5

    Set the API Key in the http request header

    curl  http://xxx.hello.com/test -H 'x-api-key: 2bda943c-ba2b-11ec-ba07-00163e1250b5'

    After the authentication is passed, an X-Mse-Consumer field will be added to the header of the request. In this example, its value is consumer1, which is used to identify the name of the caller.

    The following requests will deny access:

    The request does not provide an API Key, return 401

    curl  http://xxx.hello.com/test

    The API Key provided by the request is not authorized to access, return 401

    curl  http://xxx.hello.com/test?apikey=926d90ac-ba2e-11ec-ab68-00163e1250b5

    The caller matched according to the API Key provided in the request has no access rights, return 403

    # consumer2 is not in the allow list of route-a
    curl http://xxx.hello.com/test?apikey=c8c8e9ca-558e-4a2d-bb62-e700dcc40e35

    Gateway instance level enabled

    The following configuration does not specify the _rules_ field, so Key Auth authentication will be enabled at the gateway instance level.

    consumers:
    - credential: 2bda943c-ba2b-11ec-ba07-00163e1250b5
    name: consumer1
    - credential: c8c8e9ca-558e-4a2d-bb62-e700dcc40e35
    name: consumer2
    keys:
    - apikey
    in_query: true

    Error code

    HTTP status codeError informationReason
    401No API key found in request.API not provided by request Key.
    401Request denied by Key Auth check. Invalid API key.Current API Key access is not allowed.
    403Request denied by Basic Auth check. Unauthorized consumer.The requested caller does not have access.
    - + \ No newline at end of file diff --git a/en-us/docs/plugins/key-rate-limit/index.html b/en-us/docs/plugins/key-rate-limit/index.html index cd685bc41e..c6b7f7a469 100644 --- a/en-us/docs/plugins/key-rate-limit/index.html +++ b/en-us/docs/plugins/key-rate-limit/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    Rate limiting based on Key

    Description

    key-rate-limit plugin implements a rate-limiting function based on specific key-values. The key-values may come from URL parameters or HTTP headers.

    Configuration Fields

    NameTypeRequirementDefault ValueDescription
    limit_by_headerstringOptional. Choose one from following: limit_by_header, limit_by_param.-The name of HTTP header used to obtain key-value used in rate-limiting.
    limit_by_paramstringOptional. Choose one from following: limit_by_header, limit_by_param.-The name of URL parameter used to obtain key-value used in rate-limiting.
    limit_keysarray of objectRequired-Rate-limiting thresholds when matching specific key-values

    Field descriptions of limit_keys items:

    NameTypeRequirementDefault ValueDescription
    keystringRequired-Value to match of the specific key
    query_per_secondnumberOptional. Choose one from following: query_per_second, query_per_minute, query_per_hour, query_per_day.-Number of requests allowed per second
    query_per_minutenumberOptional. Choose one from following: query_per_second, query_per_minute, query_per_hour, query_per_day.-Number of requests allowed per minute
    query_per_hournumberOptional. Choose one from following: query_per_second, query_per_minute, query_per_hour, query_per_day.-Number of requests allowed per hour
    query_per_daynumberOptional. Choose one from following: query_per_second, query_per_minute, query_per_hour, query_per_day.-Number of requests allowed per day

    Configuration Samples

    Use query parameter apikey for rate-limiting

    limit_by_param: apikey
    limit_keys:
    - key: 9a342114-ba8a-11ec-b1bf-00163e1250b5
    query_per_second: 10
    - key: a6a6d7f2-ba8a-11ec-bec2-00163e1250b5
    query_per_minute: 100

    Use HTTP header parameter x-ca-key for rate-limiting

    limit_by_header: x-ca-key
    limit_keys:
    - key: 102234
    query_per_second: 10
    - key: 308239
    query_per_hour: 10

    Enable rate-limiting for specific routes or domains

    # Use _rules_ field for fine-grained rule configurations
    _rules_:
    # Rule 1: Match by route name
    - _match_route_:
    - route-a
    - route-b
    limit_by_header: x-ca-key
    limit_keys:
    - key: 102234
    query_per_second: 10
    # Rule 2: Match by domain
    - _match_domain_:
    - "*.example.com"
    - test.com
    limit_by_header: x-ca-key
    limit_keys:
    - key: 102234
    query_per_second: 100

    In the rule sample of _match_route_, route-a and route-b are the route names provided when creating a new gateway route. When the current route names matches the configuration, the rule following shall be applied. In the rule sample of _match_domain_, *.example.com and test.com are the domain names used for request matching. When the current domain name matches the configuration, the rule following shall be applied. All rules shall be checked following the order of items in the _rules_ field, The first matched rule will be applied. All remained will be ignored.

    - + \ No newline at end of file diff --git a/en-us/docs/plugins/request-block/index.html b/en-us/docs/plugins/request-block/index.html index ec070237ee..a04418cfd5 100644 --- a/en-us/docs/plugins/request-block/index.html +++ b/en-us/docs/plugins/request-block/index.html @@ -14,7 +14,7 @@ - + @@ -23,7 +23,7 @@ In the rule sample of _match_domain_, *.example.com and test.com are the domain names used for request matching. When the current domain name matches the configuration, the rule following shall be applied. All rules shall be checked following the order of items in the _rules_ field, The first matched rule will be applied. All remained will be ignored.

    Maximum Request Body Size Limitation

    When block_bodies is configured, body matching shall only be performed when its size is smaller than 32MB. If not, and no block_urls or block_headers configuration is matched, the request won't be blocked. When block_bodies is configured, if the size of request body exceeds the global configuration of DownstreamConnectionBufferLimits, a 413 Payload Too Large response will be returned.

    - + \ No newline at end of file diff --git a/en-us/docs/plugins/waf/index.html b/en-us/docs/plugins/waf/index.html index 30e1035fd8..33d09b1fb8 100644 --- a/en-us/docs/plugins/waf/index.html +++ b/en-us/docs/plugins/waf/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/annotation-use-case/index.html b/en-us/docs/user/annotation-use-case/index.html index 40b9227183..dcca941c66 100644 --- a/en-us/docs/user/annotation-use-case/index.html +++ b/en-us/docs/user/annotation-use-case/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/annotation/index.html b/en-us/docs/user/annotation/index.html index 09c4491240..6c7d965778 100644 --- a/en-us/docs/user/annotation/index.html +++ b/en-us/docs/user/annotation/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/configmap/index.html b/en-us/docs/user/configmap/index.html index 1f4a39fada..3c6ca758cf 100644 --- a/en-us/docs/user/configmap/index.html +++ b/en-us/docs/user/configmap/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/configurations/index.html b/en-us/docs/user/configurations/index.html index 6f351f1cba..19b8a84a3e 100644 --- a/en-us/docs/user/configurations/index.html +++ b/en-us/docs/user/configurations/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/dubbo-http2rpc/index.html b/en-us/docs/user/dubbo-http2rpc/index.html index 46fd76e503..e04ddf5ee1 100644 --- a/en-us/docs/user/dubbo-http2rpc/index.html +++ b/en-us/docs/user/dubbo-http2rpc/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/dubbo/index.html b/en-us/docs/user/dubbo/index.html index f5afecf864..11483f440a 100644 --- a/en-us/docs/user/dubbo/index.html +++ b/en-us/docs/user/dubbo/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/kruise-rollout/index.html b/en-us/docs/user/kruise-rollout/index.html index 6efc611385..4e4c528460 100644 --- a/en-us/docs/user/kruise-rollout/index.html +++ b/en-us/docs/user/kruise-rollout/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/mcp-bridge/index.html b/en-us/docs/user/mcp-bridge/index.html index 917fb5ff82..58c80ac1ef 100644 --- a/en-us/docs/user/mcp-bridge/index.html +++ b/en-us/docs/user/mcp-bridge/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/nacos-route/index.html b/en-us/docs/user/nacos-route/index.html index 4dd64f2b25..b56408d583 100644 --- a/en-us/docs/user/nacos-route/index.html +++ b/en-us/docs/user/nacos-route/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/nginx-ingress-migrate/index.html b/en-us/docs/user/nginx-ingress-migrate/index.html index 065f8be3db..78dc91d554 100644 --- a/en-us/docs/user/nginx-ingress-migrate/index.html +++ b/en-us/docs/user/nginx-ingress-migrate/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/nginx-ingress/index.html b/en-us/docs/user/nginx-ingress/index.html index 3b9e18f27b..e121d35dd0 100644 --- a/en-us/docs/user/nginx-ingress/index.html +++ b/en-us/docs/user/nginx-ingress/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/opensergo-gray/index.html b/en-us/docs/user/opensergo-gray/index.html index 486661ffb8..d998f3cec8 100644 --- a/en-us/docs/user/opensergo-gray/index.html +++ b/en-us/docs/user/opensergo-gray/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/prometheus/index.html b/en-us/docs/user/prometheus/index.html index cf68e3a9ec..dc7b5a8fca 100644 --- a/en-us/docs/user/prometheus/index.html +++ b/en-us/docs/user/prometheus/index.html @@ -14,13 +14,13 @@ - +

    Request Monitoring Based on Prometheus

    Use the Higress Console Built-In Monitor Suite

    Higress Console has a built-in monitor suite based on Prometheus + Grafana, which isn't installed by default. When installing Higress with Helm, you can enable it by adding the following argument to the command line: --set higress-console.o11y.enabled=true.

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io --set higress-console.o11y.enabled=true

    Note: When installing to a standard K8s cluster (meaning without specifying global.local=true or global.kind=true), the PersistentVolumeClaim configured in the suite uses the access mode of ReadWriteMany by default. If the target K8s cluster doesn't support this mode, you can add the following argument to the command line to change the access mode to ReadWriteOnce: --set higress-console.pvc.rwxSupported=false.

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io --set higress-console.o11y.enabled=true --set higress-console.pvc.rwxSupported=false

    After installation, open Higress Console in your browser, and click "Dashboard" on the left navigation area. The built-in dashboard will be displayed on the right.

    image

    Use a Standalone Monitor Suite

    Both the data and control planes of Higress expose a set of metrics via API. To monitor them, you just need to add probe configurations into Prometheus and configure a dashboard in Grafana.

    Before starting the configuration, please open Higress Console in your browser and switch to "Dashboard" from the left navigation area. The external dashboard configuration page and related notes will be displayed on the right.

    image

    Update the configurations of Prometheus and Grafana following the notes. Then put the Grafana dashboard into the textbox above and save. The page will reload automatically and your dashboard will be shown on the right.

    image

    If you'd like to update the dashboard URL, you can click the "Reconfigure" button on the top left corner.

    - + \ No newline at end of file diff --git a/en-us/docs/user/quickstart/index.html b/en-us/docs/user/quickstart/index.html index eb4df11ab4..fc22b21c28 100644 --- a/en-us/docs/user/quickstart/index.html +++ b/en-us/docs/user/quickstart/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    Quick Start

    Environment 1: Use in K8s

    Stage 1: Installation

    Scenario 1: Use in a Standard K8s Cluster

    Helm Installation Command

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io

    Obtain the LoadBalancer IP of Higress Gateway and write it down. You can use it and port 80 and 443 to access Higress Gateway.

    kubectl get svc -n higress-system higress-gateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

    Scenario 2: Use in Local Environment

    The following groups can be applied to all local K8s clusters. If there is already a test cluster running on your PC, you can go to Step 3 directly and install Higress.

    Step 1: Install kubectl & kind

    MacOS:

    # for Intel Macs
    [ $(uname -m) = x86_64 ] && curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
    [ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.18.0/kind-darwin-amd64
    # for Apple Silicon Macs (M1/M2)
    [ $(uname -m) = arm64 ] && curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
    [ $(uname -m) = arm64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.18.0/kind-darwin-arm64
    chmod +x ./kubectl ./kind
    sudo mv ./kubectl ./kind /usr/local/bin

    Use PowerShell in Windows:

    Download kubectl v1.27.1 and kind v0.18.0.

    Or if you have curl installed, use the following commands:

    curl.exe -LO "https://dl.k8s.io/release/v1.27.1/bin/windows/amd64/kubectl.exe"
    curl.exe -Lo kind-windows-amd64.exe https://kind.sigs.k8s.io/dl/v0.18.0/kind-windows-amd64

    Note: To find out the latest stable version of kubectl (for example, for scripting), take a look at https://dl.k8s.io/release/stable.txt.

    Then rename downloaded kind-windows-amd64 or kind-windows-amd64.exe to kind.exe. And move both exe files to a file location on your system PATH.

    Linux:

    curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
    curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.18.0/kind-linux-amd64
    chmod +x ./kubectl ./kind
    sudo mv ./kubectl ./kind /usr/local/bin
    Step 2: Create and Activate kind

    First, create a cluster config file: cluster.conf

    # cluster.conf
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
    kubeadmConfigPatches:
    - |
    kind: InitConfiguration
    nodeRegistration:
    kubeletExtraArgs:
    node-labels: "ingress-ready=true"
    extraPortMappings:
    - containerPort: 80
    hostPort: 80
    protocol: TCP
    - containerPort: 443
    hostPort: 443
    protocol: TCP

    Commands for Mac & Linux:

    kind create cluster --name higress --config=cluster.conf
    kubectl config use-context kind-higress

    Commands for Windows:

    kind.exe create cluster --name higress --config=cluster.conf
    kubectl.exe config use-context kind-higress

    Note

    currently, the namespace higress-system has a svc which type is LoadBalancer, it can not get IP in cluster by default. we can use official support to enable this function,please refer to https://kind.sigs.k8s.io/docs/user/loadbalancer/

    Step 3: Install Higress

    when you install higress in local environment, you should use --set global.kind=true; in the future, we will use --set global.local=true for unambiguous.

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set global.local=true --set higress-console.o11y.enabled=false --set higress-console.domain=console.higress.io

    If you'd like to enable the built-in o11y suite, please refer to the Deploy by Helm document.

    After installation, you can access Higress Gateway in the local cluster via port 80 and 443.

    Note: If you are using a pre-existed local K8s cluster, you may need to use the command below to forward ports out of the cluster, and try the local ports later.

    kubectl port-forward service/higress-gateway -n higress-system 80:80 443:443

    Stage 2: Configuration

    Assuming that there is already a service named "foo" deployed in the default namespace, we'd like to create a route, forwarding http://foo.bar.com/foo requests to this service.

    You can use the following YAML to create this test service if needed.

    kind: Pod
    apiVersion: v1
    metadata:
    name: foo-app
    labels:
    app: foo
    spec:
    containers:
    - name: foo-app
    image: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/http-echo:0.2.4-alpine
    args:
    - "-text=foo"
    ---
    kind: Service
    apiVersion: v1
    metadata:
    name: foo-service
    spec:
    selector:
    app: foo
    ports:
    # Default port used by the image
    - port: 5678

    Method 1: Use Higress Console

    Edit the hosts file and point domain console.higress.io to the IP of Higress Gateway (In a standard K8s cluster, use the previously obtained LoadBalancer IP. And use 127.0.0.1 instead in a local cluster).

    GatewayIP console.higress.io

    Open http://console.higress.io in browser. For the first time, you will need to configure the admin credentials.

    image

    After configuration, log into Higress Console using the credential just configured.

    image

    Click "Domain Management" on the navigation bar left. Click "Create Domain" button. Then fill the form according to the image below and click "Confirm" button.

    image

    Click "Route Management" on the navigation bar left. Click "Create Route" button. Then fill the form according to the image below and click "Confirm" button.

    image

    Method 2: Use Ingress CRD

    Use the YAML below to create the test route we need.

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: foo
    spec:
    ingressClassName: higress
    rules:
    - host: foo.bar.com
    http:
    paths:
    - pathType: Prefix
    path: "/foo"
    backend:
    service:
    name: foo-service
    port:
    number: 5678

    Stage 3: Validate

    Use the following command to check whether the test route works properly:

    # should output "foo"
    curl http://GatewayIP/foo -H "Host: foo.bar.com"

    Environment 2: Use in Docker Compose without K8s

    Stage 1: Installation

    Installation Command 1: Use a separated-deployed Nacos service

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -a -c nacos://192.168.0.1:8848 --nacos-username=nacos --nacos-password=nacos

    Please replace 192.168.0.1 with the actual IP address of Nacos service (if Nacos is deployed locally, please use a non-loopback address such as localhost or 127.0.0.1), and update the value of --nacos-username and --nacos-password based on actual configurations. If authentication isn't enabled in Nacos, you can remove these two arguments.

    Installation Command 2: Use the Higress Built-In Nacos

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -a --use-builtin-nacos

    Note: On Windows, you can use Unix-like shells such as Cygwin, Git Bash to execute the command above.

    Stage 2: Configuration

    Open http://127.0.0.1:8080 in browser. For the first time, you will need to configure the admin credentials.

    image

    After configuration, log into Higress Console using the credential just configured.

    image

    Click "Service Sources" on the navigation bar left. Click "Create Service Source" button. Then fill the form according to the image below and click "Confirm" button.

    image

    Click "Domain Management" on the navigation bar left. Click "Create Domain" button. Then fill the form according to the image below and click "Confirm" button.

    image

    Click "Route Management" on the navigation bar left. Click "Create Route" button. Then fill the form according to the image below and click "Confirm" button.

    image

    Stage 3: Validate

    Use the following command to check whether the test route works properly:

    # should output a JSON object containing request data 
    curl http://localhost/get?foo=bar -H 'host: foo.bar.com'
    - + \ No newline at end of file diff --git a/en-us/docs/user/sentinel/index.html b/en-us/docs/user/sentinel/index.html index 83c0292686..d95a631cfd 100644 --- a/en-us/docs/user/sentinel/index.html +++ b/en-us/docs/user/sentinel/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/spring-cloud/index.html b/en-us/docs/user/spring-cloud/index.html index 1d938d5ca9..5c256cec54 100644 --- a/en-us/docs/user/spring-cloud/index.html +++ b/en-us/docs/user/spring-cloud/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/waf/index.html b/en-us/docs/user/waf/index.html index f27eb3329d..3af75d57fd 100644 --- a/en-us/docs/user/waf/index.html +++ b/en-us/docs/user/waf/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/docs/user/wasm-go/index.html b/en-us/docs/user/wasm-go/index.html index 8b9a7eea52..f9459b066f 100644 --- a/en-us/docs/user/wasm-go/index.html +++ b/en-us/docs/user/wasm-go/index.html @@ -14,7 +14,7 @@ - + @@ -26,7 +26,7 @@ This local wasm file is exported to the specified plugin's directory and can be used directly for local debugging. You can also use make build-push to build and push the image together. See plugins/wasm-go for more.

    3.2 Compile wasm files locally

    Execute the following command:

    tinygo build -o main.wasm -scheduler=none -target=wasi ./main.go

    A new file named main.wasm will be created after a successful compilation, which will be used in the local debugging sample below as well.
    When using custom plugin function in the cloud native gateway market, you just need to upload this file.

    # 3. Local Debugging

    TBD

    More Samples

    ## Plugin with No Configuration If the plugin needs no configuration, just define an empty config struct.
    package main

    import (
    "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
    )

    func main() {
    wrapper.SetCtx(
    "hello-world",
    wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
    )
    }

    type MyConfig struct {}

    func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
    proxywasm.SendHttpResponse(200, nil, []byte("hello world"), -1)
    return types.ActionContinue
    }
    ## Send Requests to External Services in the Plugin Only HTTP requests are supported for now. You can send requests to Nacos and K8s services with service sources configured in the gateway console, and services with a static IP or DNS source. Please be noted, HTTP client in the `net/http` package cannot be used here. You only use the wrapped HTTP client as shown in the sample below.
    In the following sample works as below: 1. Parse service type in the config parsing stage, and generate the corresponding HTTP client. 2. In the HTTP request header processing stage, send a service request to the configured URL. 3. Parse response headers and get token value using the specified key. 4. Set the token value to the headers of the original request.
    package main

    import (
    "errors"
    "net/http"
    "strings"
    "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
    "github.com/tidwall/gjson"
    )

    func main() {
    wrapper.SetCtx(
    "http-call",
    wrapper.ParseConfigBy(parseConfig),
    wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
    )
    }

    type MyConfig struct {
    // The client used to initiate an HTTP request
    client wrapper.HttpClient
    // Request URL
    requestPath string
    // Use this key when extracting token header from the service response and setting a header to the request. The value is configurable.
    tokenHeader string
    }

    func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
    config.tokenHeader = json.Get("tokenHeader").String()
    if config.tokenHeader == "" {
    return errors.New("missing tokenHeader in config")
    }
    config.requestPath = json.Get("requestPath").String()
    if config.requestPath == "" {
    return errors.New("missing requestPath in config")
    }
    serviceSource := json.Get("serviceSource").String()
    // If serviceSource is set to "ip" or "dns", serviceName shall be specified when creating the service.
    // If serviceSource is set to "nacos" or "k8s", serviceName shall be set to the original name specified when registering the service.
    serviceName := json.Get("serviceName").String()
    servicePort := json.Get("servicePort").Int()
    if serviceName == "" || servicePort == 0 {
    return errors.New("invalid service config")
    }
    switch serviceSource {
    case "k8s":
    namespace := json.Get("namespace").String()
    config.client = wrapper.NewClusterClient(wrapper.K8sCluster{
    ServiceName: serviceName,
    Namespace: namespace,
    Port: servicePort,
    })
    return nil
    case "nacos":
    namespace := json.Get("namespace").String()
    config.client = wrapper.NewClusterClient(wrapper.NacosCluster{
    ServiceName: serviceName,
    NamespaceID: namespace,
    Port: servicePort,
    })
    return nil
    case "ip":
    config.client = wrapper.NewClusterClient(wrapper.StaticIpCluster{
    ServiceName: serviceName,
    Port: servicePort,
    })
    return nil
    case "dns":
    domain := json.Get("domain").String()
    config.client = wrapper.NewClusterClient(wrapper.DnsCluster{
    ServiceName: serviceName,
    Port: servicePort,
    Domain: domain,
    })
    return nil
    default:
    return errors.New("unknown service source: " + serviceSource)
    }
    }

    func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
    // Use the Get function of the client to initiate an HTTP Get request.
    // The timeout parameter is omitted here, whose default value is 500ms.
    config.client.Get(config.requestPath, nil,
    // A callback function which will be called asynchronously when receiving the response.
    func(statusCode int, responseHeaders http.Header, responseBody []byte) {
    // Process the response with a status code other than 200.
    if statusCode != http.StatusOK {
    log.Errorf("http call failed, status: %d", statusCode)
    proxywasm.SendHttpResponse(http.StatusInternalServerError, nil,
    []byte("http call failed"), -1)
    return
    }
    // Print out the status code and response body
    log.Infof("get status: %d, response body: %s", statusCode, responseBody)
    // Extract token value from the response header and set the header of the original request
    token := responseHeaders.Get(config.tokenHeader)
    if token != "" {
    proxywasm.AddHttpRequestHeader(config.tokenHeader, token)
    }
    // Resume the original request processing workflow. Continue the process, so the request can be forwarded to the upstream.
    proxywasm.ResumeHttpRequest()
    })
    // We need to wait for the callback to finish its process.
    // Return Pause action here to pause the request processing workflow, which can be resumed by a ResumeHttpRequest call.
    return types.ActionPause
    }
    - + \ No newline at end of file diff --git a/en-us/docs/user/wasm-image-spec/index.html b/en-us/docs/user/wasm-image-spec/index.html index 0966c3be7d..6e4a0eacd2 100644 --- a/en-us/docs/user/wasm-image-spec/index.html +++ b/en-us/docs/user/wasm-image-spec/index.html @@ -14,13 +14,13 @@ - +

    Wasm Plugin Image Specification

    1. Overview

    This document defines the structure and building method of Higress Wasm Plugin images. When preparing, we referred to Wasm Image Specification.

    2. Image Structure

    Each image needs to be build in OCI Image Specification based on scratch, and shall only contain following files:

    • spec.yaml: Required. Metadata file of the plugin. Please refer to section 3 below for its format.
    • README.md: Required. Readme file describing the usage of the plugin. Markdown format. Written in English or Chinese.
    • README_{lang}.md: Optional. Readme file describing the usage of the plugin. Markdown format. lang can be ZH or EN.
    • icon.png: Optional. Icon file of the plugin. A URL of the plugin icon can also be specified in spec.yaml. If both the file and the URL are configured, the file will be used for display.
    • plugin.wasm: Required. The binary file of the plugin.

    Each layer of the image can only contain a single file.

    Except the layer containing plugin.wasm, the media type of other layers shall be set according to the file inside:

    • spec.yaml: application/vnd.module.wasm.spec.v1+yaml
    • README.md: application/vnd.module.wasm.doc.v1+markdown
    • README_{lang}.md: application/vnd.module.wasm.doc.v1.{lang}+markdown
    • icon.png: application/vnd.module.wasm.icon.v1+png

    plugin.wasm must be placed in the last layer of the image, with the media type of application/vnd.oci.image.layer.v1.tar+gzip.

    3. Metadata File Format

    The format of metadata file, spec.yaml, is as following, using the metadata of basic-auth plugin as an example:

    apiVersion: 1.0.0  # The schema version of the content below. Always use to 1.0.0 for now.
    info:
    category: auth # Plugin category. Options: auth (authentication and authorization), security (security protection), protocol (protocol transformation), flow-control, flow-monitor,custom
    name: basic-auth/v1 # Plugin name, which is the unique identifier of the plugin. It is recommended to add a version suffix, such as "/v1", just in case an incompatible upgrade in the future.
    title: Basic Auth # Display name. I18n supported.
    description: 本插件实现了基于 HTTP Basic Auth 标准进行认证鉴权的功能。 # Plugin description. I18n supported.
    x-description-i18n: # I18n content of the description field above. Translated contents can be added using "x-{name}-i18n" fields for all i18n-supported fields.
    en-US: This plugin implements an authentication function based on HTTP Basic Auth standard.
    iconUrl: https://img.alicdn.com/imgextra/i1/O1CN01I7WjVs1K33EQjInid_!!6000000001107-2-tps-960-290.png # Optional. URL of plugin icon file.
    version: 1.0.0 # Plugin version
    contact: # Plugin contact
    name: Higress Team
    url: http://higress.io/
    email: admin@higress.io
    spec:
    phase: AUTHN # Execution phase. Please refer to https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/#PluginPhase
    priority: 0 # Execution priority within the given phase. Please refer to https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/#WasmPlugin
    configSchema: # Schema of the plugin's runtime configurations, which shall be defined with the Schema object in OpenAPI 3.0.0 standard.
    openAPIV3Schema: # Please refer to https://openapi.apifox.cn/#schema-%E5%AF%B9%E8%B1%A1 for the data structure. Some fields which can be used for display support i18n.
    type: object
    properties:
    consumers:
    type: array
    scope: GLOBAL # Field effective scope. Options: GLOBAL (global configuration), INSTANCE (instance-level configuration, which can be set associated to routes or domains.), ALL (Available as both global and instance-level configurations). Optional. Default value is INSTANCE.
    title: 调用方列表
    x-title-i18n:
    en-US: Consumer List
    description: 服务调用方列表,用于对请求进行认证
    x-description-i18n:
    en-US: List of service consumers which will be used in request authentication
    items:
    type: object
    properties:
    name:
    type: string
    title: 名称
    x-title-i18n:
    en-US: Name
    description: 该调用方的名称
    x-description-i18n:
    en-US: The name of the consumer
    # Data validation shall be implemented according JSON Schema Validation Spec
    # https://json-schema.org/draft/2020-12/json-schema-validation.html
    # Following values are supported:
    # - maximum
    # - minimum
    # - maxLength
    # - minLength
    # - pattern
    # - maxItems
    # - minItems
    # - required
    minLength: 6 # Minimum length for data validation
    maxLength: 256 # Maximum length for data validation
    pattern: "^$" # Regular experssion for data validation
    example:
    - consumer1
    credential:
    type: string
    title: 访问凭证
    x-title-i18n:
    en-US: Credential
    description: 该调用方的访问凭证
    x-description-i18n:
    en-US: The credential of the consumer
    example:
    - admin:123456
    required:
    - name
    - credential
    allow:
    type: array
    title: 授权访问的调用方列表
    x-title-i18n:
    en-US: Allowed Consumers
    description: 对于匹配上述条件的请求,允许访问的调用方列表
    x-description-i18n:
    en-US: Consumers to be allowed for matched requests
    items:
    type: string
    example:
    - consumer1
    required:
    - allow
    - consumers
    example:
    consumers:
    - name: consumer1
    credential: admin:123456
    - name: consumer2
    credential: guest:abc
    allow:
    - consumer2

    4. How to Build an Image

    1. Start the builder container from the Higress root folder
    GO_VERSION="1.19"
    TINYGO_VERSION="0.25.0"
    ORAS_VERSION="1.0.0"
    PLUGIN_NAME="hello-world"
    BUILDER_IMAGE="higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-go-builder:go${GO_VERSION}-tinygo${TINYGO_VERSION}-oras${ORAS_VERSION}"
    docker run -v ${PWD}:/workspace -e PLUGIN_NAME=${PLUGIN_NAME} -it --rm /bin/bash
    1. Build Wasm file inside the container
    cd /workspace/plugins/wasm-go/extensions/${PLUGIN_NAME}
    go mod tidy
    tinygo build -o ./plugin.wasm -scheduler=none -target=wasi ./main.go
    1. Build and push an OCI image
    tar czvf plugin.tar.gz plugin.wasm
    IMAGE_REGISTRY_SERVICE=docker.io
    IMAGE_REPOSITORY="${IMAGE_REGISTRY_SERVICE}/plugins/${PLUGIN_NAME}"
    IMAGE_TAG="v0.0.1"
    oras login ${IMAGE_REGISTRY_SERVICE}
    oras push ${IMAGE_REPOSITORY}:${IMAGE_TAG} \
    ./spec.yaml:application/vnd.module.wasm.spec.v1+yaml \
    ./README.md:application/vnd.module.wasm.doc.v1+markdown \
    ./README_EN.md:application/vnd.module.wasm.doc.v1.en+markdown \
    ./plugin.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip

    5. Appendix

    5.1 Default Icon for Each Plugin Category

    - + \ No newline at end of file diff --git a/en-us/home/community/index.html b/en-us/home/community/index.html index 0a22829de2..3bfcd6dfdf 100644 --- a/en-us/home/community/index.html +++ b/en-us/home/community/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/en-us/home/feature/index.html b/en-us/home/feature/index.html index d276def0ee..40f03ff492 100644 --- a/en-us/home/feature/index.html +++ b/en-us/home/feature/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/en-us/home/introduction/index.html b/en-us/home/introduction/index.html index 0a31426e7e..d72cf305a9 100644 --- a/en-us/home/introduction/index.html +++ b/en-us/home/introduction/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/en-us/home/msemap/index.html b/en-us/home/msemap/index.html index 2cca6c7c3f..4b73d98f80 100644 --- a/en-us/home/msemap/index.html +++ b/en-us/home/msemap/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/en-us/home/top/index.html b/en-us/home/top/index.html index 0137dfd92f..f7f3e57172 100644 --- a/en-us/home/top/index.html +++ b/en-us/home/top/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/en-us/home/users/index.html b/en-us/home/users/index.html index 349497c812..d43a333cb3 100644 --- a/en-us/home/users/index.html +++ b/en-us/home/users/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/en-us/index.html b/en-us/index.html index 925722b7c6..7314e46a5a 100644 --- a/en-us/index.html +++ b/en-us/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/en-us/markdown-page/index.html b/en-us/markdown-page/index.html index e5e94a45cb..259f9b4ffe 100644 --- a/en-us/markdown-page/index.html +++ b/en-us/markdown-page/index.html @@ -14,13 +14,13 @@ - +

    Markdown page example

    You don't need React to write simple standalone pages.

    - + \ No newline at end of file diff --git a/home/community/index.html b/home/community/index.html index 737b017384..5e51fa1884 100644 --- a/home/community/index.html +++ b/home/community/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/home/feature/index.html b/home/feature/index.html index 4f5b5ededf..590122e4a5 100644 --- a/home/feature/index.html +++ b/home/feature/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/home/introduction/index.html b/home/introduction/index.html index cee2a2cfb5..f7d99bd95d 100644 --- a/home/introduction/index.html +++ b/home/introduction/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/home/msemap/index.html b/home/msemap/index.html index 23350d1fed..ce683c45f5 100644 --- a/home/msemap/index.html +++ b/home/msemap/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/home/top/index.html b/home/top/index.html index 6f1836f252..55dcb1e68f 100644 --- a/home/top/index.html +++ b/home/top/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/home/users/index.html b/home/users/index.html index 84de19ff4d..cd4d2057d6 100644 --- a/home/users/index.html +++ b/home/users/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/index.html b/index.html index f10690593c..a5c78151b4 100644 --- a/index.html +++ b/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/markdown-page/index.html b/markdown-page/index.html index 7a56affda7..7b8bc12045 100644 --- a/markdown-page/index.html +++ b/markdown-page/index.html @@ -14,13 +14,13 @@ - +

    Markdown page example

    You don't need React to write simple standalone pages.

    - + \ No newline at end of file diff --git a/zh-cn/404.html b/zh-cn/404.html index 6a92cb28bb..c67149ae27 100644 --- a/zh-cn/404.html +++ b/zh-cn/404.html @@ -14,13 +14,13 @@ - +

    找不到页面

    我们找不到您要找的页面。

    请联系原始链接来源网站的所有者,并告知他们链接已损坏。

    - + \ No newline at end of file diff --git a/zh-cn/assets/js/b4eec107.6ff6cca7.js b/zh-cn/assets/js/b4eec107.6ff6cca7.js new file mode 100644 index 0000000000..fab2567c57 --- /dev/null +++ b/zh-cn/assets/js/b4eec107.6ff6cca7.js @@ -0,0 +1 @@ +"use strict";(self.webpackChunkhigress_website=self.webpackChunkhigress_website||[]).push([[6376],{3905:(e,n,t)=>{t.d(n,{Zo:()=>m,kt:()=>h});var a=t(7294);function r(e,n,t){return n in e?Object.defineProperty(e,n,{value:t,enumerable:!0,configurable:!0,writable:!0}):e[n]=t,e}function s(e,n){var t=Object.keys(e);if(Object.getOwnPropertySymbols){var a=Object.getOwnPropertySymbols(e);n&&(a=a.filter((function(n){return Object.getOwnPropertyDescriptor(e,n).enumerable}))),t.push.apply(t,a)}return t}function i(e){for(var n=1;n=0||(r[t]=e[t]);return r}(e,n);if(Object.getOwnPropertySymbols){var s=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,t)&&(r[t]=e[t])}return r}var l=a.createContext({}),p=function(e){var n=a.useContext(l),t=n;return e&&(t="function"==typeof e?e(n):i(i({},n),e)),t},m=function(e){var n=p(e.components);return a.createElement(l.Provider,{value:n},e.children)},c="mdxType",k={inlineCode:"code",wrapper:function(e){var n=e.children;return a.createElement(a.Fragment,{},n)}},d=a.forwardRef((function(e,n){var t=e.components,r=e.mdxType,s=e.originalType,l=e.parentName,m=o(e,["components","mdxType","originalType","parentName"]),c=p(t),d=r,h=c["".concat(l,".").concat(d)]||c[d]||k[d]||s;return t?a.createElement(h,i(i({ref:n},m),{},{components:t})):a.createElement(h,i({ref:n},m))}));function h(e,n){var t=arguments,r=n&&n.mdxType;if("string"==typeof e||r){var s=t.length,i=new Array(s);i[0]=d;var o={};for(var l in n)hasOwnProperty.call(n,l)&&(o[l]=n[l]);o.originalType=e,o[c]="string"==typeof e?e:r,i[1]=o;for(var p=2;p{t.r(n),t.d(n,{assets:()=>l,contentTitle:()=>i,default:()=>k,frontMatter:()=>s,metadata:()=>o,toc:()=>p});var a=t(7462),r=(t(7294),t(3905));const s={title:"\u901a\u8fc7Ingress Annotation\u5b9e\u73b0\u9ad8\u9636\u6d41\u91cf\u6cbb\u7406",keywords:["Ingress Annotation"],description:"\u5728Higress\u4e0a\u4f7f\u7528Ingress\u5e76\u501f\u52a9Annotation\u5b9e\u73b0\u9ad8\u9636\u6d41\u91cf\u6cbb\u7406\u3002"},i=void 0,o={unversionedId:"user/annotation-use-case",id:"user/annotation-use-case",title:"\u901a\u8fc7Ingress Annotation\u5b9e\u73b0\u9ad8\u9636\u6d41\u91cf\u6cbb\u7406",description:"\u5728Higress\u4e0a\u4f7f\u7528Ingress\u5e76\u501f\u52a9Annotation\u5b9e\u73b0\u9ad8\u9636\u6d41\u91cf\u6cbb\u7406\u3002",source:"@site/i18n/zh-cn/docusaurus-plugin-content-docs/current/user/annotation-use-case.md",sourceDirName:"user",slug:"/user/annotation-use-case",permalink:"/zh-cn/docs/user/annotation-use-case",draft:!1,editUrl:"https://github.com/higress-group/higress-group.github.io/blob/main/i18n/zh-cn/docusaurus-plugin-content-docs/current/user/annotation-use-case.md",tags:[],version:"current",frontMatter:{title:"\u901a\u8fc7Ingress Annotation\u5b9e\u73b0\u9ad8\u9636\u6d41\u91cf\u6cbb\u7406",keywords:["Ingress Annotation"],description:"\u5728Higress\u4e0a\u4f7f\u7528Ingress\u5e76\u501f\u52a9Annotation\u5b9e\u73b0\u9ad8\u9636\u6d41\u91cf\u6cbb\u7406\u3002"},sidebar:"docs",previous:{title:"Ingress Annotation \u914d\u7f6e\u8bf4\u660e",permalink:"/zh-cn/docs/user/annotation"},next:{title:"\u8fd0\u7ef4\u53c2\u6570\u914d\u7f6e\u8bf4\u660e",permalink:"/zh-cn/docs/user/configurations"}},l={},p=[{value:"\u524d\u63d0\u6761\u4ef6",id:"\u524d\u63d0\u6761\u4ef6",level:2},{value:"\u7070\u5ea6\u53d1\u5e03",id:"\u7070\u5ea6\u53d1\u5e03",level:2},{value:"\u57fa\u4e8eHeader\u7070\u5ea6\u53d1\u5e03",id:"\u57fa\u4e8eheader\u7070\u5ea6\u53d1\u5e03",level:3},{value:"\u57fa\u4e8eCookie\u7070\u5ea6\u53d1\u5e03",id:"\u57fa\u4e8ecookie\u7070\u5ea6\u53d1\u5e03",level:3},{value:"\u57fa\u4e8e\u6743\u91cd\u7070\u5ea6\u53d1\u5e03",id:"\u57fa\u4e8e\u6743\u91cd\u7070\u5ea6\u53d1\u5e03",level:3},{value:"\u8de8\u57df",id:"\u8de8\u57df",level:2},{value:"Rewrite\u91cd\u5199Path\u548cHost",id:"rewrite\u91cd\u5199path\u548chost",level:2},{value:"Rewrite\u91cd\u5199Path",id:"rewrite\u91cd\u5199path",level:3},{value:"Rewrite\u91cd\u5199Host",id:"rewrite\u91cd\u5199host",level:3},{value:"\u91cd\u5b9a\u5411",id:"\u91cd\u5b9a\u5411",level:2},{value:"\u914d\u7f6eHTTP\u91cd\u5b9a\u5411\u81f3HTTPS",id:"\u914d\u7f6ehttp\u91cd\u5b9a\u5411\u81f3https",level:3},{value:"\u6c38\u4e45\u91cd\u5b9a\u5411",id:"\u6c38\u4e45\u91cd\u5b9a\u5411",level:3},{value:"\u4e34\u65f6\u91cd\u5b9a\u5411",id:"\u4e34\u65f6\u91cd\u5b9a\u5411",level:3},{value:"Header\u63a7\u5236",id:"header\u63a7\u5236",level:2},{value:"\u8bf7\u6c42Header\u63a7\u5236",id:"\u8bf7\u6c42header\u63a7\u5236",level:3},{value:"\u54cd\u5e94Header\u63a7\u5236",id:"\u54cd\u5e94header\u63a7\u5236",level:3},{value:"\u91cd\u8bd5",id:"\u91cd\u8bd5",level:2},{value:"\u8d85\u65f6",id:"\u8d85\u65f6",level:2},{value:"\u5355\u673a\u9650\u6d41",id:"\u5355\u673a\u9650\u6d41",level:2},{value:"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u534f\u8bae\uff1aHTTPS\u6216GRPC",id:"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u534f\u8baehttps\u6216grpc",level:2},{value:"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5",id:"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5",level:2},{value:"\u666e\u901a\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5",id:"\u666e\u901a\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5",level:3},{value:"\u57fa\u4e8e\u4e00\u81f4\u6027Hash\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5",id:"\u57fa\u4e8e\u4e00\u81f4\u6027hash\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5",level:3},{value:"Cookie\u4eb2\u548c\u6027 \uff08\u4f1a\u8bdd\u4fdd\u6301\uff09",id:"cookie\u4eb2\u548c\u6027-\u4f1a\u8bdd\u4fdd\u6301",level:2},{value:"\u7f51\u5173\u4e0e\u540e\u7aef\u670d\u52a1\u53cc\u5411\u8ba4\u8bc1\uff08MTLS)",id:"\u7f51\u5173\u4e0e\u540e\u7aef\u670d\u52a1\u53cc\u5411\u8ba4\u8bc1mtls",level:2}],m={toc:p},c="wrapper";function k(e){let{components:n,...t}=e;return(0,r.kt)(c,(0,a.Z)({},m,t,{components:n,mdxType:"MDXLayout"}),(0,r.kt)("p",null,"\u672c\u7bc7\u6587\u6863\u4ecb\u7ecd\u5982\u4f55\u5728Higress\u4e0a\u4f7f\u7528Ingress\u5e76\u501f\u52a9Annotation\u5b9e\u73b0\u9ad8\u9636\u6d41\u91cf\u6cbb\u7406\u3002"),(0,r.kt)("h2",{id:"\u524d\u63d0\u6761\u4ef6"},"\u524d\u63d0\u6761\u4ef6"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},(0,r.kt)("a",{parentName:"li",href:"/zh-cn/docs/user/quickstart"},"\u5b89\u88c5Higress")),(0,r.kt)("li",{parentName:"ul"},"\u5df2\u62e5\u6709\u4e00\u4e2aKubernetes\u96c6\u7fa4\uff0c\u4e14\u914d\u7f6e\u4e86kubectl\u547d\u4ee4\u884c\u5de5\u5177")),(0,r.kt)("h2",{id:"\u7070\u5ea6\u53d1\u5e03"},"\u7070\u5ea6\u53d1\u5e03"),(0,r.kt)("p",null,"Higress\u63d0\u4f9b\u590d\u6742\u7684\u8def\u7531\u5904\u7406\u80fd\u529b\uff0c\u652f\u6301\u57fa\u4e8eHeader\u3001Cookie\u4ee5\u53ca\u6743\u91cd\u7684\u7070\u5ea6\u53d1\u5e03\u529f\u80fd\u3002\u7070\u5ea6\u53d1\u5e03\u529f\u80fd\u53ef\u4ee5\u901a\u8fc7\u8bbe\u7f6e\u6ce8\u89e3\u6765\u5b9e\u73b0\uff0c\u4e3a\u4e86\u542f\u7528\u7070\u5ea6\u53d1\u5e03\u529f\u80fd\uff0c\u9700\u8981\u8bbe\u7f6e\u6ce8\u89e3",(0,r.kt)("inlineCode",{parentName:"p"},'higress.io/canary: "true"'),"\u3002\u901a\u8fc7\u4e0d\u540c\u6ce8\u89e3\u53ef\u4ee5\u5b9e\u73b0\u4e0d\u540c\u7684\u7070\u5ea6\u53d1\u5e03\u529f\u80fd\u3002"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},"\u8bf4\u660e\uff1a\u5f53\u591a\u79cd\u65b9\u5f0f\u540c\u65f6\u914d\u7f6e\u65f6\uff0c\u7070\u5ea6\u65b9\u5f0f\u9009\u62e9\u4f18\u5148\u7ea7\u4e3a\uff1a\u57fa\u4e8eHeader > \u57fa\u4e8eCookie > \u57fa\u4e8e\u6743\u91cd\uff08\u4ece\u9ad8\u5230\u4f4e\uff09\u3002")),(0,r.kt)("h3",{id:"\u57fa\u4e8eheader\u7070\u5ea6\u53d1\u5e03"},"\u57fa\u4e8eHeader\u7070\u5ea6\u53d1\u5e03"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"\u53ea\u914d\u7f6e",(0,r.kt)("inlineCode",{parentName:"li"},"higress.io/canary-by-header"),"\uff1a\u57fa\u4e8eRequest Header\u7684\u540d\u79f0\u8fdb\u884c\u6d41\u91cf\u5207\u5206\u3002\u5f53\u8bf7\u6c42\u5305\u542b\u8be5Header\u5e76\u5176\u503c\u4e3aalways\u65f6\uff0c\u8bf7\u6c42\u6d41\u91cf\u4f1a\u88ab\u5206\u914d\u5230\u7070\u5ea6\u670d\u52a1\u5165\u53e3\uff1b\u5176\u4ed6\u60c5\u51b5\u65f6\uff0c\u8bf7\u6c42\u6d41\u91cf\u4e0d\u4f1a\u5206\u914d\u5230\u7070\u5ea6\u670d\u52a1\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u540c\u65f6\u914d\u7f6e",(0,r.kt)("inlineCode",{parentName:"li"},"higress.io/canary-by-header"),"\u548c",(0,r.kt)("inlineCode",{parentName:"li"},"higress.io/canary-by-header-value"),"\uff1a\u57fa\u4e8eRequest Header\u7684\u540d\u79f0\u548c\u503c\u8fdb\u884c\u6d41\u91cf\u5207\u5206\u3002\u5f53\u8bf7\u6c42\u4e2d\u7684header\u7684\u540d\u79f0\u548cheader\u7684\u503c\u4e0e\u8be5\u914d\u7f6e\u5339\u914d\u65f6\uff0c\u8bf7\u6c42\u6d41\u91cf\u4f1a\u88ab\u5206\u914d\u5230\u7070\u5ea6\u670d\u52a1\uff1b\u5176\u4ed6\u60c5\u51b5\u65f6\uff0c\u8bf7\u6c42\u6d41\u91cf\u4e0d\u4f1a\u5206\u914d\u5230\u7070\u5ea6\u670d\u52a1\u3002",(0,r.kt)("blockquote",{parentName:"li"},(0,r.kt)("p",{parentName:"blockquote"},"Higress\u7070\u5ea6\u53d1\u5e03\u65f6\u652f\u6301\u591a\u4e2a\u7248\u672c\u670d\u52a1\uff08\u65e0\u4e0a\u9650\uff09\u3002")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u8bf7\u6c42Header\u4e3a",(0,r.kt)("inlineCode",{parentName:"li"},"higress\uff1aalways"),"\u65f6\u5c06\u8bbf\u95ee\u7070\u5ea6\u670d\u52a1demo-service-canary\uff1b\u5176\u4ed6\u60c5\u51b5\u5c06\u8bbf\u95ee\u6b63\u5f0f\u670d\u52a1demo-service\uff0c\u914d\u7f6e\u5982\u4e0b\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/canary: "true"\n higress.io/canary-by-header: "higress"\n name: demo-canary\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service-canary\n port: \n number: 80\n path: /hello\n pathType: Exact\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /hello\n pathType: Exact \n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u8bf7\u6c42Header\u4e3a",(0,r.kt)("inlineCode",{parentName:"li"},"higress\uff1av1"),"\u65f6\u5c06\u8bbf\u95ee\u7070\u5ea6\u670d\u52a1demo-service-canary-v1\uff1b\u8bf7\u6c42Header\u4e3a",(0,r.kt)("inlineCode",{parentName:"li"},"higress\uff1av2"),"\u65f6\u5c06\u8bbf\u95ee\u7070\u5ea6\u670d\u52a1demo-service-canary-v2\uff1b\u5176\u4ed6\u60c5\u51b5\u5c06\u8bbf\u95ee\u6b63\u5f0f\u670d\u52a1demo-service\uff0c\u914d\u7f6e\u5982\u4e0b\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/canary: "true"\n higress.io/canary-by-header: "higress"\n higress.io/canary-by-header-value: "v1"\n name: demo-canary-v1\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service-canary-v1\n port: \n number: 80\n path: /hello\n pathType: Exact\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/canary: "true"\n higress.io/canary-by-header: "higress"\n higress.io/canary-by-header-value: "v2"\n name: demo-canary-v2\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service-canary-v2\n port: \n number: 80\n path: /hello\n pathType: Exact\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /hello\n pathType: Exact\n')),(0,r.kt)("h3",{id:"\u57fa\u4e8ecookie\u7070\u5ea6\u53d1\u5e03"},"\u57fa\u4e8eCookie\u7070\u5ea6\u53d1\u5e03"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/canary-by-cookie\uff1a\u57fa\u4e8eCookie\u7684Key\u8fdb\u884c\u6d41\u91cf\u5207\u5206\u3002\u5f53\u8bf7\u6c42\u7684Cookie\u4e2d\u542b\u6709\u8be5Key\u4e14\u5176\u503c\u4e3aalways\u65f6\uff0c\u8bf7\u6c42\u6d41\u91cf\u5c06\u88ab\u5206\u914d\u5230\u7070\u5ea6\u670d\u52a1\uff1b\u5176\u4ed6\u60c5\u51b5\u65f6\uff0c\u8bf7\u6c42\u6d41\u91cf\u5c06\u4e0d\u4f1a\u5206\u914d\u5230\u7070\u5ea6\u670d\u52a1\u3002",(0,r.kt)("blockquote",{parentName:"li"},(0,r.kt)("p",{parentName:"blockquote"},"\u8bf4\u660e\uff1a\u57fa\u4e8eCookie\u7684\u7070\u5ea6\u53d1\u5e03\u4e0d\u652f\u6301\u81ea\u5b9a\u4e49\u8bbe\u7f6eKey\u5bf9\u5e94\u7684\u503c\uff0c\u53ea\u80fd\u662falways\u3002")))),(0,r.kt)("p",null,"\u8bf7\u6c42\u7684Cookie\u4e3a",(0,r.kt)("inlineCode",{parentName:"p"},"demo=always"),"\u65f6\u5c06\u8bbf\u95ee\u7070\u5ea6\u670d\u52a1demo-service-canary\uff1b\u5176\u4ed6\u60c5\u51b5\u5c06\u8bbf\u95ee\u6b63\u5f0f\u670d\u52a1demo-service\u3002\u914d\u7f6e\u5982\u4e0b\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/canary: "true"\n higress.io/canary-by-cookie: "demo"\n name: demo-canary\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service-canary\n port: \n number: 80\n path: /hello\n pathType: Exact\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /hello\n pathType: Exact\n')),(0,r.kt)("h3",{id:"\u57fa\u4e8e\u6743\u91cd\u7070\u5ea6\u53d1\u5e03"},"\u57fa\u4e8e\u6743\u91cd\u7070\u5ea6\u53d1\u5e03"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/canary-weight\uff1a\u8bbe\u7f6e\u8bf7\u6c42\u5230\u6307\u5b9a\u670d\u52a1\u7684\u767e\u5206\u6bd4\uff08\u503c\u4e3a0~100\u7684\u6574\u6570\uff09"),(0,r.kt)("li",{parentName:"ul"},"higress.io/canary-weight-totatl\uff1a\u8bbe\u7f6e\u6743\u91cd\u603b\u548c\uff0c\u9ed8\u8ba4\u4e3a100")),(0,r.kt)("p",null,"\u914d\u7f6e\u7070\u5ea6\u670d\u52a1demo-service-canary-v1\u7684\u6743\u91cd\u4e3a30%\uff0c\u914d\u7f6e\u7070\u5ea6\u670d\u52a1demo-service-canary-v2\u7684\u6743\u91cd\u4e3a20%\uff0c\u914d\u7f6e\u6b63\u5f0f\u670d\u52a1demo-service\u7684\u6743\u91cd\u4e3a50%\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/canary: "true"\n higress.io/canary-weight: "30"\n name: demo-canary-v1\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service-canary-v1\n port: \n number: 80\n path: /hello\n pathType: Exact\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/canary: "true"\n higress.io/canary-weight: "20"\n name: demo-canary-v2\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service-canary-v2\n port: \n number: 80\n path: /hello\n pathType: Exact\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /hello\n pathType: Exact\n')),(0,r.kt)("h2",{id:"\u8de8\u57df"},"\u8de8\u57df"),(0,r.kt)("p",null,"\u8de8\u57df\u8d44\u6e90\u5171\u4eabCORS\uff08Cross-Origin Resource Sharing\uff09\u662f\u6307\u5141\u8bb8Web\u5e94\u7528\u670d\u52a1\u5668\u8fdb\u884c\u8de8\u57df\u8bbf\u95ee\u63a7\u5236\uff0c\u4ece\u800c\u5b9e\u73b0\u8de8\u57df\u6570\u636e\u5b89\u5168\u4f20\u8f93\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},'higress.io/enable-cors\uff1a"true" or "false"\u3002\u5f00\u542f\u6216\u5173\u95ed\u8de8\u57df\u3002'),(0,r.kt)("li",{parentName:"ul"},"higress.io/cors-allow-origin\uff1a\u5141\u8bb8\u7684\u7b2c\u4e09\u65b9\u7ad9\u70b9\uff0c\u652f\u6301\u6cdb\u57df\u540d\uff0c\u9017\u53f7\u5206\u9694\uff1b\u652f\u6301\u901a\u914d\u7b26",(0,r.kt)("em",{parentName:"li"},"\u3002\u9ed8\u8ba4\u503c\u4e3a"),"\uff0c\u5373\u5141\u8bb8\u6240\u6709\u7b2c\u4e09\u65b9\u7ad9\u70b9\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/cors-allow-methods\uff1a\u5141\u8bb8\u7684\u8bf7\u6c42\u65b9\u6cd5\uff0c\u5982GET\u3001POST\uff0c\u9017\u53f7\u5206\u9694\uff1b\u652f\u6301\u901a\u914d\u7b26*\u3002\u9ed8\u8ba4\u503c\u4e3aGET, PUT, POST, DELETE, PATCH, OPTIONS\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/cors-allow-headers\uff1a\u5141\u8bb8\u7684\u8bf7\u6c42\u5934\u90e8\uff0c\u9017\u53f7\u5206\u9694\uff1b\u652f\u6301\u901a\u914d\u7b26*\u3002\u9ed8\u8ba4\u503c\u4e3aDNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/cors-expose-headers\uff1a\u5141\u8bb8\u7684\u54cd\u5e94\u5934\u90e8\uff0c\u9017\u53f7\u5206\u9694\u3002"),(0,r.kt)("li",{parentName:"ul"},'higress.io/cors-allow-credentials\uff1a"true" or "false"\u3002\u662f\u5426\u5141\u8bb8\u643a\u5e26\u51ed\u8bc1\u4fe1\u606f\u3002\u9ed8\u8ba4\u5141\u8bb8\u3002'),(0,r.kt)("li",{parentName:"ul"},"higress.io/cors-max-age\uff1a\u9884\u68c0\u7ed3\u679c\u7684\u6700\u5927\u7f13\u5b58\u65f6\u95f4\uff0c\u5355\u4f4d\u4e3a\u79d2\uff1b\u9ed8\u8ba4\u503c\u4e3a1728000\u3002")),(0,r.kt)("p",null,"\u8de8\u57df\u8bf7\u6c42\u88ab\u9650\u5236\u4e3a\u53ea\u80fd\u6765\u81eaexample.com\u57df\u7684\u8bf7\u6c42\uff0c\u5e76\u4e14HTTP\u65b9\u6cd5\u53ea\u80fd\u662fGET\u548cPOST\uff0c\u5141\u8bb8\u7684\u8bf7\u6c42\u5934\u90e8\u4e3aX-Foo-Bar\uff0c\u4e0d\u5141\u8bb8\u643a\u5e26\u51ed\u8bc1\u4fe1\u606f\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/enable-cors: "true"\n higress.io/cors-allow-origin: "example.com"\n higress.io/cors-allow-methods: "GET,POST"\n higress.io/cors-allow-headers: "X-Foo-Bar"\n higress.io/cors-allow-credentials: "false"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /hello\n pathType: Exact\n')),(0,r.kt)("h2",{id:"rewrite\u91cd\u5199path\u548chost"},"Rewrite\u91cd\u5199Path\u548cHost"),(0,r.kt)("p",null,"\u5728\u8bf7\u6c42\u8f6c\u53d1\u7ed9\u76ee\u6807\u540e\u7aef\u670d\u52a1\u4e4b\u524d\uff0c\u91cd\u5199\u53ef\u4ee5\u4fee\u6539\u539f\u59cb\u8bf7\u6c42\u7684\u8def\u5f84\uff08Path\uff09\u548c\u4e3b\u673a\u57df\uff08Host)\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/rewrite-target\uff1a\u91cd\u5199Path\uff0c\u652f\u6301\u6355\u83b7\u7ec4\uff08Capture Group)\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/upstream-vhost\uff1a\u91cd\u5199Host\u3002")),(0,r.kt)("h3",{id:"rewrite\u91cd\u5199path"},"Rewrite\u91cd\u5199Path"),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u5c06\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"li"},"example.com/test"),"\u5728\u8f6c\u53d1\u81f3\u540e\u7aef\u670d\u52a1\u4e4b\u524d\uff0c\u91cd\u5199\u4e3a",(0,r.kt)("inlineCode",{parentName:"li"},"example.com/dev"))),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/rewrite-target: "/dev"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u5c06\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"li"},"example.com/v1/app"),"\u5728\u8f6c\u53d1\u81f3\u540e\u7aef\u670d\u52a1\u4e4b\u524d\uff0c\u53bb\u6389Path\u524d\u7f00/v1")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/rewrite-target: "/$2"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /v1(/|$)(.*)\n pathType: ImplementationSpecific\n')),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"\u5c06\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"li"},"example.com/v1/app"),"\u5728\u8f6c\u53d1\u81f3\u540e\u7aef\u670d\u52a1\u4e4b\u524d\uff0c\u5c06Path\u524d\u7f00/v1\u66f4\u6539\u4e3a/v2")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/rewrite-target: "/v2/$2"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /v1(/|$)(.*)\n pathType: ImplementationSpecific\n')),(0,r.kt)("h3",{id:"rewrite\u91cd\u5199host"},"Rewrite\u91cd\u5199Host"),(0,r.kt)("p",null,"\u5c06\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"p"},"example.com/test"),"\u5728\u8f6c\u53d1\u81f3\u540e\u7aef\u670d\u52a1\u4e4b\u524d\uff0c\u91cd\u5199\u4e3a",(0,r.kt)("inlineCode",{parentName:"p"},"test.com/test")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/upstream-vhost: "test.com"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"\u91cd\u5b9a\u5411"},"\u91cd\u5b9a\u5411"),(0,r.kt)("p",null,"\u901a\u8fc7\u91cd\u5b9a\u5411\u53ef\u4ee5\u5c06\u539f\u59cb\u5ba2\u6237\u7aef\u8bf7\u6c42\u66f4\u6539\u4e3a\u76ee\u6807\u8bf7\u6c42\u3002"),(0,r.kt)("h3",{id:"\u914d\u7f6ehttp\u91cd\u5b9a\u5411\u81f3https"},"\u914d\u7f6eHTTP\u91cd\u5b9a\u5411\u81f3HTTPS"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/ssl-redirect\uff1aHTTP\u91cd\u5b9a\u5411\u5230HTTPS"),(0,r.kt)("li",{parentName:"ul"},"higress.io/force-ssl-redirect: HTTP\u91cd\u5b9a\u5411\u5230HTTPS",(0,r.kt)("blockquote",{parentName:"li"},(0,r.kt)("p",{parentName:"blockquote"},"\u8bf4\u660e\uff1aHigress\u5bf9\u4e8e\u4ee5\u4e0a\u4e24\u4e2a\u6ce8\u89e3\u4e0d\u533a\u5206\u5bf9\u5f85\uff0c\u90fd\u662f\u5f3a\u5236\u5c06HTTP\u91cd\u5b9a\u5411\u5230HTTPS\u3002")))),(0,r.kt)("p",null,"\u5c06\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"p"},"http://example.com/test"),"\u91cd\u5b9a\u5411\u4e3a",(0,r.kt)("inlineCode",{parentName:"p"},"https://example.com/test"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/ssl-redirect: "true"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h3",{id:"\u6c38\u4e45\u91cd\u5b9a\u5411"},"\u6c38\u4e45\u91cd\u5b9a\u5411"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/permanent-redirect\uff1a\u6c38\u4e45\u91cd\u5b9a\u5411\u7684\u76ee\u6807url\uff0c\u5fc5\u987b\u5305\u542bscheme\uff08http or https)\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/permanent-redirect-code\uff1a\u6c38\u4e45\u91cd\u5b9a\u5411\u7684HTTP\u72b6\u6001\u7801\uff0c\u9ed8\u8ba4\u4e3a301\u3002")),(0,r.kt)("p",null,"\u5c06\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"p"},"http://example.com/test"),"\u6c38\u4e45\u91cd\u5b9a\u5411\u4e3a",(0,r.kt)("inlineCode",{parentName:"p"},"http://example.com/app"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/permanent-redirect: "http://example.com/app"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h3",{id:"\u4e34\u65f6\u91cd\u5b9a\u5411"},"\u4e34\u65f6\u91cd\u5b9a\u5411"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/temporal-redirect\uff1a\u4e34\u65f6\u91cd\u5b9a\u5411\u7684\u76ee\u6807url\uff0c\u5fc5\u987b\u5305\u542bscheme\uff08http or https)\u3002")),(0,r.kt)("p",null,"\u5c06\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"p"},"http://example.com/test"),"\u4e34\u65f6\u91cd\u5b9a\u5411\u4e3a",(0,r.kt)("inlineCode",{parentName:"p"},"http://example.com/app"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/temporal-redirect: "http://example.com/app"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"header\u63a7\u5236"},"Header\u63a7\u5236"),(0,r.kt)("p",null,"\u901a\u8fc7Header\u63a7\u5236\uff0c\u60a8\u53ef\u4ee5\u5728\u8f6c\u53d1\u8bf7\u6c42\u5230\u540e\u7aef\u670d\u52a1\u4e4b\u524d\u5bf9\u8bf7\u6c42Header\u8fdb\u884c\u589e\u5220\u6539\uff0c\u5728\u6536\u5230\u54cd\u5e94\u8f6c\u53d1\u7ed9\u5ba2\u6237\u7aef\u65f6\u5bf9\u54cd\u5e94Header\u8fdb\u884c\u589e\u5220\u6539\u3002"),(0,r.kt)("h3",{id:"\u8bf7\u6c42header\u63a7\u5236"},"\u8bf7\u6c42Header\u63a7\u5236"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/request-header-control-add\uff1a\u8bf7\u6c42\u5728\u8f6c\u53d1\u7ed9\u540e\u7aef\u670d\u52a1\u65f6\uff0c\u6dfb\u52a0\u6307\u5b9aHeader\u3002\u82e5\u8be5Header\u5b58\u5728\uff0c\u5219\u5176\u503c\u62fc\u63a5\u5728\u539f\u6709\u503c\u540e\u9762\u3002\u8bed\u6cd5\u5982\u4e0b\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u5355\u4e2aHeader\uff1aKey Value"),(0,r.kt)("li",{parentName:"ul"},"\u591a\u4e2aHeader\uff1a\u4f7f\u7528yaml\u7279\u6b8a\u7b26\u53f7 |\uff0c\u6bcf\u5bf9Key Value\u5355\u72ec\u5904\u4e8e\u4e00\u884c"))),(0,r.kt)("li",{parentName:"ul"},"higress.io/request-header-control-update\uff1a\u8bf7\u6c42\u5728\u8f6c\u53d1\u7ed9\u540e\u7aef\u670d\u52a1\u65f6\uff0c\u4fee\u6539\u6307\u5b9aHeader\u3002\u82e5\u8be5header\u5b58\u5728\uff0c\u5219\u5176\u503c\u8986\u76d6\u539f\u6709\u503c\u3002\u8bed\u6cd5\u5982\u4e0b\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u5355\u4e2aHeader\uff1aKey Value"),(0,r.kt)("li",{parentName:"ul"},"\u591a\u4e2aHeader\uff1a\u4f7f\u7528yaml\u7279\u6b8a\u7b26\u53f7 |\uff0c\u6bcf\u5bf9Key Value\u5355\u72ec\u5904\u4e8e\u4e00\u884c"))),(0,r.kt)("li",{parentName:"ul"},"higress.io/request-header-control-remove\uff1a\u8bf7\u6c42\u5728\u8f6c\u53d1\u7ed9\u540e\u7aef\u670d\u52a1\u65f6\uff0c\u5220\u9664\u6307\u5b9aHeader\u3002\u8bed\u6cd5\u5982\u4e0b\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u5355\u4e2aHeader\uff1aKey"),(0,r.kt)("li",{parentName:"ul"},"\u591a\u4e2aHeader\uff1a\u9017\u53f7\u5206\u9694")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u5bf9\u4e8e\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"li"},"example.com/test"),"\u6dfb\u52a0\u4e24\u4e2aHeader\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"foo: bar"),"\u548c",(0,r.kt)("inlineCode",{parentName:"li"},"test: true"),"\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/request-header-control-add: |\n foo bar\n test true\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n")),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"Header\u63a7\u5236\u53ef\u4ee5\u7ed3\u5408\u7070\u5ea6\u53d1\u5e03\uff0c\u5bf9\u7070\u5ea6\u6d41\u91cf\u8fdb\u884c\u67d3\u8272\u3002\u8bf7\u6c42Header\u4e3a",(0,r.kt)("inlineCode",{parentName:"li"},"higress\uff1av1"),"\u65f6\u5c06\u8bbf\u95ee\u7070\u5ea6\u670d\u52a1demo-service-canary-v1\uff0c\u5e76\u6dfb\u52a0Header\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"stage: gray"),"\uff1b\u5176\u4ed6\u60c5\u51b5\u5c06\u8bbf\u95ee\u6b63\u5f0f\u670d\u52a1demo-service\uff0c\u5e76\u6dfb\u52a0Header\uff0c",(0,r.kt)("inlineCode",{parentName:"li"},"stage: production"),"\u3002\u914d\u7f6e\u5982\u4e0b\uff1a")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/canary: "true"\n higress.io/canary-by-header: "higress"\n higress.io/canary-by-header-value: "v1"\n higress.io/request-header-control-add: "stage gray"\n name: demo-canary-v1\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service-canary-v1\n port: \n number: 80\n path: /hello\n pathType: Exact\n---\napiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/request-header-control-add: "stage production"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /hello\n pathType: Exact\n')),(0,r.kt)("h3",{id:"\u54cd\u5e94header\u63a7\u5236"},"\u54cd\u5e94Header\u63a7\u5236"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/response-header-control-add\uff1a\u8bf7\u6c42\u5728\u6536\u5230\u540e\u7aef\u670d\u52a1\u54cd\u5e94\u4e4b\u540e\u5e76\u4e14\u8f6c\u53d1\u54cd\u5e94\u7ed9\u5ba2\u6237\u7aef\u4e4b\u524d\uff0c\u6dfb\u52a0\u6307\u5b9aHeader\u3002\u82e5\u8be5Header\u5b58\u5728\uff0c\u5219\u5176\u503c\u62fc\u63a5\u5728\u539f\u6709\u503c\u540e\u9762\u3002\u8bed\u6cd5\u5982\u4e0b\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u5355\u4e2aHeader\uff1aKey Value"),(0,r.kt)("li",{parentName:"ul"},"\u591a\u4e2aHeader\uff1a\u4f7f\u7528yaml\u7279\u6b8a\u7b26\u53f7 |\uff0c\u6bcf\u5bf9Key Value\u5355\u72ec\u5904\u4e8e\u4e00\u884c"))),(0,r.kt)("li",{parentName:"ul"},"higress.io/response-header-control-update\uff1a\u8bf7\u6c42\u5728\u6536\u5230\u540e\u7aef\u670d\u52a1\u54cd\u5e94\u4e4b\u540e\u5e76\u4e14\u8f6c\u53d1\u54cd\u5e94\u7ed9\u5ba2\u6237\u7aef\u4e4b\u524d\uff0c\u4fee\u6539\u6307\u5b9aHeader\u3002\u82e5\u8be5header\u5b58\u5728\uff0c\u5219\u5176\u503c\u8986\u76d6\u539f\u6709\u503c\u3002\u8bed\u6cd5\u5982\u4e0b\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u5355\u4e2aHeader\uff1aKey Value"),(0,r.kt)("li",{parentName:"ul"},"\u591a\u4e2aHeader\uff1a\u4f7f\u7528yaml\u7279\u6b8a\u7b26\u53f7 |\uff0c\u6bcf\u5bf9Key Value\u5355\u72ec\u5904\u4e8e\u4e00\u884c"))),(0,r.kt)("li",{parentName:"ul"},"higress.io/response-header-control-remove\uff1a\u8bf7\u6c42\u5728\u6536\u5230\u540e\u7aef\u670d\u52a1\u54cd\u5e94\u4e4b\u540e\u5e76\u4e14\u8f6c\u53d1\u54cd\u5e94\u7ed9\u5ba2\u6237\u7aef\u4e4b\u524d\uff0c\u5220\u9664\u6307\u5b9aHeader\u3002\u8bed\u6cd5\u5982\u4e0b\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u5355\u4e2aHeader\uff1aKey"),(0,r.kt)("li",{parentName:"ul"},"\u591a\u4e2aHeader\uff1a\u9017\u53f7\u5206\u9694")))),(0,r.kt)("p",null,"\u5bf9\u4e8e\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"p"},"example.com/test"),"\u7684\u54cd\u5e94\u5220\u9664",(0,r.kt)("inlineCode",{parentName:"p"},"Header\uff1areq-cost-time"),"\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/response-header-control-remove: "req-cost-time"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"\u91cd\u8bd5"},"\u91cd\u8bd5"),(0,r.kt)("p",null,"Higress\u63d0\u4f9b\u8def\u7531\u7ea7\u522b\u7684\u91cd\u8bd5\u8bbe\u7f6e\uff0c\u53ef\u4ee5\u4e3a\u51fa\u9519\u7684\u8bf7\u6c42\u8c03\u7528\u81ea\u52a8\u8fdb\u884c\u91cd\u8bd5\u3002\u60a8\u53ef\u4ee5\u6309\u9700\u8bbe\u7f6e\u91cd\u8bd5\u6761\u4ef6\uff0c\u4f8b\u5982\u5efa\u7acb\u8fde\u63a5\u5931\u8d25\uff0c\u6216\u8005\u540e\u7aef\u670d\u52a1\u4e0d\u53ef\u7528\u4ee5\u53ca\u5bf9\u6307\u5b9aHTTP\u72b6\u6001\u7801\u7684\u54cd\u5e94\u7b49\u8fdb\u884c\u8bf7\u6c42\u91cd\u8bd5\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/proxy-next-upstream-tries\uff1a\u8bf7\u6c42\u7684\u6700\u5927\u91cd\u8bd5\u6b21\u6570\u3002\u9ed8\u8ba43\u6b21\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/proxy-next-upstream-timeout\uff1a\u8bf7\u6c42\u91cd\u8bd5\u7684\u8d85\u65f6\u65f6\u95f4\uff0c\u5355\u4f4d\u79d2\u3002\u9ed8\u8ba4\u672a\u914d\u7f6e\u8d85\u65f6\u65f6\u95f4\u3002"),(0,r.kt)("li",{parentName:"ul"},'higress.io/proxy-next-upstream\uff1a\u8bf7\u6c42\u91cd\u8bd5\u6761\u4ef6\uff0c\u9017\u53f7\u5206\u9694\uff1b\u9ed8\u8ba4\u503c\u4e3a"error,timeout"\u3002\u5408\u6cd5\u503c\u5982\u4e0b\uff1a',(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"error\uff1a\u5efa\u7acb\u8fde\u63a5\u5931\u8d25\uff0c\u8bf7\u6c42\u51fa\u95195xx\u3002"),(0,r.kt)("li",{parentName:"ul"},"timeout\uff1a\u5efa\u7acb\u8fde\u63a5\u8d85\u65f6\uff0c\u8bf7\u6c42\u51fa\u95195xx\u3002"),(0,r.kt)("li",{parentName:"ul"},"invalid_header\uff1a\u8bf7\u6c42\u51fa\u95195xx\u3002"),(0,r.kt)("li",{parentName:"ul"},"http_xxx\uff1a\u9488\u5bf9\u5177\u4f53\u54cd\u5e94\u72b6\u6001\u7801\u7684\u60c5\u51b5\u8fdb\u884c\u91cd\u8bd5\u3002\u4f8b\u5982http_502\uff0chttp_403\u3002"),(0,r.kt)("li",{parentName:"ul"},"non_idempotent\uff1a\u5bf9\u4e8e\u975e\u5e42\u7b49\u8bf7\u6c42\u51fa\u9519\u65f6\u8fdb\u884c\u91cd\u8bd5\u3002\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cHigress\u9488\u5bf9\u975e\u5e42\u7b49POST\u3001PATCH\u8bf7\u6c42\u51fa\u9519\u65f6\u4e0d\u4f1a\u8fdb\u884c\u91cd\u8bd5\uff0c\u914d\u7f6enon_idempotent\u53ef\u4ee5\u5f00\u542f\u91cd\u8bd5\u3002"),(0,r.kt)("li",{parentName:"ul"},"off\uff1a\u5173\u95ed\u91cd\u8bd5\u3002")))),(0,r.kt)("p",null,"\u8bbe\u7f6e",(0,r.kt)("inlineCode",{parentName:"p"},"example/test"),"\u8bf7\u6c42\u7684\u6700\u5927\u91cd\u8bd5\u6b21\u6570\u4e3a2\uff0c\u91cd\u8bd5\u8d85\u65f6\u65f6\u95f4\u4e3a5s\uff0c\u53ea\u6709\u5728\u54cd\u5e94\u72b6\u6001\u7801\u4e3a502\u624d\u91cd\u8bd5\uff0c\u5e76\u4e14\u5f00\u542f\u975e\u5e42\u7b49\u91cd\u8bd5\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/proxy-next-upstream-tries: "2"\n higress.io/proxy-next-upstream-timeout: "5"\n higress.io/proxy-next-upstream: "http_502,non_idempotent"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"\u8d85\u65f6"},"\u8d85\u65f6"),(0,r.kt)("p",null,"Higress\u63d0\u4f9b\u8def\u7531\u7ea7\u522b\u7684\u8d85\u65f6\u8bbe\u7f6e\uff0c\u4e0enginx ingress\u4e0d\u540c\uff0c\u6ca1\u6709\u533a\u5206\u8fde\u63a5/\u8bfb\u5199\u8d85\u65f6\uff0c\u800c\u662f\u9762\u5411\u7684\u63a5\u53e3\u5904\u7406\u603b\u5ef6\u65f6\u8fdb\u884c\u914d\u7f6e\uff0c\u5728\u672a\u8fdb\u884c\u914d\u7f6e\u65f6\u9ed8\u8ba4\u4e0d\u9650\u5236\uff0c\u4f8b\u5982\u540e\u7aef\u672a\u8fd4\u56de\u5e94\u7b54\uff0c\u7f51\u5173\u5c06\u65e0\u9650\u7b49\u5f85\u3002"),(0,r.kt)("p",null,"\u8bbe\u7f6e\u8d85\u65f6\u65f6\u95f4\u4e3a5s\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n mse.ingress.kubernetes.io/timeout: "5"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"\u5355\u673a\u9650\u6d41"},"\u5355\u673a\u9650\u6d41"),(0,r.kt)("p",null,"\u652f\u6301\u9488\u5bf9\u8def\u7531\u7ea7\u522b\u7684\u5355\u673a\u9650\u6d41\u7b56\u7565\uff0c\u5728\u8bbe\u5b9a\u7684\u65f6\u95f4\u5468\u671f\u5185\uff0c\u9650\u5236\u6bcf\u4e2a\u7f51\u5173\u526f\u672c\u5339\u914d\u5728\u67d0\u4e2a\u8def\u7531\u4e0a\u7684\u8bf7\u6c42\u6570\u91cf\u4e0d\u5927\u4e8e\u9608\u503c\u3002\u8be5\u9650\u6d41\u662f\u9488\u5bf9\u5355\u673a\u7ea7\u522b\uff0c\u5373\u914d\u7f6e\u7684\u9608\u503c\u5728\u6bcf\u4e2a\u7f51\u5173\u5b9e\u4f8b\u8fdb\u884c\u6d41\u63a7\u3002"),(0,r.kt)("p",null,(0,r.kt)("strong",{parentName:"p"},"\u63d0\u793a"),"\nHigress\u5546\u4e1a\u7248\u5177\u5907\u5168\u5c40\u9650\u6d41\u80fd\u529b\uff0c\u8be6\u60c5\u67e5\u770b",(0,r.kt)("a",{parentName:"p",href:"https://help.aliyun.com/zh/mse/user-guide/advanced-usage-of-mse-ingress?spm=a2c4g.11186623.0.0.2e3a3db3eYcspD#862f08d03d4d3"},"\u5546\u4e1a\u7248\u6587\u6863"),"\u4e2d\u5168\u5c40\u9650\u6d41\u4e00\u8282\u7684\u4ecb\u7ecd"),(0,r.kt)("p",null,"\u4f8b\u5982\uff1a"),(0,r.kt)("p",null,"\u9650\u5236example.com/test\u7684\u8bf7\u6c42\u6bcf\u5206\u949f\u6700\u5927\u8bf7\u6c42\u6570\u4e3a100\uff0c\u77ac\u65f6\u8bf7\u6c42\u6570200\u3002\u914d\u7f6e\u5982\u4e0b\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n mse.ingress.kubernetes.io/route-limit-rpm: "100"\n mse.ingress.kubernetes.io/route-limit-burst-multiplier: "2"\n name: demo\nspec:\n ingressClassName: mse\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("p",null,"\u9650\u5236example.com/test\u7684\u8bf7\u6c42\u6bcf\u79d2\u6700\u5927\u8bf7\u6c42\u6570\u4e3a10\uff0c\u77ac\u65f6\u8bf7\u6c42\u657050\u3002\u914d\u7f6e\u5982\u4e0b\uff1a"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n mse.ingress.kubernetes.io/route-limit-rps: "10"\n # \u9ed8\u8ba4\u4e3a5\n # mse.ingress.kubernetes.io/route-limit-burst-multiplier: "5"\n name: demo\nspec:\n ingressClassName: mse\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u534f\u8baehttps\u6216grpc"},"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u534f\u8bae\uff1aHTTPS\u6216GRPC"),(0,r.kt)("p",null,"Higress\u9ed8\u8ba4\u4f7f\u7528HTTP\u534f\u8bae\u8f6c\u53d1\u8bf7\u6c42\u5230\u540e\u7aef\u4e1a\u52a1\u5bb9\u5668\u3002\u5f53\u60a8\u7684\u4e1a\u52a1\u5bb9\u5668\u4e3aHTTPS\u534f\u8bae\u65f6\uff0c\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528\u6ce8\u89e3",(0,r.kt)("inlineCode",{parentName:"p"},'higress.io/backend-protocol: "HTTPS"'),"\uff1b\u5f53\u60a8\u7684\u4e1a\u52a1\u5bb9\u5668\u4e3aGRPC\u670d\u52a1\u65f6\uff0c\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528\u6ce8\u89e3",(0,r.kt)("inlineCode",{parentName:"p"},'higress.io/backend-protocol: "GRPC"'),"\u3002"),(0,r.kt)("blockquote",null,(0,r.kt)("p",{parentName:"blockquote"},'\u8bf4\u660e\uff1a\u76f8\u6bd4Nginx Ingress\u7684\u4f18\u52bf\uff0c\u5982\u679c\u60a8\u7684\u540e\u7aef\u670d\u52a1\u6240\u5c5e\u7684K8s Service\u8d44\u6e90\u4e2d\u5173\u4e8ePort Name\u7684\u5b9a\u4e49\u4e3agrpc\u6216http2\uff0c\u60a8\u65e0\u9700\u914d\u7f6e\u6ce8\u89e3higress.io/backend-protocol: "GRPC"\uff0cHigress\u4f1a\u81ea\u52a8\u4f7f\u7528GRPC\u6216\u8005HTTP2\u3002')),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"li"},"example/test"),"\u8f6c\u53d1\u81f3\u540e\u7aef\u670d\u52a1\u4f7f\u7528HTTPS\u534f\u8bae\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/backend-protocol: "HTTPS"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /\n pathType: Exact\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u8bf7\u6c42",(0,r.kt)("inlineCode",{parentName:"li"},"example/test"),"\u8f6c\u53d1\u81f3\u540e\u7aef\u670d\u52a1\u4f7f\u7528GRPC\u534f\u8bae\u3002\n\u7b2c\u4e00\u79cd\u505a\u6cd5\uff1a\u901a\u8fc7\u6ce8\u89e3\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/backend-protocol: "GRPC"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("p",null,"\u7b2c\u4e8c\u79cd\u505a\u6cd5\uff1a\u901a\u8fc7Service Port Name"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},"apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /order\n pathType: Exact\n---\napiVersion: v1\nkind: Service\nmetadata:\n name: demo-service\nspec:\n ports:\n - name: grpc\n port: 80\n protocol: TCP\n selector:\n app: demo-service\n")),(0,r.kt)("h2",{id:"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5"},"\u914d\u7f6e\u540e\u7aef\u670d\u52a1\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5"),(0,r.kt)("p",null,"\u8d1f\u8f7d\u5747\u8861\u51b3\u5b9a\u7740\u7f51\u5173\u5728\u8f6c\u53d1\u8bf7\u6c42\u81f3\u540e\u7aef\u670d\u52a1\u65f6\u5982\u4f55\u9009\u62e9\u8282\u70b9\u3002"),(0,r.kt)("h3",{id:"\u666e\u901a\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5"},"\u666e\u901a\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/load-balance\uff1a\u540e\u7aef\u670d\u52a1\u7684\u666e\u901a\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5\u3002\u9ed8\u8ba4\u4e3around_robin\u3002\u5408\u6cd5\u503c\u5982\u4e0b\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"round_robin\uff1a\u57fa\u4e8e\u8f6e\u8be2\u7684\u8d1f\u8f7d\u5747\u8861\u3002"),(0,r.kt)("li",{parentName:"ul"},"least_conn\uff1a\u57fa\u4e8e\u6700\u5c0f\u8bf7\u6c42\u6570\u7684\u8d1f\u8f7d\u5747\u8861\u3002"),(0,r.kt)("li",{parentName:"ul"},"random\uff1a\u57fa\u4e8e\u968f\u673a\u7684\u8d1f\u8f7d\u5747\u8861\u3002")))),(0,r.kt)("p",null,"\u8bbe\u7f6e\u540e\u7aef\u670d\u52a1demo-service\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5\u4e3aleast_conn\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/load-balance: "least_conn"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /order\n pathType: Exact\n')),(0,r.kt)("h3",{id:"\u57fa\u4e8e\u4e00\u81f4\u6027hash\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5"},"\u57fa\u4e8e\u4e00\u81f4\u6027Hash\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5"),(0,r.kt)("p",null,"\u57fa\u4e8e\u4e00\u81f4\u6027Hash\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5\u5177\u5907\u8bf7\u6c42\u4eb2\u548c\u6027\uff0c\u5177\u6709\u76f8\u540c\u7279\u5f81\u7684\u8bf7\u6c42\u4f1a\u59cb\u7ec8\u8d1f\u8f7d\u5230\u76f8\u540c\u8282\u70b9\u4e0a\u3002Higress\u652f\u6301\u57fa\u4e8e\u90e8\u5206Nginx \u53d8\u91cf\u3001\u8bf7\u6c42Header\u548c\u8bf7\u6c42\u8def\u5f84\u53c2\u6570\u4f5c\u4e3aHash Key\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/upstream-hash-by\uff1a\u57fa\u4e8e\u4e00\u81f4Hash\u7684\u8d1f\u8f7d\u5747\u8861\u7b97\u6cd5\u3002Higress\u652f\u6301\u4ee5\u4e0b\u51e0\u79cd\u5f62\u5f0f\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"\u652f\u6301\u914d\u7f6e\u90e8\u5206nginx\u53d8\u91cf\uff1a",(0,r.kt)("ul",{parentName:"li"},(0,r.kt)("li",{parentName:"ul"},"$request_uri\uff1a\u8bf7\u6c42\u7684Path\uff08\u5305\u62ec\u8def\u5f84\u53c2\u6570\uff09\u4f5c\u4e3aHash Key"),(0,r.kt)("li",{parentName:"ul"},"$host\uff1a\u8bf7\u6c42\u7684Host\u4f5c\u4e3aHash Key"),(0,r.kt)("li",{parentName:"ul"},"$remote_addr\uff1a\u8bf7\u6c42\u7684\u5ba2\u6237\u7aefIP\u4f5c\u4e3aHash Key"))),(0,r.kt)("li",{parentName:"ul"},"\u57fa\u4e8e\u8bf7\u6c42header\u7684\u4e00\u81f4\u6027Hash\u3002\u60a8\u53ea\u9700\u914d\u7f6e\u4e3a$http_headerName\u3002"),(0,r.kt)("li",{parentName:"ul"},"\u57fa\u4e8e\u8bf7\u6c42\u8def\u5f84\u53c2\u6570\u7684\u4e00\u81f4\u6027Hash\u3002\u60a8\u53ea\u9700\u914d\u7f6e\u4e3a$arg_varName\u3002")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u57fa\u4e8e\u8bf7\u6c42\u7684\u5ba2\u6237\u7aefIP\u4f5c\u4e3aHash Key\uff0c\u540c\u4e00\u4e2a\u5ba2\u6237\u7aefIP\u7684\u8bf7\u6c42\u59cb\u7ec8\u8d1f\u8f7d\u5230\u540c\u4e00\u4e2a\u8282\u70b9\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/upstream-hash-by: "$remote_addr"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u57fa\u4e8e\u8bf7\u6c42Header x-stage\u4f5c\u4e3aHash key\uff0c\u5e26\u6709x-stage\u5934\u90e8\u7684\u8bf7\u6c42\u4e14\u503c\u76f8\u540c\u7684\u8bf7\u6c42\u59cb\u7ec8\u8d1f\u8f7d\u5230\u540c\u4e00\u4e2a\u8282\u70b9\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/upstream-hash-by: "$http_x-stage"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("ol",{start:3},(0,r.kt)("li",{parentName:"ol"},"\u57fa\u4e8e\u8bf7\u6c42\u8def\u5f84\u53c2\u6570 x-stage\u4f5c\u4e3aHash key\uff0c\u5e26\u6709\u8def\u5f84\u53c2\u6570x-stage\u7684\u8bf7\u6c42\u4e14\u503c\u76f8\u540c\u7684\u8bf7\u6c42\u59cb\u7ec8\u8d1f\u8f7d\u5230\u540c\u4e00\u4e2a\u8282\u70b9\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/upstream-hash-by: "$arg_x-stage"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"cookie\u4eb2\u548c\u6027-\u4f1a\u8bdd\u4fdd\u6301"},"Cookie\u4eb2\u548c\u6027 \uff08\u4f1a\u8bdd\u4fdd\u6301\uff09"),(0,r.kt)("p",null,"\u5177\u5907\u76f8\u540c\u7684Cookie\u7684\u8bf7\u6c42\u4f1a\u88ab\u7f51\u5173\u59cb\u7ec8\u8d1f\u8f7d\u5230\u540c\u4e00\u4e2a\u8282\u70b9\uff0c\u5e76\u4e14\u5982\u679c\u7b2c\u4e00\u6b21\u8bbf\u95ee\u643a\u5e26Cookie\uff0cHigress\u4f1a\u5728\u7b2c\u4e00\u6b21\u54cd\u5e94\u65f6\u4e3a\u5ba2\u6237\u7aef\u751f\u6210\u4e00\u4e2aCookie\uff0c\u7528\u6765\u4fdd\u8bc1\u540e\u7eed\u7684\u8bf7\u6c42\u88ab\u7f51\u5173\u59cb\u7ec8\u8d1f\u8f7d\u5230\u76f8\u540c\u8282\u70b9\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/affinity\uff1a\u4eb2\u548c\u6027\u79cd\u7c7b\uff0c\u76ee\u524d\u53ea\u652f\u6301cookie\uff0c\u9ed8\u8ba4\u4e3acookie\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/affinity-mode\uff1a\u4eb2\u548c\u6027\u6a21\u5f0f\uff0cHigress\u76ee\u524d\u53ea\u652f\u6301balanced\u6a21\u5f0f\uff0c\u9ed8\u8ba4\u4e3abalanced\u6a21\u5f0f\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/session-cookie-name\uff1a\u914d\u7f6e\u6307\u5b9aCookie\u7684\u503c\u4f5c\u4e3aHash Key\uff0c\u9ed8\u8ba4\u4e3aINGRESSCOOKIE"),(0,r.kt)("li",{parentName:"ul"},"higress.io/session-cookie-path\uff1a\u5f53\u6307\u5b9aCookie\u4e0d\u5b58\u5728\uff0c\u751f\u6210\u7684Cookie\u7684Path\u503c\uff0c\u9ed8\u8ba4\u4e3a/"),(0,r.kt)("li",{parentName:"ul"},"higress.io/session-cookie-max-age\uff1a\u5f53\u6307\u5b9aCookie\u4e0d\u5b58\u5728\uff0c\u751f\u6210\u7684Cookie\u7684\u8fc7\u671f\u65f6\u95f4\uff0c\u5355\u4f4d\u4e3a\u79d2\uff0c\u9ed8\u8ba4\u4e3aSession\u4f1a\u8bdd\u7ea7\u522b\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/session-cookie-expires\uff1a\u5f53\u6307\u5b9aCookie\u4e0d\u5b58\u5728\uff0c\u751f\u6210\u7684Cookie\u7684\u8fc7\u671f\u65f6\u95f4\uff0c\u5355\u4f4d\u4e3a\u79d2\uff0c\u9ed8\u8ba4\u4e3aSession\u4f1a\u8bdd\u7ea7\u522b\u3002",(0,r.kt)("blockquote",{parentName:"li"},(0,r.kt)("p",{parentName:"blockquote"},"\u8bf4\u660e\uff1amax-age\u548cexpires\u90fd\u53ef\u4ee5\u7528\u6765\u6307\u5b9acookie\u8fc7\u671f\u65f6\u95f4\u3002\u5f53session-cookie-max-age\u548csession-cookie-expires\u540c\u65f6\u914d\u7f6e\u65f6\uff0cHigress\u4f18\u5148\u9009\u53d6session-cookie-max-age\u4f5c\u4e3a\u8fc7\u671f\u65f6\u95f4\u3002")))),(0,r.kt)("ol",null,(0,r.kt)("li",{parentName:"ol"},"\u5f00\u542fCookie\u4eb2\u548c\u6027\uff0c\u5229\u7528Higress\u7684\u9ed8\u8ba4\u914d\u7f6e\uff0c\u5373Cookie\u7684\u540d\u5b57\u4e3aINGRESSCOOKIE\uff0cPath\u4e3a/\uff0cCookie\u7684\u751f\u547d\u5468\u671f\u4e3aSession\u4f1a\u8bdd\u7ea7\u522b\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/affinity: "cookie"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("ol",{start:2},(0,r.kt)("li",{parentName:"ol"},"\u5f00\u542fCookie\u4eb2\u548c\u6027\uff0cCookie\u7684\u540d\u5b57\u4e3atest\uff0cPath\u4e3a/\uff0cCookie\u7684\u8fc7\u671f\u65f6\u95f4\u4e3a10s\u3002")),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/affinity: "cookie"\n higress.io/session-cookie-name: "test"\n higress.io/session-cookie-max-age: "10"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')),(0,r.kt)("h2",{id:"\u7f51\u5173\u4e0e\u540e\u7aef\u670d\u52a1\u53cc\u5411\u8ba4\u8bc1mtls"},"\u7f51\u5173\u4e0e\u540e\u7aef\u670d\u52a1\u53cc\u5411\u8ba4\u8bc1\uff08MTLS)"),(0,r.kt)("p",null,"\u9ed8\u8ba4\u60c5\u51b5\u4e0b\uff0cHigress\u9ed8\u8ba4\u4f7f\u7528HTTP\u534f\u8bae\u8f6c\u53d1\u8bf7\u6c42\u5230\u540e\u7aef\u4e1a\u52a1\u5bb9\u5668\u3002\u4f60\u53ef\u4ee5\u901a\u8fc7\u4f7f\u7528\u6ce8\u89e3",(0,r.kt)("inlineCode",{parentName:"p"},'higress.io/backend-protocol: "HTTPS"'),"\u914d\u7f6eHigress\u8bbf\u95ee\u540e\u7aef\u670d\u52a1\u4f7f\u7528HTTPS\u534f\u8bae\uff0c\u4f46\u8fd9\u662f\u5355\u5411TLS\uff0c\u4e5f\u5c31\u662f\u8bf4\u53ea\u6709Higress\u4f1a\u9a8c\u8bc1\u540e\u7aef\u670d\u52a1\u63d0\u4f9b\u7684\u8bc1\u4e66\uff0c\u4e14\u4e00\u822c\u540e\u7aef\u670d\u52a1\u4f7f\u7528\u7684\u8bc1\u4e66\u9700\u8981\u662f\u6743\u5a01CA\u7b7e\u53d1\u7684\u3002\u53e6\u4e00\u79cd\u66f4\u5b89\u5168\u7684\u6a21\u5f0f\u662f\u96f6\u4fe1\u4efb\uff0c\u7f51\u5173\u4f1a\u9a8c\u8bc1\u540e\u7aef\u670d\u52a1\u7684\u8bc1\u4e66\u662f\u5426\u5408\u6cd5\uff0c\u540c\u6837\u540e\u7aef\u670d\u52a1\u4e5f\u4f1a\u9a8c\u8bc1\u7f51\u5173\u63d0\u4f9b\u7684\u8bc1\u4e66\u662f\u5426\u5408\u6cd5\uff0c\u8fd9\u5c31\u662fMTLS\uff0c\u7f51\u5173\u4e0e\u540e\u7aef\u670d\u52a1\u8fdb\u884c\u53cc\u5411\u8ba4\u8bc1\u3002"),(0,r.kt)("ul",null,(0,r.kt)("li",{parentName:"ul"},"higress.io/proxy-ssl-secret\uff1a\u7f51\u5173\u4f7f\u7528\u7684\u5ba2\u6237\u7aef\u8bc1\u4e66\uff0c\u7528\u4e8e\u540e\u7aef\u670d\u52a1\u5bf9\u7f51\u5173\u8fdb\u884c\u8eab\u4efd\u8ba4\u8bc1\uff0c\u683c\u5f0f\u4e3a secretNamespace/secretName\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/proxy-ssl-name\uff1aTLS\u63e1\u624b\u671f\u95f4\u4f7f\u7528\u7684SNI\u3002"),(0,r.kt)("li",{parentName:"ul"},"higress.io/proxy-ssl-server-name\uff1aon or off\u3002\u5f00\u542f\u6216\u5173\u95edTLS\u63e1\u624b\u671f\u95f4\u4f7f\u7528SNI\u3002")),(0,r.kt)("p",null,"\u7f51\u5173\u4e0e\u540e\u7aef\u670d\u52a1\u8fdb\u884c\u53cc\u5411\u8ba4\u8bc1\uff0c\u7f51\u5173\u4f7f\u7528\u7684secret name\u4e3agateway-cert\uff0c\u547d\u540d\u7a7a\u4e3adefault\u3002"),(0,r.kt)("pre",null,(0,r.kt)("code",{parentName:"pre"},'apiVersion: networking.k8s.io/v1\nkind: Ingress\nmetadata:\n annotations:\n higress.io/proxy-ssl-secret: "default/gateway-cert"\n name: demo\nspec:\n ingressClassName: higress\n rules:\n - host: example.com\n http:\n paths:\n - backend:\n service:\n name: demo-service\n port: \n number: 80\n path: /test\n pathType: Exact\n')))}k.isMDXComponent=!0}}]); \ No newline at end of file diff --git a/zh-cn/assets/js/runtime~main.6f57d93d.js b/zh-cn/assets/js/runtime~main.6f57d93d.js new file mode 100644 index 0000000000..85bc9595ec --- /dev/null +++ b/zh-cn/assets/js/runtime~main.6f57d93d.js @@ -0,0 +1 @@ +(()=>{"use strict";var e,a,f,c,b,d={},t={};function r(e){var a=t[e];if(void 0!==a)return a.exports;var f=t[e]={id:e,loaded:!1,exports:{}};return d[e].call(f.exports,f,f.exports,r),f.loaded=!0,f.exports}r.m=d,r.c=t,e=[],r.O=(a,f,c,b)=>{if(!f){var d=1/0;for(i=0;i=b)&&Object.keys(r.O).every((e=>r.O[e](f[o])))?f.splice(o--,1):(t=!1,b0&&e[i-1][2]>b;i--)e[i]=e[i-1];e[i]=[f,c,b]},r.n=e=>{var a=e&&e.__esModule?()=>e.default:()=>e;return r.d(a,{a:a}),a},f=Object.getPrototypeOf?e=>Object.getPrototypeOf(e):e=>e.__proto__,r.t=function(e,c){if(1&c&&(e=this(e)),8&c)return e;if("object"==typeof e&&e){if(4&c&&e.__esModule)return e;if(16&c&&"function"==typeof e.then)return e}var b=Object.create(null);r.r(b);var d={};a=a||[null,f({}),f([]),f(f)];for(var t=2&c&&e;"object"==typeof t&&!~a.indexOf(t);t=f(t))Object.getOwnPropertyNames(t).forEach((a=>d[a]=()=>e[a]));return d.default=()=>e,r.d(b,d),b},r.d=(e,a)=>{for(var f in a)r.o(a,f)&&!r.o(e,f)&&Object.defineProperty(e,f,{enumerable:!0,get:a[f]})},r.f={},r.e=e=>Promise.all(Object.keys(r.f).reduce(((a,f)=>(r.f[f](e,a),a)),[])),r.u=e=>"assets/js/"+({53:"935f2afb",129:"964c4d56",136:"7893cef3",221:"26b6c8a0",253:"c3dd0c43",286:"b72e39f9",346:"9ca5e7b4",383:"434ebc0e",491:"5b2616d0",518:"f0b1cd8d",571:"5b8e49c8",590:"e6e760b3",799:"2d27d23c",801:"914e0e0b",1136:"1e5fa08a",1138:"60a04ac0",1166:"71f6a83e",1216:"ff24d8fd",1385:"31fc6f0a",1492:"beb5e9ee",1519:"af45db24",1529:"90c9600e",1568:"f9768388",1714:"9fa96955",1963:"846a6f45",2197:"95c943ed",2202:"54c6fa4d",2271:"fdeb5ded",2307:"61d40d5e",2430:"64197243",2477:"242cf7a2",2535:"814f3328",2537:"b47a0778",2595:"ce9873b9",2644:"138fb8a5",2735:"9b526cbd",2856:"86ca9cd8",2972:"3794dc3b",3085:"1f391b9e",3089:"a6aa9e1f",3214:"33ae2ce0",3237:"1df93b7f",3275:"2ec04f43",3455:"48412d63",3575:"da5f7e15",3591:"3d8abcf7",3599:"b8ed6dd3",3608:"9e4087bc",3735:"01f4f75a",3827:"068c09bc",3867:"453b346d",3918:"2aed9a6a",3975:"22d63f54",4081:"1992494a",4404:"a4fca0f6",4449:"16b1ceda",4900:"c6b109aa",5265:"4a1848d2",5286:"a2f06bc9",5292:"c557ece2",5299:"465ed234",5392:"8f4a8f32",5467:"17fbb55d",5550:"0cf6241b",5608:"2457f42e",5638:"3b5399d9",5707:"c8858931",5882:"b91266d6",5930:"d0206f4f",6072:"dc6bf673",6101:"a3e05b61",6103:"ccc49370",6190:"717669cf",6351:"b43c202f",6376:"b4eec107",6573:"4e321780",6604:"6a1ae202",6658:"52aaad9f",6661:"b3c6afee",6670:"e078aa5b",6907:"3408d01b",7215:"84b4ff04",7414:"393be207",7431:"1cfcb182",7720:"b7545eaf",7869:"2b991187",7881:"05d13486",7918:"17896441",7974:"5c8ef13b",8219:"9583d427",8281:"51d4973e",8300:"abf51c76",8313:"23fcf0a9",8520:"1c8d8f73",8685:"8369a6c3",8704:"ba6487cf",8729:"59217617",8786:"a71ccc39",8824:"21aabe8b",8853:"ddfe4b88",9096:"70fd7065",9304:"2a958b3e",9410:"d29b5f9b",9432:"f30c7392",9439:"265f8c6c",9514:"1be78505",9515:"a5313a33",9633:"e8f19204",9659:"6efcbf76",9949:"8784a557"}[e]||e)+"."+{53:"ffe3de9c",129:"6330c66f",136:"4b5d27c3",210:"7b457f2b",221:"eb91d6d3",253:"2aa33628",286:"bc477af8",346:"08008af7",383:"3afd685a",412:"c211d18d",491:"833d27e4",518:"cd117b14",571:"e0e6fbc1",590:"69ecc827",799:"17afcaf8",801:"1a9049d8",1136:"7c2739c7",1138:"bc29ce3c",1166:"5e74d71e",1216:"e6eae75d",1385:"599446cc",1492:"5385e4d3",1519:"a257312f",1529:"b701276e",1568:"8463836b",1714:"d0c57760",1963:"84478395",2197:"872ff7e4",2202:"539edc61",2271:"61f814d8",2307:"2372508e",2430:"51587063",2477:"bf24ab1f",2535:"642c7193",2537:"4d64a103",2595:"afe838fb",2644:"3ce586ea",2735:"9ab9eabb",2856:"092974c3",2972:"e2e2a610",3085:"5dd43995",3089:"04e59258",3214:"b752d51d",3237:"b211faaa",3275:"e1d47470",3455:"cce87dab",3575:"5110d149",3591:"1c0cc073",3599:"5ee80977",3608:"d4b4fa21",3735:"89797dd3",3827:"fd3f5d85",3867:"8d5c1af2",3918:"087b51af",3975:"7f2b3318",4081:"677a2724",4404:"989dec00",4449:"d50bd212",4900:"cf8e9490",4972:"453b6fac",5265:"eb664a72",5286:"64300c73",5292:"46e2f392",5299:"76ea77d4",5392:"879cfc10",5467:"34a18e1a",5550:"73475ef2",5608:"dbbc8fd8",5638:"83ff8dc4",5707:"48a403b2",5882:"eb37d3f2",5930:"bd0f1817",6072:"33f15aa8",6101:"7f6fefeb",6103:"f9d66d0a",6190:"ef5ab0c3",6351:"9e4d32bb",6376:"6ff6cca7",6573:"5dba3b6c",6604:"af192488",6658:"dccc2f79",6661:"585edc2e",6670:"d77456dd",6907:"6a39802e",7215:"5cfd6e33",7414:"83c88e89",7431:"752d3723",7720:"4e6dcaf2",7869:"2fc385cb",7881:"37d0d0c8",7918:"0980fa4a",7974:"31b2a946",8219:"1d850229",8281:"937f21db",8300:"b06224a2",8313:"ace5d499",8520:"33b89740",8685:"0000362c",8704:"51c07f35",8729:"488e5ad4",8786:"227b328f",8824:"51b3f084",8853:"95b9080f",9096:"4f03a2b1",9304:"d807b2d7",9410:"78e0b68b",9432:"d9c9fd79",9439:"2bf55669",9514:"7cc3593d",9515:"bb706933",9633:"4d83e2cb",9659:"0fa0802b",9949:"3b319c80"}[e]+".js",r.miniCssF=e=>{},r.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),r.o=(e,a)=>Object.prototype.hasOwnProperty.call(e,a),c={},b="higress-website:",r.l=(e,a,f,d)=>{if(c[e])c[e].push(a);else{var t,o;if(void 0!==f)for(var n=document.getElementsByTagName("script"),i=0;i{t.onerror=t.onload=null,clearTimeout(l);var b=c[e];if(delete c[e],t.parentNode&&t.parentNode.removeChild(t),b&&b.forEach((e=>e(f))),a)return a(f)},l=setTimeout(s.bind(null,void 0,{type:"timeout",target:t}),12e4);t.onerror=s.bind(null,t.onerror),t.onload=s.bind(null,t.onload),o&&document.head.appendChild(t)}},r.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.p="/zh-cn/",r.gca=function(e){return e={17896441:"7918",59217617:"8729",64197243:"2430","935f2afb":"53","964c4d56":"129","7893cef3":"136","26b6c8a0":"221",c3dd0c43:"253",b72e39f9:"286","9ca5e7b4":"346","434ebc0e":"383","5b2616d0":"491",f0b1cd8d:"518","5b8e49c8":"571",e6e760b3:"590","2d27d23c":"799","914e0e0b":"801","1e5fa08a":"1136","60a04ac0":"1138","71f6a83e":"1166",ff24d8fd:"1216","31fc6f0a":"1385",beb5e9ee:"1492",af45db24:"1519","90c9600e":"1529",f9768388:"1568","9fa96955":"1714","846a6f45":"1963","95c943ed":"2197","54c6fa4d":"2202",fdeb5ded:"2271","61d40d5e":"2307","242cf7a2":"2477","814f3328":"2535",b47a0778:"2537",ce9873b9:"2595","138fb8a5":"2644","9b526cbd":"2735","86ca9cd8":"2856","3794dc3b":"2972","1f391b9e":"3085",a6aa9e1f:"3089","33ae2ce0":"3214","1df93b7f":"3237","2ec04f43":"3275","48412d63":"3455",da5f7e15:"3575","3d8abcf7":"3591",b8ed6dd3:"3599","9e4087bc":"3608","01f4f75a":"3735","068c09bc":"3827","453b346d":"3867","2aed9a6a":"3918","22d63f54":"3975","1992494a":"4081",a4fca0f6:"4404","16b1ceda":"4449",c6b109aa:"4900","4a1848d2":"5265",a2f06bc9:"5286",c557ece2:"5292","465ed234":"5299","8f4a8f32":"5392","17fbb55d":"5467","0cf6241b":"5550","2457f42e":"5608","3b5399d9":"5638",c8858931:"5707",b91266d6:"5882",d0206f4f:"5930",dc6bf673:"6072",a3e05b61:"6101",ccc49370:"6103","717669cf":"6190",b43c202f:"6351",b4eec107:"6376","4e321780":"6573","6a1ae202":"6604","52aaad9f":"6658",b3c6afee:"6661",e078aa5b:"6670","3408d01b":"6907","84b4ff04":"7215","393be207":"7414","1cfcb182":"7431",b7545eaf:"7720","2b991187":"7869","05d13486":"7881","5c8ef13b":"7974","9583d427":"8219","51d4973e":"8281",abf51c76:"8300","23fcf0a9":"8313","1c8d8f73":"8520","8369a6c3":"8685",ba6487cf:"8704",a71ccc39:"8786","21aabe8b":"8824",ddfe4b88:"8853","70fd7065":"9096","2a958b3e":"9304",d29b5f9b:"9410",f30c7392:"9432","265f8c6c":"9439","1be78505":"9514",a5313a33:"9515",e8f19204:"9633","6efcbf76":"9659","8784a557":"9949"}[e]||e,r.p+r.u(e)},(()=>{var e={1303:0,532:0};r.f.j=(a,f)=>{var c=r.o(e,a)?e[a]:void 0;if(0!==c)if(c)f.push(c[2]);else if(/^(1303|532)$/.test(a))e[a]=0;else{var b=new Promise(((f,b)=>c=e[a]=[f,b]));f.push(c[2]=b);var d=r.p+r.u(a),t=new Error;r.l(d,(f=>{if(r.o(e,a)&&(0!==(c=e[a])&&(e[a]=void 0),c)){var b=f&&("load"===f.type?"missing":f.type),d=f&&f.target&&f.target.src;t.message="Loading chunk "+a+" failed.\n("+b+": "+d+")",t.name="ChunkLoadError",t.type=b,t.request=d,c[1](t)}}),"chunk-"+a,a)}},r.O.j=a=>0===e[a];var a=(a,f)=>{var c,b,d=f[0],t=f[1],o=f[2],n=0;if(d.some((a=>0!==e[a]))){for(c in t)r.o(t,c)&&(r.m[c]=t[c]);if(o)var i=o(r)}for(a&&a(f);n - + @@ -22,7 +22,7 @@

    Higress在2023 KubeCon China的分享

    · 阅读需 9 分钟

    分享简介

    在9月26日的2023 KubeCon阿里云云原生开放日,Higress的分享内容分为两部分:

    Part 1. 由上海费芮网络科技系统运维副总监戴喜军,带来费芮在选型企业版Higress作为K8s Ingress替代Nginx Ingress的介绍

    Part 2. 由Higress开源社区负责人澄潭,带来Higress开源项目的介绍

    开源版和企业版是Higress的一体两面,通过本次分享,相信大家会对Higress有更全面的了解。

    Part 1. 费芮互动使用Higress作为Kubernetes Ingress实现稳定性和性能提升

    费芮通过Higress解决了原本Nginx Ingress网关的诸多痛点,性能提升90%,响应时间下降50%,并大幅提升业务入口的稳定及安全性,高效支撑每日1亿+粉丝交互, 4万+线下门店、每月3000万+笔的移动支付需求。

    费芮业务场景

    image image

    费芮专注于移动营销、O2O、社交媒体、移动电商领域的创新与研发。费芮互动自主研发的自媒体平台运维超过2亿粉丝 ; 有超过4万家线下门店采用费芮O2O解决方案。费芮的主要客户包括优衣库,必胜客,肯德基,星巴克,SPG,欧莱雅,Innisfree,迪卡侬,顶新集团等。

    image

    费芮内部业务系统的日均发布次数达到100次之多,会涉及到400多条Ingress路由规则的日常更新,且网关每天需要承载的PV流量达到了1个亿。Ingress网关的性能和稳定性至关重要。

    Nginx Ingress 痛点

    image

    配置变更频繁,导致Nginx进程频繁重启,大量连接瞬时断开后并发重连会导致后端服务产生压力,严重时造成大量请求失败。

    image

    Nginx Ingress的Controller组件和Nginx组件运行在同一个POD中,控制面资源使用还会影响到数据面的性能。

    image

    Nginx Ingress还缺少面向服务限流的能力,只能实现面向单个来源IP限流,对于后端服务保护来说没有意义。

    Higress 收益

    image

    Higress企业版采用了全托管架构,与业务集群分离,无需自己运维,稳定性有更好保障。

    image

    配置更新都是动态加载,无需重启数据面,保障业务平稳发布,websocket连接的业务收益也特别明显,长连接可以始终保持不会断开。

    image

    开启了TLS硬件加速,TLS握手时延直接减半,QPS吞吐提升86%。

    image

    image

    开启WAF对吞吐影响还是比较明显的,下降了30%,但相比Ingress Nginx直接下降了90%,性能提升还是很明显,而且更大的优势是基于阿里云WAF产品,防护规则是实时更新的,而非Modsecurity的静态规则。

    image

    Higress集成了Sentinel限流的能力,可以直接面向服务的QPS吞吐上限/并发数上线进行限流,并且相比Nginx只能配置单机限制阈值,需要关注网关节点数量,Higress这里的配置是全局阈值,不受网关扩缩容影响。

    触发限流后可以自定义响应内容或者重定向到指定地址,都是很实用的能力。

    Part 2. Higress开源之路:扎根开源生态,定义云原生网关

    开源是云原生生态的基石,Higress也是借助了开源生态的力量,站在Istio/Envoy的肩膀上开发出了更多实用的功能,我们选择将MSE Higress(企业版)中的核心能力全部开源,决心扎根在开源生态中,让Higress变得更普惠,有更多人使用,从而让Higress更加强大。

    简介

    image

    Higress实际上有三次诞生过程:第一次是在阿里集团内部业务需求驱动下诞生;第二次是随着内部使用逐渐成熟沉淀为阿里云上的MSE Higress云原生网关产品;第三次是随着云产品成熟,2022年11月在云栖大会上正式宣布开源。2023年5月Release了第一个GA版本,意味着开源版本也走入成熟阶段。

    image

    从配置流转的过程来看Higress的架构:

    1. 首先用户可以通过UI控制台/命令行工具多种方式来下发配置
    2. 到了控制面,如果是K8s下,配置持久化基于CRD,如果不是K8s,配置持久化基于Nacos
    3. 除了用户下发的路由配置,实现服务路由还需要的服务IP地址信息,支持从K8s service/Nacos/Eureka/Consul/ZooKeeper/DNS/固定IP等多种方式获取
    4. Higress数据面是基于Envoy,配置通过xDS下发,这里复用了Istio的配置下发机制,因为是内置了这个机制,无需单独部署Istio
    5. 最终配置下发到数据面生效,Higress基于Envoy扩展了很多能力,而且基于Wasm扩展机制,可以很方便开发自定义插件,且具备全局/域名/路由维度的生效粒度

    核心能力

    image image

    高集成:同时集成经典微服务生态和K8s开源生态能力,可以帮助业务从传统架构迁移到云原生架构,基于流量灰度等能力,可以保障这一过程的平滑

    image

    标准化:兼容Nginx Ingress常用注解,基于统一的Ingress标准可以轻松实现Nginx到Higress这一技术鸿沟的跨越,Higress也已经支持Gateway API,路由标准本身也能借助Higress实现平滑升级

    image

    image

    易扩展:借助Higress的Wasm SDK,很少的业务代码就可以开发一个灵活的插件;并且支持基于OCI镜像标准分发,可以让插件的文档,配置约束等跟随插件本身一起被分发和共享;和传统Nginx类网关最大的差别,在于插件的分发集成阶段,实现了插件版本更新跟网关自身版本更新的解耦。

    image

    image

    热更新:Envoy相比Nginx更合理的配置系统抽象,让Higress具备了Nginx Ingress无法实现的配置热更新能力

    回顾与展望

    image

    Higress开源的前半年,专注于开源生态的打通和易用性的提升,并基于Github Action构建了开源的集成测试体系,来保障项目质量,在今年5月份发布第一个GA稳定版本后,在多个核心社区开发者的努力下,我们又很快发布了1.1和1.2两个大版本,推出了非K8s部署/Knative支持等重量级功能。

    image

    未来的RoadMap,Higress会聚焦在Gateway API/插件生态/API管理三个方向上,随着社区开发团队的不断壮大,Higress已经建立了多个不同方向的SIG 并行推进核心功能演进,未来将不断有重量级功能推出,尽请期待。

    直播回看

    https://www.aliyun.com/activity/middleware/CloudNative_Meetup

    - + \ No newline at end of file diff --git a/zh-cn/blog/30-line-wasm/index.html b/zh-cn/blog/30-line-wasm/index.html index 0be79bb700..9aff43b1ef 100644 --- a/zh-cn/blog/30-line-wasm/index.html +++ b/zh-cn/blog/30-line-wasm/index.html @@ -14,7 +14,7 @@ - + @@ -35,7 +35,7 @@ Higress 对 Istio/Envoy 的 Wasm 能力做了一些 Bugfix 的工作,目前已经都合并进了上游社区。后续的一些 Feature 能力,也会持续反哺上游社区。 同时欢迎大家一起为 Higress 的插件以及其他社区生态添砖加瓦,为 Higress 贡献请参考文档: https://higress.io/zh-cn/docs/developers/guide_dev.html

    - + \ No newline at end of file diff --git a/zh-cn/blog/DeployOnWindows/index.html b/zh-cn/blog/DeployOnWindows/index.html index c4c5c8ead7..1455f3e469 100644 --- a/zh-cn/blog/DeployOnWindows/index.html +++ b/zh-cn/blog/DeployOnWindows/index.html @@ -14,13 +14,13 @@ - +

    Windows 下 Higress 部署实践

    · 阅读需 4 分钟

    前置准备

    配置 WSL2

    详情参看步骤1-5,顺便在微软商店中下载Terminal。

    WSL手动安装步骤

    下载 Docker Desktop

    1. 访问 Docker Desktop 官方下载页面

      在浏览器中打开 Docker Desktop 的官方下载页面

    2. 下载 Docker Desktop

      在下载页面,找到适用于 Windows 的 Docker Desktop 版本,然后点击下载。

    3. 运行安装程序

      下载完成后,找到下载的安装程序(通常在你的 "下载" 文件夹中),然后双击运行。

    安装 Cygwin

    cygwin官网

    选择setup-x86_64.exe,等待安装完成。

    验证 Cygwin 安装是否成功

    cygcheck -c cygwin

    7.png

    为 Cygwin 配置环境变量

    8.png

    9.png

    10.png

    11.png

    点击确定即可添加成功

    安装 Higrees

    准备 Nacos

    nacos官网手册

    我们这里选择nacos-docker的模式安装

    A.png

    下载解压zip文件,进入 nacos-docker-master 文件夹右键选择终端打开,执行命令,我们这里选择单机模式部署

        docker-compose -f example/standalone-derby.yaml up

    等待出现界面,即安装成功

    B.png

    使用 Higrees 对接 Nacos

    安装命令:使用独立部署的 Nacos

    当访问docker容器互相访问时候本地回环地址并不是真正的地址,所以需要在cygwin中执行获取本地网卡地址

    ipconfig

    C.png

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -c nacos://192.168.0.1:8848 --nacos-username=nacos --nacos-password=nacos -p <你的密码>

    请将 192.168.0.1 替换为 Nacos 服务器的 IP(如果 Nacos 部署在本机,请不要使用如 localhost127.0.0.1 的 Loopback 地址),并按需调整 --nacos-username--nacos-password 的取值。如果 Nacos 服务未开启认证功能,则可以移除这两个参数。

    在这里未开启授权服务,直接使用WLANIP替换对应的IP

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -c nacos://10.30.0.225:8848

    输入命令等待部署,即可看到生成的用户名与密码

    D.png

    Higress 控制台配置

    访问 http://localhost:8080/, 使用用户名 admin 和安装时设置的密码登录 Higress 控制台。

    13.png

    点击左侧“服务来源”导航栏,然后点击页面右侧的“创建服务来源”按钮。按照下图所示内容填写表单并点击“确定”按钮。

    14.png

    点击左侧“域名管理”导航栏,然后点击页面右侧的“创建域名”按钮。按照下图所示内容填写表单并点击“确定”按钮。

    15.png

    点击左侧“路由管理”导航栏,然后点击页面右侧的“创建路由”按钮。按照下图片所示内容填写表单并点击“确定”按钮。

    16.png

    请求验证

    # should output a JSON object containing request data 
    curl http://localhost/get?foo=bar -H 'host: foo.bar.com'

    E.png

    更多详情与部署方案可参考 quick start

    - + \ No newline at end of file diff --git a/zh-cn/blog/ai_plugin/index.html b/zh-cn/blog/ai_plugin/index.html index acb9939d3e..81b6411e00 100644 --- a/zh-cn/blog/ai_plugin/index.html +++ b/zh-cn/blog/ai_plugin/index.html @@ -14,7 +14,7 @@ - + @@ -23,7 +23,7 @@

    本示例提供已经编译好的 AI-proxy-plugin-wasm 文件并完成对应 docker 镜像的构建和推送,推荐配置如下所示:

    名称推荐配置
    镜像地址oci://registry.cn-hangzhou.aliyuncs.com/zwj_test/chatgpt-proxy:1.0.0
    插件执行阶段鉴权阶段
    插件执行优先级1

    插件配置说明:

    插件配置简单,支持全局/域名级/路由级的代理转发。推荐进行路由级配置:选中对应的路由配置-选中对应路由-策略-启用插件。配置字段包括:

    名称数据类型填写要求默认值描述
    modelstring选填text-davinci-003调用的模型名称
    apiKeystring必填-OpenAI-API 密钥,详情可参考
    promptParamstring选填promptprompt 的来源字段名称,URL 参数
    chatgptUristring选填api.openai.com/v1/completions调用 AI 模型服务的 URL 路径,默认值为 OpenAI 的 API 调用路径

    示例配置如下:

    apiKey: "xxxxxxxxxxxxxxxxxx"
    model: "curie"
    promptParam: "text"

    根据该配置,网关代理到 OpenAI-API 下的 curie 模型,用户通过 text 关键字在 url 中输入文本。

    curl "http://{GatewayIP}/?text=Say,hello"

    得到 OpenAI-API 的响应: image.png

    基于 Key Auth 的多租户认证

    不同于为每位成员颁发 OpenAI-API 密钥的形式,企业可以基于 Higress 网关提供的认证鉴权能力,依靠内部授权(如 Key Auth 等)来管理成员对 AI 模型对访问权限,从而限制成员可以使用的服务和模型,并依靠统一的 AI-API 密钥进行请求代理转发实现对 API 用量的统一管理。接下来以 Key Auth 为例介绍 Higress 的多租户认证能力。

    Key Auth 插件实现了基于网关内 API Key 进行认证和鉴权的功能,支持从 HTTP 请求的 URL 参数或者请求头解析 API Key ,同时验证该 API 是否有权限访问。通过在Higress 控制台-插件市场-Key Auth进行全局配置路由级配置,即可实现 Higress 网关的多租户认证。

    consumers:
    - credential: "xxxxxx"
    name: "consumer1"
    - credential: "yyyyyy"
    name: "consumer2"
    global_auth: false
    in_header: true
    keys:
    - "apikey"

    allow: [consumer1]

    以上配置定义了指向 AI 模型服务的消费者组consumers,并且只有consumer1具备访问当前路由下 AI 模型服务的权限。

    curl "http://{GatewayIP}/?text=Say,hello"
    #请求未提供 API-Key ,返回 401

    curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:zzzzzz"
    #请求提供的 API-Key 未在消费者组内,无权访问,返回 401

    curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:yyyyyy"
    #根据请求提供的 API-Keyy 匹配到的调用者无 AI 模型服务的访问权限,返回 403

    curl "http://{GatewayIP}/?text=Say,hello" -H "apikey:xxxxxx"
    #请求合法且有 AI 模型服务访问权限,请求将被代理到 AI 模型,正常得到 OpenAI-API 的响应

    Higress 除了提供网关级多租户认证外,还能提供限流等能力。Key Rate Limit 插件可以根据用户在消费组中的成员资格对用户请求速率进行限制,从而限制应用程序对高成本 AI 大模型服务的消耗。基于多租户认证与限流等功能,Higress 可以完全控制 AI 大模型 API 的访问权限、访问数量与调用成本。

    基于 Request Block 保障数据安全

    对于 AI 大模型尤其是语言模型来说,要得到良好的返回往往需要用户提供足够的提示( prompt )作为模型输入。这也意味着组织和个人可能会在提供提示的过程中面临数据泄漏的风险。因此如何在使用 AI 模型的过程中保障数据安全也是 API 调用方面临重要问题。保护数据安全涉及到对 AI 模型的 API 调用渠道进行严格的控制。一种方式是使用特定的经批准的模型与其发布的 API 。另一种方式是对含敏感信息的用户请求进行拦截。这可以通过在网关级别设置特定的请求拦截来实现。Higress 基于 Request Block 插件提供请求拦截能力,既能防止未经授权的模型访问用户信息,又能防止含敏感信息的用户请求暴露到外网。

    Request Block 插件基于 URL 、请求头等特征屏蔽 HTTP 请求,可以用于防护站点资源不对外暴露。 通过在Higress 控制台-插件市场-Request Block进行屏蔽字段配置,即可防止含敏感字段的请求对外发送。

    blocked_code: 404
    block_urls:
    - password
    - pw
    case_sensitive: false

    以上配置定义了当前路由下基于 URL 的屏蔽字段,其中含敏感信息(如 password 、pw )的请求将被屏蔽。

    curl "http://{GatewayIP}/?text=Mypassword=xxxxxx" -H "apikey:xxxxxx"
    curl "http://{GatewayIP}/?text=pw=xxxxxx" -H "apikey:xxxxxx"
    #上述请求将被禁止访问,返回 404

    基于商业版 Higress 的用量观测与分析

    对于组织来说,对各用户进行 AI 模型调用的用量观测和分析有助于了解其使用情况与产生的成本。对于个人用户,了解自己的调用量和开销也是必要的。因此,在网关层进行调用的观测和分析对于 AI 大模型的 API 管理是必要的能力。商业版 Higress与各种指标与日志系统进行了深度集成,提供了开箱即用的用量观测分析报告构建机制,可以实时查看各种 API 的使用情况,并根据各类参数进行过滤,从而更好的了解 API 使用情况。

    以观察各用户对 OpenAI-Curie 模型的调用量为例,用户可通过MSE 管理控制台-云原生网关-网关实例-参数配置-日志格式调整中设置区分用户的可观测性参数请求头:x-mse-consumer,将其列入观测列表。之后进入观测分析-日志中心中设置使用统计图表功能即可完成对 API 的用量观测和分析。如下图所示,用户consumer1与用户consumer2的对 OpenAI-Curie 模型的调用量以饼状图形式呈现。 image.png

    加入 Higress 社区

    image.png

    如果您觉得 Higress 对您有帮助,欢迎前往github: Higress为我们 star 一下!

    - + \ No newline at end of file diff --git a/zh-cn/blog/archive/index.html b/zh-cn/blog/archive/index.html index b605e66404..ab5275cdf6 100644 --- a/zh-cn/blog/archive/index.html +++ b/zh-cn/blog/archive/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/blog/config-with-file/index.html b/zh-cn/blog/config-with-file/index.html index 711152830c..6ef0507006 100644 --- a/zh-cn/blog/config-with-file/index.html +++ b/zh-cn/blog/config-with-file/index.html @@ -14,13 +14,13 @@ - +

    基于文件配置实现 Higress 极简独立部署

    · 阅读需 4 分钟

    前置准备

    安装 Docker Compose

    请参考 Docker 官方文档来安装 Docker Engine,其中已经内置了 Docker Compose 组件:https://docs.docker.com/engine/install/

    环境验证

    1. 启动终端;
    2. 执行 docker compose version 命令,确认可以正常输出 Docker Compose 的版本。
      Docker Compose version v2.20.2

    安装 Higrees

    确定配置目录

    由于这次我们准备使用文件来管理 Higress 的配置数据,所以需要先确定保存配置文件的目录。下面我们将以 ~/higress/conf 目录为例进行介绍。

    执行安装

    启动终端,并执行以下命令:

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -c file://~/higress/conf -p <你的密码> -a

    请耐心等待安装过程执行完毕。Higress 的执行文件将被安装在当前目录下的 higress 子目录内。配置数据则将被写入 ~/higress/conf 目录内。

    在安装完成后,脚本会自动启动 Higress。当终端输出如下信息时,则说明 Higress 已安装完成并成功启动。

    Higress is now started. You can check out its status by executing /home/ch3cho/higress/bin/status.sh

    Higress Gateway is listening on:
    http://0.0.0.0:80
    https://0.0.0.0:443
    Visit Higress Console: http://localhost:8080/

    Higress 路由配置

    为了着重说明基于文件的路由配置方式,这里将不再展开介绍使用 Higress 控制台来进行配置的具体步骤。如有需要,大家可以查阅其他文档。

    创建服务来源

    使用文本编辑器将以下内容写入 ~/higress/conf/mcpbridges/default.yaml 文件中:

    apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    - domain: httpbin.org
    name: httpbin
    port: 80
    type: dns

    创建域名配置

    使用文本编辑器将以下内容写入 ~/higress/conf/configmaps/domain-foo.bar.com.yaml 文件中:

    apiVersion: v1
    kind: ConfigMap
    metadata:
    name: domain-foo.bar.com
    namespace: higress-system
    data:
    domain: foo.bar.com
    enableHttps: "off"

    创建服务路由

    使用文本编辑器将以下内容写入 ~/higress/conf/ingresses/route-foo-bar.yaml 文件中:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/destination: httpbin.dns
    higress.io/ignore-path-case: "false"
    name: route-foo-bar
    namespace: higress-system
    spec:
    ingressClassName: higress
    rules:
    - host: foo.bar.com
    http:
    paths:
    - backend:
    resource:
    apiGroup: networking.higress.io
    kind: McpBridge
    name: default
    path: /
    pathType: Prefix

    请求验证

    在终端中执行以下命令:

    curl http://localhost/get?foo=bar -H 'Host: foo.bar.com'

    请求应返回一段包含请求信息的 JSON 数据:

    {
    "args": {
    "foo": "bar"
    },
    "headers": {
    "Accept": "*/*",
    "Host": "foo.bar.com",
    "Original-Host": "foo.bar.com",
    "Req-Start-Time": "1693049173053",
    "User-Agent": "curl/8.1.2",
    "X-Amzn-Trace-Id": "Root=1-11111111-111111111111111111111111",
    "X-B3-Sampled": "0",
    "X-B3-Spanid": "2222222222222222",
    "X-B3-Traceid": "33333333333333333333333333333333",
    "X-Envoy-Attempt-Count": "1",
    "X-Envoy-Decorator-Operation": "httpbin.dns:80/*",
    "X-Envoy-Internal": "true"
    },
    "origin": "192.168.16.1, 123.123.123.123",
    "url": "http://foo.bar.com/get?foo=bar"
    }

    已知问题

    在 Windows 操作系统中,直接修改挂载到 Docker 容器中的本地文件后,容器内的进程无法收到通知(详情请查看 fsnotify/fsnotify #292)。如果要使用文件来保存配置数据的话,在直接修改配置文件后,Higress 无法立即加载到新的配置。如果需要在 Windows 上独立部署 Higress 网关,可以考虑通过 Higress Console 来管理配置信息,或使用 Nacos 保存网关配置。

    参考文档

    更多相关信息与 Higress 的其他部署方式可查阅以下文档:

    - + \ No newline at end of file diff --git a/zh-cn/blog/configmap/index.html b/zh-cn/blog/configmap/index.html index e44ddd2ac7..4bb785562e 100644 --- a/zh-cn/blog/configmap/index.html +++ b/zh-cn/blog/configmap/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    Higress 全局配置控制面原理分析

    · 阅读需 12 分钟

    Higress 有个全局配置 ConfigMap 对象 higress-config,参考配置如下:

    apiVersion: v1
    data:
    higress: |-
    tracing:
    enable: true
    sampling: 100
    timeout: 500
    skywalking:
    service: skywalking-oap-server.op-system.svc.cluster.local
    port: 11800
    ...
    ...
    kind: ConfigMap
    metadata:
    name: higress-config
    namespace: higress-system

    具体配置说明请参考 Higress 全局配置说明文档, 本文介绍以 Tracing 为例,详细说明 Tracing 全局配置是如何转成 EnvoyFilter 和如何同时实现实时下发到 Higress Gateway过程。

    本文涉及整体架构流程、初始化过程和启动、higress-config 变更和处理流程、通知 XDSUpdater、构建 EnvoyFilter 和下发以及如何扩展全局配置等内容。

    整体架构流程

    1. 整体架构

    img.png

    2. 核心组件

    • IngressConfig

    IngressConfig 是 Higress 一个核心结构体, 负责监控 Ingress, McpBridge, Http2Rpc, WasmPlugin 等 k8s 资源, 同时集成 ConfigStore Interface,通过 List 接口下发 VirtualService, DestinationRule, EnvoyFilter, ServiceEntry, WasmPlugin 等 CR 资源。

    • ConfigmapMgr

    ConfigmapMgr 结构体负责整个核心流程,包括通过 Informer List/Watch 机制监控 higress-config 的变更,同时遍历 ItemControllers 下发变更通知,提供构建 EnvoyFilter 列表等功能。

    • TracingController

    TracingController 结构体负责具体的 Tracing 数据校验,构建 Tracing EnvoyFilter, 以及通过 ItemEventHandler 下发变更通知等。

    • HigressConfig

    HigressConfig 是 higress-config Configmap 所对应数据的结构体。

    3. 核心流程

    • 用 Informer List/Watch 机制监控 higress-config 变更,校验变更,同时保存变更后数据。
    • 用变更数据构建 EnvoyFilter。
    • 通知 XDSUpdater,EnvoyFilter 有变更,重新拉取新的 EnvoyFilter 列表。

    初始化过程

    1. 初始化入口

    初始化过程入口在 NewIngressConfig, 初始化 IngressConfig 时同时构建 HigressConfigController 和 ConfigmapMgr。

    // pkg/ingress/config/ingress_config.go
    func NewIngressConfig(localKubeClient kube.Client, XDSUpdater model.XDSUpdater, namespace, clusterId string) *IngressConfig {
    // ...

    // 构建 controller 和 configmapMgr
    higressConfigController := configmap.NewController(localKubeClient, clusterId, namespace)
    config.configmapMgr = configmap.NewConfigmapMgr(XDSUpdater, namespace, higressConfigController, higressConfigController.Lister())

    return config
    }

    2. HigressConfigController 初始化

    通过 Higress 提供 NewCommonController 初始化 HigressConfigController 用于监听 higress-system 命名空间下 Configmap 的变化。

    // pkg/ingress/kube/configmap/controller.go
    type HigressConfigController controller.Controller[listersv1.ConfigMapNamespaceLister]

    func NewController(client kubeclient.Client, clusterId string, namespace string) HigressConfigController {
    informer := client.KubeInformer().Core().V1().ConfigMaps().Informer()
    return controller.NewCommonController("higressConfig", client.KubeInformer().Core().V1().ConfigMaps().Lister().ConfigMaps(namespace),
    informer, GetConfigmap, clusterId)
    }

    func GetConfigmap(lister listersv1.ConfigMapNamespaceLister, namespacedName types.NamespacedName) (controllers.Object, error) {
    return lister.Get(namespacedName.Name)
    }

    3. ConfigmapMgr 初始化

    ConfigmapMgr 初始化具体步骤如下:

    • 构建 ConfigmapMgr
    • 设置 HigressConfigController configmap 新增或者更新回调函数为 configmapMgr.AddOrUpdateHigressConfig
    • 设置 HigressConfig 结构体默认值
    • 初始化 TracingController
    • 把 tracingController 添加到 configmapMgr itemControllers 数组里
    • 初始化 ItemEventHandler, 同时遍历 itemControllers,设置 ItemEventHandler
    // pkg/ingress/kube/configmap/controller.go
    func NewConfigmapMgr(XDSUpdater model.XDSUpdater, namespace string, higressConfigController HigressConfigController, higressConfigLister listersv1.ConfigMapNamespaceLister) *ConfigmapMgr {
    // 构建 ConfigmapMgr
    configmapMgr := &ConfigmapMgr{
    XDSUpdater: XDSUpdater,
    Namespace: namespace,
    HigressConfigController: higressConfigController,
    HigressConfigLister: higressConfigLister,
    higressConfig: atomic.Value{},
    }
    // 设置 HigressConfigController configmap 新增或者更新回调函数 configmapMgr.AddOrUpdateHigressConfig
    configmapMgr.HigressConfigController.AddEventHandler(configmapMgr.AddOrUpdateHigressConfig)
    // 设置 HigressConfig 结构体默认值
    configmapMgr.SetHigressConfig(NewDefaultHigressConfig())

    // 初始化 TracingController
    tracingController := NewTracingController(namespace)
    // 把 tracingController 添加到 configmapMgr itemControllers 里
    configmapMgr.AddItemControllers(tracingController)
    // 初始化 itemEventHandler, 同时遍历 itemControllers,设置 itemEventHandler
    configmapMgr.initEventHandlers()

    // 返回 configmapMgr
    return configmapMgr
    }

    启动

    在 IngressConfig 添加 HigressConfigController Run() 和 HasSynced() 控制流程。

    // pkg/ingress/config/ingress_config.go
    func (m *IngressConfig) Run(stop <-chan struct{}) {
    // ...
    // 启动 HigressConfigController
    go m.configmapMgr.HigressConfigController.Run(stop)
    }

    func (m *IngressConfig) HasSynced() bool {
    // ....
    if !m.configmapMgr.HigressConfigController.HasSynced() {
    return false
    }
    }

    higress-config 变更和处理流程

    1. configmapMgr 变更处理

    ConfigmapMgr 通过收到 HigressConfigController 通知来处理变更请求。

    具体变更流程如下:

    • 判断是否 higress-system 命名空间下 name 为 higress-config Configmap 发生了变化,如果不是就返回。
    • 获取 higress-config 内容。
    • 遍历 ItemControllers, 校验 higress-config 配置是否合法,如果有一个返回不合法,就返回。
    • 和上次保存在本地 higressConfig 比对, 检查这次数据是否有变化,如果没有变化就返回。
    • 如果数据有变化,就遍历 ItemControllers 通知每个 itemController 数据有变化,同时保存这次变化到本地 higressConfig。
    // pkg/ingress/kube/configmap/controller.go
    func (c *ConfigmapMgr) AddOrUpdateHigressConfig(name util.ClusterNamespacedName) {
    // 只监听 higress-system 命名空间下 name 为 higress-config Configmap 的变化
    if name.Namespace != c.Namespace || name.Name != HigressConfigMapName {
    return
    }
    // ...
    // 获取 higress-config 内容
    higressConfigmap, err := c.HigressConfigLister.Get(HigressConfigMapName)

    // 通过 yaml.Unmarshal 转成 HigressConfig
    newHigressConfig := NewDefaultHigressConfig()
    if err = yaml.Unmarshal([]byte(higressConfigmap.Data[HigressConfigMapKey]), newHigressConfig); err != nil {
    IngressLog.Errorf("data:%s, convert to higress config error, error: %+v", higressConfigmap.Data[HigressConfigMapKey], err)
    return
    }

    // ...
    // 遍历 ItemControllers, 校验配置是否合法
    for _, itemController := range c.ItemControllers {
    if itemErr := itemController.ValidHigressConfig(newHigressConfig); itemErr != nil {
    IngressLog.Errorf("configmap %s controller valid higress config error, error: %+v", itemController.GetName(), itemErr)
    return
    }
    }

    // 和上次比对这次数据是否有变更
    oldHigressConfig := c.GetHigressConfig()
    result, _ := c.CompareHigressConfig(oldHigressConfig, newHigressConfig)
    // ...
    // 如果数据有变更,就遍历 ItemControllers 通知每个 itemController 数据有变更,同时保存这次变更到本地。
    if result == ResultReplace || result == ResultDelete {
    for _, itemController := range c.ItemControllers {
    IngressLog.Infof("configmap %s controller AddOrUpdateHigressConfig", itemController.GetName())
    if itemErr := itemController.AddOrUpdateHigressConfig(name, oldHigressConfig, newHigressConfig); itemErr != nil {
    IngressLog.Errorf("configmap %s controller AddOrUpdateHigressConfig error, error: %+v", itemController.GetName(), itemErr)
    }
    }
    // 保存这次变更
    c.SetHigressConfig(newHigressConfig)
    }
    }

    2. TracingController 变更处理

    TracingController 变更处理就比较简单:

    • 检查 Tracing 这部分数据是否有变更。
    • 如果有变更,DeepCopy 一份 Tracing 数据保存到本地,同时通过 eventHandler 下发变更通知。
    // pkg/ingress/kube/configmap/tracing.go
    func (t *TracingController) AddOrUpdateHigressConfig(name util.ClusterNamespacedName, old *HigressConfig, new *HigressConfig) error {
    // ...
    // 检查 Tracing 部分数据是否有变更
    result, _ := compareTracing(old.Tracing, new.Tracing)

    // 如果有变更,DeepCopy 一份 Tracing 数据保存到本地,同时通过 eventHandler 下发变更通知
    switch result {
    case ResultReplace:
    if newTracing, err := deepCopyTracing(new.Tracing); err != nil {
    IngressLog.Infof("tracing deepcopy error:%v", err)
    } else {
    t.SetTracing(newTracing)
    IngressLog.Infof("AddOrUpdate Higress config tracing")
    t.eventHandler(higressTracingEnvoyFilterName)
    IngressLog.Infof("send event with filter name:%s", higressTracingEnvoyFilterName)
    }
    case ResultDelete:
    t.SetTracing(NewDefaultTracing())
    IngressLog.Infof("Delete Higress config tracing")
    t.eventHandler(higressTracingEnvoyFilterName)
    IngressLog.Infof("send event with filter name:%s", higressTracingEnvoyFilterName)
    }

    return nil
    }

    通知 XDSUpdater

    在 ConfigmapMgr 初始化时候调用 configmapMgr.initEventHandlers(), 这个 func 会创建 ItemEventHandler, 同时遍历 ItemControllers 设置 ItemEventHandler。

    // pkg/ingress/kube/configmap/config.go
    type ItemEventHandler = func(name string)

    // pkg/ingress/kube/configmap/controller.go
    func (c *ConfigmapMgr) initEventHandlers() error {
    itemEventHandler := func(name string) {
    c.XDSUpdater.ConfigUpdate(&model.PushRequest{
    Full: true,
    ConfigsUpdated: map[model.ConfigKey]struct{}{{
    Kind: gvk.EnvoyFilter,
    Name: name,
    Namespace: c.Namespace,
    }: {}},
    Reason: []model.TriggerReason{ModelUpdatedReason},
    })
    }

    for _, itemController := range c.ItemControllers {
    itemController.RegisterItemEventHandler(itemEventHandler)
    }

    return nil
    }

    这里 XDSUpdater 是从 IngressConfig 初始化传入, XDSUpdater.ConfigUpdate() 用于更新通知下发。

    进一步跟踪可以发现在 Higress controller server 启动时执行 s.initXdsServer 函数创建 s.xdsServer,具体逻辑不在本文讨论范围, 有兴趣可以进一步阅读源码。

    // pkg/bootstrap/server.go
    func NewServer(args *ServerArgs) (*Server, error) {
    // ...
    s := &Server{
    ServerArgs: args,
    httpMux: http.NewServeMux(),
    environment: e,
    readinessProbes: make(map[string]readinessProbe),
    server: server.New(),
    }
    s.environment.Watcher = mesh.NewFixedWatcher(&v1alpha1.MeshConfig{})
    s.environment.Init()
    initFuncList := []func() error{
    s.initKubeClient,
    s.initXdsServer,
    s.initHttpServer,
    s.initConfigController,
    s.initRegistryEventHandlers,
    s.initAuthenticators,
    }

    for _, f := range initFuncList {
    if err := f(); err != nil {
    return nil, err
    }
    }

    // ...
    return s, nil
    }

    // pkg/bootstrap/server.go
    func (s *Server) initXdsServer() error {
    log.Info("init xds server")
    s.xdsServer = xds.NewDiscoveryServer(s.environment, nil, PodName, PodNamespace, s.RegistryOptions.KubeOptions.ClusterAliases)
    // ...
    return s.initGrpcServer()
    }

    构建和下发 EnvoyFilters

    1. IngressConfig List 下发 EnvoyFilters 列表

    IngressConfig List 用于 VirtualService, DestinationRule, EnvoyFilter, ServiceEntry, WasmPlugin 等 CR 资源下发, 这里主要关注 EnvoyFilter CR 资源下发。

    // pkg/ingress/config/ingress_config.go
    func (m *IngressConfig) List(typ config.GroupVersionKind, namespace string) ([]config.Config, error) {
    if typ != gvk.Gateway &&
    typ != gvk.VirtualService &&
    typ != gvk.DestinationRule &&
    typ != gvk.EnvoyFilter &&
    typ != gvk.ServiceEntry &&
    typ != gvk.WasmPlugin {
    return nil, common.ErrUnsupportedOp
    }
    // ...
    if typ == gvk.EnvoyFilter {
    m.mutex.RLock()
    defer m.mutex.RUnlock()
    var envoyFilters []config.Config

    // 调用 ConfigmapMgr ConstructEnvoyFilters 获取需要下发 EnvoyFilter 列表
    configmapEnvoyFilters, err := m.configmapMgr.ConstructEnvoyFilters()
    if err != nil {
    IngressLog.Errorf("Construct configmap EnvoyFilters error %v", err)
    } else {
    for _, envoyFilter := range configmapEnvoyFilters {
    envoyFilters = append(envoyFilters, *envoyFilter)
    }
    IngressLog.Infof("Append %d configmap EnvoyFilters", len(configmapEnvoyFilters))
    }
    if len(envoyFilters) == 0 {
    IngressLog.Infof("resource type %s, configs number %d", typ, len(m.cachedEnvoyFilters))
    return m.cachedEnvoyFilters, nil
    }
    // 需要下发 configmap EnvoyFilter 列表 和 m.cachedEnvoyFilters 列表聚合一下下发
    envoyFilters = append(envoyFilters, m.cachedEnvoyFilters...)
    IngressLog.Infof("resource type %s, configs number %d", typ, len(envoyFilters))
    return envoyFilters, nil
    }

    }

    调用 ConfigmapMgr ConstructEnvoyFilters 获取需要下发 EnvoyFilter 列表, 同时和 m.cachedEnvoyFilters 列表聚合一下再下发。

    这里 m.cachedEnvoyFilters 是在构建 VirtualService 时生成,有兴趣可以进一步阅读 IngressConfig 源码。

    2. ConfigmapMgr 构建 EnvoyFilter 列表

    这里比较简单,遍历一下 ItemControllers,聚合每个 itemController 返回的 EnvoyFilters.

    // /pkg/ingress/kube/configmap/controller.go
    func (c *ConfigmapMgr) ConstructEnvoyFilters() ([]*config.Config, error) {
    configs := make([]*config.Config, 0)
    for _, itemController := range c.ItemControllers {
    IngressLog.Infof("controller %s ConstructEnvoyFilters", itemController.GetName())
    if itemConfigs, err := itemController.ConstructEnvoyFilters(); err != nil {
    IngressLog.Errorf("controller %s ConstructEnvoyFilters error, error: %+v", itemController.GetName(), err)
    } else {
    configs = append(configs, itemConfigs...)
    }
    }
    return configs, nil
    }

    3. TracingController 构建 EnvoyFilters

    这里就比较简单,根据保存的 Tracing 数据构建对应的 EnvoyFilter

    // pkg/ingress/kube/configmap/tracing.go
    func (t *TracingController) ConstructEnvoyFilters() ([]*config.Config, error) {
    // ...
    tracingConfig := t.constructTracingTracer(tracing, namespace)
    if len(tracingConfig) == 0 {
    return configs, nil
    }

    config := &config.Config{
    Meta: config.Meta{
    GroupVersionKind: gvk.EnvoyFilter,
    Name: higressTracingEnvoyFilterName,
    Namespace: namespace,
    },
    Spec: &networking.EnvoyFilter{
    ConfigPatches: []*networking.EnvoyFilter_EnvoyConfigObjectPatch{
    {
    ApplyTo: networking.EnvoyFilter_NETWORK_FILTER,
    Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
    Context: networking.EnvoyFilter_GATEWAY,
    ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
    Listener: &networking.EnvoyFilter_ListenerMatch{
    FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
    Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
    Name: "envoy.filters.network.http_connection_manager",
    },
    },
    },
    },
    },
    Patch: &networking.EnvoyFilter_Patch{
    Operation: networking.EnvoyFilter_Patch_MERGE,
    Value: util.BuildPatchStruct(tracingConfig),
    },
    },
    {
    ApplyTo: networking.EnvoyFilter_HTTP_FILTER,
    Match: &networking.EnvoyFilter_EnvoyConfigObjectMatch{
    Context: networking.EnvoyFilter_GATEWAY,
    ObjectTypes: &networking.EnvoyFilter_EnvoyConfigObjectMatch_Listener{
    Listener: &networking.EnvoyFilter_ListenerMatch{
    FilterChain: &networking.EnvoyFilter_ListenerMatch_FilterChainMatch{
    Filter: &networking.EnvoyFilter_ListenerMatch_FilterMatch{
    Name: "envoy.filters.network.http_connection_manager",
    SubFilter: &networking.EnvoyFilter_ListenerMatch_SubFilterMatch{
    Name: "envoy.filters.http.router",
    },
    },
    },
    },
    },
    },
    Patch: &networking.EnvoyFilter_Patch{
    Operation: networking.EnvoyFilter_Patch_MERGE,
    Value: util.BuildPatchStruct(`{
    "name":"envoy.filters.http.router",
    "typed_config":{
    "@type": "type.googleapis.com/envoy.extensions.filters.http.router.v3.Router",
    "start_child_span": true
    }
    }`),
    },
    },
    },
    },
    }

    configs = append(configs, config)
    return configs, nil
    }

    如何扩展全局配置

    1. HigressConfig 结构体添加对应的扩展配置

    type HigressConfig struct {
    Tracing *Tracing `json:"tracing,omitempty"`
    // 在这里添加对应的数据结构来扩展配置
    }

    2. 增加扩展配置默认值

    // pkg/ingress/kube/configmap/config.go
    func NewDefaultHigressConfig() *HigressConfig {
    higressConfig := &HigressConfig{
    Tracing: NewDefaultTracing(),
    // 在这里增加扩展配置默认值
    }
    return higressConfig
    }

    3. 实现 ItemController interface

    type ItemController interface {
    GetName() string
    AddOrUpdateHigressConfig(name util.ClusterNamespacedName, old *HigressConfig, new *HigressConfig) error
    ValidHigressConfig(higressConfig *HigressConfig) error
    ConstructEnvoyFilters() ([]*config.Config, error)
    RegisterItemEventHandler(eventHandler ItemEventHandler)
    }

    4. 初始化扩展配置,同时添加到 ItemControllers

    func NewConfigmapMgr(XDSUpdater model.XDSUpdater, namespace string, higressConfigController HigressConfigController, higressConfigLister listersv1.ConfigMapNamespaceLister) *ConfigmapMgr {
    // ...
    tracingController := NewTracingController(namespace)
    configmapMgr.AddItemControllers(tracingController)
    // ...
    // 在这里初始化扩展配置,同时添加到 ItemControllers
    configmapMgr.initEventHandlers()

    return configmapMgr
    }

    参与社区贡献

    Higress 开源贡献小组正在火热招募贡献者。早期参与开源更容易成为项目 Committer,并有更多机会成为 Higress PMC(Project Management Committee) 的一员,参与主导 Higress 社区的前进方向。 欢迎加入 Higress 社区群:

    - + \ No newline at end of file diff --git a/zh-cn/blog/first-meetup/index.html b/zh-cn/blog/first-meetup/index.html index 8bfddb4bac..e6bde81935 100644 --- a/zh-cn/blog/first-meetup/index.html +++ b/zh-cn/blog/first-meetup/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/blog/higress/index.html b/zh-cn/blog/higress/index.html index d93f387c02..0688360086 100644 --- a/zh-cn/blog/higress/index.html +++ b/zh-cn/blog/higress/index.html @@ -14,7 +14,7 @@ - + @@ -23,7 +23,7 @@ 这里提一下“为什么我们认为配置的热更新,是非常重要的”?

    Tengine/Nginx 的配置更新需要 reload,reload 需要重启 worker 进程,重启时会引起流量抖动,对长连接影响尤为明显。在网关的集群规模非常大时,更是不能随意的做 reload,这时就会引发一个矛盾点:业务向网关提交配置后,希望能快速验证,但受限于 reload 机制和稳定性要求,无法满足业务快速验证与快速试错的诉求。

    现在已经有很多主流应用选择采用长连接,HTTP 1.1一般默认会使用Keep-Alive去保持长连接,后续HTTP 2以及HTTP 3也是如此,随着网络协议的发展,未来使用长连接会变得更加普遍。而配置热更新天然对长连接非常友好。

    如何解决这点呢?

    一是采用两层网关,即流量网关 + 业务网关;二是实现网关原生支持配置热更新。除了对比不同方案的优劣势,我们也调研了 Envoy 作为网关在业界的趋势,结论是目前 Envoy 作为 K8s 中的 Ingress Provider 增长最快的事实(Ingress Provider 指 K8s Ingress 规范具体实现,因 K8s Ingress 自身只是规范定义,是 K8s 下外部流量进入集群内部的网关规范定义),我们最终选择了 Envoy 来实现两层网关。

    image.png

    发展历程

    Higress从最初社区的 Istio + Envoy,到经历阿里巴巴内部的自研扩展,再到大规模生成验证,最后完成商业化产品的发布,其整个过程介绍如下:

    image.png 下面的章节会对Higress的各个阶段做进一步的详细说明。

    Higress (2020.05~2020.11)

    此阶段的大目标是为了满足集团与蚂蚁RPC互通,降低全链路的RT,解决原s2s链路因RT过高带来的用户体验差及无法满足更多集团与蚂蚁协同场景要求。s2s链路是走公网链路,协议采用HTTP。与蚂蚁互通网关的架构图如下,这里以上海云单元为背景说明。

    image.png

    上图主要展示的是集团侧的架构,最终采用了Istio+Envoy的方案,在部署的时候又分成了出口集群和入口集群。之所以拆成两个集群,一方面是当时两边互访,蚂蚁调集团的流量要远远大于集团调蚂蚁的流量,上下行特别不均等;另一方面是分开之后两个集群可以各自维护,稳定性会更好。

    Higress 从开始立项到完成第一期研发,网关改造的核心工作差不多两个人投入了一个半月左右,其中还涉及到大量网络、安全等协调部门的工作。Higress架构并没有完全按照社区方案来设计,社区版本中配置变更和服务发现使用的是K8s,在阿里内部庞大的服务规模及配置量下社区原生方案不管在稳定性及性能上都无法满足要求,因此阿里这套方案重点对服务发现、配置存储组件做了替换,及优化xDS推送性能。

    Higress 上线后,顺利达成了最初的业务诉求,目前蚂蚁互通网关链路已经成为集团与蚂蚁互通的首选方案,一些支付链路也迁移到了该方案,例如充值中心等,具体达到的成果简述如下:

    • 蚂蚁调用集团链路相比原链路RT降低50%,网关自身RT 0.3ms。
    • Higress成功复制到集团与蚂蚁的消息互通,目前集团与蚂蚁的消息互通也是走的Higress Triple链路。
    • 微服务网关从5月份上线,目前已经成为集团与蚂蚁东西向流量的核心链路,飞猪、手淘、口碑、饿了么、1688、部分导购应用、商品库、评价等业务已成功上线,而且圆满支撑了618大促、支付宝717夏至大促。
    • 在2020双11大促每秒 数十万 的请求流量,圆满支撑了双11城市生活狂欢节的互动会场。
    • 在技术侧完成了Higress在东西向流量分发的探索。

    Higress (2020.12~2021.10)

    随着阿里巴巴上云战役的推进,越来越多的场景找到我们。比如云上云下业务互通,由于 Tengine 服务管理弱导致阿里内部大量二层微服务网关需要收敛,这就需要从业务上做 Tengine+Envoy 两层网关的演进,承担南北向网关流量。在 2020 年 12 月份,团队开始了Higress 架构的继续演进,以优酷场景为例的演进过程如下图:

    image.png

    Higress 南北向的架构图如下:

    image.png

    在两层架构中,Higress 网关更多承担了微服务网关和微服务治理的需求,和 Tengine 流量网关完成了整合。在这个过程里,团队支撑优酷内部多个二层微服务网关统一的工作,大幅提升了性能和运维效率。

    在这一阶段,Higress Gateway 实现了东西向、南北向全域流量的调度分发,东西向上不仅支持跨业务域的蚂蚁 RPC 互通,也扩展到了混合云的云上云下 RPC 互通场景,覆盖钉钉文档、阿里视频云、达摩院的店小蜜、智慧数字人等。该阶段的业务大图如下(云上云下互通场景,以钉钉为例说明):

    image.png

    随着 Higress Gateway 覆盖的业务场景越来多,在跟优酷持续合作的过程中,双方团队不约而同提出了一个设想:Tengine Gateway(承担流量网关角色) + Higress Gateway(承担微服务网关角色)的两层网关是否可以合并为一层 Higress Gateway?

    我们对这一想法做了调研,答案是肯定的,并且当时大家也合作设计了新的架构方案,如下图:

    image.png

    虽然由于各种各样的原因,这个方案最终没有跟优酷继续往下推进。但这个演进方向让团队明确了网关新的发展趋势:在以 K8s 主导的容器化背景下,由于K8s 集群内外网络的天然隔离性,用户需要一款兼顾高性能与安全性,以及强大服务治理能力的入口网关。这也为后续团队将技术沉淀变成云产品、推进Higress的诞生打下了基础。

    2021 年,阿里巴巴开启了中间件三位一体战役,目标是用云产品支撑集团业务。我们开始将孵化成熟的Higress技术沉淀为云产品,即目前阿里云上提供的 MSE 云原生网关,一方面面向广大的公有云用户提供托管的网关服务,另一方面也对内服务集团。MSE 云原生网关的技术架构简图如下:

    image.png

    Higress (2021.11~2022.11)

    随着Higress成为云产品服务于更多外部用户,我们逐步发现用户对Higress提出了更高的要求,其中反馈较多的大的需求点是插件扩展、Waf防护、多注册中心、Nginx Ingress注解兼容以及HTTP转Dubbo协议,当然也有很多小的需求点在此就不一一列出,因此该阶段我们重点发力在上述用户反馈的高频需求。

    Higress 提供的插件市场,其一阶段支持Wasm插件,满足追求高性能、高安全的用户对网关的扩展诉求,二阶段会支持Lua插件,满足传统用户使用Lua的扩展的诉求,如Nginx用户,三阶段会支持进程外插件,满足多语言用户诉求,尤其是Java用户因现阶段Java社区对WebAssembly支持尚不完善但又希望对网关进行扩展的诉求。

    image.png

    Higress 也支持了Nginx Ingress注解平滑迁移的能力,满足部分用户期望迁移到Higress但又不希望重新配置网关的诉求,同时Higress打破了Nginx Ingress只能关联单个K8s集群的限制,支持关联多个K8s集群,即可以将Higress作为统一接入网关使用,同时又可以享受Ingress的红利

    image.png

    对于传统使用Dubbo的微服务用户希望使用原生RPC方式暴露对外服务,但通常提供外部访问的服务以使用HTTP为主,为了帮助Dubbo用户降低服务暴露的开发成本,Higress提供了HTTP转Dubbo协议功能,且通过Console为用户提供白屏化的配置方式,某客户使用后反馈“这是业界完成度最高的HTTP转Dubbo协议”功能

    image.png

    在云原生的浪潮下,开源已经成为软件发展的必然趋势与快速路径,因为社区的力量是非常强大的。因此我们将 这套经过内部实践沉淀下来的网关方案Higress正式对外开源,以Kubernetes Ingress网关为契机带来了流量网关与微服务网关融合的可能性,结合阿里内部实践沉淀Higress实现了流量网关 + 微服务网关 + 安全网关三合一的高集成能力,同时深度集成了Dubbo、Nacos、Sentinel等,能够帮助用户极大的降低网关的部署及运维成本,而且能力不打折。

    image.png

    Higress 未来展望

    虽然目前云原生已经成为必然趋势,但现实是有很大一部分用户处于迁移上云的过程中,在从传统架构向以Kubernetes 为代表的容器化云原生架构迁移,可预见这在未来很长一段时间会一直持续,因此 Higress 后续会重点支持非 Kubernetes 部署架构,以 Higress + Nacos 的组合形式为用户提供最小集运行环境,同时满足用户服务注册、配置管理、微服务治理的诉求。

    在以 Kubernetes 为代表的容器化云原生方向,我们在兼容好现有 Ingress 标准的基础上,会重点发力下一代的Ingress 标准 Gateway API,利用 Gateway API 带来的契机打通南北向与东西向的全域流量调度,帮助用户使用一套架构架构同时管理外部与内部流量,降低部署运维成本、提升开发及运维效率。

    - + \ No newline at end of file diff --git a/zh-cn/blog/index.html b/zh-cn/blog/index.html index bacb075b3b..4f44332774 100644 --- a/zh-cn/blog/index.html +++ b/zh-cn/blog/index.html @@ -14,7 +14,7 @@ - + @@ -34,7 +34,7 @@ helm 安装参考安装文档

    1. 安装 higress 和 istio CRD

    可以参考 higress 快速开始安装部署 来部署,这里需要安装 Istio CRD。

    这里提供一键安装脚本 local-env-setup.sh,运行 local-env-setup.sh 安装 Higress

    ./local-env-setup.sh --crd
    1. 部署 Skywalking,业务应用和 Ingress
    $ export KUBECONFIG=${HOME}/.kube/config_higress
    $ kubectl apply -f skywalking.yaml
    $ kubectl apply -f app.yaml
    $ kubectl apply -f ingress.yaml

    检查 POD 运行状态和 Ingress 状态

    $ export KUBECONFIG=${HOME}/.kube/config_higress

    $ kubectl get pods -n higress-system

    NAME READY STATUS RESTARTS AGE
    higress-console-6f554978dc-cclg7 1/1 Running 0 100m
    higress-console-grafana-7495766db4-4flq5 1/1 Running 0 131m
    higress-console-prometheus-6d7bdccfb-hxtsq 1/1 Running 0 131m
    higress-controller-689c5b965f-7wsmt 2/2 Running 0 131m
    higress-gateway-59966b45d9-z7ltd 1/1 Running 0 131m

    $ kubectl get pods -n op-system

    NAME READY STATUS RESTARTS AGE
    skywalking-oap-dashboard-65f496ccc9-dr96l 1/1 Running 0 99m
    skywalking-oap-server-859694656b-p8vcq 1/1 Running 0 99m

    $ kubectl get pods -n app-system

    NAME READY STATUS RESTARTS AGE
    backend-6b9549bc64-f98tr 1/1 Running 0 99m
    backend-6b9549bc64-x2btl 1/1 Running 0 99m
    bff-766967f8db-8ght7 1/1 Running 0 99m
    bff-766967f8db-gflbh 1/1 Running 0 99m
    middle-6f4dd7bf6c-qdjqj 1/1 Running 0 99m
    middle-6f4dd7bf6c-stzf4 1/1 Running 0 99m

    $ kubectl get svc -n app-system

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    backend ClusterIP 10.96.179.140 <none> 80/TCP 99m
    bff ClusterIP 10.96.121.62 <none> 80/TCP 99m
    middle ClusterIP 10.96.55.8 <none> 80/TCP 99m


    $ kubectl get ingress -n higress-system

    NAME CLASS HOSTS ADDRESS PORTS AGE
    higress-console higress console.higress.io 80 34m
    higress-console-grafana higress console.higress.io 80 34m
    higress-console-prometheus higress console.higress.io 80 34m
    httpbin higress httpbin.example.com 80 8s
    skywalking-dashboard higress skywalking.higress.io 80 8s
    1. 测试 Higress Console, Skywalking Dashboard, Bff 服务

    1)编辑 /etc/hosts 文件添加以下三个域名

    127.0.0.1 console.higress.io
    127.0.0.1 skywalking.higress.io
    127.0.0.1 httpbin.example.com

    2)打开 higress-gateway 端口转发

    $ export KUBECONFIG=${HOME}/.kube/config_higress
    $ kubectl -n higress-system port-forward service/higress-gateway 8080:80

    3)通过浏览器打开访问上面三个域名

    Higress 控制台: http://console.higress.io:8080。首次访问控制台时需要先初始化管理员用户。初始化完成后使用对应的用户名密码登录即可。

    img.png

    Skywalking Dashboard: http://skywalking.higress.io:8080

    img.png

    Bff 服务: http://httpbin.example.com:8080/hostname

    img.png

    六、Higress 集成 Skywalking 调用链路跟踪配置

    通过修改 Higress configmap 全局配置 higress-config 来激活 Higress 集成 Skywalking 调用链路跟踪。

    $ export KUBECONFIG=${HOME}/.kube/config_higress
    $ kubectl edit configmap higgress-config -n higress-system

    在 data 下增加 higress 配置项然后保存,具体配置内容如下:

    data:
    higress: |-
    tracing:
    enable: true
    sampling: 100
    timeout: 500
    skywalking:
    service: skywalking-oap-server.op-system.svc.cluster.local
    port: 11800

    七、Skywalking 链路跟踪

    运行压测脚本

    for i in $(seq 1 1000)
    do
    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/hostname
    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/
    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/service?services=middle,backend
    done

    调用 bff 服务 /service 接口来模拟调用链路

    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/service?services=middle,backend

    部分返回响应体情况如下:

    {
    "args": {
    },
    "form": {
    },
    "headers": {
    "accept-encoding": "gzip",
    "sw8": "1-MzYzMzM1NDctNTc0YS00MzZlLTgzNWEtNTY1YTQyNzk3YTY3-ZWQ3ODA2ZjYwNTI0MTFlZWE5ZDdmZTFhNTA5YTRmYTk=-1-bWlkZGxl-bWlkZGxlLTZmNGRkN2JmNmMtcWJ4cm0=-L0dFVC9zZXJ2aWNl-aHR0cDovL2JhY2tlbmQv",
    "sw8-correlation": "",
    "user-agent": "Go-http-client/1.1",
    "x-httpbin-trace-host": "bff-766967f8db-jwn2g/middle-6f4dd7bf6c-qbxrm/backend-6b9549bc64-8twnx",
    "x-httpbin-trace-service": "bff/middle/backend",
    "x-request-id": "e5a1b250-ebe3-931d-91d7-90e3ee2fc867"
    },
    "method": "GET",
    "origin": "",
    "url": "/",
    "envs": {
    "NODE_NAME": "higress-worker2",
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "POD_IP": "10.244.1.7",
    "POD_NAME": "backend-6b9549bc64-8twnx",
    "POD_NAMESPACE": "app-system",
    "SERVICE_ACCOUNT": "backend",
    "SERVICE_NAME": "backend",
    "VERSION": "v1"
    },
    "host_name": "backend-6b9549bc64-8twnx",
    "body": ""
    }

    响应头中和调用链路跟踪相关有如下:

    "sw8": "1-MzYzMzM1NDctNTc0YS00MzZlLTgzNWEtNTY1YTQyNzk3YTY3-ZWQ3ODA2ZjYwNTI0MTFlZWE5ZDdmZTFhNTA5YTRmYTk=-1-bWlkZGxl-bWlkZGxlLTZmNGRkN2JmNmMtcWJ4cm0=-L0dFVC9zZXJ2aWNl-aHR0cDovL2JhY2tlbmQv",
    "x-httpbin-trace-host": "bff-766967f8db-jwn2g/middle-6f4dd7bf6c-qbxrm/backend-6b9549bc64-8twnx",
    "x-httpbin-trace-service": "bff/middle/backend",

    其中:

    • sw8: Skywalking 用于跟踪的 Http Header
    • x-httpbin-trace-host: 调用链路经过 POD_NAME
    • x-httpbin-trace-service: 调用链路经过 SERVICE_NAME

    在 Skywalking dashboard 中查看如下:

    • 服务截图

    img.png

    • 调用链路截图

    img.png

    • 调用链路拓扑截图

    img.png

    八、Higress gateway 指标和监控面板

    可以通过度量各个组件的性能指标,例如响应时间、吞吐量、错误率、资源使用率等指标来了解系统的状态和性能。

    指标数据包含指标名称,指标标签,和指标值,下面是 envoy_cluster_upstream_cx_total upstream(总连接数)部分指标数据,

    其中 envoy_cluster_upstream_cx_total 是指标名称,cluster_name 是指标标签,16 是指标值。

    # TYPE envoy_cluster_upstream_cx_total counter
    envoy_cluster_upstream_cx_total{cluster_name="outbound|80||bff.app-system.svc.cluster.local"} 16

    Higress 指标数据大体可以分为三类:

    • Downstream 下游: 指标与外来的连接/请求有关,主要由侦听器,HTTP连接管理器等
    • UpStream 上游: 指标与外向的连接/请求有关,主要由连接池,路由器,过滤器,熔断等
    • Server 负载: 指标信息记录 Higress gateway 服务器实例的负载等

    Higress 指标数据类型主要有三类:

    • Counter: 无符号整数,只会增加而不会减少。例如,总请求
    • Gauge: 增加和减少的无符号整数。例如,当前活动的请求
    • Histogram: 作为指标流的一部分的无符号整数,然后由收集器聚合以最终产生汇总的百分位值(percentile,即平常说的 P99/P50/Pxx)。例如,Upstream 响应时间

    通过以下命令可以获取 Higress gateway 支持的指标和类型

    $ export HIGRESS_GATEWAY_POD=$(kubectl get pods -l app=higress-gateway -o 'jsonpath={.items[0].metadata.name}' -n higress-system)
    $ kubectl exec "$HIGRESS_GATEWAY_POD" -n higress-system -- curl -sS http://127.0.0.1:15020/stats/prometheus | grep "# TYPE"

    部分指标内容如下:

    ...
    # TYPE envoy_cluster_upstream_cx_total counter
    # TYPE envoy_cluster_upstream_cx_tx_bytes_total counter
    # TYPE envoy_cluster_upstream_flow_control_backed_up_total counter
    # TYPE envoy_cluster_upstream_flow_control_drained_total counter
    # TYPE envoy_cluster_upstream_flow_control_paused_reading_total counter
    # TYPE envoy_cluster_upstream_flow_control_resumed_reading_total counter
    # TYPE envoy_cluster_upstream_internal_redirect_failed_total counter
    # TYPE envoy_cluster_upstream_internal_redirect_succeeded_total counter
    # TYPE envoy_cluster_upstream_rq counter
    # TYPE envoy_cluster_upstream_rq_101 counter
    # TYPE envoy_cluster_upstream_rq_200 counter
    # TYPE envoy_cluster_upstream_rq_201 counter
    # TYPE envoy_cluster_upstream_rq_301 counter
    # TYPE envoy_cluster_upstream_rq_302 counter
    # TYPE envoy_cluster_upstream_rq_304 counter
    # TYPE envoy_cluster_upstream_rq_401 counter
    # TYPE envoy_cluster_upstream_rq_404 counter
    # TYPE envoy_cluster_upstream_rq_cancelled counter
    # TYPE envoy_cluster_upstream_rq_completed counter
    # TYPE envoy_cluster_upstream_rq_maintenance_mode counter
    # TYPE envoy_cluster_upstream_rq_max_duration_reached counter
    # TYPE envoy_cluster_upstream_rq_pending_failure_eject counter
    # TYPE envoy_cluster_upstream_rq_pending_overflow counter
    # TYPE envoy_cluster_upstream_rq_pending_total counter
    # TYPE envoy_cluster_upstream_rq_per_try_idle_timeout counter
    # TYPE envoy_cluster_upstream_rq_per_try_timeout counter
    # TYPE envoy_cluster_upstream_rq_retry counter
    # TYPE envoy_cluster_upstream_rq_retry_backoff_exponential counter
    # TYPE envoy_cluster_upstream_rq_retry_backoff_ratelimited counter
    # TYPE envoy_cluster_upstream_rq_retry_limit_exceeded counter
    # TYPE envoy_cluster_upstream_rq_retry_overflow counter
    # TYPE envoy_cluster_upstream_rq_retry_success counter
    # TYPE envoy_cluster_upstream_rq_rx_reset counter
    # TYPE envoy_cluster_upstream_rq_timeout counter
    # TYPE envoy_cluster_upstream_rq_total counter
    # TYPE envoy_cluster_upstream_rq_tx_reset counter
    ...
    # TYPE envoy_http_downstream_cx_total counter
    # TYPE envoy_http_downstream_cx_tx_bytes_total counter
    # TYPE envoy_http_downstream_cx_upgrades_total counter
    # TYPE envoy_http_downstream_flow_control_paused_reading_total counter
    # TYPE envoy_http_downstream_flow_control_resumed_reading_total counter
    # TYPE envoy_http_downstream_rq counter
    # TYPE envoy_http_downstream_rq_completed counter
    # TYPE envoy_http_downstream_rq_failed_path_normalization counter
    # TYPE envoy_http_downstream_rq_header_timeout counter
    # TYPE envoy_http_downstream_rq_http1_total counter
    # TYPE envoy_http_downstream_rq_http2_total counter
    # TYPE envoy_http_downstream_rq_http3_total counter
    # TYPE envoy_http_downstream_rq_idle_timeout counter
    # TYPE envoy_http_downstream_rq_max_duration_reached counter
    # TYPE envoy_http_downstream_rq_non_relative_path counter
    # TYPE envoy_http_downstream_rq_overload_close counter
    # TYPE envoy_http_downstream_rq_redirected_with_normalized_path counter
    # TYPE envoy_http_downstream_rq_rejected_via_ip_detection counter
    # TYPE envoy_http_downstream_rq_response_before_rq_complete counter
    # TYPE envoy_http_downstream_rq_rx_reset counter
    # TYPE envoy_http_downstream_rq_timeout counter
    # TYPE envoy_http_downstream_rq_too_large counter
    # TYPE envoy_http_downstream_rq_total counter
    # TYPE envoy_http_downstream_rq_tx_reset counter
    # TYPE envoy_http_downstream_rq_ws_on_non_ws_route counter
    ...

    具体指标定义参考如下:

    如何查看 Higress 指标数据:

    通过 Skywalking Dashboard 查看 Higress gateway 监控数据部分截图如下:

    img.png img.png img.png

    参考文档

    · 阅读需 9 分钟

    开源之夏介绍

    开源之夏是由中科院软件所“开源软件供应链点亮计划”发起并长期支持的一项暑期开源活动,旨在鼓励在校学生积极参与开源软件的开发维护,培养和发掘更多优秀的开发者,促进优秀开源软件社区的蓬勃发展,助力开源软件供应链建设。

    目前开源之夏官网已经开启了学生报名,只要你满足以下要求即可进行项目申请:

    • 本活动面向年满 18 周岁在校学生。
    • 暑期即将毕业的学生,只要在申请时学生证处在有效期内,就可以提交申请。
    • 中国籍学生参与活动需提供身份证、学生证、教育部学籍在线验证报告(学信网)或在读证明。
    • 外籍学生参与活动需提供护照,同时提供录取通知书、学生卡、在读证明等文件用于证明学生身份。

    参与项目不仅可以为开源世界做出自己的贡献,还能获得丰厚的结项奖金(基础难度8000 RMB/进阶难度12000 RMB),项目经验也会成为你毕业简历上的亮点,快来报名吧!

    报名截止时间为 6 月 3 日 15 点,具体参考官网活动流程和参与指南介绍:

    Higress 介绍

    Higress 是基于阿里内部两年多的实践沉淀,以开源 Istio 与 Envoy 为核心构建的下一代云原生网关。Higress 实现了安全防护网关、流量网关、微服务网关三层网关合一,可以显著降低网关的部署和运维成本。

    Higress 在阿里内部的诞生和演进历程可以看这篇文章:

    阿里巴巴重磅开源云原生网关: Higress

    Higress 开源半年时间,GitHub star 数已经破千,在上个月 Higress 已经 Release 出了第一个 RC 版本,作为正式 GA 的候选发布版本,详情可以查看这篇文章:

    上线控制台,降低使用门槛|Higress 1.0.0 RC 版本发布

    在本次开源之夏活动中,Higress 有两个进阶难度的项目可以申请,欢迎各位同学踊跃报名。

    项目介绍

    项目一:Higress Wasm 插件构建/调试/部署的命令行实现

    Higress 提供了很方便的 Wasm 插件扩展框架,具体可以查看这篇文章: 30行代码写一个Wasm Go插件

    更详细的插件开发和调试流程可以查看这篇文章:使用 Go 语言开发 WASM 插件

    这里对插件的生效机制简单做个说明:

    1. 用户将代码编译成 wasm 文件
    2. 用户将 wasm 文件构建成 oci 镜像
    3. 用户将 oci 镜像推送至镜像仓库
    4. 用户创建 WasmPlugin 资源
    5. Istio watch 到 WasmPlugin 资源的变化
    6. Higress Gateway 中的 xDS proxy 进程从 Istio 获取到配置,发现插件的镜像地址
    7. xDS proxy 从镜像仓库拉取镜像
    8. xDS proxy 从镜像中提取出 wasm 文件
    9. Higress Gateway 中的 envoy 进程从 xDS proxy 获取到配置,发现 wasm 文件的本地路径
    10. envoy 从本地文件中加载 wasm 文件

    这里 envoy 获取配置并加载 wasm 文件使用到了 ECDS (Extension Config Discovery Service)的机制,实现了 wasm 文件更新,直接热加载,不会导致任何连接中断,业务流量完全无损。

    这个项目的初衷是希望能基于 Higress 的 CLI 命令行工具(hgctl) 来进一步简化 Higress Wasm 插件的开发调试和安装部署步骤,使之更容易上手使用。

    需要实现的 hgctl 命令如下:

    • hgctl plugin build:构建 wasm OCI 镜像并推送到指定仓库
    • hgctl plugin test:启动 docker compose 测试插件功能
    • hgctl plugin install/uninstall :在当前higress集群中安装或卸载插件
    • hgctl plugin config:修改制定插件的配置

    Higress Wasm 插件配置基于 Openapi Specification (OAS 3.0)进行约束,需要能从代码中解析出插件配置字段格式,自动生成对应的 OAS 约束,用于添加到 OCI 镜像中,并同时用于 install/uninstall/config 等命令的参数配置校验

    项目二:基于 Wasm 实现 OIDC 认证插件

    Higress 作为一个云原生网关,需要实现 OIDC 认证的能力,方便用户对接外部认证服务。

    OIDC (OpenID Connect) 是基于 OAuth 2.0 的身份认证协议,可以用于实现 SSO(Single Sign On)单点登录,即通过网关统一完成用户的身份认证,在身份认证成功后,再将资源请求转发给后端服务。

    流程简介如下:

    1. 客户端向网关发起认证请求。
    2. 网关将认证请求直接转发到给认证服务。
    3. 认证服务读取请求中的验证信息(例如用户名、密码)进行验证,验证通过后返回Code给网关。
    4. 网关将携带Code的应答返回给客户端。
    5. 客户端向网关请求回调接口,请求中携带Code。
    6. 网关请求认证服务颁发Token,请求中携带Code、Client ID、Client Secret。
    7. 认证服务验证合法性,并返回ID Token。
    8. 认证成功,网关将携带ID Token的应答返回给客户端。
    9. 客户端向网关发起业务请求,请求中携带ID Token,网关校验请求中是否携带ID Token和合法性。
    10. 网关校验客户端的业务请求合法,将请求透传给业务服务。
    11. 业务服务进行业务处理后应答。
    12. 网关将业务应答返回给客户端。

    目前 Higress 也可以基于 Envoy 的 Ext Authz 机制对接外置的 oauth2-proxy 来实现鉴权,不过这个方案一方面有额外的请求开销,另一方面 oauth2-proxy 只能作一组 OIDC 配置,无法对接多个不同的认证服务

    加入社区

    GitHub:https://github.com/alibaba/higress

    官网: https://higress.io

    对于报名方式有任何疑问,或者对某一个任务非常感兴趣,并且想要深入了解的同学,欢迎扫码添加微信,备注开源之夏

    相关项目推荐

    • 对于微服务注册发现和配置管理有兴趣的同学,可以尝试填报 Nacos 开源之夏;
    • 对于微服务分布式事务有兴趣的同学,可以尝试填报 Seata 开源之夏;
    • 对于微服务框架和RPC框架有兴趣的同学,可以尝试填报 Spring Cloud AlibabaDubbo 开源之夏;
    • 对于分布式高可用防护有兴趣的同学,可以尝试填报 Sentinel 开源之夏;
    • 对于微服务治理有兴趣的同学,可以尝试填报 OpenSergo 开源之夏。
    - + \ No newline at end of file diff --git a/zh-cn/blog/nacos/index.html b/zh-cn/blog/nacos/index.html index 59bd91531b..4287cd905c 100644 --- a/zh-cn/blog/nacos/index.html +++ b/zh-cn/blog/nacos/index.html @@ -14,7 +14,7 @@ - + @@ -40,7 +40,7 @@ image.png 社区交流群: higress-comm.png

    - + \ No newline at end of file diff --git a/zh-cn/blog/ospp-2023/index.html b/zh-cn/blog/ospp-2023/index.html index 8db8c6bdba..86b0ebc6db 100644 --- a/zh-cn/blog/ospp-2023/index.html +++ b/zh-cn/blog/ospp-2023/index.html @@ -14,13 +14,13 @@ - +

    Higress 开源之夏项目报名

    · 阅读需 9 分钟

    开源之夏介绍

    开源之夏是由中科院软件所“开源软件供应链点亮计划”发起并长期支持的一项暑期开源活动,旨在鼓励在校学生积极参与开源软件的开发维护,培养和发掘更多优秀的开发者,促进优秀开源软件社区的蓬勃发展,助力开源软件供应链建设。

    目前开源之夏官网已经开启了学生报名,只要你满足以下要求即可进行项目申请:

    • 本活动面向年满 18 周岁在校学生。
    • 暑期即将毕业的学生,只要在申请时学生证处在有效期内,就可以提交申请。
    • 中国籍学生参与活动需提供身份证、学生证、教育部学籍在线验证报告(学信网)或在读证明。
    • 外籍学生参与活动需提供护照,同时提供录取通知书、学生卡、在读证明等文件用于证明学生身份。

    参与项目不仅可以为开源世界做出自己的贡献,还能获得丰厚的结项奖金(基础难度8000 RMB/进阶难度12000 RMB),项目经验也会成为你毕业简历上的亮点,快来报名吧!

    报名截止时间为 6 月 3 日 15 点,具体参考官网活动流程和参与指南介绍:

    Higress 介绍

    Higress 是基于阿里内部两年多的实践沉淀,以开源 Istio 与 Envoy 为核心构建的下一代云原生网关。Higress 实现了安全防护网关、流量网关、微服务网关三层网关合一,可以显著降低网关的部署和运维成本。

    Higress 在阿里内部的诞生和演进历程可以看这篇文章:

    阿里巴巴重磅开源云原生网关: Higress

    Higress 开源半年时间,GitHub star 数已经破千,在上个月 Higress 已经 Release 出了第一个 RC 版本,作为正式 GA 的候选发布版本,详情可以查看这篇文章:

    上线控制台,降低使用门槛|Higress 1.0.0 RC 版本发布

    在本次开源之夏活动中,Higress 有两个进阶难度的项目可以申请,欢迎各位同学踊跃报名。

    项目介绍

    项目一:Higress Wasm 插件构建/调试/部署的命令行实现

    Higress 提供了很方便的 Wasm 插件扩展框架,具体可以查看这篇文章: 30行代码写一个Wasm Go插件

    更详细的插件开发和调试流程可以查看这篇文章:使用 Go 语言开发 WASM 插件

    这里对插件的生效机制简单做个说明:

    1. 用户将代码编译成 wasm 文件
    2. 用户将 wasm 文件构建成 oci 镜像
    3. 用户将 oci 镜像推送至镜像仓库
    4. 用户创建 WasmPlugin 资源
    5. Istio watch 到 WasmPlugin 资源的变化
    6. Higress Gateway 中的 xDS proxy 进程从 Istio 获取到配置,发现插件的镜像地址
    7. xDS proxy 从镜像仓库拉取镜像
    8. xDS proxy 从镜像中提取出 wasm 文件
    9. Higress Gateway 中的 envoy 进程从 xDS proxy 获取到配置,发现 wasm 文件的本地路径
    10. envoy 从本地文件中加载 wasm 文件

    这里 envoy 获取配置并加载 wasm 文件使用到了 ECDS (Extension Config Discovery Service)的机制,实现了 wasm 文件更新,直接热加载,不会导致任何连接中断,业务流量完全无损。

    这个项目的初衷是希望能基于 Higress 的 CLI 命令行工具(hgctl) 来进一步简化 Higress Wasm 插件的开发调试和安装部署步骤,使之更容易上手使用。

    需要实现的 hgctl 命令如下:

    • hgctl plugin build:构建 wasm OCI 镜像并推送到指定仓库
    • hgctl plugin test:启动 docker compose 测试插件功能
    • hgctl plugin install/uninstall :在当前higress集群中安装或卸载插件
    • hgctl plugin config:修改制定插件的配置

    Higress Wasm 插件配置基于 Openapi Specification (OAS 3.0)进行约束,需要能从代码中解析出插件配置字段格式,自动生成对应的 OAS 约束,用于添加到 OCI 镜像中,并同时用于 install/uninstall/config 等命令的参数配置校验

    项目二:基于 Wasm 实现 OIDC 认证插件

    Higress 作为一个云原生网关,需要实现 OIDC 认证的能力,方便用户对接外部认证服务。

    OIDC (OpenID Connect) 是基于 OAuth 2.0 的身份认证协议,可以用于实现 SSO(Single Sign On)单点登录,即通过网关统一完成用户的身份认证,在身份认证成功后,再将资源请求转发给后端服务。

    流程简介如下:

    1. 客户端向网关发起认证请求。
    2. 网关将认证请求直接转发到给认证服务。
    3. 认证服务读取请求中的验证信息(例如用户名、密码)进行验证,验证通过后返回Code给网关。
    4. 网关将携带Code的应答返回给客户端。
    5. 客户端向网关请求回调接口,请求中携带Code。
    6. 网关请求认证服务颁发Token,请求中携带Code、Client ID、Client Secret。
    7. 认证服务验证合法性,并返回ID Token。
    8. 认证成功,网关将携带ID Token的应答返回给客户端。
    9. 客户端向网关发起业务请求,请求中携带ID Token,网关校验请求中是否携带ID Token和合法性。
    10. 网关校验客户端的业务请求合法,将请求透传给业务服务。
    11. 业务服务进行业务处理后应答。
    12. 网关将业务应答返回给客户端。

    目前 Higress 也可以基于 Envoy 的 Ext Authz 机制对接外置的 oauth2-proxy 来实现鉴权,不过这个方案一方面有额外的请求开销,另一方面 oauth2-proxy 只能作一组 OIDC 配置,无法对接多个不同的认证服务

    加入社区

    GitHub:https://github.com/alibaba/higress

    官网: https://higress.io

    对于报名方式有任何疑问,或者对某一个任务非常感兴趣,并且想要深入了解的同学,欢迎扫码添加微信,备注开源之夏

    相关项目推荐

    • 对于微服务注册发现和配置管理有兴趣的同学,可以尝试填报 Nacos 开源之夏;
    • 对于微服务分布式事务有兴趣的同学,可以尝试填报 Seata 开源之夏;
    • 对于微服务框架和RPC框架有兴趣的同学,可以尝试填报 Spring Cloud AlibabaDubbo 开源之夏;
    • 对于分布式高可用防护有兴趣的同学,可以尝试填报 Sentinel 开源之夏;
    • 对于微服务治理有兴趣的同学,可以尝试填报 OpenSergo 开源之夏。
    - + \ No newline at end of file diff --git a/zh-cn/blog/page/2/index.html b/zh-cn/blog/page/2/index.html index 0173d1b496..727585f81b 100644 --- a/zh-cn/blog/page/2/index.html +++ b/zh-cn/blog/page/2/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    · 阅读需 7 分钟

    前言

    历时 5 个多月,Higress 推出了首个 RC (Release Candidate,即正式发布的候选)版本 1.0.0-rc,用户可以通过控制台,开箱即用地使用云原生网关。

    选用 Higress 作为云原生网关的核心优势如下:

    • 易用性

      “云原生”已经不再是一个新鲜词,但企业对云原生技术的学习使用成本仍有许多顾虑,对云原生新标准的追赶又有很多焦虑;

      Higress 同时提供了本地安装/生产部署的 quickstart,可以一键部署,并通过控制台操作快速上手;基于简单易用的控制台,Higress 可以封装 Ingress/Gateway API 的标准细节,根治技术追赶焦虑。

    • 标准化

      K8s 带来了云原生的路由标准 Ingress/Gateway API,如同 POSIX 定义 Unix 可移植操作系统标准,历时 35 年经久不衰,云原生的路由标准的生命周期一定会远超过 K8s 本身;

      Higress 结合阿里内部实践以及阿里云产品沉淀,积累了基于 Ingress API 的丰富的路由策略扩展能力,同时还兼容大部分 Nginx Ingress 能力,这些能力后续也将在 Gateway API 上支持。

    • 高集成

      企业内有大量传统架构部署的服务,会成为向云原生架构演进的技术负担,要求云原生网关具备对接异构服务架构的能力;

      基于 Higress 提供的多种服务发现机制,网关路由不仅可以转发到 K8s 服务,也可以直接配置 IP 转发到到物理机上的服务;基于 Nacos/ZooKeeper 等注册中心对接,还可以轻松实现 Spring CloudDubbo 微服务的路由,无论其是否部署在 K8s 内。

    • 易扩展

      基于扩展机制进行二次开发的能力,是云原生网关在不同业务场景下都能适配落地的关键;

      Higress提供了灵活的插件扩展机制,目前插件市场已经推出多个官方插件,并支持用户通过控制台直接上传自己开发的插件,同时开源社区的插件市场生态也在不断建设中。

    • 热更新

      传统 Nginx 更新规则需要 reload 会导致链接抖动,导致流量损失,对实时通信、视频、IOT无法容忍;

      对于路由规则,Wasm 插件逻辑更新,以及证书改动等等,Higress 全部支持热更新,不会造成任何连接抖动。

    企业落地支持

    在 RC 版本阶段使用 Higress 的企业用户,社区会在落地阶段提供更多帮助,我们建立了 Higress 企业落地群,可以联系我(微信:nomadao 钉钉:chengtanzty),会将你加进群,群里有社区核心研发同学,可以提供更及时的响应和帮助。

    安装升级方式

    安装 RC 版本,需要 helm 安装升级时需要指定--devel参数,例如:helm upgrade higress -n higress-system --devel

    1.0.0 RC 版本已经在社区小伙伴的协作下完成了多轮测试和修复工作,欢迎大家使用。最终的正式版本,也将在近期很快推出。

    控制台功能速览

    • 丰富的可观测

      提供开箱即用的可观测,Grafana&Prometheus 可以使用内置的也可对接自建的,具体可以参考文档

    • 插件扩展机制

      官方提供了多种插件,用户也可以开发自己的插件,构建成 docker/oci 镜像后在控制台配置,可以实时变更插件逻辑,对流量完全无损。

    • 多种服务发现

      默认提供 K8s Service 服务发现,通过配置可以对接 Nacos/ZooKeeper 等注册中心实现服务发现,也可以基于静态 IP 或者 DNS 来发现

    • 域名和证书

      可以创建管理 TLS 证书,并配置域名的 HTTP/HTTPS 行为,域名策略里支持对特定域名生效插件

    • 丰富的路由能力

      基于上面配置的服务发现机制,发现的服务会出现在服务列表中;创建路由时,选择域名,定义路由匹配机制,再选择目标服务进行路由;路由策略里支持对特定路由生效插件

    进阶使用

    Higress 控制台的功能还在不断丰富和演进中,当前还有很多 Higress Ingress 注解的能力没有支持,如果有这部分深度使用的需求,可以参考这篇文档进行进阶配置

    如果希望使用 Istio 的能力进行流量治理,可以参考这篇文档的支持 Istio CRD 一节。基于 Istio 的 EnvoyFilter API 可以实现更多细粒度的管控能力。

    社区

    欢迎认领 Higress Issue 任务:https://github.com/alibaba/higress/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22

    完成一定数量的 Issues 就可以成为 Higress Committer,也有机会获得开源社区的礼物和荣誉🏆

    欢迎加入 Higress 社区群,及时了解更多 Higress 动向:

    · 阅读需 4 分钟

    UU跑腿介绍

    UU跑腿隶属于郑州时空隧道信息技术有限公司,是更专业的同城即时生活服务平台,以共享劳动力与时间为众包理念,人人都可注册成为跑腿师傅,并为附近的人提供帮取送、帮买、全能帮、帮排队等多样化同城即时服务,为中小企业、电商、本地商户提供安全专业的高端配送服务。UU跑腿秉承“让生活更美好”的理念,不断创新、不断进步,为用户提供更加优质的服务体验。

    背景需求

    UU跑腿对于云原生网关的要求是,能同时满足流量网关,微服务网关,以及安全网关的场景诉求,用一个网关来解决之前需要部署多个网关才能解决的问题:

    1. 具备高可靠性和高性能,可以替代之前部署的 Nginx Ingress 流量网关
    2. 同时支持 K8s 生态和传统微服务生态接入,支持(HTTP转Dubbo)协议转换,可以替代之前部署的 Spring Cloud Gateway 微服务网关
    3. 能够支持在网关入口处完成鉴权,避免每个后端服务重复实现鉴权功能,实现安全网关的能力
    4. 具备易用的控制台进行 API 的治理,以及具备丰富的可观测指标

    迁移 Higress 前的架构

    old-arch

    之前存在的主要痛点:

    1. Spring Cloud Gateway 自身参数调整改动需要重新部署影响流量,且动态路由需要进行复杂的配置,包括路由规则,容易出现配置错误导致系统异常
    2. 运维需要同时维护 Nginx Ingress 和 Spring Cloud Gateway,面对流量高峰进行进行扩容相关操作时,运维负担比较重,而且这样两层网关的请求的链路较长,可用性低、成本高

    迁移 Higress 后的架构

    new-arch

    Higress云原生网关实现负载均衡、路由、安全认证等功能。通过网关对外提供服务统一入口,并对请求进行鉴权、限流和监控等操作,用简单的架构保证了整体系统的稳定性和可靠性。

    1. 合并流量网关(K8s Nginx Ingress)和微服务网关(Spring Cloud Gateway ),降低网关成本,高性能服务;
    2. 同时支持 K8s service 和 Nacos 服务注册发现,满足技术需求对 K8s 生态和传统微服务生态接入。
    3. Nginx Ingress 完美迁移到 Higress,十分丝滑

    · 阅读需 5 分钟

    进展概要

    1. Higress 控制台正式 release,涵盖 Higress 的服务/路由/域名/证书管理能力,并提供开箱即用的可观测功能
    2. 安装/升级 Higress 时支持自动安装对应版本的 Higress Console,避免版本不适配的问题
    3. 支持开启 Istio API,实现更多复杂的功能,并且也可以用于平滑替换 Istio Ingress Gateway

    版本特性

    Higress 控制台

    现在通过 helm 命令安装 Higress 时将自动安装对应版本的 Higress Console, 这里通过 higress-console.domain 参数,可以指定控制台的域名。

    # 已经添加过 repo 的,请执行 helm repo update
    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io

    image

    注意:安装完成后会输出一段文本,其中包含获取控制台登录信息的命令。请执行该命令并记录用户名和密码。

    image

    正式环境部署时,建议控制台开启强制 HTTPS 访问,具体操作方式是,在 higress-system 命名空间下先创建好 TLS 证书和私钥对应的 secret,例如:

    apiVersion: v1
    kind: Secret
    type: kubernetes.io/tls
    data:
    tls.crt: -----BEGIN CERTIFICATE-----...
    tls.key: -----BEGIN RSA PRIVATE KEY-----...
    metadata:
    name: my-tls-secret
    namespace: higress-system

    然后通过下面 helm 命令开启强制 HTTPS 访问

    helm upgrade higress -n higress-system higress.io/higress --set higress-console.tlsSecretName=my-tls-secret

    如果希望启用 Higress 自带的 Prometheus&Grafana,可以通过下面 helm 命令进行安装:

    helm upgrade higress -n higress-system higress.io/higress --set higress-console.o11y.enabled=true

    这样 Higress 控制台就可以看到自带的可观测大盘了:

    image

    当然,你也可以对接已有的 Prometheus&Grafana,使用这份 Higress 官方提供的 Dashboard 配置即可:https://higress.io/grafana/dashboard.json

    可以登陆 Higress 控制台 Demo 试用现有所有功能: http://demo.higress.io

    开启 Istio API

    通过开启 Istio API,可以实现使用 Higress 平滑替换 Istio Ingress Gateway,具体 helm 命令如下:

    helm upgrade higress -n higress-system higress.io/higress --set global.enableIstioAPI=true

    基于 Istio API,可以实现目前 Higress 还未提供相应 Ingress 注解的能力,例如基于 Istio EnvoyFilter 来实现 HTTP to Dubbo 的协议转换配置方式:

    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
    name: http-dubbo-transcoder
    namespace: higress-system
    spec:
    configPatches:
    - applyTo: HTTP_FILTER
    match:
    context: GATEWAY
    listener:
    filterChain:
    filter:
    name: envoy.filters.network.http_connection_manager
    subFilter:
    name: envoy.filters.http.router
    patch:
    operation: INSERT_BEFORE
    value:
    name: envoy.filters.http.http_dubbo_transcoder
    typed_config:
    '@type': type.googleapis.com/udpa.type.v1.TypedStruct
    type_url: type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder
    - applyTo: HTTP_ROUTE
    match:
    context: GATEWAY
    routeConfiguration:
    vhost:
    route:
    name: test
    patch:
    operation: MERGE
    value:
    route:
    upgrade_configs:
    - connect_config:
    allow_post: true
    upgrade_type: CONNECT
    typed_per_filter_config:
    envoy.filters.http.http_dubbo_transcoder:
    '@type': type.googleapis.com/udpa.type.v1.TypedStruct
    type_url: type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder
    value:
    request_validation_options:
    reject_unknown_method: true
    reject_unknown_query_parameters: true
    services_mapping:
    - group: dev
    method_mapping:
    - name: sayName
    parameter_mapping:
    - extract_key: p
    extract_key_spec: ALL_QUERY_PARAMETER
    mapping_type: java.lang.String
    passthrough_setting:
    passthrough_all_headers: true
    path_matcher:
    match_http_method_spec: ALL_GET
    match_pattern: /dubbo/hello
    name: com.alibaba.nacos.example.dubbo.service.DemoService
    version: 1.0.0
    url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED

    上述配置比较复杂,原因是为了方便 Envoy 数据面程序逻辑处理而设计的 Schema。目前 Higress 社区已经在设计更方便 Ingress 配置使用的 CRD,后续也会在 Higress 控制台上提供对应的配置功能。

    GA 版本规划

    Higress 预计将在3月底/4月初发布首个 GA 版本, 这个版本的主要规划如下:

    1. 实现 HTTP to Dubbo 协议转换的控制面配置简化
    2. Higress 控制台提供 Wasm 插件能力,支持配置自定义插件
    3. 推出第一版 Higress Admin API,可以被其他平台/工具集成
    4. 全面完善 Higress 官网文档,覆盖 Higress 全部功能的详细说明

    Higress 社区

    欢迎认领 Higress Issue 任务:https://github.com/alibaba/higress/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22

    完成一定数量的 Issues 就可以成为 Higress Committer,也有机会获得开源社区的礼物和荣誉🏆

    欢迎加入 Higress 社区群,及时了解更多 Higress 动向:

    · 阅读需 14 分钟

    前言

    在11月15号的直播 《Higress 开源背后的发展历程和上手 Demo 演示》中,为大家演示了 Higress 的 Wasm 插件如何面向 Ingress 资源进行配置生效,本文对当天的 Demo 进行一个回顾,并说明背后的原理机制。

    - + \ No newline at end of file diff --git a/zh-cn/blog/plugin-transformer/index.html b/zh-cn/blog/plugin-transformer/index.html index 981fe12803..35ae28d2c0 100644 --- a/zh-cn/blog/plugin-transformer/index.html +++ b/zh-cn/blog/plugin-transformer/index.html @@ -14,14 +14,14 @@ - +

    通过 Higress Wasm 插件 3 倍性能实现 Spring-cloud-gateway 功能

    · 阅读需 11 分钟

    导读: 本文将和大家一同回顾 Spring Cloud Gateway 是如何满足 HTTP 请求/响应转换需求场景的,并为大家介绍在这种场景下使用 Higress 云原生网关的解决方案,同时还对比了两者的性能差异。

    1. SCG 修改请求/响应

    Spring Cloud Gateway (以下简称为 SCG) 中,当我们需要对 HTTP 请求或响应进行修改时,SCG 提供了许多内置的 GatewayFilter 来满足我们对这种应用场景的需求,例如 AddRequestHeader,AddRequestParameter, DedupeResponseHeader,MapRequestHeader, ModifyRequestBody 等。

    考虑以下简单用例:

    • 添加请求头部 X-First,值从请求路径中获取,例如从 /response-headers?testKey=testValue 中获取 "response-headers";
    • 将请求头部 X-First 的值映射给 X-Second;
    • 添加请求查询参数 k1=v1;
    • 剔除重复的响应头部 X-Dedupe。

    在 SCG 中使用 GatewayFilter 我们可以这样配置:

    # application.yaml:

    spring:
    cloud:
    gateway:
    routes:
    - id: test_route
    uri: lb://httpbin-svc
    predicates:
    - Path=/{api}/**
    filters:
    - AddRequestHeader=X-First, {api}
    - MapRequestHeader=X-First, X-Second
    - AddRequestParameter=k1, v1
    - DedupeResponseHeader=X-Dedupe, RETAIN_FIRST

    相信拥有 SCG 使用经验的同学对上述配置一定不陌生,那么本文将重点给出另一种能够满足上述需求并且性能更加优越的解决方案——使用 Higress 云原生网关的 Transformer 插件

    2. Higress 插件与 SCG 性能比较

    我们在同一吞吐量水平(QPS)上,开启/关闭 Higress Transformer 插件 和 SCG 相应 GatewayFilters,统计两者在 CPU 和内存资源上的开销。

    经过测试,我们得到的结论是:

    • 在 Higress 未启用 Transformer 插件,SCG 未启用 GatewayFilters 的条件下,SCG 的 CPU, 内存资源开销分别约为 Higress的 3.30, 4.88倍;
    • 在 Higress 启用 Transformer 插件,SCG 启用相应 GatewayFilters 的条件下,SCG 的 CPU,内存资源开销分别约为 Higress 的 2.98, 3.19倍。

    相同 QPS 下的 CPU 开销

    相同 QPS 下的内存开销

    可见 Higress Transformer 相比于 SCG GatewayFilter 有着相当不错的性能表现!

    接下来我们将进一步为大家介绍 Higress 云原生网关以及上述提到的 Higress Transformer 插件。

    3. Higress 简介

    Higress 是基于阿里内部的 Envoy Gateway 实践沉淀、以开源 Istio + Envoy 为核心构建的下一代云原生网关,实现了流量网关+微服务网关+安全网关三合一的高集成能力,深度集成 Dubbo、Nacos、Sentinel 等微服务技术栈,能够帮助用户极大地降低网关的部署及运维成本且能力不打折;在标准上全面支持 Ingress 与 Gateway API,积极拥抱云原生下的标准 API 规范;同时,Higress Controller 也支持 Nginx Ingress 平滑迁移,帮助用户零成本快速迁移到 Higress。 Higress 提供了一套 Wasm (WebAssembly) SDK,使得开发者能够轻松使用 C++,Golang,Rust 开发 Wasm 插件增强网关能力。下面将为大家介绍 Higress Transformer 插件的基本功能,最后简单说明 Transformer 插件的核心代码逻辑。

    Higress Architecture

    4. Transformer 插件介绍

    Higress Transformer 插件可以对请求/响应头部、请求查询参数、请求/响应体参数进行转换,支持的转换操作类型包括删除(remove)、重命名(rename)、更新(replace)、添加(add)、追加(append)、映射(map)和去重(dedupe)。

    接下来我们复现最开始提到的 SCG GatewayFilter 简单用例,来演示如何使用该插件(以下使用 Higress 控制台可以很方便地部署插件,当然也可以使用 K8s YAML Manifests 的方式):

    1. 首先根据官方文档 快速安装 Higress,结果如下:
    $ kubectl -n higress-system get deploy
    NAME READY UP-TO-DATE AVAILABLE AGE
    higress-console 1/1 1 1 1d
    higress-console-grafana 1/1 1 1 1d
    higress-console-prometheus 1/1 1 1 1d
    higress-controller 1/1 1 1 1d
    higress-gateway 1/1 1 1 1d
    1. 通过 Higress 控制台添加域名(foo.bar.com)、路由配置(foo),将流量转发至后端的 httpbin 服务:

    image

    image

    1. 为 foo 路由添加 Transformer 插件(当前未推送插件至官方镜像仓库,可以先使用 docker.io/weixinx/transformer:v0.1.0,或到代码仓库自行构建):

    image

    注:为了能够同时完成请求和响应转换的需求,我们需要为 foo 路由再添加一个 Transformer 插件,命名为 transformer-resp,用于处理响应方向。

    1. 添加 Transformer 配置并开启该插件:
    • 添加请求头部 X-First,值从请求路径中获取,例如从 /response-headers?testKey=testValue 中获取 "response-headers";
    • 将请求头部 X-First 的值映射给 X-Second;
    • 添加请求查询参数 k1=v1;
    • 剔除重复的响应头部 X-Dedupe。
    # transformer:
    type: request # 指定 Transformer 类型
    rules: # 指定转换规则
    - operate: add # 指定转换操作类型
    headers: # 指定头部转换规则
    - key: X-First
    value: $1 # 正则表达式捕获组 $1,支持 RE2 语法
    path_pattern: ^\/(\w+)[\?]{0,1}.*$
    querys: # 指定查询参数转换规则
    - key: k1
    value: v1
    - operate: map
    headers:
    - key: X-First
    value: X-Second
    ---
    # transformer-resp:
    type: response
    rules:
    - operate: dedupe
    headers:
    - key: X-Dedupe
    value: RETAIN_FIRST
    1. 发送请求进行测试:
    # 验证请求方向转换
    $ curl -v -H "host: foo.bar.com" "console.higress.io/get"
    ...
    >
    < HTTP/1.1 200 OK
    ...
    <
    {
    "args": {
    # 添加了查询参数 k1=v1
    "k1": "v1"
    },
    "headers": {
    ...
    "X-First": "get", # 添加了请求头部 X-First,值 "get" 来自请求路径
    "X-Second": "get" # 映射了请求头部 X-Second
    },
    ...
    # 添加了查询参数 k1=v1
    "url": "http://foo.bar.com/get?k1=v1"
    }


    # 验证响应方向转换
    $ curl -v -H "host: foo.bar.com" \
    "console.higress.io/response-headers?X-Dedupe=1&X-Dedupe=2&X-Dedupe=3"
    ...
    >
    < HTTP/1.1 200 OK
    < x-dedupe: 1 # 保留了响应头部 X-Dedupe 的第一个值
    ...
    <
    {
    ...
    # 通过查询参数传给 httpbin 的自定义响应头部
    "X-Dedupe": [
    "1",
    "2",
    "3"
    ],
    ...
    }

    ❗️需要注意的是:

    • 与上述例子相同,若有同时处理请求和响应转换的需求,则需要为相应路由添加两个 Transformer 插件,分别处理请求方向和响应方向(正在优化);
    • 请求体支持的 Content-Type 有:application/json, application/x-www-form-urlencoded, multipart/form-data;而响应体仅支持 application/json;
    • 更多说明详见插件文档

    5. Transformer 逻辑

    本节将简单说明 Higress Transformer 插件的核心代码逻辑,希望可以为有兴趣优化该插件或进行二次开发的同学提供一些帮助。

    首先该插件代码位于Higress 仓库的 plugins/wasm-go/extensions/transformer 目录下,使用 Higress 提供的 Wasm SDK 进行开发(关于如何开发 Wasm 插件详见官方文档)。

    插件的配置模型 TransformerConfig:

    # 模型以插件配置的形式暴露给用户
    type TransformerConfig struct {
    typ string # Transformer 类型,[request, response]
    rules []TransformRule # 转换规则

    trans Transformer # Transformer 实例,不对用户暴露配置,用于实际的转换操作
    }

    type TransformRule struct {
    operate string # 转换操作类型
    headers []Param # header 参数
    querys []Param # query 参数
    body []Param # body 参数
    }

    type Param struct {
    key string # 表示字段的 key
    value string # 表示字段的 value 或 key (map) 或 strategy (dedupe)
    valueType string # 为 application/json body 指定 value 的数据类型
    hostPattern string # host 正则匹配模式
    pathPattern string # path 正则匹配模式
    }

    其中 Transformer 作为接口分别有请求和响应两个实现(requestTransformer, responseTransformer),主要实现了 3 个接口方法 TransformHeaders,TransformerQuerys 和 TransformBody:

    type Transformer interface {
    TransformHeaders(host, path string, hs map[string][]string) error
    TransformQuerys(host, path string, qs map[string][]string) error
    TransformBody(host, path string, body interface{}) error
    ...
    }

    var _ Transformer = (*requestTransformer)(nil)
    var _ Transformer = (*responseTransformer)(nil)

    由于头部(Headers)和查询参数(Querys)都是以 key-value 的形式存在,因此通过 kvHandler 对两者采用统一的处理逻辑;而 Body 由于请求、响应支持不同的 Content-Type,因此分别通过 requestBodyHandler (kvHandler, jsonHandler 组合)和 responseBodyHandler (jsonHandler) 进行处理。综上,在修改该插件逻辑时,主要对 kvHandler 和 jsonHandler 进行修改即可,其中 jsonHandler 依赖 GJSONSJSON 工具库。

    image

    目前 handler 中的转换顺序是被硬编码的(remove -> rename -> replace -> add -> append -> map -> dedupe),我们对此有优化的打算,也欢迎感兴趣的同学参与进来 ~

    6. 总结

    本文带大家了解了 Higress Transformer 插件,并与 Spring Cloud Gateway 进行了性能比较,在文章的最后还说明了该插件的核心代码逻辑,希望能够为大家从 Spring Cloud Gateway 迁移至 Higress 提供帮助!

    image

    如果您觉得 Higress 对您有帮助,欢迎前往 Github: Higress 为我们 star⭐️ 一下!期待与您在 Higress 社区相遇 ~

    - + \ No newline at end of file diff --git a/zh-cn/blog/release-070/index.html b/zh-cn/blog/release-070/index.html index 4cccf23c94..484564276f 100644 --- a/zh-cn/blog/release-070/index.html +++ b/zh-cn/blog/release-070/index.html @@ -14,13 +14,13 @@ - +

    Higress 0.7.0 版本发布:GA 进入倒计时

    · 阅读需 5 分钟

    进展概要

    1. Higress 控制台正式 release,涵盖 Higress 的服务/路由/域名/证书管理能力,并提供开箱即用的可观测功能
    2. 安装/升级 Higress 时支持自动安装对应版本的 Higress Console,避免版本不适配的问题
    3. 支持开启 Istio API,实现更多复杂的功能,并且也可以用于平滑替换 Istio Ingress Gateway

    版本特性

    Higress 控制台

    现在通过 helm 命令安装 Higress 时将自动安装对应版本的 Higress Console, 这里通过 higress-console.domain 参数,可以指定控制台的域名。

    # 已经添加过 repo 的,请执行 helm repo update
    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io

    image

    注意:安装完成后会输出一段文本,其中包含获取控制台登录信息的命令。请执行该命令并记录用户名和密码。

    image

    正式环境部署时,建议控制台开启强制 HTTPS 访问,具体操作方式是,在 higress-system 命名空间下先创建好 TLS 证书和私钥对应的 secret,例如:

    apiVersion: v1
    kind: Secret
    type: kubernetes.io/tls
    data:
    tls.crt: -----BEGIN CERTIFICATE-----...
    tls.key: -----BEGIN RSA PRIVATE KEY-----...
    metadata:
    name: my-tls-secret
    namespace: higress-system

    然后通过下面 helm 命令开启强制 HTTPS 访问

    helm upgrade higress -n higress-system higress.io/higress --set higress-console.tlsSecretName=my-tls-secret

    如果希望启用 Higress 自带的 Prometheus&Grafana,可以通过下面 helm 命令进行安装:

    helm upgrade higress -n higress-system higress.io/higress --set higress-console.o11y.enabled=true

    这样 Higress 控制台就可以看到自带的可观测大盘了:

    image

    当然,你也可以对接已有的 Prometheus&Grafana,使用这份 Higress 官方提供的 Dashboard 配置即可:https://higress.io/grafana/dashboard.json

    可以登陆 Higress 控制台 Demo 试用现有所有功能: http://demo.higress.io

    开启 Istio API

    通过开启 Istio API,可以实现使用 Higress 平滑替换 Istio Ingress Gateway,具体 helm 命令如下:

    helm upgrade higress -n higress-system higress.io/higress --set global.enableIstioAPI=true

    基于 Istio API,可以实现目前 Higress 还未提供相应 Ingress 注解的能力,例如基于 Istio EnvoyFilter 来实现 HTTP to Dubbo 的协议转换配置方式:

    apiVersion: networking.istio.io/v1alpha3
    kind: EnvoyFilter
    metadata:
    name: http-dubbo-transcoder
    namespace: higress-system
    spec:
    configPatches:
    - applyTo: HTTP_FILTER
    match:
    context: GATEWAY
    listener:
    filterChain:
    filter:
    name: envoy.filters.network.http_connection_manager
    subFilter:
    name: envoy.filters.http.router
    patch:
    operation: INSERT_BEFORE
    value:
    name: envoy.filters.http.http_dubbo_transcoder
    typed_config:
    '@type': type.googleapis.com/udpa.type.v1.TypedStruct
    type_url: type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder
    - applyTo: HTTP_ROUTE
    match:
    context: GATEWAY
    routeConfiguration:
    vhost:
    route:
    name: test
    patch:
    operation: MERGE
    value:
    route:
    upgrade_configs:
    - connect_config:
    allow_post: true
    upgrade_type: CONNECT
    typed_per_filter_config:
    envoy.filters.http.http_dubbo_transcoder:
    '@type': type.googleapis.com/udpa.type.v1.TypedStruct
    type_url: type.googleapis.com/envoy.extensions.filters.http.http_dubbo_transcoder.v3.HttpDubboTranscoder
    value:
    request_validation_options:
    reject_unknown_method: true
    reject_unknown_query_parameters: true
    services_mapping:
    - group: dev
    method_mapping:
    - name: sayName
    parameter_mapping:
    - extract_key: p
    extract_key_spec: ALL_QUERY_PARAMETER
    mapping_type: java.lang.String
    passthrough_setting:
    passthrough_all_headers: true
    path_matcher:
    match_http_method_spec: ALL_GET
    match_pattern: /dubbo/hello
    name: com.alibaba.nacos.example.dubbo.service.DemoService
    version: 1.0.0
    url_unescape_spec: ALL_CHARACTERS_EXCEPT_RESERVED

    上述配置比较复杂,原因是为了方便 Envoy 数据面程序逻辑处理而设计的 Schema。目前 Higress 社区已经在设计更方便 Ingress 配置使用的 CRD,后续也会在 Higress 控制台上提供对应的配置功能。

    GA 版本规划

    Higress 预计将在3月底/4月初发布首个 GA 版本, 这个版本的主要规划如下:

    1. 实现 HTTP to Dubbo 协议转换的控制面配置简化
    2. Higress 控制台提供 Wasm 插件能力,支持配置自定义插件
    3. 推出第一版 Higress Admin API,可以被其他平台/工具集成
    4. 全面完善 Higress 官网文档,覆盖 Higress 全部功能的详细说明

    Higress 社区

    欢迎认领 Higress Issue 任务:https://github.com/alibaba/higress/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22

    完成一定数量的 Issues 就可以成为 Higress Committer,也有机会获得开源社区的礼物和荣誉🏆

    欢迎加入 Higress 社区群,及时了解更多 Higress 动向:

    - + \ No newline at end of file diff --git a/zh-cn/blog/release-1.3/index.html b/zh-cn/blog/release-1.3/index.html index 5b984dc2a7..cc484f1326 100644 --- a/zh-cn/blog/release-1.3/index.html +++ b/zh-cn/blog/release-1.3/index.html @@ -14,14 +14,14 @@ - +

    Higress 开源一周年:新版本,新标准,新工具,新征程

    · 阅读需 19 分钟

    历程回顾

    image

    Higress 开源一年时间,一共发布了 18 个 release 版本,收获了 40 多位社区贡献者和 1800+ star,上图是这一年过来达成的一些关键的里程碑。

    前面半年通过集成开源生态,打磨开源版本稳定性,并在发布 1.0 GA 版本后,社区又马不停蹄发布了 1.1 和 1.2 两个重要版本,实现了非 K8s 部署,Knative 适配等核心能力。

    Higress 1.3 版本已经正式发布,除了增加的新功能,已有能力也在大量社区用户反馈的过程中不断完善改进,这个版本同时标志着 1.x 进入可以大规模生产使用的状态。

    新版本:功能速览

    自发布 1.2 版本过去了一个多月时间,1.3 版本正式发布,带来两个全新能力:

    • 新标准:支持最新版本 Gateway API 标准,并且具备从 Ingress 平滑渐进演进,以及对接多种服务发现机制的能力
    • 新工具:正式 release 了 hgctl (Higress Crontroller) 这个 "All in one" 的新工具,不仅可以替代 Helm 实现更简易的安装,还提供了 WASM 插件开发工具包,以及网关配置检查等丰富功能

    除了这两个核心功能外,还有一些实用功能:

    1. 提供了 Higress Admin Java SDK,可以统一对接 K8s 和非 K8s 环境,管理域名/路由等配置
    2. 提供了 OIDC 插件,支持对接 Keycloak/Okta 等第三方身份认证系统
    3. Higress Console 的易用性和安全性提升,不再通过路由暴露,支持界面初始化/修改密码

    与此同时,Higress 开源社区已经开始准备踏上一段全新的开源征程...

    新标准:支持最新版 Gateway API

    Gateway API 在 11 月 1 日正式发布了 1.0.0 版本,其中 GatewayClass, Gateway, HTTPRoute 这三个 API正式宣布 GA,发布了 v1 版本:gateway.networking.k8s.io/v1。

    目前 Higress 已经可以支持这些最新版本的 API 配置,只需在安装/升级 Higress 时配置开启 Gateway API:

    • 使用 Helm :通过参数 --set global.enableGatewayAPI=true
    • 使用 Hgctl :通过命令行参数或者 install.yaml 中配置 global.enableGatewayAPI=true

    首先创建 GatewayClass 资源:

      apiVersion: gateway.networking.k8s.io/v1
    kind: GatewayClass
    metadata:
    name: higress-gateway
    spec:
    controllerName: "higress.io/gateway-controller"

    接着在安装 Higress 的命名空间下,创建 Gateway 资源,通过 gatewayClassName 关联上面创建的 GatewayClass 资源,指定由 Higress 来管理此 Gateway 配置,下面为域名同时配置了 HTTP 和 HTTPS 入口,并为 HTTPS 入口配置了证书:

      apiVersion: gateway.networking.k8s.io/v1
    kind: Gateway
    metadata:
    name: higress-gateway
    namespace: higress-system
    spec:
    gatewayClassName: higress-gateway
    listeners:
    - name: foobar
    hostname: "*.foobar.com"
    port: 80
    protocol: HTTP
    allowedRoutes:
    namespaces:
    from: All
    - name: foobar-https
    hostname: "*.foobar.com"
    port: 443
    protocol: HTTPS
    allowedRoutes:
    namespaces:
    from: All
    tls:
    certificateRefs:
    - kind: Secret
    name: wildcard-foobar-com
    mode: Terminate

    因为上面 Gateway 通过 allowedRoutes 配置了允许所有命名空间的路由来关联,所以这里在 default 命名空间下创建 HTTPRoute,关联上面创建的 Gateway,即可定义域名下的具体路由:

      apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
    name: foobar
    namespace: default
    spec:
    parentRefs:
    - name: higress-gateway
    namespace: higress-system
    hostnames: ["www.foobar.com"]
    rules:
    - matches:
    - path:
    type: PathPrefix
    value: /foo
    backendRefs:
    - name: foo-service
    port: 5678

    以上就是 Gateway API 的一个简单用法示例,Gateway API 还有很多功能和玩法,后面 Higress 公众号/博客会出一个系列进行系统分享和介绍。

    欢迎结合官方 API 文档,并使用 hgctl (获取方式见下文)在自己电脑上安装一个 local-k8s 模式的 Higress,来开启对这一新标准的探索:

      # 一键安装, 交互式命令选择第一种安装模式 local-k8s,将默认安装 Gateway API CRD
    hgctl install

    多种服务发现能力

    在 Ingress API 标准下,Higress 对接多种服务发现能力是独树一帜的,在 Gateway API 标准下, Higress 仍就保持了这一能力优势:

    首先通过 McpBridge 资源,可以定义多种服务发现机制:

      apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    - domain: 127.0.0.1
    nacosGroups:
    - DEFAULT_GROUP
    name: my-local-nacos
    port: 8848
    type: nacos2
    - domain: 127.0.0.1
    name: my-local-zk
    port: 2181
    type: zookeeper
    - domain: 127.0.0.1
    name: my-local-eureka
    port: 8761
    type: eureka
    - domain: 127.0.0.1
    consulDatacenter: dc1
    name: my-local-consul
    port: 8500
    type: consul

    创建一个 HTTPRoute 资源,可以同时对接 K8s 服务,和注册中心的服务,并实现灰度路由能力:

      apiVersion: gateway.networking.k8s.io/v1
    kind: HTTPRoute
    metadata:
    name: http
    namespace: default
    spec:
    parentRefs:
    - name: higress-gateway
    namespace: higress-system
    rules:
    - matches:
    - path:
    type: PathPrefix
    value: /
    backendRefs:
    - name: service-provider.DEFAULT-GROUP.public.nacos
    group: networking.higress.io
    port: 8080
    weight: 90
    - name: foo-service
    port: 5678
    weight: 10

    和 K8s 服务不同的是,这里 group 为 networking.higress.io 的服务并不需要提前创建 CRD 资源,这更符合传统微服务用户的习惯,即服务模型不需要提前创建,是通过服务节点注册自动生成。

    Ingress API 和 Gateway API 之间如何选择

    有了 Gateway API,是否应该立即抛弃 Ingress API?

    只有最合适的,没有最好的。Gateway API 虽然为更多网关能力做了标准化,但 CRD 的种类和复杂度也增加了,相比之下对于大部分简单用例场景,Ingress API 更加简单易用。

    对于以下场景,采用 Gateway API 替代 Ingress API 会带来很大帮助:

    • 大型团队划分了 SRE 角色和业务研发角色,由 SRE 通过 Gateway 资源统一管理站点域名和证书,由业务研发通过 HTTPRoute 资源管理业务路由,实现职责划分,权限收敛
    • 创建的路由和 Service 有不在一个命名空间的需求,可以借助 ReferenceGrant 资源实现
    • 有大量证书需要集中式管理,不希望将证书 Secret 同步到 Ingress 所在命名空间,带来安全风险

    Gateway API 的另一个好处是对于更多功能的标准化定义,我们建议遇到实际需要再转换到这个新的标准,而不必盲目跟随。

    Higress 支持 Gateway API 和 Ingress API 混合使用,Gateway API 下的域名路由将比 Ingress API 优先匹配,和 Ingress 相同资源名称的 HTTPRoute 还会继承 WASM 插件配置,这样用户可以按需采用 Gateway API,平滑地完成从 Ingress API 向 Gateway API 的演进,无需焦虑 API 标准升级过程中产生业务损失。

    新工具:All in one 的 hgctl

    替代 Helm 用于安装/升级

    在 K8s 下用 Helm 安装/升级组件很方便,但在 Higress 的场景下仍然存在一些问题:

    1. 无法支持非 K8s 场景下的安装/升级
    2. Higress 有很多安装参数,进行升级等操作时不好维护,使用reuse-values 有一些副作用,且容易误操作
    3. 无法管理 CRD 跟随版本更新,需要手动更新

    Higress 借鉴了 istio 的 istioctl,提供了 hgctl 这个命令行工具解决了上述问题,通过以下命令即可安装 hgctl

      # 下载最新版 Hgctl:
    curl -Ls https://raw.githubusercontent.com/alibaba/higress/main/tools/hack/get-hgctl.sh | VERSION=latest bash

    hgctl 集成了三种 Higress 安装模式,并统一了升级/运维操作:

    1. 本地 K8s 环境(例如kind/k3s)模式
    2. 正式 K8s 环境模式
    3. 不依赖 K8s 的纯 Docker 环境模式

    直接执行 hgctl install 命令即可选择任意模式进行安装

    安装配置文件将存至 ~/.hgctl/profiles/install.yaml 目录下,查看该文件内容如下:

      charts:
    higress:
    name: higress
    # 安装文件的 helm repo 地址
    url: https://higress.io/helm-charts
    # 执行 hgctl upgrade 时将自动更新至最新版本
    version: latest
    console:
    # 开启可观测组件
    o11YEnabled: true
    # 控制台实例数
    replicas: 1
    controller:
    # 控制面组件实例数
    replicas: 1
    gateway:
    # 数据面组件实例数
    replicas: 1
    global:
    # 开启 Gateway API
    enableGatewayAPI: true
    # 开启 Istio API
    enableIstioAPI: true
    # 设置监听的 ingress class
    ingressClass: higress
    # 安装模式
    install: local-k8s
    # 安装命名空间
    namespace: higress-system
    # 配置传递给 helm 的 values 参数
    values: {}
    profile: local-k8s

    修改上面文件的内容后,执行hgctl upgarde即可实现参数变更生效,如果只想修改参数,不想触发版本升级,可以将 version 参数固定为当前版本。

    WASM 插件开发工具包

    为了标准化并简化 WASM 插件的开发/编译/测试/发布,Higress 提供了 hgctl plugin 这一子命令,使用方式为:

    1. hgctl plugin init: 初始化 Golang WASM 插件项目,包括三个文件;
    2. 用户编写 WASM 插件逻辑;
    3. hgctl plugin build --output-type files: 构建 WASM 插件,在本地输出构建产物;
    4. hgctl plugin test: 使用 docker compose 在本地测试 WASM 插件,如需修改插件逻辑,则返回第 2 步;
    5. hgctl plugin build --output-type image: 构建 WASM 插件作为 OCI 镜像上传至镜像仓库;
    6. hgctl plugin install: 安装 WASM 插件,可以通过本地的 yaml 文件或插件项目进行安装。

    另外,若需要查看已安装的插件,则使用 hgctl plugin ls;若需要操作插件配置,则使用 hgctl plugin config

    通过这个工具,可以在构建 WASM 插件的同时,根据配置代码自动生成插件的配置说明文档,以及包含插件配置约束的元信息文件,这些内容都将和 WASM 文件一起放入 OCI 镜像制品中,通过镜像方式进行版本管理和分发。这一机制是后续 Higress 建设 WASM 插件市场的基石。

    其他功能

    另外介绍两个实用的子命令:

    1. hgctl dashboard: 用于呼出 UI 界面,例如 Higress 控制台,直接通过 hgctl dashboard console 即可打开
      $ hgctl dashboard
    Access to Higress web UIs

    Usage:
    hgctl dashboard [flags]
    hgctl dashboard [command]

    Aliases:
    dashboard, dash, d

    Available Commands:
    console Open Console web UI
    controller Open Controller debug web UI
    envoy Open Envoy admin web UI
    grafana Open Grafana web UI
    prometheus Open Prometheus web UI
    1. hgctl gateway-config: 用于查看数据面的 envoy 配置,可以快速验证配置是否正确下发
      $ hgctl gateway-config
    Retrieve information about Higress Gateway Configuration.

    Usage:
    hgctl gateway-config [command]

    Aliases:
    gateway-config, gc

    Available Commands:
    all Retrieves all Envoy xDS resources from the specified Higress Gateway
    bootstrap Retrieves bootstrap Envoy xDS resources from the specified Higress Gateway
    cluster Retrieves cluster Envoy xDS resources from the specified Higress Gateway
    endpoint Retrieves endpoint Envoy xDS resources from the specified Higress Gateway
    listener Retrieves listener Envoy xDS resources from the specified Higress Gateway
    route Retrieves route Envoy xDS resources from the specified Higress Gateway

    新征程:API Gateway

    上面说了 Gateway API,接着我们聊聊 API Gateway 😄,API Gateway 有两层定义:

    1. 狭义上:满足统一接入,将路由转发到不同服务的运维需求,即可称为 API Gateway;这里 API 的定义是服务的路由
    2. 广义上:在实现服务转发的基础上,需要识别带业务语义的接口,将业务能力 API 化管理,统一对外提供服务;这里 API 的定义是业务功能接口

    Higress 已经实现了狭义上的 API Gateway 能力,并且是基于 Gateway/Ingress API 这些通用路由标准来实现的。而与服务路由标准不同,业务功能接口的标准是 Swagger/OAS3/RPC IDL 等,做为 API Gateway 需要提供以下关键能力:

    1. 支持通过上传 Swagger 等接口定义文件的方式导入 API
    2. 对 API 实现精细化策略管理,例如根据出入参定义实现参数映射/转换
    3. 实现以 API 方式开放能力时的认证/鉴权,调用量控制/审计能力

    Higress 新的开源征程将向具备业务 API 管理能力的 API Gateway 形态进发。在实现方式上,我们将基于 WASM 插件去扩展这一部分能力,这可以降低我们对上游 Envoy 社区的侵入性改造,同时让对 API 的精细化策略管理具备自定义扩展能力。 目前社区已经有一些 Proposal ,欢迎了解:

    https://github.com/alibaba/higress/issues/535

    https://github.com/alibaba/higress/issues/601

    欢迎有更多小伙伴加入,和我们一起踏上新的征程,有兴趣的小伙伴可以联系我(微信:nomadao),加入 API Gateway 的 SIG(兴趣小组)。

    社区致谢

    首先要感谢 Envoy 和 Istio 社区,Higress 站在这两个软件的肩膀上演进能力,得以:

    1. 通过 WASM 机制扩展 Envoy 数据面能力,持续不断地扩大网关插件生态
    2. 通过专注在网关领域,在 Istio 优秀的控制面基础上,进一步做抽象和简化,降低上手和运维门槛

    还要感谢参与 Higress 开源贡献的开发者们,这里重点感谢下为 1.3 版本做出核心贡献的开发者:

    Maintainer:董艺荃(CH3CHO)

    人如其名“艺全”,十八般武艺样样精通,不管是控制台 TS 前端,Java 后台,还是 Higress 的 GO 控制面,以及 Standalone 安装 Shell 脚本和各种 CICD 流程,通通手到擒来。

    在 1.3 版本中主要负责了 Higress 支持 Gateway API 的能力,以及实现了 Higress Admin Java SDK 可以提供外部集成用于管理 Higress 配置,并改进了 Higress Console 的安全性和易用性。

    除了开发贡献之外,他还对社区用户充满善意和热情,无论是在 GitHub 的 Issues/Discussions,或是社区交流微信/钉钉群,随处可见他帮助用户解决问题的身影。

    Approver:吴新军(Jun),刘训灼(Xunzhuo)

    两位都在多个 Higress 版本为社区做出了贡献,Jun 的主要贡献有:在多注册中心的服务发现支持,全局配置管理架构抽象;Xunzhuo 的主要贡献有:Higress E2E 测试流程的搭建,GitHub CI 流程的建设,hgctl 的整体架构设计。

    在 1.3 版本中二位协作完成了 hgctl 的多样化能力建设,帮助 Higress 的易用性又上到了一个新的台阶。

    两位同学作为 Approver 积极参与社区贡献 PR 的 Review,目前分别是 Higress Tools SIG 和 Higress GatewayAPI SIG 的领导者。

    Member:韦鑫(WeixinX),封宇腾(Fkbqf)

    两位都是通过中科院开源之夏(OSPP 2023)项目开始参与 Higress 贡献,WeixinX 是一名研二的学生,Fkbqf 是一名大三的学生。

    在 1.3 版本中,WeixinX 实现了 hgctl plugin 子命令的能力,同时贡献了 Go 实现的 Basic Auth 插件,以及对标 Spring Cloud Gateway 请求响应转换能力的 Transformer 插件;Fkbqf 则实现了更为复杂的 OIDC 插件,具备比 Envoy 自带 OAuth2 Filter 更强大的功能,并且具备良好的扩展性。

    两位同学除了开发贡献以外,用课余时间积极参与 Higress 社区周会,一起探讨和学习技术,不亦乐乎。能够成为你们人生学业进阶路上的阶梯,Higress 荣幸之至。

    Higress 社区后续整体的 Roadmap 规划如下:

    image

    欢迎更多小伙伴一起加入我们:

    higress-comm

    - + \ No newline at end of file diff --git a/zh-cn/blog/release-100/index.html b/zh-cn/blog/release-100/index.html index 5655dc0d23..cb89b3b115 100644 --- a/zh-cn/blog/release-100/index.html +++ b/zh-cn/blog/release-100/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    上线控制台,降低使用门槛 | Higress 1.0.0 RC 版本发布

    · 阅读需 7 分钟

    前言

    历时 5 个多月,Higress 推出了首个 RC (Release Candidate,即正式发布的候选)版本 1.0.0-rc,用户可以通过控制台,开箱即用地使用云原生网关。

    选用 Higress 作为云原生网关的核心优势如下:

    • 易用性

      “云原生”已经不再是一个新鲜词,但企业对云原生技术的学习使用成本仍有许多顾虑,对云原生新标准的追赶又有很多焦虑;

      Higress 同时提供了本地安装/生产部署的 quickstart,可以一键部署,并通过控制台操作快速上手;基于简单易用的控制台,Higress 可以封装 Ingress/Gateway API 的标准细节,根治技术追赶焦虑。

    • 标准化

      K8s 带来了云原生的路由标准 Ingress/Gateway API,如同 POSIX 定义 Unix 可移植操作系统标准,历时 35 年经久不衰,云原生的路由标准的生命周期一定会远超过 K8s 本身;

      Higress 结合阿里内部实践以及阿里云产品沉淀,积累了基于 Ingress API 的丰富的路由策略扩展能力,同时还兼容大部分 Nginx Ingress 能力,这些能力后续也将在 Gateway API 上支持。

    • 高集成

      企业内有大量传统架构部署的服务,会成为向云原生架构演进的技术负担,要求云原生网关具备对接异构服务架构的能力;

      基于 Higress 提供的多种服务发现机制,网关路由不仅可以转发到 K8s 服务,也可以直接配置 IP 转发到到物理机上的服务;基于 Nacos/ZooKeeper 等注册中心对接,还可以轻松实现 Spring CloudDubbo 微服务的路由,无论其是否部署在 K8s 内。

    • 易扩展

      基于扩展机制进行二次开发的能力,是云原生网关在不同业务场景下都能适配落地的关键;

      Higress提供了灵活的插件扩展机制,目前插件市场已经推出多个官方插件,并支持用户通过控制台直接上传自己开发的插件,同时开源社区的插件市场生态也在不断建设中。

    • 热更新

      传统 Nginx 更新规则需要 reload 会导致链接抖动,导致流量损失,对实时通信、视频、IOT无法容忍;

      对于路由规则,Wasm 插件逻辑更新,以及证书改动等等,Higress 全部支持热更新,不会造成任何连接抖动。

    企业落地支持

    在 RC 版本阶段使用 Higress 的企业用户,社区会在落地阶段提供更多帮助,我们建立了 Higress 企业落地群,可以联系我(微信:nomadao 钉钉:chengtanzty),会将你加进群,群里有社区核心研发同学,可以提供更及时的响应和帮助。

    安装升级方式

    安装 RC 版本,需要 helm 安装升级时需要指定--devel参数,例如:helm upgrade higress -n higress-system --devel

    1.0.0 RC 版本已经在社区小伙伴的协作下完成了多轮测试和修复工作,欢迎大家使用。最终的正式版本,也将在近期很快推出。

    控制台功能速览

    • 丰富的可观测

      提供开箱即用的可观测,Grafana&Prometheus 可以使用内置的也可对接自建的,具体可以参考文档

    • 插件扩展机制

      官方提供了多种插件,用户也可以开发自己的插件,构建成 docker/oci 镜像后在控制台配置,可以实时变更插件逻辑,对流量完全无损。

    • 多种服务发现

      默认提供 K8s Service 服务发现,通过配置可以对接 Nacos/ZooKeeper 等注册中心实现服务发现,也可以基于静态 IP 或者 DNS 来发现

    • 域名和证书

      可以创建管理 TLS 证书,并配置域名的 HTTP/HTTPS 行为,域名策略里支持对特定域名生效插件

    • 丰富的路由能力

      基于上面配置的服务发现机制,发现的服务会出现在服务列表中;创建路由时,选择域名,定义路由匹配机制,再选择目标服务进行路由;路由策略里支持对特定路由生效插件

    进阶使用

    Higress 控制台的功能还在不断丰富和演进中,当前还有很多 Higress Ingress 注解的能力没有支持,如果有这部分深度使用的需求,可以参考这篇文档进行进阶配置

    如果希望使用 Istio 的能力进行流量治理,可以参考这篇文档的支持 Istio CRD 一节。基于 Istio 的 EnvoyFilter API 可以实现更多细粒度的管控能力。

    社区

    欢迎认领 Higress Issue 任务:https://github.com/alibaba/higress/issues?q=is%3Aopen+is%3Aissue+label%3A%22help+wanted%22

    完成一定数量的 Issues 就可以成为 Higress Committer,也有机会获得开源社区的礼物和荣誉🏆

    欢迎加入 Higress 社区群,及时了解更多 Higress 动向:

    - + \ No newline at end of file diff --git a/zh-cn/blog/skywalking/index.html b/zh-cn/blog/skywalking/index.html index 451cb04aea..7657937412 100644 --- a/zh-cn/blog/skywalking/index.html +++ b/zh-cn/blog/skywalking/index.html @@ -14,7 +14,7 @@ - + @@ -24,7 +24,7 @@ helm 安装参考安装文档

    1. 安装 higress 和 istio CRD

    可以参考 higress 快速开始安装部署 来部署,这里需要安装 Istio CRD。

    这里提供一键安装脚本 local-env-setup.sh,运行 local-env-setup.sh 安装 Higress

    ./local-env-setup.sh --crd
    1. 部署 Skywalking,业务应用和 Ingress
    $ export KUBECONFIG=${HOME}/.kube/config_higress
    $ kubectl apply -f skywalking.yaml
    $ kubectl apply -f app.yaml
    $ kubectl apply -f ingress.yaml

    检查 POD 运行状态和 Ingress 状态

    $ export KUBECONFIG=${HOME}/.kube/config_higress

    $ kubectl get pods -n higress-system

    NAME READY STATUS RESTARTS AGE
    higress-console-6f554978dc-cclg7 1/1 Running 0 100m
    higress-console-grafana-7495766db4-4flq5 1/1 Running 0 131m
    higress-console-prometheus-6d7bdccfb-hxtsq 1/1 Running 0 131m
    higress-controller-689c5b965f-7wsmt 2/2 Running 0 131m
    higress-gateway-59966b45d9-z7ltd 1/1 Running 0 131m

    $ kubectl get pods -n op-system

    NAME READY STATUS RESTARTS AGE
    skywalking-oap-dashboard-65f496ccc9-dr96l 1/1 Running 0 99m
    skywalking-oap-server-859694656b-p8vcq 1/1 Running 0 99m

    $ kubectl get pods -n app-system

    NAME READY STATUS RESTARTS AGE
    backend-6b9549bc64-f98tr 1/1 Running 0 99m
    backend-6b9549bc64-x2btl 1/1 Running 0 99m
    bff-766967f8db-8ght7 1/1 Running 0 99m
    bff-766967f8db-gflbh 1/1 Running 0 99m
    middle-6f4dd7bf6c-qdjqj 1/1 Running 0 99m
    middle-6f4dd7bf6c-stzf4 1/1 Running 0 99m

    $ kubectl get svc -n app-system

    NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
    backend ClusterIP 10.96.179.140 <none> 80/TCP 99m
    bff ClusterIP 10.96.121.62 <none> 80/TCP 99m
    middle ClusterIP 10.96.55.8 <none> 80/TCP 99m


    $ kubectl get ingress -n higress-system

    NAME CLASS HOSTS ADDRESS PORTS AGE
    higress-console higress console.higress.io 80 34m
    higress-console-grafana higress console.higress.io 80 34m
    higress-console-prometheus higress console.higress.io 80 34m
    httpbin higress httpbin.example.com 80 8s
    skywalking-dashboard higress skywalking.higress.io 80 8s
    1. 测试 Higress Console, Skywalking Dashboard, Bff 服务

    1)编辑 /etc/hosts 文件添加以下三个域名

    127.0.0.1 console.higress.io
    127.0.0.1 skywalking.higress.io
    127.0.0.1 httpbin.example.com

    2)打开 higress-gateway 端口转发

    $ export KUBECONFIG=${HOME}/.kube/config_higress
    $ kubectl -n higress-system port-forward service/higress-gateway 8080:80

    3)通过浏览器打开访问上面三个域名

    Higress 控制台: http://console.higress.io:8080。首次访问控制台时需要先初始化管理员用户。初始化完成后使用对应的用户名密码登录即可。

    img.png

    Skywalking Dashboard: http://skywalking.higress.io:8080

    img.png

    Bff 服务: http://httpbin.example.com:8080/hostname

    img.png

    六、Higress 集成 Skywalking 调用链路跟踪配置

    通过修改 Higress configmap 全局配置 higress-config 来激活 Higress 集成 Skywalking 调用链路跟踪。

    $ export KUBECONFIG=${HOME}/.kube/config_higress
    $ kubectl edit configmap higgress-config -n higress-system

    在 data 下增加 higress 配置项然后保存,具体配置内容如下:

    data:
    higress: |-
    tracing:
    enable: true
    sampling: 100
    timeout: 500
    skywalking:
    service: skywalking-oap-server.op-system.svc.cluster.local
    port: 11800

    七、Skywalking 链路跟踪

    运行压测脚本

    for i in $(seq 1 1000)
    do
    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/hostname
    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/
    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/service?services=middle,backend
    done

    调用 bff 服务 /service 接口来模拟调用链路

    curl -v -H "Host:httpbin.example.com" http://127.0.0.1:8080/service?services=middle,backend

    部分返回响应体情况如下:

    {
    "args": {
    },
    "form": {
    },
    "headers": {
    "accept-encoding": "gzip",
    "sw8": "1-MzYzMzM1NDctNTc0YS00MzZlLTgzNWEtNTY1YTQyNzk3YTY3-ZWQ3ODA2ZjYwNTI0MTFlZWE5ZDdmZTFhNTA5YTRmYTk=-1-bWlkZGxl-bWlkZGxlLTZmNGRkN2JmNmMtcWJ4cm0=-L0dFVC9zZXJ2aWNl-aHR0cDovL2JhY2tlbmQv",
    "sw8-correlation": "",
    "user-agent": "Go-http-client/1.1",
    "x-httpbin-trace-host": "bff-766967f8db-jwn2g/middle-6f4dd7bf6c-qbxrm/backend-6b9549bc64-8twnx",
    "x-httpbin-trace-service": "bff/middle/backend",
    "x-request-id": "e5a1b250-ebe3-931d-91d7-90e3ee2fc867"
    },
    "method": "GET",
    "origin": "",
    "url": "/",
    "envs": {
    "NODE_NAME": "higress-worker2",
    "PATH": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin",
    "POD_IP": "10.244.1.7",
    "POD_NAME": "backend-6b9549bc64-8twnx",
    "POD_NAMESPACE": "app-system",
    "SERVICE_ACCOUNT": "backend",
    "SERVICE_NAME": "backend",
    "VERSION": "v1"
    },
    "host_name": "backend-6b9549bc64-8twnx",
    "body": ""
    }

    响应头中和调用链路跟踪相关有如下:

    "sw8": "1-MzYzMzM1NDctNTc0YS00MzZlLTgzNWEtNTY1YTQyNzk3YTY3-ZWQ3ODA2ZjYwNTI0MTFlZWE5ZDdmZTFhNTA5YTRmYTk=-1-bWlkZGxl-bWlkZGxlLTZmNGRkN2JmNmMtcWJ4cm0=-L0dFVC9zZXJ2aWNl-aHR0cDovL2JhY2tlbmQv",
    "x-httpbin-trace-host": "bff-766967f8db-jwn2g/middle-6f4dd7bf6c-qbxrm/backend-6b9549bc64-8twnx",
    "x-httpbin-trace-service": "bff/middle/backend",

    其中:

    • sw8: Skywalking 用于跟踪的 Http Header
    • x-httpbin-trace-host: 调用链路经过 POD_NAME
    • x-httpbin-trace-service: 调用链路经过 SERVICE_NAME

    在 Skywalking dashboard 中查看如下:

    • 服务截图

    img.png

    • 调用链路截图

    img.png

    • 调用链路拓扑截图

    img.png

    八、Higress gateway 指标和监控面板

    可以通过度量各个组件的性能指标,例如响应时间、吞吐量、错误率、资源使用率等指标来了解系统的状态和性能。

    指标数据包含指标名称,指标标签,和指标值,下面是 envoy_cluster_upstream_cx_total upstream(总连接数)部分指标数据,

    其中 envoy_cluster_upstream_cx_total 是指标名称,cluster_name 是指标标签,16 是指标值。

    # TYPE envoy_cluster_upstream_cx_total counter
    envoy_cluster_upstream_cx_total{cluster_name="outbound|80||bff.app-system.svc.cluster.local"} 16

    Higress 指标数据大体可以分为三类:

    • Downstream 下游: 指标与外来的连接/请求有关,主要由侦听器,HTTP连接管理器等
    • UpStream 上游: 指标与外向的连接/请求有关,主要由连接池,路由器,过滤器,熔断等
    • Server 负载: 指标信息记录 Higress gateway 服务器实例的负载等

    Higress 指标数据类型主要有三类:

    • Counter: 无符号整数,只会增加而不会减少。例如,总请求
    • Gauge: 增加和减少的无符号整数。例如,当前活动的请求
    • Histogram: 作为指标流的一部分的无符号整数,然后由收集器聚合以最终产生汇总的百分位值(percentile,即平常说的 P99/P50/Pxx)。例如,Upstream 响应时间

    通过以下命令可以获取 Higress gateway 支持的指标和类型

    $ export HIGRESS_GATEWAY_POD=$(kubectl get pods -l app=higress-gateway -o 'jsonpath={.items[0].metadata.name}' -n higress-system)
    $ kubectl exec "$HIGRESS_GATEWAY_POD" -n higress-system -- curl -sS http://127.0.0.1:15020/stats/prometheus | grep "# TYPE"

    部分指标内容如下:

    ...
    # TYPE envoy_cluster_upstream_cx_total counter
    # TYPE envoy_cluster_upstream_cx_tx_bytes_total counter
    # TYPE envoy_cluster_upstream_flow_control_backed_up_total counter
    # TYPE envoy_cluster_upstream_flow_control_drained_total counter
    # TYPE envoy_cluster_upstream_flow_control_paused_reading_total counter
    # TYPE envoy_cluster_upstream_flow_control_resumed_reading_total counter
    # TYPE envoy_cluster_upstream_internal_redirect_failed_total counter
    # TYPE envoy_cluster_upstream_internal_redirect_succeeded_total counter
    # TYPE envoy_cluster_upstream_rq counter
    # TYPE envoy_cluster_upstream_rq_101 counter
    # TYPE envoy_cluster_upstream_rq_200 counter
    # TYPE envoy_cluster_upstream_rq_201 counter
    # TYPE envoy_cluster_upstream_rq_301 counter
    # TYPE envoy_cluster_upstream_rq_302 counter
    # TYPE envoy_cluster_upstream_rq_304 counter
    # TYPE envoy_cluster_upstream_rq_401 counter
    # TYPE envoy_cluster_upstream_rq_404 counter
    # TYPE envoy_cluster_upstream_rq_cancelled counter
    # TYPE envoy_cluster_upstream_rq_completed counter
    # TYPE envoy_cluster_upstream_rq_maintenance_mode counter
    # TYPE envoy_cluster_upstream_rq_max_duration_reached counter
    # TYPE envoy_cluster_upstream_rq_pending_failure_eject counter
    # TYPE envoy_cluster_upstream_rq_pending_overflow counter
    # TYPE envoy_cluster_upstream_rq_pending_total counter
    # TYPE envoy_cluster_upstream_rq_per_try_idle_timeout counter
    # TYPE envoy_cluster_upstream_rq_per_try_timeout counter
    # TYPE envoy_cluster_upstream_rq_retry counter
    # TYPE envoy_cluster_upstream_rq_retry_backoff_exponential counter
    # TYPE envoy_cluster_upstream_rq_retry_backoff_ratelimited counter
    # TYPE envoy_cluster_upstream_rq_retry_limit_exceeded counter
    # TYPE envoy_cluster_upstream_rq_retry_overflow counter
    # TYPE envoy_cluster_upstream_rq_retry_success counter
    # TYPE envoy_cluster_upstream_rq_rx_reset counter
    # TYPE envoy_cluster_upstream_rq_timeout counter
    # TYPE envoy_cluster_upstream_rq_total counter
    # TYPE envoy_cluster_upstream_rq_tx_reset counter
    ...
    # TYPE envoy_http_downstream_cx_total counter
    # TYPE envoy_http_downstream_cx_tx_bytes_total counter
    # TYPE envoy_http_downstream_cx_upgrades_total counter
    # TYPE envoy_http_downstream_flow_control_paused_reading_total counter
    # TYPE envoy_http_downstream_flow_control_resumed_reading_total counter
    # TYPE envoy_http_downstream_rq counter
    # TYPE envoy_http_downstream_rq_completed counter
    # TYPE envoy_http_downstream_rq_failed_path_normalization counter
    # TYPE envoy_http_downstream_rq_header_timeout counter
    # TYPE envoy_http_downstream_rq_http1_total counter
    # TYPE envoy_http_downstream_rq_http2_total counter
    # TYPE envoy_http_downstream_rq_http3_total counter
    # TYPE envoy_http_downstream_rq_idle_timeout counter
    # TYPE envoy_http_downstream_rq_max_duration_reached counter
    # TYPE envoy_http_downstream_rq_non_relative_path counter
    # TYPE envoy_http_downstream_rq_overload_close counter
    # TYPE envoy_http_downstream_rq_redirected_with_normalized_path counter
    # TYPE envoy_http_downstream_rq_rejected_via_ip_detection counter
    # TYPE envoy_http_downstream_rq_response_before_rq_complete counter
    # TYPE envoy_http_downstream_rq_rx_reset counter
    # TYPE envoy_http_downstream_rq_timeout counter
    # TYPE envoy_http_downstream_rq_too_large counter
    # TYPE envoy_http_downstream_rq_total counter
    # TYPE envoy_http_downstream_rq_tx_reset counter
    # TYPE envoy_http_downstream_rq_ws_on_non_ws_route counter
    ...

    具体指标定义参考如下:

    如何查看 Higress 指标数据:

    通过 Skywalking Dashboard 查看 Higress gateway 监控数据部分截图如下:

    img.png img.png img.png

    参考文档

    - + \ No newline at end of file diff --git a/zh-cn/blog/user-mq/index.html b/zh-cn/blog/user-mq/index.html index 787aa63fcb..c3ba69e73d 100644 --- a/zh-cn/blog/user-mq/index.html +++ b/zh-cn/blog/user-mq/index.html @@ -14,14 +14,14 @@ - +

    美洽智能客服使用 Higress 统一网关落地实践

    · 阅读需 11 分钟

    关于美洽

    美洽是一家全球智能云客服服务商,提供一站式智能客服解决方案,旗下拥有在线客服、工单系统、呼叫中心、客服机器人、语音机器人、营销机器人等产品及服务。美洽成立于2014年,总部位于成都,目前服务企业用户已超过40万家,覆盖多个行业领域。美洽的客服系统支持多平台使用,包括Web 网页端、手机客户端、PC 客户端,同时美洽也提供了开放 API 平台。

    需求背景

    1. 多条业务线使用了了不同编程语言,在微服务化演进的路上困难重重;
    2. 历史架构使用多个流量转发中间件导致流量路径冗长、复杂且故障排查困难(LB + OpenResty + Nginx + Caddy + SpringCloud-Gateway);
    3. WebSocket 长连接服务在多重路由层上不支持热更新,维护成本高。

    历史架构的流量拓扑图如下:

    需求目标

    1. 找到一个统一网关,能够一次性解决流量网关和业务网关的路由转发需求;
    2. 支持路由规则热更新,解决 WebSocket 连接在路由更新或网络抖动时产生的重连风暴;
    3. 前置API 请求权限校验、签名校验、WAF 拦截、CC 拦截;
    4. 可视化统一网关的后台操作,让普通员工也能上手;
    5. 多云架构下私有化部署支持。

    方案横向对比

    通过对目前市面上流行的网关产品进行详细的横向对比,再结合美洽对统一网关的需求目标,我们从对比的表格当中,看到了 Higress 所带来的最佳对比结果。

    同时美洽重点关注的几个点:K8S Ingress 支持、WebSocket支持、Nacos 服务发现、路由配置热更新、WASM 插件都得到了很好的支持。

    为什么选择 Higress

    面向多云架构友好

    Higress 在阿里云上有成熟的企业版产品:MSE 云原生网关,我们从 2021 年开始使用这款产品,这是一款全托管,完全免运维的 SaaS 网关产品,并且具备强劲的性能和丰富的功能,相比自建同吞吐的网关,整体成本是更低的,因此我们在阿里云上直接使用了这款产品。

    美洽除了阿里云,在其他云上也有部署业务,我们希望能统一多云的统一网关技术架构,开源版 Higress 正好符合我们的需求,相比商业版,在控制台功能上,开源版目前的能力相对较少,但大部分功能也都可以通过自己定义 K8s CRD 配置的方式来实现,完全满足我们的需求。

    原生支持 K8s Ingress

    美洽从 2021 年便已经全面迁移到 Kubernetes 进行资源调度,遇到最大的困难是历史的网关中间件,在容器化的架构里面,各种水土不服,要么需要借助 Nginx-Ingress-Controller,要么需要外部的 SLB 进行服务之间的负载均衡与网络通信。这导致了比容器化之前更加复杂的流量路径,一度让我们下定决心,必须、必须、必须要解决统一网关的问题,还必须云原生的。

    2021 年底开始,我们开始尝试使用阿里云 MSE 网关 SaaS 产品,开始将部分服务从 Nginx 路由迁移到 MSE 网关上,很快解决了Ngxin Configuration 配置维护复杂,故障频发的问题,尝到甜头后,我们便开始计划进一步扩大 MSE 网关的使用,结合 Nacos 和 K8S 的服务发现,将 80% 大部分容器化服务路由转发全部迁移到了云原生网关上。

    这带来的收益就包括:

    1. 简化了流量路径,公网流量通过 SLB 直接到达网关,网关路由直达容器 Pod;
    2. 释放了使用 ECS 自建的 Nginx 、OpenResty 、Caddy 服务,降低了大量服务器成本;
    3. 服务发现和服务治理,以及各个服务当前的健康状态都以可视化的 Dashborad 呈现出来;

    控制面和数据面解耦的架构

    控制面和数据面解耦是一种很好的设计模式,把管理控制逻辑和运行处理逻辑分开,这样可以更好地管理和扩展系统。

    1. Console 负责管理 和 Gateway 负责处理请求,灵活可扩展,互补干扰;
    2. 整个系统的性能和可用性可以得到很好的保障;
    3. 即使控制面出现问题,数据面仍然可以继续处理请求,反之亦然。

    在美洽客服自己的产品中,也大量试用了控制面和数据面分离的这种架构设计模式,在选择 Higress 统一网关的落地实践中,也更好的可以和美洽产品的架构进行配合,例如控制台采用微前端技术统一美洽运维控制台,Higress 控制台,Nacos 控制台。

    容易上手的后台 Dashboard

    在早期,美洽在 2021 年开始使用阿里云 MSE 云原生网关时,就已经对网关的控制台使用有了很多的经验基础,团队中 QA 同学也能熟练使用了。目前在其他云上的项目,私有化部署的开源版Higress,在控制台方面功能与操作和阿里云 MSE 产品的交互保持一致,团队使用很快便上手了。

    插件方面,美洽使用了 JWT Auth 鉴权,Key Rate Limit 限流,HMAC Auth 请求签名,Bot Detect 和 WAF 功能有涉及。

    美洽的落地实践

    采用 Helm 在 K8s node 上 一键部署

    helm repo add higress.io <https://higress.io/helm-charts>
    helm install higress higress.io/higress -n higress-system --create-namespace

    完全替代了 Nginx 、OpenResty、Caddy 、SLB-Intranet

    彻底解决 WebSocket 断线重连问题

    美洽的智能客服产品侧试用了 WebSocket 进行长连接保持和消息通信,所以非常依赖网络的稳定,以及更新网关配置所带来的副作用。在使用 Nginx + OpenResty 方案的期间,每一次的配置变更都会带来极大的代价,断线重连风暴时常发生。一次配置变更 Pendding 或者变更失败带来的瞬时断联是及其痛苦的。

    在迁移到 Higress 上之后,路由配置热更新特性,不在需要像 Nginx 一样需要 Reload Gateway,解决配置更新 reload 带来的断线重连风暴问题。

    另外,在 WebSocket Server 服务升级过程中,通过给 Pod 打上 stage 标签,在 Higress 侧通过标签路由进行新老版本无损流量切换,给产品快速迭代升级带了巨大的杠杆效应。

    熔断限流

    在面向 2B 的 SaaS 产品业务场景中,经常会发生某一个客户突发海量流量,占据大量带宽,影响其他客户正常使用的情况,这时我们需要针对客户规模对单个客户的 API 并发上限做灵活的动态限流,使用 Higress 的插件Key Rate Limit 就很好的解决了这个问题,根据流量大盘随时调整限流水位红线,做到精准,灵活的限流。

    经验总结

    Higress 网关的落地,给企业全面落地云原生微服务架构提供强有力的支持,对我们技术人员来说,这绝对是一个杠杆级别的开源产品,另外,在阿里云上又有对等的 SaaS 产品,这样的配合,将公有云和私有化部署的统一网关一次性全部解决,对企业来说是绝对的利好。

    1. 统一流量网关+业务网关能力,实现了给企业降本,为研发增效;
    2. 为云原生架构提供很好的基座,在异构语言服务化层面排除了网络通信难题;
    3. 路由热更新、无损升级、可视化 Console、开放的插件、基于 Kubernetes 和 Istio,给技术演进带来了更多的可能性。

    最后,我们祝愿 Higress 在云原生的道路上越走越远,大家一起用开源、开放、分享的心态将 Higress 建设地越来越好。

    - + \ No newline at end of file diff --git a/zh-cn/blog/user-uu/index.html b/zh-cn/blog/user-uu/index.html index b90f47f341..f0b97ec3bf 100644 --- a/zh-cn/blog/user-uu/index.html +++ b/zh-cn/blog/user-uu/index.html @@ -14,13 +14,13 @@ - +

    UU跑腿基于Higress的云原生网关实践

    · 阅读需 4 分钟

    UU跑腿介绍

    UU跑腿隶属于郑州时空隧道信息技术有限公司,是更专业的同城即时生活服务平台,以共享劳动力与时间为众包理念,人人都可注册成为跑腿师傅,并为附近的人提供帮取送、帮买、全能帮、帮排队等多样化同城即时服务,为中小企业、电商、本地商户提供安全专业的高端配送服务。UU跑腿秉承“让生活更美好”的理念,不断创新、不断进步,为用户提供更加优质的服务体验。

    背景需求

    UU跑腿对于云原生网关的要求是,能同时满足流量网关,微服务网关,以及安全网关的场景诉求,用一个网关来解决之前需要部署多个网关才能解决的问题:

    1. 具备高可靠性和高性能,可以替代之前部署的 Nginx Ingress 流量网关
    2. 同时支持 K8s 生态和传统微服务生态接入,支持(HTTP转Dubbo)协议转换,可以替代之前部署的 Spring Cloud Gateway 微服务网关
    3. 能够支持在网关入口处完成鉴权,避免每个后端服务重复实现鉴权功能,实现安全网关的能力
    4. 具备易用的控制台进行 API 的治理,以及具备丰富的可观测指标

    迁移 Higress 前的架构

    old-arch

    之前存在的主要痛点:

    1. Spring Cloud Gateway 自身参数调整改动需要重新部署影响流量,且动态路由需要进行复杂的配置,包括路由规则,容易出现配置错误导致系统异常
    2. 运维需要同时维护 Nginx Ingress 和 Spring Cloud Gateway,面对流量高峰进行进行扩容相关操作时,运维负担比较重,而且这样两层网关的请求的链路较长,可用性低、成本高

    迁移 Higress 后的架构

    new-arch

    Higress云原生网关实现负载均衡、路由、安全认证等功能。通过网关对外提供服务统一入口,并对请求进行鉴权、限流和监控等操作,用简单的架构保证了整体系统的稳定性和可靠性。

    1. 合并流量网关(K8s Nginx Ingress)和微服务网关(Spring Cloud Gateway ),降低网关成本,高性能服务;
    2. 同时支持 K8s service 和 Nacos 服务注册发现,满足技术需求对 K8s 生态和传统微服务生态接入。
    3. Nginx Ingress 完美迁移到 Higress,十分丝滑
    - + \ No newline at end of file diff --git a/zh-cn/community/contactItem/index.html b/zh-cn/community/contactItem/index.html index b54c83b1f5..528af29ea6 100644 --- a/zh-cn/community/contactItem/index.html +++ b/zh-cn/community/contactItem/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/community/contributorItem/index.html b/zh-cn/community/contributorItem/index.html index 15733fbe53..bc072e8651 100644 --- a/zh-cn/community/contributorItem/index.html +++ b/zh-cn/community/contributorItem/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/community/eventCard/index.html b/zh-cn/community/eventCard/index.html index 86de26c631..1b645eff38 100644 --- a/zh-cn/community/eventCard/index.html +++ b/zh-cn/community/eventCard/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/community/index.html b/zh-cn/community/index.html index 38e3402e7d..30a619d061 100644 --- a/zh-cn/community/index.html +++ b/zh-cn/community/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/docs/dev/CustomResourceDefinition/index.html b/zh-cn/docs/dev/CustomResourceDefinition/index.html index 715acb6e68..c39e11dafe 100644 --- a/zh-cn/docs/dev/CustomResourceDefinition/index.html +++ b/zh-cn/docs/dev/CustomResourceDefinition/index.html @@ -14,7 +14,7 @@ - + @@ -25,7 +25,7 @@ higress-api.png

    kubernetes client apis

    Hingress集成kubernetes client与kube-apiserver交互时会使用这里的模型对象。 kubernetes-client-api.png

    kubernetes client apis operate

    kubernetes-client-api-operate.png

    kubernetes client informer

    kubernetes-client-informer.png

    kubernetes client informer lister

    kubernetes-client-informer-lister.png

    3、集成 Controller

    这里主要是在ingress_config,添加自定义CRD Resource的引用对象,并且通过informer机制监听CRD实例的变化,然后实现相关业务逻辑,比如生成istio EnvoyFilter等

    higress/pkg/ingress/config/ingress_config.go

    定义相关属性

    //异步线程启动后,可以监听CRD-http2rpc资源变化事件
    http2rpcController http2rpc.Http2RpcController
    //资源变化事件处理时通过Lister获取发送变化的CRD实例对象
    http2rpcLister netlisterv1.Http2RpcLister
    //存储全量的http2rpcs资源对象,以便在其他事件流程中消费
    http2rpcs map[string]*higressv1.Http2Rpc

    ingress-config.png

    在higress启动阶段初始化上述变量

    这里就会引用自动化生成的一些代码,进行Controller的创建及事件绑定。 ingress-config-initial.png

    实现CRD变更事件处理逻辑

    ingress-config-event.png

    扩展阅读

    Kubernetes Controller 机制详解(一)

    Kubernetes Informer机制

    - + \ No newline at end of file diff --git a/zh-cn/docs/dev/architecture/index.html b/zh-cn/docs/dev/architecture/index.html index d453cf0f7c..0d00e18948 100644 --- a/zh-cn/docs/dev/architecture/index.html +++ b/zh-cn/docs/dev/architecture/index.html @@ -14,13 +14,13 @@ - +

    组件编译说明

    Higress Controller

    Higress 的控制面程序,会连接 Istio ,用于生成 Istio API 对象,通过 xDS 协议发送给 Istio。

    在 higress 仓库目录下执行 make build 即可进行本地环境能运行的二进制编译

    若需要编译 docker 镜像,请执行 make docker-build。Higress Controller使用的Istio pilot镜像使用make build-istio-local 编译。

    Higress Gateway

    Higress 的数据面程序,用于实现网关路由转发等能力。

    在 higress 仓库目录下执行 make build-gateway-local 会编译出 Higress Gateway 的镜像。

    - + \ No newline at end of file diff --git a/zh-cn/docs/dev/code/index.html b/zh-cn/docs/dev/code/index.html index 336b19db04..154933b1b2 100644 --- a/zh-cn/docs/dev/code/index.html +++ b/zh-cn/docs/dev/code/index.html @@ -14,13 +14,13 @@ - +

    源码阅读指引

    如果您想给 Higress 贡献代码,请参考参与贡献

    代码目录结构说明

    • cmd: 命令行参数解析等处理代码

    • pkg/ingress: Ingress 资源转换为 Istio 资源等相关代码

    • pkg/bootstrap: 包括启动 gRPC/xDS/HTTP server 等的代码

    • registry: 实现对接多种注册中心进行服务发现的代码

    • envoy: 依赖的 envoy 官方仓库 commit,以及对应的补丁代码

    • istio: 依赖的 istio 官方仓库 commit,以及对应的补丁代码

    • plugins: Higress 插件 sdk,以及官方内置插件代码

    • script: 编译相关脚本

    • docker: docker 镜像构建相关脚本

    在编译过程中会自动执行make prebuild,将产生 external 目录,这是将用到的 envoy 和 istio 依赖,打上对应的补丁代码后生成。

    如果要修改 envoy 和 istio 代码,并产生新的补丁文件,可以直接在 external 目录下修改,并进行重命名,再执行 prebuild,之后对比生成补丁文件,例如:

    mv external/envoy external/envoy_new
    make prebuild
    diff -Naur external/envoy external/envoy_new > envoy/1.20/patches/envoy/$(date +%Y%m%d)-what-changed.patch

    注意补丁执行顺序按照文件名字符顺序,请以时间戳开头

    - + \ No newline at end of file diff --git a/zh-cn/docs/developers/committer-guide/label-an-issue-guide_dev/index.html b/zh-cn/docs/developers/committer-guide/label-an-issue-guide_dev/index.html index e980587e56..fb98f520f0 100644 --- a/zh-cn/docs/developers/committer-guide/label-an-issue-guide_dev/index.html +++ b/zh-cn/docs/developers/committer-guide/label-an-issue-guide_dev/index.html @@ -14,13 +14,13 @@ - +

    给问题打标签

    如果您正在处理一个问题,请记得给这个问题标记一个或者多个您认为有意义的标签。有了标签,其他开发人员就会很轻松地识别出问题,以便对其进行分类并跟踪进度。

    对于需要编码和发版修复的issues和pull requests,需要您将其标记为milestone

    一些常用的标签:

    • 请求帮助
      • help wanted
      • good first issue
    • 优先级
      • priority/blocker
      • priority/high
      • priority/low
      • priority/normal
    • 状态
      • status/need-triage
      • status/DO-NOT-MERGE
      • status/READY-TO-MERGE
      • status/invalid
      • status/wontfix
    • 类型
      • type/bug
      • type/documentation
      • type/enhancement
      • type/feature
    - + \ No newline at end of file diff --git a/zh-cn/docs/developers/committer-guide/release-guide_dev/index.html b/zh-cn/docs/developers/committer-guide/release-guide_dev/index.html index 53921309f9..4ec287cb6a 100644 --- a/zh-cn/docs/developers/committer-guide/release-guide_dev/index.html +++ b/zh-cn/docs/developers/committer-guide/release-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/docs/developers/committer-guide/website-guide_dev/index.html b/zh-cn/docs/developers/committer-guide/website-guide_dev/index.html index 5d3ce72cb1..55c3d4fc82 100644 --- a/zh-cn/docs/developers/committer-guide/website-guide_dev/index.html +++ b/zh-cn/docs/developers/committer-guide/website-guide_dev/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/docs/developers/contributor-guide/new-contributor-guide_dev/index.html b/zh-cn/docs/developers/contributor-guide/new-contributor-guide_dev/index.html index 03d8f121dc..ec2111d1b1 100644 --- a/zh-cn/docs/developers/contributor-guide/new-contributor-guide_dev/index.html +++ b/zh-cn/docs/developers/contributor-guide/new-contributor-guide_dev/index.html @@ -14,13 +14,13 @@ - +

    新贡献者向导

    这篇向导旨在给正在准备向 Higress 提交贡献的新手提供指导。

    邮件列表描述

    TBD

    报告问题

    您始终可以通过Github Issues 向Higress报告问题。

    如果您正在报告bug,请参阅问题报告模版

    如果您正在报告功能要求,请参阅问题报告模版

    如果您正在报告常规问题,比如提出一个问题,则可以打开常规问题

    发送 pull request

    • 参考pull request template
    • 在您发送pull request之前,请同步您的github仓库和远程仓库,这会使您的pull request简单明了,具体操作请看如下所示步骤:
    git remote add upstream git@github.com:alibaba/higress.git
    git fetch upstream
    git rebase upstream/main
    git checkout -b your_awesome_patch
    ... add some work
    git push origin your_awesome_patch

    编码规范

    请按照CONTRIBUTING.md中的编码规范对自己的代码进行检查。

    - + \ No newline at end of file diff --git a/zh-cn/docs/developers/contributor-guide/reporting-security-issues_dev/index.html b/zh-cn/docs/developers/contributor-guide/reporting-security-issues_dev/index.html index d21f42bfd7..f5f52648df 100644 --- a/zh-cn/docs/developers/contributor-guide/reporting-security-issues_dev/index.html +++ b/zh-cn/docs/developers/contributor-guide/reporting-security-issues_dev/index.html @@ -14,14 +14,14 @@ - +

    报告安全问题

    Higress在消除其软件项目中的安全性问题方面采取严格的立场,对与其功能和特性有关的问题非常敏感并很快提出。

    报告漏洞

    如果您对Higress的安全性有担心,或者发现漏洞或潜在威胁,请发送电子邮件至higress@googlegroups.com 与Higress安全团队联系。在邮件中,指定问题或潜在威胁的描述。还敦促您推荐重现和复制问题的方法。Higress社区会在评估和分析调查结果之后与您联系。 请先注意在安全电子邮件中报告安全问题,然后再在公共领域公开该问题。

    漏洞处理

    漏洞处理过程的概述是:

    • 报告者将漏洞秘密报告给Higress。
    • 相应项目的安全团队与报告者私下合作来解决漏洞。
    • 制作了包含该修复程序的有关Higress产品的新版本。
    • 该漏洞已公开宣布。
    - + \ No newline at end of file diff --git a/zh-cn/docs/developers/contributor-guide/test-coverage-guide_dev/index.html b/zh-cn/docs/developers/contributor-guide/test-coverage-guide_dev/index.html index e2f9529c00..a52df9b874 100644 --- a/zh-cn/docs/developers/contributor-guide/test-coverage-guide_dev/index.html +++ b/zh-cn/docs/developers/contributor-guide/test-coverage-guide_dev/index.html @@ -14,13 +14,13 @@ - +

    测试覆盖率向导

    测试粒度如何划分

    测试粒度如何划分是个大问题。Chris Richardson 在" [降低测试金字塔:微服务的有效测试策略](https://microservices.io/microservices/testing/2019/09/20/oracle-code-one-testing.html)" 一文中将服务测试划分为:单元测试、集成测试、组件测试、端到端的测试。我们可以在设计测试用例的过程中,拿来借鉴。

    单元测试

    1.写单元测试的收益

    • 单元测试能帮助每个人深入代码细节,了解代码的功能。
    • 通过测试用例我们能发现bug,并提交代码的健壮性。
    • 测试用例同时也是代码的demo用法。

    2.单元测试用例的一些设计原则

    • 应该精心设计好步骤,颗粒度和组合条件。
    • 注意边界条件。
    • 单元测试也应该好好设计,不要写无用的代码。
    • 当你发现一个方法很难写单元测试时,如果可以确认这个方法臭代码,那么就和开发者一起重构它。
    • Higress中用的mock框架是: mockito. 下面是一些开发向导:mockito tutorial,mockito refcard
    • TDD(可选):当你开始写一个新的功能时,你可以试着先写测试用例。

    3.测试覆盖率设定值

    4.项目约定

    • Higress 项目的单元测试用例分布在项目每个子模块中,测试断言类以Test结尾。

    集成测试

    项目约定

    • 集成测试在本项目泛指单元测试以上级别的测试。
    • 项目使用github actionsjiblib maven 插件fabric maven 插件testContainers等用来构建Docker镜像,搭建集成测试环境
    • 区别于单元测试,某个测试用例,需要依赖第三方中间件的,可以不用Mock, 使用上面介绍的工具搭建docker环境,进行测试。但是也要注意搭建组件的粒度。过于复杂的环境,可以:核心测试依赖的中间件可以docker搭建,非强依赖的可以Mock
    • Higress 项目的集成测试用例分布统一放在integration-test子模块中,测试断言类以IT结尾。
    • 这里还用 Junit5
    • 测试用例并行跑的过程中,注意公共中间件的隔离状态,规划好所造数据,防止冲突。
    - + \ No newline at end of file diff --git a/zh-cn/docs/developers/developers_dev/index.html b/zh-cn/docs/developers/developers_dev/index.html index 9f82d1a879..c2adf7c89c 100644 --- a/zh-cn/docs/developers/developers_dev/index.html +++ b/zh-cn/docs/developers/developers_dev/index.html @@ -14,13 +14,13 @@ - +

    开发人员

    开发人员

    本页面展示了Higress的开发团队。请通过提交PR的方式把自己的信息添加到列表上。注:排名不分先后

    Higress Committer 列表

    姓名github公司
    张添翼johnlanniAlibaba
    耿蕾蕾gengleileiAlibaba
    范扬SpecialYangAlibaba
    赵炳堃sjtuzbkAlibaba
    凌轶群LynskylatePdd Holdings Inc
    刘训灼XunzhuoTencent
    董艺荃CH3CHOTrip.com
    李强林Charlie17LiZJU-SEL
    宋鹏远songpengyuanOkki.com
    田亚涛HinstenyAnt
    吴新军2456868764

    Higress开发者角色

    Higress开发者包含Maintainer、Committer、Contributor三种角色,每种角色的标准定义如下。

    Maintainer

    Maintainer是对Higress项目(包括Higress下的项目)的演进和发展做出显著贡献的个人。具体包含以下的标准:

    • 完成多个关键模块或者工程的设计与开发,是项目的核心开发人员;
    • 持续的投入和激情,能够积极参与社区、官网、issue、PR等项目相关事项的维护;
    • 在社区中具有有目共睹的影响力,能够代表Higress参加重要的社区会议和活动;
    • 具有培养Committer和Contributor的意识和能力;

    Committer

    Committer是具有Higress仓库写权限的个人,包含以下的标准:

    • 能够在长时间内做持续贡献issue、PR的个人;
    • 参与issue列表的维护及重要feature的讨论;
    • 参与code review;

    Contributor

    Contributor是对Higress项目有贡献的个人,标准为:

    • 提交过PR并被合并;
    - + \ No newline at end of file diff --git a/zh-cn/docs/developers/guide_dev/index.html b/zh-cn/docs/developers/guide_dev/index.html index ac457bcb42..ad481da051 100644 --- a/zh-cn/docs/developers/guide_dev/index.html +++ b/zh-cn/docs/developers/guide_dev/index.html @@ -14,13 +14,13 @@ - +

    为Higress贡献

    如果您有兴趣攻克Higress,欢迎您。首先,我们非常鼓励这种意愿。这是为您提供帮助的列表。

    话题

    贡献插件

    Higress 基于 WASM 等方式具备了很好的可扩展性,具体贡献方式请参考此处说明

    对于使用 GO 语言开发 WASM 插件,可以参考这篇文档

    报告安全问题

    安全问题应该始终得到认真对待。按照我们通常的原则,我们不鼓励任何人散布安全问题。如果您发现Higress的安全问题,请不要公开讨论,甚至不要公开问题。相反,我们建议您向我们发送一封私人电子邮件至higress@googlegroups.com进行举报。

    报告一般问题

    坦白地说,我们认为Higress的每位用户都是非常友好的贡献者。体验Higress之后,您可能会对项目有一些反馈。然后随时通过NEW ISSUE打开问题

    因为我们在一个分布式的方式合作项目Higress,我们对此表示赞赏编写良好详细明确的问题报告。为了提高沟通效率,我们希望每个人都可以搜索您的问题是否在搜索列表中。如果发现它存在,请在现有问题下的评论中添加您的详细信息,而不要打开一个全新的issue。

    为了使问题详细信息尽可能地标准,我们为问题报告者设置了“ 问题模板 ”。请务必按照说明填写模板中的字段。

    在很多情况下,您可以打开一个问题:

    • 错误报告
    • 功能要求
    • 性能问题
    • 功能提案
    • 功能设计
    • 需要帮助
    • doc不完整
    • 测试改进
    • 有关项目的任何问题
    • 等等

    另外,我们必须提醒您,在填写新issue时,请记住从您的帖子中删除敏感数据。敏感数据可以是密码,密钥,网络位置,私人业务数据等。

    代码和文档贡献

    鼓励采取一切措施使Higress项目变得更好。在GitHub上,Higress的每个改进都可以通过PR(拉取请求的缩写)来实现。

    • 如果发现错字,请尝试解决!
    • 如果发现错误,请尝试修复它!
    • 如果发现一些冗余代码,请尝试将其删除!
    • 如果发现缺少一些测试用例,请尝试添加它们!
    • 如果您可以增强功能,请不要犹豫!
    • 如果发现隐式代码,请尝试添加注释以使其清晰!
    • 如果您发现代码丑陋,请尝试重构它!
    • 如果可以帮助改善文档,那就再好不过了!
    • 如果发现文档不正确,请直接解决该问题!
    • ...

    实际上,不可能完全列出它们。只要记住一个原则:

    我们期待您的任何回复。

    由于您已准备好通过PR改善Higress,因此建议您在此处查看PR规则。

    工作准备

    要提出PR,我们假设您已经注册了GitHub ID。然后,您可以按照以下步骤完成准备工作:

    1. FORK Higress分支到您的存储库。要使此工作有效,您只需要单击Higress / Higress主页右边的按钮Fork 。然后,您将在https://github.com/<your-username>/Higressyour-username找到您的存储库,这是您的GitHub用户名。

    2. CLONE您自己的存储库以在本地进行开发。用于git clone git@github.com:<your-username>/Higress.git将存储库克隆到本地计算机。然后,您可以创建新分支来完成您希望进行的更改。

    3. Set Remote上游设置为git@github.com:alibaba/higress.git使用以下两个命令:

    git remote add upstream git@github.com:alibaba/higress.git
    git remote set-url --push upstream no-pushing

    使用此远程设置,您可以像这样检查git远程配置:

    $ git remote -v
    origin git@github.com:<your-username>/Higress.git (fetch)
    origin git@github.com:<your-username>/Higress.git (push)
    upstream git@github.com:alibaba/higress.git (fetch)
    upstream no-pushing (push)

    加上这一点,我们可以很容易地将本地分支与上游分支同步。

    分支定义

    现在,我们假设通过拉取请求所做的所有贡献都是针对Higress中的主分支。在做出贡献之前,了解分支定义会有所帮助。

    作为贡献者,请再次记住,通过拉取请求进行的每个贡献都是为了分支发展。在Higress项目中,还有其他几个分支,我们通常称它们为发布分支(例如0.6.0、0.6.1)\功能分支,修补程序分支和主分支。

    正式发布版本时,将有一个发布分支,并以版本号命名。

    发布之后,我们将发布分支的提交合并到master分支中。

    当发现某个版本中存在错误时,我们将决定在更高版本中进行修复或在特定修补程序版本中进行修复。当我们决定修复此修补程序版本时,我们将根据相应的发行分支检出该修补程序分支,执行代码修复和验证,然后将其合并到开发分支和master分支中。

    对于更大的功能,我们将拉出功能分支以进行开发和验证。

    提交规则

    实际上,在Higress中,我们在提交时要认真对待两个规则:

    提交讯息

    提交消息可以帮助审稿人更好地了解提交的PR的目的。它也可以帮助加快代码审查过程。我们鼓励贡献者清楚明白提交消息而不是模棱两可的消息。通常,我们提倡以下提交消息类型:

    • docs:xxxx。例如,“ docs:添加有关Higress群集安装的文档”。
    • feature:xxxx。例如,“新功能:在AT模式下支持oracle”。
    • bugfix:xxxx。例如,“错误修正:修正了输入nil参数时的错误”。
    • refactor:xxxx。例如,“重构:简化以使代码更具可读性”。
    • test:xxx。例如,“测试:为func InsertIntoArray添加单元测试用例”。
    • 其他可读和显式的表达方式。

    另一方面,我们不鼓励捐助者像以下方式提交消息:

    • 修正错误
    • 更新
    • 添加文档

    如果您迷路了,请参阅《如何编写Git提交消息》作为开始。

    提交内容

    提交内容表示一次提交中包含的所有内容更改。我们最好将内容包含在一个提交中,这样可以在没有任何其他提交帮助的情况下支持审阅者的完整审阅。换句话说,一次提交中的内容可以传递CI以避免代码混乱。简而言之,我们要记住三个小规则:

    • 避免在提交中进行很大的更改;
    • 每次提交均完整且可审查。
    • 提交时检查git config(user.nameuser.email)以确保它与您的GitHub ID相关联。

    另外,在代码更改部分,我们建议所有贡献者都应阅读Higress代码样式

    无论提交消息还是提交内容,我们都更加注重代码审查。

    PR 说明

    PR是更改Higress项目文件的唯一方法。为了帮助审稿人更好地实现目标,PR 说明不能太详细。我们鼓励贡献者遵循PR模板完成请求请求。

    测试用例贡献

    任何测试用例都将受到欢迎。当前,Higress功能测试用例是高度优先的。

    致力于帮助任何事情

    我们选择GitHub作为Higress合作的主要场所。因此,Higress的最新更新始终在这里。尽管通过PR捐款是一种明确的帮助方式,但我们仍然呼吁其他方式。

    • 如果可以的话,回复他人的问题;
    • 帮助解决其他用户的问题;
    • 帮助审查他人的PR设计;
    • 帮助审查PR中其他人的代码;
    • 讨论有关Higress的问题,以使事情更加清晰;
    • 在GitHub之外倡导Higress技术;
    • 在Higress上写博客,等等。
    - + \ No newline at end of file diff --git a/zh-cn/docs/ops/deploy-by-docker-compose/index.html b/zh-cn/docs/ops/deploy-by-docker-compose/index.html index 70b9096ee7..2586119e91 100644 --- a/zh-cn/docs/ops/deploy-by-docker-compose/index.html +++ b/zh-cn/docs/ops/deploy-by-docker-compose/index.html @@ -14,13 +14,13 @@ - +

    基于 Docker Compose 进行独立部署

    Docker Compose 是用于定义和运行多容器 Docker 应用程序的工具。通过它,我们可以使用 YAML 文件来脱离 K8s 集群来实现 Higress 网关的独立部署。

    安装 Higress

    基于 Docker Compose 部署时,Higress 网关由如下几个服务组成:

    • apiserver:基础设施服务。负责模拟 K8s 的 API Server;
    • controller:控制面服务一号。负责配置收集整合所有的配置数据和服务列表;
    • pilot:控制面服务一号。负责下发网关路由数据;
    • gateway:数据面服务。负责承载实际的网关请求;
    • console:Higress 网关控制台

    安装命令

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- [DESTINATION] [OPTIONS...]

    安装参数

    参数名参数说明默认值
    DESTINATION目标安装目录./higress
    -a
    --auto-run
    配置完成后自动启动 Higress 网关
    -c CONFIG_URL
    --config-url CONFIG_URL
    配置服务的 URL。
    - 若使用独立部署的 Nacos 服务(版本不低于 2.0.0),URL 格式为:nacos://192.168.0.1:8848
    - 若在本地磁盘上保存配置,URL 格式为:file://opt/higress/conf
    --use-builtin-nacos使用内置的 Nacos 服务。不建议用于生产环境。如果设置本参数,则无需设置-c参数
    --nacos-ns=NACOS_NAMESPACE用于保存 Higress 配置的 Nacos 命名空间 IDhigress-system
    --nacos-username=NACOS_USERNAME用于访问 Nacos 的用户名。仅用于 Nacos 启动了认证的情况下
    --nacos-password=NACOS_PASSWORD用于访问 Nacos 的用户密码。仅用于 Nacos 启动了认证的情况下
    -k KEY
    --data-enc-key=KEY
    用于加密敏感配置数据的密钥。长度必须为 32 个字符。若未设置,Higress 将自动生成一个随机的密钥。若需集群部署,此项必须设置随机字符串
    --nacos-port=NACOS_PORT内置 NACOS 服务在服务器本地监听的端口8848
    --gateway-http-port=GATEWAY_HTTP_PORTHigress Gateway 在服务器本地监听的 HTTP 端口80
    --gateway-https-port=GATEWAY_HTTPS_PORTHigress Gateway 在服务器本地监听的 HTTPS 端口443
    --gateway-metrics-port=GATEWAY_METRIC_PORTHigress Gateway 在服务器本地监听的用于暴露运行指标端口15020
    --console-port=CONSOLE_PORTHigress Console 在服务器本地监听的端口8080
    -r
    --rerun
    在 Higress 已配置完成后重新执行配置流程
    -h
    --help
    显示帮助信息
    - + \ No newline at end of file diff --git a/zh-cn/docs/ops/deploy-by-helm/index.html b/zh-cn/docs/ops/deploy-by-helm/index.html index d7891552f0..e302a64cdb 100644 --- a/zh-cn/docs/ops/deploy-by-helm/index.html +++ b/zh-cn/docs/ops/deploy-by-helm/index.html @@ -14,13 +14,13 @@ - +

    使用 Helm 进行云原生部署

    Helm 是一个用于自动化管理和发布 Kubernetes 软件的包管理系统。通过 Helm 可以在您的 Kubernetes 集群上快速部署安装 Higress 网关。

    安装 Higress

    Higress 网关由控制面组件 higress-controller 和数据面组件 higress-gateway 组成。higress-gateway负责承载数据流量higress-controller 负责管理配置下发

    Helm 安装命令

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress higress.io/higress -n higress-system --create-namespace

    常用安装参数

    完整参数介绍请查看运维参数说明

    参数名参数说明默认值
    全局参数
    global.local如果要安装至本地 K8s 集群(如 Kind、Rancher Desktop 等),请设置为 truefalse
    global.ingressClass用于过滤被 Higress Controller 监听的 Ingress 资源的 IngressClass
    在集群内部署了多个网关时,可以使用这一参数来区分每个网关的职责范围。
    IngressClass 有一些特殊的取值:
    1. 如果设置为“nginx”,Higress Controller 将监听 Ingress 为 nginx 或为空的 Ingress 资源。
    2. 如果设为空,Higress Controller 将监听 K8s 集群内的全部 Ingress 资源。
    higress
    global.watchNamespace如果值不为空,Higress Controller 将只会监听指定命名空间下的资源。
    当基于 K8s 命名空间进行业务系统隔离时,若需要对每个命名空间部署一套独立的网关,可以通过这一参数来限制 Higress 监听指定命名空间内的 Ingress。
    ""
    global.disableAlpnH2是否在 ALPN 中禁用 HTTP/2 协议true
    global.enableStatus若为true, Higress Controller 将会更新 Ingress 资源的 status 字段。
    为避免从 Nginx Ingress 迁移过程中,覆盖 Ingress 对象的 status 字段,可以将这一参数设置为false,这样 Higress 默认就不会将入口 IP 写入 Ingress 的 status 字段。
    true
    global.enableIstioAPI若为true,Higress Controller 将同时监听 istio 资源false
    global.istioNamespaceistio 安装到的命名空间istio-system
    核心组件参数
    higress-core.gateway.replicasHigress Gateway 的 pod 数量2
    higress-core.controller.replicasHigress Controller 的 pod 数量1
    控制台参数
    higress-console.replicaCountHigress Console 的 pod 数量1
    higress-console.service.typeHigress Console 所使用的 K8s Service 类型ClusterIP
    higress-console.domain对外用于访问 Higress Console 的域名console.higress.io
    higress-console.tlsSecretNameHigress Console 提供 HTTPS 访问所使用的 Secret 证书资源名称""
    higress-console.web.login.prompt登录页面上显示的提示信息""
    higress-console.admin.password若值不为空,则 admin 账号的密码将被配置为指定值""
    higress-console.o11y.enabled若为 true,将同时安装可观测性套件(Grafana + Promethues)false
    higress-console.pvc.rwxSupported标识目标 K8s 集群是否支持 PersistentVolumeClaim 的 ReadWriteMany 操作方式。true

    支持 Istio CRD(可选)

    集群里需要提前安装好 Istio 的 CRD,如果不希望安装 Istio,也可以只安装 Istio 的 CRD:

    helm repo add istio https://istio-release.storage.googleapis.com/charts
    helm install istio-base istio/base -n istio-system --create-namespace

    这种模式下,需要更新 Higress 的部署参数:

    helm upgrade higress -n higress-system --set global.enableIstioAPI=true higress.io/higress --reuse-values
    - + \ No newline at end of file diff --git a/zh-cn/docs/ops/hgctl/index.html b/zh-cn/docs/ops/hgctl/index.html index 8c2d2f21e2..af7fb64297 100644 --- a/zh-cn/docs/ops/hgctl/index.html +++ b/zh-cn/docs/ops/hgctl/index.html @@ -14,13 +14,13 @@ - +

    如何下载 hgctl

    通过 curl 命令下载最新版本的 hgctl 到本地

      curl -Ls https://raw.githubusercontent.com/alibaba/higress/main/tools/hack/get-hgctl.sh | VERSION=latest bash

    一、安装 Profile 说明

    higress 目前支持三个内置预定义 profile 包括: local-k8s , k8s, local-docker。

    • local-k8s profile 安装 higress 到本地 k8s 集群比如 kind 集群,主要用于开发和测试 higress 功能。 默认安装 higress 核心组件外,还安装包括可观测组件(Grafana + Promethues), IstioAPI, GatewayAPI组件。
    • k8s profile 安装 higress 到 k8s 集群, 默认只安装 higress 核心组件。
    • local-docker profile 安装 higress 到本地 docker 环境。

    1. 查看默认 profile 列表和导出 profile

    • 查看 profile 列表
    hgctl profile list

    higress configuration profiles:
    k8s
    local-docker
    local-k8s
    • 导出 profile local-k8s profile 到本地 local-k8s.yaml 文件
    hgctl profile dump local-k8s -o ./local-k8s.yaml

    2. 内置三个 profile 配置项说明

    profile 内容包含 global, console, gateway, controller, storage, values , charts 七大配置项。

    1. local-k8s profile

    local-k8s profile 具体内容和说明如下:

    profile: local-k8s # profile 名称
    global:
    install: local-k8s # 安装模式 k8s/local-k8s/local-docker
    ingressClass: higress # 用于过滤被 Higress Controller 监听的 Ingress 资源的 IngressClass。
    enableIstioAPI: true # 若为true,Higress Controller 将同时监听 istio 资源
    enableGatewayAPI: true # 若为true 激活 gateway api
    namespace: higress-system # higress 安装到的命名空间

    console:
    replicas: 1 # Higress Console 的 pod 数量
    o11yEnabled: true # 若为 true,将同时安装可观测性套件(Grafana + Promethues)

    gateway:
    replicas: 1 # Higress Gateway 的 pod 数量

    controller:
    replicas: 1 # Higress Controller 的 pod 数量

    # 其他自定义的 helm values
    values:

    charts:
    higress:
    url: https://higress.io/helm-charts # higress helm chart repo 地址
    name: higress # higress helm chart 名称
    version: latest # higress helm chart 版本
    standalone:
    url: https://higress.io/standalone/get-higress.sh # higress standalone 安装器地址
    name: standalone # higress standalone 安装器名称
    version: latest # higress standalone 安装器版本
    1. k8s profile

    k8s profile 和 local-k8s profile 差异主要在可观测组件(Grafana + Promethues), IstioAPI, GatewayAPI 默认是没有激活,如果需要这些功能,需要在安装时设置这些属性

    k8s profile 具体内容和说明如下:

    profile: k8s # profile 名称
    global:
    install: k8s # 安装模式 k8s/local-k8s/local-docker
    ingressClass: higress # 用于过滤被 Higress Controller 监听的 Ingress 资源的 IngressClass。
    enableIstioAPI: false # 若为true,Higress Controller 将同时监听 istio 资源
    enableGatewayAPI: false # 若为true 激活 gateway api
    namespace: higress-system # higress 安装到的命名空间

    console:
    replicas: 1 # Higress Console 的 pod 数量
    o11yEnabled: false # 若为 true,将同时安装可观测性套件(Grafana + Promethues)

    gateway:
    replicas: 2 # Higress Gateway 的 pod 数量

    controller:
    replicas: 1 # Higress Controller 的 pod 数量

    # 其他自定义的 helm values
    values:

    charts:
    higress:
    url: https://higress.io/helm-charts # higress helm chart repo 地址
    name: higress # higress helm chart 名称
    version: latest # higress helm chart 版本
    standalone:
    url: https://higress.io/standalone/get-higress.sh # higress standalone 安装器地址
    name: standalone # higress standalone 安装器名称
    version: latest # higress standalone 安装器版本
    1. local-docker profile

    local-docker profile 具体内容和说明如下:

    profile: local-docker # profile 名称
    global:
    install: local-docker # 安装模式 k8s/local-k8s/local-docker

    console:
    port: 8080 # console 监听端口

    gateway:
    httpPort: 80 # gateway 监听 http 端口
    httpsPort: 443 # gateway 监听 https 端口
    metricsPort: 15020 # gateway 指标输出监听端口

    controller:

    # 后端存储系统设置,现在支持文件系统和 nacos
    storage:
    url: file://${INSTALLPACKAGEPATH}/conf # 配置服务的 URL。若使用独立部署的 Nacos 服务(版本不低于 2.0.0),URL 格式为:nacos://192.168.0.1:8848 - 若在本地磁盘上保存配置,URL 格式为:file://opt/higress/conf
    ns: higress-system # 用于保存 Higress 配置的 Nacos 命名空间 ID
    username: # 用于访问 Nacos 的用户名。仅用于 Nacos 启动了认证的情况下
    password: # 用于访问 Nacos 的用户密码。仅用于 Nacos 启动了认证的情况下
    dataEncKey: # 用于加密敏感配置数据的密钥。长度必须为 32 个字符。若未设置,Higress 将自动生成一个随机的密钥。若需集群部署,此项必须设置

    charts:
    higress:
    url: https://higress.io/helm-charts # higress helm chart repo 地址
    name: higress # higress helm chart 名称
    version: latest # higress helm chart 版本
    standalone:
    url: https://higress.io/standalone/get-higress.sh # higress standalone 安装器地址
    name: standalone # higress standalone 安装器名称
    version: latest # higress standalone 安装器版本

    配置服务的 URL 默认 file://${INSTALLPACKAGEPATH}/conf 是保存在本地文件系统下, 其中 ${INSTALLPACKAGEPATH} 是当前安装下 higress-standalone目录下创建 conf 目录

    二、安装命令: hgctl install

    hgctl install 安装命令具体参数如下:

    hgctl install --help
    The install command generates an higress install manifest and applies it to a cluster.

    Usage:
    hgctl install [flags]

    Examples:
    # Apply a default higress installation
    hgctl install

    # Install higress on local kubernetes cluster
    hgctl install --set profile=local-k8s

    # Install higress on local docker environment with specific gateway port
    hgctl install --set profile=local-docker --set gateway.httpPort=80 --set gateway.httpsPort=443

    # To override profile setting
    hgctl install --set profile=local-k8s --set global.enableIstioAPI=true --set gateway.replicas=2"

    # To override helm setting
    hgctl install --set profile=local-k8s --set values.global.proxy.resources.requsts.cpu=500m"

    Flags:
    --context string The name of the kubeconfig context to use.
    -f, --filename strings Path to file containing helm custom values
    -h, --help help for install
    --kubeconfig string Path to the kubeconfig file to use for CLI requests.
    -d, --manifests string Specify a path to a directory of profiles
    (e.g. ~/Downloads/higress/manifests).
    -s, --set stringArray Override an higress profile value, e.g. override profile values (--set gateway.replicas=2), or override helm values (--set values.global.proxy.resources.requsts.cpu=500m).

    安装参数说明:

    • hgctl install 核心参数就是两个 -s (--set) 和 -f (--filename) 。

    • --set 参数是设置 profile 配置项的值, -f 传入 helm 自定义 values 值的 yaml 文件地址。

    • 通过 -s profile=profile 内置 profile 名称或者 profile yaml 文件地址来指定安装 profile 来源。

    • 安装成功后,会在当前用户 $HOME 目录下写入当前安装的profile配置 ~/.hgctl/profiles/install.yaml , 升级时根据这个 profile 来升级。(后续版本会有变化)

    安装样例说明

    1. 默认安装
    hgctl install

    Please select higress install configration profile:

    1.Install higress to local kubernetes cluster like kind etc.

    2.Install higress to kubernetes cluster

    3.Install higress to local docker environment

    Please input 1, 2 or 3 to select, input your selection:

    默认安装没有指定 profile, 会提示选择安装 profile。

    1. 指定 k8s profile 安装 , 同时激活 IstioAPI, GatewayAPI 和 helm values 自定义 console 和 gateway resources 配置。

    自定义 helm values.yaml 如下:

    global:
    istioNamespace: istio-system

    higress-console:
    resources:
    requests:
    cpu: 500m
    memory: 512Mi

    higress-core:
    gateway:
    resources:
    requests:
    cpu: 2000m
    memory: 2048Mi
    limits:
    cpu: 2000m
    memory: 2048Mi

    helm 自定义配置项参考文件如下:

    安装命令如下:

    hgctl install --set profile=k8s  --set global.enableIstioAPI=true --set global.enableGatewayAPI=true --set gateway.replicas=1 -f ./values.yaml

    1. 本地 docker 环境下安装,同时指定 gateway http 和 https 端口
    hgctl install --set profile=local-docker --set gateway.httpPort=80 --set gateway.httpsPort=443

    默认安装后端存储采用文件系统保存配置, 如果后端存储采用 nacos 保存, 安装时传入 --set storage.url=nacos://192.168.0.1:8848, 这里设置具体 nacos 服务地址。

    安装完成后,在当前目录下创建 higress-standalone 目录,具体结构如下:

    ├── hgctl
    ├── higress-standalone
    │ ├── conf
    │ │ ├── configmaps
    │ │ ├── endpoints
    │ │ ├── http2rpcs
    │ │ ├── ingressclasses
    │ │ ├── ingresses
    │ │ ├── mcpbridges
    │ │ ├── mutatingwebhookconfigurations
    │ │ ├── namespaces
    │ │ ├── nodes
    │ │ ├── pods
    │ │ ├── secrets
    │ │ ├── services
    │ │ ├── validatingwebhookconfigurations
    │ │ └── wasmplugins
    │ ├── get-higress.sh
    │ └── higress
    │ ├── CODEOWNERS
    │ ├── LICENSE
    │ ├── README.md
    │ ├── VERSION
    │ ├── bin
    │ └── compose

    目录和文件具体内容如下:

    • higress-standalone/conf: 配置后端存储文件目录
    • higress-standalone/higress: higress 安装文件目录
    • higress-standalone/higress/compose: higress docker compose 配置目录
    • higress-standalone/higress/bin: 管理 higress 脚本目录
    • higress-standalone/higress/compose/.env: higress 安装后生成配置文件

    安装成功后,会在当前用户 $HOME 目录下写入当前安装的 profile 配置: ~/.hgctl/profiles/install.yaml, 升级时根据这个 profile 来升级。(后续版本会有变化)

    四、升级命令: hgctl upgrade

    升级命令参数如下:

    hgctl upgrade --help

    The upgrade command is an alias for the install command that performs additional upgrade-related checks.

    Usage:
    hgctl upgrade [flags]

    Flags:
    --context string The name of the kubeconfig context to use.
    -f, --filename strings Path to file containing helm custom values
    -h, --help help for upgrade
    --kubeconfig string Path to the kubeconfig file to use for CLI requests.
    -d, --manifests string Specify a path to a directory of profiles
    (e.g. ~/Downloads/higress/manifests).
    -s, --set stringArray Override an higress profile value, e.g. to choose a profile
    (--set profile=local-k8s), or override profile values (--set gateway.replicas=2), or override helm values (--set values.global.proxy.resources.requsts.cpu=500m).

    升级命令参数和安装参数时一致的,核心参数就是两个 -s (--set) 和 -f (--filename) 。

    主要差别是不能设置profile, 升级 profile 是来源于安装时保存: ~/.hgctl/profiles/install.yaml 。

    三、Dashboard 命令: hgctl dashbaord

    可以通过 hgctl dashboard 命令打开 Higress Console 管理界面, Higress Controller Debug界面, Envoy 管理界面,Grafana 和 Prometheus 管理界面

    hgctl dashboard 命令参数如下:

    hgctl dashboard  --help

    Usage:
    hgctl dashboard [flags]
    hgctl dashboard [command]

    Aliases:
    dashboard, dash, d

    Available Commands:
    console Open Console web UI
    controller Open Controller debug web UI
    envoy Open Envoy admin web UI
    grafana Open Grafana web UI
    prometheus Open Prometheus web UI

    Flags:
    --browser When --browser is supplied as false, hgctl dashboard will not open the browser. Default is true which means hgctl dashboard will always open a browser to view the dashboard. (default true)
    --context string The name of the kubeconfig context to use.
    -h, --help help for dashboard
    --kubeconfig string Path to the kubeconfig file to use for CLI requests.
    -n, --namespace string Namespace where the addon is running, if not specified, higress-system would be used (default "higress-system")
    -p, --port int Local port to listen to

    Use "hgctl dashboard [command] --help" for more information about a command.

    五、卸载命令: hgctl uninstall

    hgctl uninstall 命令参数如下:

    hgctl uninstall --help

    The uninstall command uninstalls higress from a cluster or local environment

    Usage:
    hgctl uninstall [flags]

    Examples:
    # Uninstall higress
    hgctl uninstal

    # Uninstall higress, istioAPI and GatewayAPI from a cluster
    hgctl uninstall --purge-resources


    Flags:
    --context string The name of the kubeconfig context to use.
    -h, --help help for uninstall
    --kubeconfig string Path to the kubeconfig file to use for CLI requests.
    --purge-resources Delete all of IstioAPI,GatewayAPI resources

    hgctl uninstall 卸载时不会自动卸载 IstioAPI, GatewayAPI组件, 如果要卸载 IstioAPI, GatewayAPI组件,卸载时加上 --purge-resources。

    六、插件命令: hgctl plugin 命令

    - + \ No newline at end of file diff --git a/zh-cn/docs/ops/log/index.html b/zh-cn/docs/ops/log/index.html index 5943948fe9..ab45c68ccc 100644 --- a/zh-cn/docs/ops/log/index.html +++ b/zh-cn/docs/ops/log/index.html @@ -14,13 +14,13 @@ - +

    日志说明

    查看日志可以使用下面命令:

    kubectl logs -n higress-system -l app=higress-gateway  --since=5m

    Higress 默认使用的日志格式为 JSON 格式,如下所示:

    {
    "authority": "%REQ(:AUTHORITY)%",
    "bytes_received": "%BYTES_RECEIVED%",
    "bytes_sent": "%BYTES_SENT%",
    "downstream_local_address": "%DOWNSTREAM_LOCAL_ADDRESS%",
    "downstream_remote_address": "%DOWNSTREAM_REMOTE_ADDRESS%",
    "duration": "%DURATION%",
    "method": "%REQ(:METHOD)%",
    "path": "%REQ(X-ENVOY-ORIGINAL-PATH?:PATH)%",
    "protocol": "%PROTOCOL%",
    "request_id": "%REQ(X-REQUEST-ID)%",
    "requested_server_name": "%REQUESTED_SERVER_NAME%",
    "response_code": "%RESPONSE_CODE%",
    "response_flags": "%RESPONSE_FLAGS%",
    "route_name": "%ROUTE_NAME%",
    "start_time": "%START_TIME%",
    "trace_id": "%REQ(X-B3-TRACEID)%",
    "upstream_cluster": "%UPSTREAM_CLUSTER%",
    "upstream_host": "%UPSTREAM_HOST%",
    "upstream_local_address": "%UPSTREAM_LOCAL_ADDRESS%",
    "upstream_service_time": "%RESP(X-ENVOY-UPSTREAM-SERVICE-TIME)%",
    "upstream_transport_failure_reason": "%UPSTREAM_TRANSPORT_FAILURE_REASON%",
    "user_agent": "%REQ(USER-AGENT)%",
    "x_forwarded_for": "%REQ(X-FORWARDED-FOR)%"
    }

    Value 的配置含义可以参考 envoy 日志说明

    字段名类型含义
    authoritystring请求报文中的Host Header。
    bytes_receivedlong请求的Body大小(不包含Header)。
    bytes_sentlong响应的Body大小(不包含Header)。
    downstream_local_addressstring网关Pod地址。
    downstream_remote_addressstring连接到网关的Client端地址。
    durationlong请求整体耗时。
    methodstringHTTP方法。
    pathstringHTTP请求中的Path。
    protocolstringHTTP的协议版本。
    request_idstring网关会为每次请求产生一个ID,并放在Header的x-request-id中,后端可以根据这个字段记录并进行排查。
    requested_server_namestringSSL连接时使用的Server Name。
    response_codelongHTTP响应的状态码。
    response_flagsstring响应失败的原因。
    route_namestring路由名。
    start_timestring请求开始时间。
    trace_idstringTrace ID。
    upstream_clusterstring上游集群。
    upstream_hoststring上游IP。
    upstream_local_addressstring本地连接上游的地址。
    upstream_service_timelong最后一次调用上游服务的时间。
    upstream_transport_failure_reasonstring上游链接失败的原因。
    user_agentstringHTTP Header中的UserAgent。
    x_forwarded_forstringHTTP Header中的x-forwarded-for,通常用来表示HTTP请求端真实IP。
    - + \ No newline at end of file diff --git a/zh-cn/docs/ops/upgrade/index.html b/zh-cn/docs/ops/upgrade/index.html index d402b2d2fe..49c22cce73 100644 --- a/zh-cn/docs/ops/upgrade/index.html +++ b/zh-cn/docs/ops/upgrade/index.html @@ -14,13 +14,13 @@ - +

    版本升级

    云原生部署

    基于 Helm 实现版本升级

    # ${higress_version} 的值示例: v1.1.0
    kubectl apply -f https://github.com/alibaba/higress/releases/download/${higress_version}/customresourcedefinitions.gen.yaml
    helm repo update
    helm upgrade higress -n higress-system higress.io/higress

    独立部署

    # ${higress_dir} 为 Higress 独立部署的安装目录
    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- "${higress_dir}" -u
    - + \ No newline at end of file diff --git a/zh-cn/docs/overview/faq/index.html b/zh-cn/docs/overview/faq/index.html index 2252dfc3db..8d1a89a6dd 100644 --- a/zh-cn/docs/overview/faq/index.html +++ b/zh-cn/docs/overview/faq/index.html @@ -14,7 +14,7 @@ - + @@ -23,7 +23,7 @@ 建议升级到 v1.0.0 及以上版本

    具体可以参考我们的Roadmap


    Q: Higress 和 Envoy Gateway 有什么区别?

    A: Higress 是基于 Envoy 实现和扩展的,和 Envoy Gateway 一样遵循 Gateway API 标准,不同的是,还提供了:

    • Waf 防护、认证鉴权等安全插件能力
    • 多注册中心、协议转化、限流降级等服务管理插件能力,例如,对于传统使用 Dubbo 的微服务用户希望使用原生 RPC 方式暴露对外服务,但通常提供外部访问的服务以使用 HTTP 为主,为了帮助 Dubbo 用户降低服务暴露的开发成本,Higress 提供了 HTTP 转 Dubbo 协议功能,且通过 Console 为用户提供白屏化的配置方式,某客户使用后反馈“这是业界完成度最高的 HTTP 转 Dubbo 协议”功能。
    • 支持 WASM、Lua 等自定义插件,例如 Nginx 用户,我们还会支持进程外插件,满足多语言用户诉求,尤其是 Java 用户因现阶段 Java 社区对 WebAssembly 支持尚不完善但又希望对网关进行扩展的诉求。

    Q: Higress 和阿里巴巴的另一款开源网关 Tengine 有哪些不同?

    A:

    Tengine 是基于 Nginx 实现,通过 Lua 扩展,Higress 基于 istio + Envoy,通过 WASM 扩展,在技术架构上不太一样,开发者可以根据业务场景来进行选型。Higress 已经支持 Nginx Ingress 注解平滑迁移的能力,满足部分用户期望迁移到 Higress 但又不希望重新配置网关的诉求,既可以将 Higress 作为统一接入网关使用,同时又可以享受 Ingress 的红利。


    Q: Higress 阿里云上的 MSE 云原生网关有什么关系?是基于此孵化的开源项目吗?

    A:

    MSE 云原生网关是 Higress 的商业化版本,能力上是有差异的,主要体现在性能、稳定性、易用性和安全性上,因为这些都非常依赖于云上的基础设施能力,详细资源还在整理,后续会在 MSE 的产品页和文档页进行展示,方便大家选型。当然,Higress 处于演进过程中,MSE 云原生网关上的哪些能力对外进行开源,我们会和社区一起定义,开源上我们也会规划一个插件市场。


    Q: Higress 将流量网关、微服务网关、安全网关三合一,这种做法业内是否通用?是否是一种发展趋势?

    A:

    流量网关、微服务网关、安全网关在业界中一直都有使用,部署形态大多采用各自使用独立集群部署,在K8s 主导的容器化背景下,K8s 通过 Ingress 标准化了入口网关,传统流量网关、微服务网关、安全网关独立部署模式在 K8s 下就显得部署成本高、运维复杂,站在用户角度只需要一款功能丰富的高集成网关即可,基于此我们判断高集成网关会是未来的一种发展趋势。


    Q: Higress 对上游进行了定制,是否存在着无法享受社区福利、还要背负生态跟进的问题?

    A:

    Higress 核心代码基本采用可插拔的 Filter 扩展,功能新增也尽量遵循可扩展原则,在上游跟进上为保持自身稳定性也不会马上跟进最新版本,比如 APISIX、Kong 内核都是基于 Nginx,但他们依然发展的很好,事实也说明上游跟进不会成为项目发展障碍。


    Q: Higress 支持 Nacos 的服务发现,是否有支持 Consul 的计划?

    A:

    预计将在 1.2.0 版本提供


    Q: Higress 是否有离线部署版本?

    A:

    目前还没有现成的,需要您自行构建。目前 Docker 镜像都是提供的,可以自行拉取使用。


    Q: Higress 能脱离 K8s 环境,只基于 Docker 运行吗?

    A:

    已经支持了,可以看这里:https://higress.io/zh-cn/docs/user/quickstart#%E7%8E%AF%E5%A2%83%E4%BA%8C%E8%84%B1%E7%A6%BB-k8s-%E5%9C%A8-docker-compose-%E4%B8%AD%E4%BD%BF%E7%94%A8


    Q: Higress 除了运行在 K8s 上,是否支持在虚拟机和物理机上运行呢?

    A:

    同上;

    也可以考虑使用 Higress 企业版,这个模式 Higress 是全托管的,无需关心 Higress 的部署和运维,可直接对接虚拟机和物理机上部署的后端服务。


    Q: Higress 的 Dashboard 会对外开源么?

    A:

    已经开源了:https://github.com/higress-group/higress-console


    Q: 当前开源的版本支持 Waf 功能么,有相关的最佳实践么?

    A:

    支持的,可以看这篇文档:https://higress.io/zh-cn/docs/user/waf/


    Q: Higress 是否支持弹性伸缩,网关是无状态的么?

    A:

    Higress 基于 K8s HPA,是支持弹性伸缩的,网关无状态,是个 deployment 。


    Q: Higress 有 roadmap 了么?

    A:

    请参考Roadmap


    Q: 如何加入 Higress 社区进行贡献,已经迫不及待了

    A:

    我们非常欢迎大家通过各种形式参与到我们项目的建设中,包括但不限于:

    • 架构设计
    • 模块设计
    • 代码实现
    • Bug Fix
    • Demo 样例
    • 文档、网站和翻译

    具体的参与方法可以参见我们官网的开发者指引或与 higress@googlegroups.com 联系。 实际上,我们并不拘泥于贡献的形式,开发者提出的每一个 issue,无论是 Bug Report、改进建议或者甚至是问题咨询都代表着对项目的关注和帮助。希望 Higress 项目和社区一起健康成长,成为云原生网关领域一个优秀的解决方案。


    - + \ No newline at end of file diff --git a/zh-cn/docs/overview/roadmap/index.html b/zh-cn/docs/overview/roadmap/index.html index 228280d0da..3d0c533be6 100644 --- a/zh-cn/docs/overview/roadmap/index.html +++ b/zh-cn/docs/overview/roadmap/index.html @@ -14,13 +14,13 @@ - +

    版本计划

    版本号版本核心目标预计发布时间
    v0.6.0K8s 下黑屏操作(kubectl)达到GA状态;发布控制台预览版,提高安装部署的易用性2023-01
    v0.7.0控制台发布正式版本,集成开箱即用的可观测2023-02
    v1.0.0整体达到GA状态2023-05
    v1.1.0增强控制台功能中微服务网关相关能力;支持非 K8s 下安装部署2023-07
    v1.2.0支持作为 Knative 的网络层使用;支持 ARM 架构部署;支持对接 Consul2023-08
    v1.3.0完整支持 GatewayAPI;支持 Operator 模式部署2023-09
    v1.4.0推出 WASM 插件集市功能2023-10
    - + \ No newline at end of file diff --git a/zh-cn/docs/overview/terminology/index.html b/zh-cn/docs/overview/terminology/index.html index f919240aac..833fb49bbd 100644 --- a/zh-cn/docs/overview/terminology/index.html +++ b/zh-cn/docs/overview/terminology/index.html @@ -14,13 +14,13 @@ - +

    Higress Terminology

    Ingress 注解(Annotation)

    Ingress 资源中的注解(Annotation)字段,是一个 kv 字典结构,可以通过申明式的方式来实现各种路由策略,如下所示,是使用注解实现对该 Ingress 路由开启跨域访问许可:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: ingress-example
    annotations:
    higress.io/enable-cors: "true"
    spec:
    ingressClassName: nginx-example
    rules:
    - http:
    paths:
    - path: /test
    pathType: Prefix
    backend:
    service:
    name: test
    port:
    number: 80

    Higress 支持的其他注解配置方式,请参考Ingress Annotation 配置说明

    下游(Downstream)

    下游指 Higress 接收到请求的来源,一般是如浏览器等客户端

    上游(Upstream)

    上游指 Higress 转发请求的目标后端服务

    - + \ No newline at end of file diff --git a/zh-cn/docs/overview/what-is-higress/index.html b/zh-cn/docs/overview/what-is-higress/index.html index c5b83308c1..29bbd4410e 100644 --- a/zh-cn/docs/overview/what-is-higress/index.html +++ b/zh-cn/docs/overview/what-is-higress/index.html @@ -14,13 +14,13 @@ - +

    Higress是什么?

    Higress是基于阿里内部的Envoy Gateway实践沉淀、以开源Istio + Envoy为核心构建的下一代云原生网关,实现了流量网关 + 微服务网关 + 安全网关三合一的高集成能力,深度集成Dubbo、Nacos、Sentinel等微服务技术栈,能够帮助用户极大的降低网关的部署及运维成本且能力不打折;在标准上全面支持Ingress与Gateway API,积极拥抱云原生下的标准API规范;同时,Higress Controller也支持Nginx Ingress平滑迁移,帮助用户零成本快速迁移到Higress。

    image

    传统网关分类

    行业中通常把网关分为两个大类:流量网关与业务网关,流量网关主要提供全局性的、与后端业务无关的策略配置,例如阿里内部的的统一接入网关Tengine就是典型的流量网关;业务网关顾名思义主要提供独立业务域级别的、与后端业务紧耦合策略配置,随着应用架构模式从单体演进到现在的分布式微服务,业务网关也有了新的叫法 - 微服务网关(图示说明如下)。在目前容器技术与K8s主导的云原生时代,下一代网关模式依然是这样吗?

    image

    Higress定位

    在虚拟化时期的微服务架构下,业务通常采用流量网关 + 微服务网关的两层架构,流量网关负责南北向流量调度和安全防护,微服务网关负责东西向流量调度和服务治理,而在容器和 K8s 主导的云原生时代,Ingress 成为 K8s 生态的网关标准,赋予了网关新的使命,使得流量网关 + 微服务网关合二为一成为可能。

    作为面向南北向的公网网关,使用Waf防护异常流量是很常规的需求,而且随着互联网环境变得越来越复杂,用户对防护的诉求是持续增强的,常规做法是将流量先接入Waf安全网关,过滤后再将流量转发给流量网关,最后到达微服务网关;Higress希望通过内置Waf模块,使得用户的请求链接只经过Higress就可以同时完成Waf防护、流量分发、微服务治理,既可以提升链路RT,也可以降低网关的运维复杂度。因此Higress实现了流量网关 + 微服务网关 + 安全网关三合一的高集成能力。

    image

    Higress为什么选择以Envoy + Istio为内核构建?

    在容器化的云原生大背景下,Kubernetes已经成为了基础设施与上层应用的标准接口,Kubernetes集群天然的内外网络隔离环境,使得外部流量进入Kubernetes集群内部需要通过入口网关,因此Kubernetes通过Ingress来规范化入口网关的定义与标准,虽然Ingress标准存在一些如路由表达能力弱等不足之处,社区已经在积极推进Gateway API标准定义来解决,但不可否认的是目前Ingress标准仍然占据主流,CNCF年度报告中也单独统计了Ingress Provider(Ingress标准的实现方统称为Ingress Provider)的使用情况。

    image

    从上述统计报告中可以看到虽然目前Nginx Ingress仍然占据K8s Ingress Provider榜首,但Envoy的增长是最快的,已经从2019年的不足20%增长为2020年的37%,且仅在Nginx Ingress之后,增长势头非常迅猛,这说明选择以Envoy为内核是符合云原生发展趋势的;而且随着Service Mesh逐步被大众认可,Istio + Envoy的体系可以同时覆盖Mesh与Ingress领域,实现以一套技术架构调度东西向、南北向全域流量的目标,这对用户来说也是非常有意义的。

    Higress在阿里巴巴内部介绍

    Higress孵化自阿里巴巴内部2020年5月的"本地生活战役",最初是为满足阿里巴巴集团与蚂蚁集团直接使用RPC请求互访的诉求而构建,而且借该项目也成功孵化了Dubbo 3.0的Triple协议,因此Higress也是内部第一个支持Triple协议的应用,同年Higress也成功支持了双11、双12等大促活动,后续随着业务范围的扩展,目前Higress在内部已经支持优酷、钉钉、达摩院、蚂蚁等业务,业务场景也扩展到了东西向、南北向的全域流量调度。

    image

    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/basic-auth/index.html b/zh-cn/docs/plugins/basic-auth/index.html index 89f3456c46..047bc6beba 100644 --- a/zh-cn/docs/plugins/basic-auth/index.html +++ b/zh-cn/docs/plugins/basic-auth/index.html @@ -14,14 +14,14 @@ - +

    Basic 认证

    功能说明

    basic-auth插件实现了基于 HTTP Basic Auth 标准进行认证鉴权的功能

    运行属性

    插件执行阶段:认证阶段 插件执行优先级:320

    配置字段

    全局配置

    名称数据类型填写要求默认值描述
    consumersarray of object必填-配置服务的调用者,用于对请求进行认证
    global_authbool选填-若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制)

    consumers中每一项的配置字段说明如下:

    名称数据类型填写要求默认值描述
    credentialstring必填-配置该consumer的访问凭证
    namestring必填-配置该consumer的名称

    域名和路由级配置

    名称数据类型填写要求默认值描述
    allowarray of string必填-对于符合匹配条件的请求,配置允许访问的consumer名称

    注意:

    • 对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

    配置示例

    对特定路由或域名开启认证和鉴权

    以下配置将对网关特定路由或域名开启 Basic Auth 认证和鉴权,注意凭证信息中的用户名和密码之间使用":"分隔,credential字段不能重复

    全局配置

    consumers:
    - credential: 'admin:123456'
    name: consumer1
    - credential: 'guest:abc'
    name: consumer2
    global_auth: false

    路由级配置

    对 route-a 和 route-b 这两个路由做如下配置:

    allow: 
    - consumer1

    对 *.example.com 和 test.com 在这两个域名做如下配置:

    allow:
    - consumer2

    若是在控制台进行配置,此例指定的 route-aroute-b 即在控制台创建路由时填写的路由名称,当匹配到这两个路由时,将允许nameconsumer1的调用者访问,其他调用者不允许访问;

    此例指定的 *.example.comtest.com 用于匹配请求的域名,当发现域名匹配时,将允许nameconsumer2的调用者访问,其他调用者不允许访问。

    根据该配置,下列请求可以允许访问:

    请求指定用户名密码

    # 假设以下请求将会匹配到route-a路由
    # 使用 curl 的 -u 参数指定
    curl -u admin:123456 http://xxx.hello.com/test
    # 或者直接指定 Authorization 请求头,用户名密码使用 base64 编码
    curl -H 'Authorization: Basic YWRtaW46MTIzNDU2' http://xxx.hello.com/test

    认证鉴权通过后,请求的header中会被添加一个X-Mse-Consumer字段,在此例中其值为consumer1,用以标识调用方的名称

    下列请求将拒绝访问:

    请求未提供用户名密码,返回401

    curl  http://xxx.hello.com/test

    请求提供的用户名密码错误,返回401

    curl -u admin:abc  http://xxx.hello.com/test

    根据请求的用户名和密码匹配到的调用者无访问权限,返回403

    # consumer2不在route-a的allow列表里
    curl -u guest:abc http://xxx.hello.com/test

    相关错误码

    HTTP 状态码出错信息原因说明
    401Request denied by Basic Auth check. No Basic Authentication information found.请求未提供凭证
    401Request denied by Basic Auth check. Invalid username and/or password请求凭证无效
    403Request denied by Basic Auth check. Unauthorized consumer请求的调用方无访问权限
    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/bot-detect/index.html b/zh-cn/docs/plugins/bot-detect/index.html index 71d6696069..ed3da86835 100644 --- a/zh-cn/docs/plugins/bot-detect/index.html +++ b/zh-cn/docs/plugins/bot-detect/index.html @@ -14,14 +14,14 @@ - +

    机器人拦截

    功能说明

    bot-detect插件可以用于识别并阻止互联网爬虫对站点资源的爬取

    运行属性

    插件执行阶段:鉴权阶段 插件执行优先级:310

    配置字段

    名称数据类型填写要求默认值描述
    allowarray of string选填-配置匹配 User-Agent 请求头的正则表达式,匹配命中时将允许其访问
    denyarray of string选填-配置匹配 User-Agent 请求头的正则表达式,匹配命中时将屏蔽请求
    blocked_codenumber选填403配置请求被屏蔽时返回的 HTTP 状态码
    blocked_messagestring选填-配置请求被屏蔽时返回的 HTTP 应答 Body

    allowdeny 字段可以均不配置,则执行默认的爬虫判断逻辑,通过配置 allow 字段可以将原本命中默认爬虫判断逻辑的请求放行,通过配置 deny 字段可以增加额外的爬虫判断逻辑。

    默认的爬虫判断正则表达式集合如下:

    # Bots General matcher 'name/0.0'
    (?:\/[A-Za-z0-9\.]+|) {0,5}([A-Za-z0-9 \-_\!\[\]:]{0,50}(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]{0,50}))[/ ](\d+)(?:\.(\d+)(?:\.(\d+)|)|)
    # Bots General matcher 'name 0.0'
    (?:\/[A-Za-z0-9\.]+|) {0,5}([A-Za-z0-9 \-_\!\[\]:]{0,50}(?:[Aa]rchiver|[Ii]ndexer|[Ss]craper|[Bb]ot|[Ss]pider|[Cc]rawl[a-z]{0,50})) (\d+)(?:\.(\d+)(?:\.(\d+)|)|)
    # Bots containing spider|scrape|bot(but not CUBOT)|Crawl
    ((?:[A-z0-9]{1,50}|[A-z\-]{1,50} ?|)(?: the |)(?:[Ss][Pp][Ii][Dd][Ee][Rr]|[Ss]crape|[Cc][Rr][Aa][Ww][Ll])[A-z0-9]{0,50})(?:(?:[ /]| v)(\d+)(?:\.(\d+)|)(?:\.(\d+)|)|)
    # Bots Pattern '/name-0.0'
    /((?:Ant-)?Nutch|[A-z]+[Bb]ot|[A-z]+[Ss]pider|Axtaris|fetchurl|Isara|ShopSalad|Tailsweep)[ \-](\d+)(?:\.(\d+)(?:\.(\d+))?)?
    # Bots Pattern 'name/0.0'
    \b(008|Altresium|Argus|BaiduMobaider|BoardReader|DNSGroup|DataparkSearch|EDI|Goodzer|Grub|INGRID|Infohelfer|LinkedInBot|LOOQ|Nutch|OgScrper|PathDefender|Peew|PostPost|Steeler|Twitterbot|VSE|WebCrunch|WebZIP|Y!J-BR[A-Z]|YahooSeeker|envolk|sproose|wminer)/(\d+)(?:\.(\d+)|)(?:\.(\d+)|)
    # More bots
    (CSimpleSpider|Cityreview Robot|CrawlDaddy|CrawlFire|Finderbots|Index crawler|Job Roboter|KiwiStatus Spider|Lijit Crawler|QuerySeekerSpider|ScollSpider|Trends Crawler|USyd-NLP-Spider|SiteCat Webbot|BotName\/\$BotVersion|123metaspider-Bot|1470\.net crawler|50\.nu|8bo Crawler Bot|Aboundex|Accoona-[A-z]{1,30}-Agent|AdsBot-Google(?:-[a-z]{1,30}|)|altavista|AppEngine-Google|archive.{0,30}\.org_bot|archiver|Ask Jeeves|[Bb]ai[Dd]u[Ss]pider(?:-[A-Za-z]{1,30})(?:-[A-Za-z]{1,30}|)|bingbot|BingPreview|blitzbot|BlogBridge|Bloglovin|BoardReader Blog Indexer|BoardReader Favicon Fetcher|boitho.com-dc|BotSeer|BUbiNG|\b\w{0,30}favicon\w{0,30}\b|\bYeti(?:-[a-z]{1,30}|)|Catchpoint(?: bot|)|[Cc]harlotte|Checklinks|clumboot|Comodo HTTP\(S\) Crawler|Comodo-Webinspector-Crawler|ConveraCrawler|CRAWL-E|CrawlConvera|Daumoa(?:-feedfetcher|)|Feed Seeker Bot|Feedbin|findlinks|Flamingo_SearchEngine|FollowSite Bot|furlbot|Genieo|gigabot|GomezAgent|gonzo1|(?:[a-zA-Z]{1,30}-|)Googlebot(?:-[a-zA-Z]{1,30}|)|Google SketchUp|grub-client|gsa-crawler|heritrix|HiddenMarket|holmes|HooWWWer|htdig|ia_archiver|ICC-Crawler|Icarus6j|ichiro(?:/mobile|)|IconSurf|IlTrovatore(?:-Setaccio|)|InfuzApp|Innovazion Crawler|InternetArchive|IP2[a-z]{1,30}Bot|jbot\b|KaloogaBot|Kraken|Kurzor|larbin|LEIA|LesnikBot|Linguee Bot|LinkAider|LinkedInBot|Lite Bot|Llaut|lycos|Mail\.RU_Bot|masscan|masidani_bot|Mediapartners-Google|Microsoft .{0,30} Bot|mogimogi|mozDex|MJ12bot|msnbot(?:-media {0,2}|)|msrbot|Mtps Feed Aggregation System|netresearch|Netvibes|NewsGator[^/]{0,30}|^NING|Nutch[^/]{0,30}|Nymesis|ObjectsSearch|OgScrper|Orbiter|OOZBOT|PagePeeker|PagesInventory|PaxleFramework|Peeplo Screenshot Bot|PlantyNet_WebRobot|Pompos|Qwantify|Read%20Later|Reaper|RedCarpet|Retreiver|Riddler|Rival IQ|scooter|Scrapy|Scrubby|searchsight|seekbot|semanticdiscovery|SemrushBot|Simpy|SimplePie|SEOstats|SimpleRSS|SiteCon|Slackbot-LinkExpanding|Slack-ImgProxy|Slurp|snappy|Speedy Spider|Squrl Java|Stringer|TheUsefulbot|ThumbShotsBot|Thumbshots\.ru|Tiny Tiny RSS|Twitterbot|WhatsApp|URL2PNG|Vagabondo|VoilaBot|^vortex|Votay bot|^voyager|WASALive.Bot|Web-sniffer|WebThumb|WeSEE:[A-z]{1,30}|WhatWeb|WIRE|WordPress|Wotbox|www\.almaden\.ibm\.com|Xenu(?:.s|) Link Sleuth|Xerka [A-z]{1,30}Bot|yacy(?:bot|)|YahooSeeker|Yahoo! Slurp|Yandex\w{1,30}|YodaoBot(?:-[A-z]{1,30}|)|YottaaMonitor|Yowedo|^Zao|^Zao-Crawler|ZeBot_www\.ze\.bz|ZooShot|ZyBorg)(?:[ /]v?(\d+)(?:\.(\d+)(?:\.(\d+)|)|)|)

    配置示例

    放行原本命中爬虫规则的请求

    allow:
    - ".*Go-http-client.*"

    若不作该配置,默认的 Golang 网络库请求会被视做爬虫,被禁止访问

    增加爬虫判断

    deny:
    - "spd-tools.*"

    根据该配置,下列请求将被禁止访问:

    curl http://example.com -H 'User-Agent: spd-tools/1.1'
    curl http://exmaple.com -H 'User-Agent: spd-tools'
    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/custom-response/index.html b/zh-cn/docs/plugins/custom-response/index.html index 9bca00f512..c09644f762 100644 --- a/zh-cn/docs/plugins/custom-response/index.html +++ b/zh-cn/docs/plugins/custom-response/index.html @@ -14,14 +14,14 @@ - +

    自定义应答

    功能说明

    custom-response插件支持配置自定义的响应,包括自定义 HTTP 应答状态码、HTTP 应答头,以及 HTTP 应答 Body。可以用于 Mock 响应,也可以用于判断特定状态码后给出自定义应答,例如在触发网关限流策略时实现自定义响应。

    运行属性

    插件执行阶段:认证阶段 插件执行优先级:910

    配置字段

    名称数据类型填写要求默认值描述
    status_codenumber选填200自定义 HTTP 应答状态码
    headersarray of string选填-自定义 HTTP 应答头,key 和 value 用=分隔
    bodystring选填-自定义 HTTP 应答 Body
    enable_on_statusarray of number选填-匹配原始状态码,生成自定义响应,不填写时,不判断原始状态码

    配置示例

    Mock 应答场景

    status_code: 200
    headers:
    - Content-Type=application/json
    - Hello=World
    body: "{\"hello\":\"world\"}"

    根据该配置,请求将返回自定义应答如下:

    HTTP/1.1 200 OK
    Content-Type: application/json
    Hello: World
    Content-Length: 17

    {"hello":"world"}

    触发限流时自定义响应

    enable_on_status: 
    - 429
    status_code: 302
    headers:
    - Location=https://example.com

    触发网关限流时一般会返回 429 状态码,这时请求将返回自定义应答如下:

    HTTP/1.1 302 Found
    Location: https://example.com

    从而实现基于浏览器 302 重定向机制,将限流后的用户引导到其他页面,比如可以是一个 CDN 上的静态页面。

    如果希望触发限流时,正常返回其他应答,参考 Mock 应答场景配置相应的字段即可。

    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/custom/index.html b/zh-cn/docs/plugins/custom/index.html index 9d33fc74b8..6d755b8fd2 100644 --- a/zh-cn/docs/plugins/custom/index.html +++ b/zh-cn/docs/plugins/custom/index.html @@ -14,14 +14,14 @@ - +

    自定义插件

    编辑 Wasm 文件

    1. 用于使用 Go 语言开发 Higress 的 Wasm 插件的SDK
    2. 插件开发示例

    构建 Wasm 镜像

    你也可以选择先在本地将 wasm 构建出来,再拷贝到 Docker 镜像中。这要求你要先在本地搭建构建环境。

    编译环境要求如下:

    • Go 版本: >= 1.18(需要支持泛型特性)

    • TinyGo 版本: >= 0.28.1(建议使用 0.28.1 )

    下面是本地步骤构建 request-block 插件的例子。

    step1. 编译 wasm

    tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags='custommalloc nottinygc_finalizer' ./main.go

    step2. 构建并推送插件的 docker 镜像

    使用这份简单的 Dockerfile

    FROM scratch
    COPY main.wasm plugin.wasm
    docker build -t <your_registry_hub>/request-block:1.0.0 -f <your_dockerfile> .
    docker push <your_registry_hub>/request-block:1.0.0

    生效 Wasm 插件

    使用 Higress 控制台

    在插件市场中创建点击创建按钮,就可以创建自定义插件,在镜像地址一栏中填入上面构建出的 Wasm 镜像地址即可;

    创建完成后,点击插件卡片的配置按钮,填入插件的配置(如果有),打开开启开关就生效了。

    如果插件逻辑发生了变更,可以构建一个新的镜像,并使用不同的镜像 tag,点插件卡片右上方菜单中的编辑按钮,将 Wasm 镜像地址修改为新版本的地址即可。

    使用 CRD

    编写 WasmPlugin 资源如下:

    apiVersion: extensions.higress.io/v1alpha1
    kind: WasmPlugin
    metadata:
    name: request-block
    namespace: higress-system
    spec:
    defaultConfig:
    block_urls:
    - "swagger.html"
    url: oci://<your_registry_hub>/request-block:1.0.0 # 之前构建和推送的 image 地址

    使用 kubectl apply -f <your-wasm-plugin-yaml> 使资源生效。 资源生效后,如果请求url携带 swagger.html, 则这个请求就会被拒绝,例如:

    curl <your_gateway_address>/api/user/swagger.html
    HTTP/1.1 403 Forbidden
    date: Wed, 09 Nov 2022 12:12:32 GMT
    server: istio-envoy
    content-length: 0
    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/hmac-auth/index.html b/zh-cn/docs/plugins/hmac-auth/index.html index d8c9c50927..60160f0f35 100644 --- a/zh-cn/docs/plugins/hmac-auth/index.html +++ b/zh-cn/docs/plugins/hmac-auth/index.html @@ -14,7 +14,7 @@ - + @@ -22,7 +22,7 @@

    HMAC 认证

    功能说明

    hmac-auth插件实现了基于 HMAC 算法为 HTTP 请求生成不可伪造的签名,并基于签名实现身份认证和鉴权

    配置字段

    全局配置

    名称数据类型填写要求默认值描述
    consumersarray of object必填-配置服务的调用者,用于对请求进行认证
    date_offsetnumber选填-配置允许的客户端最大时间偏移,单位为秒,根据请求头Date解析客户端 UTC 时间,可用于避免请求重放;未配置时,不做校验
    global_authbool选填-若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制)

    consumers中每一项的配置字段说明如下:

    名称数据类型填写要求默认值描述
    keystring必填-配置从请求的x-ca-key头中提取的key
    secretstring必填-配置用于生成签名的secret
    namestring必填-配置该consumer的名称

    域名和路由级配置

    名称数据类型填写要求默认值描述
    allowarray of string必填-对于符合匹配条件的请求,配置允许访问的consumer名称

    注意:

    • 对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

    配置示例

    以下配置将对网关特定路由或域名开启 Hmac Auth 认证和鉴权,注意key字段不能重复

    对特定路由或域名开启

    全局配置

    consumers: 
    - key: appKey-example-1
    secret: appSecret-example-1
    name: consumer-1
    - key: appKey-example-2
    secret: appSecret-example-2
    name: consumer-2
    global_auth: false

    路由级配置

    对 route-a 和 route-b 这两个路由做如下配置:

    allow: 
    - consumer1

    对 *.exmaple.com 和 test.com 在这两个域名做如下配置:

    allow:
    - consumer2

    每条匹配规则下的allow字段用于指定该匹配条件下允许访问的调用者列表;

    若是在控制台进行配置,此例指定的 route-aroute-b 即在控制台创建路由时填写的路由名称,当匹配到这两个路由时,将允许nameconsumer1的调用者访问,其他调用者不允许访问;

    此例指定的 *.example.comtest.com 用于匹配请求的域名,当发现域名匹配时,将允许nameconsumer2的调用者访问,其他调用者不允许访问。

    认证成功后,请求的header中会被添加一个X-Mse-Consumer字段,其值为调用方的名称,例如consumer-1

    签名机制说明

    配置准备

    如上指引,在插件配置中配置生成和验证签名需要用的凭证配置

    • key: 用于请求头 x-ca-key 中设置
    • secret: 用于生成请求签名

    客户端签名生成方式

    流程简介

    客户端生成签名一共分三步处理:

    1. 从原始请求中提取关键数据,得到一个用来签名的字符串

    2. 使用加密算法和配置的 secret 对关键数据签名串进行加密处理,得到签名

    3. 将签名所相关的所有头加入到原始HTTP请求中,得到最终HTTP请求

    如下图所示:

    签名串提取流程

    客户端需要从Http请求中提取出关键数据,组合成一个签名串,生成的签名串的格式如下:

    HTTPMethod
    Accept
    Content-MD5
    Content-Type
    Date
    Headers
    PathAndParameters

    以上7个字段构成整个签名串,字段之间使用\n间隔,如果Headers为空,则不需要加\n,其他字段如果为空都需要保留\n。签名大小写敏感。下面介绍下每个字段的提取规则:

    • HTTPMethod:HTTP的方法,全部大写,比如POST

    • Accept:请求中的Accept头的值,可为空。建议显式设置 Accept Header。当 Accept 为空时,部分 Http 客户端会给 Accept 设置默认值为 */*,导致签名校验失败。

    • Content-MD5:请求中的Content-MD5头的值,可为空只有在请求存在Body且Body为非Form形式时才计算Content-MD5头,下面是Java的Content-MD5值的参考计算方式:

    String content-MD5 = Base64.encodeBase64(MD5(bodyStream.getbytes("UTF-8")));
    • Content-Type:请求中的Content-Type头的值,可为空

    • Date:请求中的Date头的值,当未开启date_offset配置时,可为空,否则将用于时间偏移校验

    • Headers:用户可以选取指定的header参与签名,关于header的签名串拼接方式有以下规则:

      • 参与签名计算的Header的Key按照字典排序后使用如下方式拼接
        HeaderKey1 + ":" + HeaderValue1 + "\n"\+
        HeaderKey2 + ":" + HeaderValue2 + "\n"\+
        ...
        HeaderKeyN + ":" + HeaderValueN + "\n"
      • 某个Header的Value为空,则使用HeaderKey+":"+"\n"参与签名,需要保留Key和英文冒号
      • 所有参与签名的Header的Key的集合使用英文逗号分割放到Key为X-Ca-Signature-Headers的Header中
      • 以下Header不参与Header签名计算:X-Ca-Signature、X-Ca-Signature-Headers、Accept、Content-MD5、Content-Type、Date
    • PathAndParameters: 这个字段包含Path,Query和Form中的所有参数,具体组织形式如下

    Path + "?" + Key1 + "=" + Value1 + "&" + Key2 + "=" + Value2 + ... "&" + KeyN + "=" + ValueN

    注意:

    1. Query和Form参数对的Key按照字典排序后使用上面的方式拼接
    2. Query和Form参数为空时,则直接使用Path,不需要添加?
    3. 参数的Value为空时只保留Key参与签名,等号不需要再加入签名
    4. Query和Form存在数组参数时(key相同,value不同的参数) ,取第一个Value参与签名计算

    签名串提取示例

    初始的HTTP请求:

    POST /http2test/test?param1=test HTTP/1.1
    host:api.aliyun.com
    accept:application/json; charset=utf-8
    ca_version:1
    content-type:application/x-www-form-urlencoded; charset=utf-8
    x-ca-timestamp:1525872629832
    date:Wed, 09 May 2018 13:30:29 GMT+00:00
    user-agent:ALIYUN-ANDROID-DEMO
    x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
    content-length:33
    username=xiaoming&password=123456789

    生成的正确签名串为:

    POST
    application/json; charset=utf-8
    application/x-www-form-urlencoded; charset=utf-8
    Wed, 09 May 2018 13:30:29 GMT+00:00
    x-ca-key:203753385
    x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
    x-ca-signature-method:HmacSHA256
    x-ca-timestamp:1525872629832
    /http2test/test?param1=test&password=123456789&username=xiaoming

    签名计算流程

    客户端从HTTP请求中提取出关键数据组装成签名串后,需要对签名串进行加密及编码处理,形成最终的签名

    具体的加密形式如下,其中 stringToSign 是提取出来的签名串,secret 就是插件配置中填写的,sign 是最终生成的签名:

    Mac hmacSha256 = Mac.getInstance("HmacSHA256");
    byte[] secretBytes = secret.getBytes("UTF-8");
    hmacSha256.init(new SecretKeySpec(secretBytes, 0, secretBytes.length, "HmacSHA256"));
    byte[] result = hmacSha256.doFinal(stringToSign.getBytes("UTF-8"));
    String sign = Base64.encodeBase64String(result);

    总结一下,就是将 stringToSign 使用UTF-8解码后得到Byte数组,然后使用加密算法对Byte数组进行加密,然后使用Base64算法进行编码,形成最终的签名。

    添加签名流程

    客户端需要将以下四个Header放在HTTP请求中传输给API网关,进行签名校验:

    • x-ca-key:取值APP Key,必选

    • x-ca-signature-method:签名算法,取值HmacSHA256或者HmacSHA1,可选,默认值为HmacSHA256

    • x-ca-signature-headers:所有签名头的Key的集合,使用英文逗号分隔,可选

    • x-ca-signature:签名,必选

    下面是携带签名的整个HTTP请求的示例:

    POST /http2test/test?param1=test HTTP/1.1
    host:api.aliyun.com
    accept:application/json; charset=utf-8
    ca_version:1
    content-type:application/x-www-form-urlencoded; charset=utf-8
    x-ca-timestamp:1525872629832
    date:Wed, 09 May 2018 13:30:29 GMT+00:00
    user-agent:ALIYUN-ANDROID-DEMO
    x-ca-nonce:c9f15cbf-f4ac-4a6c-b54d-f51abf4b5b44
    x-ca-key:203753385
    x-ca-signature-method:HmacSHA256
    x-ca-signature-headers:x-ca-timestamp,x-ca-key,x-ca-nonce,x-ca-signature-method
    x-ca-signature:xfX+bZxY2yl7EB/qdoDy9v/uscw3Nnj1pgoU+Bm6xdM=
    content-length:33
    username=xiaoming&password=123456789

    服务端签名验证方式

    流程简介

    服务器验证客户端签名一共分四步处理:

    1. 从接收到的请求中提取关键数据,得到一个用来签名的字符串

    2. 从接收到的请求中读取 key ,通过 key 查询到对应的 secret

    3. 使用加密算法和 secret 对关键数据签名串进行加密处理,得到签名

    4. 从接收到的请求中读取客户端签名,对比服务器端签名和客户端签名的一致性

    如下图所示:

    签名排错方法

    网关签名校验失败时,会将服务端的签名串(StringToSign)放到HTTP Response的Header中返回到客户端,Key为:X-Ca-Error-Message,用户只需要将本地计算的签名串(StringToSign)与服务端返回的签名串进行对比即可找到问题;

    如果服务端与客户端的StringToSign一致请检查用于签名计算的APP Secret是否正确;

    因为HTTP Header中无法表示换行,因此StringToSign中的换行符都被替换成#,如下所示:

    X-Ca-Error-Message:  Server StringToSign:`GET#application/json##application/json##X-Ca-Key:200000#X-Ca-Timestamp:1589458000000#/app/v1/config/keys?keys=TEST`

    相关错误码

    HTTP 状态码出错信息原因说明
    401Invalid Key请求头未提供 x-ca-key,或者 x-ca-key 无效
    401Empty Signature请求头未提供 x-ca-signature 签名串
    400Invalid Signature请求头 x-ca-signature 签名串,与服务端计算得到签名不一致
    400Invalid Content-MD5请求头 content-md5 不正确
    400Invalid Date根据请求头 date 计算时间偏移超过配置的 date_offset
    413Request Body Too Large请求 Body 超过限制大小:32 MB
    413Payload Too Large请求 Body 超过全局配置 DownstreamConnectionBufferLimits
    403Unauthorized Consumer请求的调用方无访问权限
    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/intro/index.html b/zh-cn/docs/plugins/intro/index.html index 5c2beb969a..e3768d2977 100644 --- a/zh-cn/docs/plugins/intro/index.html +++ b/zh-cn/docs/plugins/intro/index.html @@ -14,13 +14,13 @@ - +

    Wasm 插件使用简介

    通过 Higress 控制台进行配置

    Higress 控制台提供了 3 个入口进行插件配置:

    1. 全局配置:插件市场->选择插件进行配置
    2. 域名级配置:域名管理->选择域名->点击策略->选择插件进行配置
    3. 路由级配置: 路由配置->选择路由->点击策略->选择插件进行配置

    这三个配置的生效优先级是: 路由级 > 域名级 > 全局

    即对于没有匹配到具体路由或域名的请求才会生效全局配置

    对于一般的插件,包括自定义插件在内,路由/域名级的配置字段和全局配置字段是完全一样的;

    对于认证类插件(Key 认证,HMAC 认证,Basic 认证,JWT 认证等)则不同,全局配置仅做 Consumer 凭证配置,以及是否开启全局认证,而在路由/域名级通过allow字段配置允许访问的 Consumer 列表,详情可以查看 Key 认证的配置说明

    通过 Higress WasmPlugin CRD 进行配置

    Higress WasmPlugin CRD 在 Istio WasmPlugin CRD 的基础上进行了扩展,新增以下配置字段:

    字段名称数据类型填写要求描述
    defaultConfigobject选填插件默认配置,全局生效于没有匹配具体域名和路由配置的请求
    matchRulesarray of object选填匹配域名或路由生效的配置

    matchRules中每一项的配置字段说明:

    字段名称数据类型填写要求配置示例描述
    ingressarray of stringingressdomain中必填一项["default/foo","default/bar"]匹配 ingress 资源对象,匹配格式为: 命名空间/ingress名称
    domainarray of stringingressdomain中必填一项["example.com","*.test.com"]匹配域名,支持泛域名
    configobject选填-匹配后生效的插件配置

    请求屏蔽插件举例说明,如果希望全局生效插件的如下配置(请查看请求屏蔽文档了解配置字段说明):

    block_urls:
    - swagger.html
    - foo=bar
    case_sensitive: false

    则对应的 WasmPlugin 需要配置如下:

    apiVersion: extensions.higress.io/v1alpha1
    kind: WasmPlugin
    metadata:
    name: request-block
    namespace: higress-system
    spec:
    defaultConfig:
    block_urls:
    - swagger.html
    - foo=bar
    case_sensitive: false
    url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/request-block:1.0.0

    配置后下列请求将立即被禁止访问:

    curl http://example.com?foo=Bar
    curl http://exmaple.com/foo/Swagger.html

    如果希望对 default 命名空间下名称为 foo 的 Ingress (匹配path前缀为/foo的请求)生效如下配置:

    block_headers:
    - example-key
    - example-value

    则对应的 WasmPlugin 需要配置如下:

    apiVersion: extensions.higress.io/v1alpha1
    kind: WasmPlugin
    metadata:
    name: request-block
    namespace: higress-system
    spec:
    defaultConfig:
    block_urls:
    - swagger.html
    - foo=bar
    case_sensitive: false
    matchRules:
    # 路由级生效配置
    - ingress:
    - default/foo
    # default 命名空间下名为 foo 的 ingress 会执行下面这个配置
    config:
    block_headers:
    - example-key
    - example-value
    url: oci://higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/request-block:1.0.0

    配置后,下面请求不会匹配到具体的 ingress,因此仍然命中全局默认配置,被拒绝访问:

    curl http://example.com?foo=Bar

    下面请求由于匹配到 foo 这个 Ingress,因此走路由级的配置,不受默认配置影响,不会被拒绝访问:

    curl http://exmaple.com/foo/Swagger.html

    因为路由级配置屏蔽了请求 Header 中出现 example-key 字符的请求,所以下面这个请求会被拒绝访问:

    curl http://exmaple.com/foo -H 'exmaple-key: 123'

    matchRules 中存在多个规则时,按规则排列顺序优先匹配,建议将 ingress 匹配配置放在 domain 匹配之前,这也是 Higress 控制台的做法

    官方插件镜像地址

    插件名称镜像地址
    Key 认证higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/key-auth:1.0.0
    Basic 认证higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/basic-auth:1.0.0
    HMAC 认证higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/hmac-auth:1.0.0
    JWT 认证higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/jwt-auth:1.0.0
    机器人拦截higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/bot-detect:1.0.0
    自定义应答higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/custom-response:1.0.0
    请求屏蔽higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/request-block:1.0.0
    基于 Key 限流higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/key-rate-limit:1.0.0
    WAF 防护higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/waf:1.0.0

    Wasm 插件原理介绍

    什么是 Wasm

    // TODO...

    插件生效流程

    // TODO...

    插件执行顺序编排

    // TODO...

    Wasm 插件如何做到变更时流量无损

    // TODO...

    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/jwt-auth/index.html b/zh-cn/docs/plugins/jwt-auth/index.html index 6fc30b4576..90e038f210 100644 --- a/zh-cn/docs/plugins/jwt-auth/index.html +++ b/zh-cn/docs/plugins/jwt-auth/index.html @@ -14,14 +14,14 @@ - +

    JWT 认证

    功能说明

    jwt-auth插件实现了基于JWT(JSON Web Tokens)进行认证鉴权的功能,支持从HTTP请求的URL参数、请求头、Cookie字段解析JWT,同时验证该Token是否有权限访问。

    运行属性

    插件执行阶段:认证阶段 插件执行优先级:340

    配置字段

    全局配置

    名称数据类型填写要求默认值描述
    consumersarray of object必填-配置服务的调用者,用于对请求进行认证
    global_authbool选填-若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制)

    consumers中每一项的配置字段说明如下:

    名称数据类型填写要求默认值描述
    namestring必填-配置该consumer的名称
    jwksstring必填-https://www.rfc-editor.org/rfc/rfc7517 指定的json格式字符串,是由验证JWT中签名的公钥(或对称密钥)组成的Json Web Key Set
    issuerstring必填-JWT的签发者,需要和payload中的iss字段保持一致
    claims_to_headersarray of object选填-抽取JWT的payload中指定字段,设置到指定的请求头中转发给后端
    from_headersarray of object选填[{"name":"Authorization","value_prefix":"Bearer "}]从指定的请求头中抽取JWT
    from_paramsarray of string选填access_token从指定的URL参数中抽取JWT
    from_cookiesarray of string选填-从指定的cookie中抽取JWT
    clock_skew_secondsnumber选填60校验JWT的exp和iat字段时允许的时钟偏移量,单位为秒
    keep_tokenbool选填true转发给后端时是否保留JWT

    注意:

    • 只有当from_headers,from_params,from_cookies均未配置时,才会使用默认值

    from_headers 中每一项的配置字段说明如下:

    名称数据类型填写要求默认值描述
    namestring必填-抽取JWT的请求header
    value_prefixstring必填-对请求header的value去除此前缀,剩余部分作为JWT

    claims_to_headers 中每一项的配置字段说明如下:

    名称数据类型填写要求默认值描述
    claimstring必填-JWT payload中的指定字段,要求必须是字符串或无符号整数类型
    headerstring必填-从payload取出字段的值设置到这个请求头中,转发给后端
    overridebool选填truetrue时,存在同名请求头会进行覆盖;false时,追加同名请求头

    域名和路由级配置

    名称数据类型填写要求默认值描述
    allowarray of string必填-对于符合匹配条件的请求,配置允许访问的consumer名称

    注意:

    • 对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

    配置示例

    对特定路由或域名开启

    以下配置将对网关特定路由或域名开启 Jwt Auth 认证和鉴权,注意如果一个JWT能匹配多个jwks,则按照配置顺序命中第一个匹配的consumer

    全局配置

    consumers:
    - name: consumer1
    issuer: abcd
    jwks: |
    {
    "keys": [
    {
    "kty": "oct",
    "kid": "123",
    "k": "hM0k3AbXBPpKOGg__Ql2Obcq7s60myWDpbHXzgKUQdYo7YCRp0gUqkCnbGSvZ2rGEl4YFkKqIqW7mTHdj-bcqXpNr-NOznEyMpVPOIlqG_NWVC3dydBgcsIZIdD-MR2AQceEaxriPA_VmiUCwfwL2Bhs6_i7eolXoY11EapLQtutz0BV6ZxQQ4dYUmct--7PLNb4BWJyQeWu0QfbIthnvhYllyl2dgeLTEJT58wzFz5HeNMNz8ohY5K0XaKAe5cepryqoXLhA-V-O1OjSG8lCNdKS09OY6O0fkyweKEtuDfien5tHHSsHXoAxYEHPFcSRL4bFPLZ0orTt1_4zpyfew",
    "alg": "HS256"
    }
    ]
    }
    - name: consumer2
    issuer: abc
    jwks: |
    {
    "keys": [
    {
    "kty": "RSA",
    "e": "AQAB",
    "use": "sig",
    "kid": "123",
    "alg": "RS256",
    "n": "i0B67f1jggT9QJlZ_8QL9QQ56LfurrqDhpuu8BxtVcfxrYmaXaCtqTn7OfCuca7cGHdrJIjq99rz890NmYFZuvhaZ-LMt2iyiSb9LZJAeJmHf7ecguXS_-4x3hvbsrgUDi9tlg7xxbqGYcrco3anmalAFxsbswtu2PAXLtTnUo6aYwZsWA6ksq4FL3-anPNL5oZUgIp3HGyhhLTLdlQcC83jzxbguOim-0OEz-N4fniTYRivK7MlibHKrJfO3xa_6whBS07HW4Ydc37ZN3Rx9Ov3ZyV0idFblU519nUdqp_inXj1eEpynlxH60Ys_aTU2POGZh_25KXGdF_ZC_MSRw"
    }
    ]
    }
    global_auth: false

    路由级配置

    对 route-a 和 route-b 这两个路由做如下配置:

    allow: 
    - consumer1

    对 *.exmaple.com 和 test.com 在这两个域名做如下配置:

    allow:
    - consumer2

    每条匹配规则下的allow字段用于指定该匹配条件下允许访问的调用者列表;

    若是在控制台进行配置,此例指定的 route-aroute-b 即在控制台创建路由时填写的路由名称,当匹配到这两个路由时,将允许nameconsumer1的调用者访问,其他调用者不允许访问;

    此例指定的 *.example.comtest.com 用于匹配请求的域名,当发现域名匹配时,将允许nameconsumer2的调用者访问,其他调用者不允许访问。

    认证成功后,请求的header中会被添加一个X-Mse-Consumer字段,其值为调用方的名称,例如consumer-1

    根据该配置,下列请求可以允许访问:

    假设以下请求会匹配到route-a这条路由

    将 JWT 设置在 url 参数中

    curl  'http://xxx.hello.com/test?access_token=eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

    将 JWT 设置在 http 请求头中

    curl  http://xxx.hello.com/test -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

    认证鉴权通过后,请求的header中会被添加一个X-Mse-Consumer字段,在此例中其值为consumer1,用以标识调用方的名称

    下列请求将拒绝访问:

    请求未提供JWT,返回401

    curl  http://xxx.hello.com/test

    根据请求提供的JWT匹配到的调用者无访问权限,返回403

    ## consumer1不在*.example.com的allow列表里
    curl 'http://xxx.example.com/test' -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6IjEyMyJ9.eyJpc3MiOiJhYmNkIiwic3ViIjoidGVzdCIsImlhdCI6MTY2NTY2MDUyNywiZXhwIjoxODY1NjczODE5fQ.-vBSV0bKeDwQcuS6eeSZN9dLTUnSnZVk8eVCXdooCQ4'

    常见错误码说明

    HTTP 状态码出错信息原因说明
    401Jwt missing请求头未提供JWT
    401Jwt expiredJWT已经过期
    401Jwt verification failsJWT payload校验失败,如iss不匹配
    403Access Denied无权限访问当前路由

    机制说明

    1、基于token的认证

    1.1 简介

    很多对外开放的API需要识别请求者的身份,并据此判断所请求的资源是否可以返回给请求者。token就是一种用于身份验证的机制,基于这种机制,应用不需要在服务端保留用户的认证信息或者会话信息,可实现无状态、分布式的Web应用授权,为应用的扩展提供了便利。

    1.2 流程描述

    上图是网关利用JWT实现认证的整个业务流程时序图,下面我们用文字来详细描述图中标注的步骤:

    1. 客户端向API网关发起认证请求,请求中一般会携带终端用户的用户名和密码;

    2. 网关将请求直接转发给后端服务;

    3. 后端服务读取请求中的验证信息(比如用户名、密码)进行验证,验证通过后使用私钥生成标准的token,返回给网关;

    4. 网关将携带token的应答返回给客户端,客户端需要将这个token缓存到本地;

    5. 客户端向API网关发送业务请求,请求中携带token;

    6. 网关使用用户设定的公钥对请求中的token进行验证,验证通过后,将请求透传给后端服务;

    7. 后端服务进行业务处理后应答;

    8. 网关将业务应答返回给客户端。

    在这个整个过程中, 网关利用token认证机制,实现了用户使用自己的用户体系对自己API进行授权的能力。下面我们就要介绍网关实现token认证所使用的结构化令牌Json Web Token(JWT)。

    1.3 JWT

    1.3.1 简介

    Json Web Toke(JWT),是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准RFC7519。JWT一般可以用作独立的身份验证令牌,可以包含用户标识、用户角色和权限等信息,以便于从资源服务器获取资源,也可以增加一些额外的其它业务逻辑所必须的声明信息,特别适用于分布式站点的登录场景。

    1.3.2 JWT的构成

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

    如上面的例子所示,JWT就是一个字符串,由三部分构成:

    • Header(头部)
    • Payload(数据)
    • Signature(签名)

    Header

    JWT的头部承载两个信息:

    • 声明类型,这里是JWT
    • 声明加密的算法

    网关支持的加密算法如下:

    ES256, ES384, ES512,
    HS256, HS384, HS512,
    RS256, RS384, RS512,
    PS256, PS384, PS512,
    EdDSA

    完整的头部就像下面这样的JSON:

    {
    'typ': 'JWT',
    'alg': 'HS256'
    }

    然后将头部进行Base64编码(该编码是可以对称解码的),构成了第一部分。

    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

    Payload

    载荷就是存放有效信息的地方。定义细节如下:

    iss:令牌颁发者。表示该令牌由谁创建,该声明是一个字符串
    sub: Subject Identifier,iss提供的终端用户的标识,在iss范围内唯一,最长为255个ASCII个字符,区分大小写
    aud:Audience(s),令牌的受众,分大小写的字符串数组
    exp:Expiration time,令牌的过期时间戳。超过此时间的token会作废, 该声明是一个整数,是1970年1月1日以来的秒数
    iat: 令牌的颁发时间,该声明是一个整数,是1970年1月1日以来的秒数
    jti: 令牌的唯一标识,该声明的值在令牌颁发者创建的每一个令牌中都是唯一的,为了防止冲突,它通常是一个密码学随机值。这个值相当于向结构化令牌中加入了一个攻击者无法获得的随机熵组件,有利于防止令牌猜测攻击和重放攻击。

    也可以新增用户系统需要使用的自定义字段,比如下面的例子添加了name 用户昵称:

    {
    "sub": "1234567890",
    "name": "John Doe"
    }

    然后将其进行Base64编码,得到JWT的第二部分:

    JTdCJTBBJTIwJTIwJTIyc3ViJTIyJTNBJTIwJTIyMTIzNDU2Nzg5MCUyMiUyQyUwQSUyMCUyMCUyMm5hbWUlMjIlM0ElMjAlMjJKb2huJTIwRG9lJTIyJTBBJTdE

    Signature

    这个部分需要Base64编码后的Header和Base64编码后的Payload使用 . 连接组成的字符串,然后通过Header中声明的加密方式进行加密($secret 表示用户的私钥),然后就构成了jwt的第三部分。

    var encodedString = base64UrlEncode(header) + '.' + base64UrlEncode(payload);
    var signature = HMACSHA256(encodedString, '$secret');

    将这三部分用 . 连接成一个完整的字符串,就构成了 1.3.2 节最开始的JWT示例。

    1.3.3 时效

    网关会验证token中的exp字段,一旦这个字段过期了,网关会认为这个token无效而将请求直接打回。过期时间这个值必须设置。

    1.3.4 JWT的几个特点
    1. JWT 默认是不加密,不能将秘密数据写入 JWT。
    2. JWT 不仅可以用于认证,也可以用于交换信息。有效使用 JWT,可以降低服务器查询数据库的次数。
    3. JWT 的最大缺点是,由于服务器不保存 session 状态,因此无法在使用过程中废止某个 token,或者更改 token 的权限。也就是说,一旦 JWT 签发了,在到期之前就会始终有效,除非服务器部署额外的逻辑。
    4. JWT 本身包含了认证信息,一旦泄露,任何人都可以获得该令牌的所有权限。为了减少盗用,JWT 的有效期应该设置得比较短。对于一些比较重要的权限,使用时应该再次对用户进行认证。
    5. 为了减少盗用,JWT 不应该使用 HTTP 协议明码传输,要使用HTTPS 协议传输。

    2、用户系统如何应用JWT插件保护API

    2.1 生成一对JWK(JSON Web 密钥)

    方法一、在线生成:

    用户可以在这个站点https://mkjwk.org 生成用于token生成与验证的私钥与公钥, 私钥用于授权服务签发JWT,公钥配置到JWT插件中用于网关对请求验签,注意网关使用的jwks格式配置,下图中Public Key需要放到keys结构体中,如:{"keys":[{"kty":"RSA","e":"AQAB",...}]}

    img

    方法二、本地生成:

    本文应用Java示例说明,其他语言用户也可以找到相关的工具生成密钥对。 新建一个Maven项目,加入如下依赖:

    <dependency>
    <groupId>org.bitbucket.b_c</groupId>
    <artifactId>jose4j</artifactId>
    <version>0.7.0</version>
    </dependency>

    使用如下的代码生成一对RSA密钥:

    RsaJsonWebKey rsaJsonWebKey = RsaJwkGenerator.generateJwk(2048);
    final String publicKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.PUBLIC_ONLY);
    final String privateKeyString = rsaJsonWebKey.toJson(JsonWebKey.OutputControlLevel.INCLUDE_PRIVATE);

    2.2 使用JWK中的私钥实现颁发token 的认证服务

    需要使用2.1节中在线生成的 Keypair JSON字符串(三个方框内的第一个)或者本地生成的 privateKeyString JSON字符串作为私钥来颁发token,用于授权可信的用户访问受保护的API,具体实现可以参考下方示例。 向客户颁发token的形式由用户根据具体的业务场景决定,可以将颁发token的功能部署到生产环境,配置成普通API后由访问者通过用户名密码获得,也可以直接在本地环境生成token 后,直接拷贝给指定用户使用。

    import java.security.PrivateKey; 
    import org.jose4j.json.JsonUtil;
    import org.jose4j.jwk.RsaJsonWebKey;
    import org.jose4j.jwk.RsaJwkGenerator;
    import org.jose4j.jws.AlgorithmIdentifiers;
    import org.jose4j.jws.JsonWebSignature;
    import org.jose4j.jwt.JwtClaims;
    import org.jose4j.jwt.NumericDate;
    import org.jose4j.lang.JoseException;
    public class GenerateJwtDemo {
    public static void main(String[] args) throws JoseException {
    String keyId = "uniq_key";
    //使用本文2.1节生成的Keypair
    String privateKeyJson = "{\n"
    + " \"kty\": \"RSA\",\n"
    + " \"d\": "
    +
    "\"O9MJSOgcjjiVMNJ4jmBAh0mRHF_TlaVva70Imghtlgwxl8BLfcf1S8ueN1PD7xV6Cnq8YenSKsfiNOhC6yZ_fjW1syn5raWfj68eR7cjHWjLOvKjwVY33GBPNOvspNhVAFzeqfWneRTBbga53Agb6jjN0SUcZdJgnelzz5JNdOGaLzhacjH6YPJKpbuzCQYPkWtoZHDqWTzCSb4mJ3n0NRTsWy7Pm8LwG_Fd3pACl7JIY38IanPQDLoighFfo-Lriv5z3IdlhwbPnx0tk9sBwQBTRdZ8JkqqYkxUiB06phwr7mAnKEpQJ6HvhZBQ1cCnYZ_nIlrX9-I7qomrlE1UoQ\",\n"
    + " \"e\": \"AQAB\",\n"
    + " \"alg\": \"RS256\",\n"
    + " \"n\": \"vCuB8MgwPZfziMSytEbBoOEwxsG7XI3MaVMoocziP4SjzU4IuWuE_DodbOHQwb_thUru57_Efe"
    +
    "--sfATHEa0Odv5ny3QbByqsvjyeHk6ZE4mSAV9BsHYa6GWAgEZtnDceeeDc0y76utXK2XHhC1Pysi2KG8KAzqDa099Yh7s31AyoueoMnrYTmWfEyDsQL_OAIiwgXakkS5U8QyXmWicCwXntDzkIMh8MjfPskesyli0XQD1AmCXVV3h2Opm1Amx0ggSOOiINUR5YRD6mKo49_cN-nrJWjtwSouqDdxHYP-4c7epuTcdS6kQHiQERBd1ejdpAxV4c0t0FHF7MOy9kw\"\n"
    + "}";
    JwtClaims claims = new JwtClaims();
    claims.setGeneratedJwtId();
    claims.setIssuedAtToNow();
    //过期时间一定要设置
    NumericDate date = NumericDate.now();
    date.addSeconds(120*60);
    claims.setExpirationTime(date);
    claims.setNotBeforeMinutesInThePast(1);
    claims.setSubject("YOUR_SUBJECT");
    claims.setAudience("YOUR_AUDIENCE");
    //添加自定义参数,所有值请都使用String类型
    claims.setClaim("userId", "1213234");
    claims.setClaim("email", "userEmail@youapp.com");
    JsonWebSignature jws = new JsonWebSignature();
    jws.setAlgorithmHeaderValue(AlgorithmIdentifiers.RSA_USING_SHA256);
    jws.setKeyIdHeaderValue(keyId);
    jws.setPayload(claims.toJson());
    PrivateKey privateKey = new RsaJsonWebKey(JsonUtil.parseJson(privateKeyJson)).getPrivateKey();

    jws.setKey(privateKey);
    String jwtResult = jws.getCompactSerialization();
    System.out.println("Generate Json Web token , result is " + jwtResult);
    }
    }
    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/key-auth/index.html b/zh-cn/docs/plugins/key-auth/index.html index 053f6f6576..ff7e02bff5 100644 --- a/zh-cn/docs/plugins/key-auth/index.html +++ b/zh-cn/docs/plugins/key-auth/index.html @@ -14,14 +14,14 @@ - +

    Key 认证

    功能说明

    key-auth插件实现了基于 API Key 进行认证鉴权的功能,支持从 HTTP 请求的 URL 参数或者请求头解析 API Key,同时验证该 API Key 是否有权限访问。

    运行属性

    插件执行阶段:认证阶段 插件执行优先级:310

    配置字段

    全局配置

    名称数据类型填写要求默认值描述
    consumersarray of object必填-配置服务的调用者,用于对请求进行认证
    keysarray of string必填-API Key 的来源字段名称,可以是 URL 参数或者 HTTP 请求头名称
    in_queryboolin_queryin_header 至少有一个为 truetrue配置 true 时,网关会尝试从 URL 参数中解析 API Key
    in_headerboolin_queryin_header 至少有一个为 truetrue配置 true 时,网关会尝试从 HTTP 请求头中解析 API Key
    global_authbool选填-若配置为true,则全局生效认证机制; 若配置为false,则只对做了配置的域名和路由生效认证机制; 若不配置则仅当没有域名和路由配置时全局生效(兼容机制)

    consumers中每一项的配置字段说明如下:

    名称数据类型填写要求默认值描述
    credentialstring必填-配置该consumer的访问凭证
    namestring必填-配置该consumer的名称

    域名和路由级配置

    名称数据类型填写要求默认值描述
    allowarray of string必填-对于符合匹配条件的请求,配置允许访问的consumer名称

    注意:

    • 对于通过认证鉴权的请求,请求的header会被添加一个X-Mse-Consumer字段,用以标识调用者的名称。

    配置示例

    对特定路由或域名开启

    以下配置将对网关特定路由或域名开启 Key Auth 认证和鉴权,注意credential字段不能重复

    全局配置

    consumers:
    - credential: 2bda943c-ba2b-11ec-ba07-00163e1250b5
    name: consumer1
    - credential: c8c8e9ca-558e-4a2d-bb62-e700dcc40e35
    name: consumer2
    keys:
    - apikey
    in_query: true
    global_auth: false

    路由级配置

    对 route-a 和 route-b 这两个路由做如下配置:

    allow: 
    - consumer1

    对 *.exmaple.com 和 test.com 在这两个域名做如下配置:

    allow:
    - consumer2

    若是在控制台进行配置,此例指定的 route-aroute-b 即在控制台创建路由时填写的路由名称,当匹配到这两个路由时,将允许nameconsumer1的调用者访问,其他调用者不允许访问;

    此例指定的 *.example.comtest.com 用于匹配请求的域名,当发现域名匹配时,将允许nameconsumer2的调用者访问,其他调用者不允许访问。

    根据该配置,下列请求可以允许访问:

    假设以下请求会匹配到route-a这条路由

    将 API Key 设置在 url 参数中

    curl  http://xxx.hello.com/test?apikey=2bda943c-ba2b-11ec-ba07-00163e1250b5

    将 API Key 设置在 http 请求头中

    curl  http://xxx.hello.com/test -H 'x-api-key: 2bda943c-ba2b-11ec-ba07-00163e1250b5'

    认证鉴权通过后,请求的header中会被添加一个X-Mse-Consumer字段,在此例中其值为consumer1,用以标识调用方的名称

    下列请求将拒绝访问:

    请求未提供 API Key,返回401

    curl  http://xxx.hello.com/test

    请求提供的 API Key 无权访问,返回401

    curl  http://xxx.hello.com/test?apikey=926d90ac-ba2e-11ec-ab68-00163e1250b5

    根据请求提供的 API Key匹配到的调用者无访问权限,返回403

    # consumer2不在route-a的allow列表里
    curl http://xxx.hello.com/test?apikey=c8c8e9ca-558e-4a2d-bb62-e700dcc40e35

    相关错误码

    HTTP 状态码出错信息原因说明
    401No API key found in request请求未提供 API Key
    401Request denied by Key Auth check. Invalid API key不允许当前 API Key 访问
    403Request denied by Basic Auth check. Unauthorized consumer请求的调用方无访问权限
    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/key-rate-limit/index.html b/zh-cn/docs/plugins/key-rate-limit/index.html index de24f0c64b..ea8261c99f 100644 --- a/zh-cn/docs/plugins/key-rate-limit/index.html +++ b/zh-cn/docs/plugins/key-rate-limit/index.html @@ -14,14 +14,14 @@ - +

    基于 Key 限流

    功能说明

    key-rate-limit插件实现了基于特定键值实现限流,键值来源可以是 URL 参数、HTTP 请求头

    运行属性

    插件执行阶段:默认阶段 插件执行优先级:10

    配置字段

    名称数据类型填写要求默认值描述
    limit_by_headerstring选填,limit_by_header,limit_by_param 中选填一项-配置获取限流键值的来源 http 请求头名称
    limit_by_paramstring选填,limit_by_header,limit_by_param 中选填一项-配置获取限流键值的来源 URL 参数名称
    limit_keysarray of object必填-配置匹配键值后的限流次数

    limit_keys中每一项的配置字段说明

    名称数据类型填写要求默认值描述
    keystring必填-匹配的键值
    query_per_secondnumber选填,query_per_second,query_per_minute,query_per_hour,query_per_day 中选填一项-允许每秒请求次数
    query_per_minutenumber选填,query_per_second,query_per_minute,query_per_hour,query_per_day 中选填一项-允许每分钟请求次数
    query_per_hournumber选填,query_per_second,query_per_minute,query_per_hour,query_per_day 中选填一项-允许每小时请求次数
    query_per_daynumber选填,query_per_second,query_per_minute,query_per_hour,query_per_day 中选填一项-允许每天请求次数

    配置示例

    识别请求参数 apikey,进行区别限流

    limit_by_param: apikey
    limit_keys:
    - key: 9a342114-ba8a-11ec-b1bf-00163e1250b5
    query_per_second: 10
    - key: a6a6d7f2-ba8a-11ec-bec2-00163e1250b5
    query_per_minute: 100

    识别请求头 x-ca-key,进行区别限流

    limit_by_header: x-ca-key
    limit_keys:
    - key: 102234
    query_per_second: 10
    - key: 308239
    query_per_hour: 10

    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/request-block/index.html b/zh-cn/docs/plugins/request-block/index.html index 70ed154fc0..e23a38a713 100644 --- a/zh-cn/docs/plugins/request-block/index.html +++ b/zh-cn/docs/plugins/request-block/index.html @@ -14,14 +14,14 @@ - +

    请求屏蔽

    功能说明

    request-block插件实现了基于 URL、请求头等特征屏蔽 HTTP 请求,可以用于防护部分站点资源不对外部暴露

    运行属性

    插件执行阶段:授权阶段 插件执行优先级:320

    配置字段

    名称数据类型填写要求默认值描述
    block_urlsarray of string选填,block_urls,block_headers,block_bodys 中至少必填一项-配置用于匹配需要屏蔽 URL 的字符串
    block_headersarray of string选填,block_urls,block_headers,block_bodys 中至少必填一项-配置用于匹配需要屏蔽请求 Header 的字符串
    block_bodysarray of string选填,block_urls,block_headers,block_bodys 中至少必填一项-配置用于匹配需要屏蔽请求 Body 的字符串
    blocked_codenumber选填403配置请求被屏蔽时返回的 HTTP 状态码
    blocked_messagestring选填-配置请求被屏蔽时返回的 HTTP 应答 Body
    case_sensitivebool选填true配置匹配时是否区分大小写,默认区分

    配置示例

    屏蔽请求 url 路径

    block_urls:
    - swagger.html
    - foo=bar
    case_sensitive: false

    根据该配置,下列请求将被禁止访问:

    curl http://example.com?foo=Bar
    curl http://exmaple.com/Swagger.html

    屏蔽请求 header

    block_headers:
    - example-key
    - example-value

    根据该配置,下列请求将被禁止访问:

    curl http://example.com -H 'example-key: 123'
    curl http://exmaple.com -H 'my-header: example-value'

    屏蔽请求 body

    block_bodys:
    - "hello world"
    case_sensitive: false

    根据该配置,下列请求将被禁止访问:

    curl http://example.com -d 'Hello World'
    curl http://exmaple.com -d 'hello world'

    请求 Body 大小限制

    当配置了 block_bodys 时,仅支持小于 32 MB 的请求 Body 进行匹配。若请求 Body 大于此限制,并且不存在匹配到的 block_urlsblock_headers 项时,不会对该请求执行屏蔽操作

    - + \ No newline at end of file diff --git a/zh-cn/docs/plugins/waf/index.html b/zh-cn/docs/plugins/waf/index.html index 651c474b67..31d891f1cf 100644 --- a/zh-cn/docs/plugins/waf/index.html +++ b/zh-cn/docs/plugins/waf/index.html @@ -14,14 +14,14 @@ - +

    WAF 防护

    功能说明

    开源版 WAF 插件,支持基于 OWASP ModSecurity Core Rule Set (CRS) 的 WAF 规则配置

    运行属性

    插件执行阶段:授权阶段 插件执行优先级:330

    配置字段

    名称数据类型填写要求默认值描述
    useCRSbool选填false是否开启OWASP CRS,详情可参考coreruleset
    secRulesarray of string选填-用户自定义的waf防护规则,语法规则可参考SecLang语法参考

    配置示例

    观察模式(只会记录日志)

    defaultConfig:
    useCRS: true
    secRules:
    - "SecRuleEngine DetectionOnly"

    防护模式

    defaultConfig:
    useCRS: true
    secRules:
    - "SecRuleEngine On"
    - "SecRule REQUEST_URI \"@streq /admin\" \"id:101,phase:1,t:lowercase,deny\""

    根据该配置,以下请求将被禁止访问:

    curl http://example.com/admin

    对特定路由或域名开启

    defaultConfig:
    useCRS: true
    secRules:
    - "SecDebugLogLevel 3"
    - "SecRuleEngine On"
    - "SecRule REQUEST_URI \"@streq /admin\" \"id:101,phase:1,t:lowercase,deny\""
    - "SecRule REQUEST_BODY \"@rx maliciouspayload\" \"id:102,phase:2,t:lowercase,deny\""
    matchRules:
    - ingress:
    - default/echo-ingress
    config:
    secRules:
    - "SecRuleEngine On"
    - "SecDebugLogLevel 3"
    - "SecAction \"id:102,phase:1,deny\""

    此例 matchRules 中指定了名为 default/echo-ingress 的路由的防护配置,当发现路由匹配时,将使用 matchRulesconfig 下的配置;其他请求则使用 defaultConfig 下的配置。

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/annotation-use-case/index.html b/zh-cn/docs/user/annotation-use-case/index.html index dbd02ed425..d72736f299 100644 --- a/zh-cn/docs/user/annotation-use-case/index.html +++ b/zh-cn/docs/user/annotation-use-case/index.html @@ -14,14 +14,15 @@ - +
    -

    通过Ingress Annotation实现高阶流量治理

    本篇文档介绍如何在Higress上使用Ingress并借助Annotation实现高阶流量治理。

    前提条件

    • 安装Higress
    • 已拥有一个Kubernetes集群,且配置了kubectl命令行工具

    灰度发布

    Higress提供复杂的路由处理能力,支持基于Header、Cookie以及权重的灰度发布功能。灰度发布功能可以通过设置注解来实现,为了启用灰度发布功能,需要设置注解higress.io/canary: "true"。通过不同注解可以实现不同的灰度发布功能。

    说明:当多种方式同时配置时,灰度方式选择优先级为:基于Header > 基于Cookie > 基于权重(从高到低)。

    基于Header灰度发布

    • 只配置higress.io/canary-by-header:基于Request Header的名称进行流量切分。当请求包含该Header并其值为always时,请求流量会被分配到灰度服务入口;其他情况时,请求流量不会分配到灰度服务。
    • 同时配置higress.io/canary-by-headerhigress.io/canary-by-header-value:基于Request Header的名称和值进行流量切分。当请求中的header的名称和header的值与该配置匹配时,请求流量会被分配到灰度服务;其他情况时,请求流量不会分配到灰度服务。

      Higress灰度发布时支持多个版本服务(无上限)。

    1. 请求Header为higress:always时将访问灰度服务demo-service-canary;其他情况将访问正式服务demo-service,配置如下:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    name: demo-canary
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact
    1. 请求Header为higress:v1时将访问灰度服务demo-service-canary-v1;请求Header为higress:v2时将访问灰度服务demo-service-canary-v2;其他情况将访问正式服务demo-service,配置如下:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    higress.io/canary-by-header-value: "v1"
    name: demo-canary-v1
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v1
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    higress.io/canary-by-header-value: "v2"
    name: demo-canary-v2
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v2
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    基于Cookie灰度发布

    • higress.io/canary-by-cookie:基于Cookie的Key进行流量切分。当请求的Cookie中含有该Key且其值为always时,请求流量将被分配到灰度服务;其他情况时,请求流量将不会分配到灰度服务。

      说明:基于Cookie的灰度发布不支持自定义设置Key对应的值,只能是always。

    请求的Cookie为demo=always时将访问灰度服务demo-service-canary;其他情况将访问正式服务demo-service。配置如下:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-cookie: "demo"
    name: demo-canary
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    基于权重灰度发布

    • higress.io/canary-weight:设置请求到指定服务的百分比(值为0~100的整数)
    • higress.io/canary-weight-totatl:设置权重总和,默认为100

    配置灰度服务demo-service-canary-v1的权重为30%,配置灰度服务demo-service-canary-v2的权重为20%,配置正式服务demo-service的权重为50%。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-weight: "30"
    name: demo-canary-v1
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v1
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-weight: "20"
    name: demo-canary-v2
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v2
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    跨域

    跨域资源共享CORS(Cross-Origin Resource Sharing)是指允许Web应用服务器进行跨域访问控制,从而实现跨域数据安全传输。

    • higress.io/enable-cors:"true" or "false"。开启或关闭跨域。
    • higress.io/cors-allow-origin:允许的第三方站点,支持泛域名,逗号分隔;支持通配符。默认值为,即允许所有第三方站点。
    • higress.io/cors-allow-methods:允许的请求方法,如GET、POST,逗号分隔;支持通配符*。默认值为GET, PUT, POST, DELETE, PATCH, OPTIONS。
    • higress.io/cors-allow-headers:允许的请求头部,逗号分隔;支持通配符*。默认值为DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization。
    • higress.io/cors-expose-headers:允许的响应头部,逗号分隔。
    • higress.io/cors-allow-credentials:"true" or "false"。是否允许携带凭证信息。默认允许。
    • higress.io/cors-max-age:预检结果的最大缓存时间,单位为秒;默认值为1728000。

    跨域请求被限制为只能来自example.com域的请求,并且HTTP方法只能是GET和POST,允许的请求头部为X-Foo-Bar,不允许携带凭证信息。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/enable-cors: "true"
    higress.io/cors-allow-origin: "example.com"
    higress.io/cors-allow-methods: "GET,POST"
    higress.io/cors-allow-headers: "X-Foo-Bar"
    higress.io/cors-allow-credentials: "false"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    Rewrite重写Path和Host

    在请求转发给目标后端服务之前,重写可以修改原始请求的路径(Path)和主机域(Host)。

    • higress.io/rewrite-target:重写Path,支持捕获组(Capture Group)。
    • higress.io/upstream-vhost:重写Host。

    Rewrite重写Path

    1. 将请求example.com/test在转发至后端服务之前,重写为example.com/dev
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/rewrite-target: "/dev"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 将请求example.com/v1/app在转发至后端服务之前,去掉Path前缀/v1
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/rewrite-target: "/$2"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /v1(/|$)(.*)
    pathType: ImplementationSpecific
    1. 将请求example.com/v1/app在转发至后端服务之前,将Path前缀/v1更改为/v2
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/rewrite-target: "/v2/$2"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /v1(/|$)(.*)
    pathType: ImplementationSpecific

    Rewrite重写Host

    将请求example.com/test在转发至后端服务之前,重写为test.com/test

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-vhost: "test.com"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    重定向

    通过重定向可以将原始客户端请求更改为目标请求。

    配置HTTP重定向至HTTPS

    • higress.io/ssl-redirect:HTTP重定向到HTTPS
    • higress.io/force-ssl-redirect: HTTP重定向到HTTPS

      说明:Higress对于以上两个注解不区分对待,都是强制将HTTP重定向到HTTPS。

    将请求http://example.com/test重定向为https://example.com/test

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/ssl-redirect: "true"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    永久重定向

    • higress.io/permanent-redirect:永久重定向的目标url,必须包含scheme(http or https)。
    • higress.io/permanent-redirect-code:永久重定向的HTTP状态码,默认为301。

    将请求http://example.com/test永久重定向为http://example.com/app

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/permanent-redirect: "http://example.com/app"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    临时重定向

    • higress.io/temporal-redirect:临时重定向的目标url,必须包含scheme(http or https)。

    将请求http://example.com/test临时重定向为http://example.com/app

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/temporal-redirect: "http://example.com/app"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    Header控制

    通过Header控制,您可以在转发请求到后端服务之前对请求Header进行增删改,在收到响应转发给客户端时对响应Header进行增删改。

    请求Header控制

    • higress.io/request-header-control-add:请求在转发给后端服务时,添加指定Header。若该Header存在,则其值拼接在原有值后面。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/request-header-control-update:请求在转发给后端服务时,修改指定Header。若该header存在,则其值覆盖原有值。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/request-header-control-remove:请求在转发给后端服务时,删除指定Header。语法如下:
      • 单个Header:Key
      • 多个Header:逗号分隔
    1. 对于请求example.com/test添加两个Header,foo: bartest: true
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/request-header-control-add: |
    foo bar
    test true
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. Header控制可以结合灰度发布,对灰度流量进行染色。请求Header为higress:v1时将访问灰度服务demo-service-canary-v1,并添加Header,stage: gray;其他情况将访问正式服务demo-service,并添加Header,stage: production。配置如下:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    higress.io/canary-by-header-value: "v1"
    higress.io/request-header-control-add: "stage gray"
    name: demo-canary-v1
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v1
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/request-header-control-add: "stage production"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    响应Header控制

    • higress.io/response-header-control-add:请求在收到后端服务响应之后并且转发响应给客户端之前,添加指定Header。若该Header存在,则其值拼接在原有值后面。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/response-header-control-update:请求在收到后端服务响应之后并且转发响应给客户端之前,修改指定Header。若该header存在,则其值覆盖原有值。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/response-header-control-remove:请求在收到后端服务响应之后并且转发响应给客户端之前,删除指定Header。语法如下:
      • 单个Header:Key
      • 多个Header:逗号分隔

    对于请求example.com/test的响应删除Header:req-cost-time

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/response-header-control-remove: "req-cost-time"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    重试

    Higress提供路由级别的重试设置,可以为出错的请求调用自动进行重试。您可以按需设置重试条件,例如建立连接失败,或者后端服务不可用以及对指定HTTP状态码的响应等进行请求重试。

    • higress.io/proxy-next-upstream-tries:请求的最大重试次数。默认3次。
    • higress.io/proxy-next-upstream-timeout:请求重试的超时时间,单位秒。默认未配置超时时间。
    • higress.io/proxy-next-upstream:请求重试条件,逗号分隔;默认值为"error,timeout"。合法值如下:
      • error:建立连接失败,请求出错5xx。
      • timeout:建立连接超时,请求出错5xx。
      • invalid_header:请求出错5xx。
      • http_xxx:针对具体响应状态码的情况进行重试。例如http_502,http_403。
      • non_idempotent:对于非幂等请求出错时进行重试。默认情况下,Higress针对非幂等POST、PATCH请求出错时不会进行重试,配置non_idempotent可以开启重试。
      • off:关闭重试。

    设置example/test请求的最大重试次数为2,重试超时时间为5s,只有在响应状态码为502才重试,并且开启非幂等重试。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/proxy-next-upstream-tries: "2"
    higress.io/proxy-next-upstream-timeout: "5"
    higress.io/proxy-next-upstream: "http_502,non_idempotent"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    配置后端服务协议:HTTPS或GRPC

    Higress默认使用HTTP协议转发请求到后端业务容器。当您的业务容器为HTTPS协议时,可以通过使用注解higress.io/backend-protocol: "HTTPS";当您的业务容器为GRPC服务时,可以通过使用注解higress.io/backend-protocol: "GRPC"

    说明:相比Nginx Ingress的优势,如果您的后端服务所属的K8s Service资源中关于Port Name的定义为grpc或http2,您无需配置注解higress.io/backend-protocol: "GRPC",Higress会自动使用GRPC或者HTTP2。

    1. 请求example/test转发至后端服务使用HTTPS协议。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/backend-protocol: "HTTPS"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /
    pathType: Exact
    1. 请求example/test转发至后端服务使用GRPC协议。 -第一种做法:通过注解。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/backend-protocol: "GRPC"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    第二种做法:通过Service Port Name

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /order
    pathType: Exact
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: demo-service
    spec:
    ports:
    - name: grpc
    port: 80
    protocol: TCP
    selector:
    app: demo-service

    配置后端服务的负载均衡算法

    负载均衡决定着网关在转发请求至后端服务时如何选择节点。

    普通负载均衡算法

    • higress.io/load-balance:后端服务的普通负载均衡算法。默认为round_robin。合法值如下:
      • round_robin:基于轮询的负载均衡。
      • least_conn:基于最小请求数的负载均衡。
      • random:基于随机的负载均衡。

    设置后端服务demo-service的负载均衡算法为least_conn。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/load-balance: "least_conn"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /order
    pathType: Exact

    基于一致性Hash的负载均衡算法

    基于一致性Hash的负载均衡算法具备请求亲和性,具有相同特征的请求会始终负载到相同节点上。Higress支持基于部分Nginx 变量、请求Header和请求路径参数作为Hash Key。

    • higress.io/upstream-hash-by:基于一致Hash的负载均衡算法。Higress支持以下几种形式:
      • 支持配置部分nginx变量:
        • $request_uri:请求的Path(包括路径参数)作为Hash Key
        • $host:请求的Host作为Hash Key
        • $remote_addr:请求的客户端IP作为Hash Key
      • 基于请求header的一致性Hash。您只需配置为$http_headerName。
      • 基于请求路径参数的一致性Hash。您只需配置为$arg_varName。
    1. 基于请求的客户端IP作为Hash Key,同一个客户端IP的请求始终负载到同一个节点。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-hash-by: "$remote_addr"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 基于请求Header x-stage作为Hash key,带有x-stage头部的请求且值相同的请求始终负载到同一个节点。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-hash-by: "$http_x-stage"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 基于请求路径参数 x-stage作为Hash key,带有路径参数x-stage的请求且值相同的请求始终负载到同一个节点。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-hash-by: "$arg_x-stage"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    Cookie亲和性 (会话保持)

    具备相同的Cookie的请求会被网关始终负载到同一个节点,并且如果第一次访问携带Cookie,Higress会在第一次响应时为客户端生成一个Cookie,用来保证后续的请求被网关始终负载到相同节点。

    • higress.io/affinity:亲和性种类,目前只支持cookie,默认为cookie。
    • higress.io/affinity-mode:亲和性模式,Higress目前只支持balanced模式,默认为balanced模式。
    • higress.io/session-cookie-name:配置指定Cookie的值作为Hash Key,默认为INGRESSCOOKIE
    • higress.io/session-cookie-path:当指定Cookie不存在,生成的Cookie的Path值,默认为/
    • higress.io/session-cookie-max-age:当指定Cookie不存在,生成的Cookie的过期时间,单位为秒,默认为Session会话级别。
    • higress.io/session-cookie-expires:当指定Cookie不存在,生成的Cookie的过期时间,单位为秒,默认为Session会话级别。

      说明:max-age和expires都可以用来指定cookie过期时间。当session-cookie-max-age和session-cookie-expires同时配置时,Higress优先选取session-cookie-max-age作为过期时间。

    1. 开启Cookie亲和性,利用Higress的默认配置,即Cookie的名字为INGRESSCOOKIE,Path为/,Cookie的生命周期为Session会话级别。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/affinity: "cookie"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 开启Cookie亲和性,Cookie的名字为test,Path为/,Cookie的过期时间为10s。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/affinity: "cookie"
    higress.io/session-cookie-name: "test"
    higress.io/session-cookie-max-age: "10"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    网关与后端服务双向认证(MTLS)

    默认情况下,Higress默认使用HTTP协议转发请求到后端业务容器。你可以通过使用注解higress.io/backend-protocol: "HTTPS"配置Higress访问后端服务使用HTTPS协议,但这是单向TLS,也就是说只有Higress会验证后端服务提供的证书,且一般后端服务使用的证书需要是权威CA签发的。另一种更安全的模式是零信任,网关会验证后端服务的证书是否合法,同样后端服务也会验证网关提供的证书是否合法,这就是MTLS,网关与后端服务进行双向认证。

    • higress.io/proxy-ssl-secret:网关使用的客户端证书,用于后端服务对网关进行身份认证,格式为 secretNamespace/secretName。
    • higress.io/proxy-ssl-name:TLS握手期间使用的SNI。
    • higress.io/proxy-ssl-server-name:on or off。开启或关闭TLS握手期间使用SNI。

    网关与后端服务进行双向认证,网关使用的secret name为gateway-cert,命名空为default。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/proxy-ssl-secret: "default/gateway-cert"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    - +

    通过Ingress Annotation实现高阶流量治理

    本篇文档介绍如何在Higress上使用Ingress并借助Annotation实现高阶流量治理。

    前提条件

    • 安装Higress
    • 已拥有一个Kubernetes集群,且配置了kubectl命令行工具

    灰度发布

    Higress提供复杂的路由处理能力,支持基于Header、Cookie以及权重的灰度发布功能。灰度发布功能可以通过设置注解来实现,为了启用灰度发布功能,需要设置注解higress.io/canary: "true"。通过不同注解可以实现不同的灰度发布功能。

    说明:当多种方式同时配置时,灰度方式选择优先级为:基于Header > 基于Cookie > 基于权重(从高到低)。

    基于Header灰度发布

    • 只配置higress.io/canary-by-header:基于Request Header的名称进行流量切分。当请求包含该Header并其值为always时,请求流量会被分配到灰度服务入口;其他情况时,请求流量不会分配到灰度服务。
    • 同时配置higress.io/canary-by-headerhigress.io/canary-by-header-value:基于Request Header的名称和值进行流量切分。当请求中的header的名称和header的值与该配置匹配时,请求流量会被分配到灰度服务;其他情况时,请求流量不会分配到灰度服务。

      Higress灰度发布时支持多个版本服务(无上限)。

    1. 请求Header为higress:always时将访问灰度服务demo-service-canary;其他情况将访问正式服务demo-service,配置如下:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    name: demo-canary
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact
    1. 请求Header为higress:v1时将访问灰度服务demo-service-canary-v1;请求Header为higress:v2时将访问灰度服务demo-service-canary-v2;其他情况将访问正式服务demo-service,配置如下:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    higress.io/canary-by-header-value: "v1"
    name: demo-canary-v1
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v1
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    higress.io/canary-by-header-value: "v2"
    name: demo-canary-v2
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v2
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    基于Cookie灰度发布

    • higress.io/canary-by-cookie:基于Cookie的Key进行流量切分。当请求的Cookie中含有该Key且其值为always时,请求流量将被分配到灰度服务;其他情况时,请求流量将不会分配到灰度服务。

      说明:基于Cookie的灰度发布不支持自定义设置Key对应的值,只能是always。

    请求的Cookie为demo=always时将访问灰度服务demo-service-canary;其他情况将访问正式服务demo-service。配置如下:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-cookie: "demo"
    name: demo-canary
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    基于权重灰度发布

    • higress.io/canary-weight:设置请求到指定服务的百分比(值为0~100的整数)
    • higress.io/canary-weight-totatl:设置权重总和,默认为100

    配置灰度服务demo-service-canary-v1的权重为30%,配置灰度服务demo-service-canary-v2的权重为20%,配置正式服务demo-service的权重为50%。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-weight: "30"
    name: demo-canary-v1
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v1
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-weight: "20"
    name: demo-canary-v2
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v2
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    跨域

    跨域资源共享CORS(Cross-Origin Resource Sharing)是指允许Web应用服务器进行跨域访问控制,从而实现跨域数据安全传输。

    • higress.io/enable-cors:"true" or "false"。开启或关闭跨域。
    • higress.io/cors-allow-origin:允许的第三方站点,支持泛域名,逗号分隔;支持通配符。默认值为,即允许所有第三方站点。
    • higress.io/cors-allow-methods:允许的请求方法,如GET、POST,逗号分隔;支持通配符*。默认值为GET, PUT, POST, DELETE, PATCH, OPTIONS。
    • higress.io/cors-allow-headers:允许的请求头部,逗号分隔;支持通配符*。默认值为DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization。
    • higress.io/cors-expose-headers:允许的响应头部,逗号分隔。
    • higress.io/cors-allow-credentials:"true" or "false"。是否允许携带凭证信息。默认允许。
    • higress.io/cors-max-age:预检结果的最大缓存时间,单位为秒;默认值为1728000。

    跨域请求被限制为只能来自example.com域的请求,并且HTTP方法只能是GET和POST,允许的请求头部为X-Foo-Bar,不允许携带凭证信息。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/enable-cors: "true"
    higress.io/cors-allow-origin: "example.com"
    higress.io/cors-allow-methods: "GET,POST"
    higress.io/cors-allow-headers: "X-Foo-Bar"
    higress.io/cors-allow-credentials: "false"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    Rewrite重写Path和Host

    在请求转发给目标后端服务之前,重写可以修改原始请求的路径(Path)和主机域(Host)。

    • higress.io/rewrite-target:重写Path,支持捕获组(Capture Group)。
    • higress.io/upstream-vhost:重写Host。

    Rewrite重写Path

    1. 将请求example.com/test在转发至后端服务之前,重写为example.com/dev
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/rewrite-target: "/dev"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 将请求example.com/v1/app在转发至后端服务之前,去掉Path前缀/v1
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/rewrite-target: "/$2"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /v1(/|$)(.*)
    pathType: ImplementationSpecific
    1. 将请求example.com/v1/app在转发至后端服务之前,将Path前缀/v1更改为/v2
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/rewrite-target: "/v2/$2"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /v1(/|$)(.*)
    pathType: ImplementationSpecific

    Rewrite重写Host

    将请求example.com/test在转发至后端服务之前,重写为test.com/test

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-vhost: "test.com"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    重定向

    通过重定向可以将原始客户端请求更改为目标请求。

    配置HTTP重定向至HTTPS

    • higress.io/ssl-redirect:HTTP重定向到HTTPS
    • higress.io/force-ssl-redirect: HTTP重定向到HTTPS

      说明:Higress对于以上两个注解不区分对待,都是强制将HTTP重定向到HTTPS。

    将请求http://example.com/test重定向为https://example.com/test

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/ssl-redirect: "true"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    永久重定向

    • higress.io/permanent-redirect:永久重定向的目标url,必须包含scheme(http or https)。
    • higress.io/permanent-redirect-code:永久重定向的HTTP状态码,默认为301。

    将请求http://example.com/test永久重定向为http://example.com/app

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/permanent-redirect: "http://example.com/app"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    临时重定向

    • higress.io/temporal-redirect:临时重定向的目标url,必须包含scheme(http or https)。

    将请求http://example.com/test临时重定向为http://example.com/app

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/temporal-redirect: "http://example.com/app"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    Header控制

    通过Header控制,您可以在转发请求到后端服务之前对请求Header进行增删改,在收到响应转发给客户端时对响应Header进行增删改。

    请求Header控制

    • higress.io/request-header-control-add:请求在转发给后端服务时,添加指定Header。若该Header存在,则其值拼接在原有值后面。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/request-header-control-update:请求在转发给后端服务时,修改指定Header。若该header存在,则其值覆盖原有值。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/request-header-control-remove:请求在转发给后端服务时,删除指定Header。语法如下:
      • 单个Header:Key
      • 多个Header:逗号分隔
    1. 对于请求example.com/test添加两个Header,foo: bartest: true
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/request-header-control-add: |
    foo bar
    test true
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. Header控制可以结合灰度发布,对灰度流量进行染色。请求Header为higress:v1时将访问灰度服务demo-service-canary-v1,并添加Header,stage: gray;其他情况将访问正式服务demo-service,并添加Header,stage: production。配置如下:
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/canary: "true"
    higress.io/canary-by-header: "higress"
    higress.io/canary-by-header-value: "v1"
    higress.io/request-header-control-add: "stage gray"
    name: demo-canary-v1
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service-canary-v1
    port:
    number: 80
    path: /hello
    pathType: Exact
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/request-header-control-add: "stage production"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /hello
    pathType: Exact

    响应Header控制

    • higress.io/response-header-control-add:请求在收到后端服务响应之后并且转发响应给客户端之前,添加指定Header。若该Header存在,则其值拼接在原有值后面。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/response-header-control-update:请求在收到后端服务响应之后并且转发响应给客户端之前,修改指定Header。若该header存在,则其值覆盖原有值。语法如下:
      • 单个Header:Key Value
      • 多个Header:使用yaml特殊符号 |,每对Key Value单独处于一行
    • higress.io/response-header-control-remove:请求在收到后端服务响应之后并且转发响应给客户端之前,删除指定Header。语法如下:
      • 单个Header:Key
      • 多个Header:逗号分隔

    对于请求example.com/test的响应删除Header:req-cost-time

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/response-header-control-remove: "req-cost-time"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    重试

    Higress提供路由级别的重试设置,可以为出错的请求调用自动进行重试。您可以按需设置重试条件,例如建立连接失败,或者后端服务不可用以及对指定HTTP状态码的响应等进行请求重试。

    • higress.io/proxy-next-upstream-tries:请求的最大重试次数。默认3次。
    • higress.io/proxy-next-upstream-timeout:请求重试的超时时间,单位秒。默认未配置超时时间。
    • higress.io/proxy-next-upstream:请求重试条件,逗号分隔;默认值为"error,timeout"。合法值如下:
      • error:建立连接失败,请求出错5xx。
      • timeout:建立连接超时,请求出错5xx。
      • invalid_header:请求出错5xx。
      • http_xxx:针对具体响应状态码的情况进行重试。例如http_502,http_403。
      • non_idempotent:对于非幂等请求出错时进行重试。默认情况下,Higress针对非幂等POST、PATCH请求出错时不会进行重试,配置non_idempotent可以开启重试。
      • off:关闭重试。

    设置example/test请求的最大重试次数为2,重试超时时间为5s,只有在响应状态码为502才重试,并且开启非幂等重试。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/proxy-next-upstream-tries: "2"
    higress.io/proxy-next-upstream-timeout: "5"
    higress.io/proxy-next-upstream: "http_502,non_idempotent"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    超时

    Higress提供路由级别的超时设置,与nginx ingress不同,没有区分连接/读写超时,而是面向的接口处理总延时进行配置,在未进行配置时默认不限制,例如后端未返回应答,网关将无限等待。

    设置超时时间为5s:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    mse.ingress.kubernetes.io/timeout: "5"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    单机限流

    支持针对路由级别的单机限流策略,在设定的时间周期内,限制每个网关副本匹配在某个路由上的请求数量不大于阈值。该限流是针对单机级别,即配置的阈值在每个网关实例进行流控。

    提示 +Higress商业版具备全局限流能力,详情查看商业版文档中全局限流一节的介绍

    例如:

    限制example.com/test的请求每分钟最大请求数为100,瞬时请求数200。配置如下:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    mse.ingress.kubernetes.io/route-limit-rpm: "100"
    mse.ingress.kubernetes.io/route-limit-burst-multiplier: "2"
    name: demo
    spec:
    ingressClassName: mse
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    限制example.com/test的请求每秒最大请求数为10,瞬时请求数50。配置如下:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    mse.ingress.kubernetes.io/route-limit-rps: "10"
    # 默认为5
    # mse.ingress.kubernetes.io/route-limit-burst-multiplier: "5"
    name: demo
    spec:
    ingressClassName: mse
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    配置后端服务协议:HTTPS或GRPC

    Higress默认使用HTTP协议转发请求到后端业务容器。当您的业务容器为HTTPS协议时,可以通过使用注解higress.io/backend-protocol: "HTTPS";当您的业务容器为GRPC服务时,可以通过使用注解higress.io/backend-protocol: "GRPC"

    说明:相比Nginx Ingress的优势,如果您的后端服务所属的K8s Service资源中关于Port Name的定义为grpc或http2,您无需配置注解higress.io/backend-protocol: "GRPC",Higress会自动使用GRPC或者HTTP2。

    1. 请求example/test转发至后端服务使用HTTPS协议。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/backend-protocol: "HTTPS"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /
    pathType: Exact
    1. 请求example/test转发至后端服务使用GRPC协议。 +第一种做法:通过注解。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/backend-protocol: "GRPC"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    第二种做法:通过Service Port Name

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /order
    pathType: Exact
    ---
    apiVersion: v1
    kind: Service
    metadata:
    name: demo-service
    spec:
    ports:
    - name: grpc
    port: 80
    protocol: TCP
    selector:
    app: demo-service

    配置后端服务的负载均衡算法

    负载均衡决定着网关在转发请求至后端服务时如何选择节点。

    普通负载均衡算法

    • higress.io/load-balance:后端服务的普通负载均衡算法。默认为round_robin。合法值如下:
      • round_robin:基于轮询的负载均衡。
      • least_conn:基于最小请求数的负载均衡。
      • random:基于随机的负载均衡。

    设置后端服务demo-service的负载均衡算法为least_conn。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/load-balance: "least_conn"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /order
    pathType: Exact

    基于一致性Hash的负载均衡算法

    基于一致性Hash的负载均衡算法具备请求亲和性,具有相同特征的请求会始终负载到相同节点上。Higress支持基于部分Nginx 变量、请求Header和请求路径参数作为Hash Key。

    • higress.io/upstream-hash-by:基于一致Hash的负载均衡算法。Higress支持以下几种形式:
      • 支持配置部分nginx变量:
        • $request_uri:请求的Path(包括路径参数)作为Hash Key
        • $host:请求的Host作为Hash Key
        • $remote_addr:请求的客户端IP作为Hash Key
      • 基于请求header的一致性Hash。您只需配置为$http_headerName。
      • 基于请求路径参数的一致性Hash。您只需配置为$arg_varName。
    1. 基于请求的客户端IP作为Hash Key,同一个客户端IP的请求始终负载到同一个节点。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-hash-by: "$remote_addr"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 基于请求Header x-stage作为Hash key,带有x-stage头部的请求且值相同的请求始终负载到同一个节点。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-hash-by: "$http_x-stage"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 基于请求路径参数 x-stage作为Hash key,带有路径参数x-stage的请求且值相同的请求始终负载到同一个节点。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/upstream-hash-by: "$arg_x-stage"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    Cookie亲和性 (会话保持)

    具备相同的Cookie的请求会被网关始终负载到同一个节点,并且如果第一次访问携带Cookie,Higress会在第一次响应时为客户端生成一个Cookie,用来保证后续的请求被网关始终负载到相同节点。

    • higress.io/affinity:亲和性种类,目前只支持cookie,默认为cookie。
    • higress.io/affinity-mode:亲和性模式,Higress目前只支持balanced模式,默认为balanced模式。
    • higress.io/session-cookie-name:配置指定Cookie的值作为Hash Key,默认为INGRESSCOOKIE
    • higress.io/session-cookie-path:当指定Cookie不存在,生成的Cookie的Path值,默认为/
    • higress.io/session-cookie-max-age:当指定Cookie不存在,生成的Cookie的过期时间,单位为秒,默认为Session会话级别。
    • higress.io/session-cookie-expires:当指定Cookie不存在,生成的Cookie的过期时间,单位为秒,默认为Session会话级别。

      说明:max-age和expires都可以用来指定cookie过期时间。当session-cookie-max-age和session-cookie-expires同时配置时,Higress优先选取session-cookie-max-age作为过期时间。

    1. 开启Cookie亲和性,利用Higress的默认配置,即Cookie的名字为INGRESSCOOKIE,Path为/,Cookie的生命周期为Session会话级别。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/affinity: "cookie"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    1. 开启Cookie亲和性,Cookie的名字为test,Path为/,Cookie的过期时间为10s。
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/affinity: "cookie"
    higress.io/session-cookie-name: "test"
    higress.io/session-cookie-max-age: "10"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact

    网关与后端服务双向认证(MTLS)

    默认情况下,Higress默认使用HTTP协议转发请求到后端业务容器。你可以通过使用注解higress.io/backend-protocol: "HTTPS"配置Higress访问后端服务使用HTTPS协议,但这是单向TLS,也就是说只有Higress会验证后端服务提供的证书,且一般后端服务使用的证书需要是权威CA签发的。另一种更安全的模式是零信任,网关会验证后端服务的证书是否合法,同样后端服务也会验证网关提供的证书是否合法,这就是MTLS,网关与后端服务进行双向认证。

    • higress.io/proxy-ssl-secret:网关使用的客户端证书,用于后端服务对网关进行身份认证,格式为 secretNamespace/secretName。
    • higress.io/proxy-ssl-name:TLS握手期间使用的SNI。
    • higress.io/proxy-ssl-server-name:on or off。开启或关闭TLS握手期间使用SNI。

    网关与后端服务进行双向认证,网关使用的secret name为gateway-cert,命名空为default。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/proxy-ssl-secret: "default/gateway-cert"
    name: demo
    spec:
    ingressClassName: higress
    rules:
    - host: example.com
    http:
    paths:
    - backend:
    service:
    name: demo-service
    port:
    number: 80
    path: /test
    pathType: Exact
    + \ No newline at end of file diff --git a/zh-cn/docs/user/annotation/index.html b/zh-cn/docs/user/annotation/index.html index d535caf155..f11845fb51 100644 --- a/zh-cn/docs/user/annotation/index.html +++ b/zh-cn/docs/user/annotation/index.html @@ -14,13 +14,13 @@ - +

    Ingress Annotaion 配置说明

    标准的K8s Ingress资源只能处理简单场景下的HTTP(S)流量路由,无法处理流量切分,超时重试,Header控制和跨域等问题。因此,不同的Ingress Controller利用自定义的Ingress Annotation增强Ingress能力。常见的Nginx Ingress Controller引入了100多个Annotation对Ingress在流量治理和安全防护上进行了扩展实现。目前,Higress已经全面兼容了大部分Nginx Ingress Annotation,方便用户从Nginx Ingress无缝迁移至Higress,本文主要介绍Higress关于Ingress Annotation的配置说明。

    Ingress Annotation

    特殊说明

    Annotation Key 前缀

    以下出现的Nginx Ingress Annotation都已被Higress支持,您可以根据使用习惯继续使用Nginx Ingress的Annotation前缀nginx.ingress.kubernetes.io,或者使用Higress Ingress的Annotation前缀higress.io,两者是等价的。

    作用域说明

    • Ingress:作用域为Ingress的Annotation的作用范围仅限当前Ingress上定义的路由规则。
    • 域名:作用域为域名的Annotation,其作用范围为所有Ingress上出现的相同Host。
    • 服务:作用域为服务的Annotation,其作用范围为所有Ingress上出现的相同Service。

    流量治理

    灰度发布

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/canaryIngress兼容开启或关闭灰度发布
    nginx.ingress.kubernetes.io/canary-by-headerIngress兼容基于Request Header Key 流量切分
    nginx.ingress.kubernetes.io/canary-by-header-valueIngress兼容基于Request Header Value 流量切分,Value为精确匹配
    nginx.ingress.kubernetes.io/canary-by-header-patternIngress兼容基于Request Header Value 流量切分,Value为正则匹配
    nginx.ingress.kubernetes.io/canary-by-cookieIngress兼容基于Request Cookie Key 流量切分
    nginx.ingress.kubernetes.io/canary-weightIngress兼容基于权重 流量切分
    nginx.ingress.kubernetes.io/canary-weight-totalIngress兼容权重总和

    Fallback(容灾)

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/default-backendIngress兼容容灾服务。当Ingress定义的服务没有可用节点时,请求会自动转发该容灾服务。
    nginx.ingress.kubernetes.io/custom-http-errorsIngress兼容该注解和default-backend一起工作。当后端服务返回指定HTTP响应码,原始请求会被再次转发至容灾服务。
    > 注意:转发至容灾服务时,请求的Path会被重写为/,该行为与ingress-nginx保持一致

    重写

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/rewrite-targetIngress兼容将Ingress定义的原path重写为指定目标,支持Group Capture.
    nginx.ingress.kubernetes.io/upstream-vhostIngress兼容匹配Ingress定义的路由的请求在转发给后端服务时,修改头部host值为指定值。

    重定向

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/ssl-redirectIngress兼容HTTP 重定向为HTTPS
    nginx.ingress.kubernetes.io/force-ssl-redirectIngress兼容HTTP 重定向为HTTPS
    nginx.ingress.kubernetes.io/permanent-redirectIngress兼容永久重定向
    nginx.ingress.kubernetes.io/permanent-redirect-codeIngress兼容永久重定向状态码
    nginx.ingress.kubernetes.io/temporal-redirectIngress兼容临时重定向
    nginx.ingress.kubernetes.io/app-rootIngress兼容修改应用根路径,对于访问/的请求将会被重定向为设置的新路径

    跨域

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/enable-corsIngress兼容开启或关闭跨域
    nginx.ingress.kubernetes.io/cors-allow-originIngress兼容允许的第三方站点
    nginx.ingress.kubernetes.io/cors-allow-methodsIngress兼容允许的请求方法,如GET、POST、PUT等
    nginx.ingress.kubernetes.io/cors-allow-headersIngress兼容允许的请求Header
    nginx.ingress.kubernetes.io/cors-expose-headersIngress兼容允许的暴露给浏览器的响应Header
    nginx.ingress.kubernetes.io/cors-allow-credentialsIngress兼容是否允许携带凭证信息
    nginx.ingress.kubernetes.io/cors-max-ageIngress兼容预检结果的最大缓存时间

    超时

    注解作用域支持度说明
    higress.io/timeoutIngressHigress 扩展请求的超时时间,单位为秒。默认未配置超时时间。超时设置作用在应用层,非传输层TCP。

    单机限流

    注解作用域支持度说明
    higress.io/route-limit-rpmIngressHigress 扩展该Ingress定义的路由在每个网关实例上每分钟最大请求次数。瞬时最大请求次数为该值乘以limit-burst-multiplier。
    higress.io/route-limit-rpsIngressHigress 扩展该Ingress定义的路由在每个网关实例上每秒最大请求次数。瞬时最大请求次数为该值乘以limit-burst-multiplier。
    higress.io/route-limit-burst-multiplierIngressHigress 扩展瞬时最大请求次数的因子,默认为5。

    重试

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/proxy-next-upstream-triesIngress兼容请求的最大重试次数。默认3次。
    nginx.ingress.kubernetes.io/proxy-next-upstream-timeoutIngress兼容请求重试的超时时间,单位秒。默认未配置超时时间。
    nginx.ingress.kubernetes.io/proxy-next-upstreamIngress兼容请求重试条件,参考http://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_next_upstream

    后端服务使用的协议

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/backend-protocol服务部分兼容。不支持AJP和FCGI指定后端服务使用的协议,默认为HTTP,支持HTTP、HTTP2、HTTPS、GRPC和GRPCS

    负载均衡

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/load-balance服务部分兼容。不支持ewma算法后端服务的普通负载均衡算法。默认为round_robin。
    合法值如下:
    - round_robin:基于轮询的负载均衡。
    - least_conn:基于最小请求数的负载均衡。
    - random:基于随机的负载均衡。
    > 注意:Higress不支持ewma算法,若配置为ewma算法,会回退到round_robin算法。
    nginx.ingress.kubernetes.io/upstream-hash-by服务部分兼容。暂不支持Nginx变量、常量的组合使用方式基于一致Hash的负载均衡算法,Higress支持以下几种形式:
    1. Higress支持配置部分nginx变量:
    - $request_uri:请求的Path(包括路径参数)作为Hash Key
    - $host:请求的Host作为Hash Key
    - $remote_addr:请求的客户端IP作为Hash Key。
    2. 基于请求header的一致性Hash。您只需配置为$http_headerName。
    3. 基于请求路径参数的一致性Hash。您只需配置为$arg_varName

    Cookie亲和性

    注解作用支持度说明
    nginx.ingress.kubernetes.io/affinity服务兼容亲和性种类,目前只支持cookie,默认为cookie。
    nginx.ingress.kubernetes.io/affinity-mode服务部分兼容。暂不支持persistent模式亲和性模式,云原生网关目前只支持balanced模式,默认为balanced模式。
    nginx.ingress.kubernetes.io/session-cookie-name服务兼容配置指定Cookie的值作为Hash Key
    nginx.ingress.kubernetes.io/session-cookie-path服务兼容当指定Cookie不存在,生成的Cookie的Path值,默认为/
    nginx.ingress.kubernetes.io/session-cookie-max-age服务兼容当指定Cookie不存在,生成的Cookie的过期时间,单位为秒,默认为Session会话级别。
    nginx.ingress.kubernetes.io/session-cookie-expires服务兼容当指定Cookie不存在,生成的Cookie的过期时间,单位为秒,默认为Session会话级别。

    IP访问控制

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/whitelist-source-rangeIngress兼容指定路由上的IP白名单,支持IP地址或CIDR地址块,以逗号分隔。

    安全防护

    客户端与网关之前的通信加密

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/ssl-cipher域名兼容指定tls的加密套件,可以指定多个,英文逗号分隔,仅当tls握手时采用TLSv1.0-1.2生效。
    默认加密套件如下:
    - ECDHE-ECDSA-AES128-GCM-SHA256
    - ECDHE-RSA-AES128-GCM-SHA256
    - ECDHE-ECDSA-AES128-SHA
    - ECDHE-RSA-AES128-SHA
    - AES128-GCM-SHA256
    - AES128-SHA
    - ECDHE-ECDSA-AES256-GCM-SHA384
    - ECDHE-RSA-AES256-GCM-SHA384
    - ECDHE-ECDSA-AES256-SHA
    - ECDHE-RSA-AES256-SHA
    - AES256-GCM-SHA384
    - AES256-SHA
    nginx.ingress.kubernetes.io/auth-tls-secret域名部分兼容。secret名字格式必须是:(该域名证书所在的secret的名字)-cacert网关使用的CA证书,用于验证MTLS握手期间,客户端提供的证书。该注解主要应用于网关需要验证客户端身份的场景。

    网关与后端服务之间通信加密

    注解作用域支持度说明
    nginx.ingress.kubernetes.io/proxy-ssl-secret服务兼容网关使用的客户端证书,用于后端服务对网关进行身份认证
    nginx.ingress.kubernetes.io/proxy-ssl-name服务兼容TLS握手期间使用的SNI
    nginx.ingress.kubernetes.io/proxy-ssl-server-name服务兼容开启或关闭TLS握手期间使用SNI

    安全认证

    Basic
    注解作用域支持度说明
    nginx.ingress.kubernetes.io/auth-typeIngress部分兼容。暂只支持Basic。认证类型
    nginx.ingress.kubernetes.io/auth-secretIngress兼容Secret名字,格式支持<namespace>/<name>,包含被授予能够访问该Ingress上定义的路由的访问权限的用户名和密码。
    nginx.ingress.kubernetes.io/auth-secret-typeIngress兼容Secret内容格式。
    - auth-file:data的key为auth;value为用户名和密码,多帐号回车分隔
    - auth-map:data的key为用户名;value为密码
    nginx.ingress.kubernetes.io/auth-realmIngress兼容保护域。相同的保护域共享用户名和密码。

    备注

    关于以上提到的Nginx Ingress Annotation的更多信息,请参阅官方文档(https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#annotations)。

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/configmap/index.html b/zh-cn/docs/user/configmap/index.html index 2ccdd43519..8174fe2c2a 100644 --- a/zh-cn/docs/user/configmap/index.html +++ b/zh-cn/docs/user/configmap/index.html @@ -14,14 +14,14 @@ - +

    全局配置

    Higress 的全局配置 ConfigMap 对象 higress-config 增加 higress 项, 参考配置如下:

    apiVersion: v1
    data:
    higress: |-
    tracing:
    enable: true
    sampling: 100
    timeout: 500
    skywalking:
    service: skywalking-oap-server.op-system.svc.cluster.local
    port: 11800
    ...
    ...
    kind: ConfigMap
    metadata:
    name: higress-config
    namespace: higress-system

    配置说明

    Tracing 配置说明

    字段类型说明默认
    enableboolean是否开启 tracing 功能false
    samplingfloat采样率,0.0 - 100.0 之间100.0
    timeoutint链路跟踪中间件 grpc 连接超时,单位毫秒500
    skywalking参考下面 skywalking 设置skywalking 配置未设置
    zipkin参考下面 zipkin 设置zipkin 配置未设置

    skywalking 配置

    字段类型说明默认
    servicestringSkywalking grpc 服务地址
    portstringSkywalking grpc 服务端口
    access_tokenstringSkywalking grpc 服务访问凭证

    zipkin 配置

    字段类型说明默认
    servicestringzipkin 服务地址
    portstringzipkin 服务端口

    注意: skywalking 和 zipkin 不能同时设置,只有一个配置能生效

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/configurations/index.html b/zh-cn/docs/user/configurations/index.html index 00ca05e300..e4a9798718 100644 --- a/zh-cn/docs/user/configurations/index.html +++ b/zh-cn/docs/user/configurations/index.html @@ -14,13 +14,13 @@ - +

    Higress参数配置

    Global参数

    参数参数说明默认值
    global.ingressClassIngressClass 参数用于筛选 Higress 控制器要监听的 Ingress 资源。在集群内部署了多个网关时,可以使用这一参数来区分每个网关的职责范围 。IngressClass 有一些特殊的取值:1. 如果设置为“nginx”,Higress Controller 将监听 Ingress 为 nginx 或为空的 Ingress 资源。2. 如果设为空,Higress Controller 将监听 K8s 集群内的全部 Ingress 资源。higress
    global.watchNamespace如果值不为空,Higress Controller 将只会监听指定命名空间下的资源。当基于 K8s 命名空间进行业务系统隔离时,若需要对每个命名空间部署一套独立的网关,可以通过这一参数来限制 Higress 监听指定命名空间内的 Ingress。""
    global.disableAlpnH2是否在 ALPN 中禁用 HTTP/2 协议true
    global.enableStatus若为true, Higress Controller 将会更新 Ingress 资源的 status 字段。为避免从 Nginx Ingress 迁移过程中,覆盖 Ingress 对象的 status 字段,可以将这一参数设置为false,这样 Higress 默认就不会将入口 IP 写入 Ingress 的 status 字段。true
    global.local如果要安装至本地 K8s 集群(如 Kind、Rancher Desktop 等),请设置为 truefalse
    global.enableIstioAPI若为 true,Higress Controller 将同时监听 istio 资源false
    global.imagePullPolicy如果不希望使用默认行为,则可以指定镜像拉取策略。默认行为:最新的镜像将始终以 Always 方式拉取,否则将以 IfNotPresent 方式拉取。""
    global.imagePullSecrets为所有 ServiceAccount 配置 ImagePullSecrets,即在同一命名空间中列出的一组密钥,用于拉取任何引用此 ServiceAccount 的 pod 中的镜像。对于不使用 ServiceAccount 的组件(例如 grafana、servicegraph、tracing),ImagePullSecrets 将被添加到相应的 Deployment(StatefulSet)对象中。对于配置了私有 Docker Registry 的任何集群,都必须设置此项。[]

    meshConfig参数

    参数参数说明默认值
    higress-core.meshConfig.enablePrometheusMerge用于启用或禁用将 Prometheus 指标进行合并的选项。通过启用它,Istio 将能够将来自多个代理的指标进行聚合和展示。true
    higress-core.meshConfig.rootNamespace表示根命名空间。如果未指定,则默认为 "istio-system"。null
    higress-core.meshConfig.trustDomain表示信任域。默认为 "cluster.local"。信任域用于确定服务之间的安全通信,它将用于生成服务的证书和 JWT Token。cluster.local

    Gateway参数

    参数参数说明默认值
    higress-core.gateway.replicasHigress Gateway 的 pod 数量。2
    higress-core.gateway.rbac.enabled如果启用,则将创建 roles 以便从 Gateways 访问证书。但在使用 http://gateway-api.org/ 时,这不是必需的true
    higress-core.gateway.serviceAccount.create指定是否创建 ServiceAccount, 否则,使用默认值。true
    higress-core.gateway.serviceAccount.annotations指定需要添加到 ServiceAccount 上的注释。{}
    higress-core.gateway.serviceAccount.name指定要使用的 ServiceAccount 的名称。""
    higress-core.gateway.env指定 Gateway 使用的环境变量。{}
    higress-core.gateway.hostNetwork指定是否使用宿主机网络。false
    higress-core.gateway.labels指定应用于所有 gateway 资源的标签。{}
    higress-core.gateway.annotations指定要应用于所有 gateway 资源的注释。{}
    higress-core.gateway.podAnnotations.prometheus.io/port指定 Prometheus 监控的端口。15020
    higress-core.gateway.podAnnotations.prometheus.io/scrape指示 Prometheus 是否应该监控该 Pod 。如果该值为"true",则 Prometheus 将监控该 Pod ;如果该值为 "false" ,则不会监控该 Pod 。true
    higress-core.gateway.podAnnotations.prometheus.io/path指定 Prometheus 监控该 Pod 时,需要访问的 URL 路径。在这里设置为"/stats/prometheus"。/stats/prometheus
    higress-core.gateway.podAnnotations.sidecar.istio.io/inject指定是否启用 Istio Sidecar 模式。false
    higress-core.gateway.service.type指定 Service 的类型LoadBalancer
    higress-core.gateway.service.loadBalancerIP指定 LoadBalancer 的 IP 地址""
    higress-core.gateway.service.loadBalancerSourceRanges指定 LoadBalancer 允许的源 IP 范围。[]
    higress-core.gateway.service.annotations指定要应用到 Service 上的注释。{}
    higress-core.gateway.service.externalTrafficPolicy指定 Service 的外部流量策略。""
    higress-core.gateway.rollingMaxSurge指定滚动更新期间的最大扩容数量100%
    higress-core.gateway.rollingMaxUnavailable指定滚动更新期间的最大不可用数量。25%
    higress-core.gateway.resources.limits.cpu指定 gateway 容器的CPU请求资源限制。2000m
    higress-core.gateway.resources.limits.memory指定 gateway 容器的内存请求资源限制。2048Mi
    higress-core.gateway.resources.requests.cpu指定 gateway 容器的CPU请求资源。2000m
    higress-core.gateway.resources.requests.memory指定 gateway 容器的内存请求资源。2048Mi
    higress-core.gateway.autoscale.enabled指定是否启用 gateway Pod 自动缩放。false
    higress-core.gateway.autoscale.minReplicas允许的最小副本数。1
    higress-core.gateway.autoscale.maxReplicas允许的最大副本数。5
    higress-core.gateway.autoscale.targetCPUUtilizationPercentage表示 HPA 应该尝试将 Pod 的 CPU 利用率维持在什么水平。80
    higress-core.gateway.nodeSelector节点选择器,用于确定 gatyway 容器将部署在哪些节点上。{}
    higress-core.gateway.tolerations容忍度,用于允许 gateway 容器调度到具有指定污点的节点。[]
    higress-core.gateway.affinity亲和性,用于控制 gateway容器如何调度,使其与其他 Pod 或节点保持亲和或反亲和。{}
    higress-core.gateway.networkGateway用于指定网络网关的名称或 IP 地址。""

    Controller参数

    参数参数说明默认值
    higress-core.controller.replicasHigress Controller 的 pod 数量。1
    higress-core.controller.env指定容器所需的任何环境变量。{}
    higress-core.controller.labels指定部署 controller 容器的标签{}
    higress-core.controller.probe.httpGet.path容器的健康检查配置信息,使用 HTTP GET 请求检查容器的 /ready 路径/ready
    higress-core.controller.probe.httpGet.port指定健康检查配置端口。8888
    higress-core.controller.probe.initialDelaySeconds指定容器启动后首次进行健康检查的延迟时间。1
    higress-core.controller.probe.periodSeconds指定进行健康检查的时间间隔。3
    higress-core.controller.probe.timeoutSeconds指定等待健康检查响应的超时时间5
    higress-core.controller.imagePullSecrets指定用于拉取容器镜像的密钥信息[]
    higress-core.controller.rbac.create定义是否应该创建与此部署相关的 RBAC 规则。true
    higress-core.controller.serviceAccount.create指定是否应该创建 serviceAccount 。true
    higress-core.controller.serviceAccount.annotations指定要添加到 serviceAccount 的注释。{}
    higress-core.controller.serviceAccount.name指定要使用的 serviceAccount 的名称,如果未设置且 create 为 true ,则使用 fullname 模板生成名称。""
    higress-core.controller.podAnnotations指定要添加到 controller 容器的注释。{}
    higress-core.controller.podSecurityContext指定 Pod 的安全上下文。{}
    higress-core.controller.service.type指定 Service 的类型为 ClusterIP。ClusterIP
    higress-core.controller.securityContext指定 controller 容器的安全上下文。{}
    higress-core.controller.resources.requests.cpu分配给 controller 的 CPU 资源请求。500m
    higress-core.controller.resources.requests.memory分配给 controller 的内存资源请求。2048Mi
    higress-core.controller.resources.limits.cpu分配给 controller 的 CPU 资源请求限制。1000m
    higress-core.controller.resources.limits.memory分配给 controller 的内存资源请求限制。2048Mi
    higress-core.controller.nodeSelector用于指定 Pod 调度到特定节点的标签选择器{}
    higress-core.controller.tolerations用于指定 Pod 的容忍性,即容忍某些节点上的特定污点。[]
    higress-core.controller.affinity用于指定 Pod 的亲和性,即将 Pod 调度到特定节点或节点组。{}
    higress-core.controller.autoscaling.enabled指定是否启用 Pod 的自动缩放。false
    higress-core.controller.autoscaling.minReplicas指定自动缩放的最小 Pod 数量。1
    higress-core.autoscaling.maxReplicas指定自动缩放的最大 Pod 数量。5
    higress-core.autoscaling.targetCPUUtilizationPercentage指定自动缩放调整 Pod 数量的目标 CPU 利用率百分比。80

    Pilot参数

    参数参数说明默认值
    higress-core.pilot.autoscaleEnabled是否启用 Pilot 的自动伸缩。false
    higress-core.pilot.autoscaleMin自动伸缩时最小的副本数。1
    higress-core.pilot.autoscaleMax自动伸缩时最大的副本数。5
    higress-core.pilot.replicaCountPilot 的 pod 数量。1
    higress-core.pilot.rollingMaxSurge在进行滚动更新时,允许同时增加的 Pod 数量的最大比例。100%
    higress-core.pilot.rollingMaxUnavailable在进行滚动更新时,允许同时不可用的 Pod 数量的最大比例。25%
    higress-core.pilot.traceSampling指定应用程序的跟踪采样率,这里是1.0(即100%)。1
    higress-core.pilot.resources.requests.cpu分配给 pilot 的 CPU 资源请求。500m
    higress-core.pilot.resources.requests.memory分配给 pilot 的内存资源请求。2048Mi
    higress-core.pilot.env.PILOT_SCOPE_GATEWAY_TO_NAMESPACE如果设置为 true ,则使网关只能访问其所在的命名空间中的服务。true
    higress-core.pilot.env.PILOT_ENABLE_METADATA_EXCHANGE如果设置为 false ,则禁用与 Envoy 之间的元数据交换。false
    higress-core.pilot.env.PILOT_ENABLE_CROSS_CLUSTER_WORKLOAD_ENTRY如果设置为 false ,则禁用跨集群工作负载入口。false
    higress-core.pilot.env.VALIDATION_ENABLED如果设置为 false ,则禁用对配置文件的验证。false
    higress-core.pilot.cpu.targetAverageUtilization指定 Pod 应该尝试达到的 CPU 利用率百分比,以便触发自动缩放。例如,如果设置为80,则当 Pod 的 CPU 利用率达到80%时,将启动更多的 Pod 以处理更多的负载。80
    higress-core.pilot.enableProtocolSniffingForOutbound是否在出站流量上启用协议嗅探,这里是 true 。true
    higress-core.pilot.enableProtocolSniffingForInbound是否在入站流量上启用协议嗅探,这里是 true 。true
    higress-core.pilot.nodeSelector指定应该部署此应用程序的节点标签。{}
    higress-core.pilot.podAnnotations指定要添加到 Pod 的注释。{}
    higress-core.pilot.serviceAnnotations指定要添加到 Service 的注释。{}
    higress-core.pilot.jwksResolverExtraRootCA提供 PEM 格式的根证书,以便在解析 JWKS URI 时由 pilot 信任。""
    higress-core.pilot.configSource.subscribedResources指定配置源的来源,如果未指定,则使用默认的 MCP 。指定订阅的 Kubernetes 资源列表。[]
    higress-core.pilot.plugins指定要启用的插件列表。[]
    higress-core.pilot.keepaliveMaxServerConnectionAge限制 sidecar 与 pilot 连接的最长时间。30m
    higress-core.pilot.deploymentLabels为部署添加额外的标签。{}
    higress-core.pilot.configMap安装由values.yaml生成的 mesh config ,如果为 false ,则 Pilot 将使用默认值(默认情况下)或用户提供的值,如果为 false ,则 Pilot 将使用默认值(默认情况下)或用户提供的值true
    higress-core.pilot.podLabels为 Pod 添加额外的标签,以用于监控和日志记录配置。{}

    skywalking 参数

    参数参数说明默认值
    higress-core.skywalking.enabled是否启用 SkyWalkingfalse
    higress-core.skywalking.service.addressSkyWalking 服务地址,如果不指定则使用默认值~
    higress-core.skywalking.service.portSkyWalking 服务端口,默认为 1180011800

    控制台参数

    参数参数说明默认值
    higress-console.replicaCountHigress Console 的 pod 数量1
    higress-console.dnsPolicy指定 DNS 策略,这里为 ClusterFirst 。ClusterFirst
    higress-console.restartPolicy指定重启策略,这里指定为 Always 。Always
    higress-console.service.type指定控制台 service 类型。ClusterIP
    higress-console.domain对外用于访问 Higress Console 的域名。console.higress.io
    higress-console.resources.requests.cpu分配给 console 的 CPU 资源请求。250m
    higress-console.resources.requests.memory分配给 console 的内存资源请求。512Mi
    higress-console.web.login.prompt登录页面上显示的提示信息,默认为空。""
    higress-console.admin.username指定的用户名。admin
    higress-console.admin.displayName显示的用户名。Admin
    higress-console.admin.password若值不为空,则 admin 账号的密码将被配置为指定值。""
    higress-console.certmanager.enabled指定是否启用证书管理器。false
    higress-console.certmanager.replicasCertmanage pod 的数量。1
    higress-console.o11y.enabled若为 true,将同时安装可观测性套件(Grafana + Promethues)。false
    higress-console.o11y.grafana.replicasGrafana pod 的数量。1
    higress-console.o11y.grafana.storage分配给 Grafana 的存储类大小。1Gi
    higress-console.o11y.grafana.pvc.storageClassNameGrafana 的存储类名称。""
    higress-console.o11y.prometheus.replicasPrometheus pod 的数量。1
    higress-console.o11y.prometheus.storage分配给 prometheus 的存储类大小。1Gi
    higress-console.o11y.prometheus.pvc.storageClassNamePrometheus 的存储类名称。""
    higress-console.o11y.prometheus.resources.limits.cpu分配给 prometheus 的 CPU 资源限制。500m
    higress-console.o11y.prometheus.resources.limits.memory分配给 prometheus 的内存资源限制。2Gi
    higress-console.pvc.rwxSupportedRwxSupported 参数用于指示是否支持读写多个 Pod,即是否支持共享卷。如果该参数设置为 true,则表明支持共享卷,多个 Pod 可以同时挂载该 PVC,进行读写操作。如果设置为 false,则表明不支持共享卷,只有一个 Pod 可以挂载该 PVC 进行读写操作。true
    - + \ No newline at end of file diff --git a/zh-cn/docs/user/dubbo-http2rpc/index.html b/zh-cn/docs/user/dubbo-http2rpc/index.html index 413f64cdad..611c740526 100644 --- a/zh-cn/docs/user/dubbo-http2rpc/index.html +++ b/zh-cn/docs/user/dubbo-http2rpc/index.html @@ -14,13 +14,13 @@ - +

    HTTP转Dubbo 配置说明

    本文介绍了Http2Rpc这个自定义CRD的相关配置项。

    spec.dubbo

    字段类型说明
    servicethe dubbo interface namedubbo服务接口名例如:"com.alibaba.nacos.example.dubbo.service.DemoService"
    versionthe dubbo service versiondubbo服务版本号例如:"1.0.0"
    methodslist of spec.dubbo.methods每一项对应了一条方法映射规则

    spec.dubbo.methods

    字段类型说明
    groupstring方法名例:"dev"
    serviceMethodHTTP_METHOD_TYPE方法匹配规则例:"sayName"
    headersAttachstring需要透传的http headers1、空: 不设置表示不透传任何值;
    2、*: 表示透传所有headers;
    3、用英文逗号隔开需要透出的headers key: header-A,header-B,header-C,
    httpPathstring指定绑定serviceMethod的http-path例:"/dubbo/hello"
    paramslist of spec.dubbo.methods.params指定参数提取方式

    spec.dubbo.methods.params

    字段类型说明
    paramKeystring参数名称例:"p"
    paramSourcePARAM_SOURCE_TYPE参数来源"QUERY"
    paramTypestringDubbo方法入参的参数类型"java.lang.String"

    HTTP_METHOD_TYPE

    说明
    GEThttp GET method
    POSThttp POST method
    PUThttp PUT method
    DELETEhttp DELETE method
    PATCHhttp PATCH method

    PARAM_SOURCE_TYPE

    说明
    QUERYhttp url param
    HEADERhttp header
    PATHhttp url path
    BODYhttp request body
    - + \ No newline at end of file diff --git a/zh-cn/docs/user/dubbo/index.html b/zh-cn/docs/user/dubbo/index.html index 7ca2dcb79c..e3ae063dde 100644 --- a/zh-cn/docs/user/dubbo/index.html +++ b/zh-cn/docs/user/dubbo/index.html @@ -14,13 +14,13 @@ - +

    Higress 对接 Dubbo 服务

    Higress提供了从HTTP协议到Dubbo协议进行转换的功能,用户通过配置协议转换,可以将一个Dubbo服务以HTTP接口暴露出来,从而用HTTP请求实现对Dubbo接口的调用。本文将通过一个示例来介绍如何用Higress配置HTTP到Dubbo的协议转换。

    前提条件

    1. Higress目前支持的Dubbo框架的版本为2.x。若您使用Dubbo3.0,要求使用dubbo协议(目前暂不支持Triple协议)。
    2. 已安装Higress,并开启了对Istio CRD的支持,参考安装部署文档

    部署Dubbo服务

    您可以选用Naocs或者Zookeeper任意一种作为注册中心,部署一个Dubbo服务。具体可以参考以下文档:

    https://cn.dubbo.apache.org/zh-cn/overview/what/ecosystem/registry/nacos/

    https://cn.dubbo.apache.org/zh-cn/overview/what/ecosystem/registry/zookeeper/

    假设我们现在已经部署了如下一个Dubbo服务,其服务名为com.alibaba.nacos.example.dubbo.service.DemoService,并指定了该服务的version为“1.0.0”,group为“dev”,下面我们将介绍如何为该服务配置协议转换。

    package com.alibaba.nacos.example.dubbo.service;

    public interface DemoService {
    String sayName(String name);
    }

    通过Ingress转发请求到Dubbo服务

    Higress可以通过McpBridge来对接Nacos或者Zookeeper作为服务来源。这里我们以Nacos为例,假设Naocs的ip地址为192.xxx.xx.32,我们可以在K8s集群中apply以下资源来配置McpBridge

    apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    - domain: 192.xxx.xx.32
    nacosGroups:
    - DEFAULT_GROUP
    name: nacos-service-resource
    port: 8848
    type: nacos2

    通过McpBridge,我们可以直接从Nacos中发现Dubbo服务,并为其创建路由。

    接下来我们创建如下Ingress,从而创建一条指向Dubbo服务的HTTP路由:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/destination: providers:com.alibaba.nacos.example.dubbo.service.DemoService:1.0.0:dev.DEFAULT-GROUP.public.nacos
    higress.io/rpc-destination-name: httproute-http2rpc-demo
    name: httproute-http2rpc-demo-ingress
    namespace: higress-system
    spec:
    ingressClassName: higress
    rules:
    - http:
    paths:
    - backend:
    resource:
    apiGroup: networking.higress.io
    kind: McpBridge
    name: default
    path: /dubbo
    pathType: Prefix

    这样,path前缀为/dubbo的请求就会被路由到我们刚刚创建的Dubbo服务上。

    通过Higress自定义的CRD-Http2Rpc配置HTTP到Dubbo的协议转换规则

    经过上述步骤,我们已经通过Ingress将path前缀为/dubbo的请求路由到我们的Dubbo服务上。但光是这样是无法正常通信的,因为Dubbo服务使用的是定制的Dubbo协议,无法天然与HTTP协议进行兼容。因此接下来我们还要配置具体的HTTP到Dubbo的协议转换规则,从而实现用HTTP请求来调用Dubbo服务。

    apiVersion: networking.higress.io/v1
    kind: Http2Rpc
    metadata:
    name: httproute-http2rpc-demo
    namespace: higress-system
    spec:
    dubbo:
    service: com.alibaba.nacos.example.dubbo.service.DemoService
    version: 1.0.0
    group: dev
    methods:
    - serviceMethod: sayName
    headersAttach: "*"
    httpMethods:
    - "GET"
    httpPath: "/dubbo/hello"
    params:
    - paramKey: p
    paramSource: QUERY
    paramType: "java.lang.String"

    在以上Http2Rpc中,我们配置了将path为/dubbo/hello的HTTP请求转发到Dubbo服务com.alibaba.nacos.example.dubbo.service.DemoService:1.0.0:dev中,并调用其sayName方法,而该方法的参数则通过HTTP url中的的query参数p来指定。

    请求验证

    通过以上配置,我们就可以执行以下curl命令来调用这个dubbo服务了:

    $curl "localhost/dubbo/hello?p=abc" 
    {"result":"Service [name :demoService , port : 20880] sayName(\"abc\") : Hello,abc"}

    配置参考

    Http2Rpc的相关配置项参考HTTP转Dubbo配置说明

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/kruise-rollout/index.html b/zh-cn/docs/user/kruise-rollout/index.html index 5a1c955f7b..551d79c3c8 100644 --- a/zh-cn/docs/user/kruise-rollout/index.html +++ b/zh-cn/docs/user/kruise-rollout/index.html @@ -14,7 +14,7 @@ - + @@ -36,7 +36,7 @@ image

    测试来自安卓的流量是否路由到新版本,非安卓的流量是否路由到老版本。 image

    发布最后一批,完成全量发布。并测试所有流量是否路由到新版本。 image

    总结

    相比于传统人工手动方式,Higress & Kruise Rollouts提供了无侵入、自动化运维方式让应用发布丝滑般顺畅。开发者无需关注发布过程中如何调整Deployment、Ingress、Service等资源,只需声明并管理发布策略Rollouts资源即可,原生Deployment的滚动发布会自动实现为渐进式交付,让应用发布可批次、可灰度、可回滚,助力业务快速迭代发展同时,也提高了应用发布的稳定性和效率问题。

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/mcp-bridge/index.html b/zh-cn/docs/user/mcp-bridge/index.html index 71f6d5f197..8c85ff7544 100644 --- a/zh-cn/docs/user/mcp-bridge/index.html +++ b/zh-cn/docs/user/mcp-bridge/index.html @@ -14,13 +14,13 @@ - +

    Mcp Bridge 配置说明

    McpBridge 字段说明

    字段类型说明示例值是否必填
    registriesRegistryConfig 数组支持配置多个不同注册中心的服务来源[]

    RegistryConfig 字段说明

    字段类型说明示例值是否必填
    type字符串注册中心类型,可选项:nacos,nacos2,zookeeper,consul,eurekanacos2
    name字符串自定义的服务来源名称my-nacos
    domain字符串注册中心地址,可以是ip或域名192.168.1.2
    port整数注册中心访问端口8848
    zkServicesPath字符串数组使用zk时,填写服务注册的根路径,默认监听 /dubbo 和 /services,前者为dubbo 服务默认根路径,后者为SpringCloud服务默认根路径["/service-provider"]
    nacosNamespaceId字符串nacos命名空间idd8ac64f3-xxxx-xxxx-xxxx-47a814ecf358
    nacosGroups字符串数组nacos服务分组列表["DEFAULT_GROUP"]
    nacosAccessKey字符串nacos需要认证时填写的ak信息xxxx
    nacosSecretKey字符串nacos需要认证时填写的sk信息xxxx
    nacosRefreshInterval整数nacos需要认证时填写的服务刷新间隔纳秒数30000000000(30秒)
    consulDatacenter字符串consul需要认证时填写的数据中心名称dc1
    consulServiceTag字符串consul需要认证时填写的服务标签过滤higress
    consulRefreshInterval整数consul需要认证时填写的服务刷新间隔纳秒数30000000000(30秒)
    authSecretName字符串服务发现认证信息 Secret 名称, 具体看下面说明higress-nacos-auth

    authSecretName 字段说明

    服务发现来源认证信息保存在 higress-system 命名空间下对应 Secret 下 ,现在支持 nacos 和 consul 服务发现。

    nacos 认证信息包含用户名和密码, consul 认证信息包含认证 token, 具体 Secret 配置样例如下:

    nacos 认证

    apiVersion: v1
    data:
    nacosPassword: aGlncmVzcw==
    nacosUsername: aGlncmVzcw==
    kind: Secret
    metadata:
    name: higress-nacos-auth
    namespace: higress-system
    type: Opaque

    consul 认证

    apiVersion: v1
    data:
    consulToken: NGFkZDE2NjUtNTM5NC03YzU1LTIzYTUtNzA4MDZkNTFiYzQy
    kind: Secret
    metadata:
    name: higress-consul-auth
    namespace: higress-system
    type: Opaque
    - + \ No newline at end of file diff --git a/zh-cn/docs/user/nacos-route/index.html b/zh-cn/docs/user/nacos-route/index.html index ad753ed460..e111d28e13 100644 --- a/zh-cn/docs/user/nacos-route/index.html +++ b/zh-cn/docs/user/nacos-route/index.html @@ -14,14 +14,14 @@ - +

    配置 Ingress 转发给注册在 Nacos 的服务

    配置服务来源

    apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    # 定义一个名为 “production” 的服务来源
    - name: production
    # 注册中心类型是 Nacos 2.x,支持 gRPC 协议
    type: nacos2
    # 注册中心的访问地址,可以是域名或者IP
    domain: 192.xxx.xx.32
    # 注册中心的访问端口,Nacos 默认都是 8848
    port: 8848
    # Nacos 命名空间 ID
    nacosNamespaceId: d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358
    # Nacos 服务分组
    nacosGroups:
    - DEFAULT_GROUP
    # 定义一个名为 “uat” 的服务来源
    - name: uat
    # 注册中心类型是 Nacos 1.x,只支持 HTTP 协议
    type: nacos
    # 注册中心的访问地址,可以是域名或者IP
    domain: 192.xxx.xx.31
    # 注册中心的访问端口,Nacos 默认都是 8848
    port: 8848
    # Nacos 命名空间 ID
    nacosNamespaceId: 98ac6df3-xxxx-xxxx-xxxx-ab98115dfde4
    # Nacos 服务分组
    nacosGroups:
    - DEFAULT_GROUP

    通过McpBridge资源配置了两个服务来源,分别取名 “production”和“uat”,需要注意的是 Higress 对接 Nacos 同时支持 HTTP 和 gRPC 两种协议,建议将 Nacos 升级到 2.x 版本,这样可以在上述配置的 type 中指定 “nacos2” 使用 gRPC 协议,从而更快速地感知到服务变化,并消耗更少的 Nacos 服务端资源。 基于 McpBridge 中的 registries 数组配置,Higress 可以轻松对接多个且不同类型的服务来源(Nacos/Zookeeper/Eureka/Consul/...),这里对于 Nacos 类型的服务来源,支持配置多个不同命名空间,从而实现不同命名空间的微服务可以共用一个网关,降低自建微服务网关的资源成本开销。

    配置 Ingress

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/destination: service-provider.DEFAULT-GROUP.d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358.nacos
    name: demo
    namespace: default
    spec:
    rules:
    - http:
    paths:
    - backend:
    resource:
    apiGroup: networking.higress.io
    kind: McpBridge
    name: default
    path: /
    pathType: Prefix

    和常见的 Ingress 在 backend 中定义 service 不同,这里基于 Ingress 的 resource backend 将上面定义服务来源的 McpBridge 进行关联。并通过注解higress.io/destination指定路由最终要转发到的目标服务。

    对于 Nacos 来源的服务,这里的目标服务格式为:“服务名称.服务分组.命名空间ID.nacos”,注意这里需要遵循 DNS 域名格式,因此服务分组中的下划线'_'被转换成了横杠'-'。

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/nginx-ingress-migrate/index.html b/zh-cn/docs/user/nginx-ingress-migrate/index.html index 6e99a2ae7f..fb35826600 100644 --- a/zh-cn/docs/user/nginx-ingress-migrate/index.html +++ b/zh-cn/docs/user/nginx-ingress-migrate/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/docs/user/nginx-ingress/index.html b/zh-cn/docs/user/nginx-ingress/index.html index c175f4c979..5fb8000f72 100644 --- a/zh-cn/docs/user/nginx-ingress/index.html +++ b/zh-cn/docs/user/nginx-ingress/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/docs/user/opensergo-gray/index.html b/zh-cn/docs/user/opensergo-gray/index.html index cea9b3c322..546a4ae624 100644 --- a/zh-cn/docs/user/opensergo-gray/index.html +++ b/zh-cn/docs/user/opensergo-gray/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/docs/user/prometheus/index.html b/zh-cn/docs/user/prometheus/index.html index 67e4220867..a6dc342d58 100644 --- a/zh-cn/docs/user/prometheus/index.html +++ b/zh-cn/docs/user/prometheus/index.html @@ -14,13 +14,13 @@ - +

    基于 Prometheus 实现入口流量观测

    使用 Higress Console 的内置监控套件

    Higress Console 内置了一套基于 Prometheus + Grafana 的监控套件,但默认不会安装。在使用 Helm 安装 Higress 时,可以通过在命令行中添加 --set higress-console.o11y.enabled=true 参数启用这一监控套件。

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io --set higress-console.o11y.enabled=true

    注意:在安装到标准 K8s 集群(即未指定 global.local=trueglobal.kind=true 参数)时,监控系统所配置的 PersistentVolumeClaim 默认使用 ReadWriteMany 访问模式。如果目标 K8s 集群不支持这一访问模式,则可以在命令行中额外添加 --set higress-console.pvc.rwxSupported=false 参数来将访问模式切换为 ReadyWriteOnce

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io --set higress-console.o11y.enabled=true --set higress-console.pvc.rwxSupported=false

    完成安装后,在浏览器中访问 Higress Console,点击左侧导航栏“监控面板”,页面右侧就会展示出系统内置的监控面板。

    image

    使用独立部署的监控套件

    Higress 的数据面和控制面组件均通过 API 对外暴露了一系列的 Metrics 指标。只需要为 Prometheus 添加相应指标采集配置,并在 Grafana 中配置监控面板就可以监控 Higress 的内部运行情况了。

    在正式开始配置之前,请先在浏览器中打开 Higress Console,并在左侧导航栏切换至“监控面板”页面。在未安装内置监控套件时,页面上就会展示出外置监控面板 URL 配置页面和外部系统的配置法。

    image

    按照界面下方给出的方法更新 Prometheus 和 Grafana 中的配置,然后把 Grafana 看板的页面 URL 填入上方输入框中并保存。随后页面会自动刷新,右侧就会出现配置好的外置监控面板。

    image

    如果需要更新监控面板的 URL,则可点击页面左上角的“重新配置”按钮。

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/quickstart/index.html b/zh-cn/docs/user/quickstart/index.html index e9aab482c8..d8c0459252 100644 --- a/zh-cn/docs/user/quickstart/index.html +++ b/zh-cn/docs/user/quickstart/index.html @@ -14,14 +14,14 @@ - +

    快速开始

    环境一:在 K8s 中使用

    阶段一:安装

    场景一:在标准 K8s 集群中使用

    Helm 安装命令

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set higress-console.domain=console.higress.io

    获取 Higress Gateway 的 LoadBalancer IP,并记录下来。后续可以通过该 IP 的 80 和 443 端口访问 Higress Gateway。

    kubectl get svc -n higress-system higress-gateway -o jsonpath='{.status.loadBalancer.ingress[0].ip}'

    场景二:在本地 K8s环境中使用

    以下步骤适用于所有在本地启动 K8s 集群进行验证的场景。如果您本地已经配置好了一个测试集群,可以直接跳转到第三步安装 Higress。

    第一步:安装 kubectl & kind

    MacOS:

    # for Intel Macs
    [ $(uname -m) = x86_64 ] && curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/amd64/kubectl"
    [ $(uname -m) = x86_64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.18.0/kind-darwin-amd64
    # for Apple Silicon Macs (M1/M2), but higress image does not support ARM yet.
    # [ $(uname -m) = arm64 ] && curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/darwin/arm64/kubectl"
    # [ $(uname -m) = arm64 ] && curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.18.0/kind-darwin-arm64
    chmod +x ./kubectl ./kind
    sudo mv ./kubectl ./kind /usr/local/bin

    Windows 中使用 PowerShell:

    下载 kubectl v1.27.1kind v0.18.0

    如果你本地安装了 curl 工具,可直接执行以下命令:

    curl.exe -LO "https://dl.k8s.io/release/v1.27.1/bin/windows/amd64/kubectl.exe"
    curl.exe -Lo kind-windows-amd64.exe https://kind.sigs.k8s.io/dl/v0.18.0/kind-windows-amd64

    注:若要获知 kubectl 的最新稳定版本(例如用于脚本编写等场景),可查看 https://dl.k8s.io/release/stable.txt 的内容.

    然后将下载下来的 kind-windows-amd64 或者 kind-windows-amd64.exe 重命名为 kind.exe,并将 kubectl.exekind.exe 移动到 PATH 环境变量所包含的路径下。

    Linux:

    curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/amd64/kubectl"
    curl -Lo ./kind https://kind.sigs.k8s.io/dl/v0.18.0/kind-linux-amd64
    chmod +x ./kubectl ./kind
    sudo mv ./kubectl ./kind /usr/local/bin
    第二步:创建并启用 kind

    首先创建一个集群配置文件: cluster.conf

    # cluster.conf
    kind: Cluster
    apiVersion: kind.x-k8s.io/v1alpha4
    nodes:
    - role: control-plane
    kubeadmConfigPatches:
    - |
    kind: InitConfiguration
    nodeRegistration:
    kubeletExtraArgs:
    node-labels: "ingress-ready=true"
    extraPortMappings:
    - containerPort: 80
    hostPort: 80
    protocol: TCP
    - containerPort: 443
    hostPort: 443
    protocol: TCP

    Mac & Linux 系统执行:

    kind create cluster --name higress --config=cluster.conf
    kubectl config use-context kind-higress

    Windows 系统执行:

    kind.exe create cluster --name higress --config=cluster.conf
    kubectl.exe config use-context kind-higress

    备注

    上述配置是为了将本地(127.0.0.1)的80和443端口用于Higress访问,如果希望在本地使用 LoadBalancer IP 进行访问,可以参考Kind文档https://kind.sigs.k8s.io/docs/user/loadbalancer/ 提供的能力予以支持。

    第三步:安装 Higress

    本地安装开关: --set global.kind=true; 为避免歧义,后面会调整属性名称为:--set global.local=true

    helm repo add higress.io https://higress.io/helm-charts
    helm install higress -n higress-system higress.io/higress --create-namespace --render-subchart-notes --set global.local=true --set higress-console.o11y.enabled=false --set higress-console.domain=console.higress.io

    若要启用 Higress 内置的套件,可参阅安装部署文档。

    安装完成后,通过本地的 80 和 443 端口即可访问本地集群内的 Higress Gateway。

    注:如果您使用的是本地现存的 K8s 集群,那么可能需要先执行下方命令将 K8s 集群内的端口映射出来,然后再尝试访问本地端口。

    kubectl port-forward service/higress-gateway -n higress-system 80:80 443:443

    阶段二:配置

    假设在 default 命名空间下已经部署了一个名为 foo 的服务,而我们希望创建一个对应 http://foo.bar.com/foo 的路由指向该服务。

    如果需要的话,各位可以使用下方 YAML 来创建对应的测试服务。

    kind: Pod
    apiVersion: v1
    metadata:
    name: foo-app
    labels:
    app: foo
    spec:
    containers:
    - name: foo-app
    image: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/http-echo:0.2.4-alpine
    args:
    - "-text=foo"
    ---
    kind: Service
    apiVersion: v1
    metadata:
    name: foo-service
    spec:
    selector:
    app: foo
    ports:
    # Default port used by the image
    - port: 5678

    方法一:使用 Higress Console 进行配置

    编辑本机的 hosts 文件,将console.higress.io域名指向该 Higress Gateway 的 IP(在标准 K8s 集群中即前面获取的 LoadBalancer IP。在本地集群中可直接使用 127.0.0.1)。

    GatewayIP console.higress.io

    在浏览器中输入http://console.higress.io。首次访问时需要先初始化管理员账号。

    image

    初始化完成后,界面会自动跳转至登录页面。请使用前面设置的用户名密码登录 Higress 控制台。

    image

    点击左侧“域名管理”导航栏,然后点击页面右侧的“创建域名”按钮。按照下图所示内容填写表单并点击“确定”按钮。

    image

    点击左侧“路由管理”导航栏,然后点击页面右侧的“创建路由”按钮。按照下图片所示内容填写表单并点击“确定”按钮。

    image

    方法二:使用 Ingress CRD 进行配置

    使用下方 YAML 来创建我们需要的路由配置。

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    name: foo
    spec:
    ingressClassName: higress
    rules:
    - host: foo.bar.com
    http:
    paths:
    - pathType: Prefix
    path: "/foo"
    backend:
    service:
    name: foo-service
    port:
    number: 5678

    阶段三:请求验证

    执行以下命令,验证测试路由可以正常工作:

    # should output "foo"
    curl http://GatewayIP/foo -H 'host: foo.bar.com'

    环境二:脱离 K8s 在 Docker Compose 中使用

    阶段一:安装

    安装命令一:使用独立部署的 Nacos

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -a -c nacos://192.168.0.1:8848 --nacos-username=nacos --nacos-password=nacos

    请将 192.168.0.1 替换为 Nacos 服务器的 IP(如果 Nacos 部署在本机,请不要使用如 localhost127.0.0.1 的 Loopback 地址),并按需调整 --nacos-username--nacos-password 的取值。如果 Nacos 服务未开启认证功能,则可以移除这两个参数。

    安装命令二:使用 Higress 内置 Nacos

    curl -fsSL https://higress.io/standalone/get-higress.sh | bash -s -- -a --use-builtin-nacos

    注:Windows 系统下可以使用 Cygwin、Git Bash 等类 Unix Shell 中执行上述命令。

    阶段二:配置

    在浏览器中输入http://127.0.0.1:8080 进入 Higress 控制台。首次访问时需要先初始化管理员账号。

    image

    初始化完成后,界面会自动跳转至登录页面。请使用前面设置的用户名密码登录 Higress 控制台。

    image

    点击左侧“服务来源”导航栏,然后点击页面右侧的“创建服务来源”按钮。按照下图所示内容填写表单并点击“确定”按钮。

    image

    点击左侧“域名管理”导航栏,然后点击页面右侧的“创建域名”按钮。按照下图所示内容填写表单并点击“确定”按钮。

    image

    点击左侧“路由管理”导航栏,然后点击页面右侧的“创建路由”按钮。按照下图片所示内容填写表单并点击“确定”按钮。

    image

    阶段三:请求验证

    执行以下命令,验证测试路由可以正常工作:

    # should output a JSON object containing request data 
    curl http://localhost/get?foo=bar -H 'host: foo.bar.com'
    - + \ No newline at end of file diff --git a/zh-cn/docs/user/sentinel/index.html b/zh-cn/docs/user/sentinel/index.html index ea51d56264..b1f74d01d0 100644 --- a/zh-cn/docs/user/sentinel/index.html +++ b/zh-cn/docs/user/sentinel/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/docs/user/spring-cloud/index.html b/zh-cn/docs/user/spring-cloud/index.html index 4113d83d81..ab39e6f915 100644 --- a/zh-cn/docs/user/spring-cloud/index.html +++ b/zh-cn/docs/user/spring-cloud/index.html @@ -14,13 +14,13 @@ - +

    实现 SpringCloud 服务发现和路由

    使用 Nacos 做注册中心

    应用配置具体参考Nacos Spring Cloud 快速开始进行应用配置

    不指定命名空间

    如果 application.properties 中没有指定 Nacos 命名空间,例如:

    server.port=8080
    spring.application.name=my-service

    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848

    则 Higress 的 McpBridge 中亦无需指定命名空间:

    apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    # 定义一个名为 my-nacos 的服务来源
    - name: my-nacos
    # 注册中心类型是 Nacos 2.x,支持 gRPC 协议
    type: nacos2
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口,Nacos 默认都是 8848
    port: 8848
    # Nacos 服务分组
    nacosGroups:
    - DEFAULT_GROUP

    配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/destination: my-service.DEFAULT-GROUP.public.nacos
    name: demo
    namespace: default
    spec:
    rules:
    - http:
    paths:
    - backend:
    resource:
    apiGroup: networking.higress.io
    kind: McpBridge
    name: default
    path: /api
    pathType: Prefix

    注意这里通过注解higress.io/destination指定路由最终要转发到的目标服务。

    对于 Nacos 来源的服务,这里的目标服务格式为:“服务名称.服务分组.命名空间ID.nacos”,注意这里需要遵循 DNS 域名格式,因此服务分组中的下划线'_'被转换成了横杠'-'。命名空间未指定时,这里默认值为"public"。

    指定命名空间、服务分组等信息

    如果 application.properties 中指定了 Nacos 命名空间,服务分组等信息,例如:

    server.port=8080
    spring.application.name=my-service

    spring.cloud.nacos.discovery.server-addr=127.0.0.1:8848
    spring.cloud.nacos.discovery.namespace=d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358
    spring.cloud.nacos.discovery.group=custom-group

    则 Higress 的 McpBridge 做相应配置即可

    apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    # 定义一个名为 my-nacos 的服务来源
    - name: my-nacos
    # 注册中心类型是 Nacos 2.x,支持 gRPC 协议
    type: nacos2
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口,Nacos 默认都是 8848
    port: 8848
    # Nacos 命名空间 ID
    nacosNamespaceId: d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358
    # Nacos 服务分组
    nacosGroups:
    - custom-group

    配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/destination: my-service.custom-group.d8ac64f3-xxxx-xxxx-xxxx-47a814ecf358.nacos
    name: demo
    namespace: default
    spec:
    rules:
    - http:
    paths:
    - backend:
    resource:
    apiGroup: networking.higress.io
    kind: McpBridge
    name: default
    path: /api
    pathType: Prefix

    使用 ZooKeeper 做注册中心

    使用 Zookeeper 做注册中心时,注意必须配置spring.cloud.zookeeper.discovery.preferIpAddress=true,否则注册到注册中心中到地址为主机名称,而不是IP。

    不指定注册根路径

    如果 application.properties 中未指定注册根路径信息,例如:

    spring.application.name=my-service
    spring.cloud.zookeeper.connect-string=127.0.0.1:2181
    spring.cloud.zookeeper.discovery.preferIpAddress=true
    spring.cloud.zookeeper.discovery.enabled=true
    spring.cloud.zookeeper.discovery.register=true

    则 Higress 的 McpBridge 中亦无需指定zkServicePath:

    apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    # 定义一个名为 my-zk 的服务来源
    - name: my-zk
    # 注册中心类型是 ZooKeeper
    type: zookeeper
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口
    port: 2181

    配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/destination: my-service.services.zookeeper
    name: demo
    namespace: default
    spec:
    rules:
    - http:
    paths:
    - backend:
    resource:
    apiGroup: networking.higress.io
    kind: McpBridge
    name: default
    path: /api
    pathType: Prefix

    注意对于 ZooKeeper 来源的服务,这里的目标服务格式为:"服务名称.服务注册根路径.zookeeper",SpringCloud 在未指定服务注册根路径的情况下,根路径默认是"services"

    指定注册根路径

    如果 application.properties 中指定了注册根路径信息,例如:

    spring.application.name=my-service
    spring.cloud.zookeeper.connect-string=127.0.0.1:2181
    spring.cloud.zookeeper.discovery.preferIpAddress=true
    spring.cloud.zookeeper.discovery.enabled=true
    spring.cloud.zookeeper.discovery.register=true
    spring.cloud.zookeeper.discovery.root=my-services-root

    则 Higress 的 McpBridge 中亦需指定zkServicePath:

    apiVersion: networking.higress.io/v1
    kind: McpBridge
    metadata:
    name: default
    namespace: higress-system
    spec:
    registries:
    # 定义一个名为 my-zk 的服务来源
    - name: my-zk
    # 注册中心类型是 ZooKeeper
    type: zookeeper
    # 注册中心的访问地址,可以是域名或者IP
    domain: 127.0.0.1
    # 注册中心的访问端口
    port: 2181
    # 对应 spring.cloud.zookeeper.discovery.root 配置字段
    zkServicePath:
    - my-services-root

    配置 Ingress 转发到这个服务(假设/api前缀的路由都转发给这个服务)需要做如下配置:

    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
    annotations:
    higress.io/destination: my-service.my-services-root.zookeeper
    name: demo
    namespace: default
    spec:
    rules:
    - http:
    paths:
    - backend:
    resource:
    apiGroup: networking.higress.io
    kind: McpBridge
    name: default
    path: /api
    pathType: Prefix

    注意如果 spring.cloud.zookeeper.discovery.root 中包含了下划线,需要被替换为横杠,因为目标服务整体格式需要满足 DNS 域名规范

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/waf/index.html b/zh-cn/docs/user/waf/index.html index bfa5d16761..88f7fed638 100644 --- a/zh-cn/docs/user/waf/index.html +++ b/zh-cn/docs/user/waf/index.html @@ -14,7 +14,7 @@ - + @@ -30,7 +30,7 @@ image

    整体防护能力评估

    GoTestWAF是一款API和OWASP攻击模拟工具,支持包括REST、GraphQL、gRPC、WebSockets、SOAP、XMLRPC等多种API协议,旨在评估Web应用安全解决方案,如API安全代理、Web应用防火墙(WAF)、IPS、API网关等。

    该工具使用放置在HTTP请求正文、标头、URL参数等不同部分的不同编码的有效负载生成恶意请求,涵盖了常见的各种攻击类型。

    多种攻击测试结果如下图所示,图中结果表明WAF插件能够有效检测各种攻击类型的非法请求。 image

    WAF防护功能整体得分如下,高于gotestwaf提供的benchmark(benchmark中paranoia表示防护等级,数值越大,防护等级越高,正确拦截与误拦截的请求数均会增加),测试结果表明WAF插件具有较好的防护能力。 image

    - + \ No newline at end of file diff --git a/zh-cn/docs/user/wasm-go/index.html b/zh-cn/docs/user/wasm-go/index.html index 7c2d7f2e1a..2764eb3bf7 100644 --- a/zh-cn/docs/user/wasm-go/index.html +++ b/zh-cn/docs/user/wasm-go/index.html @@ -14,13 +14,13 @@ - +

    使用 GO 语言开发 WASM 插件

    一、工具准备

    需要先安装 Golang 和 TinyGo 两个程序

    1. Golang

    (要求 1.18 版本以上)
    官方指引链接:https://go.dev/doc/install

    Windows

    1. 下载安装文件:https://go.dev/dl/go1.19.windows-amd64.msi
    2. 打开下载好的安装文件直接安装,默认会安装到 Program FilesProgram Files (x86) 目录
    3. 安装完成后,使用键盘上的快捷键“Win+R”打开运行窗口,在运行窗口中输入“cmd”点击确定即可打开命令窗口,输入命令:go version,输出当前安装的版本,表明安装成功

    MacOS

    1. 下载安装文件:https://go.dev/dl/go1.19.darwin-amd64.pkg
    2. 打开下载好的安装文件直接安装,默认会安装到/usr/local/go目录
    3. 打开终端命令行工具,输入命令:go version,输出当前安装的版本,表明安装成功

    Linux

    1. 下载安装文件:https://go.dev/dl/go1.19.linux-amd64.tar.gz
    2. 执行下列命令进行安装:
    rm -rf /usr/local/go && tar -C /usr/local -xzf go1.19.linux-amd64.tar.gz
    export PATH=$PATH:/usr/local/go/bin
    1. 执行 go version,输出当前安装的版本,表明安装成功

    2. TinyGo

    (要求 0.28.1 版本以上)
    官方指引链接:https://tinygo.org/getting-started/install/

    Windows

    1. 下载安装文件:https://github.com/tinygo-org/tinygo/releases/download/v0.28.1/tinygo0.28.1.windows-amd64.zip
    2. 解压安装文件到指定目录
    3. 如果安装解压后的目录为C:\tinygo,则需要将C:\tinygo\bin添加到环境变量PATH中,例如通过在命令窗口中输入 set 命令设置
    set PATH=%PATH%;"C:\tinygo\bin";
    1. 在命令窗口执行命令 tinygo version,输出当前安装的版本,表明安装成功

    MacOS

    1. 下载压缩包并解压
    wget https://github.com/tinygo-org/tinygo/releases/download/v0.28.1/tinygo0.28.1.darwin-amd64.tar.gz
    tar -zxf tinygo0.28.1.darwin-amd64.tar.gz
    1. 如果安装解压后的目录为/tmp,则需要将/tmp/tinygo/bin添加到环境变量PATH中:
    export PATH=/tmp/tinygo/bin:$PATH
    1. 在终端执行 tinygo version,输出当前安装的版本,表明安装成功

    Linux

    以 Ubuntu 下 amd64 架构为例,其他系统请参考官方指引链接

    1. 下载 DEB 文件,并安装
    wget https://github.com/tinygo-org/tinygo/releases/download/v0.28.1/tinygo_0.28.1_amd64.deb
    sudo dpkg -i tinygo_0.28.1_amd64.deb
    export PATH=$PATH:/usr/local/bin
    1. 在终端执行 tinygo version,输出当前安装的版本,表明安装成功

    二、编写插件

    1. 初始化工程目录

    1. 新建一个工程目录文件,例如wasm-demo-go
    2. 在所建目录下执行以下命令,进行 Go 工程初始化
    go mod init wasm-demo-go
    1. 国内环境可能需要设置下载依赖包的代理
    go env -w GOPROXY=https://proxy.golang.com.cn,direct
    1. 下载构建插件的依赖
    go get github.com/tetratelabs/proxy-wasm-go-sdk
    go get github.com/alibaba/higress/plugins/wasm-go@main
    go get github.com/tidwall/gjson

    2. 编写 main.go 文件

    下面是一个简单示例,实现了在插件配置mockEnable: true时直接返回hello world应答;未做插件配置,或者设置mockEnable: false时给原始请求添加 hello: world请求头。更多例子请参考本文第四节。

    注意:在网关控制台中的插件配置为 yaml 格式,下发给插件时将自动转换为 json 格式,所以例子中的 parseConfig 可以直接从 json 中解析配置

    package main

    import (
    "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
    "github.com/tidwall/gjson"
    )

    func main() {
    wrapper.SetCtx(
    // 插件名称
    "my-plugin",
    // 为解析插件配置,设置自定义函数
    wrapper.ParseConfigBy(parseConfig),
    // 为处理请求头,设置自定义函数
    wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
    )
    }

    // 自定义插件配置
    type MyConfig struct {
    mockEnable bool
    }

    // 在控制台插件配置中填写的yaml配置会自动转换为json,此处直接从json这个参数里解析配置即可
    func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
    // 解析出配置,更新到config中
    config.mockEnable = json.Get("mockEnable").Bool()
    return nil
    }

    func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
    proxywasm.AddHttpRequestHeader("hello", "world")
    if config.mockEnable {
    proxywasm.SendHttpResponse(200, nil, []byte("hello world"), -1)
    }
    return types.ActionContinue
    }

    HTTP 处理挂载点

    上面示例代码中通过 wrapper.ProcessRequestHeadersBy将自定义函数 onHttpRequestHeaders用于HTTP 请求头处理阶段处理请求。除此之外,还可以通过下面方式,设置其他阶段的自定义处理函数

    HTTP 处理阶段触发时机挂载方法
    HTTP 请求头处理阶段网关接收到客户端发送来的请求头数据时wrapper.ProcessRequestHeadersBy
    HTTP 请求 Body 处理阶段网关接收到客户端发送来的请求 Body 数据时wrapper.ProcessRequestBodyBy
    HTTP 应答头处理阶段网关接收到后端服务响应的应答头数据时wrapper.ProcessResponseHeadersBy
    HTTP 应答 Body 处理阶段网关接收到后端服务响应的应答 Body 数据时wrapper.ProcessResponseBodyBy

    工具方法

    上面示例代码中的 proxywasm.AddHttpRequestHeaderproxywasm.SendHttpResponse是插件 SDK 提供的两个工具方法,主要的工具方法见下表:

    分类方法名称用途可以生效的
    HTTP 处理阶段
    请求头处理GetHttpRequestHeaders获取客户端请求的全部请求头HTTP 请求头处理阶段
    ReplaceHttpRequestHeaders替换客户端请求的全部请求头HTTP 请求头处理阶段
    GetHttpRequestHeader获取客户端请求的指定请求头HTTP 请求头处理阶段
    RemoveHttpRequestHeader移除客户端请求的指定请求头HTTP 请求头处理阶段
    ReplaceHttpRequestHeader替换客户端请求的指定请求头HTTP 请求头处理阶段
    AddHttpRequestHeader新增一个客户端请求头HTTP 请求头处理阶段
    请求 Body 处理GetHttpRequestBody获取客户端请求 BodyHTTP 请求 Body 处理阶段
    AppendHttpRequestBody将指定的字节串附加到客户端请求 Body 末尾HTTP 请求 Body 处理阶段
    PrependHttpRequestBody将指定的字节串附加到客户端请求 Body 的开头HTTP 请求 Body 处理阶段
    ReplaceHttpRequestBody替换客户端请求 BodyHTTP 请求 Body 处理阶段
    应答头处理GetHttpResponseHeaders获取后端响应的全部应答头HTTP 应答头处理阶段
    ReplaceHttpResponseHeaders替换后端响应的全部应答头HTTP 应答头处理阶段
    GetHttpResponseHeader获取后端响应的指定应答头HTTP 应答头处理阶段
    RemoveHttpResponseHeader移除后端响应的指定应答头HTTP 应答头处理阶段
    ReplaceHttpResponseHeader替换后端响应的指定应答头HTTP 应答头处理阶段
    AddHttpResponseHeader新增一个后端响应头HTTP 应答头处理阶段
    应答 Body 处理GetHttpResponseBody获取客户端请求 BodyHTTP 应答 Body 处理阶段
    AppendHttpResponseBody将指定的字节串附加到后端响应 Body 末尾HTTP 应答 Body 处理阶段
    PrependHttpResponseBody将指定的字节串附加到后端响应 Body 的开头HTTP 应答 Body 处理阶段
    ReplaceHttpResponseBody替换后端响应 BodyHTTP 应答 Body 处理阶段
    HTTP 调用DispatchHttpCall发送一个 HTTP 请求-
    GetHttpCallResponseHeaders获取 DispatchHttpCall 请求响应的应答头-
    GetHttpCallResponseBody获取 DispatchHttpCall 请求响应的应答 Body-
    GetHttpCallResponseTrailers获取 DispatchHttpCall 请求响应的应答 Trailer-
    直接响应SendHttpResponse直接返回一个特定的 HTTP 应答-
    流程恢复ResumeHttpRequest恢复先前被暂停的请求处理流程-
    ResumeHttpResponse恢复先前被暂停的应答处理流程-

    3. 编译生成 WASM 文件

    执行以下命令

    go mod tidy
    tinygo build -o main.wasm -scheduler=none -target=wasi -gc=custom -tags='custommalloc nottinygc_finalizer' ./main.go

    编译成功会在当前目录下创建文件 main.wasm。这个文件在下面本地调试的例子中也会被用到。
    在使用云原生网关插件市场的自定义插件功能时,直接上传该文件即可。

    三、本地调试

    工具准备

    安装Docker

    使用 docker compose 启动验证

    1. 进入在编写插件时创建的目录,例如wasm-demo目录,确认该目录下已经编译生成了main.wasm文件。
    2. 在目录下创建文件docker-compose.yaml,内容如下:
    version: '3.7'
    services:
    envoy:
    image: higress-registry.cn-hangzhou.cr.aliyuncs.com/higress/envoy:1.20
    depends_on:
    - httpbin
    networks:
    - wasmtest
    ports:
    - "10000:10000"
    volumes:
    - ./envoy.yaml:/etc/envoy/envoy.yaml
    - ./main.wasm:/etc/envoy/main.wasm

    httpbin:
    image: kennethreitz/httpbin:latest
    networks:
    - wasmtest
    ports:
    - "12345:80"

    networks:
    wasmtest: {}
    1. 继续在该目录下创建文件envoy.yaml,内容如下:
    admin:
    address:
    socket_address:
    protocol: TCP
    address: 0.0.0.0
    port_value: 9901
    static_resources:
    listeners:
    - name: listener_0
    address:
    socket_address:
    protocol: TCP
    address: 0.0.0.0
    port_value: 10000
    filter_chains:
    - filters:
    - name: envoy.filters.network.http_connection_manager
    typed_config:
    "@type": type.googleapis.com/envoy.extensions.filters.network.http_connection_manager.v3.HttpConnectionManager
    scheme_header_transformation:
    scheme_to_overwrite: https
    stat_prefix: ingress_http
    route_config:
    name: local_route
    virtual_hosts:
    - name: local_service
    domains: ["*"]
    routes:
    - match:
    prefix: "/"
    route:
    cluster: httpbin
    http_filters:
    - name: wasmdemo
    typed_config:
    "@type": type.googleapis.com/udpa.type.v1.TypedStruct
    type_url: type.googleapis.com/envoy.extensions.filters.http.wasm.v3.Wasm
    value:
    config:
    name: wasmdemo
    vm_config:
    runtime: envoy.wasm.runtime.v8
    code:
    local:
    filename: /etc/envoy/main.wasm
    configuration:
    "@type": "type.googleapis.com/google.protobuf.StringValue"
    value: |
    {
    "mockEnable": false
    }
    - name: envoy.filters.http.router
    clusters:
    - name: httpbin
    connect_timeout: 30s
    type: LOGICAL_DNS
    # Comment out the following line to test on v6 networks
    dns_lookup_family: V4_ONLY
    lb_policy: ROUND_ROBIN
    load_assignment:
    cluster_name: httpbin
    endpoints:
    - lb_endpoints:
    - endpoint:
    address:
    socket_address:
    address: httpbin
    port_value: 80
    1. 执行以下命令启动docker compose。
    docker compose up

    功能验证

    1. WASM功能验证

    使用curl直接访问httpbin,可以看到不经过网关时的请求头内容,如下:

    curl http://127.0.0.1:12345/get

    {
    "args": {},
    "headers": {
    "Accept": "*/*",
    "Host": "127.0.0.1:12345",
    "User-Agent": "curl/7.79.1"
    },
    "origin": "172.18.0.1",
    "url": "http://127.0.0.1:12345/get"
    }

    使用curl通过网关访问httpbin,可以看到经过网关处理后的请求头的内容,如下:

    curl http://127.0.0.1:10000/get

    {
    "args": {},
    "headers": {
    "Accept": "*/*",
    "Hello": "world",
    "Host": "127.0.0.1:10000",
    "Original-Host": "127.0.0.1:10000",
    "Req-Start-Time": "1681269273896",
    "User-Agent": "curl/7.79.1",
    "X-Envoy-Expected-Rq-Timeout-Ms": "15000"
    },
    "origin": "172.18.0.3",
    "url": "https://127.0.0.1:10000/get"
    }

    此时上文编写插件的功能已经生效了,加入了hello: world请求头。

    1. 插件配置修改验证

    修改envoy.yaml,将mockEnable配置修改为true。

      configuration:
    "@type": "type.googleapis.com/google.protobuf.StringValue"
    value: |
    {
    "mockEnable": true
    }

    使用curl通过网关访问httpbin,可以看到经过网关处理后的请求头的内容,如下:

    curl http://127.0.0.1:10000/get

    hello world

    说明插件配置修改生效,开启了mock应答直接返回了hello world。

    更多示例

    无配置插件

    插件无需配置时,直接定义空结构体即可

    package main

    import (
    "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
    )

    func main() {
    wrapper.SetCtx(
    "hello-world",
    wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
    )
    }

    type MyConfig struct {}

    func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
    proxywasm.SendHttpResponse(200, nil, []byte("hello world"), -1)
    return types.ActionContinue
    }

    在插件中请求外部服务

    目前仅支持 http 调用,支持访问在网关控制台中设置了服务来源的 Nacos、K8s 服务,以及固定地址或 DNS 来源的服务。请注意,无法直接使用net/http库中的 HTTP client,必须使用如下例中封装的 HTTP client。
    下面例子中,在配置解析阶段解析服务类型,生成对应的 HTTP client ;在请求头处理阶段根据配置的请求路径访问对应服务,解析应答头,然后再设置在原始的请求头中。

    package main

    import (
    "errors"
    "net/http"
    "strings"
    "github.com/alibaba/higress/plugins/wasm-go/pkg/wrapper"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm"
    "github.com/tetratelabs/proxy-wasm-go-sdk/proxywasm/types"
    "github.com/tidwall/gjson"
    )

    func main() {
    wrapper.SetCtx(
    "http-call",
    wrapper.ParseConfigBy(parseConfig),
    wrapper.ProcessRequestHeadersBy(onHttpRequestHeaders),
    )
    }

    type MyConfig struct {
    // 用于发起HTTP调用client
    client wrapper.HttpClient
    // 请求url
    requestPath string
    // 根据这个key取出调用服务的应答头对应字段,再设置到原始请求的请求头,key为此配置项
    tokenHeader string
    }

    func parseConfig(json gjson.Result, config *MyConfig, log wrapper.Log) error {
    config.tokenHeader = json.Get("tokenHeader").String()
    if config.tokenHeader == "" {
    return errors.New("missing tokenHeader in config")
    }
    config.requestPath = json.Get("requestPath").String()
    if config.requestPath == "" {
    return errors.New("missing requestPath in config")
    }
    serviceSource := json.Get("serviceSource").String()
    // 固定地址和dns类型的serviceName,为控制台中创建服务时指定
    // nacos和k8s来源的serviceName,即服务注册时指定的原始名称
    serviceName := json.Get("serviceName").String()
    servicePort := json.Get("servicePort").Int()
    if serviceName == "" || servicePort == 0 {
    return errors.New("invalid service config")
    }
    switch serviceSource {
    case "k8s":
    namespace := json.Get("namespace").String()
    config.client = wrapper.NewClusterClient(wrapper.K8sCluster{
    ServiceName: serviceName,
    Namespace: namespace,
    Port: servicePort,
    })
    return nil
    case "nacos":
    namespace := json.Get("namespace").String()
    config.client = wrapper.NewClusterClient(wrapper.NacosCluster{
    ServiceName: serviceName,
    NamespaceID: namespace,
    Port: servicePort,
    })
    return nil
    case "ip":
    config.client = wrapper.NewClusterClient(wrapper.StaticIpCluster{
    ServiceName: serviceName,
    Port: servicePort,
    })
    return nil
    case "dns":
    domain := json.Get("domain").String()
    config.client = wrapper.NewClusterClient(wrapper.DnsCluster{
    ServiceName: serviceName,
    Port: servicePort,
    Domain: domain,
    })
    return nil
    default:
    return errors.New("unknown service source: " + serviceSource)
    }
    }

    func onHttpRequestHeaders(ctx wrapper.HttpContext, config MyConfig, log wrapper.Log) types.Action {
    // 使用client的Get方法发起HTTP Get调用,此处省略了timeout参数,默认超时时间500毫秒
    config.client.Get(config.requestPath, nil,
    // 回调函数,将在响应异步返回时被执行
    func(statusCode int, responseHeaders http.Header, responseBody []byte) {
    // 请求没有返回200状态码,进行处理
    if statusCode != http.StatusOK {
    log.Errorf("http call failed, status: %d", statusCode)
    proxywasm.SendHttpResponse(http.StatusInternalServerError, nil,
    []byte("http call failed"), -1)
    return
    }
    // 打印响应的HTTP状态码和应答body
    log.Infof("get status: %d, response body: %s", statusCode, responseBody)
    // 从应答头中解析token字段设置到原始请求头中
    token := responseHeaders.Get(config.tokenHeader)
    if token != "" {
    proxywasm.AddHttpRequestHeader(config.tokenHeader, token)
    }
    // 恢复原始请求流程,继续往下处理,才能正常转发给后端服务
    proxywasm.ResumeHttpRequest()
    })
    // 需要等待异步回调完成,返回Pause状态,可以被ResumeHttpRequest恢复
    return types.ActionPause
    }
    - + \ No newline at end of file diff --git a/zh-cn/docs/user/wasm-image-spec/index.html b/zh-cn/docs/user/wasm-image-spec/index.html index 0da772674b..2bebcf2e2e 100644 --- a/zh-cn/docs/user/wasm-image-spec/index.html +++ b/zh-cn/docs/user/wasm-image-spec/index.html @@ -14,13 +14,13 @@ - +

    Wasm 插件镜像规范

    1. 概述

    本规范旨在定义对 Higress Wasm Plugin 镜像的内容和构建方式。在编写时,笔者参考了 Wasm Image Specification

    2. 镜像结构

    每个镜像必须基于 scratch 使用 OCI 格式规范进行构建,且可包含以下文件:

    • spec.yaml:必要。插件的元数据文件。其内容格式请见第 3 节。
    • README.md:必要。插件的用法说明文件。使用 Markdown 格式。语言可使用英文或中文。
    • README_{lang}.md:可选。插件用法说明文件的翻译版本。使用 Markdown 格式。lang 的取值为 ZHEN
    • icon.png:可选。插件的图标文件。也可以选择在 spec.yaml 中指定图标 URL。二者同时存在时,系统会使用包内部的图标文件用于展示。
    • plugin.wasm:必要。插件的二进制文件。

    镜像的每一层只可包含一个文件。

    除 plugin.wasm 所在层外,其它层需根据文件名设置 media type:

    • spec.yaml:application/vnd.module.wasm.spec.v1+yaml
    • README.md:application/vnd.module.wasm.doc.v1+markdown
    • README_{lang}.md:application/vnd.module.wasm.doc.v1.{lang}+markdown
    • icon.png:application/vnd.module.wasm.icon.v1+png

    plugin.wasm 文件必须放置于镜像的最后一层,且该层应使用 application/vnd.oci.image.layer.v1.tar+gzip 作为 media type。

    3. 元数据文件格式

    本节以 basic-auth 插件的元数据信息为例,介绍元数据文件 spec.yaml 的格式。

    apiVersion: 1.0.0  # 本文件所使用的格式版本。目前固定为 1.0.0
    info:
    category: auth # 插件类型。可选值有:auth(认证鉴权)、security(安全防护)、protocol(协议转换)、flow-control(流量控制)、flow-monitor(流量观测)、custom(自定义)
    name: basic-auth/v1 # 插件名称。这是插件的唯一标识。建议在尾部追加类似"/v1"的版本号,以便应对后续不兼容升级的场景
    title: Basic Auth # 显示名称,支持国际化
    description: 本插件实现了基于 HTTP Basic Auth 标准进行认证鉴权的功能。 # 功能描述,支持国际化
    x-description-i18n: # 上面 description 字段的国际化内容。所有支持国际化的字段均可使用"x-{name}-i18n"的方式添加国际化内容
    en-US: This plugin implements an authentication function based on HTTP Basic Auth standard.
    iconUrl: https://img.alicdn.com/imgextra/i1/O1CN01I7WjVs1K33EQjInid_!!6000000001107-2-tps-960-290.png # 可选,插件的图标文件 URL。
    version: 1.0.0 # 版本号
    contact: # 联系信息
    name: Higress Team
    url: http://higress.io/
    email: admin@higress.io
    spec:
    phase: AUTHN # 运行阶段。取值请参考 https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/#PluginPhase
    priority: 0 # 阶段内的运行优先级。取值请参考 https://istio.io/latest/docs/reference/config/proxy_extensions/wasm-plugin/#WasmPlugin
    configSchema: # 插件运行配置的数据模型,目前仅支持使用 OpenAPI 3.0.0 标准中的 Schema 格式进行定义
    openAPIV3Schema: # 以下内容的数据格式请参考 https://openapi.apifox.cn/#schema-%E5%AF%B9%E8%B1%A1 。部分显示用字段支持国际化。
    type: object
    properties:
    consumers:
    type: array
    scope: GLOBAL # 配置项作用范围。可选值:GLOBAL(全局配置)、INSTANCE(实例级配置,即在关联路由、域名时的配置)、ALL(全局、实例皆可配置)。可空。缺省值为 INSTANCE。
    title: 调用方列表
    x-title-i18n:
    en-US: Consumer List
    description: 服务调用方列表,用于对请求进行认证
    x-description-i18n:
    en-US: List of service consumers which will be used in request authentication
    items:
    type: object
    properties:
    name:
    type: string
    title: 名称
    x-title-i18n:
    en-US: Name
    description: 该调用方的名称
    x-description-i18n:
    en-US: The name of the consumer
    # 数据校验场景参照 JSON Schema Validation Spec 实现
    # https://json-schema.org/draft/2020-12/json-schema-validation.html
    # 目前支持以下字段:
    # - maximum
    # - minimum
    # - maxLength
    # - minLength
    # - pattern
    # - maxItems
    # - minItems
    # - required
    minLength: 6 # 最小长度,用于数据校验
    maxLength: 256 # 最大长度,用于数据校验
    pattern: "^$" # 正则表达式,用于数据校验
    example:
    - consumer1
    credential:
    type: string
    title: 访问凭证
    x-title-i18n:
    en-US: Credential
    description: 该调用方的访问凭证
    x-description-i18n:
    en-US: The credential of the consumer
    example:
    - admin:123456
    required:
    - name
    - credential
    allow:
    type: array
    title: 授权访问的调用方列表
    x-title-i18n:
    en-US: Allowed Consumers
    description: 对于匹配上述条件的请求,允许访问的调用方列表
    x-description-i18n:
    en-US: Consumers to be allowed for matched requests
    items:
    type: string
    example:
    - consumer1
    required:
    - allow
    - consumers
    example:
    consumers:
    - name: consumer1
    credential: admin:123456
    - name: consumer2
    credential: guest:abc
    allow:
    - consumer2

    4. 镜像构建方式

    1. 在 Higress 项目目录内启动构建用容器
    GO_VERSION="1.19"
    TINYGO_VERSION="0.25.0"
    ORAS_VERSION="1.0.0"
    PLUGIN_NAME="hello-world"
    BUILDER_IMAGE="higress-registry.cn-hangzhou.cr.aliyuncs.com/plugins/wasm-go-builder:go${GO_VERSION}-tinygo${TINYGO_VERSION}-oras${ORAS_VERSION}"
    docker run -v ${PWD}:/workspace -e PLUGIN_NAME=${PLUGIN_NAME} -it --rm /bin/bash
    1. 在容器中构建 Wasm 文件
    cd /workspace/plugins/wasm-go/extensions/${PLUGIN_NAME}
    go mod tidy
    tinygo build -o ./plugin.wasm -scheduler=none -target=wasi ./main.go
    1. 构建并推送 OCI 镜像
    tar czvf plugin.tar.gz plugin.wasm
    IMAGE_REGISTRY_SERVICE=docker.io
    IMAGE_REPOSITORY="${IMAGE_REGISTRY_SERVICE}/plugins/${PLUGIN_NAME}"
    IMAGE_TAG="v0.0.1"
    oras login ${IMAGE_REGISTRY_SERVICE}
    oras push ${IMAGE_REPOSITORY}:${IMAGE_TAG} \
    ./spec.yaml:application/vnd.module.wasm.spec.v1+yaml \
    ./README.md:application/vnd.module.wasm.doc.v1+markdown \
    ./README_EN.md:application/vnd.module.wasm.doc.v1.en+markdown \
    ./plugin.tar.gz:application/vnd.oci.image.layer.v1.tar+gzip

    5. 附录

    5.1 各插件类型的缺省图标

    - + \ No newline at end of file diff --git a/zh-cn/home/community/index.html b/zh-cn/home/community/index.html index 4e503d9d7c..7dffeae74e 100644 --- a/zh-cn/home/community/index.html +++ b/zh-cn/home/community/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/home/feature/index.html b/zh-cn/home/feature/index.html index 25e4d9f3c9..bf9a2d5e2e 100644 --- a/zh-cn/home/feature/index.html +++ b/zh-cn/home/feature/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/home/introduction/index.html b/zh-cn/home/introduction/index.html index c3a361dd70..a32adc5ba2 100644 --- a/zh-cn/home/introduction/index.html +++ b/zh-cn/home/introduction/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/home/msemap/index.html b/zh-cn/home/msemap/index.html index b24d30d94f..a23ce614ae 100644 --- a/zh-cn/home/msemap/index.html +++ b/zh-cn/home/msemap/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/home/top/index.html b/zh-cn/home/top/index.html index b98e1559a3..fe9cef0b7b 100644 --- a/zh-cn/home/top/index.html +++ b/zh-cn/home/top/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/home/users/index.html b/zh-cn/home/users/index.html index 17ec241904..7c2f54fc86 100644 --- a/zh-cn/home/users/index.html +++ b/zh-cn/home/users/index.html @@ -14,13 +14,13 @@ - +
    - + \ No newline at end of file diff --git a/zh-cn/index.html b/zh-cn/index.html index 9be8318246..4e229206a1 100644 --- a/zh-cn/index.html +++ b/zh-cn/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file diff --git a/zh-cn/markdown-page/index.html b/zh-cn/markdown-page/index.html index 308580ecb3..0300b26a7e 100644 --- a/zh-cn/markdown-page/index.html +++ b/zh-cn/markdown-page/index.html @@ -14,13 +14,13 @@ - + - + \ No newline at end of file