티스토리 뷰
1. 쿠버네티스 활용하기
매니피스트란 쿠버네티스 오브젝트를 실행하기 위한 메타 정보를 YAML 혹은 JSON 형식으로 작성한 파일을 의미합니다.
매니피스트를 활용하여 파드를 실행해 봅니다.
vi nginx-test01.yml
$ vi nginx-test01.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx01
spec:
containers:
- name: nginx-test01
image: nginx:latest
$ kubectl apply -f nginx-test01.yml
pod/nginx01 created
$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx01 0/1 ContainerCreating 0 11m
pod 실행 확인 후 임시 파일 삭제
$ kubectl delete -f nginx-test01.yml
pod "nginx01" deleted
$ kubectl get pod
No resources found in default namespace.
2. 디플로이먼트
쿠버네티스에서는 파드를 관리하기 위해 디플로이먼트 (deployment) 라는 개념을 사용합니다. 우선 래플리카셋의 개념부터 알아야합니다. 래플리카셋은 명시되어있고 유지해야하는 파드 개수에 대한 가용성을 보증하는데 사용합니다. 이 래플리카셋을 직접 다루는것 대신 디플로이먼트를 이용하는 것입니다. 즉 디플로이먼트는 래플리카셋을 관리하는 컨트롤러입니다.
디플로이먼트를 실행합니다.
$ kubectl create deployment deploy-hello --image=hello-world
deployment.apps/deploy-hello created
디플로이먼트 생성 확인
$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deploy-hello-6cff5dfbc7-72c77 0/1 ContainerCreating 0 64s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 60m
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-hello 0/1 1 0 64s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-hello-6cff5dfbc7 1 1 0 64s
$ kubectl get deployment,replicaset,pod
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-hello 0/1 1 0 3m16s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-hello-6cff5dfbc7 1 1 0 3m16s
NAME READY STATUS RESTARTS AGE
pod/deploy-hello-6cff5dfbc7-72c77 0/1 ContainerCreating 0 3m16s
디플로이먼트 삭제하기
$ kubectl delete deployment deploy-hello
deployment.apps "deploy-hello" deleted
삭제확인
$ kubectl get deploy,rs,po
No resources found in default namespace.
래플리카셋은 원하는 파드 개수만큼 유지시켜주는 역할을 하는 컨트롤러입니다. 파드 개수를 조절하려면 래플리카셋을 직접 다루는 것이 아닌 디플로이먼트를 활용해보겠습니다.
$ kubectl create deployment deploy-nginx --image=nginx --replicas=3
deployment.apps/deploy-nginx created
$ kubectl get deploy,rs,po -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/deploy-nginx 0/3 3 0 91s nginx nginx app=deploy-nginx
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/deploy-nginx-59dd4cd7cc 3 3 0 91s nginx nginx app=deploy-nginx,pod-template-hash=59dd4cd7cc
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/deploy-nginx-59dd4cd7cc-2pscn 0/1 ContainerCreating 0 91s <none> myserver02 <none> <none>
pod/deploy-nginx-59dd4cd7cc-6zqkt 0/1 ContainerCreating 0 91s <none> myserver03 <none> <none>
pod/deploy-nginx-59dd4cd7cc-9t6np 0/1 ContainerCreating 0 91s <none> myserver03 <none> <none>
한개의 파드를 삭제해봅니다.
$ kubectl delete pod deploy-nginx-59dd4cd7cc-2pscn
pod "deploy-nginx-59dd4cd7cc-2pscn" deleted
$ kubectl get deploy,rs,po -o wide
NAME READY UP-TO-DATE AVAILABLE AGE CONTAINERS IMAGES SELECTOR
deployment.apps/deploy-nginx 0/3 3 0 8m37s nginx nginx app=deploy-nginx
NAME DESIRED CURRENT READY AGE CONTAINERS IMAGES SELECTOR
replicaset.apps/deploy-nginx-59dd4cd7cc 3 3 0 8m37s nginx nginx app=deploy-nginx,pod-template-hash=59dd4cd7cc
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
pod/deploy-nginx-59dd4cd7cc-6zqkt 0/1 ContainerCreating 0 8m37s <none> myserver03 <none> <none>
pod/deploy-nginx-59dd4cd7cc-9t6np 0/1 ContainerCreating 0 8m37s <none> myserver03 <none> <none>
pod/deploy-nginx-59dd4cd7cc-gnshz 0/1 ContainerCreating 0 5s <none> myserver02 <none> <none>
파드를 삭제 했지만, 새로운 파드를 생성해내여 래플리카셋 설정 값을 유지하는 것을 확인 할 수 있습니다.
디플로이먼트를 삭제 후 확인합니다.
$ kubectl delete deployment deploy-nginx
deployment.apps "deploy-nginx" deleted
$ kubectl get deploy,rs,po -o wide
No resources found in default namespace.
매니페스트를 활용해 디플로이먼트를 실행합니다.
$ vi deploy-test01.yml
apiVersion: apps/v1
kind : Deployment
metadata:
name: deploy-test01
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: web-deploy
template:
metadata:
labels:
app.kubernetes.io/name: web-deploy
spec:
containers:
- name: nginx
image: nginx:latest
생성할 deployment의 이름은 deploy-test01입니다.
spec을 활용해 디플로이먼트의 상태를 지정합니다.
selector는 파드에 라벨을 붙이는 옵션입니다. selector를 활용해 디플로이먼트가 관리할 파드를 연결합니다. matchLabels의 app.kubernetes.io/name으로 지정하는 이름은 selector로 적용하는 이름이 되므로 이는 파드를 생성했을때 이름과 동일해야 합니다.
template는 생성할 파드의 정보를 표현할때 사용합니다.
실행 및 확인
$ kubectl apply -f deploy-test01.yml
deployment.apps/deploy-test01 created
$ kubectl get deploy,rs,po
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test01 0/3 3 0 26s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test01-5b5d959884 3 3 0 26s
NAME READY STATUS RESTARTS AGE
pod/deploy-test01-5b5d959884-9x2p2 0/1 ContainerCreating 0 26s
pod/deploy-test01-5b5d959884-p89hm 0/1 ContainerCreating 0 26s
pod/deploy-test01-5b5d959884-pkdqw 0/1 ContainerCreating 0 26s
디플로이먼트 삭제 후 확인
$ kubectl delete deployment deploy-test01
deployment.apps "deploy-test01" deleted
$ kubectl get deploy,rs,po
No resources found in default namespace.
쿠버네티스에서 스케일은 디플로이먼트 YAML파일을 수정해서 파드 개수를 조정하는 것입니다.
앞서만든 파일의 복사 폴더를 생성합니다.
user@myserver01:/home/work$ sudo cp -r ch02 ch03
user@myserver01:/home/work$ cd ch03
user@myserver01:/home/work/ch03$ ls
deploy-test01.yml
실행 후 확인
user@myserver01:/home/work/ch03$ kubectl apply -f deploy-test01.yml
deployment.apps/deploy-test01 created
user@myserver01:/home/work/ch03$ kubectl get deploy,rs,po
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test01 0/3 3 0 16s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test01-5b5d959884 3 3 0 16s
NAME READY STATUS RESTARTS AGE
pod/deploy-test01-5b5d959884-cbvnn 0/1 ContainerCreating 0 16s
pod/deploy-test01-5b5d959884-qv84b 0/1 ContainerCreating 0 16s
pod/deploy-test01-5b5d959884-xkfxh 0/1 ContainerCreating 0 16s
파일 복사 후 복사 파일 수정
user@myserver01:/home/work/ch03$ sudo cp deploy-test01.yml deploy-test02.yml
user@myserver01:/home/work/ch03$ sudo vi deploy-test02.yml
apiVersion: apps/v1
kind : Deployment
metadata:
name: deploy-test01
spec:
replicas: 5
selector:
matchLabels:
app.kubernetes.io/name: web-deploy
template:
metadata:
labels:
app.kubernetes.io/name: web-deploy
spec:
containers:
- name: nginx
image: nginx:latest
래플리카셋을 3에서 5로 수정합니다.
새로 생성한 복사파일 실행
user@myserver01:/home/work/ch03$ kubectl apply -f deploy-test02.yml
user@myserver01:/home/work/ch03$ kubectl get deploy,rs,po
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test01 0/5 5 0 4m32s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test01-5b5d959884 5 5 0 4m32s
NAME READY STATUS RESTARTS AGE
pod/deploy-test01-5b5d959884-cbvnn 0/1 ContainerCreating 0 4m32s
pod/deploy-test01-5b5d959884-nbl2d 0/1 ContainerCreating 0 19s
pod/deploy-test01-5b5d959884-qv84b 0/1 ContainerCreating 0 4m32s
pod/deploy-test01-5b5d959884-s6vsh 0/1 ContainerCreating 0 19s
pod/deploy-test01-5b5d959884-xkfxh 0/1 ContainerCreating 0 4m32s
삭제 후 확인
user@myserver01:/home/work/ch03$ kubectl delete -f deploy-test02.yml
deployment.apps "deploy-test01" deleted
user@myserver01:/home/work/ch03$ kubectl get deploy,rs,po
No resources found in default namespace.
쿠버네티스에서의 롤아웃은 컨테이너 업데이트를 의미합니다.
이미 배포되어있는 컨테이너의 버전을 업데이트 합니다. 기존의 deploy-test01.yml이 있는 폴더를 복사 후 deploy-test03.yml으로 변경합니다.
user@myserver01:/home/work$ sudo cp -r ./ch02 ./ch04
user@myserver01:/home/work$ cd ./ch04
user@myserver01:/home/work$ sudo mv deploy-test01.yml deploy-test03.yml
Nginx 버전을 변경합니다.
user@myserver01:/home/work/ch04$ sudo vi deploy-test03.yml
apiVersion: apps/v1
kind : Deployment
metadata:
name: deploy-test01
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: web-deploy
template:
metadata:
labels:
app.kubernetes.io/name: web-deploy
spec:
containers:
- name: nginx
image: nginx:1.24
디플로이먼트 실행 후 확인
user@myserver01:/home/work/ch04$ kubectl apply -f deploy-test03.yml
deployment.apps/deploy-test01 created
user@myserver01:/home/work/ch04$ kubectl get pod
NAME READY STATUS RESTARTS AGE
deploy-test01-6cdbfdd676-4twl8 0/1 ContainerCreating 0 6s
deploy-test01-6cdbfdd676-rfbb6 0/1 ContainerCreating 0 6s
deploy-test01-6cdbfdd676-zrrzc 0/1 ContainerCreating 0 6s
user@myserver01:/home/work/ch04$ kubectl describe deployment deploy-test01
Name: deploy-test01
Namespace: default
CreationTimestamp: Mon, 13 Jan 2025 07:58:53 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 1
Selector: app.kubernetes.io/name=web-deploy
Replicas: 3 desired | 3 updated | 3 total | 0 available | 3 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app.kubernetes.io/name=web-deploy
Containers:
nginx:
Image: nginx:1.24
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Conditions:
Type Status Reason
---- ------ ------
Available False MinimumReplicasUnavailable
Progressing True ReplicaSetUpdated
OldReplicaSets: <none>
NewReplicaSet: deploy-test01-6cdbfdd676 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 22s deployment-controller Scaled up replica set deploy-test01-6cdbfdd676 from 0 to 3
복사 파일 생성 후 nginx의 버전을 수정합니다.
user@myserver01:/home/work/ch04$ sudo cp deploy-test03.yml deploy-test04.yml
user@myserver01:/home/work/ch04$ sudo vi deploy-test04.yml
apiVersion: apps/v1
kind : Deployment
metadata:
name: deploy-test01
spec:
replicas: 3
selector:
matchLabels:
app.kubernetes.io/name: web-deploy
template:
metadata:
labels:
app.kubernetes.io/name: web-deploy
spec:
containers:
- name: nginx
image: nginx:1.25
파일을 비교해보면 nginx의 버전이 1.24에서 1.25로 바뀐 것을 확인할 수 있습니다.
user@myserver01:/home/work/ch04$ diff deploy-test03.yml deploy-test04.yml
17c17
< image: nginx:1.24
---
> image: nginx:1.25
실행 후 확인
user@myserver01:/home/work/ch04$ kubectl apply -f deploy-test04.yml
deployment.apps/deploy-test01 configured
user@myserver01:/home/work/ch04$ kubectl describe deployment deploy-test01
Name: deploy-test01
Namespace: default
CreationTimestamp: Mon, 13 Jan 2025 07:58:53 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 2
Selector: app.kubernetes.io/name=web-deploy
Replicas: 3 desired | 1 updated | 4 total | 0 available | 4 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app.kubernetes.io/name=web-deploy
Containers:
nginx:
Image: nginx:1.25
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Conditions:
Type Status Reason
---- ------ ------
Available False MinimumReplicasUnavailable
Progressing True ReplicaSetUpdated
OldReplicaSets: deploy-test01-6cdbfdd676 (3/3 replicas created)
NewReplicaSet: deploy-test01-6d59f57557 (1/1 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 5m55s deployment-controller Scaled up replica set deploy-test01-6cdbfdd676 from 0 to 3
Normal ScalingReplicaSet 32s deployment-controller Scaled up replica set deploy-test01-6d59f57557 from 0 to 1
위와 같이 nginx의 버전이 1.25로 업데이트 된 것을 확인할 수 있습니다.
롤백의 기능을 살펴보겠습니다. 쿠버네티스에서의 롤백은 롤아웃 이전의 컨테이너 상태로 되돌리는 것을 의미합니다.
user@myserver01:/home/work/ch04$ kubectl rollout undo deployment deploy-test01
deployment.apps/deploy-test01 rolled back
user@myserver01:/home/work/ch04$ kubectl describe deployment deploy-test01
Name: deploy-test01
Namespace: default
CreationTimestamp: Mon, 13 Jan 2025 07:58:53 +0000
Labels: <none>
Annotations: deployment.kubernetes.io/revision: 3
Selector: app.kubernetes.io/name=web-deploy
Replicas: 3 desired | 3 updated | 4 total | 0 available | 4 unavailable
StrategyType: RollingUpdate
MinReadySeconds: 0
RollingUpdateStrategy: 25% max unavailable, 25% max surge
Pod Template:
Labels: app.kubernetes.io/name=web-deploy
Containers:
nginx:
Image: nginx:1.24
Port: <none>
Host Port: <none>
Environment: <none>
Mounts: <none>
Volumes: <none>
Node-Selectors: <none>
Tolerations: <none>
Conditions:
Type Status Reason
---- ------ ------
Available False MinimumReplicasUnavailable
Progressing True ReplicaSetUpdated
OldReplicaSets: deploy-test01-6d59f57557 (1/1 replicas created)
NewReplicaSet: deploy-test01-6cdbfdd676 (3/3 replicas created)
Events:
Type Reason Age From Message
---- ------ ---- ---- -------
Normal ScalingReplicaSet 9m29s deployment-controller Scaled up replica set deploy-test01-6cdbfdd676 from 0 to 3
Normal ScalingReplicaSet 4m6s deployment-controller Scaled up replica set deploy-test01-6d59f57557 from 0 to 1
버전이 롤아웃 이전의 버전으로 돌아간 것을 확인하였습니다. 디플로이먼트를 종료합니다.
user@myserver01:/home/work/ch04$ kubectl delete -f deploy-test04.yml
deployment.apps "deploy-test01" deleted
user@myserver01:/home/work/ch04$ kubectl get deploy,rs,po
No resources found in default namespace.
3. 서비스
쿠버네티스 서비스는 클라이언트와 파드의 연결을 담당합니다. 쿠버네티스 서비스의 종류는 ClusterIP,NodePort,LoadBalancer, ExternalName이 있습니다.
쿠버네티스의 파드는 일시적인 존재로 언젠가는 정지됩니다. 즉 특정 서비스를 제공하기 위해서 수많은 파드의 생성과 종료를 반족하는 것입니다. 파드가 클라이언트에게 서비스를 제공하려면 클라이언트는 파드의 IP에 요청을 해야하는데 이때 각 파드는 개별적인 IP주소를 가집니다. 서비스 중인 파드가 죽고, 해당 서비스를 제공하는 새로운 파드가 생기면 요청을 보내야할 IP주소도 변경됩니다. 이때 클라이언트와 서버를 연결하는 방법은 쿠버네티스의 서비스 기능을 활용합니다.
쿠버네티스의 서비스는 논리적인 파드 셋을 정의하고 클라이언트가 그 파드들에 접근할 수 있는 정책을 정의하는 추상적인 개념입니다. 이를 위해 외부 트래픽 노출, 로드 밸런싱 및 파드들에 대한 서비스 디스커버리를 가능하게 합니다. 이때 서비스 디스커버리란 서비스를 구성하는 개별 인스턴스를 찾는 프로세스를 의미합니다.
쿠버네티스의 서비스는 YAML또는 JSON을 통해 정의되는데, 쿠버네티스의 서비스를 활용하면 파드 내부를 수정하지 않아도 외부로 노출 시킬 수 있다는 장점이 있습니다.
위 그림과 같이 각각의 IP주소가 있습니다. 이때 파드들은 쿠버네티스의 워커노드에 존재합니다. 쿠버네티스의 서비스를 활용하여 파드들이 외부의 트래픽을 받을 수 있도록 노출시킬 수 있습니다.
ClusterIP는 쿠버네티스 서비스의 기본 설정값으로 클러스터 내에서만 파드에 접근될 수 있도록 하는 유형입니다.Cluster IP 유형을 사용하면, 클러스터 내부에서만 접근 가능한 IP를 할당하며, 외부에서는 접근 할 수 없습니다.
예시 파일 생성하기
user@myserver01:/home/work$ sudo cp -r ch02 ch05
user@myserver01:/home/work$ cd ch05
user@myserver01:/home/work$ sudo vi service-test01.yml
apiVersion: v1
kind: Service
metadata:
name: web-service
spec:
selector:
app.kubernetes.io/name: web-deploy
type: ClusterIP
ports:
- protocol: TCP
port: 80
디플로이먼트와 서비스를 실행합니다.
user@myserver01:/home/work/ch05$ kubectl apply -f deploy-test01.yml
deployment.apps/deploy-test01 created
user@myserver01:/home/work/ch05$ kubectl apply -f service-test01.yml
service/web-service created
클러스터내 모든 리소스를 출력합니다. web-service 라는 서비스가 생성된걸 확인 할 수 있습니다.
user@myserver01:/home/work/ch05$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deploy-test01-5b5d959884-6ftz8 1/1 Running 0 27s
pod/deploy-test01-5b5d959884-bw5rw 1/1 Running 0 27s
pod/deploy-test01-5b5d959884-tcw68 1/1 Running 0 27s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h
service/web-service ClusterIP 10.97.251.32 <none> 80/TCP 17s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test01 3/3 3 3 27s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test01-5b5d959884 3 3 3 27s
쿠버네티스 서비스는 ClusterIP 형식이므로 파드로부터 요청을 받아 정보를 제공할 수 있습니다. 이를 위해 앞서 생성한 쿠버네티스 서비스에 요청할 파드를 생성하겠습니다.
user@myserver01:/home/work/ch05$ sudo vi nginx-test01.yml
apiVersion : v1
kind : Pod
metadata:
name : nginx01
spec:
containers:
- name: nginx-test01
image: nginx:latest
파드 생성 후 실행합니다.
user@myserver01:/home/work/ch05$ kubectl apply -f nginx-test01.yml
pod/nginx01 created
user@myserver01:/home/work/ch05$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deploy-test01-5b5d959884-6ftz8 1/1 Running 0 67s
pod/deploy-test01-5b5d959884-bw5rw 1/1 Running 0 67s
pod/deploy-test01-5b5d959884-tcw68 1/1 Running 0 67s
pod/nginx01 1/1 Running 0 6s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 23h
service/web-service ClusterIP 10.97.251.32 <none> 80/TCP 57s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test01 3/3 3 3 67s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test01-5b5d959884 3 3 3 67s
Nginx 파드 내부에 접속해서 쿠버네티스 서비스에 요청을 보냅니다.
user@myserver01:/home/work/ch05$ kubectl exec -it nginx01 -- /bin/bash
root@nginx01:/# curl "10.97.251.32:80"
<!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
파드 내부에서 curl 명령어를 통해 쿠버네티스 서비스에 요청을 보냈습니다. 서비스의 IP 주소와 포트 번호를 입력하면 접속이 정상적으로 되는것을 확인할 수 있습니다.
모두 종료합니다.
user@myserver01:/home/work/ch05$ kubectl delete -f service-test01.yml
service "web-service" deleted
user@myserver01:/home/work/ch05$ kubectl delete -f deploy-test01.yml
deployment.apps "deploy-test01" deleted
user@myserver01:/home/work/ch05$ kubectl delete -f nginx-test01.yml
pod "nginx01" deleted
user@myserver01:/home/work/ch05$ kubectl get pod
No resources found in default namespace.
NodePort는 각 노드의 특정 포트를 통해 외부 접근을 제공하는 유형입니다. NAT를 사용하는 클러스터 내에서 각 노드들의 지정된 포트(30000~ 23767)를 외부에 노출시켜 줍니다. NodeIP : NodePort를 이용해 클러스터 외부에서 서비스에 접근할 수 있게 해줍니다. NodePort는 ClusterIP의 상위 집합입니다.
파일 생성 후 실행
user@myserver01:/home/work$ sudo cp -r ch02 ch06
user@myserver01:/home/work$ cd ch06
user@myserver01:/home/work/ch06$ sudo vi service-test02.yml
apiVersion: v1
kind: Service
metadata:
name: web-service-nodeport
spec:
selector:
app.kubernetes.io/name: web-deploy
type: NodePort
ports:
- protocol: TCP
nodePort: 31001
port: 89
targetPort: 80
user@myserver01:/home/work/ch06$ kubectl apply -f deploy-test01.yml
deployment.apps/deploy-test01 created
user@myserver01:/home/work/ch06$ kubectl apply -f service-test02.yml
service/web-service-nodeport created
user@myserver01:/home/work/ch06$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deploy-test01-5b5d959884-8nxcl 1/1 Running 0 11s
pod/deploy-test01-5b5d959884-rgd5f 1/1 Running 0 11s
pod/deploy-test01-5b5d959884-wf4wd 1/1 Running 0 11s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
service/web-service-nodeport NodePort 10.110.72.179 <none> 89:31001/TCP 6s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test01 3/3 3 3 11s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test01-5b5d959884 3 3 3 11s
포트포워딩 설정
user@myserver01:/home/work/ch06$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 myserver01
10.0.2.4 myserver01
10.0.2.5 myserver02
10.0.2.6 myserver03
# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
http://127.0.0.1:31051/ 와 http://127.0.0.1:31061/ 인터넷 익스플로러로 실행하면 nginx 홈페이지가 실행됩니다.
접속 확인 후 모두 종료합니다.
user@myserver01:/home/work/ch06$ kubectl delete -f service-test02.yml
service "web-service-nodeport" deleted
user@myserver01:/home/work/ch06$ kubectl delete -f deploy-test01.yml
deployment.apps "deploy-test01" deleted
LoadBalancer는 외부용 LoadBalancer를 생성하고, 서비스에 고정된 공인IP를 할당합니다. LoadBalancer를 활용하면 IP 및 포트 번호를 활용해 클러스터 외부에서 서비스에 접근할 수 있습니다. LoadBalancer는 NodePort의 상위 집합입니다.
user@myserver01:/home/work$ sudo cp -r ex02 ex07
user@myserver01:/home/work/ch06$ cd ../ch07
user@myserver01:/home/work$ cd ch07
user@myserver01:/home/work/ch07$ sudo vi service-test03.yml
apiVersion : v1
kind: Service
metadata:
name: web-service-loadbalancer
spec:
selector:
app.kubernetes.io/name: web-deploy
type: LoadBalancer
ports:
- protocol: TCP
nodePort: 31002
port: 80
targetPort: 80
externalIPs:
- 10.0.2.4
user@myserver01:/home/work/ch07$ kubectl apply -f deploy-test01.yml
deployment.apps/deploy-test01 created
user@myserver01:/home/work/ch07$ kubectl apply -f service-test03.yml
service/web-service-loadbalancer created
user@myserver01:/home/work/ch07$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/deploy-test01-5b5d959884-b8p2t 1/1 Running 0 13s
pod/deploy-test01-5b5d959884-s9249 1/1 Running 0 13s
pod/deploy-test01-5b5d959884-sx5vp 1/1 Running 0 13s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
service/web-service-loadbalancer LoadBalancer 10.100.45.107 10.0.2.4 80:31002/TCP 8s
NAME READY UP-TO-DATE AVAILABLE AGE
deployment.apps/deploy-test01 3/3 3 3 13s
NAME DESIRED CURRENT READY AGE
replicaset.apps/deploy-test01-5b5d959884 3 3 3 13s
http://127.0.0.1/ 에 접속합니다.
확인 후 모두 종료합니다.
user@myserver01:/home/work/ch07$ kubectl delete -f service-test03.yml
service "web-service-loadbalancer" deleted
user@myserver01:/home/work/ch07$ kubectl delete -f deploy-test01.yml
deployment.apps "deploy-test01" deleted
user@myserver01:/home/work/ch07$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
ExternalName은 CNAME 레코드를 통해 클러스터 외부 서비스로서 DNS조회를 제공하는 유형입니다. 즉, 서비스가 클러스터 외부에 있는 외부 도메인을 가리키도록 설정할 수 있습니다.
user@myserver01:/home/work$ sudo cp -r ch01 ch08
user@myserver01:/home/work$ cd ch08
user@myserver01:/home/work/ch08$ ls
nginx-test01.yml
user@myserver01:/home/work/ch08$ sudo vi service-test04.yml
apiVersion: v1
kind: Service
metadata:
name: web-service-externalname
spec:
type: ExternalName
externalName: www.google.com
서비스 이름은 web-service-externalname으로 하고 파드에서 연결을 시도할 외부 애플리케이션을 구글로 지정하였습니다.
user@myserver01:/home/work/ch08$ kubectl apply -f service-test04.yml
service/web-service-externalname created
user@myserver01:/home/work/ch08$ kubectl apply -f nginx-test01.yml
pod/nginx01 created
user@myserver01:/home/work/ch08$ kubectl get all
NAME READY STATUS RESTARTS AGE
pod/nginx01 1/1 Running 0 5s
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
service/web-service-externalname ExternalName <none> www.google.com <none> 11s
user@myserver01:/home/work/ch08$ kubectl exec -it nginx01 -- /bin/bash
root@nginx01:/# curl 'web-service-externalname'
<!DOCTYPE html>
<html lang=en>
<meta charset=utf-8>
<meta name=viewport content="initial-scale=1, minimum-scale=1, width=device-width">
<title>Error 404 (Not Found)!!1</title>
<style>
*{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}
</style>
<a href=//www.google.com/><span id=logo aria-label=Google></span></a>
<p><b>404.</b> <ins>That’s an error.</ins>
<p>The requested URL <code>/</code> was not found on this server. <ins>That’s all we know.</ins>
root@nginx01:/# exit
exit
404 에러가 뜨는 이유는 구글은 쿠버네티스 외부에 존재하는 리소스이기 때문입니다.
모두 종료 후 확인합니다.
user@myserver01:/home/work/ch08$ kubectl delete -f nginx-test01.yml
pod "nginx01" deleted
user@myserver01:/home/work/ch08$ kubectl delete -f service-test04.yml
service "web-service-externalname" deleted
user@myserver01:/home/work/ch08$ kubectl get all
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
service/kubernetes ClusterIP 10.96.0.1 <none> 443/TCP 24h
실행중인 CoreDNS확인
user@myserver01:/home/work/ch08$ kubectl get pods --namespace kube-system | grep coredns
coredns-668d6bf9bc-d8b9z 0/1 ContainerCreating 0 20h
coredns-668d6bf9bc-jjm6s 0/1 ContainerCreating 0 20h
두개의 codedb파드가 실행 중인 것을 확인 할 수 있습니다.
codedns 서비스 정보를 확인합니다.
user@myserver01:/home/work/ch08$ kubectl get svc --namespace=kube-system
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
kube-dns ClusterIP 10.96.0.10 <none> 53/UDP,53/TCP,9153/TCP 20h
/etc/resolv.conf nameserver와 clusterIP가 동일한 것을 확인 할 수 있습니다.
5. 스토리지 볼륨
도커에서 컨테이너가 삭제될 때 파일을 보존하기 위해 도커 볼륨을 사용한다면 쿠버네티스에서는 스토리지 볼륨을 활용합니다. 쿠버네티스 컨테이너 내부의 파일 시스템은 일시적인 스토리지를 제공합니다. 즉 쿠버네티스 파드가 삭제된 후 다시 실행한다면, 컨테이너 내부의 파일은 모두 사라집니다. 이 문제를 해결하려고 파드가 재실행되더라도 데이터를 보존할 수 있는 스토리지를 제공합니다. 이때 스토리지는 노드 내부의 일부 디스크 공간을 파드와 공유하는 방식으로 제공할 수도있고, 노드 외부의 시스템과 연결하는 방식도 존재합니다.
쿠버네티스의 볼륨은 크게 emptyDir,hostPath,PersistentVolume으로 나뉩니다.
emptyDir은 파드 내부에서 임시적으로 사용하는 볼륨입니다.
hostPath는 노드 내에서 데이터를 저장할 수 있는 볼륨입니다.
PersistentVolume은 외부 서버에 데이터를 저장하는 볼륨입니다.
emptyDir은 파드가 노드에 할당될때 처음으로 생성되고 파드가 노드에서 실행하는 동안만 존재합니다.
초기에는 비어져 있는 상태로 시작합니다. 파드에 존재하는 모든 컨테이너는 emptyDir 볼륨에 존재하는 동일한 파일을 읽고 쓸 수 있습니다. 이는 볼륨이 각 컨테이너의 서로 다른 경로에 마운트되어도 가능합니다. 파드가 노드에서 삭제되면 emptyDir 내부에 존재하는 데이터도 모두 삭제됩니다.
위 그림과 같이 emptyDir 볼륨은 같은 파드내 컨테이너들은 파일을 공유 할 수 있지만 다른 파드에서는 접근할 수 없습니다.
empty볼륨 테스트 yaml파일을 생성합니다.
user@myserver01:/home/work$ sudo mkdir ch09
user@myserver01:/home/work$ cd ch09
user@myserver01:/home/work/ch09$ sudo vi volume-test01.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx-volume-01
spec:
containers:
- name: nginx-test01
image: nginx:latest
volumeMounts:
- name: empty-test01
mountPath: /mount01
volumes:
- name: empty-test01
emptyDir: {}
종류는 Pod이며 파드 이름은 nginx-volume-01로 생성합니다.
containers 하단 정보는 컨테이너 정보이며 volumes 하단 정보는 볼륨 정보입니다.
컨테이너 이름은 nginx-test01이며 컨테이너 생성에 사용할 이미지를 nginx로 지정하였습니다.
volumeMounts를 사용하여 컨테이너가 사용할 볼륨의 마운트 정보를 작성합니다.
volumes 를 사용하여 추가적으로 파드내부에 생성할 볼륨을 생성합니다. 볼륨타입은 emptyDir이고, {} 으로 추가 옵션을 사용하지 않도록 작성하였습니다.
생성한 yml파일을 실행합니다.
user@myserver01:/home/work/ch09$ kubectl apply -f volume-test01.yml
pod/nginx-volume-01 created
user@myserver01:/home/work/ch09$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-volume-01 1/1 Running 0 13m
user@myserver01:/home/work/ch09$ kubectl exec -it nginx-volume-01 -c nginx-test01 -- /bin/bash
root@nginx-volume-01:/# cd mount01/
root@nginx-volume-01:/mount01# echo "Volume test" > ./test.txt
root@nginx-volume-01:/mount01# ls
test.txt
root@nginx-volume-01:/mount01# cat test.txt
Volume test
root@nginx-volume-01:/mount01# exit
exit
삭제 후 재실행
user@myserver01:/home/work/ch09$ kubectl delete -f volume-test01.yml
pod "nginx-volume-01" deleted
user@myserver01:/home/work/ch09$ kubectl apply -f volume-test01.yml
pod/nginx-volume-01 created
user@myserver01:/home/work/ch09$ kubectl get pod
NAME READY STATUS RESTARTS AGE
nginx-volume-01 1/1 Running 0 6s
user@myserver01:/home/work/ch09$ kubectl exec -it nginx-volume-01 -- /bin/bash
root@nginx-volume-01:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt mount01 opt proc root run sbin srv sys tmp usr var
root@nginx-volume-01:/# cd mount01/
root@nginx-volume-01:/mount01# ls
root@nginx-volume-01:/mount01# exit
exit
앞서 생성한 test.txt파일이 없는 것을 확인 할 수 있습니다.
모두 종료 후 확인합니다.
user@myserver01:/home/work/ch09$ kubectl delete -f volume-test01.yml
user@myserver01:/home/work/ch09$ kubectl get all
hostPath 볼륨은 호스트 노드의 파일 시스템으로부터 파일을 마운트하는 것을 의미합니다. 즉 노드 내부 경로에 볼륨을 두는 형식입니다. 따라서 서로 다른 파드라고 할지라도 실행되는 노드가 동일하면 데이터가 유지됩니다.
노드별 상세조회
user@myserver01:/home/work$ kubectl get nodes --show-labels
NAME STATUS ROLES AGE VERSION LABELS
myserver01 Ready control-plane 25h v1.32.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=myserver01,kubernetes.io/os=linux,node-role.kubernetes.io/control-plane=,node.kubernetes.io/exclude-from-external-load-balancers=
myserver02 Ready <none> 25h v1.32.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=myserver02,kubernetes.io/os=linux
myserver03 Ready <none> 25h v1.32.0 beta.kubernetes.io/arch=amd64,beta.kubernetes.io/os=linux,kubernetes.io/arch=amd64,kubernetes.io/hostname=myserver03,kubernetes.io/os=linux
복제서버2에 접속하여 볼륨을 생성할 디렉터리를 만듭니다.
user@myserver01:/home/work$ ssh myserver03
user@myserver03:~$ cd /home/
user@myserver03:/home$ sudo mkdir work
user@myserver03:/home$ exit
logout
hostPath 볼륨을 실행할 yaml파일을 생성합니다.
user@myserver01:/home/work$ sudo mkdir ch10
user@myserver01:/home/work$ cd ch10
user@myserver01:/home/work/ch10$ sudo vi volume-test02.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx-volume-02
spec:
nodeSelector:
kubernetes.io/hostname: myserver03
containers:
- name: hostpath-test01
image: nginx:latest
volumeMounts:
- name: hostpath-test01
mountPath: /mount01
volumes:
- name: hostpath-test01
hostPath:
path: /home/work
type: DirectoryOrCreate
파드명은 nginx-volume-02입니다.
spec 정보를 사용하여 파드내부의 컨테이너와 볼륨을 생성합니다.
nodeSelector를 지정하여 파드가 실행될 노드를 정합니다.
containers 정보를 입력하여 컨테이너를 생성합니다. 컨테이너명은 hostpath-test01이며 컨테이너가 사용할 이미지는 nginx입니다. 컨테이너가 사용할 볼륨을 마운트압니다. 컨테이너가 사용하게 될 볼륨명은 hostpath-test01이며 이때 사용하게될 볼륨명은 이후 생성할 볼륨명과 일치해야합니다. 볼륨을 마운트할 경로는 /mount01입니다.
volumes : 추가적으로 파드 내부에 생성할 볼륨을 생성합니다.볼륨 타입은 hostPath이며 경로는 myserver03에서 생성한 /home/work입니다. DirectoryOrCreate옵션은 디렉터리가 존재하지 않을 경우 자동으로 생성하라는 옵션입니다.
파드 실행 후 파드 내부에 접속합니다.
user@myserver01:/home/work/ch10$ kubectl apply -f volume-test02.yml
pod/nginx-volume-02 created
실행 후 확인합니다.
user@myserver01:/home/work/ch10$ kubectl apply -f volume-test02.yml
pod/nginx-volume-02 created
user@myserver01:/home/work/ch10$ kubectl exec -it nginx-volume-02 -- /bin/bash
root@nginx-volume-02:/# ls
bin boot dev docker-entrypoint.d docker-entrypoint.sh etc home lib lib64 media mnt mount01 opt proc root run sbin srv sys tmp usr var
root@nginx-volume-02:/# cd mount01/
root@nginx-volume-02:/mount01# ls
root@nginx-volume-02:/mount01# echo "hello world" > ./test.txt
root@nginx-volume-02:/mount01# ls
test.txt
root@nginx-volume-02:/mount01# cat test.txt
hello world
root@nginx-volume-02:/mount01# exit
exit
다시 myserver03에 접속합니다.
user@myserver01:/home/work/ch10$ ssh myserver03
user@myserver03:~$ cd /home/work/
user@myserver03:/home/work$ ls -al
total 12
drwxr-xr-x 2 root root 4096 Jan 14 07:34 .
drwxr-xr-x 4 root root 4096 Jan 14 07:14 ..
-rw-r--r-- 1 root root 12 Jan 14 07:34 test.txt
user@myserver03:/home/work$ cat test.txt
hello world
user@myserver03:/home/work$ exit
logout
Connection to myserver03 closed.
재실행
user@myserver01:/home/work/ch10$ kubectl delete -f volume-test02.yml
pod "nginx-volume-02" deleted
user@myserver01:/home/work/ch10$ kubectl get pod
No resources found in default namespace.
user@myserver01:/home/work/ch10$ kubectl apply -f volume-test02.yml
pod/nginx-volume-02 created
user@myserver01:/home/work/ch10$ kubectl exec -it nginx-volume-02 -- /bin/bash
root@nginx-volume-02:/# cd mount01/
root@nginx-volume-02:/mount01# ls
test.txt
root@nginx-volume-02:/mount01# exit
exit
파드를 재실행해도 파일이 유지되는 것을 확인할 수 있습니다.
아래와 같이 복제서버 1 도 동일하게 yaml파일을 생성합니다.
user@myserver01:/home/work/ch10$ sudo cp volume-test02.yml volume-test03.yml
user@myserver01:/home/work/ch10$ sudo vi volume-test03.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx-volume-03
spec:
nodeSelector:
kubernetes.io/hostname: myserver02
containers:
- name: hostpath-test01
image: nginx:latest
volumeMounts:
- name: hostpath-test01
mountPath: /mount01
volumes:
- name: hostpath-test01
hostPath:
path: /home/work
type: DirectoryOrCreate
파드 이름과 파드가 실행될 노드만 다른것을 확인 할 수있습니다.
user@myserver01:/home/work/ch10$ diff volume-test02.yml volume-test03.yml
4c4
< name: nginx-volume-02
---
> name: nginx-volume-03
7c7
< kubernetes.io/hostname: myserver03
---
> kubernetes.io/hostname: myserver02
생성한 파일을 실행합니다.
user@myserver01:/home/work/ch10$ kubectl apply -f volume-test03.yml
pod/nginx-volume-03 created
user@myserver01:/home/work/ch10$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-volume-02 1/1 Running 0 9m52s 192.168.149.149 myserver03 <none> <none>
nginx-volume-03 1/1 Running 0 24s 192.168.131.2 myserver02 <none> <none>
nginx-volume-02 는 myserver03에 실행되고, nginx-volume-03은 myserver02에 실행된 것을 확인 할 수 있습니다.
파드 내부 실행 후 마운트된 파일을 확인합니다.
user@myserver01:/home/work/ch10$ kubectl exec -it nginx-volume-03 -- /bin/bash
root@nginx-volume-03:/# cd mount01/
root@nginx-volume-03:/mount01# ls
root@nginx-volume-03:/mount01#
root@nginx-volume-03:/mount01# exit
exit
실행 파드 모두 종료합니다.
user@myserver01:/home/work/ch10$ kubectl delete -f volume-test02.yml
pod "nginx-volume-02" deleted
user@myserver01:/home/work/ch10$ kubectl delete -f volume-test03.yml
pod "nginx-volume-03" deleted
PV 즉 PersistentVolume은 외부 스토리지를 의미합니다. PV를 사용하려면 PV와 PVC( PersistentVolumeClaim) 를 이용해야합니다. PV는 스토리지 자원을 의미하며, PVC는 스토리지를 동적으로 바인디하기 위한 요청 객체를 말합니다. 즉, 쿠버네티스 클러스터 관리자가 PV를 생성, 관리하고, PVC를 통해 PV를 요청합니다.
PV를 사용하기 위해 myserver03을 NFS서버로 사용하겠습니다. 모든 서버에 NFS(Network File System)를 설치합니다. NFS서버란 원격 서버에 존재하는 서버를 마치 내 컴퓨터에 있는 것처럼 사용하는 것을 의미합니다. NFS를 사용하려면 클라이언트 측에는 nfs-common을 서버측에서는 nfs-kernel-server 를 설치해야합니다.
user@myserver01:~$ sudo apt install -y nfs-common
user@myserver02:~$ sudo apt install -y nfs-common
user@myserver03:~$ sudo apt install -y nfs-common
user@myserver03:~$ sudo apt install -y nfs-kernel-server
myserver03이 서버역할이므로 nfs-common, nfs-kernel-server 모두 설치해줍니다.
nfs 서버 상태 확인
user@myserver03:~$ systemctl status nfs-server.service
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
Active: active (exited) since Tue 2025-01-14 08:08:25 UTC; 2min 14s ago
Main PID: 541992 (code=exited, status=0/SUCCESS)
CPU: 134ms
Jan 14 08:08:25 myserver03 systemd[1]: Starting nfs-server.service - NFS server and services...
Jan 14 08:08:25 myserver03 exportfs[541991]: exportfs: can't open /etc/exports for reading
Jan 14 08:08:25 myserver03 systemd[1]: Finished nfs-server.service - NFS server and services.
PV용 디렉터리로 k8s-pv폴더를 생성합니다.
user@myserver03:~$ sudo -i
root@myserver03:~# cd /tmp/
root@myserver03:/tmp# mkdir k8s-pv
root@myserver03:/tmp# ls
k8s-pv systemd-private-1a19c9b8de5d4cc283271f5af1cdd773-ModemManager.service-QcGw34 systemd-private-1a19c9b8de5d4cc283271f5af1cdd773-systemd-resolved.service-hT8SvU
snap-private-tmp systemd-private-1a19c9b8de5d4cc283271f5af1cdd773-polkit.service-qOhHxD systemd-private-1a19c9b8de5d4cc283271f5af1cdd773-systemd-timesyncd.service-UxMnwW
systemd-private-1a19c9b8de5d4cc283271f5af1cdd773-fwupd.service-bVqO2I systemd-private-1a19c9b8de5d4cc283271f5af1cdd773-systemd-logind.service-8SJelp systemd-private-1a19c9b8de5d4cc283271f5af1cdd773-upower.service-SRL8wX
ro
NFS 서버가 공유하는 디렉터리를 설정합니다.
vi /etc/exports
# /etc/exports: the access control list for filesystems which may be exported
..생략..
/tmp/k8s-pv 10.0.2.5(rw,no_root,squash)
하단에 추가된 항목은 [공유할 디렉터리명] [접속허용할 IP(옵션) ] 형태로 작성합니다.
NFS서버는 /tmp/k8s-pv 디렉터리를 10.0.2.5 에게 허용하며 (myserver02) rw는 읽기,쓰기 권한을 의미하고, no_root_squash 는 클라이언트의 루트 권한을 인정해준다는 의미입니다. 이 옵션이 없으면 클라이언트가 해당 디렉터리에 루트 권한으로 쓰기가 안됩니다.
nfs-server를 재시작합니다.
root@myserver03:/tmp# systemctl restart nfs-server
root@myserver03:/tmp# systemctl status nfs-server.service
● nfs-server.service - NFS server and services
Loaded: loaded (/usr/lib/systemd/system/nfs-server.service; enabled; preset: enabled)
Active: active (exited) since Tue 2025-01-14 08:21:51 UTC; 13s ago
Process: 544373 ExecStartPre=/usr/sbin/exportfs -r (code=exited, status=0/SUCCESS)
Process: 544375 ExecStart=/usr/sbin/rpc.nfsd (code=exited, status=0/SUCCESS)
Main PID: 544375 (code=exited, status=0/SUCCESS)
CPU: 105ms
Jan 14 08:21:50 myserver03 systemd[1]: Starting nfs-server.service - NFS server and services...
Jan 14 08:21:50 myserver03 exportfs[544373]: exportfs: /etc/exports [1]: Neither 'subtree_check' or 'no_subtree_check' specified for export "10.0.2.5:/tmp/k8s-pv".
Jan 14 08:21:50 myserver03 exportfs[544373]: Assuming default behaviour ('no_subtree_check').
Jan 14 08:21:50 myserver03 exportfs[544373]: NOTE: this default has changed since nfs-utils version 1.0.x
Jan 14 08:21:51 myserver03 systemd[1]: Finished nfs-server.service - NFS server and services.
서버1에서 yaml파일을 생성합니다.
user@myserver01:/home/work/ch10$ cd ../
user@myserver01:/home/work$ sudo mkdir ch11
user@myserver01:/home/work/ch11$ sudo vi volume-test04-1-pv.yml
apiVersion: v1
kind: PersistentVolume
metadata:
name: pv-01
spec:
accessModes:
- ReadWriteOnce
capacity:
storage: 100Mi
persistentVolumeReclaimPolicy: Retain
storageClassName: pv-test-01
nfs:
server: 10.0.2.6
path: /tmp/k8s-pv
accessModes를 설정합니다. ReadWriteOnce는 단하나의 노드만이 읽기, 쓰기를 위해 마운트하는 것을 의미합니다.
용량을 100메가바이트로 설정하였습니다.persistentVolumeClaim 는 pv와 pvc연결에 대한 정책을 결정하는 옵션입니다.
reclaiming은 사용이 끝난 PVC가 사용 중이던 PV를 recliam(초기화)하는 과정을 의미합니다.
이 recliam 옵션으로는 3가지 종류가 있습니다.
Retain은 PVC가 삭제되어도 PV 내부의 데이터는 유지하는 옵션입니다.
Delete는 PVC가 삭제될때 PV 역시 삭제하고, 연계되어있는 외부 스토리지 데이터도 삭제하는 옵션입니다.
Recycle은 PV 내부 파일을 삭제할 때 사용하는데, 지금은 지원하지 않습니다.
storageClassName을 설정합니다. 이때 설정하는 이름은 이후 작성할 PVC와 연결점이 됩니다.
NFS의 서버 정보와 NFS 서버 내부에서 PV로 사용할 경로를 입력합니다.
user@myserver01:/home/work/ch11$ sudo cp volume-test04-1-pv.yml volume-test04-2-pvc.yml
user@myserver01:/home/work/ch11$ sudo vi volume-test04-2-pvc.yml
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: pvc-01
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 30Mi
storageClassName: pv-test-01
오브젝트의 종류는 PersistentVolumeClaim 입니다. resources를 통해 사용할 자원을 설정합니다. PV에게 보낼 요청 사항을 적습니다. 리소스 사용량은 30메가바이트입니다. PVC가 사용할 PV의 storageClassName은 앞서 PV 파일 내부에서 사용한 storageClassName과 동일한 이름으로 설정합니다.
user@myserver01:/home/work/ch11$ sudo cp volume-test04-1-pv.yml volume-test04-3-pod.yml
user@myserver01:/home/work/ch11$ sudo vi volume-test04-3-pod.yml
apiVersion: v1
kind: Pod
metadata:
name: nginx-volume-04
spec:
nodeSelector:
kubernetes.io/hostname: myserver02
containers:
- name: nginx-test01
image: nginx:latest
volumeMounts:
- name: nfs-pv-01
mountPath: /mount01
volumes:
- name: nfs-pv-01
persistentVolumeClaim:
claimName: pvc-01
파드명은 nginx-volume-04며 파드가 실행될 노드는 myserver02입니다. nginx-test01 이름의 컨테이너 를 생성하고 컨테이너 생성에 사용할 이미지는 nginx:latest입니다.
volumeMounts 설정으로 컨테이너가 사용할 볼륨을 마운트합니다. volumes로 추가적으로 파드 내부에 생성할 볼륨을 생성합니다. 추가적으로 생성할 볼륨의 타입은 persistentVolumeClaim이며 pvc명은 앞서 생성한 pv-01입니다.
실행 후 확인
user@myserver01:/home/work/ch11$ kubectl apply -f volume-test04-1-pv.yml
persistentvolume/pv-01 created
user@myserver01:/home/work/ch11$ kubectl apply -f volume-test04-2-pvc.yml
persistentvolumeclaim/pvc-01 created
user@myserver01:/home/work/ch11$ kubectl get pvc
NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS VOLUMEATTRIBUTESCLASS AGE
pvc-01 Bound pv-01 100Mi RWO pv-test-01 <unset> 8s
user@myserver01:/home/work/ch11$ kubectl get pv
NAME CAPACITY ACCESS MODES RECLAIM POLICY STATUS CLAIM STORAGECLASS VOLUMEATTRIBUTESCLASS REASON AGE
pv-01 100Mi RWO Retain Bound default/pvc-01 pv-test-01 <unset> 20s
user@myserver01:/home/work/ch11$ kubectl apply -f volume-test04-3-pod.yml
pod/nginx-volume-04 created
user@myserver01:/home/work/ch11$ kubectl get pod -o wide
NAME READY STATUS RESTARTS AGE IP NODE NOMINATED NODE READINESS GATES
nginx-volume-04 1/1 Running 0 21s 192.168.131.5 myserver02 <none> <none>
파드 내부 접속 후 파일 생성
user@myserver01:/home/work/ch11$ kubectl exec -it nginx-volume-04 -- /bin/bash
root@nginx-volume-04:/# cd mount01/
root@nginx-volume-04:/mount01# ls
root@nginx-volume-04:/mount01# echo "hello nfs pv!" > ./nfs_pvtest.txt
root@nginx-volume-04:/mount01# ls
nfs_pvtest.txt
root@nginx-volume-04:/mount01# cat nfs_pvtest.txt
hello nfs pv!
root@nginx-volume-04:/mount01# exit
exit
nfs-server 인 myserver03에 접속하여 파일 확인
user@myserver03:/tmp$ cd /tmp/k8s-pv/
user@myserver03:/tmp/k8s-pv$ ls
nfs_pvtest.txt
user@myserver03:/tmp/k8s-pv$ cat nfs_pvtest.txt
hello nfs pv!
종료
user@myserver01:/home/work/ch11$ kubectl delete -f volume-test04-3-pod.yml
pod "nginx-volume-04" deleted
user@myserver01:/home/work/ch11$ kubectl delete -f volume-test04-2-pvc.yml
persistentvolumeclaim "pvc-01" deleted
user@myserver01:/home/work/ch11$ kubectl delete -f volume-test04-1-pv.yml
persistentvolume "pv-01" deleted
이번글에서는 쿠버네티스의 디플로이먼트와 서비스 , 스토리지볼륨에 대해 작성하였습니다.
다음글은 쿠버네티스 기능을 추가적으로 작성하겠습니다.
'Server' 카테고리의 다른 글
Docker & Kubernetes 개념 총 정리 6 (0) | 2025.01.15 |
---|---|
Docker & Kubernetes 개념 총 정리 5 (0) | 2025.01.15 |
Docker & Kubernetes 개념 총 정리 3 (0) | 2025.01.07 |
Docker & Kubernetes 개념 총 정리 2 (0) | 2025.01.03 |
Docker & Kubernetes 개념 총 정리 1 (0) | 2025.01.03 |
- Total
- Today
- Yesterday