通过 Jenkins 将应用发布到 K8S(Publish the Application to k8s Through Jenkins)

💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。****

推荐:Linux运维老纪的首页,持续学习,不断总结,共同进步,活到老学到老
导航剑指大厂系列:全面总结 运维核心技术:系统基础、数据库、网路技术、系统安全、自动化运维、容器技术、监控工具、脚本编程、云服务等。
常用运维工具系列:常用的运维开发工具, zabbix、nagios、docker、k8s、puppet、ansible等
数据库系列:详细总结了常用数据库 mysql、Redis、MongoDB、oracle 技术点,以及工作中遇到的 mysql 问题等
懒人运维系列:总结好用的命令,解放双手不香吗?能用一个命令完成绝不用两个操作
数据结构与算法系列:总结数据结构和算法,不同类型针对性训练,提升编程思维,剑指大厂
非常期待和您一起在这个小小的网络世界里共同探索、学习和成长。💝💝💝 ✨✨ 欢迎订阅本专栏 ✨✨

通过 Jenkins 将应用发布到 K8S

1.1.2 案例概述

本实验实现:使用 Jenkins 到 GitLab 拉取代码到 Jenkins 本地,在 Jenkins 上编译构
建生成镜像,并将镜像上传到 Harbor 私有仓库上。然后在 Jenkins 上远程执行 yaml 文件,
发布应用到 K8S 群集中,执行 yaml 文件时镜像的拉取是到 Harbor 私有仓库完成的。

1.1.3 案例环境

1.案例环境

实验中虚拟机使用 VMware 来实现,采用 NAT 或桥接网络模式,保证有外网连接即可,
并且虚拟机之间保持互通。实验中包括 GitLab、Jenkins、Harbor 和 K8S 群集,K8S 群集采
用 Kubeadm 方式进行安装,具体配置信息如表 1-1 所示。

|----------------|-------------------|------------|-----------------------|-----------------------------------------|
| 主机名 | IP 地址 | 推荐配置 | 操作系统 | 安装软件 |
| gitlab | 192.168.11.10 | 1 核 3G | CentOS 7.9 x86_64 | gitlab |
| jenkins | 192.168.11.20 | 1 核 2G | CentOS 7.9 x86_64 | Tomcat、Java、Git、 Jenkins |
| harbor | 192.168.11.30 | 1 核 2G | CentOS 7.9 x86_64 | Docker compose、 Harbor |
| K8s-master | 192.168.11.40 | 2核 2G | CentOS 7.9 x86_64 | kube-apiserver、 kube-scheduler等 |
| K8s-node1 | 192.168.11.50 | 1 核 2G | CentOS 7.9 x86_64 | kube-apiserver、 kube-scheduler等 |
| K8s-node2 | 192.168.11.60 | 1 核 2G | CentOS 7.9 x86_64 | kube-proxy 、 kubelet |

2.案例拓扑

本案例拓扑如图 1.1 所示。
图 1.1 实验拓扑

3.案例需求

本实验主要实现以下需求:
(1)K8S 群集部署。
(2)GitLab 部署。
(3)Jenkins 部署。
(4)Harbor 部署
(5)程序发布到 K8S 群集。

4.实现思路

(1)依次部署 K8S 群集、GitLab、Jenkins 和 Harbor 应用。
(2)上传测试程序和生成镜像的 Dockerfile 到 GitLab。
(3)编写 K8S 上发布程序的 yaml 文件及脚本。
(4)Jenkins 发布任务实现程序的自动发布更新。

1.2 案例实施

1.2.1 准备基础环境

1)准备虚拟机

依据案例环境中配置信息为虚拟机设置 IP 地址、网关、DNS 等基础信息,确保可以连
接到互联网,并且虚拟机之间可以互通。

2)配置主机名 以 GitLab 主机为例。

root@localhost \~\]# **hostnamectl set-hostname gitlab** \[root@localhost \~\]# **bash** \[root@gitlab \~\]# 其他主机依次改名为 jenkins、harbor、k8s-master、k8s-node1 和 k8s-node2。 ## **3)安装常用软件** 所有主机都需要执行,下面以 GitLab 主机执行为例。 \[root@gitlab \~\]# **yum -y install vim wget net-tools lrzsz** ## **4) 关闭防火墙** 所有主机都需要执行,下面以 GitLab 主机执行为例。 \[root@gitlab \~\]# **systemctl stop firewalld \&\& systemctl disable firewalld** ## **5) 禁用 SELinux** 所有主机都需要执行,下面以 GitLab 主机执行为例。 \[root@gitlab \~\]# **sed -i '/\^SELINUX=/s/enforcing/disabled/'** **/etc/selinux/config** \[root@gitlab \~\]# **setenforce 0** ## **1.2.2 部署 K8S 群集** ## **1.环境初始化** ## **1)更新系统** 所有 K8S 节点都需要执行,下面以 k8s-master 上执行为例。 \[root@k8s-master \~\]# **yum -y update systemd** ## **2)绑定 hosts** 所有 K8S 节点都需要执行,下面以 k8s-master 上执行为例。 \[root@k8s-master \~\]# **cat \<\< EOF \>\> /etc/hosts** **192.168.11.40 k8s-master** **192.168.11.50 k8s-node1** **192.168.11.60 k8s-node2** **EOF** ## **3)关闭交换分区 swap** 所有 K8S 节点都需要执行,下面以 k8s-master 上执行为例。 \[root@k8s-master \~\]# **swapoff -a** \[root@k8s-master \~\]# **sed -i '/swap/s/\^/#/' /etc/fstab** ### **2.Docker 部署** K8S 的三个节点(k8s-master、k8s-node1、k8s-node2)都需要安装 Docker,下面以 k8s-master 上安装为例。 ### **1)安装依赖包** \[root@k8s-master \~\]# **yum install -y yum-utils** **device-mapper-persistent-data lvm2** ### **2)添加 YUM 软件源** \[root@k8s-master \~\]# **yum-config-manager --add-repo** https://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo #### **3)安装 Docker** \[root@k8s-master \~\]# **yum makecache fast** \[root@k8s-master \~\]# **yum -y install docker-ce** ### **4)配置加速器** \[root@k8s-master \~\]# **mkdir /etc/docker** \[root@k8s-master \~\]# **vim /etc/docker/daemon.json** { "registry-mirrors": \["https://g6yrjrwf.mirror.aliyuncs.com"\], "exec-opts": \["native.cgroupdriver=systemd"

}
其中,exec-opts 用于设置 Docker 的 cgroup 驱动类型,需要将其修改为 systemd。因
为 K8S 默认就是使用的 systemd,将 Docker 和 K8S 的驱动类型统一,否则后续会有报错。
需要注意的是:K8S 内的节点上 Docker 环境都需要统一。

