본문 바로가기

자격증/CKA

구성 요소 설계 및 생성

쿠버네티스에서는 오브젝트를 생성할때 Yaml 파일을 입력으로 사용한다. 이를 통해서  Pod, ReplicaSet, Deployment, Service 등의 리소스를 선언적으로 정의하고 배포할 수 있다.

 

공식 홈페이지
https://kubernetes.io/docs/concepts/

 

기본적인 YAML파일 구조

apiVersion: <API 버전>  # 해당 오브젝트의 API 버전 지정
kind: <리소스 종류>  # 생성할 쿠버네티스 오브젝트의 종류 (Pod, Service, Deployment 등)
metadata:  # 해당 오브젝트의 메타데이터 정보 (이름, 레이블 등)
  name: <오브젝트 이름>
  labels:  # key-value 형태의 레이블 지정 (선택 사항)
    app: my-app
    env: production
spec:  # 리소스의 상세 정의 (오브젝트별로 다름)
  <세부 정의>

 

 

apiVersion

해당 오브젝트가 어떤 API 버전을 사용할 것인지 지정한다. 오브젝트의 종류에 따라 적절한 버전을 선택해야 한다.

오브젝트 유형  API 버전 
Pod v1
Service v1
ReplicaSet apps/v1
Deployment apps/v1

 

metadata

오브젝트에 대한 정보를 포함하는 부분으로, 일반적으로 name labels가 포함된다.

name: 해당 오브젝트의 이름

labels: key-value 형식의 레이블을 설정 (선택 사항)

YAML에서는 들여쓰기를 사용하여 계층 구조를 표현하며, metadata 아래의 labels는 내부 dictionary(맵)이다.

 

Dictionary는 키(Key)와 값(Value) 쌍으로 데이터를 저장하는 자료구조 (json, yaml 등에서 사용) 
값에는 숫자, 문자열, 리스트 혹은 또 다른 딕셔너리등 다양한 타입이 올 수 있다. 

 

 

spec (리소스의 상세 정의)

각 오브젝트의 구체적인 사양(Specification)을 정의하는 부분으로, 내용은 오브젝트의 종류에 따라 달라진다.

 

📌 주의할 점:

spec 내에서 -를 사용하면 리스트(List)로 정의된다.

s가 붙은 것들은 대부분 리스트 형태로 사용된다.

(예: containers, ports 등)

 

 

pod를 생성하는 yaml 예제

apiVersion: v1
kind: Pod
metadata:
  name: my-pod
  labels:
    app: my-app
spec:
  containers:  # 리스트 형식 (여러 개의 컨테이너 가능)
    - name: my-container
      image: nginx:latest
      ports:
        - containerPort: 80

 

 

 

yaml 파일을 기반으로 오브젝트 생성 명령어

kubectl create -f <파일명>.yml

 

기존 오브젝트를 업데이트하거나 새롭게 적용할 경우

kubectl apply -f <파일명>.yml

 

 

오브젝트 조회 

kubectl get pods         # 현재 실행 중인 Pod 목록 조회
kubectl get pods -A      # cluster 에서 현재 실행 중인 Pod 목록 조회
kubectl get services     # 서비스 목록 조회
kubectl get deployments  # Deployment 목록 조회

# 상세조회를 원한다면 describe 명령어 사용 가능 
kubectl describe pod <Pod이름>

 

 

POD

링크

pod에서 주로 사용되는 명령어 정리 

 

# 현재 실행 중인 Pod 목록 조회
kubectl get pods     
kubectl get pods -o wide (자세하게 보고싶을떄 사용) 

# image로 파드 생성하기  (kubect run --help로 정보확인가능) 
kubectl run nginx --image=nginx
kubectl run nginx --image=nginx --dry-run=client -o yaml (이거는 명령어로 했을떄 yaml파일 형태 보여줌) 
kubectl run nginx --image=nginx --dry-run=client -o yaml > redis.yaml (이렇게하면 파일 생성가능) 

# pod 상세보기 
kubectl describe pod <pod이름>

# pod삭제 
kubectl delete pod <pod이름>

#yml로 pod 생성 
kubectl create -f redis.yaml

#yml로 pod 수정 (생성도 가능함) 
kubectl apply -f redis.yaml

 

 

ReplicaSet

링크

 

쿠버네티스에서 Replica(복제본)는 Pod의 고가용성을 보장하고, 장애 발생 시 자동 복구하거나 트래픽 증가에 대응하기 위해 사용된다. 이를 관리하는 대표적인 개념이 Replication Controller와 ReplicaSet이다.

