Authentication


κ°œλ°œμžλ‚˜ κ΄€λ¦¬μžκ°€ K8s Cluster 와 μ†Œν†΅ν•˜κΈ° μœ„ν•΄μ„  항상 kube-apiserver λ₯Ό κ±°μΉ˜κ²Œλœλ‹€. λ•Œλ¬Έμ— kube-apiserver μ—μ„œ λͺ¨λ“  Authentication 이 이루어진닀. kube-apiserver λŠ” μš”μ²­μ„ Authenticate ν•˜κΈ° μœ„ν•΄ Static Password File, Static Token File, Certificates, Identity Service 등을 ν™œμš©ν•œλ‹€.

# user-details.csv
password123,user1,u0001,group1
password123,user2,u0002,group1
password123,user3,u0003,group1

μœ„μ²˜λŸΌ CSV ν˜•μ‹μ˜ Static Password File 을 μƒμ„±ν•˜κ³ ,

ExecStart=/usr/local/bin/kube-apiserver \
  ...
  --basic-auth-file=user-details.csv

kube-apiserver λ₯Ό μ‹€ν–‰ν•  λ•Œ μ§€μ •ν•΄μ£Όκ±°λ‚˜,

apiVersion: v1
kind: Pod
metadata:
  creationTimestamp: null
  name: kube-apiserver
  namespace: kube-system
spec:
  containers:
  - command:
    - kube-apiserver
    - ...
    - --basic-auth-file=user-details.csv

kubeadm 을 μ‚¬μš©ν–ˆμ„ 경우 yaml νŒŒμΌμ— μ˜΅μ…˜μ„ μΆ”κ°€ν•΄μ£Όλ©΄λœλ‹€.

curl -v -k https://master-node-ip:6443/api/v1/pods -u "user1:password123"

이후 μš”μ²­μ„ 보낼 λ•Œ 아이디와 λΉ„λ°€λ²ˆν˜Έλ₯Ό μœ„μ™€ 같은 λ°©μ‹μœΌλ‘œ μ „λ‹¬ν•΄μ£Όλ©΄λœλ‹€.

# user-token-details.csv
KpjCq12wfdfqgwdfw,user4,u0004,group1
rJjncqwe1dgi2dow0,user5,u0005,group1
mjpOFiEq1dngi3dkf,user6,u0006,group1

Static Token File 을 μ‚¬μš©ν•  κ²½μš°μ—”

--token-auth-file=user-token-details.csv

μ˜΅μ…˜μ„ λŒ€μ‹  μ‚¬μš©ν•˜λ©΄ λœλ‹€.

curl -v -k https://master-node-ip:6443/api/v1/pods --header "Authorization: Bearer KpjCq12wfdfqgwdfw"

이후 μš”μ²­ μ‹œ 토큰을 헀더에 ν¬ν•¨ν•˜μ—¬ 전달해쀄 수 μžˆλ‹€.

μœ„ 방법은 μ•„μ£Ό 기초적인 λ°©λ²•μœΌλ‘œ v1.19 에 Deprecated 됐닀.

TLS Certificates for Cluster Components


K8s λ‚΄λΆ€μ˜ μ•”ν˜Έν™”λœ 톡신을 μœ„ν•΄ 각 μ»΄ν¬λ„ŒνŠΈ λ§ˆλ‹€ TLS Certificate κ³Ό Private Key κ°€ ν•„μš”ν•˜λ‹€.

  • CA
    • ca.crt
    • ca.key
  • Admin
    • admin.crt + admin.key
  • kube-scheduler
    • scheduler.crt + scheduler.key
  • kube-controller-manager
    • controller-manager.crt + controller-manager.key
  • kube-proxy
    • kube-proxy.crt + kube-proxy.key
  • kube-apiserver
    • apiserver.crt + apiserver.key
    • apiserver-etcd-client.crt + apiserver-etcd-client.key
    • apiserver-kubelet-client.crt + apiserver-kubelet-client.key
  • etcd-server
    • etcdserver.crt + etcdserver.key
  • kubelet-server
    • kubelet.crt + kubelet.key
