無知

갈 길이 먼 공부 일기

기술 공부/쿠버네티스

쿠버네티스 (3) | 파드, 레이블, 네임스페이스, 어노테이션

moozii 2022. 2. 7. 08:57
앞으로의 스터디 내용은 <Kubernetes in Action>을 기반으로 진행합니다.
자세한 내용은, 해당 책을 확인해주세요! 
http://www.yes24.com/Product/Goods/89607047

 

1. 파드란

  • 여러 개의 컨테이너가 함께 배치된 컨테이너 그룹이자 쿠버네티스의 기본 빌딩 블록
  • 파드는 논리적인 호스트로, 동일한 파드 내 프로세스는 각각이 컨테이너 형태로 캡슐화되었다는 점을 제외하면
    동일한 머신 위에서 동작하는 것과 같다
  • 일반적으로 파드 하나 당 하나의 컨테이너만 포함한다
  • 하나의 파드에 여러 컨테이너가 포함된다고 해도, 그 컨테이너들은 모두 하나의 워커 노드에서 실행된다
    • 1개의 워커노드에 여러 개의 파드가 포함되고, 각 파드에는 1개 이상의 컨테이너가 포함된다

 

하나의 컨테이너에 여러 프로세스를 실행하지 않고 다중 컨테이너를 사용하는 이유

  • 컨테이너는 단일 프로세스 실행 목적으로 설계 (프로세스 실행, 로그 관리, 자동 재시작 등)
  • 단일 컨테이너, 단일 프로세스 = 다중 컨테이너의 활용 = 파드를 통한 관리의 필요성
  • 파드를 통해 컨테이너를 모아서, 여러 연관 프로세스들을 함께 실행하고 (거의) 동일한 환경을 제공하기 위해 파드를 활용한다
가상머신은 멀티 프로세싱이 되는 운영체제이지만, 컨테이너는 싱글 프로세스라는 것이다.
로그, 권한 체크, 사이드카와 같은 여러 프로세스를 기존 컨테이너에서는 동일하게 구성하기 어려우므로,가상머신과 파드를 비교하는 것이 더 적합하다.

어플리케이션은, 기존 웹 서비스 외 여러가지 보조 프로세스가 존재하므로,
싱글 프로세스 외 기타 여러 컨테이너가 보조 역할을 하여 그룹을 만들어주기 위해 파드가 필요하다.

리눅스의 프로세스 네임스페이스를 통해 컨테이너에 여러 프로세스를 만들 수는 있지만, 바람직하지 않다.
컨테이너에서 소개되는 격리, 그 중에서 Proccess의 네임스페이스 분리에 대해서는 기존 리눅스에서 제공하는 chroot를 한번 만져보면 지금 내용이 더욱 잘 이해되지 않을까 싶다.
https://www.44bits.io/ko/post/change-root-directory-by-using-chroot

결론적으로, 파드는 하나의 목적을 위한 서비스를 묶는 것이 맞다.
파드에는 메인 프로세스 컨테이너 하나와 이를 보조하는 프로세스 컨테이너들로 구성하는 방식이다.

 

파드가 같은 컨테이너들은 동일한 리눅스 네임스페이스를 사용하여 <부분격리>된다

  • 파드의 모든 컨테이너는 동일 네트워크 네임스페이스, 동일 UTS 네임스페이스, 동일 IPC 네임스페이스에서 실행되어, 호스트 이름과 네트워크 인터페이스를 공유한다. (PID 네임스페이스도 최신 버전에서 공유 가능)
  • 단, <파일시스템>의 경우에는 완전히 컨테이너 간에 격리 상태를 이룬다.
  • 컨테이너 간 파일 디렉터리를 공유하기 위해서는 <볼륨> 개념을 활용해야 한다. (추후 설명 예정)

 

파드 내 컨테이너들 간 동일한 IP와 포트 공유해서 발생하는 포트 충돌 문제

  • 파드는 앞서 말했듯 컨테이너들끼리 동일한 네트워크 네임스페이스를 사용하게 하므로,
    IP와 포트 공간도 공유한다는 것을 의미한다.
  • 따라서, 파드 안 컨테이너들은 포트 번호가 같지 않도록 해야 함에 유의하자.
  • 파드 내 컨테이너는 모두 동일한 루프백 네트워크 인터페이스를 가져 로컬호스트를 통해 상호 통신이 가능하다
    • 루프백 인터페이스(loopback interface)란 라우터나 스위치에 설정하는 가상의 인터페이스입니다. 루프백 인터페이스를 사용하는 이유는 여러가지가 있습니다. 예를 들어, 실제 네트워크에서는 각 라우터의 이더넷 인터페이스와 스위치를 연결한 후에 PC나 서버 등을 접속합니다.
      출처: https://12bme.tistory.com/356 
    • loopback 이란 가상의 인터페이스를 만들어서 사용하는 것입니다. 
      인터페이스 예로는 LAN구간 , WAN구간 마다 다르겠지만 Serial와 Ethernet이 FastEthernet  등등 다양한 인터페이스가 존재합니다. 물리적인 인터페이스의 경우 Serial 일때 Clock rate , WAN 인캡슐레이션 등 부여를 해야하고 이는 즉 외부에 간섭을 받는다는 말이 됩니다. 하지만 loopback은 설정을 하지 않아도 되며, 라우터가 죽지 않는 이상 잘 돌아가게 됩니다. 다른 인터페이스는 죽으면 통신이 안되지만 loopback 은 그렇지 않기 때문에 비교적 안전한 인터페이스라고 말합니다.
      https://min-310.tistory.com/169

 

 

파드 간 플랫 네트워크 

  • 모든 파드는 하나의 플랫한 공유 네트워크 주소 공간에 상주한다
  • 모든 파드는 다른 파드의 IP 주소를 통해 접근하는 것이 가능하다.
    각 파드는 라우팅 가능한 IP 주소를 얻고 다른 모든 파드는 해당 주소를 통해 파드를 본다
  • 두 파드 간에 어떠한 NAT도 존재하지 않는다
    어떤 워커노드에 속한 파드이든 상관없이 모든 파드는 상호 간 NAT 없는 플랫 네트워크 상의 통신이 가능하다는 의미이다.
  • 두 파드가 서로 네트워크 패킷을 보내면 상대방 실제 IP주소를 패킷 안에 있는 출발지 IP 주소에서 찾을 수 있다

 

 

2. 파드의 컨테이너 구성

  • 하나의 어플리케이션을 여러 파드로 구성하고,
    각 파드에는 서로 밀접하게 관련 있는 프로세스 및 구성요소를 컨테이너로 나누어 하나의 파드를 구성한다
  • 다계층 애플리케이션의 파드 분할 방법
    • 프론트엔드 서버와 백엔드 (데이터베이스) 서버 컨테이너를 별개의 파드에 배치한다
      파드를 분리하여 별개의 노드에 개별적으로 스케줄링해 인프라 활용도를 향상시킨다
    • 컨테이너의 수평 확장 (스케일링 아웃) 관점에서도 프론트와 백 등을 여러 파드로 분할해야 한다.
      파드는 스케일링의 기본 단위이다. 되도록 하나의 파드에 하나의 컨테이너를 두자.
    • 하나의 파드에 여러 컨테이너를 넣을 때에는 하나의 주 컨테이너를 다른 지원 컨테이너들이 보조하는 경우이다
      파드에 여러 컨테이너를 넣을 경우에는, 
      1. 컨테이너를 함께 실행해야 하거나 (동일 호스트에서 실행할 필요성)
      2. 컨테이너가 개별 구성 요소가 아니라, 여러 개가 모여 하나의 구성 요소를 나타내거나
      3. 컨테이너가 함께 스케일링되어야 하는 경우이다 

* 이번 챕터에서는 단일 컨테이너를 보유한 파드만을 기준으로 설명하며, 여러 컨테이너를 포함하는 파드의 경우 추후 설명한다.

 

 

 

 

3. 파드의 생성, 실행, 정지

(1) YAML 또는 JSON 디스크립터로 파드 생성

파드를 포함한 쿠버네티스 리소스를 JSON 혹은 YAML 파일 형태의 메니페스트에 정의해,

쿠버네티스 REST API 엔드포인트에 전송하여, 

버전 관리 시스템에 넣어 다양한 속성 집합 설정이 가능하다.

 

쿠버네티스 리소스 유형 확인하기

더보기

쿠버네티스 리소스 유형

모든 리소스 유형, 속성을 알기 위해서는 API reference 문서를 참고해야 한다.

https://kubernetes.io/ko/docs/reference/

 

레퍼런스

운영 수준의 컨테이너 오케스트레이션

