Kubernetes 애플리케이션 노출하기

KubernetesBeginner
지금 연습하기

소개

이 랩에서는 내부 및 외부 서비스를 생성하고, 레이블을 사용하며, Ingress 의 기본 사항을 탐구하는 등 다양한 기술을 사용하여 Kubernetes 애플리케이션을 노출하는 방법을 배우게 됩니다. 먼저 Minikube 를 사용하여 로컬 Kubernetes 클러스터를 설정한 다음, 샘플 NGINX 애플리케이션을 배포하고 내부 및 외부에서 모두 노출합니다. 또한 레이블을 사용하여 리소스를 구성하고 선택하는 방법을 살펴보고, 마지막으로 간단한 예제를 통해 Ingress 에 대한 간략한 소개를 받습니다. Ingress 는 복잡한 주제이므로, 이 랩에서는 개념에 대한 기본적인 소개만 제공합니다.

Kubernetes 클러스터 시작하기

이 단계에서는 Minikube 를 사용하여 로컬 Kubernetes 클러스터를 시작하고 확인하는 방법을 배우게 됩니다. 이는 로컬 머신에서 Kubernetes 애플리케이션을 개발하고 테스트하기 위한 필수적인 첫 번째 단계입니다.

먼저, Minikube 클러스터를 시작합니다:

minikube start

예시 출력:

😄  minikube v1.29.0 on Ubuntu 22.04
✨  Automatically selected the docker driver
📌  Using Docker driver with root permissions
🔥  Creating kubernetes in kubernetes cluster
🔄  Restarting existing kubernetes cluster
🐳  Preparing Kubernetes v1.26.1 on Docker 20.10.23 ...
🚀  Launching Kubernetes ...
🌟  Enabling addons: storage-provisioner, default-storageclass
🏄  Done! kubectl is now configured to use "minikube" cluster and "default" namespace

여러 명령을 사용하여 클러스터 상태를 확인합니다:

minikube status
kubectl get nodes

minikube status의 예시 출력:

minikube
type: Control Plane
host: Running
kubelet: Running
apiserver: Running
kubeconfig: Configured

kubectl get nodes의 예시 출력:

NAME       STATUS   ROLES           AGE   VERSION
minikube   Ready    control-plane   1m    v1.26.1

이러한 명령은 다음을 확인합니다:

  1. Minikube 가 성공적으로 실행 중입니다.
  2. 로컬 Kubernetes 클러스터가 생성되었습니다.
  3. 클러스터가 사용할 준비가 되었습니다.
  4. 제어 평면 (control plane) 기능을 갖춘 단일 노드 클러스터가 있습니다.

샘플 애플리케이션 배포

이 단계에서는 YAML 매니페스트를 사용하여 Kubernetes 애플리케이션을 생성하고 배포하는 방법을 배우게 됩니다. Kubernetes 리소스를 정의하고 적용하는 과정을 보여주기 위해 간단한 NGINX 웹 서버 배포를 생성합니다.

먼저, Kubernetes 매니페스트를 위한 디렉토리를 생성합니다:

mkdir -p ~/project/k8s-manifests
cd ~/project/k8s-manifests

NGINX 배포를 위한 YAML 파일을 생성합니다:

nano nginx-deployment.yaml

다음 배포 매니페스트를 추가합니다:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
        - name: nginx
          image: nginx:latest
          ports:
            - containerPort: 80

파일을 저장합니다 (Ctrl+X, Y, Enter).

Kubernetes 클러스터에 배포를 적용합니다:

kubectl apply -f nginx-deployment.yaml

예시 출력:

deployment.apps/nginx-deployment created

배포 및 파드를 확인합니다:

kubectl get deployments
kubectl get pods

kubectl get deployments의 예시 출력:

NAME               READY   UP-TO-DATE   AVAILABLE   AGE
nginx-deployment   3/3     3            3           1m

kubectl get pods의 예시 출력:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          1m
nginx-deployment-xxx-zzz            1/1     Running   0          1m
nginx-deployment-xxx-www            1/1     Running   0          1m

