OnCallReady

Lesson 30.4 · OpenShift · 19 min read

Projects vs namespaces

In plain words

Imagine a shared office building. In a normal building, only the landlord can create new offices, and everyone can read the list of all offices on the wall. In this building, anyone can walk to the front desk and ask for an office; the desk builds it from a standard plan, hands you the keys as its manager, and gives your office its own range of badge numbers. And the directory at the entrance only shows the offices you have keys for.

A Project is a namespace created that way, through a ProjectRequest. oc new-project shop makes you admin, applies the cluster's project template (quotas, limits, network policies), and annotates it with a UID range like 1000650000/10000 and SELinux categories. oc get projects shows only yours; oc policy add-role-to-user view alice shares it.

Why projects

On the kubeadm lab you were cluster admin and made namespaces whenever you liked. On a shared OpenShift cluster hundreds of developers need their own namespaces - without anyone giving them cluster-wide rights. Projects are how that works, and they also decide which UID your pods will run as.

What you need to know already: namespaces (15.26); RBAC: Role, ClusterRole, RoleBinding, and the built-in view / edit / admin roles (17.30); ServiceAccounts (17.33); ResourceQuota and LimitRange (17.9); NetworkPolicy (16.29); Pod Security Admission labels (17.39); logging in with oc (30.2).

A Project is a namespace with a front door

Kubernetes has namespaces. OpenShift has namespaces too - and Projects, which are the same objects seen through a second API (project.openshift.io). Two things make them different in practice:

  1. Who can create them. Creating a namespace needs cluster-level rights. Creating a project goes through a ProjectRequest, which any user in the self-provisioner role may make (by default: every OAuth user). The API server then creates the namespace on your behalf and makes you its admin.
  2. What you can see. oc get projects lists only the projects you have a role in. oc get namespaces as a normal user is simply forbidden.

Making one

oc new-project NAME sends the ProjectRequest. --display-name is a human-friendly title shown in the console and in oc projects; --description is free text. Neither changes the name itself:

$ oc new-project shop --display-name="Shop (dev)" --description="the web shop, dev"
Now using project "shop" on server "https://api.ocp.lab:6443".

You can add applications to this project with the 'new-app' command. For example, try:

    oc new-app rails-postgresql-example

to build a new example application in Ruby. Or use kubectl to deploy a simple Kubernetes application:

    kubectl create deployment hello-node --image=registry.k8s.io/e2e-test-images/agnhost:2.43 -- /agnhost serve-hostname

oc new-project also switched your context to it (shop/api-ocp-lab:6443/developer), so every following command runs in shop unless you pass -n. (The two example commands it suggests are just hints; ignore them.) Common failures - the first says the name must be lowercase letters, digits and - (an "RFC 1123 label", the same rule as DNS names):

$ oc new-project Shop
The ProjectRequest "Shop" is invalid: metadata.name: Invalid value: "Shop": a lowercase RFC 1123 label must consist of lower case alphanumeric characters or '-', and must start and end with an alphanumeric character (e.g. 'my-name',  or '123-abc', regex used for validation is '[a-z0-9]([-a-z0-9]*[a-z0-9])?')
$ oc new-project openshift-shop
Error from server (Forbidden): cannot request a project starting with "openshift-"
$ oc new-project shop
Error from server (AlreadyExists): project.project.openshift.io "shop" already exists

The last one also happens when someone else owns a project called shop that you cannot see. Project names are cluster-wide; many companies enforce a prefix (teamname-app-env) in the project template for that reason.

On many enterprise clusters self-provisioning is switched off (an admin removes the self-provisioner ClusterRole from the group of all logged-in users with oc adm policy remove-cluster-role-from-group self-provisioner system:authenticated:oauth) and projects are requested through a ticket or a GitOps repo (26.1). Then you get:

Error from server (Forbidden): You may not request a new project via this API.

What a project comes with

-o yaml prints the whole object, as in 15.38:

$ oc get project shop -o yaml
apiVersion: project.openshift.io/v1
kind: Project
metadata:
  annotations:
    openshift.io/description: the web shop, dev
    openshift.io/display-name: Shop (dev)
    openshift.io/requester: developer
    openshift.io/sa.scc.mcs: s0:c27,c14
    openshift.io/sa.scc.supplemental-groups: 1000650000/10000
    openshift.io/sa.scc.uid-range: 1000650000/10000
  labels:
    kubernetes.io/metadata.name: shop
    pod-security.kubernetes.io/audit: restricted
    pod-security.kubernetes.io/audit-version: latest
    pod-security.kubernetes.io/warn: restricted
    pod-security.kubernetes.io/warn-version: latest
  name: shop
spec:
  finalizers:
  - kubernetes
status:
  phase: Active

Line by line:

Inside it:

$ oc get sa
NAME       SECRETS   AGE
builder    0         20s
default    0         20s
deployer   0         20s
$ oc get rolebindings
NAME                    ROLE                                AGE
admin                   ClusterRole/admin                   20s
system:deployers        ClusterRole/system:deployer         20s
system:image-builders   ClusterRole/system:image-builder    20s
system:image-pullers    ClusterRole/system:image-puller     20s

Moving around

oc projects lists yours (* marks the current one); oc project NAME switches to one (it rewrites your kubeconfig context); oc project alone says where you are; -q (quiet) prints just the name, handy in scripts:

# shop-test and payments = the projects of the next mission
oc projects
You have access to the following projects and can switch between them with ' project <projectname>':

  * shop - Shop (dev)
    shop-test