kubernetes.io

kubectl explain 활용하기

더보기

kubectl explain을 이용해 사용 가능한 API 오브젝트 필드 찾기

 

$ kubectl explain pods

KIND:     Pod

VERSION:  v1

 

DESCRIPTION:

     Pod is a collection of containers that can run on a host. This resource is

     created by clients and scheduled onto hosts.

 

FIELDS:

   apiVersion <string>

     APIVersion defines the versioned schema of this representation of an

     object. Servers should convert recognized schemas to the latest internal

     value, and may reject unrecognized values. More info:

     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources

 

   kind <string>

     Kind is a string value representing the REST resource this object

     represents. Servers may infer this from the endpoint the client submits

     requests to. Cannot be updated. In CamelCase. More info:

     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds

 

   metadata <Object>

     Standard object's metadata. More info:

     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#metadata

 

   spec <Object>

     Specification of the desired behavior of the pod. More info:

     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

 

   status <Object>

     Most recently observed status of the pod. This data may not be up to date.

     Populated by the system. Read-only. More info:

     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

 

$ kubectl explain pod.spec

KIND:     Pod

VERSION:  v1

 

RESOURCE: spec <Object>

 

DESCRIPTION:

     Specification of the desired behavior of the pod. More info:

     https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#spec-and-status

 

     PodSpec is a description of a pod.

 

