C Run Containers as Non-Root

The Dockerfiles, as shipped, contain one Perl script that runs as root. This Perl script performs an initial configuration of the tt container in each Pod. It then switches from root to the oracle user. If you do not want any process in any container to run as root, you can use the procedure in this appendix.

Note: TimesTen (including the TimesTen daemons, the TimesTen agent, and the Kubernetes Operator) does not run as root.

The appendix shows a complete example.

The overview describes the requirements for configuring the TimesTen containers to run as non-root. The remaining sections show the standard setup procedures for configuring your active standby pairs of TimesTen databases. The final section shows you how to verify the TimesTen containers are running as non-root.

Topics:

Overview

You can configure your containers to run as non-root. This involves two additional steps from the standard setup procedures:

  1. Uncomment USER 333 in the Dockerfile located in the /ttimage directory. See "Build the TimesTen image" for details.

  2. Include .template.spec.securityContext information in the YAML file of your TimesTenClassic object. See "Create the TimesTenClassic object" for details.

Set up the environment

Before starting the example, ensure you have:

  • Completed the prerequisites. See "Prerequisites" for information on the required prerequisites.

To set up the environment, perform these steps from your Linux development host:

Download the TimesTen Operator

Perform these steps to download the full distribution of TimesTen and then unpack the TimesTen Operator distribution that is embedded within it. Perform all steps from your Linux development host.

  1. From the directory of your choice:

    • Create one subdirectory into which you will download the TimesTen full distribution. For example, create the installation_dir subdirectory. (The installation_dir directory is used in the remainder of this chapter.)

    • Create a second subdirectory into which you will unpack the TimesTen Operator distribution. For example, create the kube_files subdirectory. (This kube_files directory is used in the remainder of this chapter.)

    % mkdir -p installation_dir
    % mkdir -p kube_files
    

    You are now ready to download and unpack the TimesTen full distribution.

  2. Navigate to installation_dir.

    % cd installation_dir
    

    Download the TimesTen full distribution into this directory. As an example, download the timesten1814110.server.linux8664.zip file, (the 18.1.4.11.0 full distribution for Linux 64-bit).

  3. From the installation_dir, use the ZIP utility to unpack the TimesTen distribution.

    % unzip timesten1814110.server.linux8664.zip
    Archive:  /timesten/installation/timesten1814110.server.linux8664.zip
       creating: tt18.1.4.11.0/
       creating: tt18.1.4.11.0/ttoracle_home/
    ...
       creating: tt18.1.4.11.0/kubernetes/
    ...
    

    You successfully unpacked the TimesTen full distribution.

    Note that the installation_dir/tt18.1.4.11.0/kubernetes directory is created. The operator.zip file is located in this directory. For example, this is a sample directory structure after unpacking the distribution:

    % pwd
    installation_dir/tt18.1.4.11.0
    % dir
    3rdparty  include     lib      oraclescripts  README.html  ttoracle_home
    bin       info        network  PERL           startup
    grid      kubernetes  nls      plsql          support
    
  4. Navigate to the kube_files directory and unpack the operator.zip file into it. In this example, unpack the installation_dir/tt18.1.4.11.0/kubernetes/operator.zip file.

    % cd kube_files
    % unzip installation_dir/tt18.1.4.11.0/kubernetes/operator.zip
    [...UNZIP OUTPUT...]
    

    You successfully unpacked the installation_dir/tt18.1.4.11.0/kubernetes/operator.zip file into the kube_files directory.

  5. Review the directory structure. Later in this chapter, you will modify some of the files in these subdirectories. This example shows the most important subdirectories and files, which can change from release to release.

    README.md
    deploy/crd.yaml
    deploy/operator.yaml
    deploy/service_account.yaml
    operator/Dockerfile
    operator/timestenclassic-operator
    ttimage/agent2
    ttimage/.bashrc
    ttimage/create1.sql
    ttimage/create2.sql
    ttimage/Dockerfile
    ttimage/get1.sql
    ttimage/pausecq.sql
    ttimage/repcreate.sql
    ttimage/repduplicate.sql
    ttimage/runsql,sql
    ttimage/starthost.pl
    ttimage/.ttdotversion
    ttimage/.ttdrop
    

    Note:

    This directory tree must persist through the lifetime of the TimesTen Operator.

    In addition, do not delete the TimesTen full distribution file (timesten1814110.server.linux8664.zip, in this example). You need to copy this file into the:

    • /operator directory to build the Operator image and push the image to the image registry. See "Build the Operator image" for details.

    • /ttimage directory to build the TimesTen image and push the image to the image registry. See "Build the TimesTen image" for details.

You successfully downloaded and unpacked the TimesTen Operator distribution.

Configure Kubernetes

The Operator runs by using a Kubernetes service account. This service account needs permissions and privileges in your namespace. These permissions and privileges are granted through a role. The service_account.yaml file adds the service account and the role to your namespace, and grants the service account the privileges that are specified in the role. The service_account.yaml file is provided in the operator.zip file you previously unpacked.

Note:

The provided role gives the timestenclassic-operator broad permissions within your namespace. Examine the permissions provided in the service_account.yaml file to see if the permissions need to be modified. If so, modify the permissions before running the commands in this example.

Perform these steps:

  1. Navigate to the kube_files/deploy directory.

    % cd kube_files/deploy
    
  2. Create the service account.

    % kubectl create -f service_account.yaml
    role.rbac.authorization.k8s.io/timestenclassic-operator created
    serviceaccount/timestenclassic-operator created
    rolebinding.rbac.authorization.k8s.io/timestenclassic-operator created
    

The service_account.yaml file created the timestenclassic-operator service account and the timestenclassic-operator role in your namespace, and granted the service account the privileges specified in the role.

Deploy the TimesTenClassic CRD

Navigate to the kube_files/deploy directory, and then use the kubectl create command to create the TimesTenClassic customized resource definition (CRD) in your Kubernetes cluster.

% cd kube_files/deploy
% kubectl create -f crd.yaml
customresourcedefinition.apiextensions.k8s.io/
timestenclassics.timesten.oracle.com created

You successfully added the TimesTenClassic object type to your Kubernetes cluster.

Build the Operator image

Kubernetes Operators are Pods that run a customized image. Before you can run the Operator, you must build this image and push it to your image registry.

The files needed to create the image are provided in the kube_files/operator directory (part of the ZIP file you previously unpacked). In the kube_files/operator directory are the Dockerfile and the binaries needed to create the Operator image.

To build the Operator image and push it to your registry, perform these steps:

  1. Navigate to the kube_files/operator directory, and copy the TimesTen distribution into it. This example assumes you downloaded the timesten1814110.server.linux8664.zip distribution into the installation_dir directory. See "Download the TimesTen Operator" for information. Then, verify the timesten1814110.server.linux8664.zip file is in the kube_files/operator directory.

    % cd kube_files/operator
    % cp installation_dir/timesten1814110.server.linux8664.zip .
    % ls -a
    Dockerfile
    timesten1814110.server.linux8664.zip
    timestenclassic-operator
    
  2. Navigate to the kube_files/operator directory (if not already in this directory) and use the docker command to build the Operator image. You can choose any name for ttclassic-operator:2 (represented in bold in this example). Note that the output may change from release to release.

    % cd kube_files/operator
    % docker build -t ttclassic-operator:3 .
    Sending build context to Docker daemon  478.6MB
    Step 1/7 : FROM container-registry.oracle.com/os/oraclelinux:7
     ---> d788eca028a0
    Step 2/7 : ARG TT_DISTRO=timesten1814110.server.linux8664.zip
     ---> Using cache
     ---> a259a93fe906
    Step 3/7 : RUN yum -y install openssl unzip && /usr/sbin/useradd -d 
    /tt-operator -m -u 1001 -s /bin/nologin -U tt-operator
     ---> Using cache
     ---> e3f1427246ab
    Step 4/7 : COPY --chown=tt-operator:tt-operator timestenclassic-operator 
    /usr/local/bin/timestenclassic-operator
     ---> Using cache
     ---> 6ccad53230f0
    Step 5/7 : COPY --chown=tt-operator:tt-operator $TT_DISTRO /tt-operator/
    $TT_DISTRO
     ---> 5cd31705485a
    Step 6/7 : USER tt-operator
     ---> Running in 6a773ddac5dd
    Removing intermediate container 6a773ddac5dd
     ---> 875ee38ebc75
    Step 7/7 : ENTRYPOINT ["/usr/local/bin/timestenclassic-operator"]
     ---> Running in fed0f6c94c2f
    Removing intermediate container fed0f6c94c2f
     ---> 10dde79e1617
    Successfully built 10dde79e1617
    Successfully tagged ttclassic-operator:3
    
  3. Use the docker command to tag the Operator image.

    • Replace phx.ocir.io/youraccount with the location of your image registry. (phx.ocir.io/youraccount is represented in bold in this example.)

    • Replace ttclassic-operator:3 with the name you chose in the previous step. (ttclassic-operator is represented in bold in this example.)

    % docker tag ttclassic-operator:3 phx.ocir.io/youraccount/ttclassic-operator:3
    
  4. Use the docker command to push the Operator image to your registry.

    • Replace phx.ocir.io/youraccount with the location of your image registry. (phx.ocir.io/youraccount is represented in bold in this example.)

    • Replace ttclassic-operator:3 with the name you chose in the previous steps. (ttclassic-operator:3 is represented in bold in this example.)

    % docker push phx.ocir.io/youraccount/ttclassic-operator:3
    The push refers to repository [phx.ocir.io/youraccount/ttclassic-operator]
    46458e9fc890: Pushed
    471a399f0540: Pushed
    9e51a2b82af3: Pushed
    2f915858a916: Layer already exists
    3: digest: 
    sha256:9b941f12e3d52298b9b38f7766ddcdfb1d011857a990ff01a8adafd32f3d3e8d size: 
    1166
    

