Skip to content

Commit

Permalink
cluster up: add persistent volumes on startup
Browse files Browse the repository at this point in the history
  • Loading branch information
csrwng committed Jan 11, 2017
1 parent ba5e5e9 commit 0d35314
Show file tree
Hide file tree
Showing 14 changed files with 243 additions and 61 deletions.
2 changes: 2 additions & 0 deletions contrib/completions/bash/oc
Original file line number Diff line number Diff line change
Expand Up @@ -5620,6 +5620,8 @@ _oc_cluster_up()
local_nonpersistent_flags+=("--logging")
flags+=("--metrics")
local_nonpersistent_flags+=("--metrics")
flags+=("--persistent-volumes-dir=")
local_nonpersistent_flags+=("--persistent-volumes-dir=")
flags+=("--public-hostname=")
local_nonpersistent_flags+=("--public-hostname=")
flags+=("--routing-suffix=")
Expand Down
2 changes: 2 additions & 0 deletions contrib/completions/bash/openshift
Original file line number Diff line number Diff line change
Expand Up @@ -10241,6 +10241,8 @@ _openshift_cli_cluster_up()
local_nonpersistent_flags+=("--logging")
flags+=("--metrics")
local_nonpersistent_flags+=("--metrics")
flags+=("--persistent-volumes-dir=")
local_nonpersistent_flags+=("--persistent-volumes-dir=")
flags+=("--public-hostname=")
local_nonpersistent_flags+=("--public-hostname=")
flags+=("--routing-suffix=")
Expand Down
2 changes: 2 additions & 0 deletions contrib/completions/zsh/oc
Original file line number Diff line number Diff line change
Expand Up @@ -5768,6 +5768,8 @@ _oc_cluster_up()
local_nonpersistent_flags+=("--logging")
flags+=("--metrics")
local_nonpersistent_flags+=("--metrics")
flags+=("--persistent-volumes-dir=")
local_nonpersistent_flags+=("--persistent-volumes-dir=")
flags+=("--public-hostname=")
local_nonpersistent_flags+=("--public-hostname=")
flags+=("--routing-suffix=")
Expand Down
2 changes: 2 additions & 0 deletions contrib/completions/zsh/openshift
Original file line number Diff line number Diff line change
Expand Up @@ -10389,6 +10389,8 @@ _openshift_cli_cluster_up()
local_nonpersistent_flags+=("--logging")
flags+=("--metrics")
local_nonpersistent_flags+=("--metrics")
flags+=("--persistent-volumes-dir=")
local_nonpersistent_flags+=("--persistent-volumes-dir=")
flags+=("--public-hostname=")
local_nonpersistent_flags+=("--public-hostname=")
flags+=("--routing-suffix=")
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/oc-cluster-up.1
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ A public hostname can also be specified for the server with the \-\-public\-host
\fB\-\-metrics\fP=false
If true, install metrics (experimental)

.PP
\fB\-\-persistent\-volumes\-dir\fP="/var/lib/origin/openshift.local.pv"
Directory on host for OpenShift persistent volumes

.PP
\fB\-\-public\-hostname\fP=""
Public hostname for OpenShift cluster
Expand Down
4 changes: 4 additions & 0 deletions docs/man/man1/openshift-cli-cluster-up.1
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,10 @@ A public hostname can also be specified for the server with the \-\-public\-host
\fB\-\-metrics\fP=false
If true, install metrics (experimental)

.PP
\fB\-\-persistent\-volumes\-dir\fP="/var/lib/origin/openshift.local.pv"
Directory on host for OpenShift persistent volumes

.PP
\fB\-\-public\-hostname\fP=""
Public hostname for OpenShift cluster
Expand Down
48 changes: 30 additions & 18 deletions pkg/bootstrap/docker/host/host.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,37 +14,46 @@ import (
)

