Laptop - Development enviroment

Development environment on Kubernetes


Make sure that you've taken a look at the following tutorial(s) before you continue:

In this tutorial example.com will be used for project's domain name and example for project name and some prefixes. Commands presented in this tutorial should be executed from the root of tutorial's git repository.

By now you should have your secure WordPress website up and running. 

You are going to learn

  • how to create persistent disk from a snapshot
  • how to make a duplicate of production database
  • how to run development environment under a subdomain
  • how to secure access to development environment with HTTP Basic

Development environment – training ground for code

Gosh wouldn’t it be nice to have your own development environment running in a separate container ? To have a place where you can test your code and make it better before the world sees it. Learn how to create development environment in minutes.

1
Create new persistent disk from WordPress snapshot

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

Google Compute Engine allows for taking persistent disk snapshots. Creating snapshots from persistent disks is possible even while they are attached to a running instance. You can use that snapshot as a source when you create another persistent disk.

Development environment will use different disk than production. Files from production need to be transferred to that new device. The easiest way to do that is to create a new disk based on the snapshot of your production disk. Snapshot's size depends on the amount of the data that you have on your disk.

Go to Google Cloud PlatformCompute EngineSnapshots. Click Create snapshot at the top of the page. Create a snapshot of your WordPress disk. Disk snapshot creation is also possible using the command line.

gcloud compute --project "PROJECT_NAME" disks snapshot "DISK_NAME" --zone "ZONE_NAME" --snapshot-names "SNAPSHOT_NAME"

Create persistent disk from snapshot. For the name of development environment disk just prefix name of source disk with dev-  eg. dev-example-wordpress

If you want to create disk of lower capacity than 10GB then you will have to use command line. Otherwise you can use Google Cloud Platform Console.

Go to Google Cloud PlatformCompute EngineDisks. At the top click Create disk. Now under Source type you have to click Snapshot tab and select your snapshot. Set size, zone, name and other parameters according to your needs. Choose cheaper disk type option:

Disk Type: Standard persistent disk

You can also use command line

gcloud compute --project=GCP_PROJECT_NAME disks create DISK_NAME --zone=ZONE_NAME --type=pd-standard --source-snapshot=SNAPSHOT_NAME

This is a nice and clean way to create a copy of your production data. You are also making a backup of your WordPress production files at the same time.

Exact copy of your production environment files is on a new disk. Next steps are going to show you how to configure development environment to use that disk. This takes care of the WordPress files transfer from production to your development environment.

Step notes

When you are using Google Cloud Platform Console look at the bottom of the page for Equivalent REST or command line. You can usually get the command that corresponds to specific Google Cloud Platform action or an equivalent REST call.

You can add labels to your snapshots to organize them eg. environment: prod

2
Create development database

Reliability: HighUpdated: 28 October 2017CopiedBookmarkedBookmark removed

The same MySQL Deployment will be used for both production and development environment. All we need to do is copy the production database to some separate development database with a different name. Development environment should use its own database user for security reasons.

kubectl exec -it POD_NAME -- bash -l
mysql -uroot -hwordpress-mysql -p

Create development database and user. For name of the database use production database name prefixed with dev_. Give development user all privileges to that database. Do not use the same name for user and database (WP CLI has problems if you do).

CREATE USER 'dev_username_here'@'%' IDENTIFIED WITH mysql_native_password BY 'dev_password_here';
CREATE DATABASE IF NOT EXISTS dev_example DEFAULT CHARACTER SET utf8 COLLATE utf8_bin;
GRANT ALL PRIVILEGES ON dev_example.* TO 'dev_username_here'@'%';
SHOW GRANTS FOR 'dev_username_here'@'%';
FLUSH PRIVILEGES;

Development environment WordPress is going to use it's own database and connect to it with different credentials than production environment.

Database is ready but it's still empty. Let's transfer data from production to our development database.

mysqldump -uPROD_USERNAME -hwordpress-mysql -p example > example.sql

mysql -uDEV_USERNAME -hwordpress-mysql -p dev_example < example.sql

All the production data has been transferred to development database.

3
Create Config Map and Secrets

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

Edit k8s/wordpress/dev-configmap.yaml and adjust it to fit your needs before creating the Config Map. First find and replace example.com with your domain name and then do the same for example and your project name. Make sure that you use development database name in DB_NAME. Since you are creating a Config Map for development environment you will probably want to enable WP_DEBUG and WP_DEBUG_LOG. When modifications are done create Config Map.

kubectl apply -f k8s/wordpress/dev-configmap.yaml

You need to turn newly created MySQL credentials into a Secret. Encode username and password using base64.

echo -n "username_or_pass" | base64 -w 0
    OR
echo -n "username_or_pass" | base64 | tr -d '\n'

Paste resulting strings inside k8s/wordpress/dev-db-secret.yaml file. Replace example in the name of the Secret and create it afterwards.

kubectl apply -f k8s/wordpress/dev-db-secret.yaml

Use bash script I've created to generate a file containing Secret with WordPress key and salt values in base64 encoded form.

chmod +x k8s_wp_salt_secret.sh
./k8s_wp_salt_secret.sh

Contents of data section from the resulting file should go inside k8s/wordpress/dev-secret.yaml. Modify the name of the Secret to match the pattern dev-PROJECT_NAME-wp-secret and create it. Deployment will look for this Secret under a name like that.

kubectl apply -f k8s/wordpress/dev-secret.yaml

4
Create Persistent Volume and Claim

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

First of all you need to let Persistent Volume know which persistent disk development environment should use. Modify k8s/wordpress/dev-volume.yaml. Find and replace example with your project name. Put the name of development disk in pdName. Remember that if you changed Namespace name then you should reflect it inside k8s/wordpress/dev-volume.yaml before you create Persistent Volume.

gcePersistentDisk:
 pdName: DEV_WORDPRESS_DISK_NAME
 fsType: ext4

Create and view Persistent Volume for development environment.

kubectl apply -f k8s/wordpress/dev-volume.yaml
kubectl get pv

Create and view Persistent Volume Claim for your Persistent Volume

kubectl apply -f k8s/wordpress/dev-volume-claim.yaml
kubectl get pvc

5
Create Deployment

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

Edit k8s/wordpress/dev-deployment.yaml file. First find and replace example.com with your domain name and then do the same for example and your project name.

If you have GitLab deploy keys configured then uncomment two sections named ssh-keys (Git authorization automation).

Deployment uses image tagged with v1.0.1. Modify version to fit your container registry pushed image.

image: registry.gitlab.com/USERNAME/PROJECT_NAME/wordpress:v1.0.1

Notice that app and tier label values have stayed the same but env label value has changed and is now dev. Those labels will be used by the Services to distinguish production Deployment from development Deployment.

Create Deployment for the development environment.

kubectl apply -f k8s/wordpress/dev-deployment.yaml

Deployment will become available after some time if everything goes well.

kubectl get pod
kubectl get deployment
kubectl describe pod POD_NAME
kubectl describe deployment DEPLOYMENT_NAME

Step notes

It is a smart move to deactivate some plugins on development environment. You probably do not need caching plugins. Some plugins like Jetpack should be deactivated as soon as possible. If they contact their server then you might have some fixing/re-configuration to do.

6
Create subdomain for development environment

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

Connect to the Pod created by the Deployment and run bash login shell. If you followed naming convention of this tutorial then the Pod's name should start with dev-Verify that you are on development environment Pod

kubectl exec -it DEV_POD_NAME -- bash -l
uname -n

If you are on development environment Pod then search and replace site's URL. Do a dry run first. Do not use login shell for WP CLI (no -l after su). Substitute example.com with your domain name.

su deployer
cd /usr/src/wordpress
wp search-replace example.com dev.example.com --dry-run
wp search-replace example.com dev.example.com

Edit k8s/wordpress/dev-service.yaml. Find and replace example with your project name. Create the Service.

kubectl apply -f k8s/wordpress/dev-service.yaml

Add development environment entries to the Ingress based on two commented sections in k8s/wordpress/ingress.yaml. Just uncomment them and then copy and paste their content to edited Ingress. Be careful to keep YAML formatting in order. Replace example.com with your domain name and example with your project name.

Editor used is based on the value of EDITOR environment variable. You can also change editor by hand by setting KUBE_EDITOR before you run the command

kubectl edit ingress wordpress-ingress
KUBE_EDITOR="nano" kubectl edit ingress wordpress-ingress

If you view kube-lego logs then you will notice that your current certificate does not cover new sub-domain and new certificate is requested by kube-lego.

kubectl logs --namespace=kube-lego KUBE_LEGO_POD_NAME -f

time="2017-08-08T20:19:58Z" level=info msg="cert does not cover all domains" context="ingress_tls" 
domains=[example.com www.example.com dev.example.com] name=wordpress-ingress namespace=main

Visit https://dev.example.com

7
HTTP Basic authentication for development environment

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

You don't want just anyone to have access to your development environment if they guess the subdomain name. You can secure access with HTTP Basic quite easily. Multiple users can be created and given access to your development environment should they ever need it.

Create auth file with all the users that will have access to development environment

htpasswd -c auth SOME_USERNAME

Add another user to the same auth file

htpasswd auth SOME_OTHER_USERNAME

Encode auth file using base64 and create a Secret containing it by modifying k8s/wodrpress/dev-auth-secret.yaml file. Change the name of the Secret to reflect your project name

base64 auth
kubectl apply -f k8s/wodrpress/dev-auth-secret.yaml

You need to mount the Secret as a volume inside development Deployment. Modify k8s/wodrpress/dev-deployment.yaml. Uncomment two sections named auth-secret Change secretName to match the one you've created before.

Re-create the Deployment

kubectl delete deployment DEPLOYMENT_NAME
kubectl apply -f k8s/wordpress/dev-deployment.yaml

Connect to the Pod running your development environment

kubectl exec -it DEV_POD_NAME -- bash -l
nano /etc/nginx/conf.d/wordpress.conf

Uncomment auth_basic and auth_basic_user_file lines inside location / { ... } block.

Save changes and restart nginx

nginx -s reload

Your site should be secured with HTTP Basic. Use credentials that you've created in the auth file.

Step notes

Remember that you will have to modify nginx configuration and reload it on each development Deployment creation to have HTTP Basic authentication

8
How to re-create development environment(Optional)

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

In order to get the current version of production environment on your development environment do the following.

Make a snapshot of the production persistent disk.

gcloud compute --project "example" disks snapshot "PRODUCTION_DISK_NAME" --zone "ZONE_NAME" --snapshot-names "SNAPSHOT_NAME"

Re-import the database. This needs to be done from development environment Pod. DROP statements are included in the dump so this will replace every table in development database.

kubectl exec -it DEVELOPMENT_POD_NAME -- bash -l
mysqldump -uroot -hwordpress-mysql -p example > example.sql
mysql -uDEV_USERNAME -hwordpress-mysql -p dev_example < example.sql

Search and replace site's URL

su deployer
cd /usr/src/wordpress
wp search-replace example.com dev.example.com --dry-run
wp search-replace example.com dev.example.com

Delete development Deployment

kubectl delete deployment DEVELOPMENT_DEPLOYMENT_NAME

Do not make a mistake here! Focus! Delete development environment persistent disk. Do not touch your production disk

gcloud compute --project "example" disks delete "DEVELOPMENT_DISK_NAME" --zone "ZONE_NAME"

Re-create the disk using newly made snapshot. Size of the disk needs to be at least what production persistent disk has assigned.

gcloud compute --project "example" disks create "DEVELOPMENT_DISK_NAME" --source-snapshot=SNAPSHOT_NAME --size=5GB --zone "ZONE_NAME"
kubectl apply -f k8s/wordpress/dev-deployment.yaml

9
How to remove development environment(Optional)

Reliability: HighUpdated: 1 October 2017CopiedBookmarkedBookmark removed

Delete development Deployment

kubectl delete deployment DEPLOYMENT_NAME

Delete development environment Persistent Volume and Persistent Volume Claim

kubectl delete pv PV_NAME
kubectl delete pvc PVC_NAME

Delete development Service

kubectl delete service SERVICE_NAME

Remove entry for development environment from the Ingress

kubectl edit ingress wordpress-ingress
KUBE_EDITOR="nano" kubectl edit ingress wordpress-ingress

Do not make a mistake here! Focus! Delete development environment persistent disk. Do not touch your production disk

gcloud compute --project "example" disks delete "DEVELOPMENT_DISK_NAME" --zone "ZONE_NAME"

Good job. You deserve a bottle of Grog. Arrrr !
Success ! Let's open a case of Rum. Arrrr !
New skills gained. Beers all around! Arrrr !
Thanks for reading ! Please
  •  
  •  
  • 1
  •  
  •  
  •  
  •  
  •  

Leave a comment

Your email address will not be published. Required fields are marked *