# Key 생성
openssl genrsa -out ca.key 2048

# Certificate Signing Request 생성
openssl req -new -key ca.key -subj "/CN=KUBERNETES-CA" -out ca.csr

# Sign Certificate
openssl x509 -req -in ca.csr -signkey ca.key -out ca.crt

λ¨Όμ € CA Certificate 을 λ°œκΈ‰λ°›μ€ ν›„,

# Key 생성
openssl genrsa -out admin.key 2048

# Certificate Signing Request 생성
openssl req -new -key admin.key -subj "/CN=kube-admin" -out admin.csr

# Admin Privilage λ₯Ό ν¬ν•¨ν•œ CSR 생성
openssl req -new -key admin.key -subj "/CN=kube-admin/O=system:masters" -out admin.csr

# Sign Certificate
openssl x509 -req -in admin.csr -CA ca.crt -CAkey ca.key -out admin.crt

Admin 을 μœ„ν•œ Certificate 을 λ°œκΈ‰λ°›λŠ”λ‹€. 이후 λͺ¨λ“  μ»΄ν¬λ„ŒνŠΈμ— λ™μΌν•œ μž‘μ—…μ„ μˆ˜ν–‰ν•΄μ£Όλ©΄λœλ‹€.

openssl x509 -in /etc/kubernetes/pki/apiserver.crt -text -noout

Certificate 을 ν™•μΈν•˜κΈ° μœ„ν•΄μ„œ μœ„ λͺ…λ Ήμ–΄λ₯Ό μ‹€ν–‰ν•œ λ’€ Issuer, Subject λ“±μ˜ λ‚΄μš©μ„ 확인할 수 μžˆλ‹€.

cat /etc/kubernetes/manifests/kube-apiserver.yaml

kube-apiserver 에 μ–΄λ–€ Certificate 이 μ‚¬μš©λλŠ”μ§€ ν™•μΈν•˜λ €λ©΄ μœ„ yaml νŒŒμΌμ—μ„œ --tls-cert-file μ˜΅μ…˜μ„ ν™•μΈν•΄λ³΄μž.

cat /etc/kubernetes/manifests/etcd.yaml

etcd 에 μ–΄λ–€ Certificate 이 μ‚¬μš©λλŠ”μ§€ ν™•μΈν•˜λ €λ©΄ μœ„ yaml νŒŒμΌμ„ μ°Ύμ•„λ³΄μž.

Certificates API

openssl genrsa -out meatsby.key 2048
openssl req -new -key meatsby.key -subj "/CN=meatsby" -out meatsby.csr
cat meatsby.csr | base64 -w 0
apiVersion: certificates.k8s.io/v1beta1
kind: CertificateSigningRequest
metadata:
  name: meatsby
spec:
  groups:
  - system:authenticated
  usages:
  - digital signature
  - key encipherment
  - server auth
  request:
    <certificate-goes-here>
kubectl get csr
kubectl certificate approve meatsby
kubectl get csr meatsby -o yaml
echo "<certificate>" | base64 --decode

K8s λŠ” Admin 의 Certificate μž‘μ—…μ„ λŒ€μ‹ ν•΄μ£ΌκΈ° μœ„ν•œ API λ₯Ό μ œκ³΅ν•œλ‹€. Controller Manager κ°€ Certificate κ΄€λ ¨ μž‘μ—…μ„ λͺ¨λ‘ μ²˜λ¦¬ν•œλ‹€.

KubeConfig

curl https://my-kube-playground:6443/api/v1/pods \
  --key admin.key
  --cert admin.crt
  --cacert ca.crt
kubectl get pods
  --server my-kube-playground:6443
  --client-key admin.key
  --client-certificate admin.crt
  --certificate-authority ca.crt
kubectl get pods --kubeconfig config

