Cassandra 是一个流行的分布式NoSQL数据存储系统。最近有客户问起了Cassandra在如何Docker中运行的一些问题。本文将利用Docker Compose和阿里云容器服务轻松玩转Cassandra。
一键创建Cassandra集群
Docker Hub上已经提供了Cassandra的官方镜像,可以方便地创建单节点Cassandra实例或Cassandra集群。Cassandra采用去中心化的集群架构,没有master节点的概念;但是会有seed节点在新节点连入时通知当前集群。
下面的Docker Compose模板将为你创建一个包含3个节点的Cassandra集群,其中第一个容器“cassandra-1”为seed节点。
version: '2'
services:
cassandra-1:
image: cassandra:3
container_name: cassandra-1
environment:
- CASSANDRA_BROADCAST_ADDRESS=cassandra-1
ports:
- 7000
restart: always
cassandra-2:
image: cassandra:3
container_name: cassandra-2
environment:
- CASSANDRA_BROADCAST_ADDRESS=cassandra-2
- CASSANDRA_SEEDS=cassandra-1
ports:
- 7000
depends_on:
- cassandra-1
restart: always
cassandra-3:
image: cassandra:3
container_name: cassandra-3
environment:
- CASSANDRA_BROADCAST_ADDRESS=cassandra-3
- CASSANDRA_SEEDS=cassandra-1
ports:
- 7000
depends_on:
- cassandra-2
restart: always
注释:这里面一个重要的技巧是:在Docker的容器网络模型中(CNM, Docker Network Model),同一网络中的容器可以通过容器名互相访问。
现在,我们可以轻松利用 docker-compose 命令来启动Cassandra集群了
$ docker-compose up -d
启动之后,我们可以方便地查看集群状态
$ docker-compose ps
Name Command State Ports
----------------------------------------------------------------------------------------------------------------------
cassandra-1 /docker-entrypoint.sh cass ... Up 0.0.0.0:32768->7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp
cassandra-2 /docker-entrypoint.sh cass ... Up 0.0.0.0:32769->7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp
cassandra-3 /docker-entrypoint.sh cass ... Up 0.0.0.0:32770->7000/tcp, 7001/tcp, 7199/tcp, 9042/tcp, 9160/tcp
$ docker exec -ti cassandra-1 cqlsh cassandra-2 -e "DESCRIBE CLUSTER"
Cluster: Test Cluster
Partitioner: Murmur3Partitioner
云端部署Cassandra集群
利用阿里云容器服务,我们可以直接使用上文Compose模板部署Cassandra集群,但是为了防止在相同的ECS实例上部署了超过一个个Cassandra节点,我们可以添加部署约束来指明不同的Cassandra节点部署到不同的ECS示例上。
version: '2'
services:
cassandra-1:
image: cassandra:3
container_name: cassandra-1
environment:
- CASSANDRA_BROADCAST_ADDRESS=cassandra-1
- constraint:aliyun.node_index==1
ports:
- 7000
restart: always
cassandra-2:
image: cassandra:3
container_name: cassandra-2
environment:
- CASSANDRA_BROADCAST_ADDRESS=cassandra-2
- CASSANDRA_SEEDS=cassandra-1
- constraint:aliyun.node_index==2
ports:
- 7000
depends_on:
- cassandra-1
restart: always
cassandra-3:
image: cassandra:3
container_name: cassandra-3
environment:
- CASSANDRA_BROADCAST_ADDRESS=cassandra-3
- CASSANDRA_SEEDS=cassandra-1
- constraint:aliyun.node_index==3
ports:
- 7000
depends_on:
- cassandra-2
restart: always
注释:
- 这个示例需要集群中至少包含3个节点
constraint:aliyun.node_index
约束可以方便地指明将容器部署到集群中的第几个节点
官方Cassandra镜像的问题
在Overlay等网络使用官方Cassandra 2.2镜像的时候,如果没有指明CASSANDRA_LISTEN_ADDRESS我们会遇到一个 “Unknown listen_address” 的问题,
这个原因是因为在镜像的“docker-entrypoint.sh”脚本中,的如下代码
CASSANDRA_LISTEN_ADDRESS="$(hostname --ip-address)"
然而在Overlay网络环境中,容器会包含多块网卡,而hostname --ip-address
会返回所有网卡的IP地址导致CASSANDRA_LISTEN_ADDRESS的格式出现问题,一个简单的修正就是使用下面的命令来获取eth0网卡的IP地址
CASSANDRA_LISTEN_ADDRESS="$(hostname --ip-address | cut -d " " -f1)"
在社区中相应的Pull Request为 https://github.com/docker-library/cassandra/pull/77 大家如果遇到了类似的问题可以参考。
总结
利用Docker和Docker Compose模板可以轻松部署Cassandra集群。阿里云容器服务可以轻松复用Docker Compose模板,并添加约束支持灵活的部署控制。
想了解更多容器服务内容,请访问 https://www.aliyun.com/product/containerservice