46、在 AWS 中使用 Docker Swarm 进行容器编排与管理

在 AWS 中使用 Docker Swarm 进行容器编排与管理

1. 部署栈与监控服务

当部署栈并监控 collectstatic 服务时,可能会注意到一些初始失败情况。以下是具体操作步骤:
1. 部署栈:

docker stack deploy --with-registry-auth -c stack.yml todobackend

此命令会创建网络和服务,如 todobackend_default todobackend_net todobackend_collectstatic todobackend_app
2. 监控 collectstatic 服务:

docker service ps todobackend_collectstatic

该命令不仅会显示当前服务状态,还会显示服务历史。例如,可能会看到第一次运行 collectstatic 服务在 32 秒前失败,之后 Docker Swarm 尝试重启该服务并成功。由于重启策略设置为失败时重启,且服务最终无错误退出,Swarm 不会再次尝试启动该服务。

若此时浏览外部负载均衡器 URL,会发现 todobackend 应用的静态内容已正确呈现,但数据库配置错误仍然存在。

2. 创建持久存储

接下来,将注意力转移到应用数据库,它是 todobackend 应用的重要支持组件。在 AWS 中,可以使用 Docker for AWS 解决方案来支持持久存储。

Cloudstor 卷插件除了支持 EFS 支持的卷外,还支持可迁移的 Elastic Block Store (EBS) 卷。可迁移意味着当 Docker Swarm 决定将容器从一个节点迁移到另一个节点时,插件会自动将当前分配给容器的 EBS 卷迁移到新节点。迁移过程根据不同场景有所不同:
- 新节点在同一可用区 :插件会简单地从现有节点的 EC2 实例上分离卷,并将其重新附加到新节点。
- 新节点在不同可用区 :插件会对现有卷进行快照,然后从该快照在新可用区创建新卷,完成后销毁之前的卷。

需要注意的是,Docker 仅支持对可迁移 EBS 支持的卷进行单容器访问,即任何时候只能有一个容器对该卷进行读写操作。若需要共享卷访问,则必须创建 EFS 支持的共享卷。

以下是定义一个名为 data 的卷来存储 todobackend 数据库,并创建一个运行 MySQL 并附加到该卷的 db 服务的配置:

version: '3.6'
networks:
  net:
    driver: overlay
volumes:
  public:
    driver: cloudstor:aws
    driver_opts:
      backing: shared
  data:
    driver: cloudstor:aws
    driver_opts:
      backing: relocatable
      size: 10
      ebstype: gp2
services:
  app:
    image: 385605022855.dkr.ecr.us-east-1.amazonaws.com/docker-in-aws/todobackend
    ports:
      - target: 8000
        published: 80
    networks:
      - net
    volumes:
      - public:/public
  collectstatic:
    image: 385605022855.dkr.ecr.us-east-1.amazonaws.com/docker-in-aws/todobackend
    volumes:
      - public:/public
  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: todobackend
      MYSQL_USER: todo
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    networks:
      - net
    volumes:
      - data:/var/lib/mysql
    command:
      - --ignore-db-dir=lost+found
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager

具体操作步骤如下:
1. 创建名为 data 的卷,并将驱动配置为 cloudstor:aws ,指定支持可迁移的 EBS 卷,大小为 10 GB,EBS 类型为 gp2(SSD)存储。
2. 定义一个新的 db 服务,运行官方 MySQL 5.7 镜像,将其附加到之前定义的 net 网络,并将 data 卷挂载到 /var/lib/mysql ,这是 MySQL 存储数据库的位置。
3. 由于 Cloudstor 插件将挂载的卷格式化为 ext4,格式化过程中会自动创建一个名为 lost+found 的文件夹,这会导致 MySQL 容器认为存在名为 lost+found 的现有数据库而中止。为解决此问题,传递 --ignore-db-dir 标志,让 MySQL 守护进程忽略该文件夹。
4. 定义一个放置约束,强制 db 服务部署到 Swarm 管理器,以便后续通过更改此约束来测试 data 卷的可迁移特性。

部署栈并监控 db 服务时,由于数据卷初始化,服务启动可能需要一些时间:

docker stack deploy --with-registry-auth -c stack.yml todobackend
docker service ps todobackend_db --format "{{ .Name }} ({{ .ID }}): {{ .CurrentState }}"