FIELDS:

   activeDeadlineSeconds <integer>

     Optional duration in seconds the pod may be active on the node relative to

     StartTime before the system will actively try to mark it failed and kill

     associated containers. Value must be a positive integer.

 

   affinity <Object>

     If specified, the pod's scheduling constraints

 

   automountServiceAccountToken <boolean>

     AutomountServiceAccountToken indicates whether a service account token

     should be automatically mounted.

 

   containers <[]Object> -required-

     List of containers belonging to the pod. Containers cannot currently be

     added or removed. There must be at least one container in a Pod. Cannot be

     updated.

 

   dnsConfig <Object>

     Specifies the DNS parameters of a pod. Parameters specified here will be

     merged to the generated DNS configuration based on DNSPolicy.

 

   dnsPolicy <string>

     Set DNS policy for the pod. Defaults to "ClusterFirst". Valid values are

     'ClusterFirstWithHostNet', 'ClusterFirst', 'Default' or 'None'. DNS

     parameters given in DNSConfig will be merged with the policy selected with

     DNSPolicy. To have DNS options set along with hostNetwork, you have to

     specify DNS policy explicitly to 'ClusterFirstWithHostNet'.

 

   enableServiceLinks <boolean>

     EnableServiceLinks indicates whether information about services should be

     injected into pod's environment variables, matching the syntax of Docker

     links. Optional: Defaults to true.

 

   ephemeralContainers <[]Object>

     List of ephemeral containers run in this pod. Ephemeral containers may be

     run in an existing pod to perform user-initiated actions such as debugging.

     This list cannot be specified when creating a pod, and it cannot be

     modified by updating the pod spec. In order to add an ephemeral container

     to an existing pod, use the pod's ephemeralcontainers subresource. This

     field is beta-level and available on clusters that haven't disabled the

     EphemeralContainers feature gate.

 

   hostAliases <[]Object>

     HostAliases is an optional list of hosts and IPs that will be injected into

     the pod's hosts file if specified. This is only valid for non-hostNetwork

     pods.

 

   hostIPC <boolean>

     Use the host's ipc namespace. Optional: Default to false.

 

   hostNetwork <boolean>

     Host networking requested for this pod. Use the host's network namespace.

     If this option is set, the ports that will be used must be specified.

     Default to false.

 

   hostPID <boolean>

     Use the host's pid namespace. Optional: Default to false.

 

   hostname <string>

     Specifies the hostname of the Pod If not specified, the pod's hostname will

     be set to a system-defined value.

 

   imagePullSecrets <[]Object>

     ImagePullSecrets is an optional list of references to secrets in the same

     namespace to use for pulling any of the images used by this PodSpec. If

     specified, these secrets will be passed to individual puller

     implementations for them to use. For example, in the case of docker, only

     DockerConfig type secrets are honored. More info:

     https://kubernetes.io/docs/concepts/containers/images#specifying-imagepullsecrets-on-a-pod

 

   initContainers <[]Object>

     List of initialization containers belonging to the pod. Init containers are

     executed in order prior to containers being started. If any init container

     fails, the pod is considered to have failed and is handled according to its

     restartPolicy. The name for an init container or normal container must be

     unique among all containers. Init containers may not have Lifecycle

     actions, Readiness probes, Liveness probes, or Startup probes. The

     resourceRequirements of an init container are taken into account during

     scheduling by finding the highest request/limit for each resource type, and

     then using the max of of that value or the sum of the normal containers.

     Limits are applied to init containers in a similar fashion. Init containers

     cannot currently be added or removed. Cannot be updated. More info:

     https://kubernetes.io/docs/concepts/workloads/pods/init-containers/

 

   nodeName <string>

     NodeName is a request to schedule this pod onto a specific node. If it is

     non-empty, the scheduler simply schedules this pod onto that node, assuming

     that it fits resource requirements.

 

   nodeSelector <map[string]string>

     NodeSelector is a selector which must be true for the pod to fit on a node.

     Selector which must match a node's labels for the pod to be scheduled on

     that node. More info:

     https://kubernetes.io/docs/concepts/configuration/assign-pod-node/

 

   os <Object>

     Specifies the OS of the containers in the pod. Some pod and container

     fields are restricted if this is set.

 

     If the OS field is set to linux, the following fields must be unset:

     -securityContext.windowsOptions

 

     If the OS field is set to windows, following fields must be unset: -

     spec.hostPID - spec.hostIPC - spec.securityContext.seLinuxOptions -

     spec.securityContext.seccompProfile - spec.securityContext.fsGroup -

     spec.securityContext.fsGroupChangePolicy - spec.securityContext.sysctls -

     spec.shareProcessNamespace - spec.securityContext.runAsUser -

     spec.securityContext.runAsGroup - spec.securityContext.supplementalGroups -

     spec.containers[*].securityContext.seLinuxOptions -

     spec.containers[*].securityContext.seccompProfile -

     spec.containers[*].securityContext.capabilities -

     spec.containers[*].securityContext.readOnlyRootFilesystem -

     spec.containers[*].securityContext.privileged -

     spec.containers[*].securityContext.allowPrivilegeEscalation -

     spec.containers[*].securityContext.procMount -

     spec.containers[*].securityContext.runAsUser -

     spec.containers[*].securityContext.runAsGroup This is an alpha field and

     requires the IdentifyPodOS feature

 

   overhead <map[string]string>

     Overhead represents the resource overhead associated with running a pod for

     a given RuntimeClass. This field will be autopopulated at admission time by

     the RuntimeClass admission controller. If the RuntimeClass admission

     controller is enabled, overhead must not be set in Pod create requests. The

     RuntimeClass admission controller will reject Pod create requests which

     have the overhead already set. If RuntimeClass is configured and selected

     in the PodSpec, Overhead will be set to the value defined in the

     corresponding RuntimeClass, otherwise it will remain unset and treated as

     zero. More info:

     https://git.k8s.io/enhancements/keps/sig-node/688-pod-overhead/README.md

     This field is beta-level as of Kubernetes v1.18, and is only honored by

     servers that enable the PodOverhead feature.

 

   preemptionPolicy <string>

     PreemptionPolicy is the Policy for preempting pods with lower priority. One

     of Never, PreemptLowerPriority. Defaults to PreemptLowerPriority if unset.

     This field is beta-level, gated by the NonPreemptingPriority feature-gate.

 

   priority <integer>

     The priority value. Various system components use this field to find the

     priority of the pod. When Priority Admission Controller is enabled, it

     prevents users from setting this field. The admission controller populates

     this field from PriorityClassName. The higher the value, the higher the

     priority.

 

   priorityClassName <string>

     If specified, indicates the pod's priority. "system-node-critical" and

     "system-cluster-critical" are two special keywords which indicate the

     highest priorities with the former being the highest priority. Any other

     name must be defined by creating a PriorityClass object with that name. If

     not specified, the pod priority will be default or zero if there is no

     default.

 

   readinessGates <[]Object>

     If specified, all readiness gates will be evaluated for pod readiness. A

     pod is ready when all its containers are ready AND all conditions specified

     in the readiness gates have status equal to "True" More info:

     https://git.k8s.io/enhancements/keps/sig-network/580-pod-readiness-gates

 

   restartPolicy <string>

     Restart policy for all containers within the pod. One of Always, OnFailure,

     Never. Default to Always. More info:

     https://kubernetes.io/docs/concepts/workloads/pods/pod-lifecycle/#restart-policy

 

   runtimeClassName <string>

     RuntimeClassName refers to a RuntimeClass object in the node.k8s.io group,

     which should be used to run this pod. If no RuntimeClass resource matches

     the named class, the pod will not be run. If unset or empty, the "legacy"

     RuntimeClass will be used, which is an implicit class with an empty

     definition that uses the default runtime handler. More info:

     https://git.k8s.io/enhancements/keps/sig-node/585-runtime-class This is a

     beta feature as of Kubernetes v1.14.

 

   schedulerName <string>

     If specified, the pod will be dispatched by specified scheduler. If not

     specified, the pod will be dispatched by default scheduler.

 

   securityContext <Object>

     SecurityContext holds pod-level security attributes and common container

     settings. Optional: Defaults to empty. See type description for default

     values of each field.

 

   serviceAccount <string>

     DeprecatedServiceAccount is a depreciated alias for ServiceAccountName.

     Deprecated: Use serviceAccountName instead.

 

   serviceAccountName <string>

     ServiceAccountName is the name of the ServiceAccount to use to run this

     pod. More info:

     https://kubernetes.io/docs/tasks/configure-pod-container/configure-service-account/

 

   setHostnameAsFQDN <boolean>

     If true the pod's hostname will be configured as the pod's FQDN, rather

     than the leaf name (the default). In Linux containers, this means setting

     the FQDN in the hostname field of the kernel (the nodename field of struct

     utsname). In Windows containers, this means setting the registry value of

     hostname for the registry key

     HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters to

     FQDN. If a pod does not have FQDN, this has no effect. Default to false.

 

   shareProcessNamespace <boolean>

     Share a single process namespace between all of the containers in a pod.

     When this is set containers will be able to view and signal processes from

     other containers in the same pod, and the first process in each container

     will not be assigned PID 1. HostPID and ShareProcessNamespace cannot both

     be set. Optional: Default to false.

 

   subdomain <string>

     If specified, the fully qualified Pod hostname will be

     "<hostname>.<subdomain>.<pod namespace>.svc.<cluster domain>". If not

     specified, the pod will not have a domainname at all.

 

   terminationGracePeriodSeconds <integer>

     Optional duration in seconds the pod needs to terminate gracefully. May be

     decreased in delete request. Value must be non-negative integer. The value

     zero indicates stop immediately via the kill signal (no opportunity to shut

     down). If this value is nil, the default grace period will be used instead.

     The grace period is the duration in seconds after the processes running in

     the pod are sent a termination signal and the time when the processes are

     forcibly halted with a kill signal. Set this value longer than the expected

     cleanup time for your process. Defaults to 30 seconds.

 

   tolerations <[]Object>

     If specified, the pod's tolerations.

 

   topologySpreadConstraints <[]Object>

     TopologySpreadConstraints describes how a group of pods ought to spread

     across topology domains. Scheduler will schedule pods in a way which abides

     by the constraints. All topologySpreadConstraints are ANDed.

 

   volumes <[]Object>

     List of volumes that can be mounted by containers belonging to the pod.

     More info: https://kubernetes.io/docs/concepts/storage/volumes

 

 

 