curl λ˜λŠ” kubectl 둜 kube-apiserver 와 톡신할 λ•Œ 사싀 μœ„μ™€ 같이 인증 κ΄€λ ¨ μ˜΅μ…˜λ“€μ„ μ§€μ •ν•΄μ€˜μ•Ό ν•˜λŠ”λ° 이λ₯Ό κ°„νŽΈν•˜κ²Œ KubeConfig 둜 섀정해쀄 수 μžˆλ‹€. $HOME/.kube/config 경둜λ₯Ό κΈ°λ³Έκ°’μœΌλ‘œ μ‚¬μš©ν•˜κΈ° λ•Œλ¬Έμ— μ—¬νƒœκ» μ œμ™Έν•˜κ³  μ‚¬μš© κ°€λŠ₯ν–ˆλ˜ 것이닀.

apiVersion: v1
kind: Config
 
current-context: my-kube-admin@my-kube-playground
 
clusters:
- name: my-kube-playground
  cluster:
    certificate-authority: ca.crt
    server: https:///my-kube-playground:6443
 
contexts:
- name: my-kube-admin@my-kube-playground
  context:
    cluster: my-kube-playground
    user: my-kube-admin
    namespace: finance
 
users:
- name: my-kube-admin
  user:
    client-certificate: admin.crt
    client-key: admin.key
kubectl config view --kubeconfig=my-custom-config
kubectl config use-context prod-user@production

Authorization


K8s 에 λŒ€ν•œ μž‘μ—…μ„ μœ„ν•΄ curl μ΄λ‚˜ kubectl 둜 μš”μ²­μ„ 보내면 kube-apiserver μ—μ„œ μ œκ³΅ν•˜λŠ” API μ—μ„œ μš”μ²­μ„ μ²˜λ¦¬ν•˜κ²Œ λœλ‹€. 이 λ•Œ K8s Object 에 λŒ€ν•œ μž‘μ—…λ“€μ„ API Group 으둜 λ‚˜λ‰˜κ²Œ λ˜λŠ”λ°, /apis μ—”λ“œν¬μΈνŠΈ κΈ°μ€€μœΌλ‘œ μ•„λž˜μ™€ 같은 API Group 이 μ‘΄μž¬ν•œλ‹€.

  • /apps
    • /v1
      • /deployments
      • /replicasets
      • /statefulsets
  • /extensions
  • /networking.k8s.io
  • /storage.k8s.io
  • /authentication.k8s.io
  • /certificates.k8s.io

K8s λŠ” μœ„μ™€ 같은 λ‹€μ–‘ν•œ Resource 에 λŒ€ν•œ μž‘μ—…μ˜ κΆŒν•œμ„ μœ„ν•΄ μ•„λž˜μ™€ 같은 방법을 μ‚¬μš©ν•œλ‹€.

  • Node Authorization
    • kubelet 의 경우 Certificate 에 λͺ…μ‹œλœ system:node:node01 μ΄λΌλŠ” 이름을 톡해 Node Authorization λ°©μ‹μœΌλ‘œ kube-apiserver 와 톡신할 수 μžˆλ‹€.
  • Attribute-Based Access Controls (ABAC)
    • 각 μœ μ €λ§ˆλ‹€ Policy λ₯Ό μ μš©ν•΄μ„œ ν—ˆμš© κ°€λŠ₯ν•œ μš”μ²­λ“€μ„ μ§€μ •ν•  수 μžˆλ‹€.
  • Role-Based Access Controls (RBAC)
    • Policy λ₯Ό Role 둜 생성해 μœ μ €λ“€μ΄ Role 을 기반으둜 μš”μ²­ν•  수 μžˆλ„λ‘ ν•œλ‹€.
  • Webhook
ExecStart=/usr/local/bin/kube-apiserver \
  ...
  --authorization-mode=Node,RBAC,Webhook

