更新多个 EC2 实例的日志级别

Updating log level on multiple EC2 instances

我的应用程序在多个 EC2 实例上运行以确保高可用性。应用程序的默认日志级别为 INFO。但有时出于调试目的,我想将日志级别更新为DEBUG。更新日志级别的请求通过 ElasticLoadBalancer 将请求委托给多个 EC2 实例中的任何一个。该实例上应用 运行 的日志级别已更新,但其他实例上的应用仍将以级别 INFO 登录。我希望所有应用程序都以 DEBUG 级别登录。

我正在使用 Spring、SLF4J 和 Logback。

如果我以某种方式使日志级别信息集中化,并且请求将更新集中位置的级别,但仍然有人必须向所有实例上的应用程序告知有关更改的信息,因为应用程序永远不会请求日志等级.

你可能想看看 Zookeeper:

ZooKeeper is a centralized service for maintaining configuration information, naming, providing distributed synchronization, and providing group services.

设置和从小处着手非常容易。 EC2 节点上的应用 运行 只需要实现一个 "listener/watcher" 接口。这将在某些配置更改时通知您的应用程序(例如,您决定将全局日志级别设置为 DEBUG)。

基于这个configuration-change,你所有的节点都会更新本地log-level而不用你想出各种ELB-bypassing手册REST-calls来告诉要更新的每个节点——zookeeper 正在解决的问题:

Each time they are implemented there is a lot of work that goes into fixing the bugs and race conditions that are inevitable. Because of the difficulty of implementing these kinds of services, applications initially usually skimp on them ,which make them brittle in the presence of change and difficult to manage. Even when done correctly, different implementations of these services lead to management complexity when the applications are deployed.


当这对您有用时,您可以根据需要向 zookeeper 添加额外的配置,限制您需要打包到部署的应用程序中或与它们一起复制的配置量。

如果您需要 AWS 解决方案,您可以使用 sns。

一旦您的应用程序被实例化,将其端点(使用它的私有 ip)注册到 sns 主题以获取 http 通知。 因此,您可以发出 sns 消息,而不是通过负载平衡器更改您的日志级别,该消息将发送到注册的端点。

请记住在应用程序终止后从 sns 中注销 http 端点。

Amazons Remote Management(运行 命令)允许您在您的实例上执行 运行 命令。您只需要一个简单的脚本来更改日志级别。

但是设置起来并不容易,而且设置grant all the needed IAM rights:

实例有标签。默认存在一些标签,您可以创建自己的标签。因此,如果我们添加一个标签来标识应用程序当前所在的所有实例 运行,我们可以非常轻松地获取所有这些实例的 IP 地址。

DescribeInstancesRequest request = new DescribeInstancesRequest();

Filter filter1 = new Filter("tag:Environment", Collections.singletonList("Sandbox"));
Filter filter2 = new Filter("tag:Application", Collections.singletonList("xxxxx"));
Filter filter3 = new Filter("tag:Platform", Collections.singletonList("xxxx"));

InstanceProfileCredentialsProvider mInstanceProfileCredentialsProvider =
                new InstanceProfileCredentialsProvider();
AWSCredentials credentials = mInstanceProfileCredentialsProvider.getCredentials();

AmazonEC2 ec2Client = new AmazonEC2Client(credentials);
List<String> privateIps = new ArrayList<>();

ec2Client.describeInstances(request.withFilters(filter1, filter2, filter3)).getReservations().forEach(
                reservation -> reservation
                        .getInstances()
                        .forEach(instance -> privateIps.add(instance.getPrivateIpAddress())));

for (String privateIp : privateIps) {
     hitTheInstance(privateIp);
}

在这里,我使用了3个标签来过滤实例。