How Kubernetes works

Reference: Container부터 다시 살펴보는 Kubernetes Pod 동작 원리

What is Container?

  • Container는 격리된 환경에서 실행되는 Process 이다

Container가 격리된 환경을 구현하는 주요 원리

1. Root directory 격리 (chroot)

  • chroot

    $ chroot <NEWROOT> <COMMAND>
    • 입력된 경로 (New root path)가 root directory로 격리된 process (command)를 실행하기 위한 명령어

2. Linux namespaces

  • Process 간 system resources를 격리하기 위한 Linux kernel의 기능

    $ lsns -p <pid>	
  • unshare

    • 특정 namespace를 격리한 process를 실행할 수 있는 명령어

    • ex)

      # mount namespace를 격리 (-m)한 /bin/bash process 실행
      $ unshare -m /bin/bash
      
      # mount namespace(-m)와 ipc namespace(-i)를 격리한 /bin/bash process 실행
      $ unshare -m -i /bin/bash

3. Mount (mnt) namespace

  • mount

    • Unix 계열 system에서 특정 file system에 접근하기 위해, file system을 root directory (/)부터 시작하는 file tree 의 특정 directory에 연결하는 것

      mount -t <type> <device> <dir>
    • ex)

      # tmpfs (temporary file storage) fmf "/root/test" 경로에 mount
      $ mount -t tmpfs tmpfs /root/test
  • mount namespace

    • Process 간 서로 다른 mount point를 가질 수 있게 함

4. Process ID (pid) namespace

  • Container는 격리된 환경에서 실행되는 Process이다

    • Container 안에서는 하나의 VM처럼 보이지만, Container 밖 (host)에서는 하나의 Process일 뿐이다

    • 같은 process에 대해,

      • Host에서 확인한 PID와 container 안에서 확인한 PID가 다르다

  • PID namespace가 격리된 container에서 최초로 실행된 process (entrypoint)는 항상 PID=1을 갖는다

5. Inter-Process Communication (ipc) namespace

  • System V 기반의 process 간 통신을 격리한다

    • System V IPC

      • shared memory (shm)

      • semaphore

        • 여러 process나 thread가 공유 자원에 접근하는 것을 제어하기 위한 방법

          • 병행 처리를 위한 process 동기화 기법

      • POSIX message queue

        • /proc/sys/fs/mqueue

        • System V message queue의 새로운 버전

          • 함수의 이름과 종류는 다르지만, 하는 일은 비슷하다

          • System V 기반 message queue 함수보다 더 직관적이고 쓰기 편하다

    • IPC 객체들은 같은 IPC namespace에 존재하는 process에만 표시된다

6. Network (net) namespace

  • Network interface, routing, 방화벽 규칙들을 격리한다

  • ex)

    # "chloe-ns" 라는 이름의 network namespace 생성
    $ ip netns add chloe-ns
    $ ip netns list
    chloe-ns
    # virtual ethernet interface pair 생성 (veth1, veth2)
    # "veth1"은 chloe-ns에 생성, "veth2"는 PID 1의 network namespace에 생성
    $ ip link add veth1 netns chloe-ns type veth peer name veth2 netns 1
  • Docker의 container network 구조

    • Container는 host와 network namespace가 격리된다

      • Host - container 간 veth peer를 생성하여 연결한다

      • Host이 veth는 docker bridge 와 연결되어 container 외부로 통신 시 bridge를 거쳐간다

7. Unix Time-Shring (uts) namespace

  • Unix Time-Sharing이란?

    • Computing resource를 다른 user들과 공유하는 것에서 유래되었다

    • 여려 user가 같은 machine을 사용하고 있지만, 마치 다른 machine을 사용중인 것 처럼 만들고 싶을 때 hostname을 격리할 수 있는 공간을 만들어 사용한다

