From 827e417129c6dfc38e4166cd7da1506f93a0ca24 Mon Sep 17 00:00:00 2001 From: Joel Wetzell Date: Fri, 7 Nov 2025 13:56:32 -0600 Subject: [PATCH] split infrastructure by cluster --- clusters/ontime-dev-doks/infrastructure.yaml | 2 +- clusters/ontime-dev/infrastructure.yaml | 2 +- .../cert-manager/cert-manager.yaml | 0 .../{ => ontime-dev-doks}/csi-s3/csi-s3.yaml | 0 .../ingress-nginx/ingress-nginx.yaml | 0 .../metrics-server/metrics-server.yaml | 0 .../ontime-operator/cluster-role-binding.yaml | 0 .../ontime-operator/deploy.yaml | 0 .../ontime-operator/kustomization.yaml | 0 .../namespace-prefix-policy.yaml | 0 .../ontime-operator/service-account.yaml | 0 .../ontime-dev/cert-manager/cert-manager.yaml | 34 ++ .../csi-driver-nfs/csi-driver-nfs.yaml | 0 .../ingress-nginx/ingress-nginx.yaml | 38 ++ .../ontime-operator/cluster-role-binding.yaml | 34 ++ .../ontime-dev/ontime-operator/deploy.yaml | 390 ++++++++++++++++++ .../ontime-operator/kustomization.yaml | 7 + .../namespace-prefix-policy.yaml | 98 +++++ .../ontime-operator/service-account.yaml | 5 + 19 files changed, 608 insertions(+), 2 deletions(-) rename infrastructure/{ => ontime-dev-doks}/cert-manager/cert-manager.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/csi-s3/csi-s3.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/ingress-nginx/ingress-nginx.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/metrics-server/metrics-server.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/ontime-operator/cluster-role-binding.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/ontime-operator/deploy.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/ontime-operator/kustomization.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/ontime-operator/namespace-prefix-policy.yaml (100%) rename infrastructure/{ => ontime-dev-doks}/ontime-operator/service-account.yaml (100%) create mode 100644 infrastructure/ontime-dev/cert-manager/cert-manager.yaml rename infrastructure/{ => ontime-dev}/csi-driver-nfs/csi-driver-nfs.yaml (100%) create mode 100644 infrastructure/ontime-dev/ingress-nginx/ingress-nginx.yaml create mode 100644 infrastructure/ontime-dev/ontime-operator/cluster-role-binding.yaml create mode 100644 infrastructure/ontime-dev/ontime-operator/deploy.yaml create mode 100644 infrastructure/ontime-dev/ontime-operator/kustomization.yaml create mode 100644 infrastructure/ontime-dev/ontime-operator/namespace-prefix-policy.yaml create mode 100644 infrastructure/ontime-dev/ontime-operator/service-account.yaml diff --git a/clusters/ontime-dev-doks/infrastructure.yaml b/clusters/ontime-dev-doks/infrastructure.yaml index 25c56fa..6f8ef4c 100644 --- a/clusters/ontime-dev-doks/infrastructure.yaml +++ b/clusters/ontime-dev-doks/infrastructure.yaml @@ -11,6 +11,6 @@ spec: sourceRef: kind: GitRepository name: flux-system - path: ./infrastructure + path: ./infrastructure/ontime-dev-doks prune: true wait: true \ No newline at end of file diff --git a/clusters/ontime-dev/infrastructure.yaml b/clusters/ontime-dev/infrastructure.yaml index 25c56fa..0e201c9 100644 --- a/clusters/ontime-dev/infrastructure.yaml +++ b/clusters/ontime-dev/infrastructure.yaml @@ -11,6 +11,6 @@ spec: sourceRef: kind: GitRepository name: flux-system - path: ./infrastructure + path: ./infrastructure/ontime-dev prune: true wait: true \ No newline at end of file diff --git a/infrastructure/cert-manager/cert-manager.yaml b/infrastructure/ontime-dev-doks/cert-manager/cert-manager.yaml similarity index 100% rename from infrastructure/cert-manager/cert-manager.yaml rename to infrastructure/ontime-dev-doks/cert-manager/cert-manager.yaml diff --git a/infrastructure/csi-s3/csi-s3.yaml b/infrastructure/ontime-dev-doks/csi-s3/csi-s3.yaml similarity index 100% rename from infrastructure/csi-s3/csi-s3.yaml rename to infrastructure/ontime-dev-doks/csi-s3/csi-s3.yaml diff --git a/infrastructure/ingress-nginx/ingress-nginx.yaml b/infrastructure/ontime-dev-doks/ingress-nginx/ingress-nginx.yaml similarity index 100% rename from infrastructure/ingress-nginx/ingress-nginx.yaml rename to infrastructure/ontime-dev-doks/ingress-nginx/ingress-nginx.yaml diff --git a/infrastructure/metrics-server/metrics-server.yaml b/infrastructure/ontime-dev-doks/metrics-server/metrics-server.yaml similarity index 100% rename from infrastructure/metrics-server/metrics-server.yaml rename to infrastructure/ontime-dev-doks/metrics-server/metrics-server.yaml diff --git a/infrastructure/ontime-operator/cluster-role-binding.yaml b/infrastructure/ontime-dev-doks/ontime-operator/cluster-role-binding.yaml similarity index 100% rename from infrastructure/ontime-operator/cluster-role-binding.yaml rename to infrastructure/ontime-dev-doks/ontime-operator/cluster-role-binding.yaml diff --git a/infrastructure/ontime-operator/deploy.yaml b/infrastructure/ontime-dev-doks/ontime-operator/deploy.yaml similarity index 100% rename from infrastructure/ontime-operator/deploy.yaml rename to infrastructure/ontime-dev-doks/ontime-operator/deploy.yaml diff --git a/infrastructure/ontime-operator/kustomization.yaml b/infrastructure/ontime-dev-doks/ontime-operator/kustomization.yaml similarity index 100% rename from infrastructure/ontime-operator/kustomization.yaml rename to infrastructure/ontime-dev-doks/ontime-operator/kustomization.yaml diff --git a/infrastructure/ontime-operator/namespace-prefix-policy.yaml b/infrastructure/ontime-dev-doks/ontime-operator/namespace-prefix-policy.yaml similarity index 100% rename from infrastructure/ontime-operator/namespace-prefix-policy.yaml rename to infrastructure/ontime-dev-doks/ontime-operator/namespace-prefix-policy.yaml diff --git a/infrastructure/ontime-operator/service-account.yaml b/infrastructure/ontime-dev-doks/ontime-operator/service-account.yaml similarity index 100% rename from infrastructure/ontime-operator/service-account.yaml rename to infrastructure/ontime-dev-doks/ontime-operator/service-account.yaml diff --git a/infrastructure/ontime-dev/cert-manager/cert-manager.yaml b/infrastructure/ontime-dev/cert-manager/cert-manager.yaml new file mode 100644 index 0000000..f6a8ff0 --- /dev/null +++ b/infrastructure/ontime-dev/cert-manager/cert-manager.yaml @@ -0,0 +1,34 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: cert-manager +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: OCIRepository +metadata: + name: cert-manager + namespace: cert-manager +spec: + interval: 5m0s + url: oci://quay.io/jetstack/charts/cert-manager + layerSelector: + mediaType: "application/vnd.cncf.helm.chart.content.v1.tar+gzip" + operation: copy + ref: + tag: "v1.19.1" +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: cert-manager + namespace: cert-manager +spec: + interval: 30m + chartRef: + kind: OCIRepository + name: cert-manager + namespace: cert-manager + values: + crds: + enabled: true \ No newline at end of file diff --git a/infrastructure/csi-driver-nfs/csi-driver-nfs.yaml b/infrastructure/ontime-dev/csi-driver-nfs/csi-driver-nfs.yaml similarity index 100% rename from infrastructure/csi-driver-nfs/csi-driver-nfs.yaml rename to infrastructure/ontime-dev/csi-driver-nfs/csi-driver-nfs.yaml diff --git a/infrastructure/ontime-dev/ingress-nginx/ingress-nginx.yaml b/infrastructure/ontime-dev/ingress-nginx/ingress-nginx.yaml new file mode 100644 index 0000000..a12efe1 --- /dev/null +++ b/infrastructure/ontime-dev/ingress-nginx/ingress-nginx.yaml @@ -0,0 +1,38 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: ingress-nginx +--- +apiVersion: source.toolkit.fluxcd.io/v1 +kind: HelmRepository +metadata: + name: ingress-nginx + namespace: ingress-nginx +spec: + interval: 24h + url: https://kubernetes.github.io/ingress-nginx +--- +apiVersion: helm.toolkit.fluxcd.io/v2 +kind: HelmRelease +metadata: + name: ingress-nginx + namespace: ingress-nginx +spec: + interval: 30m + chart: + spec: + chart: ingress-nginx + version: "4.13.3" + sourceRef: + kind: HelmRepository + name: ingress-nginx + namespace: ingress-nginx + interval: 12h + values: + controller: + service: + type: "LoadBalancer" + externalTrafficPolicy: Local + admissionWebhooks: + enabled: false \ No newline at end of file diff --git a/infrastructure/ontime-dev/ontime-operator/cluster-role-binding.yaml b/infrastructure/ontime-dev/ontime-operator/cluster-role-binding.yaml new file mode 100644 index 0000000..a5aacd0 --- /dev/null +++ b/infrastructure/ontime-dev/ontime-operator/cluster-role-binding.yaml @@ -0,0 +1,34 @@ +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: edit-namespaces +rules: +- apiGroups: [""] + resources: ["namespaces"] + verbs: ["create", "get", "list", "watch", "update", "patch", "delete"] +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: edit-stages-clusterrolebinding +subjects: +- kind: ServiceAccount + name: stage-editor + namespace: ontime-operator +roleRef: + kind: ClusterRole + name: ontime-operator-stage-editor-role + apiGroup: rbac.authorization.k8s.io +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: edit-namespaces-clusterrolebinding +subjects: +- kind: ServiceAccount + name: stage-editor + namespace: ontime-operator +roleRef: + kind: ClusterRole + name: edit-namespaces + apiGroup: rbac.authorization.k8s.io \ No newline at end of file diff --git a/infrastructure/ontime-dev/ontime-operator/deploy.yaml b/infrastructure/ontime-dev/ontime-operator/deploy.yaml new file mode 100644 index 0000000..fddba33 --- /dev/null +++ b/infrastructure/ontime-dev/ontime-operator/deploy.yaml @@ -0,0 +1,390 @@ +apiVersion: v1 +kind: Namespace +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + control-plane: controller-manager + name: ontime-operator +--- +apiVersion: apiextensions.k8s.io/v1 +kind: CustomResourceDefinition +metadata: + name: stages.cloud.getontime.no +spec: + group: cloud.getontime.no + names: + kind: Stage + listKind: StageList + plural: stages + singular: stage + scope: Namespaced + versions: + - name: v1 + schema: + openAPIV3Schema: + description: Stage is the Schema for the stages API + properties: + apiVersion: + description: 'APIVersion defines the versioned schema of this representation + of an object. Servers should convert recognized schemas to the latest + internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources' + type: string + kind: + description: 'Kind is a string value representing the REST resource this + object represents. Servers may infer this from the endpoint the client + submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds' + type: string + metadata: + type: object + spec: + description: Spec defines the desired state of Stage + type: object + x-kubernetes-preserve-unknown-fields: true + status: + description: Status defines the observed state of Stage + type: object + x-kubernetes-preserve-unknown-fields: true + type: object + served: true + storage: true + subresources: + status: {} +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + name: ontime-operator-controller-manager + namespace: ontime-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: Role +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + name: ontime-operator-leader-election-role + namespace: ontime-operator +rules: +- apiGroups: + - "" + resources: + - configmaps + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - coordination.k8s.io + resources: + - leases + verbs: + - get + - list + - watch + - create + - update + - patch + - delete +- apiGroups: + - "" + resources: + - events + verbs: + - create + - patch +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ontime-operator-manager-role +rules: +- apiGroups: + - "" + resources: + - namespaces + verbs: + - get +- apiGroups: + - "" + resources: + - secrets + verbs: + - '*' +- apiGroups: + - "" + resources: + - events + verbs: + - create +- apiGroups: + - cloud.getontime.no + resources: + - stages + - stages/status + - stages/finalizers + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - "" + resources: + - services + - persistentvolumeclaims + verbs: + - '*' +- apiGroups: + - apps + resources: + - deployments + verbs: + - '*' +- apiGroups: + - networking.k8s.io + resources: + - ingresses + verbs: + - '*' +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ontime-operator-metrics-auth-role +rules: +- apiGroups: + - authentication.k8s.io + resources: + - tokenreviews + verbs: + - create +- apiGroups: + - authorization.k8s.io + resources: + - subjectaccessreviews + verbs: + - create +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + name: ontime-operator-metrics-reader +rules: +- nonResourceURLs: + - /metrics + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + name: ontime-operator-stage-admin-role +rules: +- apiGroups: + - cloud.getontime.no + resources: + - stages + verbs: + - '*' +- apiGroups: + - cloud.getontime.no + resources: + - stages/status + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + name: ontime-operator-stage-editor-role +rules: +- apiGroups: + - cloud.getontime.no + resources: + - stages + verbs: + - create + - delete + - get + - list + - patch + - update + - watch +- apiGroups: + - cloud.getontime.no + resources: + - stages/status + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRole +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + name: ontime-operator-stage-viewer-role +rules: +- apiGroups: + - cloud.getontime.no + resources: + - stages + verbs: + - get + - list + - watch +- apiGroups: + - cloud.getontime.no + resources: + - stages/status + verbs: + - get +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: RoleBinding +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + name: ontime-operator-leader-election-rolebinding + namespace: ontime-operator +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: Role + name: ontime-operator-leader-election-role +subjects: +- kind: ServiceAccount + name: ontime-operator-controller-manager + namespace: ontime-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + name: ontime-operator-manager-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ontime-operator-manager-role +subjects: +- kind: ServiceAccount + name: ontime-operator-controller-manager + namespace: ontime-operator +--- +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: ontime-operator-metrics-auth-rolebinding +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: ontime-operator-metrics-auth-role +subjects: +- kind: ServiceAccount + name: ontime-operator-controller-manager + namespace: ontime-operator +--- +apiVersion: v1 +kind: Service +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + control-plane: controller-manager + name: ontime-operator-controller-manager-metrics-service + namespace: ontime-operator +spec: + ports: + - name: https + port: 8443 + protocol: TCP + targetPort: 8443 + selector: + app.kubernetes.io/name: ontime-operator + control-plane: controller-manager +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + app.kubernetes.io/managed-by: kustomize + app.kubernetes.io/name: ontime-operator + control-plane: controller-manager + name: ontime-operator-controller-manager + namespace: ontime-operator +spec: + replicas: 1 + selector: + matchLabels: + app.kubernetes.io/name: ontime-operator + control-plane: controller-manager + template: + metadata: + annotations: + kubectl.kubernetes.io/default-container: manager + labels: + app.kubernetes.io/name: ontime-operator + control-plane: controller-manager + spec: + containers: + - args: + - --metrics-require-rbac + - --metrics-secure + - --metrics-bind-address=:8443 + - --leader-elect + - --leader-election-id=ontime-operator + - --health-probe-bind-address=:8081 + image: git.jwetzell.com/jwetzell/ontime-operator:v1.4.0 + livenessProbe: + httpGet: + path: /healthz + port: 8081 + initialDelaySeconds: 15 + periodSeconds: 20 + name: manager + ports: [] + readinessProbe: + httpGet: + path: /readyz + port: 8081 + initialDelaySeconds: 5 + periodSeconds: 10 + resources: + limits: + cpu: 500m + memory: 128Mi + requests: + cpu: 10m + memory: 64Mi + securityContext: + allowPrivilegeEscalation: false + capabilities: + drop: + - ALL + volumeMounts: [] + securityContext: + runAsNonRoot: true + seccompProfile: + type: RuntimeDefault + serviceAccountName: ontime-operator-controller-manager + terminationGracePeriodSeconds: 10 + volumes: [] diff --git a/infrastructure/ontime-dev/ontime-operator/kustomization.yaml b/infrastructure/ontime-dev/ontime-operator/kustomization.yaml new file mode 100644 index 0000000..2806d81 --- /dev/null +++ b/infrastructure/ontime-dev/ontime-operator/kustomization.yaml @@ -0,0 +1,7 @@ +apiVersion: kustomize.config.k8s.io/v1beta1 +kind: Kustomization +resources: + - ./cluster-role-binding.yaml + - ./deploy.yaml + - ./namespace-prefix-policy.yaml + - ./service-account.yaml \ No newline at end of file diff --git a/infrastructure/ontime-dev/ontime-operator/namespace-prefix-policy.yaml b/infrastructure/ontime-dev/ontime-operator/namespace-prefix-policy.yaml new file mode 100644 index 0000000..2ff640d --- /dev/null +++ b/infrastructure/ontime-dev/ontime-operator/namespace-prefix-policy.yaml @@ -0,0 +1,98 @@ +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "force-ns-prefix-for-stage-editor" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["namespaces"] + matchConditions: + - name: 'only-stage-editor' + expression: "request.userInfo.username == 'system:serviceaccount:ontime-operator:stage-editor'" + validations: + - expression: "object.metadata.name.startsWith('team-')" + message: "All namespaces managed by stage-editor must start with 'team-'" +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "force-ns-prefix-for-stage-editor-binding" +spec: + policyName: "force-ns-prefix-for-stage-editor" + validationActions: [Deny] + matchResources: + resourceRules: + - apiGroups: [""] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["namespaces"] +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "force-ns-prefix-for-stage-create-update" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["cloud.getontime.no"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["stages"] + matchConditions: + - name: 'only-stage-editor' + expression: "request.userInfo.username == 'system:serviceaccount:ontime-operator:stage-editor'" + validations: + - expression: "object.metadata.namespace.startsWith('team-')" + message: "Stages must be managed in namespaces starting with 'team-'" +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "force-ns-prefix-for-stage-create-update-binding" +spec: + policyName: "force-ns-prefix-for-stage-create-update" + validationActions: [Deny] + matchResources: + resourceRules: + - apiGroups: ["cloud.getontime.no"] + apiVersions: ["v1"] + operations: ["CREATE", "UPDATE"] + resources: ["stages"] +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicy +metadata: + name: "force-ns-prefix-for-stage-editor-delete" +spec: + failurePolicy: Fail + matchConstraints: + resourceRules: + - apiGroups: ["cloud.getontime.no"] + apiVersions: ["v1"] + operations: ["DELETE"] + resources: ["stages"] + matchConditions: + - name: 'only-stage-editor' + expression: "request.userInfo.username == 'system:serviceaccount:ontime-operator:stage-editor'" + validations: + - expression: "request.namespace.startsWith('team-')" + message: "Stages must be managed in namespaces starting with 'team-'" +--- +apiVersion: admissionregistration.k8s.io/v1 +kind: ValidatingAdmissionPolicyBinding +metadata: + name: "force-ns-prefix-for-stage-editor-delete-binding" +spec: + policyName: "force-ns-prefix-for-stage-editor-delete" + validationActions: [Deny] + matchResources: + resourceRules: + - apiGroups: ["cloud.getontime.no"] + apiVersions: ["v1"] + operations: ["DELETE"] + resources: ["stages"] \ No newline at end of file diff --git a/infrastructure/ontime-dev/ontime-operator/service-account.yaml b/infrastructure/ontime-dev/ontime-operator/service-account.yaml new file mode 100644 index 0000000..816ff02 --- /dev/null +++ b/infrastructure/ontime-dev/ontime-operator/service-account.yaml @@ -0,0 +1,5 @@ +apiVersion: v1 +kind: ServiceAccount +metadata: + name: stage-editor + namespace: ontime-operator \ No newline at end of file