본문 바로가기
AWS Cloud School 8기/쿠버네티스

[쿠버네티스] label/ ReplicaSet/ kubectl 명령 자동완성/ Deployment/ namespace/ Service/ NodePort / 삭제 모음 zip

by YUNZEE 2025. 4. 11.
728x90

삭제 모음 zip

더보기

root@master:~# kubectl delete pod --all

- pod 전부 삭제

root@master:~# kubectl delete pod --all -n kube-system

- 모든 파드를 삭제

 

root@master:~# kubectl run test1 --image=public.ecr.aws/docker/library/nginx:alpine
pod/test1 created
root@master:~# kubectl run test2 --image=public.ecr.aws/docker/library/nginx:alpine
pod/test2 created

 

root@master:~# kubectl get pod -o wide

둘 다 잘 연결되는 걸 확인할 수 있음

 

만약에 ip생성이 안되거나 연결이 안 된다면 최악의 상황.

1.kubectl delete -f kube-flannel.yml로 flannel CNI 삭제

2. 모든 노드에서 kubeadm reset으로 클러스터 리셋

3. 재부팅을 해서 CNI 관련된 호스트의 설정값들을 초기화

4.kubeadm init 및 kubeadm join으로 클러스터 재구성.

label - 리소스를 특정하기 위한 꼬리표

만약 내가 똑같은 pod를 3개 띄웠다면, pod들의 이름은 다르기 때문에 대상을 한꺼번에 특정하기 어렵다. 하지만 똑같은 label을 달아준다면 해당 레이블로 3개의 파드를 동시에 특정 가능함. 쿠버네티스에서는 보통 label을 통해 리소스를 식별하는 편

더보기

 root@master:~# vi test-pod.yml 

apiVersion: v1
kind: Pod
metadata:
  name: test-pod
  labels:
    app: my-web
spec:
  containers:
  - image: public.ecr.aws/docker/library/nginx:alpine
    name: test-pod

kubectl apply -f test-pod.yml

- 컨테이너 이름을 변경해 주기

kubectl apply -f test-pod.yml

kubectl describe pod test-pod

root@master:~/mani# kubectl delete pod test-pod

ReplicaSet(레플리카셋)

- 파드의 복제본. pod보다 한 단계 상위개념.

- 버전관리에 반드시 필요한 리소스.

- 스케일링이 가능함.

- selector를 통해 복제할 pod의 label을 선택할 수 있음.

더보기

root@master:~# mkdir mani
root@master:~# cd mani
root@master:~/mani# pwd
/root/mani

 

root@master:~/mani# vi rep.yml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: test-rep
spec:
  replicas: 2 #2개 복제
  selector:
    matchLabels:
      app: my-web #여기 있는걸 찾아서1
  template: #template는 pod의 명세
    metadata:
      labels:
        app: my-web #여기에 복제2
    spec:
      containers:
      - image: public.ecr.aws/docker/library/nginx:alpine
        name: test-pod-con

- test-pod pod를 삭제하지 않은 상태에서 실행하면 이름이 중복돼서 랜덤 한 문자가 제대로 부여받지 못함.

- 그래서 test-pod를 삭제하고 다시 실행하면 두 개의 pod가 잘 생성된 걸 확인할 수 있음

실습 1) label이 app: my-httpd이고 httpd:latest라는 이미지로 구성된 pod를 2개 띄우는 레플리카셋의 매니페스트 파일(rep-httpd.yml)을 만들어보세요.

더보기

root@master:~/mani# cp rep.yml rep-httpd.yml

root@master:~/mani# vi rep-httpd.yml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: httpd-rep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-httpd
  template:
    metadata:
      labels:
        app: my-httpd
    spec:
      containers:
      - image: public.ecr.aws/docker/library/httpd:latest
        name: test-pod-con

root@master:~/mani# kubectl apply -f rep-httpd.yml

- 한 번 특정 파일을 지워보자

- 내가 지운 pod는 삭제가 되지만, 새로운 pod가 바로 생성됨

- Desired state가 app: my-httpd라는 라벨을 달고 잇는 파드가 2개이기 때문에 내가 파드를 한 개 삭제하는 순간, status는 replicas=1이 되기 때문에 즉시 하나 더 바로 생성됨

 