5)启动 Docker

root@k8s-master \~\]# **systemctl start docker \&\& systemctl enable docker** 6) 内核优化 在 Docker 的使用过程中有时会看到下面这个警告信息。 WARNING: bridge-nf-call-iptables is disabled WARNING: bridge-nf-call-ip6tables is disabled 这种警告信息可通过配置内核参数的方式来消除,具体配置如下。 \[root@k8s-master \~\]# **cat \<\< EOF \>\> /etc/sysctl.conf** **net.bridge.bridge-nf-call-ip6tables = 1** **net.bridge.bridge-nf-call-iptables = 1** **EOF** \[root@k8s-master \~\]# **sysctl -p** ## **3.K8S 部署** ## **1)配置 K8S 的 YUM 源** 操作节点:k8s-master, k8s-node1, k8s-node2 \[root@k8s-master \~\]# **cat \<\< EOF \> /etc/yum.repos.d/kubernetes.repo** **\[kubernetes\]** **name=Kubernetes** **baseurl=https://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7** **-x86_64/** **enabled=1** **gpgcheck=1** **repo_gpgcheck=1** **gpgkey=https://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg** **https://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg** **EOF** ## **2)安装 Kubelet、Kubeadm 和 Kubectl** 操作节点:k8s-master, k8s-node1, k8s-node2 \[root@k8s-master \~\]# **yum install -y kubelet kubeadm kubectl** \[root@k8s-master \~\]# **systemctl enable kubelet** 其中 kubelet 刚安装完成后,通过 systemctl start kubelet 方式是无法启动的,需要 加入节点或初始化为 master 后才可以启动成功。 ## **3)生成初始化配置文件** 操作节点:k8s-master \[root@k8s-master \~\]# **kubeadm config print init-defaults \> init-config.yaml** ### **4)修改初始化配置文件** 操作节点:k8s-master \[root@k8s-master \~\]# **vim init-config.yaml** apiVersion: kubeadm.k8s.io/v1beta3 bootstrapTokens: - groups: - system:bootstrappers:kubeadm:default-node-token token: abcdef.0123456789abcdef ttl: 24h0m0s usages: - signing - authentication kind: InitConfiguration localAPIEndpoint: advertiseAddress: **192.168.11.40** bindPort: 6443 nodeRegistration: criSocket: /var/run/dockershim.sock imagePullPolicy: IfNotPresent name: **k8s-master** taints: null --- apiServer: timeoutForControlPlane: 4m0s apiVersion: kubeadm.k8s.io/v1beta3 certificatesDir: /etc/kubernetes/pki clusterName: kubernetes controllerManager: {} dns: {} etcd: local: dataDir: /var/lib/etcd imageRepository: **registry.aliyuncs.com/google_containers** kind: ClusterConfiguration kubernetesVersion: 1.22.0 networking: dnsDomain: cluster.local serviceSubnet: 10.96.0.0/12 **podSubnet: 10.244.0.0/16** scheduler: {} 上述加粗的地方要根据环境进行修改。 ### **5)拉取镜像** 操作节点:k8s-master \[root@k8s-master \~\]# **kubeadm config images list --config init-config.yaml** registry.aliyuncs.com/google_containers/kube-apiserver:v1.22.0 registry.aliyuncs.com/google_containers/kube-controller-manager:v1.22. 0 registry.aliyuncs.com/google_containers/kube-scheduler:v1.22.0 registry.aliyuncs.com/google_containers/kube-proxy:v1.22.0 registry.aliyuncs.com/google_containers/pause:3.5 registry.aliyuncs.com/google_containers/etcd:3.5.0-0 registry.aliyuncs.com/google_containers/coredns:v1.8.4 \[root@k8s-master \~\]# **kubeadm config images pull --config=init-config.yaml** \[config/images\] Pulled registry.aliyuncs.com/google_containers/kube-apiserver:v1.22.0 \[config/images\] Pulled registry.aliyuncs.com/google_containers/kube-controller-manager:v1.22.0 \[config/images\] Pulled registry.aliyuncs.com/google_containers/kube-scheduler:v1.22.0 \[config/images\] Pulled registry.aliyuncs.com/google_containers/kube-proxy:v1.22.0 \[config/images\] Pulled registry.aliyuncs.com/google_containers/pause:3.5 \[config/images\] Pulled registry.aliyuncs.com/google_containers/etcd:3.5.0-0 failed to pull image "registry.aliyuncs.com/google_containers/coredns:v1.8.4": output: Error response from daemon: manifest for registry.aliyuncs.com/google_containers/coredns:v1.8.4 not found: manifest unknown: manifest unknown , error: exit status 1 To see the stack trace of this error execute with --v=5 or higher 如果镜像拉取没有报错,都成功拉取完成,可直接进行后续的初始化操作。如果在执行 拉取命令时,出现了报错信息。 Error response from daemon: manifest for registry.aliyuncs.com/google_containers/coredns:v1.8.4 not found: manifest unknown: manifest unknown 说明无法拉取 coredns 镜像,镜像实际存储的名称是 coredns:1.8.4,没有 v 字符。可 以采用先手动拉取镜像,再使用给镜像打 tag 的方式实现。 \[root@k8s-master \~\]# **docker pull** **registry.aliyuncs.com/google_containers/coredns:1.8.4** 1.8.4: Pulling from google_containers/coredns c6568d217a00: Pull complete bc38a22c706b: Pull complete Digest: sha256:6e5a02c21641597998b4be7cb5eb1e7b02c0d8d23cce4dd09f4682d463798890 Status: Downloaded newer image for registry.aliyuncs.com/google_containers/coredns:1.8.4 registry.aliyuncs.com/google_containers/coredns:1.8.4 \[root@k8s-master \~\]# **docker tag** **registry.aliyuncs.com/google_containers/coredns:1.8.4** **registry.aliyuncs.com/google_containers/coredns:v1.8.4** 最终完整的镜像列表如下所示。 \[root@k8s-master \~\]# **docker image ls** REPOSITORY TAG IMAGE ID CREATED SIZE registry.aliyuncs.com/google_containers/kube-apiserver v1.22.0 838d692cbe28 8 days ago 128MB registry.aliyuncs.com/google_containers/kube-controller-manager v1.22.0 5344f96781f4 8 days ago 122MB registry.aliyuncs.com/google_containers/kube-scheduler v1.22.0 3db3d153007f 8 days ago 52.7MB registry.aliyuncs.com/google_containers/kube-proxy v1.22.0 bbad1636b30d 8 days ago 104MB registry.aliyuncs.com/google_containers/etcd 3.5.0-0 004811815584 8 weeks ago 295MB registry.aliyuncs.com/google_containers/coredns 8d147537fb7d 2 months ago 47.6MB registry.aliyuncs.com/google_containers/coredns v1.8.4 8d147537fb7d 2 months ago 47.6MB registry.aliyuncs.com/google_containers/pause 3.5 ed210e3e4a5b 4 months ago 683kB 其中的 coredns 镜像,需要保证在 k8s-node1 和 k8s-node2 上同样下载好。 ### **6)初始化 k8s-master** 操作节点:k8s-master \[root@k8s-master \~\]# **kubeadm init --config=init-config.yaml** ... 省略部分内容 ... \[mark-control-plane\] Marking the node k8s-master as control-plane by adding the label "node-role.kubernetes.io/master=''" \[mark-control-plane\] Marking the node k8s-master as control-plane by adding the taints \[node-role.kubernetes.io/master:NoSchedule

