Docker 1.11 daemon模块新特性

■ 文/ 天云软件 马俊

本次分析的Docker版本号:v1.11.0。

我们来看daemon模块,daemon模块核心的结构体是Daemon,同v1.10.0相比增加了containerd和defaultIsolation两个变量,删除了execDriver变量。

type Daemon struct {

       ID                      string

       repository                string

       containers                container.Store

       execCommands           *exec.Store

       referenceStore            reference.Store

       downloadManager           *xfer.LayerDownloadManager

       uploadManager             *xfer.LayerUploadManager

       distributionMetadataStore dmetadata.Store

       trustKey                  libtrust.PrivateKey

       idIndex                   *truncindex.TruncIndex

       configStore               *Config

       statsCollector            *statsCollector

       defaultLogConfig          containertypes.LogConfig

       RegistryService           *registry.Service

       EventsService             *events.Events

       netController             libnetwork.NetworkController

       volumes                   *store.VolumeStore

       discoveryWatcher          discoveryReloader

       root                      string

       seccompEnabled            bool

       shutdown                  bool

       uidMaps                   []idtools.IDMap

       gidMaps                   []idtools.IDMap

       layerStore                layer.Store

       imageStore                image.Store

       nameIndex                 *registrar.Registrar

       linkIndex                 *linkIndex

       containerd                libcontainerd.Client

       defaultIsolation          containertypes.Isolation

}

containerd这个变量替换了execDriver变量,因为从1.10版本,docker已经完全放弃了对LXC容器的支持,把没有用的代码都删除掉了;defaultIsolation这个变量作用是在windows操作系统上设置容器默认隔离模式,用来更好地对windows操作系统上容器提供支持。

Docker 1.11版本依赖于containerd和runC来管理容器,containerd是控制runC的后台程序,runC是Docker公司按照OCI标准规范编写的一个操作容器的命令行工具,containerd这个后台程序还可以操作满足OCI标准规范的其他容器工具,也就意味着以后只要是按照ODI标准规范开发的容器工具,都可以被containerd使用起来。使用containerd的好处是,当docker daemon或者containerd两个进程crash后,应用容器不会“死掉”,未来要实现的功能是,当containerd daemon重新启动后可以同应用容器重新建立连接。

Docker 1.11版本daemon模块调用关系图如下:

docker_daemon01

在NewDaemon这个方法中,还预留了对AppArmor的支持接口,但是并没有写具体实现源代码。AppArmor(Application Armor)是Linux内核的一个安全模块,AppArmor允许系统管理员将每个程序与一个安全配置文件关联,从而限制程序的功能。简单的说,AppArmor是与SELinux类似的一个访问控制系统,通过它你可以指定程序可以读、写或运行哪些文件,是否可以打开网络端口等。作为对传统Unix的自主访问控制模块的补充,AppArmor提供了强制访问控制机制,它已经被整合到2.6版本的Linux内核中。

在NewDaemon这个方法中,还预留了设置运行时最大线程数的配置方法configureMaxThreads,但是并没有写具体实现源代码。

结构体ImageInspect增加了变量RootFS,在inspect镜像的时候可以输出rootfs内容,显示基础层的名字和每层文件系统ID。

在daemon模块中还增加了错误日志输出内容,更方便定位和维护。

下面是最新的daemon版本同remote api版本的对应关系

Docker Daemon版本

Docker Remote API版本

1.11.x

1.23

1.10.x

1.22

1.9.x

1.21

1.8.x

1.20

1.7.x

1.19

1.6.x

1.18

1.5.x

1.17

1.4.x

1.16

1.3.x

1.15

1.2.x

1.14

在1.11版本中Remote API相关功能变化如下:

在创建容器时,相比1.10增加了一个功能,如果linux内核版本超过了4.3,容器就支持pids cgroup,也就是可以根据cgroup限制容器中的进程数;还增加了nocopy选项,docker run -v foo:/bar:nocopy,这样就不会自动将数据从容器路径拷贝到卷路径;还修改CreateDaemonEnvironment方法,如果创建容器时使用到了Hostname变量和Domainname变量,那么在设置容器中HOSTNAME环境变量时设置的是Hostname变量,在v1.10.0中设置的是Hostname.Domainname。

GET /containers/json返回值结构体:

