美文网首页Kubernetes
六、Kubernetes CICD之旅

六、Kubernetes CICD之旅

作者: Suny____ | 来源:发表于2020-04-20 22:19 被阅读0次

    1、概述

    ​ 在前面的章节中我们已经演示了不少案例与各种组件的介绍与使用,我们也实战搭建了项目。通过K8S的帮助,我们可以很方便的部署项目,但还不是很完美。如果我们部署的是自己的项目,而我们的项目又是要经常改动的,这就意味着我们需要经常进行 打包、上传、重启、测试等,这些都是重复性的工作,一次两次还好,次数多了也烦人。所以下面要讲的 CI/CD 就是来帮我们解放双手,摆脱这些重复性的工作!

    1.1、CI/CD是什么?

    • CI/CD 是一种通过在应用开发阶段引入 自动化 来频繁向客户交付应用的方法。

    • CI/CD 的核心概念是持续集成、持续交付和持续部署。

    • CI/CD 主要针对在集成新代码时所引发的问题。

    • CI/CD 可让持续自动化和持续监控贯穿于应用的整个生命周期(从集成和测试阶段,到交付和部署)。

    • 这些关联的事务通常被统称为 “CI/CD 管道”,由开发和运维团队以敏捷方式协同支持。

    1.2、 CI 和 CD 有什么区别?

    • CI/CD 中的 “CI” 始终指持续集成,它属于开发人员的自动化流程。
    • 成功的 CI 意味着应用代码的新更改会定期构建、测试并合并到共享存储库中。
    • 该解决方案可以解决在一次开发中有太多应用分支,从而导致相互冲突的问题。
    • CI/CD 中的“CD”指的是持续交付和/或持续部署,这些相关概念有时会交叉使用。
    • 两者都事关管道后续阶段的自动化,但它们有时也会单独使用,用于说明自动化程度。

    更多概念可以到 红帽 看官方介绍: https://www.redhat.com/zh/topics/devops/what-is-ci-cd

    下面这张图就相对完整的介绍了本章节要进行的工作:

    • 开发手动提交代码到git仓库
    • 自动拉取代码
    • 自动进行Maven构建、代码检查、单元测试
      • 这个步骤在生产环境一般不会做自动构建,因为公司可能进行代码检查,确认无误后由QA手动进行部署
      • 本章节只进行Maven构建,代码检查和单元测试需要集成其他组件,读者可以自行了解
    • 自动build镜像、上传镜像至镜像仓库
    • 自动拉取镜像进行部署
    image.png

    2、环境准备

    • 准备一个项目
    • 准备一个 Git 仓库
      • 可以是自己搭建的也可以是GitHub或者码云都可以
    • 准备一个镜像仓库
      • 这里使用阿里云的镜像仓库
    • 准备一个安装了 Kubernetes 的机器
      • 直接使用之前搭建好的 K8S 集群
      • 安装 Java
      • 安装 Maven
      • 安装 Git
      • 安装 Jenkins
        • Jenkins必须在k8s集群中,因为后面需要在jenkins的目录下创建文件执行K8S的命令
        • 其他环境在这台机器安装的原因在于Jenkins需要依赖这些环境

    2.1、环境搭建

    • 安装 Java

      • 下载 Java 安装包上传并解压到服务器

      • 配置环境变量

        • 采用 profile.d 目录设置环境变量,好处在于想删掉该环境可以直接删除文件,无需修改配置文件
        # 1、配置环境变量
        [root@worker01-kubeadm-k8s profile.d]# pwd
        /etc/profile.d
        [root@worker01-kubeadm-k8s profile.d]# vi java.sh
        
        export JAVA_HOME=/root/develop/java/jdk1.8.0_181
        export JRE_HOM=$JAVA_HOME/jre
        export CLASSPATH=$JAVA_HOME/lib/
        
        export PATH=$PATH:$JAVA_HOME/bin
        
        # 2、赋予权限
        [root@worker01-kubeadm-k8s profile.d]# chmod 755 ./java.sh
        
        # 3、编译文件
        [root@worker01-kubeadm-k8s profile.d]# source ./java.sh
        
        # 4、测试
        [root@worker01-kubeadm-k8s profile.d]# java -version
        java version "1.8.0_181"
        Java(TM) SE Runtime Environment (build 1.8.0_181-b13)
        Java HotSpot(TM) 64-Bit Server VM (build 25.181-b13, mixed mode)
        
    • 安装 Maven

      • 下载 Maven 安装包上传并解压到服务器

      • 配置环境变量

        # 1、配置环境变量
        [root@worker01-kubeadm-k8s profile.d]# vi mvn.sh
        
        export MAVEN_HOME=/root/develop/maven/apache-maven-3.6.3
        export PATH=$PATH:$MAVEN_HOME/bin
        
        # 2、赋予权限
        [root@worker01-kubeadm-k8s profile.d]# chmod 755 ./mvn.sh
        
        # 3、编译文件
        [root@worker01-kubeadm-k8s profile.d]# source ./mvn.sh
        
        # 4、测试
        [root@worker01-kubeadm-k8s profile.d]# mvn -v
        Apache Maven 3.6.3 (cecedd343002696d0abb50b32b541b8a6ba2883f)
        Maven home: /root/develop/maven/apache-maven-3.6.3
        Java version: 1.8.0_181, vendor: Oracle Corporation, runtime: /root/develop/java/jdk1.8.0_181/jre
        Default locale: en_US, platform encoding: UTF-8
        OS name: "linux", version: "3.10.0-1062.18.1.el7.x86_64", arch: "amd64", family: "unix"
        
      • 配置本地仓库路径、阿里云镜像

        # 1、本地仓库路径,改成自己的
        <localRepository>/root/develop/maven/repo</localRepository>
            
        # 2、配置阿里云镜像
        <mirror>
            <id>aliyunmaven</id>
            <mirrorOf>*</mirrorOf>
            <name>阿里云公共仓库</name>
            <url>https://maven.aliyun.com/repository/public</url>
        </mirror>
        
    • 安装 Git

      • 下载安装

        # 1、安装 Git
        [root@worker01-kubeadm-k8s ~]# yum install git
        
        # 2、测试
        [root@worker01-kubeadm-k8s ~]# git --version
        git version 1.8.3.1
        
      
      + 配置账号
      
        ```ruby
        [root@worker01-kubeadm-k8s ~]# git config --global user.name "Sunny"
        [root@worker01-kubeadm-k8s ~]# git config --global user.email "yzy_zhaoyang@163.com"
        [root@worker01-kubeadm-k8s ~]# ssh-keygen -t rsa -C "yzy_zhaoyang@163.com"
        
        # 出现需要输入密码的地方可以设置自己的ssh密码, 也可以直接回车表示不设置密码
        Generating public/private rsa key pair.
        Enter file in which to save the key (/root/.ssh/id_rsa):
        Enter passphrase (empty for no passphrase):
        Enter same passphrase again:
        Your identification has been saved in /root/.ssh/id_rsa.
                
        # 这里的路径文件指的是公钥,我们要打开这个文件将公钥填到 Git 仓库
        Your public key has been saved in /root/.ssh/id_rsa.pub.
        The key fingerprint is:
        ae:ca:9b:84:t5:3e:b7:as:98:51:d1:77:31:34:0e:tt yzy_zhaoyang@163.com
        The key's randomart image is:
        +--[ RSA 2048]----+
        |  ...o           |
        | . E. o          |
        |o .. o .         |
        |.o  . o          |
        |.  .    S        |
        |  ..   .         |
        | ....   .        |
        |.o=+.. .         |
        |.=+o*o.          |
        +-----------------+
      

    2.2、准备项目

    image.png
    • 上传到 Git 仓库

      image.png

    2.3、搭建 Jenkins

    • 前情提要

      Jenkins 官网:https://jenkins.io/

      入门指南:https://jenkins.io/zh/doc/pipeline/tour/getting-started/

      • 下载并上传 Jenkins 到服务器

      • 启动 Jenkins

        #以后台启动方式启动 Jenkins,设置端口为 8088
        [root@worker01-kubeadm-k8s jenkins]#  [root@sunny jenkins]# nohup java -jar jenkins.war --httpPort=8088 &
        
        # 查看启动日志
        [root@worker01-kubeadm-k8s jenkins]#  tail -f nohup.out
        Running from: /root/jenkins/jenkins.war
        webroot: $user.home/.jenkins
        2020-04-16 15:20:49.849+0000 [id=1]     INFO    org.eclipse.jetty.util.log.Log#initialized: Logging initialized @753ms to org.eclipse.jetty.util.log.JavaUtilLog
        
        # ... 省略 ...
        
        *************************************************************
        *************************************************************
        *************************************************************
        
        Jenkins initial setup is required. An admin user has been created and a password generated.
        Please use the following password to proceed to installation:
        
        # 这是进入 Jenkins 管理页面所需要的密码
        f9025b52a4824997b09cb62d5c89f7cc
        
        # 这是存放密码的文件
        This may also be found at: /root/.jenkins/secrets/initialAdminPassword
        
        *************************************************************
        *************************************************************
        *************************************************************
        
    image.png

    2.3.1、配置 Jenkins

    • 安装推荐的插件

      image.png

    等待安装即可,需要的时间比较久

    也可以先点推荐安装,然后刷新页面选择跳过安装,之后手动下载插件安装,这样会更快

    如果跳过,先截图保存一下推荐插件的列表,后面手动安装要去搜索的

    • 创建用户

      username: sunny
      password: sunny
      
      image.png
    • 安装插件

      这里说的是推荐插件安装完后还需要安装的一些插件,如果你选择了跳过安装,那要先记好它推荐了哪些插件,有些插件是必要的

      • 中文插件
        • Locale
        • Localization: Chinese (Simplified)
        • Localization Support
      • git插件
        • GitHub / Gitee
        • Gitlab Hook
        • Gitlab Plugin
    • 配置Java、Maven、Git路径

      • Manage Jenkins — Global Tool Configuration

      • 配置机器中的路径

        image.png

    2.3.2、镜像仓库与Kubernetes集群

    • 镜像仓库采用国内的阿里云镜像仓库

    • Kubernetes 集群直接采用我们之前章节中已经搭建好的 Kubernetes 集群即可。

    3、Pipeline任务

    我们一个步骤一个步骤的演示,从最开始的拉取代码,慢慢延伸到最终的CICD!

    3.1 拉取项目代码

    Jenkins要实现自动拉取代码,需要安装Git相关插件,以及要到Git仓库去进行一些配置,插件之前都已经安装了,接下来就演示一下Jenkins的配置。

    • 创建任务

      image.png
    • 创建流水线任务

      image.png
    • 编写pipeline

      注意这里要勾选上,保存webhook的链接,后面配置自动拉取时要用到

      image.png
    image.png
    node {
       // Pull
       stage('Pull') { //stage表示一个任务
          //这里是任务的内容
          //因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码
          git 'https://gitee.com/suny95/springboot-demo-k8s.git'
       }
    }
    

    配置完成后点击保存

    • 构建任务

      image.png

    构建完成后会显示绿色,构建失败是红色,可以去查看错误信息

    image.png

    这里是Jenkins工作目录:/root/.jenkins/workspace目录

    代码是拉取到这个目录下的

    # Jenkins工作目录
    [root@worker01-kubeadm-k8s workspace]# pwd
    /root/.jenkins/workspace
    [root@worker01-kubeadm-k8s workspace]# ll
    total 0
    drwxr-xr-x. 4 root root 62 Apr 18 14:37 springboot-k8s-task
    
    # 新建的任务目录
    [root@worker01-kubeadm-k8s workspace]# cd springboot-k8s-task/
    [root@worker01-kubeadm-k8s springboot-k8s-task]# ll
    total 4
    -rw-r--r--. 1 root root 1277 Apr 18 14:37 pom.xml
    drwxr-xr-x. 3 root root   18 Apr 18 14:37 src
    

    3.2 Maven自动编译

    修改之前编写好的流水线任务,增加一个Stage用来做Maven自动编译

    • 修改Pipeline脚本内容

      node {
         // Pull
         stage('Pull') { //stage表示一个任务
            //这里是任务的内容
            //因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码
            git 'https://gitee.com/suny95/springboot-demo-k8s.git'
         }
         
         //Maven
         stage('AutoCompile') {
             sh "mvn clean package"
         }
      }
      
    • 构建任务

      开始构建任务后,可以通过Console Output监控当前任务执行情况

      image.png
    image.png
    # 再次查看目录,发现已经成功编译出 target 目录了
    [root@worker01-kubeadm-k8s springboot-k8s-task]# ll
    total 4
    -rw-r--r--. 1 root root 1277 Apr 18 14:37 pom.xml
    drwxr-xr-x. 3 root root   18 Apr 18 14:37 src
    drwxr-xr-x. 6 root root  181 Apr 18 14:56 target
    

    到这里为止,手动构建的方式已经完成, 下面将要开始配置自动构建

    3.3 Git Push 触发 Jenkins 自动构建

    当用户进行git push提交代码到 GitHub / Git EE 时,能够通知 jenkins 自动构建

    注意: Jenkins 的 ip 一定要是 Git EE 能够访问到的地址

    我这里由于是本地搭建的虚拟机,就不做演示了,百度搜一下有很多的教程可以参考

    3.4 build 与 push 镜像

    经过前面的演示,现在已经可以获取到代码,并且用maven进行构建了,最终拿到一个target/xxx.jar

    现在我们要演示Docker的镜像构建与Push镜像到镜像仓库!

    • 准备执行文件

      • 到 Jenkins 的工作目录

        • cd /root/.jenkins/workspace
      • 创建 .sh 执行文件

        # 创建专门存放脚本的目录
        [root@worker01-kubeadm-k8s workspace]# mkdir scripts
        [root@worker01-kubeadm-k8s workspace]# cd scripts/
        
        # 编写执行文件
        [root@worker01-kubeadm-k8s scripts]# vi springboot-demo-k8s-build-image.sh
        
        # ================== 执行文件内容 ======================
        # 进入到springboot-k8s-task目录
        cd ../springboot-k8s-task
        
        # 编写Dockerfile文件, 这里也可以先在项目里写好
        
        cat <<EOF > Dockerfile
        FROM openjdk:8-jre-alpine
        COPY target/springboot-demo-0.0.1-SNAPSHOT.jar /springboot-demo.jar
        ENTRYPOINT ["java","-jar","/springboot-demo.jar"]
        EOF
        
        echo "Dockerfile created successfully!"
        
        # 基于指定目录下的Dockerfile构建镜像
        # 注意 zhao_yang 这个命名空间是公开的,如果是私有的,还需要配置K8S的认证
        docker build -t registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0 .
        
        # 登录docker账号
        # 注意: 如果密码不能开放的话,可以先手动在机器上登录一次,那这里就无需再次登录了
        docker login --username=用户名 --password=密码 registry.cn-shanghai.aliyuncs.com
        
        # push镜像
        docker push registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0
        # ================== 执行文件内容 ======================
        
        # 增加执行权限
        [root@worker01-kubeadm-k8s scripts]# chmod +x ./springboot-demo-k8s-build-image.sh
        
    • 修改任务的Pipeline脚本

      node {
         // Pull
         stage('Pull') { //stage表示一个任务
            //这里是任务的内容
            //因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码
            git 'https://gitee.com/suny95/springboot-demo-k8s.git'
         }
         
         //Maven
         stage('AutoCompile') {
             sh "mvn clean package"
         }
         
         //增加任务,执行脚本文件
         stage('Build And Push Image') { 
            sh "/root/.jenkins/workspace/scripts/springboot-demo-k8s-build-image.sh"
         }
      }
      
    • 构建任务,监控输出

      image.png image.png

    build 镜像与 push 镜像至镜像仓库 都已成功!!!

    3.1.5 Kubernetes 拉取镜像运行

    这个过程需要提前准备的也就是image镜像和ingress,image刚才我们都已经上传到阿里云镜像仓库了,ingress我们在之前也准备过了,如果没有ingress环境的,可以去看前面的 kubernetes 网络模型 ,里面有安装ingress的流程!

    • 编写 YAML 文件

      YAML文件可以写到项目中,也可以直接在机器上创建

      • vi /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml
      # 以Deployment部署Pod
      apiVersion: apps/v1
      kind: Deployment
      metadata: 
        name: springboot-demo-k8s
      spec: 
        selector: 
          matchLabels: 
            app: springboot-demo-k8s
        replicas: 1
        template: 
          metadata:
            labels: 
              app: springboot-demo-k8s
          spec: 
            containers: 
            - name: springboot-demo-k8s
              image: registry.cn-hangzhou.aliyuncs.com/zhao_yang/springboot-demo-k8s:v1.0
              ports: 
              - containerPort: 8080
      ---
      # 创建Pod的Service
      apiVersion: v1
      kind: Service
      metadata: 
        name: springboot-demo-k8s
      spec: 
        ports: 
        - port: 80
          protocol: TCP
          targetPort: 8080
        selector: 
          app: springboot-demo-k8s
      ---
      # 创建Ingress,定义访问规则
      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata: 
        name: springboot-demo-k8s
      spec: 
        rules: 
        - host: springboot.sunny.com
          http: 
            paths: 
            - path: /
              backend: 
                serviceName: springboot-demo-k8s
                servicePort: 80
      
    • 编写 .sh 执行文件

      [root@worker01-kubeadm-k8s scripts]# vi /root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh
      
      # ================== YAML文件内容 ============
      kubectl delete -f /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml
      kubectl apply -f /root/.jenkins/workspace/scripts/springboot-demo-k8s.yaml
      echo "k8s deploy success!"
      # ================== YAML文件内容 ============
      
      [root@worker01-kubeadm-k8s scripts]# chmod +x k8s-deploy-springboot-demo.sh
      
    • 修改Pipeline

      node {
         // Pull
         stage('Pull') { //stage表示一个任务
            //这里是任务的内容
            //因为我们的机器已经生成了秘钥且与Gieee进行了绑定,所以无需输入账号密码就可以进行拉取代码
            git 'https://gitee.com/suny95/springboot-demo-k8s.git'
         }
         
         //Maven
         stage('AutoCompile') {
             sh "mvn clean package"
         }
         
         //build push
         stage('Build And Push Image') { 
            sh "/root/.jenkins/workspace/scripts/springboot-demo-k8s-build-image.sh"
         }
         
         //k8s
         stage('K8S Deploy') { 
            sh "/root/.jenkins/workspace/scripts/k8s-deploy-springboot-demo.sh"
         }
      }
      
    • 构建任务并监控输出

      image.png

    发现出现异常了,这个问题其实是因为我们选择的机器在 K8S 集群中不是 Master 节点,它没有执行kubectl 命令的权限,我们需要配置一下!

    • 复制 .kube 文件目录到 Worker01 节点

      [root@master-kubeadm-k8s .kube]# pwd
      /root/.kube
      
      # 这里的 config 是权限认证的文件
      [root@master-kubeadm-k8s .kube]# ll
      total 12
      drwxr-xr-x. 3 root root   23 Mar 24 14:32 cache
      -rw-------. 1 root root 5454 Mar 24 14:30 config
      drwxr-xr-x. 3 root root 4096 Apr  4 08:59 http-cache
      
      image.png
    ```ruby
    [root@worker01-kubeadm-k8s ~]# mkdir .kube
    [root@worker01-kubeadm-k8s ~]# cd .kube/
    
    # 将 Master 节点中config文件内容复制进去即可
    [root@worker01-kubeadm-k8s .kube]# vi config
    [root@worker01-kubeadm-k8s .kube]# ll
    total 8
    -rw-r--r--. 1 root root 5454 Apr 19 09:45 config
    ```
    
    • 重新构建并监控

      image.png
    • 测试

      # pod 运行成功
      [root@worker01-kubeadm-k8s scripts]# kubectl get pods
      NAME                                   READY   STATUS    RESTARTS   AGE
      springboot-demo-k8s-79c867fd58-ts2f7   1/1     Running   0          5m53s
      
      # service 也创建成功
      [root@worker01-kubeadm-k8s scripts]# kubectl get svc
      NAME                  TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
      kubernetes            ClusterIP   10.96.0.1       <none>        443/TCP   25d
      springboot-demo-k8s   ClusterIP   10.99.138.171   <none>        80/TCP    6m46s
      
      # ingress 也在
      [root@worker01-kubeadm-k8s scripts]# kubectl get ingress
      NAME                  HOSTS                ADDRESS   PORTS   AGE
      springboot-demo-k8s   springboot.sunny.com             80      10m
      
      # 访问 Service IP + 路径, 成功访问到结果
      [root@worker01-kubeadm-k8s scripts]# curl 10.99.138.171/k8s
      hello K8S
      
      • 通过Ingress访问也成功
    image.png

    由于机器问题,我没办法演示 Git Push 就触发自动构建的任务,大家如果有公网的机器的话,可以去尝试弄一下!

    相关文章

      网友评论

        本文标题:六、Kubernetes CICD之旅

        本文链接:https://www.haomeiwen.com/subject/gmmsihtx.html