k8s部署gin-vue-admin框架、gitlab-ci、jenkins pipeline 、CICD
测试环境使用的jenkins
正式环境使用的gitlab-ci
测试环境
- 创建yaml文件
apiVersion: v1
kind: ConfigMap
metadata:name: dtk-go-tiktok-admin-configlabels:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/runtime: golangapp.kubernetes.io/tier: backendapp.kubernetes.io/environment: testapp.kubernetes.io/managed-by: yong.xd
data:config.yaml: |max-age: 0show-line: truelog-in-console: true---
apiVersion: v1
kind: ConfigMap
metadata:name: dtk-vue-tiktok-admin-configlabels:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/runtime: golangapp.kubernetes.io/tier: frontapp.kubernetes.io/environment: testapp.kubernetes.io/managed-by: yong.xd
data:default.conf: |server{listen 80 default_server;server_name _;access_log /dev/stdout;error_log /dev/stdout;root /opt/app/dist/;location / {try_files $uri $uri/ /index.html;}location /api {proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;rewrite ^/api/(.*)$ /$1 break; #重写add_header 'dtk-debug' 'api';#一个deployment2个pod是网络资源是共享的,所以可以直接代理proxy_pass http://127.0.0.1:8888; # 设置代理服务器的协议和地址}location /api/swagger/index.html {proxy_pass http://127.0.0.1:8888/swagger/index.html;}location /health {access_log off;return 200;}}---
apiVersion: apps/v1
kind: Deployment
metadata:name: dtk-go-tiktok-adminlabels:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/runtime: golangapp.kubernetes.io/tier: backendapp.kubernetes.io/environment: testapp.kubernetes.io/managed-by: yong.xd
spec:replicas: 1selector:matchLabels:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/runtime: golangapp.kubernetes.io/tier: backendapp.kubernetes.io/environment: testapp.kubernetes.io/managed-by: yong.xdtemplate:metadata:labels:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/runtime: golangapp.kubernetes.io/tier: backendapp.kubernetes.io/environment: testapp.kubernetes.io/managed-by: yong.xdspec:imagePullSecrets:- name: aliyun-regcredserviceAccountName: defaultsecurityContext:dnsPolicy: NonednsConfig:nameservers:- 172.31.74.196searches:- test1.svc.cluster.local- svc.cluster.local- cluster.localcontainers:- name: golangsecurityContext:runAsUser: 0image: "registry.buydance.com/dataoke-test/dtk-go-tiktok-admin-golang:latest"volumeMounts:- name: configmountPath: /opt/app/conf/ports:- name: httpcontainerPort: 8888protocol: TCPlivenessProbe:httpGet:path: /healthport: 8888initialDelaySeconds: 5periodSeconds: 20timeoutSeconds: 3readinessProbe:httpGet:path: /healthport: 8888initialDelaySeconds: 5periodSeconds: 10timeoutSeconds: 3resources:requests:cpu: 1mmemory: 20Mi- name: nginxsecurityContext:image: "registry.buydance.com/dataoke-test/dtk-go-tiktok-admin-nginx:latest"volumeMounts:- name: ng-configmountPath: /etc/nginx/conf.d/ports:- name: httpcontainerPort: 80protocol: TCPlivenessProbe:httpGet:path: /healthport: 80periodSeconds: 5readinessProbe:httpGet:path: /healthport: 80periodSeconds: 5resources:requests:cpu: 1mmemory: 64Milimits:cpu: 200mmemory: 256Mivolumes:- name: ng-configconfigMap:name: dtk-vue-tiktok-admin-config- name: configconfigMap:name: dtk-go-tiktok-admin-config
---
apiVersion: v1
kind: Service
metadata:name: dtk-go-tiktok-admin
spec:ports:- port: 80targetPort: 80protocol: TCPname: nginx- port: 8888targetPort: 8888protocol: TCPname: golangselector:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/runtime: golangapp.kubernetes.io/tier: backendapp.kubernetes.io/environment: testapp.kubernetes.io/managed-by: yong.xd
- 启动服务
kubectl apply -f ./ -n test1
- 配置jenkins
#!/usr/bin/env groovy
import groovy.json.JsonOutputString gitRepositryURL = 'https://test.com/dtk-go-tiktok-admin.git'
String dockerRegistry = 'test.com'
String dockerRegistryURL = 'https://test.com'
String dockerRegistryNameSpace = 'dataoke-test'
#dockerfile路径
String kubeManifestsRepo = '/home/jenkins/repo/dtk-kubernetes-test/app'
Map dockerFiles = ["nginx":"Dockerfile.test.nginx", "golang":"Dockerfile.test.golang"]
Map dockerImages = [:]
boolean notify = falseString jobBaseName = env.JOB_NAME[4..-1]
String jobK8sName = jobBaseName.replaceAll('_', "-") Map commitInfo = [:]
Map buildInfo = [:]commitInfo.projectName = gitRepositryURL.replaceFirst(/^.*\/([^\/]+?).git$/, '$1')
commitInfo.gitRepositryURL = gitRepositryURL
buildInfo.buildId = currentBuild.id@NonCPS
def newSh(String cmd) {def script = '#!/bin/sh +x\n' << cmdresult = sh(returnStdout: true, script: script.toString())return result
}pipeline {agent anyoptions {buildDiscarder logRotator(artifactDaysToKeepStr: '', artifactNumToKeepStr: '', daysToKeepStr: '10', numToKeepStr: '10')}parameters {choice( name: 'PENV',choices: ['dev1','dev2','test1','test2', 'test3', 'test4','test5','test6','test7','huise',
'huise4','huise3'], description: '选择发布环境,默认发布至dev1测试环境')gitParameter(name: 'GIT_BRANCH', type: 'PT_BRANCH_TAG',branchFilter: 'origin/(.*)',defaultValue: 'master',selectedValue: 'DEFAULT',sortMode: 'DESCENDING_SMART',quickFilterEnabled: true, description: 'Select your branch or tag.')booleanParam(name: 'force', defaultValue: false, description: '代码重复强制发版')}stages {stage('预处理') {steps {script {def now = new Date()buildInfo.buildDate = now.format("yy-MM-dd HH:mm", TimeZone.getTimeZone('UTC'))def causes = currentBuild.getBuildCauses()buildInfo.buildUser = causes[0]['userName']userList = readYaml(file:'/etc/jenkins/users.yaml')if (!(PENV in userList.env.dev ) && !(buildInfo.buildUser in userList.user.allow)) {error(message: "开发只能发布环境到${userList.env.dev.join(',')}") }buildInfo.gitBranch = GIT_BRANCHbuildInfo.publishEnv = PENVcurrentBuild.description = "k8s环境: ${PENV} 构建人:${buildInfo.buildUser} 分支: ${GIT_BRANCH}"newSh("check.py -u ${buildInfo.buildUser} -e ${PENV}")}}}stage('同步代码仓库') {steps {script {def scmVars = checkout([$class: 'GitSCM', branches: [[name: "${GIT_BRANCH}"]], extensions: [[$class: 'CheckoutOption', timeout: 20], [$class: 'CloneOption', depth: 1]], userRemoteConfigs: [[credentialsId: "5411496d-3606-4855-ab9c-2e4453cd2880", url: "${gitRepositryURL}"]]])commitInfo.gitCommit = scmVars.GIT_COMMITcommitInfo.gitBranch = GIT_BRANCHcommitInfo.xiangmu_name = env.JOB_BASE_NAMEcommitInfo.commitDate = newSh('git log --pretty=format:"%ci" -1')commitInfo.cmmitMessage = newSh('git log --pretty=format:"%s" -1')String gitDiff = newSh('git diff HEAD^ HEAD')def committer = [:]committer.name = newSh('git log --pretty=format:"%cn" -1')committer.email = newSh('git log --pretty=format:"%ce" -1')commitInfo.committer = committerString consoleStdout = "\n\n---------SYNCHRONIZE GIT REPOSITORY---------\nGit repo sync successfully.\n\n" + JsonOutput.prettyPrint(JsonOutput.toJson(commitInfo))println(consoleStdout)consoleStdout = "\n\n---------CHANGE LOGS---------\nGit diff:\n\n" + gitDiffprintln(consoleStdout)getDatabaseConnection(type: 'GLOBAL') {def sqlString="select commit_seccec from jenkins_commit.jenkins_jilu where xm_name = ? and env = ?"def params=[commitInfo.xiangmu_name,PENV]def rest_null = sql sql:sqlString,parameters:paramsif (rest_null.size() == 0){def sqlString2="insert into jenkins_commit.jenkins_jilu(xm_name,env,commit_seccec) values(?,?,?)"def params2=[commitInfo.xiangmu_name,PENV,commitInfo.gitCommit]sql sql:sqlString2,parameters:params2println("mysql插入数据")}if (rest_null.size() >= 1) {def Map rest = rest_null.get(0)if (rest.get("commit_seccec") == commitInfo.gitCommit && force == "false"){currentBuild.description = "k8s环境: ${PENV} 构建人:${buildInfo.buildUser} 分支: ${GIT_BRANCH} 构建失败: 代码重复不发版"println("代码没有变化不做发版")error "上一个版本和现在正在发的版本一致,不做发版"}}}}}}stage('构建') { agent {docker { image 'registry.buydance.com/dataoke-test/golang:1.19'args '--user root -v /data/jenkins_build_cache/.cache:/.cache'args '--user root -v /data/lib/go:/go'reuseNode true} }steps {script {env.STAGE = "goujian"def now = new Date()String buildDate = now.format("yy-MM-dd HH:mm", TimeZone.getTimeZone('UTC'))sh (script: '#!/bin/sh +x\n' + '''cd ./servermkdir -p .cacheexport GO111MODULE=onexport GOPROXY=https://goproxy.cn,directexport GOPRIVATE="gitlab.buydance.com/*"export CGO_ENABLED=0go mod tidygo build -o main''')def files = findFiles(glob: '**/main')String artifactPath = files[0].pathString sha1Checksum = sha1(file: artifactPath)String sha256Checksum = sha256(file: artifactPath)consoleStdout = "\n\n---------BUILD RESULTS---------\nBuild info generated successfully.\n\n" + JsonOutput.prettyPrint(JsonOutput.toJson(buildInfo))println(consoleStdout)} }}stage('构建vue') { agent {docker { image 'node:14.19.3-alpine3.15'args '--user root -v /data/jenkins_build_cache/.cache:${HOME}/.cache'args '--user root -v /data/lib/composer:/root/.composer'reuseNode true} }steps {script {sh """cd ./webnpm config set puppeteer_download_host=https://npm.taobao.org/mirrorsnpm i --registry=https://registry.npm.taobao.orgnpm run build"""consoleStdout = "\n\n---------BUILD RESULTS---------\nBuild info generated successfully.\n\n" + JsonOutput.prettyPrint(JsonOutput.toJson(buildInfo))println(consoleStdout)} }}stage('Docker') {steps {script {env.STAGE = "DOCKERFIEL"// docker.withRegistry(dockerRegistryURL, '8f1a40fa-3258-4717-825c-a9f87299916d') {docker.withRegistry(dockerRegistryURL) {String dockerFile = kubeManifestsRepo + '/' + jobBaseName + '/' + 'Dockerfile.test.nginx'if (!fileExists(dockerFile)) {dockerFile = kubeManifestsRepo + '/' + jobK8sName + '/' + 'Dockerfile.test.nginx'}String dockerRepository = dockerRegistry + '/' + dockerRegistryNameSpace + '/' + jobK8sName + '-' + 'nginx'def customImage = docker.build(dockerRepository, "-f ${dockerFile} .")customImage.push(commitInfo.gitCommit)customImage.push('latest')dockerImages.nginx = dockerRepository + ':' + commitInfo.gitCommitdockerFile = kubeManifestsRepo + '/' + jobBaseName + '/' + 'Dockerfile.test.golang'if (!fileExists(dockerFile)) {dockerFile = kubeManifestsRepo + '/' + jobK8sName + '/' + 'Dockerfile.test.golang'}dockerRepository = dockerRegistry + '/' + dockerRegistryNameSpace + '/' + jobK8sName + '-' + 'golang'customImage = docker.build(dockerRepository, "-f ${dockerFile} .")customImage.push(commitInfo.gitCommit)customImage.push('latest')dockerImages."golang" = dockerRepository + ':' + commitInfo.gitCommit}}}}stage('部署') {steps {script {env.STAGE = "bushu"dockerImages.each { k, v -> newSh("kubectl -n ${PENV} set image deployment/${jobK8sName} ${k}=${v}")newSh("kubectl -n ${PENV} rollout status deployment/${jobK8sName} --timeout=2m")}String content = "\n\n### Jenkins Pipeline\n>**构建信息**:\n>- 构建项目: ${jobBaseName}\n>- 构建id: ${currentBuild.number}\n>- 构建人: ${buildInfo.buildUser}\n>- 构建分支: ${GIT_BRANCH}\n>- 发布环境: ${PENV}\n>**版本信息**:\n>- commit_hash: ${commitInfo.gitCommit}\n>- commit_date: ${commitInfo.commitDate}\n>- commit_message: ${commitInfo.cmmitMessage}\n>- committer: ${commitInfo.committer.name}" def workflowMessage = ["msgtype": "actionCard","actionCard":["title":"构建信息","text":content,"btnOrientation": "0","btns": [["title": "详细信息","actionURL": "https://k8sjenkins.haojiequ.com/blue/organizations/jenkins/k8s_dtk_go_app_api/detail/k8s_dtk_go_app_api/${currentBuild.number}/pipeline"],["title": "日志监控","actionURL": "http://k8skibana.haou.com/app/kibana#/discover?_g=()&_a=(columns:!(_source),index:'18d51920-96c3-11eb-811f-1383c86a1d0',interval:auto,query:(language:kuery,query:''),sort:!(!('@timestamp',desc)))"],]]] String workflowMessageJSON = JsonOutput.toJson(workflowMessage)timeout(unit: 'SECONDS', time: 30) {newSh("curl 'https://oapi.dingtalk.com/robot/send?access_token=9e91f6860736ff69e7f6f986179e154e497b70e26fd749c' -s -H 'Content-Type: application/json' -d '${workflowMessageJSON}'")}}}}stage("commit入库"){steps {script{getDatabaseConnection(type: 'GLOBAL') {def sqlString3="update jenkins_commit.jenkins_jilu set commit_seccec=? where xm_name=? and env=?;"def params3=[commitInfo.gitCommit,commitInfo.xiangmu_name,PENV]sql sql:sqlString3,parameters:params3}}}}}post {failure {script{if (STAGE == "goujian") {println("----> goujian失败")}if (STAGE == "bushu") {println("----> bushu失败") }if (STAGE == "DOCKERFIEL") {println("----> DOCKERFIEL失败")}}}}
}
- 配置nginx
upstream dtk-vue-tiktok-admin {server dtk-go-tiktok-admin weight=1 max_fails=0 fail_timeout=0s;keepalive 20;
}server {
listen 80;
listen 443 ssl;
server_name test.com;
access_log /var/log/nginx/dtest.com.access.log json;
error_log /var/log/nginx/dtest.com.error.log;
ssl_certificate conf.d/dtkcert/test.com.pem;
ssl_certificate_key conf.d/dtkcert/test.com.key;
more_set_headers 'Access-Control-Allow-Headers: Cookie,DNT,X-CSRF-Token,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Auth-token';
more_set_headers 'Access-Control-Allow-Origin: *';
more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT';
more_set_headers 'Access-Control-Allow-Credentials: true';
default_type 'text/html';
set $backend 'dtk-vue-tiktok-admin';include public/deny.conf;
location / {proxy_pass http://$backend;
}location ~ /\.ht {deny all;
}
}
- jenkins机器上的dockerfile
[root@k8s-jenkins dtk-go-tiktok-admin]# cat Dockerfile.test.golang
FROM test.com/dataoke-test/alpine:3.12-CST as test
WORKDIR /opt/app
COPY $CI_PROJECT_DIR/server/main /opt/app/main
CMD ["/opt/app/main", "-c", "/opt/app/conf/config.yaml"][root@k8s-jenkins dtk-go-tiktok-admin]# cat Dockerfile.test.nginx
FROM test.com/dataoke-test/openresty:base
WORKDIR /opt/app/dist/
COPY --chown=nobody:nobody web/dist /opt/app/dist
线上环境配置
- yaml其它都一样除了svc,因为svc需要绑定slb地址
apiVersion: v1
kind: Service
metadata:name: dtk-go-tiktok-adminannotations:#开启slb使用service.beta.kubernetes.io/alibaba-cloud-loadbalancer-force-override-listeners: "true"#slb地址service.beta.kubernetes.io/alibaba-cloud-loadbalancer-id: lb-2ze1hpcomc# service.beta.kubernetes.io/alibaba-cloud-loadbalancer-protocol-port: "http:9090"service.beta.kubernetes.io/alibaba-cloud-loadbalancer-scheduler: "wrr"namespace: default
spec:type: LoadBalancerexternalTrafficPolicy: Localports:- port: 16107 #slb端口targetPort: 80 #pod服务端口protocol: TCPselector:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/runtime: golangapp.kubernetes.io/tier: backendapp.kubernetes.io/environment: prodapp.kubernetes.io/managed-by: yong.xd
- 启动
cat .gitlab-ci.ymlstages:- build- package- docker- deploy- notifybuild:stage: buildimage: test.com/dataoke-prod/golang:1.19-with-repo-certcache:key:files:- go.modpaths:- .cache/pkgartifacts:expire_in: 20 minsuntracked: falsepaths:- $CI_PROJECT_DIR/server/mainscript:- mkdir -p .cache- cd ./server - export GOPATH="$CI_PROJECT_DIR/.cache"- go env -w GO111MODULE=on - go env -w GOPROXY=https://goproxy.cn,direct - go env -w GOPRIVATE=gitlab.buydance.com - go env -w CGO_ENABLED=0- go build -o mainonly:- tagspackage:stage: packageimage: test.com/dataoke-prod/node:14.19.3-alpine3.15script:- cd ./web- npm config set puppeteer_download_host=https://npm.taobao.org/mirrors- npm i --registry=https://registry.npm.taobao.org- npm run buildcache:key:files:- package.jsonpaths:- node_modulesartifacts:name: "dist"untracked: falseexpire_in: 5 minspaths:- $CI_PROJECT_DIR/web/distonly:- tagsdocker:stage: dockerimage: test.com/dataoke-prod/kaniko-executor:debugscript:- mkdir -p /kaniko/.docker- echo "${DOCKER_AUTH_CONFIG}" > /kaniko/.docker/config.json- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile.prod.nginx --destination test.aliyuncs.com/dataoke-prod/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'`-nginx:${CI_COMMIT_SHORT_SHA} --destination test.aliyuncs.com/dataoke-prod/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'`-nginx:latest- /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile.prod.golang --destination test.aliyuncs.com/dataoke-prod/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'`-golang:${CI_COMMIT_SHORT_SHA} --destination test.aliyuncs.com/dataoke-prod/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'`-golang:latestonly:- tagsdeploy:stage: deployimage: test.com/dataoke-prod/kubectl:1.18.1variables:GIT_STRATEGY: noneK8S_NAME_SPACE: defaultscript:- mkdir -p $HOME/.kube- echo "$KUBERNETES_SECRET" >> "$HOME/.kube/config"- kubectl version- kubectl get deployments.apps -n ${K8S_NAME_SPACE}- kubectl -n ${K8S_NAME_SPACE} set image deployment/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'` nginx=test.aliyuncs.com/dataoke-prod/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'`-nginx:${CI_COMMIT_SHORT_SHA} golang=test.aliyuncs.com/dataoke-prod/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'`-golang:${CI_COMMIT_SHORT_SHA} --record- kubectl rollout status deployment/`echo ${CI_PROJECT_NAME} |sed 's@_@-@g'`only:- tagsnotifyFailWeChat:stage: notifyimage: test.aliyuncs.com/dataoke-prod/curl-image:v1script:- curl 'https://oapi.dingtalk.com/robot/send?access_token=6147ec1eb7d8b9bd5cd1b15f1c' -H 'Content-Type:application/json' -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$CI_PROJECT_NAME项目构建失败\n>本次构建由:$GITLAB_USER_NAME 触发\n>项目名称:$CI_PROJECT_NAME\n>提交号:$CI_COMMIT_SHA\n>提交日志:$CI_COMMIT_MESSAGE\n>构建分支:$CI_COMMIT_BRANCH\n>流水线地址:[$CI_PIPELINE_URL]($CI_PIPELINE_URL)\"}}"only:- tagswhen: on_failure# 构建成功时的通知消息
notifySuccessWeChat:stage: notifyimage: test.aliyuncs.com/dataoke-prod/curl-image:v1script:- curl 'https://oapi.dingtalk.com/robot/send?access_token=d6147ec1eb7d8b9bd5cd1b15f1c' -H 'Content-Type:application/json' -d "{\"msgtype\":\"text\",\"text\":{\"content\":\"$CI_PROJECT_NAME项目构建成功\n>本次构建由:$GITLAB_USER_NAME 触发\n>项目名称:$CI_PROJECT_NAME\n>提交号:$CI_COMMIT_SHA\n>提交日志:$CI_COMMIT_MESSAGE\n>构建分支:$CI_COMMIT_BRANCH\n>流水线地址:[$CI_PIPELINE_URL]($CI_PIPELINE_URL)\"}}"only:- tagswhen: on_success
- 配置dockerfile
cat Dockerfile.prod.golangFROM test.aliyuncs.com/dataoke-prod/alpine:3.12-CST as prod
WORKDIR /opt/app
COPY $CI_PROJECT_DIR/server/main /opt/app/main
CMD ["/opt/app/main", "-c", "/opt/app/conf/config.yaml"]cat Dockerfile.prod.nginxFROM test.aliyuncs.com/dataoke-prod/openresty:base
WORKDIR /opt/app/dist/
COPY --chown=nobody:nobody web/dist /opt/app/dist
- 配置nginx
upstream dtk-go-tiktok-admin {
#svc内网ip
server 192.168.10.123:16107 weight=1 max_fails=0 fail_timeout=0s;
keepalive 20;
}server {
listen 80;
listen 443 ssl;
server_name test.com;
access_log /var/log/nginx/dtest.com.access.log json;
error_log /var/log/nginx/dtest.com.error.log;
ssl_certificate conf.d/dtkcert/test.com.pem;
ssl_certificate_key conf.d/dtkcert/test.com.key;more_set_headers 'Access-Control-Allow-Headers: Cookie,DNT,X-CSRF-Token,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization,Auth-token';
more_set_headers 'Access-Control-Allow-Origin: *';
more_set_headers 'Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT';
more_set_headers 'Access-Control-Allow-Credentials: true';
default_type 'text/html';
set $backend 'dtk-vue-tiktok-admin';include public/deny.conf;
location / {
proxy_pass http://$backend;
}location ~ /\.ht {
deny all;
}
}
- 结果图
原文
相关文章:

k8s部署gin-vue-admin框架、gitlab-ci、jenkins pipeline 、CICD
测试环境使用的jenkins 正式环境使用的gitlab-ci 测试环境 创建yaml文件 apiVersion: v1 kind: ConfigMap metadata:name: dtk-go-tiktok-admin-configlabels:app.kubernetes.io/name: dtk-go-tiktok-adminapp.kubernetes.io/business: infrastructureapp.kubernetes.io/run…...

【SpringBoot项目】SpringBoot+MyBatis+MySQL电脑商城
在b站听了袁老师的开发课,做了一点笔记。 01-项目环境搭建_哔哩哔哩_bilibili 基于springboot框架的电脑商城项目(一)_springboot商城项目_失重外太空.的博客-CSDN博客 项目环境搭建 1.项目分析 1.项目功能:登录、注册、热销…...

互联网医院|互联网医院系统引领医疗科技新风潮
互联网的迅速发展已经改变了人们的生活方式,而医疗领域也不例外。近年来,互联网医院应运而生,为患者和医生提供了更便捷、高效的医疗服务。本文将深入探讨互联网医院的系统特点、功能以及未来的发展方向,为您展现医疗行业的新时代…...
Mock安装及应用
1、安装 npm install mockjs 2、Mock.Random属性 该属性是一个工具类,用于生成各种随机数据。它提供的方法如下: Basic: boolean,natural,integer,float,character,string,range,date,time,datetime,now; Image: image,dataImage; Color: color; Text: p…...
一起来看看UI设计流程详解吧!通俗易懂
UI设计2023 通俗易懂的UI设计流程详解 首先,大家要明确一下范围:一般分为新产品的从0-1和已有产品上新的模块或功能的从0-1,这两个方向的环节和产出物会有比较大的区别。其实在UI设计师介入之前,我们是需要去了解一些大的方向和…...

TikTok营销成功秘籍:ROI指标的黄金法则
在当今数字营销领域,TikTok已经崭露头角,成为了品牌和营销者们争相追逐的热门平台。 然而,要在TikTok上取得成功,不仅需要创意和内容,还需要精确的ROI(投资回报率)指标来衡量和优化你的营销策略…...

17.适配器模式(Adapter)
意图:将一个类的接口转换为Client希望的另一个接口,使得原本由于接口不兼容而不能一起工作的那些类在一起工作。 UML图 Target:定义Client使用的与特定领域相关的接口。 Client:与符合Target接口的对象协同工作。 Adaptee…...
leetcode做题笔记154. 寻找旋转排序数组中的最小值 II
已知一个长度为 n 的数组,预先按照升序排列,经由 1 到 n 次 旋转 后,得到输入数组。例如,原数组 nums [0,1,4,4,5,6,7] 在变化后可能得到: 若旋转 4 次,则可以得到 [4,5,6,7,0,1,4]若旋转 7 次࿰…...

什么是推挽电路?
推挽电路原理: 可以简单理解为推和拉; 此电路总共用到两个元器件,对应图中的Q1----NPN三极管,Q2----PNP三极管,两个电阻R1和R2起到限流的作用;两个三极管的中间对应信号的输出。 下面就举例说明是如何工作的…...
208.Flink(三):窗口的使用,处理函数的使用
目录 一、窗口 1.窗口的概念 2.窗口的分类 (1)按照驱动类型分 (2)按照窗口分配数据的规则分类 3.窗口api概览 (1)按键分区(Keyed)和非按键分区(Non-Keyed) *1)按键分区窗口(Keyed Windows) *2)非按键分区(Non-Keyed Windows) (2)代码中窗口API的调…...

时序预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络时间序列预测
时序预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络时间序列预测 目录 时序预测 | MATLAB实现POA-CNN-BiLSTM鹈鹕算法优化卷积双向长短期记忆神经网络时间序列预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 MATLAB实现POA-CNN-BiLSTM鹈鹕算…...
【知识点】增量学习、在线学习、离线学习的区别
参考链接:https://www.6aiq.com/article/1613258706447?p1&m0 离线学习 常见的学习方式,一次性将所有数据参与进训练。 离线学习完成了目标函数的优化将不会在改变了离线学习需要一次提供整个训练集时间和空间成本效率低发生数据变更或模型漂移需…...
c++ 学习 之 运算符重载 之 前置++和后置++
前言 int a1;cout << (a) << endl;cout << a << endl;int b1;cout << (b) << endl; // 这个是错误的cout << b << endl;上面样例中, 前置 返回的是引用,所以a 的值变成了3 后置 返回的不是可以改变的…...

K8s Kubelet 垃圾回收机制
前言 Kubelet 垃圾回收(Garbage Collection)是一个非常有用的功能,它负责自动清理节点上的无用镜像和容器。Kubelet 每隔 1 分钟进行一次容器清理,每隔 5 分钟进行一次镜像清理(截止到 v1.15 版本,垃圾回收间隔时间还都是在源码中固化的,不可自定义配置)。如果节点上已…...

docker安装高斯数据库openGauss数据库
1.创建容器 #创建数据没有挂在的容器 docker run --name opengauss --privilegedtrue -d -e GS_PASSWORDEnmo123 -p 8090:5432 enmotech/opengauss:latest 2. 进入容器,并切换omm用户,使用gsql连接高斯数据库 [rootansible ~]# docker ps -a CONTAIN…...

新手学习:ArcGIS 提取SHP 路网数据、节点
新手学习:ArcGIS 提取SHP 路网数据、节点 参考连接 OSM路网提取道路节点 ArcGIS:如何创建地理数据库、创建要素类数据集、导入要素类、表? 1. 导入开源路网SHP文件 2. 在交点处打断路网数据 未打断路网数据 有一些路径很长,…...

性能测试 —— Tomcat监控与调优:Jconsole监控
JConsole的图形用户界面是一个符合Java管理扩展(JMX)规范的监测工具,JConsole使用Java虚拟机(Java VM),提供在Java平台上运行的应用程序的性能和资源消耗的信息。在Java平台,标准版(Java SE平台)6,JConsole的已经更新到目前的外观…...
刷题笔记26——图论二分图判定
世界上的事情,最忌讳的就是个十全十美,你看那天上的月亮,一旦圆满了,马上就要亏厌;树上的果子,一旦熟透了,马上就要坠落。凡事总要稍留欠缺,才能持恒。 ——莫言 visited数组是在如果有环的情况下,防止在图中一直绕圈设置的,类似于剪枝操作,走…...

网站整站优化-网站整站优化工具
您是否曾为您的网站在搜索引擎中的排名而感到焦虑?是否苦苦思考如何提高流量、吸引更多用户? 什么是整站优化。简而言之,它是一项用于提升网站在搜索引擎中排名的策略和技巧。通过对网站的内容、结构、速度等方面进行优化,可以使…...

冲刺十五届蓝桥杯P0001阶乘求和
文章目录 题目描述思路分析代码解析 题目描述 思路分析 阶乘是蓝桥杯中常考的知识。 首先我们需要知道 int 和long的最大值是多少。 我们可以知道19的阶乘就已经超过了long的最大值,所以让我们直接计算202320232023!的阶乘是不现实的。 所以我们需要…...
在四层代理中还原真实客户端ngx_stream_realip_module
一、模块原理与价值 PROXY Protocol 回溯 第三方负载均衡(如 HAProxy、AWS NLB、阿里 SLB)发起上游连接时,将真实客户端 IP/Port 写入 PROXY Protocol v1/v2 头。Stream 层接收到头部后,ngx_stream_realip_module 从中提取原始信息…...

苍穹外卖--缓存菜品
1.问题说明 用户端小程序展示的菜品数据都是通过查询数据库获得,如果用户端访问量比较大,数据库访问压力随之增大 2.实现思路 通过Redis来缓存菜品数据,减少数据库查询操作。 缓存逻辑分析: ①每个分类下的菜品保持一份缓存数据…...
Spring Boot+Neo4j知识图谱实战:3步搭建智能关系网络!
一、引言 在数据驱动的背景下,知识图谱凭借其高效的信息组织能力,正逐步成为各行业应用的关键技术。本文聚焦 Spring Boot与Neo4j图数据库的技术结合,探讨知识图谱开发的实现细节,帮助读者掌握该技术栈在实际项目中的落地方法。 …...
全面解析各类VPN技术:GRE、IPsec、L2TP、SSL与MPLS VPN对比
目录 引言 VPN技术概述 GRE VPN 3.1 GRE封装结构 3.2 GRE的应用场景 GRE over IPsec 4.1 GRE over IPsec封装结构 4.2 为什么使用GRE over IPsec? IPsec VPN 5.1 IPsec传输模式(Transport Mode) 5.2 IPsec隧道模式(Tunne…...

Spring数据访问模块设计
前面我们已经完成了IoC和web模块的设计,聪明的码友立马就知道了,该到数据访问模块了,要不就这俩玩个6啊,查库势在必行,至此,它来了。 一、核心设计理念 1、痛点在哪 应用离不开数据(数据库、No…...
Device Mapper 机制
Device Mapper 机制详解 Device Mapper(简称 DM)是 Linux 内核中的一套通用块设备映射框架,为 LVM、加密磁盘、RAID 等提供底层支持。本文将详细介绍 Device Mapper 的原理、实现、内核配置、常用工具、操作测试流程,并配以详细的…...

day36-多路IO复用
一、基本概念 (服务器多客户端模型) 定义:单线程或单进程同时监测若干个文件描述符是否可以执行IO操作的能力 作用:应用程序通常需要处理来自多条事件流中的事件,比如我现在用的电脑,需要同时处理键盘鼠标…...
uniapp 集成腾讯云 IM 富媒体消息(地理位置/文件)
UniApp 集成腾讯云 IM 富媒体消息全攻略(地理位置/文件) 一、功能实现原理 腾讯云 IM 通过 消息扩展机制 支持富媒体类型,核心实现方式: 标准消息类型:直接使用 SDK 内置类型(文件、图片等)自…...
redis和redission的区别
Redis 和 Redisson 是两个密切相关但又本质不同的技术,它们扮演着完全不同的角色: Redis: 内存数据库/数据结构存储 本质: 它是一个开源的、高性能的、基于内存的 键值存储数据库。它也可以将数据持久化到磁盘。 核心功能: 提供丰…...
Docker拉取MySQL后数据库连接失败的解决方案
在使用Docker部署MySQL时,拉取并启动容器后,有时可能会遇到数据库连接失败的问题。这种问题可能由多种原因导致,包括配置错误、网络设置问题、权限问题等。本文将分析可能的原因,并提供解决方案。 一、确认MySQL容器的运行状态 …...