root@master:~/mani# kubectl delete -f rep.yml

root@master:~/mani# kubectl delete -f rep-http.yml

# 두 레플리카셋을 삭제하면

 

root@master:~/mani# kubectl get rs, pod

 - 나머지 다 삭제해 주고 다음 실습으로 ㄱㄱ

kubectl 명령 자동완성

더보기

apt-get install -y bash-completion

 

echo 'source <(kubectl completion bash)' >>~/.bashrc

echo 'source <(kubeadm completion bash)' >>~/.bashrc

kubectl completion bash >/etc/bash_completion.d/kubectl

#자동완성

 

ln -s /usr/bin/kubectl /usr/local/bin/k

# kubectl 대신 k로 단축명령.

 

# 재부팅해야 됨 그래야 반영되는 걸 확인할 수 있음

root@master:~/mani# kubectl apply -f rep.yml

 

root@master:~# cd mani
root@master:~/mani# kubectl get pod test-rep-d -> 탭을 치면 자동으로 밑에 파일이 생성된 걸 확인할 수 있음
test-rep-dbwvs  test-rep-dkdtl 

실습 2)

k8s is easy라는 내용의 index.html 파일을 배포하는 아주 간단한 public.ecr.aws/docker/library/nginx:alpine 기반 app을 컨테이너 이미지로 만들어서 도커허브에 push 한 다음 쿠버네티스 로컬클러스터에 pod 3개로 배포해 보세요. 도커허브가 안되면 ECR에 해보세요!

 

1. k8s is easy라는 내용의 index.html 파일

2. public.ecr.aws/docker/library/nginx:alpine 기반 app을 컨테이너 이미지

3. 쿠버네티스 로컬클러스터에 pod 3개로 배포

더보기

1. 컨테이너이미지 생성을 위한 Dockerfile 작성

echo k8s is easy > index.html

 

vi Dockerfile

 

FROM public.ecr.aws/docker/library/nginx:alpine

WORKDIR /usr/share/nginx/html

COPY index.html index.html

 

2. 로컬에서 이미지 build & push

먼저 도커 허브에 로그인하기

root@master:~/mani# docker login -u choyunji

패스워드 입력해 주고

 

docker build -t <도커허브계정명>/easy:1 .

docker push <도커허브계정명>/easy:1

3. 쿠버네티스에서 push 한 이미지로 매니페스트 작성 및 apply

cp rep-http.yml rep-easy.yml

vi  rep-easy.yml

apiVersion: apps/v1
kind: ReplicaSet
metadata:
  name: easy-rep
spec:
  replicas: 3
  selector:
    matchLabels:
      web: easy-k8s
  template:
    metadata:
      labels:
        web: easy-k8s
    spec:
      containers:
      - image: oolralra/easy:1
        name: easy-con

root@master:~/mani# kubectl apply -f rep-easy.yml

Deployment

- 디폴로이먼는 pod을 원하는 수만큼 유지하고, 업데이트와 롤백까지 자동으로 처리하는 컨트롤러

더보기

cp rep-http.yml dep-http.yml

vi dep-http.yml

apiVersion: apps/v1
kind: Deployment #수정
metadata:
  name: my-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: my-httpd
  template:
    metadata:
      labels:
        app: my-httpd
    spec:
      containers:
      - image: public.ecr.aws/docker/library/httpd:latest
        name: httpd-pod-con

root@master:~/mani# kubectl apply -f dep-http.yml

하면 잘 생성된 걸 확인할 수 있음

root@master:~/mani# kubectl get deploy

- 클러스터 Deployment 리소스 목록을 조회하는 명령어

- Pod를 배포하고 관리하는 상위 리소스

root@master:~/mani# kubectl get rs

- 쿠버네티스에서 리플리카셋(ReplicaSet) 리소스를 조회하는 명령어

- pod의 개수를 유지해 주는 컨트롤러

namespace

- pod 같은 리소스들을 공간적으로 분리/격리하기 위한 리소스.

- 비슷한 성질, 분류를 갖는 리소스들을 공간적으로 분리/ 격리하기 위한 리소스

- 네임스페이스별로 접근 제어도 가능

더보기

 

root@master:~/mani# kubectl create ns test-ns
namespace/test-ns created

- test-ns라는 이름을 갖는 네임스페이스 생성


