One place for hosting & domains

      Kubernetes

      How To Set Up a Ceph Cluster within Kubernetes Using Rook


      The author selected the Mozilla Foundation to receive a donation as part of the Write for DOnations program.

      Introduction

      Kubernetes containers are stateless as a core principle, but data must still be managed, preserved, and made accessible to other services. Stateless means that the container is running in isolation without any knowledge of past transactions, which makes it easy to replace, delete, or distribute the container. However, it also means that data will be lost for certain lifecycle events like restart or deletion.

      Rook is a storage orchestration tool that provides a cloud-native, open source solution for a diverse set of storage providers. Rook uses the power of Kubernetes to turn a storage system into self-managing services that provide a seamless experience for saving Kubernetes application or deployment data.

      Ceph is a highly scalable distributed-storage solution offering object, block, and file storage. Ceph clusters are designed to run on any hardware using the so-called CRUSH algorithm (Controlled Replication Under Scalable Hashing).

      One main benefit of this deployment is that you get the highly scalable storage solution of Ceph without having to configure it manually using the Ceph command line, because Rook automatically handles it. Kubernetes applications can then mount block devices and filesystems from Rook to preserve and monitor their application data.

      In this tutorial, you will set up a Ceph cluster using Rook and use it to persist data for a MongoDB database as an example.

      Prerequisites

      Before you begin this guide, you’ll need the following:

      • A DigitalOcean Kubernetes cluster with at least three nodes that each have 2 vCPUs and 4 GB of Memory. To create a cluster on DigitalOcean and connect to it, see the Kubernetes Quickstart.
      • The kubectl command-line tool installed on a development server and configured to connect to your cluster. You can read more about installing kubectl in its official documentation.
      • A DigitalOcean block storage Volume with at least 100 GB for each node of the cluster you just created—for example, if you have three nodes you will need three Volumes. Select Manually Format rather than automatic and then attach your Volume to the Droplets in your node pool. You can follow the Volumes Quickstart to achieve this.

      Step 1 — Setting up Rook

      After completing the prerequisite, you have a fully functional Kubernetes cluster with three nodes and three Volumes—you’re now ready to set up Rook.

      In this section, you will clone the Rook repository, deploy your first Rook operator on your Kubernetes cluster, and validate the given deployment status. A Rook operator is a container that automatically bootstraps the storage clusters and monitors the storage daemons to ensure the storage clusters are healthy.

      First, you will clone the Rook repository, so you have all the resources needed to start setting up your Rook cluster:

      • git clone --single-branch --branch release-1.3 https://github.com/rook/rook.git

      This command will clone the Rook repository from Github and create a folder with the name of rook in your directory. Now enter the directory using the following command:

      • cd rook/cluster/examples/kubernetes/ceph

      Next you will continue by creating the common resources you needed for your Rook deployment, which you can do by deploying the Kubernetes config file that is available by default in the directory:

      • kubectl create -f common.yaml

      The resources you’ve created are mainly CustomResourceDefinitions (CRDs) and define new resources that the operator will later use. They contain resources like the ServiceAccount, Role, RoleBinding, ClusterRole, and ClusterRoleBinding.

      Note: This standard file assumes that you will deploy the Rook operator and all Ceph daemons in the same namespace. If you want to deploy the operator in a separate namespace, see the comments throughout the common.yaml file.

      After the common resources are created, the next step is to create the Rook operator.

      Before deploying the operator.yaml file, you will need to change the CSI_RBD_GRPC_METRICS_PORT variable because your DigitalOcean Kubernetes cluster already uses the standard port by default. Open the file with the following command:

      Then search for the CSI_RBD_GRPC_METRICS_PORT variable, uncomment it by removing the #, and change the value from port 9001 to 9093:

      operator.yaml

      kind: ConfigMap
      apiVersion: v1
      metadata:
        name: rook-ceph-operator-config
        namespace: rook-ceph
      data:
        ROOK_CSI_ENABLE_CEPHFS: "true"
        ROOK_CSI_ENABLE_RBD: "true"
        ROOK_CSI_ENABLE_GRPC_METRICS: "true"
        CSI_ENABLE_SNAPSHOTTER: "true"
        CSI_FORCE_CEPHFS_KERNEL_CLIENT: "true"
        ROOK_CSI_ALLOW_UNSUPPORTED_VERSION: "false"
        # Configure CSI CSI Ceph FS grpc and liveness metrics port
        # CSI_CEPHFS_GRPC_METRICS_PORT: "9091"
        # CSI_CEPHFS_LIVENESS_METRICS_PORT: "9081"
        # Configure CSI RBD grpc and liveness metrics port
        CSI_RBD_GRPC_METRICS_PORT: "9093"
        # CSI_RBD_LIVENESS_METRICS_PORT: "9080"
      

      Once you’re done, save and exit the file.

      Next, you can deploy the operator using the following command:

      • kubectl create -f operator.yaml

      The command will output the following:

      Output

      configmap/rook-ceph-operator-config created deployment.apps/rook-ceph-operator created

      Again, you’re using the kubectl create command with the -f flag to assign the file that you want to apply. It will take around a couple of seconds for the operator to be running. You can verify the status using the following command:

      • kubectl get pod -n rook-ceph

      You use the -n flag to get the pods of a specific Kubernetes namespace (rook-ceph in this example).

      Once the operator deployment is ready, it will trigger the creation of the DeamonSets that are in charge of creating the rook-discovery agents on each worker node of your cluster. You’ll receive output similar to:

      Output

      NAME READY STATUS RESTARTS AGE rook-ceph-operator-599765ff49-fhbz9 1/1 Running 0 92s rook-discover-6fhlb 1/1 Running 0 55s rook-discover-97kmz 1/1 Running 0 55s rook-discover-z5k2z 1/1 Running 0 55s

      You have successfully installed Rook and deployed your first operator. Next, you will create a Ceph cluster and verify that it is working.

      Step 2 — Creating a Ceph Cluster

      Now that you have successfully set up Rook on your Kubernetes cluster, you’ll continue by creating a Ceph cluster within the Kubernetes cluster and verifying its functionality.

      First let’s review the most important Ceph components and their functionality:

      • Ceph Monitors, also known as MONs, are responsible for maintaining the maps of the cluster required for the Ceph daemons to coordinate with each other. There should always be more than one MON running to increase the reliability and availability of your storage service.

      • Ceph Managers, also known as MGRs, are runtime daemons responsible for keeping track of runtime metrics and the current state of your Ceph cluster. They run alongside your monitoring daemons (MONs) to provide additional monitoring and an interface to external monitoring and management systems.

      • Ceph Object Store Devices, also known as OSDs, are responsible for storing objects on a local file system and providing access to them over the network. These are usually tied to one physical disk of your cluster. Ceph clients interact with OSDs directly.

      To interact with the data of your Ceph storage, a client will first make contact with the Ceph Monitors (MONs) to obtain the current version of the cluster map. The cluster map contains the data storage location as well as the cluster topology. The Ceph clients then use the cluster map to decide which OSD they need to interact with.

      Rook enables Ceph storage to run on your Kubernetes cluster. All of these components are running in your Rook cluster and will directly interact with the Rook agents. This provides a more streamlined experience for administering your Ceph cluster by hiding Ceph components like placement groups and storage maps while still providing the options of advanced configurations.

      Now that you have a better understanding of what Ceph is and how it is used in Rook, you will continue by setting up your Ceph cluster.

      You can complete the setup by either running the example configuration, found in the examples directory of the Rook project, or by writing your own configuration. The example configuration is fine for most use cases and provides excellent documentation of optional parameters.

      Now you’ll start the creation process of a Ceph cluster Kubernetes Object.

      First, you need to create a YAML file:

      The configuration defines how the Ceph cluster will be deployed. In this example, you will deploy three Ceph Monitors (MON) and enable the Ceph dashboard. The Ceph dashboard is out of scope for this tutorial, but you can use it later in your own individual project for visualizing the current status of your Ceph cluster.

      Add the following content to define the apiVersion and the Kubernetes Object kind as well as the name and the namespace the Object should be deployed in:

      cephcluster.yaml

      apiVersion: ceph.rook.io/v1
      kind: CephCluster
      metadata:
        name: rook-ceph
        namespace: rook-ceph
      

      After that, add the spec key, which defines the model that Kubernetes will use to create your Ceph cluster. You’ll first define the image version you want to use and whether you allow unsupported Ceph versions or not:

      cephcluster.yaml

      spec:
        cephVersion:
          image: ceph/ceph:v14.2.8
          allowUnsupported: false
      

      Then set the data directory where configuration files will be persisted using the dataDirHostPath key:

      cephcluster.yaml

        dataDirHostPath: /var/lib/rook
      

      Next, you define if you want to skip upgrade checks and when you want to upgrade your cluster using the following parameters:

      cephcluster.yaml

        skipUpgradeChecks: false
        continueUpgradeAfterChecksEvenIfNotHealthy: false
      

      You configure the number of Ceph Monitors (MONs) using the mon key. You also allow the deployment of multiple MONs per node:

      cephcluster.yaml

        mon:
          count: 3
          allowMultiplePerNode: false
      

      Options for the Ceph dashboard are defined under the dashboard key. This gives you options to enable the dashboard, customize the port, and prefix it when using a reverse proxy:

      cephcluster.yaml

        dashboard:
          enabled: true
          # serve the dashboard under a subpath (useful when you are accessing the dashboard via a reverse proxy)
          # urlPrefix: /ceph-dashboard
          # serve the dashboard at the given port.
          # port: 8443
          # serve the dashboard using SSL
          ssl: false
      

      You can also enable monitoring of your cluster with the monitoring key (monitoring requires Prometheus to be pre-installed):

      cephcluster.yaml

        monitoring:
          enabled: false
          rulesNamespace: rook-ceph
      

      RDB stands for RADOS (Reliable Autonomic Distributed Object Store) block device, which are thin-provisioned and resizable Ceph block devices that store data on multiple nodes.

      RBD images can be asynchronously shared between two Ceph clusters by enabling rbdMirroring. Since we’re working with one cluster in this tutorial, this isn’t necessary. The number of workers is therefore set to 0:

      cephcluster.yaml

        rbdMirroring:
          workers: 0
      

      You can enable the crash collector for the Ceph daemons:

      cephcluster.yaml

        crashCollector:
          disable: false
      

      The cleanup policy is only important if you want to delete your cluster. That is why this option has to be left empty:

      cephcluster.yaml

        cleanupPolicy:
          deleteDataDirOnHosts: ""
        removeOSDsIfOutAndSafeToRemove: false
      

      The storage key lets you define the cluster level storage options; for example, which node and devices to use, the database size, and how many OSDs to create per device:

      cephcluster.yaml

        storage:
          useAllNodes: true
          useAllDevices: true
          config:
            # metadataDevice: "md0" # specify a non-rotational storage so ceph-volume will use it as block db device of bluestore.
            # databaseSizeMB: "1024" # uncomment if the disks are smaller than 100 GB
            # journalSizeMB: "1024"  # uncomment if the disks are 20 GB or smaller
      

      You use the disruptionManagement key to manage daemon disruptions during upgrade or fencing:

      cephcluster.yaml

        disruptionManagement:
          managePodBudgets: false
          osdMaintenanceTimeout: 30
          manageMachineDisruptionBudgets: false
          machineDisruptionBudgetNamespace: openshift-machine-api
      

      These configuration blocks will result in the final following file:

      cephcluster.yaml

      apiVersion: ceph.rook.io/v1
      kind: CephCluster
      metadata:
        name: rook-ceph
        namespace: rook-ceph
      spec:
        cephVersion:
          image: ceph/ceph:v14.2.8
          allowUnsupported: false
        dataDirHostPath: /var/lib/rook
        skipUpgradeChecks: false
        continueUpgradeAfterChecksEvenIfNotHealthy: false
        mon:
          count: 3
          allowMultiplePerNode: false
        dashboard:
          enabled: true
          # serve the dashboard under a subpath (useful when you are accessing the dashboard via a reverse proxy)
          # urlPrefix: /ceph-dashboard
          # serve the dashboard at the given port.
          # port: 8443
          # serve the dashboard using SSL
          ssl: false
        monitoring:
          enabled: false
          rulesNamespace: rook-ceph
        rbdMirroring:
          workers: 0
        crashCollector:
          disable: false
        cleanupPolicy:
          deleteDataDirOnHosts: ""
        removeOSDsIfOutAndSafeToRemove: false
        storage:
          useAllNodes: true
          useAllDevices: true
          config:
            # metadataDevice: "md0" # specify a non-rotational storage so ceph-volume will use it as block db device of bluestore.
            # databaseSizeMB: "1024" # uncomment if the disks are smaller than 100 GB
            # journalSizeMB: "1024"  # uncomment if the disks are 20 GB or smaller
        disruptionManagement:
          managePodBudgets: false
          osdMaintenanceTimeout: 30
          manageMachineDisruptionBudgets: false
          machineDisruptionBudgetNamespace: openshift-machine-api
      

      Once you’re done, save and exit your file.

      You can also customize your deployment by, for example changing your database size or defining a custom port for the dashboard. You can find more options for your cluster deployment in the cluster example of the Rook repository.

      Next, apply this manifest in your Kubernetes cluster:

      • kubectl apply -f cephcluster.yaml

      Now check that the pods are running:

      • kubectl get pod -n rook-ceph

      This usually takes a couple of minutes, so just refresh until your output reflects something like the following:

      Output

      NAME READY STATUS RESTARTS AGE csi-cephfsplugin-lz6dn 3/3 Running 0 3m54s csi-cephfsplugin-provisioner-674847b584-4j9jw 5/5 Running 0 3m54s csi-cephfsplugin-provisioner-674847b584-h2cgl 5/5 Running 0 3m54s csi-cephfsplugin-qbpnq 3/3 Running 0 3m54s csi-cephfsplugin-qzsvr 3/3 Running 0 3m54s csi-rbdplugin-kk9sw 3/3 Running 0 3m55s csi-rbdplugin-l95f8 3/3 Running 0 3m55s csi-rbdplugin-provisioner-64ccb796cf-8gjwv 6/6 Running 0 3m55s csi-rbdplugin-provisioner-64ccb796cf-dhpwt 6/6 Running 0 3m55s csi-rbdplugin-v4hk6 3/3 Running 0 3m55s rook-ceph-crashcollector-pool-33zy7-68cdfb6bcf-9cfkn 1/1 Running 0 109s rook-ceph-crashcollector-pool-33zyc-565559f7-7r6rt 1/1 Running 0 53s rook-ceph-crashcollector-pool-33zym-749dcdc9df-w4xzl 1/1 Running 0 78s rook-ceph-mgr-a-7fdf77cf8d-ppkwl 1/1 Running 0 53s rook-ceph-mon-a-97d9767c6-5ftfm 1/1 Running 0 109s rook-ceph-mon-b-9cb7bdb54-lhfkj 1/1 Running 0 96s rook-ceph-mon-c-786b9f7f4b-jdls4 1/1 Running 0 78s rook-ceph-operator-599765ff49-fhbz9 1/1 Running 0 6m58s rook-ceph-osd-prepare-pool-33zy7-c2hww 1/1 Running 0 21s rook-ceph-osd-prepare-pool-33zyc-szwsc 1/1 Running 0 21s rook-ceph-osd-prepare-pool-33zym-2p68b 1/1 Running 0 21s rook-discover-6fhlb 1/1 Running 0 6m21s rook-discover-97kmz 1/1 Running 0 6m21s rook-discover-z5k2z 1/1 Running 0 6m21s

      You have now successfully set up your Ceph cluster and can continue by creating your first storage block.

      Step 3 — Adding Block Storage

      Block storage allows a single pod to mount storage. In this section, you will create a storage block that you can use later in your applications.

      Before Ceph can provide storage to your cluster, you first need to create a storageclass and a cephblockpool. This will allow Kubernetes to interoperate with Rook when creating persistent volumes:

      • kubectl apply -f ./csi/rbd/storageclass.yaml

      The command will output the following:

      Output

      cephblockpool.ceph.rook.io/replicapool created storageclass.storage.k8s.io/rook-ceph-block created

      Note: If you’ve deployed the Rook operator in a namespace other than rook-ceph you need to change the prefix in the provisioner to match the namespace you use.

      After successfully deploying the storageclass and cephblockpool, you will continue by defining the PersistentVolumeClaim (PVC) for your application. A PersistentVolumeClaim is a resource used to request storage from your cluster.

      For that, you first need to create a YAML file:

      • nano pvc-rook-ceph-block.yaml

      Add the following for your PersistentVolumeClaim:

      pvc-rook-ceph-block.yaml

      apiVersion: v1
      kind: PersistentVolumeClaim
      metadata:
        name: mongo-pvc
      spec:
        storageClassName: rook-ceph-block
        accessModes:
        - ReadWriteOnce
        resources:
          requests:
            storage: 5Gi
      

      First, you need to set an apiVersion (v1 is the current stable version). Then you need to tell Kubernetes which type of resource you want to define using the kind key (PersistentVolumeClaim in this case).

      The spec key defines the model that Kubernetes will use to create your PersistentVolumeClaim. Here you need to select the storage class you created earlier: rook-ceph-block. You can then define the access mode and limit the resources of the claim. ReadWriteOnce means the volume can only be mounted by a single node.

      Now that you have defined the PersistentVolumeClaim, it is time to deploy it using the following command:

      • kubectl apply -f pvc-rook-ceph-block.yaml

      You will receive the following output:

      Output

      persistentvolumeclaim/mongo-pvc created

      You can now check the status of your PVC:

      When the PVC is bound, you are ready:

      Output

      NAME STATUS VOLUME CAPACITY ACCESS MODES STORAGECLASS AGE mongo-pvc Bound pvc-ec1ca7d1-d069-4d2a-9281-3d22c10b6570 5Gi RWO rook-ceph-block 16s

      You have now successfully created a storage class and used it to create a PersistenVolumeClaim that you will mount to a application to persist data in the next section.

      Step 4 — Creating a MongoDB Deployment with a rook-ceph-block

      Now that you have successfully created a storage block and a persistent volume, you will put it to use by implementing it in a MongoDB application.

      The configuration will contain a few things:

      • A single container deployment based on the latest version of the mongo image.
      • A persistent volume to preserve the data of the MongoDB database.
      • A service to expose the MongoDB port on port 31017 of every node so you can interact with it later.

      First open the configuration file:

      Start the manifest with the Deployment resource:

      mongo.yaml

      apiVersion: apps/v1
      kind: Deployment
      metadata:
        name: mongo
      spec:
        selector:
          matchLabels:
            app: mongo
        template:
          metadata:
            labels:
              app: mongo
          spec:
            containers:
            - image: mongo:latest
              name: mongo
              ports:
              - containerPort: 27017
                name: mongo
              volumeMounts:
              - name: mongo-persistent-storage
                mountPath: /data/db
            volumes:
            - name: mongo-persistent-storage
              persistentVolumeClaim:
                claimName: mongo-pvc
      
      ...
      

      For each resource in the manifest, you need to set an apiVersion. For deployments and services, use apiVersion: apps/v1, which is a stable version. Then, tell Kubernetes which resource you want to define using the kind key. Each definition should also have a name defined in metadata.name.

      The spec section tells Kubernetes what the desired state of your final state of the deployment is. This definition requests that Kubernetes should create one pod with one replica.

      Labels are key-value pairs that help you organize and cross-reference your Kubernetes resources. You can define them using metadata.labels and you can later search for them using selector.matchLabels.

      The spec.template key defines the model that Kubernetes will use to create each of your pods. Here you will define the specifics of your pod’s deployment like the image name, container ports, and the volumes that should be mounted. The image will then automatically be pulled from an image registry by Kubernetes.

      Here you will use the PersistentVolumeClaim you created earlier to persist the data of the /data/db directory of the pods. You can also specify extra information like environment variables that will help you with further customizing your deployment.

      Next, add the following code to the file to define a Kubernetes Service that exposes the MongoDB port on port 31017 of every node in your cluster:

      mongo.yaml

      ...
      
      ---
      apiVersion: v1
      kind: Service
      metadata:
        name: mongo
        labels:
          app: mongo
      spec:
        selector:
          app: mongo
        type: NodePort
        ports:
          - port: 27017
            nodePort: 31017
      

      Here you also define an apiVersion, but instead of using the Deployment type, you define a Service. The service will receive connections on port 31017 and forward them to the pods’ port 27017, where you can then access the application.

      The service uses NodePort as the service type, which will expose the Service on each Node’s IP at a static port between 30000 and 32767 (31017 in this case).

      Now that you have defined the deployment, it is time to deploy it:

      • kubectl apply -f mongo.yaml

      You will see the following output:

      Output

      deployment.apps/mongo created service/mongo created

      You can check the status of the deployment and service:

      • kubectl get svc,deployments

      The output will be something like this:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE service/kubernetes ClusterIP 10.245.0.1 <none> 443/TCP 33m service/mongo NodePort 10.245.124.118 <none> 27017:31017/TCP 4m50s NAME READY UP-TO-DATE AVAILABLE AGE deployment.apps/mongo 1/1 1 1 4m50s

      After the deployment is ready, you can start saving data into your database. The easiest way to do so is by using the MongoDB shell, which is included in the MongoDB pod you just started. You can open it using kubectl.

      For that you are going to need the name of the pod, which you can get using the following command:

      The output will be similar to this:

      Output

      NAME READY STATUS RESTARTS AGE mongo-7654889675-mjcks 1/1 Running 0 13m

      Now copy the name and use it in the exec command:

      • kubectl exec -it your_pod_name mongo

      Now that you are in the MongoDB shell let’s continue by creating a database:

      The use command switches between databases or creates them if they don’t exist.

      Output

      switched to db test

      Then insert some data into your new test database. You use the insertOne() method to insert a new document in the created database:

      • db.test.insertOne( {name: "test", number: 10 })

      Output

      { "acknowledged" : true, "insertedId" : ObjectId("5f22dd521ba9331d1a145a58") }

      The next step is retrieving the data to make sure it is saved, which can be done using the find command on your collection:

      • db.getCollection("test").find()

      The output will be similar to this:

      Output

      NAME READY STATUS RESTARTS AGE { "_id" : ObjectId("5f1b18e34e69b9726c984c51"), "name" : "test", "number" : 10 }

      Now that you have saved some data into the database, it will be persisted in the underlying Ceph volume structure. One big advantage of this kind of deployment is the dynamic provisioning of the volume. Dynamic provisioning means that applications only need to request the storage and it will be automatically provided by Ceph instead of developers creating the storage manually by sending requests to their storage providers.

      Let’s validate this functionality by restarting the pod and checking if the data is still there. You can do this by deleting the pod, because it will be restarted to fulfill the state defined in the deployment:

      • kubectl delete pod -l app=mongo

      Now let’s validate that the data is still there by connecting to the MongoDB shell and printing out the data. For that you first need to get your pod’s name and then use the exec command to open the MongoDB shell:

      The output will be similar to this:

      Output

      NAME READY STATUS RESTARTS AGE mongo-7654889675-mjcks 1/1 Running 0 13m

      Now copy the name and use it in the exec command:

      • kubectl exec -it your_pod_name mongo

      After that, you can retrieve the data by connecting to the database and printing the whole collection:

      • use test
      • db.getCollection("test").find()

      The output will look similar to this:

      Output

      NAME READY STATUS RESTARTS AGE { "_id" : ObjectId("5f1b18e34e69b9726c984c51"), "name" : "test", "number" : 10 }

      As you can see the data you saved earlier is still in the database even though you restarted the pod. Now that you have successfully set up Rook and Ceph and used them to persist the data of your deployment, let’s review the Rook toolbox and what you can do with it.

      The Rook Toolbox is a tool that helps you get the current state of your Ceph deployment and troubleshoot problems when they arise. It also allows you to change your Ceph configurations like enabling certain modules, creating users, or pools.

      In this section, you will install the Rook Toolbox and use it to execute basic commands like getting the current Ceph status.

      The toolbox can be started by deploying the toolbox.yaml file, which is in the examples/kubernetes/ceph directory:

      • kubectl apply -f toolbox.yaml

      You will receive the following output:

      Output

      deployment.apps/rook-ceph-tools created

      Now check that the pod is running:

      • kubectl -n rook-ceph get pod -l "app=rook-ceph-tools"

      Your output will be similar to this:

      Output

      NAME READY STATUS RESTARTS AGE rook-ceph-tools-7c5bf67444-bmpxc 1/1 Running 0 9s

      Once the pod is running you can connect to it using the kubectl exec command:

      • kubectl -n rook-ceph exec -it $(kubectl -n rook-ceph get pod -l "app=rook-ceph-tools" -o jsonpath="{.items[0].metadata.name}") bash

      Let’s break this command down for better understanding:

      1. The kubectl exec command lets you execute commands in a pod; like setting an environment variable or starting a service. Here you use it to open the BASH terminal in the pod. The command that you want to execute is defined at the end of the command.
      2. You use the -n flag to specify the Kubernetes namespace the pod is running in.
      3. The -i (interactive) and -t (tty) flags tell Kubernetes that you want to run the command in interactive mode with tty enabled. This lets you interact with the terminal you open.
      4. $() lets you define an expression in your command. That means that the expression will be evaluated (executed) before the main command and the resulting value will then be passed to the main command as an argument. Here we define another Kubernetes command to get a pod where the label app=rook-ceph-tool and read the name of the pod using jsonpath. We then use the name as an argument for our first command.

      Note: As already mentioned this command will open a terminal in the pod, so your prompt will change to reflect this.

      Now that you are connected to the pod you can execute Ceph commands for checking the current status or troubleshooting error messages. For example the ceph status command will give you the current health status of your Ceph configuration and more information like the running MONs, the current running data pools, the available and used storage, and the current I/O operations:

      Here is the output of the command:

      Output

      cluster: id: 71522dde-064d-4cf8-baec-2f19b6ae89bf health: HEALTH_OK services: mon: 3 daemons, quorum a,b,c (age 23h) mgr: a(active, since 23h) osd: 3 osds: 3 up (since 23h), 3 in (since 23h) data: pools: 1 pools, 32 pgs objects: 61 objects, 157 MiB usage: 3.4 GiB used, 297 GiB / 300 GiB avail pgs: 32 active+clean io: client: 5.3 KiB/s wr, 0 op/s rd, 0 op/s wr

      You can also query the status of specific items like your OSDs using the following command:

      This will print information about your OSD like the used and available storage and the current state of the OSD:

      Output

      +----+------------+-------+-------+--------+---------+--------+---------+-----------+ | id | host | used | avail | wr ops | wr data | rd ops | rd data | state | +----+------------+-------+-------+--------+---------+--------+---------+-----------+ | 0 | node-3jis6 | 1165M | 98.8G | 0 | 0 | 0 | 0 | exists,up | | 1 | node-3jisa | 1165M | 98.8G | 0 | 5734 | 0 | 0 | exists,up | | 2 | node-3jise | 1165M | 98.8G | 0 | 0 | 0 | 0 | exists,up | +----+------------+-------+-------+--------+---------+--------+---------+-----------+

      More information about the available commands and how you can use them to debug your Ceph deployment can be found in the official documentation.

      You have now successfully set up a complete Rook Ceph cluster on Kubernetes that helps you persist the data of your deployments and share their state between the different pods without having to use some kind of external storage or provision storage manually. You also learned how to start the Rook Toolbox and use it to debug and troubleshoot your Ceph deployment.

      Conclusion

      In this article, you configured your own Rook Ceph cluster on Kubernetes and used it to provide storage for a MongoDB application. You extracted useful terminology and became familiar with the essential concepts of Rook so you can customize your deployment.

      If you are interested in learning more, consider checking out the official Rook documentation and the example configurations provided in the repository for more configuration options and parameters.

      You can also try out the other kinds of storage Ceph provides like shared file systems if you want to mount the same volume to multiple pods at the same time.



      Source link

      Bereitstellen von Laravel 7 und MySQL in Kubernetes mithilfe von Helm


      Der Autor hat den Diversity in Tech Fund dazu ausgewählt, eine Spende im Rahmen des Programms Write for DOnations zu erhalten.

      Einführung

      Laravel ist heute eines der beliebtesten Open-Source-basierten PHP-Anwendungsframeworks. Es wird oft mit einer MySQL-Datenbank bereitgestellt, kann aber so konfiguriert werden, dass verschiedene Backend-Datenspeicheroptionen zum Einsatz kommen. Laravel ist stolz darauf, viele moderne Funktionen und das umfangreiche Paketökosystem von PHP zu nutzen.

      Kubernetes ist eine Plattform zur Orchestrierung von Containern, die in DigitalOcean Kubernetes-Clustern gehostet werden kann, um einen Großteil der Verwaltungsaufgaben bei der Einrichtung und Ausführung von Containern in der Produktion zu übernehmen. Helm ist ein Kubernetes-Paketmanager, der das Konfigurieren und Installieren von Diensten und Pods vereinfacht.

      In diesem Leitfaden erstellen Sie eine Laravel PHP-Anwendung, erstellen Ihre App in einem Docker-Image und stellen das Image mithilfe des LAMP Helm Chart in einem DigitalOcean Kubernetes-Cluster bereit. Als Nächstes richten Sie einen Ingress Controller ein, um Ihrer App SSL und einen benutzerdefinierten Domänennamen hinzuzufügen.Danach verfügen Sie eine funktionierende Laravel-Anwendung, die mit einer MySQL-Datenbank verbunden ist, die in einem Kubernetes-Cluster ausgeführt wird.

      Voraussetzungen

      • Docker, installiert auf dem Computer, von dem aus Sie auf Ihren Cluster zugreifen werden. Detaillierte Anweisungen zum Installieren von Docker für die meisten Linux-Distributionen finden Sie hier oder für andere Betriebssysteme auf der Website von Docker.
      • Ein Konto bei Docker Hub zur Speicherung von Docker-Images, die Sie in diesem Tutorial erstellen werden.
      • Einen DigitalOcean Kubernetes 1.17+-Cluster, bei dem Ihre Verbindung als der kubectl-Standard konfiguriert ist. Um zu erfahren, wie Sie einen Kubernetes-Cluster in DigitalOcean erstellen können, lesen Sie unser Dokument Kubernetes Schnellstart. Um zu erfahren, wie Sie eine Verbindung zum Cluster herstellen können, konsultieren Sie Herstellen einer Verbindung zu einem DigitalOcean Kubernetes-Cluster.
      • Helm 3-Paketmanager, auf Ihrem lokalen Rechner installiert. Führen Sie den ersten Schritt aus und fügen Sie das stable-Repository aus dem zweiten Schritt des Tutorials Installieren von Software in Kubernetes-Clustern mit dem Helm 3-Paketmanager hinzu.
      • Einen vollständig registrierten Domänennamen mit einem verfügbaren A-Eintrag. Dieses Tutorial verwendet in allen Bereichen your_domain. Sie können einen Domänennamen unter Namecheap günstig erwerben oder einen kostenlosen von Freenom herunterladen oder einfach die Domänenregistrierungsstelle Ihrer Wahl verwenden. Sie müssen sich erst einmal keine Gedanken um eine Verknüpfung des A-Eintrags Ihrer Domäne mit einer IP-Adresse machen. Sobald Sie Schritt 5 erreichen und Ihr Ingress Controller verfügbar ist, werden Sie your_domain mit der richtigen IP-Adresse verbinden.

      Schritt 1 — Erstellen einer neuen Laravel-Anwendung

      In diesem Schritt verwenden Sie Docker, um eine neue Laravel-7-Anwendung zu erstellen. Sie sollten jedoch mit einer bestehenden Laravel-Anwendung, die MySQL als Backing-Datenbank nutzt, das gleiche Verfahren nutzen können. Die neu erstellte Anwendung wird überprüfen, ob Laravel mit der Datenbank verbunden ist, und den Namen der Datenbank anzeigen.

      Wechseln Sie zunächst in Ihr Stammverzeichnis und erstellen Sie dann eine neue Laravel-Anwendung mit einem Docker-Container vom Typ composer:

      • cd ~
      • docker run --rm -v $(pwd):/app composer create-project --prefer-dist laravel/laravel laravel-kubernetes

      Nach der Fertigstellung des Containers und der Installation aller Composer-Pakete sollten Sie eine neue Installation von Laravel in Ihrem aktuellen Verzeichnis namens laravel-kubernetes/ sehen. Navigieren Sie zu diesem Ordner:

      Von hier führen Sie die restlichen Befehle dieses Tutorials aus.

      Zweck dieser Anwendung ist es, Ihre Datenbankverbindung zu testen und den Namen der Datenbank in Ihrem Browser anzuzeigen. Öffnen Sie die Datei ./resources/views/welcome.blade.php in einem Texteditor, um die Datenbankverbindung zu testen:

      • nano ./resources/views/welcome.blade.php

      Suchen Sie nach dem Abschnitt <div class="links">...</div> und ersetzen Sie den Inhalt durch Folgendes:

      ./resources/views/welcome.blade.php

      ...
      <div class="links">
         <strong>Database Connected: </strong>
          @php
              try {
                  DB::connection()->getPDO();
                  echo DB::connection()->getDatabaseName();
                  } catch (Exception $e) {
                  echo 'None';
              }
          @endphp
      </div>
      ...
      

      Speichern und schließen Sie die Datei.

      Weitere Anpassungen müssen Sie in diesem Tutorial an der standardmäßigen Laravel-Anwendung nicht vornehmen. Nun wird dieser kurze PHP-Abschnitt Ihre Datenbankverbindung testen und den Namen der Datenbank im Laravel-Begrüßungsbildschirm in Ihrem Webbrowser anzeigen.

      Im nächsten Schritt verwenden Sie Docker, um ein Image zu erstellen, das diese Laravel-Anwendung und Docker Compose enthält, um zu testen, ob sie lokal ausgeführt wird und eine Verbindung zu einer MySQL-Datenbank hergestellt wird.

      Schritt 2 — Containerisieren Ihrer Laravel-Anwendung

      Nachdem Sie eine neue Laravel-Anwendung erzeugt haben, müssen Sie nun Ihren Code in ein Docker-Image integrieren und das Image dann mit Docker Compose testen. Zwar ist das Ziel dieses Tutorials, Ihre Anwendung in einem Kubernetes-Cluster bereitzustellen, doch ist Docker Compose eine praktische Option, um Ihr Docker-Image und Ihre Konfiguration vor Ort zu testen, bevor Sie sie in der Cloud ausführen. Die schnelle Feedbackschleife kann nützlich sein, um kleine Änderungen vorzunehmen und zu testen.

      Erstellen Sie zunächst mit nano oder Ihrem bevorzugten Texteditor im Stammverzeichnis Ihrer Laravel-Anwendung eine Datei namens Dockerfile:

      Fügen Sie folgenden Inhalt hinzu: Docker wird diese Datei verwenden, um Ihren Code in ein Image zu integrieren:

      ./Dockerfile

      FROM php:7.4-apache
      
      # Install packages
      RUN apt-get update && apt-get install -y 
          git 
          zip 
          curl 
          sudo 
          unzip 
          libicu-dev 
          libbz2-dev 
          libpng-dev 
          libjpeg-dev 
          libmcrypt-dev 
          libreadline-dev 
          libfreetype6-dev 
          g++
      
      # Apache configuration
      ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
      RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
      RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
      RUN a2enmod rewrite headers
      
      # Common PHP Extensions
      RUN docker-php-ext-install 
          bz2 
          intl 
          iconv 
          bcmath 
          opcache 
          calendar 
          pdo_mysql
      
      # Ensure PHP logs are captured by the container
      ENV LOG_CHANNEL=stderr
      
      # Set a volume mount point for your code
      VOLUME /var/www/html
      
      # Copy code and run composer
      COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
      COPY . /var/www/tmp
      RUN cd /var/www/tmp && composer install --no-dev
      
      # Ensure the entrypoint file can be run
      RUN chmod +x /var/www/tmp/docker-entrypoint.sh
      ENTRYPOINT ["/var/www/tmp/docker-entrypoint.sh"]
      
      # The default apache run command
      CMD ["apache2-foreground"]
      

      Speichern und schließen Sie die Datei.

      Diese Dockerfile-Datei startet mit dem in Docker Hub gefundenen PHP 7.4 Apache Docker-Image und installiert dann mehrere Linux-Pakete, die allgemein von Laravel-Anwendungen benötigt werden. Als Nächstes erstellt sie Apache-Konfigurationsdateien und ermöglicht das Umschreiben von Headern. Die Dockerfile-Datei installiert mehrere gängige PHP-Erweiterungen und fügt eine Umgebungsvariable hinzu, um sicherzustellen, dass die Protokolle von Laravel über stderr an den Container gestreamt werden. So können Sie Laravel-Protokolle sehen, indem Sie Ihre Docker Compose- oder Kubernetes-Protokolle durchsehen.

      Schließlich kopiert die Dockerfile-Datei den gesamten Code in Ihrer Laravel-Anwendung nach /var/www/tmp und installiert die Abhängigkeiten von Composer. Dann setzt sie einen ENTRYPOINT. Sie müssen diese Datei aber noch erstellen, was wir als Nächstes tun werden.

      Erstellen Sie im Stammverzeichnis Ihres Projekts eine neue Datei namens docker-entrypoint.sh. Diese Datei wird ausgeführt, wenn Ihr Container lokal oder im Kubernetes Cluster ausgeführt wird. Außerdem wird Ihr Laravel-Anwendungscode vom Verzeichnis /var/www/tmp in /var/www/html kopiert, wo Apache ihn bereitstellen kann.

      • nano ./docker-entrypoint.sh

      Fügen Sie nun folgendes Skript hinzu:

      ./docker-entrypoint.sh

      #!/bin/bash
      
      cp -R /var/www/tmp/. /var/www/html/
      chown -R www-data:www-data /var/www/html
      
      exec "$@"
      

      Die abschließende Zeile exec "$@" weist das Shell an, jeden Befehl auszuführen, der als Nächstes als Eingabeargumenttext übergeben wurde. Dies ist wichtig, da Docker nach Ausführung dieses Skripts den Apache run-Befehl (apache2-foreground) weiter ausführen soll. Speichern und schließen Sie die Datei.

      Erstellen Sie als Nächstes im Stammverzeichnis Ihrer Anwendung eine Datei namens .dockerignore. Diese Datei sorgt dafür, dass Ihr Docker-Image beim Erstellen nicht mit Paketen oder Umgebungsdateien verschmutzt wird, die nicht hinein kopiert werden sollen:

      ./.dockerignore

      .env
      /vendor
      

      Speichern und schließen Sie die Datei.

      Die letzte Datei, die Sie erstellen müssen, bevor Sie Ihre Anwendung mit Docker Compose lokal ausführen können, ist eine docker-compose.yml-Datei. Bei der Konfiguration dieser YAML-Datei müssen Sie jedoch den APP_KEY eingeben, den Laravel bei der Installation generiert hat. Um ihn zu finden, öffnen und durchsuchen Sie die Datei . /.env oder führen die Sie die folgenden Befehle cat und grep aus:

      Sie werden eine Ausgabe wie diese sehen:

      Output

      APP_KEY=base64:0EHhVpgg ... UjGE=

      Kopieren Sie Ihren Schlüssel in die Zwischenablage. Vergewissern Sie sich, dass Sie das Präfix base64: einschließen. Erstellen Sie nun im Stammverzeichnis Ihrer Anwendung die Datei namens docker-compose.yml:

      • nano ./docker-compose.yml

      Hier werden wir das PHP-Image Ihrer Laravel-Anwendung sowie einen MySQL-Container für die Ausführung Ihrer Datenbank einschließen. Fügen Sie den folgenden Inhalt hinzu:

      ./docker-compose.yml

      version: '3.5'
      services:
        php:
          image: your_docker_hub_username/laravel-kubernetes:latest
          restart: always
          ports:
            - 8000:80
          environment:
            - APP_KEY="your_laravel_app_key"
            - APP_ENV=local
            - APP_DEBUG=true
            - DB_PORT=3306
            - DB_HOST=mysql
            - DB_DATABASE
            - DB_USERNAME
            - DB_PASSWORD
        mysql:
          image: mysql:5.7
          restart: always
          environment:
            - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
            - MYSQL_DATABASE=${DB_DATABASE}
            - MYSQL_USER=${DB_USERNAME}
            - MYSQL_PASSWORD=${DB_PASSWORD}
      

      Verwenden Sie die Variable APP_KEY, die Sie in Ihre Zwischenablage kopiert haben, für die Variable <^>your_laravel_app_key und Ihren Docker Hub-Benutzernamen für die Variable your_docker_hub_username<^>. Speichern und schließen Sie die Datei.

      Sie werden das erste Image lokal mit docker build erstellen. Das zweite Image ist das offizielle MySQL Docker-Image, das in Docker Hub verfügbar ist. Beide benötigen verschiedene Umgebungsvariablen, die Sie bei Ausführung der Container einschließen werden.

      Um das Docker-Image mit Ihrer Laravel-Anwendung zu erstellen, führen Sie folgenden Befehl aus. Ersetzen Sie your_docker_hub_username durch Ihren Benutzernamen oder den Benutzernamen Ihres Teams bei Docker Hub, wo dieses Image gespeichert werden soll:

      • docker build -t your_docker_hub_username/laravel-kubernetes:latest .

      Als Nächstes können Sie die beiden Container unter Verwendung von Docker Compose mit den erforderlichen Datenbankanmeldedaten ausführen:

      • DB_ROOT_PASSWORD=rootpassword DB_DATABASE=local_db DB_USERNAME=admin DB_PASSWORD=password docker-compose up -d

      Die hier verwendeten vier Umgebungsvariablen (DB_ROOT_PASSWORD, DB_DATABASE, DB_USERNAME, DB_PASSWORD) können bei Bedarf geändert werden; da Sie Ihre Anwendung jedoch nur vor Ort testen, müssen Sie sich noch nicht um ihre Sicherheit kümmern.

      Es kann bis zu 30 Sekunden dauern, bis Ihre MySQL-Datenbank initialisiert ist und die Container einsatzbereit sind. Sobald das der Fall ist, können Sie Ihre Laravel-Anwendung auf Ihrem Computer unter localhost:8000 anzeigen.

      Die Laravel-Anwendung, die mit Docker Compose lokal ausgeführt wird

      Ihre PHP-Anwendung wird sich mit Ihrer MySQL-Datenbank verbinden. Nach erfolgreicher Verbindungsherstellung wird unter dem Laravel-Logo der Text „Database Connected: localdb“ (Datenbank verbunden: localdb) angezeigt.

      Nachdem Sie Ihr Docker-Image mit Docker Compose lokal getestet haben, können Sie die Container mit docker-compose down nun herunterfahren:

      Im nächsten Abschnitt pushen Sie Ihr Docker-Image an Docker Hub, damit es Ihr Helm Chart nutzen kann, um die Anwendung in Ihrem Kubernetes-Cluster bereitzustellen.

      Schritt 3 — Pushen Ihres Docker-Image an Docker Hub

      Das LAMP Helm Chart, das Sie zur Bereitstellung Ihres Codes an Kubernetes verwenden werden, erfordert, dass Ihr Code in einer Container-Registry verfügbar ist. Zwar können Sie Ihr Image in eine private oder selbst gehostete Registry pushen, doch verwenden Sie in diesem Tutorial eine öffentlich verfügbare und kostenlose Docker-Registry in Docker Hub.

      Greifen Sie mit Ihrem Webbrowser auf Ihr Konto in Docker Hub zu und erstellen Sie dann ein neues Repository namens laravel-kubernetes.

      Erstellen eines neuen Repository in Docker Hub

      Wenn Sie von Ihrem lokalen Computer noch keine Verbindung zu Docker Hub hergestellt haben, müssen Sie sich bei Docker Hub anmelden. Sie können dies über die Befehlszeile tun:

      • docker login -u your_docker_hub_username

      Geben Sie Ihre Anmeldedaten ein, wenn Sie dazu aufgefordert werden. Dies muss normalerweise nur einmal pro Computer erfolgen, da Docker Ihre Anmeldedaten in Ihrem Stammverzeichnis in ~/.docker/config.json speichert.

      Abschließend pushen Sie Ihr Image an Docker Hub:

      • docker push your_docker_hub_username/laravel-kubernetes:latest

      Je nach Verbindungsgeschwindigkeit kann es einige Minuten dauern, bis Ihre Anwendung hochgeladen ist. Sobald Docker fertig ist, sehen Sie ein endgültiges Digest-Hash und die Größe Ihres Images im Terminal. Dies sollte ungefähr so aussehen:

      Output

      latest: digest: sha256:df4bdeda91484c8c26a989b13b8f27ab14d93ab2e676e3c396714cb3811c4086 size: 4918

      Nachdem Sie Ihre Laravel-Anwendung containerisiert und ein Image an Docker Hub gepusht haben, können Sie das Image nun in einer Helm Chart- oder Kubernetes-Bereitstellung verwenden. Im nächsten Schritt werden Sie basierend auf dem LAMP Helm Chart benutzerdefinierte Werte festlegen und die Anwendung in Ihrem DigitalOcean Kubernetes-Cluster bereitstellen.

      Schritt 4 — Konfigurieren und Bereitstellen der Anwendung mit dem LAMP Helm Chart

      Helm bietet eine Reihe von Charts, um Ihnen mit voreingestellten Kombinationen von Tools bei der Einrichtung von Kubernetes-Anwendungen zu helfen. Sie können zwar eigene Kubernetes-Dienstdateien schreiben, um eine eine ähnliche Bereitstellung zu erhalten, doch werden Sie in diesem Bereich sehen, warum die Verwendung eines Helm Chart die Konfiguration deutlich erleichtert.

      Zuerst benötigen Sie ein Verzeichnis, in dem alle Ihre Helm-Konfigurationsdateien gespeichert werden. Erstellen Sie im Stammverzeichnis Ihres Laravel-Projekts ein neues Verzeichnis namens helm/:

      Im Verzeichnis helm/ werden Sie zwei neue Dateien erstellen: values.yml und secrets.yml. Erstellen und öffnen Sie zunächst values.yml:

      Die Datei values.yml enthält nicht-geheime Konfigurationsoptionen, die die Standardwerte im LAMP Helm Chart überschreiben werden. Fügen Sie folgende Konfigurationen hinzu und stellen Sie sicher, your_docker_hub_username durch Ihren eigenen Benutzernamen zu ersetzen:

      ./helm/values.yml

      php:
        repository: "your_docker_hub_username/laravel-kubernetes"
        tag: "latest"
        fpmEnabled: false
        envVars:
          - name: APP_ENV
            value: production
          - name: APP_DEBUG
            value: false
          - name: DB_PORT
            value: 3306
          - name: DB_HOST
            value: localhost
      

      Speichern und schließen Sie die Datei.

      Erstellen Sie nun eine Datei namens secrets.yml:

      secrets.yml wird nicht in der Versionskontrolle geprüft. Sie enthält sensible Konfigurationsdaten wie Ihr Datenbankpasswort und den Laravel-App Key. Fügen Sie die folgenden Konfigurationen hinzu und nehmen Sie gegebenenfalls Anpassungen für Ihre Anmeldedaten vor:

      ./helm/secrets.yml

      mysql:
        rootPassword: "your_database_root_password"
        user: your_database_user
        password: "your_database_password"
        database: your_database_name
      
      php:
        envVars:
          - name: APP_KEY
            value: "your_laravel_app_key"
          - name: DB_DATABASE
            value: your_database_name
          - name: DB_USERNAME
            value: your_database_user
          - name: DB_PASSWORD
            value: "your_database_password"
      

      Verwenden Sie für Ihre Produktionsdatenbank starke Benutzername- und Passwortkombinationen und nutzen Sie den gleichen your_laravel_app_key wie oben; öffnen Sie alternativ ein neues Terminalfenster und generieren Sie einen neuen App Key, indem Sie folgenden Befehl ausführen. Dann können Sie den neuen Wert, den Laravel festlegt, in Ihre .env-Datei kopieren:

      • docker run --rm -v $(pwd):/app php:cli php /app/artisan key:generate

      Speichern und schließen Sie secrets.yml.

      Um zu verhindern, dass Ihre secrets.yml-Datei in das Docker-Image integriert oder in der Versionskontrolle gespeichert wird, sollten Sie als Nächstes sowohl der Datei .dockerignore als auch der Datei .gitignore die folgende Zeile hinzufügen. Öffnen und fügen Sie jeder Datei /helm/secrets.yml an oder führen Sie den folgenden Befehl aus, um beide hinzuzufügen:

      • echo '/helm/secrets.yml' >> ./.dockerignore && echo '/helm/secrets.yml' >> ./.gitignore

      Nachdem Sie Helm-Konfigurationsdateien für Ihre Anwendung und das Docker-Image erstellt haben, können Sie dieses Helm Chart nun als neue Version in Ihrem Kubernetes-Cluster installieren. Installieren Sie Ihr Chart im Stammverzeichnis Ihrer Anwendung:

      • helm install laravel-kubernetes -f helm/values.yml -f helm/secrets.yml stable/lamp

      Sie werden eine Ausgabe wie diese sehen:

      Output

      NAME: laravel-kubernetes LAST DEPLOYED: Mon May 18 13:21:20 2020 NAMESPACE: default STATUS: deployed REVISION: 1

      Ihre Anwendung wird eine oder zwei Minuten brauchen, bis sie verfügbar ist. Sie können jedoch folgenden Befehl ausführen, um die Kubernetes-Dienste in Ihrem Cluster zu überwachen:

      Suchen Sie nach dem Namen Ihrer Anwendung:

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) laravel-kubernetes-lamp LoadBalancer your_cluster_ip your_external_ip 80:32175/TCP,3306:32243/TCP

      Wenn Ihr neuer Dienst laravel-kubernetes-lamp unter EXTERNAL-IP eine IP-Adresse anzeigt, können Sie your_external_ip aufrufen, um die in Ihrem Kubernetes-Cluster ausgeführte Anwendung anzuzeigen. Ihre Anwendung wird sich mit Ihrer Datenbank verbinden und Sie werden den Namen der Datenbank unterhalb des Laravel-Logos sehen (genauso wie bei der lokalen Ausführung Ihrer Anwendung in Docker Compose).

      Die Laravel-Anwendung, die in Kubernetes mit dem LAMP Helm Chart ausgeführt wird

      Das Ausführen einer Webanwendung an einer ungesicherten IP-Adresse kann für einen Konzeptnachweis in Ordnung sein, Ihre Website ist jedoch ohne SSL-Zertifikat und einen benutzerdefinierten Domänennamen nicht bereit für die Produktion. Bevor Sie dies im nächsten Schritt einrichten, deinstallieren Sie Ihre Version über die Befehlszeile:

      • helm delete laravel-kubernetes

      Im nächsten Schritt werden Sie auf Grundlage dieser ersten Helm-Konfiguration Ihrer Laravel-Anwendung einen Ingress Controller, ein SSL-Zertifikat und eine benutzerdefinierte Domäne hinzuzufügen.

      Schritt 5 — Hinzufügen von Ingress Controller und SSL zu Ihrem Kubernetes Cluster

      Ein Ingress Controller ist in Kubernetes dafür verantwortlich, die Dienste Ihrer Anwendung im Internet zu verfügbar zu machen. Im vorherigen Schritt hat das LAMP Helm Chart einen DigitalOcean Load Balancer erstellt und Ihre Anwendung direkt über die IP-Adresse des Load Balancer verfügbar gemacht.

      Sie könnten SSL und Ihren Domänennamen direkt im Load Balancer terminieren; da Sie jedoch in Kubernetes arbeiten, kann es praktischer sein, alles an einem Ort zu verwalten. Deutlich ausführlichere Informationen zu Ingress Controllern und Details zu den folgenden Schritten finden Sie unter Verwenden eines Nginx Ingress in DigitalOcean Kubernetes mit Helm.

      Das LAMP Helm Chart enthält eine Konfigurationsoption zur Unterstützung von Ingress. Öffnen Sie die Datei helm/values.yml:

      Fügen Sie jetzt die folgenden Zeilen hinzu:

      ./helm/values.yml

      ...
      # Use Ingress Controller
      service:
        type: ClusterIP
        HTTPPort: 80
      ingress:
        enabled: true
        domain: your_domain
      

      Dadurch wird Ihre Bereitstellung angewiesen, keinen Load Balancer zu installieren und die Anwendung stattdessen an Port 80 des Kubernetes-Clusters verfügbar zu machen, wo der Ingress Controller sie im Internet verfügbar macht. Speichern und schließen Sie values.yml.

      Führen Sie nun den Befehl helm install aus, den Sie zuvor ausgeführt haben, damit Ihre Laravel-Anwendung wieder ausgeführt wird. Stellen Sie sicher, dass Sie den Befehl aus dem Stammverzeichnis Ihrer Anwendung ausführen:

      • helm install laravel-kubernetes -f helm/values.yml -f helm/secrets.yml stable/lamp

      Installieren Sie als Nächstes den Controller nginx-ingress in Ihrem Kubernetes-Cluster mit dem von Kubernetes verwalteten Nginx Ingress Controller:

      • helm install nginx-ingress stable/nginx-ingress --set controller.publishService.enabled=true

      Nach der Installation werden Sie eine Ausgabe wie diese sehen:

      Output

      NAME: nginx-ingress LAST DEPLOYED: Mon May 18 13:28:34 2020 NAMESPACE: default STATUS: deployed REVISION: 1

      Außerdem benötigen Sie eine Ingress-Ressource, um die Bereitstellung Ihrer Laravel-Anwendung verfügbar zu machen. Erstellen Sie im Stammverzeichnis Ihrer Anwendung eine neue Datei namens ingress.yml:

      Diese Datei legt den Host, den SSL-Zertifikatmanager und den Backend-Dienst und Port-Namen der Anwendung fest. Fügen Sie die folgenden Konfigurationen hinzu, wobei Sie your_domain durch die Domäne Ihrer Wahl ersetzen:

      ./ingress.yml

      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata:
        name: laravel-kubernetes-ingress
        annotations:
          kubernetes.io/ingress.class: nginx
          cert-manager.io/cluster-issuer: letsencrypt-prod
      spec:
        tls:
          - hosts:
              - your_domain
            secretName: laravel-kubernetes-tls
        rules:
          - host: your_domain
            http:
              paths:
                - backend:
                    serviceName: laravel-kubernetes-lamp
                    servicePort: 80
      

      Speichern und schließen Sie die Datei.

      Als Nächstes sollten Sie Cert-Manager installieren und einen Aussteller erstellen, mit dem Sie mit Let’s Encrypt SSL-Zertifikate für die Produktion erzeugen können. Cert-Manager erfordert benutzerdefinierte Ressourcendefinitionen, die Sie aus dem Cert-Manager-Repository über die Befehlszeile anwenden können:

      • kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.15.0/cert-manager.crds.yaml

      Dadurch wird eine Reihe von Kubernetes-Ressourcen erstellt, die in der Befehlszeile angezeigt werden:

      Output

      customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io create

      Außerdem benötigt Cert-Manager einen Namespace zur Isolation in Ihrem Kubernetes-Cluster:

      • kubectl create namespace cert-manager

      Sie sehen diese Ausgabe:

      Output

      namespace/cert-manager created

      Da Cert-Manager von Jetstack keines der von Kubernetes verwalteten Charts ist, müssen Sie auch das Jetstack Helm-Repository hinzufügen. Führen Sie folgenden Befehl aus, um es in Helm verfügbar zu machen:

      • helm repo add jetstack https://charts.jetstack.io

      Bei erfolgreicher Ergänzung erhalten Sie folgende Ausgabe:

      Output

      "jetstack" has been added to your repositories

      Jetzt können Sie Cert-Manager in Ihrem Kubernetes-Cluster im Namespace cert-manager installieren:

      • helm install cert-manager --version v0.15.0 --namespace cert-manager jetstack/cert-manager

      Nach Abschluss sehen Sie eine Zusammenfassung der Bereitstellung, die in etwa wie folgt aussieht:

      Output

      NAME: cert-manager LAST DEPLOYED: Mon May 18 13:32:08 2020 NAMESPACE: cert-manager STATUS: deployed REVISION: 1

      Die letzte Datei, die Sie dem Stammverzeichnis Ihrer Laravel-Anwendung hinzufügen müssen, ist eine Kubernetes-Konfigurationsdatei namens production_issuer.yml. Erstellen Sie die Datei:

      • nano ./production_issuer.yml

      Fügen Sie nun Folgendes hinzu:

      apiVersion: cert-manager.io/v1alpha2
      kind: ClusterIssuer
      metadata:
        name: letsencrypt-prod
      spec:
        acme:
          # Email address used for ACME registration
          email: your_email_address
          server: https://acme-v02.api.letsencrypt.org/directory
          privateKeySecretRef:
            # Name of a secret used to store the ACME account private key
            name: letsencrypt-prod-private-key
          # Add a single challenge solver, HTTP01 using nginx
          solvers:
            - http01:
                ingress:
                  class: nginx
      

      Speichern und schließen Sie die Datei.

      Let’s Encrypt sendet an your_email_address sämtliche wichtigen Hinweise und Warnungen zum Ablauf von Zertifikaten; darum sollten Sie eine Adresse hinzufügen, die Sie regelmäßig prüfen. Speichern Sie diese Datei und erstellen Sie eine neue Ressource sowohl für Ihre Ingress-Ressource als auch den Produktionsaussteller in Ihrem Kubernetes-Cluster:

      • kubectl create -f ingress.yml
      • kubectl create -f production_issuer.yml

      Aktualisieren Sie schließlich die DNS-Einträge Ihres Domänennamens so, dass ein A-Eintrag auf die IP-Adresse Ihres Load Balancer verweist. Um nach der IP-Adresse Ihres Ingress Controller zu suchen, geben Sie Folgendes ein:

      • kubectl get service nginx-ingress-controller

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-controller LoadBalancer your_cluster_ip your_external_ip 80:30187/TCP,443:31468/TCP 6m10s

      Verwenden Sie die Adresse your_external_ip als IP-Adresse für Ihren DNS A-Eintrag. Das Verfahren zur Aktualisierung Ihrer DNS-Einträge variiert, je nachdem wo Sie Ihre Domänennamen und das DNS-Hosting verwalten. Wenn Sie DigitalOcean verwenden, können Sie jedoch unseren Leitfaden zum Verwalten von DNS-Einträgen konsultieren.

      Sobald Ihre DNS-Einträge aktualisiert und das SSL-Zertifikat generiert wurden, wird Ihre Anwendung in your_domain verfügbar und SSL aktiviert.

      Die Laravel-Anwendung mit SSL-Terminierung und einem benutzerdefinierten Domänennamen

      Zwar sind Ihre PHP-Anwendung und Ihre Datenbank bereits miteinander verbunden, doch müssen Sie noch Datenbankmigrationen ausführen. Im letzten Schritt erfahren Sie, wie Sie Artisan-Befehle in Ihrem Kubernetes-Pod ausführen können, um Datenbankmigrationen und andere häufige Wartungsaufgaben durchzuführen.

      Schritt 6 — Ausführen von Remotebefehlen

      Zwar wird Ihre Laravel-Anwendung ausgeführt und ist mit der MySQL-Datenbank in Kubernetes verbunden, doch gibt es mehrere gängige Aufgaben, die Sie in einer neuen Laravel-Installation erledigen sollten. Eine gängige Aufgabe, die Sie ausführen sollten, sind Datenbankmigrationen.

      Bevor Sie in Ihrer Laravel-Anwendung einen Artisan-Befehl ausführen können, müssen Sie den Namen des Pods kennen, das Ihren Laravel-Anwendungscontainer ausführt. Mit der Befehlszeile können Sie alle Pods in Ihrem Kubernetes-Cluster anzeigen:

      Sie werden eine Ausgabe wie diese sehen:

      Output

      NAME READY STATUS RESTARTS AGE laravel-kubernetes-lamp-77fb989b46-wczgb 2/2 Running 0 16m

      Wählen Sie das Pod für Ihre laravel-kubernetes-lamp-...-Bereitstellung aus. Stellen Sie sicher, dass Sie den Namen in Ihrer Ausgabe verwenden und nicht den oben aufgeführten Namen. Jetzt können Sie kubectl exec dafür ausführen. Beispielsweise führen Sie eine Datenbankmigration mit dem Befehl artisan migrate aus. Sie fügen das Flag --force hinzu, da Sie das Pod in der Produktion ausführen:

      • kubectl exec laravel-kubernetes-lamp-77fb989b46-wczgb -- php artisan migrate --force

      Dieser Befehl wird eine Ausgabe erzeugen:

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.16 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.05 seconds)

      Sie haben Laravel 7 und MySQL nun erfolgreich in Kubernetes bereitgestellt und eine wichtige Aufgabe zur Datenbankwartung durchgeführt.

      Zusammenfassung

      In diesem Tutorial haben Sie gelernt, wie Sie eine Laravel PHP-Anwendung containerisieren, mit einer MySQL-Datenbank verbinden, ein Docker-Image mit Ihrem Code an Docker Hub pushen und dann ein Helm Chart nutzen, um das Image in einem DigitalOcean Kubernetes-Cluster bereitzustellen. Schließlich haben Sie SSL und einen benutzerdefinierten Domänennamen hinzugefügt und erfahren, wie Sie in Ihren laufenden Pods Befehlszeilentools ausführen.

      Kubernetes and Helm bieten Ihnen eine Reihe von Vorteilen gegenüber dem herkömmlichen LAMP-Stack-Hosting: Skalierbarkeit, die Fähigkeit, Dienste ohne direkte Anmeldung bei Ihrem Server auszutauschen, Tools zur Durchführung von rollierenden Upgrades und Kontrolle über Ihre Hostingumgebung. Es muss jedoch gesagt werden, dass die Komplexität der anfänglichen Containerisierung und Konfiguration Ihrer Anwendung am Anfang eine relativ hohe Barriere darstellt. Mit diesem Leitfaden als Ausgangspunkt wird die Bereitstellung von Laravel in Kubernetes jedoch verständlicher. Vielleicht wollen Sie nun mehr über die Vorzüge von Laravel oder das Hinzufügen von Überwachungstools (wie Linkerd) zu Kubernetes zu erfahren (manuell installierbar mit unserem Leitfaden oder mit einem DigitalOcean 1-Click).



      Source link

      Comment déployer Laravel 7 et MySQL sur Kubernetes en utilisant Helm


      L’auteur a choisi le Diversity in Tech Fund​​​​​ pour recevoir un don dans le cadre du programme Write for DOnations.

      Introduction

      Laravel est l’une des infrastructures d’application PHP les plus populaires aujourd’hui. Son déploiement se fait généralement avec une base de données MySQL, mais il peut être configuré pour utiliser une variété d’options de stockage de données de backend. Laravel est fier de profiter des nombreuses fonctionnalités modernes de PHP et de son vaste écosystème complet de package.

      Kubernetes est une plate-forme d’orchestration de conteneurs qui peut être hébergée sur des DigitalOcean Kubernetes clusters afin de simplifier la gestion et la configuration de conteneurs en production. Helm est un gestionnaire de packages Kubernetes qui facilite la configuration et l’installation des services et des pods sur Kubernetes.

      Dans ce guide, vous allez créer une application Laravel PHP, développer votre application dans une image Docker et déployer cette image dans un cluster DigitalOcean Kubernetes en utilisant le LAMP Helm chart​​​.​​ Ensuite, vous configurerez un contrôleur d’entrée pour ajouter SSL et un nom de domaine personnalisé à votre application. Une fois terminé, vous disposerez d’une application Laravel fonctionnelle connectée à une base de données MySQL qui s’exécute sur un cluster Kubernetes.

      Conditions préalables

      • Docker installé sur la machine à partir de laquelle vous accédez à votre cluster. Vous pouvez trouver des instructions détaillées sur l’installation de Docker pour la plupart des distributions Linux ici ou sur le site web de Docker pour d’autres systèmes d’exploitation.
      • Un compte sur Docker Hub pour stocker les images Docker que vous allez créer pendant ce tutoriel.
      • Un cluster DigitalOcean Kubernetes 1.17+ avec votre connexion configurée sur kubectl par défaut. Pour apprendre à créer un cluster Kubernetes sur DigitalOcean, voir notre Kubernetes Quickstart. Pour apprendre à se connecter au cluster, consultez Comment se connecter à un cluster DigitalOcean Kubernetes.
      • Le gestionnaire de paquets Helm 3 installé sur votre machine locale. Exécutez la première étape et ajoutez le référentiel stable à partir de la deuxième étape du tutoriel Comment installer un logiciel sur des clusters Kubernetes avec le Helm 3 Package Manager.
      • Un nom de domaine entièrement enregistré avec un enregistrement A disponible. Ce tutoriel utilisera your_domain. Vous pouvez acheter un nom de domaine sur Namecheap, en obtenir un gratuitement sur Freenom, ou utiliser le bureau d’enregistrement de domaine de votre choix. Pour le moment, ne vous souciez pas d’associer l’enregistrement A de votre domaine à un IP. Une fois que vous serez à l’étape 5 et que votre contrôleur Ingress est opérationnel, vous connecterez alors your_domain à l’IP qui convient.

      Étape 1 — Création d’une nouvelle application Laravel

      Au cours de cette étape, vous utiliserez Docker pour créer une nouvelle application Laravel 7. Cependant, vous devriez pouvoir suivre le même processus avec une application Laravel existante qui utilise MySQL comme base de données de sauvegarde. La nouvelle application que vous créez vérifiera que Laravel est bien connecté à la base de données et affichera le nom de la base de données.

      Tout d’abord, allez dans votre répertoire principal. Ensuite, créez une nouvelle application Laravel à l’aide d’un conteneur Docker composer :

      • cd ~
      • docker run --rm -v $(pwd):/app composer create-project --prefer-dist laravel/laravel laravel-kubernetes

      Une fois le conteneur créé et tous les paquets Composer installés, vous devriez voir une nouvelle installation de Laravel dans votre répertoire actuel sous le nom de laravel-kubernetes/. Allez dans ce dossier :

      Vous exécuterez le reste des commandes de ce tutoriel à partir de là.

      Cette application a pour rôle de tester votre connexion à la base de données et d’afficher son nom dans votre navigateur. Pour tester la connexion à la base de données, ouvrez le fichier ./resources/views/welcome.blade.php dans un éditeur de texte :

      • nano ./resources/views/welcome.blade.php

      Trouvez la section <div class="links">...</div> et remplacez son contenu par ce qui suit :

      ./resources/views/welcome.blade.php

      ...
      <div class="links">
         <strong>Database Connected: </strong>
          @php
              try {
                  DB::connection()->getPDO();
                  echo DB::connection()->getDatabaseName();
                  } catch (Exception $e) {
                  echo 'None';
              }
          @endphp
      </div>
      ...
      

      Enregistrez et fermez le fichier.

      Voilà l’intégralité de la personnalisation que vous devez apporter à l’application Laravel par défaut dans le cadre de ce tutoriel. Une fois terminé, ce bref extrait de PHP testera votre connexion à la base de données et affichera le nom de la base de données sur l’écran de démarrage de Laravel dans votre navigateur web.

      À l’étape suivante, vous utiliserez Docker pour créer une image contenant cette application Laravel et Docker Compose afin de tester son exécution locale et sa connexion à une base de données MySQL.

      Étape 2 — Conteneurisation de votre application Laravel

      Maintenant que vous avez créé une nouvelle application Laravel, vous devez créer votre code sur une image Docker, puis tester l’image avec Docker Compose. Bien que ce tutoriel ait pour objectif de vous apprendre à déployer votre application sur un cluster Kubernetes, Docker Compose est un moyen pratique de tester votre image et votre configuration Docker localement avant de l’exécuter dans le cloud. Cette boucle de rétroaction rapide peut s’avérer très utile pour effectuer et tester de petits changements.

      Tout d’abord, en utilisant nano ou votre éditeur de texte préféré, créez un fichier à la racine de votre application Laravel que vous appelerez Dockerfile :

      Ajoutez le contenu suivant. Docker utilisera ce fichier pour créer votre code dans une image :

      ./Dockerfile

      FROM php:7.4-apache
      
      # Install packages
      RUN apt-get update && apt-get install -y 
          git 
          zip 
          curl 
          sudo 
          unzip 
          libicu-dev 
          libbz2-dev 
          libpng-dev 
          libjpeg-dev 
          libmcrypt-dev 
          libreadline-dev 
          libfreetype6-dev 
          g++
      
      # Apache configuration
      ENV APACHE_DOCUMENT_ROOT=/var/www/html/public
      RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
      RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf
      RUN a2enmod rewrite headers
      
      # Common PHP Extensions
      RUN docker-php-ext-install 
          bz2 
          intl 
          iconv 
          bcmath 
          opcache 
          calendar 
          pdo_mysql
      
      # Ensure PHP logs are captured by the container
      ENV LOG_CHANNEL=stderr
      
      # Set a volume mount point for your code
      VOLUME /var/www/html
      
      # Copy code and run composer
      COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
      COPY . /var/www/tmp
      RUN cd /var/www/tmp && composer install --no-dev
      
      # Ensure the entrypoint file can be run
      RUN chmod +x /var/www/tmp/docker-entrypoint.sh
      ENTRYPOINT ["/var/www/tmp/docker-entrypoint.sh"]
      
      # The default apache run command
      CMD ["apache2-foreground"]
      

      Enregistrez et fermez le fichier.

      Ce Dockerfile commence avec le PHP 7.4 Apache Docker Image que se trouve sur Docker Hub, puis installe plusieurs des paquets Linux qui sont généralement nécessaires aux applications Laravel. Ensuite, il crée des fichiers de configuration Apache et active les réécritures d’en-tête. Le Dockerfile installe plusieurs extensions PHP communes et ajoute une variable d’environnement afin que les journaux de Laravel soient bien acheminés vers le conteneur via stderr. Cela vous permettra de consulter les journaux Laravel en personnalisant vos journaux Docker Compose ou Kubernetes.

      Enfin, le Dockerfile copie tous les codes de votre application Laravel sur /var/www/tmp et installe les dépendances Composer. Il définit ensuite un ENTRYPOINT, mais vous aurez besoin de créer ce fichier, ce que nous allons faire ensuite.

      Dans le répertoire racine de votre projet, créez un nouveau fichier que vous appellerez docker-entrypoint.sh. Ce fichier s’exécutera lorsque votre conteneur sera exécuté localement ou dans le cluster Kubernetes. Il copiera ensuite votre code d’application Laravel du répertoire /var/www/tmp dans /var/www/html où Apache sera capable de le servir.

      • nano ./docker-entrypoint.sh

      Maintenant, ajoutez le script suivant :

      ./docker-entrypoint.sh

      #!/bin/bash
      
      cp -R /var/www/tmp/. /var/www/html/
      chown -R www-data:www-data /var/www/html
      
      exec "$@"
      

      La ligne finale, exec "$@" indique au shell d’exécuter toute commande ensuite passée à titre d’argument de l’entrée. Ceci est important car Docker doit continuer à exécuter la commande d’exécution d’Apache (apache2-foreground) une fois ce script exécuté. Enregistrez et fermez le fichier.

      Ensuite, créez un fichier .dockerignore dans le répertoire racine de votre application. Lors de la création de votre image Docker, ce fichier veillera à ce qu’elle ne soit pas polluée par des paquets ou des fichiers d’environnement qui ne devraient pas y être copiés :

      ./.dockerignore

      .env
      /vendor
      

      Enregistrez et fermez le fichier.

      Avant de pouvoir exécuter votre application localement avec Docker Compose, vous devez créer un dernier fichier nommé docker-compose.yml. Mais, lors de la configuration de ce fichier YAML, vous devez saisir la APP_KEY générée par Laravel lors de l’installation. Trouvez-la en ouvrant et en faisant une recherche dans le fichier . /.env ou en exécutant les commandes chat et grep suivantes :

      Vous verrez un résultat similaire à ce qui suit :

      Output

      APP_KEY=base64:0EHhVpgg ... UjGE=

      Copiez votre clé dans votre presse-papiers. Veillez à bien inclure le préfixe base64: Maintenant, créez le fichier docker-compose.yml dans le répertoire racine de votre application :

      • nano ./docker-compose.yml

      Ici, nous allons inclure l’image PHP de votre application Laravel ainsi qu’un conteneur MySQL pour exécuter votre base de données. Ajoutez le contenu suivant :

      ./docker-compose.yml

      version: '3.5'
      services:
        php:
          image: your_docker_hub_username/laravel-kubernetes:latest
          restart: always
          ports:
            - 8000:80
          environment:
            - APP_KEY="your_laravel_app_key"
            - APP_ENV=local
            - APP_DEBUG=true
            - DB_PORT=3306
            - DB_HOST=mysql
            - DB_DATABASE
            - DB_USERNAME
            - DB_PASSWORD
        mysql:
          image: mysql:5.7
          restart: always
          environment:
            - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
            - MYSQL_DATABASE=${DB_DATABASE}
            - MYSQL_USER=${DB_USERNAME}
            - MYSQL_PASSWORD=${DB_PASSWORD}
      

      Utilisez la variable APP_KEY que vous avez copiée dans votre presse-papiers pour la variable your_laravel_app_key et utilisez votre nom d’utilisateur Docker Hub pour la variable your_docker_hub_username. Enregistrez et fermez le fichier.

      Vous allez créer la première image localement en utilisant docker build. La deuxième image est l’image officielle de MySQL Docker, disponible sur Docker Hub. Toutes deux nécessitent plusieurs variables d’environnement que vous allez inclure lors de l’exécution des conteneurs.

      Pour créer l’image Docker qui contient votre application Laravel, exécutez la commande suivante. Veillez à bien remplacer your_docker_hub_username par votre nom d’utilisateur ou le nom d’utilisateur de votre équipe dans Docker Hub où cette image sera sauvegardée :

      • docker build -t your_docker_hub_username/laravel-kubernetes:latest .

      Ensuite, vous pouvez exécuter les deux conteneurs avec Docker Compose et les identifiants de base de données nécessaires :

      • DB_ROOT_PASSWORD=rootpassword DB_DATABASE=local_db DB_USERNAME=admin DB_PASSWORD=password docker-compose up -d

      Au besoin, vous pouvez modifier les quatre variables d’environnement utilisées ici (DB_ROOT_PASSWORD, DB_DATABASE, DB_USERNAME, DB_PASSWORD). Cependant, étant donné vous testez votre application que localement, inutile de les sécuriser pour le moment.

      Il vous faudra près de 30 secondes pour que votre base de données MySQL soit initialisée et que vos conteneurs soient prêts. Une fois que cela est fait, vous pouvez consulter votre application Laravel sur votre machine sur localhost:8000.

      Exécution locale de l'application Laravel avec Docker Compose

      Votre application PHP se connectera à votre base de données MySQL. Une fois connecté, vous verrez apparaître le texte « Database Connected: local_db » apparaître sous le logo Laravel.

      Maintenant que vous avez testé votre image Docker localement avec Docker Compose, vous pouvez arrêter les conteneurs en exécutant docker-compose down :

      Dans la section suivante, vous allez pousser votre image Docker sur Docker Hub afin que votre chart Helm puisse l’utiliser et déployer votre application dans votre cluster Kubernetes.

      Étape 3 — Poussez votre image Docker dans Docker Hub

      Votre code doit être disponible dans un registre de conteneurs pour que le chart Helm LAMP que vous utiliserez puisse le déployer sur Kubernetes. Bien que vous puissiez pousser votre image dans un registre privé ou autohébergé, aux fins de ce tutoriel, vous utiliserez un registre Docker public et gratuit sur Docker Hub.

      Accédez à votre compte dans Docker Hub en utilisant votre navigateur web. Créez ensuite un nouveau référentiel nommé laravel-kubernetes.

      Création d'un nouveau référentiel dans Docker Hub

      Si vous n’êtes pas connecté à Docker Hub depuis votre machine locale, vous devez ensuite vous y connecter. Vous pouvez le faire grâce à la ligne de commande suivante :

      • docker login -u your_docker_hub_username

      Saisissez vos identifiants de connexion lorsque vous serez invité à le faire. Il est généralement nécessaire de le faire qu’une seule fois par machine. En effet, Docker enregistrera vos identifiants dans ~/.docker/config.json​​​ dans votre répertoire personnel.

      Enfin, poussez votre image dans Docker Hub :

      • docker push your_docker_hub_username/laravel-kubernetes:latest

      En fonction de la vitesse de votre connexion, le téléchargement de votre application peut prendre quelques minutes. Cependant, une fois Docker terminé, vous verrez un hachage cryptographique et la taille de votre image dans le terminal. Elle ressemblera à cela :

      Output

      latest: digest: sha256:df4bdeda91484c8c26a989b13b8f27ab14d93ab2e676e3c396714cb3811c4086 size: 4918

      Maintenant que votre application Laravel est conteneurisée et que vous avez poussé une image dans Docker Hub, vous pouvez utiliser l’image dans un déploiement de chart Helm ou Kubernetes. Au cours de la prochaine étape, vous allez configurer des valeurs personnalisées en fonction du chart LAMP Helm et le déployer dans votre cluster DigitalOcean Kubernetes.

      Étape 4 — Configuration et déploiement de l’application avec chart LAMP Helm

      Helm propose un certain nombre de Charts pour vous aider à configurer des applications Kubernetes en utilisant des combinaisons d’outils prédéfinies. Même si vous pouvez écrire vos propres fichiers de service Kubernetes pour effectuer un déploiement similaire, dans cette section vous verrez que l’utilisation d’un chart Helm nécessite beaucoup moins de configuration.

      Tout d’abord, vous aurez besoin d’un répertoire pour y stocker tous vos fichiers de configuration Helm. Créez un nouveau répertoire dans la racine de votre projet Laravel que vous nommerez helm/ :

      Dans le répertoire helm/, vous allez créer deux nouveaux fichiers : values.yml et secrets.yml. Commencez par créer et ouvrir values.yml :

      Le fichier values.yml comprendra des options de configuration non secrètes qui remplaceront les valeurs par défaut dans le chart LAMP Helm. Ajoutez les configurations suivantes, tout en veillant bien à remplacer your_docker_hub_username par votre nom d’utilisateur :

      ./helm/values.yml

      php:
        repository: "your_docker_hub_username/laravel-kubernetes"
        tag: "latest"
        fpmEnabled: false
        envVars:
          - name: APP_ENV
            value: production
          - name: APP_DEBUG
            value: false
          - name: DB_PORT
            value: 3306
          - name: DB_HOST
            value: localhost
      

      Enregistrez et fermez le fichier.

      Maintenant, créez un fichier secrets.yml :

      secrets.yml ne sera pas archivé dans le contrôle de version. Il contiendra des informations de configuration sensibles comme votre mot de passe et votre clé d’app Laravel. Ajoutez les configurations suivantes, en les ajustant au besoin pour qu’elles soient adaptées à vos identifiants :

      ./helm/secrets.yml

      mysql:
        rootPassword: "your_database_root_password"
        user: your_database_user
        password: "your_database_password"
        database: your_database_name
      
      php:
        envVars:
          - name: APP_KEY
            value: "your_laravel_app_key"
          - name: DB_DATABASE
            value: your_database_name
          - name: DB_USERNAME
            value: your_database_user
          - name: DB_PASSWORD
            value: "your_database_password"
      

      Veillez à utiliser des combinaisons de noms d’utilisateur et de mot de passe difficiles à trouver pour votre base de données de production. Utilisez la même your_laravel_app_key que celle indiquée ci-dessus. Sinon, ouvrez une nouvelle fenêtre et générez un nouveau fichier en exécutant la commande suivante. Vous pouvez ensuite copier la nouvelle valeur configurée par Laravel dans votre fichier .env :

      • docker run --rm -v $(pwd):/app php:cli php /app/artisan key:generate

      Sauvegardez et fermez secrets.yml​​​​.

      Ensuite, afin d’empêcher votre fichier secrets.yml d’être intégré à l’image Docker ou d’être sauvegardé dans le contrôle de version, veillez à bien ajouter la ligne suivante à la fois dans vos fichiers .dockerignore et .gitignore. Ouvrez et ajoutez /helm/secrets.yml dans chaque fichier, ou exécutez la commande suivante pour ajouter les deux :

      • echo '/helm/secrets.yml' >> ./.dockerignore && echo '/helm/secrets.yml' >> ./.gitignore

      Maintenant que vous avez créé les fichiers de configuration Helm pour votre application et l’image Docker, vous pouvez installer ce chart Helm comme une nouvelle version dans votre cluster Kubernetes. Installez votre chart dans le répertoire racine de votre application :

      • helm install laravel-kubernetes -f helm/values.yml -f helm/secrets.yml stable/lamp

      Vous verrez un résultat similaire à ce qui suit :

      Output

      NAME: laravel-kubernetes LAST DEPLOYED: Mon May 18 13:21:20 2020 NAMESPACE: default STATUS: deployed REVISION: 1

      Il faudra une à deux minutes pour que votre application soit disponible. Cependant, vous pouvez exécuter cette commande pour surveiller les services Kubernetes dans votre cluster :

      Recherchez le nom de votre application :

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) laravel-kubernetes-lamp LoadBalancer your_cluster_ip your_external_ip 80:32175/TCP,3306:32243/TCP

      Lorsque votre nouveau service laravel-kubernetes-lamp affiche une adresse IP sous EXTERNAL-IP, vous pouvez consulter your_external_ip pour voir l’application qui est exécutée dans votre cluster Kubernetes. Votre application se connectera à votre base de données. Vous verrez alors le nom de la base de données apparaître sous le logo Laravel, comme ce fut le cas lors de l’exécution locale de votre application dans Docker Compose.

      Exécution de l'application Laravel sous Kubernetes en utilisant le chart LAMP Helm

      L’exécution d’une application web sur une adresse IP non sécurisée est adaptée pour une démonstration de faisabilité. Cependant, votre site web n’est pas prêt à être publié sans certificat SSL et un nom de domaine personnalisé. Avant que vous configuriez cela à l’étape suivante, désinstallez votre version via la ligne de commande suivante :

      • helm delete laravel-kubernetes

      Au cours de la prochaine étape, vous allez étendre cette première configuration Helm pour ajouter un contrôleur Ingress, un certificat SSL et un domaine personnalisé à votre application Laravel.

      Étape 5 — Ajout d’un contrôleur Ingress et SSL à votre cluster Kubernetes

      Dans Kubernetes, un contrôleur Ingress est chargé d’exposer les services de votre application sur Internet. À l’étape précédente, le chart LAMP Helm a créé un équilibreur de charge DigitalOcean et a exposé votre application directement via l’adresse IP de l’équilibreur de charge.

      Vous pourriez résilier SSL et votre nom de domaine directement sur l’équilibreur de charge. Cependant, étant donné que vous travaillez dans Kubernetes, il serait plus pratique de gérer celà au même endroit. Pour plus d’informations sur les contrôleurs Ingress et des détails sur les étapes suivantes, consultez Comment configurer un Ingress Nginx sur DigitalOcean Kubernetes en utilisant Helm.

      Le chart LAMP Helm intègre une option de configuration pour prendre en charge Ingress. Ouvrez votre fichier helm/values.yml :

      Maintenant, ajoutez les lignes suivantes :

      ./helm/values.yml

      ...
      # Use Ingress Controller
      service:
        type: ClusterIP
        HTTPPort: 80
      ingress:
        enabled: true
        domain: your_domain
      

      Cela indique à votre déploiement de ne pas installer d’équilibreur de charge et d’exposer l’application dans le port 80 du cluster Kubernetes où le contrôleur Ingress l’exposera sur Internet. Sauvegardez et fermez values.yml​​​​.

      Maintenant, exécutez la commande helm install que vous avez exécutée précédemment pour que votre application Laravel s’exécute à nouveau. Veillez à exécuter la commande à partir du répertoire racine de votre application :

      • helm install laravel-kubernetes -f helm/values.yml -f helm/secrets.yml stable/lamp

      Ensuite, installez le contrôleur nginx-ingress sur votre cluster Kubernetes en utilisant le contrôleur Nginx Ingress maintenu sous Kubernetes :

      • helm install nginx-ingress stable/nginx-ingress --set controller.publishService.enabled=true

      Après l’installation, vous aurez un résultat similaire à ce qui suit :

      Output

      NAME: nginx-ingress LAST DEPLOYED: Mon May 18 13:28:34 2020 NAMESPACE: default STATUS: deployed REVISION: 1

      Vous avez également besoin d’une Ressource Ingress pour exposer le déploiement de votre application Laravel. Créez un nouveau fichier dans le répertoire racine de votre application que vous nommerez ingress.yml :

      Ce fichier définit l’hôte de votre application, le gestionnaire de certificat SSL, le service de backend et le nom de port de votre application. Ajoutez les configurations suivantes en remplacant your_domain avec le domaine de votre choix :

      ./ingress.yml

      apiVersion: networking.k8s.io/v1beta1
      kind: Ingress
      metadata:
        name: laravel-kubernetes-ingress
        annotations:
          kubernetes.io/ingress.class: nginx
          cert-manager.io/cluster-issuer: letsencrypt-prod
      spec:
        tls:
          - hosts:
              - your_domain
            secretName: laravel-kubernetes-tls
        rules:
          - host: your_domain
            http:
              paths:
                - backend:
                    serviceName: laravel-kubernetes-lamp
                    servicePort: 80
      

      Enregistrez et fermez le fichier.

      Ensuite, vous deviez installer Cert-Manager et créer un émetteur qui vous permettra de créer des certificats SSL de production en utilisant Let’s Encrypt. Cert-Manager nécessite des Custom Resource Definitions​​​ que vous pouvez appliquer à partir du Cert-Manager repository​​​ en utilisant la ligne de commande suivante :

      • kubectl apply --validate=false -f https://github.com/jetstack/cert-manager/releases/download/v0.15.0/cert-manager.crds.yaml

      Cela créera un certain nombre de ressources Kubernetes qui s’afficheront dans la ligne de commande :

      Output

      customresourcedefinition.apiextensions.k8s.io/certificaterequests.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/certificates.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/challenges.acme.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/clusterissuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/issuers.cert-manager.io created customresourcedefinition.apiextensions.k8s.io/orders.acme.cert-manager.io create

      Cert-Manager a également besoin d’un namespace pour l’isoler dans votre cluster Kubernetes :

      • kubectl create namespace cert-manager

      Vous verrez ce résultat :

      Output

      namespace/cert-manager created

      Étant donné que le Cert-Manager de Jetstack ne fait pas partie des charts maintenus par Kubernetes, vous aurez également besoin d’ajouter le référentiel Helm Jetstack. Exécutez la commande suivante pour le rendre disponible dans Helm :

      • helm repo add jetstack https://charts.jetstack.io

      Si l’ajout est correctement effectué, vous obtiendrez le résultat suivant :

      Output

      "jetstack" has been added to your repositories

      Maintenant, vous êtes prêt à installer Cert-Manager dans l’espace de nommage cert-manager​​​ de votre cluster Kubernetes :

      • helm install cert-manager --version v0.15.0 --namespace cert-manager jetstack/cert-manager

      Une fois terminé, vous verrez apparaître un résumé du déploiement similaire à ce qui suit :

      Output

      NAME: cert-manager LAST DEPLOYED: Mon May 18 13:32:08 2020 NAMESPACE: cert-manager STATUS: deployed REVISION: 1

      Le dernier fichier que vous devez ajouter dans le répertoire racine de votre application Laravel est un fichier de configuration de Kubernetes production_issuer.yml. Créez le fichier :

      • nano ./production_issuer.yml

      Maintenant, ajoutez ce qui suit :

      apiVersion: cert-manager.io/v1alpha2
      kind: ClusterIssuer
      metadata:
        name: letsencrypt-prod
      spec:
        acme:
          # Email address used for ACME registration
          email: your_email_address
          server: https://acme-v02.api.letsencrypt.org/directory
          privateKeySecretRef:
            # Name of a secret used to store the ACME account private key
            name: letsencrypt-prod-private-key
          # Add a single challenge solver, HTTP01 using nginx
          solvers:
            - http01:
                ingress:
                  class: nginx
      

      Enregistrez et fermez le fichier.

      Let’s Encrypt enverra toutes les notifications importantes et tous les avertissements d’expiration à your_email_address. Veillez donc à bien ajouter une adresse que vous consultez régulièrement. Sauvegardez ce fichier et créez une nouvelle ressource à la fois pour votre ressource Ingress et votre émetteur de production dans votre cluster Kubernetes :

      • kubectl create -f ingress.yml
      • kubectl create -f production_issuer.yml

      Enfin, mettez à jour les enregistrements DNS de votre nom de domaine pour qu’un enregistrement A pointe vers l’adresse IP de votre équilibreur de charge. Pour trouver l’adresse IP de votre contrôleur Ingress, saisissez ce qui suit :

      • kubectl get service nginx-ingress-controller

      Output

      NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE nginx-ingress-controller LoadBalancer your_cluster_ip your_external_ip 80:30187/TCP,443:31468/TCP 6m10s

      Utilisez l’adresse your_external_ip comme adresse IP de votre Enregistrement A de DNS. Le processus de mise à jour de vos enregistrements DNS varie en fonction de l’endroit où vous gérez vos noms de domaine et l’hébergement DNS. Cependant, si vous utilisez DigitalOcean, vous pouvez consulter notre guide Comment gérer vos enregistrements DNS.

      Une fois que vos enregistrements DNS sont mis à jour et votre certificat SSL est configuré, votre application sera disponible sur your_domain et SSL sera activée.

      L'application Laravel avec terminaison SSL et un nom de domaine personnalisé

      Même si votre application et votre base de données PHP sont déjà connectées, vous aurez encore besoin de migrer la base de données. Au cours de la dernière étape, vous verrez comment exécuter des Artisan commands sur votre pod Kubernetes pour migrer la base de données et effectuer d’autres tâches de maintenance communes.

      Étape 6 — Exécution de commandes à distance

      Même si votre application Laravel fonctionne et est connectée à la base de données MySQL dans Kubernetes, vous aurez besoin d’effectuer plusieurs opérations communes sur une nouvelle installation Laravel. Une de ces tâches communes est la migration de base de données.

      Avant que vous puissiez exécuter une commande Artisan sur votre application Laravel, vous devez connaître le nom du pod qui exécute votre conteneur d’application Laravel. En utilisant la ligne de commande suivante, vous pouvez consulter tous les pods de votre cluster Kubernetes :

      Vous verrez un résultat similaire à ce qui suit :

      Output

      NAME READY STATUS RESTARTS AGE laravel-kubernetes-lamp-77fb989b46-wczgb 2/2 Running 0 16m

      Sélectionnez le pod pour votre déploiement laravel-kubernetes-lamp-... Veillez à bien utiliser le nom dans votre résultat et non celui mentionné ci-dessus. Maintenant, vous pouvez y exécuter kubectl exec. Par exemple, exécutez une migration de base de données en utilisant la commande artisan migrate. Vous allez ajouter la balise --force car vous exécutez le pod en production :

      • kubectl exec laravel-kubernetes-lamp-77fb989b46-wczgb -- php artisan migrate --force

      Cette commande générera un résultat :

      Output

      Migration table created successfully. Migrating: 2014_10_12_000000_create_users_table Migrated: 2014_10_12_000000_create_users_table (0.16 seconds) Migrating: 2019_08_19_000000_create_failed_jobs_table Migrated: 2019_08_19_000000_create_failed_jobs_table (0.05 seconds)

      Vous avez maintenant déployé correctement Laravel 7 et MySQL dans Kubernetes et exécuté une tâche essentielle de maintenance de la base de données.

      Conclusion

      Dans ce tutoriel, vous avez appris à conteneuriser une application PHP Laravel, à la connecter à une base de données MySQL, à pousser une image Docker contenant votre code sur Docker Hub, puis à utiliser un chart Helm pour la déployer sur un cluster DigitalOcean Kubernetes. Enfin, vous avez ajouté un SSL et un nom de domaine personnalisé et appris à exécuter des outils de ligne de commande sur vos pods en cours d’exécution.

      Par rapport à l’hébergement traditionnel de pile LAMP, Kubernetes et Helm vous offrent un certain nombre d’avantages : extensibilité, échange de services sans connexion directe à votre serveur, outils de mises à jour en roulement et contrôle de votre environnement d’hébergement. Cela dit, la complexité initiale de la conteneurisation et de la configuration rendent le démarrage de votre application assez difficile. En utilisant ce guide comme point de départ, il est plus facile de déployer Laravel sur Kubernetes. À partir de là, vous pourriez envisager d’en apprendre plus sur la puissance de Laravel ou sur l’ajout d’outils de surveillance à Kubernetes (Linkerd, par exemple), que vous pouvez installer manuellement avec notre guide ou avec un DigitalOcean 1-Click​​​.



      Source link