Skip to content

Commit

Permalink
Merge branch 'dev' into develop
Browse files Browse the repository at this point in the history
  • Loading branch information
DreamPWJ committed Feb 21, 2024
2 parents c6fe381 + 8ef0b7c commit 7102ca7
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 6 deletions.
2 changes: 1 addition & 1 deletion .ci/python/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ RUN tar -pxzvf python.tar.gz >/dev/null 2>&1 \
EXPOSE $EXPOSE_PORT

# 根据主文件默认名称 app.py CMD中的"$MY_VAR"变量设置成 docker run -e MY_VAR=value 运行变量 否则无法获取
CMD ["python", "main.py"]
CMD ["python", "$PYTHON_START_FILE"]

# Flask部署 启动命令
#CMD [ "python", "-m" , "flask", "run", "--host=0.0.0.0"]
Expand Down
2 changes: 1 addition & 1 deletion .ci/python/docker-release-python.sh
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ echo "👨‍💻 启动运行Docker容器 环境: ${env_mode} 映射端口: ${h
docker run -d --restart=always -p ${host_port}:${expose_port} \
-e "PROJECT_NAME=${project_name}" \
-m ${docker_memory} --log-opt ${docker_log_opts} --log-opt max-file=1 ${dynamic_run_args} \
-e "REMOTE_DEBUGGING_PARAM=${remote_debugging_param}" \
-e "REMOTE_DEBUGGING_PARAM=${remote_debugging_param}" -e "PYTHON_START_FILE=${python_start_file}" \
-v /${deploy_folder}/${project_name}/logs:/logs \
--name ${docker_container_name} ${docker_image_name}

Expand Down
13 changes: 11 additions & 2 deletions _k8s/k8s_yaml.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
parser.add_argument('--remote_debug_port', type=int, default=None)
parser.add_argument('--is_use_session', type=bool, default=False)
parser.add_argument('--set_yaml_arags', type=str, default=None)
parser.add_argument('--set_python_start_file', type=str, default=None)

args = parser.parse_args()

Expand Down Expand Up @@ -106,15 +107,23 @@
[*nsf_server_yaml]
)

# 动态设置k8s yaml args参数
# Java动态设置k8s yaml args参数
set_yaml_arags = args.set_yaml_arags
if set_yaml_arags is not None:
print(set_yaml_arags)
# 适配Java Spring Boot框架容器动态启动命令
yaml_containers[0]["command"] = ["java"] # 覆盖或补充 ENTRYPOINT
yaml_containers[0]["command"] = ["java"] # 覆盖或补充 ENTRYPOINT 或 CMD
yaml_containers[0]["args"] = ["-jar", "-Xms128m", set_yaml_arags,
"-Djava.security.egd=file:/dev/./urandom", "/server.jar"]

# 设置python语言相关的参数
set_python_start_file = args.set_python_start_file
if set_python_start_file is not None:
print(set_python_start_file)
# 启动命令
yaml_containers[0]["command"] = ["python"] # 覆盖或补充 ENTRYPOINT 或 CMD
yaml_containers[0]["args"] = [set_python_start_file]

# 业务应用是否使用Session处理
if is_use_session:
service_spec = yamlContent[1]['spec']
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
# Author: 潘维吉
# Description: 云原生K8S中使用cert-manager基于 ACME 协议与 Let's Encrypt 自动签发与续签免费的SSL证书

# 创建一个集群级的签发机构 仅需一次
apiVersion: cert-manager.io/v1
kind: ClusterIssuer
metadata:
name: letsencrypt-prod-lanneng-open-park-third-party
namespace: cert-manager
spec:
acme:
server: https://acme-v02.api.letsencrypt.org/directory # ACME 协议的服务端 acme-staging-v02测试证书没有限制
email: 406798106@qq.com # 证书快过期的时候会有邮件提醒
privateKeySecretRef:
name: letsencrypt-prod-key-lanneng-open-park-third-party # 私钥秘密必须与cert-manager服务在同一个命名空间中才能工作 kubectl delete Secret letsencrypt-prod-key --namespace cert-manager
solvers:
- http01: # 签发机构使用 HTTP-01 的方式进行 acme 协议 (还可用 DNS 方式,acme 协议的目的是证明机器和域名都是属于你的,然后才准许颁发证书)
ingress:
#serviceType: ClusterIP
name: lannengtech-k8s-ingress-lanneng-open-park-third-party # 这个匹配是关键!!! 1. class是指定自动创建的 Ingress 的 ingress class 2. name是指定被自动修改的 Ingress 名称

