{"id":6986,"date":"2019-05-13T14:02:15","date_gmt":"2019-05-13T14:02:15","guid":{"rendered":"https:\/\/www.milesweb.in\/hosting-faqs\/?p=6986"},"modified":"2022-02-19T16:22:57","modified_gmt":"2022-02-19T10:52:57","slug":"php-application-deployment-kubernetes-ubuntu-16-04","status":"publish","type":"post","link":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/","title":{"rendered":"PHP Application Deployment with Kubernetes on Ubuntu 16.04"},"content":{"rendered":"<h2>Introduction<\/h2>\n<p><strong>Kubernetes (K8s)<\/strong> is a portable, extensible open-source container orchestration platform to manage containerized workloads and services, that makes easier declarative configuration deployment, scaling and automation. <strong>K8s<\/strong> lets you create, update and scale containers without worrying about server downtime.<\/p>\n<p class=\"western\">Nginx acts as a proxy to <span style=\"color: #000080;\"><u><a class=\"western\" href=\"http:\/\/php.net\/manual\/en\/install.fpm.php\" target=\"_blank\" rel=\"nofollow noopener\">PHP-FPM<\/a><\/u><\/span> when running a PHP application. It can be a cumbersome process if this setup <span style=\"color: #000000;\">is containerized<\/span> in a single container, but Kubernetes will help to manage both services in separate containers. <b>K8s <\/b>allows you to keep your containers switchable and reusable, and you will not have to rebuild your container image every time there&#8217;s a new version of PHP or Nginx.<\/p>\n<p class=\"western\">In this KB article, you will learn <span style=\"color: #000000;\">about<\/span> how to deploy a PHP 7 application on Kubernetes cluster with PHP-FPM and Nginx running in separate containers. Also, learn how to keep your application code and configuration files apart from the container image using <span style=\"color: #000080;\"><u><a class=\"western\" href=\"https:\/\/www.digitalocean.com\/products\/block-storage\/\" target=\"_blank\" rel=\"nofollow noopener\">DigitalOcean&#8217;s Block Storage<\/a><\/u><\/span> system. <span style=\"color: #000000;\">With<\/span> this perspective<span style=\"color: #ff0000;\">,<\/span> you can reuse the Nginx image for any application that requires web or proxy server by passing a configuration volume instead of rebuilding the image.<\/p>\n<h2>Prerequisites<\/h2>\n<ul>\n<li>\n<p class=\"western\">A basic understanding of Kubernetes objects.<\/p>\n<\/li>\n<li>\n<p class=\"western\">A Kubernetes cluster running on Ubuntu 16.04.<\/p>\n<\/li>\n<li>\n<p class=\"western\">A DigitalOcean account and an API access token with read and write permissions to create storage volume.<\/p>\n<\/li>\n<li>\n<p class=\"western\">Your application code hosted on a publicly accessible URL, like <span style=\"color: #000080;\"><u><a class=\"western\" href=\"https:\/\/github.com\/\" target=\"_blank\" rel=\"nofollow noopener\">Github<\/a><\/u><\/span>.<\/p>\n<\/li>\n<\/ul>\n<h2>STEP 1 &#8211; Create the PHP-FPM and Nginx Services<\/h2>\n<p class=\"western\"><span style=\"color: #000000;\">Here you will create the PHP-FPM and Nginx services. With the service you get an access to a set of <a class=\"western\" href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/pods\/pod\/\" target=\"_blank\" rel=\"nofollow noopener\">pods<\/a> from inside the cluster. Without the requirement for IP addresses, these services can communicate directly within the cluster through their names. By using PHP-FPM service, you can access the PHP-FPM pods, while the Nginx service will allow access to the Nginx pods.<\/span><\/p>\n<p class=\"western\">As Nginx pods will proxy the PHP-FPM pods, you have to tell the service <span style=\"color: #000000;\">the way<\/span> to find them. Instead of using IP addresses, Kubernetes&#8217; automatic service discovery is beneficial to use human-readable names to route requests to the appropriate service.<\/p>\n<p class=\"western\">To create the service, you have to create an object definition file. Every Kubernetes object definition is a <b>YAML<\/b> file that includes at least the following items:<\/p>\n<p class=\"western\" style=\"padding-left: 30px;\"><strong>apiVersion<\/strong>: The Kubernetes API version that the definition belongs to.<\/p>\n<p class=\"western\" style=\"padding-left: 30px;\"><strong>kind<\/strong>: The Kubernetes object this file represents. For example, a <strong><em>pod<\/em><\/strong> or <em><strong>service<\/strong><\/em>.<\/p>\n<p class=\"western\" style=\"padding-left: 30px;\"><strong>metadata<\/strong>: This includes the object name with any labels that you may want to apply to it.<\/p>\n<p class=\"western\" style=\"padding-left: 30px;\"><strong>spec<\/strong>: This contains a particular setup relying upon the type of object you are creating, like the container image or the ports on which the container will be available from.<\/p>\n<p class=\"western\">First, you have to create a directory to hold your Kubernetes object definitions.<\/p>\n<p class=\"western\">SSH to your <strong>master node<\/strong> and make the <strong>definitions<\/strong> directory that will clutch your Kubernetes object definitions.<\/p>\n<p style=\"padding-left: 30px;\"><strong><em>mkdir definitions<\/em><\/strong><\/p>\n<p class=\"western\">Navigate to the newly created <b>definitions<\/b> directory:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>cd definitions<\/strong><\/em><\/p>\n<p>Build your PHP-FPM service by creating a <strong>php_service.yaml<\/strong> file:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>nano php_service.yaml<\/strong><\/em><\/p>\n<p class=\"western\">Set <strong>kind<\/strong> as <strong>Service<\/strong> to define that this object is a service:<\/p>\n<p style=\"text-align: center;\"><strong>php_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>apiVersion: v1<\/em><br \/>\n<em>kind: Service<\/em><\/p>\n<p class=\"western\">Name the service <b>php<\/b> as it will give access to PHP-FPM:<\/p>\n<p style=\"text-align: center;\"><strong>php_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: php<\/em><\/p>\n<p>You can group various objects logically with labels. In this knowledge base, you will use labels to group the objects within &#8220;tiers&#8221; like frontend or backend. The PHP pods will run back of this service so you can label it as <strong>tier: backend<\/strong>.<\/p>\n<p style=\"text-align: center;\"><strong>php_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>labels:<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p class=\"western\">A service figures out which pods to access by using <b>selector<\/b> labels. A pod that coordinates these names will be serviced, independent of whether the pod was made before or after the service. You will include labels for your pods later in the tutorial.<\/p>\n<p class=\"western\">Apply the <b>tier: backend<\/b> label to assign the pod into the backend tier. Also, you have to add the <b>app: php<\/b> label to define that this pod runs PHP. Add these two labels after the <b>metadata<\/b> section.<\/p>\n<p style=\"text-align: center;\"><strong>php_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> selector:<\/em><br \/>\n<em> app: php<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p class=\"western\">Next, define the port used to access this service. You will use port <strong>9000<\/strong> in this tutorial. Add this port to the <strong>php_service.yaml<\/strong> file under <strong>spec<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>php_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>ports:<\/em><br \/>\n<em> &#8211; protocol: TCP<\/em><br \/>\n<em> port: 9000<\/em><\/p>\n<p class=\"western\">Done! Your created <strong>php_service.yaml<\/strong> file will look like this:<\/p>\n<p style=\"text-align: center;\"><strong>php_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: Service<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: php<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> selector:<\/em><br \/>\n<em> app: php<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em> ports:<\/em><br \/>\n<em> &#8211; protocol: TCP<\/em><br \/>\n<em> port: 9000<\/em><\/p>\n<p>Hit <strong>CTRL + o<\/strong> to save the file, and then <strong>CTRL + x<\/strong> to exit nano.<\/p>\n<p>Now that you have created the object definition for your service, to run this service you will use the <strong>kubectl apply<\/strong> command plus the <strong>-f<\/strong> argument and mention your <strong>php_service.yaml<\/strong> file.<\/p>\n<p>Create your service:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl apply -f php_service.yaml<\/strong><\/em><\/p>\n<p>Following output authenticates service creation:<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><br \/>\n<em>service\/php created<\/em><\/p>\n<p>Check that your service is running:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get svc<\/strong><\/em><\/p>\n<p>You will notice your PHP-FPM service running:<\/p>\n<p><strong>Output<\/strong><br \/>\n\n<table id=\"tablepress-7\" class=\"tablepress tablepress-id-7\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">TYPE<\/th><th class=\"column-3\">CLUSTER-IP<\/th><th class=\"column-4\">EXTERNAL-IP<\/th><th class=\"column-5\">PORT(S)<\/th><th class=\"column-6\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">kubernetes<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.96.0.1 <\/td><td class=\"column-4\">None<\/td><td class=\"column-5\">443\/TCP<\/td><td class=\"column-6\">10m<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">php<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.100.59.238<\/td><td class=\"column-4\">None<\/td><td class=\"column-5\">9000\/TCP<\/td><td class=\"column-6\">5m<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<\/p>\n<p>There are several <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/services-networking\/service\/#publishing-services-service-types\" target=\"_blank\" rel=\"nofollow noopener\">service types<\/a> that Kubernetes supports. Your <strong>php<\/strong> service uses the default <strong>ClusterIP<\/strong> service type. This service type assigns an internal IP and forms the service accessible only from within the cluster.<\/p>\n<p>Now your PHP-FPM service is ready. You have to create the Nginx service. Create and open a new file named <strong>nginx_service.yaml<\/strong> with the editor:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>nano nginx_service.yaml<\/strong><\/em><\/p>\n<p>This service will point Nginx pods so you can call it <strong>nginx<\/strong>. You can also add a <strong>tier: backend<\/strong> label as it applies in the backend tier:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: Service<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: nginx<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p>Point the pods with selector labels <strong>app: nginx<\/strong> and <strong>tier: backend<\/strong> as similar to the <strong>php<\/strong> service. Make this service accessible on the default HTTP port 80.<\/p>\n<p style=\"text-align: center;\"><strong>nginx_service.yaml<\/strong><\/p>\n<p style=\"text-align: left; padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> selector:<\/em><br \/>\n<em> app: nginx<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em> ports:<\/em><br \/>\n<em> &#8211; protocol: TCP<\/em><br \/>\n<em> port: 80<\/em><\/p>\n<p>The Nginx service will be publicly accessible to the internet by your Droplet&#8217;s public IP address. Under <strong>spec.externalIPs<\/strong>, <span style=\"color: #ff0000;\">your_public_ip<\/span> can be found from your <a href=\"https:\/\/cloud.digitalocean.com\/\" target=\"_blank\" rel=\"nofollow noopener\">DigitalOcean Cloud Panel<\/a>, add:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> externalIPs:<\/em><br \/>\n<em> &#8211; <span style=\"color: #ff0000;\">your_public_ip<\/span><\/em><\/p>\n<p>Your <strong>nginx_service.yaml<\/strong> file will look like as follows:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: Service<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: nginx<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> selector:<\/em><br \/>\n<em> app: nginx<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em> ports:<\/em><br \/>\n<em> &#8211; protocol: TCP<\/em><br \/>\n<em> port: 80<\/em><br \/>\n<em> externalIPs:<\/em><br \/>\n<em> &#8211; <span style=\"color: #ff0000;\">your_public_ip<\/span><\/em><\/p>\n<p>Save and close the file.<\/p>\n<p>Execute the following command to create the Nginx service:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl apply -f nginx_service.yaml<\/strong><\/em><\/p>\n<p>You will get the output when the service is running:<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><br \/>\n<em>service\/nginx created<\/em><\/p>\n<p>Run the following command to view all running services:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get svc<\/strong><\/em><\/p>\n<p>You can see both the Nginx and PHP-FPM services listed in the output:<\/p>\n\n<table id=\"tablepress-8\" class=\"tablepress tablepress-id-8\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">TYPE<\/th><th class=\"column-3\">CLUSTER-IP<\/th><th class=\"column-4\">EXTERNAL-IP<\/th><th class=\"column-5\">PORT(S)<\/th><th class=\"column-6\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">kubernetes<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.96.0.1 <\/td><td class=\"column-4\">None<\/td><td class=\"column-5\">443\/TCP<\/td><td class=\"column-6\">10m<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">nginx<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.102.160.47<\/td><td class=\"column-4\">your_public_ip<\/td><td class=\"column-5\">80\/TCP<\/td><td class=\"column-6\">50s<\/td>\n<\/tr>\n<tr class=\"row-4\">\n\t<td class=\"column-1\">php<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.100.59.238<\/td><td class=\"column-4\">None<\/td><td class=\"column-5\">9000\/TCP<\/td><td class=\"column-6\">5m<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>Please note, you can run the following command to delete a service:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl delete svc\/<span style=\"color: #ff0000;\">service_name<\/span><\/strong><\/em><\/p>\n<p>Now that you have created your PHP-FPM and Nginx services, you need to define where to store your application code and configuration files.<\/p>\n<p style=\"text-align: center;\"><strong>nginx_service.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> externalIPs:<\/em><br \/>\n<em> <span style=\"color: #ff0000;\">&#8211; your_public_ip<\/span><\/em><\/p>\n<h2>&nbsp;<\/h2>\n<h2>STEP 2 &#8211; Installing the DigitalOcean Storage Plug-In<\/h2>\n<p>Kubernetes provides various storage plug-ins that can create the storage space for your environment. In this step, you will install the <a href=\"https:\/\/github.com\/digitalocean\/csi-digitalocean\" target=\"_blank\" rel=\"nofollow noopener\">DigitalOcean storage plug-in<\/a> to generate <a href=\"https:\/\/www.digitalocean.com\/products\/storage\/\" target=\"_blank\" rel=\"nofollow noopener\">block storage<\/a> on DigitalOcean. It will add a storage class called <strong>do-block-storage<\/strong> when the installation is completed that you will use to create your block storage.<\/p>\n<p>At first, you have to configure the Kubernetes Secret object to store your DigitalOcean API token. Kubernetes Secret objects are used to share sensitive data or information such as SSH keys and passwords with other Kubernetes objects within the same namespace. Namespaces offer a way to logically separate your Kubernetes objects.<\/p>\n<p>Open a file called <strong>secret.yaml<\/strong> with the editor:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>nano secret.yaml<\/strong><\/em><\/p>\n<p>Define the name your Secret object <strong>digitalocean<\/strong> and add it to the <strong>kube-system<\/strong> <strong>namespace<\/strong>. The <strong>kube-system<\/strong> namespace is the default namespace for Kubernetes\u2019 internal services as well as it is also used by the DigitalOcean storage plug-in to launch different components.<\/p>\n<p style=\"text-align: center;\"><strong>secret.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: Secret<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: digitalocean<\/em><br \/>\n<em> namespace: kube-system<\/em><\/p>\n<p>Secret uses a <strong>data<\/strong> or <strong>stringData<\/strong> key instead of a <strong>spec<\/strong> key to hold the required information. The <strong>data<\/strong> parameter keeps base64 encoded data that is automatically decoded when retrieved. The <strong>stringData<\/strong> parameter holds non-encoded data that is automatically encoded when creation or updates and doesn&#8217;t output the data during retrieving Secrets. You can use <strong>stringData<\/strong> in this tutorial for help.<\/p>\n<p>Add the <strong>access-token<\/strong> as <strong>stringData<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>secret.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>stringData:<\/em><br \/>\n<em> access-token: <span style=\"color: #ff0000;\">your-api-token<\/span><\/em><\/p>\n<p>Save and exit the file.<\/p>\n<p>Your <strong>secret.yaml<\/strong> file will look like this:<\/p>\n<p style=\"text-align: center;\"><strong>secret.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: Secret<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: digitalocean<\/em><br \/>\n<em> namespace: kube-system<\/em><br \/>\n<em>stringData:<\/em><br \/>\n<em> access-token: <span style=\"color: #ff0000;\">your-api-token<\/span><\/em><\/p>\n<p>Create the secret:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl apply -f secret.yaml<\/strong><\/em><\/p>\n<p>Here is the output upon Secret creation:<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><br \/>\n<em>secret\/digitalocean created<\/em><\/p>\n<p>Execute the following command to view the secret:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl -n kube-system get secret digitalocean<\/strong><\/em><\/p>\n<p>The output will look like this:<\/p>\n<p><strong>Output<\/strong><\/p>\n\n<table id=\"tablepress-9\" class=\"tablepress tablepress-id-9\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">TYPE<\/th><th class=\"column-3\">DATA<\/th><th class=\"column-4\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">digitalocean<\/td><td class=\"column-2\">Opaque<\/td><td class=\"column-3\">1<\/td><td class=\"column-4\">41s<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>The <strong>Opaque<\/strong> type indicates that this Secret is read-only, which is standard for <strong>stringData<\/strong> Secrets. You can learn more about it on the <a href=\"https:\/\/github.com\/kubernetes\/community\/blob\/master\/contributors\/design-proposals\/auth\/secrets.md\" target=\"_blank\" rel=\"nofollow noopener\">Secret design spec<\/a>. The <strong>DATA<\/strong> field displays the number of items stored in this Secret. Here, it shows <strong>1<\/strong> as you have a single key stored.<\/p>\n<p>Now that your Secret is in place, install the <a href=\"https:\/\/github.com\/digitalocean\/csi-digitalocean\" target=\"_blank\" rel=\"nofollow noopener\">DigitalOcean block storage plug-in<\/a>:<\/p>\n<p style=\"padding-left: 30px;\"><strong><em>kubectl apply -f https:\/\/raw.githubusercontent.com\/digitalocean\/csi-digitalocean\/master\/deploy\/kubernetes\/releases\/csi-digitalocean-v0.3.0.yaml<\/em><\/strong><\/p>\n<p>The output will look like as follows:<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><\/p>\n<p style=\"padding-left: 30px;\"><em>storageclass.storage.k8s.io\/do-block-storage created<\/em><br \/>\n<em>serviceaccount\/csi-attacher created<\/em><br \/>\n<em>clusterrole.rbac.authorization.k8s.io\/external-attacher-runner created<\/em><br \/>\n<em>clusterrolebinding.rbac.authorization.k8s.io\/csi-attacher-role created<\/em><br \/>\n<em>service\/csi-attacher-doplug-in created<\/em><br \/>\n<em>statefulset.apps\/csi-attacher-doplug-in created<\/em><br \/>\n<em>serviceaccount\/csi-provisioner created<\/em><br \/>\n<em>clusterrole.rbac.authorization.k8s.io\/external-provisioner-runner created<\/em><br \/>\n<em>clusterrolebinding.rbac.authorization.k8s.io\/csi-provisioner-role created<\/em><br \/>\n<em>service\/csi-provisioner-doplug-in created<\/em><br \/>\n<em>statefulset.apps\/csi-provisioner-doplug-in created<\/em><br \/>\n<em>serviceaccount\/csi-doplug-in created<\/em><br \/>\n<em>clusterrole.rbac.authorization.k8s.io\/csi-doplug-in created<\/em><br \/>\n<em>clusterrolebinding.rbac.authorization.k8s.io\/csi-doplug-in created<\/em><br \/>\n<em>daemonset.apps\/csi-doplug-in created<\/em><\/p>\n<p>Now that you have installed the DigitalOcean storage plug-in, you can create block storage to keep your application code and configuration files.<\/p>\n<p>&nbsp;<\/p>\n<h2>STEP 3 &#8211; Creating the Persistent Volume<\/h2>\n<p>You are now ready to create your Persistent Volume with your Secret in place and the block storage plug-in installed. A <em><strong>Persistent Volume (PV)<\/strong><\/em> is block storage of a specified size that exists individually of a pod\u2019s life cycle. You can manage or update your pods by using Persistent Volume without worrying about losing your application code. Using <strong>PersistentVolumeClaim (PVC)<\/strong>, a Persistent Volume is accessed which mounts the PV at the necessary path.<\/p>\n<p>Open a file named <strong>code_volume.yaml<\/strong> through your editor:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>nano code_volume.yaml<\/strong><\/em><\/p>\n<p>Define the PVC <strong>code<\/strong> by adding the parameters and values to your file are as follows:<\/p>\n<p style=\"text-align: center;\"><strong>code_volume.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: PersistentVolumeClaim<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: code<\/em><\/p>\n<p>The <strong>spec<\/strong> for a PVC includes the following items:<\/p>\n<ul>\n<li><strong>accessModes<\/strong> can change by the use case. These are:\n<ul>\n<li><em><strong>ReadWriteOnce<\/strong><\/em> &#8211; scales the volume as read-write by a single node<\/li>\n<li><em><strong>ReadOnlyMany<\/strong><\/em> &#8211; scales the volume as read-only by many nodes<\/li>\n<li><em><strong>ReadWriteMany<\/strong><\/em> &#8211; scales the volume as read-write by many nodes<\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<ul>\n<li><strong>resources<\/strong> &#8211; the storage space that you need.<\/li>\n<\/ul>\n<p>DigitalOcean block storage is only scaled to a single node, so you have set the <strong>accessModes<\/strong> to <strong>ReadWriteOnce<\/strong>. This tutorial will help you by adding a small amount of application code so 1GB will be sufficient in this use case. If you wish to store a massive amount of data or code on the volume, you can adjust the <strong>storage<\/strong> parameter as per your requirements. You can increase the size of storage after volume creation, but shrinking the disk is not supported.<\/p>\n<p style=\"text-align: center;\"><strong>code_volume.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> accessModes:<\/em><br \/>\n<em> &#8211; ReadWriteOnce<\/em><br \/>\n<em>resources:<\/em><br \/>\n<em> requests:<\/em><br \/>\n<em> storage: <span style=\"color: #ff0000;\">1Gi<\/span><\/em><\/p>\n<p>Next, define the storage class that Kubernetes will use to provision the volumes. You can use the <strong>do-block-storage<\/strong> class created by the DigitalOcean block storage plug-in.<\/p>\n<p style=\"text-align: center;\"><strong>code_volume.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>storageClassName: do-block-storage<\/em><\/p>\n<p>Your <strong>code_volume.yaml<\/strong> file will look similar to this:<\/p>\n<p style=\"text-align: center;\"><strong>code_volume.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: PersistentVolumeClaim<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: code<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> accessModes:<\/em><br \/>\n<em> &#8211; ReadWriteOnce<\/em><br \/>\n<em> resources:<\/em><br \/>\n<em> requests:<\/em><br \/>\n<em> storage: <span style=\"color: #ff0000;\">1Gi<\/span><\/em><br \/>\n<em> storageClassName: do-block-storage<\/em><\/p>\n<p>Save and exit the file.<\/p>\n<p>Create the <strong>code<\/strong> PersistentVolumeClaim with using <strong>kubectl<\/strong>:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl apply -f code_volume.yaml<\/strong><\/em><\/p>\n<p>The object was successfully created. You are prepared to mount your 1GB PVC as a volume.<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><br \/>\n<em>persistentvolumeclaim\/code created<\/em><\/p>\n<p>To view available Persistent Volumes (PV):<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get pv<\/strong><\/em><\/p>\n<p>You can see your PV listed:<\/p>\n<p><strong>Output<\/strong><\/p>\n\n<table id=\"tablepress-10\" class=\"tablepress tablepress-id-10\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">CAPACITY<\/th><th class=\"column-3\">ACCESS MODES<\/th><th class=\"column-4\">RECLAIM POLICY<\/th><th class=\"column-5\">STATUS<\/th><th class=\"column-6\">CLAIM<\/th><th class=\"column-7\">STORAGECLASS<\/th><th class=\"column-8\">REASON<\/th><th class=\"column-9\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-striping row-hover\">\n<tr class=\"row-2\">\n\t<td class=\"column-1\">pvc-ca4df10f-ab8c-11e8-b89d-12331aa95b13<\/td><td class=\"column-2\">1Gi<\/td><td class=\"column-3\">RWO<\/td><td class=\"column-4\">Delete<\/td><td class=\"column-5\">Bound<\/td><td class=\"column-6\">default\/code<\/td><td class=\"column-7\">do-block-storage  <\/td><td class=\"column-8\"><\/td><td class=\"column-9\">2m<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>Above output is an overview of your configuration file except for <strong>Reclaim Policy<\/strong> and <strong>Status<\/strong>. The Reclaim Policy describes what is done with the PV, after the PVC accessing it is deleted. Delete removes the PV from Kubernetes and DigitalOcean infrastructure. You can get more information about the <strong>Reclaim Policy<\/strong> and <strong>Status<\/strong> from the <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/storage\/persistent-volumes\/\" target=\"_blank\" rel=\"nofollow noopener\">Kubernetes PV documentation<\/a>.<\/p>\n<p>You have successfully created a Persistent Volume through DigitalOcean block storage plug-in. Now your Persistent Volume is ready. You can create your pods using a Deployment.<\/p>\n<h2>&nbsp;<\/h2>\n<h2>STEP 4 &#8211; Creating a PHP-FPM Deployment<\/h2>\n<p>In this step, you will discover how to use a Deployment to create your PHP-FPM pod. Deployments provide a consistent way to create, update, and manage pods by using <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/replicaset\/\" target=\"_blank\" rel=\"nofollow noopener\">ReplicaSets<\/a>. If an update doesn&#8217;t work as expected, a Deployment will automatically rollback its pods to a previous image.<\/p>\n<p>The Deployment spec.selector key will list the labels of the pods it will manage. It will also use the template key to create the needed pods.<\/p>\n<p>In this step, we will explain the use of Init Containers. Init Containers execute one or more commands before the regular containers defined under the pod&#8217;s template key. In this tutorial, your Init Container will fetch a sample index.php file from <a href=\"https:\/\/gist.github.com\/\" target=\"_blank\" rel=\"nofollow noopener\">GitHub Gist<\/a> with using wget. Following are the contents of the sample file:<\/p>\n<p style=\"text-align: center;\"><strong>index.php<\/strong><\/p>\n<p style=\"padding-left: 30px;\"><!--?php &lt;br ?--> <em><strong>echo phpinfo();<\/strong><\/em><\/p>\n<p>Open a new file named <strong>php_deployment.yaml<\/strong> to create your deployment with your editor:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>nano php_deployment.yaml<\/strong><\/em><\/p>\n<p>This Deployment will manage your PHP-FPM pods, so you have to name the Deployment object <strong>php<\/strong>. The pods apply to the backend tier so you can arrange the Deployment into this group by using the <strong>tier: backend<\/strong> label:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: apps\/v1<\/em><br \/>\n<em>kind: Deployment<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: php<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p>For the Deployment <strong>spec<\/strong>, you have to define how many copies of this pod to create through using the <strong>replicas<\/strong> parameter. The number of <strong>replicas<\/strong> can change depending on your needs and available resources. You will create one replica in this KB:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> replicas: 1<\/em><\/p>\n<p>Under the <strong>selector<\/strong> key, the deployment will manage pods that match the <strong>app: php<\/strong> and <strong>tier: backend<\/strong> labels.<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\">&#8230;<br \/>\nselector:<br \/>\nmatchLabels:<br \/>\napp: php<br \/>\ntier: backend<\/p>\n<p>Next, the Deployment <strong>spec<\/strong> needs the <strong>template<\/strong> for your pod&#8217;s object definition. This template will define specifications to create the pod from. First, you have to add the labels that were defined for the <strong>php<\/strong> service <strong>selectors<\/strong> and the Deployment\u2019s <strong>matchLabels<\/strong>. Add <strong>app: php<\/strong> and <strong>tier: backend<\/strong> under <strong>template.metadata.labels<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> template:<\/em><br \/>\n<em> metadata:<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> app: php<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p>A pod may have many containers and volumes, but each will require a name. You can particularly mount volumes to a container by defining a mount path for each volume.<\/p>\n<p>First, define the volumes that your containers will access. You created a PVC named <strong>code<\/strong> to keep your application code, so name this volume too as <strong>code<\/strong>. Add the following code under <strong>spec.template.spec.volumes<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> volumes:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> persistentVolumeClaim:<\/em><br \/>\n<em> claimName: code<\/em><\/p>\n<p>Next, define the container you wish to run in this pod. You can get several images on the Docker store, but in this kb, you will use the <strong>php:7-fpm<\/strong> image. Add the following code under <strong>spec.template.spec.containers<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> containers:<\/em><br \/>\n<em> &#8211; name: php<\/em><br \/>\n<em> image: php:7-fpm<\/em><\/p>\n<p>Next, you will mount the volumes that the container needs access to. This container will run your PHP code so it will require access to the <strong>code<\/strong> volume. You will also need to use <strong>mountPath<\/strong> to define <strong>\/code<\/strong> as the mount point.<\/p>\n<p>Under <strong>spec.template.spec.containers.volumeMounts<\/strong>, add:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> volumeMounts:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> mountPath: \/code<\/em><\/p>\n<p>Now you mounted the volume, you require getting your application code on the volume. You may have earlier used FTP\/SFTP or cloned the code across an SSH connection to achieve this, but this step will explain to you how to copy the code using an Init Container.<\/p>\n<p>Based on the difficulty of your setup process, you can either use a single <strong>initContainer<\/strong> to run a script that creates your application, or you can use one <strong>initContainer<\/strong> per command. Make sure that the volumes are mounted to the <strong>initContainer<\/strong>.<\/p>\n<p>In this KB, you will use a single Init Container with <strong>busybox<\/strong> to download the code. <strong>busybox<\/strong> is a small image that includes the wget utility that you will use to finish this.<\/p>\n<p>Under <strong>spec.template.spec<\/strong>, add your <strong>initContainer<\/strong> and define the <strong>busybox<\/strong> image:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>initContainers:<\/em><br \/>\n<em>&#8211; name: install<\/em><br \/>\n<em>image: busybox<\/em><\/p>\n<p>Your Init Container will require access to the <strong>code<\/strong> volume so that it can download the code into that location. Under <strong>spec.template.spec.initContainers<\/strong>, mount the volume <strong>code<\/strong> at the <strong>\/code<\/strong> path:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> volumeMounts:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> mountPath: \/code<\/em><\/p>\n<p>Every Init Container requires to run a <strong>command<\/strong>. Your Init Container will use <strong>wget<\/strong> to download the code from Github into the <strong>\/code<\/strong> working directory. The <strong>-O<\/strong> option gives the downloaded file a name, and you will call this file <strong>index.php<\/strong>.<\/p>\n<p><em><strong>Note:<\/strong> Make sure to trust the code you\u2019re pulling. Before pulling it to your server, review the source code to ensure you are comfortable with what the code does.<\/em><\/p>\n<p>Add the following lines under the <strong>install<\/strong> container in <strong>spec.template.spec.initContainers<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> command:<\/em><br \/>\n<em> &#8211; wget<\/em><br \/>\n<em> &#8211; &#8220;-O&#8221;<\/em><br \/>\n<em> &#8211; &#8220;\/code\/index.php&#8221;<\/em><br \/>\n<em> &#8211; <span style=\"color: #ff0000;\">https:\/\/raw.githubusercontent.com\/do-community\/php-kubernetes\/master\/index.php<\/span><\/em><\/p>\n<p>Your completed <strong>php_deployment.yaml<\/strong> file will look similar to this:<\/p>\n<p style=\"text-align: center;\"><strong>php_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: apps\/v1<\/em><br \/>\n<em>kind: Deployment<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: php<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> replicas: 1<\/em><br \/>\n<em> selector:<\/em><br \/>\n<em> matchLabels:<\/em><br \/>\n<em> app: php<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em> template:<\/em><br \/>\n<em> metadata:<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> app: php<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em> spec:<\/em><br \/>\n<em> volumes:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> persistentVolumeClaim:<\/em><br \/>\n<em> claimName: code<\/em><br \/>\n<em> containers:<\/em><br \/>\n<em> &#8211; name: php<\/em><br \/>\n<em> image: php:7-fpm<\/em><br \/>\n<em> volumeMounts:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> mountPath: \/code<\/em><br \/>\n<em> initContainers:<\/em><br \/>\n<em> &#8211; name: install<\/em><br \/>\n<em> image: busybox<\/em><br \/>\n<em> volumeMounts:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> mountPath: \/code<\/em><br \/>\n<em> command:<\/em><br \/>\n<em> &#8211; wget<\/em><br \/>\n<em> &#8211; &#8220;-O&#8221;<\/em><br \/>\n<em> &#8211; &#8220;\/code\/index.php&#8221;<\/em><br \/>\n<em> &#8211; <span style=\"color: #ff0000;\">https:\/\/raw.githubusercontent.com\/do-community\/php-kubernetes\/master\/index.php<\/span><\/em><\/p>\n<p>Save the file and exit the editor.<\/p>\n<p>Create the PHP-FPM Deployment with <strong>kubectl<\/strong>:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl apply -f php_deployment.yaml<\/strong><\/em><\/p>\n<p>You will see the following output on Deployment creation:<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><br \/>\n<em>deployment.apps\/php created<\/em><\/p>\n<p>To sum up, this Deployment will start by downloading the defined images. It will then request the <strong>PersistentVolume<\/strong> from your <strong>PersistentVolumeClaim<\/strong> and serially run your <strong>initContainers<\/strong>. Once finished, the containers will run and mount the <strong>volumes<\/strong> to the defined mount point. When all of these actions are complete, your pod will be up and running.<\/p>\n<p>You can see your Deployment by running:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get deployments<\/strong><\/em><\/p>\n<p>You can view the output:<\/p>\n<p><strong>Output<\/strong><\/p>\n\n<table id=\"tablepress-11\" class=\"tablepress tablepress-id-11\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">DESIRED<\/th><th class=\"column-3\">CURRENT<\/th><th class=\"column-4\">UP-TO-DATE<\/th><th class=\"column-5\">AVAILABLE<\/th><th class=\"column-6\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">php<\/td><td class=\"column-2\">1<\/td><td class=\"column-3\">1<\/td><td class=\"column-4\">1<\/td><td class=\"column-5\">0<\/td><td class=\"column-6\">19s<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>The above output helps you to understand the current state of the <strong>Deployment<\/strong>. A Deployment is <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/deployment\/\" target=\"_blank\" rel=\"nofollow noopener\">one of the controllers<\/a> that manage the desired state. The <strong>template<\/strong> you created defines that the <strong>DESIRED<\/strong> state will have 1 <strong>replicas<\/strong> of the pod named php. The <strong>CURRENT<\/strong> field shows how many replicas are running, so this should match the <strong>DESIRED<\/strong> state. You can get more information about the remaining fields in the <a href=\"https:\/\/kubernetes.io\/docs\/concepts\/workloads\/controllers\/deployment\/\" target=\"_blank\" rel=\"nofollow noopener\">Kubernetes Deployments documentation<\/a>.<\/p>\n<p>You can see the pods that this Deployment started with executing the following command:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get pods<\/strong><\/em><\/p>\n<p>The output of the above command varies depending on how much time has passed after creating the Deployment. If you run it quickly after creation, the output will look like this:<\/p>\n\n<table id=\"tablepress-12\" class=\"tablepress tablepress-id-12\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">READY<\/th><th class=\"column-3\">STATUS<\/th><th class=\"column-4\">RESTARTS<\/th><th class=\"column-5\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">php-86d59fd666-bf8zd<\/td><td class=\"column-2\">0\/1<\/td><td class=\"column-3\">Init:0\/1<\/td><td class=\"column-4\">0<\/td><td class=\"column-5\">9s<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>The columns describe the following information:<\/p>\n<ul>\n<li><strong>Ready<\/strong>: The number of <strong>replicas<\/strong> running this pod.<\/li>\n<li><strong>Status<\/strong>: The status of the pod. <strong>Init<\/strong> indicates that the Init Containers are running. In this output, 0 out of 1 Init Containers have stopped running.<\/li>\n<li><strong>Restarts<\/strong>: How many times this process has restarted to start the pod. This number will increase if some of your Init Containers fail. The Deployment will restart it until it reaches the desired state.<\/li>\n<\/ul>\n<p>Based on the difficulty of your startup scripts, it can take a few minutes for the status to change to <strong>podInitializing<\/strong>:<\/p>\n\n<table id=\"tablepress-13\" class=\"tablepress tablepress-id-13\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">READY<\/th><th class=\"column-3\">STATUS<\/th><th class=\"column-4\">RESTARTS<\/th><th class=\"column-5\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">php-86d59fd666-lkwgn<\/td><td class=\"column-2\">0\/1<\/td><td class=\"column-3\">podInitializing<\/td><td class=\"column-4\">0<\/td><td class=\"column-5\">39s<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>This means the Init Containers have completed and the containers are initializing. If you run the command when all of the containers are running, you can see the pod status changed to <strong>Running<\/strong>.<\/p>\n\n<table id=\"tablepress-14\" class=\"tablepress tablepress-id-14\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">READY<\/th><th class=\"column-3\">STATUS<\/th><th class=\"column-4\">RESTARTS<\/th><th class=\"column-5\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">php-86d59fd666-lkwgn<\/td><td class=\"column-2\">1\/1<\/td><td class=\"column-3\">Running<\/td><td class=\"column-4\">0<\/td><td class=\"column-5\">1m<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>Now your pod is running successfully. In case your pod doesn&#8217;t start, you can debug with the commands mentioned below:<\/p>\n<ul>\n<li>Shows detailed information of a pod:<\/li>\n<\/ul>\n<p style=\"padding-left: 60px;\"><em><strong>kubectl describe pods <\/strong><span style=\"color: #ff0000;\">pod-name<\/span><\/em><\/p>\n<ul>\n<li>Shows logs generated by a pod:<\/li>\n<\/ul>\n<p style=\"padding-left: 60px;\"><em><strong>kubectl logs <\/strong><span style=\"color: #ff0000;\">pod-name<\/span><\/em><\/p>\n<ul>\n<li>Shows logs for a specific container in a pod:<\/li>\n<\/ul>\n<p style=\"padding-left: 60px;\"><em><strong>kubectl logs pod-name <\/strong><span style=\"color: #ff0000;\">container-name<\/span><\/em><\/p>\n<p>Your application code is mounted. The PHP-FPM service is now able to manage connections. Now you can create your Nginx Deployment.<\/p>\n<h2>STEP 5 &#8211; Creating the Nginx Deployment<\/h2>\n<p>In this last step, you will use <strong>ConfigMap<\/strong> to configure Nginx. A ConfigMap keeps your configuration in a key-value format that you can refer it in other Kubernetes object definitions. This manner will give you the flexibility to reuse or swap the image with a several Nginx versions if wanted. Updating the ConfigMap will automatically replicate the modifications to any pod mounting it.<\/p>\n<p>Create a <strong>nginx_configMap.yaml<\/strong> file for your ConfigMap with your editor:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>nano nginx_configMap.yaml<\/strong><\/em><\/p>\n<p>Name the <strong>ConfigMap nginx-config<\/strong> and arrange it into the <strong>tier: backend<\/strong> micro-service:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: ConfigMap<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: nginx-config<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p>Then, you have to add the <strong>data<\/strong> for the ConfigMap. Name the key <strong>config<\/strong> and add the contents of your Nginx configuration file as the value. You can refer the example Nginx configuration from this tutorial.<\/p>\n<p>As Kubernetes can route requests to the relevant host for a service. You can enter the name of your PHP-FPM service in the <strong>fastcgi_pass<\/strong> parameter rather than of its IP address. Add the following lines to your <strong>nginx_configMap.yaml<\/strong> file:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>data:<\/em><br \/>\n<em> config : |<\/em><br \/>\n<em> server {<\/em><br \/>\n<em> index index.php index.html;<\/em><br \/>\n<em> error_log \/var\/log\/nginx\/error.log;<\/em><br \/>\n<em> access_log \/var\/log\/nginx\/access.log;<\/em><br \/>\n<em> root ^\/code^;<\/em><\/p>\n<p style=\"padding-left: 60px;\"><em> location \/ {<\/em><br \/>\n<em> try_files $uri $uri\/ \/index.php?$query_string;<\/em><br \/>\n<em> }<\/em><\/p>\n<p style=\"padding-left: 60px;\"><em> location ~ \\.php$ {<\/em><br \/>\n<em> try_files $uri =404;<\/em><br \/>\n<em> fastcgi_split_path_info ^(.+\\.php)(\/.+)$;<\/em><br \/>\n<em> fastcgi_pass <span style=\"color: #ff0000;\">php:9000<\/span>;<\/em><br \/>\n<em> fastcgi_index index.php;<\/em><br \/>\n<em> include fastcgi_params;<\/em><br \/>\n<em> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;<\/em><br \/>\n<em> fastcgi_param PATH_INFO $fastcgi_path_info;<\/em><br \/>\n<em> }<\/em><br \/>\n<em> }<\/em><\/p>\n<p>Your <strong>nginx_configMap.yaml<\/strong> file will look similar to this:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: v1<\/em><br \/>\n<em>kind: ConfigMap<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: nginx-config<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em>data:<\/em><br \/>\n<em> config : |<\/em><br \/>\n<em> server {<\/em><br \/>\n<em> index index.php index.html;<\/em><br \/>\n<em> error_log \/var\/log\/nginx\/error.log;<\/em><br \/>\n<em> access_log \/var\/log\/nginx\/access.log;<\/em><br \/>\n<em> root <span style=\"color: #ff0000;\">\/code<\/span>;<\/em><\/p>\n<p style=\"padding-left: 60px;\"><em> location \/ {<\/em><br \/>\n<em> try_files $uri $uri\/ \/index.php?$query_string;<\/em><br \/>\n<em> }<\/em><\/p>\n<p style=\"padding-left: 60px;\"><em> location ~ \\.php$ {<\/em><br \/>\n<em> try_files $uri =404;<\/em><br \/>\n<em> fastcgi_split_path_info ^(.+\\.php)(\/.+)$;<\/em><br \/>\n<em> fastcgi_pass php:<span style=\"color: #ff0000;\">9000<\/span>;<\/em><br \/>\n<em> fastcgi_index index.php;<\/em><br \/>\n<em> include fastcgi_params;<\/em><br \/>\n<em> fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;<\/em><br \/>\n<em> fastcgi_param PATH_INFO $fastcgi_path_info;<\/em><br \/>\n<em> }<\/em><br \/>\n<em> }<\/em><\/p>\n<p>Save the file and exit the editor.<\/p>\n<p>Create the ConfigMap:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl apply -f nginx_configMap.yaml<\/strong><\/em><\/p>\n<p>You will see the following output:<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><br \/>\n<em>configmap\/nginx-config created<\/em><\/p>\n<p>You have finished creating your ConfigMap and you can now build your Nginx Deployment.<\/p>\n<p>Begin by opening a new <strong>nginx_deployment.yaml<\/strong> file in the editor:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>nano nginx_deployment.yaml<\/strong><\/em><\/p>\n<p>Specify Name the Deployment <strong>nginx<\/strong> and add the label <strong>tier: backend<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: apps\/v1<\/em><br \/>\n<em>kind: Deployment<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: nginx<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p>Define what you need one <strong>replicas<\/strong> in the Deployment <strong>spec<\/strong>. This Deployment will handle pods with labels <strong>app: nginx<\/strong> and <strong>tier: backend<\/strong>. Add the following parameters and values:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> replicas: 1<\/em><br \/>\n<em> selector:<\/em><br \/>\n<em> matchLabels:<\/em><br \/>\n<em> app: nginx<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p>Next, add the pod <strong>template<\/strong>. You have to use the same labels that you added for the Deployment <strong>selector.matchLabels<\/strong>. Add the below code:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> template:<\/em><br \/>\n<em> metadata:<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> app: nginx<\/em><br \/>\n<em> tier: backend<\/em><\/p>\n<p>Allow Nginx access to the <strong>code<\/strong> PVC that you created previously. Under <strong>spec.template.spec.volumes<\/strong>, add:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\">&#8230;<br \/>\nspec:<br \/>\nvolumes:<br \/>\n&#8211; name: code<br \/>\npersistentVolumeClaim:<br \/>\nclaimName: code<\/p>\n<p>Pods can mount a ConfigMap as a volume. Defining a file name and key will create a file with its value as the content. To use the ConfigMap, set <strong>path<\/strong> to the name of the file that will hold the contents of the <strong>key<\/strong>. You need to create a file <strong>site.conf<\/strong> from the key <strong>config<\/strong>. Under <strong>spec.template.spec.volumes<\/strong>, add the following lines:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\">&#8230;<br \/>\n&#8211; name: config<br \/>\nconfigMap:<br \/>\nname: nginx-config<br \/>\nitems:<br \/>\n&#8211; key: config<br \/>\npath: site.conf<\/p>\n<p><em><span style=\"color: #ff0000;\">Warning<\/span>: If a file is not defined, the contents of the key will replace the <strong>mountPath<\/strong> of the volume. This means that if a path is not specified in a clear and detailed manner, you will lose all content in the target folder.<\/em><\/p>\n<p>Next, you will define the image to build your pod from. This tutorial will use the <strong>nginx:1.7.9<\/strong> image for durability, but you can discover other Nginx images at <a href=\"https:\/\/hub.docker.com\/explore\/\" target=\"_blank\" rel=\"nofollow noopener\">Docker store<\/a>. Also, make Nginx accessible on port 80. Under <strong>spec.template.spec<\/strong> add:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_deployment.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> containers:<\/em><br \/>\n<em> &#8211; name: nginx<\/em><br \/>\n<em> image: <span style=\"color: #ff0000;\">nginx:1.7.9<\/span><\/em><br \/>\n<em> ports:<\/em><br \/>\n<em> &#8211; containerPort: 80<\/em><\/p>\n<p>Nginx and PHP-FPM require to access the file at the same path, so mount the <strong>code<\/strong> volume at <strong>\/code<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> volumeMounts:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> mountPath: \/code<\/em><\/p>\n<p>Under the <strong>\/etc\/nginx\/conf.d<\/strong> directory, the <strong>nginx:1.7.9<\/strong> image will automatically load any configuration files. In this directory will create the file <strong>\/etc\/nginx\/conf.d\/site.conf<\/strong> by mounting the <strong>config<\/strong> volume. Add the following lines under <strong>volumeMounts<\/strong>:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>&#8230;<\/em><br \/>\n<em> &#8211; name: config<\/em><br \/>\n<em> mountPath: \/etc\/nginx\/conf.d<\/em><\/p>\n<p>Your <strong>nginx_deployment.yaml<\/strong> file will look similar to this:<\/p>\n<p style=\"text-align: center;\"><strong>nginx_configMap.yaml<\/strong><\/p>\n<p style=\"padding-left: 60px;\"><em>apiVersion: apps\/v1<\/em><br \/>\n<em>kind: Deployment<\/em><br \/>\n<em>metadata:<\/em><br \/>\n<em> name: nginx<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em>spec:<\/em><br \/>\n<em> replicas: 1<\/em><br \/>\n<em> selector:<\/em><br \/>\n<em> matchLabels:<\/em><br \/>\n<em> app: nginx<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em> template:<\/em><br \/>\n<em> metadata:<\/em><br \/>\n<em> labels:<\/em><br \/>\n<em> app: nginx<\/em><br \/>\n<em> tier: backend<\/em><br \/>\n<em> spec:<\/em><br \/>\n<em> volumes:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> persistentVolumeClaim:<\/em><br \/>\n<em> claimName: code<\/em><br \/>\n<em> &#8211; name: config<\/em><br \/>\n<em> configMap:<\/em><br \/>\n<em> name: nginx-config<\/em><br \/>\n<em> items:<\/em><br \/>\n<em> &#8211; key: config<\/em><br \/>\n<em> path: site.conf<\/em><br \/>\n<em> containers:<\/em><br \/>\n<em> &#8211; name: nginx<\/em><br \/>\n<em> image: <span style=\"color: #ff0000;\">nginx:1.7.9<\/span><\/em><br \/>\n<em> ports:<\/em><br \/>\n<em> &#8211; containerPort: 80<\/em><br \/>\n<em> volumeMounts:<\/em><br \/>\n<em> &#8211; name: code<\/em><br \/>\n<em> mountPath: \/code<\/em><br \/>\n<em> &#8211; name: config<\/em><br \/>\n<em> mountPath: \/etc\/nginx\/conf.d<\/em><\/p>\n<p>Save the file and exit the editor.<\/p>\n<p>Create the Nginx Deployment:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl apply -f nginx_deployment.yaml<\/strong><\/em><\/p>\n<p>Now your Deployment is created. Here is the output:<\/p>\n<p style=\"padding-left: 30px;\"><strong>Output<\/strong><br \/>\n<em>deployment.apps\/nginx created<\/em><\/p>\n<p>List your Deployments with running the following command:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get deployments<\/strong><\/em><\/p>\n<p>The following output indicates Nginx and PHP-FPM Deployments:<\/p>\n<p><strong>Output<\/strong><\/p>\n\n<table id=\"tablepress-15\" class=\"tablepress tablepress-id-15\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">DESIRED<\/th><th class=\"column-3\">CURRENT<\/th><th class=\"column-4\">UP-TO-DATE<\/th><th class=\"column-5\">AVAILABLE<\/th><th class=\"column-6\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">nginx<\/td><td class=\"column-2\">1<\/td><td class=\"column-3\">1<\/td><td class=\"column-4\">1<\/td><td class=\"column-5\">0<\/td><td class=\"column-6\">16s<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">php<\/td><td class=\"column-2\">1<\/td><td class=\"column-3\">1<\/td><td class=\"column-4\">1<\/td><td class=\"column-5\">1<\/td><td class=\"column-6\">7m<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>List the pods managed by both of the Deployments:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get pods<\/strong><\/em><\/p>\n<p>You can see the pods that are running in the following output:<\/p>\n<p><strong>Output<\/strong><\/p>\n\n<table id=\"tablepress-16\" class=\"tablepress tablepress-id-16\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">READY<\/th><th class=\"column-3\">STATUS<\/th><th class=\"column-4\">RESTARTS<\/th><th class=\"column-5\">AGE<\/th>\n<\/tr>\n<\/thead>\n<tbody class=\"row-striping row-hover\">\n<tr class=\"row-2\">\n\t<td class=\"column-1\">nginx-7bf5476b6f-zppml<\/td><td class=\"column-2\">1\/1<\/td><td class=\"column-3\">Running<\/td><td class=\"column-4\">0<\/td><td class=\"column-5\">32s<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">php-86d59fd666-lkwgn<\/td><td class=\"column-2\">1\/1<\/td><td class=\"column-3\">Running<\/td><td class=\"column-4\">0<\/td><td class=\"column-5\">7m<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>Now that all of the Kubernetes objects are ready, you can hit the Nginx service at your browser.<\/p>\n<p>List the running services:<\/p>\n<p style=\"padding-left: 30px;\"><em><strong>kubectl get services -o wide<\/strong><\/em><\/p>\n<p>Get the External IP for your Nginx service:<\/p>\n\n<table id=\"tablepress-17\" class=\"tablepress tablepress-id-17\">\n<thead>\n<tr class=\"row-1\">\n\t<th class=\"column-1\">NAME<\/th><th class=\"column-2\">TYPE<\/th><th class=\"column-3\">CLUSTER-IP<\/th><th class=\"column-4\">EXTERNAL-IP<\/th><th class=\"column-5\">PORT(S)<\/th><th class=\"column-6\">AGE<\/th><th class=\"column-7\">SELECTOR<\/th>\n<\/tr>\n<\/thead>\n<tbody>\n<tr class=\"row-2\">\n\t<td class=\"column-1\">kubernetes<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.96.0.1 <\/td><td class=\"column-4\">None<\/td><td class=\"column-5\">443\/TCP<\/td><td class=\"column-6\">39m<\/td><td class=\"column-7\">None<\/td>\n<\/tr>\n<tr class=\"row-3\">\n\t<td class=\"column-1\">nginx<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.102.160.47<\/td><td class=\"column-4\">your_public_ip<\/td><td class=\"column-5\">80\/TCP<\/td><td class=\"column-6\">27m<\/td><td class=\"column-7\">app=nginx,tier=backend<\/td>\n<\/tr>\n<tr class=\"row-4\">\n\t<td class=\"column-1\">php<\/td><td class=\"column-2\">ClusterIP<\/td><td class=\"column-3\">10.100.59.238<\/td><td class=\"column-4\">None<\/td><td class=\"column-5\">9000\/TCP<\/td><td class=\"column-6\">34m<\/td><td class=\"column-7\">app=php,tier=backend<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n\n<p>At your browser, visit your server by typing in <em>http:\/\/<span style=\"color: #ff0000;\">your_public_ip<\/span><\/em>. You will see the output of <strong>php_info()<\/strong> and have verified that your Kubernetes services are live and running.<\/p>\n<h3>Conclusion<\/h3>\n<p>In this step-by-step guide, you containerized the PHP-FPM and Nginx services so that you can manage them independently. This approach enhances the scalability of your project as you grow as well as allows you to efficiently use resources. You also can save your application code on a volume so that you will simply update your services in the future.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Introduction Kubernetes (K8s) is a portable, extensible open-source container orchestration platform to manage containerized workloads and services, that makes easier declarative configuration deployment, scaling and automation. K8s lets you create, update and scale containers without worrying about server downtime. Nginx acts as a proxy to PHP-FPM when running a PHP application. It can be a [&hellip;]<\/p>\n","protected":false},"author":19,"featured_media":7019,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[676,677,678],"class_list":["post-6986","post","type-post","status-publish","format-standard","has-post-thumbnail","placeholder-for-hentry","category-howtos","tag-kubernetes","tag-php-deployment","tag-ubuntu-16-04"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.1.1 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>PHP Application Deployment with Kubernetes on Ubuntu 16.04 - Web Hosting FAQs by MilesWeb<\/title>\n<meta name=\"description\" content=\"In this KB article, you will learn about how to deploy a PHP 7 application on Kubernetes cluster with PHP-FPM and Nginx running in separate containers.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"PHP Application Deployment with Kubernetes on Ubuntu 16.04 - Web Hosting FAQs by MilesWeb\" \/>\n<meta property=\"og:description\" content=\"In this KB article, you will learn about how to deploy a PHP 7 application on Kubernetes cluster with PHP-FPM and Nginx running in separate containers.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/\" \/>\n<meta property=\"og:site_name\" content=\"Web Hosting FAQs by MilesWeb\" \/>\n<meta property=\"article:published_time\" content=\"2019-05-13T14:02:15+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2022-02-19T10:52:57+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif\" \/>\n\t<meta property=\"og:image:width\" content=\"637\" \/>\n\t<meta property=\"og:image:height\" content=\"403\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/gif\" \/>\n<meta name=\"author\" content=\"Ajit\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ajit\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"19 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/\"},\"author\":{\"name\":\"Ajit\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/7cd39cafedd7652b49b849e5e331cd48\"},\"headline\":\"PHP Application Deployment with Kubernetes on Ubuntu 16.04\",\"datePublished\":\"2019-05-13T14:02:15+00:00\",\"dateModified\":\"2022-02-19T10:52:57+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/\"},\"wordCount\":4571,\"commentCount\":0,\"image\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif\",\"keywords\":[\"Kubernetes\",\"PHP Deployment\",\"Ubuntu 16.04\"],\"articleSection\":[\"How-Tos\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/\",\"url\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/\",\"name\":\"PHP Application Deployment with Kubernetes on Ubuntu 16.04 - Web Hosting FAQs by MilesWeb\",\"isPartOf\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif\",\"datePublished\":\"2019-05-13T14:02:15+00:00\",\"dateModified\":\"2022-02-19T10:52:57+00:00\",\"author\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/7cd39cafedd7652b49b849e5e331cd48\"},\"description\":\"In this KB article, you will learn about how to deploy a PHP 7 application on Kubernetes cluster with PHP-FPM and Nginx running in separate containers.\",\"breadcrumb\":{\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage\",\"url\":\"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif\",\"contentUrl\":\"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif\",\"width\":637,\"height\":403,\"caption\":\"How To Deploy a PHP Application with Kubernetes on Ubuntu 16.04\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/www.milesweb.in\/hosting-faqs\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"PHP Application Deployment with Kubernetes on Ubuntu 16.04\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/#website\",\"url\":\"https:\/\/www.milesweb.in\/hosting-faqs\/\",\"name\":\"Web Hosting FAQs by MilesWeb\",\"description\":\"\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/www.milesweb.in\/hosting-faqs\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/7cd39cafedd7652b49b849e5e331cd48\",\"name\":\"Ajit\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/image\/\",\"url\":\"https:\/\/secure.gravatar.com\/avatar\/6d48014b3dcf0691486425b0f8443591d31e1e2f623206cd11a25fdffa417819?s=96&d=blank&r=g\",\"contentUrl\":\"https:\/\/secure.gravatar.com\/avatar\/6d48014b3dcf0691486425b0f8443591d31e1e2f623206cd11a25fdffa417819?s=96&d=blank&r=g\",\"caption\":\"Ajit\"},\"description\":\"With over 8+ years of experience in the digital marketing industry, I have achieved extensive exposure to result-oriented methodologies. And expertise in different domains like Datacentre Services, Cloud computing technology, Web hosting industry and many more.\",\"url\":\"https:\/\/www.milesweb.in\/hosting-faqs\/author\/ajit\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"PHP Application Deployment with Kubernetes on Ubuntu 16.04 - Web Hosting FAQs by MilesWeb","description":"In this KB article, you will learn about how to deploy a PHP 7 application on Kubernetes cluster with PHP-FPM and Nginx running in separate containers.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/","og_locale":"en_US","og_type":"article","og_title":"PHP Application Deployment with Kubernetes on Ubuntu 16.04 - Web Hosting FAQs by MilesWeb","og_description":"In this KB article, you will learn about how to deploy a PHP 7 application on Kubernetes cluster with PHP-FPM and Nginx running in separate containers.","og_url":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/","og_site_name":"Web Hosting FAQs by MilesWeb","article_published_time":"2019-05-13T14:02:15+00:00","article_modified_time":"2022-02-19T10:52:57+00:00","og_image":[{"width":637,"height":403,"url":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif","type":"image\/gif"}],"author":"Ajit","twitter_misc":{"Written by":"Ajit","Est. reading time":"19 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#article","isPartOf":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/"},"author":{"name":"Ajit","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/7cd39cafedd7652b49b849e5e331cd48"},"headline":"PHP Application Deployment with Kubernetes on Ubuntu 16.04","datePublished":"2019-05-13T14:02:15+00:00","dateModified":"2022-02-19T10:52:57+00:00","mainEntityOfPage":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/"},"wordCount":4571,"commentCount":0,"image":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage"},"thumbnailUrl":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif","keywords":["Kubernetes","PHP Deployment","Ubuntu 16.04"],"articleSection":["How-Tos"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/","url":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/","name":"PHP Application Deployment with Kubernetes on Ubuntu 16.04 - Web Hosting FAQs by MilesWeb","isPartOf":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage"},"image":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage"},"thumbnailUrl":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif","datePublished":"2019-05-13T14:02:15+00:00","dateModified":"2022-02-19T10:52:57+00:00","author":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/7cd39cafedd7652b49b849e5e331cd48"},"description":"In this KB article, you will learn about how to deploy a PHP 7 application on Kubernetes cluster with PHP-FPM and Nginx running in separate containers.","breadcrumb":{"@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#primaryimage","url":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif","contentUrl":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-content\/uploads\/2019\/05\/How-To-Deploy-a-PHP-Application-with-Kubernetes-on-Ubuntu-16.04.gif","width":637,"height":403,"caption":"How To Deploy a PHP Application with Kubernetes on Ubuntu 16.04"},{"@type":"BreadcrumbList","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/php-application-deployment-kubernetes-ubuntu-16-04\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.milesweb.in\/hosting-faqs\/"},{"@type":"ListItem","position":2,"name":"PHP Application Deployment with Kubernetes on Ubuntu 16.04"}]},{"@type":"WebSite","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/#website","url":"https:\/\/www.milesweb.in\/hosting-faqs\/","name":"Web Hosting FAQs by MilesWeb","description":"","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.milesweb.in\/hosting-faqs\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/7cd39cafedd7652b49b849e5e331cd48","name":"Ajit","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.milesweb.in\/hosting-faqs\/#\/schema\/person\/image\/","url":"https:\/\/secure.gravatar.com\/avatar\/6d48014b3dcf0691486425b0f8443591d31e1e2f623206cd11a25fdffa417819?s=96&d=blank&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/6d48014b3dcf0691486425b0f8443591d31e1e2f623206cd11a25fdffa417819?s=96&d=blank&r=g","caption":"Ajit"},"description":"With over 8+ years of experience in the digital marketing industry, I have achieved extensive exposure to result-oriented methodologies. And expertise in different domains like Datacentre Services, Cloud computing technology, Web hosting industry and many more.","url":"https:\/\/www.milesweb.in\/hosting-faqs\/author\/ajit\/"}]}},"_links":{"self":[{"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/posts\/6986","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/users\/19"}],"replies":[{"embeddable":true,"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/comments?post=6986"}],"version-history":[{"count":10,"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/posts\/6986\/revisions"}],"predecessor-version":[{"id":16295,"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/posts\/6986\/revisions\/16295"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/media\/7019"}],"wp:attachment":[{"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/media?parent=6986"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/categories?post=6986"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.milesweb.in\/hosting-faqs\/wp-json\/wp\/v2\/tags?post=6986"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}