파드가 "Running" 상태가 될 때까지 기다린 후 진행합니다.

YAML 매니페스트를 자세히 살펴보겠습니다:

  • apiVersion: Kubernetes API 버전을 지정합니다.
  • kind: 리소스 유형 (Deployment) 을 정의합니다.
  • metadata: 배포에 대한 이름과 레이블을 제공합니다.
  • spec.replicas: 파드 복제본의 수를 설정합니다.
  • selector: 배포가 올바른 파드를 관리하도록 돕습니다.
  • template: 파드 사양을 정의합니다.
  • containers: 컨테이너 이미지와 포트를 지정합니다.

이 배포는 세 개의 동일한 NGINX 파드를 생성하여 Kubernetes 가 컨테이너화된 애플리케이션을 관리하는 방법을 보여줍니다.

YAML 을 사용하여 내부 또는 외부에서 애플리케이션을 노출하는 서비스 생성

이 단계에서는 NGINX 배포를 내부 및 외부로 노출하기 위해 Kubernetes 서비스를 생성하는 방법을 배우게 됩니다. 두 가지 일반적인 서비스 유형인 ClusterIP 와 NodePort 를 시연합니다.

먼저, 프로젝트 디렉토리로 이동합니다:

cd ~/project/k8s-manifests

ClusterIP 서비스 YAML 파일을 생성합니다:

nano nginx-clusterip-service.yaml

다음 서비스 매니페스트를 추가합니다:

apiVersion: v1
kind: Service
metadata:
  name: nginx-clusterip-service
spec:
  selector:
    app: nginx
  type: ClusterIP
  ports:
    - port: 80
      targetPort: 80

이제 NodePort 서비스 YAML 파일을 생성합니다:

nano nginx-nodeport-service.yaml

다음 서비스 매니페스트를 추가합니다:

apiVersion: v1
kind: Service
metadata:
  name: nginx-nodeport-service
spec:
  selector:
    app: nginx
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      nodePort: 30080

두 서비스 구성을 적용합니다:

kubectl apply -f nginx-clusterip-service.yaml
kubectl apply -f nginx-nodeport-service.yaml

예시 출력:

service/nginx-clusterip-service created
service/nginx-nodeport-service created

서비스를 확인합니다:

kubectl get services

예시 출력:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        30m
nginx-clusterip-service     ClusterIP   10.104.xxx.xxx   <none>        80/TCP         1m
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   1m

NodePort 서비스에 액세스하려면 Minikube IP 를 가져옵니다:

minikube ip

예시 출력:

192.168.49.2

서비스 유형 간의 주요 차이점:

  • ClusterIP: 내부 클러스터 액세스만 가능
  • NodePort: 각 노드의 IP 에서 고정 포트로 서비스를 노출
  • NodePort 범위: 30000-32767

서비스 구성 확인

이 단계에서는 kubectl describe service를 사용하여 Kubernetes 서비스의 상세 구성을 검사하고 네트워크 속성을 이해하는 방법을 배우게 됩니다.

먼저, 프로젝트 디렉토리에 있는지 확인합니다:

cd ~/project/k8s-manifests

ClusterIP 서비스를 자세히 설명합니다:

kubectl describe service nginx-clusterip-service

예시 출력:

Name:              nginx-clusterip-service
Namespace:         default
Labels:            <none>
Annotations:       <none>
Selector:          app=nginx
Type:              ClusterIP
IP Family Policy:  SingleStack
IP Families:       IPv4
IP:                10.104.xxx.xxx
IPs:               10.104.xxx.xxx
Port:              <unset>  80/TCP
TargetPort:        80/TCP
Endpoints:         10.244.0.7:80,10.244.0.8:80,10.244.0.9:80
Session Affinity:  None
Events:            <none>

이제 NodePort 서비스를 설명합니다:

kubectl describe service nginx-nodeport-service

예시 출력:

Name:                     nginx-nodeport-service
Namespace:                default
Labels:                   <none>
Annotations:              <none>
Selector:                 app=nginx
Type:                     NodePort
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.108.yyy.yyy
IPs:                      10.108.yyy.yyy
Port:                     <unset>  80/TCP
TargetPort:               80/TCP
NodePort:                 <unset>  30080/TCP
Endpoints:                10.244.0.7:80,10.244.0.8:80,10.244.0.9:80
Session Affinity:         None
External Traffic Policy:  Cluster
Events:                   <none>

네트워크 연결을 확인하기 위해 서비스 엔드포인트를 검사합니다:

kubectl get endpoints

예시 출력:

NAME                        ENDPOINTS                               AGE
kubernetes                  192.168.49.2:8443                       45m
nginx-clusterip-service     10.244.0.7:80,10.244.0.8:80,10.244.0.9:80   15m
nginx-nodeport-service      10.244.0.7:80,10.244.0.8:80,10.244.0.9:80   15m

서비스 설명에서 이해해야 할 주요 정보:

  • Selector: 서비스에 속한 파드를 보여줍니다.
  • IP: 서비스의 클러스터 내부 IP 주소입니다.
  • Endpoints: 서비스를 제공하는 파드 IP 주소 및 포트 목록입니다.
  • Port 및 TargetPort: 트래픽 라우팅 방식을 정의합니다.
  • NodePort: NodePort 서비스 유형의 외부 포트입니다.

레이블을 사용하여 리소스 구성 및 선택

이 단계에서는 Kubernetes 에서 레이블을 사용하여 리소스를 효율적으로 구성하고 선택하는 방법을 배우게 됩니다. 레이블은 Kubernetes 객체를 관리하고 구성하는 데 도움이 되는 키 - 값 쌍입니다.

먼저, 파드에 현재 레이블이 있는지 확인합니다:

kubectl get pods --show-labels

예시 출력:

NAME                                READY   STATUS    RESTARTS   AGE   LABELS
nginx-deployment-xxx-yyy            1/1     Running   0          30m   app=nginx,pod-template-hash=xxx
nginx-deployment-xxx-zzz            1/1     Running   0          30m   app=nginx,pod-template-hash=yyy
nginx-deployment-xxx-www            1/1     Running   0          30m   app=nginx,pod-template-hash=zzz

특정 레이블을 사용하여 파드를 선택합니다:

kubectl get pods -l app=nginx

예시 출력:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          30m
nginx-deployment-xxx-zzz            1/1     Running   0          30m
nginx-deployment-xxx-www            1/1     Running   0          30m

파드 중 하나에 사용자 지정 레이블을 추가해 보겠습니다:

kubectl label pods nginx-deployment-xxx-yyy environment=development

nginx-deployment-xxx-yyy를 파드 중 하나의 이름으로 바꿉니다.

예시 출력:

pod/nginx-deployment-xxx-yyy labeled

이제 여러 레이블 선택기를 사용하여 파드를 선택합니다:

kubectl get pods -l app=nginx,environment=development

예시 출력:

NAME                                READY   STATUS    RESTARTS   AGE
nginx-deployment-xxx-yyy            1/1     Running   0          30m

파드에서 레이블을 제거합니다:

kubectl label pods nginx-deployment-xxx-yyy environment-

예시 출력:

pod/nginx-deployment-xxx-yyy unlabeled

서비스에서 레이블 선택을 시연합니다:

kubectl describe service nginx-clusterip-service

"Selector" 섹션을 찾아 서비스가 레이블을 사용하여 파드를 식별하는 방법을 확인합니다.

레이블에 대한 주요 사항:

  • 레이블은 Kubernetes 객체에 연결된 키 - 값 쌍입니다.
  • 리소스를 구성, 선택 및 필터링하는 데 사용됩니다.
  • 동적으로 추가, 수정 또는 제거할 수 있습니다.
  • 서비스 및 배포는 레이블을 사용하여 관련 파드를 관리합니다.

서비스 삭제 및 관리

