BookmarkSubscribeRSS Feed

Introducing the SAS Viya Deployment Operator

Started ‎06-22-2021 by
Modified ‎06-22-2021 by
Views 9,943

With the shipment of Stable 2020.1.4 (mid-March 2021) the preferred method of deploying SAS Viya is to use the SAS Viya Deployment Operator, or it should be going forward. In this article we will explore the deployment operator and position it relative to the Lifecycle Operations Tool.

 

Please note, it is still possible to do a manual install (deployment), but the operator is here to simplify the deployment process and will be the best approach for many or most customer sites.

 

So, what is the SAS Viya Deployment Operator?

 

The SAS Viya Deployment Operator is a Kubernetes operator that automates many of the manual tasks that are required to deploy and update the Viya software. The deployment operator can automate SAS Viya deployments in a single namespace or across multiple namespaces within a single Kubernetes cluster.

 

In the documentation this is referred to as running the operator in namespace mode and cluster-wide mode. This is illustrated below.

 

MG_1_operator_structure.png

Select any image to see a larger version.
Mobile users: To view the images, select the "Full" version at the bottom of the page.

 

 

There is also the Orchestration Tool, this is different to the deployment operator. The deployment operator is used to deploy a Viya environment and upgrade it. While the Orchestration Tool is used for what is called “lifecycle operations”. This includes starting and stopping the Viya deployment and other administration tasks.  

 

There is more than one operator…

A Kubernetes operator is an application-specific controller that extends the functionality of the Kubernetes API to create, configure, and manage instances of complex applications on behalf of a Kubernetes user.

 

In addition to the SAS Viya Deployment Operator, SAS has created other operators to assist with the deployment and operations of the Viya components. For example, the CAS Operator and the SAS Event Stream Processing (ESP) Operator.

 

We also make use of operators developed by other parties, for example the Crunchy Data Operator. This is illustrated in the figure below. The operators are depicted with the lightning bolt icons.

 

 

MG_2_operators.png

 

 

Recommended deployment approach

As previously stated, the operator can run in two modes, namespace mode and cluster-wide mode. The operator is watching for custom resource updates, objects of the type (kind) SASDeployment, when running in cluster-wide mode this can be a CR update in any SAS Viya namespace.

 

Therefore, it is important that you do NOT run the operator in a mixed mode. That is, having one or more instances of the operator deployed in namespace mode and an operator running in cluster-wide mode. You either need to run a single operator in cluster-wide mode OR deploy the operator to each SAS Viya namespace, but NOT both.

 

Taking this a step further, I would recommend using the operator in cluster-wide mode for the following reasons:

 

  • You deploy the operator once and can manage multiple SAS Viya deployments.
  • As the operator is not linked to a SAS Viya instance (not running in the SAS Viya namespace) you can delete the SAS Viya namespace without affecting the operator.
  • The operator is backward compatible; therefore, you can use it to deploy different SAS Viya versions. It is not locked to a specific SAS Viya version.

 

This approach is illustrated below. In this example, the ‘sas-ops’ namespace is being used for the deployment operator and the Orchestration Tool.

MG_DepOp_and_namespaces.png

 

What else do you need to know?

The deployment operator image is pulled from the SAS Container Registry (cr.sas.com), which means you first need to retrieve the deployment assets (the TGZ file) from the my.sas.com portal. Then, there is a simple process to configure and deploy the operator.

 

As previously stated, the SAS Viya Deployment Operator watches the cluster for SASDeployment custom resource objects. The data in the SASDeployment custom resource is used by the operator when deploying SAS Viya. The operator needs your Viya configuration as input, it doesn’t magically create this, you still must provide the kustomization files.

 

There are two ways to provide the Viya configuration:

 

  • Using the “in-line” method, or
  • Using a Git repository, HTTP file server or some form of file share.

 

As the name suggests, when using the in-line method, the input YAML files are provided “in-line” in the custom resource YAML. As you can imagine this can very quickly get unmanageable, let alone fraught with YAML indentation problems, and the fact that you may have passwords stored in plain text (it’s in there if you look closely)!

 

