apiVersion: v1
kind: Namespace
metadata:
  name: longhorn-system
---
apiVersion: v1
kind: ServiceAccount
metadata:
  name: longhorn-service-account
  namespace: longhorn-system
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  name: longhorn-role
rules:
- apiGroups:
  - apiextensions.k8s.io
  resources:
  - customresourcedefinitions
  verbs:
  - "*"
- apiGroups: [""]
  resources: ["pods", "events", "persistentvolumes", "persistentvolumeclaims","persistentvolumeclaims/status", "nodes", "proxy/nodes", "pods/log", "secrets", "services", "endpoints", "configmaps"]
  verbs: ["*"]
- apiGroups: [""]
  resources: ["namespaces"]
  verbs: ["get", "list"]
- apiGroups: ["apps"]
  resources: ["daemonsets", "statefulsets", "deployments"]
  verbs: ["*"]
- apiGroups: ["batch"]
  resources: ["jobs", "cronjobs"]
  verbs: ["*"]
- apiGroups: ["policy"]
  resources: ["poddisruptionbudgets"]
  verbs: ["*"]
- apiGroups: ["scheduling.k8s.io"]
  resources: ["priorityclasses"]
  verbs: ["watch", "list"]
- apiGroups: ["storage.k8s.io"]
  resources: ["storageclasses", "volumeattachments", "csinodes", "csidrivers"]
  verbs: ["*"]
- apiGroups: ["snapshot.storage.k8s.io"]
  resources: ["volumesnapshotclasses", "volumesnapshots", "volumesnapshotcontents", "volumesnapshotcontents/status"]
  verbs: ["*"]
- apiGroups: ["longhorn.io"]
  resources: ["volumes", "volumes/status", "engines", "engines/status", "replicas", "replicas/status", "settings",
              "engineimages", "engineimages/status", "nodes", "nodes/status", "instancemanagers", "instancemanagers/status",
              "sharemanagers", "sharemanagers/status"]
  verbs: ["*"]
- apiGroups: ["coordination.k8s.io"]
  resources: ["leases"]
  verbs: ["*"]
