前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >EggJS 云原生应用硬核实战(Kubernetes+Traefik+Helm+Prometheus+Grafana)

EggJS 云原生应用硬核实战(Kubernetes+Traefik+Helm+Prometheus+Grafana)

作者头像
为少
发布2021-05-27 19:04:07
6450
发布2021-05-27 19:04:07
举报
文章被收录于专栏:黑客下午茶黑客下午茶

介绍

这是一个关于 Egg.js 应用上云☁️的示例,笔者所在的大前端团队的已应用于生产。

CI/CD & DevOps & GitOps & HPA 等这里暂不做讨论,因为每一个点篇幅都很长。

我这里的实验条件

  • 一个可用的 Kubernetes 集群
  • 已在集群中部署 Kube-Prometheus-Stack
  • 已在集群中部署 Traefik v2.2 作为 Ingress Controller
  • 已安装 Helm V3

示例项目

可直接做实验(文章写的再好,不如提供一个上云示例)

GitHub: k8s-eggjs

GitHub: k8s-eggjs

GitHub: k8s-eggjs

这个示例,简单的提供了两个接口:

/api/posts

代码语言:javascript
复制
curl -X POST http://localhost:7001/api/posts --data '{"title":"post1", "content": "post1 content"}' --header 'Content-Type:application/json; charset=UTF-8'

api/topics

代码语言:javascript
复制
curl -X POST http://localhost:7001/api/topics --data '{"title":"topic1", "content": "topic1 content"}' --header 'Content-Type:application/json; charset=UTF-8'

笔者也把这个项目部署到了

  • k8seggjs.hacker-linner.com
  • k8seggjs.hacker-linner.com
  • k8seggjs.hacker-linner.com

上云实战

(示例已提供,可直接做实验)

Scripts

package.json 这里简单调整为:

代码语言:javascript
复制
 "start": "egg-scripts start --workers=1 --title=egg-server-k8s-eggjs-promethues",

最好是单进程启动,应用容器的编排完全交给 kubernetes。

Egg 关于 K8S 部署的相关 issues

Docker Image 准备

文件位于 docker/Dockerfile.prod

代码语言:javascript
复制
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

代码语言:javascript
复制
docker build -f docker/Dockerfile.prod -t k8s-eggjs-promethues:1.0.0 .  --no-cache

打个 tag,笔者试验镜像是放在阿里云的(公司有自己的私有仓库)

代码语言:javascript
复制
docker tag k8s-eggjs-promethues:1.0.0 registry.cn-shenzhen.aliyuncs.com/hacker-linner/k8s-eggjs-promethues:1.0.0

推送到阿里云

代码语言:javascript
复制
docker push registry.cn-shenzhen.aliyuncs.com/hacker-linner/k8s-eggjs-promethues:1.0.0

Helm Chart(k8s-helm-charts)

(示例项目已提供,可直接做实验)

生成部署 Chart

代码语言:javascript
复制
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做如下修改:

代码语言:javascript
复制
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

代码语言:javascript
复制
kubectl create ns k8seggjs

使用 Helm 部署

代码语言:javascript
复制
helm install k8seggjs ./k8seggjs -f values.yaml -n k8seggjs

# 卸载:helm uninstall k8seggjs -n k8seggjs

ServiceMonitor(k8s-prometheus)

RBAC 设置

代码语言:javascript
复制
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 设置

代码语言:javascript
复制
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 设置

代码语言:javascript
复制
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

应用

代码语言:javascript
复制
kubectl apply -f ServiceMonitor.yaml

egg-exporter & egg-prometheus

egg-exporter,Egg.js 的 Prometheus 指标收集插件,附带 Grafana 看板。

egg-prometheus,Prometheus plugin for Egg.js。

示例项目的指标收集就是用的这个。

Grafana (k8s-grafana)

dashboard-metrics.json,完整的面板 json。来自于egg-exporter。笔者这里做了 metrics 前缀的调整。

代码语言:javascript
复制
config.exporter = {
  scrapePort: 7777,
  scrapePath: '/metrics',
  prefix: 'k8seggjs_',
  defaultLabels: { stage: process.env.NODE_ENV },
};

我们导入 json 文件进行 Grafana 面板创建

修改面板 Variables

$stage

  • Query: k8seggjs_nodejs_version_info{worker="app"}
  • Regex: /.*stage="([^"]*).*/

$appname

  • Query: k8seggjs_nodejs_version_info{worker="app"}
  • Regex: /.*app="([^"]*).*/

$node

  • Query: k8seggjs_nodejs_version_info{worker="app"}
  • Regex: /.*instance="([^"]*).*/

最终效果

Refs

  • 当egg遇见K8s会发生什么?
  • egg-exporter
  • egg-prometheus
  • filter-variables-with-regex

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2020-11-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 黑客下午茶 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 介绍
    • 我这里的实验条件
      • 示例项目
      • 上云实战
        • Scripts
          • Docker Image 准备
            • Helm Chart(k8s-helm-charts)
              • ServiceMonitor(k8s-prometheus)
                • egg-exporter & egg-prometheus
                  • Grafana (k8s-grafana)
                  • Refs
                  相关产品与服务
                  容器服务
                  腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档