Skip to content

Getting started

Introduction

Kubernetes/OKD/Openshift can be very overwhelming at first, with many new concepts and vocabulary to learn. We strongly advise you to watch the videos Containers 101 and Containers for dummies. To really grasp what the possibilities are, you need to play around and read up on the material, see below for a list of additional resources.

Kubernetes and OKD are very alike, but some small differences exist, e.g.:

  • Kubernetes uses Namespace, OKD uses Project
  • Kubernetes uses Ingress, OKD uses Route

Other keywords/core objects can be found here

All Kubernetes objects can be used in OKD without any issues.

Core things you need to do to get started with our container platform after access has been established:

  1. Log into paas2 console or paas3 console and look around. Everything can be done in the GUI.
  2. A standard namespace/project often has the following core components:

  3. Deployment: a manifest that describes which containers will run in your pod

  4. Service: an object that makes Pods available on the network so that clients can interact with it
  5. Route: allows you to expose your service at a public URL. It can be secured or unsecured, depending on the network security configuration of your application.

When you have become familiar with OKD, we advise to use ArgoCD, which provides a GitOps workflow and a declarative continuous delivery tool for Kubernetes/OKD/Openshift. You will have full control of your applications through this and be able to roll back deployments very easily when mistakes occur.


Using the command line

It is often faster to do tasks in the terminal and easier to comprehend how your application is working in OKD.

Getting the binary

Go to https://github.com/okd-project/okd/releases and expand "Assets" for the latest release. Linux users will typically want the file named openshift-client-linux-amd64-rhel9-*. It contains a single binary oc which works on all recent distros.

Logging in

First log in to the web console. Click on your username in top right corner and choose "Copy login command". Click "Display Token" to view a token which is valid for 24 hours.

A convenience function for your .bashrc to jump to this page:

oc_token() {
    local paas=${1-paas3}
    xdg-open "https://oauth-openshift.apps.${paas}.rlnc.eu/oauth/authorize?client_id=openshift-browser-client&redirect_uri=https%3A%2F%2Foauth-openshift.apps.${paas}.rlnc.eu%2Foauth%2Ftoken%2Fdisplay&response_type=code"
}

oc login

The Display Token web page will give you a command you can copy-paste into your shell.

Registry login

The same token can be used to log into OKD's registry.

podman and docker are interchangable. On Linux podman is recommended.

$ podman login registry.apps.paas3.rlnc.eu
Username: <anything, can be empty>
Password: sha256~8ys…YpY
Login Succeeded!

Work with container images

Container images can be retrieved from public registries like quay.io, docker.io and gcr.io or private registries like gitlab, if you develop your own applications. Custom images can also be stored in the internal OKD registry if needed.

There are many ways to achieve this, we advise generally in most use cases to use private registries like gitlab to host your own container images.

Examples

Deploy images in your private gitlab registry (using buildkit)

Add the following in your gitlab pipeline: (.gitlab-ci.yml).

stages:
  - build-image

build:
  stage: build-image
  image: containers.redpill-linpro.com/cloud/k8s/buildah-rootless:latest
  variables:
    STORAGE_DRIVER: overlay
    BUILDAH_FORMAT: docker
    BUILDAH_ISOLATION: chroot
    KUBERNETES_SERVICE_ACCOUNT_OVERWRITE: "buildah-sa"
  before_script:
    # Log in to the GitLab container registry
    - buildah login -u "$CI_REGISTRY_USER" --password $CI_REGISTRY_PASSWORD $CI_REGISTRY
  script:
    - buildah images
    - buildah build -f Dockerfile -t $IMAGE_TAG
    - buildah images
    - buildah push $IMAGE_TAG
  only:
    - main

Deploy a image to OKD's internal registry

variables:
  DEST_TAG: registry.apps.paas3.rlnc.eu/namespace/image:latest

stages:
  - deploy

Deploy:
  stage: deploy
  image:
    name: quay.io/containers/skopeo:latest
    entrypoint: [""]
  script:
    - printf 'Copying image to %s\n' ${DEST_TAG}
    - skopeo copy --dest-tls-verify=false --src-creds "${CI_REGISTRY_USER}:${CI_REGISTRY_PASSWORD}" --dest-creds "gitlab:${OCTOKEN}" docker://${IMAGE_TAG} docker://${DEST_TAG}

