핵심만 콕 쿠버네티스 (4) - Pod / ConfigMap / Secret

김정욱·2022년 5월 12일
0
post-thumbnail

Pod 리소스

[ Pod 특징 ]

[ 1개 이상의 컨테이너 실행 ]

  • Pod는 1개 이상의 컨테이너를 가질 수 있다
  • 보통은 1개 / 상황에 따라 2개 / 정말 많으면 3개 까지 실행
    => 그 이상으로 넘어가는 경우는 거의 없다

[ 고유의 Pod IP ]

  • 노드 IP와 별개로 Pod는 클러스터 내에서 접근 가능한 고유의 IP를 할당받음
  • k8s에서는 다른 노드에 위치한 Pod더라도 NAT(Network Address Translation) 없이 Pod IP로 접근 가능
  • 같은 Pod에 있는 컨테이너는 모두 동일한 IP를 가진다 => port로 컨테이너 구분

[ Volume 공유 ]

  • Pod 안의 컨테이너끼리 동일한 볼륨으로 연결 가능
  • 파일 시스템을 기반으로 서로 파일을 주고 받을 수 있다

[ Pod의 생성 과정 ]

  1. 사용자가 kubectl 명령을 통해 Pod 정의서를 k8s 마스터(Api Server)에게 전달
  2. k8s는 Pod의 YAML정의의 유효성 체크
  3. kube-scheduler를 통해 특정 노드에 할당하고 사용자의 요청에 따라 컨테이너 실행하도록 명령
  4. 명령을 전달받은 노드의 kubelet은 요청 스펙에 맞춰 실제 컨테이너를 노드에 생성

[ 라벨링 시스템 ]

[ 개요 ]

  • key-value 형태의 라벨을 활용한 매커니즘
  • 특정 리소스 참조 / Pod에 트래픽 전달 등의 목적으로 사용
  • 라벨링 자체는 Pod의 metadata property에 문자열을 추가하는 것에 불과

[ 라벨 부여 방법 ]

  • label 명령어 (명령형 스타일)
    • command 형식 : kubectl label pod <NAME>=<VALUE>
    • ex ) kubectl label pod mynginx hello=world
  • YAML 정의서에 추가 (선언형 스타일)
/* Pod 정의서  */
apiVersion: v1
kind: Pod
metadata:
  labels:
    hello: world // hello=world 라벨 지정
...

[ 라벨 정보 확인 ]

/* -L : 특정 key값의 value 표기 */
kubectl get pod mynginx -L run

/* --show-labels : 전체 라벨 검색 */
kubectl get pod mynginx --show-labels

/* -l : 특정 라벨을 가진 Pod 검색 */
kubectl get pod -l run // run이라는 key를 가진 라벨을 포함한 pod 검색

kubectl get pod -l run=mynginx // run=mynginx 라는 라벨을 포함한 pod 검색

[ nodeSelector ]

  • Pod는 기본적으로 노드에 할당될 때 명시하지 않으면 kube-scheduler가 알아서 할당
  • nodeSelector property를 통해 특정 노드에 Pod 할당 가능
    1) Node에 Label 추가
    2) Pod 정의 YAML에 nodeSelector를 이용해 1)에서 추가한 Label 지정
  • 만약 동일한 노드에 동일한 라벨이 있다면 ?
    • k8s가 노드의 상태 (리소스 사용량 등)을 확인하여 최적의 노드 선택
/* 노드의 라벨 전체 조회 */
kubectl get node --show-labels

/* 1) worker 노드에 라벨 추가 */
kubectl label worker disktype=ssd

/* 1-1) 추가된 라벨 확인 */
kubectl get node worker disktype=ssd

/* 2) Pod의 YAML 정의서에 nodeSelector로 매핑 */
apiVersion: v1
kind: Pod
metadata:
  name: node-selector # Pod 이름
spec:
  nodeSelector:
    disktype: ssd # 추가한 라벨 매핑
...

/* 3) Pod 생성 */
kubectl apply -f node-selector.yaml

