This is an automated email from the ASF dual-hosted git repository.

caishunfeng pushed a commit to branch dev
in repository https://gitbox.apache.org/repos/asf/dolphinscheduler.git


The following commit(s) were added to refs/heads/dev by this push:
     new 1511005  [Feature][api] Task can run on kubernetes - k8s client and 
namespace #8247 (#8252)
1511005 is described below

commit 151100562f9e2751426ccca08aa71451a3f1614b
Author: qianli2022 <[email protected]>
AuthorDate: Tue Feb 15 10:21:15 2022 +0800

    [Feature][api] Task can run on kubernetes - k8s client and namespace #8247 
(#8252)
    
    * add db operator for namespace
    
    * add k8s client
    
    * add k8s controller
    
    * add namespace ui
    
    * add licenses
    
    * add kubernetes model known-dependencies
    
    * add new licenses
    
    * fix SonarCloud Code Analysis bug
    
    * remove license for standard protocol
    
    * fix variable MemoryStr to memoryStr
    
    Co-authored-by: qianl4 <[email protected]>
---
 .../api/controller/K8sNamespaceController.java     | 214 ++++++++++++++
 .../apache/dolphinscheduler/api/enums/Status.java  |   9 +
 .../api/service/K8sNameSpaceService.java           |  85 ++++++
 .../api/service/impl/K8sNameSpaceServiceImpl.java  | 326 +++++++++++++++++++++
 .../api/controller/K8sNamespaceControllerTest.java | 155 ++++++++++
 .../api/service/K8sNameSpaceServiceTest.java       | 189 ++++++++++++
 .../apache/dolphinscheduler/common/Constants.java  |   7 +
 .../apache/dolphinscheduler/dao/entity/K8s.java    | 103 +++++++
 .../dolphinscheduler/dao/entity/K8sNamespace.java  | 197 +++++++++++++
 .../dolphinscheduler/dao/mapper/K8sMapper.java     |  29 ++
 .../dao/mapper/K8sNamespaceMapper.java             |  49 ++++
 .../dao/mapper/K8sNamespaceMapper.xml              |  48 +++
 .../src/main/resources/sql/dolphinscheduler_h2.sql |  39 ++-
 .../main/resources/sql/dolphinscheduler_mysql.sql  |  37 ++-
 .../resources/sql/dolphinscheduler_postgresql.sql  |  39 ++-
 .../2.1.0_schema/mysql/dolphinscheduler_ddl.sql    |  36 +++
 .../postgresql/dolphinscheduler_ddl.sql            |  26 ++
 dolphinscheduler-dist/release-docs/LICENSE         |  28 ++
 .../release-docs/licenses/LICENSE-automaton.txt    |  24 ++
 .../e2e/pages/security/NamespacePage.java          |  94 ++++++
 .../e2e/pages/security/SecurityPage.java           |   7 +
 dolphinscheduler-service/pom.xml                   |   4 +
 .../service/k8s/K8sClientService.java              | 118 ++++++++
 .../dolphinscheduler/service/k8s/K8sManager.java   |  86 ++++++
 .../service/k8s/K8sManagerTest.java                |  78 +++++
 .../pages/namespace/_source/createNamespace.vue    | 219 ++++++++++++++
 .../security/pages/namespace/_source/list.vue      | 110 +++++++
 .../home/pages/security/pages/namespace/index.vue  | 160 ++++++++++
 .../src/js/conf/home/router/module/security.js     |   8 +
 .../src/js/conf/home/store/security/actions.js     |  63 ++++
 .../components/secondaryMenu/_source/menu.js       |  10 +
 .../src/js/module/i18n/locale/en_US.js             |  16 +-
 .../src/js/module/i18n/locale/zh_CN.js             |  16 +-
 pom.xml                                            |   7 +
 tools/dependencies/known-dependencies.txt          |  28 ++
 35 files changed, 2659 insertions(+), 5 deletions(-)

diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java
new file mode 100644
index 0000000..ddae560
--- /dev/null
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceController.java
@@ -0,0 +1,214 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.api.controller;
+
+import static 
org.apache.dolphinscheduler.api.enums.Status.CREATE_K8S_NAMESPACE_ERROR;
+import static 
org.apache.dolphinscheduler.api.enums.Status.DELETE_K8S_NAMESPACE_BY_ID_ERROR;
+import static 
org.apache.dolphinscheduler.api.enums.Status.QUERY_K8S_NAMESPACE_LIST_PAGING_ERROR;
+import static 
org.apache.dolphinscheduler.api.enums.Status.UPDATE_K8S_NAMESPACE_ERROR;
+import static 
org.apache.dolphinscheduler.api.enums.Status.VERIFY_K8S_NAMESPACE_ERROR;
+
+import org.apache.dolphinscheduler.api.aspect.AccessLogAnnotation;
+import org.apache.dolphinscheduler.api.exceptions.ApiException;
+import org.apache.dolphinscheduler.api.service.K8sNameSpaceService;
+import org.apache.dolphinscheduler.api.utils.Result;
+import org.apache.dolphinscheduler.common.Constants;
+import org.apache.dolphinscheduler.common.utils.ParameterUtils;
+import org.apache.dolphinscheduler.dao.entity.User;
+
+import java.util.Map;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestAttribute;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.ResponseStatus;
+import org.springframework.web.bind.annotation.RestController;
+
+import io.swagger.annotations.Api;
+import io.swagger.annotations.ApiImplicitParam;
+import io.swagger.annotations.ApiImplicitParams;
+import io.swagger.annotations.ApiOperation;
+import springfox.documentation.annotations.ApiIgnore;
+
+/**
+ * k8s namespace controller
+ */
+@Api(tags = "K8S_NAMESPACE_TAG")
+@RestController
+@RequestMapping("/k8s-namespace")
+public class K8sNamespaceController extends BaseController {
+
+    @Autowired
+    private K8sNameSpaceService k8sNameSpaceService;
+
+    /**
+     * query namespace list paging
+     *
+     * @param loginUser login user
+     * @param searchVal search value
+     * @param pageSize  page size
+     * @param pageNo    page number
+     * @return namespace list which the login user have permission to see
+     */
+    @ApiOperation(value = "queryNamespaceListPaging", notes = 
"QUERY_NAMESPACE_LIST_PAGING_NOTES")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "searchVal", value = "SEARCH_VAL", 
dataType = "String"),
+            @ApiImplicitParam(name = "pageSize", value = "PAGE_SIZE", required 
= true, dataType = "Int", example = "10"),
+            @ApiImplicitParam(name = "pageNo", value = "PAGE_NO", required = 
true, dataType = "Int", example = "1")
+    })
+    @GetMapping()
+    @ResponseStatus(HttpStatus.OK)
+    @ApiException(QUERY_K8S_NAMESPACE_LIST_PAGING_ERROR)
+    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
+    public Result queryProjectListPaging(@ApiIgnore @RequestAttribute(value = 
Constants.SESSION_USER) User loginUser,
+                                         @RequestParam(value = "searchVal", 
required = false) String searchVal,
+                                         @RequestParam("pageSize") Integer 
pageSize,
+                                         @RequestParam("pageNo") Integer pageNo
+    ) {
+
+        Result result = checkPageParams(pageNo, pageSize);
+        if (!result.checkResult()) {
+            return result;
+        }
+        searchVal = ParameterUtils.handleEscapes(searchVal);
+        result = k8sNameSpaceService.queryListPaging(loginUser, searchVal, 
pageNo, pageSize);
+        return result;
+    }
+
+
+    /**
+     * create namespace,if not exist on k8s,will create,if exist only register 
in db
+     *
+     * @param loginUser
+     * @param namespace    k8s namespace
+     * @param owner        owner
+     * @param tag          Which type of job is available, can be empty, all 
available
+     * @param k8s          k8s name
+     * @param limitsCpu    max cpu
+     * @param limitsMemory max memory
+     * @return
+     */
+    @ApiOperation(value = "createK8sNamespace", notes = 
"CREATE_NAMESPACE_NOTES")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "namespace", value = "NAMESPACE", 
required = true, dataType = "String"),
+            @ApiImplicitParam(name = "owner", value = "OWNER", required = 
false, dataType = "String"),
+            @ApiImplicitParam(name = "tag", value = "TAG", required = false, 
dataType = "String"),
+            @ApiImplicitParam(name = "k8s", value = "K8S", required = true, 
dataType = "String"),
+            @ApiImplicitParam(name = "limits_cpu", value = "LIMITS_CPU", 
required = false, dataType = "Double"),
+            @ApiImplicitParam(name = "limits_memory", value = "LIMITS_MEMORY", 
required = false, dataType = "Integer")
+    })
+    @PostMapping()
+    @ResponseStatus(HttpStatus.CREATED)
+    @ApiException(CREATE_K8S_NAMESPACE_ERROR)
+    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
+    public Result createNamespace(@ApiIgnore @RequestAttribute(value = 
Constants.SESSION_USER) User loginUser,
+                                  @RequestParam(value = "namespace") String 
namespace,
+                                  @RequestParam(value = "k8s") String k8s,
+                                  @RequestParam(value = "owner", required = 
false) String owner,
+                                  @RequestParam(value = "tag", required = 
false) String tag,
+                                  @RequestParam(value = "limitsCpu", required 
= false) Double limitsCpu,
+                                  @RequestParam(value = "limitsMemory", 
required = false) Integer limitsMemory
+    ) {
+        Map<String, Object> result =  
k8sNameSpaceService.createK8sNamespace(loginUser, namespace, k8s, owner, tag, 
limitsCpu, limitsMemory);
+        return returnDataList(result);
+    }
+
+    /**
+     * update namespace,namespace and k8s not allowed update, because may 
create on k8s,can delete and create new instead
+     *
+     * @param loginUser
+     * @param owner        owner
+     * @param tag          Which type of job is available,such as flink,means 
only flink job can use, can be empty, all available
+     * @param limitsCpu    max cpu
+     * @param limitsMemory max memory
+     * @return
+     */
+    @ApiOperation(value = "updateK8sNamespace", notes = 
"UPDATE_NAMESPACE_NOTES")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "K8S_NAMESPACE_ID", 
required = true, dataType = "Int", example = "100"),
+            @ApiImplicitParam(name = "owner", value = "OWNER", required = 
false, dataType = "String"),
+            @ApiImplicitParam(name = "tag", value = "TAG", required = false, 
dataType = "String"),
+            @ApiImplicitParam(name = "limitsCpu", value = "LIMITS_CPU", 
required = false, dataType = "Double"),
+            @ApiImplicitParam(name = "limitsMemory", value = "LIMITS_MEMORY", 
required = false, dataType = "Integer")})
+    @PutMapping(value = "/{id}")
+    @ResponseStatus(HttpStatus.CREATED)
+    @ApiException(UPDATE_K8S_NAMESPACE_ERROR)
+    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
+    public Result updateNamespace(@ApiIgnore @RequestAttribute(value = 
Constants.SESSION_USER) User loginUser,
+                                  @PathVariable(value = "id") int id,
+                                  @RequestParam(value = "owner", required = 
false) String owner,
+                                  @RequestParam(value = "tag", required = 
false) String tag,
+                                  @RequestParam(value = "limitsCpu", required 
= false) Double limitsCpu,
+                                  @RequestParam(value = "limitsMemory", 
required = false) Integer limitsMemory) {
+        Map<String, Object> result = 
k8sNameSpaceService.updateK8sNamespace(loginUser, id, owner, tag, limitsCpu, 
limitsMemory);
+        return returnDataList(result);
+    }
+
+    /**
+     * verify namespace and k8s,one k8s namespace is unique
+     *
+     * @param loginUser login user
+     * @param namespace namespace
+     * @param k8s       k8s
+     * @return true if the k8s and namespace not exists, otherwise return false
+     */
+    @ApiOperation(value = "verifyNamespaceK8s", notes = 
"VERIFY_NAMESPACE_K8S_NOTES")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "namespace", value = "NAMESPACE", 
required = true, dataType = "String"),
+            @ApiImplicitParam(name = "k8s", value = "K8S", required = true, 
dataType = "String")
+    })
+    @PostMapping(value = "/verify")
+    @ResponseStatus(HttpStatus.OK)
+    @ApiException(VERIFY_K8S_NAMESPACE_ERROR)
+    @AccessLogAnnotation(ignoreRequestArgs = "loginUser")
+    public Result verifyNamespace(@ApiIgnore @RequestAttribute(value = 
Constants.SESSION_USER) User loginUser,
+                                  @RequestParam(value = "namespace") String 
namespace,
+                                  @RequestParam(value = "k8s") String k8s
+    ) {
+
+        return k8sNameSpaceService.verifyNamespaceK8s(namespace, k8s);
+    }
+
+
+    /**
+     * delete namespace by id
+     *
+     * @param loginUser login user
+     * @param id        namespace id
+     * @return delete result code
+     */
+    @ApiOperation(value = "delNamespaceById", notes = 
"DELETE_NAMESPACE_BY_ID_NOTES")
+    @ApiImplicitParams({
+            @ApiImplicitParam(name = "id", value = "NAMESPACE_ID", required = 
true, dataType = "Int", example = "100")
+    })
+    @PostMapping(value = "/delete")
+    @ResponseStatus(HttpStatus.OK)
+    @ApiException(DELETE_K8S_NAMESPACE_BY_ID_ERROR)
+    @AccessLogAnnotation
+    public Result delNamespaceById(@ApiIgnore @RequestAttribute(value = 
Constants.SESSION_USER) User loginUser,
+                                   @RequestParam(value = "id") int id) {
+        Map<String, Object> result = 
k8sNameSpaceService.deleteNamespaceById(loginUser, id);
+        return returnDataList(result);
+    }
+}
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java
index 5bb6a2f..1f6add9 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/enums/Status.java
@@ -380,6 +380,15 @@ public enum Status {
     TASK_GROUP_STATUS_OPENED(130019,"The task group has been 
opened.","任务组已经被开启"),
     NOT_ALLOW_TO_DISABLE_OWN_ACCOUNT(130020, "Not allow to disable your own 
account", "不能停用自己的账号"),
     NOT_ALLOW_TO_DELETE_DEFAULT_ALARM_GROUP(130030, "Not allow to delete the 
default alarm group ", "不能删除默认告警组"),
+
+    QUERY_K8S_NAMESPACE_LIST_PAGING_ERROR(1300001, "login user query k8s 
namespace list paging error", "分页查询k8s名称空间列表错误"),
+    K8S_NAMESPACE_EXIST(1300002, "k8s namespace {0} already exists", 
"k8s命名空间[{0}]已存在"),
+    CREATE_K8S_NAMESPACE_ERROR(1300003, "create k8s namespace error", 
"创建k8s命名空间错误"),
+    UPDATE_K8S_NAMESPACE_ERROR(1300004, "update k8s namespace error", 
"更新k8s命名空间信息错误"),
+    K8S_NAMESPACE_NOT_EXIST(1300005, "k8s namespace {0} not exists", 
"命名空间ID[{0}]不存在"),
+    K8S_CLIENT_OPS_ERROR(1300006, "k8s error with exception {0}", 
"k8s操作报错[{0}]"),
+    VERIFY_K8S_NAMESPACE_ERROR(1300007, "verify k8s and namespace error", 
"验证k8s命名空间信息错误"),
+    DELETE_K8S_NAMESPACE_BY_ID_ERROR(1300008, "delete k8s namespace by id 
error", "删除命名空间错误"),
     ;
 
     private final int code;
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/K8sNameSpaceService.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/K8sNameSpaceService.java
new file mode 100644
index 0000000..c9156a3
--- /dev/null
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/K8sNameSpaceService.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.api.service;
+
+import org.apache.dolphinscheduler.api.utils.Result;
+import org.apache.dolphinscheduler.dao.entity.User;
+
+import java.util.Map;
+
+/**
+ * k8s namespace service impl
+ */
+public interface K8sNameSpaceService {
+    /**
+     * query namespace list paging
+     *
+     * @param loginUser login user
+     * @param pageNo    page number
+     * @param searchVal search value
+     * @param pageSize  page size
+     * @return k8s namespace list
+     */
+    Result queryListPaging(User loginUser, String searchVal, Integer pageNo, 
Integer pageSize);
+
+
+    /**
+     * create namespace,if not exist on k8s,will create,if exist only register 
in db
+     *
+     * @param loginUser    login user
+     * @param namespace    namespace
+     * @param k8s          k8s not null
+     * @param owner        owner can null
+     * @param tag          can null,if set means just used for one type 
job,such as flink,spark
+     * @param limitsCpu    limits cpu, can null means not limit
+     * @param limitsMemory limits memory, can null means not limit
+     * @return
+     */
+    Map<String, Object> createK8sNamespace(User loginUser, String namespace, 
String k8s, String owner, String tag, Double limitsCpu, Integer limitsMemory);
+
+
+    /**
+     * update K8s Namespace tag and resource limit
+     *
+     * @param loginUser    login user
+     * @param owner        owner
+     * @param tag          Which type of job is available,such as flink,means 
only flink job can use, can be empty, all available
+     * @param limitsCpu    max cpu
+     * @param limitsMemory max memory
+     * @return
+     */
+    Map<String, Object> updateK8sNamespace(User loginUser, int id, String 
owner, String tag, Double limitsCpu, Integer limitsMemory);
+
+    /**
+     * verify namespace and k8s
+     *
+     * @param namespace namespace
+     * @param k8s       k8s
+     * @return true if the k8s and namespace not exists, otherwise return false
+     */
+    Result<Object> verifyNamespaceK8s(String namespace, String k8s);
+
+    /**
+     * delete namespace by id
+     *
+     * @param loginUser login user
+     * @param id        namespace id
+     * @return
+     */
+    Map<String, Object> deleteNamespaceById(User loginUser, int id);
+}
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/K8sNameSpaceServiceImpl.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/K8sNameSpaceServiceImpl.java
new file mode 100644
index 0000000..faa8a24
--- /dev/null
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/impl/K8sNameSpaceServiceImpl.java
@@ -0,0 +1,326 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.api.service.impl;
+
+import org.apache.dolphinscheduler.api.enums.Status;
+import org.apache.dolphinscheduler.api.service.K8sNameSpaceService;
+import org.apache.dolphinscheduler.api.utils.PageInfo;
+import org.apache.dolphinscheduler.api.utils.Result;
+import org.apache.dolphinscheduler.common.Constants;
+import org.apache.dolphinscheduler.dao.entity.K8sNamespace;
+import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.dao.mapper.K8sNamespaceMapper;
+import org.apache.dolphinscheduler.service.k8s.K8sClientService;
+
+import org.apache.commons.lang.StringUtils;
+
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+/**
+ * k8s namespace service impl
+ */
+@Service
+public class K8sNameSpaceServiceImpl extends BaseServiceImpl implements 
K8sNameSpaceService {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(K8sNameSpaceServiceImpl.class);
+
+    private static String resourceYaml = "apiVersion: v1\n"
+        + "kind: ResourceQuota\n"
+        + "metadata:\n"
+        + "  name: ${name}\n"
+        + "  namespace: ${namespace}\n"
+        + "spec:\n"
+        + "  hard:\n"
+        + "    ${limitCpu}\n"
+        + "    ${limitMemory}\n";
+    @Autowired
+    private K8sNamespaceMapper k8sNamespaceMapper;
+    @Autowired
+    private K8sClientService k8sClientService;
+
+    /**
+     * query namespace list paging
+     *
+     * @param loginUser login user
+     * @param pageNo    page number
+     * @param searchVal search value
+     * @param pageSize  page size
+     * @return k8s namespace list
+     */
+    @Override
+    public Result queryListPaging(User loginUser, String searchVal, Integer 
pageNo, Integer pageSize) {
+        Result result = new Result();
+        if (!isAdmin(loginUser)) {
+            putMsg(result, Status.USER_NO_OPERATION_PERM);
+            return result;
+        }
+
+        Page<K8sNamespace> page = new Page<>(pageNo, pageSize);
+
+        IPage<K8sNamespace> k8sNamespaceList = 
k8sNamespaceMapper.queryK8sNamespacePaging(page, searchVal);
+
+        Integer count = (int) k8sNamespaceList.getTotal();
+        PageInfo<K8sNamespace> pageInfo = new PageInfo<>(pageNo, pageSize);
+        pageInfo.setTotal(count);
+        pageInfo.setTotalList(k8sNamespaceList.getRecords());
+        result.setData(pageInfo);
+        putMsg(result, Status.SUCCESS);
+
+        return result;
+    }
+
+    /**
+     * create namespace,if not exist on k8s,will create,if exist only register 
in db
+     *
+     * @param loginUser    login user
+     * @param namespace    namespace
+     * @param k8s          k8s not null
+     * @param owner        owner can null
+     * @param tag          can null,if set means just used for one type 
job,such as flink,spark
+     * @param limitsCpu    limits cpu, can null means not limit
+     * @param limitsMemory limits memory, can null means not limit
+     * @return
+     */
+    @Override
+    public Map<String, Object> createK8sNamespace(User loginUser, String 
namespace, String k8s, String owner, String tag, Double limitsCpu, Integer 
limitsMemory) {
+        Map<String, Object> result = new HashMap<>();
+        if (isNotAdmin(loginUser, result)) {
+            return result;
+        }
+
+        if (StringUtils.isEmpty(namespace)) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.NAMESPACE);
+            return result;
+        }
+
+        if (StringUtils.isEmpty(k8s)) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.K8S);
+            return result;
+        }
+
+        if (limitsCpu != null && limitsCpu < 0.0) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.LIMITS_CPU);
+            return result;
+        }
+
+        if (limitsMemory != null && limitsMemory < 0) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.LIMITS_MEMORY);
+            return result;
+        }
+
+        if (checkNamespaceExistInDb(namespace, k8s)) {
+            putMsg(result, Status.K8S_NAMESPACE_EXIST, namespace, k8s);
+            return result;
+        }
+
+        K8sNamespace k8sNamespaceObj = new K8sNamespace();
+        Date now = new Date();
+
+        k8sNamespaceObj.setNamespace(namespace);
+        k8sNamespaceObj.setK8s(k8s);
+        k8sNamespaceObj.setOwner(owner);
+        k8sNamespaceObj.setTag(tag);
+        k8sNamespaceObj.setLimitsCpu(limitsCpu);
+        k8sNamespaceObj.setLimitsMemory(limitsMemory);
+        k8sNamespaceObj.setOnlineJobNum(0);
+        k8sNamespaceObj.setPodReplicas(0);
+        k8sNamespaceObj.setPodRequestCpu(0.0);
+        k8sNamespaceObj.setPodRequestMemory(0);
+        k8sNamespaceObj.setCreateTime(now);
+        k8sNamespaceObj.setUpdateTime(now);
+
+        try {
+            String yamlStr = genDefaultResourceYaml(k8sNamespaceObj);
+            k8sClientService.upsertNamespaceAndResourceToK8s(k8sNamespaceObj, 
yamlStr);
+        } catch (Exception e) {
+            logger.error("namespace create to k8s error", e);
+            putMsg(result, Status.K8S_CLIENT_OPS_ERROR, e.getMessage());
+            return result;
+        }
+
+        k8sNamespaceMapper.insert(k8sNamespaceObj);
+        putMsg(result, Status.SUCCESS);
+
+        return result;
+    }
+
+    /**
+     * update K8s Namespace tag and resource limit
+     *
+     * @param loginUser    login user
+     * @param owner        owner
+     * @param tag          Which type of job is available,such as flink,means 
only flink job can use, can be empty, all available
+     * @param limitsCpu    max cpu
+     * @param limitsMemory max memory
+     * @return
+     */
+    @Override
+    public Map<String, Object> updateK8sNamespace(User loginUser, int id, 
String owner, String tag, Double limitsCpu, Integer limitsMemory) {
+        Map<String, Object> result = new HashMap<>();
+        if (isNotAdmin(loginUser, result)) {
+            return result;
+        }
+
+        if (limitsCpu != null && limitsCpu < 0.0) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.LIMITS_CPU);
+            return result;
+        }
+
+        if (limitsMemory != null && limitsMemory < 0) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.LIMITS_MEMORY);
+            return result;
+        }
+
+        K8sNamespace k8sNamespaceObj = k8sNamespaceMapper.selectById(id);
+        if (k8sNamespaceObj == null) {
+            putMsg(result, Status.K8S_NAMESPACE_NOT_EXIST, id);
+            return result;
+        }
+
+        Date now = new Date();
+        k8sNamespaceObj.setTag(tag);
+        k8sNamespaceObj.setLimitsCpu(limitsCpu);
+        k8sNamespaceObj.setLimitsMemory(limitsMemory);
+        k8sNamespaceObj.setUpdateTime(now);
+        k8sNamespaceObj.setOwner(owner);
+        try {
+            String yamlStr = genDefaultResourceYaml(k8sNamespaceObj);
+            k8sClientService.upsertNamespaceAndResourceToK8s(k8sNamespaceObj, 
yamlStr);
+        } catch (Exception e) {
+            logger.error("namespace update to k8s error", e);
+            putMsg(result, Status.K8S_CLIENT_OPS_ERROR, e.getMessage());
+            return result;
+        }
+        // update to db
+        k8sNamespaceMapper.updateById(k8sNamespaceObj);
+
+        putMsg(result, Status.SUCCESS);
+        return result;
+    }
+
+    /**
+     * verify namespace and k8s
+     *
+     * @param namespace namespace
+     * @param k8s       k8s
+     * @return true if the k8s and namespace not exists, otherwise return false
+     */
+    @Override
+    public Result<Object> verifyNamespaceK8s(String namespace, String k8s) {
+        Result<Object> result = new Result<>();
+        if (StringUtils.isEmpty(namespace)) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.NAMESPACE);
+            return result;
+        }
+
+        if (StringUtils.isEmpty(k8s)) {
+            putMsg(result, Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
Constants.K8S);
+            return result;
+        }
+
+        if (checkNamespaceExistInDb(namespace, k8s)) {
+            putMsg(result, Status.K8S_NAMESPACE_EXIST, namespace, k8s);
+            return result;
+        }
+
+        putMsg(result, Status.SUCCESS);
+        return result;
+    }
+
+    /**
+     * delete namespace by id
+     *
+     * @param loginUser login user
+     * @param id        namespace id
+     * @return
+     */
+    @Override
+    public Map<String, Object> deleteNamespaceById(User loginUser, int id) {
+        Map<String, Object> result = new HashMap<>();
+        if (isNotAdmin(loginUser, result)) {
+            return result;
+        }
+
+        K8sNamespace k8sNamespaceObj = k8sNamespaceMapper.selectById(id);
+        if (k8sNamespaceObj == null) {
+            putMsg(result, Status.K8S_NAMESPACE_NOT_EXIST, id);
+            return result;
+        }
+
+        k8sClientService.deleteNamespaceToK8s(k8sNamespaceObj.getNamespace(), 
k8sNamespaceObj.getK8s());
+        k8sNamespaceMapper.deleteById(id);
+        putMsg(result, Status.SUCCESS);
+        return result;
+    }
+
+    /**
+     * check namespace name exist
+     *
+     * @param namespace namespace
+     * @return true if the k8s and namespace not exists, otherwise return false
+     */
+    private boolean checkNamespaceExistInDb(String namespace, String k8s) {
+        return k8sNamespaceMapper.existNamespace(namespace, k8s) == 
Boolean.TRUE;
+    }
+
+    /**
+     * use cpu memory create yaml
+     *
+     * @param k8sNamespace
+     * @return yaml file
+     */
+    private String genDefaultResourceYaml(K8sNamespace k8sNamespace) {
+        //resource use same name with namespace
+        String name = k8sNamespace.getNamespace();
+        String namespace = k8sNamespace.getNamespace();
+        String cpuStr = null;
+        if (k8sNamespace.getLimitsCpu() != null) {
+            cpuStr = k8sNamespace.getLimitsCpu() + "";
+        }
+
+        String memoryStr = null;
+        if (k8sNamespace.getLimitsMemory() != null) {
+            memoryStr = k8sNamespace.getLimitsMemory() + "Gi";
+        }
+
+        String result = resourceYaml.replace("${name}", name)
+            .replace("${namespace}", namespace);
+        if (cpuStr == null) {
+            result = result.replace("${limitCpu}", "");
+        } else {
+            result = result.replace("${limitCpu}", "limits.cpu: '" + cpuStr + 
"'");
+        }
+
+        if (memoryStr == null) {
+            result = result.replace("${limitMemory}", "");
+        } else {
+            result = result.replace("${limitMemory}", "limits.memory: " + 
memoryStr);
+        }
+        return result;
+    }
+}
diff --git 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceControllerTest.java
 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceControllerTest.java
new file mode 100644
index 0000000..830943b
--- /dev/null
+++ 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/controller/K8sNamespaceControllerTest.java
@@ -0,0 +1,155 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.api.controller;
+
+import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
+import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
+import static 
org.springframework.test.web.servlet.request.MockMvcRequestBuilders.put;
+import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
+import static 
org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
+
+import org.apache.dolphinscheduler.api.enums.Status;
+import org.apache.dolphinscheduler.api.utils.Result;
+import org.apache.dolphinscheduler.common.utils.JSONUtils;
+import org.apache.dolphinscheduler.dao.entity.User;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.http.MediaType;
+import org.springframework.test.web.servlet.MvcResult;
+import org.springframework.util.LinkedMultiValueMap;
+import org.springframework.util.MultiValueMap;
+
+/**
+ * k8s namespace controller test
+ */
+public class K8sNamespaceControllerTest extends AbstractControllerTest {
+
+    private static final String NAMESPACE_CREATE_STRING = "namespace1";
+    private static final Logger logger = 
LoggerFactory.getLogger(K8sNamespaceControllerTest.class);
+    protected User user;
+
+    @Test
+    public void queryProjectListPaging() throws Exception {
+        MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
+        paramsMap.add("searchVal", "");
+        paramsMap.add("pageNo", "1");
+        paramsMap.add("pageSize", "20");
+
+        MvcResult mvcResult = mockMvc.perform(get("/k8s-namespace")
+            .header(SESSION_ID, sessionId)
+            .params(paramsMap))
+            .andExpect(status().isOk())
+            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+            .andReturn();
+        Result result = 
JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), 
Result.class);
+        Assert.assertEquals(Status.SUCCESS.getCode(), 
result.getCode().intValue());
+    }
+
+    @Test
+    public void createNamespace() throws Exception {
+
+        MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
+        paramsMap.add("namespace", NAMESPACE_CREATE_STRING);
+        paramsMap.add("k8s", "k8s");
+
+        MvcResult mvcResult = mockMvc.perform(post("/k8s-namespace")
+            .header(SESSION_ID, sessionId)
+            .params(paramsMap))
+            .andExpect(status().isCreated()) //it can
+            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+            .andReturn();
+
+        Result result = 
JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), 
Result.class);
+        Assert.assertEquals(Status.K8S_CLIENT_OPS_ERROR.getCode(), 
result.getCode().intValue());//because we not have a k8s cluster in test env
+        logger.info("create queue return result:{}", 
mvcResult.getResponse().getContentAsString());
+    }
+
+    @Test
+    public void updateNamespace() throws Exception {
+        MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
+        paramsMap.add("id", "1");
+        paramsMap.add("owner", "owmer1");
+        paramsMap.add("tag", "flink");
+
+        MvcResult mvcResult = mockMvc.perform(put("/k8s-namespace/{id}", 1)
+            .header(SESSION_ID, sessionId)
+            .params(paramsMap))
+            .andExpect(status().isCreated())
+            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+            .andReturn();
+        Result result = 
JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), 
Result.class);
+        Assert.assertEquals(Status.K8S_CLIENT_OPS_ERROR.getCode(), 
result.getCode().intValue());
+        logger.info("update queue return result:{}", 
mvcResult.getResponse().getContentAsString());
+    }
+
+    @Test
+    public void verifyNamespace() throws Exception {
+        // queue value exist
+        MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
+        paramsMap.add("namespace", NAMESPACE_CREATE_STRING);
+        paramsMap.add("k8s", "default");
+
+        // success
+
+        MvcResult mvcResult = mockMvc.perform(post("/k8s-namespace/verify")
+            .header(SESSION_ID, sessionId)
+            .params(paramsMap))
+            .andExpect(status().isOk())
+            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+            .andReturn();
+        Result result = 
JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), 
Result.class);
+        Assert.assertEquals(Status.SUCCESS.getCode(), 
result.getCode().intValue());
+        logger.info(mvcResult.getResponse().getContentAsString());
+        logger.info("verify namespace return result:{}", 
mvcResult.getResponse().getContentAsString());
+
+        //error
+        paramsMap.clear();
+        paramsMap.add("namespace", null);
+        paramsMap.add("k8s", "default");
+        mvcResult = mockMvc.perform(post("/k8s-namespace/verify")
+            .header(SESSION_ID, sessionId)
+            .params(paramsMap))
+            .andExpect(status().isOk())
+            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+            .andReturn();
+        result = 
JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), 
Result.class);
+        Assert.assertEquals(Status.VERIFY_K8S_NAMESPACE_ERROR.getCode(), 
result.getCode().intValue());
+        logger.info(mvcResult.getResponse().getContentAsString());
+        logger.info("verify namespace return result:{}", 
mvcResult.getResponse().getContentAsString());
+    }
+
+    @Test
+    public void delNamespaceById() throws Exception {
+        MultiValueMap<String, String> paramsMap = new LinkedMultiValueMap<>();
+        paramsMap.add("id", "1");
+
+        MvcResult mvcResult = mockMvc.perform(post("/k8s-namespace/delete")
+            .header(SESSION_ID, sessionId)
+            .params(paramsMap))
+            .andExpect(status().isOk())
+            .andExpect(content().contentType(MediaType.APPLICATION_JSON))
+            .andReturn();
+
+        Result result = 
JSONUtils.parseObject(mvcResult.getResponse().getContentAsString(), 
Result.class);
+        Assert.assertEquals(Status.DELETE_K8S_NAMESPACE_BY_ID_ERROR.getCode(), 
result.getCode().intValue());//there is no k8s cluster in test env
+        logger.info(mvcResult.getResponse().getContentAsString());
+    }
+}
\ No newline at end of file
diff --git 
a/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/K8sNameSpaceServiceTest.java
 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/K8sNameSpaceServiceTest.java
