(今更ながら)コンテナ技術についてのまとめ – cgroup(1)



Linux コンテナはもう基盤として充分にまとまってきた実装になりました。こちらでは、(今更のことになりますが)クラウドでも使用される基盤となっているため、Linuxコンテナを構成している技術類について改めて振り返り、まとめていきます。


こんにちは。SIOS OSSエバンジェリスト/セキュリティ担当の面 和毅です。

Linux コンテナはもう基盤として充分にまとまってきた実装になりました。こちらでは、(今更のことになりますが)クラウドでも使用される基盤となっているため、Linuxコンテナを構成している技術類について改めて振り返り、まとめていきます。


連載予定/目次(おおまかに)

  1. cgroup (cgroup v1とv2の違いを含めて)
  2. User Name Spaceの分離
  3. Capability

cgroup

cgroupとは

『cgroupは「プロセスに対するリソース制限を掛ける」際に使用される』と、あちこちのWebサイトや記事では書かれています。

多分、cgroupに関して一番体系だってまとまっているのはこちらのRed Hat Enterprise Linux 6の「リソース管理ガイド」でしょう。ここによると、cgroupを使ってCPU時間やメモリ、ネットワーク帯域幅を制限できるようです。

また、カーネルのドキュメントについてくる”cgroups.txt”にも詳しく載っています。本シリーズでは、こちらも適宜参照していきます。

では、実際のツールを用いてのcgroupの振る舞いは後程見るとして、このcgroupは「具体的に何なのか」を見ていきます。今回は、cgroup v1とcgroup v2の両方を見て比べてみたいので

  1. linux-2.6.24
  2. linux-4.18.1

の双方でcgroupの実体を見ていきます。適宜、v1とv2で異なるものがあった場合には、それぞれ説明を付与します。


ソースを見てみる

実際にカーネルソースを見てみましょう。まず、「プロセスを制御する」という機能があることから、task_struct()を覗いてみます。task_struct()の定義はlinux/include/linux/sched.hにあります。


struct task_struct {
volatile long state;    /* -1 unrunnable, 0 runnable, >0 stopped */
void *stack;
atomic_t usage;
---省略---
#ifdef CONFIG_CGROUPS
/* Control Group info protected by css_set_lock */
struct css_set *cgroups;
/* cg_list protected by css_set_lock and tsk->alloc_lock */
struct list_head cg_list;
#endif
---省略---

と、CONFIG_CGROUPSが設定されているカーネルではtask_structのメンバとしてControlg Groupの情報が入っています。

このうち、css_setという構造体はlinux/include/linux/cgroup.hで定義されており


/* A css_set is a structure holding pointers to a set of
* cgroup_subsys_state objects. This saves space in the task struct
* object and speeds up fork()/exit(), since a single inc/dec and a
* list_add()/del() can bump the reference count on the entire
* cgroup set for a task.
*/
struct css_set {
/* Reference count */
struct kref ref;
/*
* List running through all cgroup groups. Protected by
* css_set_lock
*/
struct list_head list;
/*
* List running through all tasks using this cgroup
* group. Protected by css_set_lock
*/
struct list_head tasks;
/*
* List of cg_cgroup_link objects on link chains from
* cgroups referenced from this css_set. Protected by
* css_set_lock
*/
struct list_head cg_links;
/*
* Set of subsystem states, one for each subsystem. This array
* is immutable after creation apart from the init_css_set
* during subsystem registration (at boot time).
*/
struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
};

というメンバから構成されています。list_head構造体はlinux/include/linux/list.hで定義されているようにリストを提供しているので、list, tasks, cg_linksがリストとして定義されていることがわかります。krefはリファレンスカウントオブジェクトでkref.hで定義されています。さらにサブシステムの状態セットcgroup_subsys_state構造体の集合をメンバとして持っていることがわかります。cgroup_subsys_state構造体は同じlinux/include/linux/cgroup.hで定義されており


/* Per-subsystem/per-cgroup state maintained by the system. */
struct cgroup_subsys_state {
/* The cgroup that this subsystem is attached to. Useful
* for subsystems that want to know about the cgroup
* hierarchy structure */
struct cgroup *cgroup;
/* State maintained by the cgroup system to allow
* subsystems to be "busy". Should be accessed via css_get()
* and css_put() */
atomic_t refcnt;
unsigned long flags;
};

となっています。このcgroup_subsys_stateでsubsystemがアタッチされているcgroupが定義されているようです。cgroup構造体を確認してみると、include/linux/cgroup/cgroup-defs.h中で定義されており


struct cgroup {
unsigned long flags;            /* "unsigned long" so bitops work */
/* count users of this cgroup. >0 means busy, but doesn't
* necessarily indicate the number of tasks in the
* cgroup */
atomic_t count;
/*
* We link our 'sibling' struct into our parent's 'children'.
* Our children link their 'sibling' into our 'children'.
*/
struct list_head sibling;       /* my parent's children */
struct list_head children;      /* my children */
struct cgroup *parent;  /* my parent */
struct dentry *dentry;          /* cgroup fs entry */
/* Private pointers for each registered subsystem */
struct cgroup_subsys_state *subsys[CGROUP_SUBSYS_COUNT];
struct cgroupfs_root *root;
struct cgroup *top_cgroup;
/*
* List of cg_cgroup_links pointing at css_sets with
* tasks in this cgroup. Protected by css_set_lock
*/
struct list_head css_sets;
/*
* Linked list running through all cgroups that can
* potentially be reaped by the release agent. Protected by
* release_list_lock
*/
struct list_head release_list;
};

となっています。これをまとめると、cgroup()構造体には以下のメンバが含まれています。

  • flag
  • count(このcgroupを使用しているuser数。>0はbusyを表す
  • sibling(自分の親の子供たちのリスト)
  • children(自身の子供たちのリスト)
  • parent(親のcgroup)
  • dentry(cgroup fsエントリ)
  • subsys[CGROUP_SUBSYS_COUNT](cgroup_subsys_state。レジストされているそれぞれのサブシステムへのポインタ
  • root(cgroupfs_root)
  • top_cgroup(cgroup)
  • css_sets(このcgroup中のタスクで、css_setsにポイントされているcg_cgroup_linksのリスト。css_set_lockで保護されている。)
  • release_list(全てのcgroupでリリースエージェントによりreapされたcgroupのリンクされたリスト。)
  • 
    

まとめと次回予告

今回は、ここまでです。次回は今回見たcgroup()構造体の実際の使われ方をもう少し見てみます。


セミナー情報 1

2018年10月22日から10月25日のCSS(Computer Security Symposium)2018で、「OSSセキュリティ技術ワークショップ(OWS) 2018特別セッション」 と題しまして、OSSセキュリティ技術の会後援で特別セッションを開催します。

https://www.iwsec.org/ows/2018/index.htmlにプログラム内容と一般論文申し込みの詳細を載せていきますので、是非御確認下さい(ページは更新中です)。


セミナー情報 2

2018年10月04日に、「OSSの長期利用とメンテナンス 」と題しまして、やまね氏によるセミナーが開催されます。

https://sios.connpass.com/event/100751/にプログラム内容と申し込みページがありますので、是非御確認下さい。

セキュリティ系連載案内

タイトルとURLをコピーしました