root@master:~/mani# kubectl delete deploy --all
root@master:~/mani# kubectl delete rs --all
root@master:~/mani# kubectl delete pod --all

- 기존 리소스 삭제

 

root@master:~/mani# kubectl apply -f dep-http.yml -n test-ns


root@master:~/mani# kubectl get pod

root@master:~/mani# kubectl get pod -n default 
- 우리가 네임스페이스 명시하지 않으면 기본 네임스페이스(default)에 명령어 들어감

 

root@master:~/mani# kubectl get pod -n test-ns

kubectl get pod --all-namespaces

# 모든 네임스페이스의 리소스를 다 보고 싶을 땐

 

kubectl delete ns test-ns

# 네임스페이스를 삭제 시, 내부의 모든 리소스가 전부 삭제된다.

 

vi test-ns.yml

# 이번에는 매니페스트로 ns를 정의

apiVersion: v1
kind: Namespace
metadata:
  name: test-ns

kubectl apply -f test-ns.yml

실습 3)

네임스페이스: lunch

디플로이먼트: lunch-dep

를 생성하되, 하나의 yml파일로 매니페스트를 작성해야 하고, 디플로이먼트는 lunch라는 네임스페이스에 존재해야 합니다. 이미지는 public.ecr.aws/docker/library/nginx:alpine 로 하시고 레플리카 2개로 하세요.

따로 'kubectl create 같은 명령을 쓰진 마세요!!'

더보기

root@master:~/mani# vi lunch-dep.yaml 

apiVersion: v1
kind: Namespace
metadata:
  name: lunch
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: lunch-dep
  namespace: lunch
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - image: public.ecr.aws/docker/library/nginx:alpine
        name: lunch-con

root@master:~/mani# kubectl apply -f lunch-dep.yaml 

잘 되는 걸 확인할 수 있음

 

✅ 여기서 질문!

디플로이먼트 먼저 정의하고 네임스페이스 정의해도 괜찮을까?

답은 아니! Deployment를 먼저 정의하고, 그 아래 네임스페이스를 정의하면 에러가 발생함!

Error from server (NotFound): namespaces "lunch" not found

Deployment를 만들려고 하는데, 아직 lunch 네임스페이스가 없기 때문임

 

그래서 네임스페이스 먼저 만들어주고 디폴로이먼트를 정의해 줘야 됨

Service

- 작은 로드밸런서, 주로 pod 같은 리소스들을 대표.(부하 분산 + 접속 지점)

- pod들을 주로 외부에 서비스하는 리소스

- 쿠버네티스에서 Pod은 자동으로 IP가 바뀌기 때문에, 직접 접근하면 매우 불편함

그래서 쿠버네티스는 service라는 고정된 접근 경로를 만들어줌

- 서비스를 생성 시 하나의 접속지점이 생성

- 이 서비스를 통해 모든 노드에 존재하는 파드에 트래픽을 인가할 수 있음

- 인가하는 기준은 labels를 통해 해당 파트를 특정하면 됨

 

- 서비스에는 다양한 종류(type)가 존재함

더보기

root@master:~/mani# kubectl delete -f lunch-dep.yaml 
namespace "lunch" deleted
deployment.apps "lunch-dep" deleted

 

root@master:~/mani# vi dep.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: my-con
        image: public.ecr.aws/docker/library/nginx:alpine

kubectl apply -f dep.yml

# apply 하면 그림과 같은 deployment가 생성.

ClusterIP = 클러스터 내에서만 유효한 Service IP를 생성해 주는 타입 <내부만 가능>

기본값 => type: ClusterIP 생략 가능 

=> 클러스터 외부에서는 찾아갈 수 없는 서비스. 내부 테스트 용도로만 서비스를 만들고 싶을 때 사용

더보기

 vi dep-svc.yml

apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
spec:
  selector:
    app: nginx
  ports:
  - port: 80
    targetPort: 80

 

kubectl apply -f dep-svc.yml

- svc를 좀 더 자세히 보자

NodePort 

1. 클러스터의 노드포트(nodePort, 30000-32767)로 사용자가 접근

2. 해당 노드포트에 매칭된 서비스의 포트(port)로 연결

3. 서비스는 selector를 통해 매칭된 파드의 포트(targetPort)로 접속

 

