Skip to content

Commit d62daec

Browse files
committed
fixup essential features
1 parent 3e22d1e commit d62daec

21 files changed

+168
-125
lines changed

docs/conf.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@
88
from pathlib import Path
99
from subprocess import check_output
1010

11-
import requests
12-
1311
import epics_containers
12+
import requests
1413

1514
# -- General configuration ------------------------------------------------
1615

docs/developer/how-to/update-tools.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
Update the tools
22
================
33

4-
This module is merged with the python3-pip-skeleton_. This is a generic
4+
This module is merged with the python3-pip-skeleton_. This is a Generic
55
Python project structure which provides a means to keep tools and
66
techniques in sync between multiple Python projects. To update to the
77
latest version of the skeleton, run::

docs/user/explanations/introduction.rst

Lines changed: 108 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ Concepts
1616
Images and Containers
1717
~~~~~~~~~~~~~~~~~~~~~
1818
Containers provide the means to package up IOC software and execute it
19-
in a lightweight virtual environment. This includes saving the packages
19+
in a lightweight virtual environment. These packages are then saved
2020
into public or private image registries such as DockerHub or Github Container
2121
Registry.
2222

@@ -37,19 +37,35 @@ code to suit your infrastructure. At DLS, this means that we are able to use
3737
vanilla EPICS base and support modules. We no longer require our own
3838
forks of these repositories.
3939

40+
.. _generic iocs:
41+
4042
Generic IOCs and instances
4143
""""""""""""""""""""""""""
4244

4345
An important principal of the approach presented here is that an IOC container
44-
image represents a 'generic' IOC. The generic IOC image is used for all
45-
IOC instances that connect to a given class of device.
46+
image represents a 'Generic' IOC. The Generic IOC image is used for all
47+
IOC instances that connect to a given class of device. For example the
48+
Generic IOC image here:
49+
ghcr.io/epics-containers/ioc-adaravis-linux-runtime:2023.10.1
50+
uses the AreaDetector driver ADAravis to connect to GigE cameras.
51+
52+
An IOC instance runs in a container runtime by loading two things:
53+
54+
- The Generic IOC image passed to the container runtime.
55+
- The IOC instance configuration. This is mapped into the container at
56+
runtime by mounting it into the filesystem at runtime. The mount point
57+
for this configuration is alway /epics/ioc/config.
58+
59+
The configuration will bootstrap the unique properties of that instance.
60+
The following contents for the configuration are supported:
61+
62+
- ioc.yaml: an **ibek** IOC description file which **ibek** will use to generate
63+
st.cmd and ioc.subst
64+
- st.cmd, ioc.subst: an IOC shell startup script and an optional substitution file
65+
st.cmd can refer any additional files in the configuration directory
66+
- start.sh a bash script to fully override the startup of the IOC. start.sh
67+
can refer to any additional files in the configuration directory
4668

47-
An IOC instance runs in a container that bases its
48-
filesystem on a generic IOC image.
49-
In addition the instance has configuration mapped into the
50-
container that will bootstrap the unique properties of that instance.
51-
In most cases the configuration need only be a single IOC boot script or
52-
IBEK yaml file.
5369

5470
This approach reduces the number of images required and saves disk. It also
5571
makes for simple configuration management.
@@ -70,23 +86,33 @@ since it was open-sourced in 2014.
7086

7187
Today it is by far the dominant orchestration technology for containers.
7288

73-
In this project we use Kubernetes to provide a standard way of implementing
74-
these features:
89+
In this project we use Kubernetes and helm to provide a standard way of
90+
implementing these features:
7591

7692
- Auto start IOCs when servers come up
7793
- Manually Start and Stop IOCs
7894
- Monitor IOC status and versions
7995
- Deploy versioned IOCs to the beamline
8096
- Rollback to a previous IOC version
81-
- Allocate the server which runs an IOC
97+
- Allocate a server with adequate resources on which to run each IOC
8298
- Failover to another server (for soft IOCs not tied to hardware in a server)
8399
- View the current log
84-
- View historical logs (via graylog)
100+
- View historical logs (via graylog or other centralized logging system)
85101
- Connect to an IOC and interact with its shell
86102
- debug an ioc by starting a bash shell inside it's container
87-
- etc.
88103

89104

105+
Kubernetes Alternative
106+
~~~~~~~~~~~~~~~~~~~~~~
107+
108+
If you do not have the resources to maintain a Kubernetes cluster then this project
109+
is experimentally supporing the use of podman-compose or docker-compose to deploy
110+
IOCs to a single server. Where a beamline has multiple servers the distribution of
111+
IOCs across those servers is managed by the user. These tools would replace
112+
Kubernetes and Helm in the technology stack.
113+
114+
TODO: more on this once we have a working example.
115+
90116
Helm
91117
~~~~
92118
https://helm.sh/
@@ -102,16 +128,27 @@ of the chart within the cluster.
102128
It also supports registries for storing version history of charts,
103129
much like docker.
104130

