티스토리 뷰

Server

Docker & Kubernetes 개념 총 정리 5

마시멜로co. 2025. 1. 15. 12:36

1. 스테이트 풀셋

스테이트 풀셋(StatefulSet)은 디플로이먼트 개념과 비슷합니다. 차이점은 디플로이먼트를 구성하는 각 파드는 서로 대체가 가능하지만, 스테이트 푸렛을 구성하는 파드들은 서로 동일한 스펙이더라도 각 파드마다 독자성을 유지하므로 대체 불가능합니다. 스테이트 풀셋은 파드들을 관리하는데 사용하는 워크로드 API 오브젝트입니다. 워크로드란 쿠버네티스에서 구동되는 애플리케이션을 의미합니다. 스트레이 풀셋은 파드들이 동일한 스펙으로 생성되었더라도 각 파드들은 서로 교체 될 수가 없습니다. 또한 각 파드는 영구적인 식별자를 가지는데 이는 스케쥴링을 다시 할때도 유지됩니다.

 

헤드리스 서비스(Headless Service)는 파드들의 개별 네트워크를 식별하기 위해 필요한 서비스입니다. 헤드리스 서비스의 특징은 ClusterIP가 없는 것입니다.

 

헤드리스 서비스를 생성하는 yaml 파일을 생성합니다.

user@myserver01:/home/work$ sudo mkdir ch12
user@myserver01:/home/work$ cd ch12
user@myserver01:/home/work/ch12$ sudo vi stateful-service.yml
user@myserver01:/home/work/ch12$ kubectl apply -f stateful-service.yml

apiVersion: v1
kind: Service
metadata:
  name: sfs-service01
spec:
  selector:
    app.kubernetes.io/name: web-sfs01
  type: ClusterIP
  clusterIP: None
  ports:
  - protocol: TCP
    port: 80

 

web-sfs01 스테이트 풀셋과 연동합니다.

헤드리스 서비스는 ClusterIP이므로 타입은 ClsterIP로 지정하고 서비스 포트를 TCP 80으로 설정하였습니다.

 

 

서비스 실행 및 확인

user@myserver01:/home/work/ch12$ kubectl apply -f stateful-service.yml
service/sfs-service01 created
user@myserver01:/home/work/ch12$ kubectl get svc
NAME            TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
kubernetes      ClusterIP   10.96.0.1    <none>        443/TCP   44h
sfs-service01   ClusterIP   None         <none>        80/TCP    5s

 

스테이트 풀셋을 생성합니다.

user@myserver01:/home/work/ch12$ sudo vi statefulset-web01.yml
user@myserver01:/home/work/ch12$ kubectl apply -f statefulset-web01.yml
statefulset.apps/sfs-test01 created

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sfs-test01
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: web-sfs01
  serviceName: sfs-service01
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web-sfs01
    spec:
      containers:
      - name: nginx
        image: nginx:latest

 

서비스 실행 및 확인

user@myserver01:/home/work/ch12$ kubectl apply -f statefulset-web01.yml
statefulset.apps/sfs-test01 created
user@myserver01:/home/work/ch12$ kubectl get all
NAME               READY   STATUS              RESTARTS   AGE
pod/sfs-test01-0   1/1     Running             0          10s
pod/sfs-test01-1   0/1     ContainerCreating   0          7s

NAME                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1    <none>        443/TCP   44h
service/sfs-service01   ClusterIP   None         <none>        80/TCP    11m

NAME                          READY   AGE
statefulset.apps/sfs-test01   1/3     11s
user@myserver01:/home/work/ch12$ kubectl get pod -o wide
NAME           READY   STATUS    RESTARTS   AGE     IP                NODE         NOMINATED NODE   READINESS GATES
sfs-test01-0   1/1     Running   0          4m24s   192.168.131.7     myserver02   <none>           <none>
sfs-test01-1   1/1     Running   0          4m21s   192.168.149.156   myserver03   <none>           <none>
sfs-test01-2   1/1     Running   0          4m14s   192.168.143.131   myserver01   <none>           <none>

 

 

파드 갯수를 줄여서 어떤 파드가 삭제되는지 확인합니다.

user@myserver01:/home/work/ch12$ sudo cp statefulset-web01.yml statefulset-web02.yml
user@myserver01:/home/work/ch12$ sudo vi statefulset-web02.yml

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sfs-test01
spec:
  replicas: 2
  selector:
    matchLabels:
      app.kubernetes.io/name: web-sfs01
  serviceName: sfs-service01
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web-sfs01
    spec:
      containers:
      - name: nginx
        image: nginx:latest

user@myserver01:/home/work/ch12$ kubectl apply -f statefulset-web02.yml
statefulset.apps/sfs-test01 configured
user@myserver01:/home/work/ch12$ kubectl get all
NAME               READY   STATUS    RESTARTS   AGE
pod/sfs-test01-0   1/1     Running   0          14m
pod/sfs-test01-1   1/1     Running   0          14m
user@myserver01:/home/work/ch12$ kubectl get pod -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP                NODE         NOMINATED NODE   READINESS GATES
sfs-test01-0   1/1     Running   0          18m   192.168.131.7     myserver02   <none>           <none>
sfs-test01-1   1/1     Running   0          18m   192.168.149.156   myserver03   <none>           <none>


NAME                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1    <none>        443/TCP   44h
service/sfs-service01   ClusterIP   None         <none>        80/TCP    26m

NAME                          READY   AGE
statefulset.apps/sfs-test01   2/2     14m

 

가장 최근에 생성한 파드가 삭제된 것을 확인합니다.

 

스테이트 풀셋을 이용하여 실행한 파드에 접속해 웹페이지에 접속해보겠습니다.

접속 테스트를 위한 Nginx파드를 생성합니다.

user@myserver01:/home/work/ch12$ sudo vi nginx-test01.yml
apiVersion: v1
kind: Pod
metadata:
  name: nginx01
spec:
  containers:
  - name: nginx-test01
    image: nginx:latest

user@myserver01:/home/work/ch12$ kubectl apply -f nginx-test01.yml
pod/nginx01 created
user@myserver01:/home/work/ch12$ kubectl get all
NAME               READY   STATUS              RESTARTS   AGE
pod/nginx01        0/1     ContainerCreating   0          5s
pod/sfs-test01-0   1/1     Running             0          48m
pod/sfs-test01-1   1/1     Running             0          48m

NAME                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1    <none>        443/TCP   45h
service/sfs-service01   ClusterIP   None         <none>        80/TCP    60m

NAME                          READY   AGE
statefulset.apps/sfs-test01   2/2     48m
user@myserver01:/home/work/ch12$ kubectl get pod -o wide
NAME           READY   STATUS    RESTARTS   AGE   IP                NODE         NOMINATED NODE   READINESS GATES
nginx01        1/1     Running   0          35s   192.168.131.8     myserver02   <none>           <none>
sfs-test01-0   1/1     Running   0          48m   192.168.131.7     myserver02   <none>           <none>
sfs-test01-1   1/1     Running   0          48m   192.168.149.156   myserver03   <none>           <none>
user@myserver01:/home/work/ch12$ kubectl exec -it nginx01 -- /bin/bash
root@nginx01:/# curl 192.168.131.7
<!DOCTYPE html>
<html>
<head>
<title>Welcome to nginx!</title>
<style>
html { color-scheme: light dark; }
body { width: 35em; margin: 0 auto;
font-family: Tahoma, Verdana, Arial, sans-serif; }
</style>
</head>
<body>
<h1>Welcome to nginx!</h1>
<p>If you see this page, the nginx web server is successfully installed and
working. Further configuration is required.</p>

<p>For online documentation and support please refer to
<a href="http://nginx.org/">nginx.org</a>.<br/>
Commercial support is available at
<a href="http://nginx.com/">nginx.com</a>.</p>

<p><em>Thank you for using nginx.</em></p>
</body>
</html>
root@nginx01:/# exit
exit

 

sfs-test01-0 파드의 주소로 접속하여 웹서비스를 이용해보았습니다

 

모두 종료합니다.

user@myserver01:/home/work/ch12$ kubectl delete pods --all
pod "nginx01" deleted
pod "sfs-test01-0" deleted
pod "sfs-test01-1" deleted
user@myserver01:/home/work/ch12$ kubectl delete services,statefulsets --all
service "kubernetes" deleted
service "sfs-service01" deleted
statefulset.apps "sfs-test01" deleted
user@myserver01:/home/work/ch12$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   7s

 

스테이트풀셋 볼륨을 생성합니다.

 

앞서 생성한 헤드리스 서비스를 실행합니다.

user@myserver01:/home/work/ch12$ kubectl apply -f stateful-service.yml
service/sfs-service01 created
user@myserver01:/home/work/ch12$ kubectl get all
NAME                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1    <none>        443/TCP   7m53s
service/sfs-service01   ClusterIP   None         <none>        80/TCP    6s

 

스테이트풀셋 볼륨이 사용할 볼륨을 생성하는 yaml파일을 생성합니다.

user@myserver01:/home/work/ch12$ sudo vi statefulset-vol01-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
  name: pv-sfs01
spec:
  accessModes:
  - ReadWriteOnce
  capacity:
    storage: 100Mi
  persistentVolumeReclaimPolicy: Retain
  storageClassName: pv-sfs-test01
  hostPath:
    path: /home/work
    type: DirectoryOrCreate

 

오브젝트 타입은 PersistentVolume 입니다.  오브젝트 볼륨명은 pv-sfs01입니다. 

PersistentVolume  볼륨 상태를 spec으로 정합니다.  accessModes를 설정합니다. ReadWriteOnce는 단하나의 노드만이 읽기, 쓰기를 위해 마운트하는 것을 의미합니다.

용량을 100메가바이트로 설정하였습니다.persistentVolumeClaim 는 pv와 pvc연결에 대한 정책을 결정하는 옵션입니다.

Retain은 PVC가 삭제되어도 PV 내부의 데이터는 유지하는 옵션입니다.

storageClassName을 설정합니다. 이때 설정하는 이름은 이후 작성할 PVC와 연결점이 됩니다.

볼륨타입은 hostPath입니다.

 

스테이트 풀셋을 생성하는 yaml을 생성합니다.

sudo vi statefulset-vol02.yml
apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: sfs-test01
spec:
  replicas: 1
  selector:
    matchLabels:
      app.kubernetes.io/name: web-sfs01
  serviceName: sfs-service01
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web-sfs01
    spec:
      containers:
      - name: nginx
        image: nginx:latest
        volumeMounts:
        - name: sfs-vol01
          mountPath: /mount01
  volumeClaimTemplates:
  - metadata:
      name: sfs-vol01
    spec:
      accessModes: ["ReadWriteOnce"]
      storageClassName: pv-sfs-test01
      resources:
        requests:
          storage: 20Mi

 

오브젝트 타입은 스테이트풀셋이며 StatefulSet 이름은 sfs-test01입니다.

matchLabels 로 스테이트풀셋이 관리할 앱을 설정합니다. 스테이트풀셋이 사용할 헤드리스 서비스를 serviceName로 정합니다.(sfs-service01)

입력모드는 "ReadWriteOnce"로 설정합니다. storageClassName 은  statefulset-vol01-pv.yml 의 storageClassName 과 동일해야합니다. 볼륨에 사용할 용량은 20메가바이트입니다.

 

볼륨파일 실행

user@myserver01:/home/work/ch12$ kubectl apply -f statefulset-vol01-pv.yml
persistentvolume/pv-sfs01 created
user@myserver01:/home/work/ch12$ kubectl get pv
NAME       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS    VOLUMEATTRIBUTESCLASS   REASON   AGE
pv-sfs01   100Mi      RWO            Retain           Available           pv-sfs-test01   <unset>                          9s

 

 

스테이트풀셋을 실행합니다.

user@myserver01:/home/work/ch12$ kubectl apply -f statefulset-vol02.yml
statefulset.apps/sfs-test01 created
user@myserver01:/home/work/ch12$ kubectl get all
NAME               READY   STATUS    RESTARTS   AGE
pod/sfs-test01-0   1/1     Running   0          6s

NAME                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1    <none>        443/TCP   55m
service/sfs-service01   ClusterIP   None         <none>        80/TCP    47m

NAME                          READY   AGE
statefulset.apps/sfs-test01   1/1     6s

 

정보 조회

user@myserver01:/home/work/ch12$ kubectl get pod,pv,pvc
NAME               READY   STATUS    RESTARTS   AGE
pod/sfs-test01-0   1/1     Running   0          72s

NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                            STORAGECLASS    VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pv-sfs01   100Mi      RWO            Retain           Bound    default/sfs-vol01-sfs-test01-0   pv-sfs-test01   <unset>                          5m4s

NAME                                           STATUS   VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS    VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/sfs-vol01-sfs-test01-0   Bound    pv-sfs01   100Mi      RWO            pv-sfs-test01   <unset>                 72s

 

 

스테이트 풀셋의 파드를 2개로 늘리는 소스를 생성합니다.

user@myserver01:/home/work/ch12$ sudo cp statefulset-vol02.yml  statefulset-vol03.yml
user@myserver01:/home/work/ch12$ sudo vi statefulset-vol03.yml
...생략
  replicas: 2

 

생성한 스테이트풀셋을 실행합니다.

user@myserver01:/home/work/ch12$ kubectl apply -f statefulset-vol03.yml
statefulset.apps/sfs-test01 configured
user@myserver01:/home/work/ch12$ kubectl get all
NAME               READY   STATUS    RESTARTS   AGE
pod/sfs-test01-0   1/1     Running   0          4m
pod/sfs-test01-1   0/1     Pending   0          6s

NAME                    TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes      ClusterIP   10.96.0.1    <none>        443/TCP   59m
service/sfs-service01   ClusterIP   None         <none>        80/TCP    51m

NAME                          READY   AGE
statefulset.apps/sfs-test01   1/2     4m
user@myserver01:/home/work/ch12$ kubectl get pod,pv,pvc
NAME               READY   STATUS    RESTARTS   AGE
pod/sfs-test01-0   1/1     Running   0          5m54s
pod/sfs-test01-1   0/1     Pending   0          2m

NAME                        CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM                            STORAGECLASS    VOLUMEATTRIBUTESCLASS   REASON   AGE
persistentvolume/pv-sfs01   100Mi      RWO            Retain           Bound    default/sfs-vol01-sfs-test01-0   pv-sfs-test01   <unset>                          9m46s

NAME                                           STATUS    VOLUME     CAPACITY   ACCESS MODES   STORAGECLASS    VOLUMEATTRIBUTESCLASS   AGE
persistentvolumeclaim/sfs-vol01-sfs-test01-0   Bound     pv-sfs01   100Mi      RWO            pv-sfs-test01   <unset>                 5m54s
persistentvolumeclaim/sfs-vol01-sfs-test01-1   Pending                                        pv-sfs-test01   <unset>                 2m

 

sfs-vol01-sfs-test01-0 의 상태는 정상이지만 sfs-vol01-sfs-test01-1 상태는 Pending 오류 상태입니다.

 

user@myserver01:/home/work/ch12$ kubectl describe pvc sfs-vol01-sfs-test01-1
Name:          sfs-vol01-sfs-test01-1
Namespace:     default
StorageClass:  pv-sfs-test01
Status:        Pending
Volume:
Labels:        app.kubernetes.io/name=web-sfs01
Annotations:   <none>
Finalizers:    [kubernetes.io/pvc-protection]
Capacity:
Access Modes:
VolumeMode:    Filesystem
Used By:       sfs-test01-1
Events:
  Type     Reason              Age                 From                         Message
  ----     ------              ----                ----                         -------
  Warning  ProvisioningFailed  1s (x13 over 3m1s)  persistentvolume-controller  storageclass.storage.k8s.io "pv-sfs-test01" not found

 

오류 원인은 "pv-sfs-test01" not found 으로 이미 sfs-vol01-sfs-test01-0 이 "pv-sfs-test01" 볼륨을 사용중이기때문에 사용불가한 것입니다.

 

모두 종료합니다.

user@myserver01:/home/work/ch12$ kubectl delete -f statefulset-vol03.yml
statefulset.apps "sfs-test01" deleted
user@myserver01:/home/work/ch12$ kubectl delete pv,pvc --all
persistentvolume "pv-sfs01" deleted
persistentvolumeclaim "sfs-vol01-sfs-test01-0" deleted
persistentvolumeclaim "sfs-vol01-sfs-test01-1" deleted
user@myserver01:/home/work/ch12$ kubectl delete -f stateful-service.yml
service "sfs-service01" deleted
user@myserver01:/home/work/ch12$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   79m

 

2. 인그레스

인그레스(Ingress)란 쿠버네티스 클러스터 외부에서 내부에 존재하는 쿠버네티스 서비스에 접근하기 위해 HTTP/HTTPS를 활용한 라우팅 규칙을 제공하는 오브젝트입니다. 인그레스를 활용하면 클러스터 내부에 존재하는 여러 서비스를 다수의 LoadBalancer 없이도 외부에 노출시킬수 있으므로 프로덕션 환경에서 유용하게 사용할 수 있습니다.

 

/test01로 접근하면 서비스1로 접근, /test02로 접근하면 서비스2로 연결시킵니다.

 

헬름Helm이라는 어플리케이션을 사용하여 인그레스를 실행해봅니다. 쿠버네티스 하나의 애플리케이션을 실행하기 위해 여러 리소스를 사용해야합니다. 즉 하나의 애플리케이션을 실행하려면 다수의 yaml파일을 관리해야하는데 이때 헬름을 사용하면 유용합니다. 헬름으로 쿠버네티스 클러스터에 애플리케이션 배포를 위해 필요한 파일들을 하나의 패키지 형태로 관리할 수 있기 때문입니다. 헬름은 리눅스 환경에서의 apt,yum과 비슷한 개념입니다. 헬름을 활용하면 yaml파일을 만들지 않더라도 쿠버네티스 환경에서 애플리케이션을 설치할 수 있습니다.

 

헬름 차트Helm Chart는 쿠버네티스 리소스를 생성하기 위해 필요한 파일을 모아놓은 디렉터리입니다. 

헬름 템플릿인 values,yaml 파일을 활용하면 설치에 필요한 여러 변수를 한번에 설정할 수 있고, 쿠버네티스 리소스를 최적화할 수 있습니다. 또한 헬름 리포지토리라는 다양한 헬름 차트를 저장 및 공유하는 저장소입니다. 

 

즉 헬름을 통해 쿠버네티스 애플리케이션을 설치한다는 말은 리포지토리에서 헬름 차트를 다운로드하고, 해당 디렉터리에 있는 파일을 수정해 자신의 환경에 맞게 최적화한 후 쿠버네티스 클러스터에 설치하는 것입니다. 

 

헬름을 설치하여 인그레스를 실행해봅니다. 헬름은 마스터 노드에만 설치하면 됩니다.

 

https://helm.sh/ko/docs/intro/install/ 

 

헬름 설치하기

헬름 설치하고 작동하는 방법 배우기.

helm.sh

 

user@myserver01:/home/work$ sudo mkdir helm
user@myserver01:/home/work$ cd helm/
user@myserver01:/home/work/helm$ sudo curl -fsSL -o get_helm.sh https://raw.githubusercontent.com/helm/helm/main/scripts/get-helm-3
user@myserver01:/home/work/helm$ sudo chmod 700 get_helm.sh
user@myserver01:/home/work/helm$ sudo ./get_helm.sh
Downloading https://get.helm.sh/helm-v3.16.4-linux-amd64.tar.gz
Verifying checksum... Done.
Preparing to install helm into /usr/local/bin
helm installed into /usr/local/bin/helm
user@myserver01:/home/work/helm$ helm version
version.BuildInfo{Version:"v3.16.4", GitCommit:"7877b45b63f95635153b29a42c0c2f4273ec45ca", GitTreeState:"clean", GoVersion:"go1.22.7"}
user@myserver01:/home/work/helm$

 

 

헬름 리포지토리 추가합니다. 리포지토리중 bitnami를 설치하겠습니다.

https://charts.bitnami.com/

 

Bitnami Helm Charts

The Bitnami Library for Kubernetes Popular applications, provided by Bitnami, ready to launch on Kubernetes using Kubernetes Helm. TL;DR $ helm repo add bitnami https://charts.bitnami.com/bitnami $ helm search repo bitnami $ helm install my-release bitnami

charts.bitnami.com

 

user@myserver01:/home/work/helm$ helm repo add bitnami https://charts.bitnami.com/bitnami
"bitnami" has been added to your repositories

 

설치 후 헬름 업데이트 

user@myserver01:/home/work/helm$ helm repo update
Hang tight while we grab the latest from your chart repositories...
...Successfully got an update from the "bitnami" chart repository
Update Complete. ⎈Happy Helming!⎈
user@myserver01:/home/work/helm$ helm repo list
NAME    URL
bitnami https://charts.bitnami.com/bitnami

 

