Getting Started with the Sync Agent
All that is necessary to run the Sync Agent is a running Kubernetes cluster (for testing you can use kind) and a kcp installation.
Prerequisites
- A running Kubernetes cluster to run the Sync Agent in.
- A running kcp installation as the source of truth.
- A kubeconfig with admin or comparable permissions in a specific kcp workspace.
APIExport Setup
Before installing the Sync Agent it is necessary to create an APIExport
on kcp. The APIExport
should
be empty, because it is updated later by the Sync Agent. The export's name is only important for
binding to it, the resources in it can use other API groups. An example file could look like this:
The APIExport
above might look like it is defining all resources for the test.example.com
API
group, but in reality it might contain resource schemas like v1.crontabs.initech.com
.
Create a file with a similar content and create it in a kcp workspace of your choice:
# use the kcp kubeconfig
$ export KUBECONFIG=/path/to/kcp.kubeconfig
# nativagate to the workspace where the APIExport should exist
$ kubectl ws :workspace:you:want:to:create:it
# create it
$ kubectl create --filename apiexport.yaml
apiexport/test.example.com created
Optional: Create Initial APIBinding
To save resources, kcp doesn't start API endpoints for APIExports
that are not in use (i.e. that don't
have an active APIBinding
). To avoid cryptic errors in the Sync Agent logs about resources not being found,
you can create an initial APIBinding
in the same (or another) workspace as your APIExport
.
It could look like this:
apiVersion: apis.kcp.io/v1alpha1
kind: APIBinding
metadata:
name: test.example.com
spec:
reference:
export:
name: test.example.com
While still being in your :workspace:you:want:to:create:it
workspace, you could create the APIBinding
like this:
Creating an Endpoint Slice
Beginning with kcp 0.28, APIExports
do not contain the list of URLs the Sync Agent would need to
connect to. Instead, kcp will create an APIExportEndpointSlice
of the same name in the same
workspace as the APIExport
it belongs to. Just as before, without any existing APIBindings
, this
endpoint slice will not contain any URLs, so the step in the section above still applies in kcp 0.28+.
In older kcp versions, no endpoint slice is automatically created by kcp, but admins are free to create their own.
The Sync Agent can work with either APIExports
or APIExportEndpointSlices
. Depending on your
situation and needs, start it with --apiexport-ref
or --apiexportendpointslice-ref
. When a
reference to an endpoint slice is configured, the agent will automatically determine the APIExport
the slice belongs to (and it will of course continue to manage the APIResourceSchemas
in that
APIExport
).
Note
The endpoint slices can live in workspaces other than the one where the APIExport
exists. Make
sure that the kcp-kubeconfig provided to the Sync Agent always points to the workspace that has
the configured element (i.e. if using --apiexportendpointslice-ref
, the kubeconfig must point
to the workspace where the endpoint slice exists, even if the APIExport is somewhere else).
Sync Agent Installation
The Sync Agent can be installed into any namespace, but in our example we are going with kcp-system
.
It doesn't necessarily have to live in the same Kubernetes cluster where it is synchronizing data
to, but that is the common setup. Ultimately the Sync Agent synchronizes data between two kube
endpoints.
Now that the APIExport
(and optionally the APIExportEndpointSlice
) are created, switch to the
Kubernetes cluster from which you wish to publish resources. You will
need to ensure that a kubeconfig with access to the kcp workspace that the referenced object (export
or endpoint slice) has been created in is stored as a Secret
on this cluster. Make sure that the
kubeconfig points to the right workspace (not necessarily the root
workspace).
This can be done via a command like this:
$ kubectl create secret generic kcp-kubeconfig \
--namespace kcp-system \
--from-file "kubeconfig=admin.kubeconfig"
Helm Chart Setup
The Sync Agent is shipped as a Helm chart and to install it, the next step is preparing a values.yaml
file for the Sync Agent Helm chart. We need to pass the target APIExport
or the target
APIExportEndpointSlice
, a name for the Sync Agent itself and a reference to the kubeconfig secret
we just created.
# Either of the following two are required, and both fields are mutually exclusive:
# the name of the APIExport in kcp that this Sync Agent is supposed to serve.
apiExportName: test.example.com
# -- or --
# the name of the APIExportEndpointSlice in kcp that this Sync Agent is supposed to serve.
# apiExportEndpointSliceName: test.example.com
# Required: This Agent's public name, used to signal ownership over locally synced objects.
# This value must be a valid Kubernetes label value, see
# https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#syntax-and-character-set
# for more information.
# Changing this value after the fact will make the agent ignore previously created objects,
# so beware and relabel if necessary.
agentName: unique-test
# Required: Name of the Kubernetes Secret that contains a "kubeconfig" key,
# with the kubeconfig provided by kcp to access it.
kcpKubeconfig: kcp-kubeconfig
Once this values.yaml
file is prepared, install a recent development build of the Sync Agent:
helm repo add kcp https://kcp-dev.github.io/helm-charts
helm repo update
helm install kcp-api-syncagent kcp/api-syncagent \
--values values.yaml \
--namespace kcp-system
Two kcp-api-syncagent
Pods should start in the kcp-system
namespace. If they crash you will need
to identify the reason from container logs. A possible issue is that the provided kubeconfig does not
have permissions against the target kcp workspace (note that if you have an APIExportEndpointSlice
in a different workspace than the APIExport
, you will need to grant the Sync Agent permissions in
both workspaces).
Service Cluster RBAC
The Sync Agent usually requires additional RBAC on the service cluster to function properly. The Helm chart will automatically allow it to read CRDs, namespaces and Secrets, but depending on how you configure your PublishedResources, additional permissions need to be created.
For example, if the Sync Agent is meant to create Certificate
objects (defined by cert-manager),
you would need to grant it permissions on those:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: 'api-syncagent:unique-test'
rules:
- apiGroups:
- cert-manager.io
resources:
- certificates
verbs:
- get
- list
- watch
- create
- update
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: 'api-syncagent:unique-test'
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: 'api-syncagent:unique-test'
subjects:
- kind: ServiceAccount
name: 'kcp-api-syncagent'
namespace: kcp-system
NB: Even though the PublishedResources might only create/update Certificates in a single namespace,
due to the inner workings of the Agent they will still be watched (cached) cluster-wide. So you can
tighten permissions on create
/update
operations to certain namespaces, but watch
permissions
need to be granted cluster-wide.
kcp RBAC
The Helm chart is installed on the service cluster and so cannot provision the necessary RBAC for
the Sync Agent within kcp. Usually whoever creates the APIExport
is also responsible for creating
the RBAC rules that grant the Agent access.
The Sync Agent needs to
- access the workspace of its
APIExport
orAPIExportEndpointSlice
, - get the
LogicalCluster
(if export and endpoint slice are in different workspaces, then the agent will need permission to fetch the logicalcluster in both of them), - manage its
APIExport
, - watch the
APIExportEndpointSlice
if configured, - manage
APIResourceSchemas
, - create
events
forAPIExports
and - access the virtual workspace for its
APIExport
.
This can be achieved by applying RBAC like this in the workspace where the APIExport
resides:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-syncagent-mango
rules:
# get the LogicalCluster
- apiGroups:
- core.kcp.io
resources:
- logicalclusters
resourceNames:
- cluster
verbs:
- get
# watch the APIExportEndpointSlice (optional, could also be in a different workspace)
- apiGroups:
- apis.kcp.io
resources:
- apiexportendpointslices
resourceNames:
- test.example.com
verbs:
- get
- list
- watch
# manage its APIExport
- apiGroups:
- apis.kcp.io
resources:
- apiexports
resourceNames:
- test.example.com
verbs:
- get
- list
- watch
- patch
- update
# issue events for APIExports
- apiGroups:
- ""
resources:
- events
verbs:
- get
- create
- patch
- update
# manage APIResourceSchemas
- apiGroups:
- apis.kcp.io
resources:
- apiresourceschemas
verbs:
- get
- list
- watch
- create
# access the virtual workspace
- apiGroups:
- apis.kcp.io
resources:
- apiexports/content
resourceNames:
- test.example.com
verbs:
- '*'
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: api-syncagent-mango:system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: api-syncagent-mango
subjects:
- kind: User
name: api-syncagent-mango
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: api-syncagent-mango:access
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kcp:workspace:access
subjects:
- kind: User
name: api-syncagent-mango
If you indeed have different workspaces for the export and endpoint slice, apply the RBAC above as
mentioned in the workspace with the APIExport
, and additionally apply the RBAC below in the
workspace where the APIExportEndpointSlice
exists:
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: api-syncagent-mango
rules:
# get the LogicalCluster
- apiGroups:
- core.kcp.io
resources:
- logicalclusters
resourceNames:
- cluster
verbs:
- get
# watch the APIExportEndpointSlice
- apiGroups:
- apis.kcp.io
resources:
- apiexportendpointslices
resourceNames:
- test.example.com
verbs:
- get
- list
- watch
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: api-syncagent-mango:system
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: api-syncagent-mango
subjects:
- kind: User
name: api-syncagent-mango
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: api-syncagent-mango:access
roleRef:
apiGroup: rbac.authorization.k8s.io
kind: ClusterRole
name: system:kcp:workspace:access
subjects:
- kind: User
name: api-syncagent-mango
Publish Resources
Once the Sync Agent Pods are up and running, you should be able to follow the Publishing Resources guide.
Consume Service
Once resources have been published through the Sync Agent, they can be consumed on the kcp side (i.e. objects on kcp will be synced back and forth with the service cluster). Follow the guide to consuming services.