您好,登錄后才能下訂單哦!
今天小編給大家分享一下KubeSphere中如何部署Wiki系統wiki.js并啟用中文全文檢索的相關知識點,內容詳細,邏輯清晰,相信大部分人都還太了解這方面的知識,所以分享這篇文章給大家參考一下,希望大家閱讀完這篇文章后有所收獲,下面我們一起來了解一下吧。
wiki.js 是優秀的開源 Wiki 系統,相較于 xwiki ,功能目前性上比 xwiki 不夠完善,但也在不斷進步。 Wiki 寫作、分享、權限管理功能還是有的,勝在 UI 設計很漂亮,能滿足小團隊的基本知識管理需求。
以下工作是在 KubeSphere 3.2.1 + Helm 3 已經部署好的情況下進行的。
我們使用 OpenEBS 作為存儲,OpenEBS 默認安裝的 Local StorageSlass 在 Pod 銷毀后自動刪除,不適合用于我的 MySQL 存儲,我們在 Local StorageClass 基礎上稍作修改,創建新的 StorageClass,允許 Pod 銷毀后,PV 內容繼續保留,手動決定怎么處理。
apiVersion: v1 items: - apiVersion: storage.k8s.io/v1 kind: StorageClass metadata: annotations: cas.openebs.io/config: | - name: StorageType value: "hostpath" - name: BasePath value: "/var/openebs/localretain/" openebs.io/cas-type: local storageclass.beta.kubernetes.io/is-default-class: "false" storageclass.kubesphere.io/supported-access-modes: '["ReadWriteOnce"]' name: localretain provisioner: openebs.io/local reclaimPolicy: Retain volumeBindingMode: WaitForFirstConsumer kind: List metadata: resourceVersion: "" selfLink: ""
我們團隊其他項目中也需要使用 PostgreSQL, 為了提高 PostgreSQL 數據庫的利用率和統一管理,我們獨立部署 PostgreSQL,并在安裝 wiki.js 時,配置為使用外部數據庫。
我們使用 Secret 保存 PostgreSQL 用戶密碼等敏感信息。
kind: Secret apiVersion: v1 metadata: name: postgres-prod data: POSTGRES_PASSWORD: xxxx type: Opaque
以上 POSTGRES_PASSWORD 自行準備,為 base64 編碼的數據。
使用 ConfigMap 保存數據庫初始化腳本,在 數據庫創建時,將 ConfigMap 中的數據庫初始化腳本掛載到 /docker-entrypoint-initdb.d, 容器初始化時會自動執行該腳本。
apiVersion: v1 kind: ConfigMap metadata: name: wikijs-postgres-init data: init.sql: |- CREATE DATABASE wikijs; CREATE USER wikijs with password 'xxxx'; GRANT CONNECT ON DATABASE wikijs to wikijs; GRANT USAGE ON SCHEMA public TO wikijs; GRANT SELECT,update,INSERT,delete ON ALL TABLES IN SCHEMA public TO wikijs; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO wikijs;
以上 wikijs 用戶的密碼自行準備,明文保存。
我們使用 KubeSphere 默認安裝的 OpenEBS 來提供存儲服務。可以通過創建 PVC 來提供持久化存儲。
這里聲明一個 10G 的 PVC。
kind: PersistentVolumeClaim apiVersion: v1 metadata: name: postgres-prod-data finalizers: - kubernetes.io/pvc-protection spec: accessModes: - ReadWriteOnce resources: requests: storage: 10Gi storageClassName: localretain volumeMode: Filesystem
在前面的步驟準備好各種配置信息和存儲后,就可以開始部署 PostgreSQL 服務了。
我們的 Kubernetes 沒有配置存儲陣列,使用的是 OpenEBS 作為存儲,采用 Deployment 方式部署 PostgreSQL。
apiVersion: apps/v1 kind: Deployment metadata: labels: app: postgres-prod name: postgres-prod spec: replicas: 1 selector: matchLabels: app: postgres-prod template: metadata: labels: app: postgres-prod spec: containers: - name: db imagePullPolicy: IfNotPresent image: 'abcfy2/zhparser:12-alpine' ports: - name: tcp-5432 protocol: TCP containerPort: 5432 envFrom: - secretRef: name: postgres-prod volumeMounts: - name: postgres-prod-data readOnly: false mountPath: /var/lib/postgresql/data - name: wikijs-postgres-init readOnly: true mountPath: /docker-entrypoint-initdb.d volumes: - name: postgres-prod-data persistentVolumeClaim: claimName: postgres-prod-data - name: wikijs-postgres-init configMap: name: wikijs-postgres-init
apiVersion: v1 kind: Service metadata: name: postgres-prod spec: selector: app: postgres-prod ports: - protocol: TCP port: 5432 targetPort: tcp-5432
測試略
我們使用 Secret 保存 wiki.js 用于連接數據庫的用戶名密碼等敏感信息。
apiVersion: v1 kind: Secret metadata: name: wikijs data: DB_USER: d2lraWpz DB_PASS: xxxx type: Opaque
以上 DB_PASS 自行準備,為 base64 編碼的數據。
我們使用 ConfigMap 保存 wiki.js 的數據庫連接信息。
apiVersion: v1 kind: ConfigMap metadata: name: wikijs data: DB_TYPE: postgres DB_HOST: postgres-prod.infra DB_PORT: "5432" DB_NAME: wikijs HA_ACTIVE: "true"
如果 PostgreSQL 數據庫里沒有創建 wikijs 用戶和數據 ,需要手工完成一下工作:
通過『數據庫工具』連接 PostgreSQL 數據庫,執行一下 SQL 語句,完成數據庫和用戶的創建、授權。
CREATE DATABASE wikijs; CREATE USER wikijs with password 'xxxx'; GRANT CONNECT ON DATABASE wikijs to wikijs; GRANT USAGE ON SCHEMA public TO wikijs; GRANT SELECT,update,INSERT,delete ON ALL TABLES IN SCHEMA public TO wikijs; ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO wikijs;
以上 wikijs 的密碼自行修改。
采用 Deployment 方式 部署 wiki.js 的 yaml 文件如下:
# wikijs-deploy.yaml apiVersion: apps/v1 kind: Deployment metadata: labels: app: wikijs name: wikijs spec: replicas: 1 selector: matchLabels: app: wikijs template: metadata: labels: app: wikijs spec: containers: - name: wikijs image: 'requarks/wiki:2' ports: - name: http-3000 protocol: TCP containerPort: 3000 envFrom: - secretRef: name: wikijs - configMapRef: name: wikijs
# wikijs-svc.yaml apiVersion: v1 kind: Service metadata: name: wikijs spec: selector: app: wikijs ports: - protocol: TCP port: 3000 targetPort: http-3000
# wikijs-ing.yaml kind: Ingress apiVersion: networking.k8s.io/v1 metadata: name: wikijs spec: ingressClassName: nginx rules: - host: wiki.xxxx.cn http: paths: - path: / pathType: ImplementationSpecific backend: service: name: wikijs port: number: 3000
以上 host 域名需要自行配置。
$ kubectl apply -f wikijs-deploy.yaml $ kubectl apply -f wikijs-svc.yaml $ kubectl apply -f wikijs-ing.yaml
wiki.js 的全文檢索支持基于 PostgreSQL 的檢索,也支持 Elasticsearch 等,相對來說, PostgreSQL 比較輕量級,本項目中,我們使用 PostgreSQL 的全文檢索。
但是,因為 PostgreSQL 不支持中文分詞,需要額外安裝插件并配置啟用中文分詞,下面描述了為 wiki.js 啟動基于 PostgreSQL 數據庫中文分詞的全文檢索。
通過數據庫管理工具登錄有超管權限的 PostgreSQL 用戶,臨時授予 wiki.js 用戶臨時超管權限,便于啟動中文分詞功能。
ALTER USER wikijs WITH SUPERUSER;
使用數據庫管理工具登錄 PostgreSQL 數據庫的 wikijs 用戶,執行以下命令,啟動數據庫的中文分詞功能。
CREATE EXTENSION pg_trgm; CREATE EXTENSION zhparser; CREATE TEXT SEARCH CONFIGURATION pg_catalog.chinese_zh (PARSER = zhparser); ALTER TEXT SEARCH CONFIGURATION chinese_zh ADD MAPPING FOR n,v,a,i,e,l WITH simple; -- 忽略標點影響 ALTER ROLE wikijs SET zhparser.punctuation_ignore = ON; -- 短詞復合 ALTER ROLE wikijs SET zhparser.multi_short = ON; -- 測試一下 select ts_debug('chinese_zh', '青春是最美好的年歲,青春是最燦爛的日子。每一個人的青春都無比寶貴,寶貴的青春只有與奮斗為伴才最閃光、最出彩。');
登錄 PostgreSQL 數據庫 wikijs 用戶,取消 wikijs 用戶的超管權限。
ALTER USER wikijs WITH NOSUPERUSER;
# zh-parse.yaml kind: ConfigMap apiVersion: v1 metadata: name: wikijs-zhparser data: definition.yml: |- key: postgres title: Database - PostgreSQL description: Advanced PostgreSQL-based search engine. author: requarks.io logo: https://static.requarks.io/logo/postgresql.svg website: https://www.requarks.io/ isAvailable: true props: dictLanguage: type: String title: Dictionary Language hint: Language to use when creating and querying text search vectors. default: english enum: - simple - danish - dutch - english - finnish - french - german - hungarian - italian - norwegian - portuguese - romanian - russian - spanish - swedish - turkish - chinese_zh order: 1 engine.js: |- const tsquery = require('pg-tsquery')() const stream = require('stream') const Promise = require('bluebird') const pipeline = Promise.promisify(stream.pipeline) /* global WIKI */ module.exports = { async activate() { if (WIKI.config.db.type !== 'postgres') { throw new WIKI.Error.SearchActivationFailed('Must use PostgreSQL database to activate this engine!') } }, async deactivate() { WIKI.logger.info(`(SEARCH/POSTGRES) Dropping index tables...`) await WIKI.models.knex.schema.dropTable('pagesWords') await WIKI.models.knex.schema.dropTable('pagesVector') WIKI.logger.info(`(SEARCH/POSTGRES) Index tables have been dropped.`) }, /** * INIT */ async init() { WIKI.logger.info(`(SEARCH/POSTGRES) Initializing...`) // -> Create Search Index const indexExists = await WIKI.models.knex.schema.hasTable('pagesVector') if (!indexExists) { WIKI.logger.info(`(SEARCH/POSTGRES) Creating Pages Vector table...`) await WIKI.models.knex.schema.createTable('pagesVector', table => { table.increments() table.string('path') table.string('locale') table.string('title') table.string('description') table.specificType('tokens', 'TSVECTOR') table.text('content') }) } // -> Create Words Index const wordsExists = await WIKI.models.knex.schema.hasTable('pagesWords') if (!wordsExists) { WIKI.logger.info(`(SEARCH/POSTGRES) Creating Words Suggestion Index...`) await WIKI.models.knex.raw(` CREATE TABLE "pagesWords" AS SELECT word FROM ts_stat( 'SELECT to_tsvector(''simple'', "title") || to_tsvector(''simple'', "description") || to_tsvector(''simple'', "content") FROM "pagesVector"' )`) await WIKI.models.knex.raw('CREATE EXTENSION IF NOT EXISTS pg_trgm') await WIKI.models.knex.raw(`CREATE INDEX "pageWords_idx" ON "pagesWords" USING GIN (word gin_trgm_ops)`) } WIKI.logger.info(`(SEARCH/POSTGRES) Initialization completed.`) }, /** * QUERY * * @param {String} q Query * @param {Object} opts Additional options */ async query(q, opts) { try { let suggestions = [] let qry = ` SELECT id, path, locale, title, description FROM "pagesVector", to_tsquery(?,?) query WHERE (query @@ "tokens" OR path ILIKE ?) ` let qryEnd = `ORDER BY ts_rank(tokens, query) DESC` let qryParams = [this.config.dictLanguage, tsquery(q), `%${q.toLowerCase()}%`] if (opts.locale) { qry = `${qry} AND locale = ?` qryParams.push(opts.locale) } if (opts.path) { qry = `${qry} AND path ILIKE ?` qryParams.push(`%${opts.path}`) } const results = await WIKI.models.knex.raw(` ${qry} ${qryEnd} `, qryParams) if (results.rows.length < 5) { const suggestResults = await WIKI.models.knex.raw(`SELECT word, word <-> ? AS rank FROM "pagesWords" WHERE similarity(word, ?) > 0.2 ORDER BY rank LIMIT 5;`, [q, q]) suggestions = suggestResults.rows.map(r => r.word) } return { results: results.rows, suggestions, totalHits: results.rows.length } } catch (err) { WIKI.logger.warn('Search Engine Error:') WIKI.logger.warn(err) } }, /** * CREATE * * @param {Object} page Page to create */ async created(page) { await WIKI.models.knex.raw(` INSERT INTO "pagesVector" (path, locale, title, description, "tokens") VALUES ( ?, ?, ?, ?, (setweight(to_tsvector('${this.config.dictLanguage}', ?), 'A') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'B') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'C')) ) `, [page.path, page.localeCode, page.title, page.description, page.title, page.description, page.safeContent]) }, /** * UPDATE * * @param {Object} page Page to update */ async updated(page) { await WIKI.models.knex.raw(` UPDATE "pagesVector" SET title = ?, description = ?, tokens = (setweight(to_tsvector('${this.config.dictLanguage}', ?), 'A') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'B') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'C')) WHERE path = ? AND locale = ? `, [page.title, page.description, page.title, page.description, page.safeContent, page.path, page.localeCode]) }, /** * DELETE * * @param {Object} page Page to delete */ async deleted(page) { await WIKI.models.knex('pagesVector').where({ locale: page.localeCode, path: page.path }).del().limit(1) }, /** * RENAME * * @param {Object} page Page to rename */ async renamed(page) { await WIKI.models.knex('pagesVector').where({ locale: page.localeCode, path: page.path }).update({ locale: page.destinationLocaleCode, path: page.destinationPath }) }, /** * REBUILD INDEX */ async rebuild() { WIKI.logger.info(`(SEARCH/POSTGRES) Rebuilding Index...`) await WIKI.models.knex('pagesVector').truncate() await WIKI.models.knex('pagesWords').truncate() await pipeline( WIKI.models.knex.column('path', 'localeCode', 'title', 'description', 'render').select().from('pages').where({ isPublished: true, isPrivate: false }).stream(), new stream.Transform({ objectMode: true, transform: async (page, enc, cb) => { const content = WIKI.models.pages.cleanHTML(page.render) await WIKI.models.knex.raw(` INSERT INTO "pagesVector" (path, locale, title, description, "tokens", content) VALUES ( ?, ?, ?, ?, (setweight(to_tsvector('${this.config.dictLanguage}', ?), 'A') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'B') || setweight(to_tsvector('${this.config.dictLanguage}', ?), 'C')), ? ) `, [page.path, page.localeCode, page.title, page.description, page.title, page.description, content,content]) cb() } }) ) await WIKI.models.knex.raw(` INSERT INTO "pagesWords" (word) SELECT word FROM ts_stat( 'SELECT to_tsvector(''simple'', "title") || to_tsvector(''simple'', "description") || to_tsvector(''simple'', "content") FROM "pagesVector"' ) `) WIKI.logger.info(`(SEARCH/POSTGRES) Index rebuilt successfully.`) } }
wiki.js 的基于 PostgreSQL 的全文檢索引擎配置位于 /wiki/server/modules/search/postgres ,我們將前面配置的 ConfigMap 加載到這個目錄。
# wikijs-zh.yaml kind: Deployment apiVersion: apps/v1 metadata: name: wikijs labels: app: wikijs spec: replicas: 1 selector: matchLabels: app: wikijs template: metadata: labels: app: wikijs spec: volumes: - name: volume-dysh5f configMap: name: wikijs-zhparser defaultMode: 420 containers: - name: wikijs image: 'requarks/wiki:2' ports: - name: http-3000 containerPort: 3000 protocol: TCP envFrom: - secretRef: name: wikijs - configMapRef: name: wikijs volumeMounts: - name: volume-dysh5f readOnly: true mountPath: /wiki/server/modules/search/postgres
重新 apply 新的 Delployment 文件后
$ kubectl apply -f zh-parse.yaml $ kubectl apply -f wikijs-zh.yaml
打開 wiki.js 管理
點擊搜索引擎
選擇 Database - PostgreSQL
在 Dictionary Language 的下拉菜單里選擇 chinese_zh。
點擊應用,并重建索引。
完成配置。
以上就是“KubeSphere中如何部署Wiki系統wiki.js并啟用中文全文檢索”這篇文章的所有內容,感謝各位的閱讀!相信大家閱讀完這篇文章都有很大的收獲,小編每天都會為大家更新不同的知識,如果還想學習更多的知識,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。