【K8S】基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境(环境搭建篇)

环境搭建概述

1.K8S是什么?

K8S全称是Kubernetes,是一个全新的基于容器技术的分布式架构领先方案,基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。java

若是咱们的系统设计遵循了kubernetes的设计思想,那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块,均可以使用K8S来管理,咱们没必要再费心于负载均衡的选型和部署实施问题,没必要再考虑引入或本身开发一个复杂的服务治理框架,没必要再头疼与服务监控和故障处理模块的开发。总之,使用kubernetes提供的解决方案,会大大减小开发成本,同时能够将精力更加集中于业务自己,并且因为kubernetes提供了强大的自动化机制,因此系统后期的运维难度和运维成本大幅下降。node

2.为何要用K8S?

Docker 这个新兴的容器化技术当前已经被不少公司所采用,其从单机走向集群已成必然,而云计算的蓬勃发展正在加速这一进程。Kubernetes 做为当前惟一被业界普遍承认和看好的 Docker 分布式系统解决方案。能够预见,在将来几年内,会有大量的新系统选择它,无论是运行在企业本地服务器上仍是被托管到公有云上。linux

3.使用K8S有哪些好处?

使用Kubernetes就是在全面部署微服务架构。微服务架构的核心就是将一个巨大的单体应用分解为不少小的互相链接的微服务,一个微服务背后可能有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器在 k8s 平台中有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器 在k8s 平台中发挥了重要的做用。微服务架构使得每一个服务均可以由专门的开发团队来开发,开发者能够自由选择开发技术,这对于大规模团队来讲颇有价值。另外,每一个微服务独立开发、升级、扩展,使得系统具有很高的稳定性和快速迭代进化能力。nginx

4.环境构成

整套环境的搭建包含:Docker环境的搭建、docker-compose环境的搭建、K8S集群的搭建、GitLab代码仓库的搭建、SVN仓库的搭建、Jenkins自动化部署环境的搭建、Harbor私有仓库的搭建。git

本文档中,整套环境的搭建包括:github

  • 安装Docker环境
  • 安装docker-compose
  • 安装K8S集群环境
  • 重启K8S集群引发的问题
  • K8S安装ingress-nginx
  • K8S安装gitlab代码仓库
  • 安装Harbor私有仓库
  • 安装Jenkins
  • 物理机安装SVN(推荐)
  • 物理机安装Jenkins(推荐)
  • 配置Jenkins运行环境
  • Jenkins发布Docker项目到K8S

服务器规划

IP 主机名 节点 操做系统
192.168.0.10 test10 K8S Master CentOS 8.0.1905
192.168.0.11 test11 K8S Worker CentOS 8.0.1905
192.168.0.12 test12 K8S Worker CentOS 8.0.1905

安装环境版本

软件名称 软件版本 说明
Docker 19.03.8 提供容器环境
docker-compose 1.25.5 定义和运行由多个容器组成的应用
K8S 1.18.2 是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单而且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。
GitLab 12.1.6 代码仓库
Harbor 1.10.2 私有镜像仓库
Jenkins 2.222.3 持续集成交付

安装Docker环境

Docker 是一个开源的应用容器引擎,基于 Go 语言 并听从 Apache2.0 协议开源。web

Docker 可让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,而后发布到任何流行的 Linux 机器上,也能够实现虚拟化。redis

本文档基于Docker 19.03.8 版本搭建Docker环境。spring

在全部服务器上建立install_docker.sh脚本,脚本内容以下所示。sql

#使用阿里云镜像中心
export REGISTRY_MIRROR=https://registry.cn-hangzhou.aliyuncs.com
#安装yum工具
dnf install yum*
#安装docker环境
yum install -y yum-utils device-mapper-persistent-data lvm2
#配置Docker的yum源
yum-config-manager --add-repo http://mirrors.aliyun.com/docker-ce/linux/centos/docker-ce.repo
#安装容器插件
dnf install https://mirrors.aliyun.com/docker-ce/linux/centos/7/x86_64/stable/Packages/containerd.io-1.2.13-3.1.el7.x86_64.rpm
#指定安装docker 19.03.8版本
yum install -y docker-ce-19.03.8 docker-ce-cli-19.03.8
#设置Docker开机启动
systemctl enable docker.service
#启动Docker
systemctl start docker.service
#查看Docker版本
docker version

在每台服务器上为install_docker.sh脚本赋予可执行权限,并执行脚本,以下所示。

# 赋予install_docker.sh脚本可执行权限
chmod a+x ./install_docker.sh
# 执行install_docker.sh脚本
./install_docker.sh

安装docker-compose

Compose 是用于定义和运行多容器 Docker 应用程序的工具。经过 Compose,您可使用 YML 文件来配置应用程序须要的全部服务。而后,使用一个命令,就能够从 YML 文件配置中建立并启动全部服务。

注意:在每台服务器上安装docker-compose

1.下载docker-compose文件

#下载并安装docker-compose
curl -L https://github.com/docker/compose/releases/download/1.25.5/docker-compose-`uname -s`-`uname -m` -o /usr/local/bin/docker-compose

2.为docker-compose文件赋予可执行权限

#赋予docker-compose可执行权限
chmod a+x /usr/local/bin/docker-compose

3.查看docker-compose版本

#查看docker-compose版本
[root@binghe ~]# docker-compose version
docker-compose version 1.25.5, build 8a1c60f6
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.0l  10 Sep 2019

安装K8S集群环境

Kubernetes是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kubernetes的目标是让部署容器化的应用简单而且高效(powerful),Kubernetes提供了应用部署,规划,更新,维护的一种机制。

本文档基于K8S 1.8.12版原本搭建K8S集群

安装K8S基础环境

在全部服务器上建立install_k8s.sh脚本文件,脚本文件的内容以下所示。

#################配置阿里云镜像加速器开始########################
mkdir -p /etc/docker
tee /etc/docker/daemon.json <<-'EOF'
{
  "registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"]
}
EOF
systemctl daemon-reload
systemctl restart docker
######################配置阿里云镜像加速器结束#########################
#安装nfs-utils
yum install -y nfs-utils
#安装wget软件下载命令
yum install -y wget

#启动nfs-server
systemctl start nfs-server
#配置nfs-server开机自启动
systemctl enable nfs-server

#关闭防火墙
systemctl stop firewalld
#取消防火墙开机自启动
systemctl disable firewalld

#关闭SeLinux
setenforce 0
sed -i "s/SELINUX=enforcing/SELINUX=disabled/g" /etc/selinux/config

# 关闭 swap
swapoff -a
yes | cp /etc/fstab /etc/fstab_bak
cat /etc/fstab_bak |grep -v swap > /etc/fstab

############################修改 /etc/sysctl.conf开始###########################
# 若是有配置,则修改
sed -i "s#^net.ipv4.ip_forward.*#net.ipv4.ip_forward=1#g"  /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g"  /etc/sysctl.conf
sed -i "s#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g"  /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g"  /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g"  /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g"  /etc/sysctl.conf
sed -i "s#^net.ipv6.conf.all.forwarding.*#net.ipv6.conf.all.forwarding=1#g"  /etc/sysctl.conf
# 可能没有,追加
echo "net.ipv4.ip_forward = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-ip6tables = 1" >> /etc/sysctl.conf
echo "net.bridge.bridge-nf-call-iptables = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.default.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.lo.disable_ipv6 = 1" >> /etc/sysctl.conf
echo "net.ipv6.conf.all.forwarding = 1"  >> /etc/sysctl.conf
############################修改 /etc/sysctl.conf结束###########################
# 执行命令使修改后的/etc/sysctl.conf文件生效
sysctl -p

################# 配置K8S的yum源开始#############################
cat <<EOF > /etc/yum.repos.d/kubernetes.repo
[kubernetes]
name=Kubernetes
baseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64
enabled=1
gpgcheck=0
repo_gpgcheck=0
gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg
       http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpg
EOF
################# 配置K8S的yum源结束#############################

# 卸载旧版本K8S
yum remove -y kubelet kubeadm kubectl

# 安装kubelet、kubeadm、kubectl,这里我安装的是1.18.2版本,你也能够安装1.17.2版本
yum install -y kubelet-1.18.2 kubeadm-1.18.2 kubectl-1.18.2

# 修改docker Cgroup Driver为systemd
# # 将/usr/lib/systemd/system/docker.service文件中的这一行 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
# # 修改成 ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd
# 若是不修改,在添加 worker 节点时可能会碰到以下错误
# [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/
sed -i "s#^ExecStart=/usr/bin/dockerd.*#ExecStart=/usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock --exec-opt native.cgroupdriver=systemd#g" /usr/lib/systemd/system/docker.service