(pod랑 연관 관계 없이 생각해도 괜찮다 , 기존 pod 를 관리하는 목적이 아님 그 자체로 파드를 생성하고 관리함) 

(hpa를 사용하면 hpa 셋팅 값으로 사용된다 )

 

쿠버네티스 컨트롤러

컨트롤러는 쿠버네티스의 두뇌 역할을 하며, 오브젝트(Pod, ReplicaSet, Deployment 등)를 모니터링하고 원하는 상태를 유지하도록 자동 조정하는 역할을 한다.

그리고 그러한 컨트롤러중 하나가 Replication controller이다. 

 

Replication Controller가 필요한 이유

 

 Pod의 장애 대응

단일 Pod만 실행하면 해당 Pod가 장애를 일으킬 경우 서비스 중단

Replication Controller는 설정된 개수의 Pod가 항상 유지되도록 보장

특정 Pod가 삭제되거나 장애가 발생하면 자동으로 새로운 Pod를 생성하여 복구

 

 Pod을 여러 노드에 분배

특정 노드에서 장애가 발생해도 다른 노드에서 Pod가 실행되도록 배포 가능

 

YAML 예시

Replication Controller는 YAML에서 v1 API 버전을 사용

apiVersion: v1
kind: ReplicationController
metadata:
  name: my-replication-controller
spec:
  replicas: 3  # 유지할 Pod 개수
  selector:
    app: my-app  # 관리할 Pod의 label 선택 (선택 사항)
  template:
    metadata:
      labels:
        app: my-app  # Pod의 label (이 selector와 일치해야 함)
    spec:
      containers:
        - name: my-container
          image: nginx:latest

 

 

명령어 

kubectl get replicationcontroller #조회
kubectl delete replicationcontroller my-replication-controller #삭제

# replicaset 기존에 있는거 변경 이렇게 처리 가능 (적용 자동으로 안되서 해당 pod 삭제하면 새로 적용됨)
kubectl edit replicaset new-replica-set

# replicas 이런식으로 sacle 명령어로 수정 가능 
kubectl scale rs new-replica-set --replicas=5  

# 이렇게도 사용 가능 
kubectl edit replicaset new-replica-set


# 참고 
replicaset -> rs 로 약자로 사용 가능

 

 

 

Replication Controller vs ReplicaSet

 

Replication Controller는 구형 기술이며, 현재는 ReplicaSet이 그 역할을 대체하고 있음.

ReplicaSet은 Replication Controller의 발전된 버전으로, 추가적으로 Selector 기능을 필수적으로 사용해야 한다.

 

 

ReplicaSet의 주요 특징

 

 기본적인 동작 방식은 Replication Controller와 동일

 selector가 필수로 추가됨

ReplicaSet은 단독으로 사용되기보다는 Deployment에서 내부적으로 활용됨

- Deployment를 만들면 내부적으로 ReplicaSet이 자동 생성되고, ReplicaSet이 Pod을 관리해주기 때문 

- ReplicaSet만 사용하면 Pod 개수는 유지할 수 있지만, 업데이트(버전 변경)나 롤백 기능이 없음

즉, 애플리케이션을 새로운 버전으로 배포하거나 문제가 생겼을 때 롤백하려면 수동으로 ReplicaSet을 관리해야 함

- Deployment는 Pod 업데이트(롤링 업데이트)와 롤백 기능을 지원함

 

ReplicaSet은 matchLabels + matchExpressions을 지원 (replicaController는 matchLabels만 가능)

selector:
  matchExpressions:
    - key: app
      operator: In
      values: ["my-app", "your-app"]  # 두 가지 label을 가진 Pod을 모두 관리
    - key: env
      operator: NotIn
      values: ["test"]  # 'test' 환경이 아닌 Pod만 포함

 

 

 

Yaml 예시 

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: my-replicaset
spec:
  replicas: 3  # 유지할 Pod 개수
  selector:  # 관리할 Pod을 선택하는 기준 (필수)
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app  # selector와 일치해야 함
    spec:
      containers:
        - name: my-container
          image: nginx:latest

 

 

 

Deployment 

링크

Deployment는 ReplicaSet을 관리하는 상위 개념으로 아래와 같은 주요 기능을 제공한다

  • Pod의 버전 업데이트(롤링 업데이트)
    • 새로운 버전을 배포할때 기존 pod를 한번에 종료하는게 아니라 하나씩 교체하면서 배포한다 
    • 사용자에게 영향 최소화 
  • 롤백(버전 복구)
    • kubectl rollout undo deployment my-deployment
      • 기존 replicaSet을 다시 활성화 한다 
  • 자동 스케일링  
  • 배포 전략 관리 

 

