3. 기초 오브젝트 - ConfigMap, namespace

데일리·2023년 10월 16일
1


위의 사진을 보면 몇개의 설정차이 (SSH, user)과 같은 요인들 때문에 각각 컨테이너를 생성하는 것은 자원의 낭비이다.

이를 해결하도록 나온 방법이 ConfigMap, Secret, Pod를 생성 시에 ConfigMap, Secret을 연결하면 Container의 환경 변수에 해당 값이 들어가게 되고 그 값을 Pod에서 사용이 가능하다!

1) ConfigMap, Secret - Literal


ConfigMap과 Secret의 차이는 아래와 같다

  • ConfigMap > key: value로 이루어져있고 정의해두면 해당 내용을 읽어서 사용이 가능

    • yaml파일 > kind에 ConfigMap / data에 key:value를 넣어서 사용
    • 쿠버네티스 DB에 저장이 된다
  • Secret > key: value로 이루어져있고 주로 보안적인 내용을 담아서 사용

    • yaml파일 > kind에 ConfigMap / data에 key:value를 넣어서 사용
    • 보안이 강조된 부분
      - value는 Base64로 인코딩해서 넣어야 한다
      • 메모리에 (1M)까지 저장이 가능

위의 사진 처럼 키와 벨류값을 통해 ConfigMap, Secret의 값을 할당해주었고, Secret은 값이 암호화되어 있는 것을 볼 수 있고 Pod안에서는 자동으로 디코딩되어서 나타난다.

2) ConfigMap, Secret - File


파일 또한 ConfigMap과 Secret에 할당할 수 있다. 주로 파일의 이름이 key 파일안의 내용이 value로 사용이 된다.

여기서 주의할 점은 kubectl create secret 을 사용할 때 file의 내용이 Base64로 인코딩되므로 따로 인코딩한 값을 넣어주게 되면 2번 인코딩이 되버린다는 점이다

그렇다면 Pod를 만든 후에 ConfigMap의 내용을 변경하면 어떻게 될까?

정답은 이미 Pod를 만들 때 주입된 내용이기 떄문에 ConfigMap의 내용이 변경되었을지라도 pod의 환경 변수에는 영향을 주지 못한다. 즉 pod가 재생성되어야만 변경된 값이 적용된다.

3) ConfigMap, Secret - Volumn mount File


위의 사진처럼 컨테이너 안에 mount path를 정의하고 파일 마운트를 할 수 있는데 위 방법은 2번째 방식과는 다르게 ConfigMap이 달라지면 pod에 연결된 값도 변경이 된다.

4) 실습

1. Literal

kubectl get configmap -n <네임스페이스>

kubectl get secret -n <네임스페이스>

위 코드로 정의된 ConfigMap과 Secret을 조회할 수 있다.

kubectl exec -it <pod 이름> -c <container 이름> -- /bin/sh

kubectl exec -it pod-1 -c container -- /bin/sh

sh-4.2# env
HOSTNAME=pod-1
TERM=xterm
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT=tcp://10.0.0.1:443
SSH=false
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_HOST=10.0.0.1
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
Key=1234
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
User=dev
KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1
KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443
container=docker
_=/usr/bin/env

해당 코드로 환경변수를 정의하면 key와 value값이 정의된 것을 볼 수 있다.

2. File

echo "Content" >> file-c.txt                                       4m 13s
kubectl create configmap cm-file2 --from-file=./file-c.txt
configmap/cm-file2 created

echo "Content" >> file-s.txt
kubectl create secret generic sec-file2 --from-file=./file-s.txt
secret/sec-file2 created

이 때 secret의 "Content"는 base64 인코딩 된 값이 아니다는 것을 기억하자 자동으로 create secret하면서 인코딩을 해주기 때문이다.

apiVersion: v1
kind: Pod
metadata:
  name: pod-file
spec:
  containers:
  - name: container
    image: kubetm/init
    env:
    - name: file-c // 나중에 환경 변수의 key가 됨
      valueFrom:
        configMapKeyRef: 
          name: cm-file // configmap 이름
          key: file-c.txt // 파일 이름
    - name: file-s // 나중에 환경 변수의 key가 됨
      valueFrom:
        secretKeyRef:
          name: sec-file // secret 이름
          key: file-s.txt // 파일 이름

pod을 위와 같이 생성하고 아래와 같이 env가 조회되는 것을 볼수 있다.

