Commit dd0a6c66 authored by 智勇's avatar 智勇

服务接口更新为原生

parent fa769943
const Router = require('koa-router') const Router = require('koa-router')
const yaml = require('js-yaml')
const _ = require('lodash')
const logger = require('koa-log4').getLogger() const logger = require('koa-log4').getLogger()
const templates = require('../serviceTemplate')
const lruCache = require('../services/lruCache.service')
const { ingressCreate, ingressDelete } = require('../kubeService/ingress') const { ingressCreate, ingressDelete } = require('../kubeService/ingress')
const { projectConfig, defaultConfig } = require('../serviceTemplate/resourceLimit') const { projectConfig, defaultConfig } = require('../serviceTemplate/resourceLimit')
const { const {
podGet, serviceCreate, servicesGet, getPods, serviceCreate, getServices, getServiceDetail, serviceUpdate, serviceRestart, serviceDelete,
} = require('../kubeService/service') } = require('../kubeService/service')
const router = new Router() const router = new Router()
module.exports = router module.exports = router
const serviceListTencent = async (ctx) => {
// 取节点列表的第一个作为服务的访问ip
const cacheKey = 'k8s.nodes.first'
const c = lruCache.get(cacheKey)
let lanIp = lruCache.get(cacheKey)
if (!c) {
const res = await ctx.cluster.node_list()
lanIp = _.get(res, 'nodes[0].lanIp', '')
lruCache.set(cacheKey, lanIp)
}
const data = await ctx.cluster.service_list(ctx.query.namespace)
const podData = await podGet(ctx.query.namespace)
const getDetail = async (item) => {
const resData = await ctx.cluster.service_get(item.serviceName, ctx.query.namespace)
item.image = resData.service.containers[0].image
if (item.userLabels.type === 'base') {
item.portMappings = resData.service.portMappings
const pod = podData.body.items.filter(i => i.metadata.name.indexOf(item.serviceName) !== -1)
lanIp = pod[0].status.hostIP
item.lanIp = lanIp
}
}
const task = []
for (let i = 0; i < data.services.length; i += 1) {
task.push(getDetail(data.services[i]))
}
await Promise.all(task)
ctx.body = ctx.ok(data)
}
router.get('/', async (ctx) => { router.get('/', async (ctx) => {
const data = await servicesGet(ctx.query.namespace) const data = await getServices(ctx.query.namespace)
console.log(1, data)
ctx.body = ctx.ok({ services: data }) ctx.body = ctx.ok({ services: data })
}) })
const createService = async (ctx) => { const makeResouce = (serviceName, type) => {
const {
type, serviceName, namespace, domain, label,
} = ctx.request.body
logger.info('创建服务', ctx.request.body)
// 资源限制 // 资源限制
const resources = projectConfig[serviceName] || defaultConfig[type] const resources = projectConfig[serviceName] || defaultConfig[type]
logger.info('资源限制', JSON.stringify(resources)) logger.info('资源限制', JSON.stringify(resources))
return resources
const data = ctx.request.body
data.resources = resources
await serviceCreate(data)
if (label !== 'base') {
if (serviceName === 'xyqb-user2') {
await ingressCreate(namespace, 'xyqb-user2-2', 'passportapi2')
}
await ingressCreate(namespace, serviceName, domain)
}
ctx.body = ctx.ok('创建成功')
} }
const createServiceTencent = async (ctx) => { const createService = async (ctx) => {
const { const {
type, serviceName, namespace, system_name, domain, label, type, serviceName, namespace, domain, label,
} = ctx.request.body } = ctx.request.body
logger.info('创建服务', ctx.request.body)
// 资源限制
const resources = projectConfig[serviceName] || defaultConfig[type]
logger.info('资源限制', JSON.stringify(resources))
const data = ctx.request.body const data = ctx.request.body
const resources = makeResouce(serviceName, type)
data.resources = resources data.resources = resources
if (!system_name) { logger.info('创建服务', data)
// ui abTest的时候不一样 await serviceCreate(data)
data.system_name = serviceName
}
const template = templates[type].replace(/{{([A-Za-z0-9_\.]+)}}/g, function () {
if (_.get(data, arguments[1], null) === null) {
throw new Error(`缺少模板所需变量: ${arguments[1]}`)
}
return _.get(data, arguments[1])
})
let params = yaml.load(template)
// todo: 放开限制,暂时只更新了clotho的镜像
// java项目的就绪检查需要定制
if (type === 'java' && data.system_name !== 'clotho') {
params = _.omitBy(params, (value, key) => key.indexOf('healthCheck') !== -1)
}
logger.info(params)
await ctx.cluster.service_create(params, label)
if (label !== 'base') { if (label !== 'base') {
if (serviceName === 'xyqb-user2') { if (serviceName === 'xyqb-user2') {
await ingressCreate(namespace, 'xyqb-user2-2', 'passportapi2') await ingressCreate(namespace, 'xyqb-user2-2', 'passportapi2')
...@@ -129,17 +52,13 @@ router.post('/details', async (ctx) => { ...@@ -129,17 +52,13 @@ router.post('/details', async (ctx) => {
namespace: ctx.Joi.string().required(), namespace: ctx.Joi.string().required(),
})) }))
const podData = await podGet(ctx.request.body.namespace) const data = await getServiceDetail(ctx.request.body.namespace, ctx.request.body.serviceName)
// const lanIp = podData.body.items.filter(i => i.metadata.name.indexOf(ctx.request.body.serviceName) !== -1)[0].status.hostIP ctx.body = ctx.ok(data)
const serviceItems = podData.body.items.filter(i => i.metadata.name.indexOf(ctx.request.body.serviceName) !== -1)
const lanIp = _.get(serviceItems, '[0].status.hostIP', '')
const data = await ctx.cluster.service_get(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok(Object.assign({}, data, { lanIp }))
}) })
router.post('/delete', async (ctx) => { router.post('/delete', async (ctx) => {
await ctx.cluster.service_delete(ctx.request.body.serviceName, ctx.request.body.namespace) const rsName = ctx.request.body.podName.slice(0, -6)
await serviceDelete(ctx.request.body.namespace, ctx.request.body.serviceName, rsName)
if (ctx.request.body.serviceName === 'xyqb-user2') { if (ctx.request.body.serviceName === 'xyqb-user2') {
await ingressDelete(ctx.request.body.namespace, 'xyqb-user2-2') await ingressDelete(ctx.request.body.namespace, 'xyqb-user2-2')
} }
...@@ -148,22 +67,26 @@ router.post('/delete', async (ctx) => { ...@@ -148,22 +67,26 @@ router.post('/delete', async (ctx) => {
}) })
router.post('/modifyImage', async (ctx) => { router.post('/modifyImage', async (ctx) => {
let list = await ctx.cluster.service_list(ctx.request.body.namespace) let list = await getPods(ctx.request.body.namespace)
list = list.services.map(item => item.serviceName) list = list.map(item => (item.metadata.labels && item.metadata.labels['qcloud-app']) || item.metadata.name)
if (list.includes(ctx.request.body.serviceName)) { if (list.includes(ctx.request.body.serviceName)) {
await ctx.cluster.service_modifyImage(ctx.request.body.serviceName, ctx.request.body.image, ctx.request.body.namespace) const data = ctx.request.body
if (!data.label) {
data.label = data.type
}
const resources = makeResouce(data.serviceName, data.label)
data.resources = resources
logger.info('更新服务', data)
await serviceUpdate(data)
} else { } else {
await createService(ctx) await createService(ctx)
} }
ctx.body = ctx.ok('更新成功') ctx.body = ctx.ok('更新成功')
}) })
router.post('/instance', async (ctx) => {
const data = await ctx.cluster.instance_get(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok(data)
})
router.post('/redeploy', async (ctx) => { router.post('/redeploy', async (ctx) => {
await ctx.cluster.service_redeployment(ctx.request.body.serviceName, ctx.request.body.namespace) await serviceRestart(ctx.request.body.namespace, ctx.request.body.podName)
ctx.body = ctx.ok('服务重部署成功') ctx.body = ctx.ok('重置服务成功')
}) })
const Router = require('koa-router')
const yaml = require('js-yaml')
const _ = require('lodash')
const logger = require('koa-log4').getLogger()
const templates = require('../serviceTemplate')
const lruCache = require('../services/lruCache.service')
const { ingressCreate, ingressDelete } = require('../kubeService/ingress')
const { projectConfig, defaultConfig } = require('../serviceTemplate/resourceLimit')
const { podGet, serviceCreate } = require('../kubeService/service')
const router = new Router()
module.exports = router
router.get('/', async (ctx) => {
// 取节点列表的第一个作为服务的访问ip
const cacheKey = 'k8s.nodes.first'
const c = lruCache.get(cacheKey)
let lanIp = lruCache.get(cacheKey)
if (!c) {
const res = await ctx.cluster.node_list()
lanIp = _.get(res, 'nodes[0].lanIp', '')
lruCache.set(cacheKey, lanIp)
}
const data = await ctx.cluster.service_list(ctx.query.namespace)
const podData = await podGet(ctx.query.namespace)
const getDetail = async (item) => {
const resData = await ctx.cluster.service_get(item.serviceName, ctx.query.namespace)
item.image = resData.service.containers[0].image
if (item.userLabels.type === 'base') {
item.portMappings = resData.service.portMappings
const pod = podData.body.items.filter(i => i.metadata.name.indexOf(item.serviceName) !== -1)
lanIp = pod[0].status.hostIP
item.lanIp = lanIp
}
}
const task = []
for (let i = 0; i < data.services.length; i += 1) {
task.push(getDetail(data.services[i]))
}
await Promise.all(task)
ctx.body = ctx.ok(data)
})
const createService = async (ctx) => {
const {
type, serviceName, namespace, image, system_name, domain, label, debug,
} = ctx.request.body
logger.info('创建服务', ctx.request.body)
if (label === 'base') {
await serviceCreate(namespace, serviceName, image, label)
ctx.body = ctx.ok('创建成功')
return
}
const data = {
serviceName,
namespace,
image,
system_name,
debug,
}
if (!system_name) {
// ui abTest的时候不一样
data.system_name = serviceName
}
// 资源限制
const resources = projectConfig[data.system_name] || defaultConfig[type]
logger.info('资源限制', JSON.stringify(resources))
data.resources = resources
const template = templates[type].replace(/{{([A-Za-z0-9_\.]+)}}/g, function () {
if (_.get(data, arguments[1], null) === null) {
throw new Error(`缺少模板所需变量: ${arguments[1]}`)
}
return _.get(data, arguments[1])
})
let params = yaml.load(template)
// todo: 放开限制,暂时只更新了clotho的镜像
// java项目的就绪检查需要定制
if (type === 'java' && data.system_name !== 'clotho') {
params = _.omitBy(params, (value, key) => key.indexOf('healthCheck') !== -1)
}
logger.info(params)
await ctx.cluster.service_create(params, label)
if (label !== 'base') {
if (serviceName === 'xyqb-user2') {
await ingressCreate(namespace, 'xyqb-user2-2', 'passportapi2')
}
await ingressCreate(namespace, serviceName, domain)
}
ctx.body = ctx.ok('创建成功')
}
router.post('/create', async (ctx) => {
await createService(ctx)
})
router.post('/details', async (ctx) => {
ctx.validate(ctx.Joi.object().keys({
serviceName: ctx.Joi.string().required(),
namespace: ctx.Joi.string().required(),
}))
const podData = await podGet(ctx.request.body.namespace)
// const lanIp = podData.body.items.filter(i => i.metadata.name.indexOf(ctx.request.body.serviceName) !== -1)[0].status.hostIP
const serviceItems = podData.body.items.filter(i => i.metadata.name.indexOf(ctx.request.body.serviceName) !== -1)
const lanIp = _.get(serviceItems, '[0].status.hostIP', '')
const data = await ctx.cluster.service_get(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok(Object.assign({}, data, { lanIp }))
})
router.post('/delete', async (ctx) => {
await ctx.cluster.service_delete(ctx.request.body.serviceName, ctx.request.body.namespace)
if (ctx.request.body.serviceName === 'xyqb-user2') {
await ingressDelete(ctx.request.body.namespace, 'xyqb-user2-2')
}
await ingressDelete(ctx.request.body.namespace, ctx.request.body.serviceName)
ctx.body = ctx.ok('删除成功')
})
router.post('/modifyImage', async (ctx) => {
let list = await ctx.cluster.service_list(ctx.request.body.namespace)
list = list.services.map(item => item.serviceName)
if (list.includes(ctx.request.body.serviceName)) {
await ctx.cluster.service_modifyImage(ctx.request.body.serviceName, ctx.request.body.image, ctx.request.body.namespace)
} else {
await createService(ctx)
}
ctx.body = ctx.ok('更新成功')
})
router.post('/instance', async (ctx) => {
const data = await ctx.cluster.instance_get(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok(data)
})
router.post('/redeploy', async (ctx) => {
await ctx.cluster.service_redeployment(ctx.request.body.serviceName, ctx.request.body.namespace)
ctx.body = ctx.ok('服务重部署成功')
})
const commonService = ['db', 'redis', 'rabbitmq', 'zookeeper', 'kong', 'postgres', 'mongodb']
module.exports = {
commonService,
}
...@@ -2,9 +2,11 @@ const path = require('path') ...@@ -2,9 +2,11 @@ const path = require('path')
const Client = require('kubernetes-client').Client const Client = require('kubernetes-client').Client
const config = require('kubernetes-client').config const config = require('kubernetes-client').config
const _ = require('lodash') const _ = require('lodash')
const moment = require('moment')
const yaml = require('js-yaml') const yaml = require('js-yaml')
const logger = require('koa-log4').getLogger('kubeService') const logger = require('koa-log4').getLogger('kubeService')
const yamls = require('../yamls') const yamls = require('../yamls')
const dict = require('./dictService')
const client = new Client({ const client = new Client({
config: config.fromKubeconfig( config: config.fromKubeconfig(
...@@ -13,12 +15,11 @@ const client = new Client({ ...@@ -13,12 +15,11 @@ const client = new Client({
version: '1.10', version: '1.10',
}) })
const serviceGet = async (namespace, service) => client.api.v1.namespaces(namespace).services(service).get() const makeManifest = (data) => {
const podGet = async namespace => client.api.v1.namespaces(namespace).pods.get() if (!data.debug) {
data.debug = '"0"'
const serviceCreate = async (data) => { }
const { type, namespace, serviceName } = data const yamlManifest = yamls[data.type].replace(/{{([A-Za-z0-9_\.]+)}}/g, function () {
const yamlManifest = yamls[type].replace(/{{([A-Za-z0-9_\.]+)}}/g, function () {
if (_.get(data, arguments[1], null) === null) { if (_.get(data, arguments[1], null) === null) {
throw new Error(`缺少模板所需变量: ${arguments[1]}`) throw new Error(`缺少模板所需变量: ${arguments[1]}`)
} }
...@@ -26,6 +27,12 @@ const serviceCreate = async (data) => { ...@@ -26,6 +27,12 @@ const serviceCreate = async (data) => {
}) })
const yamlArray = yamlManifest.split('---') const yamlArray = yamlManifest.split('---')
return yamlArray
}
const serviceCreate = async (data) => {
const { namespace, serviceName } = data
const yamlArray = makeManifest(data)
for (const item of yamlArray) { for (const item of yamlArray) {
const jsonObj = yaml.load(item); const jsonObj = yaml.load(item);
...@@ -58,6 +65,19 @@ const serviceCreate = async (data) => { ...@@ -58,6 +65,19 @@ const serviceCreate = async (data) => {
} }
} }
const serviceUpdate = async (data) => {
const { namespace, serviceName } = data
const yamlArray = makeManifest(data)
for (const item of yamlArray) {
const jsonObj = yaml.load(item);
if (jsonObj.kind === 'Deployment') {
logger.info('Deployment:', JSON.stringify(jsonObj))
await client.apis.apps.v1beta1.namespaces(namespace).deployments(serviceName).put({ body: jsonObj })
}
}
}
const formatServiceInfo = (obj) => { const formatServiceInfo = (obj) => {
const portObj = {} const portObj = {}
obj.spec.ports.forEach((i) => { obj.spec.ports.forEach((i) => {
...@@ -66,27 +86,49 @@ const formatServiceInfo = (obj) => { ...@@ -66,27 +86,49 @@ const formatServiceInfo = (obj) => {
return _.assign(portObj, { return _.assign(portObj, {
clusterIp: obj.spec.clusterIP, clusterIp: obj.spec.clusterIP,
ports: obj.spec.ports, portMappings: obj.spec.ports,
userLabels: obj.metadata.labels, // labels: obj.metadata.labels,
}) })
} }
const getPodStatus = (podInfo) => {
if (podInfo.status.phase === 'Pending') {
return 'Pending'
}
if (podInfo.status.conditions[2].status === 'False') {
return 'PodScheduling'
}
if (podInfo.status.conditions[0].status === 'False') {
return 'Initializing'
}
if (podInfo.status.conditions[1].status === 'False') {
return 'Waiting'
}
if (podInfo.metadata.deletionTimestamp) {
return 'Terminating'
}
return 'Normal'
}
const formatPodInfo = (podInfo) => { const formatPodInfo = (podInfo) => {
const podStatus = podInfo.status.phase === 'Running' && podInfo.status.conditions.every(i => i.status === 'True') // if (podInfo.metadata.name.indexOf('xyqb') !== -1) {
? 'Running' : 'Pending' // console.log(1, JSON.stringify(podInfo), podInfo.metadata.labels['qcloud-app'])
// }
const podStatus = getPodStatus(podInfo)
const containerImage = _.get(podInfo.status.containerStatuses, '[0].image', '') // const containerImage = _.get(podInfo.status.containerStatuses, '[0].image', '')
const containerImage = _.get(podInfo.spec.containers, '[0].image', '')
const ret = { const ret = {
serviceName: (podInfo.metadata.labels && podInfo.metadata.labels['qcloud-app']) || podInfo.metadata.name, serviceName: (podInfo.metadata.labels && podInfo.metadata.labels['qcloud-app']) || podInfo.metadata.name,
type: podInfo.metadata.labels.tier, podName: podInfo.metadata.name,
pod_name: podInfo.metadata.name, status: podStatus,
pod_status: podStatus, podIp: podInfo.status.podIP,
pod_ip: podInfo.status.podIP, lanIp: podInfo.status.hostIP,
host_ip: podInfo.status.hostIP, startTime: podInfo.status.startTime,
start_time: podInfo.status.startTime, createdAt: moment(new Date(podInfo.status.startTime)).startOf('minute').fromNow(),
// live: moment(new Date(podInfo.status.startTime)).startOf('minute').fromNow(),
image: containerImage, image: containerImage,
labels: podInfo.metadata.labels,
} }
if (containerImage !== '') { if (containerImage !== '') {
...@@ -98,15 +140,19 @@ const formatPodInfo = (podInfo) => { ...@@ -98,15 +140,19 @@ const formatPodInfo = (podInfo) => {
return ret return ret
} }
const formatIngressInfo = obj => ({ host: obj.spec && obj.spec.rules && obj.spec.rules[0].host }) const formatIngressInfo = obj => ({ host: _.get(obj.spec, 'rules[0].host', '') })
const getPods = async (namespace) => {
const podData = await client.api.v1.namespaces(namespace).pods.get()
return podData.body.items
}
const servicesGet = async (namespace) => { const getServices = async (namespace) => {
const ret = [] const ret = []
const service = {} const service = {}
const res = await Promise.all([ const res = await Promise.all([
client.api.v1.namespaces(namespace).pods.get(), client.api.v1.namespaces(namespace).pods.get(),
// client.api.v1.namespaces(namespace).pods.get({ qs: { labelSelector: 'tier!=job' } }),
client.api.v1.namespaces(namespace).services.get(), client.api.v1.namespaces(namespace).services.get(),
client.apis.extensions.v1beta1.namespaces(namespace).ingresses.get(), client.apis.extensions.v1beta1.namespaces(namespace).ingresses.get(),
]) ])
...@@ -118,7 +164,6 @@ const servicesGet = async (namespace) => { ...@@ -118,7 +164,6 @@ const servicesGet = async (namespace) => {
res[1].body.items.forEach(async (item) => { res[1].body.items.forEach(async (item) => {
console.log(2, item)
if (service[item.metadata.name]) { if (service[item.metadata.name]) {
service[item.metadata.name] = _.assign(service[item.metadata.name], formatServiceInfo(item)) service[item.metadata.name] = _.assign(service[item.metadata.name], formatServiceInfo(item))
} }
...@@ -139,9 +184,39 @@ const servicesGet = async (namespace) => { ...@@ -139,9 +184,39 @@ const servicesGet = async (namespace) => {
return ret return ret
} }
const getServiceDetail = async (namespace, name) => {
const res = await Promise.all([
client.api.v1.namespaces(namespace).pods.get({ qs: { labelSelector: `qcloud-app=${name},tier!=job` } }),
client.api.v1.namespaces(namespace).services(name).get(),
])
res[0] = formatPodInfo(res[0].body.items[0])
res[1] = formatServiceInfo(res[1].body)
if (!dict.commonService.includes(name)) {
res[3] = await client.apis.extensions.v1beta1.namespaces(namespace).ingresses(name).get()
res[3] = formatIngressInfo(res[3].body)
}
return _.assign({}, res[0], res[3], res[1])
}
const serviceRestart = async (namespace, name) => {
await client.api.v1.namespaces(namespace).pods(name).delete()
}
const serviceDelete = async (namespace, name, rsName) => {
await client.apis.apps.v1beta1.namespaces(namespace).deployments(name).delete()
await client.apis.apps.v1.namespaces(namespace).replicasets(rsName).delete()
await client.api.v1.namespaces(namespace).services(name).delete()
}
module.exports = { module.exports = {
serviceGet, getServiceDetail,
servicesGet, getServices,
podGet, getPods,
serviceCreate, serviceCreate,
serviceUpdate,
serviceRestart,
serviceDelete,
} }
...@@ -3092,6 +3092,11 @@ ...@@ -3092,6 +3092,11 @@
} }
} }
}, },
"moment": {
"version": "2.24.0",
"resolved": "http://npmprivate.quantgroups.com/moment/-/moment-2.24.0.tgz",
"integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg=="
},
"ms": { "ms": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz", "resolved": "http://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz",
......
...@@ -13,6 +13,7 @@ ...@@ -13,6 +13,7 @@
"kubernetes-client": "^6.3.2", "kubernetes-client": "^6.3.2",
"lodash": "^4.17.11", "lodash": "^4.17.11",
"lru-cache": "^5.1.1", "lru-cache": "^5.1.1",
"moment": "^2.24.0",
"request": "^2.88.0" "request": "^2.88.0"
}, },
"devDependencies": { "devDependencies": {
......
...@@ -16,9 +16,11 @@ spec: ...@@ -16,9 +16,11 @@ spec:
template: template:
metadata: metadata:
labels: labels:
type: {{label}}
qcloud-app: {{serviceName}} qcloud-app: {{serviceName}}
type: {{label}} type: {{label}}
spec: spec:
terminationGracePeriodSeconds: 0
revisionHistoryLimit: 1 revisionHistoryLimit: 1
containers: containers:
- name: {{serviceName}} - name: {{serviceName}}
......
...@@ -33,6 +33,7 @@ spec: ...@@ -33,6 +33,7 @@ spec:
metadata: metadata:
labels: labels:
qcloud-app: {{serviceName}} qcloud-app: {{serviceName}}
type: base
spec: spec:
containers: containers:
- image: ccr.ccs.tencentyun.com/{{image}} - image: ccr.ccs.tencentyun.com/{{image}}
......
...@@ -33,6 +33,7 @@ spec: ...@@ -33,6 +33,7 @@ spec:
metadata: metadata:
labels: labels:
qcloud-app: {{serviceName}} qcloud-app: {{serviceName}}
type: base
spec: spec:
# hostname固定,容器重置后数据持久化才能正常 # hostname固定,容器重置后数据持久化才能正常
hostname: {{serviceName}}-{{namespace}} hostname: {{serviceName}}-{{namespace}}
......
...@@ -32,6 +32,7 @@ spec: ...@@ -32,6 +32,7 @@ spec:
template: template:
metadata: metadata:
labels: labels:
type: base
qcloud-app: {{serviceName}} qcloud-app: {{serviceName}}
spec: spec:
containers: containers:
......
...@@ -19,6 +19,7 @@ spec: ...@@ -19,6 +19,7 @@ spec:
qcloud-app: {{serviceName}} qcloud-app: {{serviceName}}
type: {{label}} type: {{label}}
spec: spec:
terminationGracePeriodSeconds: 0
revisionHistoryLimit: 1 revisionHistoryLimit: 1
containers: containers:
- name: {{serviceName}} - name: {{serviceName}}
......
...@@ -33,6 +33,7 @@ spec: ...@@ -33,6 +33,7 @@ spec:
metadata: metadata:
labels: labels:
qcloud-app: {{serviceName}} qcloud-app: {{serviceName}}
type: base
spec: spec:
containers: containers:
- image: ccr.ccs.tencentyun.com/{{image}} - image: ccr.ccs.tencentyun.com/{{image}}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment