A Rook o no a Rook: aquesta és la qüestió

A Rook o no a Rook: aquesta és la qüestió

A principis d'aquest mes, el 3 de maig, es va anunciar un llançament important d'un "sistema de gestió per a l'emmagatzematge de dades distribuïts a Kubernetes": Torre 1.0.0. Ja fa més d'un any publicat visió general de Rook. Després ens van demanar que parléssim de la seva experiència utilitzar a la pràctica — i ara, just a temps per a una fita tan significativa en la història del projecte, estem encantats de compartir les nostres impressions acumulades.

En resum, Rook és un conjunt operadors per a Kubernetes, que pren el control total del desplegament, la gestió i la recuperació automàtica de solucions d'emmagatzematge de dades com Ceph, EdgeFS, Minio, Cassandra, CockroachDB.

En aquests moments el més desenvolupat (i l'únic в estable etapa) la solució és rook-ceph-operador.

Nota: Entre els canvis significatius a la versió de Rook 1.0.0 relacionats amb Ceph, podem destacar el suport per a Ceph Nautilus i la possibilitat d'utilitzar NFS per a cubs CephFS o RGW. El que destaca entre d'altres és la maduració del suport EdgeFS al nivell beta.

Així, en aquest article:

  • Contestem la pregunta sobre quins avantatges veiem en utilitzar Rook per desplegar Ceph en un clúster de Kubernetes;
  • Compartirem la nostra experiència i impressions d'utilitzar Rook en producció;
  • Anem a explicar-vos per què diem "Sí!" a Rook i els nostres plans per a ell.

Comencem amb conceptes generals i teoria.

"Tinc avantatge d'una torre!" (jugador d'escacs desconegut)

A Rook o no a Rook: aquesta és la qüestió

Un dels principals avantatges de Rook és que la interacció amb els magatzems de dades es realitza mitjançant mecanismes Kubernetes. Això vol dir que ja no cal copiar les ordres per configurar Ceph des del full a la consola.

— Voleu desplegar CephFS en un clúster? Només cal escriure un fitxer YAML!
- Què? També voleu desplegar un magatzem d'objectes amb l'API S3? Només heu d'escriure un segon fitxer YAML!

Rook es crea segons totes les regles d'un operador típic. La interacció amb ell es produeix utilitzant CRD (definicions de recursos personalitzades), en què descrivim les característiques de les entitats Ceph que necessitem (com que aquesta és l'única implementació estable, per defecte aquest article parlarà de Ceph, tret que s'indiqui el contrari). D'acord amb els paràmetres especificats, l'operador executarà automàticament les ordres necessàries per a la configuració.

Vegem els detalls amb l'exemple de creació d'un magatzem d'objectes, o més aviat - CephObjectStoreUser.

apiVersion: ceph.rook.io/v1
kind: CephObjectStore
metadata:
  name: {{ .Values.s3.crdName }}
  namespace: kube-rook
spec:
  metadataPool:
    failureDomain: host
    replicated:
      size: 3
  dataPool:
    failureDomain: host
    erasureCoded:
      dataChunks: 2
      codingChunks: 1
  gateway:
    type: s3
    sslCertificateRef:
    port: 80
    securePort:
    instances: 1
    allNodes: false
---
apiVersion: ceph.rook.io/v1
kind: CephObjectStoreUser
metadata:
  name: {{ .Values.s3.crdName }}
  namespace: kube-rook
spec:
  store: {{ .Values.s3.crdName }}
  displayName: {{ .Values.s3.username }}

Els paràmetres que s'indiquen al llistat són bastant estàndard i no necessiten comentaris, però val la pena parar una atenció especial als assignats a variables de plantilla.

L'esquema general de treball es redueix al fet que "ordenem" recursos mitjançant un fitxer YAML, per al qual l'operador executa les ordres necessàries i ens retorna un secret "no tan real" amb el qual podem seguir treballant. (mirar abaix). I a partir de les variables enumerades anteriorment, es compilaran l'ordre i el nom secret.

Quin tipus d'equip és aquest? Quan es crea un usuari per a l'emmagatzematge d'objectes, l'operador Rook dins del pod farà el següent:

radosgw-admin user create --uid="rook-user" --display-name="{{ .Values.s3.username }}"

El resultat d'executar aquesta ordre serà una estructura JSON:

{
    "user_id": "rook-user",
    "display_name": "{{ .Values.s3.username }}",
    "keys": [
        {
           "user": "rook-user",
           "access_key": "NRWGT19TWMYOB1YDBV1Y",
           "secret_key": "gr1VEGIV7rxcP3xvXDFCo4UDwwl2YoNrmtRlIAty"
        }
    ],
    ...
}

Keys - quines aplicacions futures necessitaran per accedir a l'emmagatzematge d'objectes mitjançant l'API S3. L'operador de Rook els selecciona amablement i els posa al seu espai de noms en forma de secret amb el nom rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}.

Per utilitzar les dades d'aquest secret, només cal afegir-les al contenidor com a variables d'entorn. Com a exemple, donaré una plantilla per a Job, en la qual creem automàticament cubs per a cada entorn d'usuari:

{{- range $bucket := $.Values.s3.bucketNames }}
apiVersion: batch/v1
kind: Job
metadata:
  name: create-{{ $bucket }}-bucket-job
  annotations:
    "helm.sh/hook": post-install
    "helm.sh/hook-weight": "2"
spec:
  template:
    metadata:
      name: create-{{ $bucket }}-bucket-job
    spec:
      restartPolicy: Never
      initContainers:
      - name: waitdns
        image: alpine:3.6
        command: ["/bin/sh", "-c", "while ! getent ahostsv4 rook-ceph-rgw-{{ $.Values.s3.crdName }}; do sleep 1; done" ]
      - name: config
        image: rook/ceph:v1.0.0
        command: ["/bin/sh", "-c"]
        args: ["s3cmd --configure --access_key=$(ACCESS-KEY) --secret_key=$(SECRET-KEY) -s --no-ssl --dump-config | tee /config/.s3cfg"]
        volumeMounts:
        - name: config
          mountPath: /config
        env:
        - name: ACCESS-KEY
          valueFrom:
            secretKeyRef:
              name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}
              key: AccessKey
        - name: SECRET-KEY
          valueFrom:
            secretKeyRef:
              name: rook-ceph-object-user-{{ $.Values.s3.crdName }}-{{ $.Values.s3.username }}
              key: SecretKey
      containers:
      - name: create-bucket
        image: rook/ceph:v1.0.0
        command: 
        - "s3cmd"
        - "mb"
        - "--host=rook-ceph-rgw-{{ $.Values.s3.crdName }}"
        - "--host-bucket= "
        - "s3://{{ $bucket }}"
        ports:
        - name: s3-no-sll
          containerPort: 80
        volumeMounts:
        - name: config
          mountPath: /root
      volumes:
      - name: config
        emptyDir: {}
