์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ๊ณต๋ถํ๋ฉด์ ์ฒ์ User Account ์ Service Account ๋ฅผ ์ ํ์ ๋ ๋จ์ํ ์ฟ ๋ฒ๋คํฐ์ค API ์๋ฒ์๊ฒ ์๊ฒฉ ์ฆ๋ช
ํ๋ ๋ฆฌ์์ค์ธ๊ฐ๋ณด๋ค ํ๊ณ ๋์ด๊ฐ๋ ์ ์ด ์์ต๋๋ค. ์ดํด๊ฐ ์๋์ ๊ทธ๋ฅ ๋์ด๊ฐ๋..
๊ทธ๋์ User Account ๋ Service Account ๋ ๋น์ทํ๊ฑฐ !! ๊ฐ์ ๊ฑฐ !! ๋ผ๋ ์๊ฐ์ ๊ฐ์ง๊ณ ์์์ฃ .. ํ์ง๋ง ์ด ๋์ ๋ถ๋ช ๋ค๋ฆ ๋๋ค.
์ฟ ๋ฒ๋คํฐ์ค์๋ ์ฟ ๋ฒ๋คํฐ์ค ๋ด์ ์กด์ฌํ๋ ์์์ ๋ํ ์ ๊ทผ์ ์ํ 2๊ฐ์ง์ account ํ์ ์ด ์กด์ฌํฉ๋๋ค.
- User Account
- Service Account
์ฟ ๋ฒ๋คํฐ์ค ๊ณต์ ๋ฌธ์์๋ ์ด์ ๊ฐ์ด ๋์์์ต๋๋ค.
์ฌ์ฉ์ ์ด์นด์ดํธ๋ ์ฌ๋์ ์ํ ๊ฒ์ด๋ค. ์๋น์ค ์ด์นด์ดํธ๋ ํ๋์์ ์คํ๋๋ ํ๋ก์ธ์ค๋ฅผ ์ํ ๊ฒ์ด๋ค.
100% ๋ง๋ ๋ง์ด์ง๋ง, ์ฒ์ ์ ํ๋ค๋ฉด ์ ์ดํด๊ฐ ๋์ง ์์ต๋๋ค. ์ ๋ํ ๊ทธ๋ฌ๊ณ ์ ๐ค
AWS ๋ฅผ ๊ฐ์ง๊ณ ์๋ฅผ ๋ค์ด๋ณด์ฃ !
์ฐ๋ฆฌ๊ฐ AWS ํํ์ด์ง์ ๋ค์ด๊ฐ๊ฒ ๋๋ค๋ฉด, ๊ฐ์ฅ ๋จผ์ ํด์ผํ ๊ฒ์ ๋ก๊ทธ์ธ ์ผ ๊ฒ์ ๋๋ค.
๋ก๊ทธ์ธ ํตํด์ AWS ์๊ฒ ์ฐ๋ฆฌ๊ฐ ๋๊ตฐ์ง ์ฆ๋ช ์ ํ ์ ์์ต๋๋ค.
๋ก๊ทธ์ธ ํ EC2 ๋ฅผ ์ด์ฉํฉ๋๋ค. EC2 ๋ ๊ฐ์ ๋จธ์ ์ ๋น๋ ค์ฃผ๋ ์๋น์ค์ ๋๋ค. ๊ทธ๋ฆฌ๊ณ ssh ๋ฅผ ํตํด EC2 ์ ์ ์ํฉ๋๋ค.
EC2 ์์ ์ฐ๋ฆฌ๋ S3 ์ ์กด์ฌํ๋ test.img ๋ฅผ ์ฌ์ฉํ๋ ค๊ณ ํฉ๋๋ค.
ํ์ง๋ง EC2 ์์ S3 ์ ์ ๊ทผ์ด ๋ถ๊ฐ๋ฅํ์ฃ . ์๋ EC2 ๋ S3 ์ ์ ๊ทผํ ์ ์๋ ๊ถํ์ด ์๊ธฐ ๋๋ฌธ์ ๋๋ค.
AWS IAM ์ ํตํด EC2 ๊ฐ S3 ์ ์ ๊ทผํ ์ ์๋ค๋ ๊ฒ์ ์ฆ๋ช ํด์ผ ํฉ๋๋ค.
๋ก๊ทธ์ธ ํตํด์ AWS ์๊ฒ ์ฐ๋ฆฌ๊ฐ ๋๊ตฐ์ง ์ฆ๋ช ์ ์ฃผ์ฒด๊ฐ User Account (์ ์ ์ด์นด์ดํธ),
EC2 ๊ฐ S3 ์ ์ ๊ทผํ๊ธฐ ์ํด ํ๋ ์ฆ๋ช ์ฃผ์ฒด๊ฐ Service Account (์๋น์ค ์ด์นด์ดํธ) ์ ๋๋ค.
์ด๋ฅผ ์ฟ ๋ฒ๋คํฐ์ค์ ๋์ ํด๋ณธ๋ค๋ฉด.. ๐
์ฟ ๋ฒ๋คํฐ์ค์ ํ ๋น๋ ์ ์ ๊ฐ User Account (์ ์ ์ด์นด์ดํธ),
Pod ๊ฐ ๋ค๋ฅธ ์ฟ ๋ฒ๋คํฐ์ค ์์ (Pods, Services ..) ์ ์ ๊ทผํ๊ธฐ ์ํด ํ๋ ์ฆ๋ช ์ฃผ์ฒด๊ฐ Service Account (์๋น์ค ์ด์นด์ดํธ) ์ ๋๋ค.
์์ง ๊ฐ์ด ์ ์์ค์๋์? ๐
๊ทธ๋ผ ํ๋ฒ ์ค์ ๋ก ์ ์ฉํด๋ณด์ฃ !
apiVersion: v1
kind: ServiceAccount
metadata:
name: service-account-example-sa
namespace: sample
Service Account ๋ฅผ ์์ฑํด์ค๋๋ค.
Service Account ๋ฅผ ์์ฑํ๊ฒ ๋๋ฉด Secret ์ผ๋ก Token ์ด ํ๋ ์๋์ผ๋ก ์์ฑ๋๋๋ฐ์, ์ด Token ์ ์ด์ฉํด์ ์ฟ ๋ฒ๋คํฐ์ค์๊ฒ ์๊ฒฉ ์ฆ๋ช ์ ํ ์ ์์ต๋๋ค.
โ ์ฟ ๋ฒ๋คํฐ์ค v1.24 ์ด์๋ถํฐ๋ ์๋์ผ๋ก Secret ์ด ์์ฑ๋์ง ์์ต๋๋ค
apiVersion: apps/v1
kind: Deployment
metadata:
name: service-account-example
namespace: sample
labels:
app: service-account-example
spec:
replicas: 1
selector:
matchLabels:
app: service-account-example
template:
metadata:
labels:
app: service-account-example
spec:
serviceAccountName: service-account-example-sa # SA ๋ฅผ ์ง์ ํด์ค๋๋ค
containers:
- name: nginx
image: nginx:latest
ports:
- containerPort: 80
Deployment ๋ ์์ฑํด์ฃผ์ฃ ๐ค
๋ ์ฌ๊ฒจ ๋ณผ ๊ฒ์ด ์์ต๋๋ค. ๋ฐ๋ก ๋ฐฐํฌ๋ Pod ์ Service Account ๊ฐ ๋ง์ดํธ ๋๋ค๋ ์ ์ด์ฃ โกโก
Containers:
nginx:
Container ID: docker://67919bf2e0cbcb079bf7a696fef23fd25d3e48691cb2329ac0dd761a251fd8a1
Image: nginx:latest
Image ID: docker-pullable://nginx@sha256:e209ac2f37c70c1e0e9873a5f7231e91dcd83fdf1178d8ed36c2ec09974210ba
Port: 80/TCP
Host Port: 0/TCP
State: Running
Started: Sun, 20 Nov 2022 14:47:02 +0900
Ready: True
Restart Count: 0
Environment: <none>
Mounts:
/var/run/secrets/kubernetes.io/serviceaccount from kube-api-access-pclnt (ro)
๊ทธ๋ผ ์ ๊ฒฝ๋ก์ ์๋ ๊ฒ์ด ๋ฌด์์ธ์ง ๋ฐ๋ก ํ์ธ ํด๋ด์ผ๊ฒ ์ฃ ? ๐
root@service-account-example-558865ff7d-vx5gl:/var/run/secrets/kubernetes.io/serviceaccount# ls -l
total 0
lrwxrwxrwx 1 root root 13 Nov 20 05:46 ca.crt -> ..data/ca.crt
lrwxrwxrwx 1 root root 16 Nov 20 05:46 namespace -> ..data/namespace
lrwxrwxrwx 1 root root 12 Nov 20 05:46 token -> ..data/token
์ํ ๐ก ๋ฐ๋ก ์ ๊ธฐ์ ์ฟ ๋ฒ๋คํฐ์ค API ์๋ฒ์ ํต์ ํ ์ ์๋ Token ์ด ์์ต๋๋ค.
๊ทธ๋ผ ์ง์ง์ธ์ง ํ๋ฒ ํ์ธํด๋ณผ๊น์?
$ TOKEN=$(cat token)
$ curl -X GET https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/default/pods --header "Authorization: Bearer $TOKEN" --insecure
{
"kind": "Status",
"apiVersion": "v1",
"metadata": {},
"status": "Failure",
"message": "pods is forbidden: User \"system:serviceaccount:sample:service-account-example-sa\" cannot list resource \"pods\" in API group \"\" in the namespace \"default\": RBAC: clusterrole.rbac.authorization.k8s.io \"service-account-example-role\" not found",
"reason": "Forbidden",
"details": {
"kind": "pods"
},
"code": 403
}
401 (Unauthorized) ๊ฐ ์๋ 403 (Forbidden) ์ด ์จ ๊ฒ์ ๋ณด๋ ์ธ์ฆ์ ๋์๋ ๋ด ๋๋ค ๐ฅ
์ด๋๋ก๋ ์์ฌ์ฐ๋ ๊ทธ๋ผ ํ๋ฒ ์์์ ๋ฐฐํฌํ Pod ์ ๋ฆฌ์คํธ๋ฅผ ๊ฐ์ ธ์๋ณด์ฃ !
์์์ ์์ฑํ Service Account ๋ ์๊ฒฉ ์ฆ๋ช ๋ง ๊ฐ๋ฅํ ๋ฟ ํ์ฌ ์ด๋ ํ ๊ถํ๋ ์์ต๋๋ค. ( Pods list, create, update .. ๋ฑ)
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: service-account-example-role
namespace: sample
rules:
- apiGroups: [""]
resources: ["pods"]
verbs: ["get", "watch", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: service-account-example-role-binding
namespace: sample
subjects:
- kind: ServiceAccount
name: service-account-example-sa
namespace: sample
roleRef:
kind: Role
name: service-account-example-role
apiGroup: rbac.authorization.k8s.io
Role ์ ์์ฑํ์ฌ Service Account ์ Role Binding ํด์ค๋๋ค.
โ Role ์ ํ์ฌ pods ์ ๋ํด ["get", "watch", "list"] ๊ฐ ๊ฐ๋ฅํฉ๋๋ค
$ curl -X GET https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/default/pods --header "Authorization: Bearer $TOKEN" --insecure
์ฌ์ ํ Forbidden ์ด ๋๋ ๊ฑธ ํ์ธํ ์ ์๋๋ฐ, ์ด๋ ๋ฐ๋ก Role ์ ๊ธฐ๋ฅ ๋๋ฌธ์ ๋๋ค. Cluster Role ๊ณผ ๋ฌ๋ฆฌ Role ์ ํน์ Namespace ์ ๋ํด์๋ง ์์ ์ ํ ์ ์์ต๋๋ค. ๋ฐ๋ผ์ default NameSpace ๊ฐ ์๋ sample NameSpace ๋ก ์์ฒญ์ ๋ณด๋ด๋ด ์๋ค !
$ curl -X GET https://$KUBERNETES_SERVICE_HOST/api/v1/namespaces/sample/pods --header "Authorization: Bearer $TOKEN" --insecure
{
"kind": "PodList",
"apiVersion": "v1",
"metadata": {
"resourceVersion": "6608823"
},
"items": [
{
"metadata": {
"name": "service-account-example-558865ff7d-vx5gl",
"generateName": "service-account-example-558865ff7d-",
"namespace": "sample",
"uid": "c85ffc48-affb-4977-8686-657644717c0e",
"resourceVersion": "6604097",
"creationTimestamp": "2022-11-20T05:46:59Z",
....
200 ์์ฒญ์ด ์์ต๋๋ค ๐ต
์ค์ต์ ๊ณผ์ ์ ํ๋ฒ ์ ๋ฆฌํด๋ณด์ฃ ๐โ๏ธ
- Service Account ์ Pods ๋ฅผ ์์ฑํ์ต๋๋ค
- Pods ์ Service Account ๊ฐ ์๋์ผ๋ก ๋ง์ดํธ๋๊ณ ์ด๊ณณ์ Token ์ด ์กด์ฌํฉ๋๋ค
- Pods ์ ์ ์ํด์ curl ๋ช ๋ น์ด๋ฅผ ๋ ๋ ธ์ง๋ง Service Account ๋ ์๊ฒฉ ์ฆ๋ช ๋ง ๋ ์ํ์ด๊ณ ๊ถํ์ ์์ต๋๋ค
- Role ๊ณผ Role Binding ์ ์์ฑํด์ Service Account ์ ๊ถํ๋ ๋ถ์ฌํด์ค๋๋ค
- ๋ค์ Pods ์ ์ ํ curl ๋ช ๋ น์ด๋ฅผ ๋ ๋ฆฌ๋ฉด 200 ์๋ต ์ํ๊ฐ ์ต๋๋ค
์ด์ User Account ์ Service Account ์ ์ฐจ์ด์ ์ด ๋ฌด์์ธ์ง ํ์คํ ๊ฐ์ด ์์๊ฑฐ๋ผ ์๊ฐํฉ๋๋ค ๐