Kubernetes 애플리케이션 노출하기

KubernetesBeginner
지금 연습하기

소개

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

이것은 가이드 실험입니다. 학습과 실습을 돕기 위한 단계별 지침을 제공합니다.각 단계를 완료하고 실무 경험을 쌓기 위해 지침을 주의 깊게 따르세요. 과거 데이터에 따르면, 이것은 초급 레벨의 실험이며 완료율은 95%입니다.학습자들로부터 99%의 긍정적인 리뷰율을 받았습니다.

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 컨트롤러 및 구성에 초점을 맞춘 전용 리소스 또는 랩을 탐색해 볼 수 있습니다.