diff --git a/Dockerfile b/Dockerfile
index 9ae8f191f..e32c158fc 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -28,6 +28,8 @@ ARG MAKE_TARGET=build
 RUN for target in $MAKE_TARGET; do make $target; done
 
 FROM ${RELEASE_IMAGE} as release
-COPY --from=builder /usr/src/airshipctl/bin/airshipctl /usr/local/bin/airshipctl
+ARG BINARY=airshipctl
+ENV BINARY=${BINARY}
+COPY --from=builder /usr/src/airshipctl/bin/${BINARY} /usr/local/bin/${BINARY}
 USER 65534
-ENTRYPOINT [ "/usr/local/bin/airshipctl" ]
+ENTRYPOINT /usr/local/bin/${BINARY}
diff --git a/Makefile b/Makefile
index 4709b20d5..800666845 100644
--- a/Makefile
+++ b/Makefile
@@ -40,6 +40,21 @@ PROXY               ?= http://proxy.foo.com:8000
 NO_PROXY            ?= localhost,127.0.0.1,.svc.cluster.local
 USE_PROXY           ?= false
 
+# docker build flags
+DOCKER_CMD_FLAGS    := --network=host
+DOCKER_CMD_FLAGS    += --force-rm=$(DOCKER_FORCE_CLEAN)
+
+DOCKER_PROXY_FLAGS  := --build-arg http_proxy=$(PROXY)
+DOCKER_PROXY_FLAGS  += --build-arg https_proxy=$(PROXY)
+DOCKER_PROXY_FLAGS  += --build-arg HTTP_PROXY=$(PROXY)
+DOCKER_PROXY_FLAGS  += --build-arg HTTPS_PROXY=$(PROXY)
+DOCKER_PROXY_FLAGS  += --build-arg no_proxy=$(NO_PROXY)
+DOCKER_PROXY_FLAGS  += --build-arg NO_PROXY=$(NO_PROXY)
+
+ifeq ($(USE_PROXY), true)
+DOCKER_CMD_FLAGS += $(DOCKER_PROXY_FLAGS)
+endif
+
 # Godoc server options
 GD_PORT             ?= 8080
 
@@ -52,6 +67,15 @@ export KIND_URL     ?= https://kind.sigs.k8s.io/dl/v0.8.1/kind-$(UNAME)-amd64
 KUBECTL_VERSION     ?= v1.18.6
 export KUBECTL_URL  ?= https://storage.googleapis.com/kubernetes-release/release/${KUBECTL_VERSION}/bin/linux/amd64/kubectl
 
