首先這標題有點繞,我先解釋下:
Vue
路由history
模式打包的應用程式(也就是build後的產物);k8s
nginx-ingress
上做下域名二級目錄代理,轉發到該靜態目錄;這就是本文的背景,相信也是很多開發/運維同學的需求;
由上:
#我們靜態服務目錄是,/cso/
https://static.chinacloudapi.cn/cso/
#靜態服務下檔案的url是
https://static.chinacloudapi.cn/cso/static/js/manifest.967d8a794130980087be.js
然後:
#我們部署的域名是:
http://test.mysite.com/cso/
#同樣,對應以上靜態服務檔案的url是:
http://test.mysite.com/cso/static/js/manifest.967d8a794130980087be.js
好了需求清楚了, 我們轉發二級目錄就是 /cso/
,我們一一來看怎麼實現。
1、在入口檔案index.html檔案中新增
<meta base="/xxx/">
2、設定Vue History的路由模式(我這裡還是vue2.x)
export default new Router({
mode: 'history',
base: '/cso/',
routes: [
...
3、在config/index.js檔案修改build屬性下面的assetsPublicPath: '/xxx/'(用Cli3搭建的專案,應該是在vue.config.js檔案修改publicPath: '/xxx/');
...
build: {
index: path.resolve(__dirname, '../dist/index.html'),
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
// assetsPublicPath: '/', //預設的
assetsPublicPath: '/cso/', //改為
...
4、存取驗證:
成功;
location ~* /cso {
root html/cso;
index index.html index.htm;
try_files $uri $uri/ /index.html;
}
這就是大家比較熟悉的history
模式必配的try_files
,原理是:
轉發靜態assets
location ~* /cso.*\.(gif|jpg|jpeg|png|bmp|swf|css|js|eot|svg|ttf|woff|woff2|properties|json)$ {
proxy_http_version 1.1;
proxy_pass https://static.chinacloudapi.cn;
}
轉發document
location ~* /cso {
proxy_http_version 1.1;
add_header Cache-Control 'no-store, no-cache';
rewrite ^ /cso/index.html break;
proxy_pass https://static.chinacloudapi.cn;
}
這裡設定兩個功能location,其實是參考try_files的原理實現的;
同時,這種設定方式也適用於解決很多想把第三方程式的UI(Hangfire等)掛載到二級域名時,靜態檔案404的問題;
說真的,用慣nginx原生設定後,在nginx-ingress稍微設定有一點點難度的規則我就想哭(主要確實不太熟);
configuration-snippet方式:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: my-custom-snippet
namespace: cso-site
annotations:
nginx.ingress.kubernetes.io/configuration-snippet: |
location ~* /cso.*\.(gif|jpg|jpeg|png|bmp|swf|css|js|eot|svg|ttf|woff|woff2|properties|json)$ {
proxy_http_version 1.1;
proxy_pass https://static.chinacloudapi.cn;
}
location ~* /cso {
proxy_http_version 1.1;
add_header Cache-Control 'no-store, no-cache';
rewrite ^ /cso/index.html break;
proxy_pass https://static.chinacloudapi.cn;
}
spec:
ingressClassName: nginx
rules:
- host: test.mysite.com
defaultBackend:
service:
name: cso-site-svc
port:
number: 80
tls:
- hosts:
- test.mysite.com
secretName: tls-secret
這種方式就比較簡單了,就直接設定支援nginx原生語法,但它也是有限制的具體參考檔案;
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/upstream-vhost: "static.chinacloudapi.cn"
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/rewrite-target: /cso/index.html
name: slz-cso-ui-doc
namespace: cso-site
spec:
rules:
- host: test.mysite.com
http:
paths:
- path: /cso/(.*)
pathType: Prefix
backend:
service:
name: cso-site
port:
number: 443
defaultBackend:
service:
name: cso-site
port:
number: 80
tls:
- hosts:
- test.mysite.com
secretName: tls-secret
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/backend-protocol: "HTTPS"
nginx.ingress.kubernetes.io/upstream-vhost: "static.chinacloudapi.cn"
nginx.ingress.kubernetes.io/rewrite-target: /cso/$1$2$3
nginx.ingress.kubernetes.io/use-regex: "true"
name: slz-cso-ui-static
namespace: cso-site
spec:
rules:
- host: test.mysite.com
http:
paths:
- path: /cso/(.*)(\.)(gif|jpg|jpeg|png|bmp|swf|css|js|eot|svg|ttf|woff|woff2|properties|json)$
pathType: Prefix
backend:
service:
name: cso-site
port:
number: 443
defaultBackend:
service:
name: cso-site
port:
number: 80
tls:
- hosts:
- test.mysite.com
secretName: tls-secret
我們來看看生成的nginx規則:
這是我抽取核心部分的規則,可以看到翻譯成原生寫法是規則生成正確的;
k8s nginx-ingress設定稍微複雜點的規則真的很痛苦;
設定ingress時在不是特別熟的情況下跟我一樣先寫原生nginx,再翻譯成ingress是個不錯的方法;
水完, 歡迎討論。