---
{{- end }}

Totes les accions enumerades en aquest treball s'han realitzat en el marc de Kubernetes. Les estructures descrites als fitxers YAML s'emmagatzemen en un repositori Git i es reutilitzen moltes vegades. Ho veiem com un gran avantatge per als enginyers de DevOps i el procés CI/CD en conjunt.

Content amb Rook i Rados

L'ús de la combinació Ceph + RBD imposa certes restriccions a l'hora de muntar volums als pods.

En particular, l'espai de noms ha de contenir un secret per accedir a Ceph per tal que les aplicacions amb estat funcionin. Està bé si teniu 2-3 entorns als seus espais de noms: podeu anar a copiar el secret manualment. Però, què passa si per a cada característica es crea un entorn independent amb el seu propi espai de noms per als desenvolupadors?

Hem resolt aquest problema nosaltres mateixos operador de shell, que copiava automàticament secrets a nous espais de noms (un exemple d'aquest ganxo es descriu a aquest article).

#! /bin/bash

if [[ $1 == “--config” ]]; then
   cat <<EOF
{"onKubernetesEvent":[
 {"name": "OnNewNamespace",
  "kind": "namespace",
  "event": ["add"]
  }
]}
EOF
else
    NAMESPACE=$(kubectl get namespace -o json | jq '.items | max_by( .metadata.creationTimestamp ) | .metadata.name')
    kubectl -n ${CEPH_SECRET_NAMESPACE} get secret ${CEPH_SECRET_NAME} -o json | jq ".metadata.namespace="${NAMESPACE}"" | kubectl apply -f -
fi

Tanmateix, quan s'utilitza Rook, aquest problema simplement no existeix. El procés de muntatge es fa utilitzant els seus propis controladors basats en Flexvolum o CSI (encara en fase beta) i per tant no requereix secrets.

Rook resol automàticament molts problemes, la qual cosa ens anima a utilitzar-lo en nous projectes.

Setge de Rook

Completem la part pràctica desplegant Rook i Ceph perquè puguem dur a terme els nostres propis experiments. Per facilitar l'assalt en aquesta torre inexpugnable, els desenvolupadors han preparat un paquet Helm. Anem a descarregar-lo:

$ helm fetch rook-master/rook-ceph --untar --version 1.0.0

A l'arxiu rook-ceph/values.yaml podeu trobar molts paràmetres diferents. El més important és especificar toleràncies per a agents i cerca. Vam descriure amb detall en què es pot utilitzar el mecanisme de contaminació/tolerància aquest article.

En resum, no volem que els pods de l'aplicació client estiguin situats als mateixos nodes que els discos d'emmagatzematge de dades. El motiu és senzill: d'aquesta manera el treball dels agents de Rook no afectarà l'aplicació en si.

Per tant, obriu el fitxer rook-ceph/values.yaml amb el vostre editor preferit i afegiu el bloc següent al final:

discover:
  toleration: NoExecute
  tolerationKey: node-role/storage
agent:
  toleration: NoExecute
  tolerationKey: node-role/storage
  mountSecurityMode: Any

Per a cada node reservat per a l'emmagatzematge de dades, afegiu el taint corresponent:

$ kubectl taint node ${NODE_NAME} node-role/storage="":NoExecute

A continuació, instal·leu el gràfic Helm amb l'ordre:

$ helm install --namespace ${ROOK_NAMESPACE} ./rook-ceph

Ara heu de crear un clúster i especificar la ubicació OSD:

apiVersion: ceph.rook.io/v1
kind: CephCluster
metadata:
  clusterName: "ceph"
  finalizers:
  - cephcluster.ceph.rook.io
  generation: 1
  name: rook-ceph
spec:
  cephVersion:
    image: ceph/ceph:v13
  dashboard:
    enabled: true
  dataDirHostPath: /var/lib/rook/osd
  mon:
    allowMultiplePerNode: false
    count: 3
  network:
    hostNetwork: true
  rbdMirroring:
    workers: 1
  placement:
    all:
      tolerations:
      - key: node-role/storage
        operator: Exists
  storage:
    useAllNodes: false
    useAllDevices: false
    config:
      osdsPerDevice: "1"
      storeType: filestore
    resources:
      limits:
        memory: "1024Mi"
      requests:
        memory: "1024Mi"
    nodes:
    - name: host-1
      directories:
      - path: "/mnt/osd"
    - name: host-2
      directories:
      - path: "/mnt/osd"
    - name: host-3
      directories:
      - path: "/mnt/osd"

Comprovant l'estat de Ceph: espereu veure'l HEALTH_OK:

$ kubectl -n ${ROOK_NAMESPACE} exec $(kubectl -n ${ROOK_NAMESPACE} get pod -l app=rook-ceph-operator -o name -o jsonpath='{.items[0].metadata.name}') -- ceph -s

Al mateix temps, comprovem que els pods amb l'aplicació client no acabin en nodes reservats per a Ceph:

$ kubectl -n ${APPLICATION_NAMESPACE} get pods -o custom-columns=NAME:.metadata.name,NODE:.spec.nodeName

A més, es poden configurar components addicionals com es desitgi. S'indiquen més detalls sobre ells a documentació. Per a l'administració, recomanem fermament instal·lar el tauler i la caixa d'eines.

Rook i ganxos: és suficient Rook per a tot?

Com podeu veure, el desenvolupament de Rook està en ple apogeu. Però encara hi ha problemes que no ens permeten abandonar completament la configuració manual de Ceph:

  • Sense Rook Driver no pot exportar mètriques sobre l'ús de blocs muntats, cosa que ens priva del seguiment.
  • Flexvolum i CSI no sé com canvieu la mida dels volums (a diferència del mateix RBD), de manera que Rook es veu privat d'una eina útil (i de vegades molt necessària!).
  • Rook encara no és tan flexible com Ceph normal. Si volem configurar l'agrupació perquè les metadades de CephFS s'emmagatzemin a l'SSD i les dades en si s'emmagatzemin a l'HDD, haurem de registrar manualment grups de dispositius separats als mapes CRUSH.
  • Tot i que rook-ceph-operator es considera estable, actualment hi ha alguns problemes a l'hora d'actualitzar Ceph de la versió 13 a la 14.

Troballes

"Ara mateix Rook està tancada del món exterior per peons, però creiem que algun dia tindrà un paper decisiu en el joc!" (cita inventada específicament per a aquest article)

Sens dubte, el projecte Rook ens ha guanyat el cor; creiem que [amb tots els seus pros i contres] definitivament mereix la vostra atenció.

Els nostres plans de futur es redueixen a fer de rook-ceph un mòdul operador-complement, que farà que el seu ús als nostres nombrosos clústers de Kubernetes sigui encara més senzill i còmode.

PS

Llegeix també al nostre blog:

Font: www.habr.com

Afegeix comentari