You successfully built the Operator image and pushed it to your image registry.

Deploy the Operator

To deploy the Operator, you first customize it for your namespace and then deploy it. As a final step, you can verify the Operator is running. See "Deploying the Operator" for information.

To customize the Operator for your namespace, navigate to the kube_files/deploy directory, and edit the operator.yaml file. This file is provided in the distribution that you previously unpacked. See "Downloading TimesTen and the TimesTen Operator" for details.

  1. Modify these fields represented in bold (in the operator.yaml file below):

    • replicas: 1

      Replace 1 with the number of copies of the Operator that you would like to run. 1 is acceptable for development and testing. However, you can run more than one replica for high availability purposes.

    • Replace sekret with the name of the image pull secret that Kubernetes uses to pull images from your registry.

    • Replace phx.ocir.io/youraccount with the location of your image registry.

    • Replace ttclassic-operator:3 with the name you chose in the previous steps.

    % cd kube_files/deploy
    % vi operator.yaml
    
    apiVersion: apps/v1
    kind: Deployment
    metadata:
      name: timestenclassic-operator
    spec:
      replicas: 1
      selector:
        matchLabels:
          name: timestenclassic-operator
      template:
        metadata:
          labels:
            name: timestenclassic-operator
        spec:
          serviceAccountName: timestenclassic-operator
          imagePullSecrets:
          - name: sekret
          containers:
            - name: timestenclassic-operator
              image: phx.ocir.io/youraccount/ttclassic-operator:3
              command:
              - timestenclassic-operator
              imagePullPolicy: Always
              env:
                - name: WATCH_NAMESPACE
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.namespace
                - name: POD_NAME
                  valueFrom:
                    fieldRef:
                      fieldPath: metadata.name
                - name: OPERATOR_NAME
                  value: "timestenclassic-operator"
                - name: GODEBUG
                  value: "x509ignoreCN=0"
    
  2. Use the kubectl create command to define the Operator to your namespace and to start the Operator.

    % kubectl create -f operator.yaml
    deployment.apps/timestenclassic-operator created
    

    You deployed the Operator. The Operator should now be running.

  3. Use the kubectl get pods command to verify the Operator is running. If the STATUS field has a value of Running, the Operator is running.

    % kubectl get pods
    NAME                                       READY   STATUS    RESTARTS   AGE
    timestenclassic-operator-846cb5c97c-9gv46  1/1     Running   0          37s
    

    You verified that the Operator is running.

Build the TimesTen image