105-
In this project we use Helm Charts to define and deploy IOC instances. Each
106-
beamline has its own Helm Repository which stores current and historical
107-
version of its IOC instances. Each IOC has a Helm Chart which defines the
108-
which generic IOC image it is based on and the configuration that makes it into
109-
an individual IOC instance.
131+
In this project we use Helm Charts to define and deploy IOC instances.
132+
Each beamline (or accelerator domain) has its own git repository that holds
133+
the beamline Helm Chart for its IOCs. Each IOC instance need only provide a
134+
values.yaml file to override the default values in the Helm Chart and a config folder
135+
as described in `generic iocs`.
136+
137+
**epics-containers** does not use helm repositories for storing IOC instances.
138+
Such repositories only hold a zipped version of the chart and a values.yaml file,
139+
and this is seen as redundant when we have a git repository holding the same
140+
information. Instead we provide a command line tool for installing and updating
141+
IOCs. Which performs the following steps:
142+
143+
- Clone the beamline repository at a specific tag to a temporary folder
144+
- extract the beamline chart and apply the values.yaml to it
145+
- additionally generate a config map from the config folder files
146+
- install the resulting chart into the cluster
147+
- remove the temporary folder
148+
149+
This means that we don't store the chart itself but we do store all of the
150+
information required to re-generate it in a version tagged repository.
110151

111-
With the epics-containers approach there is a 1:1 relationship between
112-
Helm Charts and IOC instances. These helm charts therefore hold all the
113-
information about an IOC instance and can be deployed with no additional
114-
configuration parameters.
115152

116153
Repositories
117154
~~~~~~~~~~~~
@@ -125,56 +162,51 @@ a shared filesystem are required
125162
(The legacy approach at DLS relied heavily on
126163
know locations in a shared filesystem).
127164

128-
In the epics-containers examples all repositories are held in the same
165+
In the **epics-containers** examples all repositories are held in the same
129166
github organization. This is nicely contained and means that only one set
130167
of credentials is required to access all the resources.
131168

132169
There are many alternative services for storing these repositories, both
133170
in the cloud and on premises. Below we list the choices we have tested
134171
during the POC.
135172

136-
The 3 classes of repository are as follows:
173+
The 2 classes of repository are as follows:
137174

138175
:Source Repository:
176+
139177
- Holds the source code but also provides the
140178
Continuous Integration actions for testing, building and publishing to
141179
the image / helm repositories. These have been tested:
142180

143181
- github
144182
- gitlab (on premises)
145183

146-
epics-containers defines two classes of source repository:
184+
- epics-containers defines two classes of source repository:
147185

148-
- Generic IOC source. Defines how a generic IOC image is built, this does
186+
- Generic IOC source. Defines how a Generic IOC image is built, this does
149187
not typically include source code, but instead is a set of instructions
150-
for building the generic IOC image.
188+
for building the Generic IOC image.
151189
- Beamline / Accelerator Domain source. Defines the IOC instances for a
152190
beamline or Accelerator Domain. This includes the IOC boot scripts and
153-
any other configuration required to make the IOC instance unique, for
154-
IBEK based IOCs, each IOC instance is defined by an IBEK yaml file only.
191+
any other configuration required to make the IOC instance unique.
192+
For **ibek** based IOCs, each IOC instance is defined by an **ibek**
193+
yaml file only.
155194

156195
:An OCI image repository:
157-
- Holds the generic IOC container images and their
196+
197+
- Holds the Generic IOC container images and their
158198
dependencies. The following have been tested:
159199

160200
- Github Container Registry
161201
- DockerHub
162202
- Google Cloud Container Registry
163203

164-
:An OCI helm chart repository:
165-
- This is where the definitions of IOC instances
166-
are stored. They are in the form of a helm chart which describes to
167-
Kubernetes the resources needed to spin up the IOC.
168-
These have been tested:
169-
170-
- github packages
171-
- Google Cloud Artifact Registry
172204

173205
Continuous Integration
174206
~~~~~~~~~~~~~~~~~~~~~~
175207

176208
Our examples all use continuous integration to get from pushed source
177-
to the published images / helm charts.
209+
to the published images.
178210

179211
This allows us to maintain a clean code base that is continually tested for
180212
integrity and also to maintain a direct relationship between source code tags
@@ -183,19 +215,17 @@ and the tags of their built resources.
183215
There are these types of CI:
184216

185217
:Generic IOC source:
186-
- builds a generic IOC container image
218+
- builds a Generic IOC container image
187219
- runs some tests against that image
188220
- publishes the image to github packages (only if the commit is tagged)
221+
or other OCI registry
189222