bootstrap-token\] Using token: abcdef.0123456789abcdef \[bootstrap-token\] Configuring bootstrap tokens, cluster-info ConfigMap, RBAC Roles \[bootstrap-token\] configured RBAC rules to allow Node Bootstrap tokens to post CSRs in order for nodes to get long term certificate credentials \[bootstrap-token\] configured RBAC rules to allow the csrapprover controller automatically approve CSRs from a Node Bootstrap Token \[bootstrap-token\] configured RBAC rules to allow certificate rotation for all node client certificates in the cluster \[bootstrap-token\] Creating the "cluster-info" ConfigMap in the "kube-public" namespace \[kubelet-finalize\] Updating "/etc/kubernetes/kubelet.conf" to point to a rotatable kubelet client certificate and key \[addons\] Applied essential addon: CoreDNS \[addons\] Applied essential addon: kube-proxy Your Kubernetes control-plane has initialized successfully! To start using your cluster, you need to run the following as a regular user: mkdir -p $HOME/.kube sudo cp -i /etc/kubernetes/admin.conf $HOME/.kube/config sudo chown $(id -u):$(id -g) $HOME/.kube/config You should now deploy a pod network to the cluster. Run "kubectl apply -f \[podnetwork\].yaml" with one of the options listed at: https://kubernetes.io/docs/concepts/cluster-administration/addons/ Then you can join any number of worker nodes by running the following on each as root: kubeadm join 192.168.11.40:6443 --token abcdef.0123456789abcdef \\ --discovery-token-ca-cert-hash sha256:3a95cfb88f3951320621094e41eebe4e3b5d283312afe9613a131a6678d8123f ### **7)复制配置文件到用户的 home 目录** 操作节点:k8s-master \[root@k8s-master \~\]# **mkdir -p $HOME/.kube** \[root@k8s-master \~\]# **cp -i /etc/kubernetes/admin.conf $HOME/.kube/config** \[root@k8s-master \~\]# **chown $(id -u):$(id -g) $HOME/.kube/config** ### **8)node 节点加入群集** 操作节点:k8s-node1 和 k8s-node2 \[root@k8s-node01 \~\]# **kubeadm join 192.168.11.40:6443 --token** **abcdef.0123456789abcdef --discovery-token-ca-cert-hash** **sha256:3a95cfb88f3951320621094e41eebe4e3b5d283312afe9613a131a6678d8123f** W0316 17:17:00.739681 1962 join.go:346\] \[preflight\] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set. \[preflight\] Running pre-flight checks \[WARNING IsDockerSystemdCheck\]: detected "cgroupfs" as the Docker cgroup driver. The recommended driver is "systemd". Please follow the guide at https://kubernetes.io/docs/setup/cri/ \[preflight\] Reading configuration from the cluster... \[preflight\] FYI: You can look at this config file with 'kubectl -n kube-system get cm kubeadm-config -oyaml' \[kubelet-start\] Downloading configuration for the kubelet from the "kubelet-config-1.17" ConfigMap in the kube-system namespace \[kubelet-start\] Writing kubelet configuration to file "/var/lib/kubelet/config.yaml" \[kubelet-start\] Writing kubelet environment file with flags to file "/var/lib/kubelet/kubeadm-flags.env" \[kubelet-start\] Starting the kubelet \[kubelet-start\] Waiting for the kubelet to perform the TLS Bootstrap... This node has joined the cluster: \* Certificate signing request was sent to apiserver and a response was received. \* The Kubelet was informed of the new secure connection details. Run 'kubectl get nodes' on the control-plane to see this node join the cluster. 上述命令中的 token 串要改为自己环境中的值。 ### **9)安装网络** \[root@k8s-master \~\]# **kubectl apply -f** **https://docs.projectcalico.org/v3.20/manifests/calico.yaml** 命令执行后,将会在所有节点上创建 calico 相关的 Pod 用于网络通信,在创建 Pod 之 前还需要拉取 calico 镜像。会根据网络快慢,创建 calico 对应的 Pod 时间有长短,如果一 直是创建中的状态,需要耐心等待。 K8S 群集安装完成,查看节点的状态。 \[root@k8s-master \~\]# **kubectl get node** NAME STATUS ROLES AGE VERSION k8s-master Ready control-plane,master 15h v1.22.0 k8s-node1 Ready \ 15h v1.22.0 k8s-node2 Ready \ 15h v1.22.0 至此,通过 Kubeadm 方式安装 K8S 群集已经完成。 ### **1.2.3 部署 GitLab** ### **1)安装 GitLab** \[root@gitlab \~\]# **yum -y install policycoreutils-python** \[root@gitlab \~\]# **rpm -ivh gitlab-ce-12.9.0-ce.0.el7.x86_64.rpm** \[root@gitlab \~\]# **vim /etc/gitlab/gitlab.rb** external_url 'http://192.168.11.10' \[root@gitlab \~\]# **gitlab-ctl reconfigure** 执行 reconfigure 的操作需要较长时间,需耐心等待,等提示执行成功后,进行后续的 GitLab 相关配置。 ### **2)设置 root 密码并登录** 浏览器访问 http://192.168.11.10,为默认 root 用户设置密码,密码的设置要符合复 杂度,两次输入的密码要一致。如图 1.2 所示。 ![](https://i-blog.csdnimg.cn/direct/afaf535ae3b1453ebf3f77cf829d939d.png) 图 1.2GitLab 修改密码 密码设置完成后,就会跳转到登录界面,输入 root 用户和刚设置的密码进行登录,如 图 1.3 所示。 ![](https://i-blog.csdnimg.cn/direct/eaacd90bac9848b3844a0829b24ab805.png) 图 1.3 GitLab 登录界面 ##### **3)创建项目** 进入 GitLab 主界面后,单击 "Create a project" 按钮,创建 mytest 项目。将 "Project name" 配置成 "mytest" ,最后单击 "Create project" 按钮创建该项目,如图 1.4 所示。 ![](https://i-blog.csdnimg.cn/direct/9d5ed1a95e024cdc8012bb370e796b26.png) 图 1.4 创建 mytest 项目 #### **4)安装客户端提交工具** 配置完 GitLab 仓库后,下面安装提交代码到 GitLab 仓库的客户端工具,这里采用 Windows 系统下的 TortoiseGit 软件,软件名称为 TortoiseGit-2.12.0.0-64bit.mis。该软 件在 Windows 上可以直接通过双击安装,然后一直"下一步"即可完成安装。 #### **5)提交测试页到 GitLab** 在 GitLab 上mytest 创 建 成 功 页 , 复 制 项 目 地 址 http://192.168.11.10/root/mytest.git"。如图 ![](https://i-blog.csdnimg.cn/direct/ebadc70457194606904d93089f3eb8c1.png) 1.5 所示。 图 1.5 mytest 项目创建完成 然后在本地 Windows 的 E 盘创建"source_1"目录,在"source_1"目录上右键,选择 "Git Clone",然后单击"OK",这样 mytest 项目就拉取到本地。如图 1.6 所示。 ![](https://i-blog.csdnimg.cn/direct/5dcb76ca9407432ea51e86530b00e7df.png) 图 1.6 克隆 mytest 项目 在 E:\\source_1\\mytest 目录内创建 index.html 文件,其内容如下所示。 \ \ \my test\ \ \ \ **version: 1.1** \ \ \ 文件 index.html 编写完成后,在 mytest 目录内右键单击选择"Git Commit -\>master" , 然后再最上面的"message"中填写备注信息,通常都是对提交内容的注释。下面的 index.html 文件确保已经被选中。如图 1.7 所示。 ![](https://i-blog.csdnimg.cn/direct/2328dd04ff754178b37e2c05e90102e7.png) 图 1.7 Git 提交到本地页面 之后单击"Commit"按钮提交到本地仓库,最后单击"Push"按钮上传到 GitLab 中, 从而完成本次代码的提交。如图 1.8 所示。 ![](https://i-blog.csdnimg.cn/direct/83f5e23c1e77441495a8b1e47f359078.png) 图 1.8 Git 提交到远端仓库 单击 Push 按钮,之后在单击 OK 按钮,完成提交到远端仓库。提交成功后,可以在 GitLab 中查看到 index.html 文件。如图 1.9 所示。 ![](https://i-blog.csdnimg.cn/direct/2f48355bef964f028dd0db935ed60b20.png) 图 1.9 GitLab 内项目页 #### **1.2.4 部署 Jenkins** #### **1)安装 Jenkins** \[root@jenkins \~\]# **tar zxf apache-tomcat-9.0.52.tar.gz -C /usr/local** \[root@jenkins \~\]# **mv /usr/local/apache-tomcat-9.0.52 /usr/local/tomcat** \[root@jenkins \~\]# **tar zxf jdk-8u301-linux-x64.tar.gz** \[root@jenkins \~\]# **mv jdk1.8.0_301 /usr/local/java** \[root@jenkins \~\]# **vim /etc/profile** // 尾部追加如下内容 export JAVA_HOME=/usr/local/java export PATH=$JAVA_HOME/bin:$PATH export CLASSPATH=.:$JAVA_HOME/lib/dt.jar:$JAVA_HOME/lib/tools.jar \[root@jenkins \~\]# **source /etc/profile** 将 jenkins.war 包上传到 Jenkins 主机的/usr/local/tomcat/webapp 目录下。 #### **2)启动 Jenkins** \[root@jenkins \~\]# **cd /usr/local/tomcat/bin/** \[root@jenkins bin\]# **sh startup.sh** Using CATALINA_BASE: /usr/local/tomcat Using CATALINA_HOME: /usr/local/tomcat Using CATALINA_TMPDIR: /usr/local/tomcat/temp Using JRE_HOME: /usr/local/java Using CLASSPATH: /usr/local/tomcat/bin/bootstrap.jar:/usr/local/tomcat/bin/tomcat-juli.jar Tomcat started. #### **3)安装 Docker** Jenkins 主机上也需要安装 Docker,因为此主机上承担着通过 Dockerfile 构建镜像的 任务。其安装方法参考 K8S 群集内 Docker 的安装方法。 #### **4)初始化 Jenkins** 通过浏览器访问 URL 地址 http://192.168.11.20:8080/jenkins,打开 Jenkins 配置向 导,如图 1.10 所示。 ![](https://i-blog.csdnimg.cn/direct/3f5e4df0b81f4228aa5aa33d83c82d01.png) 图 1.10 Jenkins 登录页面 查看 Jenkins 登录密码文件。 \[root@jenkins \~\]# **cat /root/.jenkins/secrets/initialAdminPassword** 476b4f82934b427db5f90b09a3bd7537 输入初始密码,单击 " 继续 " 按钮,进入 Jenkins 自定义安装界面。然后单击 " 安装推荐的 插件 " 按钮,安装一些常用的插件,如图 1.11 所示。推荐安装最新稳定版,整个安装过程所 需的时间较长。 ![](https://i-blog.csdnimg.cn/direct/77e2ff6e89174e63bdaa2d0d25f55805.png) 图 1.11 Jenkins 插件安装选择界面 推荐插件安装完成后,创建 Jenkins 管理员用户,如图 1.12 所示。 ![](https://i-blog.csdnimg.cn/direct/fe149974bdb4489c94739d413ac7a32f.png) 图 1.12 Jenkins 创建 admin 用户界面 保存后,Jenkins 基础配置完成。配置完成后,建议重启下 tomcat 服务,重新加载下 Jenkins,这样部分英文就会变为中文状态。 #### **5)Jenkins 插件安装** 为了完成项目的编译构建,需要安装一些插件。单击 " 系统管理 " -\> " 插件管理 " -\> " 可选插 件 " 选项卡,然后在搜索框内依次搜索安装如下插件: CloudBees Docker Build and Publish Git Parameter Git plugin 勾选对应的插件后,分别单击 " 直接安装 " 按钮,等待插件完成安装。 #### **6)凭据的创建** 在实验中凭据的设置主要用于登录 GitLab 拉取代码和登录到 Harbor 私有仓库上传镜 像。凭据页面的进入可通过:单击右上角 admin 用户后的下拉小三角,选择凭据,然后单击 下面的"全局"后面的下拉小三角,单击"添加凭据",如图 1.13 所示。 ![](https://i-blog.csdnimg.cn/direct/1081f02a177348b0bf471d8e4a9a534e.png) 图 1.13 进入添加凭据 其中填写的对应的用户和密码是管理mytest项目的用户。登录GitLab的凭据创建过程, 如图 1.14 所示。 ![](https://i-blog.csdnimg.cn/direct/65f4a413d3cf45139d4cc3010b472bff.png) 图 1.14 GitLab 凭据 参照上面创建凭据的过程,创建登录 Harbor 私有仓库的凭据,如图 1.15 所示。 ![](https://i-blog.csdnimg.cn/direct/5ceda9eb4e1f406eaa46ab161c22df21.png) 图 1.15 Harbor 仓库凭据 #### **1.2.5 部署 Harbor** #### **1.安装 Harbor** #### **1)安装 Docker** Harbor 主机上也需要安装 Docker,因为 Harbor 是通过 Docker compose 方式安装的, 需要 Docker 环境的支持。其安装方法参考 K8S 群集内 Docker 的安装方法。 #### **2)上传 Docker compose** 将 docker-compose 文件上传到/usr/local/bin 目录下,并赋予可执行权限。命令如下 所示。 \[root@harbor \~\]# **chmod +x /usr/local/bin/docker-compose** #### **3)安装 Harbor** 解压缩 Harbor 的安装包到/usr/local 目录下。 \[root@harbor \~\]# **tar zxf harbor-offline-installer-v2.3.1.tgz -C** **/usr/local/** 修改 Harbor 的配置文件。 \[root@harbor \~\]# **cd /usr/local/harbor** \[root@harbor harbor\]# **/bin/cp harbor.yml.tmpl harbor.yml** \[root@harbor harbor\]# **vim /usr/local/harbor/harbor.yml** hostname: 192.168.11.30 // 省略了部分内容 # https related config #https: //https 相关配置都注释掉,包括 https 、 port 、 certificate 和 private_key # https port for harbor, default is 443 #port: 443 # The path of cert and key files for nginx #certificate: /your/certificate/path #private_key: /your/private/key/path 对 hostname 配置项进行修改,https 相关内容进行注释,其他的配置项保持默认。本 实验没有生成对应的证书,不采用 https 方式。 启动 Harbor 程序。 \[root@harbor \~\]# **cd /usr/local/harbor** \[root@harbor harbor\]# **sh install.sh** // 省略了部分内容 \[Step 5\]: starting Harbor ... Creating network "harbor_harbor" with the default driver Creating harbor-log ... done Creating harbor-portal ... done Creating registryctl ... done Creating redis ... done Creating registry ... done Creating harbor-db ... done Creating harbor-core ... done Creating nginx ... done Creating harbor-jobservice ... done ✔ ----Harbor has been installed and started successfully.---- \[root@harbor harbor\]# **docker-compose ps** Name Command State Ports ---------------------------------------------------------------------- ---------------------------------- harbor-core /harbor/entrypoint.sh Up (healthy) harbor-db /docker-entrypoint.sh 96 13 Up (healthy) harbor-jobservice /harbor/entrypoint.sh Up (healthy) harbor-log /bin/sh -c /usr/local/bin/ ... Up (healthy) 127.0.0.1:1514-\>10514/tcp harbor-portal nginx -g daemon off; Up (healthy) nginx nginx -g daemon off; Up (healthy) 0.0.0.0:80-\>8080/tcp,:::80-\>8080/tcp redis redis-server /etc/redis.conf Up (healthy) registry /home/harbor/entrypoint.sh Up (healthy) registryctl /home/harbor/start.sh Up (healthy) 首 次 安 装 启 动 可 使 用 /usr/local/harbor/install.sh 脚 本 , 后 续 可 使 用 "docker-compose up -d"命令启动 Harbor,使用"docker-compose stop"命令关闭 Harbor。 #### **2.创建私有仓库** #### **1)登录 Harbor** Harbor 启动完成后,浏览器访问 http://192.168.11.30,打开 Harbor Web 页面,如图 1.16 所示。 ![](https://i-blog.csdnimg.cn/direct/fb2a0eb769e344daa883af58ceaf3eaa.png) 图 1.16 Harbor 登录页 如果打开的是英文界面,可通过右上角的语言选择,选择中文简体语言。在 Harbor 的 配置文件内有对用户名和密码的定义,默认用户为 admin,密码为 Harbor12345。登录成功 后,进入到 Harbor 的主界面。 ##### **2)创建用户** 在进一步使用 Harbor 之前,还需要先配置项目所需要的用户。从左侧的用户管理导航 栏进入用户管理界面,如图 1.17 所示。 ![](https://i-blog.csdnimg.cn/direct/05dc8f0ec16c4e70bf86a51e0c6c70e2.png) 图 1.17 Harbor 用户管理导航 在用户管理界面,单击"创建用户",设置一个项目所需的用户,如图 1.18 所示。 ![](https://i-blog.csdnimg.cn/direct/96ada73d0c64471baed78afc6422aeb0.png) 图 1.18 用户管理界面 在创建用户界面,创建一个新用户 jenkins。其中用户名填写 jenkins,其他带"\*"的 选项都需要填写,如图 1.19 所示。 ![](https://i-blog.csdnimg.cn/direct/f60ff910668b49438beb2f47b2e6d017.png) 图 1.19 创建用户界面 用户相关信息都填写完成后,单击"确定"按钮,完成用户创建。 ##### **3)创建项目** ##### 完成了用户创建之后,还需要创建实验中用到的项目。单击左侧导航栏中的项目,进入 到项目页中。然后再单击新建项目,进入到新建项目页中,如图 1.20 所示。 ![](https://i-blog.csdnimg.cn/direct/c8f43a3a28f743a5a776c59812ba8e71.png) 图 1.20 Harbor 项目页 由于是 Jenkins 构建完成镜像再上传到 Harbor 私有仓库,所以对应的私有仓库名称也 命名为 jenkins。新建项目的项目名称为 jenkins,单击确定按钮完成项目的新建。如图 1.21 所示。 ![](https://i-blog.csdnimg.cn/direct/6bcfa465c3914308a8497b848352b244.png) 图 1.21 新建项目页 项目 jenkins 创建完成后,如图 1.22 所示。 ![](https://i-blog.csdnimg.cn/direct/a078cc4a21de480fa9446d02da798028.png) 图 1.22 Harbor 项目页 ##### **4)将用户添加到项目中** 将新建的 jenkins 用户添加到 jenkins 项目的成员中,这样 jenkins 用户才可以实现对 jenkins 项目的管理,如图 1.23 所示。 ![](https://i-blog.csdnimg.cn/direct/84b2010fde5f457f8ad2107b5a0c82a4.png) 图 1.23 jenkins 项目成员页 在"成员"选项卡下,填写成员名称,填写用户"jenkins",角色选择维护人员。这 样就有权限上传及维护镜像了。最后单击确定按钮完成新成员的添加,如图 1.24 所示。 ![](https://i-blog.csdnimg.cn/direct/b9fc13b5b2a344438f7e0eeb146a1880.png) 图 1.24 新建成员页 项目 jenkins 包含两个成员,一个默认的 admin,另一个就是新添加的 jenkins 用户。 如图 1.25 所示。 ![](https://i-blog.csdnimg.cn/direct/87dcec92aa0d4cfc9997372ef499ff0e.png) 图 1.25 项目成员页 ##### **5)修改 Harbor 连接方式** 在需要跟 Harbor 私有镜像仓库连接的服务器上,将其上的 Docker 连接仓库方式修改为 http 模 式 , 因 为 默 认 的 https 方 式 是 无 法 连 接 的 。 定 义 http 连 接 方 式 使 用 insecure-registries 参数,具体的配置信息如下所示。 \[root@jenkins \~\]# **cat /etc/docker/daemon.json** { "registry-mirrors": \["https://g6yrjrwf.mirror.aliyuncs.com"\], "exec-opts": \["native.cgroupdriver=systemd"\], **"insecure-registries": \["192.168.11.30"\]** // 新添加内容 } ###### **1.2.6 发布应用** ###### **1.创建 K8S 的 yaml 文件** ###### **1)Harbor 仓库身份验证** 创建 Pod 的 yaml 文件内包含到 Harbor 私有仓库拉取镜像的步骤,在拉取之前首先要进 行身份验证,只有通过了身份验证,才能开始拉取镜像。本实验就是采用创建 secrets 方式, 创建 secrets 后可以在 yaml 文件内调用。 \[root@k8s-master \~\]# **kubectl create secret docker-registry** **harbor-login-registry --docker-server=192.168.11.30 --docker-username=jenkins** **--docker-password=123456** ###### **此处的密码需改为自己环境中的密码。** ###### **2)创建 yaml 文件** K8S 上的 yaml 文件的作用是:Jenkins 通过远程调用 k8s-master 上的 yaml 文件,生成 对应的 Pod 和 Service。Pod 和 Service 对应的 yaml 文件如下所示。 \[root@k8s-master \~\]# **mkdir /data \&\& cd /data** \[root@k8s-master data\]# **vim nginx-deploy.yaml** apiVersion: apps/v1 kind: Deployment metadata: name: nginx labels: app: nginx spec: replicas: 1 selector: matchLabels: app: nginx template: metadata: labels: app: nginx spec: imagePullSecrets: - name: harbor-login-registry containers: - name: nginx image: 192.168.11.30/jenkins/nginx:latest imagePullPolicy: Always ports: - containerPort: 80 \[root@k8s-master data\]# **vim nginx-svc.yaml** apiVersion: v1 kind: Service metadata: name: svc-nginx labels: app: svc-nginx spec: type: NodePort ports: - port: 80 targetPort: 80 nodePort: 30088 selector: app: nginx 其中,使用 nginx-deploy.yaml 通过 yaml 文件创建 Pod,只定义了一个 Nginx Pod; imagePullSecrets 参数定义了到 Harbor 仓库验证身份的信息。使用 nginx-svc.yaml 通过 yaml 文件创建 Service,定义了外部访问服务的方式是 NodePort,对外端口是 30088。 ###### **3)上传 Dockerfile 及 nginx.repo 到 GitLab** 在 E:\\source_1\\mytest 目录下创建 Dockerfile,其内容如下所示。 FROM centos:7 LABEL maintainer bdqn RUN yum -y install yum-utils COPY nginx.repo /etc/yum.repos.d/ RUN yum -y install nginx COPY index.html /usr/share/nginx/html RUN chmod 644 /usr/share/nginx/html/index.html CMD \["nginx","-g","daemon off;"