Using project "shop" on server "https://api.ocp.lab:6443".
oc project shop-test
Now using project "shop-test" on server "https://api.ocp.lab:6443".
oc project
Using project "shop-test" on server "https://api.ocp.lab:6443".
oc project -q
shop-test

Asking for a project you cannot see:

$ oc project payments
error: You are not a member of project "payments".
Your projects are:
* shop
* shop-test

Note: that is the same message whether payments exists or not. Projects you are not a member of are invisible.

Sharing a project

You are admin in your project, so you manage its RBAC yourself:

$ oc policy add-role-to-user view alice -n shop
clusterrole.rbac.authorization.k8s.io/view added: "alice"
$ oc get rolebinding view -n shop -o wide
NAME   ROLE                AGE   USERS   GROUPS   SERVICEACCOUNTS
view   ClusterRole/view    9s    alice

oc policy add-role-to-user ROLE USER creates (or extends) a RoleBinding in the current project (-n picks another one). -o wide adds the USERS / GROUPS / SERVICEACCOUNTS columns, so you see who the binding is for. The built-in roles are the Kubernetes ones - view, edit, admin - extended by OpenShift to cover Routes, Builds, ImageStreams and so on. Now alice sees shop in oc get projects and can read everything but Secrets. She still cannot change anything:

$ oc delete pod web-6d9f7c-abcde -n shop     # as alice
Error from server (Forbidden): pods "web-6d9f7c-abcde" is forbidden: User "alice" cannot delete resource "pods" in API group "" in the namespace "shop"

Undo with oc policy remove-role-from-user view alice -n shop.

Deleting

oc delete project shop-test
project.project.openshift.io "shop-test" deleted

The namespace goes to Terminating and everything in it is deleted - the same as kubectl delete ns. There is no undo; on shared clusters this is why the admin role is not given lightly.

Admin side: the template and quotas

Cluster admins shape every new project through a project request template (oc adm create-bootstrap-project-template -o yaml prints the default; point projects.config.openshift.io/cluster .spec.projectRequestTemplate at your own). A typical bank template adds a ResourceQuota, a LimitRange, default NetworkPolicies (deny from other projects) and labels for cost centres. oc adm new-project bypasses the template and the requester binding - it is the admin's raw "make a namespace with ranges".

What you can now do

Why it helps

On an enterprise OpenShift cluster, how projects are created and what they contain is the platform team's main tenancy control, and you will likely end up designing the project template: ResourceQuota, LimitRange, default-deny NetworkPolicies, labels for cost centres, naming prefixes. When a developer says "I can't create a project" or "it says AlreadyExists but I can't see it", you know it is disabled self-provisioning or a name owned by another team.

The UID range annotation is the key to understanding every SCC problem in the next lessons: it is where the random runAsUser comes from, and why you cannot hard-code a UID in a chart. And knowing that system:image-pullers is per project explains the ErrImagePull when one project tries to use another's ImageStream. Interviewers ask "what is the difference between a project and a namespace?" all the time.

Commands in this lesson

oc

FAQ

What is the difference between a Project and a namespace?

Every Project is a namespace, viewed through the project.openshift.io API. The differences are in how it is created and who sees it: a user makes a ProjectRequest, the API server creates the namespace from the project template on the user's behalf and binds them as admin, and adds SCC annotations for UID ranges and SELinux. oc get projects lists only projects you have a role in; listing namespaces needs cluster rights.

Why does my project name say AlreadyExists when I can't see it?

Project names are cluster-wide, and projects you are not a member of are invisible to you. So another team may already own shop. oc project payments gives the same "not a member" message whether the project exists or not. Many companies enforce a naming convention, such as a team prefix, through the project template or an admission policy for exactly this reason.

What do the openshift.io/sa.scc annotations mean?

They are the project's security ranges. sa.scc.uid-range: 1000650000/10000 is the block of 10,000 UIDs; restricted-v2 runs pods as the first one. sa.scc.supplemental-groups is the group range; its first value becomes the pod's fsGroup. sa.scc.mcs is the SELinux MCS level such as s0:c27,c14, which isolates the project's containers from others even at the file level.

Why can't I create a project on my company's cluster?

Many enterprise clusters remove the self-provisioner role from authenticated users, so oc new-project fails with You may not request a new project via this API. Projects are then created by the platform team through a ticket, a portal or a GitOps repository, usually with standard quotas, network policies and RoleBindings. Ask for the process rather than for broader rights.

How do I let another project pull my images?

Grant the other project's ServiceAccounts the system:image-puller role in your project: oc policy add-role-to-group system:image-puller system:serviceaccounts:<other> -n <yours>. By default only your own project's ServiceAccounts can pull your ImageStreams from the internal registry. Without the grant, the other project's pods fail with ErrImagePull and an authentication error.

In an interview Mid

What is an OpenShift project and how does it relate to a Kubernetes namespace?

A project is a namespace seen through a second API (project.openshift.io), with a front door:

Admins shape every new project with a project request template: quotas, LimitRanges, default NetworkPolicies, labels. Sharing: oc policy add-role-to-user view alice -n shop. Deleting one is kubectl delete ns - no undo.

Also asked: How would you design project onboarding for a multi-team OpenShift cluster? · How do you give a colleague read access to your project? · Why does every OpenShift project get its own UID range?

Practise this lesson in the terminal Free, in your browser - a real Ubuntu terminal to try it in, with missions that check your work.