Warning Make sure you are using the correct version of these instructions by using the link in the release notes for the version you're trying to install. If you're not sure, check our latest release.
The following lines will guide you through the process of deploying a released version of Korifi.
- Tools:
- Resources:
- Kubernetes cluster of one of the upstream releases;
- Container Registry on which you have write permissions.
This document was tested on:
- EKS, using AWS' Elastic Container Registry (ECR) (see Install Korifi on EKS);
- GKE, using GCP's Artifact Registry;
- kind: see Install Korifi on kind.
The following environment variables will be needed throughout this guide:
ROOT_NAMESPACE
: the namespace at the root of the Korifi org and space hierarchy. The default value iscf
.KORIFI_NAMESPACE
: the namespace in which Korifi will be installed.ADMIN_USERNAME
: the name of the Kubernetes user who will have CF admin privileges on the Korifi installation. For security reasons, you should choose or create a user that is different from your cluster admin user. To provision new users, follow the user management instructions specific for your cluster's authentication configuration or create a new (short-lived) client certificate for user authentication.BASE_DOMAIN
: the base domain used by both the Korifi API and, by default, all apps running on Korifi.GATEWAY_CLASS_NAME
: the name of the Gateway API gatewayclass (see contour section).
Here are the example values we'll use in this guide:
export ROOT_NAMESPACE="cf"
export KORIFI_NAMESPACE="korifi"
export ADMIN_USERNAME="cf-admin"
export BASE_DOMAIN="korifi.example.org"
export GATEWAY_CLASS_NAME="contour"
DockerHub allows only one private repository per free account. In case the DockerHub account you configure Korifi with has the private
default repository privacy enabled, then Korifi would only be able to create a single repository and would get UNAUTHORIZED: authentication required
error when trying to push to a subsequent repository. This could either cause build errors during cf push
, or the Kpack cluster builder may never become ready. Therefore you should either set the default repository privacy to public
, or upgrade your DockerHub subscription plan. As of today, the Pro
subscription plan provides unlimited private repositories.
cert-Manager allows us to automatically create internal certificates within the cluster. Follow the instructions to install the latest version.
Kpack is used to build runnable applications from source code using Cloud Native Buildpacks. Follow the instructions to install the latest version.
The Helm chart will create an example Kpack ClusterBuilder
(with the associated ClusterStore
and ClusterStack
) by default. To use your own ClusterBuilder
, specify the kpackImageBuilder.clusterBuilderName
value. See the Kpack documentation for details on how to set up your own ClusterBuilder
.
Contour is our ingress controller. Contour implements the Gateway API. There are two ways to deploy Contour with Gateway API support: static provisioning and dynamic provisioning.
Follow the static provisioning instructions from the Gateway API support guide to install the latest version. Note that as part of the Contour installation you have to create a gatewayclass with name $GATEWAY_CLASS_NAME
:
kubectl apply -f - <<EOF
kind: GatewayClass
apiVersion: gateway.networking.k8s.io/v1beta1
metadata:
name: $GATEWAY_CLASS_NAME
spec:
controllerName: projectcontour.io/gateway-controller
EOF
This gatewayclass name is a parameter of the helm chart installing korifi. The helm chart is going to define a gateway that will be used for all korifi ingress traffic.
Follow the dynamic provisioning instructions from the Gateway API support guide to install the latest version.
- Note that as part of the Contour installation you have to create a gatewayclass with name
$GATEWAY_CLASS_NAME
:kubectl apply -f - <<EOF kind: GatewayClass apiVersion: gateway.networking.k8s.io/v1beta1 metadata: name: $GATEWAY_CLASS_NAME spec: controllerName: projectcontour.io/gateway-controller EOF
- You DO NOT need to create a gateway as per the instructions. The Korifi helm chart defines a gateway that will be used for all korifi ingress traffic. The gateway will be created in the
korifi-gateway
namespace.
We use the Kubernetes Metrics Server to implement process stats.
Most Kubernetes distributions will come with metrics-server
already installed. If yours does not, you should follow the instructions to install it.
We use the Service Binding Specification for Kubernetes and its controller reference implementation to implement Cloud Foundry service bindings (see this issue). Follow the instructions to install the latest version.
At minimum, you need to install servicemanager.io runtimes: https://github.com/servicebinding/runtime/releases/download/latest/servicebinding-runtime-v.yaml
Create the root and korifi namespaces:
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: $ROOT_NAMESPACE
labels:
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/enforce: restricted
EOF
cat <<EOF | kubectl apply -f -
apiVersion: v1
kind: Namespace
metadata:
name: $KORIFI_NAMESPACE
labels:
pod-security.kubernetes.io/audit: restricted
pod-security.kubernetes.io/enforce: restricted
EOF
Warning This is not required when using ECR on an EKS deployment.
Use the following command to create a Secret
that Korifi and Kpack will use to connect to your container registry:
kubectl --namespace "$ROOT_NAMESPACE" create secret docker-registry image-registry-credentials \
--docker-username="<your-container-registry-username>" \
--docker-password="<your-container-registry-password>" \
--docker-server="<your-container-registry-hostname-and-port>"
Make sure the value of --docker-server
is a valid URI authority.
- If using DockerHub:
--docker-server
should be omitted;--docker-username
should be your DockerHub user;--docker-password
can be either your DockerHub password or a generated personal access token.
- If using Google Artifact Registry:
--docker-server
should be<region>-docker.pkg.dev
;--docker-username
should be_json_key
;--docker-password
should be the JSON-formatted access token for a service account that has permission to manage images in Google Artifact Registry.
Self-signed TLS certificates are generated automatically by the installation if generateIngressCertificates
has been set to true
.
If you want to generate certificates yourself, you should not set the generateIngressCertificates
value, and instead provide your certificates to Korifi by creating two TLS secrets in $KORIFI_NAMESPACE
:
korifi-api-ingress-cert
;korifi-workloads-ingress-cert
.
Korifi can be configured to use a custom Certificate Authority when contacting the container registry. To do so, first create a Secret
containing the CA certificate:
kubectl --namespace "$KORIFI_NAMESPACE" create secret generic <registry-ca-secret-name> \
--from-file=ca.crt=</path/to/ca-certificate>
You can then specify the <registry-ca-secret-name>
using the containerRegistryCACertSecret
.
Warning Kpack does not support self-signed/internal CA configuration out of the box (see pivotal/kpack#207). In order to make Kpack trust your CA certificate, you will have to inject it in both the Kpack controller and the Kpack build pods.
- The
kpack-controller
Deployment
can be modified to mount aSecret
similar to the one created above: see the Korifi APIDeployment
for an example of how to do this.- For the build pods you can use the cert-injection-webhook, configured on the
kpack.io/build
label.
Korifi is distributed as a Helm chart. See Customizing the Chart Before Installing for details on how to specify values when installing a Helm chart.
For example:
helm install korifi https://github.com/cloudfoundry/korifi/releases/download/v<VERSION>/korifi-<VERSION>.tgz \
--namespace="$KORIFI_NAMESPACE" \
--set=generateIngressCertificates=true \
--set=rootNamespace="$ROOT_NAMESPACE" \
--set=adminUserName="$ADMIN_USERNAME" \
--set=api.apiServer.url="api.$BASE_DOMAIN" \
--set=defaultAppDomainName="apps.$BASE_DOMAIN" \
--set=containerRepositoryPrefix=europe-docker.pkg.dev/my-project/korifi/ \
--set=kpackImageBuilder.builderRepository=europe-docker.pkg.dev/my-project/korifi/kpack-builder \
--set=networking.gatewayClass=$GATEWAY_CLASS_NAME \
--wait
containerRepositoryPrefix
is used to determine the container repository for the package and droplet images produced by Korifi.
In particular, the app GUID and image type (packages
or droplets
) are appended to form the name of the repository.
For example:
Registry | containerRepositoryPrefix | Resultant Image Ref | Notes |
---|---|---|---|
Azure Container Registry | <projectID>.azurecr.io/foo/bar/korifi- |
<projectID>.azurecr.io/foo/bar/korifi-<appGUID>-packages |
Repositories are created dynamically during push by ACR |
DockerHub | index.docker.io/<dockerOrganisation>/ |
index.docker.io/<dockerOrganisation>/<appGUID>-packages |
Docker does not support nested repositories |
Amazon Elastic Container Registry | <projectID>.dkr.ecr.<region>.amazonaws.com/foo/bar/korifi- |
<projectID>.dkr.ecr.<region>.amazonaws.com/foo/bar/korifi-<appGUID>-packages |
Korifi will create the repository before pushing, as dynamic repository creation is not posssible on ECR |
Google Artifact Registry | <region>-docker.pkg.dev/<projectID>/foo/bar/korifi- |
<region>-docker.pkg.dev/<projectID>/foo/bar/korifi-<appGUID>-packages |
The foo repository must already exist in GAR |
Google Container Registry | gcr.io/<projectID>/foo/bar/korifi- |
gcr.io/<projectID>/foo/bar/korifi-<appGUID>-packages |
Repositories are created dynamically during push by GCR |
GitHub Container Registry | ghcr.io/<githubUserName>/foo/bar/korifi- |
ghcr.io/<githubUserName>/foo/bar/korifi-<appGUID>-package |
Repositories are created dynamically during push by GHCR |
The chart provides various other values that can be set. See README.helm.md
for details.
If you are using an authentication proxy with your cluster to enable SSO, you must set the following chart values:
api.authProxy.host
: IP address of your cluster's auth proxy;api.authProxy.caCert
: CA certificate of your cluster's auth proxy.
Korifi leverages the Gateway API for networking. This means that it should be easy to switch to any Gateway API compatible Ingress Controller implementation (e.g. Istio).
Create DNS entries for the Korifi API and for the apps running on Korifi. They should match the Helm values used to deploy Korifi:
- The Korifi API entry should match the
api.apiServer.url
value. In our example, that would beapi.korifi.example.org
. - The apps entry should be a wildcard matching the
defaultAppDomainName
value. In our example,*.apps.korifi.example.org
.
The DNS entries should point to the load balancer endpoint created by Contour when installed.
If you used static provisioning of a Contour gateway, discover your endpoint with:
kubectl get service envoy -n projectcontour -ojsonpath='{.status.loadBalancer.ingress[0]}'
If you used dynamic provisioning of a Contour gateway, discover your endpoint with:
kubectl get service envoy-korifi -n korifi-gateway -ojsonpath='{.status.loadBalancer.ingress[0]}'
It may take some time before the address is available. Retry this until you see a result.
The type of DNS records to create will differ based on the type of the endpoint: ip
endpoints (e.g. the ones created by GKE) will need an A
record, while hostname
endpoints (e.g. on EKS) a CNAME
record.
cf api https://api.$BASE_DOMAIN --skip-ssl-validation
cf login # choose the entry in the list associated to $ADMIN_USERNAME
cf create-org org1
cf create-space -o org1 space1
cf target -o org1
cd <directory of a test cf app>
cf push test-app