在相同目录下创建 nginx.repo 文件,用于在容器内安装 nginx,其内容如下所示。

nginx-stable

name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key

nginx-mainline

name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearc
h/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
以上两个文件都通过 TortoiseGit 提交到 GitLab 的 mytest 项目目录下。

2.编写发布到 K8S 脚本

该脚本的作用是:在 Jenkins 服务器上远程执行启动 Pod 和 Service 服务使用的。该脚
本也在/data 目录下。脚本内容如下所示。

root@k8s-master data\]# **vim deploy.sh** #!/bin/bash cd /data newversion=$1 oldversion=$(cat nginx-deploy.yaml \| grep "image:" \| awk -F ':' '{print $NF}') echo "old version is: "${oldversion} echo "new version is: "${newversion} #replace new version sed -i 's/'"nginx:${oldversion}"'/'"nginx:${newversion}"'/g' nginx-deploy.yaml #deploy kubectl delete -f nginx-deploy.yaml kubectl create -f nginx-deploy.yaml 在脚本中,首先通过脚本参数获取新版本号,然后在 nginx-deploy.yaml 内获取镜像的 版本,最后再使用新版本好替换文件内的旧版本号。之后先删除再启动对应的 Pod。 ###### **3.创建发布任务** 在 Jenkins 控制面板页,单击新建任务,创建本次发布任务,任务名称为 nginx,选择 构建一个自由风格的软件项目,最后单击确定按钮。如图 1.26 所示。 ![](https://i-blog.csdnimg.cn/direct/bf4cafabfb5144608b3389a24f14e18d.png) 图 1.26 创建项目 在"General"面板中,勾选"参数化构建过程",然后在"添加参数"中选择"Git 参数",再填写 Git 相关参数。 其中,名称填写"Tag"。 描述是对整个过程的概述。如图 1.27 所示。 ![](https://i-blog.csdnimg.cn/direct/ae01266e32874512911bb0b522d82e67.png) 图 1.27 Git 参数配置 在源码管理内,选择"Git",之后填写项目在 GitLab 上的源码地址,选择对应的凭据, 如图 1.28 所示。 ![](https://i-blog.csdnimg.cn/direct/0796598591fb4febadb118b598f91747.png) 图 1.28 源码管理 "源码管理"这一步需要 Jenkins 主机安装了 git 软件。如果提示"无法连接仓库:Error performing git command",可在 jenkins 主机上通过"yum -y install git"进行安装。 在"构建"模块内,"增加构建步骤"中选择"Docker Build and Publish"。此步骤 用于从 GitLab 下载源码后,在 Jenkins 内构建镜像并上传到 Harbor 仓库中,如图 1.29 所 示。 ![](https://i-blog.csdnimg.cn/direct/41ee34e89c7548a180ddbf24b7a765f9.png) 图 1.29 构建类型选择 填写构建的具体配置内容,如图 1.30 所示。 ![](https://i-blog.csdnimg.cn/direct/1eec2f3c5ee84359ad1e38056a5c9965.png) 图 1.30 Docker 构建页 其中,各个参数的含义如下所示:  Repository Name 是仓库名称,通常是 Harbor 的项目名+镜像名,这里定义了 "jenkins/nginx",其中 jenkins 是 Harbor 内的项目名,nginx 是镜像名。  Tag 是标签,这里是"General"中定义的 Git 参数。  Docker Host URI 这里是固定写法,定义 Docker 主机的 URI。  Server credentials 是主机认证,这里没有使用到。  Docker registry URL 是 Harbor 仓库的地址,地址中的 jenkins 是 Harbor 中创建 的项目。  Registry credentials 是登录 Harbor 使用的凭据。 在 Jenkins 主机上,要将/var/run/docker.sock 的权限设置为 666。命令如下所示。 \[root@jenkins \~\]# **chmod 666 /var/run/docker.sock** 依然是在"构建"模块内,这次选择"执行 shell",主要用于通过脚本远程执行发布 Pod、Service 等操作。如图 1.31 所示。 ![](https://i-blog.csdnimg.cn/direct/72a393d236164277912440846f2ae171.png) 图 1.31 构建类型选择 在"执行 shell"中,填入要执行的脚本,如图 1.32 所示。 ![](https://i-blog.csdnimg.cn/direct/4aaa572680444844a494f46158734104.png) 图 1.32 执行 shell 命令 命令如下所示。 ssh 192.168.11.40 "cd /data \&\& sh deploy.sh ${Tag}" 从 Jenkins 主机到 k8s-master 主机要配置免秘钥登录,这样上面的命令才能正常执行。 配置免秘钥登录的命令如下所示。 \[root@jenkins \~\]# **ssh-keygen** \[root@jenkins \~\]# **ssh-copy-id 192.168.11.40** 单击保存按钮,完成整个任务的配置。 进入到 GitLab 项目页内,给当前 GitLab 内版本打 Tag。如图 1.33 所示。 ![](https://i-blog.csdnimg.cn/direct/ef52ce8c3edd4a30bba0696fefed692c.png) 图 1.33 引导新 Tag 新 Tag 命名为 1.1,其他选项保持默认,如图 1.34 所示。 ![](https://i-blog.csdnimg.cn/direct/29a148ad37174362b5539f473bca073e.png) 图 1.34 创建新 Tag 单击"Create Tag"按钮,完成新 Tag 的创建。 最后编译构建 nginx 任务,通过选择"Build with Parameters"进行任务的构建。之 后选择 Tag 下的 1.1,单击"开始构建"按钮。如图 1.35 所示。 ![](https://i-blog.csdnimg.cn/direct/44c6e12542ba4cf185e21ce88f908f6f.png) 图 1.35 准备开始构建 构建过程如下所示。 Started by user admin Running as SYSTEM Building in workspace /root/.jenkins/workspace/nginx The recommended git tool is: NONE using credential 59788235-6e26-4fe4-b501-6a6f65b90907 \> git rev-parse --resolve-git-dir /root/.jenkins/workspace/nginx/.git # timeout=10 Fetching changes from the remote Git repository \> git config remote.origin.url http://192.168.11.10/root/mytest.git # timeout=10 Fetching upstream changes from http://192.168.11.10/root/mytest.git \> git --version # timeout=10 \> git --version # 'git version 1.8.3.1' using GIT_ASKPASS to set credentials gitlab \> git fetch --tags --progress http://192.168.11.10/root/mytest.git +refs/heads/\*:refs/remotes/origin/\* # timeout=10 \> git rev-parse origin/1.2\^{commit} # timeout=10 \> git rev-parse 1.2\^{commit} # timeout=10 Checking out Revision 4a3d07789a567ecd0aed82bc98bddd076d3c00a7 (1.2) \> git config core.sparsecheckout # timeout=10 \> git checkout -f 4a3d07789a567ecd0aed82bc98bddd076d3c00a7 # timeout=10 Commit message: "change file version 1.2" \> git rev-list --no-walk 4a3d07789a567ecd0aed82bc98bddd076d3c00a7 # timeout=10 \[nginx\] $ docker build -t 192.168.11.30/jenkins/nginx:1.2 --pull=true /root/.jenkins/workspace/nginx WARNING: Support for the legacy \~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release Sending build context to Docker daemon 68.61kB Step 1/6 : FROM centos:7 7: Pulling from library/centos Digest: sha256:0f4ec88e21daf75124b8a9e5ca03c37a5e937e0e108a255d890492430789b60e Status: Image is up to date for centos:7 ---\> 8652b9f0cb4c Step 2/6 : LABEL maintainer bdqn ---\> Using cache ---\> e654b7e54109 Step 3/6 : RUN yum -y install yum-utils ---\> Using cache ---\> 1ff775120b31 Step 4/6 : COPY nginx.repo /etc/yum.repos.d/ ---\> Using cache ---\> 37fa84992a73 Step 5/6 : RUN yum -y install nginx ---\> Using cache ---\> b398cfc50c45 Step 6/6 : CMD \["nginx","-g","daemon off;"

