Deploy the Guestbook application to your Tanzu Kubernetes cluster to explore pod security policy for service accounts, and deployment and service creation.

Deploying the Guestbook application is a common way to explore Kubernetes. If you deploy all the Guestbook YAML files to a Tanzu Kubernetes cluster provisioned by the Tanzu Kubernetes Grid Service, the application pod is not created successfully. The following error message appears when you run the kubectl describe pod command:

“Error: container has runAsNonRoot and image will run as root”

The Guestbook application is using both deployment and replicaset resources to deploy privileged containers in the default namespace. Because the PodSecurityPolicy Controller is enabled for Tanzu Kubernetes clusters, when any cluster user attempts to create the Guestbook application pod, the service accounts for these controllers are checked against PodSecurityPolicy. If an appropriate PSP is not bound to these service accounts, the application is not deployed.

By default, Tanzu Kubernetes administrators can create privileged pods directly in any namespace using their user account. However, the Guestbook application deploys privileged containers using service accounts. A cluster administrator can create Deployments, StatefulSets, and DaemonSet in the kube-system namespace. However, the Guestbook application deploys these resources in the default namespace. In addition, non-administrative users cannot create privileged or unprivileged pods at all without the proper PSP and bindings.

One solution is to create bindings to the default privileged PSP to allow the Guestbook application to be deployed. The privileged PodSecurityPolicy permits run-as-root pods and privileged containers for bound accounts. You can create a ClusterRoleBinding that applies the vmware-system-privileged cluster-wide, but doing so might violate the principle of least privilege by granting more permission than is needed. A better approach is to create a RoleBinding that permits the system service accounts to use the privileged PodSecurityPolicy in the default namespace. For more information, see Example Role Bindings for Pod Security Policy.



  1. Log in to the Tanzu Kubernetes cluster. See Connect to a Tanzu Kubernetes Cluster as a vCenter Single Sign-On User.
  2. Create the Guestbook namespace.
    kubectl create namespace guestbook
    kubectl get ns
  3. Create role-based access control using the default privileged PSP.
    kubectl create clusterrolebinding default-tkg-admin-privileged-binding --clusterrole=psp:vmware-system-privileged --group=system:authenticated
    Note: If tighter security is required, apply a RoleBinding on the Guestbook namespace. See Example Role Bindings for Pod Security Policy
  4. Verify the storage class, or create one.
    To verify an existing storage class:
    kubectl get storageclass
    To create a storage class, see Tanzu Kubernetes Storage Class Example.
  5. Create the persistent volume claims (PVCs) that use the storage class.
    Use the following YAML files: To create the PVCs, see Tanzu Kubernetes Persistent Volume Claim Examples.
  6. Create the Guestbook YAML files.
  7. Deploy the Guestbook application in its namespace.
    kubectl apply -f . --namespace guestbook
  8. Verify creation of the Guestbook resources.
    kubectl get all -n guestbook
    NAME                                                 READY   STATUS              RESTARTS   AGE
    pod/guestbook-frontend-deployment-56fc5b6b47-cd58r   1/1     Running             0          65s
    pod/guestbook-frontend-deployment-56fc5b6b47-fh6dp   1/1     Running             0          65s
    pod/guestbook-frontend-deployment-56fc5b6b47-hgd2b   1/1     Running             0          65s
    pod/redis-follower-deployment-6fc9cf5759-99fgw       1/1     Running             0          65s
    pod/redis-follower-deployment-6fc9cf5759-rhxf7       1/1     Running             0          65s
    pod/redis-leader-deployment-7d89bbdbcf-flt4q         1/1     Running             0          65s
    NAME                                 TYPE           CLUSTER-IP       EXTERNAL-IP     PORT(S)        AGE
    service/guestbook-frontend           LoadBalancer     80:31513/TCP   65s
    service/redis-follower               ClusterIP   <none>          6379/TCP       65s
    service/redis-leader                 ClusterIP    <none>          6379/TCP       65s
    NAME                                            READY   UP-TO-DATE   AVAILABLE   AGE
    deployment.apps/guestbook-frontend-deployment   3/3     3            3           65s
    deployment.apps/redis-follower-deployment       1/2     2            1           65s
    deployment.apps/redis-leader-deployment         1/1     1            1           65s
    NAME                                                       DESIRED   CURRENT   READY   AGE
    replicaset.apps/guestbook-frontend-deployment-56fc5b6b47   3         3         3       65s
    replicaset.apps/redis-follower-deployment-6fc9cf5759       2         2         1       65s
    replicaset.apps/redis-leader-deployment-7d89bbdbcf         1         1         1       65s
  9. Access the Guestbook web page using the External-IP address of the service/guestbook-frontend load balancer, which in this example is
    You see the Guestbook web interface, and you can enter values into the Guestbook database. If you restart the application, the data is persisted.