kube-dsl
A Ruby DSL for defining Kubernetes resources.
What is this thing?
KubeDSL provides a domain-specific language for defining Kubernetes resource objects in Ruby. Why would you want to do this? Well,
- I think Ruby code is easier to read than YAML.
- every property is a Ruby method, meaning Ruby will blow up if you try to configure the object the wrong way.
- doing so follows the principle of infrastructure as code.
- validations are built-in.
Installation
Either run gem install kube-dsl
or add it to your Gemfile:
gem 'kube-dsl', '< 1'
Usage
KubeDSL directly mirrors the fields and nesting structure of each Kubernetes YAML (or JSON) object. Ruby fields are snake_cased while Kubernetes fields are camelCased. Let's take a look at a short example where we define a Namespace:
ns = KubeDSL.namespace do
metadata do
name 'my-namespace'
end
end
In the example above, we've defined a KubeDSL::DSL::V1::Namespace
object and assigned it to a local variable called ns
. Now let's convert it into a YAML string and print it out:
# ---
# apiVersion: v1
# kind: Namespace
# metadata:
# name: foo
puts ns.to_resource.to_yaml
The #to_resource
method returns an instance of the KubeDSL::Resource
class while #to_yaml
converts the resource into a YAML string. Pretty cool, eh? See the next few sections for examples creating other types of common Kubernetes objects.
ServiceAccount Example
Note how key/value pairs are added to the labels
field.
KubeDSL.service_account do
metadata do
name 'my-service-account'
namespace 'my-namespace'
labels do
add :app, 'my-app'
add :role, 'web'
end
end
end
Service Example
KubeDSL.service do
metadata do
name 'my-service'
namespace 'my-namespace'
labels do
add :app, 'my-app'
add :role, 'web'
end
end
spec do
type 'NodePort'
selector do
add :app, 'my-app'
add :role, 'web'
end
port do
name 'http'
port 3000
protocol 'TCP'
target_port 'http'
end
end
end
Deployment Example
Note:
- Elements of arrays can be given names (see the use of the
#container
method below) so they can be easily retrieved and/or modified later. - The example below shows how to add config maps and secrets to a deployment via references.
KubeDSL.deployment do
metadata do
name 'my-deployment'
namespace 'my-namespace'
labels do
add :app, 'my-app'
add :role, 'web'
end
end
spec do
replicas 2
selector do
match_labels do
add :app, 'my-app'
add :role, 'web'
end
end
strategy do
type 'RollingUpdate'
rolling_update do
max_surge '25%'
max_unavailable 1
end
end
template do
metadata do
labels do
add :app, 'my-app'
add :role, 'web'
end
end
spec do
# elements of arrays can be given names (:web in this case) so they can be
# easily retrieved and/or modified later
container(:web) do
name 'my-web-container'
image_pull_policy 'IfNotPresent'
port do
container_port 3000
name 'http'
protocol 'TCP'
end
env_from do
config_map_ref do
name 'my-config-map'
end
end
env_from do
secret_ref do
name 'my-secrets'
end
end
readiness_probe do
success_threshold 1
failure_threshold 2
initial_delay_seconds 15
period_seconds 3
timeout_seconds 1
http_get do
path '/healthz'
port 3000
scheme 'HTTP'
end
end
end
image_pull_secret do
name 'my-registry-secret'
end
end
restart_policy 'Always'
service_account_name 'my-service-account'
end
end
end
Ingress Example
NOTE: the example below includes an annotation that is specific to the Nginx ingress controller.
KubeDSL::DSL::Extensions::V1beta1::Ingress.new do
metadata do
name 'my-ingress'
namespace 'my-namespace'
annotations do
add :'kubernetes.io/ingress.class', 'nginx'
end
end
spec do
rule do
host 'my-website.com'
http do
path do
path '/'
backend do
service_name 'my-service'
service_port 80
end
end
end
end
end
end
ConfigMap Example
KubeDSL.config_map do
metadata do
name 'my-config-map'
namespace 'my-namespace'
end
data do
add :MY_VAR, 'value'
add :MY_OTHER_VAR, 'value'
end
end
Secret Example
KubeDSL.secret do
metadata do
name 'my-secrets'
namespace 'my-namespace'
end
type 'Opaque'
data do
add :MY_SECRET, 'value'
end
end
Validations
All KubeDSL::DSLObject
s respond to #valid?
and #validate
methods. Use #valid?
to determine whether or not an object is valid. Use #validate
to retrieve a list of validation errors:
ns = KubeDSL.namespace do
metadata do
name 123
end
end
ns.valid? # => false
ns.validate # => #<KubeDSL::Validations::ValidationErrors:0x00007fc8ce276e80 ... >
ns.validate.messages # => {"metadata.name"=>["is not a String"]}
The handy #validate!
method will raise a KubeDSL::ValidationError
if the object is invalid.
Code Generation
All the Ruby code present in KubeDSL is generated from the Kubernetes JSON schema available here. Run the following rake task to regenerate:
bundle exec rake generate
Authors
- Cameron C. Dutro: http://github.com/camertron
License
Licensed under the MIT license.