diff --git a/contrib/metallb/roles/provision/tasks/main.yml b/contrib/metallb/roles/provision/tasks/main.yml
index a51eeaf136bfd128db82b14b408fe240ec385248..cb065b6da4821d5df8764f20a49e0c841610348a 100644
--- a/contrib/metallb/roles/provision/tasks/main.yml
+++ b/contrib/metallb/roles/provision/tasks/main.yml
@@ -4,6 +4,22 @@
     msg: "MetalLB require kube_proxy_strict_arp = true, see https://github.com/danderson/metallb/issues/153#issuecomment-518651132"
   when:
     - "kube_proxy_mode == 'ipvs' and not kube_proxy_strict_arp"
+
+- name: Kubernetes Apps | Check AppArmor status
+  command: which apparmor_parser
+  register: apparmor_status
+  when:
+    - podsecuritypolicy_enabled
+    - inventory_hostname == groups['kube-master'][0]
+  failed_when: false
+
+- name: Kubernetes Apps | Set apparmor_enabled
+  set_fact:
+    apparmor_enabled: "{{ apparmor_status.rc == 0 }}"
+  when:
+    - podsecuritypolicy_enabled
+    - inventory_hostname == groups['kube-master'][0]
+
 - name: "Kubernetes Apps | Lay Down MetalLB"
   become: true
   template: { src: "{{ item }}.j2", dest: "{{ kube_config_dir }}/{{ item }}" }
@@ -11,6 +27,7 @@
   register: "rendering"
   when:
     - "inventory_hostname == groups['kube-master'][0]"
+
 - name: "Kubernetes Apps | Install and configure MetalLB"
   kube:
     name: "MetalLB"
diff --git a/contrib/metallb/roles/provision/templates/metallb.yml.j2 b/contrib/metallb/roles/provision/templates/metallb.yml.j2
index b830c5f52472db469980e7504be2356ddf0d9820..b2d6ce051ab57c5cd7bd6deb26cfc5747e7f26c8 100644
--- a/contrib/metallb/roles/provision/templates/metallb.yml.j2
+++ b/contrib/metallb/roles/provision/templates/metallb.yml.j2
@@ -50,6 +50,48 @@ rules:
 - apiGroups: [""]
   resources: ["services", "endpoints", "nodes"]
   verbs: ["get", "list", "watch"]
+{% if podsecuritypolicy_enabled %}
+- apiGroups: ["policy"]
+  resourceNames: ["metallb"]
+  resources: ["podsecuritypolicies"]
+  verbs: ["use"]
+---
+apiVersion: policy/v1beta1
+kind: PodSecurityPolicy
+metadata:
+  name: metallb
+  annotations:
+    seccomp.security.alpha.kubernetes.io/defaultProfileName:  'docker/default'
+    seccomp.security.alpha.kubernetes.io/allowedProfileNames: 'docker/default'
+{% if apparmor_enabled %}
+    apparmor.security.beta.kubernetes.io/defaultProfileName:  'runtime/default'
+    apparmor.security.beta.kubernetes.io/allowedProfileNames: 'runtime/default'
+{% endif %}
+  labels:
+    app: metallb
+spec:
+  privileged: true
+  allowPrivilegeEscalation: false
+  allowedCapabilities:
+  - net_raw
+  volumes:
+  - secret
+  hostNetwork: true
+  hostPorts:
+  - min: {{ metallb.port }}
+    max: {{ metallb.port }}
+  hostIPC: false
+  hostPID: false
+  runAsUser:
+    rule: 'RunAsAny'
+  seLinux:
+    rule: 'RunAsAny'
+  supplementalGroups:
+    rule: 'RunAsAny'
+  fsGroup:
+    rule: 'RunAsAny'
+  readOnlyRootFilesystem: true
+{% endif %}
 ---
 apiVersion: rbac.authorization.k8s.io/v1
 kind: Role