이 단계에서는 kubectl 명령을 사용하여 Kubernetes 서비스를 삭제하고 관리하는 방법을 배우게 됩니다. 서비스 관리를 이해하는 것은 Kubernetes 리소스를 유지 관리하고 정리하는 데 매우 중요합니다.

먼저, 현재 서비스를 나열합니다:

kubectl get services

예시 출력:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        1h
nginx-clusterip-service     ClusterIP   10.104.xxx.xxx   <none>        80/TCP         45m
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   45m

kubectl delete를 사용하여 특정 서비스를 삭제합니다:

kubectl delete service nginx-clusterip-service

예시 출력:

service "nginx-clusterip-service" deleted

서비스 삭제를 확인합니다:

kubectl get services

예시 출력:

NAME                        TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)        AGE
kubernetes                  ClusterIP   10.96.0.1        <none>        443/TCP        1h
nginx-nodeport-service      NodePort    10.108.yyy.yyy   <none>        80:30080/TCP   45m

여러 서비스 삭제를 더 명확하게 시연하기 위해 서비스를 다시 생성한 다음 함께 삭제해 보겠습니다:

## Recreate services
kubectl apply -f nginx-clusterip-service.yaml
kubectl apply -f nginx-nodeport-service.yaml
## Delete multiple services at once
kubectl delete service nginx-clusterip-service nginx-nodeport-service

예시 출력:

service "nginx-clusterip-service" deleted
service "nginx-nodeport-service" deleted

모든 서비스가 제거되었는지 확인합니다 (기본 kubernetes 서비스 제외):

kubectl get services

예시 출력:

NAME         TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   1h

서비스 삭제에 대한 주요 사항:

  • 서비스를 삭제하면 네트워크 엔드포인트가 제거됩니다.
  • 서비스가 제거될 때 파드는 삭제되지 않습니다.
  • 기본 kubernetes 서비스는 삭제할 수 없습니다.
  • 이름, YAML 파일 또는 레이블을 사용하여 서비스를 삭제할 수 있습니다.
  • 여러 서비스는 나열하거나 레이블 선택기를 사용하여 동시에 삭제할 수 있습니다.

Ingress 기본 소개 및 간단한 Ingress YAML 예시

이 단계에서는 Kubernetes 클러스터에서 서비스에 대한 외부 액세스를 관리하는 강력한 방법인 Kubernetes Ingress 에 대해 배우게 됩니다.

Ingress 란 무엇인가?

Ingress 는 일반적으로 HTTP 인 Kubernetes 클러스터 내 서비스에 대한 외부 액세스를 관리하는 API 객체입니다. Ingress 는 다음을 제공합니다:

  • 로드 밸런싱 (Load balancing): 여러 백엔드 서비스로 트래픽을 분산합니다.
  • SSL/TLS 종료 (termination): 보안 연결을 처리합니다.
  • 이름 기반 가상 호스팅 (Name-based virtual hosting): 호스트 이름을 기반으로 요청을 다른 서비스로 라우팅합니다.
  • 경로 기반 라우팅 (Path-based routing): URL 경로를 기반으로 요청을 다른 서비스로 라우팅합니다.

Ingress 는 두 가지 구성 요소로 구성됩니다:

  1. Ingress 리소스 (Resource): 라우팅 규칙을 정의하는 Kubernetes API 객체
  2. Ingress 컨트롤러 (Controller): Ingress 리소스에 정의된 규칙을 적용하는 구현

참고: 이 랩에서는 Ingress 에 대한 기본적인 소개만 제공합니다. 프로덕션 환경에서는 Ingress 구성이 고급 라우팅, 인증, 속도 제한 등을 포함하여 훨씬 더 복잡할 수 있습니다.

Minikube 에서 Ingress 애드온을 활성화해 보겠습니다:

minikube addons enable ingress

예시 출력:

💡  ingress is an addon maintained by Kubernetes. For any concerns contact minikube on GitHub.
🔉  ingress was successfully enabled

두 개의 샘플 애플리케이션에 대한 배포를 생성합니다:

kubectl create deployment web1 --image=nginx:alpine
kubectl create deployment web2 --image=httpd:alpine

이러한 배포를 서비스로 노출합니다:

kubectl expose deployment web1 --port=80 --type=ClusterIP --name=web1-service
kubectl expose deployment web2 --port=80 --type=ClusterIP --name=web2-service

Ingress YAML 파일을 생성합니다:

nano ingress-example.yaml

다음 Ingress 구성을 추가합니다:

apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: example-ingress
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  rules:
    - http:
        paths:
          - path: /web1
            pathType: Prefix
            backend:
              service:
                name: web1-service
                port:
                  number: 80
          - path: /web2
            pathType: Prefix
            backend:
              service:
                name: web2-service
                port:
                  number: 80

이 Ingress 구성의 주요 구성 요소:

  • metadata.annotations: Ingress 컨트롤러에 대한 특정 구성
  • spec.rules: 트래픽을 서비스로 라우팅하는 방법 정의
  • path: 일치할 URL 경로
  • pathType: 경로를 일치시키는 방법 (Prefix, Exact, 또는 ImplementationSpecific)
  • backend.service: 트래픽을 라우팅할 서비스 및 포트

Ingress 구성을 적용합니다:

kubectl apply -f ingress-example.yaml

Ingress 리소스를 확인합니다:

kubectl get ingress

예시 출력:

NAME              CLASS   HOSTS   ADDRESS        PORTS   AGE
example-ingress   nginx   *       192.168.49.2   80      1m

Ingress 세부 정보를 확인합니다:

kubectl describe ingress example-ingress

예시 출력은 라우팅 규칙과 백엔드 서비스를 보여줍니다.

Ingress 테스트:

## Get the Minikube IP
minikube ip

## Test access to the services through Ingress
curl $(minikube ip)/web1
curl $(minikube ip)/web2

각 명령은 해당 웹 서버에서 기본 페이지를 반환해야 합니다.

프로덕션 환경에서 Ingress 는 다음과 같이 구성할 수 있습니다:

  • 여러 호스트 이름 기반 규칙
  • HTTPS 용 TLS 인증서
  • 인증 메커니즘
  • 속도 제한
  • 사용자 지정 시간 초과 구성
  • 세션 선호도
  • 그리고 더 많은 고급 기능

Ingress 에 대한 보다 포괄적인 내용을 보려면 Kubernetes 문서를 참조하고 NGINX Ingress 또는 Traefik 과 같은 전용 Ingress 컨트롤러 문서를 살펴보십시오.

요약

이 랩에서는 로컬 머신에서 Kubernetes 애플리케이션을 개발하고 테스트하는 데 필수적인 Minikube 를 사용하여 로컬 Kubernetes 클러스터를 시작하고 확인하는 방법을 배웠습니다. 그런 다음 YAML 매니페스트를 사용하여 간단한 NGINX 웹 서버 배포를 생성하고 배포하여 Kubernetes 리소스를 정의하고 적용하는 과정을 시연했습니다.

내부적으로 (ClusterIP 사용) 및 외부적으로 (NodePort 사용) 애플리케이션을 노출하기 위해 Kubernetes 서비스를 생성하는 방법과 레이블을 사용하여 리소스를 효과적으로 구성하고 선택하는 방법을 배웠습니다. 또한 개별 서비스 및 여러 서비스를 삭제하는 것을 포함하여 서비스 관리도 연습했습니다.

마지막으로, Kubernetes Ingress 의 기본 사항을 소개받았고 경로 기반 라우팅의 간단한 예시를 보았습니다. 이 랩에서는 Ingress 에 대한 간략한 소개만 제공했지만, URL 경로를 기반으로 외부 트래픽을 다른 서비스로 라우팅하는 기본적인 개념을 보여주었습니다.

Ingress 및 해당 기능에 대한 더 깊은 이해를 얻으려면 Kubernetes Ingress 컨트롤러 및 구성에 초점을 맞춘 전용 리소스 또는 랩을 탐색해 볼 수 있습니다.