# 设置 docker 镜像,提升 docker 镜像下载速度和稳定性
# 若是访问 https://hub.docker.io 速度很是稳定,也能够跳过这个步骤,通常不需配置
# curl -sSL https://kuboard.cn/install-script/set_mirror.sh | sh -s ${REGISTRY_MIRROR}

# 从新加载配置文件
systemctl daemon-reload
#重启 docker
systemctl restart docker
# 将kubelet设置为开机启动并启动kubelet
systemctl enable kubelet && systemctl start kubelet
# 查看docker版本
docker version

在每台服务器上为install_k8s.sh脚本赋予可执行权限,并执行脚本

# 赋予install_k8s.sh脚本可执行权限
chmod a+x ./install_k8s.sh
# 运行install_k8s.sh脚本
./install_k8s.sh

初始化Master节点

只在test10服务器上执行的操做。

1.初始化Master节点的网络环境

注意:下面的命令须要在命令行手动执行。

# 只在 master 节点执行
# export 命令只在当前 shell 会话中有效,开启新的 shell 窗口后,若是要继续安装过程,请从新执行此处的 export 命令
export MASTER_IP=192.168.0.10
# 替换 k8s.master 为 您想要的 dnsName
export APISERVER_NAME=k8s.master
# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 建立,事先并不存在于物理网络中
export POD_SUBNET=172.18.0.1/16
echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts

2.初始化Master节点

在test10服务器上建立init_master.sh脚本文件,文件内容以下所示。

#!/bin/bash
# 脚本出错时终止执行
set -e

if [ ${#POD_SUBNET} -eq 0 ] || [ ${#APISERVER_NAME} -eq 0 ]; then
  echo -e "\033[31;1m请确保您已经设置了环境变量 POD_SUBNET 和 APISERVER_NAME \033[0m"
  echo 当前POD_SUBNET=$POD_SUBNET
  echo 当前APISERVER_NAME=$APISERVER_NAME
  exit 1
fi


# 查看完整配置选项 https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2
rm -f ./kubeadm-config.yaml
cat <<EOF > ./kubeadm-config.yaml
apiVersion: kubeadm.k8s.io/v1beta2
kind: ClusterConfiguration
kubernetesVersion: v1.18.2
imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containers
controlPlaneEndpoint: "${APISERVER_NAME}:6443"
networking:
  serviceSubnet: "10.96.0.0/16"
  podSubnet: "${POD_SUBNET}"
  dnsDomain: "cluster.local"
EOF

# kubeadm init
# 初始化kebeadm
kubeadm init --config=kubeadm-config.yaml --upload-certs

# 配置 kubectl
rm -rf /root/.kube/
mkdir /root/.kube/
cp -i /etc/kubernetes/admin.conf /root/.kube/config

# 安装 calico 网络插件
# 参考文档 https://docs.projectcalico.org/v3.13/getting-started/kubernetes/self-managed-onprem/onpremises
echo "安装calico-3.13.1"
rm -f calico-3.13.1.yaml
wget https://kuboard.cn/install-script/calico/calico-3.13.1.yaml
kubectl apply -f calico-3.13.1.yaml

赋予init_master.sh脚本文件可执行权限并执行脚本。

# 赋予init_master.sh文件可执行权限
chmod a+x ./init_master.sh
# 运行init_master.sh脚本
./init_master.sh

3.查看Master节点的初始化结果

(1)确保全部容器组处于Running状态

# 执行以下命令,等待 3-10 分钟,直到全部的容器组处于 Running 状态
watch kubectl get pod -n kube-system -o wide

具体执行以下所示。

[root@test10 ~]# watch kubectl get pod -n kube-system -o wide
Every 2.0s: kubectl get pod -n kube-system -o wide                                                                                                                          test10: Sun May 10 11:01:32 2020

NAME                                       READY   STATUS    RESTARTS   AGE    IP                NODE        NOMINATED NODE   READINESS GATES          
calico-kube-controllers-5b8b769fcd-5dtlp   1/1     Running   0          118s   172.18.203.66     test10   <none>           <none>          
calico-node-fnv8g                          1/1     Running   0          118s   192.168.0.10   test10   <none>           <none>          
coredns-546565776c-27t7h                   1/1     Running   0          2m1s   172.18.203.67     test10   <none>           <none>          
coredns-546565776c-hjb8z                   1/1     Running   0          2m1s   172.18.203.65     test10   <none>           <none>          
etcd-test10                             1/1     Running   0          2m7s   192.168.0.10   test10   <none>           <none>          
kube-apiserver-test10                   1/1     Running   0          2m7s   192.168.0.10   test10   <none>           <none>          
kube-controller-manager-test10          1/1     Running   0          2m7s   192.168.0.10   test10   <none>           <none>          
kube-proxy-dvgsr                           1/1     Running   0          2m1s   192.168.0.10   test10   <none>           <none>          
kube-scheduler-test10                   1/1     Running   0          2m7s   192.168.0.10   test10   <none>           <none>

(2) 查看 Master 节点初始化结果

# 查看Master节点的初始化结果
kubectl get nodes -o wide

具体执行以下所示。

[root@test10 ~]# kubectl get nodes -o wide
NAME        STATUS   ROLES    AGE     VERSION   INTERNAL-IP       EXTERNAL-IP   OS-IMAGE                KERNEL-VERSION         CONTAINER-RUNTIME
test10   Ready    master   3m28s   v1.18.2   192.168.0.10   <none>        CentOS Linux 8 (Core)   4.18.0-80.el8.x86_64   docker://19.3.8

初始化Worker节点

1.获取join命令参数

在Master节点(test10服务器)上执行以下命令获取join命令参数。

kubeadm token create --print-join-command

具体执行以下所示。

[root@test10 ~]# kubeadm token create --print-join-command
W0510 11:04:34.828126   56132 configset.go:202] WARNING: kubeadm cannot validate component configs for API groups [kubelet.config.k8s.io kubeproxy.config.k8s.io]
kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2     --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d

其中,有以下一行输出。

kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2     --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d

这行代码就是获取到的join命令。

注意:join命令中的token的有效时间为 2 个小时,2小时内,可使用此 token 初始化任意数量的 worker 节点。

2.初始化Worker节点

针对全部的 worker 节点执行,在这里,就是在test11服务器和test12服务器上执行。

在命令分别手动执行以下命令。

# 只在 worker 节点执行
# 192.168.0.10 为 master 节点的内网 IP
export MASTER_IP=192.168.0.10
# 替换 k8s.master 为初始化 master 节点时所使用的 APISERVER_NAME
export APISERVER_NAME=k8s.master
echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts

# 替换为 master 节点上 kubeadm token create 命令输出的join
kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2     --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d

具体执行以下所示。

[root@test11 ~]# export MASTER_IP=192.168.0.10
[root@test11 ~]# export APISERVER_NAME=k8s.master
[root@test11 ~]# echo "${MASTER_IP}    ${APISERVER_NAME}" >> /etc/hosts
[root@test11 ~]# kubeadm join k8s.master:6443 --token 8nblts.62xytoqufwsqzko2     --discovery-token-ca-cert-hash sha256:1717cc3e34f6a56b642b5751796530e367aa73f4113d09994ac3455e33047c0d 
W0510 11:08:27.709263   42795 join.go:346] [preflight] WARNING: JoinControlPane.controlPlane settings will be ignored when control-plane flag is not set.
[preflight] Running pre-flight checks
        [WARNING FileExisting-tc]: tc not found in system path
