💝💝💝欢迎来到我的博客,很高兴能够在这里和您见面!希望您在这里可以感受到一份轻松愉快的氛围,不仅可以获得有趣的内容和知识,也可以畅所欲言、分享您的想法和见解。****
推荐: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
\ **version: 1.1** \
\
\
文件 index.html 编写完成后,在 mytest 目录内右键单击选择"Git Commit -\>master"
,
然后再最上面的"message"中填写备注信息,通常都是对提交内容的注释。下面的
index.html 文件确保已经被选中。如图 1.7 所示。 
图 1.7 Git 提交到本地页面
之后单击"Commit"按钮提交到本地仓库,最后单击"Push"按钮上传到 GitLab 中,
从而完成本次代码的提交。如图 1.8 所示。

图 1.8 Git 提交到远端仓库
单击 Push 按钮,之后在单击 OK 按钮,完成提交到远端仓库。提交成功后,可以在 GitLab
中查看到 index.html 文件。如图 1.9 所示。

图 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 所示。 
图 1.10 Jenkins 登录页面
查看 Jenkins 登录密码文件。
\[root@jenkins \~\]# **cat /root/.jenkins/secrets/initialAdminPassword**
476b4f82934b427db5f90b09a3bd7537
输入初始密码,单击 " 继续 " 按钮,进入 Jenkins 自定义安装界面。然后单击 " 安装推荐的
插件 " 按钮,安装一些常用的插件,如图 1.11 所示。推荐安装最新稳定版,整个安装过程所
需的时间较长。

图 1.11 Jenkins 插件安装选择界面
推荐插件安装完成后,创建 Jenkins 管理员用户,如图 1.12 所示。

图 1.12 Jenkins 创建 admin 用户界面
保存后,Jenkins 基础配置完成。配置完成后,建议重启下 tomcat 服务,重新加载下
Jenkins,这样部分英文就会变为中文状态。
#### **5)Jenkins 插件安装**
为了完成项目的编译构建,需要安装一些插件。单击 " 系统管理 " -\> " 插件管理 " -\> " 可选插
件 " 选项卡,然后在搜索框内依次搜索安装如下插件:
CloudBees Docker Build and Publish
Git Parameter
Git plugin
勾选对应的插件后,分别单击 " 直接安装 " 按钮,等待插件完成安装。
#### **6)凭据的创建**
在实验中凭据的设置主要用于登录 GitLab 拉取代码和登录到 Harbor 私有仓库上传镜
像。凭据页面的进入可通过:单击右上角 admin 用户后的下拉小三角,选择凭据,然后单击
下面的"全局"后面的下拉小三角,单击"添加凭据",如图 1.13 所示。

图 1.13 进入添加凭据
其中填写的对应的用户和密码是管理mytest项目的用户。登录GitLab的凭据创建过程,
如图 1.14 所示。

图 1.14 GitLab 凭据
参照上面创建凭据的过程,创建登录 Harbor 私有仓库的凭据,如图 1.15 所示。

图 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 所示。 
图 1.16 Harbor 登录页
如果打开的是英文界面,可通过右上角的语言选择,选择中文简体语言。在 Harbor 的
配置文件内有对用户名和密码的定义,默认用户为 admin,密码为 Harbor12345。登录成功
后,进入到 Harbor 的主界面。
##### **2)创建用户**
在进一步使用 Harbor 之前,还需要先配置项目所需要的用户。从左侧的用户管理导航
栏进入用户管理界面,如图 1.17 所示。

图 1.17 Harbor 用户管理导航
在用户管理界面,单击"创建用户",设置一个项目所需的用户,如图 1.18 所示。

图 1.18 用户管理界面
在创建用户界面,创建一个新用户 jenkins。其中用户名填写 jenkins,其他带"\*"的
选项都需要填写,如图 1.19 所示。

图 1.19 创建用户界面
用户相关信息都填写完成后,单击"确定"按钮,完成用户创建。
##### **3)创建项目**
##### 完成了用户创建之后,还需要创建实验中用到的项目。单击左侧导航栏中的项目,进入
到项目页中。然后再单击新建项目,进入到新建项目页中,如图 1.20 所示。

图 1.20 Harbor 项目页
由于是 Jenkins 构建完成镜像再上传到 Harbor 私有仓库,所以对应的私有仓库名称也
命名为 jenkins。新建项目的项目名称为 jenkins,单击确定按钮完成项目的新建。如图 1.21
所示。

图 1.21 新建项目页
项目 jenkins 创建完成后,如图 1.22 所示。

图 1.22 Harbor 项目页
##### **4)将用户添加到项目中**
将新建的 jenkins 用户添加到 jenkins 项目的成员中,这样 jenkins 用户才可以实现对
jenkins 项目的管理,如图 1.23 所示。

图 1.23 jenkins 项目成员页
在"成员"选项卡下,填写成员名称,填写用户"jenkins",角色选择维护人员。这
样就有权限上传及维护镜像了。最后单击确定按钮完成新成员的添加,如图 1.24 所示。

图 1.24 新建成员页
项目 jenkins 包含两个成员,一个默认的 admin,另一个就是新添加的 jenkins 用户。
如图 1.25 所示。

图 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 所示。  图 1.26 创建项目 在"General"面板中,勾选"参数化构建过程",然后在"添加参数"中选择"Git 参数",再填写 Git 相关参数。 其中,名称填写"Tag"。 描述是对整个过程的概述。如图 1.27 所示。  图 1.27 Git 参数配置 在源码管理内,选择"Git",之后填写项目在 GitLab 上的源码地址,选择对应的凭据, 如图 1.28 所示。  图 1.28 源码管理 "源码管理"这一步需要 Jenkins 主机安装了 git 软件。如果提示"无法连接仓库:Error performing git command",可在 jenkins 主机上通过"yum -y install git"进行安装。 在"构建"模块内,"增加构建步骤"中选择"Docker Build and Publish"。此步骤 用于从 GitLab 下载源码后,在 Jenkins 内构建镜像并上传到 Harbor 仓库中,如图 1.29 所 示。  图 1.29 构建类型选择 填写构建的具体配置内容,如图 1.30 所示。  图 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 所示。  图 1.31 构建类型选择 在"执行 shell"中,填入要执行的脚本,如图 1.32 所示。  图 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 所示。  图 1.33 引导新 Tag 新 Tag 命名为 1.1,其他选项保持默认,如图 1.34 所示。  图 1.34 创建新 Tag 单击"Create Tag"按钮,完成新 Tag 的创建。 最后编译构建 nginx 任务,通过选择"Build with Parameters"进行任务的构建。之 后选择 Tag 下的 1.1,单击"开始构建"按钮。如图 1.35 所示。  图 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 所示。  图 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。如下所示。 \ \
\