You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/rfcs/0002/readme.md
+92-34Lines changed: 92 additions & 34 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,5 +1,5 @@
1
1
---
2
-
authors: Nate Thornton <nate.thornton@hpe.com>
2
+
authors: Blake Devcich <blake.devcich@hpe.com>
3
3
state: discussion
4
4
---
5
5
# Rabbit storage for containerized applications
@@ -28,21 +28,20 @@ The proposal below outlines the high level behavior of running containers in a w
28
28
29
29
1. The AUTHOR writes their application expecting NNF Storage at specific locations. For each storage requirement, they define:
30
30
1. a unique name for the storage which can be referenced in the 'container' directive
31
-
2. the expected storage types; if necessary
32
-
3. the required mount path or mount path prefix
33
-
4. other constraints or storage requirements (e.g. minimum capacity)
31
+
2. the required mount path or mount path prefix
32
+
3. other constraints or storage requirements (e.g. minimum capacity)
34
33
2. The AUTHOR works with the ADMINISTRATOR to define:
35
34
1. a unique name for the program to be referred by USER
36
-
2. the pod template specification for executing their program
35
+
2. the pod template or MPI Job specification for executing their program
37
36
3. the NNF storage requirements described above.
38
37
3. The ADMINISTRATOR creates a corresponding _NNF Container Profile_ Kubernetes custom resource with the necessary NNF storage requirements and pod specification as described by the AUTHOR
39
38
4. The USER who desires to use the application works with the AUTHOR and the related NNF Container Profile to understand the storage requirements
40
39
5. The USER submits a WLM job with the #DW container directive variables populated
41
40
6. WLM runs the workflow and drives it through the following stages...
42
41
1.`Proposal`: RABBIT validates the #DW container directive by comparing the supplied values to those listed in the NNF Container Profile. If the workflow fails to meet the requirements, the job fails
43
42
2.`PreRun`: RABBIT software:
44
-
1.creates a config map reflecting the storage requirements and any runtime parameters; this is provided to the container at the volume mount named `nnf-config`, if specified
45
-
2.duplicates the pod template specification from the Container Profile and patches the necessary Volumes and the config map. The spec is used as the basis for starting the necessary pods and containers
43
+
1.duplicates the pod template specification from the Container Profile and patches the necessary Volumes and the config map. The spec is used as the basis for starting the necessary pods and containers
44
+
2.creates a config map reflecting the storage requirements and any runtime parameters; this is provided to the container at the volume mount named `nnf-config`, if specified
46
45
3. The containerized application(s) executes. The expected mounts are available per the requirements and celebration occurs. The pods continue to run until:
47
46
1. a pod completes successfully (any failed pods will be retried)
48
47
2. the max number of pod retries is hit (indicating failure on all retry attempts)
@@ -57,12 +56,81 @@ The proposal below outlines the high level behavior of running containers in a w
57
56
58
57
During `Proposal`, the USER must assign compute nodes for the container workflow. The assigned compute nodes determine which Rabbit nodes run the containers.
59
58
59
+
### Container Definition
60
+
61
+
Containers can be launched in two ways:
62
+
63
+
1. MPI Jobs
64
+
2. Non-MPI Jobs
65
+
66
+
MPI Jobs are launched using [`mpi-operator`](https://github.com/kubeflow/mpi-operator). This uses a launcher/worker model. The launcher pod is responsible for running the `mpirun` command that will target the worker pods to run the MPI application. The launcher will run on the first targeted NNF node and the workers will run on each of the targeted NNF nodes.
67
+
68
+
For Non-MPI jobs, `mpi-operator` is **not** used. This model runs the same application on each of the targeted NNF nodes.
69
+
70
+
The NNF Container Profile allows a user to pick one of these methods. Each method is defined in similar, but different fashions. Since MPI Jobs use `mpi-operator`, the [`MPIJobSpec`](https://pkg.go.dev/github.com/kubeflow/mpi-operator@v0.4.0/pkg/apis/kubeflow/v2beta1#MPIJobSpec) is used to define the container(s). For Non-MPI Jobs a [`PodSpec`](https://pkg.go.dev/k8s.io/api/core/v1#PodSpec) is used to define the container(s).
71
+
72
+
An example of an MPI Job is below. The `data.mpiSpec` field is defined:
73
+
74
+
```yaml
75
+
kind: NnfContainerProfile
76
+
apiVersion: nnf.cray.hpe.com/v1alpha1
77
+
data:
78
+
mpiSpec:
79
+
mpiReplicaSpecs:
80
+
Launcher:
81
+
template:
82
+
spec:
83
+
containers:
84
+
- command:
85
+
- mpirun
86
+
- dcmp
87
+
- $(DW_JOB_foo_local_storage)/0
88
+
- $(DW_JOB_foo_local_storage)/1
89
+
image: ghcr.io/nearnodeflash/nnf-mfu:latest
90
+
name: example-mpi
91
+
Worker:
92
+
template:
93
+
spec:
94
+
containers:
95
+
- image: ghcr.io/nearnodeflash/nnf-mfu:latest
96
+
name: example-mpi
97
+
slotsPerWorker: 1
98
+
...
99
+
```
100
+
101
+
An example of a Non-MPI Job is below. The `data.spec` field is defined:
102
+
103
+
```yaml
104
+
kind: NnfContainerProfile
105
+
apiVersion: nnf.cray.hpe.com/v1alpha1
106
+
data:
107
+
spec:
108
+
containers:
109
+
- command:
110
+
- /bin/sh
111
+
- -c
112
+
- while true; do date && sleep 5; done
113
+
image: alpine:latest
114
+
name: example-forever
115
+
...
116
+
```
117
+
118
+
In both cases, the `spec` is used as a starting point to define the containers. NNF software supplements the specification to add functionality (e.g. mounting #DW storages). In other words, what you see here will not be the final spec for the container that ends up running as part of the container workflow.
119
+
120
+
### Security
121
+
122
+
The workflow's UID and GID are used to run the container application and for mounting the specified fileystems in the container. Kubernetes allows for a way to define permissions for a container using a [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/).
123
+
124
+
`mpirun` uses `ssh` to communicate with the worker nodes. `ssh` requires that UID is assigned to a username. Since the UID/GID are dynamic values from the workflow, work must be done to the container's `/etc/passwd` to map the UID/GID to a username. An `InitContainer` is used to modify `/etc/passwd` and mount it into the container.
125
+
60
126
### Communication Details
61
127
62
128
The following subsections outline the proposed communication between the Rabbit nodes themselves and the Compute nodes.
63
129
64
130
#### Rabbit-to-Rabbit Communication
65
131
132
+
##### Non-MPI Jobs
133
+
66
134
Each rabbit node can be reached via `<hostname>.<subdomain>` using DNS. The hostname is the Rabbit node name and the workflow name is used for the subdomain.
67
135
68
136
For example, a workflow name of `foo` that targets `rabbit-node2` would be `rabbit-node2.foo`.
@@ -88,6 +156,10 @@ data:
88
156
89
157
DNS can then be used to communicate with other Rabbit containers. The FQDN for the container running on rabbit-node2 is `rabbit-node2.foo.default.svc.cluster.local`.
90
158
159
+
##### MPI Jobs
160
+
161
+
For MPI Jobs, these hostnames and subdomains will be slightly different due to the implementation of `mpi-operator`. However, the variables will remain the same and provide a consistent way to retrieve the values.
162
+
91
163
#### Compute-to-Rabbit Communication
92
164
93
165
For Compute to Rabbit communication, the proposal is to use an open port between the nodes, so the applications could communicate using IP protocol. The port number would be assigned by the Rabbit software and included in the workflow resource's environmental variables after the Setup state (similar to workflow name & namespace). Flux should provide the port number to the compute application via an environmental variable or command line argument. The containerized application would always see the same port number using the `hostPort`/`containerPort` mapping functionality included in Kubernetes. To clarify, the Rabbit software is picking and managing the ports picked for `hostPort`.
@@ -111,7 +183,7 @@ items:
111
183
112
184
## Example
113
185
114
-
Say I authored a simple application, `foo`, that requires Rabbit local GFS2 storage and a persistent Lustre storage volume. As the author, my program is coded to expect the GFS2 volume is mounted at `/foo/local` and the Lustre volume is mounted at `/foo/persistent`
186
+
Say I authored a simple application, `foo`, that requires Rabbit local GFS2 storage and a persistent Lustre storage volume.
115
187
116
188
Working with an administrator, my application's storage requirements and pod specification are placed in an NNF Container Profile `foo`:
117
189
@@ -129,26 +201,15 @@ spec:
129
201
optional: false
130
202
- name: DW_PERSISTENT_foo-persistent-storage
131
203
optional: false
132
-
template:
133
-
metadata:
134
-
name: foo
135
-
namespace: default
136
-
spec:
137
-
containers:
138
-
- name: foo
139
-
image: foo:latest
140
-
command:
141
-
- /foo
142
-
volumeMounts:
143
-
- name: foo-local-storage
144
-
mountPath: /foo/local
145
-
- name: foo-persistent-storage
146
-
mountPath: /foo/persistent
147
-
- name: nnf-config
148
-
mountPath: /nnf/config
149
-
ports:
150
-
- name: compute
151
-
containerPort: 80
204
+
spec:
205
+
containers:
206
+
- name: foo
207
+
image: foo:latest
208
+
command:
209
+
- /foo
210
+
ports:
211
+
- name: compute
212
+
containerPort: 80
152
213
```
153
214
154
215
Say Peter wants to use `foo` as part of his job specification. Peter would submit the job with the directives below:
@@ -183,7 +244,7 @@ Peter submits the job to the WLM. WLM guides the job through the workflow states
183
244
...
184
245
```
185
246
186
-
2. Rabbit software creates a pod and duplicates the `foo` pod template spec in the NNF Container Profile and fills in the necessary volumes and config map.
247
+
2. Rabbit software creates a pod and duplicates the `foo` pod spec in the NNF Container Profile and fills in the necessary volumes and config map.
187
248
188
249
```yaml
189
250
kind: Pod
@@ -203,9 +264,9 @@ Peter submits the job to the WLM. WLM guides the job through the workflow states
203
264
- /foo
204
265
volumeMounts:
205
266
- name: foo-local-storage
206
-
mountPath: /foo/local
267
+
mountPath: <MOUNT_PATH>
207
268
- name: foo-persistent-storage
208
-
mountPath: /foo/persistent
269
+
mountPath: <MOUNT_PATH>
209
270
- name: nnf-config
210
271
mountPath: /nnf/config
211
272
ports:
@@ -238,9 +299,6 @@ Peter submits the job to the WLM. WLM guides the job through the workflow states
238
299
2. If all pods are successful, Post-Run is marked as `Ready`
239
300
3. If any pod is not successful, Post-Run is not marked as `Ready`
240
301
241
-
## Security
242
-
243
-
Kubernetes allows for a way to define permissions for a container using a [Security Context](https://kubernetes.io/docs/tasks/configure-pod-container/security-context/). This can be seen in the pod template spec above. The user and group IDs are inherited from the Workflow's spec.
244
302
245
303
## Special Note: Indexed-Mount Type for GFS2 File Systems
0 commit comments