버전 비교

  • 이 줄이 추가되었습니다.
  • 이 줄이 삭제되었습니다.
  • 서식이 변경되었습니다.
목차

...

...

1. Resource Policies

2.1 Request / Limit (최소요구사항/최대 사용량)

  • 쿠버네티스에서 파드를 어느 노드에 배포할지 스케쥴링 할 때, 스케쥴링이 될 노드에 해당 파드가 동작할 수 있는 충분한 자원이 확보가 되어야 합니다.

  • 쿠버네티스에서 파드(컨테이너)에 필요한 리소스 양을 명시 할 수 있도록 설정을 지원합니다.

  • cpu/memory와 같은 컴퓨트 리소스 외에도 gpu/storage 리소스에 대한 쿼터도 지정 할 수 있습니다.

  • CPU는 m(밀리코어, 1코어=1000밀리코어) 단위로 지정하며, 해당 컨테이너에 어느정도의 CPU를 할당할 것인지를 지정합니다.

  • 메모리는 Mi(Mib)를 사용합니다.

...

코드 블럭
root@k8s-master01:~# kubectl -n kube-system top pod | sort -n -k 2
NAME                                       CPU(cores)   MEMORY(bytes)
nginx-proxy-k8s-worker01                   1m           16Mi
nginx-proxy-k8s-worker02                   1m           17Mi
dns-autoscaler-59b8867c86-hjkvs            2m           7Mi
kube-controller-manager-k8s-master02       4m           19Mi
kube-controller-manager-k8s-master03       4m           19Mi
nodelocaldns-rdkbl                         4m           15Mi
coredns-588bb58b94-9qcvw                   5m           16Mi
kube-scheduler-k8s-master02                5m           20Mi
nodelocaldns-sd99v                         5m           10Mi
coredns-588bb58b94-zcnvc                   6m           14Mi
kube-proxy-h584h                           7m           22Mi
kube-scheduler-k8s-master03                7m           19Mi
nodelocaldns-9vlvr                         7m           9Mi
nodelocaldns-b8gpm                         7m           9Mi
metrics-server-6f77f96b88-v5jjs            8m           17Mi
nodelocaldns-r4sjf                         8m           16Mi
kube-scheduler-k8s-master01                9m           21Mi
kube-proxy-x8gcq                           12m          22Mi
calico-kube-controllers-75748cc9fd-gqdzw   13m          21Mi
kube-proxy-w87v4                           13m          15Mi
kube-proxy-96tsm                           20m          15Mi
kube-proxy-tj8pv                           24m          14Mi
kube-controller-manager-k8s-master01       36m          52Mi
calico-node-87g22                          42m          85Mi
calico-node-kk5vn                          51m          84Mi
calico-node-wckv7                          51m          85Mi
calico-node-8278d                          64m          91Mi
etcd-k8s-master02                          70m          89Mi
calico-node-4hzx4                          71m          109Mi
kube-apiserver-k8s-master02                77m          303Mi
etcd-k8s-master03                          81m          84Mi
kube-apiserver-k8s-master01                94m          349Mi
etcd-k8s-master01                          99m          95Mi
kube-apiserver-k8s-master03                111m         310Mi

2.2 ResourceQuota

  • 쿠버네티스 운영 시 특정 팀에서 많은 리소스를 요구할 경우 ResourceQuota를 이용하여 네임스페이스별로 사용할 수 있는 리소스의 양을 정하고, 컨테이너 마다 사용 할 수 있는 양을 지정할 수 있습니다.

...

코드 블럭
root@k8s-master01:~# kubectl get pod
NAME                               READY   STATUS    RESTARTS   AGE
nginx-deployment-5bccc488d-bqkvz   1/1     Running   0          18h
nginx-deployment-5bccc488d-r4s5d   1/1     Running   0          18h
nginx-deployment-5bccc488d-z29wp   1/1     Running   0          18h

root@k8s-master01:~# kubectl get quota
NAME      AGE   REQUEST                                         LIMIT
default   32s   cpu: 750m/1k, memory: 192Mi/200Gi, pods: 3/10