---

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: lannengtech-k8s-ingress-lanneng-open-park-third-party
namespace: default
annotations:
# 指定使用nginx做代理
#kubernetes.io/ingress.class: lanneng-park # 已弃用 使用 spec.ingressClassName代替
# add an annotation indicating the issuer to use
cert-manager.io/cluster-issuer: letsencrypt-prod-lanneng-open-park-third-party
acme.cert-manager.io/http01-edit-in-place: "true"

# 后端大文件上传大小
nginx.ingress.kubernetes.io/client-body-buffer-size: 1024m
nginx.ingress.kubernetes.io/proxy-max-temp-file-size: 2048m
# 数据传输大小
nginx.ingress.kubernetes.io/proxy-body-size: 1024m

# 开启CORS跨域请求
nginx.ingress.kubernetes.io/enable-cors: "true"
nginx.ingress.kubernetes.io/cors-allow-origin: "*"
nginx.ingress.kubernetes.io/cors-max-age: "64800"
nginx.ingress.kubernetes.io/cors-allow-methods: "PUT, GET, POST, DELETE, PATCH, OPTIONS"
nginx.ingress.kubernetes.io/cors-allow-credentials: "true"

# 配置是否同时支持http和https访问应用
nginx.ingress.kubernetes.io/ssl-redirect: "false"

# 采用了 “漏斗” 算法实现限流 保证服务可用性和被攻击 nginx的限流是一个队列模型。限流连接数为 队列长度+队列处理能力
# 每个IP每秒可以访问的次数 默认乘数为5
nginx.ingress.kubernetes.io/limit-rps: "50"
# 为计算限速漏桶算法的 burst size和 limit-rps 的相乘放大系数 burst为队列长度
nginx.ingress.kubernetes.io/limit-burst-multiplier: "10"
# 配合 limit-window 表示每多少秒全局限速多少次(需要依赖 memcached)
nginx.ingress.kubernetes.io/global-rate-limit: "100000"
nginx.ingress.kubernetes.io/global-rate-limit-window: 1s
# 限制发送给后端服务的发送速率为 多少MB/每秒 rate为队列处理能力
#nginx.ingress.kubernetes.io/limit-rate: 10240
# 发送给后端服务的前 多少MB 数据不进行限速
#nginx.ingress.kubernetes.io/limit-rate-after: 102400
# 白名单 客户端IP源范围要从速率限制中排除。该值是逗号分隔的CIDR列表
#nginx.ingress.kubernetes.io/limit-whitelist:
# 限流超出后的响应码
nginx.ingress.kubernetes.io/configuration-snippet: |
limit_req_status 429;
spec:
ingressClassName: lanneng-park
tls:
- hosts:
- park-foreign-api.pengbocloud.com
secretName: park-foreign-api.pengbocloud.com-tls

rules:
#自定义域名
- host: park-foreign-api.pengbocloud.com
http:
paths:
- path: /
backend:
#服务名称
service:
name: park-saas-foreign-python-service
#服务端口
port:
number: 8201
pathType: Prefix
140 changes: 140 additions & 0 deletions pipelines/epark/Jenkinsfile.lanneng-open-park-third-party-prod
Original file line number Diff line number Diff line change
@@ -0,0 +1,140 @@
#!groovy
@Library('jenkins-shared-library@dev') _

/**
* @author 潘维吉
* @description 核心Pipeline代码 针对Python语言项目CI/CD的脚本
* 注意 本文件在Git位置和名称不能随便改动 配置在jenkins里
*/

// 根据不同环境项目配置不同参数
def map = [:]

