์ต๊ทผ ๋ง์ ํ์๋ค์ด ์๋น์ค, ํ์ดํ๋ผ์ธ ๋ด์์ k8s ํด๋ฌ์คํฐ์์ ์ ๋ณด๋ฅผ ์ป์ด์์ผ ํ๋ ๊ฒฝ์ฐ, ์ด๋ฏธ์ง ๋ด์ kubectl์ ์ค์นํ๊ณ ์ฝ๋์์ kubectl ์ปค๋งจ๋๋ฅผ string์ผ๋ก ์ ์ฅํด ์ฌ์ฉํ๊ฑฐ๋(?) ์ฌ์ง์ด token๊ฐ์ string์ผ๋ก ๋ฐ์ ๋ฃ์ผ๋ ค๋(!) ์๋๋ฅผ ํ๊ณ ์์์ ๊นจ๋ฌ์๋ค.
์ด ๋ถ๋ถ์ ๋ฐ๋ก ์ก์ผ๋ฉฐ, ์ฌ๋๋ค์๊ฒ ์ด๋ค ๋ฌธ์๋ฅผ ๋ง์ด ๋ฐ์๋์ง๋ฅผ ๋ฐํ์ผ๋ก ์ ๋ฆฌํด๋ณด๊ณ ์ ํ๋ค.
kubectl์ ์ด๋ฏธ์ง ๋ด ์ค์นํ๋ค(?)
์ฌ์ค ๋ถ๊ฐ๋ฅํ ๋ฐฉ๋ฒ์ ์๋๋ค.
- ์ด๋ฏธ์ง ๋ด kubectl ๋ฐ์ด๋๋ฆฌ๋ฅผ ์ค์นํด๋๋ค.
- ์๋น์ค๊ฐ ์ฌ์ฉํ ์ ์ ํ ๊ถํ์ ๊ณ์ ์ ์ถ๊ฐํ๊ณ , kubeconfig๋ฅผ ์์ฑํ๋ค.
- configmap์ผ๋ก kubeconfig๋ฅผ ๋ง์ดํธํ๋ค.
์ด ๊ฒฝ์ฐ, ์ฝ๋ ์์ ์์คํ
์ปค๋งจ๋๋ฅผ ์คํํ๊ณ ๊ฒฐ๊ณผ๋ฅผ ํ์ฑํด์ ์ฌ์ฉํ๊ฒ ๋๋๋ฐ,
์๋ฌ ์ฒ๋ฆฌ, ๋๋ฒ๊น
๋ ์ ํ ๊ณ ๋ คํ์ง ์์ ๋ฐฉ์์ผ ๋ฟ ์๋๋ผ ์ดํ์ ์ด์ด์ง ๋ก์ง์ ๊ตฌํํ๋ ๊ฒ๋ ์์ฑํด์ง๊ฒ ๋๋ค.
๊ฐ์ธ์ ์ธ ์๊ฐ์ด์ง๋ง ๊ถํ ๊ด๋ฆฌ ์ธก๋ฉด์์๋ ์๋น์ค์ ๊ถํ์ ์๋น์ค ์ด์นด์ดํธ๋ก ๊ด๋ฆฌํ์ง ์๊ณ , ๋ฐ๋ก ๊ณ์ ์ ๋ง๋๋ ๊ฒ์ด ๊นจ๋ํ์ง ๋ชปํ ๊ด๋ฆฌ ๋ฐฉ๋ฒ์ผ๋ก ์๊ฐ๋๋ค.
kubectl
์ฌ๋๋ค์ด ์ด๋ฏธ์ง ๋ด kubectl์ ์ค์นํด ์ฌ์ฉํด์๋๊ฑด, kubectl์ด ์ด๋ป๊ฒ ๋์ํ๋ ์ง๋ ํน๋ณํ ๊ด์ฌ์ ๊ฐ์ง ์๊ณ k8s๋ฅผ ํต์ ํ๋ ์ ์ผํ ๋ง๋ฅ ๋๊ตฌ์ธ ๊ฒ ์ฒ๋ผ ์๊ฐํด์๊ธฐ ๋๋ฌธ์ด๋ค. ์ดํ๋ฆฌ์ผ์ด์ ๊ฐ๋ฐ์ ๊ด์ ์์ ์ฟ ๋ฒ๋คํฐ์ค ํด๋ฌ์คํฐ๋ ๊ฒฐ๊ตญ ์ฟ ๋ฒ๋คํฐ์ค API๋ก ๋์ํ๋ ๋ ์์ด๊ณ , kubectl ์ญ์ cli์์ API๋ฅผ ์ปค๋งจ๋๋ก ์ฝ๊ฒ ๋ ๋ฆด ์ ์๋๋ก ํด์ฃผ๋ ์ฌ๋ฌ client ์ค ํ๋์ด๋ค.
์๋ฅผ ๋ค์ด ์๋ ๊ฐ๋จํ kubectl ์ปค๋งจ๋๋, KUBECONFIG์ ์ ์๋์ด ์๋ k8s API ์๋ฒ ์ฃผ์, ์ธ์ฆ ์ ๋ณด, ๊ณ์ ์ ๋ณด ๋ฑ์ ๊ฐ์ง๊ณ "GET /api/v1/namespaces/{namespace}/pods/{name}" ์ ์์ฒญ์ k8s master ๋ ธ๋์ API ์๋ฒ์ ๋ณด๋ด๋ ๊ฒ์ด๋ค.
kubectl get pods -n spark
ํ๋ ๋ด์์ ์ฟ ๋ฒ๋คํฐ์ค API ์ ๊ทผ
๋ค์ ๋ณธ๋ก ์ผ๋ก ๋์์, ๊ทธ๋ผ ํ๋ ์์์ ์ด๋ป๊ฒ ์์ฒญ์ ๋ณด๋ด๋ ๊ฒ์ด ์ณ์ ๋ฐฉ๋ฒ์ด๋ ๋ง์ด๋.
๊ณต์๋ฌธ์์ ์์ฃผ ์ ์ค๋ช
์ด ๋์ด ์๋ค.
API ์๋ฒ๋ฅผ ์ธ์ฆํ๋ ๊ถ์ฅ ๋ฐฉ๋ฒ์ ์๋น์ค ์ด์นด์ดํธ ์๊ฒฉ ์ฆ๋ช ์ ์ฌ์ฉํ๋ ๊ฒ์ด๋ค. ๊ธฐ๋ณธ์ ์ผ๋ก, ํ๋๋ ์๋น์ค ์ด์นด์ดํธ์ ์ฐ๊ฒฐ๋์ด ์์ผ๋ฉฐ, ํด๋น ์๋น์ค ์ด์นด์ดํธ์ ๋ํ ์๊ฒฉ ์ฆ๋ช (ํ ํฐ)์ ํด๋น ํ๋์ ์๋ ๊ฐ ์ปจํ ์ด๋์ ํ์ผ์์คํ ํธ๋ฆฌ์ /var/run/secrets/kubernetes.io/serviceaccount/token ์ ์๋ค.
์์ฝํ์๋ฉด, ๊ถํ ์ ์ด, ์ธ์ฆ ๋ฑ์ ์๋น์ค๊ฐ ๋ฌผ๊ณ ์๋ ์๋น์ค ์ด์นด์ดํธ์ ์๊ณ , ํ๋์ ๋ง์ดํธ๋์ด ์์ผ๋, ๊ฐ์ ธ์ ์ ์ ํ API๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
ํ๋ ๋ด์์ "์ปค๋งจ๋"๋ก API์ ๋ ๋ ค๋ณด์๋ฉด, ์๋์ ๊ฐ์ ์์ฒญ์ด ๋๋ค.
APISERVER=https://kubernetes.default.svc
SERVICEACCOUNT=/var/run/secrets/kubernetes.io/serviceaccount
TOKEN=$(cat ${SERVICEACCOUNT}/token)
CACERT=${SERVICEACCOUNT}/ca.crt
curl --cacert ${CACERT} --header "Authorization: Bearer ${TOKEN}" -X GET ${APISERVER}/api/v1/namespaces/spark/pods
ํ๋ ๋ด์์ "ํ์ด์ฌ"์ผ๋ก API๋ฅผ ๋ ๋ ค๋ณด์๋ฉด, ์๋์ ๊ฐ์ ์์ฒญ์ด ๋๋ค.
conf = client.Configuration()
conf.api_key['authorization'] = open('/var/run/secrets/kubernetes.io/serviceaccount/token').read()
conf.api_key_prefix['authorization'] = 'Bearer'
conf.host = 'https://kubernetes.default'
conf.ssl_ca_cert = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'
conf.verify_ssl = True
v1 = client.CoreV1Api(client.ApiClient(conf))
pod_items: {} = v1.list_namespaced_pod("spark", watch=False).items
Service Account์ ๊ถํ ๋ถ์ฌ
(์ค๋ช ์ ์ํด ์ํฉ์ ๊ฐ์ ํด๋ณด์) ๋ชจ๋ธํ์ต ํ์ดํ๋ผ์ธ ํ์ด์ฌ ์ฝ๋์์, ์๋ก ์ค์นํ spark-operator์ ์ปค์คํ ์ค๋ธ์ ํธ์ธ sparkapplication์ ์์ฑํ๋ ค๊ณ ํ๋ค.
์ปค์คํ ์ค๋ธ์ ํธ๋ CRD(Custom Resource Definement)๋ฅผ ํตํด ์ ์๋๋ค. CRD์๋ ๋ฆฌ์์ค์ ์คํ๊ณผ ํด๋น ๋ฆฌ์์ค์ ๋ํ ๊ธฐ๋ฅ์ ์ ๊ณตํ API ์ด๋ฆ์ด ์ ์๋์ด ์๋ค. ์ค์ spark-operator์ crd๋ ๋ค์๊ณผ ๊ฐ๋ค.
์ด์ฐ๋๋ ํด๋น API๋ฅผ ํตํด, ํด๋น ๋ฆฌ์์ค์ ๋ํ ๊ธฐ๋ฅ์ ์์ฒญํ ์ ์๋ ๊ฒ์ด๋ฏ๋ก, ํด๋ผ์ด์ธํธ๋ฅผ ์์ฑํ๋ค. ํ์ด์ฌ ์ฝ๋์์ ๊ฐ์ ํ์ผ๋, python-kubernetes-client๋ฅผ ์ฌ์ฉํ๊ธฐ๋ก ํ๋ค. ๋จผ์ python-kubernetes-client์ ๊ณต์ ๋ฌธ์์์ ์ด๋ค ํํ๋ก ์ปค์คํ ์ค๋ธ์ ํธ์ ๋ํ ์ ๊ทผ์ ์ ๊ณตํ๋์ง ํ์ธํ๊ณ , ์คํ์ ๋ง๊ฒ ๊ตฌํํ๋ค.
์์ฑ ๊ธฐ๋ฅ๋ง ์ฐ๋ ์์ฑํด๋ณด์.
import kubernetes.client
import logging
class KubernetesClient:
def __init__(self):
conf = kubernetes.client.Configuration()
conf.api_key['authorization'] = open('/var/run/secrets/kubernetes.io/serviceaccount/token').read()
conf.api_key_prefix['authorization'] = 'Bearer'
conf.host = 'https://kubernetes.default'
conf.ssl_ca_cert = '/var/run/secrets/kubernetes.io/serviceaccount/ca.crt'
conf.verify_ssl = True
self.api_client = kubernetes.client.ApiClient(conf)
def create_crd(self, group: str, version: str, namespace: str, plural: str, body: object):
logging.info(f"Kubernetes Client::Creating custom resource {plural}({group}/{version}).")
api = kubernetes.client.CustomObjectsApi(self.api_client)
return api.create_namespaced_custom_object(
group=group,
version=version,
namespace=namespace,
plural=plural,
body=body
)
์ฝ๋๋ฅผ ์คํํ๋ ์๋ฌ๊ฐ ๋ฐ์ํ๋ค.
spark-operator๋ฅผ ์๋กญ๊ฒ ์ค์นํ๊ณ , ์๋ก์ด ๋ฆฌ์์ค์ API๊ฐ ์๊ฒผ๋๋ฐ, ํ์ฌ ํ์ดํ๋ผ์ธ์ด ๊ฐ์ง ์๋น์ค ์ด์นด์ดํธ์๋ ํด๋น API์ ๋ํ ๊ถํ ์ ๋ณด๊ฐ ์๋ ๊ฒ์ด๋ค. sparkapplication์ ๋ํ ์์ฑ, ์กฐํ, ์ญ์ ๋ฑ ํ์ํ ๊ถํ์ ๊ณจ๋ผ ๋ด์ Role์ ๋ง๋ค๊ณ ํ์ดํ๋ผ์ธ์ ์๋น์ค ์ด์นด์ดํธ์ Role์ ๋ฌถ๋ RoleBinding์ ์์ฑํด์ค๋ค. ํ์ํ ๊ฒฝ์ฐ ClusterRole ClusterRoleBinding์ ์์ฑํ๋ค. ์์ธํ ์ฌํญ์ ๊ณต์ ๋ฌธ์๋ฅผ ์ฐธ๊ณ ํ๋ค.
์์ฝ
์๋ ์ ๋๋ ๊ธฐ๋ณธ์ด๋ ์๊ณ ์ฌ์ฉํ์.
- kubectl์ ์ด๋ฏธ์ง ๋ด ์ค์นํด์ ์ฐ๋ ๊ฒ์, ์ด๋ฏธ์ง ํฌ๊ธฐ๋ฅผ ํค์ธ ๋ฟ ์๋๋ผ ๋๋ถ๋ถ์ ๊ฒฝ์ฐ ์ ์ ํ ๋ฐฉ๋ฒ์ด ์๋๋ค.
- ์๋น์ค๊ฐ ํด๋ฌ์คํฐ์ ์ ๋ณด๋ฅผ ์ฃผ๊ณ ๋ฐ์์ผ ํ๋ ๊ฒฝ์ฐ ์ฝ๋๋ก ํด๋ผ์ด์ธํธ๋ฅผ ํตํด ์ ์ดํ์.
- ์๋น์ค๊ฐ ํด๋ฌ์คํฐ ๋ด ๊ถํ์ด ํ์ํ ๊ฒฝ์ฐ role, cluseterRole์ ํ์ํ ๋ฆฌ์์ค ๊ถํ์ ๊ณจ๋ผ ๋ด์ ์๋น์ค ์ด์นด์ดํธ์ ๋ฐ์ธ๋ฉํ๋ค.
'๐ป > MLOps' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
Finagle & Thrift (0) | 2024.05.09 |
---|---|
stern : ๋ถ์ฐ ์ฒ๋ฆฌ ํ๋ซํผ ๋ชจ๋ํฐ๋ง (0) | 2024.02.23 |
[k8s] `kubectl top` (0) | 2024.01.02 |
Apache Cassandra (0) | 2023.07.31 |
[Pinot] ์คํ์์ค ๊ธฐ์ฌ ํ๋ก์ธ์ค (0) | 2023.03.05 |