/* 4) Pod가 어떤 노드에 할당되었는지 확인 : -o wide 옵션 */
kubectl get pod node-selector -o wide

[ 실행 명령 및 파라미터 지정 ]

  • Pod 생성시 실행 명령(command)과 파라미터(args)를 전달할 수 있다
apiVersion: v1
kind: Pod
...
spec:
  restartPolicy: OnFailure
  containers:
    -name: nginx
     image: nginx
     command: ["/bin/echo"] # 실행 명령 지정
     args: ["hello"] # 파라미터 지정
  • apiVersion
    • 리소스의 이름이 동일할 경우, 이름충돌을 피하기 위한 목적
    • 즉, 리소스의 scope를 정의
  • kind
    • 리소스(오브젝트)의 타입을 정의
  • metadata
    • labels : 리소스의 라벨정보
    • name : 리소스의 이름
  • spec : 리소스의 스펙 정의
    • containers : 1개 이상의 컨테이너 정의
      • name : 컨테이너 이름
      • image : 컨테이너 이미지 주소
      • command : 컨테이너의 시작 실행명령을 지정 (docker의 ENTRYPOINT와 대응)
      • args : 실행 명령에 넘겨줄 파라미터 (docker의 CMD와 대응)
    • restartPolicy : Pod의 재시작 정책
      • Always : Pod 종료시 항상 재시작
      • Never : 재시작 시도 X
      • OnFailure : 실패 시에만 재시작 시도

[ 환경변수 설정 ]

  • spec > containers > envnamevalue를 추가하여 환경변수 설정 가능
apiVersion: v1
kind: Pod
...
spec:
  containers:
    -name: nginx
     image: nginx
     env: # env property로 환경변수 지정
       -name: profile
        value: cbt

[ Volume 연결 ]

  • Pod 내부 스토리지는 Pod가 사라지면 데이터도 함께 삭제된다
  • 가장 기본이 되는 host Volume과 연결하여 데이터를 유지할수 있다
apiVersion: v1
kind: Pod
...
spec:
  containers:
   - name: nginx
     image: nginx
     volumeMounts:
      - mountPath: /container-volume # 컨테이너 내부의 mountPath
        name: my-volume # 연결할 host volume의 name
  volumes:
   - name: my-volume # host volume의 이름
     hostPath: 
       path: /home # host volume의 path
     # emptyDir: {} # Pod내에 임시로 생성되는 공간
  • volumeMounts
    • mountPath : 연결할 컨테이너 내부의 mountPath
    • name : 연결할 host volume의 name
  • volumes
    • name : host volume의 이름 (volumeMounts > name과 대응되는 property)
    • hostPath : host의 연결 위치(volume)
    • emptyDir
      • Pod 내에 임시로 생성되는 공간 (임시 volume)
      • 주로 컨테이너끼리 파일 데이터를 주고 받을 때 사용 => 큰 특징

[ 리소스 관리 ]

[ request / limits ]

  • 컨테이너 실행에 필요한 리소스를 제약할 수 있는 property
  • requests : 최소 리소스 사용량 보장
  • limits : 최대 리소스 사용량 제한
apiVersion: v1
kind: Pod
...
spec:
  containers:
   - name: nginx
     image: nginx
     resources:
       requests:
         cpu: "250m" # 0.25 core
         memory: "500Mi" # 500Mi 메모리
       limits:
         cpu: "500m" # 0.5 core
         memory: "1Gi" # 1Gi 메모리

[ 상태 확인 - liveness / readness ]

[ livenessProbe / readnessProbe ]

apiVersion: apps/v1
kind: Deployment
metadata:
  name: harmony-internship-app
  namespace: default