Deployment는 직접 Pod을 관리하지 않고, 내부적으로 ReplicaSet을 생성해서 관리하는 구조

즉 ReplicaSet이 Pod 개수를 유지하는 역할을 담당하고, Deployment가 이를 제어한다

위와 같은 방식으로 이해하면 된다. 

Deployment는 새로운 버전을 적용할떄 기존 Replicaset을 유지하면서 새로운 Replicaset을 생성하는 방식을 취한다. 

(새로운 Replicaset이 생성되고 기존 pod를 하나씩 교체하면서 배포가 된다) 

이런 방법을 통해서 수동으로 Replicaset을 만들 필요 없이 쉽게 애플리케이션 관리가능 

 

Pod 배포 전략 (Deployment 배치 방식)

 

1) 기본: RollingUpdate

 

✔ 기본적으로 새로운 Pod을 생성하면서 기존 Pod을 점진적으로 교체하는 방식

✔ 프로덕션 환경에서 서비스 중단 없이 업데이트 가능

✔ Deployment의 strategy 값이 기본적으로 RollingUpdate

spec:
  strategy:
    type: RollingUpdate

 

 Rolling Update의 동작 방식

새 ReplicaSet을 생성

새로운 Pod을 하나 띄운 후, 기존 Pod을 하나 제거

이 과정을 반복하며 전체 업데이트 완료

 

 

2) 강제 배포: Recreate

 

✔ 기존 Pod을 한꺼번에 삭제한 후, 새로운 Pod을 생성하는 방식

 한 번에 모든 Pod이 재시작되기 때문에 서비스 중단 발생 가능

✔ 빠르게 전체 업데이트가 필요할 때 사용 가능

 

spec:
  strategy:
    type: Recreate

 

 

 

Deployment의 YAML 구조

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 3  # 유지할 Pod 개수
  selector:
    matchLabels:
      app: my-app
  strategy:
    type: RollingUpdate  # 기본값 (점진적 배포)
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: nginx:1.19  # 최초 배포 버전

 

기본적인 구조는 ReplicaSet과 매우 유사하지만 Deployment에서만 사용할 수 있는 다양한 추가 설정들이 있다. 

 

 

필드 설명 기본값
strategy 배포 방식 지정 (RollingUpdate / Recreate) RollingUpdate
minReadySeconds 새 Pod이 준비 상태(Ready)로 간주되기까지 최소 대기 시간 설정 0
progressDeadlineSeconds 배포가 완료되지 않으면 롤백하는 시간 제한 설정 600 (10분)
revisionHistoryLimit 이전 ReplicaSet을 몇 개까지 보관할지 지정 (롤백 가능 개수) 10 
maxSurge 롤링 업데이트 시 한 번에 추가로 생성할 수 있는 최대 Pod 개수 25%  (참고로 이거 말고 값은 숫자로도 입력가능) 
maxUnavailable 롤링 업데이트 시 동시에 종료될 수 있는 최대 Pod 개수 25% (참고로 이거 말고 값은 숫자로도 입력가능) 

 

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-deployment
spec:
  replicas: 3
  minReadySeconds: 0  # 기본값 (즉시 Ready 상태로 인정)
  revisionHistoryLimit: 10  # 기본값 (이전 ReplicaSet 10개 보관)
  progressDeadlineSeconds: 600  # 기본값 (10분 내에 배포 완료되지 않으면 실패)
  paused: false  # 기본값 (배포 진행됨)
  strategy:
    type: RollingUpdate  # 기본값
    rollingUpdate:
      maxSurge: 25%  # 기본값 (기존 Pod 대비 25% 추가 생성 가능)
      maxUnavailable: 25%  # 기본값 (기존 Pod 대비 25%는 다운 가능)
  selector:
    matchLabels:
      app: my-app
  template:
    metadata:
      labels:
        app: my-app
    spec:
      containers:
        - name: my-container
          image: nginx:1.19

 

 

참고로 deployment를 생성하고 나면 replicaset로 같이 생성된걸 볼수가 있다, 그리고 pod까지 한번에 모두 생성이 된다. 

 

 

롤백 명령어

#배포 히스토리 조회 
kubectl rollout history deployment my-deployment

#특정 히스토리의 상세정보를 보고 싶을때 
kubectl rollout history deployment my-deployment --revision=3

#특정 배포 버전으로 롤백 
kubectl rollout undo deployment my-deployment --to-revision=3

 