new file mode 100644
index 0000000..2673556
--- /dev/null
+++ 
b/dolphinscheduler-api/src/test/java/org/apache/dolphinscheduler/api/service/K8sNameSpaceServiceTest.java
@@ -0,0 +1,189 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.api.service;
+
+import org.apache.dolphinscheduler.api.enums.Status;
+import org.apache.dolphinscheduler.api.service.impl.K8sNameSpaceServiceImpl;
+import org.apache.dolphinscheduler.api.utils.PageInfo;
+import org.apache.dolphinscheduler.api.utils.Result;
+import org.apache.dolphinscheduler.common.Constants;
+import org.apache.dolphinscheduler.common.enums.UserType;
+import org.apache.dolphinscheduler.dao.entity.K8sNamespace;
+import org.apache.dolphinscheduler.dao.entity.User;
+import org.apache.dolphinscheduler.dao.mapper.K8sNamespaceMapper;
+import org.apache.dolphinscheduler.dao.mapper.UserMapper;
+import org.apache.dolphinscheduler.service.k8s.K8sClientService;
+
+import org.apache.commons.collections.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import com.baomidou.mybatisplus.core.metadata.IPage;
+import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
+
+@RunWith(MockitoJUnitRunner.class)
+public class K8sNameSpaceServiceTest {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(K8sNameSpaceServiceTest.class);
+
+    @InjectMocks
+    private K8sNameSpaceServiceImpl k8sNameSpaceService;
+
+    @Mock
+    private K8sNamespaceMapper k8sNamespaceMapper;
+
+    @Mock
+    private K8sClientService k8sClientService;
+
+    @Mock
+    private UserMapper userMapper;
+
+    private String namespace = "default";
+    private String k8s = "default";
+
+    @Before
+    public void setUp() throws Exception {
+        
Mockito.when(k8sClientService.upsertNamespaceAndResourceToK8s(Mockito.any(K8sNamespace.class),
 Mockito.anyString())).thenReturn(null);
+        
Mockito.when(k8sClientService.deleteNamespaceToK8s(Mockito.anyString(), 
Mockito.anyString())).thenReturn(null);
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void queryListPaging() {
+        IPage<K8sNamespace> page = new Page<>(1, 10);
+        page.setTotal(1L);
+        page.setRecords(getNamespaceList());
+        
Mockito.when(k8sNamespaceMapper.queryK8sNamespacePaging(Mockito.any(Page.class),
 Mockito.eq(namespace))).thenReturn(page);
+        Result result = k8sNameSpaceService.queryListPaging(getLoginUser(), 
namespace, 1, 10);
+        logger.info(result.toString());
+        PageInfo<K8sNamespace> pageInfo = (PageInfo<K8sNamespace>) 
result.getData();
+        Assert.assertTrue(CollectionUtils.isNotEmpty(pageInfo.getTotalList()));
+    }
+
+    @Test
+    public void createK8sNamespace() {
+        // namespace is null
+        Map<String, Object> result = 
k8sNameSpaceService.createK8sNamespace(getLoginUser(), null, k8s, null, "tag", 
10.0, 100);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
result.get(Constants.STATUS));
+        // k8s is null
+        result = k8sNameSpaceService.createK8sNamespace(getLoginUser(), 
namespace, null, null, "tag", 10.0, 100);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
result.get(Constants.STATUS));
+        // correct
+        result = k8sNameSpaceService.createK8sNamespace(getLoginUser(), 
namespace, k8s, null, "tag", 10.0, 100);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
+        //null limit cpu and mem
+        result = k8sNameSpaceService.createK8sNamespace(getLoginUser(), 
namespace, k8s, null, "tag", null, null);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
+    }
+
+    @Test
+    public void updateK8sNamespace() {
+        
Mockito.when(k8sNamespaceMapper.selectById(1)).thenReturn(getNamespace());
+
+        Map<String, Object> result = 
k8sNameSpaceService.updateK8sNamespace(getLoginUser(), 1, null, "tag", null, 
null);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
+
+        result = k8sNameSpaceService.updateK8sNamespace(getLoginUser(), 1, 
null, "tag", -1.0, 100);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.REQUEST_PARAMS_NOT_VALID_ERROR, 
result.get(Constants.STATUS));
+
+        result = k8sNameSpaceService.updateK8sNamespace(getLoginUser(), 1, 
null, "tag", 1.0, 100);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
+    }
+
+    @Test
+    public void verifyNamespaceK8s() {
+
+        Mockito.when(k8sNamespaceMapper.existNamespace(namespace, 
k8s)).thenReturn(true);
+
+        //namespace null
+        Result result = k8sNameSpaceService.verifyNamespaceK8s(null, k8s);
+        logger.info(result.toString());
+        Assert.assertEquals(result.getCode().intValue(), 
Status.REQUEST_PARAMS_NOT_VALID_ERROR.getCode());
+
+        //k8s null
+        result = k8sNameSpaceService.verifyNamespaceK8s(namespace, null);
+        logger.info(result.toString());
+        Assert.assertEquals(result.getCode().intValue(), 
Status.REQUEST_PARAMS_NOT_VALID_ERROR.getCode());
+
+        //exist
+        result = k8sNameSpaceService.verifyNamespaceK8s(namespace, k8s);
+        logger.info(result.toString());
+        Assert.assertEquals(result.getCode().intValue(), 
Status.K8S_NAMESPACE_EXIST.getCode());
+
+        //not exist
+        result = k8sNameSpaceService.verifyNamespaceK8s(namespace, "other 
k8s");
+        logger.info(result.toString());
+        Assert.assertEquals(result.getCode().intValue(), 
Status.SUCCESS.getCode());
+    }
+
+    @Test
+    public void deleteNamespaceById() {
+        
Mockito.when(k8sNamespaceMapper.deleteById(Mockito.any())).thenReturn(1);
+        
Mockito.when(k8sNamespaceMapper.selectById(1)).thenReturn(getNamespace());
+
+        Map<String, Object> result = 
k8sNameSpaceService.deleteNamespaceById(getLoginUser(), 1);
+        logger.info(result.toString());
+        Assert.assertEquals(Status.SUCCESS, result.get(Constants.STATUS));
+    }
+
+    private User getLoginUser() {
+
+        User loginUser = new User();
+        loginUser.setUserType(UserType.ADMIN_USER);
+        loginUser.setId(99999999);
+        return loginUser;
+    }
+
+    private K8sNamespace getNamespace() {
+        K8sNamespace k8sNamespace = new K8sNamespace();
+        k8sNamespace.setId(1);
+        k8sNamespace.setK8s(k8s);
+        k8sNamespace.setNamespace(namespace);
+        return k8sNamespace;
+    }
+
+    private List<K8sNamespace> getNamespaceList() {
+        List<K8sNamespace> k8sNamespaceList = new ArrayList<>();
+        k8sNamespaceList.add(getNamespace());
+        return k8sNamespaceList;
+    }
+}
\ No newline at end of file
diff --git 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
index 7da88c4..671af2b 100644
--- 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
+++ 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
@@ -809,4 +809,11 @@ public final class Constants {
 
     public static final String CACHE_KEY_VALUE_ALL = "'all'";
 
+    /**
+     * use for k8s
+     */
+    public static final String NAMESPACE = "namespace";
+    public static final String K8S = "k8s";
+    public static final String LIMITS_CPU = "limitsCpu";
+    public static final String LIMITS_MEMORY = "limitsMemory";
 }
