Monday, February 18, 2019

Using Rook deployed Object Store in Kubernetes

Using Rook Deployed Object Store in Kubernetes 


This posting will explore Rook deployed object store using Ceph radosgw within a kubernetes cluster. A radosgw pod will be deployed and a user created. This will be followed by an exploration of the stored credential information and using this information with a custom deployed pod.

Background


Previously, we have deployed a Ceph storage cluster using Rook and demonstrated how to customize the cluster configuration.

Current deployments

$ kubectl -n rook-ceph get pods
NAME                                     READY   STATUS      RESTARTS   AGE
rook-ceph-mgr-a-569d76f456-sddpg         1/1     Running     0          3d21h
rook-ceph-mon-a-6bc4689f9d-r8jcm         1/1     Running     0          3d21h
rook-ceph-mon-b-566cdf9d6-mhf8w          1/1     Running     0          3d21h
rook-ceph-mon-c-74c6779667-svktr         1/1     Running     0          3d21h
rook-ceph-osd-0-6766d4f547-6qlvv         1/1     Running     0          3d21h
rook-ceph-osd-1-c5c7ddf67-xrm2k          1/1     Running     0          3d21h
rook-ceph-osd-2-f7b75cf4d-bm5sc          1/1     Running     0          3d21h
rook-ceph-osd-prepare-kube-node1-ddgkk   0/2     Completed   0          3d21h
rook-ceph-osd-prepare-kube-node2-nmgqj   0/2     Completed   0          3d21h
rook-ceph-osd-prepare-kube-node3-xzwnr   0/2     Completed   0          3d21h
rook-ceph-tools-76c7d559b6-tnmrf         1/1     Running     0          3d21h

Ceph cluster status

$ kubectl -n rook-ceph exec `kubectl -n rook-ceph get pods --selector=app=rook-ceph-tools -o jsonpath='{.items[0].metadata.name}'` -- ceph status
  cluster:
    id:     eff29897-252c-4e65-93e7-6f4975c0d83a
    health: HEALTH_OK
 
  services:
    mon: 3 daemons, quorum a,c,b
    mgr: a(active)
    osd: 3 osds: 3 up, 3 in
 
 data:
    pools:   0 pools, 0 pgs
    objects: 0  objects, 0 B
    usage:   3.1 GiB used, 57 GiB / 60 GiB avail
    pgs:     

Deploying Object Store Pod and User

Rook has CephObjectStore and CephObjectStoreUser CRD which permit the creation of a Ceph RadosGW service and related users. 
The default configurations are deployed with the below commands
RGW Pod

$ kubectl create -f object.yaml 
cephobjectstore.ceph.rook.io/my-store created
$ kubectl -n rook-ceph get pods
NAME                                      READY   STATUS      RESTARTS   AGE
rook-ceph-mgr-a-569d76f456-sddpg          1/1     Running     0          3d21h
rook-ceph-mon-a-6bc4689f9d-r8jcm          1/1     Running     0          3d21h
rook-ceph-mon-b-566cdf9d6-mhf8w           1/1     Running     0          3d21h
rook-ceph-mon-c-74c6779667-svktr          1/1     Running     0          3d21h
rook-ceph-osd-0-6766d4f547-6qlvv          1/1     Running     0          3d21h
rook-ceph-osd-1-c5c7ddf67-xrm2k           1/1     Running     0          3d21h
rook-ceph-osd-2-f7b75cf4d-bm5sc           1/1     Running     0          3d21h
rook-ceph-osd-prepare-kube-node1-ddgkk    0/2     Completed   0          3d21h
rook-ceph-osd-prepare-kube-node2-nmgqj    0/2     Completed   0          3d21h
rook-ceph-osd-prepare-kube-node3-xzwnr    0/2     Completed   0          3d21h
rook-ceph-rgw-my-store-57556c8479-vkjvn   1/1     Running     0          5m58s
rook-ceph-tools-76c7d559b6-tnmrf          1/1     Running     0          3d21h

RGW User

$ kubectl create -f object-user.yaml 
cephobjectstoreuser.ceph.rook.io/my-user created
$ kubectl -n rook-ceph exec `kubectl -n rook-ceph get pods --selector=app=rook-ceph-tools -o jsonpath='{.items[0].metadata.name}'` -- radosgw-admin user list
[
    "my-user"
]

The RGW user information can be explored with the radosgw-admin command below. Notice the access_key and secret_key are available. 