type Container struct {

       ID         string `json:”Id”`

       Names      []string

       Image      string

       ImageID    string

       Command    string

       Created    int64

       Ports      []Port

       SizeRw     int64 `json:”,omitempty”`

       SizeRootFs int64 `json:”,omitempty”`

       Labels     map[string]string

       State      string

       Status     string

       HostConfig struct {

              NetworkMode string `json:”,omitempty”`

       }

       NetworkSettings *SummaryNetworkSettings

       Mounts          []MountPoint

}

相比1.10增加了State变量和Mounts变量,State变量表示容器的状态,包括created、restarting、running、paused、exited和dead六种状态,Mounts变量表示容器的挂载点信息,挂载点信息结构体MountPoint如下:

type MountPoint struct {

       Name        string `json:”,omitempty”`

       Source      string

       Destination string

       Driver      string `json:”,omitempty”`

       Mode        string

       RW          bool

       Propagation string

}

GET /containers/(id or name)/stats返回结构体containerStats:

type containerStats struct {

       Name             string

       CPUPercentage    float64

       Memory           float64

       MemoryLimit      float64

       MemoryPercentage float64

       NetworkRx        float64

       NetworkTx        float64

       BlockRead        float64

       BlockWrite       float64

       PidsCurrent      uint64

       mu               sync.RWMutex

       err              error

}

相比1.10增加了PidsCurrent,如果linux内核版本超过了4.3,容器就支持pids cgroup,在stats时就会返回pids信息。

GET /info返回结构体Info:

type Info struct {

       ID                 string

       Containers         int

       ContainersRunning  int

       ContainersPaused   int

       ContainersStopped  int

       Images             int

       Driver             string

       DriverStatus       [][2]string

       SystemStatus       [][2]string

       Plugins            PluginsInfo

       MemoryLimit        bool

       SwapLimit          bool

       KernelMemory       bool

       CPUCfsPeriod       bool `json:”CpuCfsPeriod”`

       CPUCfsQuota        bool `json:”CpuCfsQuota”`

       CPUShares          bool

       CPUSet             bool

       IPv4Forwarding     bool

       BridgeNfIptables   bool

       BridgeNfIP6tables  bool `json:”BridgeNfIp6tables”`

       Debug              bool

       NFd                int

       OomKillDisable     bool

       NGoroutines        int

       SystemTime         string

       ExecutionDriver    string

       LoggingDriver      string

       CgroupDriver       string

       NEventsListener    int

       KernelVersion      string

       OperatingSystem    string

       OSType             string

       Architecture       string

       IndexServerAddress string

       RegistryConfig     *registry.ServiceConfig

       NCPU               int

       MemTotal           int64

       DockerRootDir      string

       HTTPProxy          string `json:”HttpProxy”`

       HTTPSProxy         string `json:”HttpsProxy”`

       NoProxy            string

       Name               string

       Labels             []string

       ExperimentalBuild  bool

       ServerVersion      string

       ClusterStore       string

       ClusterAdvertise   string

}

相比1.10增加了KernelMemory变量和CgroupDriver变量,KernelMemory变量表示是否设置linux内核内存限制,CgroupDriver变量表示使用哪个Cgroup驱动,有两种驱动,分别是cgroupfs和systemd,默认使用cgroupfs,下面的例子是使用systemd:

sudo docker daemon –exec-opt native.cgroupdriver=system 

更新容器信息POST /containers/(name)/update结构体UpdateConfig如下:

type UpdateConfig struct {

       // Contains container’s resources (cgroups, ulimits)

       Resources

       RestartPolicy RestartPolicy

}

相比1.10增加了RestartPolicy变量,这个变量用来设置容器重启策略,用来配置容器退出后的操作行为。

GET /networks/(name)返回值结构体:

type NetworkResource struct {

       Name       string

       ID         string `json:”Id”`

       Scope      string

       Driver     string

       EnableIPv6 bool

       IPAM       network.IPAM

       Internal   bool

       Containers map[string]EndpointResource

       Options    map[string]string

       Labels     map[string]string

}

相比1.10增加了EnableIPv6变量、Internal变量和Labels三个变量,EnableIPv6变量表示是否启用了IPv6,在创建网络时,通过POST /networks/create可以设置,Internal变量表示网络是否内部网络,Labels变量表示创建时的网络标签。