基本概念

CI/CD

Continuous Integration (CI) is the practice of merging all developer working copies to a shared mainline several times a day.
持续集成 的含义为 频繁的将所有开发者的工作合并到主干上
持续集成 的核心在于 确保新增的代码能够与原先代码正确的集成

  • 开发人员提交代码到 Source Repository (源代码仓库),并通过 git hook 等
  • 触发 CI Server(持续集成服务器)的相关功能。执行 编译 -> 测试 -> 输出结果 的流程
  • 向开发人员反馈结果的 report

Continuous delivery (CD) is a software engineering approach in which teams produce software in short cycles, ensuring that the software can be reliably released at any time and, when releasing the software, doing so manually.
持续交付 指的是:一种能够使得软件在较短的循环中可靠的发布的软件工程方法。
持续交付的侧重点在于交付,其核心对象不在于代码,而在于可交付的产物。由于持续集成仅仅针对于新旧代码的集成过程执行了一定的测试,其变动到持续交付后还需要一些额外的流程。

与 持续集成 相比较,持续交付 添加了 Test -> Staging -> Production 的流程,也就是为新增的代码添加了一个保证:确保新增的代码在生产环境中是可用的 。

  • Test 环节不仅仅包含基本的单元测试,还需要延伸到更为复杂的功能测试以及集成测试等。
  • Staging 指的是 类生产环境 ,其尽可能的对真实的网络拓扑、数据库数据以及硬件设备等资源进行模拟,从而为测试人员反馈代码在生成环境中的可能表现。流程中每一个环节的执行结果都会对开发人员进行反馈,每一个出现的错误都会导致版本的回滚。
  • 当测试完毕确认无误之后,将由相关人员对其进行手动部署 manual deployment 到生产环境 Production

Continuous deployment (CD) is a software engineering approach in which software functionalities are delivered frequently through automated deployments.
持续部署 意味着:通过 自动化部署 的手段将软件功能频繁的进行交付。
与持续交付以及持续集成相比,持续部署强调了通过 automated deployment 的手段,对新的软件功能进行集成。

参考文章

云原生

云原生(CloudNative)是一种构建和运行应用程序的方法,是一套技术体系和方法论。
Pivotal最新官网对云原生概括为4个要点:DevOps、持续交付、微服务、容器

  • Cloud 表示应用程序位于云中,而不是传统的数据中心;
  • Native表示应用程序从设计之初即考虑到云的环境,原生为云而设计,在云上以最佳姿势运行,充分利用和发挥云平台的弹性+分布式优势。

符合云原生架构的应用程序应该是:采用开源堆栈(K8S+Docker)进行容器化,基于微服务架构提高灵活性和可维护性,借助敏捷方法、DevOps支持持续迭代和运维自动化,利用云平台设施实现弹性伸缩、动态调度、优化资源利用率。

准备工作

docker私服

  • 你可以选择可视化的私服Harbor,我这里直接选择registry
    1
    docker run -di --name=registry -p 5000:5000 registry
  • 修改DOCKER_OPTS
    CentOS系统编辑 vim /lib/systemd/system/docker.service
    如果是WSL2 Ubuntu编辑 vim /etc/default/docker
    1
    2
    #           开启远程访问           开启本地套接字访问
    DOCKER_OPTS="-H tcp://0.0.0.0:2375 -H unix:///var/run/docker.sock"
    注意,如果是云服务器,建议设置只允许自己的ip访问2375端口,否则有安全隐患
  • 重启docker
    1
    systemctl daemon-reload && systemctl restart docker && docker start registry
  • 想要在客户端推送镜像到此仓库,在客户端需要配置 vim /etc/docker/daemon.json
    1
    {"insecure-registries":["仓库地址:5000"]}