The ${OCTOKEN} is a CI/CD variable we have added in our gitlab project. This token is a non-expiry token generated by connecting a secret to the relevant service account.

Use a external registry in your deployment

An external image registry could be hosted at various locations. For Redpill Linpro's gitlab instance it is for example called containers.redpill-linpro.com.

To use this image, the deployment needs access via a imagePullSecret configuration. Ad-Hoc create one:

        kubectl create secret docker-registry $SECRETNAME \
          --docker-server=$REGISTRY \
          --docker-username=$TOKENU \
          --docker-password=$TOKENP \
          -n $NAMESPACE
If you get error: unable to decode "secret.yaml": json: cannot unmarshal string into Go value of type unstructured.detector, try this:
oc create secret docker-registry "$SECRETNAME" \
           --docker-server="$REGISTRY" \
           --docker-username="$TOKENU" \
           --docker-password="$TOKENP" \
           -n "$NAMESPACE" \
           --dry-run=client -o yaml > secretparsed.yaml
Or define it in your k8s repo(recommended but remember to encrypt with ksops):
    apiVersion: v1
    kind: Secret
    metadata:
      name: my-registry-secret
      namespace: <optional>
    data:
      .dockerconfigjson: <base64-encoded-docker-config-json>
    type: kubernetes.io/dockerconfigjson

Then in your deployment add a reference(example):

        apiVersion: apps/v1
        kind: Deployment
        metadata:
          name: my-app
        spec:
          template:
            spec:
              containers:
              - name: my-container
                image: externalregistry.com/development/incident-program
              imagePullSecrets:
              - name: <secret-name>

Point to a ImageStream in a Deployment

Ref. upstream documentation

If you are using a Deployment, you can run the following to trigger automatic redeployments when your "ImageStream" gets a new image:

oc set triggers deployment/<name of deployment> --from-image=<containerimage>:latest -c <container name>

and add the folowing under "annotations":

annotations:
  alpha.image.policy.openshift.io/resolve-names: "*"

Push locally built image to internal OKD registry

  1. Create an empty ImageStream in your namespace

    oc create imagestream containertest
    
  2. Login to the internal OKD registry. See above for method.

  3. Add a tag to your local image with correct remote path (ie., registry.apps.paas3.rlnc.eu/).

    podman tag docker.io/library/mongo-express registry.apps.paas3.rlnc.eu/dummy/containertest:2.0
    
  4. Push to internal OKD registry

    podman push registry.apps.paas3.rlnc.eu/dummy/containertest:2.0
    

Work with persistent volumes

We advise against using persistent volumes (PV), it is often better to use a separate database or S3 storage for persisting state. However, if you have a use case, here is an example of how to use it.

apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: claim1
namespace: <your namespace>
spec:
accessModes:
- ReadWriteOnce
storageClassName: rlcs-ssd
resources:
requests:
storage: 1Gi

Then you can point to this claim in your deployment:

spec:
template:
spec:
volumes:
- name: test-db-data
persistentVolumeClaim:
claimName: claim1

No special permissions are needed to use this functionality. There is currently no support for ReadWriteMany to these volumes(RWX) which means that only one node can mount the volume at a time. Keep this in mind when designing a deployment using PVs.

Work with ArgoCD

This is a very basic "getting started with ArgoCD", for more depth, see upstream documentation

For customers with a dedicated ArgoCD instance, you need to create the following resources in your ArgoCD GUI:

  1. Create your own ArgoCD project if desirable. If not, the "default" one will be used.

    SettingsProjects+NEW PROJECT

  2. Create an ArgoCD application. It is advised to start with a "Manual" sync policy and change it to "Automatic" when you comfortable with your app/setup.

    Applications+NEW APP

    Example:

    path: "/metadata/name"
    value: "customer-app"
    
    path: "/spec/project"
    value: "<relevant ArgoCD-project>"
    
    path: "/spec/source/repoURL"
    value: "https://gitrepoURL/backend.git"
    
  3. Add your remote git repository with a token of your remote gitRepo (read_repository and read_registry permissions on your token should suffice)

    SettingsRepositories+CONNECT REPOVIA HTTP/HTTPS

    Fill inn Project and Repository URL, leave Username empty, and enter Git token into Password. Click Connect.

Work with KSOPS/Mozilla SOPS

For customers with a dedicated ArgoCD instance, for an additional cost, we can offer the Kustomize SOPS plugin which can be used to decrypt resources encrypted with SOPS.

