Please note that this is just an example on how you can use Terraform with UpCloud and should not be used in production as is. Please see LICENSE for details.
This is a demo project about how to set up UpCloud Kubernetes Service cluster using Terraform and then deploy WordPress as an example application. Demo uses Terraform as IaC tool and for fast deployment.
Created server infrastructure is portrayed in following picture
Before testing this project you should have Terraform installed in machine you want to use for testing. We're also using UpCloud's Terraform provider, but it should be automatically installed by running terraform init (make init).
To create the resources with Terraform, you'll need your API credentials exported.
export UPCLOUD_USERNAME=your_username
export UPCLOUD_PASSWORD=your_password
You must also create config.tfvars file with your own settings:
ssh_key_public = "ssh-rsa AAAA_YOUR_SSH_PUBLIC_KEY"
zone = "de-fra1"
worker_count = 2
worker_plan = "2xCPU-4GB"
mysql_plan = "1x1xCPU-2GB-25GB"
uks_network = "172.16.255.0/24
Initiate the project and install providers.
make init
Demo can now be created with Terraform. Creation takes around 10-15 minutes.
make create
After Terraform finishes you need to export kubeconfig as environment variable export KUBECONFIG=kubeconfig.yml.
After UKS control-plane has been created it will start creating worker nodes. You can monitor node status with kubectl.
kubectl get nodes
When all worker nodes are up, you start testing UKS with what ever application you want, but we have provided here few examples.
This is a simple web app that can be used to test UKS functionality. Create a deployment and expose it to the public Internet over HTTP by running the following commands:
kubectl create deployment --image=ghcr.io/upcloudltd/hello hello-uks
kubectl expose deployment hello-uks --port=80 --target-port=80 --type=LoadBalancer
kubectl get svc -w
This process will take a few minutes as our system will create a new load balancer to handle the traffic.
You can verify that it work by accessing LoadBalancer hostname in your browser or using
curl <Loadbalancer hostname> command.
If you want to expose the service over HTTPS instead run the following:
kubectl expose deployment hello-uks --port=443 --target-port=80 --type=LoadBalancer --name=hello-uks-https
We provision a TLS certificate automatically for the autogenerated Load Balancer hostname.
You might want to deploy monitoring to see how cluster resources are used during testing. We can use kube-prometheus project for fast and easy deployment for testing.
First clone the kube-prometheus project from Github.
git clone https://github.com/prometheus-operator/kube-prometheus.git
And then deploy it to UKS cluster.
kubectl apply --server-side -f kube-prometheus/manifests/setup
kubectl wait \
--for condition=Established \
--all CustomResourceDefinition \
--namespace=monitoring
kubectl apply -f kube-prometheus/manifests/
Kube-prometheus project includes multiple components, but for now we want to just access Grafana dashboards. For testing purposes, easy way to access Grafana is to use port-forwarding from your local computer localhost.
kubectl --namespace monitoring port-forward svc/grafana 3000
Then access via http://localhost:3000 and use the default grafana user:password of admin:admin.
Kube-prometheus was deployed to monitoring namespace and you need to use -n monitoring parameter when viewing
objects in monitoring namespace. For example
kubectl get svc -n monitoring
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
alertmanager-main ClusterIP 10.138.206.96 <none> 9093/TCP,8080/TCP 47m
alertmanager-operated ClusterIP None <none> 9093/TCP,9094/TCP,9094/UDP 46m
blackbox-exporter ClusterIP 10.128.106.240 <none> 9115/TCP,19115/TCP 47m
grafana ClusterIP 10.129.214.97 <none> 3000/TCP 47m
kube-state-metrics ClusterIP None <none> 8443/TCP,9443/TCP 47m
node-exporter ClusterIP None <none> 9100/TCP 47m
prometheus-adapter ClusterIP 10.131.13.100 <none> 443/TCP 47m
prometheus-k8s ClusterIP 10.138.100.82 <none> 9090/TCP,8080/TCP 47m
prometheus-operated ClusterIP None <none> 9090/TCP 46m
prometheus-operator ClusterIP None <none> 8443/TCP 47m
Next application is WordPress and to start you need to create kubernetes secret for storing MySQL credentials. These will be used by WordPress we deploy. You can do this by running the following command as Terraform has already stored credentials in separate files.
kubectl create secret generic mysql \
--from-file=user=credentials/mysql-user.txt \
--from-file=password=credentials/mysql-password.txt \
--from-file=database=credentials/mysql-db-name.txt \
--from-file=hostname=credentials/mysql-hostname.txt
Then you need to create persistent volume with UpCloud CSI driver
kubectl create -f wordpress-example/upcloud-csi-volume.yaml
Then you can deploy WordPress that uses volume we just created
kubectl create -f wordpress-example/wordpress-deployment.yaml
After this you should verify when WordPress service is up.
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress LoadBalancer 10.128.90.14 lb-0a372fcc11e14cb9b9cced602c85c36a-1.upcloudlb.com 80:31033/TCP 4m1s
Then access hostname under EXTERNAL-IP with browser to finnish WordPress install.
First you might want to delete the previous WordPress deployment as this one uses the same MySQL database. You can do this with
kubectl delete -f wordpress-example/wordpress-deployment.yaml
kubectl delete -f wordpress-example/upcloud-csi-volume.yaml
To get started with NFS you need to deploy nfs-provisioner. You can do that with commands below, but you need to fill
in the from Terraform. You can use command make print to output NFS server IP.
helm repo add nfs-subdir-external-provisioner https://kubernetes-sigs.github.io/nfs-subdir-external-provisioner
helm install nfs-subdir-external-provisioner nfs-subdir-external-provisioner/nfs-subdir-external-provisioner \
--create-namespace \
--namespace nfs-provisioner \
--set nfs.server=<nfs-server-ip> \
--set nfs.path=/data
Then you need to install nfs client to worker nodes as they do not have it by default. You can do this via SSH or
with provided bash script bash install-nfs-client-to-workers.sh
Then you can deploy WordPress that uses NFS server as persistent volume.
kubectl create -f wordpress-example/wordpress-with-nfs.yaml
Then again you access hostname under EXTERNAL-IP with browser to finnish WordPress install.
$ kubectl get services
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
wordpress-nfs LoadBalancer 10.129.156.204 lb-0a3fc4da7b7d4d1c8a99dbbdaea23d90-1.upcloudlb.com 80:31992/TCP 42m
After testing things its good to free the resources. Tearing the thing down is also just one command.
kubectl delete deployment hello-uks
kubectl delete svc hello-uks
kubectl delete svc hello-uks-https
kubectl delete -f kube-prometheus/manifests/
kubectl delete -f wordpress-example/
make destroy
This project is licensed under the MIT License - see the LICENSE.md file for details.