Before you can start TimesTen in your Kubernetes cluster, you must first package TimesTen as a container image and then push the image to your image registry. The files that you need to do this are provided in the kube_files directory tree. See "Building the TimesTen image" for information.

To run the TimesTen containers as non-root, you must uncomment USER 333 in the kube_files/ttimage/Dockerfile.

To create the TimesTen container image, perform these steps:

  1. Navigate to the kube_files/ttimage directory, and copy the TimesTen distribution into it. This example assumes you downloaded the timesten1814110.server.linux8664.zip distribution into the installation_dir directory. See "Download the TimesTen Operator" for information. Then, verify the timesten1814110.server.linux8664.zip file is in the kube_files/ttimage directory.

    % cd kube_files/ttimage
    % cp installation_dir/timesten1814110.server.linux8664.zip .
    % ls *.zip
    timesten1814110.server.linux8664.zip
    
  2. Navigate to the kube_files/ttimage directory (if not already in this directory). Edit the Dockerfile, replacing timesten1814110.server.linux8664.zip with the name of your TimesTen full distribution. If your TimesTen distribution is timesten1814110.server.linux8664.zip, no modification is necessary. If not, the modification you need to make is represented in bold. Note: The TimesTen full distribution must be 18.1.4.11.0 or later.

    In addition, uncomment USER 333 in this Dockerfile (represented in bold, in this example).

    % cd kube_files/ttimage
    % vi Dockerfile
    
    # Copyright (c) 2019, 2021, Oracle and/or its affiliates.
     
    FROM container-registry.oracle.com/os/oraclelinux:7
     
    ARG TT_DISTRO=timesten1814110.server.linux8664.zip
     
    RUN yum -y install tar gzip vim curl unzip libaio util-linux
    RUN groupadd -g 333 oracle
    RUN useradd -M -d /tt/home/oracle -s /bin/bash -u 333 -g oracle oracle
    RUN install -d -m 0750 -o oracle -g oracle /home/oracle
    COPY --chown=oracle:oracle $TT_DISTRO /home/oracle/
    COPY --chown=oracle:oracle .bashrc starthost.pl .ttdrop .ttdotversion agent2 
    create1.sql create2.sql get1.sql repcreate.sql repduplicate.sql runsql.sql 
    pausecg.sql /home/oracle/
    # Uncomment the following line if you are using the optional non-root 
    installation procedure.
    USER 333
    ENTRYPOINT "/home/oracle/starthost.pl"
    
  3. Use the docker command to build the TimesTen container image. Replace tt1814110 with a name of your choosing (represented in bold, in the docker build command below). Note that the output may change from release to release.

    % docker build -t tt1814110:3 .
    
    Sending build context to Docker daemon  445.8MB
    Step 1/9 : FROM container-registry.oracle.com/os/oraclelinux:7
     ---> d788eca028a0
    Step 2/9 : ARG TT_DISTRO=timesten1814110.server.linux8664.zip
     ---> Using cache
     ---> a259a93fe906
    Step 3/9 : RUN yum -y install tar gzip vim curl unzip libaio util-linux
     ---> Using cache
     ---> ac676b5376f3
    Step 4/9 : RUN groupadd -g 333 oracle
     ---> Using cache
     ---> ce16920f085c
    Step 5/9 : RUN useradd -M -d /tt/home/oracle -s /bin/bash -u 333 -g oracle 
    oracle
     ---> Using cache
     ---> 0319814aca1c
    Step 6/9 : RUN install -d -m 0750 -o oracle -g oracle /home/oracle
     ---> Using cache
     ---> c8612b53398a
    Step 7/9 : COPY --chown=oracle:oracle $TT_DISTRO /home/oracle/
     ---> 31cae98b71fd
    Step 8/9 : COPY --chown=oracle:oracle .bashrc starthost.pl .ttdrop 
    .ttdotversion agent2 create1.sql create2.sql get1.sql repcreate.sql 
    repduplicate.sql runsql.sql pausecg.sql /home/oracle/
     ---> e50eb99c9b54
    Step 9/9 : ENTRYPOINT "/home/oracle/starthost.pl"
     ---> Running in 0b41efd38837
    Removing intermediate container 0b41efd38837
     ---> 171245e546d5
    Successfully built 171245e546d5
    Successfully tagged tt1814110:3
    
  4. Use the docker command to tag the TimesTen container image. Replace the following, represented in bold, in the docker tag command below.

    • tt1814110:3 with the name you chose in the previous step.

    • phx.ocir.io/youraccount with the location of your image registry.

    % docker tag tt1814110:3 phx.ocir.io/youraccount/tt1814110:3
    
  5. Use the docker command to push the TimesTen container image to your registry. Replace the following, represented in bold, in the docker push command below.

    • phx.ocir.io/youraccount with the location of your image registry.

    • tt1814110:3 with the name you chose previously.

    % docker push phx.ocir.io/youraccount/tt1814110:3
    
    The push refers to repository [phx.ocir.io/youraccount/tt1814110]
    97a0f250b2fe: Pushed
    650b003a3ad4: Pushed
    b8de51528854: Pushed
    62192d26e325: Pushed
    7dfe13e9b5a4: Pushed
    d8570fce965c: Pushed
    2f915858a916: Layer already exists
    3: digest: 
    sha256:a6ac313394229eb2256d4a56fbcd8e2eda50ea2cc21991fa76f11701f2299710 
    size: 1788
    

