Update storage and Keycloak config

This commit is contained in:
2026-03-04 12:17:47 -05:00
parent d981b69669
commit d31b14cd72
28 changed files with 1433 additions and 205 deletions

View File

@@ -0,0 +1,23 @@
---
# --- Namespace ---
nfs_provisioner_namespace: nfs-provisioner
# --- External NFS server (set these to use a pre-existing NFS share) ---
# When nfs_provisioner_external_server is set, the in-cluster NFS server is
# not deployed; the provisioner points directly at the external share.
nfs_provisioner_external_server: "" # e.g. 192.168.129.100
nfs_provisioner_external_path: "" # e.g. /mnt/BIGPOOL/NoBackups/OCPNFS
# --- Backing storage for in-cluster NFS server (ignored when external_server is set) ---
nfs_provisioner_storage_class: lvms-vg-data
nfs_provisioner_storage_size: 50Gi
nfs_provisioner_server_image: registry.k8s.io/volume-nfs:0.8
nfs_provisioner_export_path: /exports
# --- NFS provisioner ---
nfs_provisioner_name: nfs-client
nfs_provisioner_storage_class_name: nfs-client
nfs_provisioner_image: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
# --- Wait ---
nfs_provisioner_wait_timeout: 300

View File

@@ -0,0 +1,67 @@
---
argument_specs:
main:
short_description: Deploy NFS provisioner (external or in-cluster) for RWX storage on OpenShift
description:
- Deploys the nfs-subdir-external-provisioner and a ReadWriteMany StorageClass.
- When nfs_provisioner_external_server is set, points directly at a pre-existing
NFS share (no in-cluster NFS server pod is deployed).
- When nfs_provisioner_external_server is empty, deploys an in-cluster NFS server
pod backed by an LVMS PVC.
options:
nfs_provisioner_namespace:
description: Namespace for the NFS provisioner (and optional in-cluster NFS server).
type: str
default: nfs-provisioner
nfs_provisioner_external_server:
description: >-
IP or hostname of a pre-existing external NFS server. When set, the
in-cluster NFS server pod is not deployed. Leave empty to use in-cluster mode.
type: str
default: ""
nfs_provisioner_external_path:
description: >-
Exported path on the external NFS server.
Required when nfs_provisioner_external_server is set.
type: str
default: ""
nfs_provisioner_storage_class:
description: >-
StorageClass (RWO) for the in-cluster NFS server backing PVC.
Ignored when nfs_provisioner_external_server is set.
type: str
default: lvms-vg-data
nfs_provisioner_storage_size:
description: >-
Size of the in-cluster NFS server backing PVC.
Ignored when nfs_provisioner_external_server is set.
type: str
default: 50Gi
nfs_provisioner_name:
description: Provisioner name written into the StorageClass.
type: str
default: nfs-client
nfs_provisioner_storage_class_name:
description: Name of the RWX StorageClass created by this role.
type: str
default: nfs-client
nfs_provisioner_image:
description: Container image for the nfs-subdir-external-provisioner.
type: str
default: registry.k8s.io/sig-storage/nfs-subdir-external-provisioner:v4.0.2
nfs_provisioner_server_image:
description: >-
Container image for the in-cluster NFS server.
Ignored when nfs_provisioner_external_server is set.
type: str
default: registry.k8s.io/volume-nfs:0.8
nfs_provisioner_export_path:
description: >-
Path exported by the in-cluster NFS server.
Ignored when nfs_provisioner_external_server is set.
type: str
default: /exports
nfs_provisioner_wait_timeout:
description: Seconds to wait for deployments to become ready.
type: int
default: 300

View File

@@ -0,0 +1,17 @@
---
galaxy_info:
author: ptoal
description: Deploy in-cluster NFS server and provisioner for ReadWriteMany storage on OpenShift
license: MIT
min_ansible_version: "2.16"
platforms:
- name: GenericLinux
versions:
- all
galaxy_tags:
- openshift
- nfs
- storage
- provisioner
dependencies: []

View File

