Docker 이미지를 다른 서버로 복사하기

반응형

Docker 이미지를 한 서버에서 다른 서버로 복사할 수 있습니다.

여러 가지 방법이 있지만, 가장 일반적인 방법은 docker save 와 docker load 명령어를 사용하는 것입니다.

 

 

1. 이미지 추출

 

기존 서버에서 이미지 리스트를 확인합니다.

# docker images
REPOSITORY          TAG       IMAGE ID       CREATED        SIZE
sysdocu_2            latest    ba025dce294f   8 hours ago    12.3GB

 

확인된 이미지를 tar 파일로 저장합니다.

# docker save -o image.tar sysdocu_2:latest

 

파일이 생성되었습니다.
# ls -al image.tar

-rw------- 1 root root 12471617536  8월  1 07:22 image.tar

 

 

2. 파일 전송

 

저장한 tar 파일을 다른 서버로 전송합니다.
# rsync -avzP image.tar root@192.168.10.2:/root/

 

 

3. 이미지 로드

 

다른 서버에서 tar 파일을 로드하여 docker 이미지 리스트에 추가합니다.

# docker load -i /root/image.tar

 

이미지가 이전된 것이 확인되었습니다.

# docker images
REPOSITORY          TAG       IMAGE ID       CREATED        SIZE
sysdocu_2            latest    ba025dce294f   8 hours ago    12.3GB

 

반응형

댓글()

K3S 설치 및 삭제, Worker node 추가 및 삭제

반응형

K3S 를 설치하고 삭제하는 방법과 노드가 부족하거나 여러대로 클러스터를 구성하기 위해 사용하는 방법입니다.

아래는 마스터 노드와 워커 노드에서 사용하는 명령을 정리하였으므로 잘 구분해서 실행하시기 바랍니다.

 

 

1. K3S 설치 

 

(마스터 노드에서)

# curl -sfL https://get.k3s.io | sh -s - --disable traefik --write-kubeconfig-mode 644

# export KUBECONFIG="/etc/rancher/k3s/k3s.yaml"

 

앞으로 SSH 접속시마다 자동으로 환경이 로드 되도록 하면 편리합니다.

# echo 'export KUBECONFIG="/etc/rancher/k3s/k3s.yaml"' >> ~/.bashrc

 

 

2. K3S 삭제

 

(마스터 노드에서)

자동 삭제 스크립트를 이용해 삭제 합니다.
# /usr/local/bin/k3s-uninstall.sh

삭제가 안된 부분이 있을 수 있으므로 수동으로 추가 삭제 명령을 내립니다.
# systemctl stop k3s

# systemctl disable k3s
# rm -rf /etc/rancher/k3s
# rm -rf /var/lib/rancher/k3s
# rm -f /usr/local/bin/k3s
# rm -f /usr/local/bin/kubectl
# rm -f /usr/local/bin/crictl
# rm -f /usr/local/bin/ctr

서비스를 제거 합니다.
# systemctl daemon-reload

 

 

3. Worker node 추가

 

(마스터 노드에서)

# cat /var/lib/rancher/k3s/server/node-token

 

(워커 노드에서)

# curl -sfL https://get.k3s.io| K3S_URL=https://<SERVER_IP>:6443 K3S_TOKEN=<TOKEN> sh -

여기에서 Master node 서버 IP 와 출력되었던 토큰을 대체 입력해야 합니다.

 

이제 추가 한 Worker node 가 연결된 것을 확인 할 수 있습니다.

# kubectl get nodes

 

 

4. Worker node 삭제

 

(워커 노드에서)
# systemctl stop k3s-agent
# systemctl disable k3s-agent
# /usr/local/bin/k3s-agent-uninstall.sh
# rm -rf /etc/rancher/k3s
# rm -rf /var/lib/rancher/k3s

 

(마스터 노드에서)
# kubectl delete node <NODE_NAME>

 

반응형

댓글()

Docker 기본 root 디렉토리 변경하기

반응형

디스크 부족 등의 이유로 디렉토리를 변경해야 할 경우가 있습니다.

설정파일을 통해 간단히 변경이 가능합니다.

 

1. 확인

현재 Docker 기본 root 디렉토리를 확인합니다.

# docker info |grep Root
 Docker Root Dir: /var/lib/docker

 

2. 디렉토리 설정 변경

Docker 의 설정 파일을 수정하여 디렉토리를 변경할 수 있습니다.

아래는 기본 디렉토리를 /data 로 변경한 예 입니다.

(파일이 없을경우 생성하면 됩니다)

# vi /etc/docker/daemon.json

{
        "data-root" : "/data"
}

 

3. 적용하기

Docker 데몬을 재시작 하면 변경한 설정이 적용되고, 디렉토리를 조회하면 새로 구성된 파일이 생성 되었음을 알 수 있습니다.

# systemctl restart docker

# ls -al /data
total 52
drwx--x--- 12 root root 4096 Apr  1 05:56 .
drwxr-xr-x 20 root root 4096 Mar 31 23:30 ..
drwx--x--x  4 root root 4096 Apr  1 05:56 buildkit
drwx--x---  2 root root 4096 Apr  1 05:56 containers
-rw-------  1 root root   36 Apr  1 05:56 engine-id
drwx------  3 root root 4096 Apr  1 05:56 image
drwxr-x---  3 root root 4096 Apr  1 05:56 network
drwx--x---  3 root root 4096 Apr  1 05:56 overlay2
drwx------  4 root root 4096 Apr  1 05:56 plugins
drwx------  2 root root 4096 Apr  1 05:56 runtimes
drwx------  2 root root 4096 Apr  1 05:56 swarm
drwx------  2 root root 4096 Apr  1 05:56 tmp
drwx-----x  2 root root 4096 Apr  1 05:56 volumes

 

반응형

댓글()

Rocky Linux 9 에서 Docker 설치하기

반응형

Rocky Linux 9 에서 Docker 설치하는 방법을 기술하였습니다.

 

1. Docker 설치

# dns -y update

# dnf config-manager --add-repo=https://download.docker.com/linux/centos/docker-ce.repo

