DEV Community

Aisalkyn Aidarova
Aisalkyn Aidarova

Posted on

statefulset vs deployment

We can deploy the exact same ECR image twice:

Restaurant Company ECR Image
             |
      ┌──────┴──────┐
      ↓             ↓
 Deployment      StatefulSet
      ↓             ↓
 restaurant-*    restaurant-0
 random names    restaurant-1
                 restaurant-2
Enter fullscreen mode Exit fullscreen mode

This lets them see the difference, instead of only hearing the theory.

Part 1 — First find your exact ECR image

On EC2 run:

aws ecr describe-repositories --region us-east-1
Enter fullscreen mode Exit fullscreen mode

Then:

aws ecr list-images \
  --repository-name restaurant-company \
  --region us-east-1
Enter fullscreen mode Exit fullscreen mode

Your image should look something like:

459532536656.dkr.ecr.us-east-1.amazonaws.com/restaurant-company:v1
Enter fullscreen mode Exit fullscreen mode

Use your actual tag below if it is not v1.


LAB 1 — Deployment

Tell students:

Сначала запускаем наш Restaurant Company как Deployment.

Потом удалим Pod и посмотрим, что Kubernetes создаст новый Pod с другим именем.

Create:

mkdir statefulset-lab
cd statefulset-lab

vim deployment.yaml
Enter fullscreen mode Exit fullscreen mode

Put:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: restaurant-deployment

spec:
  replicas: 3

  selector:
    matchLabels:
      app: restaurant

  template:
    metadata:
      labels:
        app: restaurant

    spec:
      containers:
        - name: restaurant
          image: 459532536656.dkr.ecr.us-east-1.amazonaws.com/restaurant-company:v1
          ports:
            - containerPort: 80
Enter fullscreen mode Exit fullscreen mode

Run:

kubectl apply -f deployment.yaml
Enter fullscreen mode Exit fullscreen mode

Then:

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Students should see something like:

restaurant-deployment-7d8c96b7d4-x7p2m
restaurant-deployment-7d8c96b7d4-k9t5z
restaurant-deployment-7d8c96b7d4-m4q8n
Enter fullscreen mode Exit fullscreen mode

STOP HERE and ask them

Ребята, какое имя у первого Pod?

They'll give the long name.

Then:

Как будет называться следующий Pod?

They cannot know.

Explain:

DEPLOYMENT

restaurant-deployment-xxxxx-A
restaurant-deployment-xxxxx-B
restaurant-deployment-xxxxx-C

Identity не важна.
Enter fullscreen mode Exit fullscreen mode

Delete one Deployment Pod

Get the names:

kubectl get pods
Enter fullscreen mode Exit fullscreen mode

Copy one and delete it:

kubectl delete pod restaurant-deployment-XXXXXXXXXX-XXXXX
Enter fullscreen mode Exit fullscreen mode

Immediately:

kubectl get pods -w
Enter fullscreen mode Exit fullscreen mode

Show them:

OLD:

restaurant-deployment-abc123-x7p2m ❌


NEW:

restaurant-deployment-abc123-j8k4q ✅
Enter fullscreen mode Exit fullscreen mode

Ask:

То же имя вернулось?

Нет.

That's the lesson:

Deployment говорит:

"Мне всё равно, какой Pod. Просто дай мне 3 работающих Pod."


LAB 2 — Same ECR image, but StatefulSet

Don't add storage yet.

Students need to understand identity first.

Create:

vim statefulset.yaml
Enter fullscreen mode Exit fullscreen mode

Use:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: restaurant-statefulset

spec:
  serviceName: restaurant
  replicas: 3

  selector:
    matchLabels:
      app: restaurant-stateful

  template:
    metadata:
      labels:
        app: restaurant-stateful

    spec:
      containers:
        - name: restaurant
          image: 459532536656.dkr.ecr.us-east-1.amazonaws.com/restaurant-company:v1
          ports:
            - containerPort: 80
Enter fullscreen mode Exit fullscreen mode

Apply:

kubectl apply -f statefulset.yaml
Enter fullscreen mode Exit fullscreen mode