[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.18" 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.

根据输出结果能够看出,Worker节点加入了K8S集群。

注意:kubeadm join…就是master 节点上 kubeadm token create 命令输出的join。

3.查看初始化结果

在Master节点(test10服务器)执行以下命令查看初始化结果。

kubectl get nodes -o wide

具体执行以下所示。

[root@test10 ~]# kubectl get nodes
NAME        STATUS   ROLES    AGE     VERSION
test10   Ready    master   20m     v1.18.2
test11   Ready    <none>   2m46s   v1.18.2
test12   Ready    <none>   2m46s   v1.18.2

注意:kubectl get nodes命令后面加上-o wide参数能够输出更多的信息。

重启K8S集群引发的问题

1.Worker节点故障不能启动

Master 节点的 IP 地址发生变化,致使 worker 节点不能启动。须要从新安装K8S集群,并确保全部节点都有固定的内网 IP 地址。

2.Pod崩溃或不能正常访问

重启服务器后使用以下命令查看Pod的运行状态。

#查看全部pod的运行状况
kubectl get pods --all-namespaces

发现不少 Pod 不在 Running 状态,此时,须要使用以下命令删除运行不正常的Pod。

kubectl delete pod <pod-name> -n <pod-namespece>

注意:若是Pod 是使用 Deployment、StatefulSet 等控制器建立的,K8S 将建立新的 Pod 做为替代,从新启动的 Pod 一般可以正常工做。

其中,pod-name表示运行在K8S中的pod的名称,pod-namespece表示命名空间。例如,须要删除pod名称为pod-test,命名空间为pod-test-namespace的pod,可使用下面的命令。

kubectl delete pod pod-test -n pod-test-namespace

K8S安装ingress-nginx

做为反向代理将外部流量导入集群内部,将 Kubernetes 内部的 Service 暴露给外部,在 Ingress 对象中经过域名匹配 Service,这样就能够直接经过域名访问到集群内部的服务了。相对于 traefik 来讲,nginx-ingress 性能更加优秀。

注意:在Master节点(test10服务器上执行)

1.建立ingress-nginx命名空间

建立ingress-nginx-namespace.yaml文件,主要的做用是建立ingress-nginx命名空间,文件内容以下所示。

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx
  labels:
    name: ingress-nginx

执行以下命令建立ingress-nginx命名空间。

kubectl apply -f ingress-nginx-namespace.yaml

2.安装ingress controller

建立ingress-nginx-mandatory.yaml文件,主要的做用是安装ingress-nginx。文件内容以下所示。

apiVersion: v1
kind: Namespace
metadata:
  name: ingress-nginx

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: default-http-backend
  labels:
    app.kubernetes.io/name: default-http-backend
    app.kubernetes.io/part-of: ingress-nginx
  namespace: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: default-http-backend
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: default-http-backend
        app.kubernetes.io/part-of: ingress-nginx
    spec:
      terminationGracePeriodSeconds: 60
      containers:
        - name: default-http-backend
          # Any image is permissible as long as:
          # 1. It serves a 404 page at /
          # 2. It serves 200 on a /healthz endpoint
          image: registry.cn-qingdao.aliyuncs.com/kubernetes_xingej/defaultbackend-amd64:1.5
          livenessProbe:
            httpGet:
              path: /healthz
              port: 8080
              scheme: HTTP
            initialDelaySeconds: 30
            timeoutSeconds: 5
          ports:
            - containerPort: 8080
          resources:
            limits:
              cpu: 10m
              memory: 20Mi
            requests:
              cpu: 10m
              memory: 20Mi

---
apiVersion: v1
kind: Service
metadata:
  name: default-http-backend
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: default-http-backend
    app.kubernetes.io/part-of: ingress-nginx
spec:
  ports:
    - port: 80
      targetPort: 8080
  selector:
    app.kubernetes.io/name: default-http-backend
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: nginx-configuration
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: tcp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

kind: ConfigMap
apiVersion: v1
metadata:
  name: udp-services
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---

apiVersion: v1
kind: ServiceAccount
metadata:
  name: nginx-ingress-serviceaccount
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRole
metadata:
  name: nginx-ingress-clusterrole
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - endpoints
      - nodes
      - pods
      - secrets
    verbs:
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - nodes
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - services
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - "extensions"
    resources:
      - ingresses
    verbs:
      - get
      - list
      - watch
  - apiGroups:
      - ""
    resources:
      - events
    verbs:
      - create
      - patch
  - apiGroups:
      - "extensions"
    resources:
      - ingresses/status
    verbs:
      - update

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: Role
metadata:
  name: nginx-ingress-role
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
rules:
  - apiGroups:
      - ""
    resources:
      - configmaps
      - pods
      - secrets
      - namespaces
    verbs:
      - get
  - apiGroups:
      - ""
    resources:
      - configmaps
    resourceNames:
      # Defaults to "<election-id>-<ingress-class>"
      # Here: "<ingress-controller-leader>-<nginx>"
      # This has to be adapted if you change either parameter
      # when launching the nginx-ingress-controller.
      - "ingress-controller-leader-nginx"
    verbs:
      - get
      - update
  - apiGroups:
      - ""
    resources:
      - configmaps
    verbs:
      - create
  - apiGroups:
      - ""
    resources:
      - endpoints
    verbs:
      - get

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: nginx-ingress-role-nisa-binding
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: nginx-ingress-role
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: ClusterRoleBinding
metadata:
  name: nginx-ingress-clusterrole-nisa-binding
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: nginx-ingress-clusterrole
subjects:
  - kind: ServiceAccount
    name: nginx-ingress-serviceaccount
    namespace: ingress-nginx

---

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-ingress-controller
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: ingress-nginx
      app.kubernetes.io/part-of: ingress-nginx
  template:
    metadata:
      labels:
        app.kubernetes.io/name: ingress-nginx
        app.kubernetes.io/part-of: ingress-nginx
      annotations:
        prometheus.io/port: "10254"
        prometheus.io/scrape: "true"
    spec:
      serviceAccountName: nginx-ingress-serviceaccount
      containers:
        - name: nginx-ingress-controller
          image: registry.cn-qingdao.aliyuncs.com/kubernetes_xingej/nginx-ingress-controller:0.20.0
          args:
            - /nginx-ingress-controller
            - --default-backend-service=$(POD_NAMESPACE)/default-http-backend
            - --configmap=$(POD_NAMESPACE)/nginx-configuration
            - --tcp-services-configmap=$(POD_NAMESPACE)/tcp-services
            - --udp-services-configmap=$(POD_NAMESPACE)/udp-services
            - --publish-service=$(POD_NAMESPACE)/ingress-nginx
            - --annotations-prefix=nginx.ingress.kubernetes.io
          securityContext:
            capabilities:
              drop:
                - ALL
              add:
                - NET_BIND_SERVICE
            # www-data -> 33
            runAsUser: 33
          env:
            - name: POD_NAME
              valueFrom:
                fieldRef:
                  fieldPath: metadata.name
            - name: POD_NAMESPACE
              valueFrom:
                fieldRef:
                  fieldPath: metadata.namespace
          ports:
            - name: http
              containerPort: 80
            - name: https
              containerPort: 443
          livenessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            initialDelaySeconds: 10
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1
          readinessProbe:
            failureThreshold: 3
            httpGet:
              path: /healthz
              port: 10254
              scheme: HTTP
            periodSeconds: 10
            successThreshold: 1
            timeoutSeconds: 1

---

执行以下命令安装ingress controller。

kubectl apply -f ingress-nginx-mandatory.yaml

3.安装K8S SVC:ingress-nginx

主要是用来用于暴露pod:nginx-ingress-controller。

建立service-nodeport.yaml文件,文件内容以下所示。

apiVersion: v1
kind: Service
metadata:
  name: ingress-nginx
  namespace: ingress-nginx
  labels:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx
spec:
  type: NodePort
  ports:
    - name: http
      port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 30080
    - name: https
      port: 443
      targetPort: 443
      protocol: TCP
      nodePort: 30443
  selector:
    app.kubernetes.io/name: ingress-nginx
    app.kubernetes.io/part-of: ingress-nginx

执行以下命令安装。

kubectl apply -f service-nodeport.yaml

4.访问K8S SVC:ingress-nginx

查看ingress-nginx命名空间的部署状况,以下所示。

[root@test10 k8s]# kubectl get pod -n ingress-nginx
NAME                                        READY   STATUS    RESTARTS   AGE
default-http-backend-796ddcd9b-vfmgn        1/1     Running   1          10h
nginx-ingress-controller-58985cc996-87754   1/1     Running   2          10h

在命令行服务器命令行输入以下命令查看ingress-nginx的端口映射状况。

kubectl get svc -n ingress-nginx

具体以下所示。

[root@test10 k8s]# kubectl get svc -n ingress-nginx 
NAME                   TYPE        CLUSTER-IP    EXTERNAL-IP   PORT(S)                      AGE
default-http-backend   ClusterIP   10.96.247.2   <none>        80/TCP                       7m3s
ingress-nginx          NodePort    10.96.40.6    <none>        80:30080/TCP,443:30443/TCP   4m35s

因此,能够经过Master节点(test10服务器)的IP地址和30080端口号来访问ingress-nginx,以下所示。

[root@test10 k8s]# curl 192.168.0.10:30080       
default backend - 404

也能够在浏览器打开http://192.168.0.10:30080 来访问ingress-nginx,以下所示。

K8S安装gitlab代码仓库

GitLab是由GitLabInc.开发,使用MIT许可证的基于网络的Git仓库管理工具,且具备Wiki和issue跟踪功能。使用Git做为代码管理工具,并在此基础上搭建起来的web服务。

注意:在Master节点(test10服务器上执行)

1.建立k8s-ops命名空间

建立k8s-ops-namespace.yaml文件,主要做用是建立k8s-ops命名空间。文件内容以下所示。

apiVersion: v1
kind: Namespace
metadata:
  name: k8s-ops
  labels:
    name: k8s-ops

执行以下命令建立命名空间。

kubectl apply -f k8s-ops-namespace.yaml

2.安装gitlab-redis

建立gitlab-redis.yaml文件,文件的内容以下所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis
  namespace: k8s-ops
  labels:
    name: redis
spec:
  selector:
    matchLabels:
      name: redis
  template:
    metadata:
      name: redis
      labels:
        name: redis
    spec:
      containers:
      - name: redis
        image: sameersbn/redis
        imagePullPolicy: IfNotPresent
        ports:
        - name: redis
          containerPort: 6379
        volumeMounts:
        - mountPath: /var/lib/redis
          name: data
        livenessProbe:
          exec:
            command:
            - redis-cli
            - ping
          initialDelaySeconds: 30
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command:
            - redis-cli
            - ping
          initialDelaySeconds: 10
          timeoutSeconds: 5
      volumes:
      - name: data
        hostPath:
          path: /data1/docker/xinsrv/redis

---
apiVersion: v1
kind: Service
metadata:
  name: redis
  namespace: k8s-ops
  labels:
    name: redis
spec:
  ports:
    - name: redis
      port: 6379
      targetPort: redis
  selector:
    name: redis

首先,在命令行执行以下命令建立/data1/docker/xinsrv/redis目录。

mkdir -p /data1/docker/xinsrv/redis

执行以下命令安装gitlab-redis。

kubectl apply -f gitlab-redis.yaml

3.安装gitlab-postgresql

建立gitlab-postgresql.yaml,文件内容以下所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: postgresql
  namespace: k8s-ops
  labels:
    name: postgresql
spec:
  selector:
    matchLabels:
      name: postgresql
  template:
    metadata:
      name: postgresql
      labels:
        name: postgresql
    spec:
      containers:
      - name: postgresql
        image: sameersbn/postgresql
        imagePullPolicy: IfNotPresent
        env:
        - name: DB_USER
          value: gitlab
        - name: DB_PASS
          value: passw0rd
        - name: DB_NAME
          value: gitlab_production
        - name: DB_EXTENSION
          value: pg_trgm
        ports:
        - name: postgres
          containerPort: 5432
        volumeMounts:
        - mountPath: /var/lib/postgresql
          name: data
        livenessProbe:
          exec:
            command:
            - pg_isready
            - -h
            - localhost
            - -U
            - postgres
          initialDelaySeconds: 30
          timeoutSeconds: 5
        readinessProbe:
          exec:
            command:
            - pg_isready
            - -h
            - localhost
            - -U
            - postgres
          initialDelaySeconds: 5
          timeoutSeconds: 1
      volumes:
      - name: data
        hostPath:
          path: /data1/docker/xinsrv/postgresql
---
apiVersion: v1
kind: Service
metadata:
  name: postgresql
  namespace: k8s-ops
  labels:
    name: postgresql
spec:
  ports:
    - name: postgres
      port: 5432
      targetPort: postgres
  selector:
    name: postgresql

首先,执行以下命令建立/data1/docker/xinsrv/postgresql目录。

mkdir -p /data1/docker/xinsrv/postgresql

接下来,安装gitlab-postgresql,以下所示。

kubectl apply -f gitlab-postgresql.yaml

4.安装gitlab

(1)配置用户名和密码

首先,在命令行使用base64编码为用户名和密码进行转码,本示例中,使用的用户名为admin,密码为admin.1231

转码状况以下所示。

[root@test10 k8s]# echo -n 'admin' | base64 
YWRtaW4=
[root@test10 k8s]# echo -n 'admin.1231' | base64 
YWRtaW4uMTIzMQ==

转码后的用户名为:YWRtaW4= 密码为:YWRtaW4uMTIzMQ==

也能够对base64编码后的字符串解码,例如,对密码字符串解码,以下所示。

[root@test10 k8s]# echo 'YWRtaW4uMTIzMQ==' | base64 --decode 
admin.1231

接下来,建立secret-gitlab.yaml文件,主要是用户来配置GitLab的用户名和密码,文件内容以下所示。

apiVersion: v1
kind: Secret
metadata:
  namespace: k8s-ops
  name: git-user-pass
type: Opaque
data:
  username: YWRtaW4=
  password: YWRtaW4uMTIzMQ==

执行配置文件的内容,以下所示。

kubectl create -f ./secret-gitlab.yaml

(2)安装GitLab

建立gitlab.yaml文件,文件的内容以下所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: gitlab
  namespace: k8s-ops
  labels:
    name: gitlab
spec:
  selector:
    matchLabels:
      name: gitlab
  template:
    metadata:
      name: gitlab
      labels:
        name: gitlab
    spec:
      containers:
      - name: gitlab
        image: sameersbn/gitlab:12.1.6
        imagePullPolicy: IfNotPresent
        env:
        - name: TZ
          value: Asia/Shanghai
        - name: GITLAB_TIMEZONE
          value: Beijing
        - name: GITLAB_SECRETS_DB_KEY_BASE
          value: long-and-random-alpha-numeric-string
        - name: GITLAB_SECRETS_SECRET_KEY_BASE
          value: long-and-random-alpha-numeric-string
        - name: GITLAB_SECRETS_OTP_KEY_BASE
          value: long-and-random-alpha-numeric-string
        - name: GITLAB_ROOT_PASSWORD
          valueFrom:
            secretKeyRef:
              name: git-user-pass
              key: password
        - name: GITLAB_ROOT_EMAIL
          value: 12345678@qq.com
        - name: GITLAB_HOST
          value: gitlab.binghe.com
        - name: GITLAB_PORT
          value: "80"
        - name: GITLAB_SSH_PORT
          value: "30022"
        - name: GITLAB_NOTIFY_ON_BROKEN_BUILDS
          value: "true"
        - name: GITLAB_NOTIFY_PUSHER
          value: "false"
        - name: GITLAB_BACKUP_SCHEDULE
          value: daily
        - name: GITLAB_BACKUP_TIME
          value: 01:00
        - name: DB_TYPE
          value: postgres
        - name: DB_HOST
          value: postgresql
        - name: DB_PORT
          value: "5432"
        - name: DB_USER
          value: gitlab
        - name: DB_PASS
          value: passw0rd
        - name: DB_NAME
          value: gitlab_production
        - name: REDIS_HOST
          value: redis
        - name: REDIS_PORT
          value: "6379"
        ports:
        - name: http
          containerPort: 80
        - name: ssh
          containerPort: 22
        volumeMounts:
        - mountPath: /home/git/data
          name: data
        livenessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 180
          timeoutSeconds: 5
        readinessProbe:
          httpGet:
            path: /
            port: 80
          initialDelaySeconds: 5
          timeoutSeconds: 1
      volumes:
      - name: data
        hostPath:
          path: /data1/docker/xinsrv/gitlab
---
apiVersion: v1
kind: Service
metadata:
  name: gitlab
  namespace: k8s-ops
  labels:
    name: gitlab
spec:
  ports:
    - name: http
      port: 80
      nodePort: 30088
    - name: ssh
      port: 22
      targetPort: ssh
      nodePort: 30022
  type: NodePort
  selector:
    name: gitlab

---
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: gitlab
  namespace: k8s-ops
  annotations:
    kubernetes.io/ingress.class: traefik
spec:
  rules:
  - host: gitlab.binghe.com
    http:
      paths:
      - backend:
          serviceName: gitlab
          servicePort: http

注意:在配置GitLab时,监听主机时,不能使用IP地址,须要使用主机名或者域名,上述配置中,我使用的是gitlab.binghe.com主机名。

在命令行执行以下命令建立/data1/docker/xinsrv/gitlab目录。

mkdir -p /data1/docker/xinsrv/gitlab

安装GitLab,以下所示。

kubectl apply -f gitlab.yaml

5.安装完成

查看k8s-ops命名空间部署状况,以下所示。

[root@test10 k8s]# kubectl get pod -n k8s-ops
NAME                          READY   STATUS    RESTARTS   AGE
gitlab-7b459db47c-5vk6t       0/1     Running   0          11s
postgresql-79567459d7-x52vx   1/1     Running   0          30m
redis-67f4cdc96c-h5ckz        1/1     Running   1          10h

也可使用以下命令查看。

[root@test10 k8s]# kubectl get pod --namespace=k8s-ops
NAME                          READY   STATUS    RESTARTS   AGE
gitlab-7b459db47c-5vk6t       0/1     Running   0          36s
postgresql-79567459d7-x52vx   1/1     Running   0          30m
redis-67f4cdc96c-h5ckz        1/1     Running   1          10h

两者效果同样。

接下来,查看GitLab的端口映射,以下所示。

[root@test10 k8s]# kubectl get svc -n k8s-ops
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)                     AGE
gitlab       NodePort    10.96.153.100   <none>        80:30088/TCP,22:30022/TCP   2m42s
postgresql   ClusterIP   10.96.203.119   <none>        5432/TCP                    32m
redis        ClusterIP   10.96.107.150   <none>        6379/TCP                    10h

