基于Kubernetes搭建企业级可自动伸缩Jenkins slave集群

背景
贝壳在成立后借助链家雄厚的资本实力快速发展,事业部项目数量不断扩增,项目的开发语言涵盖了java、php、nodejs、golang、C等等类型。公司从一开始使用了jenkins来完成编译部署等一些自动化工作,但是随着项目的越来越多,天然单点受限的jenkins的瓶颈越来越突出。业务方大多数是自己挤出一台空闲机器作为编译机,将一些编译环境部署好后,联系jenkins管理员,将这台编译机作为slave节点加入jenkins集群,目前jenkins-slave的节点已经达到了六十多台物理机。但是从jenkins web 上我们可以清晰的看到,jenkins的队列依然保持在十几个任务积压的状态。为什么六十多个slave节点还是不能够满足当前业务方编译的需求呢?首先,编译环境各个业务方独立使用,切编译环境不统一,这是造成当前状况的根因。这种方式造成了节点空闲不均匀,资源利用率极低。而且一旦slave节点遭到破坏,需要人为的进行修复甚至重建,非常麻烦。我们通过kubernetes集群上部署jenkins,并利用Kubernetes插件来调用k8s集群实现动态的按需扩展jenkins-slave,从而实现有任务时自动增加slave节点,任务结束slave节点自动销毁。对于jenkins来说,slave节点(容器)是临时的,任务一结束就会销毁。

kubernetes集群中安装使用ingress

在Kubernetes中,服务和Pod的IP地址仅可以在集群网络内部使用,对于集群外的应用是不可见的。为了使外部的应用能够访问集群内的服务,在Kubernetes目前提供了以下几种方案:
NodePortLoadBalancerIngress
Ingress由两部分组成:Ingress Controller和Ingress服务:
ingress controller
将新加入的Ingress转化成Nginx的配置文件并使之生效ingress服务
将Nginx的配置抽象成一个Ingress对象,每添加一个新的服务只需写一个新的Ingress的yaml文件即可
Ingress工作原理:
ingress controller通过和kubernetes api交互,动态的去感知集群中ingress规则变化,然后读取它,按照自定义的规则,规则就是写明了哪个域名对应哪个service,生成一段nginx配置,再写到nginx-ingress-control的pod里,这个Ingress controller的pod里运行着一个Nginx服务,控制器会把生成的nginx配置写入/etc/nginx.conf文件中,然后reload一下使配置生效。
以此达到域名分配置和动态更新的问题。
Ingress可以解决什么问题:
动态配置服务
如果按照传统方式, 当新增加一个服务时, 我们可能需要在流量入口加一个反向代理指向我们新的k8s服务. 而如果用了Ingress, 只需要配置好这个服务, 当服务启动时, 会自动注册到Ingress的中, 不需要而外的操作.减少不必要的端口暴露
配置过k8s的都清楚, 第一步是要关闭防火墙的, 主要原因是k8s的很多服务会以NodePort方式映射出去, 这样就相当于给宿主机打了很多孔, 既不安全也不优雅. 而Ingress可以避免这个问题, 除了Ingress自身服务可能需要映射出去, 其他服务都不要用NodePort方式
本文使用的是基于nginx的ingress
Ingress Controller是一个守护进程,部署为Kubernetes Pod,它监视apiserver的/ingresses端点以更新ingress配置,它的工作是执行Ingress的规则。

Kubernetes用户界面Web UI(Dashboard)

介绍
仪表板是基于Web的Kubernetes用户界面。您可以使用仪表板将容器化应用程序部署到Kubernetes集群,对容器化应用程序进行故障排除,以及管理集群资源。您可以使用仪表板来概述群集上运行的应用程序,以及创建或修改单个Kubernetes资源(例如部署,作业,守护进程等)。例如,您可以使用部署向导扩展部署,启动滚动更新,重新启动Pod或部署新应用程序。

在Kubernetes集群中创建CronJob运行自动化任务

创建一个Cron作业
kubectl create -f https://raw.githubusercontent.com/kubernetes/website/master/content/en/examples/application/job/cronjob.yaml
apiVersion: batch/v1beta1
kind: CronJob
metadata:
name: hello
spec:
schedule: “*/1 * * * *”
jobTemplate:
spec:
template:
spec:
containers:
– name: hello
image: busybox
args:
– /bin/sh
– -c
– date; echo Hello from the Kubernetes cluster
restartPolicy: OnFailure

或者通过kubectl run方式创建

Kubernetes secret存储和管理敏感信息

Kubernetes Secret是一个包含少量敏感数据的对象,如密码,令牌或密钥,如果这些信息放到pod或image中,存在很大的安全风险。为了降低密码泄露的风险,可以创建一个secretKeyRef,并在pod定义的时候使用。

Kubernetes集群中部署单实例MySQL

Mysql服务属于有状态的单实例应用程序,因为/var/lib/mysql目录需要持久化存储。
我们在部署mysql服务之前,首先创建了一个查找20G卷的PersistentVolumeClaim,使用PersistentVolumeClaim将其连接到现有PersistentVolume来运行有状态应用程序。