1. 쿠버네티스 네트워크 아키텍처
보통 쿠버네티스 아키텍처에서는 노드가 여러개인 구조를 가진다.
쿠버네티스 클러스터 환경에서 같은 대역의 네트워크 (192.168.56.0/24) 로 묶여져 있을 것이며, 노드들마다 IP가 할당된다. 그런데 이는 노드에 부여한 IP이지, Pod에 바로 접근할 수는 없다. 각각의 Pod들이 서로 통신을 할 수 있도록 하는 것이 CNI (Container Network Interface)의 역할이다. Pod와 호스트의 인터페이스를 연결해준다. CNI를 통해서 Pod에 할당되는 IP주소로 통신할 수 있게 한다.
그런데 이 Pod라는 것은 일회성으로 사용되는 목적으로 운영된다. 따라서 Pod에 문제가 생기거나 삭제되어버리면 IP가 변동되어 클라이언트 측에서는 Pod의 IP를 예측할 수가 없다 . 따라서 고정된 주소로 접근할 수 있도록 서비스 오브젝트를 사용한다.
2. Service 오브젝트
서비스란, 우리가 흔히 알고 있는 리눅스의 서비스 개념과는 달리 오브젝트의 종류라고 생각하면 된다. Pod은 기본적으로 일회성으로 동작하며, Pod이 생성될 때마다 동적으로 IP가 할당된다. 그런데 Pod가 삭제되고 새로운 Pod로 다시 생성되어 동작하면 IP 주소가 새롭게 부여되므로 기존의 IP주소와 다르다. 즉, 쿠버네티스 클러스터 내부에서 Pod들은 고정된 IP를 가지고 있지 않아서, 이를 논리적으로 묶어서 고정된 주소값으로 관리해주는 역할을 하는 것이 Service이다.
Service는 클러스터 내부 또는 외부에서 클러스터로 진입할 수 있는 access point를 제공하며 이 주소는 Service가 삭제되기 전까지 고정되어 사용할 수 있다.
3. Serivce 오브젝트 종류
서비스 오브젝트에는 ClusterIP, NodePort, LoadBalancer, External Name이 있다. 이중 Cluster IP는 클러스터 내부 pod 들끼리 통신을 지원하며 NodePort와 LoadBalancer는 클러스터 외부에서도 pod과 통신할 수 있게 지원한다. External Name은 이들과는 다른 목적으로, Pod 내부에서 외부의 다른 Pod으로 접근할 때, FQDN으로 접근할 수 있게 하는 서비스이다.
1) ClusterIP
클러스터 내부의 pod들끼리 통신을 하기 위한 서비스이다. 서비스의 레이블 셀렉터를 지정하면 해당 레이블 셀렉터가 관리하는 Pod들에 대해 endpoint가 자동으로 할당된다. 그리고 이 endpoint 주소를 통해서 클러스터 내부의 pod에서 또 다른 pod으로 접근이 가능하게 되는 것이다.
service object는 다음과 같이 정의한다. 별도의 타입을 지정해주지 않은 경우 ClusterIP 타입으로 서비스가 생성된다.
apiVersion: v1
kind: Service
metadata:
name: myapp-svc
spec:
ports:
- port: 80
targetPort: 8080
selector:
app: myapp-rs
selector 부분의 app: myapp-rs 례이블로 myapp-svc 서비스가 관리하게 될 pod를 지정해 줄 수 있다. 또한 spec.ports.port 는 Service 오브젝트가 사용할 포트이며, targetPort는 Service 오브젝트에서 Pod의 포트로 포워딩할 때 Pod이 사용하게 되는 포트 넘버이다. 즉, Service 오브젝트가 80포트로 외부에서 접근되면, Pod의 8080 포트로 포트포워딩해준다는 의미이다.
이 서비스만 생성하면, pod가 아직 생성되지 않았으므로 endpoints가 none이라고 뜬다.
vagrant@kube-control1:~/work/minjee$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 10d
myapp-svc ClusterIP 10.104.41.19 <none> 80/TCP 3s
app: myapp-rs 라는 레이블 셀렉터를 가진 레플리카셋을 생성한다.
apiVersion: apps/v1
kind: ReplicaSet
metadata:
name: myapp-rs
spec:
replicas: 3
selector:
matchLabels:
app: myapp-rs
template:
metadata:
labels:
app: myapp-rs
spec:
containers:
- name: myapp
image: ghcr.io/c1t1d0s7/go-myweb:alpine
ports:
- containerPort: 8080
레플리카셋 생성 후 다시 endpoint를 확인해보면 각각의 pod에 endpoint ip가 할당된 것을 확인할 수 있다.
vagrant@kube-control1:~/work/minjee$ kubectl get endpoints
NAME ENDPOINTS AGE
kubernetes 192.168.56.11:6443 10d
myapp-svc 192.168.119.184:8080,192.168.233.255:8080,192.168.9.86:8080 4m26s
위의 예시를 다이어그램으로 표현하면 아래와 같이 표현할 수 있다. 단, 물리적으로 myapp-rs 레플리카셋 오브젝트는 Control Plane에 생성될 것이다. 논리적으로는 pod 복제본들이 레플리카셋에 의해 관리되므로 저렇게 그려진 것이다.
myapp-rs 라는 레플리카셋에 의해 생성된 복제본 pod들은 app: myapp-rs 라는 레이블 셀렉터에 의해 myapp-svc 서비스가 관리하고 있다. myapp-svc는 각각의 pod에게 엔드포인트를 제공하며, 논리적으로 고정된 단일 주소와 포트(서비스 80포트 -> Pod 의 8080포트로 포워딩)를 제공하여 pod에 접근할 수 있게 한다.
2) NodePort
쿠버네티스의 모든 노드에 외부에서 접근할 수 있는 포트를 할당한다. 이때 할당되는 포트는 30000 ~ 32676 번 사이의 포트 넘버이다. 또한 고정된 포트 주소로 접근해야 하다면 NodePort 서비스 오브젝트를 정의할 때 명시적으로 지정해줄 수 있다. ManifestFile을 만들 때 30000 ~ 32767 번대 사이에서 원하는 포트 넘버로 지정하면 된다.
ClusterIP 와 NodePort 를 포함하는 오브젝트이다.
type을 NodePort로 지정해 주면 된다.
apiVersion: v1
kind: Service
metadata:
name: example-svc-nodeport
spec:
ports:
- port: 8080
targetPort: 80
selector:
appname: example-pod
type: NodePort
외부에서 NodePort가 할당한 포트 넘버를 통해 접근할 수 있다.
vagrant@kube-control1:~/work/20230216$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
example-svc-clusterip ClusterIP 10.104.93.145 <none> 80/TCP 17m
example-svc-nodeport NodePort 10.109.205.183 <none> 8080:31360/TCP 21s
kubernetes ClusterIP 10.96.0.1 <none> 443/TCP
3) LoadBalancer
클러스터 외부에서 클러스터로 접속할 때, 로드밸런서를 통해서 개별 Pod들로 접속하게 한다. 클라우드 환경과 온프레미스 환경에서 모두 사용해볼 수 있으며, 클라우드 환경에서는 AWS, Azure과 같은 서비스 제공업체를 통해 사용할 수 있고 온프레미스 환경에서는 Metallb같은 툴을 사용할 수 있다.
ClusterIP, NodePort, LoadBalancer를 포함하는 오브젝트이다.
apiVersion: v1
kind: Service
metadata:
name: example-svc-loadbalancer
spec:
ports:
- port: 80
targetPoprt: 8080
selector:
app: myapp-rs
type: LoadBalancer
서비스 목록을 확인하면 EXTERNAL-IP가 할당되었다. 이 주소로 외부에서 접근한다.
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
example-svc-loadbalancer LoadBalancer 10.103.209.78 192.168.56.200 80:32299/TCP 77s
외부에서 접근하면 개별 pod들에게 로드밸런서 서비스가 요청(트래픽)을 전달한다.
4) ExternalName
외부에서 내부로 접근하기 위한 서비스가 아니라, 내부에서 특정한 외부의 클러스터로 접근하기 위한 서비스의 한 종류이다. 특정한 외부 클러스터로 접근할 때 FQDN 주소를 사용한다. ExternalName은 외부에 있는 어플리케이션을 클러스터 내부에 있는 것처럼 사용할 수 있게 한다.
apiVersion: v1
kind: Service
metadata:
name: test
spec:
type: ExternalName
externalName: test.com
여기서 FQDN 는 test.com 이 되며 CNAME은 test가 된다. CNAME을 통해서 FQDN주소를 조회할 수 있다. 예를들어서 host test 이라는 명령어를 치면 test.com 이라는 FQDN 주소를 찾을 수 있을 것이다.
'Cloud Engineering > Kubernetes ⚙️' 카테고리의 다른 글
[Kubernetes] Ingress 컨트롤러 (0) | 2023.02.19 |
---|---|
[Kubernetes] 쿠버네티스 Volume의 종류와 특징 (0) | 2023.02.17 |
[Kubernetes] Jobs (잡)과 CronJob (0) | 2023.02.13 |
[Kubernetes] DaemonSet (데몬셋) (0) | 2023.02.13 |
[Kubernetes] Replication Controller (레플리케이션 컨트롤러) (0) | 2023.02.11 |