1. 程式人生 > 其它 >addon新增元件-微服務應用

addon新增元件-微服務應用

addon新增元件-微服務應用

kubevela簡介

背景:公司最近在研究OAM(開放應用模型),其中KubeVela 專案是 OAM 社群的官方專案,是一個端到端、面向全量場景的 OAM Kubernetes 完整實現,同時也是阿里雲 EDAS 服務和內部多個核心 PaaS/Serverless 生產系統底層的核心元件。

我這邊在嘗試了通過vela up -f xxx.yaml方式,正常部署應用之後,對於其外掛的擴充套件有了一點興趣,就研究了一下,做了一個demo。

demo工程

demo工程是基於Spring-Cloud-Alibaba

因為是demo工程,所以做得比較簡單,但是及時是這樣簡單的工程,也能體現出使用自定義元件部署應用的流程。在更加複雜的專案中也適用。

demo工程使用了:

註冊中心-nacos

快取-redis

關係型資料庫-mysql 8.0

工程中有3個服務,alpha連線資料庫和nacos,beta連線redis和nacos

aggregation連線nacos,通過openfeign呼叫服務alpha和beta做聚合邏輯

工程的內部邏輯就不多強調了,主要是其配置方面

alpha服務關於資料庫和nacos的配置:

spring:
  #profiles:
  #  include: discovery-registry
  datasource:
    #資料庫地址
    url: jdbc:mysql://${DB_URL}/framework_test?useUnicode=true&characterEncoding=utf-8&useSSL=true&serverTimezone=UTC
    #資料庫賬號
    username: ${DB_USERNAME}
    #資料庫密碼
    password: ${DB_PASSWORD}
... ...
    #nacos地址
    server-addr: ${NACOS_SERVER_ADDR}
... ...

beta服務關於redis和nacos的配置:

spring:
  redis:
    redisson:
      config: |
        singleServerConfig:
          ...
          password: ${REDIS_PASSWORD}
          address: 'redis://${REDIS_IP}:${REDIS_PORT}'
          ...
... ...
    #nacos地址
    server-addr: ${NACOS_SERVER_ADDR}
... ...

aggregation關於nacos的配置

... ...
    #nacos地址
    server-addr: ${NACOS_SERVER_ADDR}
... ...

通過環境變數的方式,傳入nacos,redis和mysql的相關資訊

然後將這三個服務容器化,只要在部署的時候通過注入環境變數的方式就能完成nacos,redis和mysql的配置。

kubevela addon

在使用原生k8s的時候,通常在部署服務的時候,需要使用k8s資源清單,將中介軟體,資料庫先行部署。

但是如果我們使用kubevela,能不能將部署中介軟體,資料庫的這些步驟,和我們的服務結合起來?

將資料庫,中介軟體這些當做專案的一個元件,做到一鍵部署,並且自動關聯到應用中。

這就可以用到kubevela的元件了。元件定義(ComponentDefinition)可以將任何型別的可部署製品封裝成待交付的“元件”。只要定義好之後,這種型別的元件就可以被使用者在部署計劃(Application)中引用、例項化並交付出去。

參考外掛文件,我這裡將redis,mysql和nacos做成元件,通過外掛的方式新增進kubevela

外掛目錄:

其中最重要的是三個.cue檔案,對應的是三個元件,其他的檔案可以參考外掛文件

myredis.cue:

import(
	"encoding/base64"
)
"myredis": {
	annotations: {}
	attributes: workload: definition: {
		apiVersion: "apps/v1"
		kind: "Deployment"
	}
	description: "My Redis component."
	labels: {}
	type: "component"
}

