Skip to content

Commit 3f24483

Browse files
committed
cluster up: optionally install metrics components
1 parent 188660b commit 3f24483

File tree

6 files changed

+240
-9
lines changed

6 files changed

+240
-9
lines changed

contrib/completions/bash/oc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -648,6 +648,7 @@ _oc_cluster_up()
648648
flags+=("--host-data-dir=")
649649
flags+=("--host-volumes-dir=")
650650
flags+=("--image=")
651+
flags+=("--metrics")
651652
flags+=("--public-hostname=")
652653
flags+=("--routing-suffix=")
653654
flags+=("--server-loglevel=")

contrib/completions/bash/openshift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4236,6 +4236,7 @@ _openshift_cli_cluster_up()
42364236
flags+=("--host-data-dir=")
42374237
flags+=("--host-volumes-dir=")
42384238
flags+=("--image=")
4239+
flags+=("--metrics")
42394240
flags+=("--public-hostname=")
42404241
flags+=("--routing-suffix=")
42414242
flags+=("--server-loglevel=")

pkg/bootstrap/docker/dockerhelper/helper.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -220,7 +220,9 @@ func (h *Helper) ListContainerNames() ([]string, error) {
220220
}
221221
names := []string{}
222222
for _, c := range containers {
223-
names = append(names, c.Names[0])
223+
if len(c.Names) > 0 {
224+
names = append(names, c.Names[0])
225+
}
224226
}
225227
return names, nil
226228
}

pkg/bootstrap/docker/openshift/helper.go

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ type StartOptions struct {
6868
UseExistingConfig bool
6969
Environment []string
7070
LogLevel int
71+
MetricsHost string
7172
}
7273