참고로 롤백을 하면 특정 버전으로 돌아가는게 아니라 해당 버전의 설정을 복사해서 새로운 버전으로 다시 배포하는 방식이다.

 

 

 

Deployment, ReplicaSet, Pod를 한번에 확인하는 방법 

$ kubectl get all

 

 

Service

링크

Service 는 쿠버네티스 클러스터 내에서 애플리케이션의 구성 요소간, 또는 외부 시스템과의 안정적인 통신을 가능하게 하는 네트워크 추상화 객체다.

ex) 

- 사용자가 외부에서 서비스에 접근 할 수 있도록 하기 

- 내부 애플리케이션이 간 서로 원활하게 통신할 수 있게 하기

 

쿠버네티스는 pod가 동적으로 생성되고 변경 될 수 있기 때문에 pod의 ip를 참조하여 관리하는 방식이 어렵고, 이러한 문제를 service가 해결해준다. service는 고정된 네트워크 엔드포인트를 제공하고 내부적으로 라벨 셀렉터를 사용해 적절한 pod에 트래픽을 전달한다. 

Service는 etcd에 저장된다 따로 실행되는 프로세스라기 보다는 etcd에 저장된 네트워크 라우팅 정보다. 

 

 

 

이러한 service는 3가지 주요한 타입으로 정의된다. 

NodePort

 

NodePort 서비스는 쿠버네티스 클러스터 외부에서 특정 포트를 통해서 내부 Pod와 통신 할 수 있도록 하는 서비스 유형이다 

(node에 포트가 열려있고 외부에서 이 포트를 통해서 내부로 접근 할 수 있다고 보면된다) 

 

노드의 포트는 지정할 수 도 있고 지정 안하면 자동 할당 (30000~32767 범위) 

해당 포트로 요청이 들어오면 service가 요청을 받아서 내부 pod로 요청을 전달한다. 

참고로 Nodeport로 서비스를 만들때 clusterIP도 자동으로 생성된다 

클러스터 내부에서는 ClusterIP를 통해서 접근하기때문

 

 

포트가 여러개 있어서 좀 헷갈리지만 정리하자면 다음 3가지 port 가 있다 

 

1. node port (노드에서 외부로 개방하는 포트) 

- 외부 사용자는 노드 IP:nodeport형태로 접근 가능 

- 참고로 포트를 개방하는 것일 뿐이기 때문에 해당 노드가 퍼블릭 ip 를 가져야지 통신이된다 

 

2. port (service의 내부 포트 , clusterIp와 동일) 

- 클러스터 내부에서 service가 사용하는 포트 

- 클러스터 내부에서 (pod등) Service를 접근할때 사용하는 포트 

 

3. targetport (pod에서 실제 운영 중인 포트) 

- pod내부 컨테이너의 포트 (운영중인 서비스 접근을 위해 설정한 포트) 

- targetport를 지정하지 않으면 port값과 동일하게 자동 설정된다. 

 

apiVersion: v1
kind: Service
metadata:
  name: my-nodeport-service
spec:
  type: NodePort
  selector:
    app: myapp
    type: front-end
  ports:
    - targetPort: 80   # Pod에서 실제 실행 중인 웹 서버 포트
      port: 80         # 클러스터 내부 Service 포트
      nodePort: 30008  # 노드에서 외부로 개방하는 포트 (지정하지 않으면 자동 할당)

 

어떤 pod와 연결할지는 selector를 통해서 지정한다 pod의 label에 정의된 값을 입력해주면 된다  

(label에 지정하는 key/value는 사용자가 자유롭게 쓸수 있다 , 보편적으로는 app 많이씀) 

 

참고로 노드가 여러개 있고 그 각 노드에 pod가 흩어진 경우 (노드포트가 여러개) 에도 각 포트로 들어가면 service를 통해서 pod를 잘 찾아갈 수 있다 (service는 노드에 종속되는게 아님) 

 

ClusterIp

 

ClusterIP는 쿠버네티스 클러스터 내부에서만 접근 가능한 가상 IP를 제공하는 서비스 타입 

Service는 pod를 그룹핑하고, 고정된 ClusterIP를 부여해서 안정적인 통신이 가능한것 

Service의 가장 기본 타입이 ClusterIP 타입이다. 

외부 접근 없이 클러스터 내부에서 안전하게 통신이 가능하다. 외부 트래픽이 필요하지 않는 백엔드 서비스나 DB에 적합 하다. 

 

apiVersion: v1
kind: Service
metadata:
  name: backend-service
spec:
  type: ClusterIP   # 타입 생략 가능(기본값이라서)
  selector:
    app: backend
  ports:
    - port: 80
      targetPort: 8080

 

 

 