# dnf -y install docker-ce docker-ce-cli containerd.io

# systemctl enable --now docker

# docker --version

Docker version 26.0.0, build 2ae903e

 

2. Docker compose 설치

# curl -L "https://github.com/docker/compose/releases/download/v2.26.0/docker-compose-linux-x86_64" -o /usr/local/bin/docker-compose
# chmod +x /usr/local/bin/docker-compose
# docker-compose --version
Docker Compose version v2.26.0

 

반응형

댓글()

Docker data root directory 변경하기

반응형

이미지 용량이 커서 별도의 디스크로 저장하고자 할 경우에 Docker 설정 파일에서 디렉토리를 변경해 주어야 합니다.

물론 같은 디렉토리로 마운트하여 사용이 가능하지만, 여기에서는 추가한 디스크의 마운트 디렉토리로 변경하는 방법을 안내합니다.

 

1. HDD 추가

SATA 4TB 디스크의 파티션 및 파일시스템을 생성하고 /data 디렉토리로 마운트 해 두었습니다. (방법 생략)

 

2. Docker 중지

Docker 가 실행중일 경우 중지합니다.

# systemctl stop docker

 

3. 기존 데이터 복사

신규 디렉토리의 퍼미션을 원래 디렉토리와 동일하게 합니다.

# chmod 710 /data

기존에 사용하던 docker 디렉토리를 신규 디렉토리 아래로 복사해 넣습니다.

# cp -arp /var/lib/docker /data/

 

4. Docker 설정 변경

Docker 설정 파일을 열고 Docker data root directory 를 변경합니다.

파일이 없는 경우 생성하면 됩니다.

# vi /etc/docker/daemon.json

{
        "data-root": "/data/docker/"
}

 

5. Docker 실행

변경된 디렉토리를 적용하기 위해 Docker 데몬을 가동합니다.

# systemctl start docker

 

전에 사용하던 이미지가 있었다면, 그대로 출력이 잘 되는지 확인합니다.

# docker images

 

반응형

댓글()

Ubuntu 22.04 단일 서버에서 K0S 설치하기

반응형

K0S 는 경량 Kubernetes 배포를 위한 오픈 소스 프로젝트로써 가능한 간소한 배포 및 관리를 목표로 합니다. 이 프로젝트는 Kubernetes 환경을 빠르게 구성하고 유지보수할 수 있도록 설계되었습니다.

K0S 는 다음과 같은 특징을 가지고 있습니다.

 

- 경량화 : 최소한의 의존성과 경량화된 구성으로 구축되어 있어, 자원 사용이 적습니다.

- 포터빌리티 : 다양한 환경에서 실행되도록 설계되어 있어, 로컬 머신, 가상 머신, 또는 클라우드 환경에서 사용할 수 있습니다.

- 간편한 설치 및 운영 : 설치 및 운영이 간단하며, 개발자나 작은 규모의 프로젝트에 적합합니다.

- 플러그인 시스템 : 필요한 경우 플러그인을 추가하여 기능을 확장할 수 있습니다.

 

K0S 는 K8S Cluster 를 관리하고 유지보수하는데 더 간편한 옵션을 제공합니다. 하지만 특정 프로젝트의 요구에 따라 다른 Kubernetes 배포 옵션도 고려해볼 필요가 있습니다.

 

본 내용은 공식 Document 내용을 참고하여 실행해보고 기록하였습니다.

- 공식 Document : https://github.com/k0sproject/k0s/blob/main/docs/install.md

 

 

1. 설치

# curl -sSLf https://get.k0s.sh | sudo sh
Downloading k0s from URL: https://github.com/k0sproject/k0s/releases/download/v1.29.1+k0s.1/k0s-v1.29.1+k0s.1-amd64
k0s is now executable in /usr/local/bin

 

기본 구성으로 컨트롤러 및 작업자 기능을 포함하는 단일 노드 K0S 를 설치합니다.

# k0s install controller --single

 

참고로 재설치가 필요한 경우 --force 옵션을 사용하면 됩니다.

예) k0s install controller --single --force

 

2. 구동

K0S 서비스를 시작합니다.
# k0s start

K0S 인스턴스 상태를 확인합니다.
# k0s status
Version: v1.29.1+k0s.1
Process ID: 1787
Role: controller
Workloads: true
SingleNode: true
Kube-api probing successful: true
Kube-api probing last error:  

kubectl 을 사용하면 애플리케이션을 배포하거나 노드 상태를 확인할 수 있습니다.
# k0s kubectl get nodes
NAME            STATUS   ROLES           AGE     VERSION
sysdocu-23890   Ready    control-plane   3m53s   v1.29.1+k0s

참고로 서비스 중지는 다음과 같습니다.
# k0s stop

 

3. 삭제

중지 후에는 필요에 따라 K0S 를 초기화 할 수 있습니다.

이 명령은 설치된 시스템 서비스, 데이터 디렉터리, 컨테이너, 마운트 및 네트워크 네임스페이스를 모두 정리합니다.

# k0s reset

 

그리고 리부팅을 해야 하는데, 그 이유는 정리되지 못한 데몬이나 iptables 가 남아 있을 수 있기 때문입니다.

# reboot

 

반응형

댓글()

[Kubernetes] metrics-server 설치하기 (error: Metrics API not available 조치)

반응형

metrics-server 는 Kubernetes 클러스터 내에서 노드 및 Pod 의 리소스 사용량에 대한 메트릭 데이터를 수집하고 제공하는 서버입니다. 이러한 메트릭 데이터는 Kubernetes API 서버를 통해 조회할 수 있어, 사용자나 다른 Kubernetes 구성 요소들이 클러스터의 성능 및 리소스 사용에 대한 정보를 얻을 수 있습니다.