此时,能够看到,能够经过Master节点(test10)的主机名gitlab.binghe.com和端口30088就可以访问GitLab。因为我这里使用的是虚拟机来搭建相关的环境,在本机访问虚拟机映射的gitlab.binghe.com时,须要配置本机的hosts文件,在本机的hosts文件中加入以下配置项。

192.168.0.10 gitlab.binghe.com

注意:在Windows操做系统中,hosts文件所在的目录以下。

C:\Windows\System32\drivers\etc

接下来,就能够在浏览器中经过连接:http://gitlab.binghe.com:30088 来访问GitLab了,以下所示。

此时,能够经过用户名root和密码admin.1231来登陆GitLab了。

注意:这里的用户名是root而不是admin,由于root是GitLab默认的超级用户。

到此,K8S安装gitlab完成。

安装Harbor私有仓库

Habor是由VMWare公司开源的容器镜像仓库。事实上,Habor是在Docker Registry上进行了相应的企业级扩展,从而得到了更加普遍的应用,这些新的企业级特性包括:管理用户界面,基于角色的访问控制 ,AD/LDAP集成以及审计日志等,足以知足基本企业需求。

注意:这里将Harbor私有仓库安装在Master节点(test10服务器)上,实际生产环境中建议安装在其余服务器。

1.下载Harbor的离线安装版本

