Bertus van Zyl
Bertus van Zyl

Reputation: 592

How get consistent names for Pods in Kubernetes

I want to run this docker image in kubernetes: https://hub.docker.com/_/rabbitmq

This is not a problem, and it is running. The problem is that I need to send through switches do the "docker run" command. For this image, when starting the container in docker you would run this:

docker run -d --hostname my-rabbit --name some-rabbit rabbitmq:3

The yaml file will then look something like this:

apiVersion: apps/v1
kind: Deployment
metadata:  
  name: rb
  namespace: rabbittest
spec:
  selector:
    matchLabels:
        app: rb
  replicas: 1
  template:
    metadata:
      labels:
        app: rb
    spec:
      containers:
      - name: rb-container
        env:                    
          - name: HOSTNAME
            value: "rbnode001"
        image: rabbitmq:3-management        
        resources:
          requests:
            cpu: 100m
            memory: 128Mi
          limits:
            cpu: 250m
            memory: 256Mi
        volumeMounts:
          - name: azure
            mountPath: /mnt/azure
        ports:
          - containerPort: 5672
      volumes:
      - name: azure
        azureFile:
          secretName: azure-secret
          shareName: rabbittest
          readOnly: false

My question is, how do I get kubernetes to apply the --name and --hostname when kubernetes executes the "docker run" commands?

Upvotes: 0

Views: 1799

Answers (2)

David Maze
David Maze

Reputation: 159865

Kubernetes's options are just different from Docker's options. Many options have equivalents in the pod spec object; some options don't have direct equivalents, or are split into multiple layers (volume mounts, published ports).

For the two options you mention:

  • docker run --name sets the name of the container. In Kubernetes you don't usually directly interact with containers, so you can't set their names. The metadata: {name: } sets the name of the Deployment, and generated Pods have names derived from that; the containers within a Pod also have names but it's very rare to use these.

  • docker run --hostname sets the name a container believes its hostname is. You almost never need this option; RabbitMQ is the notable exception. The pod spec has a hostname: option that can set this.

    spec:
      template:
        spec:
          hostname: my-rabbit
          containers: [...]
    

As @Shahriar's answer suggests, a StatefulSet is a better match for deployments that need some backing persistent state. In this case the StatefulSet automatically sets the host name based on the pod identity, so you don't need to do anything.

(The important detail for RabbitMQ is that the hostname must be consistent across recreating the container, and if the hostname is always rb-0 from a StatefulSet that satisfies this rule. An autogenerated Docker container ID, or a variable Kubernetes Deployment pod name, will be different on every restart, and Rabbit will lose track of its state.)

Upvotes: 1

Shahriar
Shahriar

Reputation: 13814

First of all, you need to create StatefulSets to RabbitMQ.

In your StatefulSet, add this ENV.

env:
  - name: POD_NAME
    valueFrom:
      fieldRef:
        apiVersion: v1
        fieldPath: metadata.name
  - name: POD_NAMESPACE
    valueFrom:
      fieldRef:
        apiVersion: v1
        fieldPath: metadata.namespace
  - name: K8S_SERVICE_NAME
    value: rabbitmq-headless
  - name: RABBITMQ_NODENAME
    value: $(POD_NAME).$(K8S_SERVICE_NAME).$(POD_NAMESPACE).svc.cluster.local

Here, K8S_SERVICE_NAME is headless service required by statefulset.

Finally, RABBITMQ_NODENAME will hold the HOSTNAME.

Upvotes: 2

Related Questions