Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Deploy Thorium

1) Deploy Thorium Operator

Create Thorium ServiceAccount and RBAC

The Thorium operator and scaler can be configured to use a service account with the ability to modify K8s resources. This is the default configuration for single K8s cluster Thorium deployments.

Start by creating a namespace for all Thorium resources.

kubectl create ns thorium

Create a Thorium ServiceAccount and roles

cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: ServiceAccount
metadata:
  name: thorium
  namespace: thorium
imagePullSecrets:
  - name: registry-token
automountServiceAccountToken: true
---

apiVersion: v1
kind: Secret
metadata:
  name: thorium-account-token
  namespace: thorium
  annotations:
    kubernetes.io/service-account.name: thorium
type: kubernetes.io/service-account-token
---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
  # "namespace" omitted since ClusterRoles are not namespaced
  name: thorium-operator
rules:
### https://kubernetes.io/docs/reference/kubectl/#resource-types
### create custom resources
- apiGroups: ["apiextensions.k8s.io"] 
  resources: ["customresourcedefinitions"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
### any custom resources under the sandia.gov group
- apiGroups: ["sandia.gov"] 
  resources: ["*"]
  verbs: ["*"]
### deployments
- apiGroups: ["apps"] 
  resources: ["deployments"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
### networking
- apiGroups: ["networking.k8s.io"] 
  resources: ["networkpolicies"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
### events
- apiGroups: ["events.k8s.io"] 
  resources: ["events"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
### v1 API resources
- apiGroups: [""] 
  resources: ["pods", "services", "secrets", "configmaps", "nodes", "namespaces", "events"]
  verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---

apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
  name: thorium-operator-binding
subjects:
- kind: ServiceAccount
  name: thorium 
  namespace: thorium
  #apiGroup: "rbac.authorization.k8s.io"
roleRef:
  kind: ClusterRole
  name: thorium-operator
  apiGroup: "rbac.authorization.k8s.io" 
EOF

Create a registry pull secret (optional)

Create a registry token that will enable pulling the Thorium container image from the registry.

kubectl create secret generic operator-registry-token --namespace="thorium" --type=kubernetes.io/dockerconfigjson --from-file=".dockerconfigjson"

Here is an example of a .dockerconfigjson file. Replace the fields wrapped by <> with registry values.

{
	"auths": {
		"<REGISTRY.DOMAIN>": {
			"auth": "<base64 of username:password>"
		}
	}
}

Create the Thorium Operator

Update the image field with the correct registry path and tag for the Thorium container image.

cat <<EOF | kubectl apply -f -
apiVersion: apps/v1
kind: Deployment
metadata:
  name: operator
  namespace: thorium
  labels:
    app: operator
spec:
  replicas: 1
  selector:
    matchLabels:
      app: operator
  template:
    metadata:
      labels:
          app: operator
    spec:
      serviceAccountName: thorium
      automountServiceAccountToken: true
      containers:
        - name: operator
          image: "<REGISTRY.DOMAIN/path/to/image/thorium:tag>"
          imagePullPolicy: Always
          resources:
            requests:
              memory: "1Gi"
              cpu: 1
            limits:
              memory: "1Gi"
              cpu: 1
          env:
            - name: "noproxy"
            - name: "http_proxy"
            - name: "https_proxy"
            - name: "NOPROXY"
            - name: "HTTP_PROXY"
            - name: "HTTPS_PROXY"
      imagePullSecrets:
        - name: operator-registry-token
EOF

Verify the operator has successfully started

kubectl rollout status --watch --timeout=600s deployment.apps/operator -n thorium

4) Create a Thorium banner ConfigMap

Create a text file called banner.txt that contains a banner message. This message will be displayed when users login into the Thorium web interface.

kubectl create cm banner --from-file=/path/to/banner.txt -n thorium

5) Create a ThoriumCluster resource

The ThoriumCluster CRD defines database client access, Thorium cluster nodes, and much more. Enter all the passwords, DB/S3 endpoints, and Thorium container image path/tag into this file. The operator will use this the CRD to deploy a working Thorium instance. If this resource definition is updated after the initial deployment the operator will role those changes out and restart Thorium components such as the scaler and API.

Create a thorium-cluster.yml file and update the example values:

apiVersion: sandia.gov/v1
kind: ThoriumCluster
metadata:
  name: prod
  namespace: thorium
spec:
  registry: "<REGISTRY.DOMAIN/path/to/image/thorium>"
  version: "<IMAGE TAG>"
  image_pull_policy: Always
  components:
    api:
      replicas: 1
      urls:
      - "<THORIUM FQDN>"
      ports:
      - 80
      - 443
    scaler:
      service_account: true
    baremetal_scaler: {}
    search_streamer: {}
    event_handler: {}
  config: 
    thorium:
      secret_key: "<SECRET>" 
      tracing:
        external:
          Grpc:
            endpoint: "http://quickwit-indexer.quickwit.svc.cluster.local:7281"
            level: "Info"
        local:
          level: "Info"
      files:
        bucket: "thorium-files"
        password: "SecretCornIsBest"
        earliest: 1610596807
      results:
        bucket: "thorium-result-files"
        earliest: 1610596807
      attachments:
        bucket: "thorium-comment-files"
      repos:
        bucket: "thorium-repo-files"
      ephemeral:
        bucket: "thorium-ephemeral-files"
      s3:
        access_key: "<KEY>"
        secret_token: "<TOKEN>"
        endpoint: "https://<S3 FQDN>"
      auth:
        local_user_ids:
          group: 1879048192
          user: 1879048192
        token_expire: 90
      scaler:
        crane:
          insecure: true
        k8s:
          clusters:
            kubernetes-admin@cluster.local:
              alias: "production"
              nodes:
                - "<K8s host 1>"
                - "<K8s host 2>"
                - "<K8s host 3>"
                - "<K8s host 4>"
                - "<K8s host 5>"
    redis:
      host: "redis.redis.svc.cluster.local"
      port: 6379
      password: "<PASSWORD>"
    scylla:
      nodes:
	- <SCYLLA IP 1>
	- <SCYLLA IP 2>
	- <SCYLLA IP 3>
      replication: 3
      auth:
        username: "thorium"
        password: "<PASSWORD>"
    elastic:
      node: "https://elastic-es-http.elastic-system.svc.cluster.local:9200"
      username: "thorium"
      password: "<PASSWORD>"
      results: "results"
  registry_auth:
    <REGISTRY.DOMAIN: <base64 USERNAME:PASSWORD>
    <REGISTRY2.DOMAIN: <base64 USERNAME:PASSWORD>

Thorium deployments that consist of multiple K8s clusters (managed by a single scaler pod) will require a dedicated kubeconfig secret rather than the use of a service account that is default for single cluster instances. This secret file must be built manually from the kubeconfig files of the Thorium clusters that will be managed. The service_account field in the ThoriumCluster CRD will be set to false for multi-cluster Thorium deployments. Most Thorium deployments will are not multi-cluster.

Create the ThoriumCluster resource:

The operator will attempt to deploy the ThoriumCluster from the CRD you applied. This will include creating secrets such as the shared thorium config (thorium.yml). It will also deploy scaler, api, event-handler, and search-streamer pods if those have been been specified.

# create the thorium CRD
kubectl create -f thorium-cluster-<DEPLOYMENT>.yml

6) Create IngressRoutes

IngressRoutes will be needed to direct web traffic to the Thorium API through the Traefik ingress proxy. Modify the following command with the correct THORIUM.DOMAIN FQDN. A TLS certificate called api-certs will be required. Without that K8s secret, Traefik will serve a default self-signed cert that web clients will flag as insecure.

Create TLS K8s secret

Once you have signed tls.crt and tls.key files, create the api-certs secret using kubectl.

kubectl create secret tls api-certs --namespace="thorium" --key="tls.key" --cert="tls.crt"

Create Traefik IngressRoutes and Middleware

apiVersion: traefik.io/v1alpha1
kind: TLSStore
metadata:
  name: default
  namespace: thorium
spec:
  defaultCertificate:
    secretName: api-certs
---

apiVersion: traefik.io/v1alpha1 
kind: Middleware
metadata:
  name: ui-prefix-prepend
spec:
  addPrefix:
    prefix: /ui
---

apiVersion: traefik.io/v1alpha1
kind: IngressRoute
metadata:
  name: thorium-ingress
spec:
  entryPoints:
    - websecure
  routes:
  - match: "Host(`THORIUM.DOMAIN`) && PathPrefix(`/api`)"
    kind: Rule
    services:
    - name: thorium-api
      port: 80
  - match: "Host(`THORIUM.DOMAIN`) && PathPrefix(`/assets`)"
    kind: Rule
    services:
    - name: thorium-api
      port: 80
  - match: "Host(`THORIUM.DOMAIN) && PathPrefix(`/ui`)"
    kind: Rule
    services:
    - name: thorium-api
      port: 80
  - match: "Host(`THORIUM.DOMAIN`)"
    kind: Rule
    services:
    - name: thorium-api
      port: 80
    middlewares:
      - name: ui-prefix-prepend
  tls:
    secretName: api-certs