我正在使用 eksctl 在 EKS/AWS 上设置集群。
按照 EKS 文档中的指南,我对几乎所有内容都使用默认值。
集群创建成功,我从集群更新了 Kubernetes 配置,并且可以成功运行各种 kubectl 命令 - 例如“kubectl get nodes”显示节点处于“就绪”状态。
我没有动任何其他东西,我有一个干净的开箱即用的集群,没有做任何其他更改,到目前为止,一切似乎都按预期运行。我没有向它部署任何应用程序,我只是让它保持原样。
问题是,在一段相对较短的时间内(大约在集群创建后 30 分钟),节点从“就绪”变为“未就绪”,并且永远无法恢复。
事件日志显示了这一点(我删除了IP):
LAST SEEN TYPE REASON OBJECT MESSAGE
22m Normal Starting node/ip-[x] Starting kubelet.
22m Normal NodeHasSufficientMemory node/ip-[x] Node ip-[x] status is now: NodeHasSufficientMemory
22m Normal NodeHasNoDiskPressure node/ip-[x] Node ip-[x] status is now: NodeHasNoDiskPressure
22m Normal NodeHasSufficientPID node/ip-[x] Node ip-[x] status is now: NodeHasSufficientPID
22m Normal NodeAllocatableEnforced node/ip-[x] Updated Node Allocatable limit across pods
22m Normal RegisteredNode node/ip-[x] Node ip-[x] event: Registered Node ip-[x] in Controller
22m Normal Starting node/ip-[x] Starting kube-proxy.
21m Normal NodeReady node/ip-[x] Node ip-[x] status is now: NodeReady
7m34s Normal NodeNotReady node/ip-[x] Node ip-[x] status is now: NodeNotReady
集群中其他节点也发生相同事件。
连接到实例并检查 /var/log/messages 时显示,同时节点进入 NotReady 状态:
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.259207 3896 kubelet_node_status.go:385] Error updating node status, will retry: error getting node "ip-[x]": Unauthorized
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.385044 3896 kubelet_node_status.go:385] Error updating node status, will retry: error getting node "ip-[x]": Unauthorized
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.621271 3896 reflector.go:270] object-"kube-system"/"aws-node-token-bdxwv": Failed to watch *v1.Secret: the server has asked for the client to provide credentials (get secrets)
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.621320 3896 reflector.go:270] object-"kube-system"/"coredns": Failed to watch *v1.ConfigMap: the server has asked for the client to provide credentials (get configmaps)
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.638850 3896 reflector.go:270] k8s.io/client-go/informers/factory.go:133: Failed to watch *v1beta1.RuntimeClass: the server has asked for the client to provide credentials (get runtimeclasses.node.k8s.io)
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.707074 3896 reflector.go:270] k8s.io/kubernetes/pkg/kubelet/config/apiserver.go:47: Failed to watch *v1.Pod: the server has asked for the client to provide credentials (get pods)
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.711386 3896 reflector.go:270] object-"kube-system"/"coredns-token-67fzd": Failed to watch *v1.Secret: the server has asked for the client to provide credentials (get secrets)
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.714899 3896 reflector.go:270] object-"kube-system"/"kube-proxy-config": Failed to watch *v1.ConfigMap: the server has asked for the client to provide credentials (get configmaps)
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.720884 3896 kubelet_node_status.go:385] Error updating node status, will retry: error getting node "ip-[x]": Unauthorized
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.868003 3896 kubelet_node_status.go:385] Error updating node status, will retry: error getting node "ip-[x]": Unauthorized
Mar 7 10:40:37 ip-[X] kubelet: E0307 10:40:37.868067 3896 controller.go:125] failed to ensure node lease exists, will retry in 200ms, error: Get https://[X]/apis/coordination.k8s.io/v1beta1/namespaces/kube-node-lease/leases/ip-[x]?timeout=10s: write tcp 192.168.91.167:50866->34.249.27.158:443: use of closed network connection
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.017157 3896 kubelet_node_status.go:385] Error updating node status, will retry: error getting node "ip-[x]": Unauthorized
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.017182 3896 kubelet_node_status.go:372] Unable to update node status: update node status exceeds retry count
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.200053 3896 controller.go:125] failed to ensure node lease exists, will retry in 400ms, error: Unauthorized
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.517193 3896 reflector.go:270] object-"kube-system"/"kube-proxy": Failed to watch *v1.ConfigMap: the server has asked for the client to provide credentials (get configmaps)
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.729756 3896 controller.go:125] failed to ensure node lease exists, will retry in 800ms, error: Unauthorized
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.752267 3896 reflector.go:126] object-"kube-system"/"aws-node-token-bdxwv": Failed to list *v1.Secret: Unauthorized
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.824988 3896 reflector.go:126] object-"kube-system"/"coredns": Failed to list *v1.ConfigMap: Unauthorized
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.899566 3896 reflector.go:126] k8s.io/client-go/informers/factory.go:133: Failed to list *v1beta1.RuntimeClass: Unauthorized
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.963756 3896 reflector.go:126] k8s.io/client-go/informers/factory.go:133: Failed to list *v1beta1.CSIDriver: Unauthorized
Mar 7 10:40:38 ip-[X] kubelet: E0307 10:40:38.963822 3896 reflector.go:126] object-"kube-system"/"kube-proxy-config": Failed to list *v1.ConfigMap: Unauthorized
身份验证器组件的 CloudWatch 日志显示了许多以下消息:
time="2020-03-07T10:40:37Z" level=warning msg="access denied" arn="arn:aws:iam::[ACCOUNT_ID]]:role/AmazonSSMRoleForInstancesQuickSetup" client="127.0.0.1:50132" error="ARN is not mapped: arn:aws:iam::[ACCOUNT_ID]:role/amazonssmroleforinstancesquicksetup" method=POST path=/authenticate
我通过 IAM 控制台确认该角色确实存在。
显然,由于这些身份验证失败,该节点报告 NotReady。
这是大约 30 分钟后超时的身份验证令牌吗?如果是这样,难道不应该自动请求新令牌吗?还是我应该设置其他东西?
我很惊讶 eksctl 创建的新集群会出现这个问题。
我错过了什么?
答案1
这些是我解决此问题所遵循的步骤...
通过 SSH 连接到失败的实例。
执行“aws sts get-caller-identity”
记下用户的 ARN,它可能是这样的 arn:aws:sts::999999999999:assumed-role/AmazonSSMRoleForInstancesQuickSetup/i-00000000000ffffff
请注意,这里的角色是 AmazonSSMRoleForInstancesQuickSetup,这对我来说似乎是错误的 - 但据我所知,我在创建集群时严格遵循了指南。
目前存在的问题:
a) 为什么此角色用于 AWS 身份?
b) 如果这是正确的角色,为什么它一开始就成功,但在集群创建 30 分钟后才失败?
c) 如果这是正确的角色,缺少哪些访问权限?
就我个人而言,我觉得这对我来说是错误的角色,但我通过解决要点 (c) 解决了我的问题。
继续步骤...
- 如果通过 AWS 控制台中的 IAM 服务检查此角色,则可以看到它没有所有必需的权限,默认情况下它具有:
- AmazonSSMManagedInstanceCore
- 假设此角色是正确的角色,那么它至少需要添加以下策略:
- AmazonEC2ContainerRegistryPowerUser
以通常的方式附加该策略,我承认这可能会授予比需要更多的权限,但那是另一回事了。
至此,AWS 安全配置应该是正确的,但这并不是故事的结束。
- Kubernetes 通过 kubelet 进程有自己的安全角色映射需要考虑——即将 Kubernetes 用户映射到 IAM 用户或 AWS 上的角色。
通过编辑 Kubernetes 配置映射来维护此配置。
使用“kubectl edit -n kube-system configmap/aws-auth”编辑配置映射。
这是创建集群之后、进行任何更改之前的配置:
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::999999999999:role/eksctl-my-demo-nodegroup-my-demo-NodeInstanceRole-AAAAAAAAAAAAA
username: system:node:{{EC2PrivateDNSName}}
kind: ConfigMap
metadata:
[...whatever...]
这里映射的唯一角色是节点实例角色 —— 该角色是在通过配置集群期间自动创建的eksctl
。
- 更改配置图:
apiVersion: v1
data:
mapRoles: |
- rolearn: arn:aws:iam::999999999999:role/eksctl-my-demo-nodegroup-my-demo-NodeInstanceRole-AAAAAAAAAAAAA
username: system:node:{{EC2PrivateDNSName}}
groups:
- system:bootstrappers
- system:nodes
- rolearn: arn:aws:iam::999999999999:role/AmazonSSMRoleForInstancesQuickSetup
username: MyDemoEKSRole
groups:
- system:masters
- rolearn: arn:aws:iam::999999999999:role/MyDemoEKSRole
username: CodeBuild
groups:
- system:masters
- system:bootstrappers
- system:nodes
kind: ConfigMap
metadata:
[...whatever...]
我已将 AmazonSSMRoleForInstancesQuickSetup 角色映射为 Kubernetes 主角色。
我还将MyDemoEKSRole
先前为集群配置创建的集群安全角色映射到各种 Kubernetes 角色,以供 Kubernetes 被 CodeBuild 管道调用的情况。
- 保存此配置图,最终集群将自我修复并报告准备就绪。
结论:
执行完所有这些集群创建后步骤后,我的身份验证失败就消失了,集群再次开始报告成功状态,清除健康检查并将节点返回到状态Ready
。
我坦率地承认这可能不是解决我的问题的“正确”方法,并且确实感觉我开放的安全方式比我应该开放的要多,但它确实有效并解决了我的问题。
正如此后不久提到的,我们转换到了 Azure 而不是 AWS,所以我没有再采取任何进一步的行动 - 但我最终得到了一个完全正常运行的集群,并且不再有任何过期的凭据。
我天真地以为这些工具能帮我创建一个工作集群。我发现的任何指南中都没有提到这个问题或这些步骤。
答案2
您的角色似乎即将到期。
您可以从Amazon EKS 故障排除部分Unauthorized or Access Denied (kubectl)
。
如果在运行时收到以下错误之一 库布克 命令,然后你的 库布克 没有为 Amazon EKS 正确配置,或者您使用的 IAM 用户或角色凭证未映射到 Amazon EKS 集群中具有足够权限的 Kubernetes RBAC 用户。
could not get token: AccessDenied: Access denied
error: You must be logged in to the server (Unauthorized)
error: the server doesn't have a resource type "svc"
这可能是因为集群是使用一组 AWS 凭证(来自 IAM 用户或角色)创建的,并且 库布克 正在使用一组不同的凭证。
创建 Amazon EKS 集群时,创建集群的 IAM 实体(用户或角色)将作为管理员(具有
system:master
权限)添加到 Kubernetes RBAC 授权表中。最初,只有该 IAM 用户可以使用 库布克更多信息,请参阅 管理集群的用户或 IAM 角色。此外, 适用于 Kubernetes 的 AWS IAM 身份验证器 使用 AWS SDK for Go 针对您的 Amazon EKS 集群进行身份验证。如果您使用控制台创建集群,则必须确保在运行 库布克 命令。如果您安装并配置了 AWS CLI,则可以为您的用户配置 IAM 凭证。如果为您的用户正确配置了 AWS CLI,则 适用于 Kubernetes 的 AWS IAM 身份验证器 也可以找到这些凭据。有关详细信息,请参阅 配置 AWS CLI 在里面 AWS 命令行界面用户指南。
如果您承担创建 Amazon EKS 集群的角色,则必须确保 库布克 配置为承担相同的角色。使用以下命令更新 kubeconfig 文件以使用 IAM 角色。有关更多信息,请参阅 为 Amazon EKS 创建 kubeconfig。
aws --region `region-code` eks update-kubeconfig --name `cluster_name` --role-arn arn:aws:iam::`aws_account_id`:role/`role_name
要将 IAM 用户映射到 Kubernetes RBAC 用户,请参阅 管理集群的用户或 IAM 角色 或者观看 视频 关于如何映射用户。
你应该阅读管理集群身份验证对于 AWS 和为 Amazon EKS 创建 kubeconfig。
请记住,您应该使用aws-iam-authenticator
可用的安装过程这里。
答案3
部署节点组时,必须授予节点组角色,如下所述在文档中(aws-auth-cm.yaml)
尽管所有 pod 看起来都正常,但我的节点在启动后约 7 分钟内进入 NotReady 状态,并出现类似上述问题的错误。
原因:由于输入错误,nodegroup 的角色与该 yaml 中的角色不一样。