wget https://github.com/goharbor/harbor/releases/download/v1.10.2/harbor-offline-installer-v1.10.2.tgz

2.解压Harbor的安装包

tar -zxvf harbor-offline-installer-v1.10.2.tgz

解压成功后,会在服务器当前目录生成一个harbor目录。

3.配置Harbor

注意:这里,我将Harbor的端口修改为了1180,若是不修改Harbor的端口,默认的端口是80。

(1)修改harbor.yml文件

cd harbor
vim harbor.yml

修改的配置项以下所示。

hostname: 192.168.0.10
http:
  port: 1180
harbor_admin_password: binghe123
###并把https注释掉,否则在安装的时候会报错:ERROR:root:Error: The protocol is https but attribute ssl_cert is not set
#https:
  #port: 443
  #certificate: /your/certificate/path
  #private_key: /your/private/key/path

(2)修改daemon.json文件

修改/etc/docker/daemon.json文件,没有的话就建立,在/etc/docker/daemon.json文件中添加以下内容。

[root@binghe~]# cat /etc/docker/daemon.json
{
  "registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"],
  "insecure-registries":["192.168.0.10:1180"]
}

也能够在服务器上使用 ip addr 命令查看本机全部的IP地址段,将其配置到/etc/docker/daemon.json文件中。这里,我配置后的文件内容以下所示。

{
    "registry-mirrors": ["https://zz3sblpi.mirror.aliyuncs.com"],
    "insecure-registries":["192.168.175.0/16","172.17.0.0/16", "172.18.0.0/16", "172.16.29.0/16", "192.168.0.10:1180"]
}

4.安装并启动harbor

配置完成后,输入以下命令便可安装并启动Harbor

[root@binghe harbor]# ./install.sh

5.登陆Harbor并添加帐户

安装成功后,在浏览器地址栏输入http://192.168.0.10:1180打开连接,输入用户名admin和密码binghe123,登陆系统。

接下来,咱们选择用户管理,添加一个管理员帐户,为后续打包Docker镜像和上传Docker镜像作准备。

密码为Binghe123。点击确,此时,帐户binghe还不是管理员,此时选中binghe帐户,点击“设置为管理员”。

此时,binghe帐户就被设置为管理员了。到此,Harbor的安装就完成了。

6.修改Harbor端口

若是安装Harbor后,你们须要修改Harbor的端口,能够按照以下步骤修改Harbor的端口,这里,我以将80端口修改成1180端口为例

(1)修改harbor.yml文件

cd harbor
vim harbor.yml

修改的配置项以下所示。

hostname: 192.168.0.10
http:
  port: 1180
harbor_admin_password: binghe123
###并把https注释掉,否则在安装的时候会报错:ERROR:root:Error: The protocol is https but attribute ssl_cert is not set
#https:
  #port: 443
  #certificate: /your/certificate/path
  #private_key: /your/private/key/path

(2)修改docker-compose.yml文件

vim docker-compose.yml

修改的配置项以下所示。

ports:
      - 1180:80

(3)修改config.yml文件

cd common/config/registry
vim config.yml

修改的配置项以下所示。

realm: http://192.168.0.10:1180/service/token

(4)重启Docker

systemctl daemon-reload
systemctl restart docker.service

(5)重启Harbor

[root@binghe harbor]# docker-compose down
Stopping harbor-log ... done
Removing nginx             ... done
Removing harbor-portal     ... done
Removing harbor-jobservice ... done
Removing harbor-core       ... done
Removing redis             ... done
Removing registry          ... done
Removing registryctl       ... done
Removing harbor-db         ... done
Removing harbor-log        ... done
Removing network harbor_harbor
 
[root@binghe harbor]# ./prepare
prepare base dir is set to /mnt/harbor
Clearing the configuration file: /config/log/logrotate.conf
Clearing the configuration file: /config/nginx/nginx.conf
Clearing the configuration file: /config/core/env
Clearing the configuration file: /config/core/app.conf
Clearing the configuration file: /config/registry/root.crt
Clearing the configuration file: /config/registry/config.yml
Clearing the configuration file: /config/registryctl/env
Clearing the configuration file: /config/registryctl/config.yml
Clearing the configuration file: /config/db/env
Clearing the configuration file: /config/jobservice/env
Clearing the configuration file: /config/jobservice/config.yml
Generated configuration file: /config/log/logrotate.conf
Generated configuration file: /config/nginx/nginx.conf
Generated configuration file: /config/core/env
Generated configuration file: /config/core/app.conf
Generated configuration file: /config/registry/config.yml
Generated configuration file: /config/registryctl/env
Generated configuration file: /config/db/env
Generated configuration file: /config/jobservice/env
Generated configuration file: /config/jobservice/config.yml
loaded secret from file: /secret/keys/secretkey
Generated configuration file: /compose_location/docker-compose.yml
Clean up the input dir
 
[root@binghe harbor]# docker-compose up -d
Creating network "harbor_harbor" with the default driver
Creating harbor-log ... done
Creating harbor-db   ... done
Creating redis       ... done
Creating registry    ... done
Creating registryctl ... done
Creating harbor-core ... done
Creating harbor-jobservice ... done
Creating harbor-portal     ... done
Creating nginx             ... done
 
[root@binghe harbor]# docker ps -a
CONTAINER ID        IMAGE                                               COMMAND                  CREATED             STATUS                             PORTS

安装Jenkins(通常的作法)

Jenkins是一个开源的、提供友好操做界面的持续集成(CI)工具,起源于Hudson(Hudson是商用的),主要用于持续、自动的构建/测试软件项目、监控外部任务的运行(这个比较抽象,暂且写上,不作解释)。Jenkins用Java语言编写,可在Tomcat等流行的servlet容器中运行,也可独立运行。一般与版本管理工具(SCM)、构建工具结合使用。经常使用的版本控制工具备SVN、GIT,构建工具备Maven、Ant、Gradle。

1.安装nfs(以前安装过的话,能够省略此步)

