Namespace Onboarding
Kubernetes namespaces are a way to organize clusters into virtual sub-clusters. A namespace is created for your team in all clusters when you are onboarded to Kubernetes. This page aims to give an overview of this namespace and common resources created within it.
Namespace onboarding is performed by applying Terraform code located in terraform-aks. Details on how to add a new namespace for your team can be found in the repository README file. You can inspect all resources created during the onboarding by looking into /terraform-aks/namespaces/environments.
Namespace common resources
The following common resources are created during Namespace Onboarding
Resource Quota
The total amount of memory and CPU that is allowed to use by all containers running in a namespace is restricted to a default amount. If you exceed this amount, Kubernetes will respond with an error event telling you that creation of pods are forbidden due to exceeded quota. Read more about namespace resource quotas in the official Kubernetes docs :book:
Increasing the default amount is done by self-service in the repo argocd. Locate your team's configurations/<environment>/teams/team_<team-name>.json-file (<environment> is test or prod) and set the resource_quota field for your namespace:
"resource_quota": {
"requests": {
"cpu": "5",
"memory": "10Gi"
},
"limits": {
"cpu": "10",
"memory": "20Gi"
}
}
Set all four values when overriding the defaults. Then create a Pull Request against the main-branch — this requires approval from your team as well as the Platform team. See the repository documentation for more details.
OpenTelemetry Instrumentation
Applications on GAP are automatically instrumented with an OpenTelemetry agent that exports traces to Grafana Tempo (see Tracing). Instrumentation versions were previously managed centrally by the Platform team, which made it hard to support every team's mix of runtimes and framework versions. This is now self-service.
A shared catalog of supported runtime versions (Java, Node.js, Python, .NET) is published per environment from configurations/templates/versions.libsonnet in the argocd repo. You can use the catalog in two ways:
-
Pin a single workload to an explicit catalog version with an annotation on the pod template:
instrumentation.opentelemetry.io/inject-java: system-instrumentations/java-2.31.1 -
Change the default for your whole namespace by adding an
instrumentationfield to your team'sconfigurations/<environment>/teams/team_<team-name>.json-file:"instrumentation": {"java": "2.31.1"}Workloads using the generic Gappynator-managed annotation
instrumentation.opentelemetry.io/inject-{runtime}: "true"will then pick up this namespace default instead of the platform default.
For compatibility, every namespace's default is currently pinned to the legacy instrumentation versions until a team opts in to a newer one. Changing the namespace default does not restart already-running workloads; restart them to pick up the change. Adding or changing an explicit annotation on a workload's pod template does trigger a rollout when Argo CD syncs it.
Changes to teams/team_<team-name>.json are submitted as a Pull Request against main in the argocd repo and require approval from your team as well as the Platform team.
See the argocd repository documentation for the full list of supported versions and configuration details.
RBAC
Role Based Access Control is applied as a part of the Namespace Onboarding. The following RBAC is applied:
- ClusterRoleBinding giving your team read access to resources inside your namespace as well as resources in other parts of the cluster. This role is bound to the native Kubernetes 'view' role on a cluster level
- RoleBinding giving your team access to edit resources inside your namespace. This role is bound to the native Kubernetes 'edit' role on a namespace level. To enable this, Just In Time Access is required as described in Accessing from laptop
Docker credentials
Each namespace comes with a Kubernetes Docker config Secret named acr-credentials. This secret can be used to pull container images from Gjensidige's Azure Container Registry by specifying the imagePullSecrets field:
apiVersion: apps/v1
kind: Deployment
metadata:
name: "test-app"
spec:
selector:
matchLabels:
app: "test-app"
template:
metadata:
name: "test-app"
spec:
containers:
- name: "test-app"
image: "gjensidige.azurecr.io/test-app:12345"
imagePullSecrets:
- name: "acr-credentials"
Learn how to build and push a container image to Azure Container Registry with GitHub Actions in this guide
Setup for Azure AD Pod Identity
Azure AD Pod Identity enables Kubernetes applications to access cloud resources securely with Azure Active Directory using User-assigned managed identity and Service Principal.
Basic configuration for Azure AD Pod Identity is created during Namespace Onboarding:
- AzureIdentity describes the Azure User Managed Identity created for your team. This identity has access to your team's resources in Azure. The User Managed Identity is created with Terraform in this repo
- AzureIdentityBinding describes the identity binding relationship between an
AzureIdentityand a pod with a specific selector as part of its label
ConfigMaps containing CA Bundle and JVM TrustStore
Namespaces are also mounted with ConfigMaps for Gjensidige's common CA Bundle and JVM Truststore. Both are copied from the Heimdall On-Prem application framework.
apiVersion: v1
kind: ConfigMap
metadata:
name: "cacerts"
binaryData:
cacerts: "..."
apiVersion: v1
kind: ConfigMap
metadata:
name: "ca-certificates"
data:
ca-certificates.crt: "..."
Gappynator mounts these ConfigMaps into your pods automatically. See Platform-provided mounts.
JWT Properties and Signing Certificate
Sometimes you need properties, and a signing certificate to enable JWT in your application. For convenience, we have provided a ConfigMap suitable for most use-cases:
apiVersion: v1
kind: ConfigMap
metadata:
name: "jwt-config"
data:
JWTConfig.properties: "..."
gjensidige_signer.cer: "..."
Gappynator mounts this ConfigMap at /mnt/jwt-config automatically. See Platform-provided mounts for the Spring Boot property you need to set.