본문 바로가기

Container/Kubernetes

[K8S] Certificates API

Certificates(인증서)

인증서는 Kubernetes 클러스터 내 구성 요소(예: kube-apiserver, kubelet, etcd) 간의 TLS 통신을 암호화하고 인증하는 데 사용된다. 각 구성 요소는 인증서를 통해 서로의 신원을 확인하고, 안전하게 통신할 수 있다.

 

  • 클라이언트 인증서:
    • 클라이언트(예: kubectl)가 API 서버에 접근할 때 자신의 신원 증명
    • kubectl은 --client-certificate와 --client-key 옵션을 사용해 인증서를 지정
  • 서버 인증서:
    • 서버(API 서버, kubelet, etcd)가 클라이언트에게 자신의 신원 증명
    • 서버는 TLS 연결을 암호화하고, CA 인증서를 사용해 신뢰 보장
  • CA(Certificate Authority) 인증서:
    • 인증서를 발급하고, 클라이언트와 서버의 신뢰 보장

 

CertificateSigningRequest(CSR)

CSR은 TLS 인증서를 발급받기 위해 생성되는 요청(공개키, CN등 각종 정보)이다. 

참고 문서 : https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/

  • Private key 만들기
$ openssl genrsa -out myuser.key 2048
$ openssl req -new -key myuser.key -out myuser.csr -subj "/CN=myuser"
  • CSR 만들기
controlplane ~ ➜  cat akshay.csr | base64 -w 0
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZqQ0NBVDRDQVFBd0VURVBNQTBHQTFVRUF3d0dZV3R6YUdGNU1JSUJJakFOQmdrcWhraUc5dzBCQVFFRgpBQU9DQVE4QU1JSUJDZ0tDQVFFQXovTDFRWnRWM24wTmE1bDlKTEVSQlRTTlRsd0E3enFQTlFScFRBRkQ2djBMCnRka1BtTTVPejl0cEs1VVRiWWI0WXVKQTJqWS9LQmlHM3BHZ2NFWURhNlFsT1I5dTEyeE1wTXgzNHNpSFlWbFAKMU5JNFBVenpTclRqdWxCMmxFZGZKYWd3WjVCaGRsSU8yRTI2cDBZdGV5d1N1KzZmVTlLcEJJNC91Qzd4bjZOSwovRkhyZ0hyTldMdThWc0lCdU1SK2FxVG9COW02dkpoZzU1bXlYT1NPWW5mSS8zeG9POFRraFRWWlhLUy9vZU53CmN1V1hjRXd5TWVGakwrL24xbHZWRWtISlNob045LzRQRG9RVHJsZmwxYkhmOXhXRXVRdnZhK0ppV3dWTHlmYUgKT0dseWtWQlVmdGlhenEyMStFNDA5SnZyN0JWSU9CR0tQWVpJMEJPRG53SURBUUFCb0FBd0RRWUpLb1pJaHZjTgpBUUVMQlFBRGdnRUJBR01oNjhSZ29XT0t3NGpuM2pFTXhtSUdwa3ZodkpPVWJudTkxcHhEVnJiTVBmTUpwdkVCCmFKbVVoMzdGaVJFaVRYUVdpMjdWdG8yRU9VOXJ1UzRSMXFTT1o4ZHVBY05VSTNYVU9tWkRXdHA1NlpiQi94RW4KS3lMYzlza2x2TE9wUDNhNWtEZlJNZUI3SFc1eDUza1krMUIvOHUzbEUrOWVvVmJJdW9PYVpyMmtPbnRUMWs4TApwakgwSDRtRkZZYTBhaFg0eE5ndU4yZENMR0hrd1ZQQ1J4eDdURmo1bFZ3RTg1VmpHTXJEUDlrYkltTkRYeE4xCjNSTDArM1I3WFZNeVFQb1N2eVl5bHR5emN4ZnF0Mm5saU9Xci91YjRoL2JGV09zUG93cTlNQXVFV1kzK1Iva0sKZ0ZGT0trTUI1aHVXbEh1aEJTL2d3YUJCNUh5dEo1WTE5YnM9Ci0tLS0tRU5EIENFUlRJRklDQVRFIFJFUVVFU1QtLS0tLQo=