LoadBalance

LoadBalancer는 외부 사용자가 단일 URL로 접근 할 수 있도록 요청을 여러 노드로 분산시키는 서비스 타입 

NodePort를 여러개 사용한다고 보면 각 노드마다 url이 다르게 생겨서 관리가 어렵다. (포트는 같아도 node주소가다름)

이런 불편함을 하나의 고정된 URL(도메인/ip)을 제공하면서 해결해준다. 

참고로 클라우드 제공업체에서 제공하는 로드밸런서 통합해서 사용(클라우드 환경에서만 지원된다)

 

요약하자면 해당 타입을 사용하면 외부에서 하나의 단일 url로 호출하면 알아서 해당하는 nodeport들로 나눠서 요청을 보내준다

(외부에서 단일 URL, 내부적 NodePort) 

 

 

호출 흐름 
외부 요청 -> LoadBalancer → NodePort (노드의 개방된 포트) → ClusterIP → Pod
(클라우드 제공 업체는 쿠버네티스 내부 네트워크 구조 모르기 때문에 nodeport거쳐서 들어옴, clusterIP 는 클러스터 내부에서만 접근가능) 

 

AWS에서 사용한다고 하면 ALB 같은 리소스가 생성된다고 생각하면 된다. 

호출되는 단인 url도 해당 alb의 external url 이 기본으로 사용된다 

 

apiVersion: v1
kind: Service
metadata:
  name: my-loadbalancer
spec:
  type: LoadBalancer  # 서비스 타입을 LoadBalancer로 설정
  selector:
    app: myapp
  ports:
    - port: 80         # Service가 노출하는 포트
      targetPort: 8080 # Pod 내부 컨테이너 포트

 

 

 

loadbalancer랑 ingress는 비슷한데 다름 
기본적으로 클라우드환경에서 loadbalancer를 쓰고 ingress는 ingress controller를 사용해서 동작한다 
근데 ingress는 url 패턴 기반으로 라우팅을 설정할 수 있어서 loadbalancer를 여러개 생성하는 대신 ingress 하나로 여러서비스를 관리하기도 한다 

 

 

 

정리

Service는 하나의 노드가 아니라 클러스터 전체에서 유지가 된다 (여러 노드에 pod가 분산되어져 있어도 상관없다) 

라벨을 기반으로 pod들을 그룹핑하여서 특정 서비스를 유지하고 pod 가 여러개 있어서 서비스가 자동으로 부하를 분산해준다 

(서비스 자체가 로드밸랜싱 기능을 내장 하고 있다) 

 

kubectl get services // 현재 생성된 모든 Service 정보를 확인 가능

 

kubectl descirbe로 service를 보면 endpoints라는 정보가 있는데 이는 service에 label로 연결된 파드들의 IP1:port 주소 이다

 

 

Namespace

링크

네임스페이스는 쿠버네티스의 리소스를 논리적으로 구분하는 단위로 리소스의 격리를 위해서 사용된다. 

같은 클러스터 안에서 여러 팀, 서비스, 환경 등을 구분해서 운영할 수 있도록 도와준다. 

 

기본적으로 클러스터를 생성했을때 default라는 네임스페이스가 생성되고 별도의 설정을 안한다면 이쪽에 리소스 들이 생성된다 

클러스터의 주요 관리 환경들은 kube-system, kube-public등의 네임스페이스로 별도로 만들어져 있다. 

 

추라고 이렇게 네임스페이스를 여러개로 분리하면 각 네임스페이스에 대해서 네트워크 정책, RBAC, 리소스 제한 등의 설정을 각각 해줄 수 있다. 

 

정책 설정 방법

리소스 제한 

링크

리소스 제한은 ResourceQuota 리소스를 통해서 설정할 수 있으며 

해당 네임스페이스의 pod 수, cpu 양, memory양 등을 제한 할 수 있다 

apiVersion: v1
kind: ResourceQuota
metadata:
  name: dev-quota
  namespace: dev
spec:
  hard:
    pods: "10"
    requests.cpu: "4"
    requests.memory: 4Gi
    limits.cpu: "10"
    limits.memory: 10Gi

 

 

네트워크 정책 (시험 중요)

링크

기본적으로 설정이 없다면 쿠버네티스는 모든 pod간의 통신을 허용한다 

NetworkPolicy 리소스를 통해서 pod간 네트워크 통신을 제어하는 정책을 생성할 수 있다. 

네임스페이스 안에서 누가 누구에게 통신할 수 있는지를 제어할 수 있는것으로 