190223
:beamline definition source:
191224
- builds a helm chart from each ioc definition
192-
- IF the commit is tagged then those IOCs that have changed since the last
193-
tag will be published to the helm OCI repository with the same version
194-
tag.
195-
196-
:helm library source:
197-
- builds the helm library chart shared by all Generic IOCs.
198-
- publishes it to github packages (only if the commit is tagged)
225+
- tests that the helm chart is deployable (but does not deploy it)
226+
- locally launches each IOC instance and loads its configuration to
227+
verify that the configuration is valid (no system tests because this
228+
would require talking to beamline hardware).
199229

200230
:documentation source:
201231
- builds the sphinx docs
@@ -208,34 +238,48 @@ on MVME5500 hardware. Soft IOCs that require access to hardware on the
208238
server (e.g. USB or PCIe) will be supported by mounting the hardware into
209239
the container (theses IOCS will not support failover).
210240

211-
Other linux architectures could be added to the Kubernetes cluster.
241+
Other linux architectures could be added to the Kubernetes cluster. We have
242+
tested arm64 native builds and will add this as a supported architecture
243+
in the future.
212244

213-
Note that OPI is also out of scope for this initial phase. See
214-
`no_opi`
215245

216246
Additional Tools
217247
----------------
218248

219249
epics-containers-cli
220250
~~~~~~~~~~~~~~~~~~~~
221-
The project epics-containers-cli implements simple command
222-
line functions for deploying and monitoring IOCs. It is just a wrapper
223-
around the tools kubectl, podman and helm, but saves typing and provides
224-
help and command line completion.
251+
This define the developer's 'outside of the container' helper tool. The command
252+
line entry point is **ec**.
253+
254+
The project is a python package featuring simple command
255+
line functions for deploying, monitoring building and debugging
256+
Generic IOCs and IOC instances. It is a wrapper
257+
around the standard command line tools kubectl, podman/docker, helm, and git
258+
but saves typing and provides help and command line completion.
225259

226260
See `CLI` for details.
227261

228-
dev-e7
229-
~~~~~~
230-
This project provides a Dockerfile for building a personal developer container,
231-
allowing a developer to work on support modules or IOCs anywhere. All the
232-
tools required to build and deploy IOCs are included in the container.
233262

263+
**ibek**
264+
~~~~~~~~
265+
IOC Builder for EPICS and Kubernetes is the developer's 'inside the container'
266+
helper tool. It is a python package that is installed into the Generic IOC
267+
container images. It is used:
234268

235-
Ibek
236-
~~~~
237-
IOC Builder for EPICS and Kubernetes provides a way to generate an IOC
238-
helm chart from a YAML description of the IOC.
269+
- at container build time to fetch and build EPICS support modules
270+
- to generate the IOC source code and compile it
271+
- to extract all useful build artifacts into a runtime image
239272

240273
See https://github.com/epics-containers/ibek.
241274

275+
PVI
276+
~~~
277+
Process Variables Interface is a python package that is installed into the
278+
Generic IOC container images. It is used to give structure to the IOC's PVI
279+
interface allowing us to:
280+
281+
- add metadata to the IOCs DB records for use by bluesky
282+
- auto generate screens for the device (as bob, adl or edm files)
283+
284+
285+

docs/user/explanations/kubernetes_cluster.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,14 +91,14 @@ Argus is a multi-tenant cluster. Namespaces are used to enforce multi-tenancy. A
9191
Beamline Local Cluster Nodes
9292
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
9393

94-
As part of the investigation work some worker nodes in Argus have been connected that are physically located at the beamline. These nodes do not share the same rack as Argus, and hence are part of a different routed subnet to the /22 that the control plane and main workers are within. This model assumes one centralised control plane (and some generic workers), and a set of beamline cluster nodes that may be distributed across the network (in different subnets).
94+
As part of the investigation work some worker nodes in Argus have been connected that are physically located at the beamline. These nodes do not share the same rack as Argus, and hence are part of a different routed subnet to the /22 that the control plane and main workers are within. This model assumes one centralised control plane (and some Generic workers), and a set of beamline cluster nodes that may be distributed across the network (in different subnets).
9595

9696
The beamline cluster nodes require a few interesting sets of configuration to make this architecture work. See the following subheadings for details.
9797

9898
Metallb Pools
9999
+++++++++++++
100100