- apiGroups: ["metrics.k8s.io"]
  resources: ["pods", "nodes"]
  verbs: ["get", "list"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: longhorn-bind
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: ClusterRole
  name: longhorn-role
subjects:
- kind: ServiceAccount
  name: longhorn-service-account
  namespace: longhorn-system
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: Engine
  name: engines.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: Engine
    listKind: EngineList
    plural: engines
    shortNames:
    - lhe
    singular: engine
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            x-kubernetes-preserve-unknown-fields: true
          status:
            x-kubernetes-preserve-unknown-fields: true
    subresources:
      status: {}
    additionalPrinterColumns:
    - name: State
      type: string
      description: The current state of the engine
      jsonPath: .status.currentState
    - name: Node
      type: string
      description: The node that the engine is on
      jsonPath: .spec.nodeID
    - name: InstanceManager
      type: string
      description: The instance manager of the engine
      jsonPath: .status.instanceManagerName
    - name: Image
      type: string
      description: The current image of the engine
      jsonPath: .status.currentImage
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: Replica
  name: replicas.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: Replica
    listKind: ReplicaList
    plural: replicas
    shortNames:
    - lhr
    singular: replica
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            x-kubernetes-preserve-unknown-fields: true
          status:
            x-kubernetes-preserve-unknown-fields: true
    subresources:
      status: {}
    additionalPrinterColumns:
    - name: State
      type: string
      description: The current state of the replica
      jsonPath: .status.currentState
    - name: Node
      type: string
      description: The node that the replica is on
      jsonPath: .spec.nodeID
    - name: Disk
      type: string
      description: The disk that the replica is on
      jsonPath: .spec.diskID
    - name: InstanceManager
      type: string
      description: The instance manager of the replica
      jsonPath: .status.instanceManagerName
    - name: Image
      type: string
      description: The current image of the replica
      jsonPath: .status.currentImage
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: Setting
  name: settings.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: Setting
    listKind: SettingList
    plural: settings
    shortNames:
    - lhs
    singular: setting
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        x-kubernetes-preserve-unknown-fields: true
    additionalPrinterColumns:
    - name: Value
      type: string
      description: The value of the setting
      jsonPath: .value
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: Volume
  name: volumes.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: Volume
    listKind: VolumeList
    plural: volumes
    shortNames:
    - lhv
    singular: volume
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            x-kubernetes-preserve-unknown-fields: true
          status:
            x-kubernetes-preserve-unknown-fields: true
    subresources:
      status: {}
    additionalPrinterColumns:
    - name: State
      type: string
      description: The state of the volume
      jsonPath: .status.state
    - name: Robustness
      type: string
      description: The robustness of the volume
      jsonPath: .status.robustness
    - name: Scheduled
      type: string
      description: The scheduled condition of the volume
      jsonPath: .status.conditions['scheduled']['status']
    - name: Size
      type: string
      description: The size of the volume
      jsonPath: .spec.size
    - name: Node
      type: string
      description: The node that the volume is currently attaching to
      jsonPath: .status.currentNodeID
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: EngineImage
  name: engineimages.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: EngineImage
    listKind: EngineImageList
    plural: engineimages
    shortNames:
    - lhei
    singular: engineimage
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            x-kubernetes-preserve-unknown-fields: true
          status:
            x-kubernetes-preserve-unknown-fields: true
    subresources:
      status: {}
    additionalPrinterColumns:
    - name: State
      type: string
      description: State of the engine image
      jsonPath: .status.state
    - name: Image
      type: string
      description: The Longhorn engine image
      jsonPath: .spec.image
    - name: RefCount
      type: integer
      description: Number of volumes are using the engine image
      jsonPath: .status.refCount
    - name: BuildDate
      type: date
      description: The build date of the engine image
      jsonPath: .status.buildDate
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: Node
  name: nodes.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: Node
    listKind: NodeList
    plural: nodes
    shortNames:
    - lhn
    singular: node
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            x-kubernetes-preserve-unknown-fields: true
          status:
            x-kubernetes-preserve-unknown-fields: true
    subresources:
      status: {}
    additionalPrinterColumns:
    - name: Ready
      type: string
      description: Indicate whether the node is ready
      jsonPath: .status.conditions['Ready']['status']
    - name: AllowScheduling
      type: boolean
      description: Indicate whether the user disabled/enabled replica scheduling for the node
      jsonPath: .spec.allowScheduling
    - name: Schedulable
      type: string
      description: Indicate whether Longhorn can schedule replicas on the node
      jsonPath: .status.conditions['Schedulable']['status']
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: InstanceManager
  name: instancemanagers.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: InstanceManager
    listKind: InstanceManagerList
    plural: instancemanagers
    shortNames:
    - lhim
    singular: instancemanager
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            x-kubernetes-preserve-unknown-fields: true
          status:
            x-kubernetes-preserve-unknown-fields: true
    subresources:
      status: {}
    additionalPrinterColumns:
    - name: State
      type: string
      description: The state of the instance manager
      jsonPath: .status.currentState
    - name: Type
      type: string
      description: The type of the instance manager (engine or replica)
      jsonPath: .spec.type
    - name: Node
      type: string
      description: The node that the instance manager is running on
      jsonPath: .spec.nodeID
    - name: Age
      type: date
      jsonPath: .metadata.creationTimestamp
---
apiVersion: apiextensions.k8s.io/v1
kind: CustomResourceDefinition
metadata:
  labels:
    longhorn-manager: ShareManager
  name: sharemanagers.longhorn.io
spec:
  group: longhorn.io
  names:
    kind: ShareManager
    listKind: ShareManagerList
    plural: sharemanagers
    shortNames:
      - lhsm
    singular: sharemanager
  scope: Namespaced
  versions:
  - name: v1beta1
    served: true
    storage: true
    schema:
      openAPIV3Schema:
        type: object
        properties:
          spec:
            x-kubernetes-preserve-unknown-fields: true
          status:
            x-kubernetes-preserve-unknown-fields: true
    subresources:
      status: {}
    additionalPrinterColumns:
      - name: State
        type: string
        description: The state of the share manager
        jsonPath: .status.state
      - name: Node
        type: string
        description: The node that the share manager is owned by
        jsonPath: .status.ownerID
      - name: Age
        type: date
        jsonPath: .metadata.creationTimestamp
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: longhorn-default-setting
  namespace: longhorn-system
data:
  default-setting.yaml: |-
    backup-target:
    backup-target-credential-secret:
    allow-recurring-job-while-volume-detached:
    create-default-disk-labeled-nodes:
    default-data-path:
    replica-soft-anti-affinity:
    storage-over-provisioning-percentage:
    storage-minimal-available-percentage:
    upgrade-checker:
    default-replica-count:
    default-data-locality:
    guaranteed-engine-cpu:
    default-longhorn-static-storage-class:
    backupstore-poll-interval:
    taint-toleration:
    priority-class:
    auto-salvage:
    auto-delete-pod-when-volume-detached-unexpectedly:
    disable-scheduling-on-cordoned-node:
    replica-zone-soft-anti-affinity:
    volume-attachment-recovery-policy:
    node-down-pod-deletion-policy:
    allow-node-drain-with-last-healthy-replica:
    mkfs-ext4-parameters:
    disable-replica-rebuild:
    replica-replenishment-wait-interval:
    disable-revision-counter:
    system-managed-pods-image-pull-policy:
    allow-volume-creation-with-degraded-availability:
    auto-cleanup-system-generated-snapshot:
---
apiVersion: policy/v1beta1
kind: PodSecurityPolicy
metadata:
  name: longhorn-psp
spec:
  privileged: true
  allowPrivilegeEscalation: true
  requiredDropCapabilities:
    - NET_RAW
  allowedCapabilities:
    - SYS_ADMIN
  hostNetwork: false
  hostIPC: false
  hostPID: true
  runAsUser:
    rule: RunAsAny
  seLinux:
    rule: RunAsAny
  fsGroup:
    rule: RunAsAny
  supplementalGroups:
    rule: RunAsAny
  volumes:
    - configMap
    - downwardAPI
    - emptyDir
    - secret
    - projected
    - hostPath
---
apiVersion: rbac.authorization.k8s.io/v1
kind: Role
metadata:
  name: longhorn-psp-role
  namespace: longhorn-system
rules:
  - apiGroups:
      - policy
    resources:
      - podsecuritypolicies
    verbs:
      - use
    resourceNames:
      - longhorn-psp
---
apiVersion: rbac.authorization.k8s.io/v1
kind: RoleBinding
metadata:
  name: longhorn-psp-binding
  namespace: longhorn-system
roleRef:
  apiGroup: rbac.authorization.k8s.io
  kind: Role
  name: longhorn-psp-role
subjects:
  - kind: ServiceAccount
    name: longhorn-service-account
    namespace: longhorn-system
  - kind: ServiceAccount
    name: default
    namespace: longhorn-system
---
apiVersion: v1
kind: ConfigMap
metadata:
  name: longhorn-storageclass
  namespace: longhorn-system
data:
  storageclass.yaml: |
    kind: StorageClass
    apiVersion: storage.k8s.io/v1
    metadata:
      name: longhorn
    provisioner: driver.longhorn.io
    allowVolumeExpansion: true
    reclaimPolicy: Delete
    volumeBindingMode: Immediate
    parameters:
      numberOfReplicas: "3"
      staleReplicaTimeout: "2880"
      fromBackup: ""
    #  diskSelector: "ssd,fast"
    #  nodeSelector: "storage,fast"
    #  recurringJobs: '[{"name":"snap", "task":"snapshot", "cron":"*/1 * * * *", "retain":1},
    #                   {"name":"backup", "task":"backup", "cron":"*/2 * * * *", "retain":1,
    #                    "labels": {"interval":"2m"}}]'
---
apiVersion: apps/v1
kind: DaemonSet
metadata:
  labels:
    app: longhorn-manager
  name: longhorn-manager
  namespace: longhorn-system
spec:
  selector:
    matchLabels:
      app: longhorn-manager
  template:
    metadata:
      labels:
        app: longhorn-manager
    spec:
      containers:
      - name: longhorn-manager
        image: longhornio/longhorn-manager:v1.1.0
        imagePullPolicy: IfNotPresent
        securityContext:
          privileged: true
        command:
        - longhorn-manager
        - -d
        - daemon
        - --engine-image
        - longhornio/longhorn-engine:v1.1.0
        - --instance-manager-image
        - longhornio/longhorn-instance-manager:v1_20201216
        - --share-manager-image
        - longhornio/longhorn-share-manager:v1_20201204
        - --manager-image
        - longhornio/longhorn-manager:v1.1.0
        - --service-account
        - longhorn-service-account
        ports:
        - containerPort: 9500
          name: manager
        readinessProbe:
          tcpSocket:
            port: 9500
        volumeMounts:
        - name: dev
          mountPath: /host/dev/
        - name: proc
          mountPath: /host/proc/
        - name: longhorn
          mountPath: /var/lib/longhorn/
          mountPropagation: Bidirectional
        - name: longhorn-default-setting
          mountPath: /var/lib/longhorn-setting/
        env:
        - name: POD_NAMESPACE
          valueFrom:
            fieldRef:
              fieldPath: metadata.namespace
        - name: POD_IP
          valueFrom:
            fieldRef:
              fieldPath: status.podIP
        - name: NODE_NAME
          valueFrom:
            fieldRef:
              fieldPath: spec.nodeName
        # Should be: mount path of the volume longhorn-default-setting + the key of the configmap data in 04-default-setting.yaml
        - name: DEFAULT_SETTING_PATH
          value: /var/lib/longhorn-setting/default-setting.yaml
      volumes:
      - name: dev
        hostPath:
          path: /dev/
      - name: proc
        hostPath:
          path: /proc/
      - name: longhorn
        hostPath:
          path: /var/lib/longhorn/
      - name: longhorn-default-setting
        configMap:
          name: longhorn-default-setting
#      imagePullSecrets:
#      - name: ""
      serviceAccountName: longhorn-service-account
  updateStrategy:
    rollingUpdate:
      maxUnavailable: "100%"
---
apiVersion: v1
kind: Service
metadata:
  labels:
    app: longhorn-manager
  name: longhorn-backend
  namespace: longhorn-system
spec:
  type: ClusterIP
  sessionAffinity: ClientIP
  selector:
    app: longhorn-manager
  ports:
  - name: manager
    port: 9500
    targetPort: manager
---
apiVersion: apps/v1
kind: Deployment
metadata:
  labels:
    app: longhorn-ui
  name: longhorn-ui
  namespace: longhorn-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: longhorn-ui
  template:
    metadata:
      labels:
        app: longhorn-ui
    spec:
      containers:
      - name: longhorn-ui
        image: longhornio/longhorn-ui:v1.1.0
        imagePullPolicy: IfNotPresent
        securityContext:
          runAsUser: 0
        ports:
        - containerPort: 8000
          name: http
        env:
          - name: LONGHORN_MANAGER_IP
            value: "http://longhorn-backend:9500"
#      imagePullSecrets:
#      - name:
---
kind: Service
apiVersion: v1
metadata:
  labels:
    app: longhorn-ui
  name: longhorn-frontend
  namespace: longhorn-system
spec:
  type: ClusterIP
  selector:
    app: longhorn-ui
  ports:
  - name: http
    port: 80
    targetPort: http
    nodePort: null
---
apiVersion: apps/v1
kind: Deployment
metadata:
  name: longhorn-driver-deployer
  namespace: longhorn-system
spec:
  replicas: 1
  selector:
    matchLabels:
      app: longhorn-driver-deployer
  template:
    metadata:
      labels:
        app: longhorn-driver-deployer
    spec:
      initContainers:
        - name: wait-longhorn-manager
          image: longhornio/longhorn-manager:v1.1.0
          command: ['sh', '-c', 'while [ $(curl -m 1 -s -o /dev/null -w "%{http_code}" http://longhorn-backend:9500/v1) != "200" ]; do echo waiting; sleep 2; done']
      containers:
        - name: longhorn-driver-deployer
          image: longhornio/longhorn-manager:v1.1.0
          imagePullPolicy: IfNotPresent
          command:
          - longhorn-manager
          - -d
          - deploy-driver
          - --manager-image
          - longhornio/longhorn-manager:v1.1.0
          - --manager-url
          - http://longhorn-backend:9500/v1
          env:
          - name: POD_NAMESPACE
            valueFrom:
              fieldRef:
                fieldPath: metadata.namespace
          - name: NODE_NAME
            valueFrom:
              fieldRef:
                fieldPath: spec.nodeName
          - name: SERVICE_ACCOUNT
            valueFrom:
              fieldRef:
                fieldPath: spec.serviceAccountName
          # Manually set root directory for csi
          #- name: KUBELET_ROOT_DIR
          #  value: /var/lib/rancher/k3s/agent/kubelet
          # For AirGap Installation
          # Replace PREFIX with your private registery
          #- name: CSI_ATTACHER_IMAGE
          #  value: PREFIX/csi-attacher:v2.2.1-lh1
          #- name: CSI_PROVISIONER_IMAGE
          #  value: PREFIX/csi-provisioner:v1.6.0-lh1
          #- name: CSI_NODE_DRIVER_REGISTRAR_IMAGE
          #  value: PREFIX/csi-node-driver-registrar:v1.2.0-lh1
          #- name: CSI_RESIZER_IMAGE
          #  value: PREFIX/csi-resizer:v0.5.1-lh1
          #- name: CSI_SNAPSHOTTER_IMAGE
          #  value: PREFIX/csi-snapshotter:v2.1.1-lh1
          # Manually specify number of CSI attacher replicas
          #- name: CSI_ATTACHER_REPLICA_COUNT
          #  value: "3"
          # Manually specify number of CSI provisioner replicas
          #- name: CSI_PROVISIONER_REPLICA_COUNT
          #  value: "3"
          #- name: CSI_RESIZER_REPLICA_COUNT
          #  value: "3"
          #- name: CSI_SNAPSHOTTER_REPLICA_COUNT
          #  value: "3"
      #imagePullSecrets:
      #- name:
      serviceAccountName: longhorn-service-account
      securityContext:
        runAsUser: 0
---