On the Cluster, Redpill Linpro will:

  • Deploy GitOps operator
  • Generate a private/public key with the age binary
  • Create a secret in the ArgoCD namespace of the customer that stores the public and private keys
  • Customize the Argo CD instance to use the Kustomize SOPS plugin
  • Push the Public key into the git repository/or send it securely to the customer

Developers/the customer will:

  • Create a Secret on their local console
  • Download the public key to encrypt the secret with SOPS CLI
  • Generate KSOPS YAML with the encrypted secret and push to their Git repository

Requirements for the developer/Customer

Download the following binaries to your client machine: (Decrypting locally is only possible if you have the private key stored on your client machine, which is not advised)

  1. sops
  2. kustomize

Configure SOPS

  1. SOPS is configured via .sops.yaml

    For this example and testing, KSOPS relies on the SOPS creation rules defined in .sops.yaml. To make encrypted secrets more readable, we suggest using the following encryption regex to only encrypt data and stringData values. This leaves non-sensitive fields, like the secret's name, unencrypted and human readable.

    cat <<EOF > .sops.yaml
    creation_rules:
      - encrypted_regex: "^(data|stringData)$"
        age: <your public key>
    EOF
    
  2. Create a Resource (local Kubernetes Secret)

    cat <<EOF > secret.yaml
    apiVersion: v1
    kind: Secret
    metadata:
      name: mysecret
    type: Opaque
    data:
      username: YWRtaW4=
      password: MWYyZDFlMmU2N2Rm
    EOF
    
  3. Encrypt the Resources with SOPS CLI (Specific SOPS configuration in .sops.yaml)

    All changes to the yaml file after encryption will give data integrity errors, so re-encrypt if you want to add stuff!

    sops -e secret.yaml > secret.enc.yaml
    
  4. Define KSOPS kustomize Generator(Create a local Kubernetes Secret)

    cat <<EOF > secret-generator.yaml
    apiVersion: viaduct.ai/v1
    kind: ksops
    metadata:
    # Specify a name
      name: secret-generator
      annotations:
        config.kubernetes.io/function: |
          exec:
            path: ksops
    files:
      - ./secret.enc.yaml
    EOF
    
  5. Create an kustomization.yaml (example)

    cat <<EOF > kustomization.yaml
    apiVersion: kustomize.config.k8s.io/v1beta1
    kind: Kustomization
    generatorOptions:
      disableNameSuffixHash: true
    namespace: yournamespace
    
    generators:
      - ./secret-generator.yaml
    EOF
    
  6. Run ArgoCD

Troubleshooting

Sanity Checks

  1. Validate ksops command is in your path

    # Should output a path to KSOPS executable
    command -v ksops
    
  2. If you prefer to not install ksops to your path, make sure the path to the executable in the generator manifest is relative to the manifests files

  3. Running kustomize build --enable-alpha-plugins --enable-exec . | oc diff -f - will not work locally since you need the private key to decrypt your encrypted values. A typical error output of this would be:

    failed to evaluate function: error decrypting file "secret.sops.yaml" from manifest.Files: trouble decrypting file: Error getting data key: 0 successful groups required, got 0unable to generate manifests: error decrypting file "secret.sops.yaml" from manifest.Files: trouble decrypting file: Error getting data key: 0 successful groups required, got 0Error: couldn't execute function: exit status 1
    
  4. If the following annotation is not configured with correct indentation

    metadata:
      annotations:
        config.kubernetes.io/function: |
          exec:
            path: ksops
    

    you will get the following error output:

    Failed to load target state: failed to generate manifest for source 1 of 1: rpc error: code = Unknown desc = Manifest generation error (cached): `kustomize build <path to cached source>/k8s --enable-alpha-plugins --enable-exec` failed exit status 1: Error: accumulating resources: accumulation err='accumulating resources from 'test': '<path to cached source>/' must resolve to a file': recursed accumulation of path '<path to cached source>/k8s/test': loading generator plugins: failed to load generator: unable to find plugin root - tried: ('<no value>'; homed in $KUSTOMIZE_PLUGIN_HOME), ('/.config/kustomize/plugin'; homed in $XDG_CONFIG_HOME), ('/.config/kustomize/plugin'; homed in default value of $XDG_CONFIG_HOME), ('/kustomize/plugin'; homed in home directory)