Watch it:

kubectl get pods -w
Enter fullscreen mode Exit fullscreen mode

Now something very important happens.

Students should see:

restaurant-statefulset-0
restaurant-statefulset-1
restaurant-statefulset-2
Enter fullscreen mode Exit fullscreen mode

Tell them:

STOP. Смотрите на имена.

Compare:

DEPLOYMENT

restaurant-deployment-7d8c9-x8p2m
restaurant-deployment-7d8c9-k3j9q
restaurant-deployment-7d8c9-p7w4a


STATEFULSET

restaurant-statefulset-0
restaurant-statefulset-1
restaurant-statefulset-2
Enter fullscreen mode Exit fullscreen mode

Now ask:

Если я поставлю replicas: 4, как будет называться следующий Pod?

Students should answer:

restaurant-statefulset-3
Enter fullscreen mode Exit fullscreen mode

That's when they'll start understanding StatefulSet.


Now delete StatefulSet Pod

Run:

kubectl delete pod restaurant-statefulset-1
Enter fullscreen mode Exit fullscreen mode

Then:

kubectl get pods -w
Enter fullscreen mode Exit fullscreen mode

They should see:

restaurant-statefulset-1
Enter fullscreen mode Exit fullscreen mode

come back.

Tell them:

Я удалил restaurant-statefulset-1.

Kubernetes не сказал: "Дам тебе какой-нибудь новый Pod."

Он сказал:

"Мне нужен именно номер 1 обратно."

Draw:

STATEFULSET

restaurant-statefulset-0
restaurant-statefulset-1  ❌
restaurant-statefulset-2

             ↓

restaurant-statefulset-0
restaurant-statefulset-1  ✅
restaurant-statefulset-2
Enter fullscreen mode Exit fullscreen mode

This is stable identity.


Now the question that makes the class understand

Ask:

Хорошо. Имя вернулось. Но если внутри restaurant-statefulset-1 были важные данные — вернутся ли данные?

Answer:

Not automatically.

Now introduce storage.

Identity:
restaurant-statefulset-1
        +
Storage:
PVC-1

        =

Stateful application
Enter fullscreen mode Exit fullscreen mode

LAB 3 — StatefulSet + Persistent Storage

For your Restaurant Company app, Nginx normally serves static files, so it does not actually need StatefulSet in production.

Tell students this clearly:

Мы используем Restaurant Company с StatefulSet для обучения.

В реальном проекте этот frontend лучше запускать Deployment.

Database — MySQL, PostgreSQL, MongoDB — гораздо более естественный пример StatefulSet.

But Restaurant Company makes the mechanics easy to see.

Let's give each Pod its own /data.

First check:

kubectl get storageclass
Enter fullscreen mode Exit fullscreen mode

Then modify statefulset.yaml:

apiVersion: apps/v1
kind: StatefulSet
metadata:
  name: restaurant-statefulset

spec:
  serviceName: restaurant
  replicas: 3

  selector:
    matchLabels:
      app: restaurant-stateful

  template:
    metadata:
      labels:
        app: restaurant-stateful

    spec:
      containers:
        - name: restaurant
          image: 459532536656.dkr.ecr.us-east-1.amazonaws.com/restaurant-company:v1

          ports:
            - containerPort: 80

          volumeMounts:
            - name: restaurant-data
              mountPath: /data

  volumeClaimTemplates:
    - metadata:
        name: restaurant-data

      spec:
        accessModes:
          - ReadWriteOnce

        resources:
          requests:
            storage: 1Gi
Enter fullscreen mode Exit fullscreen mode

Because an existing StatefulSet may not accept this structural change cleanly, for the classroom the simplest route is to recreate the lab StatefulSet:

kubectl delete statefulset restaurant-statefulset
Enter fullscreen mode Exit fullscreen mode

Then:

kubectl apply -f statefulset.yaml
Enter fullscreen mode Exit fullscreen mode

Watch:

kubectl get pods -w
Enter fullscreen mode Exit fullscreen mode

Then:

kubectl get pvc
Enter fullscreen mode Exit fullscreen mode