使用 nfs 最大的问题就是写权限,可使用 kubernetes 的 securityContext/runAsUser 指定 jenkins 容器中运行 jenkins 的用户 uid,以此来指定 nfs 目录的权限,让 jenkins 容器可写;也能够不限制,让全部用户均可以写。这里为了简单,就让全部用户可写了。

若是以前已经安装过nfs,则这一步能够省略。找一台主机,安装 nfs,这里,我以在Master节点(test10服务器)上安装nfs为例。

在命令行输入以下命令安装并启动nfs。

yum install nfs-utils -y
systemctl start nfs-server
systemctl enable nfs-server

2.建立nfs共享目录

在Master节点(test10服务器)上建立 /opt/nfs/jenkins-data目录做为nfs的共享目录,以下所示。

mkdir -p /opt/nfs/jenkins-data

接下来,编辑/etc/exports文件,以下所示。

vim /etc/exports

在/etc/exports文件文件中添加以下一行配置。

/opt/nfs/jenkins-data 192.168.175.0/24(rw,all_squash)

这里的 ip 使用 kubernetes node 节点的 ip 范围,后面的 all_squash 选项会将全部访问的用户都映射成 nfsnobody 用户,无论你是什么用户访问,最终都会压缩成 nfsnobody,因此只要将 /opt/nfs/jenkins-data 的属主改成 nfsnobody,那么不管什么用户来访问都具备写权限。

这个选项在不少机器上因为用户 uid 不规范致使启动进程的用户不一样,可是同时要对一个共享目录具备写权限时颇有效。

接下来,为 /opt/nfs/jenkins-data目录受权,并从新加载nfs,以下所示。

#为/opt/nfs/jenkins-data/目录受权
chown -R 1000 /opt/nfs/jenkins-data/
#从新加载nfs-server
systemctl reload nfs-server

在K8S集群中任意一个节点上使用以下命令进行验证:

#查看nfs系统的目录权限
showmount -e NFS_IP

若是可以看到 /opt/nfs/jenkins-data 就表示 ok 了。

具体以下所示。

[root@test10 ~]# showmount -e 192.168.0.10
Export list for 192.168.0.10:
/opt/nfs/jenkins-data 192.168.175.0/24

[root@test11 ~]# showmount -e 192.168.0.10
Export list for 192.168.0.10:
/opt/nfs/jenkins-data 192.168.175.0/24

3.建立PV

Jenkins 其实只要加载对应的目录就能够读取以前的数据,可是因为 deployment 没法定义存储卷,所以咱们只能使用 StatefulSet。

首先建立 pv,pv 是给 StatefulSet 使用的,每次 StatefulSet 启动都会经过 volumeClaimTemplates 这个模板去建立 pvc,所以必须得有 pv,才能供 pvc 绑定。

建立jenkins-pv.yaml文件,文件内容以下所示。

apiVersion: v1
kind: PersistentVolume
metadata:
  name: jenkins
spec:
  nfs:
    path: /opt/nfs/jenkins-data
    server: 192.168.0.10
  accessModes: ["ReadWriteOnce"]
  capacity:
    storage: 1Ti

我这里给了 1T存储空间,能够根据实际配置。

执行以下命令建立pv。

kubectl apply -f jenkins-pv.yaml

4.建立serviceAccount

建立service account,由于 jenkins 后面须要可以动态建立 slave,所以它必须具有一些权限。

建立jenkins-service-account.yaml文件,文件内容以下所示。

apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins

---
kind: Role
apiVersion: rbac.authorization.k8s.io/v1beta1
metadata:
  name: jenkins
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
  - apiGroups: [""]
    resources: ["pods/exec"]
    verbs: ["create", "delete", "get", "list", "patch", "update", "watch"]
  - apiGroups: [""]
    resources: ["pods/log"]
    verbs: ["get", "list", "watch"]
  - apiGroups: [""]
    resources: ["secrets"]
    verbs: ["get"]

---
apiVersion: rbac.authorization.k8s.io/v1beta1
kind: RoleBinding
metadata:
  name: jenkins
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: jenkins
subjects:
  - kind: ServiceAccount
    name: jenkins

上述配置中,建立了一个 RoleBinding 和一个 ServiceAccount,而且将 RoleBinding 的权限绑定到这个用户上。因此,jenkins 容器必须使用这个 ServiceAccount 运行才行,否则 RoleBinding 的权限它将不具有。

RoleBinding 的权限很容易就看懂了,由于 jenkins 须要建立和删除 slave,因此才须要上面这些权限。至于 secrets 权限,则是 https 证书。

执行以下命令建立serviceAccount。

kubectl apply -f jenkins-service-account.yaml

5.安装Jenkins

建立jenkins-statefulset.yaml文件,文件内容以下所示。

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: jenkins
  labels:
    name: jenkins
spec:
  selector:
    matchLabels:
      name: jenkins
  serviceName: jenkins
  replicas: 1
  updateStrategy:
    type: RollingUpdate
  template:
    metadata:
      name: jenkins
      labels:
        name: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccountName: jenkins
      containers:
        - name: jenkins
          image: docker.io/jenkins/jenkins:lts
          imagePullPolicy: IfNotPresent
          ports:
            - containerPort: 8080
            - containerPort: 32100
          resources:
            limits:
              cpu: 4
              memory: 4Gi
            requests:
              cpu: 4
              memory: 4Gi
          env:
            - name: LIMITS_MEMORY
              valueFrom:
                resourceFieldRef:
                  resource: limits.memory
                  divisor: 1Mi
            - name: JAVA_OPTS
              # value: -XX:+UnlockExperimentalVMOptions -XX:+UseCGroupMemoryLimitForHeap -XX:MaxRAMFraction=1 -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
              value: -Xmx$(LIMITS_MEMORY)m -XshowSettings:vm -Dhudson.slaves.NodeProvisioner.initialDelay=0 -Dhudson.slaves.NodeProvisioner.MARGIN=50 -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
          volumeMounts:
            - name: jenkins-home
              mountPath: /var/jenkins_home
          livenessProbe:
            httpGet:
              path: /login
              port: 8080
            initialDelaySeconds: 60
            timeoutSeconds: 5
            failureThreshold: 12 # ~2 minutes
          readinessProbe:
            httpGet:
              path: /login
              port: 8080
            initialDelaySeconds: 60
            timeoutSeconds: 5
            failureThreshold: 12 # ~2 minutes
  # pvc 模板,对应以前的 pv
  volumeClaimTemplates:
    - metadata:
        name: jenkins-home
      spec:
        accessModes: ["ReadWriteOnce"]
        resources:
          requests:
            storage: 1Ti

jenkins 部署时须要注意它的副本数,你的副本数有多少就要有多少个 pv,一样,存储会有多倍消耗。这里我只使用了一个副本,所以前面也只建立了一个 pv。

使用以下命令安装Jenkins。

kubectl apply -f jenkins-statefulset.yaml

6.建立Service

建立jenkins-service.yaml文件,主要用于后台运行Jenkins,文件内容以下所示。

apiVersion: v1
kind: Service
metadata:
  name: jenkins
spec:
  # type: LoadBalancer
  selector:
    name: jenkins
  # ensure the client ip is propagated to avoid the invalid crumb issue when using LoadBalancer (k8s >=1.7)
  #externalTrafficPolicy: Local
  ports:
    - name: http
      port: 80
      nodePort: 31888
      targetPort: 8080
      protocol: TCP
    - name: jenkins-agent
      port: 32100
      nodePort: 32100
      targetPort: 32100
      protocol: TCP
  type: NodePort

使用以下命令安装Service。

kubectl apply -f jenkins-service.yaml

7.安装 ingress

jenkins 的 web 界面须要从集群外访问,这里咱们选择的是使用 ingress。建立jenkins-ingress.yaml文件,文件内容以下所示。

apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  name: jenkins
spec:
  rules:
    - http:
        paths:
          - path: /
            backend:
              serviceName: jenkins
              servicePort: 31888
      host: jekins.binghe.com

这里,须要注意的是host必须配置为域名或者主机名,不然会报错,以下所示。

The Ingress "jenkins" is invalid: spec.rules[0].host: Invalid value: "192.168.0.10": must be a DNS name, not an IP address

使用以下命令安装ingress。

kubectl apply -f jenkins-ingress.yaml

最后,因为我这里使用的是虚拟机来搭建相关的环境,在本机访问虚拟机映射的jekins.binghe.com时,须要配置本机的hosts文件,在本机的hosts文件中加入以下配置项。