2장 파드의 YAML 디스크립터 살펴보기

디스크립터 파일 확인하기

더보기
$ kubectl get po kubia -o yaml
apiVersion: v1    # 해당 디스크립터에서 사용한 쿠버네티스 API 버전
kind: Pod         # 쿠버네티스 오브젝트 및 리소스 유형
metadata:         # 파드 메타데이터 (이름, 레이블, 어노테이션)
  creationTimestamp: "2022-02-06T04:12:30Z"
  labels:
    run: kubia
  name: kubia
  namespace: default
  resourceVersion: "7887"
  uid: 229271ca-7672-4dd5-bce8-1d89f309ac86
spec:             # 파드 정의 및 내용 (컨테이너 목록, 볼륨 등)
  containers:
  - image: joon0615/kubia
    imagePullPolicy: Always
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP
    resources: {}
    terminationMessagePath: /dev/termination-log
    terminationMessagePolicy: File
    volumeMounts:
    - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
      name: kube-api-access-sf8c7
      readOnly: true
  dnsPolicy: ClusterFirst
  enableServiceLinks: true
  nodeName: minikube
  preemptionPolicy: PreemptLowerPriority
  priority: 0
  restartPolicy: Always
  schedulerName: default-scheduler
  securityContext: {}
  serviceAccount: default
  serviceAccountName: default
  terminationGracePeriodSeconds: 30
  tolerations:
  - effect: NoExecute
    key: node.kubernetes.io/not-ready
    operator: Exists
    tolerationSeconds: 300
  - effect: NoExecute
    key: node.kubernetes.io/unreachable
    operator: Exists
    tolerationSeconds: 300
  volumes:
  - name: kube-api-access-sf8c7
    projected:
      defaultMode: 420
      sources:
      - serviceAccountToken:
          expirationSeconds: 3607
          path: token
      - configMap:
          items:
          - key: ca.crt
            path: ca.crt
          name: kube-root-ca.crt
      - downwardAPI:
          items:
          - fieldRef:
              apiVersion: v1
              fieldPath: metadata.namespace
            path: namespace