为验证 EBS 卷是否实际创建,可以使用 AWS CLI:

aws ec2 describe-volumes --filters Name=tag:CloudstorVolumeName,Values=* \
    --query "Volumes[*].{ID:VolumeId,Zone:AvailabilityZone,Attachment:Attachments,Tag:Tags}"
3. 迁移 EBS 卷

成功创建并附加 EBS 支持的数据卷后,可以通过更改 db 服务的放置约束来测试将其从管理器节点迁移到工作节点:

version: '3.6'
services:
  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: todobackend
      MYSQL_USER: todo
      MYSQL_PASSWORD: password
      MYSQL_ROOT_PASSWORD: password
    networks:
      - net
    volumes:
      - data:/var/lib/mysql
    command:
      - --ignore-db-dir=lost+found
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == worker

部署更改后,可以观察 EBS 迁移过程:
1. 定义查询命令:

volumes='aws ec2 describe-volumes --filters Name=tag:CloudstorVolumeName,Values=* \
    --query "Volumes[*].{ID:VolumeId,State:Attachments[0].State,Zone:AvailabilityZone}" \
    --output text'
snapshots='aws ec2 describe-snapshots --filters Name=status,Values=pending \
    --query "Snapshots[].{Id:VolumeId,Progress:Progress}" --output text'
  1. 部署更改:
docker stack deploy --with-registry-auth -c stack.yml todobackend
  1. 观察迁移过程:
eval $volumes
eval $snapshots

通过多次运行 eval $volumes 命令,可以观察到卷从 us-east-1b 可用区的管理器节点迁移到 us-east-1a 可用区的工作节点的过程。最后,使用 docker service ps 命令验证 db 服务是否再次正常运行。

由于当前在栈文件中使用明文密码的密码管理策略不理想,且数据库已使用这些密码初始化,在继续之前需要拆除栈:

docker stack rm todobackend
docker volume ls
docker volume rm todobackend_public
docker volume rm todobackend_data

需要注意的是,拆除栈时,必须手动删除栈中使用的任何卷。

4. 使用 Docker 机密进行秘密管理

在之前创建 db 服务的示例中,未将应用与 db 服务集成,部分原因是当前以明文形式配置 db 服务的密码,这并不理想。

Docker Swarm 包含一个名为 Docker 机密的功能,它为在 Docker Swarm 集群上运行的应用提供安全的秘密管理解决方案。机密存储在名为 raft 日志的内部加密存储机制中,并复制到集群中的所有节点,确保任何被授予访问机密权限的服务和相关容器都能安全地访问该机密。

创建 Docker 机密的步骤如下:

openssl rand -base64 32 | docker secret create todobackend_mysql_password -
openssl rand -base64 32 | docker secret create todobackend_mysql_root_password -
openssl rand -base64 50 | docker secret create todobackend_secret_key -
docker secret ls

创建多个机密后,可以配置栈来使用这些机密:

version: '3.6'
networks:
  ...
volumes:
  ...
secrets:
  todobackend_mysql_password:
    external: true
  todobackend_mysql_root_password:
    external: true
  todobackend_secret_key:
    external: true
services:
  app:
    ...
    environment:
      DJANGO_SETTINGS_MODULE: todobackend.settings_release
      MYSQL_HOST: db
      MYSQL_USER: todo
    secrets:
      - source: todobackend_mysql_password
        target: MYSQL_PASSWORD
      - source: todobackend_secret_key
        target: SECRET_KEY
    command:
    ...
  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: todobackend
      MYSQL_USER: todo
      MYSQL_PASSWORD_FILE: /run/secrets/mysql_password
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
    secrets:
      - source: todobackend_mysql_password
        target: mysql_password
      - source: todobackend_mysql_root_password
        target: mysql_root_password
  ...

具体配置步骤如下:
1. 声明顶级 secrets 参数,指定之前创建的每个机密的名称,并将每个机密配置为外部机密,因为这些机密是在栈外部创建的。
2. 重新配置 app 服务,通过 secrets 属性使用每个机密。指定目标为 MYSQL_PASSWORD SECRET_KEY ,当将机密附加到服务时,会在 /run/secrets 创建基于内存的 tmpfs 挂载,每个机密存储在 /run/secrets/<target-name> 位置。
3. 配置 db 服务以使用 MySQL 密码和根密码机密,并配置每个机密的目标,使相应机密挂载到 db 服务容器中。
4. 从 db 服务中移除 MYSQL_PASSWORD MYSQL_ROOT_PASSWORD 环境变量,并用基于文件的等效项替换,引用每个配置机密的路径。

