k8s+jenkins+docker部署微服务实现CI/CD

“所爱隔山海,山海不可平,海有舟可渡,山有路可行,此爱翻山海,山海皆可平。”


作为一个想搞开发的,最近似乎都在干运维,不知道有没有跑偏。。。

CI/CD介绍

网上关于CI/CD的文章一大堆,刚开始听着好像好高大尚的感觉,持续集成CI(Continuous Integration),持续交付(Continuous Delivery),持续部署CD(Continuous Deployment),个人认为就是有错尽早发现,添加一点东西就测一下,部一下(部到整体,而不是自己所写的那么一点,因为自己写的肯定没毛病啊。。),看看有无毛病,而不是等着都干完了一起测,哪的多费劲。其实平时好像也是这么开发的啊,但CI/CD还强调自动化部署,这点挺重要的。

  • 持续集成:写了新的代码,添加了新的功能,马上提到仓库测一下,看看和原来的代码会不会有毛病,有毛病就得赶紧治。
  • 持续交付:在持续集成的基础上,将新加的代码部署到接近于生成环境,比如生产环境,测一测。
  • 持续部署:在持续部署的基础上,自动化的进行上面的一些列操作,你只需要提交代码,自动的实现部署,省的自己费半天劲。

k8s搭建

花了一个星期搞了搞k8s,感觉有点复杂,虽然搭建起来了,虽然只学到了皮毛,但是学习过程中找到了很多不错的资源,希望对你们有所帮助。
为什么要用k8s,我现在接触的感觉k8s比较强的一点是,如果你服务有两个副本,其中一个挂了,那么他会帮你自动帮你新建一个副本,保证一直有两个正常的服务在运行,如果挂的服务正常了,多余的将会被删除,个人感觉这个功能非常强悍(匹夫之见)
自己按照网上五花八门的教程,搭了几遍都失败了,不是这个错就是那个错,有的还要,国内要求科学上网,所以只能解决一时的问题,最后找到了大佬搭建的脚本,只需几步便搭建成功了。
搭建之前,如果需要dns,可以先配置一下dns,省的后面麻烦,因为k8s部署后他里面内置的coredns,配置是从宿主机copy过去的,如果你需要用dns先配置一下(云服务器应该不用配,华为云dns是在控制台配置的,自己视情况而定)
教程是使用ansible搭建的k8s
https://github.com/easzlab/kubeasz
首先下载脚本,下载完成执行完命令后,在/etc/ansible下面有个host文件,需要配置一下
对ansible不了解的可以先去了解一下,了解一下就ok,知道配置的意义,已经怎么配。
这是我的配置,仅供参考,ip啥的改成自己的,我是在103机器装的ansible,108为master节点,111和148位node节点,听说k8s后面将不会区分master和node,具体是不是就不得而知了。配置完成后继续执行后面的命令完成安装。

# 'etcd' cluster should have odd member(s) (1,3,5,...)
# variable 'NODE_NAME' is the distinct name of a member in 'etcd' cluster
[etcd]
192.168.1.103 NODE_NAME=etcd1
192.168.1.108 NODE_NAME=etcd2
192.168.1.111 NODE_NAME=etcd3
192.168.1.148 NODE_NAME=etcd4

# master node(s)
[kube-master]
192.168.1.108

# work node(s)
[kube-node]
192.168.1.111
192.168.1.148

# [optional] harbor server, a private docker registry
# 'NEW_INSTALL': 'yes' to install a harbor server; 'no' to integrate with existed one
[harbor]
#192.168.1.8 HARBOR_DOMAIN="harbor.yourdomain.com" NEW_INSTALL=no

# [optional] loadbalance for accessing k8s from outside
[ex-lb]
#192.168.1.6 LB_ROLE=backup EX_APISERVER_VIP=192.168.1.250 EX_APISERVER_PORT=8443
#192.168.1.7 LB_ROLE=master EX_APISERVER_VIP=192.168.1.250 EX_APISERVER_PORT=8443

# [optional] ntp server for the cluster
[chrony]
#192.168.1.1

[all:vars]
# --------- Main Variables ---------------
# Cluster container-runtime supported: docker, containerd
CONTAINER_RUNTIME="docker"

# Network plugins supported: calico, flannel, kube-router, cilium, kube-ovn
CLUSTER_NETWORK="flannel"

# Service proxy mode of kube-proxy: 'iptables' or 'ipvs'
PROXY_MODE="ipvs"

# K8S Service CIDR, not overlap with node(host) networking
SERVICE_CIDR="10.68.0.0/16"

# Cluster CIDR (Pod CIDR), not overlap with node(host) networking
CLUSTER_CIDR="172.20.0.0/16"

# NodePort Range
NODE_PORT_RANGE="20000-40000"

# Cluster DNS Domain
CLUSTER_DNS_DOMAIN="cluster.local."

# -------- Additional Variables (don't change the default value right now) ---
# Binaries Directory
bin_dir="/opt/kube/bin"

# CA and other components cert/key Directory
ca_dir="/etc/kubernetes/ssl"

# Deploy Directory (kubeasz workspace)
base_dir="/etc/ansible"