template: {
	output: {
		apiVersion: "v1"
		kind: "ConfigMap"
		metadata: {
			name: context.name + "-redis-config"
			labels: app: context.name
		}
		data: {
			"redis.conf": """
              dir /data
              port 6379
              bind 0.0.0.0
              appendonly yes
              protected-mode no
              pidfile /data/redis-6379.pid
              requirepass
              """ + " "  + parameter.redisPassword
		}
	}
	outputs: {
		redis: {
		apiVersion: "apps/v1"
		kind: "Deployment"
		metadata: {
			name: "redis"
			labels: app: context.name
		}
		spec: {
			replicas: 1
			selector: matchLabels: app: context.name
			template: {
				metadata: labels: app: context.name
				spec: {
					containers: [{
						name: context.name
						command: ["sh", "-c", "redis-server /usr/local/etc/redis/redis.conf"]
						image: "redis:6.2.6"
						ports: [{
							containerPort: 6379
						}]
						volumeMounts: [{
							name:      "data"
							mountPath: "/data"
						}, {
							name:      "config"
							mountPath: "/usr/local/etc/redis/redis.conf"
							subPath:   "redis.conf"
						}]
					}]
					volumes: [{
						name: "data"
						hostPath: path: parameter.hostPath
					}, {
						name: "config"
						configMap: name: context.name + "-redis-config"
					}]
				}
			}
		}
	}
	web: {
		apiVersion: "v1"
		kind:       "Service"
		metadata: {
			name: context.name
			labels: app: context.name
		}
		spec: {
			ports: [{
				name: context.name
				port: 6379
				targetPort: 6379
				if parameter.serviceType == "NodePort" {
					  nodePort:   parameter.nodePort
					}
			}]
			selector: app: context.name
			type: parameter.serviceType
	  }
	}
	secret: {
		apiVersion: "v1"
		kind:       "Secret"
		metadata: {
			name: context.name + "-myredis-secret"
		}
		type: "Opaque"
		data: {
			password: base64.Encode(null,parameter.redisPassword)
			ip: base64.Encode(null,context.name + "." + context.namespace + ".svc.cluster.local")
			port: base64.Encode(null,"6379")
		}
	}
	}
	parameter: {
              hostPath: *"/home/k8s/redis/data1" | string
              serviceType: *"ClusterIP" | "NodePort"
              redisPassword: *"123456" | string
              nodePort: *30003 | int
            }
}

mysql.cue

import(
	"encoding/base64"
)
mysql: {
	annotations: {}
	attributes: workload: definition: {
		apiVersion: "apps/v1"
		kind:       "StatefulSet"
	}
	description: "My mysql component."
	labels: {}
	type: "component"
}

template: {
	output: {
		apiVersion: "v1"
		data: "mysqld.cnf": """
        [mysqld]
        pid-file        = /var/run/mysqld/mysqld.pid
        socket          = /var/run/mysqld/mysqld.sock
        datadir         = /var/lib/mysql
        bind-address   = 0.0.0.0
        symbolic-links=0
        max_connections=1000
        default_storage_engine=innodb
        skip_external_locking
        lower_case_table_names=1
        skip_host_cache
        skip_name_resolve
        character_set_server=utf8
        sql_mode=STRICT_TRANS_TABLES,NO_ZERO_IN_DATE,NO_ZERO_DATE,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
        """
		kind: "ConfigMap"
		metadata: {
			name:      context.name + "-mysql-config"
		}
	}
	outputs: {
		mysql: {
			apiVersion: "apps/v1"
			kind:       "StatefulSet"
			metadata: {
				name: context.name + "-mysql"
			}
			spec: {
				selector: matchLabels: app: context.name + "-mysql"
				replicas:    1
				serviceName: context.name + "-mysql-headless"
				template: {
					metadata: labels: app: context.name + "-mysql"
					spec: {
						containers: [{
							name: "mysql"
							env: [{
								name:  "MYSQL_ROOT_PASSWORD"
								value: parameter.rootPassword
							}, {
								if parameter.database != _|_ {
								  name:  "MYSQL_DATABASE"
								  value: parameter.database
								}
							}]
							ports: [{
								name:          "mysql"
								containerPort: 3306
							}]
							image: "mysql:8.0.28"
							volumeMounts: [{
								name: context.name + "-mysql-data"
								mountPath: "/var/lib/mysql"
							}, {
								name: context.name + "-mysql-config"
								mountPath: "/etc/mysql/conf.d/"
							},{
								if parameter.initdb != _|_{
								  name:  context.name + "-mysql-initdb"
								  mountPath: "/docker-entrypoint-initdb.d"
								}
						    }
						]
						}]
						volumes: [{
							name: context.name+ "-mysql-data"
							hostPath: path: parameter.hostPath
						}, {
							name: context.name + "-mysql-config"
							configMap: name: context.name + "-mysql-config"
						},{
					     if parameter.initdb != _|_		{
							     name: context.name + "-mysql-initdb"
							     configMap: name: parameter.initdb
						    }
					   }
				]
					}
				}
			}
		}
		"mysql-headless": {
			apiVersion: "v1"
			kind:       "Service"
			metadata: {
				name:  context.name + "-mysql-headless"
				labels: app: context.name + "-mysql"
			}
			spec: {
				ports: [{
					name:       "tcp"
					port:       3306
					protocol:   "TCP"
					targetPort: 3306
				}]
				selector: app: context.name + "-mysql"
				clusterIP: "None"
			}
		}
		"mysql-service": {
			apiVersion: "v1"
			kind:       "Service"
			metadata: {
				name: context.name + "-mysql-service"
				labels: app: context.name + "-mysql"
			}
			spec: {
				ports: [{
					name:       "tcp"
					if parameter.serviceType == "NodePort" {
					  nodePort:   parameter.nodePort
					}

					port:       3306
					protocol:   "TCP"
					targetPort: 3306
				}]
				selector: app: context.name + "-mysql"
				type: parameter.serviceType
			}
		}
	  secret: {
		  apiVersion: "v1"
		  kind:       "Secret"
		  metadata: {
			  name: context.name + "-mysql-secret"
		  }
		  type: "Opaque"
		  data: {
			  root: base64.Encode(null,"root")
			  password: base64.Encode(null,parameter.rootPassword)
			  url: base64.Encode(null,context.name + "-mysql-service." + context.namespace + ".svc.cluster.local:3306")
		  }
	  }
	}
	parameter: {
		initdb ?: string
		hostPath: *"/home/k8s/mysql" | string
    serviceType: *"ClusterIP" | "NodePort"
    nodePort: *30001 | int
    rootPassword: *"123456" | string
    database ?: string
	}
}

