Apache Mesos
cni.hpp
Go to the documentation of this file.
1 // Licensed to the Apache Software Foundation (ASF) under one
2 // or more contributor license agreements. See the NOTICE file
3 // distributed with this work for additional information
4 // regarding copyright ownership. The ASF licenses this file
5 // to you under the Apache License, Version 2.0 (the
6 // "License"); you may not use this file except in compliance
7 // with the License. You may obtain a copy of the License at
8 //
9 // http://www.apache.org/licenses/LICENSE-2.0
10 //
11 // Unless required by applicable law or agreed to in writing, software
12 // distributed under the License is distributed on an "AS IS" BASIS,
13 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 // See the License for the specific language governing permissions and
15 // limitations under the License.
16 
17 #ifndef __NETWORK_CNI_ISOLATOR_HPP__
18 #define __NETWORK_CNI_ISOLATOR_HPP__
19 
20 #include <process/id.hpp>
21 #include <process/subprocess.hpp>
22 
23 #include <stout/subcommand.hpp>
24 
25 #include "slave/flags.hpp"
26 
28 
31 
32 #include "linux/ns.hpp"
33 
34 namespace mesos {
35 namespace internal {
36 namespace slave {
37 
38 // Forward declarations.
39 class NetworkCniIsolatorSetup;
40 
41 
42 // This isolator implements support for Container Network Interface (CNI)
43 // specification <https://github.com/appc/cni/blob/master/SPEC.md> . It
44 // provides network isolation to containers by creating a network namespace
45 // for each container, and then adding the container to the CNI network
46 // specified in the NetworkInfo for the container. It adds the container to
47 // a CNI network by using CNI plugins specified by the operator for the
48 // corresponding CNI network.
50 {
51 public:
53 
55 
56  bool supportsNesting() override;
57 
59  const std::vector<mesos::slave::ContainerState>& states,
60  const hashset<ContainerID>& orphans) override;
61 
63  const ContainerID& containerId,
64  const mesos::slave::ContainerConfig& containerConfig) override;
65 
67  const ContainerID& containerId,
68  pid_t pid) override;
69 
71  const ContainerID& containerId) override;
72 
74  const ContainerID& containerId) override;
75 
77  const ContainerID& containerId) override;
78 
79 private:
80  struct ContainerNetwork
81  {
82  // CNI network name.
83  std::string networkName;
84 
85  // Interface name.
86  std::string ifName;
87 
88  // NetworkInfo copied from the ExecutorInfo.containerInfo.network_infos
89  // in 'prepare()' and '_recover()'.
90  Option<mesos::NetworkInfo> networkInfo;
91 
92  // Protobuf of CNI network information returned by CNI plugin.
93  Option<cni::spec::NetworkInfo> cniNetworkInfo;
94  };
95 
96  struct Info
97  {
98  Info (const hashmap<std::string, ContainerNetwork>& _containerNetworks,
99  const Option<std::string>& _rootfs = None(),
100  const Option<std::string>& _hostname = None(),
101  bool _joinsParentsNetwork = false)
102  : containerNetworks (_containerNetworks),
103  rootfs(_rootfs),
104  hostname(_hostname),
105  joinsParentsNetwork(_joinsParentsNetwork) {}
106 
107  // CNI network information keyed by network name.
108  //
109  // NOTE: For nested containers, since the container shares the
110  // network namespace with the root container of its hierarchy,
111  // this should simply be a copy of the `containerNetworks` of its
112  // root container.
113  hashmap<std::string, ContainerNetwork> containerNetworks;
114 
115  // Rootfs of the container file system. In case the container uses
116  // the host file system, this will be `None`.
117  const Option<std::string> rootfs;
118 
120  const bool joinsParentsNetwork;
121  };
122 
123  // Reads each CNI config present in `configDir`, validates if the
124  // `plugin` is present in the search path associated with
125  // `pluginDir` and adds the CNI network config to `networkConfigs`
126  // if the validation passes. If there is an error while reading the
127  // CNI config, or if the plugin is not found, we log an error and the
128  // CNI network config is not added to `networkConfigs`.
129  static Try<hashmap<std::string, std::string>> loadNetworkConfigs(
130  const std::string& configDir,
131  const std::string& pluginDir);
132 
134  const Flags& _flags,
135  const hashmap<std::string, std::string>& _networkConfigs,
137  const Option<ContainerDNSInfo::MesosInfo>& _defaultCniDNS = None(),
138  const Option<std::string>& _rootDir = None())
139  : ProcessBase(process::ID::generate("mesos-network-cni-isolator")),
140  flags(_flags),
141  networkConfigs(_networkConfigs),
142  cniDNSMap(_cniDNSMap),
143  defaultCniDNS(_defaultCniDNS),
144  rootDir(_rootDir) {}
145 
146  process::Future<Nothing> _isolate(
147  const ContainerID& containerId,
148  pid_t pid,
149  const std::vector<process::Future<Nothing>>& attaches);
150 
151  process::Future<Nothing> __isolate(
152  const NetworkCniIsolatorSetup& setup);
153 
154  Try<Nothing> _recover(
155  const ContainerID& containerId,
156  const Option<mesos::slave::ContainerState>& state = None());
157 
159  const ContainerID& containerId,
160  const std::string& networkName,
161  const std::string& netNsHandle);
162 
163  process::Future<Nothing> _attach(
164  const ContainerID& containerId,
165  const std::string& networkName,
166  const std::string& plugin,
167  const std::tuple<
171 
173  const ContainerID& containerId,
174  const std::string& networkName);
175 
176  process::Future<Nothing> _detach(
177  const ContainerID& containerId,
178  const std::string& networkName,
179  const std::string& plugin,
180  const std::tuple<
184 
185  process::Future<Nothing> _cleanup(
186  const ContainerID& containerId,
187  const std::vector<process::Future<Nothing>>& detaches);
188 
189  static Try<ResourceStatistics> _usage(
190  const hashset<std::string> ifNames);
191 
192  // Searches the `networkConfigs` hashmap for a CNI network. If the
193  // hashmap doesn't contain the network, will try to load all the CNI
194  // configs from `flags.network_cni_config_dir`, and will then
195  // perform another search of the `networkConfigs` hashmap to see if
196  // the missing network was present on disk.
197  Try<JSON::Object> getNetworkConfigJSON(const std::string& network);
198 
199  // Given a network name and the path for the CNI network
200  // configuration file, reads the file, parses the JSON and
201  // validates the name of the network to which this configuration
202  // file belongs.
203  Try<JSON::Object> getNetworkConfigJSON(
204  const std::string& network,
205  const std::string& path);
206 
207  const Flags flags;
208 
209  // A map storing the path to CNI network configuration files keyed
210  // by the network name.
211  hashmap<std::string, std::string> networkConfigs;
212 
213  // DNS informations of CNI networks keyed by CNI network name.
215 
216  // Default DNS information for all CNI networks.
217  const Option<ContainerDNSInfo::MesosInfo> defaultCniDNS;
218 
219  // CNI network information root directory.
220  const Option<std::string> rootDir;
221 
222  // Information of CNI networks that each container joins.
224 
225  // Runner manages a separate thread to call `usage` functions
226  // in the containers' namespaces.
227  ns::NamespaceRunner namespaceRunner;
228 };
229 
230 
231 // A subcommand to setup container hostname and mount the hosts,
232 // resolv.conf and hostname from the host file system into the
233 // container's file system. The hostname needs to be setup in the
234 // container's UTS namespace, and the files need to be bind mounted in
235 // the container's mnt namespace.
237 {
238 public:
239  static const char* NAME;
240 
241  struct Flags : public virtual flags::FlagsBase
242  {
243  Flags();
244 
253  };
254 
256 
258 
259 protected:
260  int execute() override;
261  flags::FlagsBase* getFlags() override { return &flags; }
262 };
263 
264 } // namespace slave {
265 } // namespace internal {
266 } // namespace mesos {
267 
268 #endif // __NETWORK_CNI_ISOLATOR_HPP__
Definition: path.hpp:26
std::string generate(const std::string &prefix="")
Returns &#39;prefix(N)&#39; where N represents the number of instances where the same prefix (wrt...
void execute(const std::string &script)
ProcessBase(const std::string &id="")
NetworkCniIsolatorSetup()
Definition: cni.hpp:255
Definition: check.hpp:33
~NetworkCniIsolatorProcess() override
Definition: cni.hpp:54
Definition: flags.hpp:39
DWORD pid_t
Definition: windows.hpp:181
Option< std::string > etc_resolv_conf
Definition: cni.hpp:250
Definition: subcommand.hpp:41
Definition: flags.hpp:44
Definition: spec.hpp:26
static Try< mesos::slave::Isolator * > create(const Flags &flags)
Try< std::string > hostname()
Definition: net.hpp:154
process::Future< Option< mesos::slave::ContainerLaunchInfo > > prepare(const ContainerID &containerId, const mesos::slave::ContainerConfig &containerConfig) override
process::Future< Nothing > isolate(const ContainerID &containerId, pid_t pid) override
Option< std::string > etc_hosts_path
Definition: cni.hpp:248
Option< std::string > rootfs
Definition: cni.hpp:247
process::Future< Nothing > cleanup(const ContainerID &containerId) override
Definition: none.hpp:27
Definition: attributes.hpp:24
flags::FlagsBase * getFlags() override
Definition: cni.hpp:261
Definition: ns.hpp:190
process::Future< ContainerStatus > status(const ContainerID &containerId) override
process::Future< ResourceStatistics > usage(const ContainerID &containerId) override
Option< std::string > hostname
Definition: cni.hpp:246
Option< pid_t > pid
Definition: cni.hpp:245
Definition: parse.hpp:33
process::Future< Nothing > recover(const std::vector< mesos::slave::ContainerState > &states, const hashset< ContainerID > &orphans) override
Option< std::string > etc_hostname_path
Definition: cni.hpp:249
static const char * NAME
Definition: cni.hpp:239