Skip to content

Commit f7dc1b6

Browse files
committed
*: add CRI-O handler
Signed-off-by: Antonio Murdaca <[email protected]>
1 parent 03d7288 commit f7dc1b6

File tree

6 files changed

+638
-3
lines changed

6 files changed

+638
-3
lines changed

Diff for: container/container.go

+1
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ const (
3434
ContainerTypeDocker
3535
ContainerTypeRkt
3636
ContainerTypeSystemd
37+
ContainerTypeCrio
3738
)
3839

3940
// Interface for container operation handlers.

Diff for: container/crio/client.go

+85
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
// Copyright 2017 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
// Handler for CRI-O containers.
16+
package crio
17+
18+
import (
19+
"encoding/json"
20+
"net/http"
21+
)
22+
23+
type Info struct {
24+
StorageDriver string `json:"storage_driver"`
25+
StorageRoot string `json:"storage_root"`
26+
}
27+
28+
type ContainerInfo struct {
29+
Pid int `json:"pid"`
30+
Image string `json:"image"`
31+
CreatedTime int64 `json:"created_time"`
32+
Labels map[string]string `json:"labels"`
33+
Annotations map[string]string `json:"annotations"`
34+
LogPath string `json:"log_path"`
35+
Root string `json:"root"`
36+
}
37+
38+
type crioClient interface {
39+
Info() (Info, error)
40+
ContainerInfo(string) (*ContainerInfo, error)
41+
}
42+
43+
type crioClientImpl struct {
44+
client *http.Client
45+
}
46+
47+
// Client ...
48+
func Client() (crioClient, error) {
49+
c := &http.Client{}
50+
return &crioClientImpl{
51+
client: c,
52+
}, nil
53+
}
54+
55+
// Info ...
56+
func (c *crioClientImpl) Info() (Info, error) {
57+
info := Info{}
58+
// TODO(runcom): use crio.sock, PR coming in CRI-O
59+
// and also, get it from pkg/kubelet/cadvisor/cadvisor_linux.go
60+
resp, err := c.client.Get("http://localhost:7373/info")
61+
if err != nil {
62+
return info, err
63+
}
64+
defer resp.Body.Close()
65+
if err := json.NewDecoder(resp.Body).Decode(&info); err != nil {
66+
return info, err
67+
}
68+
return info, nil
69+
}
70+
71+
// ContainerInfo ...
72+
func (c *crioClientImpl) ContainerInfo(id string) (*ContainerInfo, error) {
73+
// TODO(runcom): use crio.sock, PR coming in CRI-O
74+
// and also, get it from pkg/kubelet/cadvisor/cadvisor_linux.go
75+
resp, err := c.client.Get("http://localhost:7373/containers/" + id)
76+
if err != nil {
77+
return nil, err
78+
}
79+
defer resp.Body.Close()
80+
cInfo := ContainerInfo{}
81+
if err := json.NewDecoder(resp.Body).Decode(&cInfo); err != nil {
82+
return nil, err
83+
}
84+
return &cInfo, nil
85+
}

Diff for: container/crio/factory.go