101-
Metallb cannot be used to provide loadBalancer services for pods running on the beamline cluster nodes. This is because metallb currently only supports a single pool of IPs to allocate from. In the case of Argus, the pool is allocated from within the /22 in which the control plane (and a few generic workers) sit. Should a pod with a loadBalancer Service IP get brought up on a beamline cluster node, the traffic would not be routable because the beamline TOR switch does not send ARP messages for subnets that it is not directly connected to. This is not an issue running IOCs since they do not make use of loadBalancer Services. There is a feature request for Metallb to support address pools that is currently pending.
101+
Metallb cannot be used to provide loadBalancer services for pods running on the beamline cluster nodes. This is because metallb currently only supports a single pool of IPs to allocate from. In the case of Argus, the pool is allocated from within the /22 in which the control plane (and a few Generic workers) sit. Should a pod with a loadBalancer Service IP get brought up on a beamline cluster node, the traffic would not be routable because the beamline TOR switch does not send ARP messages for subnets that it is not directly connected to. This is not an issue running IOCs since they do not make use of loadBalancer Services. There is a feature request for Metallb to support address pools that is currently pending.
102102

103103
Node Labelling and Taints
104104
+++++++++++++++++++++++++

docs/user/explanations/repositories.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ Source and Registry Locations
55

66
**DLS Users** DLS is currently using these locations for assets:
77

8-
- Generic IOC Source: ``https://github.com/epics-containers<generic ioc>``
8+
- Generic IOC Source: ``https://github.com/epics-containers<Generic ioc>``
99
- Beamline Source repos: ``https://gitlab.diamond.ac.uk/controls/containers/beamline/<beamline>``
1010
- Accelerator Source repos: ``https://gitlab.diamond.ac.uk/controls/containers/accelerator/<domain>``
11-
- Generic IOC Container Images: ``ghcr.io/epics-containers/<generic ioc>``
11+
- Generic IOC Container Images: ``ghcr.io/epics-containers/<Generic ioc>``
1212
- IOC Instance Helm Charts: ``helm-test.diamond.ac.uk/iocs/<domain>/<ioc instance>``
1313

1414
Where to Keep Source Code
@@ -28,11 +28,11 @@ also contribute to the development of the IOC.
2828

2929
The intention is that a Generic IOC container image is a reusable component
3030
that can be used by multiple IOC instances in multiple domains. Because
31-
generic IOCs are containerized and not facility specific, they should work
31+
Generic IOCs are containerized and not facility specific, they should work
3232
anywhere. Therefore these make sense as public repositories.
3333

3434
There may be cases where the this is not possible, for example if the
35-
generic IOC relies on proprietary support modules with restricted licensing.
35+
Generic IOC relies on proprietary support modules with restricted licensing.
3636

3737
The existing Continuous
3838
Integration files for Generic IOCs work with GitHub actions, but also

docs/user/how-to/run_iocs.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
Run an IOC without Kubernetes
22
=============================
33

4-
When we run a containerized IOC we are selecting a generic IOC container image
4+
When we run a containerized IOC we are selecting a Generic IOC container image
55
to launch and some configuration to pass to the IOC. The configuration we
6-
pass is what makes the IOC a unique instance instead of a generic IOC.
6+
pass is what makes the IOC a unique instance instead of a Generic IOC.
77

88
In the tutorials we are running the IOC in a Kubernetes cluster and we
99
use a Kubernetes ConfigMap to pass the configuration to the IOC.
@@ -19,7 +19,7 @@ will see the IOC running in a container:
1919
2020
podman run --net host -it --rm -v $(pwd)/iocs/bl01t-ea-ioc-01/config:/repos/epics/ioc/config ghcr.io/epics-containers/ioc-template-linux-runtime:23.3.3
2121
22-
What you have done here is pull down the generic ``ioc-template-linux-runtime``
22+
What you have done here is pull down the Generic ``ioc-template-linux-runtime``
2323
container image from the GitHub Container Registry and run it.
2424
The ``-it`` means it is an interactive terminal session. ``--rm`` means the
2525
container is removed when it exits, best for keeping your cache tidy.
@@ -37,7 +37,7 @@ is appended to the path and that is required because the path for mounting
3737
into a container must be absolute.
3838

3939
``iocs/bl01t-ea-ioc-01/config`` contains a simple iocShell boot script and the
40-
default behaviour is to pass that to the generic IOC binary.
40+
default behaviour is to pass that to the Generic IOC binary.
4141

4242
Using this approach you could manage your config folders and IOC launches
4343
yourself using whatever mechanism you prefer. Probably docker compose or

docs/user/how-to/update_templated.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ The tutorials use two template projects as follows:
1010
* - Template Project
1111
- Purpose
1212
* - ioc-template
13-
- create a new generic IOC container project
13+
- create a new Generic IOC container project
1414
* - blxxi-template
1515
- create a new IOC Instance Domain project
1616

docs/user/overview.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Kubernetes for EPICS IOCs applies modern industry standards to the management
2-
of IOCs.
1+
**epics-containers** applies modern industry best practice for software
2+
delivery to the management of EPICS IOCs.
33

44
There are 5 themes to this strategy:
55

0 commit comments

Comments
 (0)