25๋ ๋ AWS EKS Hands-on Study ์คํฐ๋ ์ ๋ฆฌ ๋ด์ฉ์ ๋๋ค.
RBAC ๊ถํ ํ์ธ
kubectl krew install access-matrix rbac-tool rbac-view rolesum whoami
์ค์ต์ ์ํ ๋๊ตฌ๋ฅผ ์ค์นํ๋ค.
- access-matrix: ์ฌ์ฉ์์ RBAC ๊ถํ์ ๋งคํธ๋ฆญ์ค๋ก ํ์ธ
- rbac-tool: RBAC ์ญํ (Role)๊ณผ ๋ฐ์ธ๋ฉ ์ ๋ณด๋ฅผ ์กฐํ
- rbac-view: ์น UI์์ RBAC ์ญํ ์ ์๊ฐ์ ์ผ๋ก ๋ถ์
- rolesum: RBAC ์์ฝ ์ ๋ณด๋ฅผ ์ ๊ณต
- whoami: ํ์ฌ ์ปจํ ์คํธ์์์ ์ธ์ฆ๋ ์ฌ์ฉ์ ํ์ธ
kubectl rolesum aws-node -n kube-system ServiceAccount: kube-system/aws-node Secrets: Policies: โข [CRB] */aws-node โถ [CR] */aws-node Resource Name Exclude Verbs G L W C U P D DC cninodes.vpcresources.k8s.aws [*] [-] [-] โ โ โ โ โ โ โ โ eniconfigs.crd.k8s.amazonaws.com [*] [-] [-] โ โ โ โ โ โ โ โ events.[,events.k8s.io] [*] [-] [-] โ โ โ โ โ โ โ โ namespaces [*] [-] [-] โ โ โ โ โ โ โ โ nodes [*] [-] [-] โ โ โ โ โ โ โ โ pods [*] [-] [-] โ โ โ โ โ โ โ โ policyendpoints.networking.k8s.aws [*] [-] [-] โ โ โ โ โ โ โ โ policyendpoints.networking.k8s.aws/status [*] [-] [-] โ โ โ โ โ โ โ โ
aws-node SA๋ AWS VPC CNI ํ๋ฌ๊ทธ์ธ์ด ๋คํธ์ํฌ ๊ด๋ จ ๋ฆฌ์์ค๋ฅผ ์กฐ์ํ ์ ์๋๋ก ํ์ํ ๊ถํ์ ๊ฐ์ง๊ณ ์๋ค.
- cninodes.vpcresources.k8s.aws VPC CNI ๊ด๋ จ ๋ ธ๋ ๊ด๋ฆฌ
- eniconfigs.crd.k8s.amazonaws.com AWS ENI(Elastic Network Interface) ์ค์ ๊ด๋ฆฌ
- nodes ํด๋ฌ์คํฐ ๋ด ๋ ธ๋ ์ ๋ณด ์กฐํ ๊ฐ๋ฅ
- pods Pod ์ ๋ณด ์กฐํ ๊ฐ๋ฅ
- policyendpoints.networking.k8s.aws ๋คํธ์ํฌ ์ ์ฑ ์ ์ฉ
kubectl rolesum -k User system:kube-proxy User: system:kube-proxy Policies: โข [CRB] */system:node-proxier โถ [CR] */system:node-proxier Resource Name Exclude Verbs G L W C U P D DC endpoints [*] [-] [-] โ โ โ โ โ โ โ โ endpointslices.discovery.k8s.io [*] [-] [-] โ โ โ โ โ โ โ โ events.[,events.k8s.io] [*] [-] [-] โ โ โ โ โ โ โ โ nodes [*] [-] [-] โ โ โ โ โ โ โ โ services [*] [-] [-] โ โ โ โ โ โ โ โ
Kube-Proxy๋ ํด๋ฌ์คํฐ ๋คํธ์ํน์ ๊ด๋ฆฌํ๊ธฐ ์ํด ์๋น์ค ๋ฐ ์๋ํฌ์ธํธ ์ ๋ณด๋ฅผ ๊ฐ์ง๋ค.
- endpoints ํด๋ฌ์คํฐ ๋ด ์๋น์ค์ ์๋ํฌ์ธํธ ์ ๋ณด ์กฐํ ๊ฐ๋ฅ
- endpointslices.discovery.k8s.io ์๋น์ค์ ์๋ํฌ์ธํธ ์ฌ๋ผ์ด์ค ์ ๋ณด ์กฐํ ๊ฐ๋ฅ
- events.[,events.k8s.io] ์ด๋ฒคํธ ๊ด๋ จ ์ ๋ณด ์กฐํ ๊ฐ๋ฅ
- nodes ํด๋ฌ์คํฐ ๋ด ๋ ธ๋ ์ ๋ณด ์กฐํ ๊ฐ๋ฅ
- services ์๋น์ค ์ ๋ณด ์กฐํ ๊ฐ๋ฅ
kubectl rolesum -k Group system:masters Group: system:masters Policies: โข [CRB] */cluster-admin โถ [CR] */cluster-admin Resource Name Exclude Verbs G L W C U P D DC *.* [*] [-] [-] โ โ โ โ โ โ โ โ
ํด๋ฌ์คํฐ ๊ด๋ฆฌ์ ๊ทธ๋ฃน์ผ๋ก ์ฟ ๋ฒ๋คํฐ์ค ์ต๊ณ ๊ถํ์ธ cluster-admin ์ญํ ์ ๋ถ์ฌ๋ฐ์ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ์์ ๊ฐ๋ฅํ๋ค.
kubectl rolesum -k Group system:nodes Group: system:nodes Policies: โข [CRB] */eks:node-bootstrapper โถ [CR] */eks:node-bootstrapper Resource Name Exclude Verbs G L W C U P D DC certificatesigningrequests.certificates.k8s.io/selfnodeserver [*] [-] [-] โ โ โ โ โ โ โ โ
EKS(๋๋ Kubernetes ํด๋ฌ์คํฐ)์์ ์๋ก์ด ๋ ธ๋๊ฐ ํด๋ฌ์คํฐ์ ์ถ๊ฐ๋ ๋ ํ์ํ ๊ถํ์ eks:node-bootstrapper๋ก ๋ถํฐ ์ฃผ์ด์ง๋๋ฐ,
๋ ธ๋(Kubelet)๋ ์์ ์ ์ธ์ฆ์๋ฅผ ์์ฒญ(Certificate Signing Request, CSR)ํ๊ณ ๊ด๋ฆฌ์๋ก๋ถํฐ ์น์ธ๋ฐ์์ผ API ์๋ฒ์ ํต์ ์ด ๊ฐ๋ฅํ๊ฒ ๋๋ค.
๋ ธ๋๋ API ์๋ฒ์ ์์ ํ๊ฒ ํต์ ํ๊ธฐ ์ํด ์์ฒด ์ธ์ฆ์ ์์ฒญ์ ์์ฑํ ์ ์๋ค.
kubectl rolesum -k Group system:authenticated Group: system:authenticated Policies: โข [CRB] */system:basic-user โถ [CR] */system:basic-user Resource Name Exclude Verbs G L W C U P D DC selfsubjectaccessreviews.authorization.k8s.io [*] [-] [-] โ โ โ โ โ โ โ โ selfsubjectreviews.authentication.k8s.io [*] [-] [-] โ โ โ โ โ โ โ โ selfsubjectrulesreviews.authorization.k8s.io [*] [-] [-] โ โ โ โ โ โ โ โ โข [CRB] */system:discovery โถ [CR] */system:discovery โข [CRB] */system:public-info-viewer โถ [CR] */system:public-info-viewer
API ์๋ฒ์ ์ธ์ฆ๋ ๋ชจ๋ ์ฌ์ฉ์๊ฐ ์๋์ผ๋ก ํฌํจ๋๋ ๊ทธ๋ฃน์ผ๋ก RBAC ์ ์ฑ ์ ํตํด ํน์ ๋ฆฌ์์ค์ ์ ๊ทผํ ์ ์๋ค.
EKS ์ธ์ฆ
EKS์์ ์ก์ธ์ค ์ ์ด๋ AWS Identity and Access Management(IAM)๊ณผ ์ฟ ๋ฒ๋คํฐ์ค์ ์ญํ ๊ธฐ๋ฐ ์ก์ธ์ค ์ ์ด(RBAC)๋ฅผ ๊ฒฐํฉํ์ฌ ์ด๋ฃจ์ด์ง๋ค. IAM์ ํด๋ฌ์คํฐ์ ๋ํ ์ธ์ฆ์ ์ฒ๋ฆฌํ๊ณ Kubernetes RBAC๋ ํด๋ฌ์คํฐ ๋ด ๋ฆฌ์์ค์ ๋ํ ๊ถํ์ ๊ด๋ฆฌํ๋ค.
- IAM ์ฌ์ฉ์ ๋ฐ ์ญํ ์ ์ฟ ๋ฒ๋คํฐ์ค API ์ก์ธ์ค ๋ถ์ฌ: IAM ์ฌ์ฉ์ ๋๋ ์ญํ ์ด Kubernetes API์ ์ ๊ทผํ๋ ค๋ฉด ์ก์ธ์ค ํญ๋ชฉ์ ์ฌ์ฉํ์ฌ Kubernetes RBAC ๊ถํ์ ํด๋น IAM ์ํฐํฐ์ ์ฐ๊ฒฐํ์ฌ ๊ฐ๋ฐ์๋ ์ ํ๋ฆฌ์ผ์ด์ ์ด ํด๋ฌ์คํฐ์ ์ํธ ์์ฉ ๊ฐ๋ฅํ๋ค.
- AWS Management Console์์ Kubernetes ๋ฆฌ์์ค ๋ณด๊ธฐ: AWS Management Console์ ํตํด ํด๋ฌ์คํฐ์ ๋ค์์คํ์ด์ค, ๋ ธ๋, ํ๋์ ๊ฐ์ Kubernetes ๋ฆฌ์์ค๋ฅผ ์๊ฐํํ๊ธฐ ์ํด ์ฝ์์ด Amazon EKS ํด๋ฌ์คํฐ์ ํต์ ํ๋๋ก ๊ตฌ์ฑํด์ผ ํ๋ค.
- kubectl์ EKS ํด๋ฌ์คํฐ์ ์ฐ๊ฒฐ: AWS CLI๋ฅผ ์ฌ์ฉํ์ฌ kubeconfig ํ์ผ์ ์์ฑํ๊ฑฐ๋ ์ ๋ฐ์ดํธํจ์ผ๋ก์จ kubectl cli ๋๊ตฌ๊ฐ Amazon EKS ํด๋ฌ์คํฐ์ API ์๋ฒ์ ํต์ ํ ์ ์๋๋ก ์ค์ ํ๋ค.
- Kubernetes ์๋น์ค ์ด์นด์ดํธ๋ฅผ ํตํ AWS API ์ก์ธ์ค: Kubernetes ์ํฌ๋ก๋๊ฐ AWS API๋ฅผ ํธ์ถํ ์ ์๋๋ก ํ๋ ค๋ฉด ์๋น์ค ์ด์นด์ดํธ์ IAM ์ญํ ์ ์ค์ ํ์ฌ ํ๋๊ฐ AWS ๋ฆฌ์์ค์ ์์ ํ๊ฒ ์ ๊ทผํ ์ ์๋ค.
์ฌ์ฉ ๊ฐ๋ฅํ ๋กค ํ์ธ
kubectl describe clusterrolebindings.rbac.authorization.k8s.io cluster-admin Name: cluster-admin Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate: true Role: Kind: ClusterRole Name: cluster-admin Subjects: Kind Name Namespace ---- ---- --------- Group system:masters kubectl describe clusterrole cluster-admin Name: cluster-admin Labels: kubernetes.io/bootstrapping=rbac-defaults Annotations: rbac.authorization.kubernetes.io/autoupdate: true PolicyRule: Resources Non-Resource URLs Resource Names Verbs --------- ----------------- -------------- ----- *.* [] [] [*] [*] [] [*]
cluster-admin์ Kubernetes ํด๋ฌ์คํฐ์์ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌํ ์ ์๋ ์ต๊ณ ๊ถํ์ ๊ฐ์ง ์ญํ ์ด๋ค.
system:masters ๊ทธ๋ฃน์ cluster-admin ์ญํ ์ ๋ถ์ฌํ๋๋ฐ system:masters ๊ทธ๋ฃน์ ์ํ ์ฌ์ฉ์๋ ํด๋ฌ์คํฐ์ ๋ชจ๋ ๋ฆฌ์์ค๋ฅผ ๊ด๋ฆฌ ๊ฐ๋ฅํ๋ค.
cluster-admin ์ญํ ์ ๊ฐ์ง ์ฌ์ฉ์๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด ๋ชจ๋ ๋ฆฌ์์ค์ API ์๋ํฌ์ธํธ์ ๋ํด ์ ํ ์์ด ์ ๊ทผ ๊ฐ๋ฅํ๋ค.
aws auth config map
aws iam create-user --user-name testuser aws iam create-access-key --user-name testuser aws iam attach-user-policy --policy-arn arn:aws:iam::aws:policy/AdministratorAccess --user-name testuser
์ค์ต์ ์ํ ํ ์คํธ ์ ์ ๋ฅผ ์์ฑํ๊ณ ์ด๋๋ฏผ ์ก์ธ์ค ๊ถํ์ ๋ถ์ฌํ๋ค.
kubectl get node -v6 I0316 05:40:16.553046 2768 round_trippers.go:553] GET http://localhost:8080/api?timeout=32s in 0 milliseconds E0316 05:40:16.553210 2768 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: Get \"http://localhost:8080/api?timeout=32s\": dial tcp 127.0.0.1:8080: connect: connection refused" I0316 05:40:16.554763 2768 cached_discovery.go:120] skipped caching discovery info due to Get "http://localhost:8080/api?timeout=32s": dial tcp 127.0.0.1:8080: connect: connection refused I0316 05:40:16.555075 2768 round_trippers.go:553] GET http://localhost:8080/api?timeout=32s in 0 milliseconds E0316 05:40:16.555135 2768 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: Get \"http://localhost:8080/api?timeout=32s\": dial tcp 127.0.0.1:8080: connect: connection refused" I0316 05:40:16.558345 2768 cached_discovery.go:120] skipped caching discovery info due to Get "http://localhost:8080/api?timeout=32s": dial tcp 127.0.0.1:8080: connect: connection refused I0316 05:40:16.559675 2768 shortcut.go:103] Error loading discovery information: Get "http://localhost:8080/api?timeout=32s": dial tcp 127.0.0.1:8080: connect: connection refused I0316 05:40:16.560892 2768 round_trippers.go:553] GET http://localhost:8080/api?timeout=32s in 0 milliseconds E0316 05:40:16.560975 2768 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: Get \"http://localhost:8080/api?timeout=32s\": dial tcp 127.0.0.1:8080: connect: connection refused" I0316 05:40:16.562193 2768 cached_discovery.go:120] skipped caching discovery info due to Get "http://localhost:8080/api?timeout=32s": dial tcp 127.0.0.1:8080: connect: connection refused I0316 05:40:16.562483 2768 round_trippers.go:553] GET http://localhost:8080/api?timeout=32s in 0 milliseconds E0316 05:40:16.562535 2768 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: Get \"http://localhost:8080/api?timeout=32s\": dial tcp 127.0.0.1:8080: connect: connection refused" I0316 05:40:16.563622 2768 cached_discovery.go:120] skipped caching discovery info due to Get "http://localhost:8080/api?timeout=32s": dial tcp 127.0.0.1:8080: connect: connection refused I0316 05:40:16.563803 2768 round_trippers.go:553] GET http://localhost:8080/api?timeout=32s in 0 milliseconds E0316 05:40:16.563844 2768 memcache.go:265] "Unhandled Error" err="couldn't get current server API group list: Get \"http://localhost:8080/api?timeout=32s\": dial tcp 127.0.0.1:8080: connect: connection refused" I0316 05:40:16.564946 2768 cached_discovery.go:120] skipped caching discovery info due to Get "http://localhost:8080/api?timeout=32s": dial tcp 127.0.0.1:8080: connect: connection refused I0316 05:40:16.565005 2768 helpers.go:264] Connection error: Get http://localhost:8080/api?timeout=32s: dial tcp 127.0.0.1:8080: connect: connection refused The connection to the server localhost:8080 was refused - did you specify the right host or port?
AWS ์๊ฒฉ ์ฆ๋ช ์ ๋ฌธ์ ์์ง๋ง Kubernetes RBAC ๋ฐ ์ธ์ฆ ์ค์ ์ ํ์ธํด์ผ ํ๋ค.
iam ๋งคํ
# 1๋ฒ ๋ฐฐ์ค์ฒ ์๋ฒ eksctl get iamidentitymapping --cluster $CLUSTER_NAME eksctl create iamidentitymapping --cluster $CLUSTER_NAME --username testuser --group system:masters --arn arn:aws:iam::$ACCOUNT_ID:user/testuser eksctl get iamidentitymapping --cluster $CLUSTER_NAME ARN USERNAME GROUPS ACCOUNT ... arn:aws:iam::390844768149:user/testuser testuser system:masters
# 2๋ฒ ๋ฐฐ์ค์ฒ ์๋ฒ aws eks update-kubeconfig --name $CLUSTER_NAME --user-alias testuser Updated context testuser in /root/.kube/config cat ~/.kube/config ... - name: testuser user: exec: apiVersion: client.authentication.k8s.io/v1beta1 args: - --region - ap-northeast-2 - eks - get-token - --cluster-name - myeks - --output - json command: aws kubectl ns default Context "testuser" modified. Active namespace is "default". (testuser:default) [root@operator-host-2 ~]# kubectl get node -v6 I0316 06:04:22.045436 3159 loader.go:395] Config loaded from file: /root/.kube/config I0316 06:04:23.069865 3159 round_trippers.go:553] GET https://~~~.yl4.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500 200 OK in 1015 milliseconds NAME STATUS ROLES AGE VERSION ip-192-168-1-31.ap-northeast-2.compute.internal Ready <none> 5h53m v1.31.5-eks-5d632ec ip-192-168-2-143.ap-northeast-2.compute.internal Ready <none> 5h53m v1.31.5-eks-5d632ec ip-192-168-3-145.ap-northeast-2.compute.internal Ready <none> 5h53m v1.31.5-eks-5d632ec
testuser์ ๊ทธ๋ฃน ๊ถํ์ ๋ณ๊ฒฝํ๋ฉด?
kubectl edit cm -n kube-system aws-auth ... - groups: - system:authenticated userarn: arn:aws:iam::390844768149:user/testuser username: testuser eksctl get iamidentitymapping --cluster $CLUSTER_NAME arn:aws:iam::390844768149:user/testuser testuser system:authenticated kubectl get node -v6 I0316 06:07:56.767482 3307 loader.go:395] Config loaded from file: /root/.kube/config I0316 06:07:57.923161 3307 round_trippers.go:553] GET https://~~.yl4.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500 403 Forbidden in 1147 milliseconds I0316 06:07:57.923812 3307 helpers.go:246] server response object: [{ "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "nodes is forbidden: User \"testuser\" cannot list resource \"nodes\" in API group \"\" at the cluster scope", "reason": "Forbidden", "details": { "kind": "nodes" }, "code": 403 }] Error from server (Forbidden): nodes is forbidden: User "testuser" cannot list resource "nodes" in API group "" at the cluster scope
testuser๊ฐ system:authenticated ๊ทธ๋ฃน์ ์ํด ์๊ณ , nodes ๋ฆฌ์์ค์ ๋ํ RBAC ๊ถํ์ด ์๊ธฐ ๋๋ฌธ์ ์ ์์ ์ผ๋ก ์ ๊ทผ์ด ์ฐจ๋จ๋๋ค.
testuser IAM ๋งคํ ์ญ์
eksctl delete iamidentitymapping --cluster $CLUSTER_NAME --arn arn:aws:iam::$ACCOUNT_ID:user/testuser 2025-03-16 06:09:54 [โน] removing identity "arn:aws:iam::390844768149:user/testuser" from auth ConfigMap (username = "testuser", groups = ["system:authenticated"]) eksctl get iamidentitymapping --cluster $CLUSTER_NAME kubectl get cm -n kube-system aws-auth -o yaml # 2๋ฒ ๋ฐฐ์ค์ฒ ์๋ฒ kubectl get node -v6 I0316 06:10:54.403658 3413 loader.go:395] Config loaded from file: /root/.kube/config I0316 06:10:56.447285 3413 round_trippers.go:553] GET https://~~~.yl4.ap-northeast-2.eks.amazonaws.com/api/v1/nodes?limit=500 401 Unauthorized in 2035 milliseconds I0316 06:10:56.447752 3413 helpers.go:246] server response object: [{ "kind": "Status", "apiVersion": "v1", "metadata": {}, "status": "Failure", "message": "Unauthorized", "reason": "Unauthorized", "code": 401 }] error: You must be logged in to the server (Unauthorized)
๊ธฐ์กด์ testuser๋ aws-auth ConfigMap์ ๋ฑ๋ก๋์ด ์์๋๋ฐ IAM ๋งคํ์ ์ ๊ฑฐํ ํ, kubectl get nodes๋ฅผ ์คํํ๋ฉด 401 Unauthorized ์ค๋ฅ ๋ฐ์ํ๊ฒ ๋๋ค.
์ด๋ testuser๊ฐ ์ด์ Kubernetes API ์๋ฒ์ ์ธ์ฆ๋์ง ์๊ธฐ ๋๋ฌธ์ด๋ค.
'Infra > AWS' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[AEWS] #6์ฃผ์ฐจ Kyverno ์ค์ต (5) (0) | 2025.03.16 |
---|---|
[AEWS] #6์ฃผ์ฐจ IRSA ์ค์ต (4) (1) | 2025.03.16 |
[AEWS] #6์ฃผ์ฐจ ์๋น์ค ์ด์นด์ดํธ, role ๊ถํ ํ์ธ ์ค์ต (2) (0) | 2025.03.16 |
[AEWS] #6์ฃผ์ฐจ x.509 ์ธ์ฆ์ ๊ตฌ์กฐ ๋ฐ ๊ฒ์ฆ ์ค์ต (1) (0) | 2025.03.16 |
AWS MFA ์ญ์ ํ์ ๋ ์กฐ์น ๋ฐ PC๋ก ์ธ์ฆ ๋ณ๊ฒฝ (0) | 2025.03.10 |