+175
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,175 @@
1+
// Copyright 2017 Google Inc. All Rights Reserved.
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// http://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
package crio
16+
17+
import (
18+
"flag"
19+
"fmt"
20+
"path"
21+
"regexp"
22+
"strings"
23+
24+
"github.com/google/cadvisor/container"
25+
"github.com/google/cadvisor/container/libcontainer"
26+
"github.com/google/cadvisor/fs"
27+
info "github.com/google/cadvisor/info/v1"
28+
"github.com/google/cadvisor/manager/watcher"
29+
30+
"github.com/golang/glog"
31+
)
32+
33+
var ArgCrioEndpoint = flag.String("crio", "unix:///var/run/crio.sock", "crio endpoint")
34+
35+
// The namespace under which crio aliases are unique.
36+
const CrioNamespace = "crio"
37+
38+
// Regexp that identifies docker cgroups, containers started with
39+
// --cgroup-parent have another prefix than 'docker'
40+
var crioCgroupRegexp = regexp.MustCompile(`([a-z0-9]{64})`)
41+
42+
type storageDriver string
43+
44+
const (
45+
// TODO add full set of supported drivers in future..
46+
overlayStorageDriver storageDriver = "overlay"
47+
overlay2StorageDriver storageDriver = "overlay2"
48+
)
49+
50+
type crioFactory struct {
51+
machineInfoFactory info.MachineInfoFactory
52+
53+
storageDriver storageDriver
54+
storageDir string
55+
56+
// Information about the mounted cgroup subsystems.
57+
cgroupSubsystems libcontainer.CgroupSubsystems
58+
59+
// Information about mounted filesystems.
60+
fsInfo fs.FsInfo
61+
62+
ignoreMetrics container.MetricSet
63+
64+
client crioClient
65+
}
66+
67+
func (self *crioFactory) String() string {
68+
return CrioNamespace
69+
}
70+
71+
func (self *crioFactory) NewContainerHandler(name string, inHostNamespace bool) (handler container.ContainerHandler, err error) {
72+
client, err := Client()
73+
if err != nil {
74+
return
75+
}
76+
// TODO are there any env vars we need to white list, if so, do it here...
77+
metadataEnvs := []string{}
78+
handler, err = newCrioContainerHandler(
79+
client,
80+
name,
81+
self.machineInfoFactory,
82+
self.fsInfo,
83+
self.storageDriver,
84+
self.storageDir,
85+
&self.cgroupSubsystems,
86+
inHostNamespace,
87+
metadataEnvs,
88+
self.ignoreMetrics,
89+
)
90+
return
91+
}
92+
93+
// Returns the CRIO ID from the full container name.
94+
func ContainerNameToCrioId(name string) string {
95+
id := path.Base(name)
96+
97+
if matches := crioCgroupRegexp.FindStringSubmatch(id); matches != nil {
98+
return matches[1]
99+
}
100+
101+
return id
102+
}
103+
104+
// isContainerName returns true if the cgroup with associated name
105+
// corresponds to a crio container.
106+
func isContainerName(name string) bool {
107+
// always ignore .mount cgroup even if associated with crio and delegate to systemd
108+
if strings.HasSuffix(name, ".mount") {
109+
return false
110+
}
111+
return crioCgroupRegexp.MatchString(path.Base(name))
112+
}
113+
114+
// crio handles all containers under /crio
115+
func (self *crioFactory) CanHandleAndAccept(name string) (bool, bool, error) {
116+
glog.Infof("CRIO CAN HANDLE AND ACCEPT: %v", name)
117+
if strings.HasPrefix(path.Base(name), "crio-conmon") {
118+
glog.Info("SKIPPING CRIO-CONMON")
119+
}
120+
if !strings.HasPrefix(path.Base(name), CrioNamespace) {
121+
return false, false, nil
122+
}
123+
// if the container is not associated with docker, we can't handle it or accept it.
124+
if !isContainerName(name) {
125+
return false, false, nil
126+
}
127+
glog.Infof("CRIO HANDLE AND ACCEPT: %v", name)
128+
// TODO should we call equivalent of a crio info to be sure its really ours
129+
// and to know if the container is running...
130+
return true, true, nil
131+
}
132+
133+
func (self *crioFactory) DebugInfo() map[string][]string {
134+
return map[string][]string{}
135+
}
136+
137+
var (
138+
version_regexp_string = `(\d+)\.(\d+)\.(\d+)`
139+
version_re = regexp.MustCompile(version_regexp_string)
140+
apiversion_regexp_string = `(\d+)\.(\d+)`
141+
apiversion_re = regexp.MustCompile(apiversion_regexp_string)
142+
)
143+
144+
// Register root container before running this function!
145+
func Register(factory info.MachineInfoFactory, fsInfo fs.FsInfo, ignoreMetrics container.MetricSet) error {
146+
client, err := Client()
147+
if err != nil {
148+
return err
149+
}
150+
151+
info, err := client.Info()
152+
if err != nil {
153+
return err
154+
}
155+
// TODO determine crio version so we can work differently w/ future versions if needed
156+
157+
cgroupSubsystems, err := libcontainer.GetCgroupSubsystems()
158+
if err != nil {
159+
return fmt.Errorf("failed to get cgroup subsystems: %v", err)
160+
}
161+
162+
glog.Infof("Registering CRI-O factory")
163+
f := &crioFactory{
164+
client: client,
165+
cgroupSubsystems: cgroupSubsystems,
166+
fsInfo: fsInfo,
167+
machineInfoFactory: factory,
168+
storageDriver: storageDriver(info.StorageDriver),
169+
storageDir: info.StorageRoot,
170+
ignoreMetrics: ignoreMetrics,
171+
}
172+
173+
container.RegisterContainerHandlerFactory(f, []watcher.ContainerWatchSource{watcher.Raw})
174+
return nil
175+
}

0 commit comments

Comments
 (0)