[CKA] Udemy CKA 강의 Core Concepts02 - Pod, Replica set, Deployment, Service, Namespace
Pod
- 응용 프로그램을 컨테이너의 형태로 워커 노드(worker node)에 배포할 때 pod로 캡슐화
- pod는 응용 프로그램(application)의 단일 인스턴스(instance)
- 쿠버네티스에서 만들 수 있는 가장 작은 객체(object)
- pod는 일반적으로 컨테이너와 1:1 관계
- 스케일업을 할 때 pod를 생성, 스케일다운을 할 때 pod를 삭제
- 기존 pod에 컨테이너를 추가로 생성하지 않음
- 멀티 컨테이너 pod
- 헬퍼 컨테이너가 필요할 때 동일 pod 내에 여러 개의 컨테이너를 가질 수 있음
- 동일한 네트워크 공간 및 저장 공간 사용
명령어
- pod 생성해 도커 컨테이너 배포
- kubectl run nginx --image nginx
- 도커 허브에서 도커 이미지 다운로드 (--image)
- pod 확인
- kubectl get pods
- kubectl get pods -o wide
- pod 자세하게 확인
- kubectl describe pod [이름]
- pod 삭제
- kubectl delete pod [이름]
yaml
쿠버네티스에서 YAML 기반의 configuration 파일을 사용해 파드를 생성하는 방법을 설명합니다. 기본적인 구조와 설정 방법은 아래와 같습니다:
- ApiVersion: 오브젝트 생성에 사용하는 Kubernetes API 버전입니다. 현재 파드 작업이므로 v1으로 설정합니다.
- kind: 생성하려는 오브젝트의 유형으로, 파드를 만들려면 Pod로 설정합니다.
- metadata: 오브젝트에 대한 정보를 담는 곳입니다. 여기에는 name(파드 이름)과 labels(오브젝트 식별을 위한 key-value 쌍) 같은 속성이 포함됩니다. metadata 하위에는 미리 정의된 속성만 사용할 수 있습니다.
- spec: 생성할 오브젝트에 필요한 추가 정보를 정의하는 곳입니다. containers라는 속성을 사용해 컨테이너를 정의하며, 각 컨테이너의 name과 image를 지정합니다.
// pod-definition.yaml
apiVersion: v1
kind: Pod
metadata:
name: nginx
labels:
app: myapp
tier: frontend
spec:
containers:
- name: nginx
image: nginx //이미지 레포지토리(도커허브)의 이미지 이름
구조가 완성되면 kubectl create -f pod-definition.yml 명령어로 파드를 생성할 수 있습니다.
- kubectl create -f pod-definition.yml
- kubectl apply -f pod-definition.yml
- kubectl run [이름] --image=[이미지명] --dry-run=client -o yaml > [파일명].yaml
요약: Kubernetes YAML 파일의 최상위 속성인 ApiVersion, kind, metadata, spec을 이해하고, 오브젝트에 맞는 추가 설정을 통해 파드를 생성합니다.
Replica Set
- 응용 프로그램의 지속적인 수행을 보장하기 위함 (high availability)
- 동일한 서비스를 제공하는 pod 여러 개를 Replication Controller가 관리하거나
- 하나의 pod만 있더라도 Replication Controller가 관리 (서비스 죽으면 바로 복구)
- 사용자가 몰릴 경우에도 원활한 서비스 제공 (load balancing & scaling)
- 사용자가 몰려 로드가 증가할 때 pod를 추가로 만들어 응용 프로그램을 제공
- Replication Controller는 여러 개의 node에 걸칠 수 있음
YAML
Replication Controller
- 이전 버전에서 사용됨
// rc-definition.yaml
apiVersion: v1
kind: ReplicationController
metadata: // for rc
name: myapp-rc
labels:
app: myapp
type: front-end
spec:
template: // rc가 포드 템플릿을 보고 포드를 복제
metadata: // for pod
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
- kubectl create -f rc-definition.yml
- kubectl get replicationcontroller
- kubectl get pods
Replica Sets
- 최근 버전에서 사용됨
// replicaset-definition.yaml
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-replicaset
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
selector: // 파드들을 식별할 수 있게 해줌
matchLabels:
type: front-end
- kubectl create -f replicaset-definition.yml
- kubectl get replicaset
- kubectl get pods
Labels and Selectors
- Replica Set은 pod를 모니터링하는 프로세스
- 어떠한 pod를 모니터링할지는 레이블링으로 결정
- matchLabels (replicaset yaml) == labels (pod yaml)
- 만약 이미 돌고 있는 pod가 있다면 해당 pod를 포함, 그렇지 않다면 새로 생성
명령어
- replica set 스케일 하는 법
- 1. 직접 yaml 파일 replicas 숫자 업데이트 후 kubectl replace -f replicaset-definition.yml
- 2. 명령어 이용하기
- kubectl scale --replicas=6 -f replicaset-definition.yml
- kubectl scale --replicas=6 replicaset myapp-replicaset
- 하지만 파일 안의 내용이 자동으로 업데이트되지는 않음 -> 나중에 다룰 것
- kubectl create -f replicaset-definition.yml
- kubectl get replicaset
- kubectl get pods
- kubectl delete replicaset(rs) myapp-replicaset
- kubectl edit replicaset(rs) myapp-replicaset
- 수정 후에 기존 pod를 삭제해야 변경사항이 반영된 pod가 자동으로 생성됨
실습
- 1) k get pods
- 2) k get rs
- 3,4) k get rs
- 5,6) k describe rs new-replica-set
- 7) k describe pod new-tab
- 8) k delete pod new-tab
- 9) k get pods
- 11) k create -f replicaset-definition-1.yaml -> error: v1 | k explain rs -> apiVersion: app/v1
- 12) k create -f replicaset-definition-2.yaml -> error: spec.template.metadata.labels, invalid value: selector does not match template labels -> spec.selector.matchLabels.tier와 spec.template.metadata.labels.tier가 일치해야함 아니면 복제본을 관리할 수 없음
- 13) k get rs | k delete rs replicaset-1 replicaset-2
- 14) k get rs | k edit rs new-replicaset-set -> 직접 spec.template.spec.container로 가서 Image 고치기 -> image 고쳐도 자동으로 업데이트 안되니까 파드를 다 지워서 새로운 파드가 만들어지게 하거나, rs를 지우고 다시 create해야함
- 15) k scale rs new-replica-set --replicas=5
- 16) k scale rs new-replica-set --replicas=2
Deployment
- Deployment는 아래와 같은 기능을 가능케 함
- 운영환경에 배포 시 여러 개의 인스턴스 필요
- 응용 프로그램의 새로운 버전 등장 시 인스턴스 업그레이드
- 동시에 업그레이드하지 않고 인스턴스를 하나씩 업그레이드할 수도 있음 (rolling update)
- 문제가 발생할 시 롤백 (roll back)
- 환경을 잠시 멈추고 모든 변경사항을 수행한 뒤 재시작
- Deployment는 Replica Set을 감싸고 있는 상위 객체
- Replica Sets
- 여러 개의 pod를 배포
- Pod
- 응용 프로그램의 단일 인스턴스 배포
- 컨테이너를 캡슐화
- Replica Sets
YAML
// deployment-definition.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp-replicaset
labels:
app: myapp
type: front-end
spec:
template:
metadata:
name: myapp-pod
labels:
app: myapp
type: front-end
spec:
containers:
- name: nginx-container
image: nginx
replicas: 3
selector:
matchLabels:
type: front-end
- apiVersion과 kind를 제외한 다른 부분은 Replica Set과 동일
kubectl run으로 yaml file 간편하게 만들기
- nginx pod 만들기
- kubectl run nginx --image=nginx
- POD manifest yaml 파일 (-o yaml) 작성
- kubectl run nginx --image=nginx --dry-run=client -o yaml
- dry-run 사용 시 파일만 생성될 뿐 실제 pod가 생성되지는 않음
- Deployment yaml 파일 작성
- kubectl create deployment --image=nginx nginx --dry-run=client -o yaml > nginx-deployment.yaml
- kubectl create deployment --image=nginx nginx --replicas=4 --dry-run=client -o yaml > nginx-deployment.yaml
- 1.19 버전 이상에서는 --replicas 옵션으로 deployment 생성 가능
- 파일 수정 후 Deployment 생성
- kubectl create -f nginx-deployment.yaml
명령어
- kubectl create -f deployment-definition.yml
- kubectl get deployments(deploy)
- kubectl get all
실습
- 1,6) k get pods
- 2,5,7) k get rs
- 3,4) k get deploy
- 8,9) k describe pod frontend-tab -> 파드 중에 하나만 골라서 image 보기
- 10) k create -f deployment-definition-1.yaml -> error: no kind deployment is registered -> kind: Deployment
- 11) k create deployment httpd-frontend --replicas=3 --image=httpd:2.4-alpine
Deployment와 Replicaset의 관계
Deployment는 내부적으로 ReplicaSet을 관리하여 파드를 생성하고 유지합니다.
Deployment를 사용하면 직접 ReplicaSet을 관리할 필요 없이, 롤링 업데이트와 롤백과 같은 기능을 통해 애플리케이션을 더 유연하게 운영할 수 있습니다.
Service
- 다양한 파드 그룹 사이의 연결성(connectivity) 및 통신 담당
- 프론트엔드과 엔드 유저(사용자)
- 프론트엔드와 백엔드
- 백엔드와 데이터
- 애플리케이션의 msa 간에 낮은 결합도로 연결가능하게 해줌
- 노트북에서 ssh 연결 없이 쿠버네티스 노드의 ip에 접근하고 웹 서버에 접속하고 싶다면
- 노트북에서 노드로, 노드에서 파드로 중간에 요청을 매핑하는 service가 필요
- service type
- 1. node port: 서비스가 내부 파드를 노드의 파드에 액세스할 수 있도록 있게 함
- 2. clusterip: 클러스터 안에 가상 ip를 만들어 다른 서비스 간의 통신을 가능하게 함
- 3. loadbalancer: 클라우드 제공자에 있는 응용 프로그램을 위해 프로비저닝
NodePort
- 워커 nodeport에서 외부 애플리케이션을 사용할 수 있도록 함
- 노드의 포트로부터 들어오는 요청을 pod에 전달하는 역할
- 사용자가 쿠버네티스 노드 내의 pod에 접속하고자 할 때 사용
- 1) TargetPort: Pod에 붙어있는 포트
- 2) Port: Service에 붙어있는 포트, 클러스터 IP와 함께 존재
- 3) NodePort: Node에 붙어있는 포트, 30000-32767 (범위)
- 여러 개의 pod와 연결될 때, 랜덤 알고리즘으로 로드 밸런싱 -> 서비스는 파드 간 부하를 분산하면서 기본적으로 lb 역할을 함
- 1(pod):1(node), N:1, N:N일 경우 모두 가능
- 만약 파드가 여러 노드에 분산되어 있으면?
- 서비스는 자동으로 클러스터의 모든 노드에서 대상 포트를 매핑하도록 만들고, 이때 클러스터의 모든 노드는 동일한 포드 번호를 사용
YAML
//service-definition.yaml
apiVersion: v1
kind: Service
metadata:
name: myapp-service
spec: // 실제 서비스를 정의하는 부분
type: NodePort
ports:
- targetPort: 80 // 안 적으면 port와 동일하다고 간주
port: 80 // 필수 필드
nodePort: 30008 // 지정 안하면 자동으로 배정됨
selector: // 연결할 파드의 labels 정보를 입력하면 파드와 연결
app: myapp
type: front-end
ClusterIP
- 클러스터 내에 가상의 IP를 생성
- 다른 서비스들 간의 통신을 담당 (e.g. 프론트엔드와 백엔드)
- 여러 개의 서비스 pod(e.g. 백엔드)를 위한 단일한 인터페이스를 제공
YAML
// service-definition.yaml
apiVersion: v1
kind: Service
metadata:
name: back-end
spec:
type: ClusterIP
ports:
- targetPort: 80 // 백엔드가 노출되는 포트
port: 80 // 서비스가 노출되는 포트
selector: // 파드의 Labels 정보 가져오기
app: myapp
type: back-end
- k create -f service-definition.yaml
- k get services
LoadBalancer
- 로드 트래픽을 여러 다른 웹서버로 분산하는 역할
- 여러 개의 클러스터 노드 IP에 대해 개별 접속하는 것이 아니라 단일한 경로로 서비스를 사용할 수 있도록 도움
- NodePort 대신 LoadBalancer 사용할 수 있음
- Google Cloud Platform 등에서는 사용 가능
- VirtualBox에서는 사용 불가
YAML
// service-definition.yaml
apiVersion: v2
kind: Service
metadata:
name: myapp-service
spec:
type: LoadBalancer
ports:
- targetPort: 80
port: 80
nodePort: 30008
명령어
- kubectl create -f [파일명].yaml
- kubectl get services(svc)
- curl http://192.168.1.2:30008
- NodePort의 IP, port 정보 (접속 시)
- kubectl expose pod [pod명] --port=[포트번호] --name [service명] --dry-run=client -o yaml
- pod를 포트에 노출시키는 ClusterIP 타입의 서비스 파일 생성
- pod의 레이블을 자동으로 selector로 사용
- kubectl create service clusterip [pod명] --tcp=6379:6379 --dry-run=client -o yaml
- 위와 동일하게 서비스 파일을 생성하는 명령어
- selector를 자동으로 선택하는 것이 아니라 app=redis로 설정하기 때문에 주의 필요 (수정 필요할 수 있음)
- kubectl run [pod명] --image=[이미지명] --port=[포트번호] --expose=true
- Service와 Pod를 동시에 생성할 수 있음
Namespace
- 자동 생성 네임스페이스
- Default
- 클러스터가 셋업될 당시 자동으로 만들어짐
- kube-system
- 네트워킹, DNS 등 사용자가 실수로 삭제해서는 안 될 것들을 모아놓음
- kube-public
- 모든 사용자들이 이용 가능한 자원
- Default
- 서비스와 자원들을 고립시킬 때 유용 (isolation)
- e.g. 개발환경과 운영환경을 분리할 때
- 네임스페이스마다 다른 정책 사용 가능 (policies)
- 사용 가능한 자원의 한계를 지정 가능 (resource limit)
명령어
- 기본 네임스페이스 내 명령어 (pod 확인, 생성)
- kubectl get pods
- kubectl create -f [파일명].yaml
- 네임스페이스 지정 명령어 (pod 확인, 생성)
- kubectl get pods --namespace=kube-system(-n=)
- kubectl create -f [파일명].yaml --namespace=dev
- 혹은 yaml file metadata 하위에 namespace: dev와 같이 작성
- 네임스페이스 확인
- kubectl get namespaces(ns)
- 네임스페이스 생성
- kubectl create namespace [이름]
- 네임스페이스 전환 (기본에서 변경)
- kubectl config set-context $(kubectl config current-context) --namespace=dev
- 모든 네임스페이스 확인
- kubectl get pods --all-namespaces(-A)
YAML
- apiVersion: v1
- kind: Namespace
- metadata:
- name: dev
DNS
- 같은 네임스페이스 안에서는 이름으로 호출 가능
- e.g. mysql.connect("db-service")
- 다른 네임스페이스에 있는 서비스를 호출할 때는 서비스명.네임스페이스.svc.cluster.local 형태로 호출
- e.g. mysql.connect("db-service.dev.svc.cluster.local")
- cluster.local은 기본 도메인명 (쿠버네티스 클러스터)
- svc는 서브도메인 (서비스)
Resource Quota
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev
spec:
hard:
pods: '10'
requests.cpu: '4'
requests.memory: 5Gi
limits.cpu: '10'
limits.memory: 10Gi
- kubectl create -f [파일명].yaml
실습
1) k get ns
2) k get pods -n=research(or --namespace=research)
3) k run redis --image=redis -n=finance
4) k get pods -A(or --all-namespaces)
5) just click open button
6) k get pods -n=marketing | k get svc -n=marketing
7) k get pods -n=dev -> db-service.dev.svc.cluster.local
Imperative vs. Declarative
- Imperative - 시험 준비 시 이거를 연습해야함
- 무엇이 필요한지, 어떻게 해야 하는지 단계적 설명 제공
- 직접적으로 객체의 생성, 변경, 삭제 등을 진행
- YAML 파일을 변경하지 않고 명령어로 생성, 수정 시에 쿠버네티스 메모리에는 기록이 남으나 로컬 파일에는 변경되지 않으므로 주의 필요
- kubectl run --image=nginx nginx
- kubectl create deployment --image=nginx nginx
- kubectl expose deployment nginx --port=80
- kubectl edit deployment nginx
- kubectl scale deployment nginx --replicas=5
- kubectl set image deployment nginx nginx=nginx:1.18
- kubectl create -f nginx.yaml
- kubectl replace -f nginx.yaml
- kubectl delete -f nginx.yaml
- Declarative
- 필요한 것들만 명시, 시스템이 알아서 진행
- configuration을 시스템이 확인하고 알아서 생성, 변경, 삭제 등을 진행
- kubectl apply -f nginx.yaml
- 쿠버네티스의 live object configuration에 정보 저장됨 (다른 명령어와 동일)
- json 포맷으로 변경되어 마지막으로 적용된 configuration 저장 (다른 명령어와 다름)
- live object configuration 내에 저장됨
- 어떤 필드가 삭제되었는지 확인 용이
💡 Certfication Tips - Imperative Commans with Kubectl
1. --dry-run=client: 명령어가 어떻게 수행될지에 대한 정보만 먼저 알려줌
2. -o yaml: 출력 형식을 yaml 형태로 지정
Example)
1. k run nginx --image=nginx --dry-run=client -o yaml
: 생성될 nginx 파드의 yaml을 출력
2. k create deployment --image=nginx nginx --dry-run=client -o yaml
: 생성될 nginx deployment의 yaml을 출력
3. k create deployment --image=nginx nginx --dry-run=client -o yaml > nginx-deployment.yaml
: yaml 파일 저장도 가능
Service
1. k expose pod redis --port=6379 --name=redis-service --dry-run=client -o yaml
: redis-service라는 이름의 ClusterIP 타입의 svc로 노출시키는 시뮬레이션
2. kubectl create service clusterip redis --tcp=6379:6379 --dry-run=client -o yaml
: 1번과 같은 역할을 하는 명령어
: 다만, selector를 자동으로 사용하지 않고, 기본적으로 app=redis 선택자가 사용됨. 즉, redis 파드가 app=redis 라벨을 가져야지 연결됨
3. kubectl expose pod nginx --type=NodePort --port=80 --name=nginx-service --dry-run=client -o yaml
: nginx-service라는 이름의 nodeport 타입의 svc로 노출시키는 시뮬레이션
4. kubectl create service nodeport nginx --tcp=80:80 --node-port=30080 --dry-run=client -o yaml
: 3번과 같은 역할이고, 30080포트를 노드에서 사용할 수 있게 지정함. 선택자를 자동으로 설정하지 않아 기본적으로 app=nginx라벨을 사용함
실습
1) k run nginx-pod --image=nginx:alpine
2) k run redis --image=redis:alpine --labels="tier=db"
4) k expose pod redis --name=redis-service --port=6379
5) k create deployment webapp --image=kodekloud/webapp-color --replicas=3
6) k run custom-nginx --image=nginx --port=8080
7) k create namespace dev-ns
8) k create deployment redis-deploy -n=dev-ns --image=redis --replicas=2
9) k run httpd --port=80 --image=httpd:alpine --namespace=default && k expose pod httpd
service/httpd exposed