metrics-server 가 제공하는 주요 메트릭은 다음과 같습니다:
- CPU 사용량 (CPU Usage) : 클러스터 내의 각 노드 및 Pod 가 사용하는 CPU 의 양을 측정합니다.
- 메모리 사용량 (Memory Usage) : 클러스터 내의 각 노드 및 Pod 가 사용하는 메모리의 양을 측정합니다.
- 네트워크 입출력 (Network I/O) : 클러스터 내의 각 노드 및 Pod 가 수행하는 네트워크 입출력을 측정합니다.
- 파일 시스템 사용량 (Filesystem Usage) : 클러스터 내의 각 노드 및 Pod 가 사용하는 파일 시스템의 용량과 사용량을 측정합니다.

이러한 메트릭 데이터는 Kubernetes 의 Horizontal Pod Autoscaling (HPA) 및 기타 리소스 관리 및 모니터링 도구에서 사용됩니다. metrics-server 는 일반적으로 클러스터 내에서 자동으로 배포되며, Kubernetes 버전 1.8 이상에서는 기본적으로 활성화됩니다.

사용자는 kubectl top 명령을 통해 metrics-server 에서 수집된 메트릭 데이터를 조회할 수 있습니다. 예를 들어, kubectl top pods, kubectl top nodes 등을 사용하여 Pod 및 노드의 리소스 사용량을 확인할 수 있습니다.

 

 

1. Metrics-server 설치

 

설치는 한번의 명령으로 끝이 납니다.

아래 URL 은 공식 배포 URL 로써 항상 최신버전의 metrics-server 가 설치 됩니다.

# kubectl apply -f https://github.com/kubernetes-sigs/metrics-server/releases/latest/download/components.yaml
serviceaccount/metrics-server created
clusterrole.rbac.authorization.k8s.io/system:aggregated-metrics-reader created
clusterrole.rbac.authorization.k8s.io/system:metrics-server created
rolebinding.rbac.authorization.k8s.io/metrics-server-auth-reader created
clusterrolebinding.rbac.authorization.k8s.io/metrics-server:system:auth-delegator created
clusterrolebinding.rbac.authorization.k8s.io/system:metrics-server created
service/metrics-server created
deployment.apps/metrics-server created
apiservice.apiregistration.k8s.io/v1beta1.metrics.k8s.io created

 

명령이 잘 실행되는지 확인합니다.

아래는 nodes 의 자원 사용률 확인 명령입니다.

# kubectl top nodes
error: Metrics API not available

 

이와 동일한 에러가 출력된 경우, metrics-server Pod 가 잘 생성되었는지 확인합니다.

# kubectl get pod -A |grep metrics
kube-system                                     metrics-server-5d875656f5-vmv66                                 0/1     Running     0          10s

 

설치가 되었으나 Running 중인 Pod 는 0개로 확인 됩니다.

Pod 의 상세 정보에서는 HTTP status code 500 에러가 확인되었습니다.

# kubectl describe pod metrics-server-5d875656f5-vmv66 -n kube-system

...

(생략)

...

Events:
  Type     Reason     Age               From               Message
  ----     ------     ----              ----               -------
  Normal   Scheduled  52s               default-scheduler  Successfully assigned kube-system/metrics-server-5d875656f5-vmv66 to kind-control-plane
  Normal   Pulled     51s               kubelet            Container image "registry.k8s.io/metrics-server/metrics-server:v0.6.4" already present on machine
  Normal   Created    51s               kubelet            Created container metrics-server
  Normal   Started    51s               kubelet            Started container metrics-server
  Warning  Unhealthy  1s (x4 over 31s)  kubelet            Readiness probe failed: HTTP probe failed with statuscode: 500

 

문제 해결을 위해 Deployment 를 수정합니다.

# kubectl edit deployment metrics-server -n kube-system

출력된 내용중에 metric-resolution 문자열을 검색해서 그 다음에 옵션을 하나 더 추가해 주어야 하는데, 문자열을 검색하면 두 군데 나옵니다. 그중에서 아래와 같이 옵션이 행으로 구분된 곳에 --kubelet-insecure-tls 옵션을 추가해 줍니다.

kubelet-insecure-tls 옵션은 공식적으로 발급받은 인증서인지 확인하지 않고 접근하겠다는 의미입니다.

...

(생략)

...

    spec:
      containers:
      - args:
        - --cert-dir=/tmp
        - --secure-port=4443
        - --kubelet-preferred-address-types=InternalIP,ExternalIP,Hostname
        - --kubelet-use-node-status-port
        - --metric-resolution=15s
        - --kubelet-insecure-tls
        image: registry.k8s.io/metrics-server/metrics-server:v0.6.4

...

(생략)

...

 

저장 후 시간이 조금 지나야 적용됩니다.

적용이 되면 아래와 같이 자원 사용량 확인이 가능합니다.

# kubectl top nodes
NAME                 CPU(cores)   CPU%   MEMORY(bytes)   MEMORY%   
kind-control-plane   294m         3%     2753Mi          17%  

 

# kubectl top pods
NAME                                                    CPU(cores)   MEMORY(bytes)   
b07a7888-df03-451f-8475-13c6d9bac48d-cf--cb3e18e9fd-0   1m           4Mi             
nginx-665cb6f744-wf5g5                                  0m           6Mi      

 

반응형

댓글()

[Kubernetes] 네임스페이스의 메모리 및 CPU 할당량 구성

반응형

네임스페이스에 일정 용량을 적용하여 그 안의 Pod 가 제한된 용량 안에서만 자원을 나누어 사용할 수 있도록 합니다.

본 매뉴얼은 아래 공식 문서를 참고하여 작성하였습니다.

https://kubernetes.io/docs/tasks/administer-cluster/manage-resources/quota-memory-cpu-namespace/

 

 

1. 네임스페이스 생성

 

테스트를 위한 네임스페이스를 생성합니다.

# kubectl create namespace sysdocu-ns

 

 

2. 할당량 생성 및 적용

 

네임스페이스에 적용할 할당량을 설정합니다.

# vi rq.yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  name: mem-cpu-limits
spec:
  hard:
    requests.cpu: "1"
    requests.memory: 1Gi
    limits.cpu: "2"
    limits.memory: 2Gi

 

작성한 할당량을 먼저 생성한 네임스페이스에 적용합니다.

