๐ ํด๋น ํฌ์คํ
์ ์์ํ์ธ์! ๋์ปค/์ฟ ๋ฒ๋คํฐ์ค ์์ ์ ์ฝ๊ณ ๊ฐ์ธ์ ์ธ ๋ชฉ์ ํ์ ์์ฑ๋๋ ๊ธ์
๋๋ค. ํฌ์คํ
์ ์ฌ์ฉ๋๋ ๋ชจ๋ ์๋ฃ๋ ์ ๊ฐ ์ง์ ์ฌ๊ตฌ์ฑํ์์์ ์๋ฆฝ๋๋ค.
์ผ๋ฐ์ ์ผ๋ก ์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ์ฌ์ฉํ๋ ํ๊ฒฝ์ ํ ๋ช ์ ๊ฐ๋ฐ์๊ฐ ์ด์ํ๊ณ ์ฌ์ฉํ๋ ๊ฒฝ์ฐ๋ ๊ฑฐ์ ์๋ค. ๋๋ถ๋ถ ์ฌ๋ฌ ๋ช ์ DevOps ๊ฐ๋ฐ์ ๋๋ ์ฌ๋ฌ ๋ช ์ ๋ฐฑ์๋ ๊ฐ๋ฐ์, MLOps ๊ฐ๋ฐ์ ๋ฑ ์ธํ๋ผ๋ฅผ ๋ค์ฌ๋ค๋ณด๋ ๊ฐ๋ฐ์๋ค์ด ํจ๊ป ์ฌ์ฉํ๋ค. ํ์ง๋ง ์ด ๋ชจ๋ ๊ฐ๋ฐ์๋ค์ด ๋์ผํ ๋ฒ์์ ๊ถํ์ผ๋ก k8s ํด๋ฌ์คํฐ๋ฅผ ์ ์ดํ์ง๋ ์๋๋ค. ์ด์์ฒด์ ๊ฐ ์ ์ ๋ณ๋ก ๋๋ ํ ๋ฆฌ ๋๋ ํ์ผ์ ์ ๊ทผ ๊ถํ์ ๋ค๋ฅด๊ฒ ๋ถ์ฌํ์ฌ ๊ด๋ฆฌํ๋ ๊ฒ์ฒ๋ผ ์ฟ ๋ฒ๋คํฐ์ค์์๋ ์ ์ ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ๋ณ๋ก ์ฟ ๋ฒ๋คํฐ์ค์ ์ ๊ทผ ๊ถํ์ ์ ์ดํ ์๊ฐ ์๋ค.
์ด๋ฒ ํฌ์คํ ์์๋ ์ฟ ๋ฒ๋คํฐ์ค์์ RBAC(Role Based Access Control)์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์๋น์ค ์ด์นด์ดํธ(Service Account)๋ผ๋ ๋ฆฌ์์ค ์ค๋ธ์ ํธ, ๊ทธ๋ฆฌ๊ณ RBAC์ ๊ฐ๋ฅํ๊ฒ ํ๋ ๋กค, ํด๋ฌ์คํฐ ๋กค ์ด๋ผ๋ ๋ฆฌ์์ค ์ค๋ธ์ ํธ์ ๋ํด์๋ ๋ฐฐ์๋ณด๋๋ก ํ์.
1. ์ฟ ๋ฒ๋คํฐ์ค์์๋ ๊ถํ ์ธ์ฆ์ ์ด๋ป๊ฒ ํ ๊น?
์ด์ ๋ชฉ์ฐจ์์ ResourceQuota ๋ผ๋ ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ฅผ ๋ฐฐ์์ผ๋ก์จ ๊ฐ๋จํ๊ฒ๋๋ง ์ฌ์ฉ์๊ฐ ์ฟ ๋ฒ๋คํฐ์ค๋ก ์์ฒญ์ ๋ณด๋์ ๋, ๋ด๋ถ์ ์ผ๋ก ์ด๋ค ๊ณผ์ ์ด ์ํ๋๋์ง ์ดํด๋ณด์์๋ค. ๊ทธ๋ ์ดํด๋ณธ ๊ทธ๋ฆผ์ ๋ค์ ๊ฐ์ ธ์๋ณด์. ๋น์์๋ ์๋ ๊ทธ๋ฆผ์์ Mutating Admission Controller, Validating Adminssion Controller ๋จ๊ณ์ ๋ํด ์ค๋ช ํ์๋ค.
์ด๋ฒ์ ์ฐ๋ฆฌ๊ฐ ์ดํด๋ณผ ๋ถ๋ถ์ Authentication(์ธ์ฆ)๊ณผ Authorization(์ธ๊ฐ)์ด๋ค. Authentication์ ์์ฒญ์ ๋ณด๋ธ ํด๋ผ์ด์ธํธ๊ฐ ์ฟ ๋ฒ๋คํฐ์ค์ ์ฌ์ฉ์๊ฐ ๋ง๋์ง ๊ฒ์ฌํ๋ ๋ถ๋ถ์ด๋ค. ๋ฐ๋ฉด์ Authorization ๋ถ๋ถ์ ํด๋ผ์ด์ธํธ๊ฐ ๋ณด๋ธ ์์ฒญํ ์ด๋ค ๊ธฐ๋ฅ์ ์คํํ ๊ถํ์ด ๊ทธ ํด๋ผ์ด์ธํธ๊ฐ ๊ฐ๊ณ ์๋์ง ํ์ธํ๋ ๋ถ๋ถ์ด๋ค.
์ผ๋ก๋ก, ์ด๋ค ํด๋ผ์ด์ธํธ๊ฐ kube-system ์ด๋ผ๋ ๋ค์์คํ์ด์ค์ ํ๋๋ฅผ ์ถ๋ ฅํ๋ ์์ฒญ์ ๋ณด๋๋ค๊ณ ํด๋ณด์. ์ด ํด๋ผ์ด์ธํธ๋ ์ฟ ๋ฒ๋คํฐ์ค ์ฌ์ฉ์์์ ๋ง์์ Authentication ๋จ๊ณ๊ฐ ํต๊ณผ๊ฐ ๋์์ง๋ง ํ๋ ๋ชฉ๋ก์ ์ถ๋ ฅํ๋ ๊ธฐ๋ฅ์ ์คํํ๋ ๊ถํ์ด ์๋ค๋ฉด ํด๋น ํด๋ผ์ด์ธํธ๋ 403 ์๋ฌ๋ฅผ ๋ฐํ๋ฐ์ ๊ฒ์ด๋ค.
์ด๋ฌํ ์ธ์ฆ๊ณผ ์ธ๊ฐ์์ ์ฟ ๋ฒ๋คํฐ์ค๋ ์๋น์ค ์ด์นด์ดํธ๋ฅผ ์ฌ์ฉํ ์๋ ์๊ณ , ์๋ํํฐ ์ธ์ฆ(OIDC, Open ID Connect: OAuth), ์ธ์ฆ์ ๋ฑ์ ์ฌ์ฉํ ์ ์๋ค.
2. ๊ธฐ๋ณธ์ ์ธ ์ธ์ฆ, ์ธ๊ฐ ๋ฐฉ๋ฒ: kubeconfig ํ์ฉํ๊ธฐ!
์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ์ค์นํ๊ฑฐ๋ ์๋ก์ด ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ์ ๊ทผํ๊ธฐ ์ํด์ ๊ฐ์ฅ ์ฒ์ ์๋ํ๋ ๋ฐฉ์์ kubectl CLI๋ฅผ ์ํํด์ ์ ๊ทผํ ๊ฒ์ด๋ค. kubectl ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ๋๋ ๊ธฐ๋ณธ์ ์ผ๋ก .kube ๋ผ๋ ๋๋ ํ ๋ฆฌ์ config ํ์ผ(.kube/config)์ ์ ์ฅ๋ ์ค์ ์ ์ฝ์ด๋ค์ฌ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ์ ๊ทผ์ ์ํํ๋ค. ํด๋น ํ์ผ์ ๋ณดํต ๋ก์ปฌ ํธ์คํธ์ ํ ๋๋ ํ ๋ฆฌ์ ์์นํ๊ธฐ ๋๋ฌธ์ ๋๋ถ๋ถ ~/.kube/config ๊ฒฝ๋ก์ ์กด์ฌํ ๊ฒ์ด๋ค. ๊ทธ๋ฆฌ๊ณ ์ด๋ฌํ config ํ์ผ์ ๋ฐ๋ก kubeconfig ๋ผ๊ณ ๋ถ๋ฅธ๋ค.
ํด๋น ํ์ผ์ ์ด์ด๋ณด๋ฉด ํฌ๊ฒ clusters, contexts, users ํญ๋ชฉ์ด ๋ค์ด์๊ณ , ๊ฐ ํญ๋ชฉ๋ค์ ์ฌ๋ฌ ๊ฐ์ง ๊ฐ๋ค์ ํฌํจํ๊ณ ์์ ์ ์๋ค.(YAML์ array) ์์ ๋ด์ฉ์ ๋ค์๊ณผ ๊ฐ๋ค.
์ config ํ์ผ ๋ด์ฉ์ ๋ณด๋ฉด users ๋ผ๋ ํญ๋ชฉ์๋ ์ธ์ฆ์ ์ํ ๋ฐ์ดํฐ๊ฐ ์ ์ฅ๋์ด ์๋ค. ๋ณด๋ฉด client-certificate ์ client-key์ ์ค์ ๋ ๊ฒฝ๋ก์ ํ์ผ์ bsas64๋ก ์ธ์ฝ๋ฉ๋ ์ธ์ฆ์(๊ณต๊ฐํค์ ๋น๋ฐํค)์ด๋ฉฐ, ์ด ํค ์์ ์ฟ ๋ฒ๋คํฐ์ค์์ ์ต๊ณ ๊ถํ(cluster-admin) ๊ถํ์ ๊ฐ๊ฒ๋๋ค. ๊ทธ๋ฆฌ๊ณ clusters ํญ๋ชฉ์๋ ์ ๊ทผํ๊ธฐ ์ํ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ค์ ๋ํ ์ ๋ณด๋ฅผ ๊ฐ๊ณ ์๋ค.
ํ์ง๋ง ์ด๋ฌํ config ํ์ผ๊ณผ ์ธ์ฆ์๋ฅผ ํ์ฉํด์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ก๋ถํฐ ์ธ์ฆ์ ๋ฐ๋ ๋ฐฉ๋ฒ์ ์ ์ฐจ๊ฐ ๋ณต์กํ๊ณ ๊ด๋ฆฌํ๊ธฐ๊ฐ ์ด๋ ต๊ธฐ ๋๋ฌธ์ ์์ฃผ ์ฌ์ฉ๋์ง๋ ์๋๋ค. ๋ค๋ฅธ ๋ฐฉ๋ฒ ์ค ๋ํ์ ์ธ ๋ฐฉ์์ ๋ฐ๋ก ์๋น์ค ์ด์นด์ดํธ๋ฅผ ํ์ฉํ๋ ๊ฒ์ด๋ค.
3. ๋ ๋ค๋ฅธ ์ธ์ฆ, ์ธ๊ฐ ๋ฐฉ๋ฒ : ServiceAccount ํ์ฉํ๊ธฐ
์ด๋ฒ์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ, ์๋ฐํ ๋งํ๋ฉด kube-apiserver๋ก๋ถํฐ ํด๋ผ์ด์ธํธ๋ฅผ ์ธ์ฆ, ์ธ๊ฐํ๋ ๋ ๋ค๋ฅธ ๋ฐฉ๋ฒ์ธ ServiceAccount(์ดํ SA)๋ฅผ ์ด์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํด ๋ฐฐ์๋ณด์. SA๋ ํ ๋ช ์ ์ฌ์ฉ์ ๋๋ ์ ํ๋ฆฌ์ผ์ด์ ์ ํด๋นํ๋ค๊ณ ์๊ฐํ๋ฉด ๋๋ค. SA๋ ๋ค์์คํ์ด์ค์ ์ข ์์ ์ธ ์ค๋ธ์ ํธ์ด๋ฉฐ serviceaccount ๋๋ sa ์ด๋ฆ์ผ๋ก ์ฌ์ฉ์ด ๊ฐ๋ฅํ๋ค. ์ฐธ๊ณ ๋ก kubectl ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ๋, ํน์ SA๋ฅผ ์ฌ์ฉํด์ kube-apiserver๋ก ์์ฒญ์ ๋ณด๋ผ ์๋ ์๋๋ฐ(์ด๋ฅผ Impersonate ๋ผ๊ณ ๋ถ๋ฆ), ์ฌ์ฉ ๋ช ๋ น์ด ์์๋ ๋ค์๊ณผ ๊ฐ๋ค.
kubectl get pods --as system:serviceaccount:$NAMESPACE:$SA_NAME
๊ทธ๋ฐ๋ฐ SA ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ฅผ ์๋ก ์์ฑํ๊ฑฐ๋ ๋๋ ๊ธฐ์กด์ ์ด์ฉํ๊ณ ์๋ SA๋ฅผ ์ด์ฉํ๋ค๊ณ ๊ฐ์ ํด๋ณด์. ์ด๊ฒ ๋์ผ๊น? ์๋๋ค. ์ฐ๋ฆฌ๋ SA๋ฅผ ์ฌ์ฉํด์ ์ํ๋ ๊ธฐ๋ฅ์ ํด๋ฌ์คํฐ์์ ์ํํ๊ธฐ ์ํด kube-apiserver๋ก๋ถํฐ ์ธ์ฆ, ์ธ๊ฐ๋ฅผ ๋ฐ์์ผ ํ๋ค. ๊ทธ๋ฌ๋ฉด ์ฐ๋ฆฌ๊ฐ ์ฌ์ฉํ SA์ ์ด๋ค ๊ถํ์ ๋ถ์ฌํ ์ง๋ฅผ ๋ช ์ํด์ฃผ์ด์ผ ํ๋ค.
์ด๋ฅผ ์ดํด๋ณด๊ธฐ ์ํด ๋จผ์ ํฐ ๊ทธ๋ฆผ๋ถํฐ ์ดํด๋ณด์. ๊ฒฐ๋ก ๋ถํฐ ๋งํ๋ฉด SA์ ๊ถํ์ ๋ถ์ฌํ๋ ค๋ฉด SA ๋ง๊ณ ๋ ๋กค(Role)๊ณผ ๋กค๋ฐ์ธ๋ฉ(RoleBinding)์ด๋ผ๋ ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ฅผ ์ถ๊ฐ๋ก ์์ฑํด์ฃผ์ด์ผ ํ๋ค. SA, ๋กค, ๋กค๋ฐ์ธ๋ฉ ๊ฐ์ ๊ด๊ณ๋ฅผ ๋ํ๋ด๋ฉด ์๋์ ๊ฐ๋ค.
์๊ฐ๋ณด๋ค ๊ฐ๋จํ๋ค. ์ ๋ฆฌํ๋ฉด SA์๋ ๊ณ์ ์ ๋ํ ์ ๋ณด๋ฅผ ๋ช ์, (SA๊ฐ ์ฌ์ฉํ )๊ถํ๋ค์ Role์ ๋ช ์, ๊ทธ Role์ ์ด๋ค SA์๋ค๊ฐ ์ฐ๊ฒฐ(๋ฐ์ธ๋ฉ)ํด์ค์ง๋ RoleBinding์ ๋ช ์ํ๋ค. ๊ทธ๋ฐ๋ฐ ์ ์ด๋ ๊ฒ 3๊ฐ์ง๋ก ๊ฐ๊ฐ ๋ถ๋ฆฌ๋ฅผ ์ํํ์๊น? ๊ทธ๋ฅ SA์ ํ๋์ Role, RoleBinding์ ๋ค ๋ช ์ํ๋ฉด ๋๋๊ฑฐ ์๋๊ฐ? ์ถ๊ธฐ๋ ํ๋ค. ์ฌ๊ฒฌ์ด์ง๋ง, ํ๋์ ๋ฆฌ์์ค ์ค๋ธ์ ํธ์๋ ์ต์์ ๊ธฐ๋ฅ๋ง ํฌํจ์์ผ SA, Role, RoleBinind๋ค์ด ์๋ก ๊ฐ์ 1:1 ๊ด๊ณ ๋ฟ๋ง ์๋๋ผ, 1:N, N:N ๊ด๊ณ๋ ๋งบ์ ์ ์๋๋ก ํ๋ ค๊ณ ํ ๊ฒ์ด ๋ชฉ์ ์ด์ง ์์๊น ์ถ๋ค.
์ฐธ๊ณ ๋ก Role๊ณผ RoleBinding์ ํ์ํ์ผ๋ก ClusterRole๊ณผ ClusterRoleBinding์ด ์กด์ฌํ๋ค. ์ด๋ฆ์์๋ ์ ์ถํ ์ ์๋ค์ํผ ClusterRole๊ณผ ClusterRoleBinding๋ 'ํด๋ฌ์คํฐ'๋ผ๋ ํค์๋๊ฐ ๋ค์ด๊ฐ๋ ๊ฒ์ฒ๋ผ ํด๋ฌ์คํฐ ๋จ์์ ๊ถํ์ ์ ์ํ ๋ ์ฌ์ฉํ๋ค. ์ผ๋ก๋ก, PV(Persistent Volume)์ ๊ฒฝ์ฐ ๋ค์์คํ์ด์ค์ ์ข ์์ ์ธ ๋ฆฌ์์ค ์ค๋ธ์ ํธ๊ฐ ์๋๊ธฐ ๋๋ฌธ์ ๋ง์ฝ PV ๊ด๋ จ ๊ถํ์ ์ค์ ํด์ฃผ๋ ค๊ณ ํ๋ค๋ฉด ClusterRole๊ณผ ClusterRoleBinding์ ์ด์ฉํด์ผ ํ๋ค. ํ์ง๋ง ๊ทธ๋ ๋ค๊ณ ํด์ ClusterRole๊ณผ ClusterRoleBinding์ด ๋ค์์คํ์ด์ค์ ์ข ์์ ์ธ ํ๋๋ ๋ํ๋ก์ด๋จผํธ์ ๊ฐ์ ๊ฒ๋ค์ ๋ํ ๊ถํ์ ์ค์ ํ ์ ์๋ ๊ฒ์ ์๋๋ค. ๋ณดํต ์ฌ๋ฌ ๋ค์์คํ์ด์ค์์ ๋ฐ๋ณต์ ์ผ๋ก ์ฌ์ฉ๋๋ ๊ถํ์ ํด๋ฌ์คํฐ ๋กค๋ก ๋ง๋ค์ด ์ฌ์ฌ์ฉํ๊ธฐ๋ ํ๋ค.
3-1. SA์ ๋ถ์ฌํ ๊ถํ์ ์ ์ํ์: Role, ClusterRole
๊ทธ๋ฌ๋ฉด ์ด์ SA์ ๋ถ์ฌํ ๊ถํ์ ์ ์ํ๋ Role๊ณผ ClusterRole ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ฅผ ์์ฑํ๋ ์์ ๋งค๋ํ์คํธ๋ฅผ ์ดํด๋ณด์. ๋จผ์ Role์ด๋ค.
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
namespace: zedd-default
name: service-reader-role
rules:
- apiGroups: [""]
resources: ["services"]
verbs: ["get", "list"]
์ง์ ์ ์ธ๊ธํ๋ค์ํผ Role์ ๋ค์์คํ์ด์ค์ ์ข ์์ ์ธ ๋ฆฌ์์ค ์ค๋ธ์ ํธ์ด๊ธฐ ๋๋ฌธ์ metadata.namespace ํญ๋ชฉ์ ํด๋น Role์ด ์ํ ๋ค์์คํ์ด์ค๋ฅผ ๋ช ์ํด์ค๋ค. ๊ทธ๋ฆฌ๊ณ rules ํญ๋ชฉ์ 3๊ฐ์ง ํญ๋ชฉ์ ์ ์ํด์ฃผ๋ฉด ๋๋ค.
- apiGroups: ์ด๋ ํ API ๊ทธ๋ฃน์ ์ํ๋ ๋ฆฌ์์ค ์ค๋ธ์ ํธ์ ๋ํด ๊ถํ์ ์ง์ ํ ์ง๋ฅผ ์ค์ ํจ. ์ด API ๊ทธ๋ฃน์ด๋ผ๋ ๊ฒ์ ๋ํด์๋ ์ด์ CRD ํฌ์คํ ์์ ์ดํด๋ณธ ๊ฒ๊ณผ ๊ฐ์ ๊ฐ๋ ์. ์ ์์์์ services ๋ฆฌ์์ค ์ค๋ธ์ ํธ์ ๊ฒฝ์ฐ, ์ฝ์ด API ๊ทธ๋ฃน์ ์ํ๊ธฐ ๋๋ฌธ์ "" ๋ก ๋ช ์ํ์. ์ด๋ค ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ค์ด ์ด๋ค API ๊ทธ๋ฃน์ ์ํ๋์ง ๋ณด๊ณ ์ถ๋ค๋ฉด kubectl api-resources ๋ช ๋ น์ด๋ก ๋ณผ ์ ์์
- resources: ์ด๋ ํ ์ฟ ๋ฒ๋คํฐ์ค ์ค๋ธ์ ํธ์ ๋ํ ๊ถํ์ ์ ์ํ ๊ฒ์ธ์ง๋ฅผ ๋ช ์. ์ด ๋ํ kubectl api-resources ๋ช ๋ น์ด๋ก ๋ณผ ์ ์์
- verbs: ์ด ๋กค์ ๋ถ์ฌ๋ฐ์ SA๊ฐ ๋ช ์ํ resources์ ๋ํด์ ์ด๋ค ๋์์ ์ํํ ์ ์์์ง ๋ช ์. ์ ์์์์๋ get, list๋ฅผ ๋ช ์. ์ฐธ๊ณ ๋ก ์ด ํญ๋ชฉ์๋ ์์ผ๋์นด๋(*)๋ฅผ ์ฌ์ฉํ ์ ๋ ์๊ณ ํน์ ๋ฆฌ์์ค์ ํ์ ๋ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ๋ ์๋ธ ๋ฆฌ์์ค(ex. pods/exec)๋ฅผ ๋ช ์ํ ์๋ ์์
๋ค์์ ClusterRole ๋งค๋ํ์คํธ์ด๋ค.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nodes-reader-cluster-role
rules:
- apiGroups: [""]
resources: ["nodes"]
verbs: ["get", "list"]
๋งค๋ํ์คํธ ๋ด์ฉ์ Role๊ณผ ๊ฑฐ์ ๋น์ทํ๋ค. ๋ค๋ง, ClusterRole์ ๋ค์์คํ์ด์ค์ ์ข ์์ ์ด์ง ์๊ธฐ ๋๋ฌธ์ metadata.namespace ํญ๋ชฉ์ด ์๋ ๊ฒ์ด ์ฐจ์ด์ ์ด๋ค.
ํด๋ฌ์คํฐ ๋กค์ ์ถ๊ฐ์ ์ธ ๋ด์ฉ์ ๋ํด์ ํ๋๋ง ๋ ์ดํด๋ณด์. ํด๋ฌ์คํฐ ๋กค์ ์ฌ๋ฌ ๊ฐ๋ฅผ ์กฐํฉํด์ ์ฌ์ฉํ ์๋ ์๋ค. ์ฆ, ์์ฃผ ์ฌ์ฉ๋๋ ํด๋ฌ์คํฐ ๋กค์ด ์๋ค๋ฉด ๋ค๋ฅธ ํด๋ฌ์คํฐ ๋กค์ ํฌํจ์์ผ์ ์ฌ์ฌ์ฉํ ์๋ ์๋ค. ์ด๋ฌํ ๊ธฐ๋ฅ์ 'ํด๋ฌ์คํฐ ๋กค aggregation'์ด๋ผ๊ณ ํ๋ค. ์ด๋ฅผ ์ํ ๋งค๋ํ์คํธ๋ฅผ ํ๋ ์ดํด๋ณด์.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: parent-cluster-role
labels:
rbac.authorization.k8s.io/aggregate-to-child-clusterrole: "true"
rules:
- verbs: ["get", "list"]
resources: ["nodes"]
apiGroups: [""]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: child-cluster-role
aggregationRule:
clusterRoleSelectors:
- matchLabels:
rbac.authorization.k8s.io/aggregate-to-child-clusterrole: "true"
rules: []
๋จผ์ parent-cluster-role ์ด๋ผ๋ ์ด๋ฆ์ ํด๋ฌ์คํฐ ๋กค์ ์ ์ํ๋๋ฐ, metadata์ labels ํญ๋ชฉ์ ์ค์ ํ๋ค. ์ด์ ์ฟ ๋ฒ๋คํฐ์ค์ ๋ง์ด ์ต์ํด์ง์ ๋ถ๋ค์ด๋ฉด ์ 'labels' ํญ๋ชฉ๋ง ๋ณด๋๋ผ๋ "์ ์ด labels๋ก ๋ ์ด๋๊ฐ์์ ๋ผ๋ฒจ ์ ๋ ํฐ๋ฅผ ์ฐ๊ฒ ๊ตฌ๋ง" ์ด๋ผ๊ณ ์์ํ ์๋ ์์ ๊ฒ์ด๋ค. ๊ทธ ์์์ด ๋ง๋ค.
ํด๋น labels๋ ์๋์ child-cluster-role ์ด๋ฆ์ ํด๋ฌ์คํฐ ๋กค์ ์ ์ํ ๋ ์ฌ์ฉ๋๋ฉฐ, aggregationRule.clusterRoleSelectors.matchLabels ํญ๋ชฉ์์ ์ฌ์ฉ๋๋ค. ๊ทธ๋์ ์ ๋งค๋ํ์คํธ์์ child-cluster-role ์ด๋ผ๋ ํด๋ฌ์คํฐ ๋กค์ rules ํญ๋ชฉ์ ์๋ฌด๊ฒ๋ ๋ช ์ํ์ง ์์์ง๋ง aggregationRule๋ก ์ธํด parent-cluster-role ์ด๋ผ๋ ํด๋ฌ์คํฐ ๋กค์ ๊ถํ๋ค์ ์์๋ฐ์ ์ ์๊ฒ ๋๋ค.
3-2. SA์ ๊ถํ์ ์ฐ๊ฒฐํ์: RoleBinding, ClusterRoleBinding
SA๋ ์ ์ํ๊ณ , SA์ ๋ถ์ฌํ ๊ถํ์ธ ๋กค๋ ์ ์ํ๋ค. ๊ทธ๋ฌ๋ฉด ์ด์ ์ด ๋ ๊ฐ๋ฅผ ์ฐ๊ฒฐ์์ผ์ฃผ๊ธฐ๋ง ํ๋ฉด ๋๋ค. ์ด๋ฅผ ์ํด RoleBinding๊ณผ ClusterRoleBinding ๋งค๋ํ์คํธ ์์๋ฅผ ์ดํด๋ณด์. ๋จผ์ RoleBinding์ด๋ค.
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
namespace: zedd-default
name: service-reader-role-binding
subjects:
- kind: ServiceAccount
name: zedd-default-sa
namespace: zedd-default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: Role
name: service-reader-role
์ฐ๋ฆฌ๊ฐ ์ฃผ๋ชฉํ ๋ถ๋ถ์ subjects์ roleRef์ด๋ค.
- subjects : ๊ถํ์ ๋ถ์ฌํ ๋์์ด ์ด๋ค SA์ธ์ง๋ฅผ ๋ช ์
- roleRef: subjects์ ๋ช ์ํ SA์ ์ด๋ค ๊ถํ ์ฆ, ์ด๋ค Role์ ๋ถ์ฌํ ๊ฒ์ธ์ง ๋ช ์. ์ด ๋์ Role์ [๋ชฉ์ฐจ 3-1]์์ ์์ฑํ Role์
๋ค์์ ClusterRoleBinding ๋งค๋ํ์คํธ์ด๋ค. ๋ด์ฉ์ RoleBinding ๋งค๋ํ์คํธ ํ์๊ณผ ๋์ผํ๋ค.
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nodes-reader-cluster-role-binding
subjects:
- kind: ServiceAccount
name: zedd-default-sa
namespace: zedd-default
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: nodes-reader-cluster-role
4. ์ฟ ๋ฒ๋คํฐ์ค API ์๋ฒ์ ์ ๊ทผํ๊ธฐ
์ด๋ฒ ๋ชฉ์ฐจ์์๋ ์ฟ ๋ฒ๋คํฐ์ค์ ์ปจํธ๋กค ํ๋ ์ธ ์ค kube-apiserver๋ก ์ ๊ทผํ๋ ์ฌ๋ฌ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด์. kube-apiserver๋ ์ฟ ๋ฒ๋คํฐ์ค์ ํต์ฌ ์ปดํฌ๋ํธ ์ค ํ๋๋ก, ์ฌ์ฉ์๊ฐ kubectl ๋ช ๋ น์ด๋ฅผ ์์ฒญํ๊ฑฐ๋ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด๋ถ์์ ์ด์ ์ค์ธ ํ๋์ ๊ฐ์ ๋ค์ํ ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ค์ด Watch API๋ฅผ ์ด์ฉํ๋ค๊ฑฐ๋ etcd์์ ๋ฉํ ์ ๋ณด๋ฅผ ๊ฐ์ ธ์ค๊ฑฐ๋ ํ๊ธฐ ์ํด์ API ์์ฒญ์ ์ ์กํ๋ ๊ณณ์ด๋ค.
์ด๋ฐ kube-apiserver์ ์ ๊ทผํ๊ธฐ ์ํด์ kubectl ๋ช ๋ น์ด๋ฅผ ์ฌ์ฉํ ๋๋ ์ง์ ๋ชฉ์ฐจ์์ ์์๋ณธ .kube/config ํ์ผ์ ๋ด์ฉ์ ์ด์ฉํ๊ฑฐ๋ ์ฌ์ ์ ์์ฑํด๋ SA ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ฅผ --as ์ต์ ๊ณผ ํจ๊ป ์ด์ฉํ์๋ค. ํ์ง๋ง ๋ง์ฝ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด๋ถ ๋๋ ์ธ๋ถ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด kube-apiserver์ ์ ๊ทผ์ ์ํํ๋ ์ํฉ์ด๋ผ๋ฉด ์ด๋ฌํ ์ ๊ทผ ๋ฐฉ์์ด ์ ์ ํ์ง ์์ ์ ์๋ค.
๋ฐ๋ผ์ ์ด๋ฒ ๋ชฉ์ฐจ์์๋ ์ ํ๋ฆฌ์ผ์ด์ ์์ kube-apiserver๋ก ์ ๊ทผํ๋ ๋ํ์ ์ธ 3๊ฐ์ง ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๋ ค๊ณ ํ๋ค.
4-1. SA์ Secret ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ฅผ ์ด์ฉํด ์ ๊ทผํ์!
๋จผ์ kube-apiserver๋ HTTP ์์ฒญ์ ํตํด์ ์ฟ ๋ฒ๋คํฐ์ค์ ๊ธฐ๋ฅ์ ์ฌ์ฉํ ์ ์๋๋ก REST API๋ฅผ ์ ๊ณตํ๊ณ ์๋ค. ์ด ์๋ํฌ์ธํธ๋ ๋ง์ฝ kubeadm์ธ ๊ฒฝ์ฐ ์ฟ ๋ฒ๋คํฐ์ค ๋ง์คํฐ ๋ ธ๋์ IP์ 6443 ํฌํธ๋ก, GKE๋ kops์ ๊ฒฝ์ฐ๋ผ๋ฉด 443 ํฌํธ๋ก ์ ๊ทผํ ์ ์๋ค. ์ฐธ๊ณ ๋ก ํด๋น ์๋ํฌ์ธํธ๋ ๋ฐ๋์ HTTPS ์์ฒญ๋ง ์ฒ๋ฆฌํ ์ ์์ผ๋ฉฐ, ์ค์ค๋ก ์ฌ์ธํ self-signed ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ๋ค๋ ์ ์ ์ ์ํด์ผ ํ๋ค.
์ด๋ฌํ ์๋ํฌ์ธํธ์ ์ ๊ทผํ๊ธฐ ์ํด์ SA์ secret์ ์ด์ฉํ ์ ์๋ค. SA๋ฅผ ์์ฑํ๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก secret ๋ฆฌ์์ค ์ค๋ธ์ ํธ๊ฐ ๊ฐ์ด ์์ฑ๋๋ค. ์ด secret์ ํด๋น SA๋ฅผ ์ฆ๋ช ํ๊ธฐ ์ํ ์๋จ์ผ๋ก ์ฌ์ฉ๋๋ค. ์ด๋ค ์ ํ๋ฆฌ์ผ์ด์ ์ด ํด๋น SA์ secret์ ์ฌ์ฉํด์ kube-apiserver์ ์ ๊ทผํ๋ค๋ผ๊ณ ํ๋ค๋ฉด ๊ตฌ์กฐ๋๋ ๋ค์๊ณผ ๊ฐ์์ง๋ค.
์ ๊ตฌ์กฐ์์ ์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ๊ฐ kube-apiserver์ ์ ๊ทผ์ ์ํํ ๋๋ ๊ตฌ์ฒด์ ์ผ๋ก JWT(Json Web Token) ์ธ์ฆ์ ์ฌ์ฉํ๊ฒ ๋๋ค. ๊ทธ๋์ ์ ํ๋ฆฌ์ผ์ด์ ์๋ฒ๋ kube-apiserver๋ก REST API ์์ฒญ์ ๋ณด๋ผ ๋, Secret์ ์ ์ฅ๋ token์ ๋ฐ์ดํฐ๋ฅผ ํจ๊ป ๋ด์์ ๋ณด๋ด๋ฉด "ํด๋น ์ ํ๋ฆฌ์ผ์ด์ ์ "zedd" ๋ผ๋ SA๋ฅผ ์ฌ์ฉํด์ ์๊ฒฉ์ ์ฆ๋ช ํ์ต๋๋ค" ๋ผ๊ณ ์ ๋ฌํ๋ ์ ์ด๋ค. REST API๋ฅผ ์์ฒญํ๋ curl ๋ช ๋ น์ด ์์๋ ๋ค์๊ณผ ๊ฐ๋ค. ๋ง์ฝ default ๋ค์์คํ์ด์ค์ ์กด์ฌํ๋ ์๋น์ค ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ค ๋ชฉ๋ก์ ๋ณด๋ ค๋ฉด ์๋์ฒ๋ผ ์ํํ๋ฉด ๋๋ค. ์ด ๋ ํค๋์ ๋ด๋ ํ ํฐ์ base64๋ก ์ธ์ฝ๋ฉ๋ ์ํ์์ ๋์ฝ๋ฉํ ๊ฐ์ผ๋ก ์ค์ ํด์ฃผ์ด์ผ ํ๋ค.
# kubeadm์ผ๋ก ์ค์นํ ๊ฒฝ์ฐ
curl https://$MASTER_NODE_IP:6443/api/v1/namespaces/default/services \
-k \
-H "Authorization: Bearer $DECODED_TOKEN"
ํ์ง๋ง ์ด๋ฌํ ๋ฐฉ๋ฒ์ secret์ ํ ํฐ์ ์๋์ผ๋ก ๋์ฝ๋ฉํด์ฃผ๊ณ , REST API ์์ฒญ ์ ํ์ด๋ก๋ ๋ถ๋ถ์ ํ ํฐ ๊ฐ์ ์ง์ ๋ด์์ค์ผํ๋ ๋ฑ ์ฌ๋ฌ๊ฐ์ง ๋ถํธํ ์ ์ด ์กด์ฌํ๋ค.
4-2. ํด๋ฌ์คํฐ ๋ด๋ถ์์ kubernetes ์๋น์ค ์ด์ฉํด ์ ๊ทผํ๊ธฐ!
์ด๋ฒ์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด๋ถ์ ์ ํ๋ฆฌ์ผ์ด์ ์ด๋ผ๊ณ ํ์ ํ์ ๋, [๋ชฉ์ฐจ 4-1] ๋ฐฉ๋ฒ์ฒ๋ผ ํ ํฐ ๊ฐ์ ์๋์ผ๋ก ์ค์ ํด์ฃผ์ง ์๊ณ ์๋์ผ๋ก ์ ํ๋ฆฌ์ผ์ด์ ์ด kube-apiserver์ ์ ๊ทผํ ์ ์๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด๋๋ก ํ์.
์ด๋ฅผ ์ํด์ ์ฟ ๋ฒ๋คํฐ์ค์์ ๊ธฐ๋ณธ์ ์ผ๋ก ์์ฑํด๋ default ๋ค์์คํ์ด์ค์ kubernetes ๋ผ๋ ์ด๋ฆ์ ClusterIP ํ์ ์ ์๋น์ค ๋ฆฌ์์ค ์ค๋ธ์ ํธ๋ฅผ ์ด์ฉํ๋ ๊ฒ์ด๋ค. ์ฆ, ํ๋๋ค์ ์ด kubernetes ๋ผ๋ ์ด๋ฆ์ ์๋น์ค๋ฅผ ์ด์ฉํด์ kube-apiserver๋ก ์ ๊ทผ์ ์ํํ๋ค๋ ๊ฒ์ด๋ค. ์ด ๋, ํ๋๊ฐ kubernetes ์๋น์ค๋ก ํต์ ํ ๋ ๋ช ์ํ๋ ๋๋ฉ์ธ์ ์ด์ ํฌ์คํ ์์ ๋ฐฐ์ ๋ ํด๋ฌ์คํฐ ํต์ ๋๋ฉ์ธ์ธ FQDN์ ์ด์ฉํ๋ฉด ๋๋ค.
๊ทธ๋ฐ๋ฐ ์ด ๋, ํ๋๋ ๋จ์ํ kubernetes ๋ผ๋ ์๋น์ค๋ก ์ ๊ทผํ๋ ๊ฒ์ผ๋ก๋ง kube-apiserver๋ก ์์ฒญํ ๋ชจ๋ ๊ธฐ๋ฅ๋ค์ ์ฌ์ฉํ ์ ์์๊น? ์๋๋ค. ์ด ๋๋ [๋ชฉ์ฐจ 4-1]๋ ์ฒ๋ผ ํ๋์ "์ด๋ค SA"์ ์ํฌ๋ฆฟ ๊ฐ์ HTTP ์์ฒญ์ ๋ด์ ๋ณด๋ด์ฃผ์ด์ผ ํ๋ค. ๊ทธ๋์ผ "์ด๋ค SA"์ ๋ฐ์ธ๋ฉ๋ Role์ ์ ์๋ ๊ถํ๋ค์ ํํ์ฌ kube-apiserver๋ก ์์ฒญํ ๋ค ์ ์ ์๋ต์ ๋ฐ์๋ผ ์ ์๋ค.
๊ทธ๋ ๋ค๋ฉด ์ฌ๊ธฐ์ "์ด๋ค SA"๋ผ๋ ๊ฒ์ ๋ฌด์์ผ๊น? ํ๋๊ฐ ์์ฑ๋ ๋ ๋งค๋ํ์คํธ์ ํน๋ณํ SA๋ฅผ ๋ช ์ํด์ฃผ์ง ์์๋ค๋ฉด ๊ธฐ๋ณธ์ ์ผ๋ก "์ด๋ค SA"์ ์ํฌ๋ฆฟ์ ํ๋ ๋ด๋ถ์ ๋ง์ดํธํ๊ฒ ๋๋ค. ์ด "์ด๋ค SA"๋ ๋ฐ๋ก default ๋ผ๋ ๋ค์์คํ์ด์ค์ 'default' ๋ผ๋ ์ด๋ฆ์ ๊ฐ์ง SA๋ฅผ ๋ปํ๋ค. ์ค์ ๋ก ํ๋๋ฅผ ์์ฑํ ๋ค, describe๋ฅผ ํด๋ณด๋ฉด Containers.Mounts ํญ๋ชฉ์ ์๋์ ๊ฐ์ ๊ฒฝ๋ก์ ๋๋ ํ ๋ฆฌ๊ฐ ๋ง์ดํธ๋์ด ์์์ ๋ณผ ์ ์๋ค.
/var/run/secrets/kubernetes.io/serviceaccount
ํด๋น ๋๋ ํ ๋ฆฌ์ ๊ฐ๋ฉด ์๋์ ๊ฐ์ ํ์ผ๋ค์ด ์ฌ๋ณผ๋ฆญ ๋งํฌ ํํ๋ก ์กด์ฌํ๋ ๊ฒ์ ๋ณผ ์ ์๋ค.
๊ทธ๋์ ๋ง์ฝ ํ๋์์ kube-apiserver๋ก ์ ๊ทผํ๋ ค๋ฉด ํด๋น ๊ฒฝ๋ก์ ์๋ token ์ด๋ผ๋ ์ด๋ฆ์ ํ์ผ์ ์ ์ฅ๋ ๋ด์ฉ์ ์ฝ์ด์์ kubernetes ์ด๋ฆ์ ์๋น์ค๋ก ์์ฒญํ๋ฉด ๋๋ค.
์ฐธ๊ณ ๋ก ํ๋๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ๋ default ๋ผ๋ ์ด๋ฆ์ SA ๋ง๊ณ ๋ด๊ฐ ์ฌ์ ์ ๋ณ๋๋ก ์์ฑํ SA๋ฅผ ์ฌ์ฉํ๊ฒ๋ ํ๊ณ ์ถ๋ค๋ฉด ํ๋ ๋งค๋ํ์คํธ์์ spec.serviceAccountName ํญ๋ชฉ์ SA ์ด๋ฆ์ ์์ฑํด์ฃผ๋ฉด ๋๋ค.
4-3. ์ฟ ๋ฒ๋คํฐ์ค SDK๋ฅผ ์ด์ฉํด ์ ๊ทผํ๊ธฐ!
์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ ๋ด๋ถ ์ ํ๋ฆฌ์ผ์ด์ ์์ ์ ๊ทผํ๋ค๊ณ ํ์ ํ์ ๋, ์ด๋ฒ์๋ ํน์ ํ๋ก๊ทธ๋๋ฐ ์ธ์ด๋ก ๋ฐ์ธ๋ฉ๋ ์ฟ ๋ฒ๋คํฐ์ค SDK(ex. pypi kubernetes)๋ฅผ ์ด์ฉํด์ kubernetes ์๋น์ค์ ์ ๊ทผํ๋ ๊ฒ์ด๋ค. ์ด๋ [๋ชฉ์ฐจ 4-2]์ ๋์ผํ ๊ตฌ์กฐ์ด๋, kubernetes ์๋น์ค๋ก ์ ๊ทผํ ๋ ํน์ ์ธ์ด๋ก ๋ฐ์ธ๋ฉ๋ SDK๋ฅผ ์ฌ์ฉํ๋ ๊ฒ๋ง์ด ์ฐจ์ด์ ์ด๋ค.
Python ์ธ์ด๋ก ๋ฐ์ธ๋ฉ๋ SDK๋ฅผ ์ฌ์ฉํ ๋ ์๋์ ์์ค์ฝ๋๋ฅผ ํญ์ ๋ณผ ์ ์๋ค.
from kubernetes import config
config.load_incluster_config()
์ load_incluster_config() ๋ฉ์๋๋ฅผ ํธ์ถํ๊ฒ ๋๋ฉด ์๊น [๋ชฉ์ฐจ 4-2]์์ ๋ณด์๋ ํ๋ ๋ด๋ถ์ ๋ง์ดํธ๋ "/var/run/secrets/kubernetes.io/serviceaccount" ๋ผ๋ ๊ฒฝ๋ก์ ์กด์ฌํ๋ ํ์ผ๋ค์ ์ฝ์ด๋ค์ฌ kube-apiserver๋ก์ ์ธ์ฆ, ์ธ๊ฐ ์์ ์ ์ํํ๊ณ SDK๊ฐ ๋ด๋ถ์ ์ผ๋ก kubernetes ์ด๋ฆ์ ์๋น์ค๋ก ์์ฒญ์ ์ํํ๋ค. [๋ชฉ์ฐจ 4-2]๋์ ๋ค๋ฅธ ์ ์ด๋ผ๊ณ ํ๋ค๋ฉด ์์ค์ฝ๋ ๋ ๋ฒจ์์ FQDN์ ๋ช ์์ ์ผ๋ก ์ ์ํด์ ์์ฒญํ์ง ์๋๋ค๋ ์ ์ด ๋ค๋ฅด๋ค.
5. SA๋ก ์ฌ์ค(Private) ์ด๋ฏธ์ง ๋ ์ง์คํธ๋ฆฌ ์ ๊ทผํ๊ธฐ
์ด๋ฒ ๋ชฉ์ฐจ์์๋ SA๋ฅผ ํ์ฉํด์ ์ฌ์ค ์ด๋ฏธ์ง ๋ ์ง์คํธ๋ฆฌ์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ ๋ํด ์์๋ณด์. ์ด์ ํฌ์คํ ์์ docker-registry ๋ผ๋ ์ ํ์ ์ํฌ๋ฆฟ์ ์์ฑํ๊ณ , ํด๋น ์ํฌ๋ฆฟ์ ๋ํ๋ก์ด๋จผํธ๋ ํ๋ ๋งค๋ํ์คํธ์ imagePullSecrets ํญ๋ชฉ์ ๋ช ์ํ๋ฉด ํด๋น ๋ํ๋ก์ด๋จผํธ ๋๋ ํ๋๊ฐ ํด๋น ์ํฌ๋ฆฟ์ ์ด์ฉํด์ ์ฌ์ค ์ด๋ฏธ์ง ๋ ์ง์คํธ๋ฆฌ์ ์ ๊ทผํ ์ ์๋ค๋ ๊ฒ์ ์ดํด๋ณด์๋ค. ํ์ง๋ง ์ด ๋ฐฉ๋ฒ์ ์ฌ์ค ์ด๋ฏธ์ง ๋ ์ง์คํธ๋ฆฌ์ ์ ๊ทผํ๋ ค๋ ๋ชจ๋ ๋ํ๋ก์ด๋จผํธ ๋๋ ํ๋์ ๋งค๋ํ์คํธ ๋ง๋ค ๋งค๋ฒ imagePullSecrets ํญ๋ชฉ์ ์ํฌ๋ฆฟ์ ์ ์ํด์ผ ํ์๋ค.
์ด๋ฐ ๋ฒ๊ฑฐ๋ก์์ SA๋ฅผ ์ฌ์ฉํ๋ฉด ํด๊ฒฐํ ์ ์๋ค. SA์ docker-registry ํ์ ์ ์ํฌ๋ฆฟ์ ํ ๋ฒ ์ค์ ํด๋์ ๋ค, ์ฌ์ค ์ด๋ฏธ์ง ๋ ์ง์คํธ๋ฆฌ์ ์ ๊ทผํ๋ ค๋ ๋ชจ๋ ๋ํ๋ก์ด๋จผํธ์ ํ๋๋ค์ ๋จ์ง ํด๋น SA๋ง ์ฌ์ฉํ๋๋ก ์ค์ ํด์ฃผ๋ฉด ๋๋ค. SA์ docker-registry ํ์ ์ ์ํฌ๋ฆฟ์ ์ค์ ํ๋ ๋ฐฉ๋ฒ์ ๋ค์๊ณผ ๊ฐ๋ค.
apiVersion: v1
kind: ServiceAccount
metadata:
name: private-registry-sa
namespace: zedd-ns
imagePullSecrets:
- name: registry-auth
์ ๋งค๋ํ์คํธ์์ registry-auth ๋ผ๋ ์ํฌ๋ฆฟ์ docker-registry ํ์ ์ผ๋ก, ๋ฏธ๋ฆฌ ์์ฑํด๋์ ์ํฌ๋ฆฟ์ ์ด๋ฆ์ด๋ค. ์ฐธ๊ณ ๋ก [๋ชฉ์ฐจ 4-2]์์ ๋ฐฐ์ด ๊ฒ์ฒ๋ผ, ๋ณ๋ค๋ฅธ ์ค์ ์ ํ์ง ์์์ ๋ ํ๋๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ฌ์ฉํ๋ default ๋ผ๋ ์ด๋ฆ์ SA์ ์ํฌ๋ฆฟ์ ์ฌ์ฉํ๋๋ก ์ค์ ํ ์๋ ์๋ค.
6. kubeconfig ํ์ผ์ SA ์ธ์ฆ ์ ๋ณด๋ฅผ ์ค์ ํด์ k8s ํด๋ฌ์คํฐ์ ์ ๊ทผํ๊ธฐ
์ด๋ฒ์ ๋ฐฐ์ธ ๋ด์ฉ์ [๋ชฉ์ฐจ 2๋ฒ]์์ ์ดํด๋ณธ kubeconfig ํ์ผ ์ฆ, (๋ณ๋ ์ค์ ํ์ง ์์๋ค๋ฉด) ~/.kube/config ๊ฒฝ๋ก์ ํ์ผ์๋ค๊ฐ ์ฟ ๋ฒ๋คํฐ์ค SA ์ธ์ฆ ์ ๋ณด๋ฅผ ์ค์ ํ ๋ค, ํด๋น SA ์ธ์ฆ ์ ๋ณด๋ฅผ ๊ฐ์ง๊ณ k8s ํด๋ฌ์คํฐ์ ์ ๊ทผํ๋ ๋ฐฉ๋ฒ์ด๋ค.
(์ฐธ๊ณ ๋ก kubeconfig ํ์ผ์ ๋ณ๋๋ก ์ค์ ํ์ง ์์ผ๋ฉด ~/.kube/config ๊ฒฝ๋ก์ ๊ธฐ๋ณธ์ ์ผ๋ก ์กด์ฌํ์ง๋ง, ํ๊ฒฝ๋ณ์์ธ KUBECONFIG ๋ผ๋ ๊ฐ์ ๋ค๋ฅธ ๊ฒฝ๋ก๋ฅผ ์ค์ ํด์ kubeconfig ํ์ผ์ด ํด๋น ๊ฒฝ๋ก์ ์ ์ฅ๋๊ฒ ํ ์๋ ์๋ค)
๊ทธ๋ฐ๋ฐ ์๋ก ์ ์ผ๋ก ๋์๊ฐ์ ์ kubeconfig ํ์ผ์ ๊ตณ์ด SA ์ธ์ฆ ์ ๋ณด๋ฅผ ์ค์ ํ๋ ๊ฑธ๊น? ๊ทธ๋ฅ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ ๋์ด ์๋ ๊ด๋ฆฌ์ ๊ถํ์ ๊ฐ๋ ์ธ์ฆ์ ์ ๋ณด๋ก ํ๋ฉด ์๋ ๊น? ๋ฌผ๋ก ์๋๋ ๊ฒ์ ์๋์ง๋ง, ๋ณดํต k8s ํด๋ฌ์คํฐ์๋ ๋ค์ํ ์ง๋ฌด์ ๊ฐ๋ฐ์๊ฐ ์ ๊ทผํ๋ฉฐ, ๊ฐ ๊ฐ๋ฐ์์ ์ญํ ์ด ๊ฐ๊ธฐ ์๋ก ๋ค๋ฅด๋ค. ์ด๋ ๊ฒ ๋จ์ ๋ฐ๋ผ ์์ฐ์ค๋ ๊ฐ๋ฐ์์ ์ง๋ฌด๋ ์ญํ ์ ๋ฐ๋ผ k8s ํด๋ฌ์คํฐ์ ์ ๊ทผํด์ ํ ์ ์๋ ๊ถํ๋ค์ ์ ํํ ํ์๊ฐ ์๋ค. ์ด๋ ๊ฒ ๊ฐ๋ฐ์ ์ฆ, ์ผ์ข ์ ์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ์ฌ์ฉํ๋ ํด๋ผ์ด์ธํธ ๋ง๋ค ๊ถํ์ ๋ค๋ฅด๊ฒ ์ฃผ๊ธฐ ์ํด์ ๊ถํ์ด ์ ํ๋ SA๋ฅผ kubeconfig์ ์ค์ ํ๊ฒ ๋๋ค.
kubeconfig ํ์ผ์ SA๋ฅผ ์ค์ ํ๊ธฐ ์ ์ kubeconfig ํ์ผ์ ์์ฑ๋์ด ์๋ ๋ด์ฉ์ ๋ํด์ ์ข ๋ ๋ํ ์ผํ๊ฒ ์ดํดํ ํ์๊ฐ ์๋ค. [๋ชฉ์ฐจ 2๋ฒ]์์๋ ์ ๊น ์๊ฐํ๋ ์ ๋๋ก๋ง ํ๊ธฐ ๋๋ฌธ์ ์ด๋ฒ ๋ชฉ์ฐจ์์ ์ข ๋ ๋ํ ์ผํ๊ฒ ์์๋ณด์. ์ฐ์ kubeconfig ์์ ํ์ผ์ ํ๋ ์ดํด๋ณด์.
kubeconfig ํ์ผ์ ํฌ๊ฒ 3๊ฐ์ง ๋ถ๋ถ์ผ๋ก ๊ตฌ์ฑ๋์ด ์๋ค.
- clusters: ์ ์ํ ์ฟ ๋ฒ๋คํฐ์ค API ์๋ฒ์ ๋ชฉ๋ก. ์์๋ 1๊ฐ์ API ์๋ฒ๋ง ์กด์ฌํ์ง๋ง, ์ํ๋ค๋ฉด ๋ ์ถ๊ฐํ ์๋ ์์
- users: ์ฟ ๋ฒ๋คํฐ์ค API ์๋ฒ๋ก ์ ์ํ๊ธฐ ์ํ ์ฌ์ฉ์ ์ธ์ฆ ์ ๋ณด ๋ชฉ๋ก. ํด๋น ํญ๋ชฉ์ SA์ ํ ํฐ์ ์ ๋ ฅํ ์๋ ์๊ณ , ์ฟ ๋ฒ๋คํฐ์ค์์ ์ฌ์ฉ๋๋ ๋ฃจํธ ์ธ์ฆ์๋ก๋ถํฐ ๋ฐ๊ธ๋ฐ์ ํ์ ์ธ์ฆ์์ ๋ฐ์ดํฐ๋ฅผ ์ ๋ ฅํ ์๋ ์์
- contexts: clusters ํญ๋ชฉ์ ์๋ ํ๋์ cluster ์ users ํญ๋ชฉ์ ์๋ ํ๋์ user๋ฅผ ์กฐํฉํด์ ์ต์ข ์ ์ผ๋ก ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ์ ๋ณด๋ฅผ ์ค์ . ์ฆ, ์ค์ง์ ์ผ๋ก ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ก ์ ๊ทผํ ๋๋ ์ด ์ปจํ ์คํธ๋ผ๋ ๊ฒ 1๊ฐ๋ฅผ ์ ํํด์ ์ ๊ทผํจ. '์กฐํฉ'์ด๋ผ๋ ๋จ์ด์์ ์ ์ถํ ์ ์๋ฏ์ด M๊ฐ์ cluster ํญ๋ชฉ๊ณผ N๊ฐ์ user ํญ๋ชฉ์ด ์๋ค๋ฉด ์ด๋ฅผ ์๋ก ๋ชจ๋ ์กฐํฉํด์ ์ปจํ ์คํธ๋ฅผ ๋ง๋ค ์ ์์
๋ง์ฝ ์ฌ๋ฌ ๊ฐ์ ์ปจํ ์คํธ๋ฅผ ์ฌ์ฉํ๊ฒ ๋๋ฉด ์ธ์ ๋ ๋ด๊ฐ ๋ก์ปฌ์์ ๊ตฌ์ถํ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ก ์ ๊ทผํ๊ณ , ๋ ์ธ์ ๋ ํ์ฌ์ ์๊ฒฉ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ์ ๊ทผํ ์๋ ์๋ค.
์ด์ kubeconfig ํ์ผ์ ๋ด์ฉ์ ์์ ํด์ ํน์ SA๋ฅผ ์ค์ ํ ๋ค, ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ํด๋น SA์ ๊ถํ์ผ๋ก ์ ๊ทผํด๋ณด๋๋ก ํ์. kubeconfig ํ์ผ๋ ์ด์จ๊ฑด ํ ์คํธ ํํ์ ํ์ผ์ด๊ธฐ ๋๋ฌธ์ vim์ด๋ nano, IDE์ ๊ฐ์ ์๋ํฐ๋ก ์ง์ ์์ ํ ์๋ ์๊ธด ํ์ง๋ง kubectl config ๊ณ์ด์ ๋ช ๋ น์ด๋ก๋ ์์ ํ ์ ์๋ค. ๋ง์ฝ ์ ์ ๋ฅผ ํ๋ ์ถ๊ฐํ๋ ๋ช ๋ น์ด๋ฅผ ์ํํ๋ค๊ณ ํ๋ฉด ์์๋ ์๋์ ๊ฐ๋ค.
kubectl config set-credentials $USER_NAME --token=$DECODED_TOKEN
$DECODED_TOKEN ์ด๋ผ๋ ๋ณ์ ๊ฐ์๋ ์ถ๊ฐํ๋ ค๋ SA์ ์ค์ ๋ ์ํฌ๋ฆฟ์ Token์ base64 ๋์ฝ๋ฉํ ๊ฐ์ ๋ช ์ํ๋ฉด ๋๋ค. ๊ทธ๋ฐ๋ฐ ์ด๋ ๊ฒ ํ๊ณ ๋์ผ๊น? ์๋๋ค. ์์์ ์ค๋ช ํ์ง๋ง ์ค์ง์ ์ผ๋ก ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ์ ๊ทผํ ๋ ์ฌ์ฉํ๋ ํญ๋ชฉ์ 'context' ๋ผ๊ณ ํ๋ค. ์ด์ ์ฐ๋ฆฌ๋ ์๋ก์ด ์ ์ ๋ฅผ ์ถ๊ฐํด์ฃผ์์ผ๋, ์ด ์ถ๊ฐํ ์ ์ ๊ฐ ์ด๋ค ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ์ ์ ๊ทผํ ๊ฒ์ธ์ง ๋ช ์ํ๋ ์ปจํ ์คํธ๋ฅผ ๋ง๋ค์ด ์ค ์ฐจ๋ก๋ค. ์ด ๋ํ kubectl config ๋ช ๋ น์ด๋ก ์์ฑ์ด ๊ฐ๋ฅํ๋ค. ์์๋ ์๋์ ๊ฐ๋ค.
kubectl config set-context $NEW_CONTEXT_NAME --cluster=$CLUSTER_NAME --user=$USER_NAME
7. k8์์์ User ์ Group
์ฟ ๋ฒ๋คํฐ์ค์์๋ SA ์ธ์๋ User์ Group ์ด๋ผ๋ ๊ฐ๋ ์ด ์กด์ฌํ๋ค. User๋ ๋ง ๊ทธ๋๋ก ์ฟ ๋ฒ๋คํฐ์ค๋ฅผ ์ฌ์ฉํ๋ ์ค์ ์ฌ์ฉ์๋ฅผ ๋ปํ๋ฉฐ User 1๊ฐ ๋น ์ฌ์ฉ์ 1๋ช ์ ๋๋ก(๋ฌผ๋ก ์ค์ ์ฌ๋ 1๋ช ์ ์๋ฏธํ๋ ๊ฒ์ ์๋)์๊ฐํ๋ฉด ์ฝ๋ค. ๊ทธ๋ฆฌ๊ณ Group์ ์ด User ์ฌ๋ฌ ๊ฐ๋ฅผ ๋ชจ์ ๋์ ์งํฉ์ ์๋ฏธํ๋ค. ์ค์ ๋ก ์ด User, Group๋ ๋กค ๋ฐ์ธ๋ฉ ๋๋ ํด๋ฌ์คํฐ ๋กค ๋ฐ์ธ๋ฉ ๋งค๋ํ์คํธ์ subjects ํญ๋ชฉ์ SA ์ฒ๋ผ ๋ช ์ํ ์ ์๋ค. ์๋ ๋งค๋ํ์คํธ๋ ์ค์ ์ฟ ๋ฒ๋คํฐ์ค ๊ณต์ ๋ฌธ์์์ RoleBinding ๋ด์ฉ์ ์ค๋ช ํ ๋ ์ฌ์ฉํ๋ ์์ ์ค ํ๋์ด๋ค.
apiVersion: rbac.authorization.k8s.io/v1
# This role binding allows "jane" to read pods in the "default" namespace.
# You need to already have a Role named "pod-reader" in that namespace.
kind: RoleBinding
metadata:
name: read-pods
namespace: default
subjects:
# You can specify more than one "subject"
- kind: User
name: jane # "name" is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
# "roleRef" specifies the binding to a Role / ClusterRole
kind: Role #this must be Role or ClusterRole
name: pod-reader # this must match the name of the Role or ClusterRole you wish to bind to
apiGroup: rbac.authorization.k8s.io
๊ทธ๋ฐ๋ฐ ์ฌ๊ธฐ์ ํท๊ฐ๋ฆฌ๋ ์ ์ด ์๋ค. SA๋ ๊ทธ๋ผ User์ Group ๊ฐ๋ ๊ณผ ์ด๋ค ์ฐจ์ด๊ฐ ์๋ ๊ฑธ๊น? ์ฌ์ค์ SA๋ ์ต์ข ์ ์ผ๋ก๋ User ๊ฐ๋ ์ ์ํ๋ค. ์ด์ ๋ํ ๊ทผ๊ฑฐ๋ก, ํน์ ๋ฆฌ์์ค ๋ฐ ์ก์ ์ ๋ํ ๊ถํ์ด ์๋ SA์ธ๋ฐ, ๊ทธ ๊ถํ์ ์ทจํ๋ ค๊ณ ํ๋ค๋ฉด kube-apiserver๋ ๋ค์๊ณผ ๊ฐ์ ์๋ฌ ์๋ต์ ๋ด๋ฑ๊ฒ ๋๋ค.
Error from server (Forbidden): pods is forbidden: User "system:serviceaccount:default:zedd-sa" cannot list resource "pods" in API group "" in the namespace "default"
์ ๋ฉ์ธ์ง๋ zedd-sa ๋ผ๋ ์ด๋ฆ์ SA๊ฐ default ๋ผ๋ ๋ค์์คํ์ด์ค์ ํ๋์ ๋ํด์ ๋ชฉ๋ก์ ์ถ๋ ฅํ๋ list ๊ถํ์ด ์๋ค๋ ์๋ฏธ์ด๋ค. ์ด ๋ ์ฃผ๋ชฉํ ๋ถ๋ถ์ ์๋ฌ ๋ฉ์ธ์ง ์ 'User' ๋ผ๊ณ ๋์ด ์๋ ๋ถ๋ถ์ด๋ค. ๋ถ๋ช ์ฐ๋ฆฌ๋ SA๋ฅผ ์ด์ฉํด ๊ถํ์ ์ทจํ๋ ค๊ณ ํ๋๋ฐ kube-apiserver๋ ์ด SA๋ฅผ ๋ณด๊ณ 'User'๋ผ๊ณ ํํํ๊ณ ์๋ค. ์ฆ, ์ด SA๋ ์ผ์ข ์ User์ธ ์ ์ด๊ณ , ๊ทธ User ์ด๋ฆ์ด 'system:serviceaccount:default:zedd-sa' ๊ฐ ๋๋ ๊ฒ์ด๋ค. ์ค์ ๋ก ๋กค ๋ฐ์ธ๋ฉ์ ํด๋น User ์ด๋ฆ์ "kind: User" ๋ผ๋ ๊ฒ์ ์ด์ฉํด ๋ช ์ํ ์ ์๋ค.
...(RoleBinding ๋งค๋ํ์คํธ ์๋ต)...
subjects:
- kind: User
name: system:serviceaccount:default:zedd-sa
namespace: default
roleRef:
(... ์๋ต ...)
๊ทธ๋ฌ๋ฉด Group์ ์ User ์ด๋ฆ์์ ์ด๋ค ๋ถ๋ถ์ ์ง์นญํ ๊น? ๊ทธ๋ฆผ์ผ๋ก ํํํ๋ฉด ์๋์ ๊ฐ๋ค.
์ด ์์์์๋ Group์ ์ด 2๊ฐ๋ฅผ ์ง์นญํ ์ ์๋๋ฐ, ์ฒซ ๋ฒ์งธ๋ system:serviceaccount ์ด๋ค. ์ด Group์ ๋ชจ๋ ๋ค์์คํ์ด์ค์ ์ํ๋ ๋ชจ๋ ์๋น์ค ์ด์นด์ดํธ๊ฐ ์ํด ์๋ ๊ทธ๋ฃน์ ์๋ฏธํ๋ค. ๋ ๋ฒ์งธ์ธ system:serviceaccount:default ๋ผ๋ Group์ default ๋ผ๋ ๋ค์์คํ์ด์ค์ ์ํ๋ ๋ชจ๋ ์๋น์ค ์ด์นด์ดํธ๊ฐ ์ํด ์๋ ๊ทธ๋ฃน์ ์๋ฏธํ๋ค.
์ด๋ฌํ Group๋ค์ ํด๋ฌ์คํฐ ๋กค ๋ฐ์ธ๋ฉ์ ์๋์ ๊ฐ์ด ๋ช ์๋ ์ ์๋ค.
# docs: https://kubernetes.io/docs/reference/access-authn-authz/rbac/#clusterrolebinding-example
apiVersion: rbac.authorization.k8s.io/v1
# This cluster role binding allows anyone in the "manager" group to read secrets in any namespace.
kind: ClusterRoleBinding
metadata:
name: read-secrets-global
subjects:
- kind: Group
name: manager # Name is case sensitive
apiGroup: rbac.authorization.k8s.io
roleRef:
kind: ClusterRole
name: secret-reader
apiGroup: rbac.authorization.k8s.io
system ์ด๋ผ๋ ์ ๋์ด๋ก ์์ํ๋ ๊ฒ๋ค์ ์ฟ ๋ฒ๋คํฐ์ค๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ๋ฏธ๋ฆฌ ์ ์ํด ๋ ์ ์ ๋ ๊ทธ๋ฃน๋ค์ด๋ค. ์ด๋ฌํ ๋ํ์ ์ธ ์์๋ค๋ก๋, API ์๋ฒ์ ์ธ์ฆ์ ์ฑ๊ณตํ ๊ทธ๋ฃน์ ์๋ฏธํ system:authenticated, ์ธ์ฆ์ ์คํจํ ๊ทธ๋ฃน์ธ system:unauthenticated, ์ธ์ฆ์ ์คํจํ ์ ์ ๋ฅผ ์๋ฏธํ๋ system:anonymous ๋ฑ์ด ์๋ค. ์ฐธ๊ณ ํด์ ์์๋๋๋ก ํ์.
์ด๋ ๊ฒ ์ฟ ๋ฒ๋คํฐ์ค๊ฐ ๊ธฐ๋ณธ์ ์ผ๋ก ์ ์ํด๋ ์ ์ ์ ๊ทธ๋ฃน์ ์ฌ์ฉํ๋ฉด ๋๊ธด ํ์ง๋ง, ์ค๋ก์ง ์ด๊ฒ๋ง ์ฌ์ฉํด์ผ ํ๋ ๊ฒ์ ์๋๋ค. ๊ฐ์์ ์กฐ์ง์ ๋ง๊ฒ ์ปค์คํ ํ๊ฒ ์ ์ ์ ๊ทธ๋ฃน์ ๊ตฌ์ฑํ ์ ์๋ค. ์๋ฅผ ๋ค์ด, kubeconfig ํ์ผ์ ๊ธฐ๋ณธ์ ์ผ๋ก ์ค์ ๋์ด ์๋ ์ธ์ฆ ๋ฐฉ๋ฒ์ธ x509 ์ธ์ฆ์๋ฅผ ์ฌ์ฉํ๊ฑฐ๋ ๋ณ๋์ ์ธ์ฆ ์๋ฒ์ธ ๊นํ๋ธ ๊ณ์ , ๊ตฌ๊ธ ๊ณ์ , LDAP ๋ฐ์ดํฐ ๋ฑ์ ์ฟ ๋ฒ๋คํฐ์ค ์ฌ์ฉ์ ์ธ์ฆ์ ์ฌ์ฉํ ์๋ ์๋ค.
์ฐธ๊ณ ๋ก ๋ณ๋์ ์ธ์ฆ์๋ฒ๋ผ ํจ์ ๋ณดํต OAuth์ OIDC๋ฅผ ์ด์ฉํ Dex๋ ๋จ์ ํ ํฐ์ ์ด์ฉํด ์นํ ์ธ์ฆ ์์คํ ์ ๊ตฌํํ๋ Guard ๋ฑ์ด ์๋ค.