Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

add example with lammps pvc #66

Merged
merged 2 commits into from
Sep 26, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions examples/addons/volumes/lammps-pvc.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
apiVersion: flux-framework.org/v1alpha2
kind: MetricSet
metadata:
labels:
app.kubernetes.io/name: metricset
app.kubernetes.io/instance: metricset-sample
name: metricset-sample
spec:
# Number of pods for lammps (one launcher, the rest workers)
pods: 4

# Keep interactive so we can decide when to quit
logging:
interactive: true

metrics:

# Running more scaled lammps is our main goal
- name: app-lammps

# This has intel mpi on rocky linux, per suggested by Google
image: ghcr.io/converged-computing/metric-lammps-intel-mpi:rocky

options:
command: lmp -v x 2 -v y 2 -v z 2 -in in.reaxc.hns -nocite
workdir: /opt/lammps/examples/reaxff/HNS
soleTenancy: "true"

# Add on hpctoolkit, will mount a volume and wrap lammps
addons:

- name: volume-pvc
options:
name: data
claimName: data
path: /storage
readOnly: "false"

- name: perf-hpctoolkit
options:
mount: /opt/mnt
# This allows us to ask where is the event blocked / taking more time
events: "-e REALTIME@10000"

# Use a custom container here too (we have for rocky and ubuntu)
image: ghcr.io/converged-computing/metric-hpctoolkit-view:rocky

# hpcrun needs to have mpirun in front of hpcrun <command> e.g.,
# mpirun <MPI args> hpcrun <hpcrun args> <app> <app args>
prefix: /opt/intel/mpi/2021.8.0/bin/mpirun --hostfile ./hostlist.txt -np 4 -map-by ppr:1:node

# Ensure the working directory is consistent
workdir: /opt/lammps/examples/reaxff/HNS

# Target container for entrypoint addition is the launcher, not workers
containerTarget: launcher
20 changes: 10 additions & 10 deletions pkg/addons/addons.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,34 +65,34 @@ type AddonBase struct {
mapOptions map[string]map[string]intstr.IntOrString
}

func (b AddonBase) SetOptions(metric *api.MetricAddon) {}
func (b AddonBase) CustomizeEntrypoints([]*specs.ContainerSpec, []*jobset.ReplicatedJob) {}
func (b *AddonBase) SetOptions(metric *api.MetricAddon) {}
func (b *AddonBase) CustomizeEntrypoints([]*specs.ContainerSpec, []*jobset.ReplicatedJob) {}