kubectl exec -it pod-file -c container -- /bin/sh
sh-4.2# env

file-c=Content

HOSTNAME=pod-file
TERM=xterm
KUBERNETES_PORT_443_TCP_PORT=443
KUBERNETES_PORT=tcp://10.0.0.1:443
KUBERNETES_SERVICE_PORT=443
KUBERNETES_SERVICE_HOST=10.0.0.1
file-s=Content

PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
PWD=/
SHLVL=1
HOME=/root
KUBERNETES_PORT_443_TCP_PROTO=tcp
KUBERNETES_SERVICE_PORT_HTTPS=443
KUBERNETES_PORT_443_TCP_ADDR=10.0.0.1
KUBERNETES_PORT_443_TCP=tcp://10.0.0.1:443
container=docker
_=/usr/bin/env

3. volumn mount

apiVersion: v1
kind: Pod
metadata:
  name: pod-mount
spec:
  containers:
  - name: container
    image: kubetm/init
    volumeMounts:
    - name: file-volume
      mountPath: /mount
  volumes:
  - name: file-volume
    configMap:
      name: cm-file2 // 파일 이름

위와 같이 mount path를 지정해주고

kubectl exec -it pod-mount -c container -- /bin/sh                 5m 20s

sh-4.2# ls
anaconda-post.log  boot  etc   lib    media  mount  proc  run	srv  tmp  var
bin		   dev	 home  lib64  mnt    opt    root  sbin	sys  usr

sh-4.2# cd mount
sh-4.2# ls
file-c.txt

sh-4.2# cat *
Content

위의 path를 조회하면 file이 조회된는 것을 볼 수 있다.

5) Namespace, ResourceQuota, LimitRange


위의 사진 처럼 Cluster 안에서 사용할 수 있는 자원 > Memory, Cpu 등 이런 메모리들은 Namespace 내의 pod에서 이를 공유한다.

그러나 하나의 namespace에서 자원의 독점의 이슈가 생길 수 있는데 이를 방지하는 것이 ResourceQuota이다

아래의 사진처럼 ResourceQuota는 각 namespace마다 자원의 최대 한계를 정해놓을 수 있다.

그러나 namespace안에서 하나의 pod이 자원을 독접하게 된다면 어떻게 될까? 이를 관리하기 위한 것이 Limit Range이다


위의 사진처럼 LimitRange를 사용하면 해당 범위를 벗어난 pod은 생성이 불가한 것을 볼 수 있다.

1. namespace

  • namespace 내에 같은 이름의 pod 생성 불가
  • 다른 namespace에 있는 자원과 분리되어 있음
  • namespace를 지우면 안에 있는 자원 또한 모두 삭제

2. ResourceQuota

  • namespace의 자원의 한계를 설정한다.
  • ResourceQuota가 지정되어 있는 namespace에 pod을 만드려면 => pod에 memory 등 resource stack이 무조건 명시되어 있어야 한다.
  • 주의할 점
    • ResourceQuota 없이 pod를 만들고 이후에 resourceQuota를 만들면 해당 pod들은 그대로 존재하게 된다.
      => 즉 namespace에 지정된 resourceQuota 데이터 보다 더 많은 자원을 사용하게 된다.
      => resourceQuota를 생성하기전 생성된 pod이 없는 지 확인해야한다.

3. LimitRange

  • 각각의 pod마다 namespace에 들어갈 수 있는 자원을 체크
  • min: pod 설정 memory limit가 min 값보다 커야함
  • max: pod 설정 memory limit가 max값 초과 불가능
  • maxLimitRequestRatio : request 값과 limit 값의 비율 최대 값
  • defaultRequest, defualt : pod에 아무런 설정하지 않았을 때 pod가 해당 값으로 자동 생성됨
  • 주의할 점
    • 한 namespace에 여러개의 limitrange가 들어갈 수 있는데 그러면 예상치 못한 동작을 할 수 있기 때문에 주의해햔다.
    • ex) A 리미트 레인지의 default값 > B 리미트 레인지의 max값인 경우 등

4. Request & Limit


위의 그림처럼 request는 생성될 때 요청하는 리소스 양이고 limit는 컨테이너가 생성된 후에 실행되다가 리소스가 더 필요한 경우 추가로 더 사용할 수 있는 부분이다.

profile
하루에 한편 씩 읽기 좋은 테크 로그

0개의 댓글