티스토리 뷰
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 없이도 외부에 노출시킬수 있으므로 프로덕션 환경에서 유용하게 사용할 수 있습니다.
![](https://blog.kakaocdn.net/dn/cbpyrg/btsLNZuvSxu/CuooCYPoKHILLJAwekM1Wk/img.png)
/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를 설치하겠습니다.
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
![](https://blog.kakaocdn.net/dn/J1yLH/btsLNWdFd5r/XCzxUbQMzRHnZYtQBHuss1/img.png)
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"
인그레스를 통해 외부에 포트를 열어주기 위해 포트포워딩 설정을 합니다.
![](https://blog.kakaocdn.net/dn/bVsdns/btsLN9cNo0x/he0LcdskwKobnKte6r7pM0/img.png)
인그레스를 활용하여 하나의 서비스를 배포하겠습니다.
디플로이먼트 파일을 생성합니다.
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
접속 확인
![](https://blog.kakaocdn.net/dn/cBYFoW/btsLPtOKCsX/awpTmhjK88csu0Sk2RcrA1/img.png)
모두 종료합니다.
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
![](https://blog.kakaocdn.net/dn/4zGE2/btsLN4o99vv/HJgLEn3vuo0RosTJPkxqPk/img.png)
http://127.0.0.1:2000/test02
![](https://blog.kakaocdn.net/dn/H2wDx/btsLOLJqCJz/G4n8coronQjV6lov5JFCf1/img.png)
모두 종료합니다.
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
다음글에서는 도커를 활용하여 웹서비스 배포를 해보겠습니다.
'Server' 카테고리의 다른 글
Docker & Kubernetes 개념 총 정리 7 (0) | 2025.01.16 |
---|---|
Docker & Kubernetes 개념 총 정리 6 (0) | 2025.01.15 |
Docker & Kubernetes 개념 총 정리 4 (0) | 2025.01.13 |
Docker & Kubernetes 개념 총 정리 3 (0) | 2025.01.07 |
Docker & Kubernetes 개념 총 정리 2 (0) | 2025.01.03 |
- Total
- Today
- Yesterday