ex) backend 라는 라벨에는 frontend 라벨을 가진 pod만 접근 할수 있다 

apiVersion: networking.k8s.io/v1
kind: NetworkPolicy
metadata:
  name: allow-only-frontend
  namespace: my-namespace
spec:
  podSelector:
    matchLabels:
      role: backend   # 이 정책은 backend 라벨을 가진 Pod에 적용
  policyTypes:
  - Ingress
  ingress:
    - from:
        - podSelector:
            matchLabels:
              role: frontend  # frontend 라벨을 가진 Pod만 이 backend로 접근 가능

 

추가로 위에 policyType을 지정했는데 아래쪽에 관련해서 규칙을 지정안하면 

해당 트래픽 전부 차잔으로 해석한다 (egress로 하고 아래 규칙없으면 외부로 아에 못나가도록되는것) 

 

 

클러스터가 CNI 플러그인을 지원해야지만 NetworkPolicy가 실제로 적용된다 

EKS 같은 환경은 AWS VPC CNI가 기본 설정 옛날에는 pod간 통신만 지원하고 networkpolicy 지원 안해줬는데 현재는 지원  (링크)

 

CNI : pod간 네트워크를 어떻게 연결하고 라우팅하고 정책을 적용할지 정의하는 표준 인터페이스
cni는 pod에 ip주소할당, pod간 트래픽 라우팅, networkpolicy적용 등의 역할을 한다

 

# 모든 네임스페이스에서 적용된 네트워크 정책 확인 
kubectl get networkpolicy --all-namespaces

# 특정 네임스페이스에서 적용된 네트워크 정책 확인 
kubectl get networkpolicy -n <namespace>

# 상세 보기 
kubectl describe networkpolicy <정책이름> -n <namespace>

# yml형태로 상세 보기
kubectl get networkpolicy <정책이름> -n <namespace> -o yaml

 

 

RBAC  (시험 중요)

링크

사용자/ 서비스 계쩡의 리소스에 접근 권한을 제어하는 정책으로 

특정 사용자가 해당 네임스페이스 안에서 어떤 리소스에 접근 할 수 있는지를 제어할 수 있다

 

Role (권한 정의) +  RoleBinding(누구에게 권한을 줄지) 

두개의 리소스를 정의해서 사용한다 

 

apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  namespace: dev
  name: pod-reader
rules:
  - apiGroups: [""]
    resources: ["pods"]
    verbs: ["get", "list", "watch"]
 ---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: read-pods-in-dev
  namespace: dev
subjects:
  - kind: User
    name: alice
    apiGroup: rbac.authorization.k8s.io
roleRef:
  kind: Role
  name: pod-reader
  apiGroup: rbac.authorization.k8s.io

 

 

 

RBAC는 네임스페이스 안의 범위에 대한 제한(Role) 뿐만 아니라 

클러스터 전체 범위의 권한(ClusterRole) 에 대해서도 설정이 가능하다 (이때는 ClutserRoleBinding) 

 

 

RBAC기능은 활성화했다가 비활성화 했다가 할 수 있다 

비활성화의 경우는 모든 사용자가 모든 리소스에 접근 가능하고 활성화 되어있다면 권한이 있는 사용자만 리소스에 접근 가능하다 

#내 클러스터가 RBAC 활성화되어 있는지 확인 
kubectl api-versions | grep rbac

#아래와 같이 응답이 오면 기능이 켜져 있다 
rbac.authorization.k8s.io/v1

 

 

Service account에 권한을 주는것도 RBAC의 일부다 

(특정 pod가 api를 통해 다른 리소스를 읽도록 허용하고 싶을때 serviceaccout에 권한부여) 

 

kubectl get clusterrole
kubectl get role -n <namespace>
kubectl get clusterrolebinding
kubectl get rolebinding -n <namespace>
kubectl describe role <role-name> -n <namespace>
kubectl describe rolebinding <binding-name> -n <namespace>

 

 

DNS 구성과 접근 방식 

같은 네임스페이스 안에서는 리소스를 이름만으로도 호출 할 수 있다 

예를 들어서 db서버의 이름이 db-service라면 

해당 이름만으로도 호출이 가능하다 

 

다만 다른 네임스페이스에 접근할떄는 전체 도메니으로 호출해야한다 

<service-name>.<namespace>.svc.cluster.local

ex) db-service.dev.svc.cluster.local 

dev 네임스페이스의 db-service 에 대한 호출 

 

이러한 구조는 서비스가 생성되면 자동으로 DNS에 등록되기 때문에 사용이 가능한것이다. 

 

 

