skip to Main Content

I have a running Elasticsearch STS with a headless Service assigned to it:

svc.yaml:

kind: Service
apiVersion: v1
metadata:
  name: elasticsearch
  namespace: elasticsearch-namespace
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  clusterIP: None
  ports:
    - port: 9200
      name: rest
    - port: 9300
      name: inter-node

stateful.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: es-cluster
  namespace: elasticsearch-namespace
spec:
  serviceName: elasticsearch
  replicas: 3
  selector:
    matchLabels:
      app: elasticsearch
  template:
    metadata:
      labels:
        app: elasticsearch
    spec:
      containers:
      - name: elasticsearch
        image: docker.elastic.co/elasticsearch/elasticsearch:7.2.0
        resources:
            limits:
              cpu: 1000m
            requests:
              cpu: 100m
        ports:
        - containerPort: 9200
          name: rest
          protocol: TCP
        - containerPort: 9300
          name: inter-node
          protocol: TCP
        volumeMounts:
          - name: elasticsearch-persistent-storage
            mountPath: /usr/share/elasticsearch/data
        env:
          - name: cluster.name
            value: k8s-logs
          - name: node.name
            valueFrom:
              fieldRef:
                fieldPath: metadata.name
          - name: discovery.seed_hosts
            value: "es-cluster-0.elasticsearch,es-cluster-1.elasticsearch,es-cluster-2.elasticsearch"
          - name: cluster.initial_master_nodes
            value: "es-cluster-0,es-cluster-1,es-cluster-2"
          - name: ES_JAVA_OPTS
            value: "-Xms512m -Xmx512m"
      initContainers:
      - name: fix-permissions
        image: busybox
        command: ["sh", "-c", "chown -R 1000:1000 /usr/share/elasticsearch/data"]
        securityContext:
          privileged: true
        volumeMounts:
        - name: elasticsearch-persistent-storage
          mountPath: /usr/share/elasticsearch/data
      - name: increase-vm-max-map
        image: busybox
        command: ["sysctl", "-w", "vm.max_map_count=262144"]
        securityContext:
          privileged: true
      - name: increase-fd-ulimit
        image: busybox
        command: ["sh", "-c", "ulimit -n 65536"]
        securityContext:
          privileged: true
  volumeClaimTemplates:
    - metadata:
        name: elasticsearch-persistent-storage
        labels:
          app: elasticsearch
      spec:
        accessModes: [ "ReadWriteOnce" ]
        storageClassName: elasticsearch-storageclass
        resources:
          requests:
            storage: 20Gi

The question is: how to access this STS with PODs of Deployment Kind? Let’s say, using this Redis POD:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: redis-ws-app
  labels:
    app: redis-ws-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: redis-ws-app
  template:
    metadata:
      labels:
        app: redis-ws-app
    spec:
      containers:
      - name: redis-ws-app
        image: redis:latest
        command: [ "redis-server"]
        ports:
        - containerPort: 6379

I have been trying to create another service, that would enable me to access it from the outside, but without any luck:

kind: Service
apiVersion: v1
metadata:
  name: elasticsearch-tcp
  namespace: elasticsearch-namespace
  labels:
    app: elasticsearch
spec:
  selector:
    app: elasticsearch
  ports:
  - protocol: TCP
    port: 9200
    targetPort: 9200

2

Answers


  1. Chosen as BEST ANSWER

    User @suren was right about the headless service. In my case, I was just using a wrong reference.

    The Kube-DNS naming convention is 
    service.namespace.svc.cluster-domain.tld 
    and the default cluster domain is cluster.local
    

    In my case, the in order to reach the pod, one has to use:

    curl -I elasticsearch.elasticsearch-namespace
    

  2. You would reach it directly hitting the headless service. As an example, this StatefulSet and this Service.

    apiVersion: apps/v1
    kind: StatefulSet
    metadata:
      name: web
    spec:
      selector:
        matchLabels:
          app: nginx
      serviceName: "nginx"
      replicas: 4
      template:
        metadata:
          labels:
            app: nginx
        spec:
          containers:
          - name: nginx
            image: nginx
            ports:
            - containerPort: 80
              name: web
    
    ---
    
    kind: Service
    apiVersion: v1
    metadata:
      name: nginx-headless
    spec:
      selector:
        app: nginx
      clusterIP: None
      ports:
        - port: 80
          name: http
    

    I could reach the pods of the statefulset, through the headless service from any pod within the cluster:

    / # curl -I nginx-headless
    HTTP/1.1 200 OK
    Server: nginx/1.19.0
    Date: Tue, 09 Jun 2020 12:36:47 GMT
    Content-Type: text/html
    Content-Length: 612
    Last-Modified: Tue, 26 May 2020 15:00:20 GMT
    Connection: keep-alive
    ETag: "5ecd2f04-264"
    Accept-Ranges: bytes
    

    The singularity of the headless service, is that it doesn’t create iptable rules for that service. So, when you query that service, it goes to kube-dns (or CoreDNS), and it returns the backends, rather then the IP address is the service itself. So, if you do nslookup, for example, it will return all the backends (pods) of that service:

    / # nslookup nginx-headless
    
    Name:      nginx-headless
    Address 1: 10.56.1.44
    Address 2: 10.56.1.45
    Address 3: 10.56.1.46
    Address 4: 10.56.1.47
    

    And it won’t have any iptable rules assigned to it:

    $ sudo iptables-save | grep -i nginx-headless
    $
    

    Unlike a normal service, that would return the IP address of the service itself:

    / # nslookup nginx
    
    Name:      nginx
    Address 1: 10.60.15.30 nginx.default.svc.cluster.local
    

    And it will have iptable rules assigned to it:

    $ sudo iptables-save | grep -i nginx
    -A KUBE-SERVICES ! -s 10.56.0.0/14 -d 10.60.15.30/32 -p tcp -m comment --comment "default/nginx: cluster IP" -m tcp --dport 80 -j KUBE-MARK-MASQ
    -A KUBE-SERVICES -d 10.60.15.30/32 -p tcp -m comment --comment "default/nginx: cluster IP" -m tcp --dport 80 -j KUBE-SVC-4N57TFCL4MD7ZTDA
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search