Table of Contents

I got the inspiration for writing a so called operator for Kubernetes from the CoreOS project prometheus-operator. So a big thanks to them for creating the project, as also the code is almost completely based on their operator code.

The project can be found on GitHub: https://github.com/galexrt/elasticsearch-operator

Installation

Use the bundle.yaml that is in the repo root, to run the operator on the cluster.

1
$ kubectl create -f bundle.yaml

Verify the installation of the ThirdPartyResources

To verify that the operator has successful installed its ThirdPartyResources, you simply check the Kubernetes server for them:

1
2
3
4
5
6
$ kubectl get thirdpartyresources
NAME                                       DESCRIPTION                           VERSION(S)
[...]
curator.elasticsearch.zerbytes.net         Managed Curator instance(s)           v1alpha1
elasticsearch.elasticsearch.zerbytes.net   Managed Elasticsearch instance(s)     v1alpha1
[...]
If those two entries are shown, the operator should now be working.

Examples

Use the examples

You use the kubectl create command for that. If you need help, check the help menu.

Elasticsearch manifest

The manifest below would create a simple Elasticsearch cluster, consisting of 1x master, 1x data and 1x ingest node.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
apiVersion: "elasticsearch.zerbytes.net/v1alpha1"
kind: "Elasticsearch"
metadata:
  name: "example"
spec:
  version: "5.4.0"
  # automatically calculate java memory opts
  # not implemented yet
  javaMemoryControl: true
  # this is currently not implemented due to it being missing
  # from the used k8s go-client
  #imagePullSecrets: "example"
  # config that is added to *all* autogenrated config file
  additionalConfig: |
    action.auto_create_index: .security,.monitoring*,.watches,.triggered_watches,.watcher-history*,filebeat-*,metricbeat-*,packetbeat-*,winlogbeat-*,heartbeat-*
  master:
    replicas: 1
    #nodeSelector:
    #  elasticsearch-data: "yes"
    resources:
      limits:
        memory: "512Mi"
      requests:
        memory: "512Mi"
    # add to the jvm.options file
    javaOpts: |
      # your additional java opts here
    additionalConfig: |
      # your addtional elasticsearch configuration here
    storage:
      class: rbd
      resources:
        requests:
          storage: 10Gi
  data:
    replicas: 1
    #nodeSelector:
    #  elasticsearch-data: "yes"
    resources:
      limits:
        memory: "512Mi"
      requests:
        memory: "512Mi"
    javaOpts: |
      # your additional java opts here
    additionalConfig: |
      # your addtional elasticsearch configuration here
    storage:
      class: rbd
      resources:
        requests:
          storage: 15Gi
  ingest:
    replicas: 1
    #nodeSelector:
    #  elasticsearch-data: "yes"
    resources:
      limits:
        memory: "512Mi"
      requests:
        memory: "512Mi"
    javaOpts: |
      # your additional java opts here
    additionalConfig: |
      # your addtional elasticsearch ingest configuration here

Curator manifest

Curator manifests are very primitive. You have to provide a full configuration for it. I may improve them in the future.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
apiVersion: "elasticsearch.zerbytes.net/v1alpha1"
kind: Curator
metadata:
  name: "example"
spec:
  schedule: "1 0 * * *"
  config: |
  # Remember, leave a key empty if there is no value.  None will be a string,
  # not a Python "NoneType"
  client:
    hosts:
      - elasticsearch-example
    port: 9200
    url_prefix:
    use_ssl: False
    certificate:
    client_cert:
    client_key:
    ssl_no_validate: False
    http_auth: "elastic:changeme"
    timeout: 30
    master_only: False
  logging:
    loglevel: INFO
    logfile:
    logformat: default
    blacklist: ['elasticsearch', 'urllib3']
  actions: |
    # Remember, leave a key empty if there is no value.  None will be a string,
    # not a Python "NoneType"
    #
    # Also remember that all examples have 'disable_action' set to True.  If you
    # want to use this action as a template, be sure to set this to False after
    # copying it.
    actions:
      1:
        action: delete_indices
        description: "Clean up ES by deleting old indices"
        options:
          timeout_override:
          continue_if_exception: False
          disable_action: False
          ignore_empty_list: True
          timeout_override: 300
        filters:
        - filtertype: age
          source: name
          direction: older
          timestring: '%Y.%m.%d'
          unit: days
          unit_count: 4
          field:
          stats_result:
          epoch:
          exclude: False


If you have any questions about the operator or the usage, feel free to open an issue on GitHub or leave a comment.

Have Fun!