명령어

kubectl get pods                # 현재 context의 namespace에서만 조회
kubectl get pods --namespace=kube-system  # 특정 namespace 지정
kubectl get pods --all-namespaces         # 모든 namespace의 리소스 조회

 

 

apiVersion: v1
kind: Namespace
metadata:
  name: dev

위의 yml  형식말고도 

kubectl create namespace {이름} 과같이 명령어로 간단하게 생성 할 수도 있따. 

 

 

# 기본 네임스페이스 변경 명령어
kubectl config set-context $(kubectl config current-context) --namespace=dev

 

 

 

 

 

Imperative(명령형) VS Declarative(선언형)

쿠버네티스에서 인프라를 관리하는 대표적인 방법은 명령형과 선언형이 있다. 

선언형 명령형
kubectl apply -f nginx.yaml kubectl run --image=nginx nginx (pod 생성하는거 이미지 nginx 고 이름 nginx)
  kubectl create deployment --image=nginx nginx (deployment생성 위랑 동일) 
  kubectl expose deployment nginx --port 80 (deploymeny외부접근 가능하게 service생성 type 필요하면 --type=NodePort)

 

선언형 명령형
kubectl apply -f nginx.yaml kubectl edit deployment nginx (직접 편짐할때 사용한다, 빠르게 설정 바꿀때)
  kubectl scale deployment nginx --replicas=5 (replica수를 조정하는 명령어) 
  kubectl set image deployment nginx nginx=nginx:1.18 (nginx의 컨테이너 이미지 변경하는거)

 

명령형

명령형은 무엇을 어떻게 할지 단계별로 직접 지시하는 방법이다. 

사용자가 시스템에게 이렇게 하라고 명령을 내리는 것으로 과정 중심적이다. 

 

장점으로는 명령어만 호출하면 해당 리소스에 대한 수정 생성들이 처리 되기 때문에 

시험을 치는 상황에서는 해당 명령어를 통해서 빠르게 처리를 할 수 있다. 

(파일 없이 간편하게 적용할 수 있다) 

 

다만 명령 실행 시점 이후에는 기록이 남지 않기 때문에 어떻게 구성이 되었는지 추적하기가 어렵고, 협업/유지 보수에서 불편한 점이 있다. 

 

시험을 칠때는 명령형을 통해서 최대한 시간을 절약할 수 있다 (공식 문서 확인 해볼것) 
https://kubernetes.io/docs/tasks/manage-kubernetes-objects/

 

 

선언형

최종 상태만 정의하면 시스템이 알아서 해당 상태에 도달할 수 있또록 처리하는 방식이다. 

이렇게 되어있어야한다는 결과 중심의 선언을 하면 시스템이 알아서 상태에 맞춘다 

 

kubectl apply -f nginx-deployment.yaml

 

yaml파일에서 원하는 리소스의 상태를 정의하고 kubectl apply 명령어로 적용한다 

기존 상태와 비교해서 필요한 부분만 자동으로 업데이트 한다. 

 

구성 상태를 코드로 관리할 수 있어서 git과 같은 형상관리 도구와 연동이 가능(협업에 유리, 추척/롤백에 유리) 

 

 

 

시험 명령형 팁

명령어 알고 싶은거 있으면 
kubectl {명령어} --help 
ex)
kubectl run --help
kubectl create service --help
kubectl create service clusterip --help


명령어는 --images 이렇게 있으면 = 로 붙여서 쓸수도 있고 그냥 공백 띄어서 쓸 수 도 있다 


# 기본옵션
--dry-run=client: 리소스를 실제로 생성하지 않고 명령어의 유효성만 확인함.
-o yaml: 명령 결과를 YAML 형식으로 출력함. 보통 --dry-run과 함께 사용하여 템플릿 생성에 활용.

# 사용 예시
kubectl run nginx --image=nginx --dry-run=client -o yaml > pod.yaml

# 실제 파드 생성 
kubectl run nginx --image=nginx

kubectl run redis -l tier=db --image=redis:alpine (라벨을 설정할 수 있음) 

# yaml만 생성함 실제 리소스 생성안함
kubectl run nginx --image=nginx --dry-run=client -o yaml


#Deployment 생성 
kubectl create deployment nginx --image=nginx

#replicas 4개 생성
kubectl create deployment nginx --image=nginx --replicas=4

# dev-ns라는 namespac에 생성 
kubectl create deployment redis-deploy --image=redis --replicas=2 -n dev-ns

#기존 deployment의 sacle조정
kubectl scale deployment nginx --replicas=4

