這是一個關於 Egg.js 應用上雲☁️的示例,筆者所在的大前端團隊的已應用於生產。前端
CI/CD
& DevOps
& GitOps
& HPA
等這裏暫不作討論,由於每個點篇幅都很長。node
可直接作實驗(文章寫的再好,不如提供一個上雲示例)git
GitHub: k8s-eggjs->點我github
GitHub: k8s-eggjsweb
GitHub: k8s-eggjsdocker
這個示例,簡單的提供了兩個接口:npm
/api/posts
json
curl -X POST http://localhost:7001/api/posts --data '{"title":"post1", "content": "post1 content"}' --header 'Content-Type:application/json; charset=UTF-8'
api/topics
api
curl -X POST http://localhost:7001/api/topics --data '{"title":"topic1", "content": "topic1 content"}' --header 'Content-Type:application/json; charset=UTF-8'
筆者也把這個項目部署到了微信
(示例已提供,可直接作實驗)
package.json
這裏簡單調整爲:
"start": "egg-scripts start --workers=1 --title=egg-server-k8s-eggjs-promethues",
最好是單進程啓動,應用容器的編排徹底交給 kubernetes。
文件位於 docker/Dockerfile.prod
FROM node:15-alpine RUN ln -sf /usr/share/zoneinfo/Asia/ShangHai /etc/localtime RUN echo "Asia/Shanghai" > /etc/timezone COPY package.json /app/dependencies/package.json COPY yarn.lock /app/dependencies/yarn.lock RUN cd /app/dependencies \ && yarn install --frozen-lockfile --registry=https://registry.npm.taobao.org \ && yarn cache clean \ && mkdir /app/egg \ && ln -s /app/dependencies/node_modules /app/egg/node_modules COPY ./ /app/egg/ WORKDIR /app/egg EXPOSE 7001 CMD npm run start
構建Image
docker build -f docker/Dockerfile.prod -t k8s-eggjs-promethues:1.0.0 . --no-cache
打個 tag
,筆者試驗鏡像是放在阿里雲的(公司有本身的私有倉庫)
docker tag k8s-eggjs-promethues:1.0.0 registry.cn-shenzhen.aliyuncs.com/hacker-linner/k8s-eggjs-promethues:1.0.0
推送到阿里雲
docker push registry.cn-shenzhen.aliyuncs.com/hacker-linner/k8s-eggjs-promethues:1.0.0
(示例項目已提供,可直接作實驗)
生成部署 Chart
mkdir k8s-helm-charts && cd k8s-helm-charts helm create k8seggjs
咱們複製一份 k8seggjs/values.yaml
到外層與 k8seggjs
文件夾同級(k8s-helm-charts/values.yaml
)。
k8s-helm-charts/values.yaml
作以下修改:
replicaCount: 3 # 部署副本我用3個實例作負載均衡,保證服務可用 image: repository: registry.cn-shenzhen.aliyuncs.com/hacker-linner/k8s-eggjs-promethues # 鏡像變爲剛上傳 pullPolicy: Always # 鏡像拉取策略可直接用默認`IfNotPresent` # apiPort,metricsPort 默認模板沒有, # 這裏我對 template 裏面的 ingress.yaml service.yaml deployment.yaml 文件作了相應改動 service: type: ClusterIP apiPort: 7001 # 這個 API 服務的端口 metricsPort: 7777 # 這個是 prometheus 所需的 metrics 端口 # Ingress Controller,根據你的環境決定,我這裏用的是 traefik ingress: enabled: true annotations: ingress.kubernetes.io/ssl-redirect: "true" ingress.kubernetes.io/proxy-body-size: "0" kubernetes.io/ingress.class: "traefik" traefik.ingress.kubernetes.io/router.tls: "true" traefik.ingress.kubernetes.io/router.entrypoints: websecure hosts: - host: k8seggjs.hacker-linner.com paths: - / tls: - secretName: hacker-linner-cert-tls hosts: # 作資源限制,防止內存泄漏,交給 K8S 殺掉而後重啓,保證服務可用 resources: limits: cpu: 100m memory: 128Mi requests: cpu: 100m memory: 128Mi
建立部署 Namespace
kubectl create ns k8seggjs
使用 Helm 部署
helm install k8seggjs ./k8seggjs -f values.yaml -n k8seggjs # 卸載:helm uninstall k8seggjs -n k8seggjs
RBAC 設置
apiVersion: rbac.authorization.k8s.io/v1 kind: RoleList items: - apiVersion: rbac.authorization.k8s.io/v1 kind: Role metadata: name: prometheus-k8s-k8seggjs namespace: k8seggjs rules: - apiGroups: - "" resources: - services - endpoints - pods verbs: - get - list - watch --- apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBindingList items: - apiVersion: rbac.authorization.k8s.io/v1 kind: RoleBinding metadata: name: prometheus-k8s-k8seggjs namespace: k8seggjs roleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: prometheus-k8s-k8seggjs subjects: - kind: ServiceAccount name: prometheus-k8s namespace: monitoring
指標 Service 設置
apiVersion: v1 kind: Service metadata: namespace: k8seggjs name: k8seggjs-metrics labels: k8s-app: k8seggjs-metrics annotations: prometheus.io/scrape: 'true' prometheus.io/scheme: http prometheus.io/path: /metrics prometheus.io/port: "7777" spec: selector: app.kubernetes.io/name: k8seggjs ports: - name: k8seggjs-metrics port: 7777 targetPort: 7777 protocol: TCP
ServiceMonitor 設置
apiVersion: monitoring.coreos.com/v1 kind: ServiceMonitor metadata: name: k8seggjs namespace: monitoring spec: endpoints: - bearerTokenFile: /var/run/secrets/kubernetes.io/serviceaccount/token interval: 5s port: k8seggjs-metrics jobLabel: k8s-app namespaceSelector: matchNames: - k8seggjs selector: matchLabels: k8s-app: k8seggjs-metrics
應用
kubectl apply -f ServiceMonitor.yaml
egg-exporter,Egg.js 的 Prometheus 指標收集插件,附帶 Grafana 看板。
egg-prometheus,Prometheus plugin for Egg.js。
示例項目的指標收集就是用的這個。
dashboard-metrics.json
,完整的面板 json。來自於egg-exporter。筆者這裏作了 metrics
前綴的調整。
config.exporter = { scrapePort: 7777, scrapePath: '/metrics', prefix: 'k8seggjs_', defaultLabels: { stage: process.env.NODE_ENV }, };
咱們導入 json
文件進行 Grafana
面板建立
修改面板 Variables
$stage
k8seggjs_nodejs_version_info{worker="app"}
/.*stage="([^"]*).*/
$appname
k8seggjs_nodejs_version_info{worker="app"}
/.*app="([^"]*).*/
$node
k8seggjs_nodejs_version_info{worker="app"}
/.*instance="([^"]*).*/
最終效果
個人微信: