Jenkins+K8s+Docker 自动化部署

verison

1.16.3 (建议指定版本,不同版本对组件兼容性不一)
部署环境: 百度云/阿里云
ps:文件中的IP不可代入;资料文件可以私聊我/或者其他使用问题都可以交流,欢迎评论

部署前必备

修改/ets/hosts文件

将所有节点写入

192.168.0.128 k8s-master
192.168.0.131 k8s-node1
192.168.0.132 k8s-node2
192.168.0.135 k8s-node3
关闭防火墙和关闭****SELinux**
systemctl stop fifirewalld systemctl disable fifirewalld setenforce 0 临时关闭 vi /etc/sysconfig/selinux 永久关闭 改为SELINUX=disabled
设置系统参数

设置允许路由转发,不对bridge的数据进行处理

创建文件

vi /etc/sysctl.d/k8s.conf

内容如下:

net.bridge.bridge-nf-call-ip6tables = 1net.bridge.bridge-nf-call-iptables = 1 net.ipv4.ip_forward = 1vm.swappiness = 0

执行文件

sysctl -p /etc/sysctl.d/k8s.conf
kube-proxy开启ipvs****的前置条件
vi /etc/sysconfig/modules/ipvs.modules modprobe -- ip_vs
modprobe -- ip_vs_rr
modprobe -- ip_vs_wrr
modprobe -- ip_vs_sh
modprobe -- nf_conntrack_ipv4执行 chmod 755 /etc/sysconfig/modules/ipvs.modules && bash /etc/sysconfig/modules/ipvs.modules && lsmod | grep -e ip_vs -e nf_conntrack_ipv4
所有节点关闭****swap
swapoff -a 临时关闭 vi /etc/fstab 永久关闭

注释掉以下字段

/dev/mapper/cl-swap swap swap defaults 0 0
创建 k8s yum 源
vim /etc/yum.repos.d/kubernetes.repo[kubernetes]
name=Kubernetes
baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg

安装docker环境

  $ wget https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo -O/etc/yum.repos.d/docker-ce.repo$ yum -y install docker-ce$ systemctl enable docker && systemctl start docker**$ docker --version

安装k8s

安装:

yum  install -y kubelet-1.16.3 kubeadm-1.16.3 kubectl-1.16.3

kubelet设置开机启动(注意:先不启动,现在启动的话会报错)

systemctl enable kubelet

查看版本

kubelet --version

初始化

– master 节点需要完成初始化

kubeadm init --kubernetes-version=**1.16.3** --apiserver-advertise-address=192.168.255.14 --image-repository registry.aliyuncs.com/google_containers --service-cidr=10.1.0.0/16 --pod-network-cidr=10.244.0.0/16
  • 记住加入主节点的密钥,后面子节点加入集群环境的时候需要执行此命令
kubeadm join 192.168.255.14:6443 --token 6o05b2.9bloexv68xwasjjb \--discovery-token-ca-cert-hash sha256:fd03cb1bdd7293b4bde56709d2c787f345089c229ac3067900dfc5c1323b0f0d

初始化入失败如何处理

在节点上执行 kubeadm reset

常见错误:

错误一:[WARNING IsDockerSystemdCheck]: detected “cgroupfs” as the Docker cgroup driver

作为Docker cgroup驱动程序。,Kubernetes推荐的Docker驱动程序是“systemd”

解决方案:修改Docker的配置: vi /etc/docker/daemon.json,加入

{
“exec-opts”: [“native.cgroupdriver=systemd”]
}

然后重启Docker

配置kubectl 工具

mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config

安装calico网络组件

下载calico的yaml文件

mkdir k8s cd k8s wget https://docs.projectcalico.org/v3.10/getting-started/kubernetes/installation/hosted/kubernetes-datastore/calico-networking/1.7/calico.yaml   --no-check-certificatesed -i 's/192.168.0.0/10.244.0.0/g' calico.yaml

创建calico服务

kubectl apply -f calico.yaml

等待几分钟,查看所有Pod的状态,确保所有Pod都是Running状态

nfs-client的安装(所有节点都需要安装)

安装命令

yum install -y nfs-utils systemctl enable nfs 开机启动

以下操作只需在master节点上进行

创建共享目录

mkdir -p /opt/nfs/jenkins vi /etc/exports 编写NFS的共享配置 /opt/nfs/jenkins *(rw,no_root_squash) *代表对所有IP都开放此目录,rw是读写

3)启动服务

service start  nfs

4)查看NFS共享目录

创建NFS client provisioner

nfs-client-provisioner 是一个Kubernetes的简易NFS的外部provisioner,本身不提供NFS,需要现有

的NFS服务器提供存储。

上传nfs-client-provisioner构建文件

其中注意修改deployment.yaml,使用之前配置NFS服务器和目录

构建nfs-client-provisioner的pod资源

kubectl create -f .

查看pod是否创建成功

安装jenkins-master

上传Jenkins-Master构建文件

其中有两点注意:

第一、在StatefulSet.yaml文件,声明了利用nfs-client-provisioner进行Jenkins-Master文件存储

第二 、Service发布方法采用NodePort,会随机产生节点访问端口

创建kube-ops的namespace

因为我们把Jenkins-Master的pod放到kube-ops下

kubectl create namespace kube-ops

构建Jenkins-Master的pod资源

kubectl create -f .

查看pod是否创建成功

kubectl get pods -n kube-ops

查看信息,并查看Pod运行在那个Node上

kubectl describe pods -n kube-ops

查看分配的端口

kubectl get service -n kube-ops

最终访问的地址为 http://master-ip:31713

安装基本的插件

Localization:Chinese

Git

Pipeline

Extended Choice Parameter

Jenkins与Kubernetes整合

安装Kubernetes插件

系统管理->插件管理->可选插件

实现Jenkins与Kubernetes整合

系统管理->系统配置->云->新建云->Kubernetes

名称不要随便写,后面会用到

kubernetes地址采用了kube的服务器发现:https://kubernetes.default.svc.cluster.local

namespace填kube-ops,然后点击Test Connection,如果出现 Connection test successful 的提

示信息证明 Jenkins 已经可以和 Kubernetes 系统正常通信

Jenkins URL 地址:http://jenkins.kube-ops.svc.cluster.local:8080

构建Jenkins-Slave自定义镜像

Jenkins-Master在构建Job的时候,Kubernetes会创建Jenkins-Slave的Pod来完成Job的构建。我们选择

运行Jenkins-Slave的镜像为官方推荐镜像:jenkins/jnlp-slave:latest,但是这个镜像里面并没有Maven

环境,为了方便使用,我们需要自定义一个新的镜像:

准备材料:

构建出一个新镜像:

jenkins-slave-maven:latest

在目录下 执行 docker build -t jenkins-slave-maven:latest . 进行构建镜像

镜像上传到Harbor

先登录harbor

docker login -u admin -p Harbor123456 192.168.0.133:85 (192.168.0.133:85 harbor的地址)

docker tag jenkins-slave-maven:latest 192.168.0.133:85/library/jenkins-slave-maven:latest
docker push 192.168.0.133:85/library/jenkins-slave-maven:latest

Jenkins+Kubernetes+Docker完成微服务持续集成

拉取代码,构建镜像

1)创建NFS共享目录

让所有Jenkins-Slave构建指向NFS的Maven的共享仓库目录

jenkins创建项目,编写构建Pipeline

创建一个Jenkins流水线项目

构建分支参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-FhhhrxXw-1648864695613)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637736197532.png)]

构建发布服务选项参数

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-YVeA20We-1648864695614)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637736224416.png)]

Number of Visible Items 代表下面的参数面板默认展示几个

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-WKReJFwc-1648864695614)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637736369949.png)]

delimiter 分隔符可随意设定,但要与 pipeline脚本中的分隔符保持一致

 // 第三步stage('构建镜像,部署项目'){//把选择的项目信息转为数组def selectedProjects = "${project_name}".split(',')

编写pipeline脚本


def git_address = ""; //git项目地址
def git_auth = "982116f3-def0-4a6f-8327-e08cbaf2872c"
//构建版本的名称
def tag = "latest"
//Harbor私服地址
def harbor_url = "127.0.0.1:18085"  //自己的harbor仓库地址
//Harbor的项目名称
def harbor_project_name = "pa-sas"
//Harbor的凭证
def harbor_auth = "4c4bd142-864d-4573-890a-031ad2155bcd"
def secret_name = "registry-auth-secret"
//k8s凭证
def k8s_auth = "f5e3a4c1-e9a3-4a54-afb9-8245e7c08cd2"podTemplate(label: 'jenkins-slave', cloud: 'kubernetes', containers: [containerTemplate(name: 'jnlp', image: "127.0.0.1:18085/library/jenkins-slave-maven:latest"),containerTemplate(name: 'docker', image: "docker:stable",ttyEnabled: true,command: 'cat'),],volumes: [hostPathVolume(mountPath: '/var/run/docker.sock', hostPath: '/var/run/docker.sock'),nfsVolume(mountPath: '/usr/local/apache-maven/repo', serverAddress: '127.0.0.1' , serverPath: '/opt/nfs/maven'),  //NFS 服务的IP],
)
{node("jenkins-slave"){// 第一步stage('拉取代码'){checkout([$class: 'GitSCM', branches: [[name: '${branch}']], userRemoteConfigs: [[credentialsId: "${git_auth}", url: "${git_address}"]]])}// 第二步stage('代码编译'){//编译并安装公共工程sh "mvn -f pa-framework-model clean install"sh "mvn -f pa-framework-utils clean install"sh "mvn -f pa-framework-common clean install"}// 第三步stage('构建镜像,部署项目'){//把选择的项目信息转为数组def selectedProjects = "${project_name}".split(',')for(int i=0;i<selectedProjects.size();i++){//取出每个项目的名称和端口def currentProject = selectedProjects[i];//项目名称def currentProjectName = currentProject.split('@')[0]//项目启动端口def currentProjectPort = currentProject.split('@')[1]//定义镜像名称def imageName = "${currentProjectName}:${tag}"//编译,构建本地镜像sh "mvn -f ${currentProjectName} clean package dockerfile:build"container('docker') {//给镜像打标签sh "docker tag ${imageName} ${harbor_url}/${harbor_project_name}/${imageName}"//登录Harbor,并上传镜像withCredentials([usernamePassword(credentialsId: "${harbor_auth}", passwordVariable: 'password', usernameVariable: 'username')]) {//登录sh "docker login -u ${username} -p ${password} ${harbor_url}"//上传镜像sh "docker push ${harbor_url}/${harbor_project_name}/${imageName}"}//删除本地镜像sh "docker rmi -f ${imageName}"sh "docker rmi -f ${harbor_url}/${harbor_project_name}/${imageName}"}def deploy_image_name = "${harbor_url}/${harbor_project_name}/${imageName}"//部署到K8Ssh """sed -i 's#\$IMAGE_NAME#${deploy_image_name}#' ${currentProjectName}/deploy.ymlsed -i 's#\$SECRET_NAME#${secret_name}#' ${currentProjectName}/deploy.yml"""kubernetesDeploy configs: "${currentProjectName}/deploy.yml", kubeconfigId: "${k8s_auth}"} }}
}

Pipeline 说明

git_address : git地址

git_auth :需 在jenkins中配置相应的凭据

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-CWWT7bgH-1648864695614)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637725118468.png)]

harbor_url

harbor仓库地址

harbor_project_name

harbor仓库中的项目名称,如果没有,需要事先在harbor仓库中建立

harbor_auth

同样git_auth,在jenkins中建立相应的凭据

secret_name

k8s 建立harbor凭证,用于在harbor中拉取镜像