const (
cmdTestNsenterMount = "nsenter --mount=/rootfs/proc/1/ns/mnt findmnt"
cmdEnsureHostDirs = "for dir in %s; do if [ ! -d \"${dir}\" ]; then mkdir -p \"${dir}\"; fi; done"
cmdTestNsenterMount = "nsenter --mount=/rootfs/proc/1/ns/mnt findmnt"
cmdEnsureHostDirs = `#/bin/bash
for dir in %s; do
if [ ! -d "${dir}" ]; then
mkdir -p "${dir}"
fi
done
`
cmdCreateVolumesDirBindMount = "cat /rootfs/proc/1/mountinfo | grep /var/lib/origin || " +
"nsenter --mount=/rootfs/proc/1/ns/mnt mount -o bind %[1]s %[1]s"
cmdCreateVolumesDirShare = "cat /rootfs/proc/1/mountinfo | grep %[1]s | grep shared || " +
"nsenter --mount=/rootfs/proc/1/ns/mnt mount --make-shared %[1]s"

DefaultVolumesDir = "/var/lib/origin/openshift.local.volumes"
DefaultConfigDir = "/var/lib/origin/openshift.local.config"
DefaultVolumesDir = "/var/lib/origin/openshift.local.volumes"
DefaultConfigDir = "/var/lib/origin/openshift.local.config"
DefaultPersistentVolumesDir = "/var/lib/origin/openshift.local.pv"
)

// HostHelper contains methods to help check settings on a Docker host machine
// using a privileged container
type HostHelper struct {
runHelper *run.RunHelper
client *docker.Client
image string
volumesDir string
configDir string
dataDir string
runHelper *run.RunHelper
client *docker.Client
image string
volumesDir string
configDir string
dataDir string
persistentVolumesDir string
}

// NewHostHelper creates a new HostHelper
func NewHostHelper(client *docker.Client, image, volumesDir, configDir, dataDir string) *HostHelper {
func NewHostHelper(client *docker.Client, image, volumesDir, configDir, dataDir, pvDir string) *HostHelper {
return &HostHelper{
runHelper: run.NewRunHelper(client),
client: client,
image: image,
volumesDir: volumesDir,
configDir: configDir,
dataDir: dataDir,
runHelper: run.NewRunHelper(client),
client: client,
image: image,
volumesDir: volumesDir,
configDir: configDir,
dataDir: dataDir,
persistentVolumesDir: pvDir,
}
}

Expand Down Expand Up @@ -147,13 +156,16 @@ func (h *HostHelper) EnsureHostDirectories() error {
if h.volumesDir == DefaultVolumesDir {
dirs = append(dirs, path.Join("/rootfs", h.volumesDir))
}
if h.persistentVolumesDir == DefaultPersistentVolumesDir {
dirs = append(dirs, path.Join("/rootfs", h.persistentVolumesDir))
}
if len(dirs) > 0 {
cmd := fmt.Sprintf(cmdEnsureHostDirs, strings.Join(dirs, " "))
rc, err := h.runner().
Image(h.image).
DiscardContainer().
Privileged().
Bind("/var:/rootfs/var").
Bind("/var:/rootfs/var:z").
Entrypoint("/bin/bash").
Command("-c", cmd).Run()
if err != nil || rc != 0 {
Expand Down
10 changes: 9 additions & 1 deletion pkg/bootstrap/docker/openshift/admin.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"fmt"
"io"
"os"
"path"
"path/filepath"

"github.com/golang/glog"
Expand All @@ -31,7 +32,7 @@ const (
)

// InstallRegistry checks whether a registry is installed and installs one if not already installed
func (h *Helper) InstallRegistry(kubeClient kclientset.Interface, f *clientcmd.Factory, configDir, images string, out, errout io.Writer) error {
func (h *Helper) InstallRegistry(kubeClient kclientset.Interface, f *clientcmd.Factory, configDir, images, pvDir string, out, errout io.Writer) error {
_, err := kubeClient.Core().Services(DefaultNamespace).Get(SvcDockerRegistry)
if err == nil {
// If there's no error, the registry already exists
Expand All @@ -40,6 +41,12 @@ func (h *Helper) InstallRegistry(kubeClient kclientset.Interface, f *clientcmd.F
if !apierrors.IsNotFound(err) {
return errors.NewError("error retrieving docker registry service").WithCause(err).WithDetails(h.OriginLog())
}

err = AddSCCToServiceAccount(kubeClient, "privileged", "registry", "default")
if err != nil {
return errors.NewError("cannot add privileged SCC to registry service account").WithCause(err).WithDetails(h.OriginLog())
}

imageTemplate := variable.NewDefaultImageTemplate()
imageTemplate.Format = images
opts := &registry.RegistryOptions{
Expand All @@ -52,6 +59,7 @@ func (h *Helper) InstallRegistry(kubeClient kclientset.Interface, f *clientcmd.F
Labels: "docker-registry=default",
Volume: "/registry",
ServiceAccount: "registry",
HostMount: path.Join(pvDir, "registry"),
},
}
cmd := registry.NewCmdRegistry(f, "", "registry", out, errout)
Expand Down
36 changes: 21 additions & 15 deletions pkg/bootstrap/docker/openshift/helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -68,21 +68,22 @@ type Helper struct {

// StartOptions represent the parameters sent to the start command
type StartOptions struct {
ServerIP string
RouterIP string
DNSPort int
UseSharedVolume bool
SetPropagationMode bool
Images string
HostVolumesDir string
HostConfigDir string
HostDataDir string
UseExistingConfig bool
Environment []string
LogLevel int
MetricsHost string
LoggingHost string
PortForwarding bool
ServerIP string
RouterIP string
DNSPort int
UseSharedVolume bool
SetPropagationMode bool
Images string
HostVolumesDir string
HostConfigDir string
HostDataDir string
HostPersistentVolumesDir string
UseExistingConfig bool
Environment []string
LogLevel int
MetricsHost string
LoggingHost string
PortForwarding bool
}

// NewHelper creates a new OpenShift helper
Expand Down Expand Up @@ -351,6 +352,9 @@ func (h *Helper) Start(opt *StartOptions, out io.Writer) (string, error) {
if len(opt.HostDataDir) > 0 {
binds = append(binds, fmt.Sprintf("%s:/var/lib/origin/openshift.local.etcd:z", opt.HostDataDir))
}
if len(opt.HostPersistentVolumesDir) > 0 {
binds = append(binds, fmt.Sprintf("%s:/var/lib/origin/openshift.local.pv:z", opt.HostPersistentVolumesDir))
}
_, err = h.runHelper.New().Image(h.image).
Name(h.containerName).
Privileged().
Expand Down Expand Up @@ -505,6 +509,8 @@ func (h *Helper) updateConfig(configDir, routerIP, metricsHost, loggingHost stri
cfg.AssetConfig.LoggingPublicURL = fmt.Sprintf("https://%s", loggingHost)
}

cfg.JenkinsPipelineConfig.TemplateName = "jenkins-persistent"

cfgBytes, err := configapilatest.WriteYAML(cfg)
if err != nil {
return err
Expand Down
1 change: 1 addition & 0 deletions pkg/bootstrap/docker/openshift/logging.go
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ func (h *Helper) InstallLogging(f *clientcmd.Factory, publicHostname, loggerHost
"public-master-url": fmt.Sprintf("https://%s:8443", publicHostname),
"es-cluster-size": "1",
"es-instance-ram": "1024M",
"es-pvc-size": "100G",
}
kubeClient.Core().ConfigMaps(loggingNamespace).Create(loggingConfig)

Expand Down
2 changes: 1 addition & 1 deletion pkg/bootstrap/docker/openshift/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ func metricsDeployerJob(hostName, imagePrefix, imageVersion string) *kbatch.Job
},
{
Name: "USE_PERSISTENT_STORAGE",
Value: "false",
Value: "true",
},
{
Name: "CASSANDRA_NODES",
Expand Down
125 changes: 125 additions & 0 deletions pkg/bootstrap/docker/openshift/pvsetup.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
package openshift

import (
"fmt"

kapi "k8s.io/kubernetes/pkg/api"
kbatch "k8s.io/kubernetes/pkg/apis/batch"
kclientset "k8s.io/kubernetes/pkg/client/clientset_generated/internalclientset"

"github.com/openshift/origin/pkg/bootstrap/docker/errors"
"github.com/openshift/origin/pkg/client"
)

const pvCount = 1000
const createPVScript = `#/bin/bash
set -e
function create_pv() {
BASEDIR=${1}
NAME=${2}
cat <<EOF
apiVersion: v1
kind: PersistentVolume
metadata:
name: ${NAME}
labels:
volume: ${NAME}
spec:
capacity:
storage: 100Gi
accessModes:
- ReadWriteOnce
hostPath:
path: ${BASEDIR}/${NAME}
persistentVolumeReclaimPolicy: Retain
EOF
}
mkdir -p /var/lib/origin/openshift.local.pv/registry /var/lib/origin/openshift.local.pv/pv{1..%[1]d}
if ! chcon -t svirt_sandbox_file_t -R /var/lib/origin/openshift.local.pv &> /dev/null; then
echo "Not applying SELinux labels"
fi
chmod 770 -R /var/lib/origin/openshift.local.pv
for i in {1..%[1]d}; do
create_pv "%[2]s" pv${i} | oc create -f -
# Pause every 10 reps to rate-limit creation
export index=${i}
if [[ "$(expr ${index} %% 10)" == "0" ]]; then
sleep 1
fi
done
`

func (h *Helper) SetupPersistentStorage(osclient client.Interface, kclient kclientset.Interface, dir string) error {

// Check whether a PV installer SA exists. If it does, PVs have already
// been provisioned.
sa, err := kclient.Core().ServiceAccounts("default").Get("pvinstaller")
if err == nil {
return nil
}

// Create installer SA
sa = &kapi.ServiceAccount{}
sa.Name = "pvinstaller"
_, err = kclient.Core().ServiceAccounts("default").Create(sa)
if err != nil {
return errors.NewError("cannot create pvinstaller service account").WithCause(err).WithDetails(h.OriginLog())
}
err = AddSCCToServiceAccount(kclient, "privileged", "pvinstaller", "default")
if err != nil {
return errors.NewError("cannot add privileged SCC to pvinstaller service account").WithCause(err).WithDetails(h.OriginLog())
}
err = AddClusterRole(osclient, "cluster-admin", "system:serviceaccount:default:pvinstaller")
if err != nil {
return errors.NewError("cannot add cluster role to pvinstaller service account").WithCause(err).WithDetails(h.OriginLog())
}

setupJob := persistentStorageSetupJob(dir, h.image)
_, err = kclient.Batch().Jobs("default").Create(setupJob)
if err != nil {
return errors.NewError("cannot create job to setup persistent volumes").WithCause(err).WithDetails(h.OriginLog())
}

return nil
}

func persistentStorageSetupJob(dir, image string) *kbatch.Job {
// Job volume
volume := kapi.Volume{}
volume.Name = "pvdir"
volume.HostPath = &kapi.HostPathVolumeSource{Path: dir}

// Volume mount
mount := kapi.VolumeMount{}
mount.Name = "pvdir"
mount.MountPath = "/var/lib/origin/openshift.local.pv"

// Job container
container := kapi.Container{}
container.Name = "storage-setup-job"
container.Image = image
container.Command = []string{"/bin/bash", "-c", fmt.Sprintf(createPVScript, pvCount, dir)}
privileged := true
container.SecurityContext = &kapi.SecurityContext{
Privileged: &privileged,
}
container.VolumeMounts = []kapi.VolumeMount{mount}

// Job
completions := int32(1)
deadline := int64(60 * 20)
job := &kbatch.Job{}
job.GenerateName = "persistent-storage-setup-"
job.Spec.Completions = &completions
job.Spec.ActiveDeadlineSeconds = &deadline
job.Spec.Template.Spec.Volumes = []kapi.Volume{volume}
job.Spec.Template.Spec.RestartPolicy = kapi.RestartPolicyNever
job.Spec.Template.Spec.ServiceAccountName = "pvinstaller"
job.Spec.Template.Spec.Containers = []kapi.Container{container}
return job
}
1 change: 1 addition & 0 deletions pkg/bootstrap/docker/status.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ func status(container *docker.Container, config *api.MasterConfig) string {

status = status + fmt.Sprintf("Config is at host directory %s\n", mountMap["/var/lib/origin/openshift.local.config"])
status = status + fmt.Sprintf("Volumes are at host directory %s\n", mountMap["/var/lib/origin/openshift.local.volumes"])
status = status + fmt.Sprintf("Persistent volumes are at host directory %s\n", mountMap["/var/lib/origin/openshift.local.pv"])
if _, hasKey := mountMap["/var/lib/origin/openshift.local.etcd"]; hasKey {
status = status + fmt.Sprintf("Data is at host directory %s\n", mountMap["/var/lib/origin/openshift.local.etcd"])
} else {
Expand Down
Loading

0 comments on commit 0d35314

Please sign in to comment.