nacos.cue:

import(
	"encoding/base64"
)
nacos: {
	annotations: {}
	attributes: workload: definition: {
		apiVersion: "apps/v1"
		kind:       "StatefulSet"
	}
	description: "My nacos component."
	labels: {}
	type: "component"
}

template: {
	output: {
		apiVersion: "v1"
		data: {
			"mysql.db.name":  parameter.mysql.db
			"mysql.host":     parameter.mysql.host
			"mysql.password": parameter.mysql.password
			"mysql.port":     parameter.mysql.port
			"mysql.user":     parameter.mysql.user
		}
		kind: "ConfigMap"
		metadata: {
			name: context.name + "-nacos-config"
		}
	}
	outputs: {
		nacos: {
			apiVersion: "apps/v1"
			kind:       "StatefulSet"
			metadata: {
				name: context.name + "-nacos"
			}
			spec: {
				selector: matchLabels: app: context.name + "-nacos"
				replicas:    1
				serviceName: context.name + "-nacos-headless"
				template: {
					metadata: labels: app:context.name + "-nacos"
					spec: containers: [{
						name: "nacos"
						env: [{
							name: "MYSQL_SERVICE_HOST"
							valueFrom: configMapKeyRef: {
								name: context.name + "-nacos-config"
								key:  "mysql.host"
							}
						}, {
							name: "MYSQL_SERVICE_DB_NAME"
							valueFrom: configMapKeyRef: {
								name: context.name + "-nacos-config"
								key:  "mysql.db.name"
							}
						}, {
							name: "MYSQL_SERVICE_PORT"
							valueFrom: configMapKeyRef: {
								name: context.name + "-nacos-config"
								key:  "mysql.port"
							}
						}, {
							name: "MYSQL_SERVICE_USER"
							valueFrom: configMapKeyRef: {
								name: context.name + "-nacos-config"
								key:  "mysql.user"
							}
						}, {
							name: "MYSQL_SERVICE_PASSWORD"
							valueFrom: configMapKeyRef: {
								name: context.name + "-nacos-config"
								key:  "mysql.password"
							}
						}, {
							name:  "MODE"
							value: "standalone"
						}, {
							name:  "NACOS_SERVER_PORT"
							value: "8848"
						}]
						ports: [{
							name:          "client"
							containerPort: 8848
						}]
						image:           "nacos/nacos-server:2.0.2"
					}]
				}
			}
		}
		"nacos-headless": {
			apiVersion: "v1"
			kind:       "Service"
			metadata: {
				name:      context.name + "-nacos-headless"
				labels: app: context.name + "-nacos"
			}
			spec: {
				clusterIP: "None"
				ports: [{
					name:       "server"
					port:       8848
					targetPort: 8848
				}]
				selector: app: context.name + "-nacos"
			}
		}
		"nacos-service": {
			apiVersion: "v1"
			kind:       "Service"
			metadata: {
				name:      context.name + "-nacos-service"
			}
			spec: {
				ports: [{
					name:       "http"
					port:       8848
					targetPort: 8848
					if parameter.serviceType == "NodePort" {
					  nodePort:   parameter.nodePort
					}
					protocol:   "TCP"
				}]
				selector: app: context.name + "-nacos"
				type: parameter.serviceType
			}
		}
		secret: {
		apiVersion: "v1"
		kind:       "Secret"
		metadata: {
			name: context.name + "-nacos-secret"
		}
		type: "Opaque"
		data: {
			url: base64.Encode(null,context.name + "-nacos-service." + context.namespace + ".svc.cluster.local:8848")
		}
	}
	}
	parameter: {
		mysql: {
			db: *"nacos" | string
			host: *"mysql.default.svc.cluster.local" | string
			port: *"3306" | string
			user: *"root" | string
			password: *"123456" | string
		}
		serviceType: *"ClusterIP" | "NodePort"
    nodePort: *30002 | int
	}
}