NodePort는 쿠버네티스 노드의 포트를 열어서 클러스터 외부에서 접근 가능하게 만드는 Service타입

✅ 흐름 정리

[브라우저] --> http://<노드 IP>:32000
                         ↓
                   [NodePort Service]
                         ↓
                    [nginx Pod:80]

더보기

 vi dep-svc.yml의 타입을 NodePort로 변경

apiVersion: v1
kind: Service
metadata:
  name: svc-nginx
spec:
  selector:
    app: nginx
  type: NodePort # ClusterIP가 아닌 NodePort 타입,수정
  ports: #3개의 포트를 명시
  - nodePort: 30001 #추가
    port: 80
    targetPort: 80

 

# dep-svc.yml의 타입을 NodePort로 변경.

 

root@master:~/mani# kubectl apply -f dep-svc.yml 
service/svc-nginx configured

- 기존 서비스가 변경

 

root@master:~/mani# kubectl get svc svc-nginx 

- 어느 노드의 주소든 괜찮음

- 외부에서 노드로 통신만 된다면, 노드포트를 통해 pod로 접속 가능함

root@master:~/mani# kubectl describe svc svc-nginx 

3개의 포트( nodePort, port, targetPort )가 각각 어떤 대상인지 구분할 수 있어야 함.

실습 4)

하나의 yml 파일을 통해

서비스이름: svc-ipnginx

서비스포트: 80

노드포트: 32000

label = app: myipnginx

이미지: oolralra/ipnginx

파드수: 3개

네임스페이스: ip-ns

 

위와 같이 구성해 보자

더보기

root@master:~/mani# vi svc-ipnginx.yml 

# 네임스페이스 정의
# 네임스페이스: ip-ns
apiVersion: v1
kind: Namespace
metadata:
  name: ip-ns
---
# 디플로이먼트 정의
#label = app: myipnginx
#이미지: oolralra/ipnginx
#파드수: 3개
apiVersion: apps/v1
kind: Deployment
metadata:
  name: ipnginx-deploy
  namespace: ip-ns
spec:
  replicas: 3
  selector:
    matchLabels:
      app: myipnginx
  template:
    metadata:
      labels:
        app: myipnginx
    spec:
      containers:
      - name: ipnginx
        image: oolralra/ipnginx
        ports:
        - containerPort: 80
---
# 서비스 정의
#서비스이름: svc-ipnginx
#서비스포트: 80
#노드포트: 32000
apiVersion: v1
kind: Service
metadata:
  name: svc-ipnginx
  namespace: ip-ns
spec:
  type: NodePort
  selector:
    app: myipnginx
  ports:
  - port: 80
    targetPort: 80
    nodePort: 32000

 

✅ kubectl get pod에 왜 안 보이지?

-> 이걸 해결하려면 네임스페이스 개념을 정확히 이해해야 됨

-> 이 명령은 네임스페이스가 default안에 있는 pod만 보여줌

즉, 따로 설정하지 않으면 default 모음 안에 다 포함하게 됨

kubectl get pods -n ip-ns를 입력하면 잘 확인할 수 있음

 

kubectl get svc -n ip-ns

오류 /해결 방안 - oolralra/ipnginx파일을 가져와야 되는데 가져오지 못하는 상태임

더보기

 

 파일이 잘 안 가져와지는 걸 확인할 수 있음

root@master:~/mani# kubectl get pod -n ip-ns
NAME                           READY   STATUS             RESTARTS   AGE
ipnginx-deploy-bcb7b85-jcpgg   0/1     ImagePullBackOff   0          28m
ipnginx-deploy-bcb7b85-kqj5v   0/1     ImagePullBackOff   0          28m
ipnginx-deploy-bcb7b85-vkkdk   0/1     ImagePullBackOff   0          28m

- 이걸 보면 yaml파일이 정확히 작동해서 pod 3개가 생성되었음을 보여주지만 ImagePullBackOff 이기 때문에 정상적으로 실행이 안 되는 걸 확인할 수 있음

 

✅ 현재 상황 분석

STATUS: ImagePullBackOff

이 상태는 다음과 같은 의미야: 쿠버네티스가 Pod을 만들려고 했지만,