Here is an example of an inline configuration for SAS Viya running in a namespace called 'lab'.

 

Example 1. Inline configuration method

 

apiVersion: orchestration.sas.com/v1alpha1
kind: SASDeployment
metadata:
  name: lab-inline-sasdeployment
spec:
  cadenceName: "stable"
  cadenceVersion: "2020.1.4"
  cadenceRelease: ""
  # The following is an example of how to specify inline user content.
  # See documentation for specifying license, client certificate,
  # and certificate authority certificate.
  userContent:
    files:
      "kustomization.yaml": |-
        ---
        namespace: lab
        resources:
          - sas-bases/base
          - sas-bases/overlays/cert-manager-issuer     # TLS
          - sas-bases/overlays/network/ingress
          - sas-bases/overlays/network/ingress/security   # TLS
          - sas-bases/overlays/internal-postgres
          - sas-bases/overlays/crunchydata
          - sas-bases/overlays/cas-server
          - sas-bases/overlays/update-checker       # added update checker
          - sas-bases/overlays/cas-server/auto-resources    # CAS-related
        configurations:
          - sas-bases/overlays/required/kustomizeconfig.yaml  # required for 0.6
        transformers:
          - sas-bases/overlays/network/ingress/security/transformers/product-tls-transformers.yaml   # TLS
          - sas-bases/overlays/network/ingress/security/transformers/ingress-tls-transformers.yaml   # TLS
          - sas-bases/overlays/network/ingress/security/transformers/backend-tls-transformers.yaml   # TLS
          - sas-bases/overlays/required/transformers.yaml
          - sas-bases/overlays/internal-postgres/internal-postgres-transformer.yaml
          - site-config/security/cert-manager-provided-ingress-certificate.yaml     # TLS
          - sas-bases/overlays/cas-server/auto-resources/remove-resources.yaml    # CAS-related
        #- sas-bases/overlays/scaling/zero-scale/phase-0-transformer.yaml
        #- sas-bases/overlays/scaling/zero-scale/phase-1-transformer.yaml
        configMapGenerator:
          - name: ingress-input
            behavior: merge
            literals:
              - INGRESS_HOST=lab.my-organisation.com
          - name: sas-shared-config
            behavior: merge
            literals:
              - SAS_SERVICES_URL=https://lab.my-organisation.com
          - name: sas-consul-config            ## This injects content into consul. You can add, but not replace
            behavior: merge
            files:
              - SITEDEFAULT_CONF=sitedefault.yaml
          # # This is to fix an issue that only appears in RACE Exnet.
          # # Do not do this at a customer site
          - name: sas-go-config
            behavior: merge
            literals:
              - SAS_BOOTSTRAP_HTTP_CLIENT_TIMEOUT_REQUEST='5m'
        generators:
          - postgres-custom-config.yaml
      "sitedefault.yaml": |-
        ---
        config:
          application:
            sas.logon.initial:
              user: sasboot
              password: lnxsas
      "postgres-custom-config.yaml": |-
        ---
        apiVersion: builtin
        kind: ConfigMapGenerator
        metadata:
          name: postgresql-custom
        behavior: merge
        literals:
        - |
          postgres-ha.yaml=
          ---
          bootstrap:
            dcs:
              loop_wait: 10                                      # Added through SAS provided kustomize configMapGenerator
              ttl: 30                                            # Added through SAS provided kustomize configMapGenerator
              master_start_timeout: 0                            # Added through SAS provided kustomize configMapGenerator
              postgresql:
                parameters:
                  archive_timeout: 60                            # Added through SAS provided kustomize configMapGenerator
                  checkpoint_completion_target: 0.9              # Added through SAS provided kustomize configMapGenerator
                  effective_cache_size: 4GB                      # Added through SAS provided kustomize configMapGenerator
                  hot_standby: on                                # Added through SAS provided kustomize configMapGenerator
                  log_filename: 'postgresql_%Y%m%d%H%M%S.log'    # Added through SAS provided kustomize configMapGenerator
                  log_line_prefix: '%m'                          # Added through SAS provided kustomize configMapGenerator
                  log_min_duration_statement: -1                 # Added through SAS provided kustomize configMapGenerator
                  log_statement: 'none'                          # Added through SAS provided kustomize configMapGenerator
                  log_truncate_on_rotation: on                   # Added through SAS provided kustomize configMapGenerator
                  logging_collector: on                          # Added through SAS provided kustomize configMapGenerator
                  maintenance_work_mem: 128MB                    # Added through SAS provided kustomize configMapGenerator
                  max_connections: 1280                          # Added through SAS provided kustomize configMapGenerator
                  max_prepared_transactions: 1280                # Added through SAS provided kustomize configMapGenerator
                  max_wal_senders: 8                             # Added through SAS provided kustomize configMapGenerator
                  max_wal_size: 2GB                              # Added through SAS provided kustomize configMapGenerator
                  min_wal_size: 80MB                             # Added through SAS provided kustomize configMapGenerator
                  password_encryption: scram-sha-256 # Added through SAS provided kustomize configMapGenerator
                  shared_buffers: 4GB                            # Added through SAS provided kustomize configMapGenerator
                  ssl_ciphers: 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384'     # Added through SAS provided kustomize configMapGenerator
                  ssl_prefer_server_ciphers: on                  # Added through SAS provided kustomize configMapGenerator
                  synchronous_standby_names: ''                  # Added through SAS provided kustomize configMapGenerator
                  wal_buffers: 16MB                              # Added through SAS provided kustomize configMapGenerator
                  wal_keep_segments: 1000                        # Added through SAS provided kustomize configMapGenerator
                  wal_level: hot_standby                         # Added through SAS provided kustomize configMapGenerator
                  wal_log_hints: on                              # Added through SAS provided kustomize configMapGenerator
                  work_mem: 16MB                                 # Added through SAS provided kustomize configMapGenerator
            initdb:
             - encoding: UTF8
             - no-locale
          postgresql:
            pg_hba:
              - local all postgres peer
              - local all all trust
              - local all crunchyadm peer
              - hostssl replication primaryuser 0.0.0.0/0 scram-sha-256
              - hostssl all all 127.0.0.1/32 scram-sha-256
              - hostssl all all 0.0.0.0/0 scram-sha-256
      "site-config/security/cert-manager-provided-ingress-certificate.yaml": |-
        ---
        apiVersion: builtin
        kind: PatchTransformer
        metadata:
          name: sas-cert-manager-ingress-annotation-transformer
        patch: |-
          - op: add
            path: /metadata/annotations/cert-manager.io~1issuer
            value: sas-viya-issuer # name of the cert-manager issuer that will supply the Ingress cert, such as sas-viya-issuer
        target:
          kind: Ingress
          name: .*
  license:
    secretKeyRef:
      name: order-secrets
      key: license
  clientCertificate:
    secretKeyRef:
      name: order-secrets
      key: certificate
  caCertificate:
    secretKeyRef:
      name: order-secrets
      key: cacertificate

 