# kubectl apply -f rq.yaml -n sysdocu-ns
resourcequota/mem-cpu-limits created

 

설정한 리소스 할당량과 사용량에 대한 정보를 볼 수 있습니다.

# kubectl get resourcequota mem-cpu-limits -n sysdocu-ns --output=yaml
apiVersion: v1
kind: ResourceQuota
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ResourceQuota","metadata":{"annotations":{},"name":"mem-cpu-limits","namespace":"sysdocu-ns"},"spec":{"hard":{"limits.cpu":"2","limits.memory":"2Gi","requests.cpu":"1","requests.memory":"1Gi"}}}
  creationTimestamp: "2024-01-11T00:29:34Z"
  name: mem-cpu-limits
  namespace: sysdocu-ns
  resourceVersion: "12801859"
  uid: 98127c56-33bc-4ccc-a55c-1152b7f04128
spec:
  hard:
    limits.cpu: "2"
    limits.memory: 2Gi
    requests.cpu: "1"
    requests.memory: 1Gi
status:
  hard:
    limits.cpu: "2"
    limits.memory: 2Gi
    requests.cpu: "1"
    requests.memory: 1Gi
  used:
    limits.cpu: "0"
    limits.memory: "0"
    requests.cpu: "0"
    requests.memory: "0"

 

위 예시의 리소스 할당량 (ResourceQuota : mem-cpu-limits) 이 설정된 네임스페이스에 다음과 같은 제약 사항이 있습니다.
- 네임스페이스의 모든 Pod 에 대해 각 컨테이너에는 메모리 요청, 메모리 제한, CPU 요청 및 CPU 제한이 있어야 합니다.
- 해당 네임스페이스에 있는 모든 Pod 에 대한 메모리 요청 합계는 1 GiB 를 초과해서는 안 됩니다.
- 해당 네임스페이스에 있는 모든 Pod 의 메모리 제한 합계는 2 GiB 를 초과해서는 안 됩니다.
- 해당 네임스페이스에 있는 모든 포드에 대한 CPU 요청 합계는 1 CPU 를 초과해서는 안 됩니다.
- 해당 네임스페이스에 있는 모든 포드의 CPU 제한 합계는 2 CPU 를 초과해서는 안 됩니다.

 

 

3. 첫번째 Pod 생성

 

테스트를 위해 간단한 Pod 를 생성합니다.

# vi pod1.yaml

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod1
spec:
  containers:
  - name: demo-pod1
    image: nginx
    resources:
      limits:
        memory: "800Mi"
        cpu: "800m"
      requests:
        memory: "600Mi"
        cpu: "400m"

 

# kubectl apply -f pod1.yaml -n sysdocu-ns
pod/demo-pod1 created

 

Pod 가 정상 실행되고 있는지 확인합니다.

# kubectl get pod demo-pod1 -n sysdocu-ns
NAME        READY   STATUS    RESTARTS   AGE
demo-pod1   1/1     Running   0          80s

 

설정한 리소스 할당량과 사용량에 대한 정보를 다시 확인합니다.

아래와 같이 사용량이 변경된 것을 확인할 수 있습니다.

# kubectl get resourcequota mem-cpu-limits -n sysdocu-ns --output=yaml

apiVersion: v1
kind: ResourceQuota
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","kind":"ResourceQuota","metadata":{"annotations":{},"name":"mem-cpu-limits","namespace":"sysdocu-ns"},"spec":{"hard":{"limits.cpu":"2","limits.memory":"2Gi","requests.cpu":"1","requests.memory":"1Gi"}}}
  creationTimestamp: "2024-01-11T00:29:34Z"
  name: mem-cpu-limits
  namespace: sysdocu-ns
  resourceVersion: "12805135"
  uid: 98127c56-33bc-4ccc-a55c-1152b7f04128
spec:
  hard:
    limits.cpu: "2"
    limits.memory: 2Gi
    requests.cpu: "1"
    requests.memory: 1Gi
status:
  hard:
    limits.cpu: "2"
    limits.memory: 2Gi
    requests.cpu: "1"
    requests.memory: 1Gi
  used:
    limits.cpu: 800m
    limits.memory: 800Mi
    requests.cpu: 400m
    requests.memory: 600Mi

 

jq 명령어 사용이 가능한 시스템에서는 아래와 같이 필요한 항목만 출력시킬 수 있습니다.

# kubectl get resourcequota mem-cpu-limits -n sysdocu-ns -o jsonpath='{ .status.used }' | jq .
{
  "limits.cpu": "800m",
  "limits.memory": "800Mi",
  "requests.cpu": "400m",
  "requests.memory": "600Mi"
}

 

 

4. 두번째 Pod 생성

 

테스트를 위해 두번째 Pod 를 생성합니다.

# vi pod2.yaml

apiVersion: v1
kind: Pod
metadata:
  name: demo-pod2
spec:
  containers:
  - name: demo-pod2
    image: redis
    resources:
      limits:
        memory: "1Gi"
        cpu: "800m"
      requests:
        memory: "700Mi"
        cpu: "400m"

 

# kubectl apply -f pod2.yaml -n sysdocu-ns
Error from server (Forbidden): error when creating "pod2.yaml": pods "demo-pod2" is forbidden: exceeded quota: mem-cpu-limits, requested: requests.memory=700Mi, used: requests.memory=600Mi, limited: requests.memory=1Gi

 

네임스페이스 내에서 사용 가능한 요청 메모리가 1Gi 인데, Pod1 의 메모리 600MiB 에 Pod2 의 메모리 700MiB 를 추가하려니까 에러가 발생했습니다.

600MiB + 700MiB > 1 GiB.

 

이렇게 ResourceQuota 을 이용해 네임스페이스에 리소스 할당량을 사용하여 제한하는 방법을 알아보았습니다.

 

반응형

댓글()

Kubernetes Pod 의 CPU 요청 및 제한값 변경하기 (Vertical Pod Autoscaler)

반응형

Autoscaler 종류는 총 세가지 입니다.