// 远程服务器地址 k8s集群方式可填空或填公网代理负载IP
map.put('remote_ip', '120.92.149.246')
// 工作服务器地址 同时支持N个服务器自动化分布式部署
map.put('remote_worker_ips', [])
// 远程服务器用户名
map.put('remote_user_name', 'root')
// 代理机或跳板机外网ip用于透传部署到内网目标机器 选填 目标机器外部无法直接访问情况填写内网ip
map.put('proxy_jump_ip', ' ')
// 自定义跳板机ssh和scp访问用户名 可精细控制权限 默认root
map.put('proxy_jump_user_name', 'root')
// 自定义跳板机ssh和scp访问端口 默认22
map.put('proxy_jump_port', ' ')

// 默认统一设置项目级别的分支 方便整体控制改变分支 将覆盖单独job内的设置
map.put('default_git_branch', ' ')

// 保持构建的最大个数
map.put('build_num_keep', 2)

// Docker相关参数
// JVM内存设置
map.put('docker_java_opts', '-Xmx2000m')
// docker内存限制 不支持小数点形式设置
map.put('docker_memory', '2G')
// docker日志限制
map.put('docker_log_opts', 'max-size=150m') // --log-opt max-size=50m --log-opt max-file=3
// docker挂载映射 docker run -v 参数(格式 宿主机挂载路径:容器内目标路径) 多个用逗号,分割
map.put('docker_volume_mount', '')
// Dockerfile多阶段构建 镜像名称
map.put('docker_multistage_build_images', ' ')
// 是否上传镜像到docker容器仓库
map.put('is_push_docker_repo', true)
// docker容器镜像仓库账号信任id
map.put('docker_repo_credentials_id', '73f6b3b0-4580-4acf-b04a-63892fcf9ba8')
// docker镜像仓库注册地址
map.put('docker_repo_registry', 'hub-cn-shanghai-2.kce.ksyun.com')
// docker仓库命名空间名称
map.put('docker_repo_namespace', 'lanneng')

// K8S集群相关参数
// K8S集群访问授权账号kube.config配置信息信任ids 多集群,逗号分割 Jenkins系统管理的Manage Credentials,类型选择为“Secret file”配置
map.put('k8s_credentials_ids', 'a1d2642d-296f-47a2-8d1a-087b46e3255e')
// K8S集群私有镜像仓库拉取密钥 在集群内使用kubectl create secret命令生成
map.put('k8s_image_pull_secrets', 'lannengkeji2022')

// 项目标签或项目简称
map.put('project_tag', '停车开放平台')

// 是否是生产环境
map.put('is_prod', true)
// 是否在同一台服务器蓝绿部署或滚动部署 非k8s集群方式设置
map.put('is_same_server', false)
// 是否进行优雅停机
map.put('is_grace_shutdown', false)
// 是否进行服务启动健康探测 K8S集群类型设置false
map.put('is_health_check', false)
// 是否Pipeline内脚本钉钉通知 总开关
map.put('is_ding_notice', true)
// 是否进行部署前通知
map.put('is_before_deploy_notice', false)
// 是否通知变更记录
map.put('is_notice_change_log', true)
// 是否在生产环境发布成功后自动给Git仓库打Tag版本和生成变更记录
map.put('is_git_tag', false)
// 是否需要css预处理器sass
map.put('is_need_sass', false)

// jenkins分布式构建节点label名称 预配置在jenkins节点管理内
map.put('jenkins_node', 'master')
map.put('jenkins_node_front_end', 'master')

// 构建环境变量 分别使用Node和Maven关键字加版本号方式 如Maven3.6
map.put('nodejs', 'Node18')
map.put('maven', 'Maven3.6')
map.put('jdk', '11')

// 相关信任标识
map.put('ci_git_credentials_id', '5379273a-f829-4091-ab19-46c184fcbeb2')
map.put('git_credentials_id', '5379273a-f829-4091-ab19-46c184fcbeb2')
map.put('ding_talk_credentials_id', 'd33ae0ba-e531-41c8-8983-d9734e53a25a')
// OSS对象存储访问凭据配置 Jenkins系统管理的Manage Credentials,类型选择为“Secret file”配置
map.put('oss_credentials_id', ' ')
// 直连方式服务器集群自动SSH连接信息 实现CI构建机器和多台部署机之间的免密连接
map.put('ssh_hosts_id', ' ')
// 跳板机方式服务器集群自动SSH连接信息 实现CI构建机器和多台部署机之间的免密连接
map.put('proxy_jump_hosts_id', ' ')