cue語法可以參考:

cue

其實我這裡也不是從零開始寫的cue檔案,而是通過vela def init nacos -t component --desc "My nacos component." --template-yaml ./nacos.yaml -o nacos.cue這個命令將yaml檔案生成cue檔案,然後在此基礎上更改的。

也就是說編寫元件的流程是:

1.先寫好一個yaml檔案,即普通的k8s資源清單,比如:

---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: redis
  labels:
    app: redis
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis
  template:
    metadata:
      labels:
        app: redis
    spec:
      containers:
        - name: redis
          image: redis:6.2.6
          command:
            - "sh"
            - "-c"
            - "redis-server /usr/local/etc/redis/redis.conf"
          ports:
            - containerPort: 6379
          volumeMounts:
            - name: data
              mountPath: /data
            - name: config
              mountPath: /usr/local/etc/redis/redis.conf
              subPath: redis.conf
      volumes:
        - name: data
          hostPath:
            path: /home/k8s/redis/data
        - name: config
          configMap:
            name: redis-config

2.通過vela def init {component-name} -t component --desc "xxx" --template-yaml ./xxx.yaml -o xxx.cue命令,生成cue檔案

3.修改cue檔案,完成元件編寫

在cue檔案中,我這裡使用了encoding/base64,將ip,password,port存入了一個secret中,這是因為kubevela在部署應用的時候,可以通過一個叫service-binding的一個trait,將secret對映到pod的環境變數中

CUE 有很多 internal packages 可以被 KubeVela 使用,這樣可以滿足更多的開發需求。

安裝外掛

當前kubevela(1.2版本)通過UX在頁面上只能新增github或者aliyunOSS的外掛,本地外掛,gitlab中的外掛不支援,所以這裡使用CLI命令安裝

# 進入外掛程式碼目錄
$ cd /home/kubevela-addon
$ vela addon enable /home/kubevela-addon

# 檢視外掛是否安裝成功
$ vela addon ls
# 檢視外掛中定義的component
$ vela component

部署應用

還記得我們的工程中是如何配置中介軟體和資料庫的嗎?

是使用環境變數的方式

為什麼要這樣去配置呢?

因為kubevela在部署應用的時候,可以通過一個叫service-binding的一個trait,將secret對映到pod的環境變數中

這樣就能達到在不同環境中,自定義元件配置的目的