1) HPA (Horizontal Pod Autoscaler) : 애플리케이션의 복제본 수를 조정합니다. HPA 는 CPU 활용도를 기반으로 복제 컨트롤러, 배포, 복제본 집합 또는 상태 저장 집합의 포드 수를 조정합니다. HPA 는 또한 사용자 지정 또는 외부 메트릭을 기반으로 스케일링 결정을 내리도록 구성될 수 있습니다.

2) CA (Cluster Autoscaler) : 클러스터의 노드 수를 조정합니다. 클러스터 오토스케일러는 노드가 포드를 실행할 수 있는 자원이 부족하거나 (노드를 추가), 노드의 활용도가 낮은 상태로 있을 때 (노드를 제거), 포드가 다른 노드에 할당될 수 있을 때 (노드를 제거), 클러스터에서 노드를 자동으로 추가하거나 제거합니다.

3) VPA (Vertical Pod Autoscaler) : 클러스터 내 컨테이너의 리소스 요청 및 제한을 조정합니다. 본 매뉴얼에서 다룰 내용입니다.

- 공식 Document : https://github.com/kubernetes/autoscaler/tree/master/vertical-pod-autoscaler

 

 

1. VPA (Vertical Pod Autoscaler) 배포

 

VPA 사용을 위해 필요한 파일을 다운로드 받고 클러스터에 배포합니다.
# git clone https://github.com/kubernetes/autoscaler.git
# cd autoscaler/vertical-pod-autoscaler
# ./hack/vpa-up.sh

 

배포가 잘 되었는지 확인합니다.

# kubectl get pods -n kube-system |grep vpa
NAME                                         READY   STATUS    RESTARTS   AGE
vpa-admission-controller-754ccfdf99-pkxnl    1/1     Running   0          45s
vpa-recommender-667f9769fb-84rl5             1/1     Running   0          46s
vpa-updater-696b8787f9-6665j                 1/1     Running   0          46s

 

- VPA Admission-Controller : VPA 업데이터가 Pod 를 제거하고 다시 시작할 때마다 새 Pod 가 시작되기 전에 Webhook 를 사용하여 CPU 및 메모리 설정을 변경합니다.

- VPA Recommender : Metric Server 의 정보를 참조하여 적합한 리소스 크기를 추천합니다.

- VPA Updater : 1분에 1회씩 변경 사항을 확인하고 업데이트 합니다.

 

VPA 사용자 지정 리소스 정의가 생성되었는지 확인합니다.
# kubectl get customresourcedefinition | grep verticalpodautoscalers

verticalpodautoscalers.autoscaling.k8s.io             2023-12-29T07:32:30Z

 

 

2. Pod 생성

 

Deployment 로 생성한 Pod 에 적용이 잘 되는지 확인해보겠습니다.

아래와 같이 Deployment 구성 파일을 작성합니다.

# vi deployment.yaml

apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx
spec:
  selector:
    matchLabels:
      app: nginx
  replicas: 1
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginxinc/nginx-unprivileged:latest
        resources:
          limits:
            cpu: 100m
            memory: 256Mi
          requests:
            cpu: 50m
            memory: 128Mi
        securityContext:
          allowPrivilegeEscalation: false
          capabilities:
            drop: ["ALL"]
          runAsNonRoot: true
          seccompProfile:
            type: RuntimeDefault

 

작성한 yaml 파일을 적용합니다.

# kubectl apply -f deployment.yaml

deployment.apps/nginx created

 

생성된 Pod 이름을 확인합니다.

# kubectl get pod

NAME                                                     READY   STATUS      RESTARTS   AGE
nginx-7f856c878-gbk77                                    1/1     Running     0          7m43s

 

Pod 에 적용된 자원 요청 및 제한값을 확인합니다.

# kubectl describe pod nginx-7f856c878-gbk77 |grep -E 'cpu|memory'
      cpu:     100m
      memory:  256Mi
      cpu:        50m
      memory:     128Mi

 

변경을 위해 Vertical Pod Autoscaler 구성 파일을 작성합니다.

# vi vpa.yaml

apiVersion: "autoscaling.k8s.io/v1"
kind: VerticalPodAutoscaler
metadata:
  name: nginx-vpa
spec:
  targetRef:
    apiVersion: "v1"
    kind: Deployment
    name: nginx
  updatePolicy:
    updateMode: "Auto"
  resourcePolicy:
    containerPolicies:
      - containerName: '*'
        minAllowed:
          cpu: 100m
          memory: 256Mi
        maxAllowed:
          cpu: 200m
          memory: 512Mi
        controlledResources: ["cpu", "memory"]

 

작성한 yaml 파일을 적용합니다.

# kubectl apply -f vpa.yaml

verticalpodautoscaler.autoscaling.k8s.io/nginx-vpa created

 

생성한 VPA 를 확인합니다.

VPA Updater 가 1분 간격으로 변경 사항을 확인하고 업데이트 하기 때문에 조금 기다려야 정확한 내용 확인이 가능합니다.

# kubectl get vpa
NAME        MODE   CPU    MEM     PROVIDED   AGE
nginx-vpa   Auto   100m   256Mi   True       8m28s

 

자세한 VPA 정보를 확인합니다.

# kubectl describe vpa nginx-vpa

...

Status:
  Conditions:
    Last Transition Time:  2024-01-02T05:17:45Z
    Status:                True
    Type:                  RecommendationProvided
  Recommendation:
    Container Recommendations:
      Container Name:  nginx
      Lower Bound:
        Cpu:     100m
        Memory:  256Mi
      Target:
        Cpu:     100m
        Memory:  256Mi
      Uncapped Target:
        Cpu:     25m
        Memory:  262144k
      Upper Bound:
        Cpu:     100m
        Memory:  256Mi

...

 

이미 생성되어 있는 Pod 에는 적용되지 않으므로 Pod 를 삭제하여 재생성 되도록 합니다.

# kubectl delete pod nginx-7f856c878-gbk77

pod "nginx-7f856c878-gbk77" deleted

 

재생성된 Pod 이름을 확인합니다.