2.3 LimitRange

  • ResourceQuota를 사용하면 네임스페이스의 리소스를 제한하고, LimitRange는 네임스페이스 내 파드(컨테이너)의 리소스를 제한합니다.

  • 사용자가 컨테이너 리소스를 너무 크게 사용하면 특정 컨테이너가 많은 리소스를 점유하는 것을 방지할 수 있기 때문에 LimitRange를 사용합니다.

...

코드 블럭
root@k8s-master01:~# cat LimitRange.yaml
apiVersion: v1
kind: LimitRange
metadata:
  name: cpu-min-max-demo-lr
  namespace: default
spec:
  limits:
  - max:
      cpu: "800m"
    min:
      cpu: "200m"
    type: Pod #Container
root@k8s-master01:~# more nginx-deploy.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: nginx-deployment
  labels:
    app: nginx
spec:
  replicas: 3
  selector:
    matchLabels:
      app: nginx
  template:
    metadata:
      labels:
        app: nginx
    spec:
      containers:
      - name: nginx
        image: nginx:1.19
        ports:
        - containerPort: 80
        resources:
          requests:
            memory: "64Mi"
            cpu: "1000m"
          limits:
            memory: "128Mi"
            cpu: "1500m"

경고

root@k8s-master01:~# # kubectl get event --sort-by='lastTimestamp'
LAST SEEN TYPE REASON OBJECT MESSAGE
78s Warning FailedCreate replicaset/nginx-deployment-8579d7f98c Error creating: pods "nginx-deployment-8579d7f98c-mxw8q" is forbidden: maximum cpu usage per Pod is 800m, but limit is 1500m

...

2. Label & Selector

  • Label

    • Label은 Pod와 같은 객체에 연결된 키/값 쌍입니다.

    • 리소스를 논리적인 그룹으로 나누거나, 식별의 편의를 위해 붙이는 이름표입니다.

    • Label은 생성 시 객체에 첨부할 수 있으며 나중에 언제든지 추가 및 수정할 수 있습니다.

  • Selector

    • 특정 Label에 해당하는 객체를 식별하고 검색할 수 있습니다.

2.1 Node Label

...

코드 블럭
# Node Label 확인
kubectl get nodes --show-labels

# Node Label 추가
kubectl label nodes k8s-worker01 svc=web

2.2 Pod Selector

pod-label.yml

코드 블럭
apiVersion: v1
kind: Pod
metadata:
  name: nginx
  labels:
    env: test
spec:
  containers:
  - name: nginx
    image: nginx
    imagePullPolicy: IfNotPresent
  nodeSelector:
    svc: web

...

3. 쿠버네티스 볼륨

  • PV(PersistentVolume): PV는 관리자가 프로비저닝했거나 스토리지 클래스를 사용해 동적으로 프로비저닝한 클러스터의 스토리지입니다. PV는 볼륨과 같은 볼륨 플러그인이지만 PV를 사용하는 개별 Pod와 독립적인 수명 주기를 가집니다.

  • PVC(PersistentVolumeClaim): PVC는 사용자가 볼륨을 사용하기 위해 PV에 하는 스토리지 요청입니다. Pod와 유사하게 Pod는 노드 리소스를 소비하고, PVC는 PV 리소스를 소비합니다.

3.1 PV의 Lifecycle

...

...

(1

...

) Provisioning

PV를 생성하는 단계로 프로비저닝 방법에는 두 가지가 있습니다.

  • 정적 프로비저닝

    • 정적 프로비저닝은 클러스터 관리자가 미리 적정 용량의 PV를 만들어 두고 사용자의 요청이 있을 시 미리 만들어 둔 PV를 할당하는 방식입니다.

    • 사용할 수 있는 스토리지 용량에 제한이 있을 때 유용합니다.

  • 동적 프로비저닝

    • 동적 프로비저닝은 사용자가 PVC를 거쳐서 PV를 요청했을 때 생성해 제공합니다.

    • 클러스터에 사용자가 원하는 만큼의 스토리지 용량이 있다면, 원하는 용량만큼을 생성해서 사용할 수 있습니다.