spec:
  selector:
    matchLabels:
      app: internship-app
  replicas: 1
  template:
    metadata:
      labels:
        app: internship-app
    spec:
      containers:
        - name: internship-app
          image: {image 주소}
          imagePullPolicy: Always 
          readinessProbe: # Pod가 트래픽을 받을 준비가 되어있는지 확인하는 property
            httpGet:
              path: /actuator/health # spring actuator path 적용
              port: 8090
            initialDelaySeconds: 60
            periodSeconds: 5
          livenessProbe: # Pod가 살아있는지 확인하는 property
            httpGet:
              path: /actuator/health # spring actuator path 적용
              port: 8090
            initialDelaySeconds: 60
            periodSeconds: 5
            timeoutSeconds: 2
          lifecycle:
            preStop:
              exec: # Pod가 종료되기 전 graceful한 종료를 위해 sleep 사용 => 10초간은 트래픽을 받지 않고, 받은 트래픽은 모두 처리하기 위함
                command: [ "/bin/sleep","10" ]
  • Http Status code2xx ~ 3xx 인 경우 정상으로 판단
  • livenessProbe이 정상적인 응답을 받지 못하면
    • restartPolicy 에 의해 재시작 수행
    • restartPolicy = Always(기본값) / OnFailure / Never
  • $ kubectl get pod 수행시 나오는 RESTARTS 값이 재시작 횟수를 의미
  • HTTP 통신 뿐만 아니라, 명령 실행(exec)을 통해서도 livenessProbe / readnessProbe 설정 가능
    • return 값이 0 이외의 값이면 모두 비정상으로 인식

[ Pod 디자인 패턴 ]

  • Pod 내 Container의 실행순서는 보장되지 않는다
    => initContainer 프로퍼티로 초기화 작업(initalize) 수행 가능
  • SideCar 패턴
    • 기본 컨테이너의 기능을 확장하거나 강화하는 용도로 컨테이너를 추가하는 패턴
    • 하나의 Pod에 여러개의 Container가 존재하게 된다
    • 로그수집 등등을 목적으로 많이 사용하는 k8s 패턴
  • Adapter 패턴
    • pod 내 proxy 역할을 하는 컨테이너를 추가하는 패턴
    • pod 내에서 외부 서버에 접근할 때 내부 proxy에 접근하고, 실제 외부 연결은 proxy에서 처리
  • Ambassador 패턴
    • Pod 외부로 노출되는 정보를 표준화 하는 역할을 하는 컨테이너를 추가하는 패턴
    • 주로 pod 모니터링 지표를 어댑터 컨테이너를 통해 표준화 형식으로 노출시키고,
      외부의 모니터링 시스템에서 데이터를 주기적으로 가져가서 모니터링에 이용

ConfigMap 리소스

[ ConfigMap 기본 ]

  • k8s에서 설정값들을 따로 모아두고 필요할 때 꺼내 사용할 수 있는 리소스
  • 설정값을 가져와서 Pod에서 사용할 수 있다

[ cli를 통한 ConfigMap 생성 ]

// --from-file 옵션으로 test.properties 파일을 통해 test-config라는 configmap 생성
$ kubectl create configmap test-config --from-file=test.propertis

// configmap 조회 cm이 configmap 약자
$ kubectl get cm test-config -o yaml

// --from-literal 옵션으로 직접 값 설정하면서 configmap 생성
$ kubectl create configmap special-config \
            --from-literal=special.power=10 \
            --from-literal=speical.strength=20

[ yaml을 통한 ConfigMap 생성 ]

apiVersion: v1
kind: ConfigMap
metadata:
  name: test-config
  namespace: default
data: # 데이터 표기
  name: hue 
  age: 27
  money: 10000

[ ConfigMap 활용 ]

[ Pod와 Volume 연결 ]

apiVersion: v1
kind: Pod
metadata:
  name: game-volume
spec:
  restartPolicy: OnFailure
  containers:
  - name: game-volume
    image: k8s.gcr.io/busybox
    command: [ "/bin/sh", "-c", "cat /etc/config/game.properties" ]
    volumeMounts:
    - name: game-volume
      mountPath: /etc/config
  volumes: 
  - name: game-volume
    configMap: # 기존 hostPath, emptyDir 외에 configMap도 volume으로 지정 가능
      name: game-config # game-config라는 configmap을 volume으로 지정
  • volumes > configMap 프로퍼티에 특정 configMap을 연결해서 볼륨으로 사용