헬름을 활용하여 nginx ingress controller를 설치합니다. nginx ingress contoller는 쿠버네티스 환경에서 트래픽을 관리할 수 있도록 도와주는 애플리케이션입니다. 

user@myserver01:/home/work/nginx-ingress-controller$ sudo -i
root@myserver01:/home/work$ mkdir nginx-ingress-controller
root@myserver01:/home/work$ cd nginx-ingress-controller/
root@myserver01:/home/work/nginx-ingress-controller$ helm search repo nginx
NAME                                    CHART VERSION   APP VERSION     DESCRIPTION
bitnami/nginx                           18.3.5          1.27.3          NGINX Open Source is a web server that can be a...
bitnami/nginx-ingress-controller        11.6.4          1.12.0          NGINX Ingress Controller is an Ingress controll...
bitnami/nginx-intel                     2.1.15          0.4.9           DEPRECATED NGINX Open Source for Intel is a lig...

root@myserver01:/home/work/nginx-ingress-controller# helm pull bitnami/nginx-ingress-controller
root@myserver01:/home/work/nginx-ingress-controller# ls
nginx-ingress-controller-11.6.4.tgz
root@myserver01:/home/work/nginx-ingress-controller# tar xvfz nginx-ingress-controller-11.6.4.tgz
..생략..
root@myserver01:/home/work/nginx-ingress-controller# ls
nginx-ingress-controller  nginx-ingress-controller-11.6.4.tgz
root@myserver01:/home/work/nginx-ingress-controller# mv nginx-ingress-controller  nginx-ingress-controller-11.6.4
root@myserver01:/home/work/nginx-ingress-controller# ls
nginx-ingress-controller-11.6.4  nginx-ingress-controller-11.6.4.tgz

root@myserver01:/home/work/nginx-ingress-controller# cd nginx-ingress-controller-11.6.4/
root@myserver01:/home/work/nginx-ingress-controller/nginx-ingress-controller-11.6.4# ls
Chart.lock  charts  Chart.yaml  README.md  templates  values.yaml
root@myserver01:/home/work/nginx-ingress-controller/nginx-ingress-controller-11.6.4# cp values.yaml my-values.yaml
root@myserver01:/home/work/nginx-ingress-controller/nginx-ingress-controller-11.6.4# ls
Chart.lock  charts  Chart.yaml  my-values.yaml  README.md  templates  values.yaml

 

지금부터 설치할  nginx ingress contoller는 새로운 네임스페이스에 설치합니다. 각 애플리케이션의 용도에 맞추어 전용 네임스페이스를 통해 관리하겠습니다.

 

현재 네임스페이스를 확인합니다.

root@myserver01:/home/work/nginx-ingress-controller/nginx-ingress-controller-11.6.4# exit
logout
user@myserver01:/home/work/nginx-ingress-controller$ kubectl get namespace
NAME               STATUS   AGE
calico-apiserver   Active   24h
calico-system      Active   24h
default            Active   2d
kube-flannel       Active   47h
kube-node-lease    Active   2d
kube-public        Active   2d
kube-system        Active   2d
tigera-operator    Active   24h

 

다른 오브젝트와 구분하기 위해 default 네임스페이스가 아니라 새로운 네임스페이스를 추가합니다.

user@myserver01:/home/work/nginx-ingress-controller$ cd nginx-ingress-controller-11.6.4/
user@myserver01:/home/work/nginx-ingress-controller/nginx-ingress-controller-11.6.4$ kubectl create namespace mynginx
namespace/mynginx created
user@myserver01:/home/work/nginx-ingress-controller/nginx-ingress-controller-11.6.4$ kubectl get namespace
NAME               STATUS   AGE
calico-apiserver   Active   24h
calico-system      Active   24h
default            Active   2d
kube-flannel       Active   47h
kube-node-lease    Active   2d
kube-public        Active   2d
kube-system        Active   2d
mynginx            Active   26s
tigera-operator    Active   24h

 

nginx-ingress-controller를 설치합니다

user@myserver01:/home/work/nginx-ingress-controller/nginx-ingress-controller-11.6.4$  helm install --namespace mynginx --generate-name bitnami/nginx-ingress-controller -f my-values.yaml
NAME: nginx-ingress-controller-1736921098
LAST DEPLOYED: Wed Jan 15 06:05:03 2025
NAMESPACE: mynginx
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
CHART NAME: nginx-ingress-controller
..생략..

 

--namespace 옵션은 nginx-ingress-controller 가 설치될 네임스페이스 지정할 수 있는 옵션입니다.

--generate-name 옵션은 적절한 이름을 랜덤하게 생성해주는 옵션입니다. 앞서 생성한 my-values.yaml 파일을 활용해 설치합니다. 

 

$ kubectl get all --namespace mynginx

 

 

 

mynginx 네임스페이스에서 정상 실행 중인 것을 확인합니다. 그런데 nginx-ingress-controller 를 외부에서 접근할 수 있는 EXTERNAL-IP가 Pending인 것으로 나옵니다. 이것은 IP가 할당받지 못했음을 의미합니다. 이를 해결하기 위해 metallb을 설치함으로써 service/nginx-ingress-controller-1736921098에 EXTERNAL-IP를 할당하겠습니다. 

 

위에서 실행한 방법들은 쿠버네티스 내부에서 생성한 인그레스를 외부로 노출시키는 과정에서 IP주소를 할당해서 노출시키는 경우입니다. 이번에는 온프레미스 On-Premise 상황에서 자체 LoadBalancer를 생성해 자동으로 nginx-ingress-controller에 IP를 부여할 수 있도록 하겠습니다.

 

kube-proxy의 strictARP를 확인합니다. 

user@myserver01:~$ kubectl get configmap kube-proxy -n kube-system -o yaml | grep strictARP
      strictARP: false

 

만약 strictARP 모드가 false이면 true로 변경합니다.

user@myserver01:~$ kubectl get configmap kube-proxy -n kube-system -o yaml | sed -e "s/strictARP: false/strictARP: true/" | kubectl apply -f - -n kube-system
Warning: resource configmaps/kube-proxy is missing the kubectl.kubernetes.io/last-applied-configuration annotation which is required by kubectl apply. kubectl apply should only be used on resources created declaratively by either kubectl create --save-config or kubectl apply. The missing annotation will be patched automatically.
configmap/kube-proxy configured

 

변경된 내용 확인