You successfully built the TimesTen container image. It is pushed to your image registry.

Create the ConfigMap object

This section creates the sample ConfigMap. This ConfigMap contains the db.ini, the adminUser, and the schema.sql metadata files. This ConfigMap will be referenced when you define the TimesTenClassic object. See "Understanding the configuration metadata and the Kubernetes facilities" for information on the configuration files and the ConfigMap facility.

On your Linux development host, perform these steps:

  1. From the directory of your choice, create an empty subdirectory for the metadata files. This example creates the cm_sample subdirectory. (The cm_sample directory is used in the remainder of this example to denote this directory.)

    % mkdir -p cm_sample
    
  2. Navigate to the ConfigMap directory.

    % cd cm_sample
    
  3. Create the db.ini file in this ConfigMap directory (cm_sample, in this example). In this db.ini file, define the PermSize and DatabaseCharacterSet connection attributes.

    vi db.ini
    
    PermSize=200
    DatabaseCharacterSet=AL32UTF8
    
  4. Create the adminUser file in this ConfigMap directory (cm_sample in this example). In this adminUser file, create the scott user with the tiger password.

    vi adminUser
    
    scott/tiger
    
  5. Create the schema.sql file in this ConfigMap directory (cm_sample in this example). In this schema.sql file, define the s sequence and the emp table for the scott user. The Operator will automatically initialize your database with these object definitions.

    vi schema.sql
    
    create sequence scott.s;
    create table scott.emp (
      id number not null primary key,
      name char(32)
    );
    
  6. Create the ConfigMap. The files in the cm_sample directory are included in the ConfigMap and, later, will be available in the TimesTen containers.

    In this example:

    • The name of the ConfigMap is sample. Replace sample with a name of your choosing. (sample is represented in bold in this example.)

    • This example uses cm_sample as the directory where the files that will be copied into the ConfigMap reside. If you use a different directory, replace cm_sample with the name of your directory. (cm_sample is represented in bold in this example.)

    Use the kubectl create command to create the ConfigMap:

    % kubectl create configmap sample --from-file=cm_sample
    configmap/sample created
    

    You successfully created and deployed the sample ConfigMap.

  7. Use the kubectl describe command to verify the contents of the ConfigMap. (sample, in this example.)

    % kubectl describe configmap sample
    Name:         sample
    Namespace:    mynamespace
    Labels:       <none>
    Annotations:  <none>
     
    Data
    ====
    adminUser:
    ----
    scott/tiger
     
    db.ini:
    ----
    PermSize=200
    DatabaseCharacterSet=AL32UTF8
     
    schema.sql:
    ----
    create sequence scott.s;
    create table scott.emp (
      id number not null primary key,
      name char(32)
    );
     
     
    Events:  <none>
    

Create the TimesTenClassic object

This section creates the TimesTenClassic object. See "Defining and creating the TimesTenClassic object" and "The TimesTenClassic object type" for detailed information on the TimesTenClassic object.