k8s 建立harbor凭证

在master节点中登录harbor

docker login -u admin -p Harbor123 127.0.0.1:85

生成令牌

kubectl create secret docker-registry **registry-auth-secret** --docker-server=127.0.0.1:85  --docker-username=admin --docker-password=Harbor123  --
docker-email=test@sec.com

查看令牌

kubectl get secret
构建k8s_auth

与harbor和git生成令牌的方式不一样。

需要jenkins安装kcd插件

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-IPnDjC2E-1648864695615)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637725716389.png)]

安装完成之后,添加凭证

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-0EymWtZb-1648864695615)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637725771324.png)]

获取凭证内容

到k8s的Master节点复制

cat /root/.kube/config

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-cnacwXAt-1648864695616)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637726002806.png)]

复制整个文件内容至Content内容框内即可。

至此,流水线发布所需工作已做完

微服务配置文件

编写deploy.yml,用于 K8S 发布

---
apiVersion: v1
kind: Service
metadata:name: pa-govern-gatewaylabels:app: pa-govern-gateway
spec:type: NodePortports:- port: 18080name: pa-govern-gatewaytargetPort: 18080nodePort: 31003   # 指定pod暴露出的接口   只需要在网关项目指定protocol: TCPselector:app: pa-govern-gateway
---
apiVersion: apps/v1
kind: StatefulSet
metadata:name: pa-govern-gateway
spec:serviceName: "pa-govern-gateway"replicas: 1selector:matchLabels:app: pa-govern-gatewaytemplate:metadata:labels:app: pa-govern-gatewayspec:imagePullSecrets:- name: $SECRET_NAMEcontainers:- name: pa-govern-gatewayimage: $IMAGE_NAMEports:- containerPort: 18080podManagementPolicy: "Parallel"

编写Dockerfile,用于docker生成服务镜像

#FROM java:8
FROM openjdk:8-jdk-alpine
ARG JAR_FILE
COPY ${JAR_FILE} myservice.jar
EXPOSE 18080
ENTRYPOINT ["java","-jar","-Xms2048M","-Xmx2048M","/myservice.jar"]

pom文件增加docker编译插件

  <build><finalName>pa-govern-gateway-18080</finalName><plugins><plugin><groupId>org.springframework.boot</groupId><artifactId>spring-boot-maven-plugin</artifactId><version>${spring-boot.version}</version><executions><execution><goals><goal>repackage</goal></goals></execution></executions></plugin><plugin><groupId>com.spotify</groupId><artifactId>dockerfile-maven-plugin</artifactId><version>1.3.6</version><configuration><repository>${project.artifactId}</repository><buildArgs><JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE></buildArgs></configuration></plugin><plugin><groupId>org.apache.maven.plugins</groupId><artifactId>maven-resources-plugin</artifactId></plugin></plugins></build>

kubectl 常用命令及常见问题

kubectl get nodes 查看所有主从节点的状态

kubectl get ns 获取所有namespace资源

kubectl get pods -n {$nameSpace} 获取指定namespace的pod

kubectl describe pod的名称 -n {$nameSpace} 查看某个pod的执行过程

kubectl logs --tail=1000 pod的名称 | less 查看日志

kubectl create -f xxx.yml 通过配置文件创建一个集群资源对象

kubectl delete -f xxx.yml 通过配置文件删除一个集群资源对象

kubectl delete pod名称 -n {$nameSpace} 通过pod删除集群资源

kubectl get service -n {$nameSpace} 查看pod的service情况

kubectl get svc -n kubernetes-dashboard

如何查看 systemctl 启动的日志

journalctl -f

pod 一直处于pending状态 如果查看问题

kubectl describe pod -n kube-ops jenkins-0 查看日志

安装calico 时的问题 running状态 但是 not ready

  • [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-u0du5Cz9-1648864695617)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637560572704.png)]

  • 解决方案 :在calico的yaml中 增加以下配置

  • name: IP_AUTODETECTION_METHOD

  • value: “interface=eth.*” eth 为本地网卡的前缀名称

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pkzgNsdf-1648864695617)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637560550193.png)]