Now the students should see the big idea:

restaurant-data-restaurant-statefulset-0
restaurant-data-restaurant-statefulset-1
restaurant-data-restaurant-statefulset-2
Enter fullscreen mode Exit fullscreen mode

Draw:

restaurant-statefulset-0
           |
           ↓
restaurant-data-restaurant-statefulset-0


restaurant-statefulset-1
           |
           ↓
restaurant-data-restaurant-statefulset-1


restaurant-statefulset-2
           |
           ↓
restaurant-data-restaurant-statefulset-2
Enter fullscreen mode Exit fullscreen mode

Now PROVE the data survives

This is the most important part of today's class.

Enter Pod 1:

kubectl exec -it restaurant-statefulset-1 -- sh
Enter fullscreen mode Exit fullscreen mode

Inside:

echo "HELLO FROM POD NUMBER 1" > /data/student.txt
Enter fullscreen mode Exit fullscreen mode

Check:

cat /data/student.txt
Enter fullscreen mode Exit fullscreen mode

You should get:

HELLO FROM POD NUMBER 1
Enter fullscreen mode Exit fullscreen mode

Exit:

exit
Enter fullscreen mode Exit fullscreen mode

Now tell students:

Сейчас я уничтожу Pod.

kubectl delete pod restaurant-statefulset-1
Enter fullscreen mode Exit fullscreen mode

Watch:

kubectl get pods -w
Enter fullscreen mode Exit fullscreen mode

Wait until:

restaurant-statefulset-1   1/1   Running
Enter fullscreen mode Exit fullscreen mode

Now:

kubectl exec -it restaurant-statefulset-1 -- sh
Enter fullscreen mode Exit fullscreen mode

Then:

cat /data/student.txt
Enter fullscreen mode Exit fullscreen mode

And:

HELLO FROM POD NUMBER 1
Enter fullscreen mode Exit fullscreen mode

This is your wow moment.

Tell them:

Pod умер.

Container умер.

Новый container был создан.

Но данные остались.

Because:

OLD POD
restaurant-statefulset-1 ❌
           |
           ↓
        PVC-1 ✅
           |
           ↓
         DATA ✅


NEW POD
restaurant-statefulset-1 ✅
           |
           ↓
        SAME PVC-1
           |
           ↓
         DATA ✅
Enter fullscreen mode Exit fullscreen mode

Then prove each Pod has its OWN storage

Run:

kubectl exec -it restaurant-statefulset-0 -- sh
Enter fullscreen mode Exit fullscreen mode

Inside:

cat /data/student.txt
Enter fullscreen mode Exit fullscreen mode

It should not contain Pod 1's file.

Then:

echo "I AM POD ZERO" > /data/student.txt
exit
Enter fullscreen mode Exit fullscreen mode

Check Pod 0:

kubectl exec restaurant-statefulset-0 -- cat /data/student.txt
Enter fullscreen mode Exit fullscreen mode

Result:

I AM POD ZERO
Enter fullscreen mode Exit fullscreen mode

Check Pod 1:

kubectl exec restaurant-statefulset-1 -- cat /data/student.txt
Enter fullscreen mode Exit fullscreen mode

Result:

HELLO FROM POD NUMBER 1
Enter fullscreen mode Exit fullscreen mode

Now draw this:

             STATEFULSET

       restaurant-statefulset

       /          |          \
      /           |           \

    POD-0        POD-1        POD-2
      |            |            |
      ↓            ↓            ↓
    PVC-0        PVC-1        PVC-2
      |            |            |
      ↓            ↓            ↓
"I AM 0"      "HELLO 1"      DATA-2
Enter fullscreen mode Exit fullscreen mode

The sentence I want your students to repeat

Have the whole class say this:

Deployment сохраняет количество Pod.

StatefulSet сохраняет identity Pod.

PVC сохраняет данные.

And then:

Deployment:
"I need 3 Pods."


StatefulSet:
"I need Pod 0,
 I need Pod 1,
 I need Pod 2,
 and each can have its own storage."
Enter fullscreen mode Exit fullscreen mode

Top comments (0)