8. User ID (user) namespace

  • Host에서의 uid와 Container의 uid 를 다르게 mapping 한다

  • Docker container는 기본적으로 user namespace를 격리하지 않는다

    • 즉, container의 user가 host와 (거의) 같은 uid 권한을 그대로 행사할 수 있다!

    • Docker가 user namespace를 격리하지 않는 이유

      • PID, Network namespace 공유 기능호환 문제

      • user mapping을 지원하지 않는 외부 volume 또는 driver와의 호환 문제

      • 격리된 user namespace의 user가 mapping 된 실제 host 상의 uid로부터, host에서 binding 한 file에 접근 권한이 보장되어야 하는 복잡성

      • 격리되지 않은 user namespace에서 container root가 host root와 거의 대등한 수준의 권한을 가지긴 하지만 전체 root 권한을 의미하는 것은 아니다

    • Kubernetes 또한 user namespace 격리를 아직 지원하지 않는다

    • User namespace 격리를 사용하지 않을 때

      • 신뢰할 수 있는 사용자만 container runtime (ex. Docker)을 실행할 수 있도록 제한한다

      • Container의 process가 root user로 실행하지 않도록 한다

        • 특정 UID, GID로 실행될 수 있도록 지정한다

      • Host의 directory를 container가 직접 접근할 수 있도록 mount 하지 않는다

    • Kubernetes에서도 같은 원리의 보안 설정을 제공한다

9. Control group (cgroup)

  • Process group자원 할당을 제한하고, 격리할 수 있는 Linux Kernel 기능

    • CPU

      • ex) CPU 사용량을 제한

    • Memory

      • ex) Memory 사용량을 제한

    • Network

      • ex) Network Traffic 우선 순위를 설정

    • Disk

      • ex) Disk 사용량에 대한 통계를 제공

Wrap-up: Container가 격리된 환경을 구현하는 주요 원리

  • Container는 격리된 환경에서 실행되는 process이다

  • namespace를 통해 process의 격리된 환경을 구현한다

  • cgroups를 통해 process의 자원 사용량제한한다

What is Kubernetes Pod?

  • Kubernetes에서 배포할 수 있는 최소 객체 단위

  • 1개 이상의 container로 이루어진 group

Pod는 "배포 가능한 최소 객체 단위"이다

K8s application은 pod 단위로 배포되고, pod는 여러 형태의 resource에 의해 배포된다

  • Job

    • 한 번 실행되고 작업이 완료되면 종료되는 형태의 pod를 관리

  • ReplicaSet

    • 명시된 pod 개수가 실행되는 상태를 보장

  • DaemonSet

    • 각 node마다 하나씩만 실행되는 pod를 관리

  • StatefulSet

    • Stateful application을 실행하는 pod를 관리

  • Deployment

    • Pod, ReplicaSet의 update에 대한 배포를 관리

Pod는 Kubernetes에서 생성하고 관리되는 가장 기본적인 단위이다!

Pod는 1개 이상의 container로 이루어진 group이다

  • Pod에는 1개 이상의 container가 존재할 수 있다

    • 단일 container를 실행하는 pod

    • 여러 container를 실행하는 pod

Pod를 여러 container로 구성하는 경우

  • Main 역할을 하는 1개의 Primary Container

  • 1개 이상의 Sidecar Containers

    • Primary Container의 보완 역할을 하기 위해 실행되는 container

    • ex) monitoring, logging, etc.

Container에서는 단일 Process를 실행하도록 권장한다

  • Why?

    • Container는 앞서 언급했듯이, 격리된 환경에서 실행되는 process이다

    • 격리된 PID namespace에서 최초로 실행된 process는 pid=1이다

    • 즉, Container에서 최초로 실행된 process의 state == Container의 수명이다!

  • If container 안에서 여러 process가 실행 중이라면?

    • Container가 실행 중이라도, main process를 제외한 다른 process들의 실행 상태를 보장할 수 없다

    • 즉, Container에서 실행되는 process들의 state != Container의 state

  • If Kubernetes pod의 특정 container가 종료되면?

    • Kubernetes는 선언된 restartPolicy에 따라 container를 재시작한다

      • restartPolicy options

        • Always

        • OnFailure

        • Never