controlplane ~ ➜  cat > akshay.yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: akshay
spec:
  request: <bas64 인코딩된 csr 붙여넣기>
  signerName: kubernetes.io/kube-apiserver-client
  expirationSeconds: 86400  # one day
  usages:
  - client auth
  
  controlplane ~ ➜  kubectl create -f akshay.yaml 
certificatesigningrequest.certificates.k8s.io/akshay created

controlplane ~ ➜  kubectl get csr
NAME        AGE   SIGNERNAME                                    REQUESTOR                  REQUESTEDDURATION   CONDITION
akshay      19s   kubernetes.io/kube-apiserver-client           kubernetes-admin           <none>              Pending
csr-4tkvt   12m   kubernetes.io/kube-apiserver-client-kubelet   system:node:controlplane   <none>              Approved,Issued
  • CSR Approve
controlplane ~ ➜  kubectl certificate approve akshay
certificatesigningrequest.certificates.k8s.io/akshay approved

controlplane ~ ➜  kubectl get csr
NAME        AGE   SIGNERNAME                                    REQUESTOR                  REQUESTEDDURATION   CONDITION
akshay      20m   kubernetes.io/kube-apiserver-client           kubernetes-admin           <none>              Approved,Issued
csr-4tkvt   33m   kubernetes.io/kube-apiserver-client-kubelet   system:node:controlplane   <none>              Approved,Issued
  • CSR로부터 Ceritificate 조회하기
controlplane ~ ➜  kubectl get csr agent-smith -o yaml
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  creationTimestamp: "2025-01-13T07:53:48Z"
  name: agent-smith
  resourceVersion: "3101"
  uid: 5df8a2bc-57ee-490b-9ec1-cf8cc59ec11f
spec:
  groups:
  - system:masters
  - system:authenticated
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1dEQ0NBVUFDQVFBd0V6RVJNQThHQTFVRUF3d0libVYzTFhWelpYSXdnZ0VpTUEwR0NTcUdTSWIzRFFFQgpBUVVBQTRJQkR3QXdnZ0VLQW9JQkFRRE8wV0pXK0RYc0FKU0lyanBObzV2UklCcGxuemcrNnhjOStVVndrS2kwCkxmQzI3dCsxZUVuT041TXVxOTlOZXZtTUVPbnJEVU8vdGh5VnFQMncyWE5JRFJYall5RjQwRmJtRCs1eld5Q0sKeTNCaWhoQjkzTUo3T3FsM1VUdlo4VEVMcXlhRGtuUmwvanYvU3hnWGtvazBBQlVUcFdNeDRCcFNpS2IwVSt0RQpJRjVueEF0dE1Wa0RQUTdOYmVaUkc0M2IrUVdsVkdSL3o2RFdPZkpuYmZlek90YUF5ZEdMVFpGQy93VHB6NTJrCkVjQ1hBd3FDaGpCTGt6MkJIUFI0Sjg5RDZYYjhrMzlwdTZqcHluZ1Y2dVAwdEliT3pwcU52MFkwcWRFWnB3bXcKajJxRUwraFpFV2trRno4MGxOTnR5VDVMeE1xRU5EQ25JZ3dDNEdaaVJHYnJBZ01CQUFHZ0FEQU5CZ2txaGtpRwo5dzBCQVFzRkFBT0NBUUVBUzlpUzZDMXV4VHVmNUJCWVNVN1FGUUhVemFsTnhBZFlzYU9SUlFOd0had0hxR2k0CmhPSzRhMnp5TnlpNDRPT2lqeWFENnRVVzhEU3hrcjhCTEs4S2czc3JSRXRKcWw1ckxaeTlMUlZyc0pnaEQ0Z1kKUDlOTCthRFJTeFJPVlNxQmFCMm5XZVlwTTVjSjVURjUzbGVzTlNOTUxRMisrUk1uakRRSjdqdVBFaWM4L2RoawpXcjJFVU02VWF3enlrcmRISW13VHYybWxNWTBSK0ROdFYxWWllKzBIOS9ZRWx0K0ZTR2poNUw1WVV2STFEcWl5CjRsM0UveTNxTDcxV2ZBY3VIM09zVnBVVW5RSVNNZFFzMHFXQ3NiRTU2Q0M1RGhQR1pJcFVibktVcEF3a2ErOEUKdndRMDdqRytocGtueG11RkFlWHhnVXdvZEFMYUo3anUvVERJY3c9PQotLS0tLUVORCBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0K
  signerName: kubernetes.io/kube-apiserver-client
  usages:
  - digital signature
  - key encipherment
  - server auth
  username: agent-x
status: {}
  • CSR 거절하기
controlplane ~ ➜  kubectl certificate deny agent-smith
certificatesigningrequest.certificates.k8s.io/agent-smith denied
controlplane ~ ➜  kubectl get csr
NAME          AGE     SIGNERNAME                                    REQUESTOR                  REQUESTEDDURATION   CONDITION
agent-smith   3m43s   kubernetes.io/kube-apiserver-client           agent-x                    <none>              Denied
# CSR 삭제
controlplane ~ ➜  kubectl delete csr agent-smith
certificatesigningrequest.certificates.k8s.io "agent-smith" deleted

 

[ 실습 ]

Create a new user called john. Grant him access to the cluster. John should have permission to create, list, get, update and delete pods in the development namespace . The private key exists in the location: /root/CKA/john.key and csr at /root/CKA/john.csr.
  • CSR
# private key와 csr이 이미 제공이 되어 있음
controlplane ~/CKA ➜  ls
john.csr  john.key  use-pv.yaml

# base64 인코딩
controlplane ~/CKA ➜  cat john.csr | base64 | tr -d "\n"
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZEQ0NBVHdDQVFBd0R6RU5NQXNHQTFVRUF3d0VhbTlvYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRApnZ0VQQURDQ0FRb0NnZ0VCQU1sdjBFRkpURjlwWk4ySDVMWS9obXhYV0dKemgrZ1hKV2xBTW5ZZUJvNmlBUFJLCjVWaTJLQ1ViellDSnBucWJ2enB2MmNQSmNlZDkzSkRTWlVlaVZDRldPRjVCNjExd21kUG1qbUcwRzlPLzNYN2oKVU5URkppREJwenVWbzIrV2lVRnNrR3ZVdFdHc3pXZGlNemhmYkpMR2pZUWdxTXVjSGZvajhJNkpSWmVyUjFOQwpWRnpBeUpVMW9PeWgwM1UzUm1IRGk2SU9kRVVsR3laMG1pdVU4V0JTNjIyNW8xRWU5M3hrTmNnRHFDUmE1RGxTCllMc3JlVmZqWjFrcjJ6UDN2dXc5SDd2ZGUwR2RTcE52MEZCQ0VSUEx5bDM0RGpwWUZVSEtUUFFYY3BYUmFlbUsKUUVPa3I0R2VPZVlLaExnaXFXVFlQSDZlWFhzU1BQTkZtRkhtbFZjQ0F3RUFBYUFBTUEwR0NTcUdTSWIzRFFFQgpDd1VBQTRJQkFRRERPd3pOZXByUEx2RGdxVlVVVmpxRFZ0N0JNUlpxWFJ4MTFLTFYvc1h0L0hYd25aMXVmNjF5CmNnRm5Vc0JhM2Q2UjE1K0ViNnJDQTA0NTVLZERjYzhLWmMzM3p2Sjd2QThOK0NhSEpIRUN4ckh3cHA1SzNBbEcKek05RVJ3bEE2eEVNQThFcjFTK2sydU9FOWo2UkhFVkthU0hSU0xiY2NOL1plQnRIeU5zbDE0V3Z5Vm54QnptQgpTWmg0RUJucDNJQmF3T3FVM1pGbW1vcVo5Mkh3bUZ0SlR5UkxNYnpRK2k5ajdTSVZUOERHZnAwMHg5K2NkUWo0CndFMmFwYWs1OUVrVXRTLzVqaHgzSE1CUzlQRUpPdlUrc0I2YTA3YnE2bllJZm1ORXFUZ0ZYUitWSzdvRkhtRGMKazE3U3A4YjU5TVJCZHEzL1dRSW4rYno3RWFXVHYxTFgKLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==