+# Plugins options
+PLUGINS_DIR         := krm-functions
+PLUGINS             := $(subst $(PLUGINS_DIR)/,,$(wildcard $(PLUGINS_DIR)/*))
+PLUGINS_IMAGE_TGT   := $(foreach tgt,$(PLUGINS),docker-image-$(tgt))
+PLUGINS_BASE_IMAGE  ?= alpine:3.12.0
+
+$(PLUGINS):
+	 @CGO_ENABLED=0 go build -o $(BINDIR)/$@ $(GO_FLAGS) ./$(PLUGINS_DIR)/$@/
+
 .PHONY: depend
 depend:
 	@go mod download
@@ -106,32 +130,30 @@ golint:
 
 .PHONY: images
 images: docker-image
+images: $(PLUGINS_IMAGE_TGT)
 
 .PHONY: docker-image
 docker-image:
-ifeq ($(USE_PROXY), true)
-	@docker build . --network=host \
-		--build-arg http_proxy=$(PROXY) \
-		--build-arg https_proxy=$(PROXY) \
-		--build-arg HTTP_PROXY=$(PROXY) \
-		--build-arg HTTPS_PROXY=$(PROXY) \
-		--build-arg no_proxy=$(NO_PROXY) \
-		--build-arg NO_PROXY=$(NO_PROXY) \
-	    --build-arg MAKE_TARGET=$(DOCKER_MAKE_TARGET) \
-	    --tag $(DOCKER_IMAGE) \
-	    --target $(DOCKER_TARGET_STAGE) \
-	    --force-rm=$(DOCKER_FORCE_CLEAN)
-else
-	@docker build . --network=host \
-	    --build-arg MAKE_TARGET=$(DOCKER_MAKE_TARGET) \
-	    --tag $(DOCKER_IMAGE) \
-	    --target $(DOCKER_TARGET_STAGE) \
-	    --force-rm=$(DOCKER_FORCE_CLEAN)
-endif
+	@docker build . $(DOCKER_CMD_FLAGS) \
+		--target $(DOCKER_TARGET_STAGE) \
+		--build-arg MAKE_TARGET=$(DOCKER_MAKE_TARGET) \
+		--tag $(DOCKER_IMAGE)
 ifeq ($(PUBLISH), true)
 	@docker push $(DOCKER_IMAGE)
 endif
 
+.PHONY: $(PLUGINS_IMAGE_TGT)
+$(PLUGINS_IMAGE_TGT):
+	$(eval plugin_name=$(subst docker-image-,,$@))
+	@docker build . $(DOCKER_CMD_FLAGS) \
+		--target $(DOCKER_TARGET_STAGE) \
+		--build-arg MAKE_TARGET=$(plugin_name) \
+		--build-arg BINARY=$(plugin_name) \
+		--build-arg RELEASE_IMAGE=$(PLUGINS_BASE_IMAGE) \
+		--tag $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(plugin_name):$(DOCKER_IMAGE_TAG)
+ifeq ($(PUBLISH), true)
+	@docker push $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(plugin_name):$(DOCKER_IMAGE_TAG)
+endif
 
 .PHONY: print-docker-image-tag
 print-docker-image-tag:
diff --git a/krm-functions/replacement-transformer/Dockerfile.sample b/krm-functions/replacement-transformer/Dockerfile.sample
new file mode 100644
index 000000000..5cf4c1604
--- /dev/null
+++ b/krm-functions/replacement-transformer/Dockerfile.sample
@@ -0,0 +1,11 @@
+FROM golang:1.13-stretch as builder
+ENV CGO_ENABLED=0
+WORKDIR /go/src/
+COPY image/go.mod .
+RUN go mod download
+COPY main.go .
+RUN go build -v -o /usr/local/bin/config-function ./
+
+FROM alpine:latest
+COPY --from=builder /usr/local/bin/config-function /usr/local/bin/config-function
+CMD ["/usr/local/bin/config-function"]
diff --git a/krm-functions/replacement-transformer/Makefile b/krm-functions/replacement-transformer/Makefile
new file mode 100644
index 000000000..83b045610
--- /dev/null
+++ b/krm-functions/replacement-transformer/Makefile
@@ -0,0 +1,78 @@
+.PHONY: generate license fix vet fmt test build tidy image
+
+SHELL := /bin/bash
+GOBIN := $(shell go env GOPATH)/bin
+
+# docker image options
+DOCKER_REGISTRY     ?= quay.io
+DOCKER_IMAGE_NAME   ?= replacement-transformer
+DOCKER_IMAGE_PREFIX ?= airshipit
+DOCKER_IMAGE_TAG    ?= dev
+DOCKER_IMAGE        ?= $(DOCKER_REGISTRY)/$(DOCKER_IMAGE_PREFIX)/$(DOCKER_IMAGE_NAME):$(DOCKER_IMAGE_TAG)
+PUBLISH             ?= false
+DOCKER_FORCE_CLEAN  ?= true
+
+# proxy options
+PROXY               ?= http://proxy.foo.com:8000
+NO_PROXY            ?= localhost,127.0.0.1,.svc.cluster.local
+USE_PROXY           ?= false
+
+.PHONY: build
+build:
+	(cd image && go build -v -o $(GOBIN)/config-function .)
+
+.PHONY: all
+all: generate license build fix vet fmt test lint tidy
+
+.PHONY: fix
+fix:
+	(cd image && go fix ./...)
+
+.PHONY: fmt
+fmt:
+	(cd image && go fmt ./...)
+
+.PHONY: generate
+generate:
+	(which $(GOBIN)/mdtogo || go get sigs.k8s.io/kustomize/cmd/mdtogo)
+	(cd image && GOBIN=$(GOBIN) go generate ./...)
+
+.PHONY: tidy
+tidy:
+	(cd image && go mod tidy)
+
+.PHONY: fix
+lint:
+	(which $(GOBIN)/golangci-lint || go get github.com/golangci/golangci-lint/cmd/golangci-lint@v1.19.1)
+	(cd image && $(GOBIN)/golangci-lint run ./...)
+
+.PHONY: test
+test:
+	(cd image && go test -cover ./...)
+
+.PHONY: vet
+vet:
+	(cd image && go vet ./...)
+
+.PHONY: image
+image:
+ifeq ($(USE_PROXY), true)
+	cd image && \
+	docker build . --network=host \
+		--build-arg http_proxy=$(PROXY) \
+		--build-arg https_proxy=$(PROXY) \
+		--build-arg HTTP_PROXY=$(PROXY) \
+		--build-arg HTTPS_PROXY=$(PROXY) \
+		--build-arg no_proxy=$(NO_PROXY) \
+		--build-arg NO_PROXY=$(NO_PROXY) \
+	  --tag $(DOCKER_IMAGE) \
+	  --force-rm=$(DOCKER_FORCE_CLEAN)
+else
+	cd image && \
+	docker build . --network=host \
+	    --tag $(DOCKER_IMAGE) \
+	    --force-rm=$(DOCKER_FORCE_CLEAN)
+endif
+ifeq ($(PUBLISH), true)
+	@docker push $(DOCKER_IMAGE)
+endif
diff --git a/krm-functions/replacement-transformer/README.md b/krm-functions/replacement-transformer/README.md
new file mode 100644
index 000000000..8179ba4ed
--- /dev/null
+++ b/krm-functions/replacement-transformer/README.md
@@ -0,0 +1,75 @@
+# Replacement Transformer
+
+This plugin is written in `go` and uses the `kyaml` and `airshipctl` libraries
+for parsing the input and writing the output.
+
+## Function implementation
+
+The function is implemented as an [image](image), and built using `make image`.
+Function reads configuration, a collection of input resources, and performs values
+replacement based on configuration.
+
+## Function invocation
+
+The function is invoked by authoring a [local Resource](local-resource)
+with `metadata.annotations.[config.kubernetes.io/function]` and running:
+
+    kustomize config run local-resource/
+
+This exits non-zero if there is an error.
+
+## Running the Example
+
+Run `Replacement Transformer` with:
+
+    kustomize fn run local-resource --dry-run
+
+Value of `spec.version` in resource `KubeadmControlPlane` (`v1.18.6`) will be replaced
+with value of `kubernetes` field defined in `VariableCatalogue` resource
+
+## Configuration file format
+
+`Replacement Transformer` configuration resource is represented as a standard
+k8s resource with Group, Version, Kind and Metadata header. Replacement
+configuration is defined under `replacements` field which contains a list of
+object with following structure.
+
+    source:
+      objref:
+        group: airshipit.org
+        version: v1alpha1
+        kind: Clusterctl
+        name: resource-name
+        namespace: capm3
+      value: "string value"
+      fieldref: {.data.host}
+    target:
+      objref:
+        group: airshipit.org
+        version: v1alpha1
+        kind: KubeConfig
+        name: resource-name
+        namespace: capi-system
+      fieldrefs:
+        - {.config.kind}
+
+* `source` defines where a substitution is from. It can from two different
+kinds of sources from a field of one resource or from a string.
+  * `objref` refers to a kubernetes object by Group, Version, Kind, Name and
+  Namespace. Each field can be omitted or be an empty string.
+  * `value` static string value to substitute into `target`.
+  * `fieldref` JSON path to particular object field. This field essentially
+  represents JSON query with syntax used in `kubectl` executed with
+  flag `--jsonpath`. JSON path syntax end elements is defined by
+  https://goessner.net/articles/JsonPath/
+* `target` defines a substitution target.
+  * `objref` specifies a set of resources. Any resource that matches
+  intersection of all conditions (Group, Version, Kind, Name and Namespace) is
+  included in this set.
+  * `fieldrefs` list of JSON path strings which identify target field to
+  substitute into. Field reference may have include pattern which is used as a
+  replacement variable. For example in following query `{.metadata.name}%NAME%`
+  string surrounded by `%` symbols (i.e. `NAME`) is considered as a pattern
+  inside a field value identified by JSON path `metadata.name`. Therefore if
+  value of `metadata.name` is `some-NAME-of-the-pod` only `NAME` substring is
+  replaced with the string defined by substitution source.
diff --git a/krm-functions/replacement-transformer/image/go.mod b/krm-functions/replacement-transformer/image/go.mod
new file mode 100644
index 000000000..3520e46ae
--- /dev/null
+++ b/krm-functions/replacement-transformer/image/go.mod
@@ -0,0 +1,8 @@
+module opendev.org/airship/airshipctl/functions/replacement-transformer/image
+
+go 1.14
+
+require (
+	opendev.org/airship/airshipctl v0.0.0-20201007215749-76e4d3f48c5a
+	sigs.k8s.io/kustomize/kyaml v0.7.1
+)
diff --git a/krm-functions/replacement-transformer/local-resource/example-use.yaml b/krm-functions/replacement-transformer/local-resource/example-use.yaml
new file mode 100644
index 000000000..893040174
--- /dev/null
+++ b/krm-functions/replacement-transformer/local-resource/example-use.yaml
@@ -0,0 +1,47 @@
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+---
+apiVersion: airshipit.org/v1alpha1
+kind: ReplacementTransformer
+metadata:
+  annotations:
+    config.kubernetes.io/function: |-
+      container:
+        image: quay.io/airshipit/replacement-transformer:dev
+  name: k8scontrol-versions-replacements
+replacements:
+# Replace the Kubernetes version in the KubeadmControlPlane
+- source:
+    objref:
+      name: versions-airshipctl
+    fieldref: kubernetes
+  target:
+    objref:
+      kind: KubeadmControlPlane
+      name: cluster-controlplane
+    fieldrefs:
+      - "{.spec.version}"
+---
+kind: KubeadmControlPlane
+apiVersion: controlplane.cluster.x-k8s.io/v1alpha3
+metadata:
+  name: cluster-controlplane
+spec:
+  replicas: 1
+  version: v1.18.6
+---
+apiVersion: airshipit.org/v1alpha1
+kind: VariableCatalogue
+metadata:
+  name: versions-airshipctl
+kubernetes: v1.19
diff --git a/krm-functions/replacement-transformer/main.go b/krm-functions/replacement-transformer/main.go
new file mode 100644
index 000000000..69a8ee6ce
--- /dev/null
+++ b/krm-functions/replacement-transformer/main.go
@@ -0,0 +1,32 @@
+// Copyright 2019 The Kubernetes Authors.
+// SPDX-License-Identifier: Apache-2.0
+
+// Package main implements an injection function for resource reservations and
+// is run with `kustomize config run -- DIR/`.
+package main
+
+import (
+	"fmt"
+	"os"
+
+	"sigs.k8s.io/kustomize/kyaml/fn/framework"
+
+	"opendev.org/airship/airshipctl/pkg/document/plugin/replacement"
+)
+
+func main() {
+	cfg := make(map[string]interface{})
+	resourceList := &framework.ResourceList{FunctionConfig: &cfg}
+	cmd := framework.Command(resourceList, func() error {
+		plugin, err := replacement.New(cfg)
+		if err != nil {
+			return err
+		}
+		resourceList.Items, err = plugin.Filter(resourceList.Items)
+		return err
+	})
+	if err := cmd.Execute(); err != nil {
+		fmt.Fprint(os.Stderr, err)
+		os.Exit(1)
+	}
+}
diff --git a/manifests/function/baremetal-operator/replacements/versions.yaml b/manifests/function/baremetal-operator/replacements/versions.yaml
index f49c00450..144a7d939 100644
--- a/manifests/function/baremetal-operator/replacements/versions.yaml
+++ b/manifests/function/baremetal-operator/replacements/versions.yaml
@@ -4,79 +4,83 @@ apiVersion: airshipit.org/v1alpha1
 kind: ReplacementTransformer
 metadata:
   name: baremetal-operator-versions-replacements
+  annotations:
+    config.kubernetes.io/function: |-
+      container:
+        image: quay.io/airshipit/replacement-transformer:dev
 replacements:
 # Container versions for the ironic Deployment
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.ironic.init_bootstrap
+    fieldref: "{.images.baremetal_operator.ironic.init_bootstrap}"
   target:
     objref:
       kind: Deployment
       name: ironic
-    fieldrefs: ["spec.template.spec.initContainers[name=init-bootstrap].image"]
+    fieldrefs: ["{.spec.template.spec.initContainers[?(.name == 'init-bootstrap')].image}"]
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.ironic.dnsmasq
+    fieldref: "{.images.baremetal_operator.ironic.dnsmasq}"
   target:
     objref:
       kind: Deployment
       name: ironic
-    fieldrefs: ["spec.template.spec.containers[name=dnsmasq].image"]
+    fieldrefs: ["{.spec.template.spec.containers[?(.name == 'dnsmasq')].image}"]
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.ironic.httpd
+    fieldref: "{.images.baremetal_operator.ironic.httpd}"
   target:
     objref:
       kind: Deployment
       name: ironic
-    fieldrefs: ["spec.template.spec.containers[name=httpd].image"]
+    fieldrefs: ["{.spec.template.spec.containers[?(.name == 'httpd')].image}"]
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.ironic.ironic
+    fieldref: "{.images.baremetal_operator.ironic.ironic}"
   target:
     objref:
       kind: Deployment
       name: ironic
-    fieldrefs: ["spec.template.spec.containers[name=ironic].image"]
+    fieldrefs: ["{.spec.template.spec.containers[?(.name == 'ironic')].image}"]
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.ironic.ironic_inspector
+    fieldref: "{.images.baremetal_operator.ironic.ironic_inspector}"
   target:
     objref:
       kind: Deployment
       name: ironic
-    fieldrefs: ["spec.template.spec.containers[name=ironic-inspector].image"]
+    fieldrefs: ["{.spec.template.spec.containers[?(.name == 'ironic-inspector')].image}"]
 # Container versions for the metal3-baremetal-operator Deployment
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.metal3_baremetal_operator.baremetal_operator
+    fieldref: "{.images.baremetal_operator.metal3_baremetal_operator.baremetal_operator}"
   target:
     objref:
       kind: Deployment
       name: metal3-baremetal-operator
-    fieldrefs: ["spec.template.spec.containers[name=baremetal-operator].image"]
+    fieldrefs: ["{.spec.template.spec.containers[?(.name == 'baremetal-operator')].image}"]
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.metal3_baremetal_operator.ironic_proxy
+    fieldref: "{.images.baremetal_operator.metal3_baremetal_operator.ironic_proxy}"
   target:
     objref:
       kind: Deployment
       name: metal3-baremetal-operator
-    fieldrefs: ["spec.template.spec.containers[name=ironic-proxy].image"]
+    fieldrefs: ["{.spec.template.spec.containers[?(.name == 'ironic-proxy')].image}"]
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: images.baremetal_operator.metal3_baremetal_operator.ironic_inspector_proxy
+    fieldref: "{.images.baremetal_operator.metal3_baremetal_operator.ironic_inspector_proxy}"
   target:
     objref:
       kind: Deployment
       name: metal3-baremetal-operator
-    fieldrefs: ["spec.template.spec.containers[name=ironic-inspector-proxy].image"]
+    fieldrefs: ["{.spec.template.spec.containers[?(.name == 'ironic-inspector-proxy')].image}"]
 
diff --git a/manifests/function/clusterctl/replacements/versions.yaml b/manifests/function/clusterctl/replacements/versions.yaml
index d7f830503..f655c0baa 100644
--- a/manifests/function/clusterctl/replacements/versions.yaml
+++ b/manifests/function/clusterctl/replacements/versions.yaml
@@ -3,25 +3,29 @@ apiVersion: airshipit.org/v1alpha1
 kind: ReplacementTransformer
 metadata:
   name: k8scontrol-versions-replacements
+  annotations:
+    config.kubernetes.io/function: |-
+      container:
+        image: quay.io/airshipit/replacement-transformer:dev
 replacements:
 # Replace the Kubernetes version in the KubeadmControlPlane
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: kubernetes
+    fieldref: "{.kubernetes}"
   target:
     objref:
       kind: KubeadmControlPlane
       name: cluster-controlplane
-    fieldrefs: ["spec.version"]
+    fieldrefs: ["{.spec.version}"]
 # Replace the controlplane disk image in the Metal3MachineTemplate
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: files.k8scontrol.cluster_controlplane_image
+    fieldref: "{.files.k8scontrol.cluster_controlplane_image}"
   target:
     objref:
       kind: Metal3MachineTemplate
       name: cluster-controlplane
-    fieldrefs: ["spec.template.spec.image"]
+    fieldrefs: ["{.spec.template.spec.image}"]
 
diff --git a/manifests/function/hardwareprofile-example/replacements/hosts.yaml b/manifests/function/hardwareprofile-example/replacements/hosts.yaml
index fa406fea6..d8d9f20fd 100644
--- a/manifests/function/hardwareprofile-example/replacements/hosts.yaml
+++ b/manifests/function/hardwareprofile-example/replacements/hosts.yaml
@@ -5,15 +5,19 @@ kind: ReplacementTransformer
 metadata:
   # NOTE: change this when copying this example
   name: hardwareprofile-example-replacements
+  annotations:
+    config.kubernetes.io/function: |-
+      container:
+        image: quay.io/airshipit/replacement-transformer:dev
 replacements:
 - source:
     objref:
       # NOTE: change this to match your hardwareProfile's metadata.name
       name: hardwareprofile-example
-    fieldref: hardwareProfile
+    fieldref: "{.hardwareProfile}"
   target:
     objref:
       kind: Templater
       name: m3-host-template
     # NOTE: change "example" below when copying this example
-    fieldrefs: [values.hardwareProfiles.example]
+    fieldrefs: ["{.values.hardwareProfiles.example}"]
diff --git a/manifests/function/hostgenerator-m3/replacements/hosts.yaml b/manifests/function/hostgenerator-m3/replacements/hosts.yaml
index fd91dbce6..10f2a9a61 100644
--- a/manifests/function/hostgenerator-m3/replacements/hosts.yaml
+++ b/manifests/function/hostgenerator-m3/replacements/hosts.yaml
@@ -4,31 +4,35 @@ apiVersion: airshipit.org/v1alpha1
 kind: ReplacementTransformer
 metadata:
   name: m3-host-replacements
+  annotations:
+    config.kubernetes.io/function: |-
+      container:
+        image: quay.io/airshipit/replacement-transformer:dev
 replacements:
 - source:
     objref:
       name: host-catalogue
-    fieldref: hosts.m3
+    fieldref: "{.hosts.m3}"
   target:
     objref:
       kind: Templater
       name: m3-host-template
-    fieldrefs: [values.hosts]
+    fieldrefs: ["{.values.hosts}"]
 - source:
     objref:
       name: host-generation-catalogue
-    fieldref: hosts.m3
+    fieldref: "{.hosts.m3}"
   target:
     objref:
       kind: Templater
       name: m3-host-template
-    fieldrefs: [values.hostsToGenerate]
+    fieldrefs: ["{.values.hostsToGenerate}"]
 - source:
     objref:
       name: common-networking-catalogue
-    fieldref: commonNetworking
+    fieldref: "{.commonNetworking}"
   target:
     objref:
       kind: Templater
       name: m3-host-template
-    fieldrefs: [values.commonNetworking]
+    fieldrefs: ["{.values.commonNetworking}"]
diff --git a/manifests/function/k8scontrol/replacements/versions.yaml b/manifests/function/k8scontrol/replacements/versions.yaml
index d7f830503..f655c0baa 100644
--- a/manifests/function/k8scontrol/replacements/versions.yaml
+++ b/manifests/function/k8scontrol/replacements/versions.yaml
@@ -3,25 +3,29 @@ apiVersion: airshipit.org/v1alpha1
 kind: ReplacementTransformer
 metadata:
   name: k8scontrol-versions-replacements
+  annotations:
+    config.kubernetes.io/function: |-
+      container:
+        image: quay.io/airshipit/replacement-transformer:dev
 replacements:
 # Replace the Kubernetes version in the KubeadmControlPlane
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: kubernetes
+    fieldref: "{.kubernetes}"
   target:
     objref:
       kind: KubeadmControlPlane
       name: cluster-controlplane
-    fieldrefs: ["spec.version"]
+    fieldrefs: ["{.spec.version}"]
 # Replace the controlplane disk image in the Metal3MachineTemplate
 - source:
     objref:
       name: versions-airshipctl
-    fieldref: files.k8scontrol.cluster_controlplane_image
+    fieldref: "{.files.k8scontrol.cluster_controlplane_image}"
   target:
     objref:
       kind: Metal3MachineTemplate
       name: cluster-controlplane
-    fieldrefs: ["spec.template.spec.image"]
+    fieldrefs: ["{.spec.template.spec.image}"]
 
diff --git a/pkg/api/v1alpha1/replacement_plugin_types.go b/pkg/api/v1alpha1/replacement_plugin_types.go
index 6ac48f1ee..4ab1c50ce 100644
--- a/pkg/api/v1alpha1/replacement_plugin_types.go
+++ b/pkg/api/v1alpha1/replacement_plugin_types.go
@@ -28,7 +28,6 @@ type ReplacementTransformer struct {
 
 	// Replacements list of source and target field to do a replacement
 	Replacements []types.Replacement `json:"replacements,omitempty" yaml:"replacements,omitempty"`
-	Tst          []string
 }
 
 // DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
diff --git a/pkg/document/plugin/replacement/transformer.go b/pkg/document/plugin/replacement/transformer.go
index cbaa0ef53..74e7f69a3 100644
--- a/pkg/document/plugin/replacement/transformer.go
+++ b/pkg/document/plugin/replacement/transformer.go
@@ -26,7 +26,7 @@ import (
 var (
 	pattern = regexp.MustCompile(`(\S+)\[(\S+)=(\S+)\]`)
 	// substring substitutions are appended to paths as: ...%VARNAME%
-	substringPatternRegex = regexp.MustCompile(`(\S+)%(\S+)%$`)
+	substringPatternRegex = regexp.MustCompile(`(.+)%(\S+)%$`)
 )
 
 const (
diff --git a/playbooks/get-vm-config.yaml b/playbooks/get-vm-config.yaml
index 74de7539a..a784e449d 100644
--- a/playbooks/get-vm-config.yaml
+++ b/playbooks/get-vm-config.yaml
@@ -15,7 +15,7 @@
     set -e
     kustomize build --enable_alpha_plugins \
       {{ airship_config_manifest_directory }}/{{ airship_config_site_path }}/{{ path }} |
-    kustomize config grep  "kind=BareMetalHost"
+    kustomize cfg grep  "kind=BareMetalHost"
   register: bmh_command
   failed_when: "bmh_command.stdout == ''"
   environment:
@@ -30,7 +30,7 @@
     set -e
     kustomize build --enable_alpha_plugins \
       {{ airship_config_manifest_directory }}/{{ airship_config_site_path }}/{{ path }} |
-    kustomize config grep  "metadata.name={{ item.spec.networkData.name }}"
+    kustomize cfg grep  "metadata.name={{ item.spec.networkData.name }}"
   register: netdata_command
   failed_when: "netdata_command.stdout == ''"
   environment:
diff --git a/roles/install-kustomize/defaults/main.yml b/roles/install-kustomize/defaults/main.yml
index 40eadb415..756f87f09 100644
--- a/roles/install-kustomize/defaults/main.yml
+++ b/roles/install-kustomize/defaults/main.yml
@@ -10,7 +10,7 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-kustomize_version: v3.5.5
+kustomize_version: v3.8.5
 kustomize_download_url: "https://github.com/kubernetes-sigs/kustomize/releases/download/kustomize/{{ kustomize_version }}/kustomize_{{ kustomize_version }}_linux_amd64.tar.gz"
 proxy:
   http:
diff --git a/tools/deployment/21_systemwide_executable.sh b/tools/deployment/21_systemwide_executable.sh
index be1305b76..e11dc5774 100755
--- a/tools/deployment/21_systemwide_executable.sh
+++ b/tools/deployment/21_systemwide_executable.sh
@@ -19,8 +19,8 @@ export HTTPS_PROXY=${HTTPS_PROXY:-${https_proxy}}
 export HTTP_PROXY=${HTTP_PROXY:-${http_proxy}}
 export NO_PROXY=${NO_PROXY:-${no_proxy}}
 
-echo "Build airshipctl in docker image"
-make docker-image
+echo "Build airshipctl docker images"
+make images
 
 echo "Copy airshipctl from docker image"
 DOCKER_IMAGE_TAG=$(make print-docker-image-tag)