Make sure that you've taken a look at the following tutorial(s) before you continue:
- - First steps
- $300 free trial. How to use it wisely ?
- Let's get MySQL up and running on Kubernetes
- Let's get WordPress up and running on Kubernetes
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 MySQL and WordPress Deployments up and running. MySQL Deployment should have a corresponding Service. WordPress Deployment should have no Service. If Load Balancer Service from the previous part of this tutorial series still exists then delete it now.
You are going to need a domain. There are ways to get a free one
You are going to learn
- how to point your domain to a Service inside your cluster
- how to setup DNS records using Cloudflare or Google Cloud DNS API
- how to secure your website with free Let's Encrypt SSL/TLS certificate with auto-renewal using kube-lego
- how to create your own nginx based LoadBalancer
- how to create an Ingress
- how to install WordPress on Kubernetes and have a SSL/TLS secured site up and running
- how to create persistent disk snapshot
- Serve SSL/TLS secured web application from your Kubernetes cluster
- 1Create Service for WordPress
- 2Controll the cost of Load Balancing with nginx Ingress controller
- 3Configure DNS records for your domain
- 4Free self-renewing SSL certificate with kube-lego
- 5Create an Ingress and install WordPress
- 6Backup strategies for your WordPress website
- 7Remove Mixed-Content warning
- 8Turn on Cloudflare's HTTP proxy
Serve SSL/TLS secured web application from your Kubernetes cluster
This tutorial will teach you how to secure your application and host it in your cluster. You are going to create a Load Balancer and learn how to point your domain to your cluster with Domain Name Server. If you choose you can use Cloudflare which can increase security and reduce you server’s load thus saving you even more money in the long run. Backup strategies are also mentioned along the way.
This has no type declaration so it will have default type assigned which is
NodePort. Creating it will not provision Google's Load Balancer unlike the one from the previous part of the tutorial. Modify
k8s/wordpress/service.yaml. Find and replace example with your project name.
I will repeat here what was said about Load Balancers in the earlier part of the tutorial series. When a Load Balancer is created additional charges start applying. Google charges you for something called Network Load Balancing: Forwarding Rule Minimum Service Charge. Monthly cost of this is about the same as the cost of one g1-small instance. Take notice of the word "Minumum" there. Basically it means that if you have five forwarding rules or less you pay about $20 a month (quite steep in my opinion). If you have more than five then additional charges kick in.
You can avoid exceeding five forwarding rules limit by setting up your own Load Balancer. Thanks to nginx Ingresss controller you can have many different domains pointing to various Services in your cluster while still using only one forwarding rule.
Create nginx Ingress controller resources
Now get the IP of your Load Balancer. We will use it inside A type record on the DNS of your choice. Cloudflare and Google Cloud DNS based solutions are presented below.
LoadBalancer Ingress: 18.104.22.168
You can use Google Cloud DNS API for it or alternatively DNS. If you decide to use Google Cloud DNS API then you will have to create a Managed Zone. There is some little cost connected to setting up and maintaining your own Managed Zone. In my case it's been about 20 cents per month per domain. If you do not want to pay for Google's DNS services you can use Cloudflare's services instead but you will have to sign up for it first. Cloudflare brings some other extremely useful functionalities to the table so I suggest signing up for it.
Configure Cloudflare DNS
Configuring Cloudflare's DNS is as easy as falling off a log. Once you sign up for the account you can add your site. Cloudflare will ask you to configure your domain provider to use external DNS servers which addresses Cloudflare will provide to you. Once it's done go to CloudflareDNS.
Add A type record for your domain. Use the LoadBalancer Ingress IP address that you retrieved using
Add two CNAME type records for sub-domains www and dev.
There is a button next to the records (orange or grey cloud) under Status column. It changes the settings of Cloudflare's HTTP proxy. We can decide if we want to use only the Cloudflare's DNS or if we want to use their HTTP proxy (CDN) as well.
In order to make it work:
- with HTTP proxy turned Off change CloudflareCryptoSSL setting to Off
- with HTTP proxy turned On change CloudflareCryptoSSL setting to Full
For now you should probably turn off Cloudflare's HTTP proxy for all A nad CNAME records you've added and set SSL to Off. You will turn it on after everything else is set up.
Configure Google Cloud DNS API
Alternatively to Cloudflare you can use Google Cloud DNS. Go to Google Cloud PlatformAPI Manager and enable Google Cloud DNS API
You can use Google Cloud PlatformNetwork ServicesCloud DNS to create a Managed Zone. You can also use the command line
Configure your domain provider to use external DNS servers. Use name server addresses returned by the command above.
Verify if you've been redirected (should happen within 120 sec). Verification for ns-cloud-d2.googledomains.com would look like this:
Ctrl+C to stop watching
If you wanted to verify that your Service is up and reachable using your domain then you could create an Ingress without TLS but you would have to delete it afterwards. If you ever need to do that use
Reliability of this step is Medium because with DNS things sometimes get a bit complicated. When something did not work for me I tried different settings, clicked here, changed something there. In the end I got it working twice so step instructions should be accurate.
kube-lego is a nice piece of software that simplifies developer's life. It will connect to Let's Encrypt and automatically requests certificates domain defined in your . It only takes into account an Ingress which has
kubernetes.io/tls-acme: "true" annotation. kube-lego checks all namespaces in the cluster.
kube-lego Deployment additionally creates a Service on its own.
Check if kube-lego Pod is present
Notice that in
k8s/kube-lego/deployment.yaml version 0.1.3 of kube-lego is used. I've tried 0.1.5 and encountered some problems. I did not have time to investigate. This is why reliability of this step is Medium
Now a new type of resource called needs to be created. Ingress is best described as a collection of rules that allow inbound connections to reach the Services in your cluster. Service we want to expose has to be of
NodePort type. WordPress Service is exactly that type.
You can tell Kubernetes which type of Ingress should be created using annotations. Annotations are just another way of attaching metadata to objects. Similar in their role to labels but with a different purpose.
Ingress that will direct connections to your Service has to have annotation
kubernetes.io/ingress.class: "nginx" This annotation will tell nginx Ingress controller to take care of that Ingress.
You also want kube-lego to notice that Ingress and do some work on it. Second annotation that the Ingress has to have is
It always takes some time after Ingress creation for things to start working.
In one terminal view the logs of kube-lego Pod with
-f stands for follow - Logs are streamed and output is appended as files grow.
After a while a Secret with the name specified inside
k8s/wordpress/ingress.yaml should be created by kube-lego. By viewing logs of kube-lego you can examine if there are any problems with getting the certificate from Let's Encrypt.
Now finally go to type your domain name in your browser and press Enter. You should get WordPress installation page. CSS styles are probably gone but do not worry about it at all. Mixed-Content warning is fixed in next steps.
Just install WordPress as you would normally do it. First choose your language. On the next screen enter the name of the site, your admin username and password and you're done. Visit your domain again to see a clean WordPress site.
You now have a SSL secured WordPress website that is running on your Kubernetes controlled cluster in the cloud.
Remember that adding new (sub)domains to Let's Encrypt should never ever be done in a batch.
Let's Encrypt has a Rate Limits. If you exceed them it will be a huge pain in the ...
In my experience it's very easy to exceed Failed Validation limit and you get an error like this:
level=warning msg="authorization failed after 1m0s: getting authorization failed: 429 urn:acme:error:rateLimited: Error creating new authz :: Too many invalid authorizations recently."
If you wish to avoid this error you should add/uncomment domain entries inside your
k8s/wordpress/ingress.yaml no more than two or three at a time. Failed Validation limit should reset after (about) an hour. You may have to delete kube-lego Deployment to stop hitting Let's Encrypt servers. Check kube-lego logs to examine what is going on.
There is another Rate Limit which when exceeded may have some nasty consequences. I have in mind the main limit which is Certificates per Registered Domain limit of 20 per week.
Do not exceed it. Ever ! You can view the status of this limit using
lectl script. lectl on GitHub
Just download the
lectl file and run it
You can also use Cloudflare's PKI/TLS toolkit to view certificate information. cfssl on GitHub
If you use Cloudflare and your SSL is turned on then you might see a shared certificate as the result of the last command instead of the one from Let’s Encrypt. You will probably see a lot of other domain names next to your own in such case. Don’t worry about it. Cloudflare has to decrypt the data at the edge in order to cache and filter any bad traffic. Then it re-encrypts the traffic if SSL settings say so. Cloudflare's free plan does not allow you to upload your own certificate. You will get a free shared certificate instead. It somehow works in the end.
There are two strategies for backup presented here. You can use one of them or both at the same time.
Persistent disk snapshots
You can create a snapshot of the disk by using Google Cloud Platform ConsoleCompute EngineSnapshots. Click Create snapshot at the top of the page. Make one for both of the persistent drives. Snapshots are differential. Learn more about persistent disk snapshots
Disk snapshot creation is also possible using the command line.
Export the database and copy the files
Use WP CLI tool to export the database. Login shell does not work correctly with that custom
wp-config.php so use
su deployer instead of
su -l deployer if you intend to use WP CLI commands.
Copy the resulting file somewhere safe using following command
Archive the content of
/var/www/example.com and copy it from the Pod as well.
Having even a single element on your site that is served via HTTP and not HTTPS will make you site appear not secure for the browsers. Depending on the browser the padlock icon will disappear or your site will be marked as not safe in some way.
Replacing http:// with https:// in your
WP_SITEURL along with search and replace done on your WordPress database will fix it.
If you ever decide to drop HTTPS support then you will have to change all of this back
Go to CloudflareDNS. Click button next to each of the A and CNAME records under Status column to turn on HTTP proxy. It should turn orange.
Go to CloudflareCrypto. Set SSL to Full. Enable Automatic HTTPS rewrites