$ kubectl -n rook-ceph exec `kubectl -n rook-ceph get pods --selector=app=rook-ceph-tools -o jsonpath='{.items[0].metadata.name}'` -- radosgw-admin user info --uid my-user
{
    "user_id": "my-user",
    "display_name": "my display name",
    "email": "",
    "suspended": 0,
    "max_buckets": 1000,
    "auid": 0,
    "subusers": [],
    "keys": [
        {
            "user": "my-user",
            "access_key": "C6FIZTCAAEH1LBWNY84X",
            "secret_key": "i8Pw44ViKt3DVAQTSWIEJcazUHrYRCj0u6Xw9jPE"
        }
    ],
    "swift_keys": [],
    "caps": [],
    "op_mask": "read, write, delete",
    "default_placement": "",
    "placement_tags": [],
    "bucket_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "user_quota": {
        "enabled": false,
        "check_on_raw": false,
        "max_size": -1,
        "max_size_kb": 0,
        "max_objects": -1
    },
    "temp_url_keys": [],
    "type": "rgw",
    "mfa_ids": []
}

Rook adds the access_key and secret_key to a stored secret for usage by other pods.

$ kubectl -n rook-ceph get secrets
NAME                                     TYPE                                  DATA   AGE
default-token-67jhm                      kubernetes.io/service-account-token   3      3d21h
rook-ceph-admin-keyring                  kubernetes.io/rook                    1      3d21h
rook-ceph-config                         kubernetes.io/rook                    2      3d21h
rook-ceph-dashboard-password             kubernetes.io/rook                    1      3d21h
rook-ceph-mgr-a-keyring                  kubernetes.io/rook                    1      3d21h
rook-ceph-mgr-token-sbk8f                kubernetes.io/service-account-token   3      3d21h
rook-ceph-mon                            kubernetes.io/rook                    4      3d21h
rook-ceph-mons-keyring                   kubernetes.io/rook                    1      3d21h
rook-ceph-object-user-my-store-my-user   kubernetes.io/rook                    2      7m31s
rook-ceph-osd-token-qlsst                kubernetes.io/service-account-token   3      3d21h
rook-ceph-rgw-my-store                   kubernetes.io/rook                    1      14m

$ kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user
NAME                                     TYPE                 DATA   AGE
rook-ceph-object-user-my-store-my-user   kubernetes.io/rook   2      7m49s

$ kubectl -n rook-ceph get secret rook-ceph-object-user-my-store-my-user -o yaml
apiVersion: v1
data:
  AccessKey: QzZGSVpUQ0FBRUgxTEJXTlk4NFg=
  SecretKey: aThQdzQ0VmlLdDNEVkFRVFNXSUVKY2F6VUhyWVJDajB1Nlh3OWpQRQ==
kind: Secret
metadata:
  creationTimestamp: "2019-02-18T14:37:40Z"
  labels:
    app: rook-ceph-rgw
    rook_cluster: rook-ceph
    rook_object_store: my-store
    user: my-user
  name: rook-ceph-object-user-my-store-my-user
  namespace: rook-ceph
  ownerReferences:
  - apiVersion: v1
    blockOwnerDeletion: true
    kind: CephCluster
    name: rook-ceph
    uid: 200d59ce-307a-11e9-bc12-52540087c4d1
  resourceVersion: "1175482"
  selfLink: /api/v1/namespaces/rook-ceph/secrets/rook-ceph-object-user-my-store-my-user
  uid: be847f63-338a-11e9-bc12-52540087c4d1
type: kubernetes.io/rook

The AccessKey and SecretKey values are base64 encoded stores of the access_key and secret_key seen in the radosgw-admin command.

$ base64 -d -
QzZGSVpUQ0FBRUgxTEJXTlk4NFg=
C6FIZTCAAEH1LBWNY84X
$ base64 -d -
aThQdzQ0VmlLdDNEVkFRVFNXSUVKY2F6VUhyWVJDajB1Nlh3OWpQRQ==
i8Pw44ViKt3DVAQTSWIEJcazUHrYRCj0u6Xw9jPE

The RGW service can be queried to display currently available S3 buckets. No buckets are initially created by Rook.

$ kubectl -n rook-ceph exec `kubectl -n rook-ceph get pods --selector=app=rook-ceph-tools -o jsonpath='{.items[0].metadata.name}'` -- radosgw-admin bucket list
[]

Consume Object Store