diff --git 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8s.java
 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8s.java
new file mode 100644
index 0000000..2cddf17
--- /dev/null
+++ 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8s.java
@@ -0,0 +1,103 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.dao.entity;
+
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+/**
+ * multi-data centre k8s temporary structure, waiting for new feature to 
complete will switch
+ */
+@TableName("t_ds_k8s")
+public class K8s {
+    /**
+     * id
+     */
+    @TableId(value = "id", type = IdType.AUTO)
+    private int id;
+    /**
+     * k8s name
+     */
+    @TableField(value = "k8s_name")
+    private String k8sName;
+    /**
+     * k8s client config(yaml or json)
+     */
+    @TableField(value = "k8s_config")
+    private String k8sConfig;
+
+    /**
+     * create_time
+     */
+    @TableField("create_time")
+    private Date createTime;
+    /**
+     * update_time
+     */
+    @TableField("update_time")
+    private Date updateTime;
+
+
+    public K8s() {
+
+    }
+
+    public int getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getK8sName() {
+        return k8sName;
+    }
+
+    public void setK8sName(String k8sName) {
+        this.k8sName = k8sName;
+    }
+
+    public String getK8sConfig() {
+        return k8sConfig;
+    }
+
+    public void setK8sConfig(String k8sConfig) {
+        this.k8sConfig = k8sConfig;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+}
diff --git 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8sNamespace.java
 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8sNamespace.java
new file mode 100644
index 0000000..d22e7bd
--- /dev/null
+++ 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/K8sNamespace.java
@@ -0,0 +1,197 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.dao.entity;
+
+import java.util.Date;
+
+import com.baomidou.mybatisplus.annotation.IdType;
+import com.baomidou.mybatisplus.annotation.TableField;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+
+/**
+ * k8s namespace
+ */
+@TableName("t_ds_k8s_namespace")
+public class K8sNamespace {
+    @TableId(value = "id", type = IdType.AUTO)
+    private Integer id;
+
+    /**
+     * namespace name
+     */
+    @TableField(value = "namespace")
+    private String namespace;
+    /**
+     * total cpu limit
+     */
+    @TableField(value = "limits_cpu")
+    private Double limitsCpu;
+    /**
+     * total memory limit,mi
+     */
+    private Integer limitsMemory;
+    /**
+     * owner
+     */
+    @TableField(value = "owner")
+    private String owner;
+
+    /**
+     * create_time
+     */
+    @TableField("create_time")
+    private Date createTime;
+    /**
+     * update_time
+     */
+    @TableField("update_time")
+    private Date updateTime;
+    /**
+     * tag use for set this namespace allow run which type
+     */
+    @TableField("tag")
+    private String tag;
+
+    @TableField("pod_request_cpu")
+    private Double podRequestCpu = 0.0;
+    /**
+     * Mi
+     */
+    @TableField("pod_request_memory")
+    private Integer podRequestMemory = 0;
+    /**
+     *
+     */
+    @TableField("pod_replicas")
+    private Integer podReplicas = 0;
+    /**
+     * online job
+     */
+    @TableField("online_job_num")
+    private Integer onlineJobNum = 0;
+    /**
+     * k8s name
+     */
+    @TableField("k8s")
+    private String k8s;
+
+    public Integer getId() {
+        return id;
+    }
+
+    public void setId(int id) {
+        this.id = id;
+    }
+
+    public String getNamespace() {
+        return namespace;
+    }
+
+    public void setNamespace(String namespace) {
+        this.namespace = namespace;
+    }
+
+    public Double getLimitsCpu() {
+        return limitsCpu;
+    }
+
+    public void setLimitsCpu(Double limitsCpu) {
+        this.limitsCpu = limitsCpu;
+    }
+
+    public Integer getLimitsMemory() {
+        return limitsMemory;
+    }
+
+    public void setLimitsMemory(Integer limitsMemory) {
+        this.limitsMemory = limitsMemory;
+    }
+
+    public String getOwner() {
+        return owner;
+    }
+
+    public void setOwner(String owner) {
+        this.owner = owner;
+    }
+
+    public Date getCreateTime() {
+        return createTime;
+    }
+
+    public void setCreateTime(Date createTime) {
+        this.createTime = createTime;
+    }
+
+    public Date getUpdateTime() {
+        return updateTime;
+    }
+
+    public void setUpdateTime(Date updateTime) {
+        this.updateTime = updateTime;
+    }
+
+    public String getTag() {
+        return tag;
+    }
+
+    public void setTag(String tag) {
+        this.tag = tag;
+    }
+
+    public Integer getPodRequestMemory() {
+        return podRequestMemory;
+    }
+
+    public void setPodRequestMemory(Integer podRequestMemory) {
+        this.podRequestMemory = podRequestMemory;
+    }
+
+    public Integer getPodReplicas() {
+        return podReplicas;
+    }
+
+    public void setPodReplicas(Integer podReplicas) {
+        this.podReplicas = podReplicas;
+    }
+
+    public Integer getOnlineJobNum() {
+        return onlineJobNum;
+    }
+
+    public void setOnlineJobNum(Integer onlineJobNum) {
+        this.onlineJobNum = onlineJobNum;
+    }
+
+    public String getK8s() {
+        return k8s;
+    }
+
+    public void setK8s(String k8s) {
+        this.k8s = k8s;
+    }
+
+    public Double getPodRequestCpu() {
+        return podRequestCpu;
+    }
+
+    public void setPodRequestCpu(Double podRequestCpu) {
+        this.podRequestCpu = podRequestCpu;
+    }
+}
diff --git 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sMapper.java
 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sMapper.java
new file mode 100644
index 0000000..bcf617b
--- /dev/null
+++ 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sMapper.java
@@ -0,0 +1,29 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.dao.mapper;
+
+import org.apache.dolphinscheduler.dao.entity.K8s;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ * k8s mapper interface
+ */
+public interface K8sMapper extends BaseMapper<K8s> {
+
+}
diff --git 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.java
 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.java
new file mode 100644
index 0000000..e804d55
--- /dev/null
+++ 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.java
@@ -0,0 +1,49 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.dao.mapper;
+
+import org.apache.dolphinscheduler.dao.entity.K8sNamespace;
+
+import org.apache.ibatis.annotations.Param;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.baomidou.mybatisplus.core.metadata.IPage;
+
+/**
+ * namespace interface
+ */
+public interface K8sNamespaceMapper extends BaseMapper<K8sNamespace> {
+    /**
+     * k8s namespace page
+     *
+     * @param page      page
+     * @param searchVal searchVal
+     * @return k8s namespace IPage
+     */
+    IPage<K8sNamespace> queryK8sNamespacePaging(IPage<K8sNamespace> page,
+                                                @Param("searchVal") String 
searchVal);
+
+    /**
+     * check the target namespace exist
+     *
+     * @param namespace namespace
+     * @param k8s       k8s name
+     * @return true if exist else return null
+     */
+    Boolean existNamespace(@Param("namespace") String namespace, @Param("k8s") 
String k8s);
+}
diff --git 
a/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml
 
b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml
new file mode 100644
index 0000000..9099e0c
--- /dev/null
+++ 
b/dolphinscheduler-dao/src/main/resources/org/apache/dolphinscheduler/dao/mapper/K8sNamespaceMapper.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+  ~ Licensed to the Apache Software Foundation (ASF) under one or more
+  ~ contributor license agreements.  See the NOTICE file distributed with
+  ~ this work for additional information regarding copyright ownership.
+  ~ The ASF licenses this file to You under the Apache License, Version 2.0
+  ~ (the "License"); you may not use this file except in compliance with
+  ~ the License.  You may obtain a copy of the License at
+  ~
+  ~     http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+  -->
+
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" 
"http://mybatis.org/dtd/mybatis-3-mapper.dtd";>
+<mapper namespace="org.apache.dolphinscheduler.dao.mapper.K8sNamespaceMapper">
+
+    <sql id="baseSql">
+        id, namespace, k8s, owner, tag, limits_memory, limits_cpu, 
online_job_num, pod_replicas, pod_request_cpu, pod_request_memory, create_time, 
update_time
+    </sql>
+    <select id="queryK8sNamespacePaging" 
resultType="org.apache.dolphinscheduler.dao.entity.K8sNamespace">
+        select
+        <include refid="baseSql"/>
+        from t_ds_k8s_namespace
+        where 1= 1
+        <if test="searchVal != null and searchVal != ''">
+            and namespace like concat('%', #{searchVal}, '%')
+        </if>
+        order by update_time desc
+    </select>
+
+    <select id="existNamespace" resultType="java.lang.Boolean">
+        select 1 = 1
+        from t_ds_k8s_namespace
+        where 1 = 1
+        <if test="namespace != null and namespace != ''">
+            and namespace = #{namespace}
+        </if>
+        <if test="k8s != null and k8s != ''">
+            and k8s =#{k8s}
+        </if>
+    </select>
+
+</mapper>
diff --git 
a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql 
b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql
index 45a452f..3d4536d 100644
--- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql
+++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_h2.sql
@@ -1870,4 +1870,41 @@ CREATE TABLE t_ds_audit_log
     time                timestamp NULL DEFAULT CURRENT_TIMESTAMP,
     resource_id         int(11) NOT NULL,
     PRIMARY KEY (id)
-);
\ No newline at end of file
+);
+
+
+DROP TABLE IF EXISTS t_ds_k8s;
+CREATE TABLE t_ds_k8s
+(
+    id           int(11) NOT NULL AUTO_INCREMENT ,
+    k8s_name     varchar(100) DEFAULT NULL ,
+    k8s_config   text DEFAULT NULL,
+    create_time  datetime DEFAULT NULL ,
+    update_time  datetime DEFAULT NULL ,
+    PRIMARY KEY (id)
+);
+
+DROP TABLE IF EXISTS t_ds_k8s_namespace;
+CREATE TABLE t_ds_k8s_namespace (
+    id                 int(11) NOT NULL AUTO_INCREMENT ,
+    limits_memory      int(11) DEFAULT NULL,
+    namespace          varchar(100) DEFAULT NULL,
+    online_job_num     int(11) DEFAULT NULL,
+    owner              varchar(100) DEFAULT NULL,
+    pod_replicas       int(11) DEFAULT NULL,
+    pod_request_cpu    decimal(14,3) DEFAULT NULL,
+    pod_request_memory int(11) DEFAULT NULL,
+    tag                varchar(100) DEFAULT NULL,
+    limits_cpu         decimal(14,3) DEFAULT NULL,
+    k8s                varchar(100) DEFAULT NULL,
+    create_time        datetime DEFAULT NULL ,
+    update_time        datetime DEFAULT NULL ,
+    PRIMARY KEY (id) ,
+    UNIQUE KEY k8s_namespace_unique (namespace,k8s)
+);
+
+-- ----------------------------
+-- Records of t_ds_k8s_namespace
+-- ----------------------------
+INSERT INTO t_ds_k8s_namespace
+VALUES (1, 10000, 'default', 99, 
'owner',1,NULL,1,'test',NULL,'default',null,null);
\ No newline at end of file
diff --git 
a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql 
b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql
index ca3724b..eed27f9 100644
--- a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql
+++ b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_mysql.sql
@@ -1856,4 +1856,39 @@ CREATE TABLE `t_ds_audit_log` (
   `time` datetime DEFAULT CURRENT_TIMESTAMP COMMENT 'create time',
   `resource_id` int(11) NULL DEFAULT NULL COMMENT 'resource id',
   PRIMARY KEY (`id`)
-) ENGINE=InnoDB AUTO_INCREMENT= 1 DEFAULT CHARSET=utf8;
\ No newline at end of file
+) ENGINE=InnoDB AUTO_INCREMENT= 1 DEFAULT CHARSET=utf8;
+
+-- ----------------------------
+-- Table structure for t_ds_k8s
+-- ----------------------------
+DROP TABLE IF EXISTS `t_ds_k8s`;
+CREATE TABLE `t_ds_k8s` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `k8s_name` varchar(100) DEFAULT NULL,
+  `k8s_config` text DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL COMMENT 'create time',
+  `update_time` datetime DEFAULT NULL COMMENT 'update time',
+  PRIMARY KEY (`id`)
+) ENGINE= INNODB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8;
+
+-- ----------------------------
+-- Table structure for t_ds_k8s_namespace
+-- ----------------------------
+DROP TABLE IF EXISTS `t_ds_k8s_namespace`;
+CREATE TABLE `t_ds_k8s_namespace` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `limits_memory` int(11) DEFAULT NULL,
+  `namespace` varchar(100) DEFAULT NULL,
+  `online_job_num` int(11) DEFAULT NULL,
+  `owner` varchar(100) DEFAULT NULL,
+  `pod_replicas` int(11) DEFAULT NULL,
+  `pod_request_cpu` decimal(14,3) DEFAULT NULL,
+  `pod_request_memory` int(11) DEFAULT NULL,
+  `tag` varchar(100) DEFAULT NULL,
+  `limits_cpu` decimal(14,3) DEFAULT NULL,
+  `k8s` varchar(100) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL COMMENT 'create time',
+  `update_time` datetime DEFAULT NULL COMMENT 'update time',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `k8s_namespace_unique` (`namespace`,`k8s`)
+) ENGINE= INNODB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8;
diff --git 
a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql 
b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql
index 1e371d7..5d5ce6f 100644
--- 
a/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql
+++ 
b/dolphinscheduler-dao/src/main/resources/sql/dolphinscheduler_postgresql.sql
@@ -1850,4 +1850,41 @@ CREATE TABLE t_ds_audit_log (
     time timestamp DEFAULT NULL ,
     resource_id int NOT NULL,
     PRIMARY KEY (id)
-);
\ No newline at end of file
+);
+
+--
+-- Table structure for table t_ds_k8s
+--
+
+DROP TABLE IF EXISTS t_ds_k8s;
+CREATE TABLE t_ds_k8s (
+   id serial NOT NULL,
+   k8s_name    VARCHAR(100) DEFAULT NULL ,
+   k8s_config  text ,
+   create_time timestamp DEFAULT NULL ,
+   update_time timestamp DEFAULT NULL ,
+   PRIMARY KEY (id)
+);
+
+--
+-- Table structure for table t_ds_k8s_namespace
+--
+
+DROP TABLE IF EXISTS t_ds_k8s_namespace;
+CREATE TABLE t_ds_k8s_namespace (
+   id serial NOT NULL,
+   limits_memory      int DEFAULT NULL ,
+   namespace          varchar(100) DEFAULT NULL ,
+   online_job_num     int DEFAULT '0' ,
+   owner              varchar(100) DEFAULT NULL,
+   pod_replicas       int(11) DEFAULT NULL,
+   pod_request_cpu    NUMERIC(13,4) NULL,
+   pod_request_memory int(11) DEFAULT NULL,
+   tag                varchar(100) DEFAULT NULL,
+   limits_cpu         NUMERIC(13,4) NULL,
+   k8s                varchar(100) DEFAULT NULL,
+   create_time        timestamp DEFAULT NULL ,
+   update_time        timestamp DEFAULT NULL ,
+   PRIMARY KEY (id) ,
+   CONSTRAINT k8s_namespace_unique UNIQUE (namespace,k8s)
+);
diff --git 
a/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/mysql/dolphinscheduler_ddl.sql
 
