쿠버네티스(kubernetes) Deployment, Service
디플로이먼트(Deployment): 레플리카셋, 포드의 배포를 관리
쿠버네티스 운영환경에서 레플리카셋을 YAML 파일을 통해 사용하는 경우는 거의 없고, 대부분은 레플리카셋과 포드의 정보를 정의하는 디플로이먼트라는 이름의 오브젝트를 YAML 파일로 정의해서 사용한다. (디플로이먼트는 레플리카셋의 상위 수준의 오브젝트)
<deployment-nginx.yaml>
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-nginx-deployment
spec:
replicas: 3
selector:
matchLabels:
app: my-nginx
template:
metadata:
name: my-nginx-pod
labels:
app: my-nginx
spec:
containers:
- name: nginx
image: nginx:1.10
ports:
- containerPort: 80
디플로이먼트 생성
$ kubectl apply -f deployment-nginx.yaml
$ kubectl get deploy
$ kubectl get replicasets
$ kubectl get pods
디플로이먼트, 레플리카셋 함께 생성되어 있음
디플로이먼트를 삭제하면 레플리카셋, 포드 또한 삭제됨
kubectl delete deploy my-nginx-deployment
디플로이먼트를 사용하는 이유는 애플리케이션의 업데이트와 배포를 더 편하게 만들기 위해서다.
디플로이먼트를 이용해 앱의 버전을 업데이트해 배포하는 간단한 예시를 살펴보자.
$ kubectl apply -f deployment-nginx.yaml --record
$ kubectl get pods
nginx의 버전을 변경하려면..
$ kubectl set image deployment my-nginx-deployment nginx=nginx:1.11 --record
YAML 파일에서 직접 수정하거나 kubectl edit 명령어로도 사용 가능함
그 뒤에 레플리카셋의 목록을 출력해보면?
$ kubectl get replicasets
두 개의 레플리카셋이 있는 걸 볼 수 있다.
디플로이먼트는 포드의 정보를 업데이트함으로써 새로운 레플리카셋과 포드를 생성했음에도 불구하고 이전 버전의 레플리카셋을 삭제하지 않고 남겨두고 있다. 해쉬값이 변경되어 관리되며 이전의 정보를 리비전으로 보존한다.
리비전 정보를 다음 명령어로 더 자세히 확인 가능
$ kubectl rollout history deployment my-nginx-deployment
이전 버전으로 롤백하고 싶다면?
$ kubectl rollout undo deployment my-nginx-deployment --to-revision=1
리소스 정리
$ kubectl delete deployment, pod ,rs --all
서비스(Service): 포드를 연결하고 외부에 노출
현재까지는 로컬 개발 환경 또는 클러스터 내부에서만 접근이 가능했다.
포트를 외부로 노출해 사용자들이 접근하거나, 다른 디플로이먼트의 포드들이 내부적으로 접근하려면 서비스라고 부르는 별도의 오브젝트를 생성해야 한다.
서비스 기능
- 고유한 도메인 이름을 부여함
- 로드 밸런서 기능 수행
- 포드를 외부로 노출
호스트 이름을 반환하는 간단한 웹 서버의 디플로이먼트 생성
<deployment-hostname.yaml>
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 apply -f deployment-hostname.yaml
서비스는 포드에 어떻게 접근할 것이냐에 따라 종류가 여러개로 세분화 된다.
목적에 맞는 적절한 서비스의 종류를 선택해야 하며 주로 사용하는 서비스 타입은 3가지다.
- ClusterIP: 쿠버네티스 내부에서만 포드에 접근할 때 (관리자가 주로 사용)
- NodePort: 클러스터의 모든 노드에 동일하게 개방
- LoadBalancer: 로드 밸런스를 동적으로 프로비저닝하여 포드에 연결
ClusterIP 타입의 서비스
<hostname-svc-clusterip.yaml>
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 어떤 라벨을 갖는 포드에 접근할 수 있게 만들 것인지 결정
- spec.ports.port: 쿠버네티스 내부에서만 사용할 수 있는 고유한 IP
- spec.ports.tartgetPort: selector 항목에 의해 정의된 라벨에 의해 접근 대상이 된 포드들이 내부적으로 사용하고 있는 포트
서비스 목록 확인
$ kubectl apply -f hostname-svc-clusterip.yaml
$ kubectl get services
$ kubectl get svc # services
생성된 서비스를 확인할 수 있고, 출력 내용 중에서 CLUSTER-IP와 PORT(S)를 통해 요청 보내면 된다.
임시 포드를 만들어 요청해보면..
$ kubectl run -i --tty --rm debug --image=alicek106/ubuntu:curl --restart=Never -- bash
# 서버에 접속한 뒤
$ curl 10.101.98.33:8080 --silent | grep Hello
$ curl hostname-svc-clusterip:8080 --silent | grep Hello
서비스 이름 자체로도 접근 가능
서비스의 IP와 포트를 통해 포드에 접근하고 있으며, 별도의 설정을 하지 않아도 로드 밸런싱이 수행되어 요청이 분산됨
서비스 삭제
$ kubectl delete svc hostname-svc-clusterip
$ kubectl delete -f hostname-svc-clusterip.yaml
NodePort 타입의 서비스
ClusterIP 타입의 서비스는 내부에서만 접근 가능하지만, NodePort 타입의 서비스는 클러스터 외부에서도 접근 가능함
모든 노드의 특정 포트를 개방해 서비스에 접근하는 방식
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-nodeport
spec:
ports:
- name: web-port
port: 8080
targetPort: 80
selector:
app: webserver
type: NodePort
서비스 생성하면..
$ kubectl apply -f hostname-svc-nodeport.yaml
$ kubectl get services
PORT(S) 항목에 31514라고 출력되는데, 이는 모든 노드에서 동일하게 접근할 수 있는 포트를 의미한다.
모든 노드에 내부 IP 또는 외부 IP를 통해 31514 포트로 접근하면 동일한 서비스에 연결할 수 있다.
한 가지 특이한 점은 kubectl get service 명령어에서 CLUSTER-IP 항목에 내부 IP가 할당되어 있는데, 이는 NodePort 타입의 서비스가 ClusterIP의 기능을 포함하고 있기 때문이다.
즉, NodePort 타입의 서비스는 내부 네트워크와 외부 네트워크 양쪽에서 접근할 수 있다.
클라우드 플랫폼의 로드 밸런서와 연동하기
LoadBalancer 타입의 서비스는 서비스 생성과 동시에 로드 밸런서를 새롭게 생성해 포드와 연결한다.
NodePort를 사용할 때는 각 노드의 IP를 알아야만 접근할 수 있었지만 LoadBalancer 타입의 서비스는 클라우드 플랫폼으로부터 도메인 이름과 IP를 할당받기 때문에 더 쉽게 접근할 수 있다.
일반적으로 AWS, GCP와 같은 클라우드 플랫폼 환경에서 LoadBalancer 타입을 사용할 수 있으며 가상 머신이나 온프레미스 환경에선 힘들 수 있다.
hostname-deployment라는 디플로이먼트는 미리 생성되어 있다고 가정
<hostname-svc-lb.yaml>
apiVersion: v1
kind: Service
metadata:
name: hostname-svc-lb
spec:
ports:
- name: web-port
port: 80
targetPort: 80
selector:
app: webserver
type: LoadBalancer
서비스 생성
$ kubectl apply -f hostname-svc-lb.yaml
LoadBalancer 타입 또한 NodePort나 ClusterIP와 동일하게 IP가 할당됨
눈여겨봐야 할 것은 EXTERNAL-IP가 생성되며 이는 클라우드 플랫폼에서 자동으로 할당된 것임
인프런: 대세는 쿠버네티스 강의자료 참조
추가 중급 서비스 내용
파드를 동시에 생성하는 경우에 파드에서 파드로 접근할 때, IP를 알 수 없으니 Headless를 이용하여 도메인을 통한 접근하는 방법과 파드와 서비스를 연결하는 Endpoint 그리고 ExternalName도 알아둘 것
References:
https://kubetm.github.io/k8s/03-beginner-basic-resource/service/
http://www.yes24.com/Product/Goods/84927385
'DevOps > Kubernetes' 카테고리의 다른 글
쿠버네티스(kubernetes) ingress (0) | 2022.05.15 |
---|---|
쿠버네티스(kubernetes) Namespace, ConfigMap, Secret (0) | 2022.05.14 |
[troubleshooting] [kubelet-check] It seems like the kubelet isn't running or healthy. (0) | 2022.05.14 |
쿠버네티스(kubernetes) Pod, Replica Set (0) | 2022.05.08 |
쿠버네티스(Kubernetes) 설치 (0) | 2022.05.07 |