func (b AddonBase) Validate() bool {
func (b *AddonBase) Validate() bool {
return true
}
func (b AddonBase) AssembleContainers() []specs.ContainerSpec {
func (b *AddonBase) AssembleContainers() []specs.ContainerSpec {
return []specs.ContainerSpec{}
}

// Assemble Volumes (for now) just generates one
func (b AddonBase) AssembleVolumes() []specs.VolumeSpec {
func (b *AddonBase) AssembleVolumes() []specs.VolumeSpec {
return []specs.VolumeSpec{}
}

func (b AddonBase) Description() string {
func (b *AddonBase) Description() string {
return b.Summary
}
func (b AddonBase) Name() string {
func (b *AddonBase) Name() string {
return b.Identifier
}
func (b AddonBase) Options() map[string]intstr.IntOrString {
func (b *AddonBase) Options() map[string]intstr.IntOrString {
return b.options
}
func (b AddonBase) ListOptions() map[string][]intstr.IntOrString {
func (b *AddonBase) ListOptions() map[string][]intstr.IntOrString {
return b.listOptions
}
func (b AddonBase) MapOptions() map[string]map[string]intstr.IntOrString {
func (b *AddonBase) MapOptions() map[string]map[string]intstr.IntOrString {
return b.mapOptions
}

Expand Down
21 changes: 18 additions & 3 deletions pkg/addons/commands.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ import (
jobset "sigs.k8s.io/jobset/api/jobset/v1alpha2"
)

const (
commandsName = "commands"
perfCommandsName = "perf-commands"
)

// Perf addon expects the same command structure, but adds sys caps for trace and admin
type PerfAddon struct {
CommandAddon
Expand All @@ -37,6 +42,11 @@ func (a *PerfAddon) CustomizeEntrypoints(
}
}

func (a *PerfAddon) SetOptions(metric *api.MetricAddon) {
a.Identifier = perfCommandsName
a.SetSharedCommandOptions(metric)
}

// addContainerCaps adds capabilities to a container spec
func (a *PerfAddon) addContainerCaps(
cs []*specs.ContainerSpec,
Expand Down Expand Up @@ -92,8 +102,13 @@ func (m CommandAddon) Family() string {
return AddonFamilyApplication
}

// Set custom options / attributes for the metric
func (a *CommandAddon) SetOptions(metric *api.MetricAddon) {
a.Identifier = commandsName
a.SetSharedCommandOptions(metric)
}

// Set custom options / attributes for the metric
func (a *CommandAddon) SetSharedCommandOptions(metric *api.MetricAddon) {
target, ok := metric.Options["target"]
if ok {
a.target = target.StrVal
Expand Down Expand Up @@ -213,14 +228,14 @@ func init() {

// Config map volume type
base := AddonBase{
Identifier: "commands",
Identifier: commandsName,
Summary: "customize a metric's entrypoints",
}
app := CommandAddon{AddonBase: base}
Register(&app)

base = AddonBase{
Identifier: "perf-commands",
Identifier: perfCommandsName,
Summary: "customize a metric's entrypoints expecting performance tracing (adding ptrace and admin caps)",
}
cmd := CommandAddon{AddonBase: base}
Expand Down
6 changes: 5 additions & 1 deletion pkg/addons/hpctoolkit.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ import (
// hpcstruct hpctoolkit-sleep-measurements
// hpcprof hpctoolkit-sleep-measurements
// hpcviewer ./hpctoolkit-lmp-database
const (
hpctoolkitIdentifier = "perf-hpctoolkit"
)

type HPCToolkit struct {
ApplicationAddon
Expand Down Expand Up @@ -121,6 +124,7 @@ func (a *HPCToolkit) SetOptions(metric *api.MetricAddon) {
a.volumeName = "hpctoolkit"
a.output = "hpctoolkit-result"
a.postAnalysis = true
a.Identifier = hpctoolkitIdentifier

// UseColor set to anything means to use it
output, ok := metric.Options["output"]
Expand Down Expand Up @@ -399,7 +403,7 @@ sleep infinity

func init() {
base := AddonBase{
Identifier: "perf-hpctoolkit",
Identifier: hpctoolkitIdentifier,
Summary: "performance tools for measurement and analysis",
}
app := ApplicationAddon{AddonBase: base}
Expand Down
30 changes: 23 additions & 7 deletions pkg/addons/volumes.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ import (
"k8s.io/apimachinery/pkg/util/intstr"
)

const (
hostPathName = "volume-hostpath"
pvcName = "volume-pvc"
emptyName = "volume-empty"
secretName = "volume-secret"
cmName = "volume-cm"
)

type VolumeBase struct {
AddonBase
readOnly bool
Expand Down Expand Up @@ -98,6 +106,8 @@ func (v *ConfigMapVolume) Validate() bool {
// Set custom options / attributes for the metric
func (v *ConfigMapVolume) SetOptions(metric *api.MetricAddon) {

v.Identifier = cmName

// Set an empty list of items
v.items = map[string]string{}

Expand Down Expand Up @@ -190,6 +200,9 @@ func (v *PersistentVolumeClaim) Validate() bool {

// Set custom options / attributes
func (v *PersistentVolumeClaim) SetOptions(metric *api.MetricAddon) {

v.Identifier = pvcName

claimName, ok := metric.Options["claimName"]
if ok {
v.claimName = claimName.StrVal
Expand All @@ -207,8 +220,6 @@ func (v *PersistentVolumeClaim) AssembleVolumes() []specs.VolumeSpec {
},
},
}

// ConfigMaps have to be read only!
return []specs.VolumeSpec{{
Volume: volume,
Path: filepath.Dir(v.path),
Expand Down Expand Up @@ -236,6 +247,8 @@ func (v *SecretVolume) Validate() bool {

// Set custom options / attributes
func (v *SecretVolume) SetOptions(metric *api.MetricAddon) {

v.Identifier = secretName
secretName, ok := metric.Options["secretName"]
if ok {
v.secretName = secretName.StrVal
Expand Down Expand Up @@ -281,6 +294,8 @@ func (v *HostPathVolume) Validate() bool {
// Set custom options / attributes
func (v *HostPathVolume) SetOptions(metric *api.MetricAddon) {

v.Identifier = hostPathName

// Name is required!
path, ok := metric.Options["hostPath"]
if ok {
Expand Down Expand Up @@ -319,6 +334,7 @@ func (v *EmptyVolume) Validate() bool {

// Set custom options / attributes
func (v *EmptyVolume) SetOptions(metric *api.MetricAddon) {
v.Identifier = emptyName
name, ok := metric.Options["name"]
if ok {
v.name = name.StrVal
Expand Down Expand Up @@ -347,7 +363,7 @@ func init() {

// Config map volume type
base := AddonBase{
Identifier: "volume-cm",
Identifier: cmName,
Summary: "config map volume type",
}
volBase := VolumeBase{AddonBase: base}
Expand All @@ -356,7 +372,7 @@ func init() {

// Secret volume type
base = AddonBase{
Identifier: "volume-secret",
Identifier: secretName,
Summary: "secret volume type",
}
volBase = VolumeBase{AddonBase: base}
Expand All @@ -365,7 +381,7 @@ func init() {

// Hostpath volume type
base = AddonBase{
Identifier: "volume-hostpath",
Identifier: hostPathName,
Summary: "host path volume type",
}
volBase = VolumeBase{AddonBase: base}
Expand All @@ -374,7 +390,7 @@ func init() {

// persistent volume claim volume type
base = AddonBase{
Identifier: "volume-pvc",
Identifier: pvcName,
Summary: "persistent volume claim volume type",
}
volBase = VolumeBase{AddonBase: base}
Expand All @@ -383,7 +399,7 @@ func init() {

// EmptyVolume
base = AddonBase{
Identifier: "volume-empty",
Identifier: emptyName,
Summary: "empty volume type",
}
volBase = VolumeBase{AddonBase: base}
Expand Down
5 changes: 3 additions & 2 deletions pkg/metrics/base.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,10 @@ type BaseMetric struct {
func (m *BaseMetric) RegisterAddon(addon *addons.Addon) {
a := (*addon)
if m.Addons == nil {
logger.Infof("🟧️ Resetting addons - they are unset.")
m.Addons = map[string]*addons.Addon{}
}
logger.Infof("🟧️ Registering addon %s", a)
logger.Infof("🟧️ Registering addon %s", a.Name())
m.Addons[a.Name()] = addon
}

Expand Down Expand Up @@ -142,10 +143,10 @@ func (m BaseMetric) AddAddons(
// These are container specs that need to be written to configmaps
cms := []*specs.ContainerSpec{}

logger.Infof("🟧️ Addons to include %s\n", m.Addons)
for _, addon := range m.Addons {
a := (*addon)

logger.Infof("🟧️ Including Addon", a.Name())
volumes = append(volumes, a.AssembleVolumes()...)

// Assemble containers that addons provide, also as specs
Expand Down
2 changes: 2 additions & 0 deletions pkg/metrics/metrics.go
Original file line number Diff line number Diff line change
Expand Up @@ -85,10 +85,12 @@ func GetMetric(metric *api.Metric, set *api.MetricSet) (Metric, error) {
// Register addons, meaning adding the spec but not instantiating yet (or should we?)
for _, a := range metric.Addons {

logger.Infof("Attempting to add addon %s", a.Name)
addon, err := addons.GetAddon(&a)
if err != nil {
return nil, fmt.Errorf("Addon %s for metric %s did not validate", a.Name, metric.Name)
}
logger.Infof("Registering addon %s", a.Name)
m.RegisterAddon(&addon)
}

Expand Down