无法解析域名的问题

修改coredns组件里的configmap

kubectl edit cm -n kube-system coredns

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-jZZnlWxo-1648864695618)(C:\Users\DELL\AppData\Roaming\Typora\typora-user-images\1637639481335.png)]

docker 构建镜像无权限问题

node 打标签,用于部署时选择节点 (master节点上执行)

kubectl label node k8s-node1 type=node1

如何让你的机器加入到K8s环境中

执行部署前必备流程

安装docker环境

安装K8s

yum  install -y kubelet-1.16.3 kubeadm-1.16.3 kubectl-1.16.3
systemctl enable kubelet

执行加入节点的命令

kubeadm join 192.168.255.14:6443 --token 6o05b2.9bloexv68xwasjjb--discovery-token-ca-cert-hash    sha256:fd03cb1bdd7293b4bde56709d2c787f345089c229ac3067900dfc5c1323b0f0d

加入成功后启动kubelet

systemctl start kubelet

回到Master节点查看,如果Status全部为Ready,则说明加入成功

kubectl get nodes

在你的机器上安装nfs-client

yum install -y nfs-utils
systemctl enable nfs 开机启动
systemctl start nfs
showmount -e 192.168.255.14(安装nfs的master机器IP)

查看nfs是否可正常读取到共享地址

在master机器上给你的机器打上标签

kubectl label node k8s-node1 type=node1

如果已有标签,加上 --overwrite 进行覆盖

修改服务的deploy.yml配置文件,发布到指定node

装K8s

yum  install -y kubelet-1.16.3 kubeadm-1.16.3 kubectl-1.16.3
systemctl enable kubelet

执行加入节点的命令

kubeadm join 192.168.255.14:6443 --token 6o05b2.9bloexv68xwasjjb--discovery-token-ca-cert-hash    sha256:fd03cb1bdd7293b4bde56709d2c787f345089c229ac3067900dfc5c1323b0f0d

加入成功后启动kubelet

systemctl start kubelet

回到Master节点查看,如果Status全部为Ready,则说明加入成功

kubectl get nodes

在你的机器上安装nfs-client

yum install -y nfs-utils
systemctl enable nfs 开机启动
systemctl start nfs
showmount -e 192.168.255.14(安装nfs的master机器IP)

查看nfs是否可正常读取到共享地址

在master机器上给你的机器打上标签

kubectl label node k8s-node1 type=node1

如果已有标签,加上 --overwrite 进行覆盖

修改服务的deploy.yml配置文件,发布到指定node