其他步骤很完善,我这里不在复述,沟通交流那里可以加群,里面大佬挺多的,有问题可以在里面问,也可以留言,我尽量解答。
我是搭建没有问题。。
使用kubectl的一串命令验证一下集群有没有毛病,然后就是搭建可视化界面,
找了一个Kuboard

kubectl apply -f https://kuboard.cn/install-script/kuboard.yaml

执行命令获取token

kubectl -n kube-system describe secret $(kubectl -n kube-system get secret | grep kuboard-user | awk '{print $1}')

k8s+jenkins+docker部署微服务实现CI/CD_第1张图片
访问任意节点的IP:32567即可访问界面,附上大佬的k8s教程,
https://www.kuboard.cn/learning/

k8s+jenkins+docker部署微服务实现CI/CD_第2张图片
k8s就搭建成功了

jenkins

你可以在k8s外搭建jenkins,也可以在k8s上搭建jenkins,搭建在k8s中可以保证其高可用,
外面搭建jenkins很简单,就下载war包java命令运行就行,或者使用docker运行,不在复苏,感兴趣可以去百度,我这里介绍在k8s中搭建jenkins
参考:https://www.jianshu.com/p/0aef1cc27d3d
-首先创建pv用于数剧挂载,pvc.yaml

apiVersion: v1
kind: PersistentVolume
metadata:
  name: opspv
spec:
  capacity:
    storage: 20Gi
  accessModes:
  - ReadWriteMany
  persistentVolumeReclaimPolicy: Delete
  nfs:
    server: 192.168.1.108
    path: /opt/nfs/jenkins

---
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: opspvc
  namespace: kube-ops
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
      storage: 20Gi

注意修改server,其他自己视情况修改。

  • 创建权限,因为 jenkins 后面需要能够动态创建 slave,因此它必须具备一些权限,jenkins-rbac.yaml
apiVersion: v1
kind: ServiceAccount
metadata:
  name: jenkins
  namespace: kube-ops

---

kind: ClusterRole
apiVersion: rbac.authorization.k8s.io/v1
metadata:
  name: jenkins