b/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/mysql/dolphinscheduler_ddl.sql
index e12b696..5f66888 100644
--- 
a/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/mysql/dolphinscheduler_ddl.sql
+++ 
b/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/mysql/dolphinscheduler_ddl.sql
@@ -168,3 +168,39 @@ CREATE TABLE `t_ds_relation_rule_input_entry` (
                                                   `update_time` datetime 
DEFAULT NULL,
                                                   PRIMARY KEY (`id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+
+-- ----------------------------
+-- Table structure for t_ds_k8s
+-- ----------------------------
+DROP TABLE IF EXISTS `t_ds_k8s`;
+CREATE TABLE `t_ds_k8s` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `k8s_name` varchar(100) DEFAULT NULL,
+  `k8s_config` text DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL COMMENT 'create time',
+  `update_time` datetime DEFAULT NULL COMMENT 'update time',
+  PRIMARY KEY (`id`)
+) ENGINE= INNODB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8;
+
+-- ----------------------------
+-- Table structure for t_ds_k8s_namespace
+-- ----------------------------
+DROP TABLE IF EXISTS `t_ds_k8s_namespace`;
+CREATE TABLE `t_ds_k8s_namespace` (
+  `id` int(11) NOT NULL AUTO_INCREMENT,
+  `limits_memory` int(11) DEFAULT NULL,
+  `namespace` varchar(100) DEFAULT NULL,
+  `online_job_num` int(11) DEFAULT NULL,
+  `owner` varchar(100) DEFAULT NULL,
+  `pod_replicas` int(11) DEFAULT NULL,
+  `pod_request_cpu` decimal(14,3) DEFAULT NULL,
+  `pod_request_memory` int(11) DEFAULT NULL,
+  `tag` varchar(100) DEFAULT NULL,
+  `limits_cpu` decimal(14,3) DEFAULT NULL,
+  `k8s` varchar(100) DEFAULT NULL,
+  `create_time` datetime DEFAULT NULL COMMENT 'create time',
+  `update_time` datetime DEFAULT NULL COMMENT 'update time',
+  PRIMARY KEY (`id`),
+  UNIQUE KEY `k8s_namespace_unique` (`namespace`,`k8s`)
+) ENGINE= INNODB AUTO_INCREMENT= 1 DEFAULT CHARSET= utf8;
\ No newline at end of file
diff --git 
a/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/postgresql/dolphinscheduler_ddl.sql
 
b/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/postgresql/dolphinscheduler_ddl.sql
index 3e35d60..854b787 100644
--- 
a/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/postgresql/dolphinscheduler_ddl.sql
+++ 
b/dolphinscheduler-dao/src/main/resources/sql/upgrade/2.1.0_schema/postgresql/dolphinscheduler_ddl.sql
@@ -154,6 +154,32 @@ EXECUTE 'CREATE INDEX IF NOT EXISTS 
idx_task_definition_log_project_code ON ' ||
 EXECUTE 'DROP INDEX IF EXISTS "idx_task_instance_code_version"';
 EXECUTE 'CREATE INDEX IF NOT EXISTS idx_task_instance_code_version ON' || 
quote_ident(v_schema) ||'.t_ds_task_instance USING 
Btree("task_code","task_definition_version")';
 
+EXECUTE 'CREATE TABLE IF NOT EXISTS '|| quote_ident(v_schema) ||'."t_ds_k8s" (
+   id serial NOT NULL,
+   k8s_name    VARCHAR(100) DEFAULT NULL ,
+   k8s_config  text ,
+   create_time timestamp DEFAULT NULL ,
+   update_time timestamp DEFAULT NULL ,
+   PRIMARY KEY (id)
+)';
+
+EXECUTE 'CREATE TABLE IF NOT EXISTS '|| quote_ident(v_schema) 
||'."t_ds_k8s_namespace" (
+   id serial NOT NULL,
+   limits_memory      int DEFAULT NULL ,
+   namespace          varchar(100) DEFAULT NULL ,
+   online_job_num     int DEFAULT ''0'' ,
+   owner              varchar(100) DEFAULT NULL,
+   pod_replicas       int(11) DEFAULT NULL,
+   pod_request_cpu    NUMERIC(13,4) NULL,
+   pod_request_memory int(11) DEFAULT NULL,
+   tag                varchar(100) DEFAULT NULL,
+   limits_cpu         NUMERIC(13,4) NULL,
+   k8s                varchar(100) DEFAULT NULL,
+   create_time        timestamp DEFAULT NULL ,
+   update_time        timestamp DEFAULT NULL ,
+   PRIMARY KEY (id) ,
+   CONSTRAINT k8s_namespace_unique UNIQUE (namespace,k8s)
+)';
 
 return 'Success!';
 exception when others then
diff --git a/dolphinscheduler-dist/release-docs/LICENSE 
b/dolphinscheduler-dist/release-docs/LICENSE
index 6c4e134..642bee4 100644
--- a/dolphinscheduler-dist/release-docs/LICENSE
+++ b/dolphinscheduler-dist/release-docs/LICENSE
@@ -405,6 +405,33 @@ The text of each license is also included at 
licenses/LICENSE-[project].txt.
     protostuff-collectionschema 1.7.2: 
https://github.com/protostuff/protostuff/protostuff-collectionschema Apache-2.0
     prometheus client_java(simpleclient) 0.12.0: 
https://github.com/prometheus/client_java, Apache 2.0
     snowflake snowflake-2010: 
https://github.com/twitter-archive/snowflake/tree/snowflake-2010, Apache 2.0
+    kubernetes-client 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-client/5.8.0, Apache 
2.0
+    kubernetes-model-admissionregistration 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-admissionregistration/5.8.0,
 Apache 2.0
+    kubernetes-model-apiextensions 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-apiextensions/5.8.0,
 Apache 2.0
+    kubernetes-model-apps 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-apps/5.8.0, 
Apache 2.0
+    kubernetes-model-autoscaling 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-autoscaling/5.8.0,
 Apache 2.0
+    kubernetes-model-batch 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-autoscaling/5.8.0,
 Apache 2.0
+    kubernetes-model-certificates 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-certificates/5.8.0,
 Apache 2.0
+    kubernetes-model-common 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-common/5.8.0, 
Apache 2.0
+    kubernetes-model-coordination 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-coordination/5.8.0,
 Apache 2.0
+    kubernetes-model-core 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-core/5.8.0, 
Apache 2.0
+    kubernetes-model-discovery 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-discovery/5.8.0, 
Apache 2.0
+    kubernetes-model-events 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-events/5.8.0, 
Apache 2.0
+    kubernetes-model-extensions 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-extensions/5.8.0,
 Apache 2.0
+    kubernetes-model-flowcontrol 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-flowcontrol/5.8.0,
 Apache 2.0
+    kubernetes-model-metrics 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-metrics/5.8.0, 
Apache 2.0
+    kubernetes-model-networking 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-networking/5.8.0,
 Apache 2.0
+    kubernetes-model-node 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-node/5.8.0, 
Apache 2.0
+    kubernetes-model-policy 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-policy/5.8.0, 
Apache 2.0
+    kubernetes-model-rbac 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-rbac/5.8.0, 
Apache 2.0
+    kubernetes-model-scheduling 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-scheduling/5.8.0,
 Apache 2.0
+    kubernetes-model-storageclass 5.8.0: 
https://mvnrepository.com/artifact/io.fabric8/kubernetes-model-storageclass/5.8.0,
 Apache 2.0
+    zjsonpatch 0.3.0 
https://mvnrepository.com/artifact/io.fabric8/zjsonpatch/0.3.0, Apache 2.0
+    generex 1.0.2 
https://mvnrepository.com/artifact/com.github.mifmif/generex/1.0.2, Apache 2.0
+    jackson-dataformat-yaml 2.12.5 
https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml/2.12.5,
 Apache 2.0
+    logging-interceptor 3.14.9 
https://mvnrepository.com/artifact/com.squareup.okhttp3/logging-interceptor/3.14.9,
 Apache 2.0
+    okhttp 3.14.3 
https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp/3.14.3, Apache 
2.0
+    okio 1.17.2 
https://mvnrepository.com/artifact/com.squareup.okio/okio/1.17.2, Apache 2.0
 
 ========================================================================
 BSD licenses
@@ -428,6 +455,7 @@ The text of each license is also included at 
licenses/LICENSE-[project].txt.
     LatencyUtils 2.0.3: https://github.com/LatencyUtils/LatencyUtils, 
BSD-2-Clause
     janino 3.1.6: 
https://mvnrepository.com/artifact/org.codehaus.janino/janino/3.1.6, BSD 
3-clause
     commons-compiler 3.1.6: 
https://mvnrepository.com/artifact/org.codehaus.janino/janino/3.1.6, BSD 
3-clause
+    automaton 1.11-8 
https://mvnrepository.com/artifact/dk.brics.automaton/automaton/1.11-8, BSD 
2-clause
 
 ========================================================================
 CDDL licenses
diff --git a/dolphinscheduler-dist/release-docs/licenses/LICENSE-automaton.txt 
b/dolphinscheduler-dist/release-docs/licenses/LICENSE-automaton.txt
new file mode 100644
index 0000000..7253426
--- /dev/null
+++ b/dolphinscheduler-dist/release-docs/licenses/LICENSE-automaton.txt
@@ -0,0 +1,24 @@
+Copyright (c) 2001-2022 Anders Moeller
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. The name of the author may not be used to endorse or promote products
+   derived from this software without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
\ No newline at end of file
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/NamespacePage.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/NamespacePage.java
new file mode 100644
index 0000000..0d10e34
--- /dev/null
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/NamespacePage.java
@@ -0,0 +1,94 @@
+/*
+ * Licensed to Apache Software Foundation (ASF) under one or more contributor
+ * license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright
+ * ownership. Apache Software Foundation (ASF) licenses this file to you under
+ * the Apache License, Version 2.0 (the "License"); you may
+ * not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.dolphinscheduler.e2e.pages.security;
+
+import org.apache.dolphinscheduler.e2e.pages.common.NavBarPage;
+
+import java.util.List;
+
+import org.openqa.selenium.By;
+import org.openqa.selenium.WebElement;
+import org.openqa.selenium.remote.RemoteWebDriver;
+import org.openqa.selenium.support.FindBy;
+import org.openqa.selenium.support.PageFactory;
+
+import lombok.Getter;
+
+@Getter
+public final class NamespacePage extends NavBarPage implements 
SecurityPage.Tab {
+    @FindBy(id = "btnCreateNamespace")
+    private WebElement buttonCreateNamespace;
+
+    @FindBy(className = "items")
+    private List<WebElement> namespaceList;
+
+    private final NamespaceForm createNamespaceForm;
+    private final NamespaceForm editNamespaceForm;
+
+    public NamespacePage(RemoteWebDriver driver) {
+        super(driver);
+        createNamespaceForm = new NamespaceForm();
+        editNamespaceForm = new NamespaceForm();
+    }
+
+    public NamespacePage create(String namespaceName, String namespaceValue) {
+        buttonCreateNamespace().click();
+        createNamespaceForm().inputNamespaceName().sendKeys(namespaceName);
+        createNamespaceForm().inputNamespaceValue().sendKeys(namespaceValue);
+        createNamespaceForm().buttonSubmit().click();
+        return this;
+    }
+
+    public NamespacePage update(String namespaceName, String 
editNamespaceName, String editNamespaceValue) {
+        namespaceList()
+                .stream()
+                .filter(it -> 
it.findElement(By.className("namespaceName")).getAttribute("innerHTML").contains(namespaceName))
+                .flatMap(it -> it.findElements(By.className("edit")).stream())
+                .filter(WebElement::isDisplayed)
+                .findFirst()
+                .orElseThrow(() -> new RuntimeException("No edit button in 
namespace list"))
+                .click();
+
+        editNamespaceForm().inputNamespaceName().sendKeys(editNamespaceName);
+        editNamespaceForm().inputNamespaceValue().sendKeys(editNamespaceValue);
+        editNamespaceForm().buttonSubmit().click();
+
+        return this;
+    }
+
+    @Getter
+    public class NamespaceForm {
+        NamespaceForm() {
+            PageFactory.initElements(driver, this);
+        }
+
+        @FindBy(id = "inputNamespaceName")
+        private WebElement inputNamespaceName;
+
+        @FindBy(id = "inputNamespaceValue")
+        private WebElement inputNamespaceValue;
+
+        @FindBy(id = "btnSubmit")
+        private WebElement buttonSubmit;
+
+        @FindBy(id = "btnCancel")
+        private WebElement buttonCancel;
+    }
+}
diff --git 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
index 2bbdd7b..d2d7835 100644
--- 
a/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
+++ 
b/dolphinscheduler-e2e/dolphinscheduler-e2e-case/src/test/java/org/apache/dolphinscheduler/e2e/pages/security/SecurityPage.java
@@ -52,6 +52,9 @@ public class SecurityPage extends NavBarPage implements 
NavBarItem {
     @FindBy(className = "tab-token-manage")
     private WebElement menuTokenManage;
 
+    @FindBy(className = "tab-namespace-manage")
+    private WebElement menuNamespaceManage;
+
     public SecurityPage(RemoteWebDriver driver) {
         super(driver);
     }
@@ -88,6 +91,10 @@ public class SecurityPage extends NavBarPage implements 
NavBarItem {
             menuTokenManage().click();
             return tab.cast(new TokenPage(driver));
         }
+        if (tab == NamespacePage.class) {
+            menuNamespaceManage().click();
+            return tab.cast(new NamespacePage(driver));
+        }
         throw new UnsupportedOperationException("Unknown tab: " + 
tab.getName());
     }
 
diff --git a/dolphinscheduler-service/pom.xml b/dolphinscheduler-service/pom.xml
index 387f613..8143cd7 100644
--- a/dolphinscheduler-service/pom.xml
+++ b/dolphinscheduler-service/pom.xml
@@ -90,5 +90,9 @@
             <groupId>com.github.ben-manes.caffeine</groupId>
             <artifactId>caffeine</artifactId>
         </dependency>
+        <dependency>
+            <groupId>io.fabric8</groupId>
+            <artifactId>kubernetes-client</artifactId>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/k8s/K8sClientService.java
 
b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/k8s/K8sClientService.java
new file mode 100644
index 0000000..c921054
--- /dev/null
+++ 
b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/k8s/K8sClientService.java
@@ -0,0 +1,118 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.service.k8s;
+
+import org.apache.dolphinscheduler.dao.entity.K8sNamespace;
+
+import java.util.Optional;
+
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.yaml.snakeyaml.Yaml;
+
+import io.fabric8.kubernetes.api.model.Namespace;
+import io.fabric8.kubernetes.api.model.NamespaceList;
+import io.fabric8.kubernetes.api.model.ObjectMeta;
+import io.fabric8.kubernetes.api.model.ResourceQuota;
+import io.fabric8.kubernetes.client.KubernetesClient;
+
+/**
+ * Encapsulates all client-related operations, not involving the db
+ */
+@Component
+public class K8sClientService {
+
+    private static Yaml yaml = new Yaml();
+    @Autowired
+    private K8sManager k8sManager;
+
+    public ResourceQuota upsertNamespaceAndResourceToK8s(K8sNamespace 
k8sNamespace, String yamlStr) {
+        upsertNamespaceToK8s(k8sNamespace.getNamespace(), 
k8sNamespace.getK8s());
+        return upsertNamespacedResourceToK8s(k8sNamespace, yamlStr);
+    }
+
+    public Optional<Namespace> deleteNamespaceToK8s(String name, String k8s) {
+        Optional<Namespace> result = getNamespaceFromK8s(name, k8s);
+        if (result.isPresent()) {
+            KubernetesClient client = k8sManager.getK8sClient(k8s);
+            Namespace body = new Namespace();
+            ObjectMeta meta = new ObjectMeta();
+            meta.setNamespace(name);
+            meta.setName(name);
+            body.setMetadata(meta);
+            client.namespaces().delete(body);
+        }
+        return getNamespaceFromK8s(name, k8s);
+    }
+
+    private ResourceQuota upsertNamespacedResourceToK8s(K8sNamespace 
k8sNamespace, String yamlStr) {
+
+        KubernetesClient client = 
k8sManager.getK8sClient(k8sNamespace.getK8s());
+
+        //创建资源
+        ResourceQuota queryExist = client.resourceQuotas()
+                .inNamespace(k8sNamespace.getNamespace())
+                .withName(k8sNamespace.getNamespace())
+                .get();
+
+
+        ResourceQuota body = yaml.loadAs(yamlStr, ResourceQuota.class);
+
+        if (queryExist != null) {
+            if (k8sNamespace.getLimitsCpu() == null && 
k8sNamespace.getLimitsMemory() == null) {
+                
client.resourceQuotas().inNamespace(k8sNamespace.getNamespace())
+                        .withName(k8sNamespace.getNamespace())
+                        .delete();
+                return null;
+            }
+        }
+
+        return client.resourceQuotas().inNamespace(k8sNamespace.getNamespace())
+                .withName(k8sNamespace.getNamespace())
+                .createOrReplace(body);
+    }
+
+    private Optional<Namespace> getNamespaceFromK8s(String name, String k8s) {
+        NamespaceList listNamespace =
+                k8sManager.getK8sClient(k8s).namespaces().list();
+
+        Optional<Namespace> list =
+                listNamespace.getItems().stream()
+                        .filter((Namespace namespace) ->
+                                namespace.getMetadata().getName().equals(name))
+                        .findFirst();
+
+        return list;
+    }
+
+    private Namespace upsertNamespaceToK8s(String name, String k8s) {
+        Optional<Namespace> result = getNamespaceFromK8s(name, k8s);
+        //if not exist create
+        if (!result.isPresent()) {
+            KubernetesClient client = k8sManager.getK8sClient(k8s);
+            Namespace body = new Namespace();
+            ObjectMeta meta = new ObjectMeta();
+            meta.setNamespace(name);
+            meta.setName(name);
+            body.setMetadata(meta);
+            return client.namespaces().create(body);
+        }
+        return result.get();
+    }
+
+}
diff --git 
a/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/k8s/K8sManager.java
 
b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/k8s/K8sManager.java
new file mode 100644
index 0000000..c86d0ec
--- /dev/null
+++ 
b/dolphinscheduler-service/src/main/java/org/apache/dolphinscheduler/service/k8s/K8sManager.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.service.k8s;
+
+import org.apache.dolphinscheduler.dao.entity.K8s;
+import org.apache.dolphinscheduler.dao.mapper.K8sMapper;
+import org.apache.dolphinscheduler.remote.exceptions.RemotingException;
+
+import java.util.Hashtable;
+import java.util.List;
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.context.event.ApplicationReadyEvent;
+import org.springframework.context.event.EventListener;
+import org.springframework.stereotype.Component;
+
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
+
+import io.fabric8.kubernetes.client.Config;
+import io.fabric8.kubernetes.client.DefaultKubernetesClient;
+import io.fabric8.kubernetes.client.KubernetesClient;
+
+/**
+ * A separate class, because then wait for multiple environment feature, 
currently using db configuration, later unified
+ */
+@Component
+public class K8sManager {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(K8sManager.class);
+    /**
+     * cache k8s client
+     */
+    private static Map<String, KubernetesClient> clientMap = new Hashtable<>();
+
+    @Autowired
+    private K8sMapper k8sMapper;
+
+    public KubernetesClient getK8sClient(String k8sName) {
+        if (null == k8sName) {
+            return null;
+        }
+        return clientMap.get(k8sName);
+    }
+
+
+    @EventListener
+    public void buildApiClientAll(ApplicationReadyEvent readyEvent) throws 
RemotingException {
+        QueryWrapper<K8s> nodeWrapper = new QueryWrapper<>();
+        List<K8s> k8sList = k8sMapper.selectList(nodeWrapper);
+
+        if (k8sList != null) {
+            for (K8s k8s : k8sList) {
+                DefaultKubernetesClient client = getClient(k8s.getK8sConfig());
+                clientMap.put(k8s.getK8sName(), client);
+            }
+        }
+    }
+
+    private DefaultKubernetesClient getClient(String configYaml) throws 
RemotingException {
+        try {
+            Config config = Config.fromKubeconfig(configYaml);
+            return new DefaultKubernetesClient(config);
+        } catch (Exception e) {
+            logger.error("fail to get k8s ApiClient", e);
+            throw new RemotingException("fail to get k8s ApiClient:" + 
e.getMessage());
+        }
+    }
+}
diff --git 
a/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/k8s/K8sManagerTest.java
 
b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/k8s/K8sManagerTest.java
new file mode 100644
index 0000000..2740b7d
--- /dev/null
+++ 
b/dolphinscheduler-service/src/test/java/org/apache/dolphinscheduler/service/k8s/K8sManagerTest.java
@@ -0,0 +1,78 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.service.k8s;
+
+import org.apache.dolphinscheduler.dao.entity.K8s;
+import org.apache.dolphinscheduler.dao.mapper.K8sMapper;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.junit.MockitoJUnitRunner;
+
+import io.fabric8.kubernetes.client.KubernetesClient;
+
+@RunWith(MockitoJUnitRunner.Silent.class)
+public class K8sManagerTest {
+
+    @InjectMocks
+    private K8sManager k8sManager;
+
+    @Mock
+    private K8sMapper k8sMapper;
+
+    @Before
+    public void setUp() throws Exception {
+    }
+
+    @After
+    public void tearDown() throws Exception {
+    }
+
+    @Test
+    public void getK8sClient() {
+        
Mockito.when(k8sMapper.selectList(Mockito.any())).thenReturn(getK8sList());
+
+        KubernetesClient result = k8sManager.getK8sClient("must null");
+        Assert.assertNull(result);
+        result = k8sManager.getK8sClient(null);
+        Assert.assertNull(result);
+    }
+
+    private K8s getK8s() {
+        K8s k8s = new K8s();
+        k8s.setId(1);
+        k8s.setK8sName("default");
+        k8s.setK8sConfig("k8s config");
+        return k8s;
+    }
+
+    private List<K8s> getK8sList() {
+        List<K8s> k8sList = new ArrayList<>();
+        k8sList.add(getK8s());
+        return k8sList;
+    }
+}
\ No newline at end of file
diff --git 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/_source/createNamespace.vue
 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/_source/createNamespace.vue
new file mode 100644
index 0000000..3d0903e
--- /dev/null
+++ 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/_source/createNamespace.vue
@@ -0,0 +1,219 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+<template>
+  <m-popover
+          ref="popover"
+          :ok-text="item ? $t('Edit') : $t('Submit')"
+          @ok="_ok"
+          @close="close">
+    <template slot="content">
+      <div class="create-tenement-model">
+        <m-list-box-f>
+          <template slot="name"><strong>*</strong>{{$t('Name')}}</template>
+          <template slot="content">
+            <el-input
+                    type="input"
+                    v-model="namespace"
+                    maxlength="60"
+                    size="mini"
+                    :disabled="item ? true: false"
+                    :placeholder="$t('Please enter name')">
+            </el-input>
+          </template>
+        </m-list-box-f>
+        <m-list-box-f>
+          <template slot="name"><strong>*</strong>{{$t('K8s 
Cluster')}}</template>
+          <template slot="content">
+            <el-input
+                    type="input"
+                    v-model="k8s"
+                    maxlength="60"
+                    size="mini"
+                    :disabled="item ? true: false"
+                    :placeholder="$t('Please enter k8s cluster')">
+            </el-input>
+          </template>
+        </m-list-box-f>
+        <m-list-box-f>
+          <template slot="name">{{$t('K8s Tag')}}</template>
+          <template slot="content">
+            <el-input
+              type="input"
+              v-model="tag"
+              maxlength="60"
+              size="mini"
+              :placeholder="$t('Please enter k8s cluster')">
+            </el-input>
+          </template>
+        </m-list-box-f>
+
+        <m-list-box-f>
+          <template slot="name">{{$t('Limits Cpu')}}</template>
+          <template slot="content">
+            <el-input
+              v-model="limitsCpu"
+              size="small"
+            >
+              <template slot="append">Core</template>
+            </el-input>
+          </template>
+        </m-list-box-f>
+
+        <m-list-box-f>
+          <template slot="name">{{$t('Limits Memory')}}</template>
+          <template slot="content">
+            <el-input
+              v-model="limitsMemory"
+              size="small"
+            >
+              <template slot="append">GB</template>
+            </el-input>
+          </template>
+        </m-list-box-f>
+
+        <m-list-box-f>
+          <template slot="name">{{$t('Namespace Owner')}}</template>
+          <template slot="content">
+            <el-input
+              type="input"
+              v-model="owner"
+              maxlength="60"
+              size="mini"
+              :placeholder="$t('Please enter owner')">
+            </el-input>
+          </template>
+        </m-list-box-f>
+
+      </div>
+    </template>
+  </m-popover>
+</template>
+<script>
+  import _ from 'lodash'
+  import i18n from '@/module/i18n'
+  import store from '@/conf/home/store'
+  import mPopover from '@/module/components/popup/popover'
+  import mListBoxF from '@/module/components/listBoxF/listBoxF'
+
+  export default {
+    name: 'create-namespace',
+    data () {
+      return {
+        store,
+        namespace: '',
+        k8s: '',
+        owner: '',
+        tag: '',
+        limitsCpu: '',
+        limitsMemory: ''
+      }
+    },
+    props: {
+      item: Object
+    },
+    methods: {
+      _ok () {
+        if (!this._verification()) {
+          return
+        }
+
+        let param = {
+          namespace: _.trim(this.namespace),
+          k8s: _.trim(this.k8s),
+          owner: _.trim(this.owner),
+          tag: _.trim(this.tag),
+          limitsCpu: _.trim(this.limitsCpu),
+          limitsMemory: _.trim(this.limitsMemory)
+        }
+        // edit
+        if (this.item) {
+          param.id = this.item.id
+        }
+
+        let $then = (res) => {
+          this.$emit('onUpdate')
+          this.$message.success(res.msg)
+          this.$refs.popover.spinnerLoading = false
+        }
+
+        let $catch = (e) => {
+          this.$message.error(e.msg || '')
+          this.$refs.popover.spinnerLoading = false
+        }
+
+        if (this.item) {
+          this.$refs.popover.spinnerLoading = true
+          this.store.dispatch('security/updateNamespace', param).then(res => {
+            $then(res)
+          }).catch(e => {
+            $catch(e)
+          })
+        } else {
+          this._verifyName(param).then(() => {
+            this.$refs.popover.spinnerLoading = true
+            this.store.dispatch('security/createNamespace', param).then(res => 
{
+              $then(res)
+            }).catch(e => {
+              $catch(e)
+            })
+          }).catch(e => {
+            this.$message.error(e.msg || '')
+          })
+        }
+      },
+      _verification () {
+        if (!this.namespace.replace(/\s*/g, '')) {
+          this.$message.warning(`${i18n.$t('Please enter name')}`)
+          return false
+        }
+        if (!this.k8s.replace(/\s*/g, '')) {
+          this.$message.warning(`${i18n.$t('Please enter namespace')}`)
+          return false
+        }
+        return true
+      },
+      _verifyName (param) {
+        return new Promise((resolve, reject) => {
+          this.store.dispatch('security/verifyNamespaceK8s', param).then(res 
=> {
+            resolve()
+          }).catch(e => {
+            reject(e)
+          })
+        })
+      },
+      close () {
+        this.$emit('close')
+      }
+    },
+    watch: {
+    },
+    created () {
+      if (this.item) {
+        this.namespace = this.item.namespace
+        this.k8s = this.item.k8s
+        this.owner = this.item.owner
+        this.tag = this.item.tag
+        this.limitsCpu = this.item.limitsCpu
+        this.limitsMemory = this.item.limitsMemory
+      }
+    },
+    mounted () {
+
+    },
+    components: { mPopover, mListBoxF }
+  }
+</script>
diff --git 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/_source/list.vue
 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/_source/list.vue
new file mode 100644
index 0000000..73153b8
--- /dev/null
+++ 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/_source/list.vue
@@ -0,0 +1,110 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+<template>
+  <div class="list-model">
+    <div class="table-box">
+      <el-table :data="list" size="mini" style="width: 100%">
+        <el-table-column type="index" :label="$t('#')" 
width="50"></el-table-column>
+        <el-table-column prop="namespace" :label="$t('K8s 
Namespace')"></el-table-column>
+        <el-table-column prop="k8s" :label="$t('K8s 
Cluster')"></el-table-column>
+        <el-table-column prop="owner" :label="$t('Namespace 
Owner')"></el-table-column>
+        <el-table-column prop="tag" :label="$t('K8s Tag')"></el-table-column>
+        <el-table-column prop="limitsCpu" :label="$t('Limits 
Cpu')"></el-table-column>
+        <el-table-column prop="limitsMemory" :label="$t('Limits 
Memory')"></el-table-column>
+
+        <el-table-column :label="$t('Create Time')" min-width="120">
+          <template slot-scope="scope">
+            <span>{{scope.row.createTime | formatDate}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('Update Time')" min-width="120">
+          <template slot-scope="scope">
+            <span>{{scope.row.updateTime | formatDate}}</span>
+          </template>
+        </el-table-column>
+        <el-table-column :label="$t('Operation')" width="100">
+          <template slot-scope="scope">
+            <el-tooltip :content="$t('Edit')" placement="top">
+              <el-button type="primary" size="mini" 
icon="el-icon-edit-outline" @click="_edit(scope.row)" circle></el-button>
+            </el-tooltip>
+            <el-tooltip :content="$t('Delete')" placement="top">
+              <el-popconfirm
+                :confirmButtonText="$t('Confirm')"
+                :cancelButtonText="$t('Cancel')"
+                icon="el-icon-info"
+                iconColor="red"
+                :title="$t('Delete?')"
+                @onConfirm="_delete(scope.row,scope.row.id)"
+              >
+                <el-button type="danger" size="mini" icon="el-icon-delete" 
circle slot="reference"></el-button>
+              </el-popconfirm>
+            </el-tooltip>
+          </template>
+        </el-table-column>
+      </el-table>
+    </div>
+  </div>
+</template>
+<script>
+  import { mapActions } from 'vuex'
+
+  export default {
+    name: 'namespace-list',
+    data () {
+      return {
+        list: []
+      }
+    },
+    props: {
+      namespaceList: Array,
+      pageNo: Number,
+      pageSize: Number
+    },
+    methods: {
+      ...mapActions('security', ['deleteNamespace']),
+      _delete (item, i) {
+        this.deleteNamespace({
+          id: item.id
+        }).then(res => {
+          this.list.splice(i, 1)
+          this.$message.success(res.msg)
+          this.$emit('onUpdate')
+        }).catch(e => {
+          this.$message.error(e.msg || '')
+        })
+      },
+      _edit (item) {
+        this.$emit('on-edit', item)
+      }
+    },
+    watch: {
+      namespaceList (a) {
+        console.warn(a)
+        this.list = []
+        setTimeout(() => {
+          this.list = a
+        })
+      }
+    },
+    created () {
+      this.list = this.namespaceList
+    },
+    mounted () {
+    },
+    components: { }
+  }
+</script>
diff --git 
a/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/index.vue 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/index.vue
new file mode 100644
index 0000000..b4c91c6
--- /dev/null
+++ 
b/dolphinscheduler-ui/src/js/conf/home/pages/security/pages/namespace/index.vue
@@ -0,0 +1,160 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+<template>
+  <m-list-construction :title="$t('Namespace manage')">
+    <template slot="conditions">
+      <m-conditions @on-conditions="_onConditions">
+        <template slot="button-group" v-if="isADMIN">
+          <el-button size="mini" @click="_create('')">{{$t('Create 
namespace')}}</el-button>
+          <el-dialog
+            :title="item ? $t('Edit namespace') : $t('Create namespace')"
+            v-if="createNamespaceDialog"
+            :visible.sync="createNamespaceDialog"
+            width="auto">
+            <m-create-namespace :item="item" @onUpdate="onUpdate" 
@close="close"></m-create-namespace>
+          </el-dialog>
+        </template>
+      </m-conditions>
+    </template>
+    <template slot="content">
+      <template v-if="namespaceList.length || total>0">
+        <m-list @on-edit="_onEdit"
+                @onUpdate="onUpdate"
+                :namespace-list="namespaceList"
+                :page-no="searchParams.pageNo"
+                :page-size="searchParams.pageSize">
+
+        </m-list>
+        <div class="page-box">
+          <el-pagination
+            background
+            @current-change="_page"
+            @size-change="_pageSize"
+            :page-size="searchParams.pageSize"
+            :current-page.sync="searchParams.pageNo"
+            :page-sizes="[10, 30, 50]"
+            layout="sizes, prev, pager, next, jumper"
+            :total="total">
+          </el-pagination>
+        </div>
+      </template>
+      <template v-if="!namespaceList.length && total<=0">
+        <m-no-data></m-no-data>
+      </template>
+      <m-spin :is-spin="isLoading" :is-left="isLeft"></m-spin>
+    </template>
+  </m-list-construction>
+</template>
+<script>
+  import _ from 'lodash'
+  import { mapActions } from 'vuex'
+  import mList from './_source/list'
+  import store from '@/conf/home/store'
+  import mSpin from '@/module/components/spin/spin'
+  import mCreateNamespace from './_source/createNamespace'
+  import mNoData from '@/module/components/noData/noData'
+  import listUrlParamHandle from '@/module/mixin/listUrlParamHandle'
+  import mConditions from '@/module/components/conditions/conditions'
+  import mListConstruction from 
'@/module/components/listConstruction/listConstruction'
+
+  export default {
+    name: 'namespace-index',
+    data () {
+      return {
+        total: null,
+        isLoading: true,
+        namespaceList: [],
+        searchParams: {
+          pageSize: 10,
+          pageNo: 1,
+          searchVal: ''
+        },
+        isLeft: true,
+        isADMIN: store.state.user.userInfo.userType === 'ADMIN_USER',
+        item: {},
+        createNamespaceDialog: false
+
+      }
+    },
+    mixins: [listUrlParamHandle],
+    props: {},
+    methods: {
+      ...mapActions('security', ['getNamespaceListP']),
+      /**
+       * Query
+       */
+      _onConditions (o) {
+        this.searchParams = _.assign(this.searchParams, o)
+        this.searchParams.pageNo = 1
+      },
+      _page (val) {
+        this.searchParams.pageNo = val
+      },
+      _pageSize (val) {
+        this.searchParams.pageSize = val
+      },
+      _onEdit (item) {
+        this._create(item)
+      },
+      _create (item) {
+        this.item = item
+        this.createNamespaceDialog = true
+      },
+      onUpdate () {
+        this._debounceGET('false')
+        this.createNamespaceDialog = false
+      },
+      close () {
+        this.createNamespaceDialog = false
+      },
+      _getList (flag) {
+        if (sessionStorage.getItem('isLeft') === '0') {
+          this.isLeft = false
+        } else {
+          this.isLeft = true
+        }
+        this.isLoading = !flag
+        this.getNamespaceListP(this.searchParams).then(res => {
+          if (this.searchParams.pageNo > 1 && res.totalList.length === 0) {
+            this.searchParams.pageNo = this.searchParams.pageNo - 1
+          } else {
+            this.namespaceList = res.totalList
+            this.total = res.total
+            this.isLoading = false
+          }
+        }).catch(e => {
+          this.isLoading = false
+        })
+      }
+    },
+    watch: {
+      // router
+      '$route' (a) {
+        // url no params get instance list
+        this.searchParams.pageNo = _.isEmpty(a.query) ? 1 : a.query.pageNo
+      }
+    },
+    created () {
+    },
+    mounted () {
+    },
+    beforeDestroy () {
+      sessionStorage.setItem('isLeft', 1)
+    },
+    components: { mList, mListConstruction, mConditions, mSpin, mNoData, 
mCreateNamespace }
+  }
+</script>
diff --git a/dolphinscheduler-ui/src/js/conf/home/router/module/security.js 
b/dolphinscheduler-ui/src/js/conf/home/router/module/security.js
index 4087460..cac6e48 100644
--- a/dolphinscheduler-ui/src/js/conf/home/router/module/security.js
+++ b/dolphinscheduler-ui/src/js/conf/home/router/module/security.js
@@ -94,6 +94,14 @@ const security = [
         meta: {
           title: `${i18n.$t('Token manage')}`
         }
+      },
+      {
+        path: '/security/namespace',
+        name: 'namespace',
+        component: resolve => 
require(['../../pages/security/pages/namespace'], resolve),
+        meta: {
+          title: `${i18n.$t('K8s Namespace')}`
+        }
       }
     ]
   }
diff --git a/dolphinscheduler-ui/src/js/conf/home/store/security/actions.js 
b/dolphinscheduler-ui/src/js/conf/home/store/security/actions.js
index b6b5a87..07cc6c9 100644
--- a/dolphinscheduler-ui/src/js/conf/home/store/security/actions.js
+++ b/dolphinscheduler-ui/src/js/conf/home/store/security/actions.js
@@ -710,5 +710,68 @@ export default {
         reject(e)
       })
     })
+  },
+
+  /**
+   * create namespace
+   */
+  createNamespace ({ state }, payload) {
+    return new Promise((resolve, reject) => {
+      io.post('k8s-namespace', payload, res => {
+        resolve(res)
+      }).catch(e => {
+        reject(e)
+      })
+    })
+  },
+  /**
+   * update namespace
+   */
+  updateNamespace ({ state }, payload) {
+    return new Promise((resolve, reject) => {
+      io.put(`k8s-namespace/${payload.id}`, payload, res => {
+        resolve(res)
+      }).catch(e => {
+        reject(e)
+      })
+    })
+  },
+  /**
+   * update namespace k8s
+   */
+  verifyNamespaceK8s ({ state }, payload) {
+    return new Promise((resolve, reject) => {
+      io.post('k8s-namespace/verify', payload, res => {
+        resolve(res)
+      }).catch(e => {
+        reject(e)
+      })
+    })
+  },
+
+  /**
+   * delete namespace
+   * @param "id":int
+   */
+  deleteNamespace ({ state }, payload) {
+    return new Promise((resolve, reject) => {
+      io.post('k8s-namespace/delete', payload, res => {
+        resolve(res)
+      }).catch(e => {
+        reject(e)
+      })
+    })
+  },
+  /**
+   * get namespace list pages
+   */
+  getNamespaceListP ({ state }, payload) {
+    return new Promise((resolve, reject) => {
+      io.get('k8s-namespace', payload, res => {
+        resolve(res.data)
+      }).catch(e => {
+        reject(e)
+      })
+    })
   }
 }
diff --git 
a/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js 
b/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js
index 62f627e..96a812c 100644
--- a/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js
+++ b/dolphinscheduler-ui/src/js/module/components/secondaryMenu/_source/menu.js
@@ -187,6 +187,16 @@ const menu = {
       icon: 'el-icon-document',
       children: [],
       classNames: 'tab-token-manage'
+    },
+    {
+      name: `${i18n.$t('K8s Namespace')}`,
+      id: 2,
+      path: 'namespace',
+      isOpen: true,
+      icon: 'el-icon-s-grid',
+      children: [],
+      enabled: true,
+      classNames: 'tab-namespace-manage'
     }
   ],
   resource: [
diff --git a/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js 
b/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
index 7b73389..a42f195 100755
--- a/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
+++ b/dolphinscheduler-ui/src/js/module/i18n/locale/en_US.js
@@ -901,5 +901,19 @@ export default {
   Last7DayFluctuation: 'Last7DayFluctuation',
   Last30DayFluctuation: 'Last30DayFluctuation',
   SrcTableTotalRows: 'SrcTableTotalRows',
-  TargetTableTotalRows: 'TargetTableTotalRows'
+  TargetTableTotalRows: 'TargetTableTotalRows',
+  // k8s
+  'Create namespace': 'Create namespace',
+  'Edit namespace': 'Edit namespace',
+  'Namespace manage': 'K8s namespace manage',
+  'K8s Namespace': 'k8s Namespace',
+  'Limits Cpu': 'Limit Cpu',
+  'Limits Memory': 'Limit Memory',
+  'K8s Cluster': 'k8s',
+  'Namespace Owner': 'Owner',
+  'Please enter k8s cluster': 'Please enter k8s cluster',
+  'Please enter namespace': 'Please enter namespace',
+  'Please enter namespace tag': 'Please enter namespace tag can null',
+  'Please enter owner': 'Please enter owner can null',
+  'K8s Tag': 'tag'
 }
diff --git a/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js 
b/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js
index d0c2871..dd823bb 100755
--- a/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js
+++ b/dolphinscheduler-ui/src/js/module/i18n/locale/zh_CN.js
@@ -901,5 +901,19 @@ export default {
   Last7DayFluctuation: '最近7天波动',
   Last30DayFluctuation: '最近30天波动',
   SrcTableTotalRows: '源表总行数',
-  TargetTableTotalRows: '目标表总行数'
+  TargetTableTotalRows: '目标表总行数',
+  // k8s
+  'Create namespace': '创建命名空间',
+  'Edit namespace': '编辑命名空间',
+  'Namespace manage': 'k8s命名空间 管理',
+  'K8s Namespace': 'k8s命名空间',
+  'Limits Cpu': '最大Cpu',
+  'Limits Memory': '最大内存',
+  'K8s Cluster': 'k8s集群',
+  'Namespace Owner': '负责人',
+  'Please enter k8s cluster': '请输入k8s集群值',
+  'Please enter namespace': '请输入命名空间',
+  'Please enter namespace tag': '请输入命名空间标签可空',
+  'Please enter owner': '请输入owner可空',
+  'K8s Tag': '标签'
 }
diff --git a/pom.xml b/pom.xml
index 9c7bceb..8d3fb24 100644
--- a/pom.xml
+++ b/pom.xml
@@ -127,6 +127,7 @@
         
<error_prone_annotations.version>2.5.1</error_prone_annotations.version>
         <exec-maven-plugin.version>3.0.0</exec-maven-plugin.version>
         <janino.version>3.1.6</janino.version>
+        <kubernetes.version>5.8.0</kubernetes.version>
 
         <docker.hub>apache</docker.hub>
         <docker.repo>${project.name}</docker.repo>
@@ -902,6 +903,12 @@
                 <artifactId>error_prone_annotations</artifactId>
                 <version>${error_prone_annotations.version}</version>
             </dependency>
+
+            <dependency>
+                <groupId>io.fabric8</groupId>
+                <artifactId>kubernetes-client</artifactId>
+                <version>${kubernetes.version}</version>
+            </dependency>
         </dependencies>
     </dependencyManagement>
 
diff --git a/tools/dependencies/known-dependencies.txt 
b/tools/dependencies/known-dependencies.txt
index 973f3cb..6e9ecfb 100755
--- a/tools/dependencies/known-dependencies.txt
+++ b/tools/dependencies/known-dependencies.txt
@@ -237,3 +237,31 @@ xmlbeans-3.1.0.jar
 xmlenc-0.52.jar
 zookeeper-3.4.14.jar
 Java-WebSocket-1.5.1.jar
+kubernetes-client-5.8.0.jar
+kubernetes-model-admissionregistration-5.8.0.jar
+kubernetes-model-apiextensions-5.8.0.jar
+kubernetes-model-apps-5.8.0.jar
+kubernetes-model-autoscaling-5.8.0.jar
+kubernetes-model-batch-5.8.0.jar
+kubernetes-model-certificates-5.8.0.jar
+kubernetes-model-common-5.8.0.jar
+kubernetes-model-coordination-5.8.0.jar
+kubernetes-model-core-5.8.0.jar
+kubernetes-model-discovery-5.8.0.jar
+kubernetes-model-events-5.8.0.jar
+kubernetes-model-extensions-5.8.0.jar
+kubernetes-model-flowcontrol-5.8.0.jar
+kubernetes-model-metrics-5.8.0.jar
+kubernetes-model-networking-5.8.0.jar
+kubernetes-model-node-5.8.0.jar
+kubernetes-model-policy-5.8.0.jar
+kubernetes-model-rbac-5.8.0.jar
+kubernetes-model-scheduling-5.8.0.jar
+kubernetes-model-storageclass-5.8.0.jar
+zjsonpatch-0.3.0.jar
+automaton-1.11-8.jar
+generex-1.0.2.jar
+jackson-dataformat-yaml-2.12.5.jar
+logging-interceptor-3.14.9.jar
+okhttp-3.14.9.jar
+okio-1.17.2.jar
\ No newline at end of file

Reply via email to