...

(2) Binding

바인딩은 프로비저닝으로 생성된 PV를 PVC와 연결하는 단계입니다. PVC에서 원하는 스토리지 용량과 접근방법을 명시해서 용청하면 거기에 맞는 PV가 할당됩니다. PV와 PVC의 매핑은 1대1 관계입니다.

(3

...

) Using

PVC는 Pod에 설정되고, Pod는 PVC를 볼륨으로 인식해서 사용합니다. 클러스터는 PVC를 확인하여 바인딩된 PV를 찾고 해당 볼륨을 Pod에서 사용할 수 있도록 해줍니다. 할당된 PVC는 파드를 유지하는 동안 계속 사용되며, 시스템에서 임의로 삭제할 수 없습니다.

...

(4) Reclaiming

사용이 끝난 PVC는 삭제되고, PV를 초기화(reclaim)하는 과정을 거칩니다. PV는 기존에 사용했던 PVC가 아니더라도 다른 PVC로 재활용이 가능합니다.

  • PV 초기화 정책

    • Retain: PV의 데이터를 그대로 보존합니다.

    • Recycle: 재사용하게 될 경우 기존의 PV 데이터들을 모두 삭제 후 재사용합니다.

    • Delete: 사용이 종료되면 해당 볼륨을 삭제합니다.

3.2 PV 생성

코드 블럭
apiVersion: v1
kind: PersistentVolume
metadata:
  name: test-pv
  labels:
    name: test-pv
spec:
  capacity:
    storage: 1Gi
  accessModes:
  - ReadWriteMany
  hostPath:
    path: "/test/volume"

# Value
- capacity: 사용할 용량을 설정합니다.
- accessModes:특정 접근 모드를 선택합니다.
- hostPath: 노드에 저장되는 디렉토리를 설정합니다.

# 적용하기
kubectl apply -f test-pv.yaml

# PV 조회
kubectl get pv
NAME      CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS      CLAIM   STORAGECLASS   REASON   AGE
test-pv   1Gi        RWX            Retain           Available                                   15s

3.3 PVC 생성

코드 블럭
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: test-pvc
spec:
  accessModes:
    - ReadWriteMany
  resources:
    requests:
     storage: 1Gi

kubectl apply -f test-pvc.yaml

# PV, PVC 조회
 kubectl get pv,pvc
NAME                       CAPACITY   ACCESS MODES   RECLAIM POLICY   STATUS   CLAIM              STORAGECLASS   REASON   AGE
persistentvolume/test-pv   1Gi        RWX            Retain           Bound    default/test-pvc                           2m22s

NAME                             STATUS   VOLUME    CAPACITY   ACCESS MODES   STORAGECLASS   AGE
persistentvolumeclaim/test-pvc   Bound    test-pv   1Gi        RWX                           18s
=> PV와 PVC가 연결되어 PV가 Bound 상태로 변경된 것을 확인할 수 있습니다.

3.4 PVC를 사용할 Pod 생성

코드 블럭
apiVersion: v1
kind: Pod
metadata:
  name: test-nginx2
spec:
  containers:
  - name: test-nginx2
    image: nginx:1.19
    ports:
    - containerPort: 80
    volumeMounts:
      - mountPath: "/test/volume"
        name: test-pv
  volumes:
  - name: test-pv
    persistentVolumeClaim:
      claimName: test-pvc

# 옵션
- volumeMounts.mountPath: 볼륨 마운트할 컨테이너 안의 경로를 작성합니다.
- volumes:.persistentVolumeClaim: 컨테이너에서 사용할 PV의 이름을 가져오고, PV와 연결되어 있으며 요청을 보낼 PVC를 지정합니다.

# 적용하기
kubectl apply -f test-nginx2.yaml

# 확인해보기
# 외부에서 확인
# kubectl describe pod test-nginx2 | grep -A1 Mounts
    Mounts:
      /test/volume from test-pv (rw)