To run the TimesTen containers as non-root, you must add SecurityContext as illustrated below.

Perform these steps:

  1. Create an empty YAML file. You can choose any name, but you may want to use the same name you used for the name of the TimesTenClassic object. (In this example, sample.) The YAML file contains the definitions for the TimesTenClassic object. See "TimesTenClassicSpecSpec" for information on the fields that you must specify in this YAML file as well as the fields that are optional.

    To run the TimesTen containers as non-root, add .template.spec.securityContext information (represented in bold, in this example).

    In addition, replace the following. (The values you can replace are represented in bold.)

    • name: Replace sample with the name of your TimesTenClassic object.

    • storageClassName: Replace oci with the name of the storage class used to allocate PersistentVolumes to hold TimesTen.

    • storageSize: Replace 250G with the amount of storage that should be requested for each Pod to hold TimesTen. Note: This example assumes a production environment and uses a value of 250G for storageSize. For demonstration purposes, a value of 50G is adequate. See the storageSize and the logStorageSize entries in the Table 11-3, "TimesTenClassicSpecSpec" for information.

    • image: Replace phx.ocir.io/youraccount/tt1814110:3 with the location of the image registry (phx.ocir.io/youraccount) and the image containing TimesTen (tt1814110:3)

    • imagePullSecret: Replace sekret with the image pull secret that Kubernetes should use to fetch the TimesTen image.

    • dbConfigMap: This example uses one ConfigMap (called sample) for the db.ini, the adminUser, and the schema.sql metadata files. This ConfigMap will be included in the ProjectedVolume. This volume is mounted as /ttconfig in the TimesTen containers. See "Using ConfigMaps and Secrets" and "Example using one ConfigMap" for information on ConfigMaps.

    % vi sample.yaml
    
    apiVersion: timesten.oracle.com/v1
    kind: TimesTenClassic
    metadata:
      name: sample
    spec:
      ttspec:
        storageClassName: oci
        storageSize: 250G
        image: phx.ocir.io/youraccount/tt1814110:3
        dbConfigMap:
        - sample
        imagePullSecret: sekret
     template:
        spec:
          securityContext:
            fsGroup: 333
          containers:
          - name: tt
            securityContext:
              runAsUser: 333
              runAsGroup: 333
    
  2. Use the kubectl create command to create the TimesTenClassic object from the contents of the YAML file (in this example, sample.yaml). Doing so begins the process of deploying your active standby pair of TimesTen databases in the Kubernetes cluster.

    % kubectl create -f sample.yaml
    configmap/sample created
    timestenclassic.timesten.oracle.com/sample created
    

You successfully created the TimesTenClassic object in the Kubernetes cluster. The process of deploying your TimesTen databases begins, but is not yet complete.

Monitor deployment

Use the kubectl get and the kubectl describe commands to monitor the progress of the active standby pair as it is provisioned.

Note:

