前言
最近了解到很多团队会用到Kubernetes来统一管理应用. 当然. 我们公司也不例外。所以后续会对 各种类型的应用上 Kubernetes 做一些分享。
统一部署Kubernetes的好处.
可以对所有应用统一管理. 融灾. 迁移...
举个🌰. 当我们在阿里云深圳区A的k8s集群因为各种原因出现服务故障 无法正常提供服务后. 我们可以快速在 上海区 或者 其他云例如 Azure 购买服务器然后通过ansible脚本一键部署k8s集群. 在最快的时间内恢复服务.
实施
SPA 应用因为完全没有涉及到node 跟 服务端. 我们都不需要用到 Service
, 只需要一个 Ingress 跟 CDN 存储, 我们可以直接将每个版本的资源上传到CDN. 然后通过 Ingress 转发到 CDN 到每个版本.
我们先创建一个 helm 项目.
helm 是一个k8s的项目管理工具. 这里我们不讨论. google关于这个的资料.
helm create frontendexamples
### 因为我们只需要用到 ingress 所以删除其他多余到服务.
rm deployment.yaml service.yaml serviceaccount.yaml
然后编辑 ingress.yaml 成我们需要到样子. 根据前端到静态资源来转发并且根据版本号做缓存
{{- $ingress := .Values.ingress }}
{{- $top := . -}}
{{- if $ingress.enabled }}
---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
name: {{ include "frontendexamples.fullname" . }}-{{ $ingress.name }}
labels:
{{- include "frontendexamples.labels" . | nindent 4 }}
{{- with $ingress.annotations }}
annotations:
kubernetes.io/ingress.class: nginx
nginx.ingress.kubernetes.io/configuration-snippet: |
### 默认重定向到首页
return 302 $scheme://$host/index.html;
nginx.ingress.kubernetes.io/server-snippet: |
location = / {
return 302 $scheme://$host/index.html;
}
{{- $cdnHost := $top.Values.cdnHost -}}
{{- $cdnPrefix := $top.Values.cdnPrefix -}}
{{- range $top.Values.htmlList -}}
location = {{ . }} {
rewrite ^(.*)$ /{{ $cdnPrefix }}{{ . }} break;
proxy_pass {{ $cdnHost }};
proxy_buffering on;
proxy_buffer_size 128k;
proxy_buffers 100 128k;
proxy_cache auth_cache;
proxy_cache_key {{ $cdnPrefix }};
proxy_cache_valid 200 1d;
proxy_cache_use_stale error timeout invalid_header updating
http_500 http_502 http_503 http_504;
}
{{- end -}}
{{- toYaml . | nindent 4 }}
{{- end }}
spec:
rules:
{{- range $ingress.hosts }}
- host: {{ .host | quote }}
http:
paths:
{{- range .paths }}
- path: {{ . }}
backend:
serviceName: none
servicePort: 80
{{- end }}
{{- end }}
{{- end }}
然后. 我们写一个前端编译然后生成对应静态资源文件(index.html)的部署bash脚本.
用来生成一份helm values文件
# Default values for frontendexamples.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
cdnHost: "https://bg-stage.wkcoding.com/"
cdnPrefix: "wixland/pro/2031"
htmlList:
- /index.html
build -> upload cdn -> generate html values
scripts/deploy.sh
#!/bin/bash
set -o errexit
set -o nounset
set -o pipefail
### get project dir
SOURCE="${BASH_SOURCE[0]}"
while [ -h "$SOURCE" ]; do
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
SOURCE="$(readlink "$SOURCE")"
[[ $SOURCE != /* ]] && SOURCE="$DIR/$SOURCE"
done
DIR="$( cd -P "$( dirname "$SOURCE" )" >/dev/null 2>&1 && pwd )"
readonly PROJECT_ROOT="$(dirname $DIR)"
readonly BUILDOUT_DIR=${BUILDOUT_DIR:-"$PROJECT_ROOT/build"}
readonly BUCKET_HOST=${BUCKET_HOST:-""}
readonly APPLICATION_NAME=${APPLICATION_NAME:-"frontendexamples"}
readonly RESOURCES_PREFIX=${RESOURCES_PREFIX:-"wixland/pro"}
readonly BUCKET=${BUCKET:-"bp-stage"}
readonly QINIU_AK=${QINIU_AK:-""}
readonly QINIU_SK=${QINIU_SK:-""}
cd $PROJECT_ROOT
VERSION=""
### application version
get_current_version() {
if [[ -z "$VERSION" ]]; then
echo -e "Enter version:" >&2
read -r VERSION
fi
echo $VERSION;
#echo $(date +%Y%m%d%H%M%S)
}
### build code
build() {
echo "building..."
version=${1:-""}
appVersion=${version} appResourcesPrefix=${RESOURCES_PREFIX} cdnHost=${BUCKET_HOST} yarn build
}
### upload builded code to qiniu cdn
upload() {
echo "uploading..."
version=${1:-""}
/Users/albert/code/github/qiniu-uploader/bin/qiniu-upload.js -r 1 -es 1000000 \
--verbose -b ${BUCKET} \
-p "${RESOURCES_PREFIX}/${version}" \
--base ./build --ak ${QINIU_AK} --sk ${QINIU_SK} 'build/**'
}
### Auto install [qiniu2uploader](https://github.com/work4fun/qiniu-uploader)
### An small resume upload qiniu tools
dectect_autoinstall_qiniu2uploader() {
if ! [ -x "$(command -v qiniu-upload)" ]; then
yarn global add -g qiniu2uploader
fi
}
dectect_autoinstall_qiniu2uploader
version=$(get_current_version)
build $version
upload $version
### Generate helm values.
### Examples:
### cdnHost: "http://bg-stage.wkcoding.com/"
### cdnPrefix: "wixland/pro/20000"
### htmlList:
### - /index.html
###
htmlList=""
for html in $(find "$BUILDOUT_DIR" -type f -name "*.html")
do
### Replace string
### ${content/search/replace}
html=${html/$BUILDOUT_DIR/''}
htmlList="- $html
$htmlList
"
done
cat << EOF > "$PROJECT_ROOT/docker/$APPLICATION_NAME/html.yaml"
# Default values for $APPLICATION_NAME.
# This is a YAML-formatted file.
# Declare variables to be passed into your templates.
cdnHost: "https:$BUCKET_HOST"
cdnPrefix: "$RESOURCES_PREFIX/$version"
htmlList:
$htmlList
EOF
### deploy with helm
helm upgrade $APPLICATION_NAME ./docker/$APPLICATION_NAME --install --values ./docker/$APPLICATION_NAME/html.yaml
上面都完成后我们只需要运行. 就可以完成部署了.
bash ./scripts/deploy.sh
缺点
- 依赖 ingress-nginx
- 依赖单点cdn存储. 如果cdn挂了集群也挂了.
- 缺少对cdn的监控
后续
- 实现多cdn上传
- 实现cdn心跳检测. 自动切换主/备 CDN
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。