#마찬가지 실제 생성없이 yaml로 저장 
kubectl create deployment nginx --image=nginx --dry-run=client -o yaml > nginx-deployment.yaml


#서비스 포트 6379를 노출하는 서비스 yaml생성 (실제 수행 x) 
kubectl expose pod redis --port=6379 --name=redis-service --dry-run=client -o yaml
kubectl create service clusterip redis --tcp=6379:6379 --dry-run=client -o yaml
(selector를 명시할수는 없고 기본적으로 app=redis로 저장이 된다) 

# type 주고 싶은 경우
kubectl expose pod nginx --type=NodePort --port=80 --name=nginx-service --dry-run=client -o yaml
kubectl create service nodeport nginx --tcp=80:80 --node-port=30080 --dry-run=client -o yaml

# 한번에 pod만들고 서비스도 만드는 케이스 
kubectl run httpd --image=httpd:alpine --port=80 --expose

아래 두게가 위에로 하나로 합쳐진거 (expose옵션이 pod를 상생하면서 동시에 service도 자동으로 생성해주는거) 
kubectl run httpd --image=httpd:alpine --port=80           # Pod 생성
kubectl expose pod httpd --port=80                         # Service 생성


#namespace 생성
kubectl create namespace {name}

 

Kebectl Apply 

kubectl apply는 선언형 방식으로 Kubernetes 리소스를 생성하고 관리하는 명령어입니다.

해당 명령으는 리소스가 없으면 생성하고, 있으면 업데이트한다.

 

kubectl apply -f sample.yaml

 

1. YAML → JSON 변환 및 저장

  • 사용자가 작성한 YAML 파일은 내부적으로 JSON 형식으로 변환
  • JSON은 해당 리소스의 “last-applied-configuration” 애노테이션으로 Kubernetes 객체에 함께 저장됩니다
  • 저장은 kubectl apply 명령을 사용할 때만 수행

2. 리소스 비교 및 병합(Merge)

  • 클러스터에 이미 존재하는 객체가 있다면 아래의 3가지 상태를 비교해서 어떤 필드를 추가/수정/삭제할지 판단 
    • 현재 클러스터에 존재하는 리소스 (라이브 상태)
    • 마지막으로 kubectl apply로 적용한 구성 (last applied configuration) (json형태)
    • 새롭게 적용하려는 YAML 구성
  • 변경사항을 라이브중인 리소스에 변경해서 적용, 마지막 구성(last applied configuration)도 최신 상태로 갱신합니다.

3. last-applied-configuration의 역할

  • 사용자가 YAML에서 어떤 항목을 삭제했는지를 판단하는 데 필요합니다.
    • 쿠버네티스에게 내가 마지막으로 apply한 구성은 이거야! 라고 알려주는 역할
  • 단순히 현재 라이브 상태와 새 YAML만 비교하면, 어떤 필드를 명시적으로 제거했는지 알 수 없습니다.
    • 의도된 삭제인지 아닌지를 정확하게 판단하기가 어려움, 왜냐면 사영자가 설정한 필드 이외에도 다양한 리소스들이 자동으로 추가한 필드들도 있기 때문(처음에 없었는데 기본으로 붙여준건가? 아니면 삭제한건가? 이런것에 대한 구분이 애매함) 
  • 이 정보가 있어야 정확한 변경 추적(diff) 과 필드 삭제가 가능합니다.
apply로 생성 수정된거 보면 이렇게 애노테이션으로 붙는다 

metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {
        "apiVersion": "apps/v1",
        "kind": "Deployment",
        "metadata": {
          "name": "nginx-deployment",
          "labels": {
            "app": "nginx"
          }
        },
        "spec": {
          "replicas": 2,
          "selector": {
            "matchLabels": {
              "app": "nginx"
            }
          },
          "template": {
            "metadata": {
              "labels": {
                "app": "nginx"
              }
            },
            "spec": {
              "containers": [
                {
                  "name": "nginx",
                  "image": "nginx:1.14.2",
                  "ports": [
                    {
                      "containerPort": 80
                    }
                  ]
                }
              ]
            }
          }
        }
      }

 

공식 문서의 설명

https://kubernetes.io/docs/tasks/manage-kubernetes-objects/declarative-config/#merging-changes-to-primitive-fields

'자격증 > CKA' 카테고리의 다른 글

cluster 관리  (0) 2025.04.12
Lifecycle Management  (0) 2025.04.06
Logging & Monitoring  (0) 2025.04.06
쿠버네티스 Scheduling  (0) 2025.03.31
기초 개념 정리  (0) 2025.03.03