基于Docker+K8S+GitLab/SVN+Jenkins+Harbor搭建持续集成交付环境的详细教程
亲爱的家人们可以到链接:http://xiazai.jb51.net/202105/yuanma/javayaml_jb51.rar 下载所需要的yaml文件。
1.K8S是什么?K8S全称是Kubernetes,是一个全新的基于容器技术的分布式架构领先方案,基于容器技术,目的是实现资源管理的自动化,以及跨多个数据中心的资源利用率的最大化。
如果我们的系统设计遵循了kubernetes的设计思想,那么传统系统架构中那些和业务没有多大关系的底层代码或功能模块,都可以使用K8S来管理,我们不必再费心于负载均衡的选型和部署实施问题,不必再考虑引入或自己开发一个复杂的服务治理框架,不必再头疼与服务监控和故障处理模块的开发。总之,使用kubernetes提供的解决方案,会大大减少开发成本,同时可以将精力更加集中于业务本身,而且由于kubernetes提供了强大的自动化机制,所以系统后期的运维难度和运维成本大幅降低。
2.为什么要用K8S?Docker 这个新兴的容器化技术当前已经被很多公司所采用,其从单机走向集群已成必然,而云计算的蓬勃发展正在加速这一进程。Kubernetes 作为当前唯一被业界广泛认可和看好的 Docker 分布式系统解决方案。可以预见,在未来几年内,会有大量的新系统选择它,不管是运行在企业本地服务器上还是被托管到公有云上。
3.使用K8S有哪些好处?使用Kubernetes就是在全面部署微服务架构。微服务架构的核心就是将一个巨大的单体应用分解为很多小的互相连接的微服务,一个微服务背后可能有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器在 k8s 平台中有多个实例副本在支撑,副本的数量可能会随着系统的负荷变化而进行调整,内嵌的负载均衡器 在k8s 平台中发挥了重要的作用。微服务架构使得每个服务都可以由专门的开发团队来开发,开发者可以自由选择开发技术,这对于大规模团队来说很有价值。另外,每个微服务独立开发、升级、扩展,使得系统具备很高的稳定性和快速迭代进化能力。
4.环境构成整套环境的搭建包含:Docker环境的搭建、docker-compose环境的搭建、K8S集群的搭建、GitLab代码仓库的搭建、SVN仓库的搭建、Jenkins自动化部署环境的搭建、Harbor私有仓库的搭建。
本文档中,整套环境的搭建包括:
安装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 协议开源。
Docker 可以让开发者打包他们的应用以及依赖包到一个轻量级、可移植的容器中,然后发布到任何流行的 Linux 机器上,也可以实现虚拟化。
本文档基于Docker 19.03.8 版本搭建Docker环境。
在所有服务器上创建install_docker.sh脚本,脚本内容如下所示。
#使用阿里云镜像中心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#启动Dockersystemctl 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-composecurl -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-compose3.查看docker-compose版本
#查看docker-compose版本[root@binghe ~]# docker-compose versiondocker-compose version 1.25.5, build 8a1c60f6docker-py version: 4.1.0CPython version: 3.7.5OpenSSL 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/dockertee /etc/docker/daemon.json <<-’EOF’{ 'registry-mirrors': ['https://zz3sblpi.mirror.aliyuncs.com']}EOFsystemctl daemon-reloadsystemctl restart docker######################配置阿里云镜像加速器结束##########################安装nfs-utilsyum install -y nfs-utils#安装wget软件下载命令yum install -y wget#启动nfs-serversystemctl start nfs-server#配置nfs-server开机自启动systemctl enable nfs-server#关闭防火墙systemctl stop firewalld#取消防火墙开机自启动systemctl disable firewalld#关闭SeLinuxsetenforce 0sed -i 's/SELINUX=enforcing/SELINUX=disabled/g' /etc/selinux/config# 关闭 swapswapoff -ayes | cp /etc/fstab /etc/fstab_bakcat /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.confsed -i 's#^net.bridge.bridge-nf-call-ip6tables.*#net.bridge.bridge-nf-call-ip6tables=1#g' /etc/sysctl.confsed -i 's#^net.bridge.bridge-nf-call-iptables.*#net.bridge.bridge-nf-call-iptables=1#g' /etc/sysctl.confsed -i 's#^net.ipv6.conf.all.disable_ipv6.*#net.ipv6.conf.all.disable_ipv6=1#g' /etc/sysctl.confsed -i 's#^net.ipv6.conf.default.disable_ipv6.*#net.ipv6.conf.default.disable_ipv6=1#g' /etc/sysctl.confsed -i 's#^net.ipv6.conf.lo.disable_ipv6.*#net.ipv6.conf.lo.disable_ipv6=1#g' /etc/sysctl.confsed -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.confecho 'net.bridge.bridge-nf-call-ip6tables = 1' >> /etc/sysctl.confecho 'net.bridge.bridge-nf-call-iptables = 1' >> /etc/sysctl.confecho 'net.ipv6.conf.all.disable_ipv6 = 1' >> /etc/sysctl.confecho 'net.ipv6.conf.default.disable_ipv6 = 1' >> /etc/sysctl.confecho 'net.ipv6.conf.lo.disable_ipv6 = 1' >> /etc/sysctl.confecho '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=Kubernetesbaseurl=http://mirrors.aliyun.com/kubernetes/yum/repos/kubernetes-el7-x86_64enabled=1gpgcheck=0repo_gpgcheck=0gpgkey=http://mirrors.aliyun.com/kubernetes/yum/doc/yum-key.gpg http://mirrors.aliyun.com/kubernetes/yum/doc/rpm-package-key.gpgEOF################# 配置K8S的yum源结束############################## 卸载旧版本K8Syum 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#重启 dockersystemctl restart docker# 将kubelet设置为开机启动并启动kubeletsystemctl 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 为 您想要的 dnsNameexport APISERVER_NAME=k8s.master# Kubernetes 容器组所在的网段,该网段安装完成后,由 kubernetes 创建,事先并不存在于物理网络中export POD_SUBNET=172.18.0.1/16echo '${MASTER_IP} ${APISERVER_NAME}' >> /etc/hosts2.初始化Master节点
在test10服务器上创建init_master.sh脚本文件,文件内容如下所示。
#!/bin/bash# 脚本出错时终止执行set -eif [ ${#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 1fi# 查看完整配置选项 https://godoc.org/k8s.io/kubernetes/cmd/kubeadm/app/apis/kubeadm/v1beta2rm -f ./kubeadm-config.yamlcat <<EOF > ./kubeadm-config.yamlapiVersion: kubeadm.k8s.io/v1beta2kind: ClusterConfigurationkubernetesVersion: v1.18.2imageRepository: registry.cn-hangzhou.aliyuncs.com/google_containerscontrolPlaneEndpoint: '${APISERVER_NAME}:6443'networking: serviceSubnet: '10.96.0.0/16' podSubnet: '${POD_SUBNET}' dnsDomain: 'cluster.local'EOF# kubeadm init# 初始化kebeadmkubeadm init --config=kubeadm-config.yaml --upload-certs# 配置 kubectlrm -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/onpremisesecho '安装calico-3.13.1'rm -f calico-3.13.1.yamlwget https://kuboard.cn/install-script/calico/calico-3.13.1.yamlkubectl apply -f calico-3.13.1.yaml
赋予init_master.sh脚本文件可执行权限并执行脚本。
# 赋予init_master.sh文件可执行权限chmod a+x ./init_master.sh# 运行init_master.sh脚本./init_master.sh3.查看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 wideEvery 2.0s: kubectl get pod -n kube-system -o wide test10: Sun May 10 11:01:32 2020NAME READY STATUS RESTARTS AGE IPNODENOMINATED 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>
(2) 查看 Master 节点初始化结果
# 查看Master节点的初始化结果kubectl get nodes -o wide
具体执行如下所示。
[root@test10 ~]# kubectl get nodes -o wideNAMESTATUS ROLES AGE VERSION INTERNAL-IP EXTERNAL-IP OS-IMAGEKERNEL-VERSION CONTAINER-RUNTIMEtest10 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-commandW0510 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 节点的内网 IPexport MASTER_IP=192.168.0.10# 替换 k8s.master 为初始化 master 节点时所使用的 APISERVER_NAMEexport APISERVER_NAME=k8s.masterecho '${MASTER_IP} ${APISERVER_NAME}' >> /etc/hosts# 替换为 master 节点上 kubeadm token create 命令输出的joinkubeadm 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 nodesNAMESTATUS ROLES AGE VERSIONtest10 Ready master 20m v1.18.2test11 Ready <none> 2m46s v1.18.2test12 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-namespaceK8S安装ingress-nginx
作为反向代理将外部流量导入集群内部,将 Kubernetes 内部的 Service 暴露给外部,在 Ingress 对象中通过域名匹配 Service,这样就可以直接通过域名访问到集群内部的服务了。相对于 traefik 来说,nginx-ingress 性能更加优秀。
注意:在Master节点(test10服务器上执行)
1.创建ingress-nginx命名空间创建ingress-nginx-namespace.yaml文件,主要的作用是创建ingress-nginx命名空间,文件内容如下所示。
apiVersion: v1kind: Namespacemetadata: name: ingress-nginx labels: name: ingress-nginx
执行如下命令创建ingress-nginx命名空间。
kubectl apply -f ingress-nginx-namespace.yaml2.安装ingress controller
创建ingress-nginx-mandatory.yaml文件,主要的作用是安装ingress-nginx。文件内容如下所示。
apiVersion: v1kind: Namespacemetadata: name: ingress-nginx---apiVersion: apps/v1kind: Deploymentmetadata: name: default-http-backend labels: app.kubernetes.io/name: default-http-backend app.kubernetes.io/part-of: ingress-nginx namespace: ingress-nginxspec: 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-backendapp.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: v1kind: Servicemetadata: name: default-http-backend namespace: ingress-nginx labels: app.kubernetes.io/name: default-http-backend app.kubernetes.io/part-of: ingress-nginxspec: ports: - port: 80 targetPort: 8080 selector: app.kubernetes.io/name: default-http-backend app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata: name: nginx-configuration namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata: name: tcp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx---kind: ConfigMapapiVersion: v1metadata: name: udp-services namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginx---apiVersion: v1kind: ServiceAccountmetadata: 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/v1beta1kind: ClusterRolemetadata: name: nginx-ingress-clusterrole labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxrules: - 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/v1beta1kind: Rolemetadata: name: nginx-ingress-role namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxrules: - 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/v1beta1kind: RoleBindingmetadata: name: nginx-ingress-role-nisa-binding namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: nginx-ingress-rolesubjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx---apiVersion: rbac.authorization.k8s.io/v1beta1kind: ClusterRoleBindingmetadata: name: nginx-ingress-clusterrole-nisa-binding labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxroleRef: apiGroup: rbac.authorization.k8s.io kind: ClusterRole name: nginx-ingress-clusterrolesubjects: - kind: ServiceAccount name: nginx-ingress-serviceaccount namespace: ingress-nginx---apiVersion: apps/v1kind: Deploymentmetadata: name: nginx-ingress-controller namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxspec: 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-nginxapp.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.yaml3.安装K8S SVC:ingress-nginx
主要是用来用于暴露pod:nginx-ingress-controller。
创建service-nodeport.yaml文件,文件内容如下所示。
apiVersion: v1kind: Servicemetadata: name: ingress-nginx namespace: ingress-nginx labels: app.kubernetes.io/name: ingress-nginx app.kubernetes.io/part-of: ingress-nginxspec: 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.yaml4.访问K8S SVC:ingress-nginx
查看ingress-nginx命名空间的部署情况,如下所示。
[root@test10 k8s]# kubectl get pod -n ingress-nginxNAMEREADY STATUS RESTARTS AGEdefault-http-backend-796ddcd9b-vfmgn1/1 Running 1 10hnginx-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 TYPECLUSTER-IP EXTERNAL-IP PORT(S) AGEdefault-http-backend ClusterIP 10.96.247.2 <none>80/TCP 7m3singress-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: v1kind: Namespacemetadata: name: k8s-ops labels: name: k8s-ops
执行如下命令创建命名空间。
kubectl apply -f k8s-ops-namespace.yaml 2.安装gitlab-redis
创建gitlab-redis.yaml文件,文件的内容如下所示。
apiVersion: apps/v1kind: Deploymentmetadata: name: redis namespace: k8s-ops labels: name: redisspec: selector: matchLabels: name: redis template: metadata: name: redis labels:name: redis spec: containers: - name: redisimage: sameersbn/redisimagePullPolicy: IfNotPresentports:- name: redis containerPort: 6379volumeMounts:- mountPath: /var/lib/redis name: datalivenessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 30 timeoutSeconds: 5readinessProbe: exec: command: - redis-cli - ping initialDelaySeconds: 10 timeoutSeconds: 5 volumes: - name: datahostPath: path: /data1/docker/xinsrv/redis---apiVersion: v1kind: Servicemetadata: name: redis namespace: k8s-ops labels: name: redisspec: 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/v1kind: Deploymentmetadata: name: postgresql namespace: k8s-ops labels: name: postgresqlspec: selector: matchLabels: name: postgresql template: metadata: name: postgresql labels:name: postgresql spec: containers: - name: postgresqlimage: sameersbn/postgresqlimagePullPolicy: IfNotPresentenv:- name: DB_USER value: gitlab- name: DB_PASS value: passw0rd- name: DB_NAME value: gitlab_production- name: DB_EXTENSION value: pg_trgmports:- name: postgres containerPort: 5432volumeMounts:- mountPath: /var/lib/postgresql name: datalivenessProbe: exec: command: - pg_isready - -h - localhost - -U - postgres initialDelaySeconds: 30 timeoutSeconds: 5readinessProbe: exec: command: - pg_isready - -h - localhost - -U - postgres initialDelaySeconds: 5 timeoutSeconds: 1 volumes: - name: datahostPath: path: /data1/docker/xinsrv/postgresql---apiVersion: v1kind: Servicemetadata: name: postgresql namespace: k8s-ops labels: name: postgresqlspec: 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.yaml4.安装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: v1kind: Secretmetadata: namespace: k8s-ops name: git-user-passtype: Opaquedata: username: YWRtaW4= password: YWRtaW4uMTIzMQ==
执行配置文件的内容,如下所示。
kubectl create -f ./secret-gitlab.yaml
(2)安装GitLab
创建gitlab.yaml文件,文件的内容如下所示。
apiVersion: apps/v1kind: Deploymentmetadata: name: gitlab namespace: k8s-ops labels: name: gitlabspec: selector: matchLabels: name: gitlab template: metadata: name: gitlab labels:name: gitlab spec: containers: - name: gitlabimage: sameersbn/gitlab:12.1.6imagePullPolicy: IfNotPresentenv:- 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: 22volumeMounts:- mountPath: /home/git/data name: datalivenessProbe: httpGet: path: / port: 80 initialDelaySeconds: 180 timeoutSeconds: 5readinessProbe: httpGet: path: / port: 80 initialDelaySeconds: 5 timeoutSeconds: 1 volumes: - name: datahostPath: path: /data1/docker/xinsrv/gitlab---apiVersion: v1kind: Servicemetadata: name: gitlab namespace: k8s-ops labels: name: gitlabspec: ports: - name: http port: 80 nodePort: 30088 - name: ssh port: 22 targetPort: ssh nodePort: 30022 type: NodePort selector: name: gitlab---apiVersion: extensions/v1beta1kind: Ingressmetadata: name: gitlab namespace: k8s-ops annotations: kubernetes.io/ingress.class: traefikspec: 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.yaml5.安装完成
查看k8s-ops命名空间部署情况,如下所示。
[root@test10 k8s]# kubectl get pod -n k8s-opsNAME READY STATUS RESTARTS AGEgitlab-7b459db47c-5vk6t 0/1 Running 0 11spostgresql-79567459d7-x52vx 1/1 Running 0 30mredis-67f4cdc96c-h5ckz1/1 Running 1 10h
也可以使用如下命令查看。
[root@test10 k8s]# kubectl get pod --namespace=k8s-opsNAME READY STATUS RESTARTS AGEgitlab-7b459db47c-5vk6t 0/1 Running 0 36spostgresql-79567459d7-x52vx 1/1 Running 0 30mredis-67f4cdc96c-h5ckz1/1 Running 1 10h
二者效果一样。
接下来,查看GitLab的端口映射,如下所示。
[root@test10 k8s]# kubectl get svc -n k8s-opsNAME TYPECLUSTER-IP EXTERNAL-IP PORT(S) AGEgitlab NodePort 10.96.153.100 <none>80:30088/TCP,22:30022/TCP 2m42spostgresql ClusterIP 10.96.203.119 <none>5432/TCP 32mredisClusterIP 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:WindowsSystem32driversetc
接下来,就可以在浏览器中通过链接: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.tgz2.解压Harbor的安装包
tar -zxvf harbor-offline-installer-v1.10.2.tgz
解压成功后,会在服务器当前目录生成一个harbor目录。
3.配置Harbor注意:这里,我将Harbor的端口修改成了1180,如果不修改Harbor的端口,默认的端口是80。
(1)修改harbor.yml文件
cd harborvim harbor.yml
修改的配置项如下所示。
hostname: 192.168.0.10http: port: 1180harbor_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 harborvim harbor.yml
修改的配置项如下所示。
hostname: 192.168.0.10http: port: 1180harbor_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/registryvim config.yml
修改的配置项如下所示。
realm: http://192.168.0.10:1180/service/token
(4)重启Docker
systemctl daemon-reloadsystemctl restart docker.service
(5)重启Harbor
[root@binghe harbor]# docker-compose downStopping harbor-log ... doneRemoving nginx ... doneRemoving harbor-portal ... doneRemoving harbor-jobservice ... doneRemoving harbor-core ... doneRemoving redis ... doneRemoving registry ... doneRemoving registryctl ... doneRemoving harbor-db ... doneRemoving harbor-log... doneRemoving network harbor_harbor [root@binghe harbor]# ./prepareprepare base dir is set to /mnt/harborClearing the configuration file: /config/log/logrotate.confClearing the configuration file: /config/nginx/nginx.confClearing the configuration file: /config/core/envClearing the configuration file: /config/core/app.confClearing the configuration file: /config/registry/root.crtClearing the configuration file: /config/registry/config.ymlClearing the configuration file: /config/registryctl/envClearing the configuration file: /config/registryctl/config.ymlClearing the configuration file: /config/db/envClearing the configuration file: /config/jobservice/envClearing the configuration file: /config/jobservice/config.ymlGenerated configuration file: /config/log/logrotate.confGenerated configuration file: /config/nginx/nginx.confGenerated configuration file: /config/core/envGenerated configuration file: /config/core/app.confGenerated configuration file: /config/registry/config.ymlGenerated configuration file: /config/registryctl/envGenerated configuration file: /config/db/envGenerated configuration file: /config/jobservice/envGenerated configuration file: /config/jobservice/config.ymlloaded secret from file: /secret/keys/secretkeyGenerated configuration file: /compose_location/docker-compose.ymlClean up the input dir [root@binghe harbor]# docker-compose up -dCreating network 'harbor_harbor' with the default driverCreating harbor-log ... doneCreating harbor-db ... doneCreating redis ... doneCreating registry ... doneCreating registryctl ... doneCreating harbor-core ... doneCreating harbor-jobservice ... doneCreating harbor-portal ... doneCreating nginx ... done [root@binghe harbor]# docker ps -aCONTAINER IDIMAGE 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 -ysystemctl start nfs-serversystemctl enable nfs-server2.创建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-serversystemctl reload nfs-server
在K8S集群中任意一个节点上使用如下命令进行验证:
#查看nfs系统的目录权限showmount -e NFS_IP
如果能够看到 /opt/nfs/jenkins-data 就表示 ok 了。
具体如下所示。
[root@test10 ~]# showmount -e 192.168.0.10Export list for 192.168.0.10:/opt/nfs/jenkins-data 192.168.175.0/24[root@test11 ~]# showmount -e 192.168.0.10Export list for 192.168.0.10:/opt/nfs/jenkins-data 192.168.175.0/243.创建PV
Jenkins 其实只要加载对应的目录就可以读取之前的数据,但是由于 deployment 无法定义存储卷,因此我们只能使用 StatefulSet。
首先创建 pv,pv 是给 StatefulSet 使用的,每次 StatefulSet 启动都会通过 volumeClaimTemplates 这个模板去创建 pvc,因此必须得有 pv,才能供 pvc 绑定。
创建jenkins-pv.yaml文件,文件内容如下所示。
apiVersion: v1kind: PersistentVolumemetadata: name: jenkinsspec: 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: v1kind: ServiceAccountmetadata: name: jenkins---kind: RoleapiVersion: rbac.authorization.k8s.io/v1beta1metadata: name: jenkinsrules: - 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/v1beta1kind: RoleBindingmetadata: name: jenkinsroleRef: apiGroup: rbac.authorization.k8s.io kind: Role name: jenkinssubjects: - 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/v1kind: StatefulSetmetadata: name: jenkins labels: name: jenkinsspec: 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: v1kind: Servicemetadata: name: jenkinsspec: # 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/v1beta1kind: Ingressmetadata: name: jenkinsspec: 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:WindowsSystem32driversetc
接下来,就可以在浏览器中通过链接:http://jekins.binghe.com:31888 来访问Jekins了。
物理机安装SVNApache 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/svnmkdir -p /data/svn #初始化svnsvnserve -d -r /data/svn#创建代码仓库svnadmin create /data/svn/test3.配置SVN
mkdir /data/svn/confcp /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,&joeSuperAdmin = adminbinghe = 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 = sallyssecretadmin = admin123binghe = 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 = noneauth-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’? y4.启动SVN服务
(1)创建svnserve.service服务
创建svnserve.service文件
vim /usr/lib/systemd/system/svnserve.service
文件的内
相关文章: