美文网首页Docker DevOps工具
docker入门(10)--零中断部署

docker入门(10)--零中断部署

作者: 随意的ID | 来源:发表于2018-11-02 14:42 被阅读92次

    本节主要学习,如何在不终止服务的情况下,升级服务中的应用等。
    为了做到零终端,通常,我们应用的部署策略有三种:

    三者的一些比较:
    微服务部署:蓝绿部署、滚动部署、灰度发布等部署方案对比与总结
    蓝绿部署、金丝雀发布(灰度发布)、A/B测试的准确定义
    docker swarm默认支持Rolling updates的开箱即用。其他两种方式可通过扩展支持。

    1. 滚动部署

    关于原理部分可参考上面的链接,下面我们进行实践。
    定义一个包含rolling update相关配置的stack,命名为rolling-update.yml:

    version: "3.5"
    services:
      web:
        image: nginx:1.13-alpine
        ports:
          - 8080:80
        deploy:
          replicas: 10
          update_config:
            parallelism: 2
            delay: 10s
    

    上面的大部分内容之前都学习过,我们这里主要看update_config部分。上面的配置表示,一共会启用10个task,在升级时,每2个task会成为一组进行升级操作,每一组升级成功之后,间隔10s开始下一组的升级。

    1、开始部署上面的stack:
    docker stack deploy -c rolling-update.yml web命令执行部署,部署完成后,可以使用watch docker stack ps web命令查看,刚开始可能如下图,正在Preparing的一般是镜像还没有拉取下来,要等到超时之后下一次重试(每次重试间隔大约5分钟,应该是可以进行相关设置的。在我没换国内镜像仓库之前失败的次数更多,不过镜像下载一次之后,后续就不用下载了,部署起来速度很快)。


    所有的task都必须正常启动了之后,才能开始进行下面的升级工作,如下:


    2、升级上面的stack
    执行升级之前,建议再开一个窗口,并且将docker-machine环境变量设置为node-1,然后执行watch docker stack ps web,可以实时查看相关进度。
    执行如下命令,升级上面stack中的nginx版本:
    docker service update --image nginx:1.14-alpine web_web
    可以看到就是每次两个task进行升级操作,其他task继续提供服务。


    3、测试完成,删除stack
    docker stack rm web

    2. 健康检查

    有时候,你在查看容器运行的状态时,它可能是显示OK的状态,但容器内的应用是否OK,你这个时候还无法确定。因此,我们通常使用健康检查来确定一个服务是否确实在正常运行。
    我们通常有两种方式来定义健康检查。

    2.1 Dockerfile定义健康检查

    我们可以在制作镜像时,就为镜像内的服务定义健康检查,通常如下:

    FROM alpine:3.6
    ...
    HEALTHCHECK --interval=30s \
        --timeout=10s
        --retries=3
        --start-period=60s
        CMD curl -f http://localhost:3000/health || exit 1
    ...
    

    --start-period=60s:通常服务的启动,需要一定时间,在这段时间内不会执行健康检查。
    --interval=30s:每次检查的时间间隔。
    --timeout=10s:每次检查的超时时间。
    --retries=3:重试多少次后,认为服务不可用。
    CMD curl -f http://localhost:3000/health || exit 1:通过在容器内执行什么命令,来检查服务是否可用。

    2.2 stack file文件内定义健康检查

    一个示例如下:

    version: "3.5"
    services:
      web:
        image: nginx:alpine
        healthcheck:
          test: ["CMD", "wget", "-qO", "-", "http://localhost"]
          interval: 5s
          timeout: 2s
          retries: 3
          start_period: 15s
    

    参数与上面的Dockerfile中的类似,需要注意的是:1、你必须为每个service定义一个健康检查,而不是对整个stack进行。2、如果你的service所引用的镜像内已经包含健康检查,那么这里的定义会覆盖它。

    部署上面的示例看看:
    docker stack deploy -c stack-health.yml myapp


    你会看到与之前有所不同的地方是,在STATUS栏,多了个healthy。

    3. 回滚操作

    可能有多种原因造成新的版本,确实新版无法正常运行的时候,我们需要预定义好回滚操作。
    一个配置示例如下:

    version: "3.5"
    services:
      web:
        image: nginx:1.12-alpine
        ports:
          - 80:80
        deploy:
          replicas: 10
          update_config:
          parallelism: 2
          delay: 10s
          
          failure_action: rollback
          monitor: 10s
          
        healthcheck:
          test: ["CMD", "wget", "-qO", "-", "http://localhost"]
          interval: 2s
          timeout: 2s
          retries: 3
          start_period: 2s
    

    通过前面的知识,我们知道,一个task要被确认为不健康的状态,需要的时间是:start_period + interval*retries,因此,这里需要8秒钟。
    monitor: 10s:定义在一个task开始部署后,需要对它持续监控的时间,用来决定是否进行下一组的升级操作。因此,需要大于上面的8秒。
    failure_action: rollback:该参数在默认情况下,如果发现升级失败,那么会立即停止这次升级,并保持这个状态退出升级(例如前面包含10个task,每次升级2个的service,会保持其余8个task还是运行老旧版本的状态,并对外提供服务)。而我们如果配置为rollback值的话,表示进行回滚操作,那2个失败的task会恢复运行之前的版本,并提供服务。

    4. 密码管理

    我们经常需要向容器内传递一些敏感信息,例如最常见的密码。我们可以通过-e参数来指定传入的变量以及对应的值,但是,这样我们的密码就以明文形式暴露了。为了解决这个问题,docker swarm 提供了 secret 机制。
    secret需要由manager节点创建,并保存。worker需要使用的时候,通过tmpFS文件系统挂载使用。

    4.1 创建密码

    从标准输出创建:
    echo "sample secret value" | docker secret create sample-secret -
    读取文件内容创建:
    docker secret create other-secret ~/my-secrets/secret-value.txt
    查看当前已有的密码和审查:

    [root@node2 swarm]# docker secret ls
    ID                          NAME                DRIVER              CREATED             UPDATED
    ams8zjhm15z8qpfv9mgv5wrv9   sample-secret                           7 seconds ago       7 seconds ago
    [root@node2 swarm]# docker secret inspect sample-secret
    [
        {
            "ID": "ams8zjhm15z8qpfv9mgv5wrv9",
            "Version": {
                "Index": 893
            },
            "CreatedAt": "2018-11-05T03:20:51.9911386Z",
            "UpdatedAt": "2018-11-05T03:20:51.9911386Z",
            "Spec": {
                "Name": "sample-secret",
                "Labels": {}
            }
        }
    ]
    

    4.2 使用密码

    [root@node2 swarm]# docker service create --name web \
    > --secret sample-secret \
    > --publish 8000:8000 \
    > fundamentalsofdocker/whoami:latest
    
    jwwd32a5qbld0lviruneezcl5
    overall progress: 1 out of 1 tasks 
    1/1: running   [==================================================>] 
    verify: Service converged
    [root@node2 swarm]# docker service ls
    ID                  NAME                MODE                REPLICAS            IMAGE                                PORTS
    jwwd32a5qbld        web                 replicated          1/1                 fundamentalsofdocker/whoami:latest   *:8000->8000/tcp
    [root@node2 swarm]# docker service ps web
    ID                  NAME                IMAGE                                NODE                DESIRED STATE       CURRENT STATE            ERROR               PORTS
    kd8jknn6llb6        web.1               fundamentalsofdocker/whoami:latest   node-3              Running             Running 47 seconds ago
    [root@node2 swarm]# docker-machine ssh node-3
    docker@node-3:~$ docker container ls
    CONTAINER ID        IMAGE                                COMMAND             CREATED             STATUS              PORTS               NAMES
    cf2952b075cc        fundamentalsofdocker/whoami:latest   "/app/http"         2 minutes ago       Up 2 minutes        8000/tcp            web.1.kd8jknn6llb6vfgne68of5v01
    docker@node-3:~$ docker container exec -it cf2952b075cc cat /run/secrets/sample-secret
    sample secret value
    

    以上操作为:
    1、创建一个使用了sample-secret密码的service。
    2、查看对应的task在哪个节点上,node-3。
    3、登录到node-3上,查看对应的容器。
    4、在容器内执行cat /run/secrets/sample-secret,可以得到明文的密码。
    以上操作表明了,默认会把密码挂载到容器的/run/secrets/目录下。
    当然,你也可以通过--secret参数,把密码挂载到容器的指定目录下:
    --secret source=sample-secret,target=/run/my-secrets/api-secret-key

    相关文章

      网友评论

        本文标题:docker入门(10)--零中断部署

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