# kubectl get pod
NAME                                                     READY   STATUS      RESTARTS   AGE
nginx-75954b4f8d-6g54j                                   1/1     Running     0          62s

 

새로 적용된 자원 요청 및 제한값을 확인합니다.

Deployment 의 설정값보다 VPA 설정값이 우선시 되는것을 확인하였습니다.

# kubectl describe pod nginx-75954b4f8d-6g54j |grep -E 'cpu|memory'

                  vpaUpdates: Pod resources updated by nginx-vpa: container 0: cpu request, memory request, cpu limit, memory limit
      cpu:     200m
      memory:  512Mi
      cpu:        100m
      memory:     256Mi

 

참고로, VPA 에서 Deployment 가 인식되는 시간 (최대 1분) 이 필요한데, VPA 를 먼저 정의한 다음에 Deployment (Pod 자동 생성) 를 생성한다 하더라도 VPA 가 Deployment 를 인식하기 전에 Pod 가 먼저 생성되는 경우가 많으므로 Pod 삭제 작업은 꼭 필요합니다.

삭제 작업 없이 Pod 를 생성하는대로 적용하고 싶으면, Deployment 생성시 replicas: 0 으로 먼저 적용하고, VPA 에서 인식이 되면 replicas: 1 등으로 수정, 적용하세요. Deployment 인식 이후에 생성된 Pod 이므로 VPA 요청 및 제한값에 맞추어 생성됩니다.

 

반응형

댓글()

[Kubernetes] 지워지지않는 Terminating 네임스페이스 삭제하기

반응형

다음과 같이 삭제되지 않는 네임스페이스를 강제로 삭제하는 방법입니다.

# kubectl get ns |grep Terminating
cf-org-d550a9c8-9bf1-49db-9887-310bc39261b1   Terminating   29m

 

방법1

kubectl 명령 옵션으로 삭제합니다.

# kubectl delete namespace cf-org-0ff8cc13-3a8e-47e2-839b-e68f5510583c --grace-period=0 --force

 

방법2

TARGET 변수에 삭제하고자하는 네임스페이스 이름을 넣고 실행합니다.

jq 명령어가 필요하므로 사전에 jq 패키지를 설치해주세요.

# apt -y install jq

# TARGET="cf-org-0ff8cc13-3a8e-47e2-839b-e68f5510583c"

# kubectl proxy & kubectl get namespace $TARGET -o json |jq '.spec = {"finalizers":[]}' > temp.json

[2] 375218
error: listen tcp 127.0.0.1:8001: bind: address already in use
[2]+  Exit 1                  kubectl proxy

 

위와 같이 에러가 출력되어도 괜찮습니다. 계속 진행합니다.

# kubectl replace --raw "/api/v1/namespaces/$TARGET/finalize" -f temp.json

 

[출처] https://mightytedkim.tistory.com/44

 

반응형

댓글()

개인 도커 레지스트리 (Docker Registry) 구축하기

반응형

Docker Registry 는 Docker 이미지를 업로드 하거나, 다운로드하여 컨테이너를 생성하는 등 이미지 저장소의 역할을 담당합니다. Docker Hub 와 같이 알려진 공개 Docker Registry 말고, 개인적으로 사용 가능한 Docker Registry 를 직접 만들어 보겠습니다.

보통은 Private Registry 라고 하며 Kubernetes 내에서 생성하고 사설 네트워크로 연결하도록 구성하지만, 여기에서는 별도의 단독 서버 1대 (공인IP) 로만 구성할 예정입니다. Registry 서버가 Kubernetes Cluster 와 동일한 스위치 내에 위치한다면 방화벽을 설치함으로써 Private Registry 과 같은 형태로 만들 수 있습니다. 이런 형태로 서비스에 적용할 예정이라면 스토리지 여러대로 GlusterFS 나 Ceph 를 구성하고 별도로 마운트하고 도커 서비스를 구동할 서버 1대로 구성하면 됩니다.

 

다시 말씀 드리면, 두가지 방식중 아래 방식으로 진행합니다.

- Kubernetes 설치, 스토리지 준비, PV 및 PVC 생성, Registry Pod 생성

- Docker 설치, Registry Container 생성

 

[환경 및 사전준비]

OS : Ubuntu 22.04

/data 디렉토리 생성 (로컬 호스트의 이미지 저장소)

 

 

1. SSL 인증서 생성

 

Registry 를 사용할때 파일을 업로드 하거나 다운로드 하게되는데, 이때 암호화 전송이 필요합니다.

(암호화 전송 없이 http 프로토콜을 사용하는 옵션도 있긴 합니다)

인증서가 없을 경우, Let's encrypt SSL 에서 무료 인증서를 발급받을 수 있습니다.

운영체제에 따라 인증서 발급 명령이 다르므로 아래 포스팅을 확인하여 자신의 운영체제에 맞는 명령을 참고하시기 바랍니다.

https://sysdocu.tistory.com/search/let's%20encrypt

 

발급 방법은 위 포스팅에 있으므로 여기에서는 생략하고 넘어가겠습니다.

이제 도메인 인증서를 생성하였고, 인증서를 master 서버의 /root/certs 디렉토리에 복사해 두었습니다.

- 도메인 : registry.az1.sysdocu.kr

- 인증서 파일 위치 : /opt/registry/certs/

 

 

2. Docker 설치

 

Registry 서비스는 Docker Registry 컨테이너를 이용할 것이기 때문에 Docker 패키지를 설치해야 합니다.

패키지 목록을 최신화하고 업그레이드 합니다.
# apt -y update

# apt -y upgrade
# apt -y install apt-transport-https ca-certificates curl gnupg lsb-release

Docker 공식 GPG 를 설치합니다.
# curl -fsSL https://download.docker.com/linux/ubuntu/gpg |gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Docker 공식 저장소를 추가합니다.
# echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" |tee /etc/apt/sources.list.d/docker.list > /dev/null

Docker 를 설치하고 확인합니다.

# apt -y update
# apt -y install docker-ce docker-ce-cli containerd.io
# docker --version

Docker version 24.0.6, build ed223bc

 

 

3. Registry 설치 및 가동

 

Docker Hub 에서 Docker Registry 최신버전 이미지를 다운로드 합니다.
# docker pull registry:latest
latest: Pulling from library/registry
7264a8db6415: Pull complete 
c4d48a809fc2: Pull complete 
88b450dec42e: Pull complete 
121f958bea53: Pull complete 
7417fa3c6d92: Pull complete 
Digest: sha256:d5f2fb0940fe9371b6b026b9b66ad08d8ab7b0d56b6ee8d5c71cb9b45a374307
Status: Downloaded newer image for registry:latest
docker.io/library/registry:latest

 

다운로드 된 이미지를 확인합니다.

# docker images
REPOSITORY   TAG       IMAGE ID       CREATED       SIZE
registry     latest    0030ba3d620c   3 weeks ago   24.1MB

 

Registry 에 접근할 사용자를 생성합니다.

사용자 생성 방식은 htpasswd 를 이용하였습니다.

# apt -y install apache2-utils

# mkdir -p /opt/registry/auth

# htpasswd -c -b -B /opt/registry/auth/htpasswd sysdocu 12345678
Adding password for user sysdocu

 
이제 Registry Docker 이미지, SSL 인증서, 사용자 계정이 준비되었습니다.

컨테이너를 다음과 같은 명령으로 가동합니다.
# docker run --name MyRegistry --restart=always -p 5000:5000 \
    -v /opt/registry/auth:/auth \
    -v /opt/registry/certs:/certs \
    -v /data:/var/lib/registry \
    -e "REGISTRY_AUTH=htpasswd" \
    -e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" \
    -e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd \
    -e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain1.pem \
    -e REGISTRY_HTTP_TLS_KEY=/certs/privkey1.pem \
    -e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true \
    -d registry

* 참고

-v: command not found, -e: command not found 등의 에러 출력시 행 사이에 줄이 떨어져 있는 것이므로 메모장에 기입해 빈 행을 없애거나 역슬래시를 제거하여 한줄 명령으로 사용하면 됩니다.

 

* 설명

--name MyRegistry : 실행되는 컨테이너의 이름을 MyRegistry 로 설정합니다.
--restart=always : 컨테이너가 종료되거나 실패할 경우 자동으로 다시 시작하도록 설정합니다.

-p 5000:5000 : 호스트의 포트 5000 과 컨테이너의 포트 5000 을 연결하여 Registry 에 엑세스할 수 있게 합니다.

-v /opt/registry/auth:/auth : 호스트의 /opt/registry/auth 디렉토리와 컨테이너 내의 /auth 디렉토리를 볼륨 마운트합니다. 이 디렉토리는 사용자 인증 정보를 저장하기 위한 것으로, htpasswd 형식의 사용자 인증 파일이 여기에 저장됩니다.
-v /opt/registry/certs:/certs : 호스트의 /opt/registry/certs 디렉토리와 컨테이너 내의 /certs 디렉토리를 볼륨 마운트합니다. 이 디렉토리에는 TLS (SSL) 인증서 및 키 파일이 저장됩니다.
-v /data:/var/lib/registry : 호스트의 /data 디렉토리와 컨테이너 내의 /var/lib/registry 디렉토리를 볼륨 마운트합니다. 여기에는 레지스트리의 이미지 데이터가 저장됩니다.

-e "REGISTRY_AUTH=htpasswd" : 환경 변수를 설정하여 레지스트리가 htpasswd 형식의 사용자 인증을 사용하도록 합니다.
-e "REGISTRY_AUTH_HTPASSWD_REALM=Registry Realm" : htpasswd 형식의 사용자 인증을 위한 Realm 을 설정합니다.
-e REGISTRY_AUTH_HTPASSWD_PATH=/auth/htpasswd : 사용자 인증 정보를 저장하는 htpasswd 파일의 경로를 지정합니다.
-e REGISTRY_HTTP_TLS_CERTIFICATE=/certs/fullchain1.pem : TLS (SSL) 인증서 파일의 경로를 설정합니다.
-e REGISTRY_HTTP_TLS_KEY=/certs/privkey1.pem : TLS (SSL) 인증서의 개인 키 파일의 경로를 설정합니다.
-e REGISTRY_COMPATIBILITY_SCHEMA1_ENABLED=true : Docker Registry v2의 호환성을 유지하고 Docker v1/v1 API를 사용할 수 있도록 활성화합니다.
-d registry : 컨테이너를 백그라운드에서 실행하도록 설정하고, 다운로드 받아놓은 registry 라는 Docker Image 를 사용하여 컨테이너를 시작합니다.

 

구동된 컨테이너를 확인합니다.

# docker ps
CONTAINER ID   IMAGE      COMMAND                  CREATED         STATUS         PORTS                                       NAMES
f246853edd47   registry   "/entrypoint.sh /etc…"   6 seconds ago   Up 5 seconds   0.0.0.0:5000->5000/tcp, :::5000->5000/tcp   MyRegistry

 

포트도 5000 번으로 정상적으로 열린것이 확인되었습니다.

# netstat -nltp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name    
tcp        0      0 127.0.0.53:53           0.0.0.0:*               LISTEN      23260/systemd-resol 
tcp        0      0 0.0.0.0:5000            0.0.0.0:*               LISTEN      54372/docker-proxy  
tcp        0      0 0.0.0.0:22              0.0.0.0:*               LISTEN      18912/sshd: /usr/sb 
tcp6       0      0 :::5000                 :::*                    LISTEN      54379/docker-proxy  
tcp6       0      0 :::22                   :::*                    LISTEN      18912/sshd: /usr/sb 

 

만들어진 Registry 컨테이너로 로그인을 해봅니다.

계정은 위에서 htpasswd 로 생성했던 계정입니다.

# docker login -u sysdocu -p 12345678 https://registry.az1.sysdocu.kr:5000
WARNING! Using --password via the CLI is insecure. Use --password-stdin.
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

 

로그인 성공하여 접근 허용이 되었으면, Registry 이미지 리스트를 확인합니다.

업로드한 이미지가 없기때문에 아직은 아무것도 출력되지 않습니다.