Compare this to the Git method, using a GitLab server called 'gitlab.devops.my-organisation.com'. The 'discovery' project was created by a user called 'cloud-user'.

 

Example 2. Using GitLab

 


apiVersion: orchestration.sas.com/v1alpha1
kind: SASDeployment
metadata:
  annotations:
    environment.orchestration.sas.com/readOnlyRootFilesystem: "false"
    operator.sas.com/checksum: ""
  name: discovery-sasdeployment
spec:
  cadenceName: "stable"
  cadenceVersion: "2020.1.4"
  cadenceRelease: ""
  repositoryWarehouse:
    url: https://ses.sas.download/ses           ## this is the default value
    updatePolicy: Never                         ## this is the default value. The alternative is 'Releases'
  # The following is an example of using URLs to specify user
  # content, a license, a client certificate, and a CA certiciate.
  userContent:
    # See HashiCorp's Go Getter "URL Format" documentation for details:
    #    https://pkg.go.dev/github.com/hashicorp/go-getter@v1.4.1?tab=overview#url-format
    url: git::http://gitlab.devops.my-organisation.com/cloud-user/discovery.git
  license:
    url: http://gitlab.devops.my-organisation.com/cloud-user/discovery/-/raw/master/secrets/license/SASViyaV4_license.jwt
  clientCertificate:
    url: http://gitlab.devops.my-organisation.com/cloud-user/discovery/-/raw/master/secrets/entitlement-certificates/entitlement_certificate.pem
  caCertificate:
    url: http://gitlab.devops.my-organisation.com/cloud-user/discovery/-/raw/master/secrets/ca-certificates/SAS_CA_Certificate.pem

 