部署更新后的栈后,可以通过以下命令确定 Swarm 管理器上运行的 app 服务实例的容器 ID,并检查 /run/secrets 目录的内容:

docker stack deploy --with-registry-auth -c stack.yml todobackend
docker ps -f name=todobackend -q
docker exec -it <container_id> ls -l /run/secrets
docker exec -it <container_id> cat /run/secrets/MYSQL_PASSWORD

若此时浏览外部负载均衡器 URL 的 /todos 路径,会收到访问被拒绝错误,这是因为 todobackend 应用不知道如何使用这些机密,需要对应用进行一些修改。

5. 配置应用以使用机密

之前使用入口点脚本在容器启动时注入机密,另一种更有效、更安全的方法是配置应用以原生支持机密管理策略。

对于 Docker 机密,由于机密挂载在容器本地文件系统的已知位置 /run/secrets ,配置应用支持 Docker 机密非常简单。以下是修改 src/todobackend/settings_release.py 文件以支持 Docker 机密的示例:

from .settings import *
import os

# Disable debug
DEBUG = True

# Looks up secret in following order:
# 1. /run/secret/<key>
# 2. Environment variable named <key>
# 3. Value of default or None if no default supplied
def secret(key, default=None):
    root = os.environ.get('SECRETS_ROOT','/run/secrets')
    path = os.path.join(root,key)
    if os.path.isfile(path):
        with open(path) as f:
            return f.read().rstrip()
    else:
        return os.environ.get(key,default)

# Set secret key
SECRET_KEY = secret('SECRET_KEY', SECRET_KEY)

# Must be explicitly specified when Debug is disabled
ALLOWED_HOSTS = os.environ.get('ALLOWED_HOSTS', '*').split(',')

# Database settings
DATABASES = {
    'default': {
        'ENGINE': 'mysql.connector.django',
        'NAME': os.environ.get('MYSQL_DATABASE','todobackend'),
        'USER': os.environ.get('MYSQL_USER','todo'),
        'PASSWORD': secret('MYSQL_PASSWORD','password'),
        'HOST': os.environ.get('MYSQL_HOST','localhost'),
        'PORT': os.environ.get('MYSQL_PORT','3306'),
    },
    'OPTIONS': {
      'init_command': "SET sql_mode='STRICT_TRANS_TABLES'"
    }
}

STATIC_ROOT = os.environ.get('STATIC_ROOT', '/public/static')
MEDIA_ROOT = os.environ.get('MEDIA_ROOT', '/public/media')

MIDDLEWARE.insert(0,'aws_xray_sdk.ext.django.middleware.XRayMiddleware')

首先创建一个名为 secret() 的简单函数,它接受设置或键的名称作为输入,以及一个可选的默认值。该函数会尝试在 /run/secrets 路径查找与请求的键同名的文件,如果找到则读取文件内容;否则,查找同名的环境变量;如果所有查找都失败,则返回传递给 secret() 函数的默认值。

更新 todobackend 应用以支持 Docker 机密后,需要提交更改并进行测试、构建和发布:

git commit -a -m "Add support for Docker secrets"
make login
make test
make release
make publish

发布镜像后,切换回连接到 Swarm 集群的终端会话,使用 docker stack deploy 命令重新部署栈:

docker stack deploy --with-registry-auth -c stack.yml todobackend
docker service ps todobackend_app --format "{{ .Name }}: {{ .CurrentState }}"

运行 docker service ps 命令时,可能会发现 todobackend 服务未重新部署,这是因为栈文件中默认使用最新镜像。为确保能够持续交付和部署应用,需要引用特定版本或构建标签。可以利用 todobackend 应用仓库中已有的 Makefile,并包含一个返回当前 Git 提交哈希的 APP_VERSION 环境变量,然后在栈文件中引用该变量:

version: '3.6'
services:
  app:
    image: 385605022855.dkr.ecr.us-east-1.amazonaws.com/docker-in-aws/todobackend:${APP_VERSION}
    ...
  collectstatic:
    image: 385605022855.dkr.ecr.us-east-1.amazonaws.com/docker-in-aws/todobackend:${APP_VERSION}
    ...

