第一部分——Docker篇 第五章 容器编排

Docker容器编排工具的探索与实践

关于系统的改造探索

开篇:系统改造的调研报告

第一部分——Docker篇

第一章 Docker容器
第二章 Docker安装
第三章 构建自定义镜像
第四章 搭建镜像仓库
第五章 容器编排
第六章 容器监控



前言

    随着业务的发展,传统的架构已经不符合项目的要求了。双活、集群也渐渐提上了日程。。。


    生产上往往不止一台机子,而部署的应用也有很多。一条条命令去敲也很麻烦,需要对进行 容器 编排,方便管理

docker-compose

    首先出场的是 docker-compose,这个也是 Docker官方 提供的管理工具,不知道为什么,官方提供的往往不用

在这里插入图片描述

不过还是需要了解下,单机节点下还是很方便的。 docker-compose 简单来说:就是把多个 容器 的运行命令写到 YAML 文件中去,这样方便统一管理,易于共享。老样子,下边一起来体验一下

  1. 下载
    老样子,先下载 docker-compose,这里用的是v2.24.5(根据自己需求选择)

在这里插入图片描述

  1. 安装
    把下载好的文件上传至服务器,执行命令:
#重命名文件
mv docker-compose-linux-x86_64 docker-compose
#添加执行权限
chmod u+x docker-compose
#移动到系统目录
mv docker-compose /usr/bin/
#查看版本
docker-compose -v

在这里插入图片描述

  1. 验证
    之前启动 镜像 都是用命令行直接启动,现在体验一下 docker-compose,看看为什么选择它。就以 一个 Springboot项目Nginx 为例

Springboot项目 配置不做改动。Nginx 配置文件如下:


user  nginx;
worker_processes  auto;

error_log  /var/log/nginx/error.log notice;
pid        /var/run/nginx.pid;


events {
    worker_connections  1024;
}