user@myserver01:~$  kubectl get configmap kube-proxy -n kube-system -o yaml | grep strictARP
      strictARP: true
      {"apiVersion":"v1","data":{"config.conf":"apiVersion: kubeproxy.config.k8s.io/v1alpha1\nbindAddress: 0.0.0.0\nbindAddressHardFail: false\nclientConnection:\n  acceptContentTypes: \"\"\n  burst: 0\n  contentType: \"\"\n  kubeconfig: /
      ..생략..

 

metallb 설치

https://metallb.io/installation/

 

Installation :: MetalLB, bare metal load-balancer for Kubernetes

Before starting with installation, make sure you meet all the requirements. In particular, you should pay attention to network addon compatibility. If you’re trying to run MetalLB on a cloud platform, you should also look at the cloud compatibility page

metallb.io

user@myserver01:/home/work$ sudo mkdir metallb
user@myserver01:/home/work$ cd metallb/
user@myserver01:/home/work/metallb$ sudo -i
root@myserver01:~# cd /home/work/metallb/
root@myserver01:/home/work/metallb#  helm pull metallb/metallb
Error: repo metallb not found
root@myserver01:/home/work/metallb# helm repo add metallb https://metallb.github.io/metallb
"metallb" has been added to your repositories
root@myserver01:/home/work/metallb#  helm search repo metallb
NAME            CHART VERSION   APP VERSION     DESCRIPTION
bitnami/metallb 6.4.2           0.14.9          MetalLB is a load-balancer implementation for b...
metallb/metallb 0.14.9          v0.14.9         A network load-balancer implementation for Kube...
root@myserver01:/home/work/metallb#  helm pull metallb/metallb
root@myserver01:/home/work/metallb# ls
metallb-0.14.9.tgz
root@myserver01:/home/work/metallb# tar xvfz metallb-0.14.9.tgz
metallb/Chart.yaml
metallb/Chart.lock
metallb/values.yaml
..생략..

root@myserver01:/home/work/metallb# ls
metallb  metallb-0.14.9.tgz
root@myserver01:/home/work/metallb# mv metallb metallb-0.14.9
root@myserver01:/home/work/metallb# ls
metallb-0.14.9  metallb-0.14.9.tgz
root@myserver01:/home/work/metallb# cd metallb-0.14.9/
root@myserver01:/home/work/metallb/metallb-0.14.9# ls
Chart.lock  charts  Chart.yaml  policy  README.md  templates  values.schema.json  values.yaml
root@myserver01:/home/work/metallb/metallb-0.14.9# cp values.yaml my-values.yaml
root@myserver01:/home/work/metallb/metallb-0.14.9# ls
Chart.lock  charts  Chart.yaml  my-values.yaml  policy  README.md  templates  values.schema.json  values.yaml
root@myserver01:/home/work/metallb/metallb-0.14.9# exit
logout

 

 

네임스페이스를 생성합니다.

user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl create namespace mymetallb
namespace/mymetallb created
user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl get namespace
NAME               STATUS   AGE
calico-apiserver   Active   25h
calico-system      Active   25h
default            Active   2d
kube-flannel       Active   2d
kube-node-lease    Active   2d
kube-public        Active   2d
kube-system        Active   2d
mymetallb          Active   10s
mynginx            Active   34m
tigera-operator    Active   25h

 

헬름을 활용하여 metallb를 설치합니다.

user@myserver01:/home/work/metallb/metallb-0.14.9$ helm install --namespace mymetallb --generate-name metallb/metallb -f my-values.yaml
NAME: metallb-1736923135
LAST DEPLOYED: Wed Jan 15 06:38:56 2025
NAMESPACE: mymetallb
STATUS: deployed
REVISION: 1
TEST SUITE: None
NOTES:
MetalLB is now running in the cluster.

Now you can configure it via its CRs. Please refer to the metallb official docs
on how to use the CRs.
user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl get all --namespace mymetallb
NAME                                                 READY   STATUS     RESTARTS   AGE
pod/metallb-1736923135-controller-5d7dd5db77-8bkwf   0/1     Running    0          19s
pod/metallb-1736923135-speaker-8bp56                 0/4     Init:0/3   0          19s
pod/metallb-1736923135-speaker-kc846                 0/4     Init:0/3   0          19s
pod/metallb-1736923135-speaker-vf27t                 0/4     Init:0/3   0          19s

NAME                              TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/metallb-webhook-service   ClusterIP   10.98.156.54   <none>        443/TCP   19s

NAME                                        DESIRED   CURRENT   READY   UP-TO-DATE   AVAILABLE   NODE SELECTOR            AGE
daemonset.apps/metallb-1736923135-speaker   3         3         0       3            0           kubernetes.io/os=linux   19s

NAME                                            READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/metallb-1736923135-controller   0/1     1            0           19s

NAME                                                       DESIRED   CURRENT   READY   AGE
replicaset.apps/metallb-1736923135-controller-5d7dd5db77   1         1         0       19s

 

kubectl get configmap 명령어를 사용하여 metallb를 설치합니다. configmap 은 설정을 키-값 형태로 저장하는 데 사용하는 API 오브젝트입니다. 

 

ip 설정파일을 추가합니다.

user@myserver01:/home/work/metallb/metallb-0.14.9$ sudo vi my-config.yaml

---
apiVersion: metallb.io/v1beta1
kind: IPAddressPool
metadata:
  name: my-metallb-config
  namespace: mymetallb
spec:
  addresses:
  - 10.0.2.20-10.0.2.40
  autoAssign: true
---
apiVersion: metallb.io/v1beta1
kind: L2Advertisement
metadata:
  name: my-metallb-config
  namespace: mymetallb
spec:
  ipAddressPools:
    - my-metallb-config

 

IP 범위를 설정하지만 myserver01,myserver02,myserver03을 포함하지 않는 10.0.2.20-10.0.2.40 범위로 설정합니다.

 

실행 후 확인합니다.

user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl apply -f my-config.yaml
ipaddresspool.metallb.io/my-metallb-config created
l2advertisement.metallb.io/my-metallb-config created
user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl get ipaddresspool.metallb.io --namespace mymetallb
NAME                AUTO ASSIGN   AVOID BUGGY IPS   ADDRESSES
my-metallb-config   true          false             ["10.0.2.20-10.0.2.40"]

 

my-metallb-config 정보 확인

user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl describe  ipaddresspool.metallb.io my-metallb-config --namespace mymetallb
Name:         my-metallb-config
Namespace:    mymetallb
Labels:       <none>
Annotations:  <none>
API Version:  metallb.io/v1beta1
Kind:         IPAddressPool
Metadata:
  Creation Timestamp:  2025-01-15T07:00:34Z
  Generation:          1
  Resource Version:    133105
  UID:                 97cedd09-e85b-4341-8f8e-e231cd6128fa
Spec:
  Addresses:
    10.0.2.20-10.0.2.40
  Auto Assign:       true
  Avoid Buggy I Ps:  false
Events:              <none>

 

mynginx 네임스페이스에 존재하는 오브젝트를 확인합니다.

user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl get all --namespace mynginx
NAME                                                                  READY   STATUS    RESTARTS   AGE
pod/nginx-ingress-controller-1736921098-75c7fbb599-cxq52              1/1     Running   0          60m
pod/nginx-ingress-controller-1736921098-default-backend-869c8fdc7dt   1/1     Running   0          60m

NAME                                                          TYPE           CLUSTER-IP       EXTERNAL-IP   PORT(S)                      AGE
service/nginx-ingress-controller-1736921098                   LoadBalancer   10.101.166.160   10.0.2.20     80:30629/TCP,443:30274/TCP   60m
service/nginx-ingress-controller-1736921098-default-backend   ClusterIP      10.103.88.142    <none>        80/TCP                       60m

NAME                                                                  READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/nginx-ingress-controller-1736921098                   1/1     1            1           60m
deployment.apps/nginx-ingress-controller-1736921098-default-backend   1/1     1            1           60m

NAME                                                                             DESIRED   CURRENT   READY   AGE
replicaset.apps/nginx-ingress-controller-1736921098-75c7fbb599                   1         1         1       60m
replicaset.apps/nginx-ingress-controller-1736921098-default-backend-869c8f7bc8   1         1         1       60m

 

 

서비스 영역에서 nginx-ingress-controller에 CLUSTER-IP가 10.0.2.20으로 설정되어 있는 것을 확인했습니다.

 

nginx-ingress-controller 정보를 확인합니다.

user@myserver01:/home/work/metallb/metallb-0.14.9$ kubectl describe service/nginx-ingress-controller-1736921098 --namespace mynginx
Name:                     nginx-ingress-controller-1736921098
Namespace:                mynginx
Labels:                   app.kubernetes.io/component=controller
                          app.kubernetes.io/instance=nginx-ingress-controller-1736921098
                          app.kubernetes.io/managed-by=Helm
                          app.kubernetes.io/name=nginx-ingress-controller
                          app.kubernetes.io/version=1.12.0
                          helm.sh/chart=nginx-ingress-controller-11.6.4
Annotations:              meta.helm.sh/release-name: nginx-ingress-controller-1736921098
                          meta.helm.sh/release-namespace: mynginx
                          metallb.io/ip-allocated-from-pool: my-metallb-config
Selector:                 app.kubernetes.io/component=controller,app.kubernetes.io/instance=nginx-ingress-controller-1736921098,app.kubernetes.io/name=nginx-ingress-controller
Type:                     LoadBalancer
IP Family Policy:         SingleStack
IP Families:              IPv4
IP:                       10.101.166.160
IPs:                      10.101.166.160
LoadBalancer Ingress:     10.0.2.20 (VIP)
Port:                     http  80/TCP
TargetPort:               http/TCP
NodePort:                 http  30629/TCP
Endpoints:                192.168.131.11:8080
Port:                     https  443/TCP
TargetPort:               https/TCP
NodePort:                 https  30274/TCP
Endpoints:                192.168.131.11:8443
Session Affinity:         None
External Traffic Policy:  Cluster
Internal Traffic Policy:  Cluster
Events:
  Type    Reason        Age    From                Message
  ----    ------        ----   ----                -------
  Normal  IPAllocated   8m14s  metallb-controller  Assigned IP ["10.0.2.20"]
  Normal  nodeAssigned  8m14s  metallb-speaker     announcing from node "myserver02" with protocol "layer2"

 

인그레스를 통해 외부에 포트를 열어주기 위해 포트포워딩 설정을 합니다.

 

 

인그레스를 활용하여 하나의 서비스를 배포하겠습니다.

 

디플로이먼트 파일을 생성합니다.

user@myserver01:/home/work$ sudo mkdir ch13
user@myserver01:/home/work$ cd ch13
user@myserver01:/home/work/ch13$ sudo vi ingress01-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-deploy-test01
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: web-deploy01
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web-deploy01
    spec:
      containers:
      - name: nginx
        image: nginx:1.25

 

selector를 활용하여 디플로이먼트가 관리할 파드를 연결할 수 있습니다. selector는 파드에 라벨을 붙이는 옵션입니다.

spec으로 파드 정보를 입력합니다.

 

서비스를 생성하기 위한 yaml파일을 생성합니다.

user@myserver01:/home/work/ch13$ sudo vi ingress01-service.yml

apiVersion: v1
kind: Service
metadata:
  name: ingress-service-test01
spec:
  selector:
    app.kubernetes.io/name: web-deploy01
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

 

ingress01-deploy.yml 파일에서 생성한 web-deploy01앱과 연동합니다.

서비스타입은 ClusterIP로 지정하였습니다. 해당서비스를 사용하기 위한 포트는 80포트입니다. 파드가 받게 될 포트인 targetPort를 80으로 설정하였습니다.

 

인그레스를 생성하는 yaml파일을 생성합니다.

user@myserver01:/home/work/ch13$ sudo vi ingress01-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test01
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /test01
        pathType: Prefix
        backend:
          service:
            name: ingress-service-test01
            port:
              number: 80

 

인그레스를 생성하려면 버전을 networking.k8s.io/v1으로 설정하여야합니다.

annotations는 인그레스 컨트롤러에 대해 옵션을 설정할 때 쓰는 항목입니다. nginx.ingress.kubernetes.io/rewrite-target: / 로 설정하면, 이후 URL 접근경로를 루트 경로로 바꾸는 옵션입니다. 예를 들어 URL창에서는 /test01로 접근하지만 실제 접근 경로는 / 를 의미합니다.

인그레스클레스이름은 $ kubectl get ingressclass 로 입력했을때 나오는 이름과 동일하게 설정합니다.

rules로 규칙을 설정하며 http를 사용합니다. pathType은 앞서 설정한 경로를 인식하는 방식을 정하는 옵션입니다. Prefix는 경로의 접두사가 일치하면 해당 경로가 적용하는 방식입니다. PathType:Exact로 설정하면 경로가 정확히 일치해야 인식합니다. backend: 옵션으로 백엔드를 설정합니다. 인그레스에 연동할 서비스를 등록합니다. (ingress-service-test01)

 

 

오브젝트를 실행합니다.

user@myserver01:/home/work/ch13$ kubectl apply -f ingress01-deploy.yml
deployment.apps/ingress-deploy-test01 created
user@myserver01:/home/work/ch13$ kubectl get all
NAME                                        READY   STATUS              RESTARTS   AGE
pod/ingress-deploy-test01-8d74cdb6b-444n5   0/1     ContainerCreating   0          5s
pod/ingress-deploy-test01-8d74cdb6b-8z9qb   0/1     ContainerCreating   0          5s
pod/ingress-deploy-test01-8d74cdb6b-cjfxz   0/1     ContainerCreating   0          5s

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

NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-deploy-test01   0/3     3            0           6s

NAME                                              DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-deploy-test01-8d74cdb6b   3         3         0       6s
user@myserver01:/home/work/ch13$ kubectl apply -f ingress01-service.yml
service/ingress-service-test01 created
user@myserver01:/home/work/ch13$ kubectl get service
NAME                     TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)   AGE
ingress-service-test01   ClusterIP   10.106.68.236   <none>        80/TCP    8s
kubernetes               ClusterIP   10.96.0.1       <none>        443/TCP   3h54m
user@myserver01:/home/work/ch13$ kubectl apply -f ingress01-ingress.yml
ingress.networking.k8s.io/ingress-test01 created
user@myserver01:/home/work/ch13$ kubectl get ingress
NAME             CLASS   HOSTS   ADDRESS   PORTS   AGE
ingress-test01   nginx   *                 80      8s

 

접속 확인

 

모두 종료합니다.

user@myserver01:/home/work/ch13$ kubectl delete -f ingress01-ingress.yml
ingress.networking.k8s.io "ingress-test01" deleted
user@myserver01:/home/work/ch13$ kubectl delete -f ingress01-service.yml
service "ingress-service-test01" deleted
user@myserver01:/home/work/ch13$ kubectl delete -f ingress01-deploy.yml
deployment.apps "ingress-deploy-test01" deleted
user@myserver01:/home/work/ch13$ kubectl get ingress
No resources found in default namespace.

 

 

인그레스로 웹서비스를 2개 배포합니다.

user@myserver01:/home/work$ sudo cp -r ch13 ch14
user@myserver01:/home/work$ cd ch14
user@myserver01:/home/work/ch14$ ls
ingress01-deploy.yml  ingress01-ingress.yml  ingress01-service.yml
user@myserver01:/home/work/ch14$ sudo cp ingress01-deploy.yml ingress02-deploy.yml
user@myserver01:/home/work/ch14$ sudo vi ingress02-deploy.yml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ingress-deploy-test02
spec:
  replicas: 3
  selector:
    matchLabels:
      app.kubernetes.io/name: web-deploy02
  template:
    metadata:
      labels:
        app.kubernetes.io/name: web-deploy02
    spec:
      containers:
      - name: nginx
        image: nginx:1.25

user@myserver01:/home/work/ch14$ sudo cp ingress01-service.yml ingress02-service.yml
user@myserver01:/home/work/ch14$ sudo vi ingress02-service.yml
apiVersion: v1
kind: Service
metadata:
  name: ingress-service-test02
spec:
  selector:
    app.kubernetes.io/name: web-deploy02
  type: ClusterIP
  ports:
  - protocol: TCP
    port: 80
    targetPort: 80

user@myserver01:/home/work/ch14$ sudo cp ingress01-ingress.yml ingress02-ingress.yml
user@myserver01:/home/work/ch14$ sudo vi ingress02-ingress.yml
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
  name: ingress-test02
  annotations:
    nginx.ingress.kubernetes.io/rewrite-target: /
spec:
  ingressClassName: nginx
  rules:
  - http:
      paths:
      - path: /test01
        pathType: Prefix
        backend:
          service:
            name: ingress-service-test01
            port:
              number: 80
      - path: /test02
        pathType: Prefix
        backend:
          service:
            name: ingress-service-test02
            port:
              number: 80

 

 

디플로이먼트와 서비스를 실행합니다.

user@myserver01:/home/work/ch14$ kubectl apply -f ingress01-deploy.yml
deployment.apps/ingress-deploy-test01 created
user@myserver01:/home/work/ch14$ kubectl apply -f ingress01-service.yml
service/ingress-service-test01 created
user@myserver01:/home/work/ch14$ kubectl apply -f ingress02-deploy.yml
deployment.apps/ingress-deploy-test02 created
user@myserver01:/home/work/ch14$ kubectl apply -f ingress02-service.yml
service/ingress-service-test02 created
user@myserver01:/home/work/ch14$ kubectl get all
NAME                                         READY   STATUS    RESTARTS   AGE
pod/ingress-deploy-test01-8d74cdb6b-2wccp    1/1     Running   0          50s
pod/ingress-deploy-test01-8d74cdb6b-44ql9    1/1     Running   0          50s
pod/ingress-deploy-test01-8d74cdb6b-bpn62    1/1     Running   0          50s
pod/ingress-deploy-test02-69cd9c9c55-2ghxg   1/1     Running   0          16s
pod/ingress-deploy-test02-69cd9c9c55-k7vvp   1/1     Running   0          16s
pod/ingress-deploy-test02-69cd9c9c55-x9v7h   1/1     Running   0          16s

NAME                             TYPE        CLUSTER-IP     EXTERNAL-IP   PORT(S)   AGE
service/ingress-service-test01   ClusterIP   10.97.77.81    <none>        80/TCP    40s
service/ingress-service-test02   ClusterIP   10.107.224.5   <none>        80/TCP    10s
service/kubernetes               ClusterIP   10.96.0.1      <none>        443/TCP   4h8m

NAME                                    READY   UP-TO-DATE   AVAILABLE   AGE
deployment.apps/ingress-deploy-test01   3/3     3            3           50s
deployment.apps/ingress-deploy-test02   3/3     3            3           16s

NAME                                               DESIRED   CURRENT   READY   AGE
replicaset.apps/ingress-deploy-test01-8d74cdb6b    3         3         3       50s
replicaset.apps/ingress-deploy-test02-69cd9c9c55   3         3         3       16s

 

 

인그레스 파일을 실행합니다.

user@myserver01:/home/work/ch14$ kubectl apply -f ingress02-ingress.yml
ingress.networking.k8s.io/ingress-test02 created
user@myserver01:/home/work/ch14$ kubectl get ingress
NAME             CLASS   HOSTS   ADDRESS    PORTS   AGE
ingress-test02   nginx   *       10.0.2.5   80      26s

 

http://127.0.0.1:2000/test01

 

http://127.0.0.1:2000/test02

 

모두 종료합니다.

user@myserver01:/home/work/ch14$ kubectl delete -f ingress02-ingress.yml
ingress.networking.k8s.io "ingress-test02" deleted
user@myserver01:/home/work/ch14$ kubectl delete -f ingress01-service.yml
service "ingress-service-test01" deleted
user@myserver01:/home/work/ch14$ kubectl delete -f ingress02-service.yml
service "ingress-service-test02" deleted
user@myserver01:/home/work/ch14$ kubectl delete -f ingress01-deploy.yml
deployment.apps "ingress-deploy-test01" deleted
user@myserver01:/home/work/ch14$ kubectl delete -f ingress02-deploy.yml
deployment.apps "ingress-deploy-test02" deleted
user@myserver01:/home/work/ch14$ kubectl get ingress
No resources found in default namespace.
user@myserver01:/home/work/ch14$ kubectl get all
NAME                 TYPE        CLUSTER-IP   EXTERNAL-IP   PORT(S)   AGE
service/kubernetes   ClusterIP   10.96.0.1    <none>        443/TCP   4h15m

 

 

3. 잡과 크론잡

 쿠버네티스 잡이란 쿠버네티스 애플리케이션의 실행 및 종료에 초점을 맞춘 리소스 유형입니다. 쿠버네티스에서 잡을 활용하면, 파드를 생성하고 지정된 수의 파드가 성공적으로 종료될 때까지 계속해서 파드의 실행을 재시도합니다. 그리고 지정된 수의 성공 완료 횟수에 도달하면 잡이 종료됩니다. 

쿠버네티스 크론잡은 반복일정에 따라 잡을 만듭니다. 리눅스에서의 크론탭과 비슷합니다.

 

잡을 생성하는 yaml파일을 생성합니다.

user@myserver01:/home/work$ sudo mkdir ch15
user@myserver01:/home/work$ cd ch15
user@myserver01:/home/work/ch15$ sudo vi job-cronjob01.yml
apiVersion: batch/v1
kind: Job
metadata:
  name: job-test01
spec:
  template:
    spec:
      containers:
      - name: nginx-test01
        image: nginx:1.25
        command: ["echo", "Hello, Kubernetes!"]
      restartPolicy: Never
  backoffLimit: 3

 

잡의 이름은 job-test01입니다. spec 으로 잡의 내부 상태를 설정합니다.  command로 job을 통해 입력할 명령어를 입력합니다.  restartPolicy로 재시작 정책을 정합니다.  backoffLimit은 잡 실행에 실패할 경우 재시도 횟수를 의미합니다.

 

잡을 실행합니다.

user@myserver01:/home/work/ch15$ kubectl apply -f job-cronjob01.yml
job.batch/job-test01 created
user@myserver01:/home/work/ch15$ kubectl get job
NAME         STATUS     COMPLETIONS   DURATION   AGE
job-test01   Complete   1/1           4s         5s
user@myserver01:/home/work/ch15$ kubectl describe job job-test01
Name:             job-test01
Namespace:        default
Selector:         batch.kubernetes.io/controller-uid=e37e3062-1313-4560-a862-f08030708af4
Labels:           batch.kubernetes.io/controller-uid=e37e3062-1313-4560-a862-f08030708af4
                  batch.kubernetes.io/job-name=job-test01
                  controller-uid=e37e3062-1313-4560-a862-f08030708af4
                  job-name=job-test01
Annotations:      <none>
Parallelism:      1
Completions:      1
Completion Mode:  NonIndexed
Suspend:          false
Backoff Limit:    3
Start Time:       Wed, 15 Jan 2025 08:10:48 +0000
Completed At:     Wed, 15 Jan 2025 08:10:52 +0000
Duration:         4s
Pods Statuses:    0 Active (0 Ready) / 1 Succeeded / 0 Failed
Pod Template:
  Labels:  batch.kubernetes.io/controller-uid=e37e3062-1313-4560-a862-f08030708af4
           batch.kubernetes.io/job-name=job-test01
           controller-uid=e37e3062-1313-4560-a862-f08030708af4
           job-name=job-test01
  Containers:
   nginx-test01:
    Image:      nginx:1.25
    Port:       <none>
    Host Port:  <none>
    Command:
      echo
      Hello, Kubernetes!
    Environment:   <none>
    Mounts:        <none>
  Volumes:         <none>
  Node-Selectors:  <none>
  Tolerations:     <none>
Events:
  Type    Reason            Age   From            Message
  ----    ------            ----  ----            -------
  Normal  SuccessfulCreate  47s   job-controller  Created pod: job-test01-8wh8p
  Normal  Completed         43s   job-controller  Job completed
user@myserver01:/home/work/ch15$ kubectl logs job-test01-8wh8p
Hello, Kubernetes!

 

정상 실행 확인 후 모두 종료합니다.

user@myserver01:/home/work/ch15$ kubectl delete -f job-cronjob01.yml
job.batch "job-test01" deleted

 

크론잡을 생성하는 yaml파일을 작성합니다.

user@myserver01:/home/work$ sudo mkdir ch15
user@myserver01:/home/work$ cd ch15
user@myserver01:/home/work/ch15$ sudo vi job-cronjob01.yml

apiVersion: batch/v1
kind: CronJob
metadata:
  name: cronjob-test02
spec:
  schedule: "*/1 * * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: nginx-test02
            image: nginx:1.25
            command:
            - /bin/sh
            - -c
            - echo Hello Kubernetes!
          restartPolicy: Never

 

크론잡의 스케쥴은 1분에 1번씩 실행하는 것을 의미합니다. 텍스트를 출력하는 명령어를 생성하였습니다.

 

실행합니다.

user@myserver01:/home/work/ch16$ kubectl apply -f job-cronjob02.yml
cronjob.batch/cronjob-test02 created
user@myserver01:/home/work/ch16$ kubectl get cronjob
NAME             SCHEDULE      TIMEZONE   SUSPEND   ACTIVE   LAST SCHEDULE   AGE
cronjob-test02   */1 * * * *   <none>     False     0        <none>          9s
user@myserver01:/home/work/ch16$ kubectl describe cronjob cronjob-test02
Name:                          cronjob-test02
Namespace:                     default
Labels:                        <none>
Annotations:                   <none>
Schedule:                      */1 * * * *
Concurrency Policy:            Allow
Suspend:                       False
Successful Job History Limit:  3
Failed Job History Limit:      1
Starting Deadline Seconds:     <unset>
Selector:                      <unset>
Parallelism:                   <unset>
Completions:                   <unset>
Pod Template:
  Labels:  <none>
  Containers:
   nginx-test02:
    Image:      nginx:1.25
    Port:       <none>
    Host Port:  <none>
    Command:
      /bin/sh
      -c
      echo Hello Kubernetes!
    Environment:     <none>
    Mounts:          <none>
  Volumes:           <none>
  Node-Selectors:    <none>
  Tolerations:       <none>
Last Schedule Time:  <unset>
Active Jobs:         <none>
Events:              <none>

 

아직 이벤트가 발생하지 않아 몇분 후 확인합니다.

user@myserver01:/home/work/ch16$ kubectl describe cronjob cronjob-test02
Name:                          cronjob-test02
Namespace:                     default
Labels:                        <none>
Annotations:                   <none>
Schedule:                      */1 * * * *
Concurrency Policy:            Allow
Suspend:                       False
Successful Job History Limit:  3
Failed Job History Limit:      1
Starting Deadline Seconds:     <unset>
Selector:                      <unset>
Parallelism:                   <unset>
Completions:                   <unset>
Pod Template:
  Labels:  <none>
  Containers:
   nginx-test02:
    Image:      nginx:1.25
    Port:       <none>
    Host Port:  <none>
    Command:
      /bin/sh
      -c
      echo Hello Kubernetes!
    Environment:     <none>
    Mounts:          <none>
  Volumes:           <none>
  Node-Selectors:    <none>
  Tolerations:       <none>
Last Schedule Time:  Wed, 15 Jan 2025 08:21:00 +0000
Active Jobs:         <none>
Events:
  Type    Reason            Age                From                Message
  ----    ------            ----               ----                -------
  Normal  SuccessfulCreate  3m46s              cronjob-controller  Created job cronjob-test02-28948818
  Normal  SawCompletedJob   3m43s              cronjob-controller  Saw completed job: cronjob-test02-28948818, condition: Complete
  Normal  SuccessfulCreate  2m46s              cronjob-controller  Created job cronjob-test02-28948819
  Normal  SawCompletedJob   2m43s              cronjob-controller  Saw completed job: cronjob-test02-28948819, condition: Complete
  Normal  SuccessfulCreate  106s               cronjob-controller  Created job cronjob-test02-28948820
  Normal  SawCompletedJob   102s               cronjob-controller  Saw completed job: cronjob-test02-28948820, condition: Complete
  Normal  SuccessfulCreate  46s                cronjob-controller  Created job cronjob-test02-28948821
  Normal  SuccessfulDelete  43s                cronjob-controller  Deleted job cronjob-test02-28948818
  Normal  SawCompletedJob   43s (x2 over 43s)  cronjob-controller  Saw completed job: cronjob-test02-28948821, condition: Complete

 

메시지 확인 후 크론잡을 종료합니다.

user@myserver01:/home/work/ch16$ kubectl delete -f job-cronjob02.yml
cronjob.batch "cronjob-test02" deleted

 

다음글에서는 도커를 활용하여 웹서비스 배포를 해보겠습니다. 

최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크