1.3 Configuration

After the initial installation, we can start configuring the cluster. Because of the extended use of operators, nearly everything in OpenShift 4 is configured via custom resources. In some cases configmaps or templates are used, but this is clearly the minority.

Most of the configuration is done post-installation and can be used to better adapt the cluster to its environment or change its default behaviour. We are going to configure our own kubelet arguments and change the default project template in order to automatically create some NetworkPolicy resources.

Task 1.3.1: Configure kubelet arguments

OpenShift lets us change the kubelet configuration via the custom resource KubeletConfig. But why change it at all?

The default kubelet configuration doesn’t reserve any memory or cpu for the kubelet or the operating system itself. It also defines an eviction threshold which, in some cases, is too low for the kubelet to react fast enough.

Configure a KubeletConfig resource each for master and worker nodes defining the following parameters:

  • Set a hard eviction threshold to 500Mi available memory
  • Set the reserved kubelet resources to 250m cpu and 1Gi memory
  • Set the reserved system resources to 250m cpu and 1Gi memory

You can find relevant information on the OpenShift documentation pages here and here .

Hints

Change the masters’ configuration to this:

apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
metadata:
  name: master
spec:
  kubeletConfig:
    evictionHard:
      memory.available: 500Mi
    kubeReserved:
      cpu: 250m
      memory: 1Gi
    systemReserved:
      cpu: 250m
      memory: 1Gi
  machineConfigPoolSelector:
    matchLabels:
      'pools.operator.machineconfiguration.openshift.io/master': ''

And the worker nodes’ configuration to this:

apiVersion: machineconfiguration.openshift.io/v1
kind: KubeletConfig
metadata:
  name: worker
spec:
  kubeletConfig:
    evictionHard:
      memory.available: 500Mi
    kubeReserved:
      cpu: 250m
      memory: 1Gi
    systemReserved:
      cpu: 250m
      memory: 1Gi
  machineConfigPoolSelector:
    matchLabels:
      'pools.operator.machineconfiguration.openshift.io/worker': ''

There are multiple possible ways to apply these configuration resources to the cluster. We are going to use one of the quickest methods and apply via URL:

oc apply -f https://raw.githubusercontent.com/acend/openshift-operations-training/main/content/en/docs/01/resources/kubeletconfig_master.yaml
oc apply -f https://raw.githubusercontent.com/acend/openshift-operations-training/main/content/en/docs/01/resources/kubeletconfig_worker.yaml

To learn more about kubelet configuration, check the Kubernetes and OpenShift documentation .

Task 1.3.2: Generate the default project template

When creating a new project using oc new-project, OpenShift instantiates a template using the information provided. We can modify this template if we want to alter it or add more resources, such as NetworkPolicies or LimitRanges.

And this is exactly what you are going to do first of all: Generate the default template according to the documentation and change its name to project-request-extended.

Hints

Simply execute the command from the documentation with a slight change to the filename (according to the tip above):

oc adm create-bootstrap-project-template -o yaml > template_project-request-extended.yaml

Open the file using your favorite editor and change the name:

kind: Template
metadata:
  creationTimestamp: null
  name: project-request-extended
objects:
  [...]

Task 1.3.3: Network policies

Now, what you usually want to ensure first on a new cluster is that the different namespaces are isolated from each other in terms of network traffic. User A’s pods in project A should not be able to directly talk to user B’s pods in project B. Except of course for certain use cases, but thanks to the flexibility of network policies, we can easily define a sane default and change it on a namespace-basis if necessary.

Add the necessary network policies to the default project template. A sane default is already provided by Red Hat in its documentation .

Hints

Your file should now look like this:

apiVersion: template.openshift.io/v1
kind: Template
metadata:
  creationTimestamp: null
  name: project-request-extended
  namespace: openshift-config
objects:
- apiVersion: project.openshift.io/v1
  kind: Project
  metadata:
    annotations:
      openshift.io/description: ${PROJECT_DESCRIPTION}
      openshift.io/display-name: ${PROJECT_DISPLAYNAME}
      openshift.io/requester: ${PROJECT_REQUESTING_USER}
    creationTimestamp: null
    name: ${PROJECT_NAME}
  spec: {}
  status: {}
- apiVersion: rbac.authorization.k8s.io/v1
  kind: RoleBinding
  metadata:
    creationTimestamp: null
    name: admin
    namespace: ${PROJECT_NAME}
  roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: admin
  subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: ${PROJECT_ADMIN_USER}
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-from-openshift-ingress
    namespace: ${PROJECT_NAME}
  spec:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            policy-group.network.openshift.io/ingress: ""
    podSelector: {}
    policyTypes:
    - Ingress
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-from-openshift-monitoring
    namespace: ${PROJECT_NAME}
  spec:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            network.openshift.io/policy-group: monitoring
    podSelector: {}
    policyTypes:
    - Ingress
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-same-namespace
    namespace: ${PROJECT_NAME}
  spec:
    podSelector:
    ingress:
    - from:
      - podSelector: {}
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-from-kube-apiserver-operator
    namespace: ${PROJECT_NAME}
  spec:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            kubernetes.io/metadata.name: openshift-kube-apiserver-operator
        podSelector:
          matchLabels:
            app: kube-apiserver-operator
    policyTypes:
    - Ingress