kube-apiserver λ₯Ό μ‹€ν–‰ν•  λ•Œ --authorization-mode μ˜΅μ…˜μ„ 톡해 μ μš©ν•  Authorization Mechanism 을 지정해쀄 수 μžˆλ‹€. μœ„μ™€ 같이 μ„€μ •ν•΄ 쀄 경우, Node Authorization 을 μ‹œλ„ν•˜κ³  μ‹€νŒ¨ν•˜λ©΄ RBAC, 그리고 Webhook 순으둜 κΆŒν•œμ„ ν™•μΈν•œλ‹€.

Role-Based Access Controls

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: developer
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["pods"]
  verbs: ["get", "update", "create"]
  resourceNames: ["blue", "orange"]
- apiGroups: [""]
  resources: ["ConfigMap"]
  verbs: ["create"]
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: devuser-developer-binding
subjects:
- kind: User
  name: dev-user # "name" is case sensitive
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: developer
  apiGroup: rbac.authorization.k8s.io

Role κ³Ό RoleBinding 을 톡해 RBAC 을 μ μš©ν•  수 μžˆλ‹€.

kubectl get roles
kubectl get rolebindings
kubectl describe role developer
kubectl describe rolebinding devuser-developer-binding

Role κ³Ό RoleBinding λͺ¨λ‘ K8s Object 이기 λ•Œλ¬Έμ— μœ„ λͺ…λ Ήμ–΄λ“€λ‘œ μ‘°νšŒκ°€ κ°€λŠ₯ν•˜λ‹€.

kubectl auth can-i create deployments
kubectl auth can-i delete nodes

kubectl auth can-i create deployments --as dev-user
kubectl auth can-i create pods --as dev-user

kubectl auth can-i create pods --as dev-user --namespace test

Role 이 μ–΄λ–€ μž‘μ—…μ„ μˆ˜ν–‰ν•  수 μžˆλŠ”μ§€ 확인해야할 경우 μœ„ λͺ…령어듀을 μ‚¬μš©ν•  수 μžˆλ‹€.

Cluster Roles and Role Bindings

# namespace 에 ν¬ν•¨λœ λ¦¬μ†ŒμŠ€ 확인
kubectl api-resources --namespaced=true

# namespace 에 ν¬ν•¨λ˜μ§€ μ•Šμ€ λ¦¬μ†ŒμŠ€ 확인
kubectl api-resources --namespaced=false
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: cluster-administrator
rules:
- apiGroups: [""] # "" indicates the core API group
  resources: ["nodes"]
  verbs: ["get", "list", "delete", "create"]
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: cluster-admin-role-binding
subjects:
- kind: User
  name: cluster-admin
  apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: ClusterRole
  name: cluster-administrator
  apiGroup: rbac.authorization.k8s.io

Role 은 Namespace λ₯Ό μ§€μ •ν•΄μ£Όμ§€ μ•Šμ„ 경우 default namespace 둜 μ„€μ •λœλ‹€. pods, replicasets, deployment λ“± namespace 에 ν¬ν•¨λ˜λŠ” K8s Object λ“€κ³Ό λ‹€λ₯΄κ²Œ nodes, PV, namespaces 와 같은 Cluster Scoped Object 듀은 Cluster Role 을 톡해 접근을 μ œν•œν•  수 μžˆλ‹€.

Service Accounts


K8s Account λŠ” User Account 와 Service Account 둜 λ‚˜λ‰œλ‹€. User Account λŠ” Admin, Developer 등이 μ‚¬μš©ν•˜κ³  Service Account λŠ” Prometheus, Jenkins λ“±μ˜ Application 이 μ‚¬μš©ν•œλ‹€. Application 이 kube-apiserver 와 ν†΅μ‹ ν•˜κΈ° μœ„ν•΄ Authentication 을 거쳐야 ν•˜λŠ”λ° 이λ₯Ό Service Account λ₯Ό 톡해 이뀄낼 수 μžˆλ‹€.

kubectl create serviceaccount dashboard-sa
kubectl get serviceaccount
kubectl describe serviceaccount dashboard-sa
kubectl describe secret dashboard-sa-token-kbbdm