status:           # 파드와 그 안의 컨테이너에 대한 상세 상태
  conditions:
  - lastProbeTime: null
    lastTransitionTime: "2022-02-06T04:12:30Z"
    status: "True"
    type: Initialized
  - lastProbeTime: null
    lastTransitionTime: "2022-02-06T04:12:35Z"
    status: "True"
    type: Ready
  - lastProbeTime: null
    lastTransitionTime: "2022-02-06T04:12:35Z"
    status: "True"
    type: ContainersReady
  - lastProbeTime: null
    lastTransitionTime: "2022-02-06T04:12:30Z"
    status: "True"
    type: PodScheduled
  containerStatuses:
  - containerID: docker://aea5a91026a8c9f154fde88230d578e80cd6730c2e41a8e1c422df88273b03c5
    image: joon0615/kubia:latest
    imageID: docker-pullable://joon0615/kubia@sha256:fd06de01c736aba25effbe0c7024668a28a60a73344ab286853e2a813071353e
    lastState: {}
    name: kubia
    ready: true
    restartCount: 0
    started: true
    state:
      running:
        startedAt: "2022-02-06T04:12:34Z"
  hostIP: 192.168.59.100
  phase: Running
  podIP: 172.17.0.3
  podIPs:
  - ip: 172.17.0.3
  qosClass: BestEffort
  startTime: "2022-02-06T04:12:30Z"

 

각 쿠버네티스 리소스가 보유한 3가지 주요 부분

  • Metadata 메타데이터 = 파드에 대한 정보 : 이름, 네임스페이스, 레이블, 기타 정보
  • Spec 스펙 = 파드 컨테이너, 볼륨, 기타 데이터 등 파드 자체에 대한 실제 명세
  • Status 상태 = 파드 상태, 내부 IP 등 현재 실행 정보. (파드 신규 생성 시 작성 불필요)
# kubia-manual.yaml (source = https://github.com/luksa/kubernetes-in-action/blob/master/Chapter03/kubia-manual.yaml )
apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP
  • 포트를 명시적으로 정의한 이유
    • 클러스터를 사용하는 모든 사람이 파드 노출 포트를 빠르게 확인 가능하도록
    • 포트에 이름을 지정하여 편의성을 높이도록
    • 굳이 정의하지 않더라도 컨테이너가 0.0.0.0 주소에 열어둔 포트의 접속을 허용할 시 접속 가능하다.

 

kubectl create 명령으로 파드 생성

$ kubectl create -f kubia-manual.yaml
pod "kubia-manual" created

 

실행 중인 파드의 정의 파일 확인하기 (YAML / JSON 요청)

만든 포맷과 다른 옵션으로 요청하면 전환하여 반환하도록 동작한다

$ kubectl get po kubia-manual -o yaml
$ kubectl get po kubia-manual -o json

 

(2) 애플리케이션 로그 보기

Node.js 애플리케이션을 통해 로그를 프로세스 표준 출력에 기록해보자. 

도커와 같은 컨테이너 런타임이 이 표준 출력으로 기록도는 로그 스트림을 파일 형태로 전달하고, 

컨테이너 런타임 명령어를 통해 사용자는 컨테이너 로그를 가져올 수 있다. 

(ssh 접속 후 $docker logs <containerID>를 입력하면 가능하다고 한다)

 

kubectl로 파드 로그 보기

파드 로그, 컨테이너 로그를 kubectl을 활용하여 간단히 로컬 머신 상에서 확인해보자

