lsekfe 发表于 2021-9-9 10:14:02

实例学习:持续集成容器化设计实践之系统集成

系统集成

有赞QA创建容器如上图所示,有需求的同学可以在有赞QA平台发起创建业务线容器,后台会调用 k8s api 创建 Jenkins 、 Sonarqube 容器,并返回访问地址。如下图:



有赞QA创建容器1有赞QA-list有赞QA-ingress这里我们使用的k8s客户端是fabric8io/kubernetes-client项目,需要在项目的pom 文件中加入kubernetes-client依赖:
<dependency>
            <groupId>io.fabric8</groupId>
            <artifactId>kubernetes-client</artifactId>
            <version>4.1.0</version>
      </dependency>
Create Deployment
  Deployment 为 Pod 和 Replica Set(下一代Replication Controller)提供声明式更新。只需要在 Deployment 中描述你想要的目标状态是什么,Deployment controller 就会帮你将 Pod 和 ReplicaSet 的实际状态改变到您的目标状态。

  Create Service
  Service 通过 Label Selector 跟服务中的 Pod 绑定,为 Pod 中的服务类应用提供了一个稳定的访问入口。通过使用 Service,我们就可以不用关心这个服务下面的 Pod 的增加和减少、故障重启等,只需通过 Service 就能够访问到对应服务的容器。

  Create Ingress
  Service 虽然可以 LB, NodePort 对外提供服务,但是当集群服务很多的时候,NodePort 方式最大的缺点是会占用很多集群机器的端口,LB 方式最大的缺点则是每个Service一个 LB 又有点浪费和麻烦,并且需要 K8s 之外的支持, 而 Ingress 则只需要一个 NodePort 或者一个 LB 就可以满足所有 service 对外服务的需求。
  注意点:
  K8s 集群中,将图片或是文件上传到文件服务器上,如文件大于1M会报错所以 Ingress 的 Annotations 需要配置下"nginx.ingress.kubernetes.io/proxy-body-size", "600m"
  由于 Jenkins Master 容器起来 K8s 插件配置信息都需要初始化好,就需要知道起来后 Pod Node Ip,这里可以通过 Env 来获取 Pod Node Ip
env:
      - name: MY_POD_IP
          valueFrom:
            fieldRef:
            fieldPath: status.podIP
      status.podIP :pod IP
前端访问 Jenkins Master 时会存在跨域问题,在 Ingress 中,跨域(CORS)的配置如下:
nginx.ingress.kubernetes.io/cors-allow-headers: DNT,X-CustomHeader,Keep-Alive,User-Agent,X-Requested-With,If-Modified-Since,Cache-Control,Content-Type,Authorization
    nginx.ingress.kubernetes.io/cors-allow-methods: PUT, GET, POST, OPTIONS
    nginx.ingress.kubernetes.io/cors-allow-origin: '*'
    nginx.ingress.kubernetes.io/enable-cors: "true"
    nginx.ingress.kubernetes.io/proxy-body-size: 600mK8s Web Terminal
  当需要进入容器内执行一些 shell 命令时,web terminal 可以让我们更方便的访问 container,执行 shell 命令,提高工作效率。如下图:

实现:
 前端用 xterm.js 库,它是模拟一个 terminal 在浏览器中,此时并没有通讯能力。需要在后端搭建 k8s-websocket 服务。前端建立 websocket,连到后台搭建的 k8s-websocket 服务端。服务端会基于 k8s 的 remotecommand 包,建立与 container 的ssh长连接。我们将输入输出写入到 Websocket 流中即可,当浏览器中 terminal 大小改变了,前端应该把最新的 terminal 大小发给服务端,服务端模拟终端也要相应的 resize。
  遇到的问题:
  由于我们使用的 kubernetes-client 当时只提供了 pod 启动时,初始化 terminal 大小的功能,未实现 resize 功能。当浏览器中的 terminal 的大小改变时,由于与初始化时传递的行列数不同,导致显示不全或显示区域过小的问题。在查阅资料的过程中发现 k8s 的 remotecommand 实际上是提供了该功能的(详情可见remotecommand.go)。此文件中,定义 resizeChannel 为4,即将发送的命令 byte 数组的第一位修改为4,就可发送 resize 的相关命令。

  后记
  测试的时候发现 K8s Slave 调度速度比较慢,尤其是多个同类型的 Slave 并行需要等待比较长的时间,上网查询发下默认情况下 Jenkins 保守地生成代理。如果队列中有2个构建,不会立即生成2个执行程序。会产生一个执行器并等待一段时间看第一个执行器有没有被释放,然后再决定产生第二个执行器。以确保产生的每个执行者都得到最大限度的利用。如果要覆盖此行为并立即为队列中的每个构建生成执行程序,可以在 Jenkins Mater 启动时参加一下参数:
  -Dhudson.slaves.NodeProvisioner.initialDelay=0
  -Dhudson.slaves.NodeProvisioner.MARGIN=50
  -Dhudson.slaves.NodeProvisioner.MARGIN0=0.85
  总而言之 K8s 博大精深,在 CI/CD 容器化的道路上还有很多知识点需要去学习。


页: [1]
查看完整版本: 实例学习:持续集成容器化设计实践之系统集成