컨테이너 이미지를 다운로드(pull)할 수 없어서 "잠시 멈춤" 상태로 바뀐 거야.

즉, image: oolralra/ipnginx 를 다운로드할 수 없어서 생긴 문제야.

 

이럴 때는 테더링을 해주면 됨

 

테더링이란? 

- 핸드폰 인터넷을 노트북, 태스크탑, 가상머신에 공유해 주는 기능

- 이럴 때 핸드폰 테더링(hotspot)을 사용해 인터넷 연결 가능

 

오류/ 해결 방안 - 3개 중 status가 하나만 running 된 상태임

더보기

 3개가 다 running 된 상태여야 하는데 하나만 running된 상태임 지우고 다시 생성해 주겠음

 

root@master:~/mani# kubectl delete -f svc-ipnginx.yml 

root@master:~/mani# kubectl apply -f svc-ipnginx.yml 
root@master:~/mani# kubectl get pod -n ip-ns

- 계속 입력해주다 보면 결국 3개다 running 한 상태가 됨

자율과제1)

서비스에서 selector를 통해 pod의 label을 선택할때, 해당 label이 존재하지 않는경우의 svc를 describe해서 확인해보세요. 정상적인 svc와 deployment를 먼저 만들고 어떤 변경점이 있는지 비교해보세요.

더보기

hw1.yml을 열어서 Service의 라벨을 수정.

# app: myipnginx1이라는 라벨을 달고 있는 pod들이 없기때문에 svc의 describe상의 endpoints에도 뜨지 않

자율과제2)

61.254.18.30:5000 에는 박찬민의 http 통신을 하는 사설 레지스트리가 존재합니다. http://61.254.18.30:5001 통해 어떤 이미지레포가 있는지도 확인가능합니다! 이 사설 레지스트리에 본인이름으로 된 이미지를 push 하고, 본인의 클러스터에 해당 이미지를 배포해보세요

더보기

docker로 해당 레지스트리에 push를 하기 위해 docker 설정 변경

 

vi /etc/docker/daemon.json

{

"insecure-registries": ["61.254.18.30:5000"]

}

systemctl restart docker

 

root@master:~/mani# docker pull public.ecr.aws/docker/library/nginx:alpine

# push할 이미지를 아무거나

 

docker tag public.ecr.aws/docker/library/nginx:alpine 61.254.18.30:5000/pcm:1

# push를 하기위해 태그변경.

 

docker push 61.254.18.30:5000/pcm:1

 

docker image rm 61.254.18.30:5000/pcm:1

# 푸쉬후 로컬에 있는 이미지는 삭제

 

docker run -dp 5959:80 --name test 61.254.18.30:5000/pcm:1

# 이미지 유효한지 테스트.

# 테스트 목적: push된 이미지에는 문제가 없다라는걸 보장하고 싶음.

 

이미지를 땡겨오는 주체가 누구인지? 어디서 땡겨오는지?

1. docker라는 런타임이냐? 아니면 containerd라는 런타임이냐? => containerd

 

우리가 매니페스트 파일을 apply 하면, api-server를 통해 노드의 kubelet이 pod를 생성하는데 그때 kubelet이 containerd라는 컨테이너런타음으로 pod에 들어갈 컨테이너를 생성. 따라서 containerd라는 컨테이너런타임이 레지스트리에 접근할 수 있어야 함

 

docker에서는 daemon.json에서 구성했듯

containerd 에서는 /etc/containerd/config.toml 에 내용을 추가해야함

 

2. 어디서 땡겨 오냐?

- 각 워커노드기 때문에 containerd설정을 워커노드에서 해줘야됨

 

vi free.yml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-dep
spec:
  replicas: 2
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: my-con
        image: 61.254.18.30:5000/pcm:1

# push된 이미지로 Deployment 매니페스트 작성.

kubectl apply -f free.yml

cat <<EOF >> /etc/containerd/config.toml
[plugins."io.containerd.grpc.v1.cri".registry.mirrors."61.254.18.30:5000"]
      endpoint = ["http://61.254.18.30:5000"]
[plugins."io.containerd.grpc.v1.cri".registry.configs."61.254.18.30:5000".tls]
      insecure_skip_verify = true
EOF

systemctl restart containerd

 

kubectl delete -f free.yml 

kubectl apply -f free.yml

728x90