For the kubectl get timestenclassic and kubectl describe timestenclassic commands, you can alternatively specify kubectl get ttc and kubectl describe ttc respectively. timestenclassic and ttc are synonymous when used in these commands, and return the same results. The first kubectl get and the first kubectl describe examples in this appendix use timestenclassic. The remaining examples in this appendix use ttc for simplicity.
  1. Use the kubectl get command and review the STATE field. Observe the value is Initializing. The active standby pair provisioning has begun, but is not yet complete.

    % kubectl get timestenclassic sample
    NAME     STATE          ACTIVE   AGE
    sample   Initializing   None     11s
    
  2. Use the kubectl get command again to see if value of the STATE field has changed. In this example, the value is Normal, indicating the active standby pair of databases are now provisioned and the process is complete.

    % kubectl get ttc sample
    NAME     STATE    ACTIVE     AGE
    sample   Normal   sample-0   3m33s
    
  3. Use the kubectl describe command again to view the active standby pair provisioning in detail. Note the Security Context (represented in bold) is included in the active standby pair provisioning, indicating the TimesTen containers are running as non-root.

    % kubectl describe ttc sample
    Name:         sample
    Namespace:    mynamespace
    Labels:       <none>
    Annotations:  <none>
    API Version:  timesten.oracle.com/v1
    Kind:         TimesTenClassic
    Metadata:
      Creation Timestamp:  2021-04-09T22:01:34Z
      Generation:          1
      Resource Version:    148466657
      Self Link:     
       /apis/timesten.oracle.com/v1/namespaces/mynamespace/timestenclassics/sample
      UID:                 25ff6f40-997f-11eb-86a3-06b2b9dd76bc
    Spec:
      Template:
        Spec:
          Containers:
            Name:  tt
            Security Context:
              Run As Group:  333
              Run As User:   333
          Security Context:
            Fs Group:  333
      Ttspec:
        Db Config Map:
          sample
        Image:               phx.ocir.io/youraccount/tt1814110:3
        Image Pull Policy:   Always
        Image Pull Secret:   sekret
        Storage Class Name:  oci
        Storage Size:        250G
    Status:
      Classic Upgrade Status:
        Active Start Time:           0
        Active Status:
        Image Update Pending:        false
        Last Upgrade State Switch:   0
        Prev Reset Upgrade State:
        Prev Upgrade State:
        Standby Start Time:          0
        Standby Status:
        Upgrade Start Time:          0
        Upgrade State:
      Active Pods:                   sample-0
      High Level State:              Normal
      Last Event:                    27
      Last High Level State Switch:  1618005884
      Pod Status:
        Cache Status:
          Cache Agent:        Not Running
          Cache UID Pwd Set:  true
          N Cache Groups:     0
        Db Status:
          Db:                          Loaded
          Db Id:                       34
          Db Updatable:                Yes
        Initialized:                   true
        Last High Level State Switch:  ?
        Pod Status:
          Agent:                Up
          Last Time Reachable:  1618006024
          Pod IP:               10.244.7.37
          Pod Phase:            Running
        Prev High Level State:  Healthy
        Prev Image:
        Replication Status:
          Last Time Rep State Changed:  0
          Rep Agent:                    Running
          Rep Peer P State:             start
          Rep Scheme:                   Exists
          Rep State:                    ACTIVE
        Times Ten Status:
          Daemon:          Up
          Instance:        Exists
          Release:         18.1.4.11.0
        Admin User File:   true
        Cache User File:   false
        Cg File:           false
        Disable Return:    false
        High Level State:  Healthy
        Intended State:    Active
        Local Commit:      false
        Name:              sample-0
        Schema File:       true
        Using Twosafe:     false
        Cache Status:
          Cache Agent:        Not Running
          Cache UID Pwd Set:  true
          N Cache Groups:     0
        Db Status:
          Db:                          Loaded
          Db Id:                       34
          Db Updatable:                No
        Initialized:                   true
        Last High Level State Switch:  ?
        Pod Status:
          Agent:                Up
          Last Time Reachable:  1618006024
          Pod IP:               10.244.14.33
          Pod Phase:            Running
        Prev High Level State:  Healthy
        Prev Image:
        Replication Status:
          Last Time Rep State Changed:  0
          Rep Agent:                    Running
          Rep Peer P State:             start
          Rep Scheme:                   Exists
          Rep State:                    STANDBY
        Times Ten Status:
          Daemon:             Up
          Instance:           Exists
          Release:            18.1.4.11.0
        Admin User File:      true
        Cache User File:      false
        Cg File:              false
        Disable Return:       false
        High Level State:     Healthy
        Intended State:       Standby
        Local Commit:         false
        Name:                 sample-1
        Schema File:          true
        Using Twosafe:        false
      Prev High Level State:  Initializing
      Prev Reexamine:
      Prev Stop Managing:
      Rep Create Statement:   create active standby pair "sample" on 
    "sample-0.sample.mynamespace.svc.cluster.local", "sample" on 
    "sample-1.sample.mynamespace.svc.cluster.local" NO RETURN store "sample" on 
    "sample-0.sample.mynamespace.svc.cluster.local" PORT 4444 FAILTHRESHOLD 0 
    store "sample" on "sample-1.sample.mynamespace.svc.cluster.local" PORT 4444 
    FAILTHRESHOLD 0
      Rep Port:               4444
      Status Version:         1.0
    Events:
      Type  Reason       Age    From       Message
      ----  ------       ----   ----       -------
      -     Create       5m34s  ttclassic  Service sample created
      -     Create       5m34s  ttclassic  StatefulSet sample created
      -     Create       5m34s  ttclassic  Secret 
    tt25ff6f40-997f-11eb-86a3-06b2b9dd76bc created
      -     StateChange  4m12s  ttclassic  Pod sample-1 Daemon Up
      -     StateChange  4m12s  ttclassic  Pod sample-0 Agent Up
      -     StateChange  4m12s  ttclassic  Pod sample-0 Release 18.1.4.11.0
      -     StateChange  4m12s  ttclassic  Pod sample-1 Agent Up
      -     StateChange  4m12s  ttclassic  Pod sample-1 Release 18.1.4.11.0
      -     StateChange  4m12s  ttclassic  Pod sample-0 Daemon Up
      -     StateChange  3m2s   ttclassic  Pod sample-0 Database Loaded
      -     StateChange  3m2s   ttclassic  Pod sample-0 Database Updatable
      -     StateChange  3m2s   ttclassic  Pod sample-0 CacheAgent Not Running
      -     StateChange  3m2s   ttclassic  Pod sample-0 RepAgent Not Running
      -     StateChange  3m2s   ttclassic  Pod sample-0 RepState IDLE
      -     StateChange  3m2s   ttclassic  Pod sample-0 RepScheme None
      -     StateChange  3m1s   ttclassic  Pod sample-0 RepAgent Running
      -     StateChange  3m1s   ttclassic  Pod sample-0 RepScheme Exists
      -     StateChange  3m1s   ttclassic  Pod sample-0 RepState ACTIVE
      -     StateChange  2m42s  ttclassic  Pod sample-1 Database Loaded
      -     StateChange  2m42s  ttclassic  Pod sample-1 Database Not Updatable
      -     StateChange  2m42s  ttclassic  Pod sample-1 CacheAgent Not Running
      -     StateChange  2m42s  ttclassic  Pod sample-1 RepAgent Not Running
      -     StateChange  2m42s  ttclassic  Pod sample-1 RepScheme Exists
      -     StateChange  2m42s  ttclassic  Pod sample-1 RepState IDLE
      -     StateChange  2m31s  ttclassic  Pod sample-1 RepAgent Running
      -     StateChange  2m31s  ttclassic  Pod sample-1 RepState STANDBY
      -     StateChange  2m25s  ttclassic  TimesTenClassic was Initializing, now 
    Normal
    