$ kubectl logs kubia-manual 
Kiada - Kubernetes in Action Demo Application
---------------------------------------------
Kiada 0.1 starting...
Local hostname is kubia-manual
Listening on port 8080

파드가 삭제되면 해당 로그도 함께 사라짐에 유의하자. 

삭제 이후에도 로그를 확인하기 위해서는,
클러스터 전체의 중앙집중식 로깅 설정을 통해 모든 로그를 중앙 저장소에 저장하도록 해야 한다.

 

 

(3) 파드 동작 확인 요청

파드의 실제 동작 확인을 위해서는 서비스를 활용하거나, 포트 포워딩을 진행해야 한다.

서비스는 후술할 예정이니, 포트 포워딩에 대해 알아보자.

 

로컬 네트워크 포트를 파드 포트로 포트포워딩하기

포트 포워딩 구성은 $ kubectl port-forward 명령어를 통해 진행한다.

머신 로컬 포트 8888을 파드의 8080포트로 향하도록 포트포워딩해보자.

$ kubectl port-forward kubia-manual 8888:8080
Forwarding from 127.0.0.1:8888 -> 8080
Forwarding from [::1]:8888 -> 8080

이렇게 하나의 터미널에서 포트 포워딩을 실행 중이면, 

다른 새로운 터미널 하나를 열어 아래의 명령어를 수행하여 로컬 머신 8888에 요청을 보내면, 

앞서 실행 중인 포트 포워딩에 의해 파드의 포트로 이어준다.

$ curl localhost:8888
Kiada version 0.1. Request processed by "kubia-manual". Client IP: ::ffff:127.0.0.1

 

 

(4) 파드 중지와 제거

$ kubectl delete po podname
$ kubectl delete po podname_1 podname_2
  1. kubectl 명령어를 통해 파드를 삭제하도록 지시한다.
  2. 쿠버네티스가 파드를 삭제한 뒤 모든 컨테이너의 종료를 지시한다.
    1. 쿠버네티스는 SIGTREM 신호를 프로세스에 보내 지정 시간을 대기한다. (기본값=30초)
  3. 지정 시간 내 종료되지 않을 경우 SIGKILL 신호를 통해 강제로 종료한다.

 

레이블 셀렉터를 통한 파드 삭제

레이블에 대한 개념은 아래 쪽에 서술되어 있으니 확인토록 하자. 

$ kubectl delete po -l creation_method=manual

 

네임스페이스와 소속 파드 한번에 제거하기

네임스페이스 개념은 아래쪽에 서술되어 있으니 확인토록 하자. 

$ kubectl delete ns custom-namespace

 

네임스페이스는 유지하고 소속 파드 전체만 삭제하기

$ kubectl delete po --all

만약 파드를 레플리케이션 컨트롤러 등 자동 복구 기능을 활성화시켜 생성했다면, 이렇게 파드를 삭제해도 다시 새로운 파드가 생성되기 마련이다. 네임스페이스 내 전체 리소스를 삭제하려면 아래 명령어를 입력해야 한다.

$ kubectl delete all --all

 

 

 

4. 파드와 다른 리소스를 레이블로 조직화하기

