728x90

가상화의 발전 과정

베어 메탈과 가상화, 컨테이너 환경의 비교

IT 인프라는 기존 하나의 장비 위에 하나의 OS를 올려 사용하던 Bare Metal 환경에서, 리소스 낭비를 막기 위해 가상화 환경으로 변화하였다. 하나의 장비에서 여러 OS를 구동할 수 있게 된 가상화 환경에서는, 각각의 Guest OS마다 Application 등의 버전을 모두 맞춰 주기 번거롭다는 단점이 존재한다. 물론 VM 템플릿을 통해 동일한 환경의 VM 배포가 가능하지만, App의 라이프사이클이 짧아지면서 버전 관리에 상당한 시간이 소요되게 되었다.

 

컨테이너 환경은 기반 OS에 컨테이너 엔진을 올린 다음 컨테이너를 독립 실행할 수 있다. Guest OS가 필요하지 않고, 작업 환경의 배포가 보다 빠르고 자유롭다는 이점이 있다.

 

 

Docker, Kubernetes?

도커는 컨테이너를 배포하는 실무자고, 쿠버네티스는 이런 도커들을 관리하고 명령을 내리는 역할을 한다.

개발 LifeCycle과 Devops

이 그림은 개발 LifeCycle에서 Docker와 Kubenetes가 커버하는 영역을 나타낸다. 개발에서부터 운영까지의 영역을 하나의 팀에서 담당하는 문화인 Devops는, 24/7 죽지 않는 서비스에 해당하는 운영 측면까지 생각하지 않을 수 없다. Kubernetes는 이를 위해 도입되었다고 생각하면 된다.

 

도커의 대안으로 Podman을 사용하기도 하고, 도커 내에서 쿠버네티스의 역할을 하는 Swarm을 사용할 수도 있다.

 

 

도커 역사

도커의 역사

chroot은 root 디렉토리를 변경하는 것이다. 파일과 디렉토리의 액세스 권한을 제어해 주지만, 네트워크 및 프로세스 컨트롤은 불가능하다.

 

FreeBSD의 Jail은 파일시스템과 프로세스, 네트워크까지 분리하였다. 컨테이너의 시작이라고 볼 수 있다. Jail의 뜻을 생각해 보면 이해하기 쉬운데, 감옥은 간수가 관리하지만 하나의 방 안은 독립된 공간으로 죄수가 사용한다. 리눅스에서도 Vserver, 리눅스 격리 환경을 구현해 내었다. OS 가상화라고 볼 수 있다. 비슷하게 솔라리스에서는 Zone 기술을 발표하였는데, 솔라리스 9에서 솔라리스 8을 가상 OS로 사용하는 것이다.

 

cgroups(Control groups)은 프로세스들의 리소스 사용을 제어하고 격리시키는 커널 기능이다. CPU와 Memory, Disk, Network를 각 컨테이너마다 별개로 사용 가능하다. 사용자 공간을 설정하고 해당 프로세스를 관리하는 초기화 시스템인 systemd를 사용하여 격리된 프로세스를 더 효과적으로 제어할 수 있게 한다. 이 기술은 Linux에 대한 전반적인 관리성을 향상시키면서 환경을 분리된 상태로 유지할 방법을 제시하는 프레임워크가 되었으며, Docker에서도 사용된다.

 

Namespace는 프로세스 실행 시 시스템의 리소스를 분리해서 실행하는 기능이다. 주로 사용되는 몇 가지 기능을 아래에 소개한다.

  • mnt: 독립적인 파일시스템 마운트
  • pid: 독립적인 프로세스 공간 할당
  • net: namespace간 network 충돌 방지
  • ipc: 프로세스간 독립적인 통신 통로 할당
  • uts: 독립적인 hostname 할당
  • user: 독립적인 사용자 할당

LXC는 cgroup과 Namespace를 사용하여 구현한 최초의 컨테이너 엔진이다.

Docker는 이와 같은 컨테이너를 관리해 주는 도구이다. 애플리케이션 컨테이너 런타임이라고도 한다. 새 이미지를 실행하고 구축하는 간편한 CLI와 서버 데몬, 사전 구축된 컨테이너 이미지 라이브러리 및 레지스트리 서버의 개념 등의 기술을 결합해 컨테이너를 신속하게 구축하고 다른 사용자들과 간편하게 공유할 수 있다.