parameters:
- name: PROJECT_NAME
- name: PROJECT_DISPLAYNAME
- name: PROJECT_DESCRIPTION
- name: PROJECT_ADMIN_USER
- name: PROJECT_REQUESTING_USER

Task 1.3.4: Limit range

Limit ranges are very important in keeping the resource usage on the cluster in check. In this training, we assume you already know about limit ranges. If not, the documentation provides a good foundation.

A good starting point could look as follows:

apiVersion: v1
kind: LimitRange
metadata:
  name: limitrange
spec:
  limits:
  - default:
      cpu: 500m
      memory: 512Mi
    defaultRequest:
      cpu: 10m
      memory: 32Mi
    type: Container

Add the LimitRange resource to your default project template.

Hints

Your project template should now look like this:

apiVersion: template.openshift.io/v1
kind: Template
metadata:
  name: project-request-extended
  namespace: openshift-config
objects:
- apiVersion: project.openshift.io/v1
  kind: Project
  metadata:
    annotations:
      openshift.io/description: ${PROJECT_DESCRIPTION}
      openshift.io/display-name: ${PROJECT_DISPLAYNAME}
      openshift.io/requester: ${PROJECT_REQUESTING_USER}
    name: ${PROJECT_NAME}
  spec: {}
  status: {}
- apiVersion: rbac.authorization.k8s.io/v1
  kind: RoleBinding
  metadata:
    name: admin
    namespace: ${PROJECT_NAME}
  roleRef:
    apiGroup: rbac.authorization.k8s.io
    kind: ClusterRole
    name: admin
  subjects:
  - apiGroup: rbac.authorization.k8s.io
    kind: User
    name: ${PROJECT_ADMIN_USER}
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-from-openshift-ingress
    namespace: ${PROJECT_NAME}
  spec:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            policy-group.network.openshift.io/ingress: ""
    podSelector: {}
    policyTypes:
    - Ingress
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-from-openshift-monitoring
    namespace: ${PROJECT_NAME}
  spec:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            network.openshift.io/policy-group: monitoring
    podSelector: {}
    policyTypes:
    - Ingress
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-same-namespace
    namespace: ${PROJECT_NAME}
  spec:
    podSelector:
    ingress:
    - from:
      - podSelector: {}
- apiVersion: networking.k8s.io/v1
  kind: NetworkPolicy
  metadata:
    name: allow-from-kube-apiserver-operator
    namespace: ${PROJECT_NAME}
  spec:
    ingress:
    - from:
      - namespaceSelector:
          matchLabels:
            kubernetes.io/metadata.name: openshift-kube-apiserver-operator
        podSelector:
          matchLabels:
            app: kube-apiserver-operator
    policyTypes:
    - Ingress
- apiVersion: v1
  kind: LimitRange
  metadata:
    name: limitrange
    namespace: ${PROJECT_NAME}
  spec:
    limits:
    - default:
        cpu: 500m
        memory: 512Mi
      defaultRequest:
        cpu: 10m
        memory: 32Mi
      type: Container
parameters:
- name: PROJECT_NAME
- name: PROJECT_DISPLAYNAME
- name: PROJECT_DESCRIPTION
- name: PROJECT_ADMIN_USER
- name: PROJECT_REQUESTING_USER

Task 1.3.5: Configure the template

The only thing missing now is to configure the cluster to use the new template.

Create the template and configure all necessary resources so new projects use our custom template.

When you think everything is set up, create a new project and check that the NetworkPolicy and LimitRange resources were created automatically.

Hints

Create the template on the cluster by either using your own template:

oc apply -f template_project-request-extended.yaml

Or use our provided solution:

oc apply -f https://raw.githubusercontent.com/acend/openshift-operations-training/main/content/en/docs/01/resources/template_project-request-extended.yaml

And finally, we need to configure the Project custom resource:

oc patch project.config.openshift.io cluster --type=merge --patch '{"spec": {"projectRequestTemplate": {"name": "project-request-extended"}}}'

Task 1.3.6: Console URL

You probably already noticed the quite unwieldy console URL https://console-openshift-console.apps.+username+-ops-training.openshift.ch . It’s among a number of other route hostnames that are created by OpenShift this way by default.

Because the console URL is the one we probably will use the most, we are going to simplify it. Find the appropriate instructions in OpenShift’s documentation and adapt the route name.

Hints

The proper way is to edit the ingress config resource:

oc edit ingress.config.openshift.io cluster

Append the componentRoutes part so your resource looks similar to the example below:

apiVersion: config.openshift.io/v1
kind: Ingress
metadata:
  name: cluster
spec:
  componentRoutes:
    - name: console
      namespace: openshift-console
      hostname: console.apps.+username+-ops-training.openshift.ch
  domain: apps.+username+-ops-training.openshift.ch
  [...]