rules:
  - apiGroups: ["extensions", "apps"]
    resources: ["deployments"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - apiGroups: [""]
    resources: ["services"]
    verbs: ["create", "delete", "get", "list", "watch", "patch", "update"]
  - 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/v1
kind: ClusterRoleBinding
metadata:
  name: jenkins
  namespace: kube-ops
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: jenkins
subjects:
  - kind: ServiceAccount
    name: jenkins
    namespace: kube-ops
  • 部署jenkins-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: jenkins
  namespace: kube-ops
spec:
  template:
    metadata:
      labels:
        app: jenkins
    spec:
      terminationGracePeriodSeconds: 10
      serviceAccount: jenkins
      containers:
      - name: jenkins
        image: jenkins/jenkins:lts
        imagePullPolicy: IfNotPresent
        ports:
        - containerPort: 8080
          name: web
          protocol: TCP
        - containerPort: 50000
          name: agent
          protocol: TCP
        resources:
          limits:
            cpu: 1000m
            memory: 1Gi
          requests:
            cpu: 500m
            memory: 512Mi
        livenessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        readinessProbe:
          httpGet:
            path: /login
            port: 8080
          initialDelaySeconds: 60
          timeoutSeconds: 5
          failureThreshold: 12
        volumeMounts:
        - name: jenkinshome
          subPath: jenkins
          mountPath: /var/jenkins_home
      securityContext:
        fsGroup: 1000
      volumes:
      - name: jenkinshome
        persistentVolumeClaim:
          claimName: opspvc
  selector:
    matchLabels:
      app: jenkins
---
apiVersion: v1
kind: Service
metadata:
  name: jenkins
  namespace: kube-ops
  labels:
    app: jenkins
spec:
  selector:
    app: jenkins
  type: NodePort
  ports:
  - name: web
    port: 8080
    targetPort: web
    nodePort: 30003
  - name: agent
    port: 50000
    targetPort: agent

对于配置的含义,大部分教程里面都有。
然后就是部署

kubectl create -f pvc.yaml
kubectl create -f jenkins-rbac.yaml
kubectl create -f jenkins-deployment.yaml

然后查看状态

kubectl get pods -n kube-ops

在这里插入图片描述
如果ready哪里是0/1标识不正常
执行命令查看状态

kubectl describe pod jenkins-86d6987987-c9m2t -n kube-ops

查看日志

kubectl logs jenkins-86d6987987-c9m2t -n kube-ops

如果报错

touch: cannot touch '/var/jenkins_home/copy_reference_file.log': Permission denied
Can not write to /var/jenkins_home/copy_reference_file.log. Wrong volume permissions?

很明显是nfs挂载文件没有权限,加权限就行

chown -R 1000 /opt/nfs/jenkins

然后新建一个

# 删除原来的
kubectl delete -f jenkins.yaml
# 新建
kubectl create -f jenkins.yaml
# 再查看状态是否正常,不正常继续排查
kubectl get pods -n kube-ops

然后访问任意节点的ip:30003即可访问jenkins
第一次登陆的密码在日志里面可以看见,然后就是安装他推荐的插件,安装完成后就是配置jenkins,在jenkins配置里面配置好你所需的配置,根据自己情况而定,比如我们项目使用grade我就要配置gradle等等。。

CI/CD实现

到这里你已经搭建好k8s集群,配置好jenkins(太费劲了,曾经的我一度想放弃,这什么玩意儿。。。),然后就是新建一个项目
讲一下你们的心路历程(没错就是你们的),你提交代码到仓库,如果是getlab,使用webhook自动触发拉取,不是的话就配置cron表达式定时构建,jenkins拉取到代码后,需要进行构建,测试,打包,一系列操作,这是最基本的,姑且认为这是持续集成,然后需要将镜像push到镜像仓库,然后执行k8s的命令,从镜像仓库拉取镜像,部署服务,这可以叫持续交付,整个过程你干嘛了?你就提交了代码,啥也没干,看能不能部署成功就完事,整体自动化,这可以算是持续部署,整体思路就是这样
理想很丰满,现实很骨感,k8s感觉性能上还有待提升吧,我直接使用docker,可以自行好几个微服务,但使用k8s部署几个既感觉不太行了,而且我们的项目是saas平台的,如果每一套都要搭建一套的话,不太现实,直接使用jenkins+docker也可以实现CI/CD只是没有k8s的诸多优点,视情况而定吧
我举例部署一个eureka
k8s+jenkins+docker部署微服务实现CI/CD_第3张图片
如果用的仓库是getlab的建议使用流水线,直接使用管道Pipeline实现CI/CD,而且有webhook插件可以提供自动触发构建,非常的方便,说实话Pipeline我也不是很会。。群里有人用这个,需要的话可以在群里问,或者@me,我虽然不太会,但我知道有人会啊。。(怎样@me,请看头像),使用Pipeline的话相比比较容易实现,但你的学点Pipeline的知识,反正我是不会。
我们公司用的是华为云的仓库,目前流水线只能使用getlab的仓库,没办法建一个自由项目吧,

  • 配置好代码仓库
    k8s+jenkins+docker部署微服务实现CI/CD_第4张图片
  • 构建
    k8s+jenkins+docker部署微服务实现CI/CD_第5张图片
    我们项目使用gradle,使用maven的自己配置,不会的话网上也有其他文章,用完gradle感觉比maven好,不说别的,构建,测试,打包一个build命令完事,真的太方便了。我去掉了测试,加上测试忒慢了,果断先去掉。
  • push镜像
    k8s+jenkins+docker部署微服务实现CI/CD_第6张图片
    我用的是阿里云的镜像仓库,还有nexus搭建的docker仓库,都一样,你也可以使用dockerhub的想用啥就用啥,私有镜像仓库注意镜像的标签,比如我的:registry.cn-beijing.aliyuncs.com/byb-docker/regist:001,阿里云私有仓库也有介绍,这里使用dockerfile构建镜像 ,Directory for Dockerfile哪里有一个 . 表示在当前工作空间的根目录,也就是项目的根目录
    k8s+jenkins+docker部署微服务实现CI/CD_第7张图片
  • k8s拉取镜像部署微服务,配置文件放在了项目的根目录下,上图的k8s-deployment.yaml
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: admin-regist
  namespace: kube-spring-cloud
  labels:
    app: regist
spec:
  replicas: 1
  selector:
    matchLabels:
      app: regist
  template:
    metadata:
      labels:
        app: regist
      namespace: kube-spring-cloud
    spec:
      containers:
      - name: regist
        image: registry.cn-beijing.aliyuncs.com/byb-docker/regist:001
        imagePullPolicy: Always
      imagePullSecrets:
      - name: aliyun-secret
---
apiVersion: v1
kind: Service
metadata:
  name: admin-regist
  namespace: kube-spring-cloud
spec:
  type: NodePort
  ports:
  - name: web
    port: 38001
    targetPort: 38001
    nodePort: 38001
  selector:
    app: regist

可以通过参数化构建,将名称和镜像以参数传入配置文件,这样所有的服务用一个配置即可,我是用的是nodeport建立与外网的联系,也可以使用ingerss。
如果k8s里面搭建的jenkins直接执行脚本就行,我是在外面不得jenkins所以使用了ssh
k8s+jenkins+docker部署微服务实现CI/CD_第8张图片

echo "---------------delete old deployment-----------------------"
kubectl delete deployment admin-regist -n kube-spring-cloud

echo "---------------delete old service-----------------------"
kubectl delete service admin-regist -n kube-spring-cloud

echo "---------------delete old ingress-----------------------"
kubectl get ingress admin-regist -n kube-spring-cloud

echo "---------------deploy-----------------------"
kubectl create -f  /root/k8s/k8s-deployment.yaml -n kube-spring-cloud

在kube-spring-cloud便可以看见部署的微服务
k8s+jenkins+docker部署微服务实现CI/CD_第9张图片
访问任意节点的ip:380011都可以访问注册中心k8s+jenkins+docker部署微服务实现CI/CD_第10张图片
至此部署完毕!!!

你可能感兴趣的:(k8s)