# 컨테이너 내부에서 확인
kubectl exec -it test-nginx2 -- bash
root@test-nginx2:/# df -Th | grep volume
/dev/vda1      xfs       50G  3.7G   47G   8% /test/volume
=> 지정한 경로에 볼륨이 마운트된 것을 확인할 수 있습니다.

# 컨테이너 내부에서 test용 파일 생성
root@test-nginx2:/# touch /test/volume/test.txt

# PV 생성 시 설정한 노드의 경로에서도 확인이 가능합니다.
[root@worker-node ~]# ls -al /test/volume/
total 0
drwxr-xr-x 2 root root 22 Mar 10 06:22 .
drwxr-xr-x 3 root root 20 Mar 10 06:18 ..
-rw-r--r-- 1 root root  0 Mar 10 06:22 test.txt

4. 컨피그맵

  • Key-Value 쌍으로 기밀이 아닌 데이터를 저장하는 데 사용하는 API 오브젝트입니다.

  • 컨테이너 이미지에서 환경 별 구성을 분리하여, 애플리케이션을 쉽게 이식할 수 있습니다.

  • 개발/운영 환경의 컨테이너는 동일하게 구성하고, 컨피그맵 설정을 다르게 적용하여 서비스를 관리할 수 있습니다.

  • 파드와 컨피그맵은 동일한 네임스페이스에 있어야 합니다.

4.1 컨피그맵 사용

4.1.1 컨피그맵을 생성합니다.

코드 블럭
apiVersion: v1
kind: ConfigMap
metadata:
  name: prod-account
  namespace: default
data:
  ID: prod-user
  PASSWORD: prod-pass
  LOG_LEVEL: info

4.1.2 컨테이너에서 prod-account 컨피그맵의 LOG_LEVEL값을 가지고 오도록 설정합니다.

코드 블럭
piVersion: apps/v1
kind: Deployment
metadata:
  name: configmap-test
  labels:
    app: prod
spec:
  replicas: 1
  selector:
    matchLabels:
      app: prod
  template:
    metadata:
      labels:
        app: prod
    spec:
      containers:
      - name: testapp
        image: nginx:1.19
        ports:
        - containerPort: 8080
        env:
          - name: LOG_LEVEL
            valueFrom:
              configMapKeyRef:
                 name: prod-account
                 key: LOG_LEVEL

4.1.3 설정이 제대로 되었는지 파드 안에서 확인합니다.

코드 블럭
root@k8s-master01:~/kb# kubectl get pod
NAME                              READY   STATUS    RESTARTS   AGE
configmap-test-779ff45747-f4969   1/1     Running   0          80s

root@k8s-master01:~/kb# kubectl exec -it configmap-test-779ff45747-f4969 -- bash

root@configmap-test-779ff45747-f4969:/# env | grep LOG_LEVEL
LOG_LEVEL=info

5. 시크릿

  • 비밀번호, OAuth 토큰, ssh 키와 같은 민감한 정보를 저장하는 용도로 사용됩니다.

  • 시크릿 생성 시 데이터는 base64로 인코딩되어 저장됩니다.

  • 컨피그맵은 보안/암호화를 제공하지 않기 때문에, 저장하려는 데이터가 기밀인 경우, Secret을 사용하여 데이터를 비공개로 유지합니다.

    • 시크릿은 ETCD에 암호화되지 않은 상태로 저장되기 때문에, API 접근 권한이 있는 모든 사용자는 시크릿을 조회/수정 할 수 있습니다.

  • TLS 인증서를 시크릿으로 저장하여 사용하는 경우도 많습니다.

  • secret 리소스의 type 필드로 타입을 명시 할 수 있습니다.

...

빌트인 타입

...

사용처

...

Opaque

...

임의의 사용자 정의 데이터

...

kubernetes.io/service-account-token

...

서비스 어카운트 토큰

...

kubernetes.io/dockercfg

...

직렬화 된(serialized) ~/.dockercfg 파일