http {
    include       /etc/nginx/mime.types;
    default_type  application/octet-stream;

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /var/log/nginx/access.log  main;

    sendfile        on;
    #tcp_nopush     on;

    keepalive_timeout  65;

    #gzip  on;

    include /etc/nginx/conf.d/*.conf;
	
	server {
       listen       80;
       server_name  192.168.233.135;
       location / {
            proxy_read_timeout 300;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_pass http://docker-demo:8080;
        }
	}

}

注:其他配置大家应该都不陌生,可能会对proxy_pass http://docker-demo:8080感到疑惑,这个涉及到docker网络部分,后边会聊到

编写 YAML 文件如下:

version: '2' # 表示该 Docker-Compose 文件使用的是 Version 2 file
services:
  docker-demo:  # 服务名称
    image: docker-demo:1.0
    container_name: docker-demo #容器名称
#    build: /usr/local/docker/docker-demo   # 指定 Dockerfile 所在路径
    ports:    # 指定端口映射
      - "8080:8080"
    volumes:
      - /usr/local/docker/docker-demo/classes:/config
      
    networks:
      - docker-demo
      
  nginx:  # 服务名称
    image: nginx
    container_name: nginx #容器名称
    ports:    # 指定端口映射
      - "8081:80"
    volumes:
      - /usr/local/docker/nginx/logs:/var/log/nginx
      - /usr/local/docker/nginx/config/nginx.conf:/etc/nginx/nginx.conf
      
    networks:
      - docker-demo


networks:
  docker-demo:
    driver: bridge #使用桥接创建网络


接着,进去 docker-compose 文件所在目录,执行启动命令:

#启动所有应用,-d后台启动
docker-compose -f docker-demo.yml up -d
#关闭所有应用
docker-compose -f docker-demo.yml down
#重启所有应用
docker-compose -f docker-demo.yml restart

在这里插入图片描述

在这里插入图片描述

应用起来了,疑惑也起来。下边就来看下volumes(数据卷)networks(网络)

networks(网络)

    玩过Vmware的应该配置过它的网络,以前该接触时,要么主机ping不通虚拟机,要么虚拟机ping不通主机,对此没少百度。现在回头再来看,Vmware的网络大致分为:

  • 桥接
    桥接模式下,虚拟机和宿主机都会连接到虚拟交换机上,宿主机的网卡与虚拟机的虚拟网卡通过虚拟网桥连接起来,它们的地位“平等”,同处于一个网段互不干拢,虚拟机是网络的完整参与者

阿道夫地方

  • NAT
    NAT模式下,虚拟机在外部网络上没有自己的 IP 地址。相反,在宿主机上设置一个专用网络。其原理是将专用网络中虚拟机的 IP 地址转换为主机系统的 IP 地址。当虚拟机发送访问网络资源的请求时,网络资源看起来就像该请求来自主机系统。这样看来,宿主机像是虚拟机的“上级”
    撒大声地

  • 仅主机
    仅主机模式下,虚拟机和主机虚拟网络适配器连接到专用以太网,虚拟机只能和主机通信,不能与外网进行通信,相当于一个封闭的局域网
    撒大大

跑题了~,回到 Docker,再看下 Docker 的网络:

  • Bridge
    Bridge模式虽然叫Bridge,但是并不等价于Vmware的桥接,而是与NAT模式相似,docker会在宿主机创建一个docker0网卡,该网卡会与一个虚拟交换机相连,当容器Bridge模式创建启动时,会给容器创建一个虚拟网卡,该网卡分配的IP与宿主机的docker0所在同一个局域网内

  • Host
    Host模式会直接使用宿主机的网卡,容器本身并不会创建虚拟网卡,容器暴露的端口可以直接在宿主机中查到,可以当成就是在宿主机真实执行的程序。使用此模式时 -p 参数失效

  • Container
    Container模式会指定一个容器的网卡为网卡,当前容器也不会创建虚拟网卡。这两个容器不能有一样的端口暴露

  • None
    None模式不会给容器创建网卡,相当于一个没有网卡的机子,无法与外部通讯

  • Overlay
    Overlay模式是为了在多个docker守护进程主机之间创建分布式网络,即不同机子上部署的docker可以相互通讯,该模式允许连接到它的容器(包括集群服务容器)安全地通信

  • IPvlan
    IPvlan模式比较麻烦,没看懂,直接摘取官网的描述:IPvlan 是经过考验的真实网络虚拟化技术的新变化。 Linux 实现非常轻量级,因为它们不是使用传统的 Linux 桥进行隔离,而是与 Linux 以太网接口或子接口相关联,以强制网络之间的分离以及与物理网络的连接。

    IPvlan提供了许多独特的功能,并为各种模式的进一步创新提供了充足的空间。这些方法的两个高级优势是,绕过 Linux 桥的积极性能影响以及移动部件较少的简单性。移除传统上位于 docker 主机 NIC 和容器接口之间的桥接器,留下由直接连接到 docker 主机接口的容器接口组成的简单设置。面向外部的服务很容易访问此结果,因为在这些场景中不需要端口映射

IPvlan L2
在这里插入图片描述

  • Macvlan
    Macvlan模式一样没看懂,官网描述:某些应用程序,尤其是遗留应用程序或监视网络流量的应用程序,期望直接连接到物理网络。在这种情况下,您可以使用Macvlan网络驱动程序为每个容器的虚拟网络接口分配一个MAC地址,使其看起来像是直接连接到物理网络的物理网络接口。在这种情况下,您需要在docker主机上指定用于 Macvlan的物理接口,以及网络的子网和网关。您甚至可以使用不同的物理网络接口隔离 Macvlan 网络

在这里插入图片描述

volumes(数据卷)

    volumes又是个麻烦的话题。简单来说,是为了方便备份或迁移,以及共享。前文提到过,如果没有volumes(命令行的 -v 或 --mount 、Docker Composevolumes),一旦容器挂了,数据就会丢失,类似于数据库这样的应用,怕是牢饭管饱。。。

    为了避免牢饭管饱,就需要把容器内的数据映射到宿主机上边保存,这也是volumes主要作用

在这里插入图片描述


docker-swarm

    docker-compose 还是老生常谈的问题:只能单机部署,对于集群环境,我们更需要的是对整个集群的把控。于是就有了 docker-swarm

    docker-swarm 也是 Docker 官方出品的 容器编排工具 ,提供基本的 容器编排、负载均衡服务发现 等功能,相较于与 k8sdocker-swarm 集成在 Docker引擎 中,不需要额外安装软件,适合较小规模的集群和较简单的应用

早期 Docker Swarm 和 k8s 处于竞争关系,最开始因为 Docker Swarm 和 Docker 无缝结合,用户更倾向于 Docker Swarm,后来 Kubernetes 崛起,并很快在容器编排领域取得了领先地位。其丰富的功能、扩展能力和强大的社区支持使得越来越多的企业选择 Kubernetes。到了 2017年,Docker 宣布在 Docker Enterprise 中集成 Kubernetes,这一举措标志着 Docker Inc. 认可了 Kubernetes 在容器编排领域的主导地位,并开始为用户提供更多选择

大概了解了 docker-swarm ,现在来一起体验下它的魅力,假定有三台已安装好 Docker环境 的机子,分别为:192.168.233.139(master节点)、192.168.233.140、192.168.233.141。如果不知道怎么安装 Docker,可以参考前面的文章

  1. 初始化主节点
    在主节点下,执行如下命令:
docker swarm init --advertise-addr  192.168.233.139

在这里插入图片描述

记录下 docker swarm join --token SWMTKN-1-5u4y7wefs34fse7f5ktadmhil8ut3qnh2br9dfslte70ehx8x0-63mb5m9efjo62pax9to52yl6f 192.168.233.139:2377 ,后边需要用到

  1. 添加从节点
    在两个从节点,各自执行如下命令:
docker swarm join --token SWMTKN-1-5u4y7wefs34fse7f5ktadmhil8ut3qnh2br9dfslte70ehx8x0-63mb5m9efjo62pax9to52yl6f 192.168.233.139:2377
  1. 验证

在主节点下,执行如下命令进行验证:

docker node ls

在这里插入图片描述

可以看的出来,三台机子都已经加入集群了,并且标明了 Leader 节点

  1. 部署 Nginx

假定需要部署3个 Nginx,在主节点下,执行如下命令部署 Nginx

#--publish即映射主机端口,--replicas 即部署多少个nginx
 docker service create   --name my-web   --publish published=8080,target=80   --replicas 3   nginx

在这里插入图片描述

部署完成后,执行 docker service ps my-web 查看部署应用具体部署到哪里,如下:

在这里插入图片描述

  1. 扩缩容
    Swarm 也支持动态扩缩容,扩容命令如下:
#把nginx个数扩展到5个
docker service scale my-web=5

在这里插入图片描述

缩容命令也是一样的,调整 scale 个数即可,如下:

docker service scale my-web=2

在这里插入图片描述

  1. 路由网格
    我们先试用 docker service ps my-web 查看下,应用的部署情况,如下:
    在这里插入图片描述
    可以看到,当前 Nginx 并没有部署在 master 节点上,现在我们用 master 节点的IP 访问看看:

在这里插入图片描述

可以看到,就算 master 节点没有部署 Nginx,依然可以访问的到,这个就是 Swarm 模式路由网格,当访问任何节点上的端口 8080 时,Docker 会将您的请求路由到活动容器

在这里插入图片描述

Swarm 除了上述这些功能,也支持 滚动更新负载均衡故障转移 等功能。限于篇幅,这些就由大家自己去试验了

k3s

    由于这部分的内容属于 Docker 篇幅,所以这里就不过多的讨论 k8s 的相关内容,这里我们选用 k3s 来体验下就可以了

  1. k3s 安装
#下载minikube
curl -LO https://storage.googleapis.com/minikube/releases/latest/minikube-linux-amd64

#安装minikube
sudo install minikube-linux-amd64 /usr/local/bin/minikube && rm minikube-linux-amd64

#启动
minikube start --force

#启用别名
alias kubectl="minikube kubectl --"

#添加提示
source <(kubectl completion bash)

#验证
minikube dashboard

用虚拟机的浏览器访问url,如下:

在这里插入图片描述

  1. 部署应用
#创建服务
kubectl create deployment kubernetes-bootcamp --image=gcr.io/google-samples/kubernetes-bootcamp:v1

#暴露端口
kubectl expose deployment/kubernetes-bootcamp --type="NodePort" --port 8080

在这里插入图片描述

  1. 扩缩容
#扩容到3,缩容也是同理,修改replicas数量即可
kubectl scale deployments/kubernetes-bootcamp --replicas=3

#查看
kubectl get pods

在这里插入图片描述

这里大概体验一下,更具体的 k8s 内容会在第二部分提及,如果想继续学习的,可以参考 官网教程

总结

    在 容器编排 方面,尝试了多种方案,最终还是选择了 k8s ,虽然 Docker Swarm 更简单,但是没有相应的操作界面,有操作界面的属于 Docker Cloud 的内容,一来这个是收费的内容,二来在 2018年 停止了其核心功能。k8s 虽然学习陡峭,但是提供了更完整的解决方案,社区也很完善

docker-compose 搭建的lamp+redis 代码 附上docker-compose # 标准配置文件应该包含 version、services、networks 三大部分, # 其中最关键的就是 services 和 networks 两个部分,下面先来看 services 的书写规则 # 指定版本号 version: '2' services: # 在 services 标签下的第二级标签是 console,这个名字是用户自己自定义,它就是服务名称。 console: # 为自定义的容器指定一个名称,而不是使用默认的名称 container_name: console # 容器内置名称 hostname: console # 指明路径 build: # context 指定绝对路径或者相对路径 context: ./images/console # dockerfile 指定 Dockerfile 的文件名称 dockerfile: Dockerfile # volumes_from 从其它容器或者服务挂载数据卷, # 可选的参数是 :ro 或 :rw,前者表示容器只读,后者表示容器对数据卷是可读可写的(默认情况为可读可写的)。 volumes_from: - php # 挂载一个目录或者一个已存在的数据卷容器,可以直接使用 HOST:CONTAINER 这样的格式 # ,或者使用 HOST:CONTAINER:ro 这样的格式,后者对于容器来说,数据卷是只读的,这样可以有效保护宿主机的文件系统 volumes: # 使用绝对路径挂载数据卷 - /root/.ssh/:/root/.ssh/ # 类似于使用 docker run 的效果 我也不知道 不写因为console并不是直接启动导致镜像不会产生 tty: true # web,这个名字是用户自己自定义,它就是服务名称。 web: # 为自定义的容器指定一个名称,而不是使用默认的名称 container_name: web # 容器内置名称 hostname: web # 指明路径 build: # context 指定绝对路径或者相对路径 context: ./images/nginx # dockerfile 指定 Dockerfile 的文件名称 dockerfile: Dockerfile # 映射端口 ports: - '80:80' # 此选项解决了启动顺序的问题 这个的意思是必须在php启动以后才能启动 # 注意的是,默认情况下使用 docker-compose up web 这样的方式启动 web 服务时, # 也会启动 php 服务,因为在配置文件中定义了依赖关系 depends_on: - php # volumes_from 从其它容器或者服务挂载数据卷, volumes_from: - php volumes: # 已经存在的命名的数据卷 - nginx-log:/var/log/nginx # 以 Compose 配置文件为中心的相对路径作为数据卷挂载到容器 - ./images/nginx/sites-enabled:/etc/nginx/sites-enabled - ./images/nginx/cert:/etc/nginx/cert # 加入指定网络 networks: default: # 同一网络上的其他容器可以使用服务器名称或别名来连接到其他服务的容器 aliases: - web.sunchanghao.top - mid.sunchanghao.top - sevice.sunchanghao.top - admin.sunchanghao.top # php,这个名字是用户自己自定义,它就是服务名称。 php: # 为自定义的容器指定一个名称,而不是使用默认的名称 container_name: php # 容器内置名称 hostname: php # 服务除了可以基于指定的镜像,还可以基于一份 Dockerfile, # 在使用 up 启动之时执行构建任务,这个构建标签就是 build,它可以指定 Dockerfile # 所在文件夹的路径。Compose 将会利用它自动构建这个镜像,然后使用这个镜像启动服务容器 build: # context 选项可以是 Dockerfile 的文件路径,也可以是到链接到 git 仓库的 url # 当提供的值是相对路径时,它被解析为相对于撰写文件的路径,此目录也是发送到 Docker 守护进程的 context context: ./images/php # 使用此 dockerfile 文件来构建,必须指定构建路径 dockerfile: Dockerfile # 挂载一个目录或者一个已存在的数据卷容器volumes: # 以 Compose 配置文件为中心的相对路径作为数据卷挂载到容器。 - ./app:/mnt/app # db,这个名字是用户自己自定义,它就是服务名称。 db: # 为自定义的容器指定一个名称,而不是使用默认的名称 container_name: db # 容器内置名称 hostname: db # 从指定的镜像中启动容器,可以是存储仓库、标签以及镜像 ID image: mysql:5.7 environment: MYSQL_USER: 'sch' MYSQL_PASS: '1111' MYSQL_ROOT_PASSWORD: 'root' volumes: - db:/var/lib/mysql ports: - '3306:3306' redis: # 为自定义的容器指定一个名称,而不是使用默认的名称 container_name: redis # 容器内置名称 hostname: redis # image 则是指定服务的镜像名称或镜像 ID。如果镜像在本地不存在,Compose 将会尝试拉取这个镜像。 image: redis:3.2.7 # 设置端口号 ports: - '6379:6379' # 挂载一个目录或者一个已存在的数据卷容器 volumes: # 已经存在的命名的数据卷。 - redis:/data # node volumes: nginx-log: # 设置volume的驱动,默认是local. driver: local db: driver: local redis: driver: local
### 如何正确地重载或重启 Docker 容器 #### 一、基本操作命令 要重新加载或重启 Docker 容器,可以使用以下基础命令来实现: - **启动已停止的容器** 使用 `docker start` 命令可启动一个或多个已经处于停止状态的容器。例如: ```bash docker start 15b4aaa5d079 ``` 这里的 `15b4aaa5d079` 是目标容器的 ID 或名称[^1]。 - **停止正在运行的容器** 如果需要先停止某个正在运行的容器再执行其他操作,则可以通过如下方式停止它: ```bash docker stop 15b4aaa5d079 ``` - **重启容器** 若要快速重启某容器而无需手动停止后再启动,可以直接调用 `docker restart` 命令: ```bash docker restart 15b4aaa5d079 ``` 以上三种方法均适用于单个容器的操作需求。 #### 二、批量处理多容器情况下的重启 当存在大量需要同步管理(比如全部重启)的情况时,可通过脚本或者组合命令一次性完成任务。下面是一个简单的 Bash 脚本来遍历所有当前存在的容器并逐一重启它们: ```bash #!/bin/bash for container_id in $(docker ps -aq); do echo "Restarting $container_id..." docker restart "$container_id" done ``` 此脚本会获取到所有的容器列表并通过循环逐一对其发出重启指令。 #### 三、针对特定服务组件(如 Redis) 的特殊场景下重启 如果是在某些复杂架构环境下部署的服务实例 (例如通过 Compose 文件定义好的应用集群),那么可能更倾向于直接作用于整个编排环境而非单独调整每一个独立单元。此时应该考虑利用 `docker-compose` 工具来进行高层次上的控制动作,像这样就可以轻松达到目的——仅需指定具体的服务名即可触发对应部分更新过程而不影响全局稳定性: ```bash docker-compose restart redis ``` 上述例子展示了怎样专门针对名为 “redis” 的服务实施重启流程[^2]。 #### 四、动态更改配置后的生效机制探讨 假设我们刚刚完成了对本地安装版本镜像源地址替换之类的改动之后希望立即让这些新设定反映出来而不是等待自然周期结束前被动接受变化的话;又或者是遇到过因为底层守护进程本身异常退出而导致功能受限等问题急需恢复常态之时……这时就需要借助操作系统层面发送信号给 daemon 来通知其刷新内部缓存数据结构从而即时体现最新参数设置效果啦!以下是推荐使用的做法之一: ```bash kill -SIGHUP $(pidof dockerd) ``` 这条语句的作用就是向正在后台持续监听网络请求等活动事件流的核心引擎传递一条特殊的中断消息(Signal Hup),促使后者主动丢弃旧有连接池资源转而依据最新的规则集重建关联关系链路图谱等等一系列必要的初始化准备工作[^3]。 #### 五、自动化维护策略建议 —— Linux Crontab 实现定期自动重启计划安排 对于那些长期运行却偶尔会出现莫名卡死现象的老系统来说,在短期内无法彻底根治根本原因的前提下,制定一套合理的预防措施显得尤为重要。其中一种常见手段便是依靠系统的内置调度程序 Cron 来预先规划好固定时间间隔内的例行检查与纠正活动。例如每天凌晨两点钟准时唤醒服务器并对指定范围内的所有容器对象依次施行强制性重启干预措施以确保第二天能够正常投入使用不受干扰。 编辑用户的 crontab 文件加入类似这样的条目内容即可达成预期目标: ```cron 0 2 * * * /usr/bin/docker restart my_container_name >> ~/logs/cron_docker_restart.log 2>&1 ``` 这里设置了每日清晨两点半整点时刻触发展开一次限定为单一实体(my_container_name)级别的简单版方案示范[^5]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

穷儒公羊

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值