192.168.0.10 jekins.binghe.com

注意:在Windows操做系统中,hosts文件所在的目录以下。

C:\Windows\System32\drivers\etc

接下来,就能够在浏览器中经过连接:http://jekins.binghe.com:31888 来访问Jekins了。

物理机安装SVN

Apache Subversion 一般被缩写成 SVN,是一个开放源代码的版本控制系统,Subversion 在 2000 年由 CollabNet Inc 开发,如今发展成为 Apache 软件基金会的一个项目,一样是一个丰富的开发者和用户社区的一部分。

SVN相对于的RCS、CVS,采用了分支管理系统,它的设计目标就是取代CVS。互联网上免费的版本控制服务多基于Subversion。

这里,以在Master节点(binghe101服务器)上安装SVN为例。

1.使用yum安装SVN

在命令行执行以下命令安装SVN。

yum -y install subversion

2.建立SVN库

依次执行以下命令。

#建立/data/svn
mkdir -p /data/svn 
#初始化svn
svnserve -d -r /data/svn
#建立代码仓库
svnadmin create /data/svn/test

3.配置SVN

mkdir /data/svn/conf
cp /data/svn/test/conf/* /data/svn/conf/
cd /data/svn/conf/
[root@binghe101 conf]# ll
总用量 20
-rw-r--r-- 1 root root 1080 5月  12 02:17 authz
-rw-r--r-- 1 root root  885 5月  12 02:17 hooks-env.tmpl
-rw-r--r-- 1 root root  309 5月  12 02:17 passwd
-rw-r--r-- 1 root root 4375 5月  12 02:17 svnserve.conf
  • 配置authz文件,
vim authz

配置后的内容以下所示。

[aliases]
# joe = /C=XZ/ST=Dessert/L=Snake City/O=Snake Oil, Ltd./OU=Research Institute/CN=Joe Average

[groups]
# harry_and_sally = harry,sally
# harry_sally_and_joe = harry,sally,&joe
SuperAdmin = admin
binghe = admin,binghe

# [/foo/bar]
# harry = rw
# &joe = r
# * =

# [repository:/baz/fuz]
# @harry_and_sally = rw
# * = r

[test:/]
@SuperAdmin=rw
@binghe=rw
  • 配置passwd文件
vim passwd

配置后的内容以下所示。

[users]
# harry = harryssecret
# sally = sallyssecret
admin = admin123
binghe = binghe123
  • 配置 svnserve.conf
vim svnserve.conf

配置后的文件以下所示。

### This file controls the configuration of the svnserve daemon, if you
### use it to allow access to this repository.  (If you only allow
### access through http: and/or file: URLs, then this file is
### irrelevant.)

### Visit http://subversion.apache.org/ for more information.

[general]
### The anon-access and auth-access options control access to the
### repository for unauthenticated (a.k.a. anonymous) users and
### authenticated users, respectively.
### Valid values are "write", "read", and "none".
### Setting the value to "none" prohibits both reading and writing;
### "read" allows read-only access, and "write" allows complete 
### read/write access to the repository.
### The sample settings below are the defaults and specify that anonymous
### users have read-only access to the repository, while authenticated
### users have read and write access to the repository.
anon-access = none
auth-access = write
### The password-db option controls the location of the password
### database file.  Unless you specify a path starting with a /,
### the file's location is relative to the directory containing
### this configuration file.
### If SASL is enabled (see below), this file will NOT be used.
### Uncomment the line below to use the default password file.
password-db = /data/svn/conf/passwd
### The authz-db option controls the location of the authorization
### rules for path-based access control.  Unless you specify a path
### starting with a /, the file's location is relative to the
### directory containing this file.  The specified path may be a
### repository relative URL (^/) or an absolute file:// URL to a text
### file in a Subversion repository.  If you don't specify an authz-db,
### no path-based access control is done.
### Uncomment the line below to use the default authorization file.
authz-db = /data/svn/conf/authz
### The groups-db option controls the location of the file with the
### group definitions and allows maintaining groups separately from the
### authorization rules.  The groups-db file is of the same format as the
### authz-db file and should contain a single [groups] section with the
### group definitions.  If the option is enabled, the authz-db file cannot
### contain a [groups] section.  Unless you specify a path starting with
### a /, the file's location is relative to the directory containing this
### file.  The specified path may be a repository relative URL (^/) or an
### absolute file:// URL to a text file in a Subversion repository.
### This option is not being used by default.
# groups-db = groups
### This option specifies the authentication realm of the repository.
### If two repositories have the same authentication realm, they should
### have the same password database, and vice versa.  The default realm
### is repository's uuid.
realm = svn
### The force-username-case option causes svnserve to case-normalize
### usernames before comparing them against the authorization rules in the
### authz-db file configured above.  Valid values are "upper" (to upper-
### case the usernames), "lower" (to lowercase the usernames), and
### "none" (to compare usernames as-is without case conversion, which
### is the default behavior).
# force-username-case = none
### The hooks-env options specifies a path to the hook script environment 
### configuration file. This option overrides the per-repository default
### and can be used to configure the hook script environment for multiple 
### repositories in a single file, if an absolute path is specified.
### Unless you specify an absolute path, the file's location is relative
### to the directory containing this file.
# hooks-env = hooks-env

[sasl]
### This option specifies whether you want to use the Cyrus SASL
### library for authentication. Default is false.
### Enabling this option requires svnserve to have been built with Cyrus
### SASL support; to check, run 'svnserve --version' and look for a line
### reading 'Cyrus SASL authentication is available.'
# use-sasl = true
### These options specify the desired strength of the security layer
### that you want SASL to provide. 0 means no encryption, 1 means
### integrity-checking only, values larger than 1 are correlated
### to the effective key length for encryption (e.g. 128 means 128-bit
### encryption). The values below are the defaults.
# min-encryption = 0
# max-encryption = 256

接下来,将/data/svn/conf目录下的svnserve.conf文件复制到/data/svn/test/conf/目录下。以下所示。

[root@binghe101 conf]# cp /data/svn/conf/svnserve.conf /data/svn/test/conf/
cp:是否覆盖'/data/svn/test/conf/svnserve.conf'? y

4.启动SVN服务

(1)建立svnserve.service服务

建立svnserve.service文件

vim /usr/lib/systemd/system/svnserve.service

文件的内容以下所示。

[Unit]
Description=Subversion protocol daemon
After=syslog.target network.target
Documentation=man:svnserve(8)

[Service]
Type=forking
EnvironmentFile=/etc/sysconfig/svnserve
#ExecStart=/usr/bin/svnserve --daemon --pid-file=/run/svnserve/svnserve.pid $OPTIONS
ExecStart=/usr/bin/svnserve --daemon $OPTIONS
PrivateTmp=yes

[Install]
WantedBy=multi-user.target

接下来执行以下命令使配置生效。

systemctl daemon-reload

命令执行成功后,修改 /etc/sysconfig/svnserve 文件。

vim /etc/sysconfig/svnserve

修改后的文件内容以下所示。

# OPTIONS is used to pass command-line arguments to svnserve.
# 
# Specify the repository location in -r parameter:
OPTIONS="-r /data/svn"

(2)启动SVN

首先查看SVN状态,以下所示。

[root@test10 conf]# systemctl status svnserve.service
● svnserve.service - Subversion protocol daemon
   Loaded: loaded (/usr/lib/systemd/system/svnserve.service; disabled; vendor preset: disabled)
   Active: inactive (dead)
     Docs: man:svnserve(8)

能够看到,此时SVN并无启动,接下来,须要启动SVN。

systemctl start svnserve.service

设置SVN服务开机自启动。

systemctl enable svnserve.service

接下来,就能够下载安装TortoiseSVN,输入连接svn://192.168.0.10/test 并输入用户名binghe,密码binghe123来链接SVN了。

Docker安装SVN

拉取SVN镜像

docker pull docker.io/elleflorio/svn-server

启动SVN容器

docker run -v /usr/local/svn:/home/svn -v /usr/local/svn/passwd:/etc/subversion/passwd -v /usr/local/apache2:/run/apache2 --name svn_server -p 3380:80 -p 3690:3960 -e SVN_REPONAME=repos -d docker.io/elleflorio/svn-server

进入SVN容器内部

docker exec -it svn_server bash

进入容器后,能够参照物理机安装SVN的方式配置SVN仓库。

物理机安装Jenkins

注意:安装Jenkins以前须要安装JDK和Maven,我这里一样将Jenkins安装在Master节点(binghe101服务器)。

1.启用Jenkins库

运行如下命令如下载repo文件并导入GPG密钥:

wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat-stable/jenkins.repo
rpm --import https://jenkins-ci.org/redhat/jenkins-ci.org.key

2.安装Jenkins

执行以下命令安装Jenkis。

yum install jenkins

接下来,修改Jenkins默认端口,以下所示。

vim /etc/sysconfig/jenkins

修改后的两项配置以下所示。

JENKINS_JAVA_CMD="/usr/local/jdk1.8.0_212/bin/java"
JENKINS_PORT="18080"

此时,已经将Jenkins的端口由8080修改成18080

3.启动Jenkins

在命令行输入以下命令启动Jenkins。

systemctl start jenkins

配置Jenkins开机自启动。

systemctl enable jenkins

查看Jenkins的运行状态。

[root@test10 ~]# systemctl status jenkins
● jenkins.service - LSB: Jenkins Automation Server
   Loaded: loaded (/etc/rc.d/init.d/jenkins; generated)
   Active: active (running) since Tue 2020-05-12 04:33:40 EDT; 28s ago
     Docs: man:systemd-sysv-generator(8)
    Tasks: 71 (limit: 26213)
   Memory: 550.8M

说明,Jenkins启动成功。

配置Jenkins运行环境

1.登陆Jenkins

首次安装后,须要配置Jenkins的运行环境。首先,在浏览器地址栏访问连接http://192.168.0.10:18080,打开Jenkins界面。

根据提示使用以下命令到服务器上找密码值,以下所示。

[root@binghe101 ~]# cat /var/lib/jenkins/secrets/initialAdminPassword
71af861c2ab948a1b6efc9f7dde90776

将密码71af861c2ab948a1b6efc9f7dde90776复制到文本框,点击继续。会跳转到自定义Jenkins页面,以下所示。

这里,能够直接选择“安装推荐的插件”。以后会跳转到一个安装插件的页面,以下所示。

此步骤可能有下载失败的状况,可直接忽略。

2.安装插件

须要安装的插件

  • Kubernetes Cli Plugin:该插件可直接在Jenkins中使用kubernetes命令行进行操做。
  • Kubernetes plugin: 使用kubernetes则须要安装该插件
  • Kubernetes Continuous Deploy Plugin:kubernetes部署插件,可根据须要使用

还有更多的插件可供选择,可点击 系统管理->管理插件进行管理和添加,安装相应的Docker插件、SSH插件、Maven插件。其余的插件能够根据须要进行安装。以下图所示。

3.配置Jenkins

(1)配置JDK和Maven

在Global Tool Configuration中配置JDK和Maven,以下所示,打开Global Tool Configuration界面。

接下来就开始配置JDK和Maven了。

因为我在服务器上将Maven安装在/usr/local/maven-3.6.3目录下,因此,须要在“Maven 配置”中进行配置,以下图所示。

接下来,配置JDK,以下所示。

注意:不要勾选“Install automatically”

接下来,配置Maven,以下所示。

注意:不要勾选“Install automatically”

(2)配置SSH

进入Jenkins的Configure System界面配置SSH,以下所示。

找到 SSH remote hosts 进行配置。

配置完成后,点击Check connection按钮,会显示 Successfull connection。以下所示。

至此,Jenkins的基本配置就完成了。

Jenkins发布Docker项目到K8s集群

1.调整SpringBoot项目的配置

实现,SpringBoot项目中启动类所在的模块的pom.xml须要引入打包成Docker镜像的配置,以下所示。

<properties>
  	 	<docker.repostory>192.168.0.10:1180</docker.repostory>
        <docker.registry.name>test</docker.registry.name>
        <docker.image.tag>1.0.0</docker.image.tag>
        <docker.maven.plugin.version>1.4.10</docker.maven.plugin.version>
  </properties>

<build>
  		<finalName>test-starter</finalName>
		<plugins>
            <plugin>
			    <groupId>org.springframework.boot</groupId>
			    <artifactId>spring-boot-maven-plugin</artifactId>
			</plugin>
			
			<!-- docker的maven插件,官网:https://github.com/spotify/docker‐maven‐plugin -->
			<!-- Dockerfile maven plugin -->
			<plugin>
			    <groupId>com.spotify</groupId>
			    <artifactId>dockerfile-maven-plugin</artifactId>
			    <version>${docker.maven.plugin.version}</version>
			    <executions>
			        <execution>
			        <id>default</id>
			        <goals>
			            <!--若是package时不想用docker打包,就注释掉这个goal-->
			            <goal>build</goal>
			            <goal>push</goal>
			        </goals>
			        </execution>
			    </executions>
			    <configuration>
			    	<contextDirectory>${project.basedir}</contextDirectory>
			        <!-- harbor 仓库用户名及密码-->
			        <useMavenSettingsForAuth>useMavenSettingsForAuth>true</useMavenSettingsForAuth>
			        <repository>${docker.repostory}/${docker.registry.name}/${project.artifactId}</repository>
			        <tag>${docker.image.tag}</tag>
			        <buildArgs>
			            <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
			        </buildArgs>
			    </configuration>
			</plugin>

        </plugins>
        
		<resources>
			<!-- 指定 src/main/resources下全部文件及文件夹为资源文件 -->
			<resource>
				<directory>src/main/resources</directory>
				<targetPath>${project.build.directory}/classes</targetPath>
				<includes>
					<include>**/*</include>
				</includes>
				<filtering>true</filtering>
			</resource>
		</resources>
	</build>

