|
| 1 | +--- |
| 2 | +title: Change Logs |
| 3 | +weight: 210 |
| 4 | +description: "Change logs help you audit all changes made to your resources" |
| 5 | +state: alpha |
| 6 | +alphaVersion: "1.17" |
| 7 | +--- |
| 8 | + |
| 9 | +The "change logs" feature is designed to help users of Crossplane Providers to |
| 10 | +understand what changes a provider is making to the resources it's managing. |
| 11 | +Whenever a provider creates, updates, or deletes a managed resource, an entry |
| 12 | +explaining the details of the change is recorded in the provider's change log. |
| 13 | + |
| 14 | +Change logs are important for awareness of the changes that a provider is |
| 15 | +making to its managed resources. Due to the nature of Crossplane's active |
| 16 | +reconciliation, it's possible for a provider to make changes to managed |
| 17 | +resources without any user interaction. Consider the scenario when someone |
| 18 | +updates a resource outside of Crossplane, for example via the AWS console or |
| 19 | +`gcloud` CLI. When Crossplane detects this configuration drift it will |
| 20 | +enforce its source of truth to eventually correct this unexpected change |
| 21 | +without any user interaction. |
| 22 | + |
| 23 | +With Crossplane acting continuously and autonomously to update critical |
| 24 | +infrastructure, it's vital for users to have insight into the operations being |
| 25 | +performed, so they can build and maintain a strong sense of confidence and trust |
| 26 | +in their control planes. Change logs provide details about all changes the |
| 27 | +provider makes, so users can remain aware of any changes, even when they aren't |
| 28 | +explicitly expecting any. |
| 29 | + |
| 30 | +{{<hint "tip">}} Change logs help you understand all the changes a provider is |
| 31 | +making to your resources, even when changes weren't explicitly requested, for |
| 32 | +example as a result of Crossplane's automatic correction of configuration drift. |
| 33 | +{{</hint>}} |
| 34 | + |
| 35 | +## Enabling Change Logs |
| 36 | + |
| 37 | +{{<hint "important" >}} Change logs are an alpha feature and must be explicitly |
| 38 | +enabled for each provider through the use of a `DeploymentRuntimeConfig`. |
| 39 | +{{</hint >}} |
| 40 | + |
| 41 | +To enable change logs for a provider, use a `DeploymentRuntimeConfig` to |
| 42 | +configure each provider pod that should start producing change logs. The |
| 43 | +`DeploymentRuntimeConfig` has a few important configuration details: |
| 44 | + |
| 45 | +1. A command line argument to the provider container that enables the change |
| 46 | + logs feature, for example `--enable-changelogs`. |
| 47 | +1. A [side car container](https://github.com/crossplane/changelogs-sidecar) that |
| 48 | + collects change events and produces change log entries to the provider's pod |
| 49 | + logs. |
| 50 | +1. A shared volume mounted to both the provider and sidecar containers that |
| 51 | + enables communication of change events between the two containers. |
| 52 | + |
| 53 | +### Prerequisites |
| 54 | + |
| 55 | +This guide assumes you have a control plane with [Crossplane installed]({{<ref "../software/install">}}). |
| 56 | + |
| 57 | +It also assumes you have the [`jq` tool installed](https://jqlang.org/download/), |
| 58 | +to perform lightweight querying and filtering of the content in the change logs. |
| 59 | + |
| 60 | +The only other prerequisite for enabling change logs is that the provider must |
| 61 | +have added support for the change logs feature. This is optional and not all |
| 62 | +providers in the Crossplane ecosystem have added this support yet. |
| 63 | + |
| 64 | +{{<hint "tip">}} Not all providers support the change logs feature. Check with |
| 65 | +your provider of choice to confirm it has added support for change logs. |
| 66 | +{{</hint>}} |
| 67 | + |
| 68 | +This guide walks through a full example of generating change logs with |
| 69 | +[`provider-kubernetes`](https://github.com/crossplane-contrib/provider-kubernetes). |
| 70 | + |
| 71 | +### Create a `DeploymentRuntimeConfig` |
| 72 | + |
| 73 | +Create a `DeploymentRuntimeConfig` that will enable change logs for |
| 74 | +the provider when it's installed by performing the necessary configuration |
| 75 | +steps: |
| 76 | + |
| 77 | +1. The {{<hover label="drc" line="15">}}--enable-changelogs{{</hover>}} flag is |
| 78 | + set on the provider. |
| 79 | +1. The {{<hover label="drc" line="19">}}sidecar container{{</hover>}} is added |
| 80 | + to the provider pod. |
| 81 | +1. A {{<hover label="drc" line="24">}}shared volume{{</hover>}} is declared and |
| 82 | + then mounted in the {{<hover label="drc" line="16">}}provider |
| 83 | + container{{</hover>}} and the {{<hover label="drc" line="21">}}sidecar |
| 84 | + container{{</hover>}}. |
| 85 | + |
| 86 | +```yaml {label="drc",copy-lines="all"} |
| 87 | +cat <<EOF | kubectl apply -f - |
| 88 | +apiVersion: pkg.crossplane.io/v1beta1 |
| 89 | +kind: DeploymentRuntimeConfig |
| 90 | +metadata: |
| 91 | + name: enable-changelogs |
| 92 | +spec: |
| 93 | + deploymentTemplate: |
| 94 | + spec: |
| 95 | + selector: {} |
| 96 | + template: |
| 97 | + spec: |
| 98 | + containers: |
| 99 | + - name: package-runtime |
| 100 | + args: |
| 101 | + - --enable-changelogs |
| 102 | + volumeMounts: |
| 103 | + - name: changelogs-vol |
| 104 | + mountPath: /var/run/changelogs |
| 105 | + - name: changelogs-sidecar |
| 106 | + image: xpkg.crossplane.io/crossplane/changelogs-sidecar:v0.0.1 |
| 107 | + volumeMounts: |
| 108 | + - name: changelogs-vol |
| 109 | + mountPath: /var/run/changelogs |
| 110 | + volumes: |
| 111 | + - name: changelogs-vol |
| 112 | + emptyDir: {} |
| 113 | + serviceAccountTemplate: |
| 114 | + metadata: |
| 115 | + name: provider-kubernetes |
| 116 | +EOF |
| 117 | +``` |
| 118 | + |
| 119 | +### Install the provider |
| 120 | + |
| 121 | +Install the {{<hover label="provider" line="7">}}provider{{</hover>}} and |
| 122 | +instruct it to use the {{<hover label="provider" line="8">}}DeploymentRuntimeConfig{{</hover>}} |
| 123 | +that was just created. |
| 124 | + |
| 125 | +```yaml {label="provider",copy-lines="all"} |
| 126 | +cat <<EOF | kubectl apply -f - |
| 127 | +apiVersion: pkg.crossplane.io/v1 |
| 128 | +kind: Provider |
| 129 | +metadata: |
| 130 | + name: provider-kubernetes |
| 131 | +spec: |
| 132 | + package: xpkg.crossplane.io/crossplane-contrib/provider-kubernetes:v0.18.0 |
| 133 | + runtimeConfigRef: |
| 134 | + apiVersion: pkg.crossplane.io/v1beta1 |
| 135 | + kind: DeploymentRuntimeConfig |
| 136 | + name: enable-changelogs |
| 137 | +EOF |
| 138 | +``` |
| 139 | + |
| 140 | +### Configure permissions |
| 141 | + |
| 142 | +In order for the provider to create Kubernetes resources within the control |
| 143 | +plane, it must be granted the appropriate permissions. This guide only creates a |
| 144 | +`ConfigMap`, so only permissions for that resource type are needed. |
| 145 | + |
| 146 | +{{<hint "important">}} This guide grants specific permissions to the provider |
| 147 | +for example purposes. This approach isn't intended to be representative of a |
| 148 | +production environment. More examples on configuring `provider-kubernetes` can |
| 149 | +be found in its [examples directory](https://github.com/crossplane-contrib/provider-kubernetes/tree/main/examples/provider). |
| 150 | +{{</hint>}} |
| 151 | + |
| 152 | +```yaml {label="rbac",copy-lines="all"} |
| 153 | +cat <<EOF | kubectl apply -f - |
| 154 | +apiVersion: rbac.authorization.k8s.io/v1 |
| 155 | +kind: ClusterRole |
| 156 | +metadata: |
| 157 | + name: configmap-edit |
| 158 | +rules: |
| 159 | + - apiGroups: |
| 160 | + - "" |
| 161 | + resources: |
| 162 | + - configmaps |
| 163 | + verbs: |
| 164 | + - "*" |
| 165 | +--- |
| 166 | +apiVersion: rbac.authorization.k8s.io/v1 |
| 167 | +kind: ClusterRoleBinding |
| 168 | +metadata: |
| 169 | + name: provider-kubernetes-configmap-edit |
| 170 | +subjects: |
| 171 | + - kind: ServiceAccount |
| 172 | + name: provider-kubernetes |
| 173 | + namespace: crossplane-system |
| 174 | +roleRef: |
| 175 | + kind: ClusterRole |
| 176 | + name: configmap-edit |
| 177 | + apiGroup: rbac.authorization.k8s.io |
| 178 | +--- |
| 179 | +apiVersion: kubernetes.crossplane.io/v1alpha1 |
| 180 | +kind: ProviderConfig |
| 181 | +metadata: |
| 182 | + name: default |
| 183 | +spec: |
| 184 | + credentials: |
| 185 | + source: InjectedIdentity |
| 186 | +EOF |
| 187 | +``` |
| 188 | + |
| 189 | +### Create a resource |
| 190 | + |
| 191 | +Now that the provider is installed and configured with change logs enabled, |
| 192 | +create a resource that will generates change logs entries reflecting the actions |
| 193 | +the control plane is taking. |
| 194 | + |
| 195 | +```yaml {label="provider",copy-lines="all"} |
| 196 | +cat <<EOF | kubectl apply -f - |
| 197 | +apiVersion: kubernetes.crossplane.io/v1alpha2 |
| 198 | +kind: Object |
| 199 | +metadata: |
| 200 | + name: configmap-for-changelogs |
| 201 | +spec: |
| 202 | + forProvider: |
| 203 | + manifest: |
| 204 | + apiVersion: v1 |
| 205 | + kind: ConfigMap |
| 206 | + metadata: |
| 207 | + namespace: default |
| 208 | + name: configmap-for-changelogs |
| 209 | + data: |
| 210 | + key-1: cool-value-1 |
| 211 | +EOF |
| 212 | +``` |
| 213 | + |
| 214 | +### Examine the change logs |
| 215 | + |
| 216 | +Check to see that the resource creation operation was recorded in the change |
| 217 | +logs. Examine the pod logs for `provider-kubernetes`, specifically at the |
| 218 | +`changelogs-sidecar` container: |
| 219 | +```shell {label="changelogs-output-full",copy-lines="1"} |
| 220 | +kubectl -n crossplane-system logs -l pkg.crossplane.io/provider=provider-kubernetes -c changelogs-sidecar | jq |
| 221 | +{ |
| 222 | + "timestamp": "2025-04-25T08:23:34Z", |
| 223 | + "provider": "provider-kubernetes:v0.18.0", |
| 224 | + "apiVersion": "kubernetes.crossplane.io/v1alpha2", |
| 225 | + "kind": "Object", |
| 226 | + "name": "configmap-for-changelogs", |
| 227 | + "externalName": "configmap-for-changelogs", |
| 228 | + "operation": "OPERATION_TYPE_CREATE", |
| 229 | + "snapshot": { |
| 230 | + ...(omitted for brevity)... |
| 231 | +``` |
| 232 | +
|
| 233 | +Each change log entry contains rich information about the state of the resource |
| 234 | +when the change operation occurred. Since each entry is a structured `JSON` |
| 235 | +object, they can be filtered and queried to find any subset of information you |
| 236 | +are interested in: |
| 237 | +```shell {label="changelogs-output-scoped",copy-lines="1-2"} |
| 238 | +kubectl -n crossplane-system logs -l pkg.crossplane.io/provider=provider-kubernetes -c changelogs-sidecar \ |
| 239 | + | jq '.timestamp + " " + .provider + " " + .kind + " " + .name + " " + .operation' |
| 240 | +"2025-04-25T08:23:34Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_CREATE" |
| 241 | +``` |
| 242 | +
|
| 243 | +### Full lifecycle operations |
| 244 | +
|
| 245 | +In addition to change log entries that record the creation of resources, update |
| 246 | +and delete operations will also generate corresponding change log entries. |
| 247 | +
|
| 248 | +Update the resource by patching its data field `key-1` with a new value |
| 249 | +`cooler-value-2`: |
| 250 | +```shell {label="object-patch",copy-lines="1-2"} |
| 251 | +kubectl patch object configmap-for-changelogs --type=json \ |
| 252 | + -p='[{"op": "replace", "path": "/spec/forProvider/manifest/data/key-1", "value": "cooler-value-2"}]' |
| 253 | +object.kubernetes.crossplane.io/configmap-for-changelogs patched |
| 254 | +``` |
| 255 | +
|
| 256 | +Then, delete the object entirely: |
| 257 | +```shell {label="object-delete",copy-lines="1"} |
| 258 | +kubectl delete object configmap-for-changelogs |
| 259 | +object.kubernetes.crossplane.io "configmap-for-changelogs" deleted |
| 260 | +``` |
| 261 | +
|
| 262 | +Check the change logs again to verify that both the update and delete operations |
| 263 | +were recorded, and the full lifecycle of the object has been captured in the |
| 264 | +change logs: |
| 265 | +```shell {label="changelogs-output-final",copy-lines="1-2"} |
| 266 | +kubectl -n crossplane-system logs -l pkg.crossplane.io/provider=provider-kubernetes -c changelogs-sidecar \ |
| 267 | + | jq '.timestamp + " " + .provider + " " + .kind + " " + .name + " " + .operation' |
| 268 | +"2025-04-25T08:23:34Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_CREATE" |
| 269 | +"2025-04-25T08:24:21Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_UPDATE" |
| 270 | +"2025-04-25T08:24:25Z provider-kubernetes:v0.18.0 Object configmap-for-changelogs OPERATION_TYPE_DELETE" |
| 271 | +``` |
0 commit comments