Some information must be gathered so they can be provided to the custom pod. 
Object Store name: 
$ kubectl -n rook-ceph get pods --selector='app=rook-ceph-rgw' -o jsonpath='{.items[0].metadata.labels.rook_object_store}'
my-store

Object Store Service Hostname
$ kubectl -n rook-ceph get services
NAME                      TYPE        CLUSTER-IP       EXTERNAL-IP   PORT(S)    AGE
rook-ceph-mgr             ClusterIP   10.108.38.115            9283/TCP   3d23h
rook-ceph-mgr-dashboard   ClusterIP   10.107.5.72              8443/TCP   3d23h
rook-ceph-mon-a           ClusterIP   10.99.36.158             6789/TCP   3d23h
rook-ceph-mon-b           ClusterIP   10.103.132.39            6789/TCP   3d23h
rook-ceph-mon-c           ClusterIP   10.101.117.131           6789/TCP   3d23h
rook-ceph-rgw-my-store    ClusterIP   10.107.251.22            80/TCP     147m
 

Create Custom Deployment
A custom deployment file to deploy a basic CentOS7 and install the python-bono package. The environment is populated with the needed parameters to access the S3 store and create a bucket. 

$ cat ~/my-deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
  name: mydemo
  namespace: rook-ceph
  labels:
    app: mydemo
spec:
  replicas: 1
  selector:
    matchLabels:
      app: mydemo
  template:
    metadata:
      labels:
        app: mydemo
    spec:
      dnsPolicy: ClusterFirstWithHostNet
      hostNetwork: true
      containers:
      - name: mydemo
        image: docker.io/jdeathe/centos-ssh
        imagePullPolicy: IfNotPresent
        command: ["/usr/bin/supervisord"]
        securityContext:
          privileged: true
          capabilities:
            add:
              - SYS_ADMIN
        lifecycle:
          postStart:
            exec:
              command: ["/usr/bin/yum", "install", "-y", "python-boto"]
        env:
          - name: AWSACCESSKEYID
            valueFrom:
              secretKeyRef:
                name: rook-ceph-object-user-my-store-my-user
                key: AccessKey
          - name: AWSSECRETACCESSKEY
            valueFrom:
              secretKeyRef:
                name: rook-ceph-object-user-my-store-my-user
                key: SecretKey
          - name: BUCKETNAME
            value: my-store
          - name: RGWHOST
            # the value is {service-name}.{name-space}
            value: rook-ceph-rgw-my-store.rook-ceph


$ kubectl create -f ~/my-deployment.yaml
 deployment.apps/mydemo created

Once the pod is running, open a shell and examine the environment

$ kubectl -n rook-ceph exec `kubectl -n rook-ceph get pods --selector=app=mydemo -o jsonpath='{.items[0].metadata.name}'` -it /bin/bash
# printenv | sort | grep -E "AWSACCESS|AWSSECRET|BUCKETNAME|RGWHOST"
AWSACCESSKEYID=C6FIZTCAAEH1LBWNY84X
AWSSECRETACCESSKEY=i8Pw44ViKt3DVAQTSWIEJcazUHrYRCj0u6Xw9jPE
BUCKETNAME=my-store
RGWHOST=rook-ceph-rgw-my-store.rook-ceph
Create and run a simple test script. This script will connect to the RGW and create a bucket. No output will be printed on a success.

# cat ~/test-s3.py
import boto
import os
import boto.s3.connection
access_key = os.environ['AWSACCESSKEYID']
secret_key = os.environ['AWSSECRETACCESSKEY']
bucket = os.environ['BUCKETNAME']
myhost = os.environ['RGWHOST']
conn = boto.connect_s3(
        aws_access_key_id = access_key,
        aws_secret_access_key = secret_key,
        host = myhost,
        is_secure=False,
        calling_format = boto.s3.connection.OrdinaryCallingFormat(),
        )
bucket = conn.create_bucket(bucket)

# python ~/test-s3.py 

The RGW service can be queried to display the created bucket

$ kubectl -n rook-ceph exec `kubectl -n rook-ceph get pods --selector=app=rook-ceph-tools -o jsonpath='{.items[0].metadata.name}'` -- radosgw-admin bucket list
[
    "my-store"
]

Issues and Going Forward

  • Deleting the CephObjectStoreUser does not delete the stored secret.
  • The ceph.conf section name is hard coded for the radosgw service
  • Dynamically query the environment variables used for the application deployment

No comments:

Post a Comment