在 Makefile 根目录添加 deploy 配方:

.PHONY: test release clean version login logout publish deploy
export APP_VERSION ?= $(shell git rev-parse --short HEAD)

version:
  @ echo '{"Version": "$(APP_VERSION)"}'

deploy: login
  @ echo "Deploying version ${APP_VERSION}..."
  docker stack deploy --with-registry-auth -c stack.yml todobackend

login:
  $$(aws ecr get-login --no-include-email)
...

现在可以通过运行 make deploy 命令部署栈更新:

make deploy
docker service ps todobackend_app --format "{{ .Name }}: {{ .CurrentState }}"

由于栈现在配置了特定的镜像标签,检测到更改后会更新 app 服务。若此时浏览外部负载均衡器 URL 的 /todos 路径,认证错误应会被表不存在错误取代,这证明现在至少能够连接到数据库,但尚未处理 Docker Swarm 解决方案中的数据库迁移问题。

总结

本文详细介绍了在 AWS 中使用 Docker Swarm 进行容器编排与管理的一系列操作,包括部署栈、监控服务、创建持久存储、迁移 EBS 卷、使用 Docker 机密进行秘密管理以及配置应用以使用机密等。通过这些操作,可以实现更高效、安全的容器化应用部署和管理。

流程图

graph TD;
    A[部署栈] --> B[监控服务];
    B --> C[创建持久存储];
    C --> D[迁移 EBS 卷];
    D --> E[使用 Docker 机密管理];
    E --> F[配置应用使用机密];

表格

操作步骤 命令示例 说明
部署栈 docker stack deploy --with-registry-auth -c stack.yml todobackend 创建网络和服务
监控服务 docker service ps todobackend_collectstatic 显示服务状态和历史
创建持久存储 docker stack deploy --with-registry-auth -c stack.yml todobackend 初始化数据卷
迁移 EBS 卷 docker stack deploy --with-registry-auth -c stack.yml todobackend 更改放置约束并观察迁移过程
创建 Docker 机密 openssl rand -base64 32 | docker secret create todobackend_mysql_password - 生成并创建机密
部署更新栈 docker stack deploy --with-registry-auth -c stack.yml todobackend 重新部署栈

在 AWS 中使用 Docker Swarm 进行容器编排与管理

6. 数据库迁移问题分析

当浏览外部负载均衡器 URL 的 /todos 路径时,出现表不存在错误,这表明虽然已经能够连接到数据库,但尚未处理数据库迁移问题。在 Docker Swarm 环境中,数据库迁移是确保应用正常运行的关键步骤。

7. 解决数据库迁移问题的思路

为了解决数据库迁移问题,需要在应用启动时执行数据库迁移脚本。可以通过修改 app 服务的启动命令来实现这一目标。以下是修改后的 stack.yml 文件示例:

version: '3.6'
networks:
  net:
    driver: overlay
volumes:
  public:
    driver: cloudstor:aws
    driver_opts:
      backing: shared
  data:
    driver: cloudstor:aws
    driver_opts:
      backing: relocatable
      size: 10
      ebstype: gp2
secrets:
  todobackend_mysql_password:
    external: true
  todobackend_mysql_root_password:
    external: true
  todobackend_secret_key:
    external: true
services:
  app:
    image: 385605022855.dkr.ecr.us-east-1.amazonaws.com/docker-in-aws/todobackend:${APP_VERSION}
    ports:
      - target: 8000
        published: 80
    networks:
      - net
    volumes:
      - public:/public
    environment:
      DJANGO_SETTINGS_MODULE: todobackend.settings_release
      MYSQL_HOST: db
      MYSQL_USER: todo
    secrets:
      - source: todobackend_mysql_password
        target: MYSQL_PASSWORD
      - source: todobackend_secret_key
        target: SECRET_KEY
    command:
      - sh
      - -c
      - |
        python manage.py migrate
        python manage.py runserver 0.0.0.0:8000
  collectstatic:
    image: 385605022855.dkr.ecr.us-east-1.amazonaws.com/docker-in-aws/todobackend:${APP_VERSION}
    volumes:
      - public:/public
  db:
    image: mysql:5.7
    environment:
      MYSQL_DATABASE: todobackend
      MYSQL_USER: todo
      MYSQL_PASSWORD_FILE: /run/secrets/mysql_password
      MYSQL_ROOT_PASSWORD_FILE: /run/secrets/mysql_root_password
    networks:
      - net
    volumes:
      - data:/var/lib/mysql
    command:
      - --ignore-db-dir=lost+found
    deploy:
      replicas: 1
      placement:
        constraints:
          - node.role == manager

