📍 해당 글은 Udemy의 Certified Kubernetes Administrator (CKA) with Practice Tests 강의를 듣고 정리했습니다.
풀스택 웹 어플리케이에는 프론트엔드 웹 서버를 실행파는 pod, 백엔드 웹서버를 실행하는 pod, 데이터베이스를 실행 중인 파드 등 여러 종류의 파드가 존재한다.
이때, 프론트엔드 서버는 백엔드 서버와 통신해야하고, 백엔드 서버는 데이터베이스 서버와 통신해야한다.
모든 파드에는 할당된 IP 주소가 있으니, 이를 이용하면 통신할 수 있을 것이라고 예상할 수 있다.
하지만 pod는 중지되거나 삭제한 뒤 다시 생성하면 IP 주소가 바뀐다. 즉, pod에 할당된 주소는 정적 주소가 아니기 떄문에 통신 시에는 pod IP에 의존할 수 없다.
그리고 pod IP를 통신에 사용하려면 문제가 하나 더 있다. 아래 사진과 같이 백엔드 파드가 여러 개일 때는 어떤 파드의 ip주소로 연결해야할지 결정해야한다.
이런 문제를 해결하기위해 Service
는 Pod에 액세스할 수 있는 단일 인터페이스(Virtual IP
)를 제공한다. 다른 파드가 서비스에 접근하면 요청이 연결된 파드 중 하나로 전달된다.
이를 통해 우리는 애플리케이션의 효과적인 배포가 가능하고, 서비스 간 통신에 영향을 주지 않고 레이어의 크기를 조정할 수 있다. 각 서비스에는 IP와 이름이 할당되는데, 이는 클러스터 내부에서 사용하는 이름로 Cluster IP
라고 한다.
apiVersion: v1
kind: Service
metadata:
name: back-end
spec:
types: ClusterIP # Service의 defult 타입
ports:
- targetPort: 80 # back-end가 노출되는 포트
port: 80 # service가 노출되는 포트
selector:
app: myapp
type: back-end
kubectl create|apply -f service-definition.yaml
kubectl get service
NodePort를 사용하면 외부에 있는 사용자가 애플리케이션에 접근할 수 있다. NodePort타입 서비스는 노드로 들어오는 트래픽을 수신하고 각 노드에 트래픽을 라우팅해준다.
하지만 이렇게되면 유저가 애플리케이션에 접근하고자 할 때 사용할 URL이 여러개 생긴다.
사용자에게는 단일 URL을 제공해야한다. 이를 위한 방법은 로드밸런서 서버를 구성하는 것이다.
우리는 GCP, AWS, Azure 등의 클라우드 플랫폼에서 native loadbalancer를 사용할 수 있다.
q2. k8s에는 default service가 존재한다.
namespace의 목적으로는 리소스 격리
, 정책 분리
, 자원 제한
이 있다.
개발과 프로덕션 네임스페이스를 구분해놓는다면 리소스를 격리할 수 있다. 이러면 개발 환경에서 작업하는 동안 프로덕션 리소스를 실수로 수정하는 일을 막을 수 있다.
또한 각 namespace는 누가 무엇을 할 수 있는지 정의하고, 리소스 할당에 대한 정책을 정할 수 있다.
<사진>
같은 네임스페이스 안에서는 각 리소스들은 서로를 단순히 이름만으로 참조할 수 있다.
# default ns에 있는 pod 조회
k get po
# kube-system에 있는 pod 조회
k get po --namespace=kube-system
네임스페이스를 지정하기 위해서는 kubectl
명령 옵션으로 --namespace=[ns명]
을 지정하거나 manifest file에 namespace를 명시하면 된다.
apiVersion: v1
kind: Pod
metadata:
name: app-pod
namespae: dev
만약 새로운 네임스페이스를 생성하고자 한다면, 다른 오브젝트와 마찬가지로 Namespace의 definition file을 정의하면 된다.
apiVersion: v1
kind: NameSpace
metadatd:
name: dev # 네임스페이스 이름을 지정
# 네임스페이스 옵션을 생략하면 dev 네임스페이스를 조회하고 싶다면
kubectl config set-context $(kubectl config current-context) --namespace=dev
namespace에서 리소스를 제한하려면 Resource Quota
를 사용하여 리소스 할당량을 만들어주면 된다.
apiVersion: v1
kind: ResourceQuota
metadata:
name: compute-quota
namespace: dev
spec:
hard:
pods: "10" # 10개의 파드
requests.cpu: "4"
requests.memory: 5Gi
limits.cpu: "10" # 10개의 cpu 유닛
limits.memory: 10Gi # 10GBi 메모리
명시형
은 "어떻게"에 더 중점을 두는 방식이고, 선언형
은 "무엇을"에 더 중점을 두는 방식이다.
<사진>
명시형 방식은, 변경이나 수정 전에 항상 현재 구성에 대해 알고 있어야하기때문에 관리자에게 부담이 된다.
kubectl edit
명령을 활용하자.명시형 명령은 일회성 작업을 빠르게 완료하고 definition file을 쉽게 생성하는데 도움을 준다.
--dry-run=client
: 리소스를 생성하지 않고 리소스 생성 여부와 명령이 올바른지의 여부를 알 수 있다.-o yaml
: 리소스 정의를 YAML 형식으로 출력할 수 있다.# Service 관련 명령
# Create a Service named redis-service of type ClusterIP to expose pod redis on port 6379
1. k expose pod redis --port=6379 --name redis-service --dry-run=client -o yaml
2. k create service clusterip redis --tcp=6379:6379 --dry-run=client -o yaml
이렇게하면 pod label을 selector로 사용하지 않고 대신 selector를 app=redis로 가정한다. (?)
# Create a Service named nginx of type NodePort to expose pod nginx's port 80 on port 30080 on the nodes
1. k expose pod nginx --type=NodePort --port=80 --name=nginx-service --dry-run=client -o yaml
이렇게하면 노드 포트는 지정할 수가 없어서 definition file을 수정한 다음 생성해야한다.
2. k create service nodeport nginx --tcp=80:80 --node-port=30080 --dry-run=client -o yaml
이렇게하면 파드 label을 selector로 사용하지 않는다.
두 가지 명령 모두 문제가 있다. 하나는 nodeport를 지정할 수 없고, 하나는 selector를 허용할 수 없다.
따라서 k expose 명령을 사용하는 것이 좋다. nodeport를 지정해야하는 경우라면 k expose 명령 후 definition 파일의 nodeport를 직젒 수정하고 생성하자.
https://kubernetes.io/docs/reference/generated/kubectl/kubectl-commands
https://kubernetes.io/docs/reference/kubectl/conventions/
먼저 세 종류의 파일이 존재한다.
이 세가지 파일을 비교하여 오브젝트를 생성, 삭제, 변경한다.
<사진>