1. Node와 Pod
여기 Worker Node라고 불리는 Node1이 하나 있다.
이 node는 하나의 물리 머신 또는 가상 머신일 수 있다.
그리고 이 노드 안에 'Pod'라고 하는 가장 기본적이고 심플한 쿠버네티스의 구성요소가 있다.
파드는 컨테이너의 추상화를 도와준다.
이를 abstraction over container라고 한다.
우리는 컨테이너라고 하면 기본적으로 Docker를 떠올릴 수 있지만, 노드들은 그렇지 못하다.
실제로 컨테이너 도구는 Docker이외에 다른 다양한 도구들이 있고, 쿠버네티스는 그들 중 어떤 컨테이너 도구를 사용해도 적응할 수가 있다.
적응을 도와주는 것이 바로 컨테이너의 추상화를 도와준다고 하는 파드 덕분이다.
파드에는 일반적으로 하나의 애플리케이션 컨테이너가 들어가게 된다.
하지만 메인 애플리케이션 컨테이너를 도와주기 위해서 side 컨테이너 또는 helper컨테이너 같은 것들이 같은 파드 내에서 동시에 추가적으로 구동될 수 있다.
쿠버네티스 내부에서 컨테이너들은 서로 어떻게 소통할까?
각각의 파드들은 고유한 내부 IP 주소를 가지게 된다.
파드 내부의 컨테이너들은 모두 같은 IP 주소를 가지게 된다는 뜻이고, 하나의 파드로 네트워크가 묶이게 된다.
이러한 IP 자원을 이용한 통신에는 문제가 있다.
파드는 매우 일시적인 개념이다. 그래서 쿠버네티스에서 파드는 언제든지 파괴되고, 생성될 수 있으며(이하 restart) 새로 생성될 때마다 파드는 새로운 IP주소를 할당받게 된다.
파드의 이런 특성은 쿠버네티스의 중요한 특징 중 하나이다.
그렇다면 종종 발생하는 파드의 Restart마다 my-app에서는 데이터베이스와의 통신을 위해서 매번 IP를 다르게 설정해주어야 할 것이다. 이는 매우 불편한 상황이 될 것이다.
그래서 쿠버네티스는 Service라는 개념이 존재한다.
2. Service와 Ingress
IP 부분이 Service로 바뀌었다.
쿠버네티스에서 서비스는 static IP 주소(영구적인)를 부여받게 된다.
my-app 파드는 자신의 service를 가지게 되고, DB 파드는 자신의 service를 가지게 된다.
좋은 점은 파드와 서비스의 생명주기는 서로 연관성이 없다는 것이다.
파드가 Restart를 하더라도 서비스의 IP주소는 유지된다는 뜻이다. 그래서 애플리케이션의 endpoint를 더 이상 바꿀 필요가 없어진다.
만약 브라우저에서 접근할 수 있는 웹 애플리케이션(my-app)을 배포하고 싶다면 External Service를 만들어야 한다.
External service는 외부 요소들과 통신할 수 있도록 통로를 열어준다.
그러나 DB의 통로를 열고 싶지 않다면 Internal service를 만들어 주면 된다.
따라서 서비스를 만들 때는 일반적으로 External과 Internal 중 하나를 고를 수 있다.
실제로 서비스는 아래 4가지로 나누어 지는데 나중에 자세히 다루도록 하겠다.
- ClusterIP
- LoadBalancer
- NodePort
- ExternalName
일반적으로 External service의 url은 실용적이지 못하다. 주로 Node의 ip주소에 서비스의 port 번호가 더해져서 해당 애플리케이션 파드로 요청이 보내진다.(ex. 112.119.2.11:8080) 이러한 방법은 테스트를 위해서는 매우 좋은 방법이다. 하지만 최종 배포 상황에서는 매우 좋지 못하다.
따라서 애플리케이션에 어울리는 도메인으로 소통하기 위해서 Ingress라고 불리는 쿠버네티스 구성요소를 사용하게 된다.
Ingress는 서비스로 들어오는 Request들을 먼저 받아서 서비스로 포워딩해주는 역할을 수행한다.
Ingress에 대한 설명이 조금 부족한 것 같아 추가적으로 알아보았다.
Ingress는 클러스터 외부에서 내부 서비스로 접근하는 HTTP, HTTPS 요청들을 어떻게 처리할지 정의해둔 규칙들의 모음을 말한다.
클러스터 외부에서 접근 가능한 URL을 사용할 수 있게 하며, 트래픽을 로드밸런싱도 해주고, SSL 인증서 처리도 해주고, 도메인 기반으로 가상 호스팅을 제공하기도 한다.
Ingress 규칙들을 Ingress 자원(resource)이라고도 할 수 있는데 자원을 사용하기 위해서는 Ingress Controller라는 것이 필요하다.
Ingress Controller는 일반적으로 AWS, GCE, Nginx 인그레스 컨트롤러를 사용할 수 있다.
3. ConfigMap과 Secret
my-app 파드는 DB와 서로 소통한다.
my-app은 mongo-db-service라는 이름의 endpoint로 DB파드와 통신하고 있다.
(http://mongo-db-service가 URL이 될 수 있다는 뜻.)
일반적으로 이러한 URL은 애플리케이션 내부에서 직접 적어주어야 한다.
그렇다면 만약 DB서비스의 이름이 바뀐다면 개발자가 DB통신 URL을 하나하나 찾아서 바꿔줘야 하는데, 이는 매우 불편할 것이다.
URL을 변경하면 애플리케이션을 Re-build 하고, Repo에 이미지를 올리고, 이미지를 pull 받아서 관련 파드를 모두 재시작해야 할 것이다.
이러한 불편함을 해소하기 위해서 쿠버네티스는 ConfigMap이라는 도구를 제공한다.
ConfigMap은 기본적으로 애플리케이션의 외부와의 통신을 설정해주는 역할을 한다.
그리고 일반적으로 파드와 연결하기 위한 정보들을 가지고 있어서 파드는 ConfigMap에서 자신이 필요한 정보들을 가져올 수 있다.
그래서 DB의 URL을 변경 시, ConfigMap의 DB_URL 부분만 변경해주면 되기 때문에 위에서 말했던 파드 재시작 사이클을 수행하지 않아도 된다.
그리고 DB의 username, password 같은 부분들도 다 저장해 놓을 수 있어서 이들의 값이 바뀐대도 언제든지 편하게 바뀐대로 적용해줄 수 있다.
그러나 password같이 인증에 필요한 값들을 ConfigMap에 저장하면 보안상 취약할 수 있다.
그래서 보안에 관련된 부분을 충족시켜 주기 위해서 Secret이라는 컴포넌트가 존재한다.
Secret은 ConfigMap과 거의 비슷하지만 secret data를 저장하기 위해서 평문을 base64로 인코딩해서 저장하는 방식을 사용한다.
암호화 된 것은 아니며, 단순히 인코딩 된 것이다.
물론 password같은 credential들을 ConfigMap에 저장할 수 있지만 ConfigMap은 모두가 볼 수 있기 때문에 보안에 취약할 것이다.
지금까지 쿠버네티스의 가장 기본적인 구성요소인 Pod, Service, Ingress, ConfigMap, Secrets에 대해서 알아보았다.
아주 간단하게 정리해보자면,
my-app에 들어오는 요청은 external-service의 Ingress로 들어온다. Service는 Ingress를 거쳐 요청을 전달 받고 DB와 my-app은 서로의 서비스 URL과 유저 정보를 통해서 소통을 한다. 이때 URL 등이 기록된 요소를 ConfigMap이라고 하고, password 같은 credential들이 저장된 곳을 secrets라고 한다.
4. Volumes
데이터 저장소에 관한 아주 중요한 개념인 volume을 알아보고 이것이 쿠버네티스에서 어떻게 적용되는지 알아보자.
지금까지 본 DB파드는 재시작할 경우에 모든 데이터가 사라진다는 큰 위험을 가지고 있다. DB에 오류가 나서 재시작을 해야 할 수도 있지만, 그때마다 데이터가 모두 사라져야 한다면 사용하기 힘들 것이다.
볼륨은 볼륨을 사용하는 파드가 위치한 Local 머신의 Hard 저장소에 위치할 수 있고, 외부 클라우드나 다른 온프레미스 서버에 위치할 수 있다.
그래서 DB 파드가 재시작 되어도 볼륨으로 연결된 내부 데이터들은 멀쩡히 유지된다.
구분해야 할 점은 Volume은 쿠버네티스 클러스터가 관리하지 않는다는 점이다.
데이터의 백업, 복제, 관리에 관한 부분들은 적절한 하드웨어를 사용해 저장할 뿐이다. 왜냐하면 쿠버네티스는 데이터의 영속에 관심이 없기 때문이다.
5. Deployment와 Stateful Set
지금까지 알아본 쿠버네티스 구성요소를 사용해서 브라우저를 통해 우리가 만든 웹 애플리케이션에 접속할 수 있다.
그런데 만약 애플리케이션 파드가 파괴되면 어떻게 될까? 개발자는 downtime을 직접 인식하고, 직접 재시작 해야할 것이다. 배포 중이었다면 이는 최악의 상황일 것이다.
이러한 상황을 방지하기 위해서 쿠버네티스는 Multiple Server를 구축할 수 있다.
각 노드에는 동일한 이미지를 가지고 만들어지는 파드가 존재한다. 이들을 Replica라고 부르며 Replica들은 서로 같은 서비스로 묶이게 된다.
여기서 서비스는 2가지의 기능을 가진다.
서비스만의 영구적인 IP를 가지고, 로드밸런서의 역할을 하게된다.
서비스로 요청이 들어오면, 서비스는 자신과 연결된 파드 중에서 하나를 골라 요청을 포워딩 해준다.
위와 같은 노드 구성을 똑같이 다시 구성해야 한다면 힘들 것이다.
그래서 우리는 '파드당 몇 개의 Replica를 생성할 지(ReplicaSet)'에 대한 정보들이 적힌 청사진(Blueprint)이 필요하다.
이를 Deployment라고 부른다.
실제로 파드를 직접 생성하거나 구동하지 않고, Deployment를 생성해서 파드에 접근한다.
Deployment는 파드가 몇 개의 Replica를 가질 지를 정할 수 있고, Scale Up 과 Down이 쉽게 가능하다.
그래서 Deployment를 '파드의 추상화' 라고도 부를 수 있다.
Deployment를 통해 2개의 Replicaset를 가진 my-app은 node1의 파드가 파괴되어도 node2의 파드가 존재하기 때문에 downtime을 겪지 않아도 된다.
그런데 위 그림에서는 DB 파드에 대한 ReplicaSet이 없다.
그렇다면 node1에 있는 DB 파드가 파괴된다면 my-app이 데이터에 접근하지 못해서 애플리케이션이 정상적으로 작동하지 않을 것이다. 그렇다면 DB 파드도 똑같이 ReplicaSet을 설정해주면 되지 않냐고 할 수 있다.
DB 파드는 일반적으로 Replica를 생성하는 것이 불가능하다.
왜냐하면 DB는 데이터에 대한 상태(state of data)를 가지고 있기 때문이다.
DB 파드는 분명 같은 DB를 공유할 것이다. Replica되어 다른 노드에 있는 경우, 특정 노드는 데이터에 대한 쓰기 작업을 할 수 있을 것이고, 다른 노드는 데이터에 대한 읽기 작업을 할 수 있을 것이다. 이렇게 데이터에 영향을 주는 작업이 서로 다른 곳에서 일어나기 때문에 데이터의 무결성이 파괴될 것이다.
이러한 문제를 해결하기 위해서 쿠버네티스 구성요소 중 하나인 Stateful Set이 존재한다.
MySQL, mongoDB, elasticSearch처럼 상태를 가진 애플리케이션들은 Deployment 대신에 Stateful sets를 사용해 생성되어야 한다.
Stateful Set도 deployment와 마찬가지로 파드에 대한 Replicating과 Scale up/down을 관리한다.
그러나 다른점은 DB를 읽고 쓰는데 있어서 동기화를 제공해준다는 점이다. 즉, Stateful set으로 만들어진 replica 들은 항상 서로 같은 상태(데이터)를 유지할 수 있게 된다.
중요한 문제는 Stateful set 으로 파드를 배포하기가 매우 어렵다는 것이다.
그래서 일반적으로 DB는 쿠버네티스 클러스터 외부의 호스트에 따로 Replica를 적용해서 사용한다.
이는 쿠버네티스 클러스터 내부에서와 다르게 별다른 문제가 생기지 않는다.
요약
컨테이너 추상화
파드간 통신
트래픽을 가장 먼저 받음
내/외부 설정 값
데이터 영속성
Pods의 ReplicaSet에 대한 blueprint
StatefulSet은 상태가 있는 앱(ex. db)에 사용됨
쿠버네티스의 구성요소는 더 많이 있지만, 지금까지 알아본 구성요소만 잘 사용해서도 충분히 강력한 애플리케이션을 구축할 수 있다.
출처 : https://www.youtube.com/watch?v=X48VuDVv0do
번역 : 나
Chapter : Main K8s Components
'DevOps > Kubernetes' 카테고리의 다른 글
[kubernetes] #4 Minikube와 kubectl - 클러스터 구축 (0) | 2022.02.28 |
---|---|
[kubernetes] #3 쿠버네티스 아키텍처 (0) | 2022.02.27 |
[Kubernetes] #1 쿠버네티스란? (0) | 2022.02.26 |
[K8S] 쿠버네티스 파드의 생명주기 (0) | 2022.01.18 |
[K8S] 쿠버네티스 구성요소 (0) | 2022.01.18 |