Skip to content

Commit dae8a6d

Browse files
authored
Doc initial (#2)
README and HOOKS content
1 parent 8a4d088 commit dae8a6d

File tree

4 files changed

+362
-49
lines changed

4 files changed

+362
-49
lines changed

HOOKS.md

+260
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,260 @@
1+
# HOOKs
2+
3+
A hook is a script in any language you prefer with an added events configuration code. Shell-operator will execute the script in a Kubernetes cluster on events you configured.
4+
5+
> A corresponding runtime environment must be added into the image to execute a hook.
6+
7+
Every hook must have an argument `--config`. Getting `--config` as an argument, hook should return to `stdout` its [bindings configuration](#bindings) as a JSON structure.
8+
9+
When one or more events the hook is bound are triggered, Shell-operator executes the hook without arguments but with the following environment variables set:
10+
- BINDING_CONTEXT_PATH — [execution context](#execution-context), contains a path to a JSON file with information about an event that was triggered.
11+
- WORKING_DIR — contains a path to a hooks directory. It can be helpful when you use shared libraries in your hooks.
12+
13+
## How hooks run
14+
15+
Shell-operator searches and runs hooks going through the following steps:
16+
- Recursively searches hooks in a working directory. A working directory is `"/hooks"` by default and can be specified wiht a WORKING_DIR environment variable or with a `--working-dir` argument (overrides WORKING_DIR):
17+
- directories starting from the dot symbol are excluded
18+
- directories and files are sorted alphabetically
19+
- every **executable** file not starting from dot symbol counts as a hook.
20+
- Executes hooks to get hooks configuration:
21+
- hooks are executed in the order found (see above)
22+
- each hook is executed in the hook directory in which it is located with the `--config` argument and the WORKING_DIR environment variable set
23+
- hook returns to `stdout` a JSON array of its [bindings configuration](#bindings).
24+
- Executes hooks depending on the schedule and Kubernetes events:
25+
- if there is more than one hook for a triggered event, hooks executed sequentially in the same order they have been found.
26+
- Export [metrics](METRICS.md) to Prometheus.
27+
28+
Shell operator executes each hook one by one (without concurrency), and executes each hook until it finishes. On that note, you may have a question — "What happens if one of the hooks fails?".
29+
30+
### What happens if hook fails?
31+
32+
If hook fails (exit with exit status > 0) Shell-operator does the following (by default):
33+
- writes the corresponding message to stdout (use e.g. `kubectl logs` to see it)
34+
- increases the `shell_operator_hook_errors` counter
35+
- waits for 3 seconds
36+
- tries to execute the hook again...
37+
38+
If you want Shell-operator to skip failed hook, you can use the `allowFailure: yes` option for `schedule` and `onKubernetesEvent` binding types.
39+
40+
## Hook configuration
41+
42+
Hook must return to stdout its binding configuration when the hook is executed with the `--config` argument. Binding configuration is the following JSON structure:
43+
44+
```
45+
{
46+
"BINDING_TYPE": "BINDING_PARAMETERS",
47+
...
48+
"BINDING_TYPE": "BINDING_PARAMETERS",
49+
"BINDING_TYPE": "BINDING_PARAMETERS"
50+
}
51+
```
52+
53+
Where:
54+
- BINDING_NAME is one of `onStartup`, `schedule`, `onKubernetesEvent` binding types.
55+
- BINDING_PARAMETERS is a value for binding or a JSON array with binding parameters (learn the [bindings](#bindings) section below)
56+
57+
### Bindings
58+
59+
There are three types of bindings:
60+
- onStartup
61+
- schedule
62+
- onKubernetesEvent
63+
64+
#### onStartup
65+
66+
This type of binding tells Shell-operator to execute hook once at Shell-operator startup. The `onStartup` binding requires only a single parameter — a hook execution order.
67+
68+
Syntax:
69+
```
70+
{
71+
"onStartup": ORDER
72+
}
73+
```
74+
75+
#### schedule
76+
77+
This type of binding tells Shell-operator to execute a hook on a specified schedule or schedules. You can bind one hook for any number of schedules. The `schedule` binding requires a JSON array of event descriptors.
78+
79+
Syntax:
80+
```
81+
{
82+
"schedule": [
83+
{
84+
"name": "EVENT_NAME",
85+
"crontab": CRON_EXPRESSION,
86+
"allowFailure": true|false,
87+
},
88+
{
89+
"crontab": CRON_EXPRESSION,
90+
"allowFailure": true|false,
91+
},
92+
...
93+
]
94+
}
95+
```
96+
97+
The `name` is an optional parameter. It specifies a binding name, which hook can get in the execution time from the [execution context](#execution-context)
98+
99+
The `CRON_EXPRESSION` is a crontab syntax with 6 values separated by spaces, each of them can be:
100+
- a number
101+
- a set of numbers separated by commas
102+
- a range, — two numbers separated by a hyphen
103+
- an asterisk `*` or a slash `/`
104+
- [predefined values](https://godoc.org/github.com/robfig/cron#hdr-Predefined_schedules)
105+
- [intervals](https://godoc.org/github.com/robfig/cron#hdr-Intervals)
106+
107+
Syntax:
108+
```
109+
* * * * * *
110+
| | | | | |
111+
| | | | | +---- Day of the Week (range: 1-7, 1 standing for Monday)
112+
| | | | +------ Month of the Year (range: 1-12)
113+
| | | +-------- Day of the Month (range: 1-31)
114+
| | +---------- Hour (range: 0-23)
115+
| +------------ Minute (range: 0-59)
116+
+-------------- Second (range: 0-59)
117+
```
118+
119+
The `allowFailure` — is an optional field, false by default. When true, Shell-operator will not try to re-execute hook if it fails and will skip it.
120+
121+
#### onKubernetesEvent
122+
123+
This type of binding tells Shell-operator to execute hook on a specified event from a Kubernetes cluster.
124+
125+
The `onKubernetesEvent` binding requires a JSON array of event descriptors. Each event descriptor assumes tracking object events of only one kind (see below).
126+
127+
Syntax:
128+
```
129+
{
130+
"onKubernetesEvent": [
131+
{
132+
"name": "EVENT_NAME",
133+
"kind": RESOURCE,
134+
"event": EVENTS_LIST,
135+
"selector": {
136+
"matchLabels": {
137+
"myLabel": "myLabelValue",
138+
"someKey": "someValue",
139+
...
140+
},
141+
"matchExpressions": [
142+
{
143+
"key": "tier",
144+
"operation": "In",
145+
"values": ["cache"],
146+
},
147+
...
148+
],
149+
},
150+
"namespaceSelector": {
151+
"matchNames": ["somenamespace", "bush-production", "bush-stage"],
152+
"any": true|false,
153+
},
154+
"jqFilter": ".metadata.labels",
155+
"allowFailure": true|false,
156+
"disableDebug": true|false,
157+
},
158+
...
159+
]
160+
}
161+
```
162+
163+
Where:
164+
- `name` — is an optional parameter, specifies a binding name, which hook can get in the execution time from the [execution context](#execution-context).
165+
- `kind` — is a kind of a Kubernetes object, events of which is required to bind. Case-insensitive. Can be one of the following:
166+
- namespace
167+
- cronjob
168+
- daemonset
169+
- deployment
170+
- job
171+
- pod
172+
- replicaset
173+
- replicationcontroller
174+
- statefulset
175+
- endpoints
176+
- ingress
177+
- service
178+
- configmap
179+
- secret
180+
- persistentvolumeclaim
181+
- storageclass
182+
- node
183+
- serviceaccount
184+
- `event` — is an optional parameter, by default equals to `["add", "update", "delete"]`. Specifies an array of Kubernetes events to bind, can be any combination of:
185+
- `add` — an event of adding a Kubernetes resource of a specified `kind`
186+
- `update` — an event of updating a Kubernetes resource of a specified `kind`
187+
- `delete` — an event of deleting a Kubernetes resource of a specified `kind`.
188+
- `selector` — is an optional parameter, specifies the condition for selecting a subset of objects. The `selector.matchLabels` is a `{key,value}` Kubernetes filter by lable/selector. The `selector.matchExpressions` is a standard Kubernetes list of pod selector requirements (learn more about Kubernetes labels and selectors [here](https://kubernetes.io/docs/concepts/overview/working-with-objects/labels)). If you don't specify a `selector`, all objects of this kind are assumed.
189+
- `namespaceSelector` — is an optional parameter, by defaul equals to `namespaceSelector.any=true`. Specifies a filter for namespaces for selecting objects. `namespaceSelector.matchNames` can contain an array of namespaces for selecting objects.
190+
- `jqFilter` — is an optional parameter, specifies additional event filter. Since a Kubernetes object has many events during its life, binding on the `update` event may give you a lot of events that you may not need. The `jqFilter` option allows binding hook only on necessary events because Shell-operator will apply defined in `jqFilter` option filter before binding to objects.
191+
- Suppose you want to execute a hook only when labels of the specified object have changed. Then you can set `"jqFilter":".metadata.labels"` and the hook will be executed only on labels of the object have changed.
192+
- `disableDebug` — is an optional field, disables debug messages for a specified event when true.
193+
- `allowFailure` — is an optional field, false by default. When true, Shell-operator will not try to re-execute hook if it fails and will skip it.
194+
195+
Example:
196+
```
197+
{
198+
"onKubernetesEvent": [
199+
{
200+
"name": "myLabelValue pods",
201+
"kind": "pod",
202+
"event": ["add", "delete"],
203+
"selector": {
204+
"matchLabels": {
205+
"myLabel": "myLabelValue"
206+
}
207+
},
208+
"namespaceSelector": {
209+
"any": true
210+
},
211+
"jqFilter": ".metadata.labels",
212+
"allowFailure": true
213+
}
214+
]
215+
}
216+
```
217+
218+
> Note, than Shell-operator Deployment must have the serviceAccount with the appropriate rights to monitor resources in a Kubernetes cluster.
219+
220+
## Execution context
221+
222+
As hook can have more than one bindings, it should identify a binding (or in other words — an event) which was triggered. When a hook is executing, the BINDING_CONTEXT_PATH environment variable contains a path to an execution context — a JSON file with information about the binding that was triggered.
223+
224+
The execution context contains the following fields:
225+
- `binding` — contains the name of the binding type or a `name` value from the binding configuration (if set)
226+
- `resourceNamespace`, `resourceKind`, `resourceName`, `resourceEvent` — corresponding values for identifying a resource on an `onKubernetesEvent` binding.
227+
228+
For example, you have the following hook binding configuration:
229+
```json
230+
{
231+
"schedule": [
232+
{
233+
"name": "incremental",
234+
"crontab": "* 2 */3 * * *",
235+
"allowFailure": true
236+
},
237+
{
238+
"crontab": "* 59 23 * * *",
239+
"allowFailure": false
240+
}
241+
]
242+
}
243+
```
244+
245+
At 12:02 this hook will be executed with the following context:
246+
```json
247+
[{ "binding": "incremental"}]
248+
```
249+
250+
At 23:59 this hook will be executed with the following context:
251+
```json
252+
[{ "binding": "schedule"}]
253+
```
254+
255+
## Debug
256+
257+
For debugging you can use the following:
258+
- get logs of a Shell-operator pod by using `kubectl logs <POD_NAME>`
259+
- get a hook queue content in the `/tmp/shell-operator-queue` file of a Shell-operator pod
260+
- get a hook queue content by executing CURL to the `POD_IP:9115/queue` (e.g. from a Shell-operator pod itself).

METRICS.md

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# METRICS
2+
3+
Shell-operator can export metrics to Prometheus.

0 commit comments

Comments
 (0)