在部署之前,我們需要對資料庫進行初始化,在編寫mysql.cue的時候,有這樣一段:

             {
								if parameter.initdb != _|_{
								  name:  context.name + "-mysql-initdb"
								  mountPath: "/docker-entrypoint-initdb.d"
								}
						    }
						]
						}]
						volumes: [
              ...
              ,{
					     if parameter.initdb != _|_		{
							     name: context.name + "-mysql-initdb"
							     configMap: name: parameter.initdb

這裡的意思是將configmap與容器中docker-entrypoint-initdb.d這個目錄關聯起來。

根據MySQL Docker映象README,與容器啟動時的資料初始化相關的部分是確保你所有的初始化檔案都掛載到容器的//docker-entrypoint-initdb.d資料夾

所以我們要先建立一個configmap,初始化nacos的庫

apiVersion: v1
data:
  initdb.sql: |
    CREATE TABLE `config_info` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(255) DEFAULT NULL,
      `content` longtext NOT NULL COMMENT 'content',
      `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
      `src_user` text COMMENT 'source user',
      `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
      `app_name` varchar(128) DEFAULT NULL,
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶欄位',
      `c_desc` varchar(256) DEFAULT NULL,
      `c_use` varchar(64) DEFAULT NULL,
      `effect` varchar(64) DEFAULT NULL,
      `type` varchar(64) DEFAULT NULL,
      `c_schema` text,
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfo_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info';

    CREATE TABLE `config_info_aggr` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(255) NOT NULL COMMENT 'group_id',
      `datum_id` varchar(255) NOT NULL COMMENT 'datum_id',
      `content` longtext NOT NULL COMMENT '內容',
      `gmt_modified` datetime NOT NULL COMMENT '修改時間',
      `app_name` varchar(128) DEFAULT NULL,
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶欄位',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfoaggr_datagrouptenantdatum` (`data_id`,`group_id`,`tenant_id`,`datum_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='增加租戶欄位';

    CREATE TABLE `config_info_beta` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(128) NOT NULL COMMENT 'group_id',
      `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
      `content` longtext NOT NULL COMMENT 'content',
      `beta_ips` varchar(1024) DEFAULT NULL COMMENT 'betaIps',
      `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
      `src_user` text COMMENT 'source user',
      `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶欄位',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfobeta_datagrouptenant` (`data_id`,`group_id`,`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_beta';

    CREATE TABLE `config_info_tag` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(128) NOT NULL COMMENT 'group_id',
      `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
      `tag_id` varchar(128) NOT NULL COMMENT 'tag_id',
      `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
      `content` longtext NOT NULL COMMENT 'content',
      `md5` varchar(32) DEFAULT NULL COMMENT 'md5',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
      `src_user` text COMMENT 'source user',
      `src_ip` varchar(50) DEFAULT NULL COMMENT 'source ip',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_configinfotag_datagrouptenanttag` (`data_id`,`group_id`,`tenant_id`,`tag_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_info_tag';

    CREATE TABLE `config_tags_relation` (
      `id` bigint(20) NOT NULL COMMENT 'id',
      `tag_name` varchar(128) NOT NULL COMMENT 'tag_name',
      `tag_type` varchar(64) DEFAULT NULL COMMENT 'tag_type',
      `data_id` varchar(255) NOT NULL COMMENT 'data_id',
      `group_id` varchar(128) NOT NULL COMMENT 'group_id',
      `tenant_id` varchar(128) DEFAULT '' COMMENT 'tenant_id',
      `nid` bigint(20) NOT NULL AUTO_INCREMENT,
      PRIMARY KEY (`nid`),
      UNIQUE KEY `uk_configtagrelation_configidtag` (`id`,`tag_name`,`tag_type`),
      KEY `idx_tenant_id` (`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='config_tag_relation';

    CREATE TABLE `group_capacity` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
      `group_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Group ID,空字元表示整個叢集',
      `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額,0表示使用預設值',
      `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
      `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個配置大小上限,單位為位元組,0表示使用預設值',
      `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個數,,0表示使用預設值',
      `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個聚合資料的子配置大小上限,單位為位元組,0表示使用預設值',
      `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數量',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_group_id` (`group_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='叢集、各Group容量資訊表';

    CREATE TABLE `his_config_info` (
      `id` bigint(64) unsigned NOT NULL,
      `nid` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
      `data_id` varchar(255) NOT NULL,
      `group_id` varchar(128) NOT NULL,
      `app_name` varchar(128) DEFAULT NULL COMMENT 'app_name',
      `content` longtext NOT NULL,
      `md5` varchar(32) DEFAULT NULL,
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP,
      `src_user` text,
      `src_ip` varchar(50) DEFAULT NULL,
      `op_type` char(10) DEFAULT NULL,
      `tenant_id` varchar(128) DEFAULT '' COMMENT '租戶欄位',
      PRIMARY KEY (`nid`),
      KEY `idx_gmt_create` (`gmt_create`),
      KEY `idx_gmt_modified` (`gmt_modified`),
      KEY `idx_did` (`data_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='多租戶改造';

    CREATE TABLE `tenant_capacity` (
      `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',
      `tenant_id` varchar(128) NOT NULL DEFAULT '' COMMENT 'Tenant ID',
      `quota` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '配額,0表示使用預設值',
      `usage` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '使用量',
      `max_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個配置大小上限,單位為位元組,0表示使用預設值',
      `max_aggr_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '聚合子配置最大個數',
      `max_aggr_size` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '單個聚合資料的子配置大小上限,單位為位元組,0表示使用預設值',
      `max_history_count` int(10) unsigned NOT NULL DEFAULT '0' COMMENT '最大變更歷史數量',
      `gmt_create` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '建立時間',
      `gmt_modified` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改時間',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_tenant_id` (`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='租戶容量資訊表';

    CREATE TABLE `tenant_info` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'id',
      `kp` varchar(128) NOT NULL COMMENT 'kp',
      `tenant_id` varchar(128) default '' COMMENT 'tenant_id',
      `tenant_name` varchar(128) default '' COMMENT 'tenant_name',
      `tenant_desc` varchar(256) DEFAULT NULL COMMENT 'tenant_desc',
      `create_source` varchar(32) DEFAULT NULL COMMENT 'create_source',
      `gmt_create` bigint(20) NOT NULL COMMENT '建立時間',
      `gmt_modified` bigint(20) NOT NULL COMMENT '修改時間',
      PRIMARY KEY (`id`),
      UNIQUE KEY `uk_tenant_info_kptenantid` (`kp`,`tenant_id`),
      KEY `idx_tenant_id` (`tenant_id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='tenant_info';

    CREATE TABLE `users` (
        `username` varchar(50) NOT NULL PRIMARY KEY,
        `password` varchar(500) NOT NULL,
        `enabled` boolean NOT NULL
    );

    CREATE TABLE `roles` (
        `username` varchar(50) NOT NULL,
        `role` varchar(50) NOT NULL,
        UNIQUE INDEX `idx_user_role` (`username` ASC, `role` ASC) USING BTREE
    );

    CREATE TABLE `permissions` (
        `role` varchar(50) NOT NULL,
        `resource` varchar(255) NOT NULL,
        `action` varchar(8) NOT NULL,
        UNIQUE INDEX `uk_role_permission` (`role`,`resource`,`action`) USING BTREE
    );

    INSERT INTO users (username, password, enabled) VALUES ('nacos', '$2a$10$EuWPZHzz32dJN7jexM34MOeYirDdFAZm2kuWj7VEOJhhZkDrxfvUu', TRUE);

    INSERT INTO roles (username, role) VALUES ('nacos', 'ROLE_ADMIN');
kind: ConfigMap
metadata:
  name: web-demo-initdb
  namespace: default

Kubevela 部署檔案deploy.yaml

apiVersion: core.oam.dev/v1beta1
kind: Application
metadata:
  name: web-demo
  namespace: default
spec:
  components:
    - name: redis
      type: myredis
      properties:
        serviceType: NodePort
    - name: mysql
      type: mysql
      properties:
        serviceType: NodePort
        database: nacos
        initdb: web-demo-initdb
    - name: nacos
      type: nacos
      properties:
        serviceType: NodePort
        mysql:
          host: web-demo-mysql-service.default.svc.cluster.local
    - name: alpha
      type: webservice
      properties:
        image: harbor.dev.wh.digitalchina.com/kubevela/labrador-service-alpha:latest
        port: 8090
      traits:
        - type: service-binding
          properties:
            envMappings:
              NACOS_SERVER_ADDR:
                secret: nacos-nacos-secret
                key: url
              DB_URL:
                secret: mysql-mysql-secret
                key: url
              DB_PASSWORD:
                secret: mysql-mysql-secret
                key: password
    - name: beta
      type: webservice
      properties:
        image: harbor.dev.wh.digitalchina.com/kubevela/labrador-service-beta:latest
        port: 9090
      traits:
        - type: service-binding
          properties:
            envMappings:
              NACOS_SERVER_ADDR:
                secret: nacos-nacos-secret
                key: url
              REDIS_IP:
                secret: redis-myredis-secret
                key: ip
              REDIS_PASSWORD:
                secret: redis-myredis-secret
                key: password
              REDIS_PORT:
                secret: redis-myredis-secret
                key: port
    - name: aggregation
      type: webservice
      properties:
        image: harbor.dev.wh.digitalchina.com/kubevela/labrador-service-aggregation:latest
        port: 8080
      traits:
        - type: service-binding
          properties:
            envMappings:
              NACOS_SERVER_ADDR:
                secret: nacos-nacos-secret
                key: url
    - name: service
      type: k8s-objects
      properties:
        objects:
        - apiVersion: v1
          kind: Service
          metadata:
            name: web
          labels:
            app: web
          spec:
            type: NodePort
            ports:
              - name: web
                port: 8080
                targetPort: 8080
                nodePort: 30080
            selector:
              app.oam.dev/component: aggregation

使用service-bindingsecret中的值,注入到pod的環境變數中

使用命令部署

# 部署
$ vela up -f deploy.yaml

# 檢視應用
$ vela ls

# 檢視應用狀態
$ vela status web-demo

登入nacos,服務成功註冊

登入aggregation 服務的knife4j頁面,呼叫介面

訪問資料庫成功

訪問redis成功