// 服务器上部署所在的文件夹名称
map.put('deploy_folder', "my")
// Web项目NPM打包代码所在的文件夹名称
map.put('npm_package_folder', "dist")
// Web项目解压到指定目录层级
map.put('web_strip_components', 1)
// 如果Maven模块化存在二级模块目录 设置一级模块目录名称
map.put('maven_one_level', ' ')
// Maven自定义指定settings.xml文件 如设置私有库或镜像源情况
map.put('maven_setting_xml', ' ')

// 调用核心通用Pipeline
sharedLibrary(map)


// ---------------------------------------------------------------------------------------------------------------------
// https://git.pengbocloud.com/lanneng_develop/jenkins-shared-library.git pipelines/epark/Jenkinsfile.lanneng-open-park-third-party-prod

/*
park-saas-foreign-k8s-prod
停车开放服务-k8s集群
JSON_PARAMS
{
"REPO_URL" : "https://git.pengbocloud.com/lanneng_develop/park_saas_foreign_python.git" ,
"BRANCH_NAME" : "master" ,
"PROJECT_TYPE" : "2" ,
"COMPUTER_LANGUAGE" : "3" ,
"PROJECT_NAME" : "park-saas-foreign" ,
"SHELL_PARAMS" : "park-saas-foreign python 8201 5000 prod",
"IS_K8S_DEPLOY" : true,
"K8S_POD_REPLICAS" : "1",
"CUSTOM_PYTHON_VERSION" : "3.10.0",
"CUSTOM_PYTHON_START_FILE" : "app.py",
"CUSTOM_HEALTH_CHECK_PATH" : "/healthy-check",
"APPLICATION_DOMAIN" : "https://park-foreign-api.pengbocloud.com"
}
*/


9 changes: 7 additions & 2 deletions src/shared/library/common/Kubernetes.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -151,6 +151,7 @@ class Kubernetes implements Serializable {
def yamlVolumeMounts = ""
def yamlNfsParams = ""
def setYamlArags = ""
def setPythonParams = ""
// 复杂参数动态组合配置yaml文件
if ("${ctx.IS_USE_SESSION}" == "true") { // k8s集群业务应用是否使用Session 做亲和度关联
isYamlUseSession = " --is_use_session=true "
Expand All @@ -161,12 +162,16 @@ class Kubernetes implements Serializable {
if ("${ctx.NFS_MOUNT_PATHS}".trim() != "") { // NFS服务
yamlNfsParams = " --nfs_server=${ctx.NFS_SERVER} --nfs_params=${ctx.NFS_MOUNT_PATHS} "
}
// 动态设置k8s yaml args参数
// java动态设置k8s yaml args参数
if ("${ctx.PROJECT_TYPE}".toInteger() == GlobalVars.backEnd && "${ctx.COMPUTER_LANGUAGE}".toInteger() == GlobalVars.Java && "${ctx.JAVA_FRAMEWORK_TYPE}".toInteger() == GlobalVars.SpringBoot) {
setYamlArags = " --set_yaml_arags='${map.docker_java_opts}' "
}
// 设置python语言相关的参数
if ("${ctx.PROJECT_TYPE}".toInteger() == GlobalVars.backEnd && "${ctx.COMPUTER_LANGUAGE}".toInteger() == GlobalVars.Python) {
setPythonParams = " --set_python_start_file=${ctx.CUSTOM_PYTHON_START_FILE} "
}

pythonYamlParams = isYamlUseSession + yamlVolumeMounts + yamlNfsParams + yamlDefaultPort + setYamlArags
pythonYamlParams = isYamlUseSession + yamlVolumeMounts + yamlNfsParams + yamlDefaultPort + setYamlArags + setPythonParams
if ("${pythonYamlParams}".trim() != "") {
ctx.dir("${ctx.env.WORKSPACE}/ci/_k8s") {
ctx.println("使用Python的ruamel包动态配置K8S的Yaml文件: " + pythonYamlParams)
Expand Down

0 comments on commit 7102ca7

Please sign in to comment.