@@ -0,0 +1,394 @@
---
# Deploy nfs-subdir-external-provisioner on OpenShift, backed by either:
# (a) an external NFS server (set nfs_provisioner_external_server / nfs_provisioner_external_path)
# (b) an in-cluster NFS server pod backed by an LVMS RWO PVC (default)
#
# Architecture (in-cluster mode):
# - NFS server StatefulSet: backs exports with an LVMS RWO PVC
# - Service: exposes NFS server at a stable ClusterIP
# - nfs-subdir-external-provisioner: creates PVs on-demand under the export path
# - StorageClass: "nfs-client" with ReadWriteMany support
#
# Architecture (external mode, nfs_provisioner_external_server != ""):
# - In-cluster NFS server is NOT deployed
# - nfs-subdir-external-provisioner points directly at the external NFS share
# - StorageClass: "nfs-client" with ReadWriteMany support
#
# The in-cluster NFS server requires privileged SCC on OpenShift (kernel NFS).
# All tasks are idempotent (kubernetes.core.k8s state: present).
# ------------------------------------------------------------------
# Step 1: Namespace and RBAC
# ------------------------------------------------------------------
- name: Create NFS provisioner namespace
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Namespace
metadata:
name: "{{ nfs_provisioner_namespace }}"
- name: Create NFS server ServiceAccount
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-server
namespace: "{{ nfs_provisioner_namespace }}"
when: nfs_provisioner_external_server | length == 0
- name: Create NFS provisioner ServiceAccount
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: ServiceAccount
metadata:
name: nfs-provisioner
namespace: "{{ nfs_provisioner_namespace }}"
- name: Create ClusterRole to use privileged SCC (NFS server)
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-server-scc
rules:
- apiGroups: [security.openshift.io]
resources: [securitycontextconstraints]
verbs: [use]
resourceNames: [privileged]
when: nfs_provisioner_external_server | length == 0
- name: Bind privileged SCC ClusterRole to NFS server ServiceAccount
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nfs-server-scc
subjects:
- kind: ServiceAccount
name: nfs-server
namespace: "{{ nfs_provisioner_namespace }}"
roleRef:
kind: ClusterRole
name: nfs-server-scc
apiGroup: rbac.authorization.k8s.io
when: nfs_provisioner_external_server | length == 0
- name: Create ClusterRole to use hostmount-anyuid SCC (NFS provisioner)
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-provisioner-scc
rules:
- apiGroups: [security.openshift.io]
resources: [securitycontextconstraints]
verbs: [use]
resourceNames: [hostmount-anyuid]
- name: Bind hostmount-anyuid SCC ClusterRole to NFS provisioner ServiceAccount
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: nfs-provisioner-scc
subjects:
- kind: ServiceAccount
name: nfs-provisioner
namespace: "{{ nfs_provisioner_namespace }}"
roleRef:
kind: ClusterRole
name: nfs-provisioner-scc
apiGroup: rbac.authorization.k8s.io
- name: Create ClusterRole for NFS provisioner
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: nfs-provisioner-runner
rules:
- apiGroups: [""]
resources: [persistentvolumes]
verbs: [get, list, watch, create, delete]
- apiGroups: [""]
resources: [persistentvolumeclaims]
verbs: [get, list, watch, update]
- apiGroups: [storage.k8s.io]
resources: [storageclasses]
verbs: [get, list, watch]
- apiGroups: [""]
resources: [events]
verbs: [create, update, patch]
- name: Bind ClusterRole to NFS provisioner ServiceAccount
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: run-nfs-provisioner
subjects:
- kind: ServiceAccount
name: nfs-provisioner
namespace: "{{ nfs_provisioner_namespace }}"
roleRef:
kind: ClusterRole
name: nfs-provisioner-runner
apiGroup: rbac.authorization.k8s.io
- name: Create Role for leader election
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
name: leader-locking-nfs-provisioner
namespace: "{{ nfs_provisioner_namespace }}"
rules:
- apiGroups: [""]
resources: [endpoints]
verbs: [get, list, watch, create, update, patch]
- name: Bind leader election Role
kubernetes.core.k8s:
state: present
definition:
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
name: leader-locking-nfs-provisioner
namespace: "{{ nfs_provisioner_namespace }}"
subjects:
- kind: ServiceAccount
name: nfs-provisioner
namespace: "{{ nfs_provisioner_namespace }}"
roleRef:
kind: Role
name: leader-locking-nfs-provisioner
apiGroup: rbac.authorization.k8s.io
# ------------------------------------------------------------------
# Step 2: NFS server backing storage and StatefulSet (in-cluster mode only)
# ------------------------------------------------------------------
- name: Create NFS server backing PVC
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: nfs-server-data
namespace: "{{ nfs_provisioner_namespace }}"
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: "{{ nfs_provisioner_storage_size }}"
storageClassName: "{{ nfs_provisioner_storage_class }}"
when: nfs_provisioner_external_server | length == 0
- name: Deploy NFS server StatefulSet
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: StatefulSet
metadata:
name: nfs-server
namespace: "{{ nfs_provisioner_namespace }}"
spec:
replicas: 1
selector:
matchLabels:
app: nfs-server
serviceName: nfs-server
template:
metadata:
labels:
app: nfs-server
spec:
serviceAccountName: nfs-server
containers:
- name: nfs-server
image: "{{ nfs_provisioner_server_image }}"
ports:
- name: nfs
containerPort: 2049
- name: mountd
containerPort: 20048
- name: rpcbind
containerPort: 111
securityContext:
privileged: true
volumeMounts:
- name: nfs-data
mountPath: "{{ nfs_provisioner_export_path }}"
volumes:
- name: nfs-data
persistentVolumeClaim:
claimName: nfs-server-data
when: nfs_provisioner_external_server | length == 0
- name: Create NFS server Service
kubernetes.core.k8s:
state: present
definition:
apiVersion: v1
kind: Service
metadata:
name: nfs-server
namespace: "{{ nfs_provisioner_namespace }}"
spec:
selector:
app: nfs-server
ports:
- name: nfs
port: 2049
- name: mountd
port: 20048
- name: rpcbind
port: 111
when: nfs_provisioner_external_server | length == 0
# ------------------------------------------------------------------
# Step 3: Wait for in-cluster NFS server to be ready (in-cluster mode only)
# ------------------------------------------------------------------
- name: Wait for NFS server to be ready
kubernetes.core.k8s_info:
api_version: apps/v1
kind: StatefulSet
namespace: "{{ nfs_provisioner_namespace }}"
name: nfs-server
register: __nfs_provisioner_server_status
until: >-
__nfs_provisioner_server_status.resources | length > 0 and
(__nfs_provisioner_server_status.resources[0].status.readyReplicas | default(0)) >= 1
retries: "{{ __nfs_provisioner_wait_retries }}"
delay: 10
when: nfs_provisioner_external_server | length == 0
# ------------------------------------------------------------------
# Step 4: Resolve NFS server address, then deploy nfs-subdir-external-provisioner
# ------------------------------------------------------------------
- name: Set NFS server address (external)
ansible.builtin.set_fact:
__nfs_provisioner_server_addr: "{{ nfs_provisioner_external_server }}"
__nfs_provisioner_server_path: "{{ nfs_provisioner_external_path }}"
when: nfs_provisioner_external_server | length > 0
- name: Retrieve in-cluster NFS server ClusterIP
kubernetes.core.k8s_info:
api_version: v1
kind: Service
namespace: "{{ nfs_provisioner_namespace }}"
name: nfs-server
register: __nfs_provisioner_svc
when: nfs_provisioner_external_server | length == 0
- name: Set NFS server address (in-cluster)
ansible.builtin.set_fact:
__nfs_provisioner_server_addr: "{{ __nfs_provisioner_svc.resources[0].spec.clusterIP }}"
__nfs_provisioner_server_path: "{{ nfs_provisioner_export_path }}"
when: nfs_provisioner_external_server | length == 0
- name: Deploy nfs-subdir-external-provisioner
kubernetes.core.k8s:
state: present
definition:
apiVersion: apps/v1
kind: Deployment
metadata:
name: nfs-provisioner
namespace: "{{ nfs_provisioner_namespace }}"
spec:
replicas: 1
selector:
matchLabels:
app: nfs-provisioner
strategy:
type: Recreate
template:
metadata:
labels:
app: nfs-provisioner
spec:
serviceAccountName: nfs-provisioner
containers:
- name: nfs-provisioner
image: "{{ nfs_provisioner_image }}"
env:
- name: PROVISIONER_NAME
value: "{{ nfs_provisioner_name }}"
- name: NFS_SERVER
value: "{{ __nfs_provisioner_server_addr }}"
- name: NFS_PATH
value: "{{ __nfs_provisioner_server_path }}"
volumeMounts:
- name: nfs-client-root
mountPath: /persistentvolumes
volumes:
- name: nfs-client-root
nfs:
server: "{{ __nfs_provisioner_server_addr }}"
path: "{{ __nfs_provisioner_server_path }}"
# ------------------------------------------------------------------
# Step 5: Create StorageClass
# ------------------------------------------------------------------
- name: Create NFS StorageClass
kubernetes.core.k8s:
state: present
definition:
apiVersion: storage.k8s.io/v1
kind: StorageClass
metadata:
name: "{{ nfs_provisioner_storage_class_name }}"
provisioner: "{{ nfs_provisioner_name }}"
parameters:
archiveOnDelete: "false"
reclaimPolicy: Delete
volumeBindingMode: Immediate
# ------------------------------------------------------------------
# Step 6: Wait for provisioner to be ready
# ------------------------------------------------------------------
- name: Wait for NFS provisioner deployment to be ready
kubernetes.core.k8s_info:
api_version: apps/v1
kind: Deployment
namespace: "{{ nfs_provisioner_namespace }}"
name: nfs-provisioner
register: __nfs_provisioner_deploy_status
until: >-
__nfs_provisioner_deploy_status.resources | length > 0 and
(__nfs_provisioner_deploy_status.resources[0].status.readyReplicas | default(0)) >= 1
retries: "{{ __nfs_provisioner_wait_retries }}"
delay: 10
- name: Display NFS provisioner summary
ansible.builtin.debug:
msg:
- "NFS provisioner deployment complete!"
- " Namespace : {{ nfs_provisioner_namespace }}"
- " NFS server : {{ __nfs_provisioner_server_addr }}:{{ __nfs_provisioner_server_path }}"
- " Mode : {{ 'external' if nfs_provisioner_external_server | length > 0 else 'in-cluster (LVMS-backed)' }}"
- " StorageClass : {{ nfs_provisioner_storage_class_name }} (ReadWriteMany)"

View File

@@ -0,0 +1,3 @@
---
# Computed internal variables - do not override
__nfs_provisioner_wait_retries: "{{ (nfs_provisioner_wait_timeout / 10) | int }}"