具体修改内容如下:
1. 在 app 服务的 command 部分,添加了 python manage.py migrate 命令,用于执行数据库迁移。
2. 保留 python manage.py runserver 0.0.0.0:8000 命令,用于启动 Django 应用。

8. 重新部署栈并验证

修改 stack.yml 文件后,需要重新部署栈:

make deploy

部署完成后,可以通过以下命令验证服务状态:

docker service ps todobackend_app --format "{{ .Name }}: {{ .CurrentState }}"

若服务正常运行,再次浏览外部负载均衡器 URL 的 /todos 路径,表不存在错误应该会消失,应用应该能够正常显示数据。

9. 最佳实践总结

为了确保在 AWS 中使用 Docker Swarm 进行容器编排与管理的高效性和安全性,以下是一些最佳实践总结:
- 使用特定镜像标签 :避免在栈文件中使用默认的最新镜像,而是引用特定版本或构建标签,确保每次部署的一致性。
- 使用 Docker 机密管理 :使用 Docker 机密功能安全地存储和管理敏感信息,如数据库密码和应用密钥。
- 处理数据库迁移 :在应用启动时执行数据库迁移脚本,确保数据库结构与应用代码同步。
- 手动清理资源 :拆除栈时,手动删除栈中使用的任何卷,避免资源浪费。

流程图

graph TD;
    A[发现数据库迁移问题] --> B[修改 app 服务启动命令];
    B --> C[重新部署栈];
    C --> D[验证服务状态];
    D --> E{服务是否正常运行};
    E -- 是 --> F[应用正常显示数据];
    E -- 否 --> B;

表格

最佳实践 说明
使用特定镜像标签 确保每次部署的一致性,避免使用默认的最新镜像
使用 Docker 机密管理 安全地存储和管理敏感信息,如数据库密码和应用密钥
处理数据库迁移 在应用启动时执行数据库迁移脚本,确保数据库结构与应用代码同步
手动清理资源 拆除栈时,手动删除栈中使用的任何卷,避免资源浪费

总结

通过以上步骤,我们详细介绍了在 AWS 中使用 Docker Swarm 进行容器编排与管理的完整流程,包括部署栈、监控服务、创建持久存储、迁移 EBS 卷、使用 Docker 机密进行秘密管理、配置应用以使用机密以及处理数据库迁移等。遵循这些步骤和最佳实践,可以实现高效、安全的容器化应用部署和管理。

内容概要:本文介绍了一个基于MATLAB实现的无人机三维路径规划项目,采用蚁群算法(ACO)多层感知机(MLP)相结合的混合模型(ACO-MLP)。该模型通过三维环境离散化建模,利用ACO进行全局路径搜索,并引入MLP对环境特征进行自适应学习启发因子优化,实现路径的动态调整多目标优化。项目解决了高维空间建模、动态障碍规避、局部最优陷阱、算法实时性及多目标权衡等关键技术难题,结合并行计算参数自适应机制,提升了路径规划的智能性、安全性和工程适用性。文中提供了详细的模型架构、核心算法流程及MATLAB代码示例,涵盖空间建模、信息素更新、MLP训练融合优化等关键步骤。; 适合人群:具备一定MATLAB编程基础,熟悉智能优化算法神经网络的高校学生、科研人员及从事无人机路径规划相关工作的工程师;适合从事智能无人系统、自动驾驶、机器人导航等领域的研究人员; 使用场景及目标:①应用于复杂三维环境下的无人机路径规划,如城市物流、灾害救援、军事侦察等场景;②实现飞行安全、能耗优化、路径平滑实时避障等多目标协同优化;③为智能无人系统的自主决策环境适应能力提供算法支持; 阅读建议:此资源结合理论模型MATLAB实践,建议读者在理解ACOMLP基本原理的基础上,结合代码示例进行仿真调试,重点关注ACO-MLP融合机制、多目标优化函数设计及参数自适应策略的实现,以深入掌握混合智能算法在工程中的应用方法。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值