maven项目结构

  • 在每个需要单独运行的模块的 src/main 创建 /docker/Dockerfile 文件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    FROM openjdk:8-jre-alpine

    ENV VERSION 1.0-SNAPSHOT

    # 修改镜像源地址为阿里云
    RUN echo "http://mirrors.aliyun.com/alpine/v3.8/main" > /etc/apk/repositories \
    && echo "http://mirrors.aliyun.com/alpine/v3.8/community" >> /etc/apk/repositories \
    && apk update upgrade \
    && apk add --no-cache procps curl bash tzdata \
    && ln -sf /usr/share/zoneinfo/Asia/Shanghai /etc/localtime \
    && echo "Asia/Shanghai" > /etc/timezone

    # 复制镜像到容器
    ADD 模块名-${VERSION}.jar 模块名.jar
    # touch更新文件信息
    RUN bash -c 'touch /模块名.jar'

    # 暴露容器端口
    EXPOSE 8080 9090

    # 设置环境变量
    ENV JAVA_OPTS=""
    ENTRYPOINT ["bash", "-c", "java $JAVA_OPTS -jar /模块名.jar"]
  • 为该模块配置两个插件
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    <build>
    <plugins>
    <plugin>
    <!--docker部署插件,官网:https://github.com/spotify/docker-maven-plugin -->
    <groupId>com.spotify</groupId>
    <artifactId>docker-maven-plugin</artifactId>
    <version>0.4.13</version>
    <configuration>
    <dockerHost>http://仓库地址:2375</dockerHost>
    <imageName>仓库地址:5000/${project.artifactId}:${project.version}</imageName>
    <dockerDirectory>src/main/docker</dockerDirectory>
    <resources>
    <resource>
    <targetPath>/</targetPath>
    <directory>${project.build.directory}</directory>
    <include>${project.build.finalName}.jar</include>
    </resource>
    </resources>
    </configuration>
    </plugin>
    <!--maven打包插件,防止出现依赖问题-->
    <plugin>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-maven-plugin</artifactId>
    <executions>
    <execution>
    <goals>
    <goal>repackage</goal>
    </goals>
    </execution>
    </executions>
    </plugin>
    </plugins>
    </build>

Gogs

  • 创建mysql容器,并建立一个 gogs 数据库(如果已有其他mysql服务器可跳过)
    1
    docker run -di --name="mysql_gogs" -p 3306:3306 -e MYSQL_ROOT_PASSWORD="root" mysql
  • 创建gogs容器(--link mysql:mysql_gogs 是表示和mysql_gogs容器建立连接,主机地址是mysql)
    1
    docker run -d --name=gogs -p 10022:22 -p 3000:3000 --link mysql_gogs:mysql_gogs -v /var/gogsdata:/data gogs/gogs
  • 安装gogs(与mysql容器建立连接后可以直接使用mysql:3306
  • 访问 http://localhost:3000 注册,登录,一个私有的git平台就搭建完成了!

Jenkins

  • 配置java环境
    1
    apt install openjdk-8-jre-headless
  • 下载 jenkins.war,运行 java -jar jenkins.war --httpPort=8888,复制初始密码
    下一次可以在后台运行,使用 nohup java -jar jenkins.war --httpPort=8888 &
  • 如果不幸安装失败或者想删除jenkins缓存文件,可以 rm -rf /root/.jenkins/
  • 进入连接 http://localhost:8888 ,稍等片刻,输入初始密码,安装推荐的插件。
  • 现在,我们有两种方式构建项目

基于插件快速构建

  • 进入 系统管理 - 插件管理 安装以下插件,并重启Jenkins
    Maven Integration
    Git Plugin
    Gogs Plugin
  • 新建任务
  • 配置Gogs Webhook变量以及Git仓库地址

    构建选择执行shell
    1
    2
    cd ${WORKSPACE}/${module_path}
    mvn clean ${maven_cmd}
  • 现在,来到任务界面,选择Build with Paramerters
    首先我们需要install一下根目录,把所有模块装到maven仓库方便各个模块相互依赖
  • 点击开始构建!等待构建完成
  • OK,现在,发布一个子模块只需要动动小手,选择package docker:build -DpushImage即可

Rancher

Rancher是一个开源的企业级全栈化容器部署及管理平台。Rancher为容器提供多种基础架构服务:CNI兼容的网络服务、存储服务、主机管理、负载均衡、防护墙。
Rancher让上述服务跨越公有云、私有云、虚拟机、物理机环境运行,真正实现一键式应用部署和管理。

  • 使用rancher时,不可使用localhost,需自备虚拟机或云服务器
  • 创建Rancher容器
    1
    docker run ‐d ‐‐name=rancher ‐p 9999:8080 rancher/server
  • 访问 http://服务器地址:9999 ,点击Got it,右下角切换语言 简体中文
  • 新建环境
  • 基础架构 - 添加主机
    将生成的脚本复制到其他主机的docker上运行,与rancher建立连接
  • 此时,就可以很方便的管理主机的docker容器了
  • 添加应用
  • 添加服务,和docker命令一样,简简单单~

  • 部署自己项目,镜像填写 仓库地址:5000/xxx/xxx:xxx 即可 。