# 기반으로 csr.yaml 생성
controlplane ~/CKA ➜  cat csr.yaml 
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: john-developer
spec:
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1ZEQ0NBVHdDQVFBd0R6RU5NQXNHQTFVRUF3d0VhbTlvYmpDQ0FTSXdEUVlKS29aSWh2Y05BUUVCQlFBRApnZ0VQQURDQ0FRb0NnZ0VCQU1sdjBFRkpURjlwWk4ySDVMWS9obXhYV0dKemgrZ1hKV2xBTW5ZZUJvNmlBUFJLCjVWaTJLQ1ViellDSnBucWJ2enB2MmNQSmNlZDkzSkRTWlVlaVZDRldPRjVCNjExd21kUG1qbUcwRzlPLzNYN2oKVU5URkppREJwenVWbzIrV2lVRnNrR3ZVdFdHc3pXZGlNemhmYkpMR2pZUWdxTXVjSGZvajhJNkpSWmVyUjFOQwpWRnpBeUpVMW9PeWgwM1UzUm1IRGk2SU9kRVVsR3laMG1pdVU4V0JTNjIyNW8xRWU5M3hrTmNnRHFDUmE1RGxTCllMc3JlVmZqWjFrcjJ6UDN2dXc5SDd2ZGUwR2RTcE52MEZCQ0VSUEx5bDM0RGpwWUZVSEtUUFFYY3BYUmFlbUsKUUVPa3I0R2VPZVlLaExnaXFXVFlQSDZlWFhzU1BQTkZtRkhtbFZjQ0F3RUFBYUFBTUEwR0NTcUdTSWIzRFFFQgpDd1VBQTRJQkFRRERPd3pOZXByUEx2RGdxVlVVVmpxRFZ0N0JNUlpxWFJ4MTFLTFYvc1h0L0hYd25aMXVmNjF5CmNnRm5Vc0JhM2Q2UjE1K0ViNnJDQTA0NTVLZERjYzhLWmMzM3p2Sjd2QThOK0NhSEpIRUN4ckh3cHA1SzNBbEcKek05RVJ3bEE2eEVNQThFcjFTK2sydU9FOWo2UkhFVkthU0hSU0xiY2NOL1plQnRIeU5zbDE0V3Z5Vm54QnptQgpTWmg0RUJucDNJQmF3T3FVM1pGbW1vcVo5Mkh3bUZ0SlR5UkxNYnpRK2k5ajdTSVZUOERHZnAwMHg5K2NkUWo0CndFMmFwYWs1OUVrVXRTLzVqaHgzSE1CUzlQRUpPdlUrc0I2YTA3YnE2bllJZm1ORXFUZ0ZYUitWSzdvRkhtRGMKazE3U3A4YjU5TVJCZHEzL1dRSW4rYno3RWFXVHYxTFgKLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==
  signerName: kubernetes.io/kube-apiserver-client
  usages:
  - client auth
  
controlplane ~/CKA ➜  kubectl create -f csr.yaml 
certificatesigningrequest.certificates.k8s.io/john-developer created

controlplane ~/CKA ➜  kubectl get csr
NAME             AGE   SIGNERNAME                                    REQUESTOR                 REQUESTEDDURATION   CONDITION
csr-lm9gp        21m   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:mod04i   <none>              Approved,Issued
john-developer   4s    kubernetes.io/kube-apiserver-client           kubernetes-admin          <none>              Pending
# Pending 상태임
controlplane ~/CKA ➜  kubectl certificate approve john-developer
certificatesigningrequest.certificates.k8s.io/john-developer approved
# Approve 
controlplane ~/CKA ➜  kubectl get csr
NAME             AGE   SIGNERNAME                                    REQUESTOR                 REQUESTEDDURATION   CONDITION
csr-lm9gp        21m   kubernetes.io/kube-apiserver-client-kubelet   system:bootstrap:mod04i   <none>              Approved,Issued
john-developer   33s   kubernetes.io/kube-apiserver-client           kubernetes-admin          <none>              Approved,Issued
  • Role 