While the Orchestration Tool can be used to create the SASDeployment CR, it is definitely a lot simpler to manage and understand the SASDeployment CR when using the Git method.

 

Therefore, the other recommendation that I will make is to use a source code repository, such as Git, to place all the configuration files and the custom resource file under version control.

 

The following diagram illustrates using GitLab and the high-level process flow that happens when using the deployment operator.

 

MG_4_example.png

 

In this example we are using OpenLDAP for the identities, this is shown by the GELLDAP box.

 

The numbered circles indicate the deployment (process) steps:

 

  1. Issue the kubectl apply to create or update the SASDeployment custom resource (CR).
  2. The operator watches for SASDeployment CR changes and this triggers the Viya deployment. In the exercise it is for a Discovery environment.
  3. The operator reads the source files described in the SASDeployment CR from the Git project.
  4. The operator deploys the Viya environment to the discovery namespace.

 

Hierarchy of files

There is a hierarchy of files, especially when using the second method (a Git repository, HTTP server or file share). You will see from the example above, that the SASDeployment YAML (the CR YAML) includes references to other files. For example, the kustomization.yaml file.

 

The deployment operator is ONLY looking for changes to the CR, so what happens if the configuration change is in one of the other YAML files?

 

For example, you might be making an administration (configuration) change, changing from using an SMP CAS server to a MPP CAS server, or increasing the number of CAS Workers.

 

These changes are in other files so would not trigger the deployment operator to update the Viya deployment. But don’t worry there is a method to trigger an update.

 

To ensure that any change is picked up by the deployment operator it is recommended that the following annotation is added to the SASDeployment CR definition

 

operator.sas.com/checksum: ""

 

This will reset the CR checksum each time the ‘kubectl apply’ command is issued. Thus, forcing the operator to read all the configuration files as it does when the CR is first created. If you look closely at the second example above, you will see that this annotation has been added to the ‘metadata’ section.  

 

Who updates the deployment operator?

Finally, the deployment operator doesn’t automatically update itself, so today a manual process is required to periodically update the operator.

 

I would recommend doing that before deploying any new SAS Viya version. Remember, the deployment operator is backward compatible; therefore, the most recent version of the operator can use it to deploy different SAS Viya versions. It is not locked to a specific SAS Viya version.  

 

Conclusion

The more I use the deployment operator the more I like it. Remember, you still have to provide the configuration for your site / SAS Viya environment, the Deployment Operator doesn't create this for you.

 

Find more articles from SAS Global Enablement and Learning here.

 

Version history
Last update:
‎06-22-2021 10:44 PM
Updated by:
Contributors

SAS Innovate 2025: Register Now

Registration is now open for SAS Innovate 2025 , our biggest and most exciting global event of the year! Join us in Orlando, FL, May 6-9.
Sign up by Dec. 31 to get the 2024 rate of just $495.
Register now!

Free course: Data Literacy Essentials

Data Literacy is for all, even absolute beginners. Jump on board with this free e-learning  and boost your career prospects.

Get Started

Article Tags