
Kubeform by AppsCode is a Kubernetes operator for Terraform . Kubeform provides auto-generated Kubernetes CRDs for Terraform resources and modules so that you can manage any cloud infrastructure in a Kubernetes native way. You just write a CRD for a cloud infrastructure, apply it and Kubeform will create it for you! Kubeform currently supports 5 top cloud platforms. These are AWS, Google Cloud, Azure, Digitalocean and Linode.
The key features of Kubeform are:
- Native kubernetes support
- Built on Terraform
- Supports Terraform resources and modules
- Use cloud infrastructures as code
- Define & Manage cloud infrastructures as Kubernetes
CRD(Custom Resource Definition) - Supports multiple cloud platform
- 100% open source
How Kubeform Works
The following diagram shows how Kubeform creates a resource on a Cloud Provider (GCP, AWS, etc.).
The Resource Creation Process of Kubeform consists of the following steps:
At first, a user creates a secret with access credentials of the Cloud provider where the resource will be created.
Then, he creates a CRD of the resource that specifies the information of the Cloud Resource. The CRD also holds the credential information.
The KubeForm Controller (KFC) watches the created CRD.
Then, KFC creates
.tffiles from the CRDSpecand the provider secret.If the
.tfstatefile doesn’t exist then KFC creates the.tfstatefile from thestatus.output&status.statefields of the CRD.Then KFC runs
terraform applycommands on the.tfstatefile and.tffiles that were created in the previous steps.After successful execution of
terraform applycommand, it creates the specified resource on the specified Cloud Provider.Then
terraform applycommand updates thetfstatefile if necessary.If the
.tfstatefile is updated, KFC also updates thestatus.output&status.statefields of the CRD.
How to use Kubeform
Let’s take a look at how can we create anp AWS RDS (Relational Database Service) using Kubeform.
- First install the kubeform operator following the instructions here :
Using Helm 3
Kubeform can be installed via Helm
using the chart
from AppsCode Charts Repository
. To install the chart with the release name my-release:
$ helm repo add appscode https://charts.appscode.com/stable/
$ helm repo update
$ helm search repo appscode/kubeform
NAME CHART VERSION APP VERSION DESCRIPTION
appscode/kubeform v0.1.0 v0.1.0 Kubeform by AppsCode - Build Cloud Infrastructure from Kubernetes
$ helm install kfc appscode/kubeform --version v0.1.0 --namespace kube-system
To see the detailed configuration options, visit here .
Using Helm 2
Kubeform can be installed via Helm
using the chart
from AppsCode Charts Repository
. To install the chart with the release name my-release:
$ helm repo add appscode https://charts.appscode.com/stable/
$ helm repo update
$ helm search appscode/kubeform
NAME CHART VERSION APP VERSION DESCRIPTION
appscode/kubeform v0.1.0 v0.1.0 Kubeform by AppsCode - Build Cloud Infrastructure from Kubernetes
$ helm install appscode/kubeform --name kfc --version v0.1.0 --namespace kube-system
To see the detailed configuration options, visit here .
- Now, we need AWS provider secrets to connect with AWS. For terraform, this secrets are provided like this in a
.tffile:
{
"provider": {
"aws": {
"access_key": "ACCESS_KEY",
"region": "us-east-1",
"secret_key": "SECRET_KEY"
}
}
}
For using it in Kubeform, we need to convert it to a secret like this:
apiVersion: v1
kind: Secret
metadata:
name: aws
type: kfc.io/aws
data:
region: dXMtZWFzdC0xCg== # base64 encoded value of `us-east-1`
access_key: '<base64 encoded access key>'
secret_key: '<base64 encoded secret key>'
Then we have to reference it from our Resource CRD.
- Now We need to create the AWS RDS CRD. We can create the AWS RDS CRD using the following kubectl command:
kubectl apply -f https://github.com/kubeform/kubeform/raw/master/api/crds/aws.kubeform.com_dbinstances.yaml
- The AWS RDS configuration of terraform is given in a
.tflike this:
{
"resource": {
"aws_db_instance": {
"test1": {
"allocated_storage": 5,
"engine": "mysql",
"engine_version": "5.7",
"instance_class": "db.t2.micro",
"name": "mydb",
"parameter_group_name": "default.mysql5.7",
"password": "foobar1234",
"storage_type": "gp2",
"username": "foo"
}
}
}
}
We can see that, there is a field called password, which is a sensitive value. So, we should not use this kind of sensitive value directly in the yaml. We’ll create a secret to store the sensitive value like the this:
apiVersion: v1
kind: Secret
metadata:
name: rds-pass
type: kfc.io/aws
data:
password: Zm9vYmFyMTIzNAo= # base64 encoded value of `foobar1234`
Then we can reference it from our DbInstance CRD. The DbInstance CRD will look like this:
apiVersion: aws.kubeform.com/v1alpha1
kind: DbInstance
metadata:
name: test1
spec:
allocatedStorage: 5
storageType: gp2
engine: mysql
engineVersion: '5.7'
instanceClass: db.t2.micro
name: mydb
username: foo
parameterGroupName: default.mysql5.7
providerRef:
name: aws
secretRef:
name: rds-pass
Here, we can see that the provider secret is referenced using a field called providerRef and the sensitive value secret is referenced using a field called secretRef.
- Let’s put it altogether and apply it using kubectl. First create a
aws_rds.yamlusing the following yaml:
AWS RDS
apiVersion: v1
kind: Secret
metadata:
name: aws
type: kfc.io/aws
data:
region: dXMtZWFzdC0xCg==
access_key: '<base64 encoded access key>'
secret_key: '<base64 encoded secret key>'
---
apiVersion: v1
kind: Secret
metadata:
name: rds-pass
type: kfc.io/aws
data:
password: Zm9vYmFyMTIzNAo=
---
apiVersion: aws.kubeform.com/v1alpha1
kind: DbInstance
metadata:
name: test1
spec:
allocatedStorage: 5
storageType: gp2
engine: mysql
engineVersion: '5.7'
instanceClass: db.t2.micro
name: mydb
username: foo
parameterGroupName: default.mysql5.7
providerRef:
name: aws
secretRef:
name: rds-pass
Then, run:
kubectl apply -f aws_rds.yaml
After that, an AWS RDS will be created!
- To delete the rds instance just run:
kubectl delete -f aws_rds.yaml
How Kubeform handles Terraform State
Terraform Resource
For individual resources, Kubeform doesn’t store the full tfstate file in the CRD. The tfstate json file contains version, terraform_version, serial, lineage and resources fields.
Kubeform stores the tfstate file in the CRD using the following way:
- The
version,terraform_version,serialand,lineagefields are stored instatus.statefield in the custom resources. - The data from the
resourcesfield that are not sensitive are stored in theoutputfield of the CRD. - The data from the
resourcesfield that are sensitive are stored in a secret. The secret name is specified in asecretReffield of the CRD. If thesecretRefis not set, then KFC creates a secret and stores the sensitive outputs there.
To obtain the tfstate from the state field:
- The
version,terraform_version,serialand,lineagefields are retrieves from thestatus.statefield of a Kubeform resource. - The non-sensitive data from the
outputfield ofstatusand the sensitive data from the secret are merged and then set on theresourcesfield.
Terraform Module
For Terraform modules, Kubeform stores the full tfstate file in the CRD status object. As the tfstate file may contain sensitive information, KFC doesn’t store the tfstate file directly.
Before storing the tfstate file in the CRD, the tfstate is transformed in the following steps:
- First, the content of the tfstate file is compressed using
gzip. - Then the compressed data is encrypted using a secret key. The secret key is a base64 encoded key which is 32 bytes when decoded. The secret key is provided by the user to the Kubeform operator(
kfc). - The encrypted data is
basE91encoded.basE91is an advanced method for encoding binary data as ASCII characters. It is similar to base64, but is more efficient. The overhead produced by basE91 depends on the input data. It amounts at most to 23% (versus 33% for base64). - Finally, the base91 encoded data is stored in the
statefield ofstatusobject in the CRD.
The process is shown in the following figure:
To obtain the tfstate file from the status.state field of a custom resource, the steps is followed in reverse:
- First, the
status.statefield of the Kubeform module resource is base91 decoded. - The base91 decoded data is then decrypted using the secret key.
- Then the decrypted data is decompressed using
gzip. - Finally, decompressed data is saved as a
tfstatefile.
The process is shown in the following figure:
Alternatives
We have explored the option of using Kubernetes Service Catalog project to consume cloud services in Kubernetes using the Open Service Broker API. But CRDs provide better tooling in the context of Kubernetes. Also, this project has seen very little activity in recent times and cloud providers are abandoning it in favor of CRD based solutions.
Visit Kubeform project website to learn more. You can also find us on GitHub .
If you have read all the way to the end, I want to thank you. If you have any questions and want to know more, you can reach us via Email .





