EKS kubelet의 권한과 Node Authorization
By Bys on October 5, 2023
1. Kubelet은 어떤 권한을 가질까?
가장 먼저 ps 커맨드를 통해 kubelet 프로세스를 확인하면 kubeconfig
옵션을 통해 kubeconfig 파일의 위치를 /var/lib/kubelet/kubeconfig
로 지정하고 있음을 알 수 있다.
ps -ef | grep kubelet
root 29136 1 1 Oct04 ? 00:09:22 /usr/bin/kubelet --config /etc/kubernetes/kubelet/kubelet-config.json --kubeconfig /var/lib/kubelet/kubeconfig --container-runtime-endpoint unix:///run/containerd/containerd.sock --image-credential-provider-config /etc/eks/image-credential-provider/config.json --image-credential-provider-bin-dir /etc/eks/image-credential-provider --node-ip=10.20.41.45 --pod-infra-container-image=602401143452.dkr.ecr.ap-northeast-2.amazonaws.com/eks/pause:3.5 --v=2 --hostname-override=ip-10-20-41-45.ap-northeast-2.compute.internal --cloud-provider=external
노드에 접속하여 kubeconfig 파일을 확인해보면 다음과 같이 kubeconfig 파일이 정의되어 있는 것을 확인할 수 있다.
apiVersion: v1
kind: Config
clusters:
- cluster:
certificate-authority: /etc/kubernetes/pki/ca.crt
server: https://xxxxx.gr7.ap-northeast-2.eks.amazonaws.com
name: kubernetes
contexts:
- context:
cluster: kubernetes
user: kubelet
name: kubelet
current-context: kubelet
users:
- name: kubelet
user:
exec:
apiVersion: client.authentication.k8s.io/v1beta1
command: /usr/bin/aws-iam-authenticator
args:
- "token"
- "-i"
- "eks-test"
- --region
- "ap-northeast-2"
따라서 kubelet은 aws-iam-authenticator token을 통해 API서버로 요청하면 인증/인가 과정이 이뤄지게 된다.
그렇다면 Kubelet은 어떤 IAM Role/User를 통해 권한을 받게될까?
- 바로 노드가 사용하는 IAM Role인 my-node-role이다.
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::111122223333:role/my-node-role
username: system:node:
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
my-node-role을 사용하는 IAM Role에 대해서는 system:bootstrappers, system:nodes 그룹을 리턴해준다.
그렇다면 system:bootstrappers, system:nodes 그룹은 어떤 권한을 가지고 있을까?
ClusterRoleBinding 리소스에 매핑된 내용을 확인해보면 eks:node-bootstrapper
ClusterRole 외 에는 맵핑된 ClusterRole이 없는 것을 확인할 수 있다.
Name: eks:node-bootstrapper
Labels: eks.amazonaws.com/component=node
Annotations: <none>
Role:
Kind: ClusterRole
Name: eks:node-bootstrapper
Subjects:
Kind Name Namespace
---- ---- ---------
Group system:bootstrappers
Group system:nodes
그렇다면 eks:node-bootstrapper ClusterRole은 어떤 권한을 가지고 있을까?
특이하게도 자기 자신 노드에 대한 인증서에대한 서명 요청 외에는 권한이 없다. 이는 최초 노드 등록 후 자기 자신 서버에 대한 kubelet이 서버로 동작하기 위한 CSR 요청을 하기 위한 권한이다.
$ kubectl describe clusterrole eks:node-bootstrapper
Name: eks:node-bootstrapper
Labels: eks.amazonaws.com/component=node
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
certificatesigningrequests.certificates.k8s.io/selfnodeserver [] [] [create]
그렇다면 Kubelet은 어떻게 KUBE-API 서버로 많은 권한을 가지고 요청을 할 수 있을까?
아래는 Amazon EKS에서 API 서버의 feature를 확인해보면 EKS에서는 authorization-mode로 Node, RBACK, Webhook 3가지를 사용하는 것을 확인할 수 있다.
CloudWatch Logs Insights
fields @message
| filter @logStream like /^kube-apiserver-/
| filter @logStream not like /^kube-apiserver-audit/
| filter @message like "FLAG"
| sort @timestamp desc
| @message | — | | I1001 04:09:41.141998 10 flags.go:64] FLAG: –authorization-mode=”[Node,RBAC,Webhook]” | | I1001 04:09:41.142161 10 flags.go:64] FLAG: –enable-admission-plugins=”[NodeRestriction,ExtendedResourceToleration]” | —
- Kubelet은 kubeconfig를 사용하여 API서버와 통신
apiVersion: v1 kind: Config clusters: - cluster: certificate-authority: /etc/kubernetes/pki/ca.crt server: https://A8845D3F0E5C385227204D33B8635ABC.sk1.ap-northeast-2.eks.amazonaws.com name: kubernetes contexts: - context: cluster: kubernetes user: kubelet name: kubelet current-context: kubelet users: - name: kubelet user: exec: apiVersion: client.authentication.k8s.io/v1beta1 command: /usr/bin/aws-iam-authenticator args: - "token" - "-i" - "bys-dev-eks-main" - --region - "ap-northeast-2"
- aws-iam-authenticator에 의해서 얻는 권한은 eks:node-bootstrapper clusterrole
이 권한은 오로지 CSR 생성을 하기 위해서만 얻어지는 권한이다. eks:node-bootstrapper
# kubectl describe clusterrolebinding eks:node-bootstrapper Name: eks:node-bootstrapper Labels: eks.amazonaws.com/component=node Annotations: <none> Role: Kind: ClusterRole Name: eks:node-bootstrapper Subjects: Kind Name Namespace ---- ---- --------- Group system:bootstrappers Group system:nodes
# kubectl describe clusterrole eks:node-bootstrapper
Name: eks:node-bootstrapper
Labels: eks.amazonaws.com/component=node
Annotations: <none>
PolicyRule:
Resources Non-Resource URLs Resource Names Verbs
--------- ----------------- -------------- -----
certificatesigningrequests.certificates.k8s.io/selfnodeserver [] [] [create]
- 그 외 Kubelet은 Kubernetes의 Node Authorizer에 의하여 권한을 획득 받음 (인가)
- https://github.com/kubernetes/kubernetes/blob/master/plugin/pkg/auth/authorizer/node/node_authorizer.go#L96C74-L96C84
- 소스 확인 결과
- configmaps, secrets, pvc, pv, volumeattachments, sa, lease 등과 같은 특정 리소스에 대해서는 subdivide access를 평가함.
- 이 외에는 not subdivide하며 nodeRules에 의하여 Decision Allow/Disallow 를 결정한다.
-
if rbac.RulesAllow(attrs, r.nodeRules...) { return authorizer.DecisionAllow, "", nil } return authorizer.DecisionNoOpinion, "", nil
- https://github.com/kubernetes/kubernetes/blob/master/plugin/pkg/auth/authorizer/node/node_authorizer.go#L137
즉 Kubelet은 CSR 생성 요청에 대해서만 RBAC을 사용하며 이 외에는 Node Authrozier 권한을 사용한다.
그런데 Node Authroizer 권한을 사용하기 위해서는 반드시 system:node:
따라서 아래의 설정은 system:nodes 그룹의 권한이 CSR 생성 밖에 없기 때문에 Lease 객체를 업데이트하지 못하고 NotReady 상태에 빠진다.
apiVersion: v1
data:
mapRoles: |
- groups:
- system:bootstrappers
- system:nodes
rolearn: arn:aws:iam::111122223333:role/AmazonEKSWorkerNodeRole
username: WorkerNodeRole
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
아래의 설정은 system:masters 권한을 이용하여 RBAC 승인을 받기 때문에 노드는 정상적으로 Ready가 되지만 Bootstrap 단계에서 CSR 이름이 노드 이름과 달라지면서 CSR 승인이 되지 않는다. 이 경우 kbuectl logs, exec등의 커맨드에 문제가 생긴다.
apiVersion: v1
data:
mapRoles: |
- groups:
- system:masters
rolearn: arn:aws:iam::111122223333:role/AmazonEKSWorkerNodeRole
username: WorkerNodeRole
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
아래의 경우 정상적이다.
apiVersion: v1
data:
mapRoles: |
- groups:
- system:masters
rolearn: arn:aws:iam::111122223333:role/AmazonEKSWorkerNodeRole
username: system:node:
kind: ConfigMap
metadata:
name: aws-auth
namespace: kube-system
kubernetes
eks
kubelet
authorization
]