# curl -u sysdocu:12345678 https://registry.az1.sysdocu.kr:5000/v2/_catalog
{"repositories":[]}

 

여기까지 Registry 구축이 완료되었습니다.

아래는 다른 서버에서 Registry 를 사용하는 방법입니다.

 

 

4. 이미지 업로드 및 컨테이너 생성

 

두가지 방법이 있는데, 여기에서는 기본 컨테이너에서 내용을 변경해보는 아래 방식으로 진행합니다.

- Docker Hub 이미지 그대로 Registry 에 업로드

- Docker Hub 이미지를 받아서 수정하고 Registry 에 업로드

 

진행할 예제는 php:7.4-apache 기준으로 작성하였습니다.
우선 php:7.4-apache 이미지를 다운로드 합니다.

# docker pull docker.io/php:7.4-apache

 

테스트용으로 PHP 소스 파일을 만듭니다.

# mkdir ./source

# vi ./source/index.php

<?php
echo "Good job";
?>

 

Dockerfile 을 아래 내용으로 작성합니다.
# vi Dockerfile

FROM docker.io/php:7.4-apache
COPY ./source/ /var/www/html/
RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf
CMD ["apache2-foreground"]

 

* 설명

FROM docker.io/php:7.4-apache : 기본 이미지를 지정하는 부분입니다. php2.4 와 apache 웹서버가 설치된 이미지 입니다.
COPY ./source/ /var/www/html/ : 호스트 시스템의 ./source/ 디렉토리의 내용을 컨테이너 내부의 /var/www/html/ 디렉토리로 복사하는 명령입니다. 

RUN echo "ServerName localhost" >> /etc/apache2/apache2.conf : Apache 웹서버에 ServerName 옵션을 추가합니다.
CMD ["apache2-foreground"] : 컨테이너가 시작될 때 실행될 명령입니다. 여기에서는 Apache 웹 서버를 시작합니다.

 

만들어진 Dockerfile 을 사용하여 Docker 이미지를 새로 만듭니다.

형식) docker build --tag <새 이미지 이름> <Dockerfile 위치>

# docker build --tag php7.4-apache-update .

 

만들어진 새 이미지가 확인 되었습니다.

# docker images
REPOSITORY             TAG       IMAGE ID       CREATED          SIZE
php7.4-apache-update   latest    b36ddfe193e1   28 seconds ago   453MB
registry               latest    0030ba3d620c   3 weeks ago      24.1MB

 

이번에는 로컬에 만들어져 있는 php7.4-apache-update 이미지를 Registry 에 올려 보겠습니다.

업로드 권한이 필요하므로 생성했던 htpasswd 계정을 이용해 Registry 에 로그인을 합니다.

(아까 위에서 로그인 했을 경우 생략 가능)

# docker login -u sysdocu -p 12345678 https://registry.az1.sysdocu.kr:5000

 

태그 설정을 하고 업로드 합니다.

태그 이름은 로컬에 만들어놓은 이름 (php7.4-apache-update) 과 동일하게 하겠습니다.

그리고 sysdocu 라는 디렉토리로 이미지 용도를 구분 짓도록 하겠습니다.

# docker tag php7.4-apache-update registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update

# docker push registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update
Using default tag: latest
The push refers to repository [registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update]
61323a0752b4: Pushed 
3d4722dde23c: Pushed 
3d33242bf117: Pushed 
529016396883: Pushed 
5464bcc3f1c2: Pushed 
28192e867e79: Pushed 
d173e78df32e: Pushed 
0be1ec4fbfdc: Pushed 
30fa0c430434: Pushed 
a538c5a6e4e0: Pushed 
e5d40f64dcb4: Pushed 
44148371c697: Pushed 
797a7c0590e0: Pushed 
f60117696410: Pushed 
ec4a38999118: Pushed 
latest: digest: sha256:2a03e9c0ac98d726ec0f6707d4bd6265aec6de5b0aa3b982315b9eaae0b61123 size: 3449

 

Registry 컨테이너 가동시 지정했던 로컬 호스트 디렉토리 /data 에서 컨테이너에 올려진 데이터가 확인됩니다.

# ll /data/docker/registry/v2/repositories/sysdocu/php7.4-apache-update/
total 20
drwxr-xr-x 5 root root 4096 Sep  6 02:26 ./
drwxr-xr-x 3 root root 4096 Sep  6 02:26 ../
drwxr-xr-x 3 root root 4096 Sep  6 02:26 _layers/
drwxr-xr-x 4 root root 4096 Sep  6 02:26 _manifests/
drwxr-xr-x 2 root root 4096 Sep  6 02:26 _uploads/

 

이렇게도 확인이 됩니다.

아까는 빈 내용이였던 Registry 에 업로드한 이미지가 확인됩니다.

# curl -u sysdocu:12345678 https://registry.az1.sysdocu.kr:5000/v2/_catalog
{"repositories":["sysdocu/php7.4-apache-update"]}

 

이제 업로드 된 이미지를 활용하여 애플리케이션을 구동할 수 있습니다.

방법은 두가지 형식이 있으며 여기에서는 간단히 Docker 컨테이너로 생성해 보겠습니다.

- Kubernetes (Openshift, K-PaaS 등) 에서 Pod 생성, Service 생성

- Docker 에서 컨테이너 생성

# docker run -d -p 80:80 registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update

 

* 설명
-d : 컨테이너를 백그라운드에서 실행합니다.
-p 80:80 : 호스트의 포트 80 을 컨테이너의 포트 80 으로 매핑합니다. 즉, 웹 서버가 동작하는 포트에 접근할 수 있게 됩니다.
registry.az1.sysdocu.kr:5000/sysdocu/php7.4-apache-update : 실행할 Docker 이미지를 지정합니다.

 

컨테이너가 실행되면 웹 서버가 시작되어 호스트의 IP 또는 도메인과 80 번 포트로 웹서버에 접속할 수 있게 됩니다.

# curl http://registry.az1.sysdocu.kr

Good job

 

반응형

댓글()