[ Pod의 환경변수에 등록 - 특정 값만 ]

apiVersion: v1
kind: Pod
metadata:
  name: special-env
spec:
  restartPolicy: OnFailure
  containers:
  - name: special-env
    image: k8s.gcr.io/busybox
    command: [ "printenv" ]
    args: [ "special_env" ]
    env: # 환경변수 지정 property
    - name: special_env
      valueFrom: # valueFrom으로 다른 리소스 정보를 참조한다는 의미
        configMapKeyRef: # configMap의 key를 참조한다는 의미
          name: special-config # configMap 이름
          key: special.power # 특정 key값

[ Pod의 환경변수에 등록 - ConfigMap 자체를 ]

apiVersion: v1
kind: Pod
metadata:
  name: monster-env
spec:
  restartPolicy: OnFailure
  containers:
  - name: monster-env
    image: k8s.gcr.io/busybox
    command: [ "printenv" ]
    # env 대신에 envFrom 사용
    envFrom: 
    - configMapRef: # configMap 전체를 적용
        name: monster-config

Secret 리소스

[ Secret 기본 ]

  • ConfigMap과 유사하지만, 민감 데이터를 저장하는데 특화된 리소스
  • 각 노드에서 사용될 때 디스크에 저장되지 않고, tmpfs 라는 메모리 기반 파일시스템을 사용하여 보안에 강하다
  • Secret 리소스를 사용자가 조회할 때 base64로 한번 인코딩 되어 표시된다 (암호화는 X)

[ yaml을 통한 Secret 생성 ]

apiVersion: v1
kind: Secret
metadata:
  name: user-info
type: Opaque # ttoken / tls 등 사용 가능
data:
  username: YWRtaW4=            # admin
  password: cGFzc3dvcmQxMjM=    # password123
  • 직접 사용자가 base64로 인코딩해서 넣을 수도 있지만, k8s에서 대신 처리하길 원한다면 stringData 프로퍼티를 사용하면 된다
apiVersion: v1
kind: Secret
metadata:
  name: user-info-stringdata
type: Opaque
stringData: # k8s에게 인코딩을 수행하게 하는 property
  username: admin
  password: password123

[ Secret 활용 ]

[ Pod와 Volume 연결 ]

apiVersion: v1
kind: Pod
metadata:
  name: secret-volume
spec:
  restartPolicy: OnFailure
  containers:
  - name: secret-volume
    image: k8s.gcr.io/busybox
    command: [ "sh" ]
    args: ["-c", "ls /secret; cat /secret/username"]
    volumeMounts:
    - name: secret
      mountPath: "/secret"
  volumes:
  - name: secret
    secret: # secret 프로퍼티로 secret 리소스를 volume과 연결 가능
      secretName: user-info

[ Pod의 환경변수에 등록 - 특정 값만 ]

apiVersion: v1
kind: Pod
metadata:
  name: secret-env
spec:
  restartPolicy: OnFailure
  containers:
  - name: secret-env
    image: k8s.gcr.io/busybox
    command: [ "printenv" ]
    env: # 환경변수 지정 property
    - name: USERNAME
      valueFrom: # valueFrom으로 다른 k8s리소스 참조 가능
        secretKeyRef: # secret 리소스의 key를 참조한다는 의미
          name: user-info
          key: username
    - name: PASSWORD
      valueFrom: # 위와 동일
        secretKeyRef: # 위와 동일
          name: user-info
          key: password

[ Pod의 환경변수에 등록 - ConfigMap 자체를 ]

apiVersion: v1
kind: Pod
metadata:
  name: secret-envfrom
spec:
  restartPolicy: OnFailure
  containers:
  - name: secret-envfrom
    image: k8s.gcr.io/busybox
    command: [ "printenv" ]
    envFrom: # envFrom으로 secret 리소스 전체를 환경변수로 등록
    - secretRef: 
        name: user-info
profile
Developer & PhotoGrapher

0개의 댓글