Continuing from the previous post, in this second part we will be provisioning Kubernetes objects. Once we are done, this will complete WordPress on Kubernetes with GCP MySQL and Workload Identity sample.
WordPress on Kubernetes
In the last part, we used Config Connector to create GCP objects that we need to power our WordPress site. In this part, we’ll build the Kubernetes side of of our configuration.
Stateful Set
First of all, let’s create a stateful set. As you can see below, it consists of 2 containers. One container is to host WordPress workload, another container is to host SQL proxy. To clarify, I’m omitting non-essential configuration for livenessProbe
, readinessProbe
and resource limit requests. Please see the full configuration with these sections included here.
Most significantly, there are no secrets that we had to mount to cloudsql-proxy
pod. This is part of workload identity “magic”, that propagates these secrets, without having to mount the keys.
apiVersion: apps/v1 kind: StatefulSet metadata: namespace: default name: wordpress spec: selector: matchLabels: app: wordpress serviceName: "wordpress" replicas: 1 template: metadata: labels: app: wordpress spec: terminationGracePeriodSeconds: 30 serviceAccountName: sql-wp-ksa-wi containers: - name: wordpress image: wordpress:5.2.2-apache imagePullPolicy: IfNotPresent env: - name: WORDPRESS_DB_HOST value: 127.0.0.1:3306 - name: WORDPRESS_DB_USER valueFrom: secretKeyRef: name: wordpress-cloudsql-db-credentials key: username - name: WORDPRESS_DB_PASSWORD valueFrom: secretKeyRef: name: wordpress-cloudsql-db-credentials key: password ports: - containerPort: 80 volumeMounts: - name: wordpress-volume-2 mountPath: /var/www/html - name: cloudsql-proxy image: gcr.io/cloudsql-docker/gce-proxy:1.11 env: - name: CONNECTION_NAME valueFrom: secretKeyRef: name: wordpress-cloudsql-db-credentials key: connectionName - name: PROJECT_ID valueFrom: secretKeyRef: name: wordpress-cloudsql-db-credentials key: projectId command: ["/cloud_sql_proxy", "-instances=$(PROJECT_ID):$(CONNECTION_NAME)=tcp:3306"] volumeClaimTemplates: - metadata: name: wordpress-volume-2 spec: accessModes: [ "ReadWriteOnce" ] resources: requests: storage: 10Gi
K8s Service Account
Next, let’s apply the configuration below. It instantiates a Kubernetes service account. Most importantly, note the annotation that connects it to Google service account. We need this as part of Workload identity setup.
apiVersion: v1 kind: ServiceAccount metadata: name: sql-wp-ksa-wi annotations: iam.gke.io/gcp-service-account: sql-wp-sa@[PROJECT_ID].iam.gserviceaccount.com
K8s SQL DB Credentials
apiVersion: v1 kind: Secret metadata: name: wordpress-cloudsql-db-credentials stringData: projectId: [PROJECT_ID] username: wordpress password: change-me connectionName: us-central1:wp-db
K8s Service and External Load Balancer
apiVersion: v1 kind: Service metadata: namespace: default name: wordpress labels: app: wordpress spec: ports: - port: 80 name: web clusterIP: None selector: app: wordpress --- apiVersion: v1 kind: Service metadata: namespace: default name: wordpress-external labels: app: wordpress spec: type: LoadBalancer ports: - port: 80 name: web targetPort: 80 protocol: TCP selector: app: wordpress
Workload Identity
To sum up, this is what we created to configure workload identity:
- Provision GCP cluster, using Beta create API to configure workload identity namespace
- Google Service Account
- IAM Policy for Google Service Account – defines permissions that Google Service account has
- Workload Identity role for K8s Service Account on Google Service Account
- K8s service account with annotation linking it to K8s service account
Once you have these building blocks in place, you no longer need to mount the secrets to use in the pod. For more details, please see Workload Identity documentation.
Applying configuration
To create complete configuration, run kubectl apply
on all the resources that we discussed. Finally, run one temporary gcloud step until the gap with policy binding is addressed.
This is it! To summarize, we created WordPress on Kubernetes with GCP and Workload Identity. You can get complete configuration for this sample here.