{"originWidth":1659,"originHeight":1080,"style":"alignCenter","caption":"Namespace and Label

레이블을 통한 파드 구성

마이크로서비스 아키텍처가 보편화되면서, 파드의 수도 매우 많이 늘어나기 때문에, 

파드를 정리하는 메커니즘은 필수적이다.

파드를 작은 그룹들로 임의의 기준에 따라 나누어, 각 그룹을 한번에 작업하는 것이 좋다.

레이블을 활용해 파드와 더불어 다른 쿠버네티스 오브젝트까지 조직화한다.

 

레이블이란

  • 파드와 다른 리소스를 조직화하는 기능
  • 리소스에 첨부하는 키-값 쌍
  • 레이블 셀렉터를 활용해 리소스 선택에 이용되는 기능
  • 각 파드는 여러 개의 레이블을 가질 수 있다 (레이블 키는 고유해야 한다)

https://kubernetes.io/ko/docs/concepts/overview/working-with-objects/labels/ 

 

레이블과 셀렉터

레이블 은 파드와 같은 오브젝트에 첨부된 키와 값의 쌍이다. 레이블은 오브젝트의 특성을 식별하는 데 사용되어 사용자에게 중요하지만, 코어 시스템에 직접적인 의미는 없다. 레이블로 오브

kubernetes.io

활용예시

- app : 파드가 속한 애플리케이션, 구성요소 혹은 마이크로서비스가 무엇인지

(app=ui, app=as, app=pc, app=sc, app=os)

- rel : 실행 중인 애플리케이션의 상태

(rel=stable, rel=beta, rel=canary)

 

Canary Release, 카나리 릴리스란?

더보기

전체 사용자에게 배포하기 이전에 소수 사용자에게 테스트 용도로 확인하는 릴리스.

 

 

파드 생성 시 레이블 지정하기

# kubia-manual-with-lables.yaml
apiVersion: v1
kind: Pod
metadata:
  name: kubia-manual-v2
  labels:
    creation_method: manual
    env: prod
spec:
  containers:
  - image: luksa/kubia
    name: kubia
    ports:
    - containerPort: 8080
      protocol: TCP

https://github.com/luksa/kubernetes-in-action/blob/master/Chapter03/kubia-manual-with-labels.yaml

 

$ kubectl create -f kubia-manual-with-labels.yaml
pod/kubia-manual-v2 created

$ kubectl get po --show-labels 
NAME              READY   STATUS              RESTARTS   AGE    LABELS
kubia             1/1     Running             0          145m   run=kubia
kubia-manual      1/1     Running             0          57m    <none>
kubia-manual-v2   0/1     ContainerCreating   0          22s    creation_method=manual,env=prod

$ kubectl get po -L creation_method,env
NAME              READY   STATUS    RESTARTS   AGE     CREATION_METHOD   ENV
kubia             1/1     Running   0          146m                      
kubia-manual      1/1     Running   0          59m                       
kubia-manual-v2   1/1     Running   0          2m16s   manual            prod

* get po 명령어는 레이블을 표시하지 않으므로 --show-lables 옵션을 추가해야 한다

* -L 스위치를 활용하면 지정한 해당 레이블을 열로 표시하여 정보를 확인할 수 있다

 

파드 레이블 수정하기

$ kubectl label po kubia-manual creation_method=manual
pod/kubia-manual labeled

기존 레이블을 변경하기 위해서는 --overwrite 옵션을 사용해야 한다

$ kubectl label po kubia-manual-v2 env=debug --overwrite
pod/kubia-manual-v2 labeled

$ kubectl get po -L creation_method,env
NAME              READY   STATUS    RESTARTS   AGE     CREATION_METHOD   ENV
kubia             1/1     Running   0          150m                      
kubia-manual      1/1     Running   0          63m     manual            
kubia-manual-v2   1/1     Running   0          6m16s   manual            debug

 

 

5. 특정 레이블을 가진 파드에서 작업 수행시키기

레이블 셀렉터를 이용한 파드 나열

  • 레이블 셀렉터는 특정 레이블로 태그된 파드의 부분 집합을 선택해 작업을 수행한다
  • 레이블 셀렉터는 다음 기준에 따라 리소스를 선택한다
    • 특정 키를 포함할 경우 / 포함하지 않은 경우
    • 특정 키 + 값을 가진 경우
    • 특정 키를 가졌으나 해당 값을 가지지 않은 경우

 

6. 어노테이션

어노테이션은 레이블과 비슷한 키-값 쌍이지만, 식별 정보를 가지지 않는다. 

어노테이션 셀렉터는 존재하지 않아 오브젝트 선택이 불가하기는 하지만, 레이블보다 많은 정보를 포함할 수 있다. 

어노테이션은 추가 정보 제공 외에 스펙 명세를 넣어 자동으로 다른 프로세스가 읽게끔하기도 한다. 

 

7. 네임스페이스

격리 기술을 제공하는 리눅스 네임스페이스와는 달리 쿠버네티스 내 오브젝트 그룹핑에 사용되는 개념이다.

네임스페이스는, 각 오브젝트를 겹치지 않는 그룹으로 분할할 때 사용된다. 

모든 리소스를 단일 네임스페이스에 두는 대신 여러 네임스페이스로 분할할 수 있고,

분리된 네임스페이스는 같은 리소스 이름을 다른 네임스페이스에 걸쳐 여러번 사용할 수 있다.

네임스페이스는 권한 관리(접근 제어)를 위해서 하기도 하고, 격리를 위함이기도 하다.