---> Using cache
---> 13dc7ea9f79a
Successfully built 13dc7ea9f79a
Successfully tagged 192.168.11.30/jenkins/nginx:1.2

nginx\] $ docker tag 13dc7ea9f79a 192.168.11.30/jenkins/nginx:latest WARNING: Support for the legacy \~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release \[nginx\] $ docker inspect 13dc7ea9f79a WARNING: Support for the legacy \~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release \[nginx\] $ docker push 192.168.11.30/jenkins/nginx:1.2 WARNING: Support for the legacy \~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release The push refers to repository \[192.168.11.30/jenkins/nginx

9fa8a918c324: Preparing
30ddc06c9965: Preparing
634e449b866c: Preparing
174f56854903: Preparing
30ddc06c9965: Layer already exists
9fa8a918c324: Layer already exists
634e449b866c: Layer already exists
174f56854903: Layer already exists
1.2: digest:
sha256:e92ac93f6e1737841824cdf5a36ede4a736da9892ba2ee01009bfa3526025cf4 size:
1160

nginx\] $ docker push 192.168.11.30/jenkins/nginx:latest WARNING: Support for the legacy \~/.dockercfg configuration file and file-format is deprecated and will be removed in an upcoming release The push refers to repository \[192.168.11.30/jenkins/nginx

9fa8a918c324: Preparing
30ddc06c9965: Preparing
634e449b866c: Preparing
174f56854903: Preparing
30ddc06c9965: Layer already exists
634e449b866c: Layer already exists
174f56854903: Layer already exists
9fa8a918c324: Layer already exists
latest: digest:
sha256:e92ac93f6e1737841824cdf5a36ede4a736da9892ba2ee01009bfa3526025cf4 size:
1160

nginx\] $ /bin/sh -xe /usr/local/tomcat/temp/jenkins1710235867695216091.sh + ssh 192.168.11.40 'cd /data \&\& sh deploy.sh 1.2' old version is: latest new version is: 1.1 deployment.apps "nginx" deleted deployment.apps/nginx created Finished: SUCCESS 在 k8s-master 节点上启动 Service,过程如下所示。 \[root@k8s-master \~\]# **cd /data \&\& kubectl create -f nginx-svc.yaml** 查看测试页面内容,如图 1.36 所示。 ![](https://i-blog.csdnimg.cn/direct/005b0cf3007842ae940ec9721ef8dcfd.png) 图 1.36 版本 1.1 测试页 如果出现 403 forbidden,可以修改 nginx 容器内配置文件/etc/nginx/nginx.conf, 将 运 行 用 户 修 改 为 root 用 户 , 重 新 reload 后 , 即 可 显 示 正 常 。 或 者 检 查 /usr/share/nginx/html 目录内的 index.html 是否有可读权限,添加上可读权限即可。 ###### **4.对程序进行更新** 修改本地 E:\\source_1\\mytest\\index.html 文件内容,将版本号改为 1.2。如下所示。 \ \ \my test\ \ \ \version: **1.2** \ \ \ 通过 TortoiseGit 工具将修改后的 index.html 文件提交到 GitLab 主机中。 在 GitLab 的 mytest 项目页内,项目名称后面的下拉列表内选择"New tag",创建新 tag,如图 1.37 所示。 ![](https://i-blog.csdnimg.cn/direct/d9dadcc6a92e4918b8ce9a0238a8e823.png) 图 1.37 新建 tag 选择 在弹出的创建新 tag 页面内,"Tag name"填写 1.2,其他不填写,单击"Create Tag" 按钮保存。 之后在 Jenkins 页面内,nginx 任务下,依然选择"Build with Parameters",在右 侧选择新添加的版本 1.2 版本,然后单击"开始构建"等待构建结束。如图 1.38 所示。 ![](https://i-blog.csdnimg.cn/direct/9a23361fd5404ef79757bff7111379da.png) 图 1.38 版本 1.2 构建 再次访问测试页,已经升级成功。如图 1.39 所示。 ![](https://i-blog.csdnimg.cn/direct/32c80ff11e3a4fa185f2df42aee10477.png) 图 1.39 更新程序后的测试页面![](https://i-blog.csdnimg.cn/direct/a2ba606a260f4b84afd298ac82b0be99.gif)