如何使用K8S实现自动化部署相关推荐

  1. K8S搭建自动化部署环境(三)Jenkins下载、安装和启动

    各位大佬,前文如下: K8S搭建自动化部署环境(一)安装Kubernetes K8S搭建自动化部署环境(二)安装K8S管理工具Kuboard V3 一.jenkins 下载 jenkins下载地址:h ...

  2. K8S搭建自动化部署环境(四)Jenkins多分支流水线Blue Ocean的安装和使用

    各位大佬,前文如下: K8S搭建自动化部署环境(一)安装Kubernetes K8S搭建自动化部署环境(二)安装K8S管理工具Kuboard V3 K8S搭建自动化部署环境(三)Jenkins下载.安 ...

  3. k8s+jenkins自动化部署

    一:环境准备 1. 四台服务器:根据具体需求分配 A :master (192.168.0.115) 2核4g 用于k8s的主节点 B: node1 (192.168.0.126) 2核8g C: n ...

  4. K8S实战集训第一课 Ansible自动化部署k8s、弹性伸缩、Helm包管理、k8s网络模型介绍

    Ansible自动化部署K8S集群 一.Ansible自动化部署K8S集群 1.1 Ansible介绍 Ansible是一种IT自动化工具.它可以配置系统,部署软件以及协调更高级的IT任务,例如持续部 ...

  5. Jenkins+Docker+K8S+Git+CICD自动化部署

    1.构建流程图 自动触发jenkins部署通过svn或Git的hooks来实现,是否自动触发根据项目内部沟通决定,我们目前没有自动触发,原因是QA在测试的过程中不希望被自动触发的部署打断,不过也可以方 ...

  6. kubernetes+Azure DevOps实现.Net Core项目的自动化部署均衡负载

    1. 前言 前前后后学习kubernetes也有一个来月了,关于kubernetes的博客也写了有十多篇.但是技术如果无法落地到实际的应用场景终归是纸上谈兵,所以就有了这一出:通过结合kubernet ...

  7. asp.net core结合Gitlab-CI实现自动化部署

    一.前言 在之前的文章中写过k8s+Jenkins+GitLab-自动化部署asp.net core项目 的topic,这次讲解一下gitlab-ci的CI/CD,说实话,自动化部署是在是非常的舒服, ...

  8. 架构设计:服务自动化部署和管理流程

    本文源码:GitHub·点这里 || GitEE·点这里 一.分布式服务 从常规分布式架构系统来说,划分出十来个独立的微服务模块是很常见的,然后不同的开发人员分工几个服务块,负责日常开发和维护,微服务 ...

  9. 【k8s系列001】K8s集群部署H2O

    一.k3s集群部署 https://docs.rancher.cn/docs/k3s/_index k3s官网 1.安装master curl -sfL http://rancher-mirror.c ...

  10. 小米Redis的K8s容器化部署实践

    本文讲述了小米是如何将Redis Cluster部署在K8S上提供高质量的服务的 往期文章回顾:HBase Region Read Replicas功能详解 背景 Why K8S How K8s Wh ...

最新文章

  1. 你熟悉Git常用的命令吗?(点赞+收藏)
  2. (初学必看)deep graph library(dgl)库的入门引导
  3. golang设置默认地区
  4. python正则group()的用法—正则提取括号内以及其他符号内内容
  5. JDBC预状态通道设置时间格式的问题
  6. unity镜头边缘羽化_【后期修图】如何利用Ps中的自适应广角滤波器校正镜头失真?...
  7. Flash开发的基本概念
  8. 交互系统的构建之(三)TTS语音合成的加盟
  9. vue中使用百度地图,悬浮窗搜索功能
  10. 三星GalaxyS21或取消附赠有线耳机:捆绑卖新款无线耳机
  11. mysql 显示各列的数据类型命令_mysql中查看库中某个表的所有列和对应的字段类型...
  12. 配置VIM语法高亮及自动缩进
  13. 请详细描述listview与gridview的异同点_专利和著作权有什么异同点,听听专业人士怎么说...
  14. win8修复计算机u盘,Win8系统U盘里的文件不见了怎么办?
  15. 实验一 结构化分析(软件工程)
  16. 命令行解压cab文件
  17. 众泰Z700导航升级高德地图
  18. 网络扫描及安全评估实验实验报告
  19. HTTP请求的TCP瓶颈分析
  20. 华为软件类校招 2014年9月3日 熟悉机考环境 1.记票统计 2.求最大递增数 3.Word Maze(单词迷宫)

热门文章

  1. 2020电子设计竞赛G题 - 非接触物体尺寸形态测量
  2. linux两台电脑共享文件夹怎么设置,快速几步完美实现两台电脑共享上网的设置...
  3. 矩阵键盘控制拉闭幕式流水灯
  4. Tyvj P1288 飘飘乎居士取能量块
  5. VS2019CPU/内存诊断功能
  6. java游戏猿人时代_猿人时代游戏下载-猿人时代游戏(附攻略)正版下载v1.0.0-第五驱动...
  7. 技术人如何才能做好绩效管理提升团队绩效?
  8. 配置访问路径自定义的swagger接口说明文档api
  9. charles——教程——转载
  10. AI上推荐 之 NeuralCF与PNN模型(改变特征交叉方式)