Service Account λ₯Ό μƒμ„±ν•˜λ©΄ 인증을 μœ„ν•΄ μ‚¬μš©λ˜λŠ” Token μ—­μ‹œ μƒμ„±λœλ‹€. Token 의 경우 Secret Object λ₯Ό 톡해 κ΄€λ¦¬λœλ‹€. ν•΄λ‹Ή Token 을 ν™œμš©ν•΄ Application 을 인증 받을 수 μžˆλ‹€.

λ§Œμ•½ Application 을 Pod 의 ν˜•νƒœλ‘œ K8s Cluster λ‚΄μ—μ„œ ν˜ΈμŠ€νŒ…ν•œλ‹€λ©΄ Token 을 μˆ˜λ™μœΌλ‘œ μ œκ³΅ν•˜λŠ” λŒ€μ‹  λ³Όλ₯¨μ„ λ§ˆμš΄νŒ…ν•˜μ—¬ κ°„λ‹¨ν•˜κ²Œ μ œκ³΅ν•  수 μžˆλ‹€. K8s λŠ” 기본적으둜 각 namespace λ§ˆλ‹€ Service Account λ₯Ό μžλ™μœΌλ‘œ μƒμ„±ν•œλ‹€. ν•΄λ‹Ή namespace 에 Pod κ°€ 생성될 λ•Œ λ§ˆλ‹€ μƒμ„±λœ Service Account 와 Token 이 μžλ™μœΌλ‘œ λ³Όλ₯¨μ— λ§ˆμš΄νŒ…λœλ‹€.

kubectl create serviceaccount dashboard-sa
kubectl create token dashbaord-sa
apiVersion: v1
kind: Secret
type: kubernetes.io/service-account-token
metadata:
  name: mysecretname
  annotations:
    kubernetes.io/service-account.name: dashboard-sa

v1.22 λΆ€ν„° μœ„ λ‚΄μš©μ΄ λ³€κ²½λ˜μ—ˆλŠ”λ°, Service Account κ°€ TokenRequestAPI 둜 λΆ€ν„° Token 을 λ°›μ•„μ˜€λŠ” ν˜•μ‹μœΌλ‘œ μž‘λ™ν•œλ‹€. v1.24 μ—” Service Account λ₯Ό μƒμ„±ν•˜λ©΄ Token 을 직접 μƒμ„±ν•΄μ„œ μ„€μ •ν•΄μ£Όμ–΄μ•Όν•œλ‹€.

kubectl describe pod my-kubernetes-dashboard
kubectl exec -it my-kubernetes-dashboard -- ls /var/run/secrets/kubernetes.io/serviceaccount
kubectl exec -it my-kubernetes-dashboard cat /var/run/secrets/kubernetes.io/serviceaccount/token

Pod λ₯Ό μƒμ„±ν•œ λ’€ describe λ₯Ό 톡해 확인해보면 volumes.default-token-xxxxx 이 μƒμ„±λ˜μ–΄ μžˆλŠ” 것을 확인할 수 μžˆλ‹€.

apiVersion: v1
kind: Pod
metadata:
  name: my-kubernetes-dashboard
spec:
  containers:
  - name: my-kubernetes-dashboard
    image: my-kubernetes-dashboard
  serviceAccountName: dashboard-sa
  automountServiceAccountToken: false

Pod 에 Service Account λ₯Ό μ§€μ •ν•΄μ£ΌκΈ° μœ„ν•΄ spec.serviceAccountName 을 μ‚¬μš©ν•  수 있고 μžλ™μœΌλ‘œ Service Account κ°€ λ°°μ •λ˜λŠ” 것을 막기 μœ„ν•΄ spec.automountServiceAccountToken 을 μ‚¬μš©ν•  수 μžˆλ‹€.

Image Security


docker login private-registry.io
docker run private-registry.io/apps/internal-app

