记录一条HPA:TARGETS <unknown>/50%解决方法

本文介绍了如何在安装metrics-server后遇到的HPA无法获取metrics值的问题,通过在kube-controller-manager配置文件中添加`--horizontal-pod-autoscaler-use-rest-clients=false`并重启服务,成功解决了这个问题。

前言:我已经安装了metrics-server可以正常获取到pod资源分配情况如下:
在这里插入图片描述这里我已经加入了PHA弹性伸缩但是查看结果如下:
在这里插入图片描述于是我查看了一下pod详细信息发现:HPA无法通过API获取到metrics值。
使用kubectl describe命令:信息如下
在这里插入图片描述解决方法如下:
在 /opt/kubernetes/cfg/kube-controller-manager.conf 配置文件中新增 --horizontal-pod-autoscaler-use-rest-clients=false 配置参数。然后重启kube-controller-manager服务即可。

看下结果:
在这里插入图片描述问题解决

<think> 我们设计一个工具类,它需要处理两种类型的数据结构: 1. `std::list<std::pair<std::string, double>>`:简单的键值对列表。 2. `std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>`:嵌套的键值对,其中值是一个键值对列表。 我们需要根据键(字符串)从这两种结构中获取值。 思路: 1. 对于第一种结构(`std::list<std::pair<std::string, double>>`),我们可以直接遍历列表,找到匹配的键,返回对应的double值。 2. 对于第二种结构(嵌套结构),我们有两种可能的需求: a. 从外层列表中根据键获取内层的整个列表(即`std::list<std::pair<std::string, double>>`)。 b. 从内层列表中根据键获取具体的double值,但需要指定外层键和内层键。 因此,我们可以设计一个工具类,提供以下功能: - 从简单列表中获取值:给定键,返回double值(如果找到的话)。 - 从嵌套列表中获取整个内层列表:给定外层键,返回内层列表。 - 从嵌套列表中通过两层键获取具体的double值:给定外层键和内层键,返回内层键对应的double值。 由于数据结构不同,我们可以使用函数重载。 注意:由于可能找不到键,我们需要考虑返回值的情况。这里我们可以使用`std::optional`来避免返回无效值或使用异常。 设计工具类`PairListUtils`,包含静态成员函数: 1. 针对简单列表的查找: ```cpp static std::optional<double> getValue( const std::list<std::pair<std::string, double>>& list, const std::string& key); ``` 2. 针对嵌套列表的查找(获取内层列表): ```cpp static std::optional<std::list<std::pair<std::string, double>>> getList( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey); ``` 3. 针对嵌套列表的两层键查找(直接获取内层键对应的值): ```cpp static std::optional<double> getValue( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey, const std::string& innerKey); ``` 实现: 对于简单列表的查找,遍历列表,找到匹配的键,返回对应的值;找不到则返回`std::nullopt`。 对于嵌套列表的查找,先在外层列表中查找outerKey,找到则返回整个内层列表(注意:返回的是整个列表的副本,如果列表很大,考虑返回引用?但注意,返回引用可能面临生命周期问题,所以这里返回一个optional的列表。或者返回指针?但optional可以包装值类型,也可以包装引用类型,但这里我们返回整个列表的副本,因为列表可能被修改,且我们不希望工具类修改原始数据,所以返回副本是安全的。但性能上,如果列表很大,复制可能开销大。另一种方法是返回`std::optional<std::reference_wrapper<const std::list<...>>>`,这样可以避免复制。用户可以根据需要选择。) 但是,考虑到性能,我们可以提供两种版本:返回副本和返回常量引用。但为了简单,我们先返回副本。 然而,在嵌套列表的两层查找中,我们可以先找到内层列表,然后在内层列表中查找innerKey。 代码示例: 注意:由于C++中模板的使用,我们也可以考虑使用模板函数来避免重复,但这里数据结构不同,我们使用重载。 我们先实现第一个函数(简单列表): ```cpp #include <list> #include <string> #include <optional> #include <utility> // for pair class PairListUtils { public: static std::optional<double> getValue( const std::list<std::pair<std::string, double>>& list, const std::string& key) { for (const auto& pair : list) { if (pair.first == key) { return pair.second; } } return std::nullopt; } }; ``` 第二个函数(获取嵌套列表中的内层列表): ```cpp static std::optional<std::list<std::pair<std::string, double>>> getList( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey) { for (const auto& outerPair : nestedList) { if (outerPair.first == outerKey) { return outerPair.second; // 返回整个内层列表的副本 } } return std::nullopt; } ``` 第三个函数(通过两层键获取值): ```cpp static std::optional<double> getValue( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey, const std::string& innerKey) { // 先找到外层键对应的内层列表 for (const auto& outerPair : nestedList) { if (outerPair.first == outerKey) { // 在内层列表中查找innerKey for (const auto& innerPair : outerPair.second) { if (innerPair.first == innerKey) { return innerPair.second; } } // 内层列表没有找到innerKey,返回nullopt return std::nullopt; } } return std::nullopt; } ``` 但是,第三个函数中,我们遍历了外层列表和内层列表,效率较低,但这是线性查找,对于小规模数据可以接受。 另外,我们也可以利用第二个函数来实现第三个函数: ```cpp static std::optional<double> getValue( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey, const std::string& innerKey) { auto innerListOpt = getList(nestedList, outerKey); if (innerListOpt) { // 在获取到的内层列表中查找 return getValue(innerListOpt.value(), innerKey); } return std::nullopt; } ``` 这样代码更简洁,但效率上多了一次内层列表的复制(因为getList返回的是整个列表的副本)。为了避免复制,我们可以修改getList返回引用。但是,返回引用需要确保传入的nestedList在函数返回后仍然存在,因为返回的是其内部元素的引用。我们可以修改getList返回一个指向常量的指针(或者返回`optional<reference_wrapper<const ...>>`)来避免复制。 修改第二个函数,返回常量引用的optional(实际上optional可以包装引用类型,但需要显式指定): 但是,optional包装引用类型需要使用`std::optional<std::reference_wrapper<const T>>`。 修改如下: 第二个函数(返回内层列表的常量引用): ```cpp static std::optional<std::reference_wrapper<const std::list<std::pair<std::string, double>>>> getList( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey) { for (const auto& outerPair : nestedList) { if (outerPair.first == outerKey) { return std::cref(outerPair.second); } } return std::nullopt; } ``` 然后,第三个函数可以这样实现(避免复制内层列表): ```cpp static std::optional<double> getValue( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey, const std::string& innerKey) { auto innerListOpt = getList(nestedList, outerKey); if (innerListOpt) { // 获取到内层列表的引用,然后调用第一个getValue函数(注意:第一个getValue函数接受的是简单列表,而这里我们有一个引用包装,需要调用getValue时解引用) return getValue(innerListOpt->get(), innerKey); } return std::nullopt; } ``` 但是,这里出现了一个问题:第一个getValue函数接受的是`const std::list<std::pair<std::string, double>>&`,而`innerListOpt->get()`返回的是`const std::list<...>&`,所以可以直接传递。 但是,我们第一个getValue函数是重载的,它接受简单列表,所以可以匹配。 但是,由于我们修改了第二个函数的返回类型,那么用户如果只需要内层列表,现在得到的是一个`optional`包装的引用包装器,使用起来需要调用`.get()`来获取实际的引用。 例如: ```cpp auto innerListOpt = PairListUtils::getList(nestedList, "outer"); if (innerListOpt) { const auto& innerList = innerListOpt->get(); // 得到常量引用 // 使用innerList } ``` 这样避免了复制大列表。 另外,第一个函数(简单列表的查找)我们保持不变。 但是,我们也可以为第一个函数提供一个接受常量引用的重载,这样在第三个函数中调用时就不会有额外的复制。 因此,我们最终设计如下: 头文件: ```cpp #include <list> #include <string> #include <optional> #include <functional> // for reference_wrapper, cref class PairListUtils { public: // 针对简单列表:根据键获取值 static std::optional<double> getValue( const std::list<std::pair<std::string, double>>& list, const std::string& key); // 针对嵌套列表:根据外层键获取内层列表(返回常量引用,避免复制) static std::optional<std::reference_wrapper<const std::list<std::pair<std::string, double>>>> getList( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey); // 针对嵌套列表:直接通过外层键和内层键获取内层值 static std::optional<double> getValue( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey, const std::string& innerKey); }; ``` 实现: ```cpp std::optional<double> PairListUtils::getValue( const std::list<std::pair<std::string, double>>& list, const std::string& key) { for (const auto& pair : list) { if (pair.first == key) { return pair.second; } } return std::nullopt; } std::optional<std::reference_wrapper<const std::list<std::pair<std::string, double>>>> PairListUtils::getList( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey) { for (const auto& outerPair : nestedList) { if (outerPair.first == outerKey) { return std::cref(outerPair.second); } } return std::nullopt; } std::optional<double> PairListUtils::getValue( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey, const std::string& innerKey) { auto innerListOpt = getList(nestedList, outerKey); if (innerListOpt) { // 调用第一个getValue函数,传入内层列表的常量引用 return getValue(innerListOpt->get(), innerKey); } return std::nullopt; } ``` 这样,我们避免了内层列表的复制,提高了效率。 注意:如果用户需要修改获取到的内层列表,那么我们的设计就不合适了,因为我们返回的是常量引用。根据需求,工具类一般用于查询,所以常量引用是合适的。 另外,如果数据结构很大,查找效率低,可以考虑使用其他数据结构(如std::map)来替代std::list,但这里用户给的是list,所以我们按线性查找实现。 使用示例: 对于简单列表: ```cpp std::list<std::pair<std::string, double>> simpleList = {{"a", 1.0}, {"b", 2.0}}; auto value = PairListUtils::getValue(simpleList, "a"); if (value) { std::cout << *value << std::endl; // 输出1.0 } ``` 对于嵌套列表,获取内层列表: ```cpp std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>> nestedList = {{"outer1", {{"x", 1.0}, {"y", 2.0}}}, {"outer2", {{"z", 3.0}}}}; auto innerListOpt = PairListUtils::getList(nestedList, "outer1"); if (innerListOpt) { const auto& innerList = innerListOpt->get(); for (const auto& p : innerList) { std::cout << p.first << ": " << p.second << std::endl; } } ``` 对于嵌套列表,直接获取内层值: ```cpp auto val = PairListUtils::getValue(nestedList, "outer1", "x"); if (val) { std::cout << *val << std::endl; // 输出1.0 } ``` 这样,工具类就设计完成了。 注意:我们假设键是唯一的(在同一个列表中),如果同一个列表中有重复的键,我们返回第一个匹配的值。如果需求是返回所有匹配的值,那么我们需要修改设计,但这里按照第一个匹配设计。 另外,我们可以考虑使用模板来泛化键的类型(比如支持其他类型的键,不仅仅是string)和值的类型(不仅仅是double),但根据问题,我们只处理string和double。 最后,生成相关问题。 </think> ### 从嵌套键值对结构中获取值的工具类设计 我将为您设计一个工具类,用于从两种嵌套结构中根据键获取值。以下是实现方案: ```cpp #include <list> #include <string> #include <optional> #include <stdexcept> class PairValueExtractor { public: // 从简单列表获取值: std::list<std::pair<std::string, double>> static std::optional<double> getValue( const std::list<std::pair<std::string, double>>& simpleList, const std::string& key) { for (const auto& pair : simpleList) { if (pair.first == key) { return pair.second; } } return std::nullopt; } // 从嵌套列表获取内层值: std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>> static std::optional<double> getValue( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey, const std::string& innerKey) { // 查找外层键 for (const auto& outerPair : nestedList) { if (outerPair.first == outerKey) { // 在内层列表中查找内层键 for (const auto& innerPair : outerPair.second) { if (innerPair.first == innerKey) { return innerPair.second; } } } } return std::nullopt; } // 获取整个内层列表 static std::optional<std::list<std::pair<std::string, double>>> getInnerList( const std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>>& nestedList, const std::string& outerKey) { for (const auto& outerPair : nestedList) { if (outerPair.first == outerKey) { return outerPair.second; } } return std::nullopt; } }; ``` ### 使用示例 ```cpp #include <iostream> int main() { // 简单列表示例 std::list<std::pair<std::string, double>> simpleData = { {"temperature", 23.5}, {"pressure", 1013.25}, {"humidity", 45.0} }; // 嵌套列表示例 std::list<std::pair<std::string, std::list<std::pair<std::string, double>>>> nestedData = { {"sensor1", {{"temp", 22.1}, {"pressure", 1012.8}}}, {"sensor2", {{"temp", 24.3}, {"humidity", 50.2}}}, {"sensor3", {{"temp", 21.7}, {"pressure", 1013.5}, {"humidity", 48.9}}} }; // 从简单列表获取值 if (auto value = PairValueExtractor::getValue(simpleData, "pressure")) { std::cout << "Pressure: " << *value << " hPa\n"; } // 从嵌套列表获取值 if (auto value = PairValueExtractor::getValue(nestedData, "sensor2", "temp")) { std::cout << "Sensor2 temp: " << *value << "°C\n"; } // 获取整个内层列表 if (auto innerList = PairValueExtractor::getInnerList(nestedData, "sensor3")) { std::cout << "Sensor3 values:\n"; for (const auto& pair : *innerList) { std::cout << " " << pair.first << ": " << pair.second << "\n"; } } return 0; } ``` ### 设计要点说明 1. **多态接口设计**: - 使用重载函数处理不同数据结构 - 简单列表只需单个键参数 - 嵌套列表需要外层键和内层键两个参数 2. **安全返回值处理**: - 使用 `std::optional` 避免异常或无效返回值 - 当键不存在时返回 `std::nullopt` - 调用方可通过 `*value` 或 `value.value()` 获取值 3. **嵌套结构支持**: - 提供 `getInnerList()` 获取整个内层列表 - 支持任意层级嵌套(通过递归调用) 4. **类型安全**: - 严格保持键为 `std::string` 类型 - 值统一为 `double` 类型(可根据需求模板化) 5. **性能考虑**: - 线性搜索 $O(n)$ 适用于小型列表 - 对于大型数据集,建议改用 `std::map` 或 `std::unordered_map` ### 扩展建议 1. 添加模板支持: ```cpp template <typename K, typename V> class GenericPairExtractor { // 可支持任意键值类型 }; ``` 2. 添加缓存机制: ```cpp static std::unordered_map<std::string, double> cache; ``` 3. 添加批量查询接口: ```cpp static std::vector<double> getValues( const ContainerType& container, const std::vector<std::string>& keys); ``` 这种设计允许从复杂嵌套结构中高效提取数据,同时保持接口简洁性和类型安全性。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值