kubernetes single node elasticsearch

Step 1: Disk

Note: this step is only for cloud, for local can be skipped, idea here to be able to control disk name and type, otherwise kubernetes will create disk with uuid name which is hard to manage in future

Go to disks management and create one

  • Name: es1
  • Description: disk for "es1" pod in kubernetes
  • Type: SSD persistent disk
  • Zone: europe-west1-b
  • Size (GB): 10

Step 2: Password

create password secret

kubectl create secret generic es1 --from-literal=password='xxxxxxx'

Notes:

  • es1 is the name of secret at will be used later, keep eye on it and do not forget to rename it
  • on the other hand it can be optional and you can reuse already created secret

Step 3: Persistent Volume

For local kubernetes use:

local.yml

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: es1-pv
spec:
  storageClassName: manual
  capacity:
    storage: 10Gi
  accessModes:
    - ReadWriteOnce
  hostPath:
    # Note: do not forget to change me
    path: "/Users/mac/Desktop/k8s-nginx-pvc/elastic/data"
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: es1-pvc
spec:
  storageClassName: manual
  volumeName: es1-pv
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10G
kubectl apply -f local.yml
kubectl get pv
kubectl get pvc

For cloud kubernetes:

cloud.yml

---
apiVersion: v1
kind: PersistentVolume
metadata:
  name: es1-pv
spec:
  storageClassName: ""
  capacity:
    storage: 10G
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    # https://console.cloud.google.com/compute/disksDetail/zones/europe-west1-b/disks/es1?project=majestic-cairn-171208
    pdName: es1
    fsType: ext4
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: es1-pvc
spec:
  storageClassName: ""
  volumeName: es1-pv
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 10G
kubectl apply -f cloud.yml
kubectl get pv
kubectl get pvc

Notes:

  • use same metadata.name for both local and cloud persisten volumes to prevent misunderstunding
  • gcePersistentDisk.pdName is a disk name you have created in step 1
  • capacity.storage can not be bigger than a disk space
  • kubernetes persistent volume 5 minutes video

Step 4: Elastic

elastic.yml

---
apiVersion: v1
kind: Pod
metadata:
  name: es1
  labels:
    app: es1
  annotations:
    prometheus.io/scrape: "true"
    prometheus.io/port: "9114"
spec:
  securityContext:
    runAsUser: 1000
    runAsGroup: 1000
    fsGroup: 1000
  volumes:
    - name: data
      persistentVolumeClaim:
        claimName: es1-pvc
  initContainers:
    - name: init-sysctl
      image: busybox
      securityContext:
        privileged: true
      command:
        - sysctl
        - -w
        - vm.max_map_count=262144
  containers:
    - name: es1
      image: docker.elastic.co/elasticsearch/elasticsearch:7.5.0
      ports:
        - containerPort: 9200
      env:
        # The heap size should be half the size of RAM allocated to the Pod - https://www.elastic.co/guide/en/cloud-on-k8s/current/k8s-managing-compute-resources.html#k8s-compute-resources-elasticsearch
        - name: ES_JAVA_OPTS
          value: -Xms1g -Xmx1g
        - name: ELASTIC_PASSWORD
          valueFrom:
            secretKeyRef:
              name: es1
              key: password
        - name: node.name
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: cluster.name
          valueFrom:
            fieldRef:
              fieldPath: metadata.name
        - name: xpack.security.enabled
          value: "true"
        - name: discovery.type
          value: single-node
        - name: bootstrap.memory_lock
          value: "false"
      resources:
        requests:
          memory: 2G
        limits:
          memory: 2G
      readinessProbe:
        exec:
          command:
            - bash
            - -c
            - curl --fail --silent --output /dev/null --user elastic:$ELASTIC_PASSWORD localhost:9200
        initialDelaySeconds: 30
        periodSeconds: 10
        timeoutSeconds: 10
        failureThreshold: 60
      livenessProbe:
        exec:
          command:
            - bash
            - -c
            - curl --fail --silent --output /dev/null --user elastic:$ELASTIC_PASSWORD localhost:9200
        initialDelaySeconds: 60
        periodSeconds: 10
        timeoutSeconds: 10
      securityContext:
        privileged: true
        capabilities:
          add:
            - IPC_LOCK
            - SYS_RESOURCE
      volumeMounts:
        - name: data
          mountPath: /usr/share/elasticsearch/data
    - name: exporter
      image: justwatch/elasticsearch_exporter
      ports:
        - containerPort: 9114
      env:
        - name: ELASTIC_PASSWORD
          valueFrom:
            secretKeyRef:
              name: es1
              key: password
        - name: ES_URI
          value: http://elastic:$(ELASTIC_PASSWORD)@localhost:9200
        - name: ES_INDICES
          value: "true"
        - name: ES_SHARDS
          value: "true"