...

kubernetes.io/dockerconfigjson

...

직렬화 된 ~/.docker/config.json 파일

...

kubernetes.io/basic-auth

...

기본 인증을 위한 자격 증명(credential)

...

kubernetes.io/ssh-auth

...

SSH를 위한 자격 증명

...

kubernetes.io/tls

...

TLS 클라이언트나 서버를 위한 데이터

...

bootstrap.kubernetes.io/token

...

부트스트랩 토큰 데이터

5.1 불투명(Opaque) 시크릿 사용

5.1.1 명령어로 시크릿 생성

코드 블럭
root@k8s-master01:~/kb# cat prod-user.txt
prod-user
root@k8s-master01:~/kb# cat prod-pass.txt
prod-pass


root@k8s-master01:~/kb# kubectl create secret generic prod-user --from-file=./prod-user.txt --from-file=./prod-pass.txt
secret/prod-user-secret created


root@k8s-master01:~/kb# kubectl get secrets
NAME               TYPE     DATA   AGE
prod-user-secret   Opaque   2      4s


root@k8s-master01:~/kb# kubectl get secrets prod-user-secret -o yaml
apiVersion: v1
data:
  prod-pass.txt: cHJvZC1wYXNzCg==
  prod-user.txt: cHJvZC11c2VyCg==
kind: Secret
metadata:
  creationTimestamp: "2023-03-13T02:35:54Z"
  name: prod-user-secret
  namespace: default
  resourceVersion: "1226226"
  uid: 41a2cb2d-97f2-41bc-824f-c0c2783ec678
type: Opaque


*원래 값 확인방
root@k8s-master01:~/kb# echo cHJvZC11c2VyCg== | base64 --decode
prod-user

5.1.2 yaml 파일로 시크릿 생성

  • yaml 파일로 생성시 필요 값들을 base64로 인코딩된 값을 넣어야 합니다.

코드 블럭
root@k8s-master01:~/kb# echo -n "prod-user" | base64
cHJvZC11c2Vy
root@k8s-master01:~/kb# echo -n "prod-pass" | base64
cHJvZC1wYXNz
  • 시크릿을 생성합니다.

코드 블럭
apiVersion: v1
kind: Secret
metadata:
  name: prod-user
type: Opaque
data:
  username: cHJvZC11c2Vy
  password: cHJvZC1wYXNz
  • 생성된 시크릿을 확인합니다.

코드 블럭
root@k8s-master01:~/kb# kubectl apply -f prod-user-secret.yaml


root@k8s-master01:~/kb# kubectl get secrets
NAME        TYPE     DATA   AGE
prod-user   Opaque   2      5s


root@k8s-master01:~/kb# kubectl get secrets prod-user -o yaml
apiVersion: v1
data:
  password: cHJvZC1wYXNz
  username: cHJvZC11c2Vy
kind: Secret
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: |
      {"apiVersion":"v1","data":{"password":"cHJvZC1wYXNz","username":"cHJvZC11c2Vy"},"kind":"Secret","metadata":{"annotations":{},"name":"prod-user","namespace":"default"},"type":"Opaque"}
  creationTimestamp: "2023-03-13T02:49:45Z"
  name: prod-user
  namespace: default
  resourceVersion: "1228228"
  uid: a5eff12c-2329-4697-92f7-f252a4f724ba
type: Opaque

5.1.3 시크릿 사용

코드 블럭
apiVersion: apps/v1
kind: Deployment
metadata:
  name: secretapp
  labels:
    app: secretapp
spec:
  replicas: 1
  selector:
    matchLabels:
      app: secretapp
  template:
    metadata:
      labels:
        app: secretapp
    spec:
      containers:
      - name: testapp
        image: nginx:1.19
        ports:
        - containerPort: 8080
        env:
          - name: SECRET_USERNAME
            valueFrom:
              secretKeyRef:
                name: prod-user
                key: username
          - name: SECRET_PASSWORD
            valueFrom:
              secretKeyRef:
                name: prod-user
                key: password

...