相关推荐
韶君13 分钟前
Jenkins(CI/CD工具)
ci/cd·jenkins
在河之洲木水1 小时前
现代多核调度器的本质 调度三重奏
linux·服务器·系统架构
程序员JerrySUN1 小时前
驱动开发硬核特训 · Day 22(下篇): # 深入理解 Power-domain 框架:概念、功能与完整代码剖析
linux·开发语言·驱动开发·嵌入式硬件
白总Server1 小时前
多智能体系统的中间件架构
linux·运维·服务器·中间件·ribbon·架构·github
未来会更好yes2 小时前
Centos 7.6安装redis-6.2.6
linux·redis·centos
二猛子2 小时前
Linux(Centos版本)中安装Docker
linux·docker·centos
浪裡遊3 小时前
跨域问题(Cross-Origin Problem)
linux·前端·vue.js·后端·https·sprint
Johny_Zhao4 小时前
OpenStack 全套搭建部署指南(基于 Kolla-Ansible)
linux·python·信息安全·云计算·openstack·shell·yum源·系统运维
2401_867021904 小时前
文件缓冲区(IO与文件 ·III)(linux/C)
linux·运维·服务器·c语言
记得开心一点嘛4 小时前
Docker compose 部署微服务项目(从0-1出发纯享版无废话)
docker·容器·eureka