容器化微服务部署:从基础到高级
1. 实验资源清理
在完成任何实验后,可以运行
terraform destroy
命令来清理由 Terraform 管理的所有资源。不过要注意,对于生产服务而言,这是一个危险的命令。
2. 服务发现
当使用 Docker 处理容器集群时,管理工作会变得相当复杂。正确管理需要在不同主机间共享配置,并确保容器的启动和停止部分自动化。
静态配置在很多场景下会变得复杂,例如:
- 将微服务迁移到新的 AWS 区域或不同的云提供商时,如何通知使用该微服务的其他服务?
- 当通过功能标志控制新功能时,如何快速开启或关闭该功能?
- 负载均衡器如何知晓所有应接收流量的容器?
服务发现是解决这些问题的编排方法。像 Consul(https://www.consul.io/)和 etcd(https://etcd.io/)这类工具,允许将值存储在知名键后面,并能动态更新。
下面以 etcd 为例,结合基本的 Quart 服务和 etcd3 Python 库进行说明。假设按照 etcd 官网说明以默认选项启动 etcd,可在服务中添加配置更新代码:
# etcd_basic.py
from quart import Quart, current_app
import etcd3
# Can read this map from a traditional config file
settings_map = {
"dataservice_url": "/services/dataservice/url",
}
settings_reverse_map = {v: k for k, v in settings_map.items()}
etcd_client = etcd3.client()
def load_settings():
config = dict()
for setting, etcd_key in settings_map.items():
config[setting] = etcd_client.get(etcd_key)[0].decode("utf-8")
return config
def create_app(name=__name__):
app = Quart(name)
app.config.update(load_settings())
return app
app = create_app()
def watch_callback(event):
global app
for update in event.events:
# Determine which setting to update, and convert from bytes to str
config_option = settings_reverse_map[update.key.decode("utf-8")]
app.config[config_option] = update.value.decode("utf-8")
# Start to watch for dataservice url changes
# You can also watch entire areas with add_watch_prefix_callback
watch_id = etcd_client.add_watch_callback("/services/dataservice/url", watch_callback)
@app.route("/api")
def what_is_url():
return {"url": app.config["dataservice_url"]}
app.run()
在这个例子中,应用启动时会加载
settings_map
中的键,如
/services/dataservice/url
,后续可验证并使用该值。当 etcd 中的值发生变化时,
watch_callback
函数会在单独线程中运行,并更新应用配置:
$ curl http://127.0.0.1:5000/api
{"url":"https://firsturl.example.com/api"}
$ etcdctl put "/services/dataservice/url" "https://secondurl.example.com/api"
OK
$ curl http://127.0.0.1:5000/api
{"url":"https://secondurl.example.com/api"}
如果应用的配置选项相互依赖,如访问令牌对,最好将它们编码在一个选项中,以便在一次操作中更新。否则,若部分配置更新失败,应用可能会出现意外行为。
3. Docker Compose
在同一主机上运行多个容器时,添加名称、网络和绑定多个套接字的命令可能会很长。Docker Compose(https://docs.docker.com/compose/)可简化此任务,它允许在单个配置文件中定义多个容器的配置,以及这些容器之间的依赖关系。
安装步骤:
- macOS 和 Windows 系统:Docker 安装时会一并安装 Docker Compose。
- Linux 系统:可通过系统包安装,或按 https://docs.docker.com/compose/install/ 中的说明获取安装脚本。
安装脚本后,创建一个包含要运行的服务和网络信息的 yaml 文件,默认文件名是
docker-compose.yml
。以下是一个示例:
version: '3'
networks:
jeeves:
services:
dataservice:
networks:
- jeeves
build:
context: dataservice/
ports:
- "8080:8080"
tokendealer:
networks:
- jeeves
build:
context: tokendealer/
ports:
- "8090:8090"
rabbitmq:
image: "rabbitmq:latest"
networks:
- jeeves
Compose 文件通过
networks
部分创建网络,使容器能够相互通信。容器会获得私有 DNS 条目,可通过镜像名称引用。使用以下命令构建并运行这些容器:
$ docker compose up
首次执行该命令时,会构建两个本地容器镜像。这些镜像可以是静态的,也可以挂载卷以进行源码开发。
使用 Docker Compose 能为微服务提供完整的工作栈,适合小型环境中部署多个容器,且无需管理大型基础设施的场景。不过,对于数据库等服务,虽然可以容器化,但在生产环境中,通常使用专用服务器更合适,因为 Docker 容器是临时文件系统,若使用容器存储数据,需确保数据写入目录挂载在主机文件系统上。
4. Docker Swarm
Docker 内置了名为 swarm 模式(https://docs.docker.com/engine/swarm/)的集群功能。该模式功能丰富,可通过单一工具管理所有容器集群,适合小型部署或对容器伸缩灵活性要求不高的场景。
部署集群后,需设置负载均衡器,如 nginx、OpenResty 或 HAProxy,以实现集群实例间的工作负载共享。
设置 swarm 的步骤如下:
1. 准备三个 EC2 实例,确保可通过端口 22 进行 SSH 访问配置,端口 2377 用于 Docker 通信,并开放应用所需的其他端口,如 443 用于 HTTPS 连接。
2. 使用 SSH 连接到其中一个实例,将其转换为 Docker Swarm 管理器:
$ sudo docker swarm init —advertise-addr <Public IP Address>
- 添加工作节点:
docker swarm join —token <some long token> 52.212.189.167:2377
-
添加管理节点:运行
docker swarm join-token manager并按说明操作。
创建服务:
$ sudo docker service create —replicas 1 —name dataservice jeeves/dataservice
可根据需要扩展服务:
$ sudo docker service scale dataservice=5
只要管理节点可用,部分工作节点正常运行,容器服务就会保持活跃。可使用
docker service ps
查看服务状态,添加节点时,可调整 Terraform 配置并重新运行
terraform apply
,然后将新节点加入 swarm。
5. 不同工具对比
| 工具 | 适用场景 | 特点 |
|---|---|---|
| Docker Compose | 小型环境部署多个容器,无需管理大型基础设施 | 配置简单,适合快速搭建本地开发环境 |
| Docker Swarm | 需要灵活调整容器部署数量以应对变化,且愿意管理大型云基础设施 | 内置集群功能,可通过单一工具管理 |
| Kubernetes | 自动化和灵活性至关重要,且有人员和时间管理基础设施及处理复杂性 | 功能强大,可跨平台自动化管理容器化系统 |
以下是不同工具使用场景的 mermaid 流程图:
graph LR
A[部署需求] --> B{环境规模}
B -->|小型环境| C[Docker Compose]
B -->|大型环境| D{伸缩灵活性}
D -->|灵活性要求低| E[Docker Swarm]
D -->|灵活性要求高| F{自动化需求}
F -->|自动化需求高| G[Kubernetes]
F -->|自动化需求低| E
综上所述,在选择容器编排工具时,需根据自身需求进行评估。不同工具各有优劣,且构建的容器可在不同工具间使用,但切换编排工具可能会因配置复杂程度而带来一定工作量。同时,云提供商也提供了内置功能来处理部署,如 AWS、Google Cloud 和 Microsoft Azure 等。
容器化微服务部署:从基础到高级
6. Kubernetes
Kubernetes(https://kubernetes.io/,也称为 k8s)最初由 Google 设计,现在由独立基金会维护。它提供了一种与平台无关的方式来自动化处理容器化系统,允许用户通过不同组件描述系统,并向控制器发出命令来调整设置。
Kubernetes 运行在服务器集群上。可以自己搭建这个集群,不过一些云提供商提供了相关服务,使管理实例集群变得更加容易。例如,AWS 的 eksctl 工具(https://eksctl.io/),虽然不是由 Amazon 创建,但它是用于在 Amazon 的 Elastic Kubernetes Service 中创建集群的官方支持客户端。
使用 eksctl 进行 Kubernetes 实验的步骤如下:
1. 获取之前示例中的 AWS 凭证。
2. 安装 eksctl 和 kubectl(Kubernetes 命令行工具)。
3. 使用以下命令创建集群:
$ eksctl create cluster —name=jeeves-cluster-1 —nodes=4 —region=eu-west-1
创建集群需要几分钟时间,完成后,它会将 kubectl 需要的凭证写入正确的文件,无需进一步设置。可以使用以下命令查看创建的节点:
$ kubectl get nodes
在 k8s 集群中,基本的工作单元是 Pod,它描述了集群上一组运行的容器。可以使用以下命令查看 Pod:
$ kubectl get pods
$ kubectl get pods —namespace kube-system
为了更方便地管理不同类型的工作,Kubernetes 提供了更高级的抽象,如用于无状态应用的 Deployment(如 Web 界面或代理)、需要附加存储的 StatefulSet、一次性任务的 Jobs 和定时重复任务的 CronJobs。
下面是一个使用 nginx 的示例 manifest 文件:
# nginx.yml
apiVersion: apps/v1
kind: Deployment
metadata:
name: nginx-deployment
labels:
app: nginx
spec:
replicas: 3
selector:
matchLabels:
app: nginx
template:
metadata:
labels:
app: nginx
spec:
containers:
- name: nginx
image: nginx:1.21.0
ports:
- containerPort: 80
使用以下命令应用该 manifest:
$ kubectl apply -f nginx.yml
可以使用以下命令查看创建的 Pod:
$ kubectl get pods
使用
kubectl describe
命令可以获取更多关于创建资源的信息:
$ kubectl describe deployment nginx-deployment
如果需要更多的 nginx 容器,可以更新 manifest 文件中的
replicas
数量,然后重新应用 manifest:
$ kubectl get pods -l app=nginx
Kubernetes 有多种更新服务的策略,以确保最终用户不太可能注意到更新的发生。例如,可以创建全新的容器 Pod 并将流量重定向到它,也可以在 Pod 内进行滚动更新,只有当替换容器成功启动后才销毁原容器。Kubernetes 允许通过存活和就绪检查来确定容器是否成功启动。
完成实验后,可使用以下命令删除创建的资源:
$ kubectl delete -f nginx.yml
$ eksctl delete cluster —name=jeeves-cluster-1 —region=eu-west-1
7. 总结与选择建议
容器化技术在微服务部署中应用广泛,容器化应用具有临时性,设计为可按需销毁和重新创建,未通过挂载点外部化的数据会丢失。
在服务的配置和集群化方面,没有通用的解决方案,选择的工具取决于具体需求。以下是不同场景下的工具选择建议:
-
Docker Compose
:适用于在小型环境中部署多个容器,且无需管理大型基础设施的场景。操作步骤简单,可在单个配置文件中定义多个容器的配置和依赖关系。
-
Docker Swarm
:当需要根据变化的情况灵活调整容器部署数量,并且愿意管理较大的云基础设施时适用。具有内置的集群功能,可通过单一工具管理。
-
Kubernetes
:当自动化和灵活性至关重要,且有人员和时间来管理基础设施并处理复杂性时选择。功能强大,能跨平台自动化管理容器化系统。
选择编排工具后并非被锁定,构建的容器可在不同工具中使用,但切换编排工具可能会因配置复杂程度而带来一定工作量。云提供商为了让服务更易用和有吸引力,也内置了处理部署的功能,目前主要的云提供商有 AWS、Google Cloud 和 Microsoft Azure 等。
在解决容器化部署问题时,建议先手动部署所有内容,然后在合理的地方进行自动化。自动化虽然很好,但如果使用不完全理解或过于复杂的工具集,可能会很快变得困难。
总之,根据自身的实际情况,按照以下步骤选择合适的容器编排工具:
1. 评估部署环境的规模,是小型环境还是大型环境。
2. 考虑对容器伸缩的灵活性要求。
3. 确定对自动化的需求程度。
4. 结合团队的人员和时间情况,判断是否有能力管理基础设施和处理复杂性。
通过以上步骤,就能选择出最适合自己的容器编排工具,实现高效、稳定的微服务部署。
超级会员免费看
945

被折叠的 条评论
为什么被折叠?