接下来,在SpringBoot启动类所在模块的根目录建立Dockerfile,内容示例以下所示。

#添加依赖环境,前提是将Java8的Docker镜像从官方镜像仓库pull下来,而后上传到本身的Harbor私有仓库中
FROM 192.168.0.10:1180/library/java:8
#指定镜像制做做者
MAINTAINER binghe
#运行目录
VOLUME /tmp
#将本地的文件拷贝到容器
ADD target/*jar app.jar
#启动容器后自动执行的命令
ENTRYPOINT [ "java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/app.jar" ]

根据实际状况,自行修改。

注意:FROM 192.168.0.10:1180/library/java:8的前提是执行以下命令。

docker pull java:8
docker tag java:8 192.168.0.10:1180/library/java:8
docker login 192.168.0.10:1180
docker push 192.168.0.10:1180/library/java:8

在SpringBoot启动类所在模块的根目录建立yaml文件,录入叫作test.yaml文件,内容以下所示。

apiVersion: apps/v1
kind: Deployment
metadata:
  name: test-starter
  labels:
    app: test-starter
spec:
  replicas: 1
  selector:
    matchLabels:
      app: test-starter
  template:
    metadata:
      labels:
        app: test-starter
    spec:
      containers:
      - name: test-starter
        image: 192.168.0.10:1180/test/test-starter:1.0.0
        ports:
        - containerPort: 8088
      nodeSelector:
        clustertype: node12

---
apiVersion: v1
kind: Service
metadata:
  name: test-starter
  labels:
    app: test-starter
spec:
  ports:
    - name: http
      port: 8088
      nodePort: 30001
  type: NodePort
  selector:
    app: test-starter

2.Jenkins配置发布项目

将项目上传到SVN代码库,例如地址为svn://192.168.0.10/test

接下来,在Jenkins中配置自动发布。步骤以下所示。

点击新建Item。

在描述文本框中输入描述信息,以下所示。

接下来,配置SVN信息。

注意:配置GitLab的步骤与SVN相同,再也不赘述。

定位到Jenkins的“构建模块”,使用Execute Shell来构建发布项目到K8S集群。

执行的命令依次以下所示。

#删除本地原有的镜像,不会影响Harbor仓库中的镜像
docker rmi 192.168.0.10:1180/test/test-starter:1.0.0
#使用Maven编译、构建Docker镜像,执行完成后本地Docker容器中会从新构建镜像文件
/usr/local/maven-3.6.3/bin/mvn -f ./pom.xml clean install -Dmaven.test.skip=true
#登陆 Harbor仓库
docker login 192.168.0.10:1180 -u binghe -p Binghe123
#上传镜像到Harbor仓库
docker push 192.168.0.10:1180/test/test-starter:1.0.0
#中止并删除K8S集群中运行的
/usr/bin/kubectl delete -f test.yaml
#将Docker镜像从新发布到K8S集群
/usr/bin/kubectl apply -f test.yaml
相关文章
相关标签/搜索