Kubernetes는 운영을 위해 다수의 컨테이너를 적절하게 분산하고 스케줄링하는 도구다.

 

 

도커 특징

장점

  • 높은 이식성 Portability: 모든 독립적인 컨테이너는 이미지 형식으로 공유할 수 있다. 컨테이너 실행 환경을 공유 및 재현 가능하다.
  • 상태 없음 Stateless: 컨테이너에 어떠한 정보도 저장되지 않고 App과 격리된다. 즉 일관성이 있다.
  • 신속 배포 Rapid Application Deployment: docker 이미지는 가벼우며, OS를 부팅할 필요가 없다.
  • 버전 제어, 컴포넌트 재사용: 컨테이너 버전을 추적하고 차이점을 비교하거나 이전 버전으로의 롤백이 빠르게 가능하다.
  • 또한, Guest OS의 관리가 필요 없다.

단점

  • 컨테이너가 프로세스로 running하기 때문에 신뢰성 문제 발생할 수 있다. 컨테이너 프로세스가 죽을 수 있고, 죽으면 파일이 날아간다.
  • hub.docker.com에 보안 취약성이 존재한다. 악성 이미지 중 일부는 암호 화폐 채굴에 사용되고 있으므로 Official Image만 사용해야 한다.
  • Docker process는 root 권한이 필요하다.

 

 

도커 아키텍처

도커 아키텍처

  • Client는 도커 명령어라고 생각하면 된다. 도커 Container를 관리하고 실행하기 위해 데몬과 상호작용하는 Binary 파일이다.
  • Daemon은 서버 역할을 한다. 호스트에 설치되어 컨테이너를 관리하는 데몬 프로세스다. dockerd가 전체 프로세스에 영향을 미친다. 그러므로 dockerd 문제 발생시 docker 정상 사용이 불가능하다. 클라이언트와 서버, 즉 컨테이너와 데몬과의 통신은 /var/run/docker.sock 파일로 진행되며 이 파일이 존재해야 정상 작동된다. DinD(docker in docker) 같은 경우는 link를 걸어서 소켓 파일 공유한다. 바깥 도커의 것을 사용한다.
  • Registry는 도커 이미지가 저장되어 있는 장소로 퍼블릭 레지스트리와 프라이빗 레지스트리로 나뉜다. 대표적으로 docker hub가 있다.
  • 이미지: 데몬을 통해 컨테이너로 실행되는 프로그램, 라이브러리, 소스 등이 설치된 파일이다.

 

 

관련 용어

용어 설명
도커 컨테이너를 관리하는 도구
도커 호스트 하나 이상의 도커 컨테이너를 실행하는 리눅스 머신
도커 데몬 도커 클라이언트의 요청을 받아 도커 컨테이너를 실행/종료/관리함
도커 클라이언트 도커 명령을 실행하는 머신
도커 허브 도커 이미지를 올리고 받고 검색할 수 있는 공식 리포지토리
도커 이미지 도커 컨테이너의 초기 상태를 기록한 파일 (iso처럼)
컨테이너 도커 이미지를 실행한 상태, 하나의 프로세스라고도 할 수 있다

 

 

도커 설치

Docker 사이트의 설치 가이드를 따르면 된다. (ex. centos) https://docs.docker.com/engine/install/centos/

 

Install Docker Engine on CentOS

 

docs.docker.com

다음은 centos7/8에서의 설치 과정이다.

 

* 설치 전, 기존 설치된 도커를 삭제하고 싶을 경우

yum remove docker

1. 도커 리포지토리 셋업

yum install -y yum-utils

yum-config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

 

2. 도커 엔진 설치

sudo yum install docker-ce docker-ce-cli containerd.io docker-compose-plugin

centos 8에서 설치 시 try to add '--allowerasing' to command line to replace conflicting packages or '--skip-brokeip uninstallable packages or '--nobest' to use not only best candidate packages 메시지가 출력될 경우 --allowerasing 옵션을 추가해 주면 된다. centos 8에 기본 설치되어 있는 podman 관련 패키지가 삭제된다.

 

* 버전을 선택하고 싶을 경우 리스트에 있는 버전 확인 후 선택하여 설치하면 된다.

yum list docker-ce --showduplicates | sort -r
docker-ce.x86_64            3:20.10.9-3.el7                    docker-ce-stable
docker-ce.x86_64            3:20.10.8-3.el7                    docker-ce-stable
docker-ce.x86_64            3:20.10.7-3.el7                    docker-ce-stable

yum install docker-ce-<3.20.10.9> docker-ce-cli-<3.20.10.9> containerd.io docker-compose-plugin


3. 도커 서비스 실행, 자동 실행 설정

systemctl start docker
systemctl enable docker
systemctl status docker

 

4. 도커 상태 확인

docker info

docker version

 

 

도커 파일 시스템

도커는 파일 시스템으로 overlay2를 이용한다.

$ docker info | grep Storage
Storage Driver: overlay2

 

이미지 파일 다운로드, 설치, 실행을 포함하고 있는 run 명령어를 통해 이미지 파일을 다운받는 과정을 살펴보면 다음과 같다.

$ docker run -d --name web nginx
Unable to find image 'nginx:latest' locally
latest: Pulling from library/nginx
7d63c13d9b9b: Pull complete
15641ef07d80: Pull complete
392f7fc44052: Pull complete
8765c7b04ad8: Pull complete
8ddffa52b5c7: Extracting [==================================================>] 665B/665B
353f1054328a: Download complete
Digest: sha256:dfef797ddddfc01645503cef9036369f03ae920cac82d344d58b637ee861fda1
Status: Downloaded newer image for nginx:latest
83e9d030b9010ea327e78a2009cb04bdb6891388c5ed99937ccd6fec2bfc86c6

$ docker ps
CONTAINER ID   IMAGE   COMMAND                  CREATED          STATUS          PORTS     NAMES
83e9d030b901   nginx   "/docker-entrypoint.…"   13 minutes ago   Up 13 minutes   80/tcp    web

 

먼저 로컬에 해당 이미지가 있는지 찾아보고, 없다면 라이브러리에서 제일 최신(latest) 버전을 Pull하여 당겨온다. 한 가지 파일은 여러 레이어로 되어 있어서, 각 레이어를 다운로드 받은 후 하나의 이미지로 합쳐지게 된다. run 명령어의 마지막줄과 CONTAINER ID를 비교해 보면 앞 부분이 같다는 것을 확인할 수 있다.

 

 

읽고 쓰기가 가능한 컨테이너 레이어에서 해당 컨테이너의 수정이 이루어진다.

삭제 시, 이미지 레이어는 삭제되지 않지만 컨테이너 레이어는 해당 컨테이너가 종료될 경우 같이 소멸된다. 만약 사용자가 Container Layer에서 작업하던 내용을 Image layer로 적용하고 싶을 경우 docker commit을 사용하면 된다. docker commit을 사용하게 되면 기존의 Image layer들과 직접 작성한 Container Layer를 이용해 새로운 이미지를 생성할 수 있다.

 

 

도커 명령어

기본적으로는 docker --help 명령어를 통해 사용 가능한 명령어의 확인이 가능하다.

자주 사용하는 몇 가지만 간략히 소개한 후 글을 마치도록 하겠다.

  • docker attach – 러닝 중인 컨테이너 내부 접속
  • docker build – 도커 이미지 생성
  • docker commit – 새로운 이미지 생성
  • docker exec – 러닝 중인 컨테이너 내부로 명령 전달
  • docker images – 도커 이미지 조회
  • docker inspect – 이미지/컨테이너 세부 정보 출력
  • docker kill – 컨테이너 죽이기
  • docker ps – 컨테이너 목록 조회
  • docker pull – 이미지 당겨오기
  • docker push – 이미지 저장소에 올리기
  • docker run – 이미지 당겨와서 컨테이너 생성 후 실행
  • docker rm – 컨테이너 삭제
  • docker rmi – 도커 이미지 삭제
  • docker search – 도커 허브에서 이미지 검색
  • docker top – 도커 삭제
  • create, start, stop, restart…
728x90
728x90

※ (2021.01.03) K8S 1.23 버전에서는 Trident install 불가합니다.

[root@master trident-installer]# ./tridentctl install -n trident
INFO Created Kubernetes clients.                   namespace=default version=v1.23.1
ERRO Kubernetes version 1.23.1 is an unsupported Kubernetes version; Trident supports Kubernetes versions in the range [1.17, 1.22]. NetApp will not take Support calls or open Support tickets when using Trident with an unsupported Kubernetes version.

 

알아야 할 것: PV, PVC, CSI 관련 문서

매뉴얼: https://netapp-trident.readthedocs.io/en/latest/kubernetes/deploying/tridentctl-deploy.html

(2024.04.15) trident 매뉴얼 문서 링크 변경됨 -> https://docs.netapp.com/us-en/trident/trident-use/ontap-nas-prep.html#requirements

 

(2023.10.17) tanzu에 설치하는 경우 vserver의 nfs에 mount-rootonly 옵션을 enable해 줘야 하는 경우도 있음

https://docs.netapp.com/us-en/netapp-solutions/containers/tanzu_with_netapp/vtwn_trident_ontap_nfs.html#create-an-svm-in-ontap


1. Download & extract the installer

* wget 없을 시 설치 (yum install wget)

[root@master ~]# wget https://github.com/NetApp/trident/releases/download/v21.07.2/trident-installer-21.07.2.tar.gz
[root@master ~]# tar -xf trident-installer-21.07.2.tar.gz
[root@master ~]# cd trident-installer

[root@master ~]# pwd
/root/trident-installer

2. Install Trident

[root@master ~]# ./tridentctl install -n trident
....
INFO Starting Trident installation.                namespace=trident
INFO Created service account.
INFO Created cluster role.
INFO Created cluster role binding.
INFO Added finalizers to custom resource definitions.
INFO Created Trident service.
INFO Created Trident secret.
INFO Created Trident deployment.
INFO Created Trident daemonset.
INFO Waiting for Trident pod to start.
INFO Trident pod started.                          namespace=trident pod=trident-csi-679648bd45-cv2mx
INFO Waiting for Trident REST interface.
INFO Trident REST interface is up.                 version=21.07.2
INFO Trident installation succeeded.
....

[root@master ~]# kubectl get pod -n trident
NAME                           READY   STATUS    RESTARTS   AGE
trident-csi-679648bd45-cv2mx   4/4     Running   0          5m29s
trident-csi-vgc8n              2/2     Running   0          5m29s

[root@master ~]# ./tridentctl -n trident version
+----------------+----------------+
| SERVER VERSION | CLIENT VERSION |
+----------------+----------------+
| 21.07.2        | 21.07.2        |
+----------------+----------------+

3. setup directory의 yaml 수정 (스토리지 파트 참조)

매뉴얼: https://netapp-trident.readthedocs.io/en/latest/kubernetes/operations/tasks/backends/ontap/index.html

Assigning aggregates to SVMs: 연동할 Netapp SVM에 -aggr-list 속성을 지정해 줘야 한다. (link)

 

backend.json은 연동할 NetApp Storage에 대한 정보를 기입한다. 해당 부분은 스토리지 엔지니어에게 문의하면 된다.

storagePrefix는 스토리지에 생성되는 볼륨의 Prefix로, 정한 이후 수정이 불가능하다.

[root@master ~]# cp sample-input/backends-samples/ontap-nas/backend-ontap-nas.json backend.json
[root@master ~]# vi backend.json
[root@master ~]# cat backend.json
{
    "debug": true,
    "version": 1,
    "storageDriverName": "ontap-nas",
    "backendName": "ontap-nas_git",
    "managementLIF": "10.100.30.43",
    "dataLIF": "10.100.31.105",
    "svm": "<svm_name>",
    "username": "<username>",
    "password": "<password>",
    "aggregate": "<aggr_name>",
    "storagePrefix": "<k8s_>"
}

[root@master ~]# ./tridentctl -n trident create backend -f backend.json
+---------------+----------------+--------------------------------------+--------+---------+
|     NAME      | STORAGE DRIVER |                 UUID                 | STATE  | VOLUMES |
+---------------+----------------+--------------------------------------+--------+---------+
| ontap-nas_git | ontap-nas      | ********-****-****-****-************ | online |       0 |
+---------------+----------------+--------------------------------------+--------+---------+

.[root@master ~]# ./tridentctl -n trident get backend
+---------------+----------------+--------------------------------------+--------+---------+
|     NAME      | STORAGE DRIVER |                 UUID                 | STATE  | VOLUMES |
+---------------+----------------+--------------------------------------+--------+---------+
| ontap-nas_git | ontap-nas      | ********-****-****-****-************ | online |       0 |
+---------------+----------------+--------------------------------------+--------+---------+

4. storage class 적용

[root@master ~]# cp sample-input/storage-class-samples/storage-class-csi.yaml.templ sample-input/storage-class-basic-csi.yaml
[root@master ~]# vi sample-input/storage-class-basic-csi.yaml
[root@master ~]# cat sample-input/storage-class-basic-csi.yaml
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
  name: netapp-csi
  annotations:
    storageclass.kubernetes.io/is-default-class: "true"
provisioner: csi.trident.netapp.io
parameters:
  backendType: "ontap-nas"
  provisioningType: thin
  snapshots: "True"

[root@master ~]# kubectl create -f sample-input/storage-class-basic-csi.yaml
storageclass.storage.k8s.io/netapp-csi created

[root@master ~]# kubectl get sc netapp-csi
NAME                   PROVISIONER             RECLAIMPOLICY   VOLUMEBINDINGMODE   ALLOWVOLUMEEXPANSION   AGE
netapp-csi (default)   csi.trident.netapp.io   Delete          Immediate           false                  25s

[root@master ~]# ./tridentctl -n trident get storageclass netapp-csi -o json
{
  "items": [
    {
      "Config": {
        "version": "1",
        "name": "netapp-csi",
        "attributes": {
          "backendType": "ontap-nas",
          "provisioningType": "thin",
          "snapshots": "true"
        },
        "storagePools": null,
        "additionalStoragePools": null
      },
      "storage": {
        "ontap-nas_git": [
          "n2_aggr1"
        ]
      }
    }
  ]
}

* 설치 중 문제 발생시 trident 완전 삭제

https://netapp-trident.readthedocs.io/en/stable-v20.01/kubernetes/troubleshooting.html#troubleshooting

./tridentctl -n trident obliviate crd


* 테스트

각 node에 nfs-util이 설치되어 있어야 한다 (yum install -y nfs-utils)

설치 후 reboot

 

1. PVC 생성

[root@master ~]# cat sample-input/pvc-basic.yaml
kind: PersistentVolumeClaim
apiVersion: v1
metadata:
  name: basic
spec:
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 1Gi
  storageClassName: netapp-csi

[root@master ~]# kubectl create -f sample-input/pvc-basic.yaml
persistentvolumeclaim/basic created

[root@master ~]# kubectl get pvc
NAME    STATUS   VOLUME                                     CAPACITY   ACCESS MODES   STORAGECLASS   AGE
basic   Bound    pvc-18b6c7af-a289-4c08-a82e-28289fdc477d   1Gi        RWO            netapp-csi     2s

2. pod 생성

[root@master ~]# vi task-pv-pod.yaml
[root@master ~]# cat task-pv-pod.yaml
kind: Pod
apiVersion: v1
metadata:
  name: task-pv-pod
spec:
  volumes:
    - name: task-pv-storage
      persistentVolumeClaim:
       claimName: basic
  containers:
    - name: task-pv-container
      image: nginx
      ports:
        - containerPort: 80
          name: "http-server"
      volumeMounts:
        - mountPath: "/usr/share/nginx/html"
          name: task-pv-storage

[root@master ~]# kubectl create -f task-pv-pod.yaml
pod/task-pv-pod created

[root@master ~]# kubectl get pod
NAME          READY   STATUS    RESTARTS   AGE
task-pv-pod   1/1     Running   0          9m13s

[root@master ~]# kubectl exec -it task-pv-pod -- df -h /usr/share/nginx/html
Filesystem                                                   Size  Used Avail Use% Mounted on
10.100.31.105:/k8s_pvc_18b6c7af_a289_4c08_a82e_28289fdc477d  1.0G  320K  1.0G   1% /usr/share/nginx/html

스토리지에서도 만들어진 PV 볼륨을 확인할 수 있다.

C190::> vol show
Vserver   Volume       Aggregate    State      Type       Size  Available Used%
--------- ------------ ------------ ---------- ---- ---------- ---------- -----
k8s       k8s_pvc_18b6c7af_a289_4c08_a82e_28289fdc477d
                       n2_aggr1     online     RW          1GB     1023MB    0%
728x90