Щелкните здесь, чтобы опубликовать эту статью в LinkedIn »

РЕДАКТИРОВАТЬ: Google обновил свои документы и исправил это…

TL; DR StatefulSets только что перешли на GA в k8s 1.9. Это моя история о том, как мне удалось развернуть StatefulSet в моем кластере GKE после борьбы с учебником Google и официальными документами Kubernetes по этому вопросу. Также я закончил писать это в 1:00, так что, если вы видите опечатки, просто hmu в комментариях.

Полные файлы yaml доступны ниже. Суть этой истории в том, что я не мог понять, как заставить StatefulSet развернуть на GKE. Частично это было из-за того, что Google не выпустил kubectl 1.9 внутри своего набора инструментов sdk CLI, другая часть была в том, что учебники Googles не были полностью реализованы, а другая, вероятно, была связана с тем, что я был собой и все испортил. Мне удалось развернуть свой StatefulSet, и вот как я это сделал. Если вы знаете способ получше или знаете, как volumeClaimTemplates работает, напишите мне в комментариях :)

Как я уже упоминал в предыдущих сообщениях здесь, на Medium и на моем личном сайте, я сейчас создаю slackbot (и ищу бета-пользователей, так что хму на https://categorylinksbot.io ), чтобы помочь людям организовать свои ссылки. Моя долгосрочная цель - создать интеграцию мессенджера для каждой из основных платформ обмена сообщениями. Затем используйте эти данные для создания лучшего рекламного продукта, чем Google Search. Ирония судьбы создания рекламной платформы, которая превосходит поиск Google поверх GCP, не ускользает от меня 😜.

Мой slackbot требует взаимодействия между запросами с сохранением состояния. Я использую Redis для управления этими взаимодействиями. Redis великолепен, но если экземпляр, который у вас Redis запущен при перезагрузке, все ваши данные исчезнут. Поскольку я запускаю redis в качестве контейнера для вытесняемых экземпляров в моем кластере GKE (потому что я дешевый), мои экземпляры можно перезапустить в любое время практически без предупреждения. Мне нужно было иметь возможность периодически запускать BGSAVE в моей базе данных redis, чтобы минимизировать проблемы конечного пользователя при повторном запуске вытесняемых экземпляров.

В Kubernetes правильным способом масштабирования приложения с отслеживанием состояния является использование StatefulSets. StatefulSets позволяет вам создавать реплики вашего приложения (читай: масштабировать), которые затем могут получить доступ к подключенным томам, которые вы используете для хранения файла, созданного BGSAVE.

Прежде всего, вам нужно определить PersistentVolume (pv). В Руководстве по GCP pv описывает монтируемый том. В примере в руководстве по GCP есть ошибка. Ему нужно что-то, называемое storageClassName, чтобы на него (далее) ссылался созданный нами ПВХ. В приведенном ниже примере ¹ обновлен параметр storageClassName в определении yaml. Без него мы не смогли бы привязаться к этому pv.

Если говорить о привязке, то в этом нам поможет PersistentVolumeClaims (ПВХ). Взглянув на этот пример, ² снова покажет ошибку - ›нет storageClassName. Отказ от ответственности: если вы не обращаете внимания и просто копируете файлы туда, я добавил это для вас. Так что добро пожаловать :)

Теперь, когда вы запускаете kubectl apply -f my-pv.yaml, а затем делаете то же самое для своего my-pv-claim.yaml файла (он же файл ¹ и файл ² соответственно), вы должны увидеть, что утверждение могло быть привязано к pv и запуск gcloud compute disks list или w / e также должен отобразите созданный вами диск. Пожалуйста, прочтите этот раздел в руководстве, поскольку он объясняет, что искать, когда ПВХ не связывается с PV. Что-то что-то отказ от ответственности ..

Третья часть, которая вам нужна, - это служба для взаимодействия с вашим StatefulSet. У меня есть контейнер nginx, обрабатывающий все запросы, направляемые в мое приложение, поэтому эта служба уже была создана, но я поместил ее под ³ для ясности и, вероятно, запутать читателей, которые просто копируют и вставляют то, что у меня есть в нижнем колонтитуле.

И, наконец, определение StatefulSet, которое я просто помещаю ниже, потому что создание ссылок нижнего колонтитула - это PITA (также вот ссылка, где я научился это делать). Последняя проблема с учебником Google и официальными документами kubernetes - это использование раздела volumeClaimTemplates в определении StatefulSet. На всю жизнь я не мог заставить это проверить или что-то еще, когда я запускал kubectl apply. Я пытался сделать кучу вещей, но безуспешно. В конце концов я погуглил и нашел это сообщение в блоге. Основная суть состоит в том, что вы должны использовать ключевое слово persistentVolumeClaim внутри раздела volumes вашего определения StatefulSet.

В основном ваше определение StatefulSet должно выглядеть так:

apiVersion: apps/v1beta2
kind: StatefulSet
metadata:
  name: [STATEFULSET_NAME]
spec:
  serviceName: [SERVICE_NAME]
  replicas: 3
  template:
    metadata:
      labels:
        app: [APP_NAME]
    spec:
      updateStrategy:
        type: RollingUpdate
      containers:
      - name: [CONTAINER_NAME]
        image: ...
        ports:
        - containerPort: 80
          name: [PORT_NAME]
        volumeMounts:
        - name: my-volume
          mountPath: /data-or-something
      volumes:
        - ...
        - name: my-volume
          persistentVolumeClaim:
            claimName: $$YOUR-PVC-NAME

Так и должно быть! Пишите в разделе комментариев любые вопросы, которые у вас есть. Я надеюсь, что это послужит хорошей справочной страницей по устранению неполадок для всех, кто застрял при выполнении StatefulSets. Все в сообществе k8s говорят, что k8s все еще пытается правильно создавать приложения с отслеживанием состояния. Я считаю, что StatefulSets - это шаг в правильном направлении. Это огромная функция, которая принесет огромную пользу мелким разработчикам, таким как я. Я действительно хочу отказаться от экземпляра Google Cloud SQL и просто запустить контейнер Postgres StatefulSet в k8s и таким образом сэкономить немного денег. Я также надеюсь, что больше людей будут использовать StatefulSets для создания действительно крутых вещей в k8s.

[1]:

apiVersion: v1
kind: PersistentVolume
metadata:
  name: $$NAME-ME-SOMETHING
spec:
  capacity:
    storage: 20Gi
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  gcePersistentDisk:
    pdName: [PD_NAME]
    fsType: ext4

[2]:

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
  name: $$NAME-ME-SOMETHING
spec: 
  storageClassName: manual
  accessModes:
    - ReadWriteOnce
  resources:
    requests:
      storage: 20Gi

[3]:

apiVersion: v1
kind: Service
metadata:
  name: myApp
  namespace: default
spec:
  ports:
  - port: 80
    targetPort: 80
    protocol: TCP
  type: NodePort
  selector:
    run: myApp