controlplane ~/CKA ➜  kubectl create role developer  --verb=create,get,list,update,delete --resource=pods -n development
role.rbac.authorization.k8s.io/developer created

controlplane ~/CKA ➜  kubectl describe role -n development 
Name:         developer
Labels:       <none>
Annotations:  <none>
PolicyRule:
  Resources  Non-Resource URLs  Resource Names  Verbs
  ---------  -----------------  --------------  -----
  pods       []                 []              [create get list update delete]

# 권한 확인
controlplane ~/CKA ➜  kubectl auth can-i get pods --namespace development --as john
no

controlplane ~/CKA ✖ kubectl auth can-i create pods --namespace development --as 
john
no
# 아직 모든 권한이 주어지지 않았다.
# -> Rolebinding 생성 필요

controlplane ~/CKA ➜  kubectl create rolebinding john-developer  --role=developer  --user=john -n development
rolebinding.rbac.authorization.k8s.io/john-developer created

controlplane ~/CKA ➜  kubectl get rolebinding -n development
NAME             ROLE             AGE
john-developer   Role/developer   21s

controlplane ~/CKA ➜  kubectl describe rolebinding -n development 
Name:         john-developer
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  Role
  Name:  developer
Subjects:
  Kind  Name  Namespace
  ----  ----  ---------
  User  john
  
# 이제 정상 작동
controlplane ~/CKA ➜  kubectl auth can-i create pods --namespace development --as john
yes

 

[ 실습 ] 

CSR(Certificate Signing Request)를 통해 app-manager 인증서를 발급받은 user app-manager 에게 cluster내 모든 namespace의 deployment, pod, service 리소스를 create, list, get, update, delete 할 수 있는권한을 할당하시오.

참고: https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#normal-user

  • user name : app-manager
  • certificate name: app-manager
  • clusterRole name : app-access
  • clusterRoleBinding name: app-access-binding

1. 인증서 key 만들기

# 인증서 키 만들기
controlplane $ openssl genrsa -out app-manager.key 2048
Generating RSA private key, 2048 bit long modulus (2 primes)
............+++++
.......................................................................................................................................................+++++
e is 65537 (0x010001)
# CSR 만들기 (인증서를 요청해주는 파일)
controlplane $ openssl req -new -key app-manager.key -out app-manager.csr -subj "/CN=app-manager"

 

2. CSR 생성 요청하기

controlplane $ cat app-manager.yaml 
apiVersion: certificates.k8s.io/v1
kind: CertificateSigningRequest
metadata:
  name: app-manager