Pod를 구성하는 기준

  • Container들이 꼭 같은 node에서 실행되어야 하는가?

    • 같은 pod에 존재하는 container들은 항상 같은 node에 존재한다!

  • 해당 container들이 같은 개수로 수평 확장되어야 하는가?

    • Pod 단위 == 확장의 단위!

  • Container들은 하나의 group으로 함께 배포해야 하는가?

Kubernetes Pod의 container 간 격리

  • Pod가 실행중인 node에서 container를 확인해보면,

    • cgroup namespace, user namespace는 따로 격리하지 않는다

    • mnt, uts, pid namespace는 각 container 별로 격리한다

      • 같은 pod여도 공유하지 않는다!

    • ipc, net namespace는 pod의 container간 공유한다

      • Container process간 shared memory 등의 IPC 가능

      • Container 간 동일한 IP주소, port를 공유한다 (충돌 주의)

Pause Container란?

  • Pause container는 격리된 IPC, Network namespace를 생성하고 유지한다

    • 나머지 container들은 해당 namespace를 공유하여 사용한다

      • 즉, user가 실행한 특정 container가 비정상 종료되어 container 전체에서 공유되는 namespace에 문제가 발생하는 것을 방지한다!

  • 단순히 무한 loop를 돌면서 SIGINT, SIGTERM을 받으면 종료한다

    • SIGINT

      • keyboard로 부터 오는 interrupt signal

        • [CTRL] + [C] 입력 시에 보내지는 signal

      • 실행을 중지시킨다

    • SIGTERM

      • Terminate의 약자로, 가능한 정상 종료하도록 하는 signal

      • kill 명령의 기본 signal

  • Zombie Process Reaping 역할을 한다

    • PID namespace sharing을 하는 경우!

Kubernetes의 PID namespace sharing

  • 각 container에서 Zombie process가 발생할 우려가 있는 경우, Kubernetes PID namespace sharing option을 활성화하여 Pause containerZombie process reaping 역할을 위임할 수 있다

  • 활성화 방법

    • 해당 pod yml file의 spec.template.spec.shareProcessNamespace: true로 설정한다

Wrap-up

Kubernetes Pod의 개념

Pod란?

  • Kubernetes에서 배포할 수 있는 최소 객체 단위

    • Pod는 여러 형태의 resource에 의해 배포된다 (Job, ReplicaSet 등)

  • 1개 이상의 container로 이루어진 group

    • 단일 container를 실행하는 pod

    • 여러 container를 실행하는 pod

      • Primary Container

      • Sidecar containers

하나의 container에서 여러 process를 실행하는 것은 권장하지 않는다

  • Container가 실행 중이라도 main process를 제외한 다른 process들이 실행 중인 상태를 보장할 수 없기 때문이다!

Kubernetes Pod의 특정 container가 종료되면, KubeletrestartPolicy에 따라 container를 재시작한다

Pod를 어떻게 구성할지 판단 기준

  • Container들이 꼭 같은 node에서 실행되어야 하는가?

  • 해당 container들이 같은 개수수평 확장되어야 하는가?

  • Container들을 하나의 group으로 함께 배포해야 하는가?

Pod의 container 간 격리

  • Host와 공유되는 namespace

    • cgroup

    • user

  • 같은 pod container 간 공유되는 namespace

    • ipc

    • net

  • Container 별로 격리되는 namespace

    • mount

    • uts

    • pid

      • pid namespace 공유는 optional!

Pause Container란?

  • Container 간 공유될 IPC, Network namespace를 생성하고 유지한다

  • PID namespace 공유 시 Zombie process reaping 역할도 수행한다

Last updated