给 Strapi 应用添加健康检查端点

共 4957字,需浏览 10分钟

 ·

2021-11-17 16:34



今天继续上周的主题,给 k8s 集群里的服务添加健康检查探针。上一篇《给 SpringBoot 服务添加健康检查》是针对 Java 服务的。除了 java 服务,公司还有一个 CMS 系统部署在 k8s 集群中,基于 Strapi 开发,是一个 nodejs 项目。粗看了一下 Strapi,感觉它的理念和 Koa 很像,仔细看它果然依赖 koa,并且文档中也提到了 Koa。这让我比较激动,毕竟,我也是 Koa 项目的 Contributor(尽管只有一丢丢贡献):


5d97fb198d44ce472f7d5974be591cee.webp


先追求有,再追求好


如同上一篇给 SpringBoot 服务添加健康检查路由一样,本篇介绍只追求有,即添加最简单的实现。要完美的话,还需要写一些额外的代码,以便在一些外部依赖(比如数据库)发生问题时得到通知,并让健康检查端点返回错误。


测试


如同上一篇一样,仍然是在写实现代码前,先把测试写好,即把最终效果写下来,这是一种以终为始的思维方式,有助于避免掉进软件开发的焦油坑:《我是如何从焦油坑里爬出来的》。


添加测试工具


由于项目里没有引入测试工具,先补上:


yarn add --dev jest supertest sqlite3


jest 是 Facebook(现在叫 Meta?)开发的测试框架。supertest 用来测试 Web 服务,而 sqlite3 可以简化测试时的数据库依赖。


测试配置


增加 config/env/test/database.json 指定测试时使用 sqlite:

{    "defaultConnection": "default",    "connections": {        "default": {            "connector": "bookshelf",            "settings": {                "client": "sqlite",                "filename": ".tmp/test.db"            },            "options": {                "useNullAsDefault": true,                "pool": {                    "min": 0,                    "max": 1                }            }        }    }}


测试命令


在 package.json 里的 scripts 字段中加入测试相关命令:


+     "test": "jest --forceExit --detectOpenHandles"


在 package.json 的最后添加:


  "jest": {    "testPathIgnorePatterns": [      "/node_modules/",      ".tmp",      ".cache"    ],    "testEnvironment": "node"  }


健康检查测试用例


tests/healthz/index.test.js

const Strapi = require('strapi');const http = require('http');const request = require('supertest')

let instance;

async function setupStrapi() { if (!instance) { /** the following code in copied from `./node_modules/strapi/lib/Strapi.js` */ await Strapi().load(); instance = strapi; // strapi is global now await instance.app .use(instance.router.routes()) // populate KOA routes .use(instance.router.allowedMethods()); // populate KOA methods

instance.server = http.createServer(instance.app.callback()); } return instance;}

jest.setTimeout(20000)describe('Health Check', () => { beforeAll(async () => { await setupStrapi() })

it('should live', async () => { await request( strapi.server) .get('/healthz/liveness') .expect(200) .then(data => { expect(data.text).toBe('I\'m alive!') }) })

it('should ready', async()=>{ await request( strapi.server) .get('/healthz/readiness') .expect(200) .then(data => { expect(data.text).toBe('I\'m ready!') }) })})


实现路由


首先增加 api/healthz 目录


添加路由配置


api/healthz/config/routes.json

{    "routes": [        {            "method": "GET",            "path": "/healthz",            "handler": "Healthz.index"        },        {            "method": "GET",            "path": "/healthz/liveness",            "handler": "Healthz.liveness"        },        {            "method": "GET",            "path": "/healthz/readiness",            "handler": "Healthz.readiness"        }    ]}


注意,一定不要使用官方的默认示例,不能含有 policies 数组:

{    "routes": [        {            "method": "GET",            "path": "/healthz",            "handler": "Healthz.index",            "config": {              "policies": []            }        }    ]}


如果这样,运行测试就会得到 403 的错误,原因是它会触发 user permissions 插件的权限检查。尽管你可以通过管理后台配置其权限公开访问:


03ceef5e93de8ac4d64cb1622a54aa2e.webp



但是对于健康检查接口,没有必要专门配置权限,直接绕开权限插件即可:


7b929e95a7cfa4992fcb8d641f4756c4.webp


实现路由逻辑


api/healthz/controllers/Healthz.js

module.exports = {    // GET /healthz    async index(ctx) {        ctx.send('Hello World!')    },

async readiness(ctx) { ctx.send('I\'m ready!') },

async liveness(ctx) { ctx.send('I\'m alive!') },}


运行测试,通过。


添加 deployment 配置



readinessProbe: httpGet: path: /healthz/readiness port: 1337 initialDelaySeconds: 30 timeoutSeconds: 10 livenessProbe: httpGet: path: /healthz/liveness port: 1337 initialDelaySeconds: 130 timeoutSeconds: 10


部署后可以验证:


74a07407d2364bb07cf6826182cc9cc4.webp


在 k8s 集群里查看是否生效:


kubectl describe pod/your-pod

...Containers: cms: Container ID: docker://7245d2d8644d6bcc7c7ff39fdea5e680457c4edf2ff70610a8607c3cef5d3332 Image: 13659932xxxx.dkr.ecr.cn-northwest-1.amazonaws.com.cn/cms:cccc1aec Image ID: docker-pullable://13659932xxx.dkr.ecr.cn-northwest-1.amazonaws.com.cn/cms@sha256:bc4317cc2347eb2aed74b8e4e9f39b901b613e4bbc7781e09957e2eb4a0bd0db Port: 1337/TCP Host Port: 0/TCP State: Running Started: Mon, 15 Nov 2021 10:23:42 +0000 Ready: True Restart Count: 0 Limits: cpu: 1 memory: 2000Mi Requests: cpu: 500m memory: 1000Mi Liveness: http-get http://:1337/healthz/liveness delay=130s timeout=10s period=10s #success=1 #failure=3 Readiness: http-get http://:1337/healthz/readiness delay=30s timeout=10s period=10s #success=1 #failure=3 Environment Variables from:...


注意以上输出的 Liveness 和 Readiness 部分,小功告成!


浏览 24
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

分享
举报