여러개의 디플로이먼트를 하나의 완벽한 어플리케이션으로 연동하려면 포드 IP가아닌 서로를 발견(Discovery)할 수 있는 방법이 필요
Container
와 Pods
의 IP는 영속적이지 않아 변할 수 있음포트를 외부로 노출해 사용자들이 접근하거나, 다른 디플로이먼트의 포트들이 내부적으로 접근하려는 방법이 필요함.
서비스는 포드에 접근하기 위한 네트워크 규칙을 정의하는 오브젝트
종류 | 설명 |
---|---|
ClusterIp 타입 | 쿠버네티스 내부에서만 포드들에 접근할 때 사용, 외부로 포드 노출 X 따라서 클러스터 내부에서만 사용되는 포드에 적합 |
NodePort 타입 | 포드에 접근할 수 있는 포트를 클러스터의 모든노드에 동일하게 개방, 따라서 외부에서 접근할 수 있는 서비스 타입. 접근할 수 있는 포트는 랜덤으로 정해지지만, 특정 포트로 지정가능 |
LoadBalancer 타입 | 로드밸런서를 동적으로 프로비저닝해 포드에 연결, NodePort 타입과 마찬가지로 외부에서 접근할 수 있는 서비스 타입, 일반적으로 AWS, GCP 등과 같은 클라우드 플랫폼환경에서만 사용가능. |
실제 목적에 맞는 적절한 서비스 종류를 선택하는 것이 중요.
# 이 Deployment로 Service 수행
apiVersion: apps/v1
kind: Deployment
metadata:
name: hostname-deployment
spec:
replicas: 3
selector:
matchLabels:
app: webserver
template:
metadata:
name: my-webserver
labels:
app: webserver
spec:
containers:
- name: my-webserver
image: alicek106/rr-test:echo-hostname
ports:
- containerPort: 80
다음명령어로 서비스가 제대로 생성되었는지 확인가능
kubectl get pods
kubectl get deployment
kubectl get pods -o wide
kubectl run -i --tty --rm debug \
--image=alicek106/ubuntu:curl --restart=Never {Pods IP} | grep Hello
--restart : 컨테이너 재시작 정책 always
, never
, OnFailure
등 존재.
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-clusterip
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
selector:
app: webserver
type: ClusterIP
spec.selector: selector 항목은 이 서비스에서 어떠한 라벨을 가지는 포드에 접근할 수 있게 만들 것인지 확인
kubectl describe deployment
# 이후 selector name 확인
위 예시에서는 app: webserver 라는 라벨을 가지는 포드들의 집합에 접근할 수 있는 서비스를 생성
spec.ports.port : 서비스 IP에 접근할때 사용할 포트를 설정
spec.ports.targetPort: selector 항목에서 정의한 라벨에 의해 접근 대상이 된 포드들이 내부적으로 사용하고 있는 포트를 입력
spec.type : 이 서비스가 어떤 타입인지 나타내는 것, 서비스의 종류에는 ClusterIP
, NodePort
, LoadBalacer
등이 존재
kubectl apply -f hostname-svc-clusterip.yaml
kubectl get services
#or
kubectl get svc
kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never --bash
curl {serviceIP}:{servicePort} --silent | grep Hello
어플리케이션이 서비스나 포드를 쉽게 찾을 수 있도록 내부 DNS를 구동하고 있기때문에 가능.
curl hostname-svc-clusterip:8080 --slient | grep Hello
kubectl delete svc hostname-svc-clusterip
kubectl delete -f hostname-svc-clusterip.yaml
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-nodeport
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
selector:
app: webserver
type: NodePort
kubectl get services
kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
hostname-svc-nodeport NodePort 10.107.13.254 {serverIP} 8080:{port}/TCP 9s
kubernetes ClusterIP 10.96.0.1 {serverIP} 443/TCP 55d
NodePort 타입의 서비스가 생성됐음을 알 수 있는데, PORT항목의 31139라는 숫자는 모든 노드에서 동일하게 접근할 수 있는 포트를 부여 받음을 의미
또한 nodeport 타입또한 ClusterIP가 부여되는 것을 볼 수 있는데, nodeport는 내부적으로 이용할 수 있는 clusterIP도 생성하면서, 외부에서도 접근가능하도록 할수 있음
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-nodeport
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
nodePort: 31000
selector:
app: webserver
type: NodePort
# nodeport를지정함으로써 사용가능
default 옵션은 노드에서 개방되는 포트는 30000~32768 포트 중에 랜덤으로 선택됨
로드밸런서 타입은 일반적으로 AWS, GCP 등과 같은 클라우드 플랫폼 환경에서만 LoadBalancer 타입을 사용할 수 있습니다.
네이버 클라우드 플랫폼 또한 도커에 대한 로드밸런서를 지원하는듯 하나 현재 네이버
만 이용이 가능한 것으로 보임.
따라서 온프레미스 환경의 MetalLB
를 사용
metalLB 설치
#MatalLb 설치
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/namespace.yaml
kubectl apply -f https://raw.githubusercontent.com/metallb/metallb/v0.10.2/manifests/metallb.yaml
kubectl create secret generic -n metallb-system memberlist --from-literal=secretkey="$(openssl rand -base64 128)"
apiVersion: v1
kind: ConfigMap
metadata:
namespace: metallb-system
name: config
data:
config: |
address-pools:
- name: default
protocol: layer2
addresses:
- 192.168.219.101-192.168.219.255
kubectl apply -f hostname-configmap.yaml
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-lb
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
selector:
app: webserver
type: LoadBalancer
kubectl get svc -o wide
LoadBalancer
타입의 서비스를 사용하면 외부로부터 들어온 요청은 노드 중 하나로 보내지며, 그 노드에서 다시 포드중 하나로 전달kubectl get svc hostname-svc-nodeport -o yaml
# 혹은
kubectl get svc hostname-svc-lb -o yaml
설정 값 | 설명 | 비고 |
---|---|---|
Cluster | 같은 클러스터내에 묶여진 포드로 요청 전송 가능, 추가적인 네트워크 홉 발생할 수 있음. | Default |
Local | 포드가 생성된 노드에서만 포드로 접근 가능, 추가적인 네트워크 홉이 발생하지 않음 |
externalTrafficPolicy를 무조건 Local로 설정하는 것이 무조건 좋은 것은아님 예를들어, 각 노드에 포드가 고르지 않게 스케줄링 됐을때 요청이 고르게 분산되지 않을 수도 있기 때문입니다.
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-external
spec:
type: ExternalName
externalName: www.google.com