---
apiVersion: v1
kind: Pod
metadata:
  name: kibana1
  labels:
    app: kibana1
spec:
  initContainers:
    - name: init-myservice
      image: busybox
      command:
        - sh
        - -c
        - until nslookup es1; do echo waiting for es1; sleep 2; done;
  containers:
    - name: kibana1
      image: docker.elastic.co/kibana/kibana:7.5.0
      ports:
        - containerPort: 5601
      env:
        - name: ES_JAVA_OPTS
          value: -Xms512m -Xmx512m
        - name: ELASTICSEARCH_HOSTS
          value: http://es1:9200
        - name: ELASTICSEARCH_USERNAME
          value: elastic
        - name: ELASTICSEARCH_PASSWORD
          valueFrom:
            secretKeyRef:
              name: es1
              key: password
      resources:
        # Default limits applied by the operator
        requests:
          memory: 1G
        limits:
          memory: 1G
      readinessProbe:
        tcpSocket:
          port: 5601
        initialDelaySeconds: 60
        periodSeconds: 5
        timeoutSeconds: 5
        failureThreshold: 30
      livenessProbe:
        tcpSocket:
          port: 5601
        initialDelaySeconds: 60
        periodSeconds: 5
        timeoutSeconds: 5
---
apiVersion: v1
kind: Service
metadata:
  name: es1
spec:
  type: LoadBalancer
  ports:
    - port: 9200
      protocol: TCP
  selector:
    app: es1
---
apiVersion: v1
kind: Service
metadata:
  name: kibana1
spec:
  type: LoadBalancer
  ports:
    - port: 5601
      protocol: TCP
  selector:
    app: kibana1
kubectl apply -f elastic.yml

Step 5: Test for persistence

save document

kubectl exec es1 -- bash -c 'curl -s -u elastic:$ELASTIC_PASSWORD -H "Content-Type: application/json" localhost:9200/test/doc/1 -d "{\\"foo\\": \\"bar\\"}"'

retrieve document

kubectl exec es1 -- bash -c 'curl -s -u elastic:$ELASTIC_PASSWORD -H "Content-Type: application/json" localhost:9200/test/doc/1'

kill elastic

kubectl exec es1 -- kill 1

Wait for elastic to be up and running again

retrieve document

kubectl exec es1 -- bash -c 'curl -s -u elastic:$ELASTIC_PASSWORD -H "Content-Type: application/json" localhost:9200/test/doc/1'
# Cleanup

kubectl delete -f elastic.yml
kubectl delete pvc es1-pvc
kubectl delete pv es1-pv

Notes

Persistent volumes - are reservations for disks, persisten volume claims - are reservations on top of PV

kubectl get pv
kubectl get pvc
kubectl delete pvc es1-pvc
kubectl delete pv es1-pv

TODO

https/ssl

docker run -it --rm -v $PWD/certs:/certs -w /certs docker.elastic.co/elasticsearch/elasticsearch:7.5.0 elasticsearch-certutil ca --days 9999 --out /certs/elastic-stack-ca.p12 --pass "" --silent

docker run -it --rm -v $PWD/certs:/certs -w /certs docker.elastic.co/elasticsearch/elasticsearch:7.5.0 elasticsearch-certutil cert --ca /certs/elastic-stack-ca.p12 --ca-pass "" --days 9999 --out /certs/elastic-certificates.p12 --pass "" --silent

https://www.elastic.co/guide/en/elasticsearch/reference/current/configuring-tls-docker.html

http://codingfundas.com/setting-up-elasticsearch-6-8-with-kibana-and-x-pack-security-enabled/index.html

https://alexmarquardt.com/2018/11/05/security-tls-ssl-pki-authentication-in-elasticsearch/

https://www.elastic.co/blog/configuring-ssl-tls-and-https-to-secure-elasticsearch-kibana-beats-and-logstash

oidc auth via identity server?