Pod μ—μ„œ 싀행될 Container 의 Image λŠ” 기본적으둜 Docker Hub μ—μ„œ 가져와 μ‚¬μš©ν•˜κ²Œ λœλ‹€. λ§Œμ•½ Private Registry μ—μ„œ Image λ₯Ό κ°€μ Έμ˜¨λ‹€λ©΄ μœ„μ™€ 같이 Docker 둜 λ‘œκ·ΈμΈν•΄μ„œ κ°€μ Έμ˜€κ²Œ λœλ‹€.

kubectl create secret docker-registry regcred \
  --docker-server=private-registry.io \
  --docker-username=registry-user \
  --docker-password=registry-password \
  --docker-email=registry-user@org.com
apiVersion: v1
kind: Pod
metadata:
  name: nginx-pod
spec:
  containers:
  - name: nginx
    image: private-registry.io/apps/internal-app
  imagePullSecrets:
  - name: regcred

K8s μ—μ„œ Pod Definition File 둜 Private Registry λ₯Ό μ΄μš©ν•˜λ €λ©΄ Image 의 μ „μ²΄κ²½λ‘œμ™€ Private Registry 에 λ‘œκ·ΈμΈν•˜κΈ° μœ„ν•œ Secret λ₯Ό μ—°λ™ν•΄μ€˜μ•Ό ν•œλ‹€.

Security Contexts


Docker Security

Docker Container λŠ” 기본적으둜 호슀트의 Process 둜써 μ‹€ν–‰λ˜κ³  Linux namespace λ₯Ό 톡해 κ²©λ¦¬λœλ‹€.

docker run --user=1000 ubuntu sleep 3600

Docker Container λŠ” 기본적으둜 root user 둜 μ‹€ν–‰λ˜κΈ° λ•Œλ¬Έμ— Container λ₯Ό μ‹€ν–‰ν•  λ•Œ --user μ˜΅μ…˜μ„ 톡해 root user κΆŒν•œμ„ μ œν•œν•  수 μžˆλ‹€.

docker run ubuntu

Docker Container λŠ” mac_admin, broadcast, net_admin, sys_admin λ“± ν˜ΈμŠ€νŠΈμ— 영ν–₯을 쀄 수 μžˆλŠ” Capability 듀이 μ œν•œλœλ‹€. λͺ¨λ“  Capability λŠ” /usr/include/linux/capability.h μ—μ„œ 확인할 수 μžˆλ‹€.

docker run --cap-add MAC_ADMIN ubuntu
docker run --cap-drop KILL ubuntu
docker run --privillege ubuntu

μœ„ μ˜΅μ…˜λ“€μ„ 톡해 Container 의 κΆŒν•œμ„ μ œμ–΄ν•  수 μžˆλ‹€.

Kubernetes Security

apiVersion: v1
kind: Pod
metadata:
  name: web-pod
spec:
  securityContext:
    runAsUser: 1000
    capabilities:
	  add: ["MAC_ADMIN"]
  containers:
  - name: ubuntu
    image: ubuntu
    command: ["sleep", "3600"]
    securityContext:
      runAsUser: 1001
      capabilities:
        add: ["MAC_ADMIN"]

K8s Pod μ—μ„œλ„ λ§ˆμ°¬κ°€μ§€λ‘œ user 의 κΆŒν•œμ„ securityContext λ₯Ό 톡해 μ œμ–΄ν•  수 μžˆλ‹€. Container λ ˆλ²¨μ— μ„ μ–Έλœ securityContext λŠ” ν•΄λ‹Ή Container 의 κΆŒν•œμ„ μ œμ–΄ν•˜κ³ , Pod λ ˆλ²¨μ— μ„ μ–Έλœ securityContext λŠ” Pod λ‚΄ λͺ¨λ“  Container 의 κΆŒν•œμ„ μ œμ–΄ν•œλ‹€.

kubectl exec ubuntu-sleeper -- whoami

μœ„ λͺ…λ Ήμ–΄λ₯Ό 톡해 Container User λ₯Ό 확인할 수 μžˆλ‹€.

Network Policy


apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: db-policy
spec:
  podSelector:
    matchLabels:
      role: db
  policyTypes:
  - Ingress
  - Egress
  ingress:
  - from:
    - podSelector:
        matchLabels:
          role: api-pod
    - namespaceSelector:
        matchLabels:
          name: prod
    - ipBlock:
        cidr: 192.168.5.10/32
	ports:
    - protocol: TCP
      port: 3306
  egress:
  - to:
    - ipBlock:
        cidr: 192.168.5.10/32
    ports:
    - protocol: TCP
      port: 80

K8s Cluster λŠ” 기본적으둜 μ†ν•œ λͺ¨λ“  Pod κ°„μ˜ 톡신을 ν—ˆμš©ν•œλ‹€. λ§Œμ•½ Ingress 와 Egress λ₯Ό μ œν•œν•˜κ³  μ‹Άλ‹€λ©΄ NetworkPolicy λ₯Ό μƒμ„±ν•˜μž.

Custom Resource Definition


apiVersion: flights.com/v1
kind: FlightTicket
metadata:
  name: my-flight-ticket
spec:
  from: Mumbai
  to: London
  number: 2

K8s 에선 ReplicaSet, Deployment λ“± 기본적으둜 μ œκ³΅λ˜λŠ” Resource 외에 μ‚¬μš©μžκ°€ μ»€μŠ€ν…€μœΌλ‘œ Resource λ₯Ό λ§Œλ“€ 수 μžˆλ‹€. μœ„μ™€ 같은 Resource λ₯Ό λ§Œλ“€κ³  싢을 λ•Œ Custom Resource Definition 을 생성해 Object λ₯Ό μƒμ„±ν•˜κ³  관리할 수 μžˆλ‹€.

apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  name: flighttickets.flights.com
spec:
  scope: Namespaced
  group: flights.com
  names:
    kind: FlightTicket
    singular: flightticket
    plural: flighttickets
  versions:
  - name: v1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            type: object
            properties:
              from:
                type: string
              to:
                type: string
              number:
                type: integer
                minimum: 1
                maximum: 10

μœ„μ™€ 같이 Custom Resource Definition 을 μƒμ„±ν•˜λ©΄ μ •μ˜λœ Custom Resource λ₯Ό μƒμ„±ν•˜κ³  관리할 수 μžˆλ‹€. λ‹€λ§Œ ETCD 에 μ €μž₯만 될 뿐 μ–΄λ–€ κΈ°λŠ₯이 μžˆλŠ” 것은 μ•„λ‹ˆλ‹€. κΈ°λŠ₯을 μΆ”κ°€ν•˜κΈ° μœ„ν•΄ Custom Controller λ₯Ό μž‘μ„±ν•  수 μžˆλ‹€.

Custom Controllers


Custom Resource λ₯Ό μ œμ–΄ν•˜λ €λ©΄ Custom Controller λ₯Ό μž‘μ„±ν•΄μ•Ό ν•˜λŠ”λ°, 파이썬 λ“± λ‹€μ–‘ν•œ μ–Έμ–΄λ‘œ μž‘μ„±ν•  수 μžˆμ§€λ§Œ API μ½œμ„ 기반으둜 ν†΅μ‹ ν•˜κΈ° λ•Œλ¬Έμ— 자체적으둜 큐 및 캐싱 μ‹œμŠ€ν…œμ„ 포함해야 ν•˜λŠ” μˆ˜κ³ κ°€ μžˆμ„ 수 μžˆλ‹€. λ•Œλ¬Έμ— K8s Go ν΄λΌμ΄μ–ΈνŠΈλ‘œ Custom Controller λ₯Ό μž‘μ„±ν•˜λ©΄ μ’€ 더 μ‰½κ²Œ Controller λ₯Ό ꡬ좕할 수 μžˆλ‹€.

Operator Framework


Operator Framework λŠ” CustomResourceDefinition κ³Ό CustomController λ₯Ό νŒ¨ν‚€μ§€ν™”ν•˜μ—¬ K8s 에 배포할 수 μžˆλ„λ‘ 도와쀀닀.

References