Your active standby pair of TimesTen databases are successfully deployed (as indicated by Normal.) There are two TimesTen databases, configured as an active standby pair. One database is active. (In this example, sample-0 is the active database, as indicated by Rep State ACTIVE). The other database is standby. (In this example, sample-1 is the standby database as indicated by Rep State STANDBY). The active database can be modified and queried. Changes made on the active database are replicated to the standby database. If the active database fails, the Operator automatically promotes the standby database to be the active. The formerly active database will be repaired or replaced, and will then become the standby.

Verify the TimesTen container runs as non-root

You can run the kubectl exec command to invoke shells in your Pods and control TimesTen, which is running in those Pods. Run the Linux id command to verify the UID is 333.

  1. Establish a shell in the Pod and run the Linux id command.

    % kubectl exec -it sample-0 -c tt -- /usr/bin/bash
    % id
    uid=333(oracle) gid=333(oracle) groups=333(oracle)
    
  2. Verify you can connect to the sample database and run a simple query.

    % ttisql sample 
    Copyright (c) 1996, 2020, Oracle and/or its affiliates. All rights reserved. 
    Type ? or "help" for help, type "exit" to quit ttIsql. 
    
    
    
    connect "DSN=sample"; 
    Connection successful: 
    DSN=sample;UID=oracle;DataStore=/tt/home/oracle/datastore/sample;
    DatabaseCharacterSet=AL32UTF8;ConnectionCharacterSet=US7ASCII;AutoCreate=0;
    PermSize=200;DDLReplicationLevel=3;ForceDisconnectEnabled=1; 
    (Default setting AutoCommit=1) 
    
    Command> SELECT * FROM dual; 
    < X > 
    1 row found.