7374
// NewHelper creates a new OpenShift helper
@@ -223,7 +224,7 @@ func (h *Helper) Start(opt *StartOptions, out io.Writer) (string, error) {
223224
if err != nil {
224225
return "", errors.NewError("could not copy OpenShift configuration").WithCause(err)
225226
}
226-
err = h.updateConfig(configDir, opt.HostConfigDir, opt.ServerIP)
227+
err = h.updateConfig(configDir, opt.HostConfigDir, opt.ServerIP, opt.MetricsHost)
227228
if err != nil {
228229
cleanupConfig()
229230
return "", errors.NewError("could not update OpenShift configuration").WithCause(err)
@@ -351,7 +352,7 @@ func (h *Helper) copyConfig(hostDir string) (string, error) {
351352
return filepath.Join(tempDir, filepath.Base(hostDir)), nil
352353
}
353354

354-
func (h *Helper) updateConfig(configDir, hostDir, serverIP string) error {
355+
func (h *Helper) updateConfig(configDir, hostDir, serverIP, metricsHost string) error {
355356
masterConfig := filepath.Join(configDir, "master", "master-config.yaml")
356357
glog.V(1).Infof("Reading master config from %s", masterConfig)
357358
cfg, err := configapilatest.ReadMasterConfig(masterConfig)
@@ -366,6 +367,10 @@ func (h *Helper) updateConfig(configDir, hostDir, serverIP string) error {
366367
cfg.RoutingConfig.Subdomain = fmt.Sprintf("%s.xip.io", serverIP)
367368
}
368369

370+
if len(metricsHost) > 0 && cfg.AssetConfig != nil {
371+
cfg.AssetConfig.MetricsPublicURL = fmt.Sprintf("https://%s/hawkular/metrics", metricsHost)
372+
}
373+
369374
cfgBytes, err := configapilatest.WriteYAML(cfg)
370375
if err != nil {
371376
return err
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
package openshift
2+
3+
import (
4+
"fmt"
5+
6+
"github.com/openshift/origin/pkg/cmd/util/clientcmd"
7+
kapi "k8s.io/kubernetes/pkg/api"
8+
apierrors "k8s.io/kubernetes/pkg/api/errors"
9+
10+
"github.com/openshift/origin/pkg/bootstrap/docker/errors"
11+
"github.com/openshift/origin/pkg/cmd/admin/policy"
12+
)
13+
14+
const (
15+
infraNamespace = "openshift-infra"
16+
svcMetrics = "hawkular-metrics"
17+
metricsDeployerSA = "metrics-deployer"
18+
)
19+
20+
// InstallMetrics checks whether metrics is installed and installs it if not already installed
21+
func (h *Helper) InstallMetrics(f *clientcmd.Factory, hostName, prefix, imageVersion string) error {
22+
osClient, kubeClient, err := f.Clients()
23+
if err != nil {
24+
return errors.NewError("cannot obtain API clients").WithCause(err).WithDetails(h.OriginLog())
25+
}
26+
27+
_, err = kubeClient.Services(infraNamespace).Get(svcMetrics)
28+
if err == nil {
29+
// If there's no error, the registry already exists
30+
return nil
31+
}
32+
if !apierrors.IsNotFound(err) {
33+
return errors.NewError("error retrieving metrics service").WithCause(err).WithDetails(h.OriginLog())
34+
}
35+
36+
// Create metrics deployer service account
37+
routerSA := &kapi.ServiceAccount{}
38+
routerSA.Name = metricsDeployerSA
39+
_, err = kubeClient.ServiceAccounts(infraNamespace).Create(routerSA)
40+
if err != nil {
41+
return errors.NewError("cannot create metrics deployer service account").WithCause(err).WithDetails(h.OriginLog())
42+
}
43+
44+
// Add edit role to deployer service account
45+
roleBindingAccessor := policy.NewLocalRoleBindingAccessor(infraNamespace, osClient)
46+
addEditRole := policy.RoleModificationOptions{
47+
RoleName: "edit",
48+
RoleBindingAccessor: roleBindingAccessor,
49+
Subjects: []kapi.ObjectReference{
50+
{
51+
Namespace: infraNamespace,
52+
Name: metricsDeployerSA,
53+
Kind: "ServiceAccount",
54+
},
55+
},
56+
}
57+
if err = addEditRole.AddRole(); err != nil {
58+
return errors.NewError("cannot add edit role to metrics deployer service account").WithCause(err).WithDetails(h.OriginLog())
59+
}
60+
61+
// Add cluster reader role to heapster service account
62+
clusterRoleBindingAccessor := policy.NewClusterRoleBindingAccessor(osClient)
63+
addClusterReaderRole := policy.RoleModificationOptions{
64+
RoleName: "cluster-reader",
65+
RoleBindingAccessor: clusterRoleBindingAccessor,
66+
Users: []string{"system:serviceaccount:openshift-infra:heapster"},
67+
}
68+
if err = addClusterReaderRole.AddRole(); err != nil {
69+
return errors.NewError("cannot add cluster reader role to heapster service account").WithCause(err).WithDetails(h.OriginLog())
70+
}
71+
72+
// Create metrics deployer secret
73+
deployerSecret := &kapi.Secret{}
74+
deployerSecret.Name = "metrics-deployer"
75+
deployerSecret.Data = map[string][]byte{"nothing": []byte("/dev/null")}
76+
if _, err = kubeClient.Secrets(infraNamespace).Create(deployerSecret); err != nil {
77+
return errors.NewError("cannot create metrics deployer secret").WithCause(err).WithDetails(h.OriginLog())
78+
}
79+
80+
// Create deployer Pod
81+
imagePrefix := fmt.Sprintf("%s-", prefix)
82+
deployerPod := metricsDeployerPod(hostName, imagePrefix, imageVersion)
83+
if _, err = kubeClient.Pods(infraNamespace).Create(deployerPod); err != nil {
84+
return errors.NewError("cannot create metrics deployer pod").WithCause(err).WithDetails(h.OriginLog())
85+
}
86+
return nil
87+
}
88+
89+
func metricsDeployerPod(hostName, imagePrefix, imageVersion string) *kapi.Pod {
90+
env := []kapi.EnvVar{
91+
{
92+
Name: "PROJECT",
93+
ValueFrom: &kapi.EnvVarSource{
94+
FieldRef: &kapi.ObjectFieldSelector{
95+
FieldPath: "metadata.namespace",
96+
},
97+
},
98+
},
99+
{
100+
Name: "POD_NAME",
101+
ValueFrom: &kapi.EnvVarSource{
102+
FieldRef: &kapi.ObjectFieldSelector{
103+
FieldPath: "metadata.name",
104+
},
105+
},
106+
},
107+
{
108+
Name: "IMAGE_PREFIX",
109+
Value: imagePrefix,
110+
},
111+
{
112+
Name: "IMAGE_VERSION",
113+
Value: imageVersion,
114+
},
115+
{
116+
Name: "MASTER_URL",
117+
Value: "https://kubernetes.default.svc:443",
118+
},
119+
{
120+
Name: "HAWKULAR_METRICS_HOSTNAME",
121+
Value: hostName,
122+
},
123+
{
124+
Name: "MODE",
125+
Value: "deploy",
126+
},
127+
{
128+
Name: "REDEPLOY",
129+
Value: "false",
130+
},
131+
{
132+
Name: "IGNORE_PREFLIGHT",
133+
Value: "false",
134+
},
135+
{
136+
Name: "USE_PERSISTENT_STORAGE",
137+
Value: "false",
138+
},
139+
{
140+
Name: "CASSANDRA_NODES",
141+
Value: "1",
142+
},
143+
{
144+
Name: "CASSANDRA_PV_SIZE",
145+
Value: "10Gi",
146+
},
147+
{
148+
Name: "METRIC_DURATION",
149+
Value: "7",
150+
},
151+
{
152+
Name: "HEAPSTER_NODE_ID",
153+
Value: "nodename",
154+
},
155+
{
156+
Name: "METRIC_RESOLUTION",
157+
Value: "10s",
158+
},
159+
}
160+
pod := &kapi.Pod{
161+
Spec: kapi.PodSpec{
162+
DNSPolicy: kapi.DNSClusterFirst,
163+
RestartPolicy: kapi.RestartPolicyNever,
164+
ServiceAccountName: "metrics-deployer",
165+
Volumes: []kapi.Volume{
166+
{
167+
Name: "empty",
168+
VolumeSource: kapi.VolumeSource{
169+
EmptyDir: &kapi.EmptyDirVolumeSource{},
170+
},
171+
},
172+
{
173+
Name: "secret",
174+
VolumeSource: kapi.VolumeSource{
175+
Secret: &kapi.SecretVolumeSource{
176+
SecretName: "metrics-deployer",
177+
},
178+
},
179+
},
180+
},
181+
},
182+
}
183+
pod.GenerateName = "metrics-deployer-"
184+
pod.Spec.Containers = []kapi.Container{
185+
{
186+
Image: fmt.Sprintf("%smetrics-deployer:%s", imagePrefix, imageVersion),
187+
Name: "deployer",
188+
VolumeMounts: []kapi.VolumeMount{
189+
{
190+
Name: "secret",
191+
MountPath: "/secret",
192+
ReadOnly: true,
193+
},
194+
{
195+
Name: "empty",
196+
MountPath: "/etc/deploy",
197+
},
198+
},
199+
Env: env,
200+
},
201+
}
202+
return pod
203+
}
204+
205+
func MetricsHost(routingSuffix, serverIP string) string {
206+
if len(routingSuffix) > 0 {
207+
return fmt.Sprintf("metrics-openshift-infra.%s", routingSuffix)
208+
}
209+
return fmt.Sprintf("metrics-openshift-infra.%s.xip.io", serverIP)
210+
}

pkg/bootstrap/docker/up.go

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,7 @@ func NewCmdUp(name, fullName string, f *osclientcmd.Factory, out io.Writer) *cob
126126
cmd.Flags().StringVar(&config.HostDataDir, "host-data-dir", "", "Directory on Docker host for OpenShift data. If not specified, etcd data will not be persisted on the host.")
127127
cmd.Flags().IntVar(&config.ServerLogLevel, "server-loglevel", 0, "Log level for OpenShift server")
128128
cmd.Flags().StringSliceVarP(&config.Environment, "env", "e", config.Environment, "Specify key value pairs of environment variables to set on OpenShift container")
129+
cmd.Flags().BoolVar(&config.ShouldInstallMetrics, "metrics", false, "Install metrics (experimental)")
129130
return cmd
130131
}
131132

@@ -145,8 +146,7 @@ type ClientStartConfig struct {
145146
DockerMachine string
146147
ShouldCreateDockerMachine bool
147148
SkipRegistryCheck bool
148-
InstallLogAggregation bool
149-
InstallMetrics bool
149+
ShouldInstallMetrics bool
150150

151151
UseNsenterMount bool
152152
Out io.Writer
@@ -243,6 +243,11 @@ func (c *ClientStartConfig) Complete(f *osclientcmd.Factory, cmd *cobra.Command)
243243
// Install a router
244244
c.addTask("Installing router", c.InstallRouter)
245245

246+
// Install metrics
247+
if c.ShouldInstallMetrics {
248+
c.addTask("Install Metrics", c.InstallMetrics)
249+
}
250+
246251
// Import default image streams
247252
c.addTask("Importing image streams", c.ImportImageStreams)
248253

@@ -471,6 +476,9 @@ func (c *ClientStartConfig) StartOpenShift(out io.Writer) error {
471476
LogLevel: c.ServerLogLevel,
472477
DNSPort: c.DNSPort,
473478
}
479+
if c.ShouldInstallMetrics {
480+
opt.MetricsHost = openshift.MetricsHost(c.RoutingSuffix, c.ServerIP)
481+
}
474482
c.LocalConfigDir, err = c.OpenShiftHelper().Start(opt, out)
475483
return err
476484
}
@@ -518,15 +526,19 @@ func (c *ClientStartConfig) ImportTemplates(out io.Writer) error {
518526
}
519527

520528
/*
521-
// TODO: implement these
529+
// TODO: implement this
522530
func (c *ClientStartConfig) InstallLogging() error {
523531
return nil
524532
}
533+
*/
525534

526-
func (c *ClientStartConfig) InstallMetrics() error {
527-
return nil
535+
func (c *ClientStartConfig) InstallMetrics(out io.Writer) error {
536+
f, err := c.Factory()
537+
if err != nil {
538+
return err
539+
}
540+
return c.OpenShiftHelper().InstallMetrics(f, openshift.MetricsHost(c.RoutingSuffix, c.ServerIP), c.Image, c.ImageVersion)
528541
}
529-
*/
530542

531543
// Login logs into the new server and sets up a default user and project
532544
func (c *ClientStartConfig) Login(out io.Writer) error {

0 commit comments

Comments
 (0)