spec:
  request: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURSBSRVFVRVNULS0tLS0KTUlJQ1d6Q0NBVU1DQVFBd0ZqRVVNQklHQTFVRUF3d0xZWEJ3TFcxaGJtRm5aWEl3Z2dFaU1BMEdDU3FHU0liMwpEUUVCQVFVQUE0SUJEd0F3Z2dFS0FvSUJBUURWR2s0SVZYOHBZdkFzSGVzOEV6K1Zpbzg2WXdCTmxxNU9wS3ZZCkd5MUIzNG9MSGU3MWxPN2xFa0ExbTFHMnBtS1E2bW9IQVFuaGxCQlRVTDNRWkZ2YzVIWjZ1SmY4bjA1L2F2UFQKamlZSkY0Qk5LdGdySzdseGhuUjlhRk1Rdy9SS2pYTnMzUGVYOUxxZm8vbTVySHhjN1V4UHQyWk9GQldkdUhQRwpLMTFDWFRjV3NXbFVST3Y1elpmZDFpRE5qUkN5N2ZMZzhSTFRXTEdUZGpwV2dxeGdCc0d0VEd2Tmlib083QUI1CnMxL0Z3emZma0c5Y2szZmdPNXU3a3lnV1p2aTEvL1lVWndRVHN1bGdnK3NrS09USXl0WTcxTzF1bUgzSzhQSWUKMUowODlDTUVLM3pQUFNvZzROWFBJdlBnbmRtb1BNdzlmUlhuN2ZIeFRtSnlVd3JYQWdNQkFBR2dBREFOQmdrcQpoa2lHOXcwQkFRc0ZBQU9DQVFFQWIxVG9YT3ZJRHRIaldkQ1l4bEIxVUhWV2xoSXgyd2dRY3JGQml0QWRWeTF2Cmp3ejAzdFVyMlRBRlBVd3Q0QkxWQWkrNmsrV3NZdFFhTTUzdXBVYWhLNk5WMkxJcitPakpibFdpaHdHNmtwSU8KbmRkMEdWY3BZWHNFZm1BZCtaWFBnVjA5UGt5R3BzT2dtU2pqOXBJYkt3a0l6OWVQeG0rSWs0TUZKTCsrY05VNQpLYWZLTjRoNzFSMGZtWXlSV2x4dUZKaHgrWHh2WG4xVzdhc0lNcVdRNm93SmhMd0RBdGRBdElYYUwrVmJFZFFaCjNlTEtubzZlUTNTVFRkcWtueHhjNVYwb0ZkY2tLbXBQZ21lbHJZL2hjZjQ4ZEphY2xEaGh1K3haaFZqaVZWaCsKcDdGU24xY1VlNHJIaWdFc3FBZ0NmUXhTMHhvNTRvQmNBV08zVS9FWklRPT0KLS0tLS1FTkQgQ0VSVElGSUNBVEUgUkVRVUVTVC0tLS0tCg==
  signerName: kubernetes.io/kube-apiserver-client
  usages:
  - client auth
controlplane $ kubectl apply -f app-manager.yaml 
certificatesigningrequest.certificates.k8s.io/app-manager created

 

  • 승인 요청하기
controlplane $ kubectl certificate approve app-manager 
certificatesigningrequest.certificates.k8s.io/app-manager approved
controlplane $ kubectl get csr
NAME          AGE   SIGNERNAME                            REQUESTOR          REQUESTEDDURATION   CONDITION
app-manager   56s   kubernetes.io/kube-apiserver-client   kubernetes-admin   <none>              Approved,Issued

 

3. CSR로부터 발행된 certificate expose하

controlplane $ kubectl get csr app-manager -o jsonpath='{.status.certificate}'| base64 -d >
 app-manager.crt

 

4. Clusterrole, ClusterRoleBinding 만들기

controlplane $ kubectl create clusterrole app-access --verb=create,list,get,update,delete  --resource=deployment,pod,service
clusterrole.rbac.authorization.k8s.io/app-access created
controlplane $ kubectl get clusterrole app-access 
NAME         CREATED AT
app-access   2025-03-03T08:31:47Z

kubectl create clusterrolebinding app-access-binding --clusterrole=app-access --user=app-manager
clusterrolebinding.rbac.authorization.k8s.io/app-access-binding created
controlplane $ kubectl describe clusterrolebinding app-access-binding 
Name:         app-access-binding
Labels:       <none>
Annotations:  <none>
Role:
  Kind:  ClusterRole
  Name:  app-access
Subjects:
  Kind  Name         Namespace
  ----  ----         ---------
  User  app-manager

 

5. app-manager.crt 인증서를 사용하는 user app-manager 등록
→  https://kubernetes.io/docs/reference/access-authn-authz/certificate-signing-requests/#add-to-kubeconfig

반응형

'Container > Kubernetes' 카테고리의 다른 글

[K8S] api-resources  (0) 2025.01.23
[K8S] Authorization  (1) 2025.01.20
[K8S] TLS  (0) 2025.01.10
[K8S] Encrypting Secret Data at Rest  (0) 2025.01.08
[K8S] ConfigMap  (0) 2025.01.08