Build your operator with the right tool

Build Your Operator With the
Right Tool
Rafał Leszko
@RafalLeszko
rafalleszko.com
Hazelcast
About me
● Integration Team Lead at Hazelcast
● Worked at Google and CERN
● Author of the book "Continuous Delivery
with Docker and Jenkins"
● Trainer and conference speaker
● Live in Kraków, Poland
About Hazelcast
● Distributed Company
● Open Source Software
● 140+ Employees
● Products:
○ Hazelcast IMDG
○ Hazelcast Jet
○ Hazelcast Cloud
@Hazelcast
● Introduction
● Tools for building Operators
○ Operator SDK
■ Helm
■ Ansible
■ Go
○ Operator Frameworks: KOPF, Java Operator SDK, ...
○ Bare Programming Language: Java, Kotlin, C#, ...
● Summary
Agenda
Introduction
Kubernetes Operator
Kubernetes Operator
Operator is an application that watches a custom Kubernetes
resource and performs some operations upon its changes.
apiVersion: hazelcast.my.domain/v1
kind: Hazelcast
metadata:
name: hazelcast-sample
spec:
size: 1
Resource (hazelcast.yaml)
apiVersion: hazelcast.my.domain/v1
kind: Hazelcast
metadata:
name: hazelcast-sample
spec:
size: 1
$ kubectl apply -f hazelcast.yaml
Resource (hazelcast.yaml)
Hazelcast
Resource
Kubernetes APIHazelcast Operator
modify
watches change events
adjust state
Kubernetes
Operators
FRAMEWORKS
KOPF
Operator Similarities
Step 1: Implement the operator logic
Operator Similarities
Step 1: Implement the operator logic
Step 2: Dockerize your operator
$ docker build -t <user>/hazelcast-operator .
$ docker push <user>/hazelcast-operator
Operator Similarities
Step 1: Implement the operator logic
Step 2: Dockerize your operator
$ docker build -t <user>/hazelcast-operator .
$ docker push <user>/hazelcast-operator
Step 3: Create CRD (Custom Resource Definition)
$ kubectl apply -f hazelast.crd.yaml
Operator Similarities
Operator Similarities
Step 4: Create RBAC (Role and Role Binding)
$ kubectl apply -f role.yaml
$ kubectl apply -f role_binding.yaml
Operator Similarities
Step 4: Create RBAC (Role and Role Binding)
$ kubectl apply -f role.yaml
$ kubectl apply -f role_binding.yaml
Step 5: Deploy the operator
$ kubectl apply -f operator.yaml
Operator Similarities
Step 4: Create RBAC (Role and Role Binding)
$ kubectl apply -f role.yaml
$ kubectl apply -f role_binding.yaml
Step 5: Deploy the operator
$ kubectl apply -f operator.yaml
Step 6: Create your custom resource
$ kubectl apply -f hazelcast.yaml
Operator Similarities
Step 1: Implement the operator logic
Step 2: Dockerize your operator
Step 3: Create CRD (Custom Resource Definition)
Step 4: Create RBAC (Role and Role Binding)
Step 5: Deploy the operator
Step 6: Create your custom resource
● Introduction ✔
● Tools for building Operators
○ Operator SDK
■ Helm
■ Ansible
■ Go
○ Operator Frameworks: KOPF, Java Operator SDK, ...
○ Bare Programming Language: Java, Kotlin, C#, ...
● Summary
Agenda
Operator SDK: Helm
Helm is a package manager for Kubernetes.
It allows you to:
● create templated Kubernetes configurations
● package them into a Helm chart
● render them using parameters defined in values.yaml
Helm: Create Helm Chart
$ helm create chart
# chart/templates/deployment.yaml
apiVersion: apps/v1
kind: Deployment
metadata:
name: {{ include "hazelcast.fullname" . }}
spec:
replicas: {{ .Values.size }}
selector:
matchLabels:
app: hazelcast
# chart/values.yaml
size: 1
template:
metadata:
labels:
app: hazelcast
spec:
containers:
- name: hazelcast
image: "hazelcast/hazelcast"
Generate Hazelcast Operator
$ operator-sdk init --plugins=helm
$ operator-sdk create api --group=hazelcast --version=v1
--helm-chart=./chart
Common Operator Steps: build, install, and use
$ docker build -t <user>/hazelcast-operator .
$ docker push <user>/hazelcast-operator
$ make install
$ make deploy IMG=<user>/hazelcast-operator
$ kubectl apply -f config/samples/hazelcast_v1_hazelcast.yaml
Helm: Generate Operator
Operator SDK: Operator Capability Levels
What does "Operator SDK: Helm" mean to You?
● Implementation is declarative and
simple
● If you already have a Helm chart, then
no work at all
● Limited to the features available in Helm
● Operator manifest/configuration files
are automatically generated
Operator SDK: Ansible
Ansible is a very powerful tool for IT automation.
It allows you to:
● create tasks in a declarative way
● perform complex DevOps tasks using simple YAML files
● interact with Kubernetes API using the
community.kubernetes.k8s plugin
Ansible: Create Operator
# roles/hazelcast/tasks/main.yml
---
- name: start hazelcast
community.kubernetes.k8s:
definition:
kind: Deployment
apiVersion: apps/v1
metadata:
name: hazelcast
namespace: '{{ansible_operator_meta.namespace}}'
spec:
replicas: "{{size}}"
selector:
matchLabels:
app: hazelcast
template:
metadata:
labels:
app: hazelcast
spec:
containers:
- name: hazelcast
image: "hazelcast/hazelcast"
$ operator-sdk init --plugins=ansible
$ operator-sdk create api --group hazelcast --version v1 --kind Hazelcast 
--generate-role
Common Operator Steps: build, install, and use
$ docker build -t <user>/hazelcast-operator .
$ docker push <user>/hazelcast-operator
$ make install
$ make deploy IMG=<user>/hazelcast-operator
$ kubectl apply -f config/samples/hazelcast_v1_hazelcast.yaml
Ansible: Build, Install, Use Operator
Operator SDK: Operator Capability Levels
What does "Operator SDK: Ansible" mean to You?
● Implementation is declarative and
therefore concise and human-readable
● YAML configuration is executed via the
community.kubernetes.k8s plugin
● Ansible covers all capability levels
● Operator manifest/configuration files
are automatically generated
Operator SDK: Go
Go is a general-purpose programming language.
Advantages:
● Kubernete is written in Go
● good Kubernetes client library
● performance
Go: Create Operator
// controllers/hazelcast_controller.go
// +kubebuilder:rbac:groups=hazelcast.my.domain,resources=hazelcasts,verbs=get;list…
func (r *HazelcastReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) {
...
hazelcast := &hazelcastv1.Hazelcast{}
err := r.Get(ctx, req.NamespacedName, hazelcast)
...
found := &appsv1.Deployment{}
err = r.Get(ctx, types.NamespacedName{Name: hazelcast.Name,
Namespace: hazelcast.Namespace}, found)
if err != nil && errors.IsNotFound(err) { dep := r.deploymentForHazelcast(hazelcast) }
...
}
$ operator-sdk init --repo=github.com/<user>/hazelcast-operator
$ operator-sdk create api --version v1 --group=hazelcast --kind Hazelcast --resource=true
--controller=true
Go: Create Operator
// controllers/hazelcast_controller.go
...
Spec: appsv1.DeploymentSpec{
Replicas: &replicas,
Selector: &metav1.LabelSelector{
MatchLabels: ls,
},
Template: corev1.PodTemplateSpec{
ObjectMeta: metav1.ObjectMeta{
Labels: ls,
},
Spec: corev1.PodSpec{
Containers: []corev1.Container{{
Image: "hazelcast/hazelcast",
Name: "hazelcast",
}}, }, }, }, }
// api/v1/hazelcast_types.go
type HazelcastSpec struct {
Size int32 `json:"size,omitempty"`
}
Common Operator Steps: build, install, and use
$ docker build -t <user>/hazelcast-operator .
$ docker push <user>/hazelcast-operator
$ make install
$ make deploy IMG=<user>/hazelcast-operator
$ kubectl apply -f config/samples/hazelcast_v1_hazelcast.yaml
Go: Build, Install, Use Operator
What does "Operator SDK: Go" mean to You?
● Implementation is imperative and
requires more work and caution
● Go language is well integrated with
Kubernetes
● No limits on the functionality
● Operator boilerplate files are
automatically generated
● Introduction ✔
● Tools for building Operators
○ Operator SDK ✔
■ Helm ✔
■ Ansible ✔
■ Go ✔
○ Operator Frameworks: KOPF, Java Operator SDK, ...
○ Bare Programming Language: Java, Kotlin, C#, ...
● Summary
Agenda
Operator Frameworks
KOPF C# Operator SDK Java
Operator SDK
NodeJS
Operator Framework
Roperator
KOPF C# Operator SDK Java
Operator SDK
NodeJS
Operator Framework
Roperator
KOPF C# Operator SDK Java
Operator SDK
NodeJS
Operator Framework
Roperator
KOPF C# Operator SDK Java
Operator SDK
NodeJS
Operator Framework
Roperator
KOPF: Create Operator
1. Implement configuration and manifest files
● Dockerfile
● hazelcast.crd.yaml
● role.yaml, role_binding.yaml
● operator.yaml
● hazelcast.yaml
2: Implement operator logic in operator.py
KOPF: Create Operator
@kopf.on.create('hazelcast.my.domain','v1','hazelcasts')
def create_fn(spec, **kwargs):
doc = create_deployment(spec)
kopf.adopt(doc)
api = pykube.HTTPClient(pykube.KubeConfig.from_env())
deployment = pykube.Deployment(api, doc)
deployment.create()
api.session.close()
return {'children': [deployment.metadata['uid']]}
def create_deployment(spec):
return yaml.safe_load(f"""
apiVersion: apps/v1
kind: Deployment
metadata:
name: hazelcast
spec:
replicas: {spec.get('size', 1)}
selector:
matchLabels:
app: hazelcast
template:
metadata:
labels:
app: hazelcast
spec:
containers:
- name: hazelcast
image: "hazelcast/hazelcast"
""")
Common Operator Steps: build, install, and use
$ docker build -t <user>/hazelcast-operator .
$ docker push <user>/hazelcast-operator
$ kubectl apply -f hazelcast.crd.yaml
$ kubectl apply -f role.yaml
$ kubectl apply -f role_binding.yaml
$ kubectl apply -f operator.yaml
$ kubectl apply -f hazelcast.yaml
KOPF: Build, Install, Use Operator
What does "Operator Framework" mean to You?
● Less developed and popular than
Operator SDK
● No project scaffolding and boilerplate
code generation
● No limits on the functionality
● Kubernetes clients are usually inferior to
the Go Kubernetes client
● Introduction ✔
● Tools for building Operators
○ Operator SDK ✔
■ Helm ✔
■ Ansible ✔
■ Go ✔
○ Operator Frameworks: KOPF, Java Operator SDK, … ✔
○ Bare Programming Language: Java, Kotlin, C#, ...
● Summary
Agenda
Bare Programming Language
Build your operator with the right tool
Java + Quarkus: Create Operator
1. Implement configuration and manifest files
● hazelcast.crd.yaml
● role.yaml, role_binding.yaml
● operator.yaml
● hazelcast.yaml
2: Implement Java classes with the operator logic
Java + Quarkus: Create Operator
List hazelcastDeployments = client.apps().deployments().list().getItems().stream()
.filter(ownerRefMatches)
.collect(toList());
if (hazelcastDeployments.isEmpty()) {
client.apps().deployments().create(newDeployment(resource));
} else {
for (Deployment deployment : hazelcastDeployments) {
setSize(deployment, resource);
client.apps().deployments().createOrReplace(deployment);
}
}
Java + Quarkus: Create Operator
public class ClientProvider {
@Produces
@Singleton
@Named("namespace")
private String findNamespace() throws IOException {
return new String(Files.readAllBytes(Paths.get("/var/run/secrets/kubernetes.io/serviceaccount/namespace")));
}
@Produces
@Singleton
KubernetesClient newClient(@Named("namespace") String namespace) {
return new DefaultKubernetesClient().inNamespace(namespace);
}
@Produces
@Singleton
NonNamespaceOperation<HazelcastResource, HazelcastResourceList, HazelcastResourceDoneable, Resource<HazelcastResource, HazelcastResourceDoneable>> makeCustomResourceClient(
KubernetesClient defaultClient, @Named("namespace") String namespace) {
KubernetesDeserializer.registerCustomKind("hazelcast.my.domain/v1", "Hazelcast", HazelcastResource.class);
CustomResourceDefinition crd = defaultClient
.customResourceDefinitions()
.list()
.getItems()
.stream()
.filter(d -> "hazelcasts.hazelcast.my.domain".equals(d.getMetadata().getName()))
.findAny()
.orElseThrow(
() -> new RuntimeException(
"Deployment error: Custom resource definition "hazelcasts.hazelcast.my.domain" not found."));
return defaultClient
.customResources(crd, HazelcastResource.class, HazelcastResourceList.class, HazelcastResourceDoneable.class)
.inNamespace(namespace);
}
}
Java + Quarkus: Create Operator
@ApplicationScoped
public class DeploymentInstaller {
@Inject
private KubernetesClient client;
@Inject
private HazelcastResourceCache cache;
void onStartup(@Observes StartupEvent _ev) {
new Thread(this::runWatch).start();
}
private void runWatch() {
cache.listThenWatch(this::handleEvent);
}
private void handleEvent(Watcher.Action action, String uid) {
try {
HazelcastResource resource = cache.get(uid);
if (resource == null) {
return;
}
Predicate ownerRefMatches = deployments -> deployments.getMetadata().getOwnerReferences().stream()
.anyMatch(ownerReference -> ownerReference.getUid().equals(uid));
List hazelcastDeployments = client.apps().deployments().list().getItems().stream()
.filter(ownerRefMatches)
.collect(toList());
if (hazelcastDeployments.isEmpty()) {
client.apps().deployments().create(newDeployment(resource));
} else {
for (Deployment deployment : hazelcastDeployments) {
setSize(deployment, resource);
client.apps().deployments().createOrReplace(deployment);
}
}
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
private Deployment newDeployment(HazelcastResource resource) {
Deployment deployment = client.apps().deployments().load(getClass().getResourceAsStream("/deployment.yaml")).get();
setSize(deployment, resource);
deployment.getMetadata().getOwnerReferences().get(0).setUid(resource.getMetadata().getUid());
deployment.getMetadata().getOwnerReferences().get(0).setName(resource.getMetadata().getName());
return deployment;
}
private void setSize(Deployment deployment, HazelcastResource resource) {
deployment.getSpec().setReplicas(resource.getSpec().getSize());
}
}
Java + Quarkus: Create Operator
@ApplicationScoped
public class DeploymentInstaller {
@Inject
private KubernetesClient client;
@Inject
private HazelcastResourceCache cache;
void onStartup(@Observes StartupEvent _ev) {
new Thread(this::runWatch).start();
}
private void runWatch() {
cache.listThenWatch(this::handleEvent);
}
private void handleEvent(Watcher.Action action, String uid) {
try {
HazelcastResource resource = cache.get(uid);
if (resource == null) {
return;
}
Predicate ownerRefMatches = deployments -> deployments.getMetadata().getOwnerReferences().stream()
.anyMatch(ownerReference -> ownerReference.getUid().equals(uid));
List hazelcastDeployments = client.apps().deployments().list().getItems().stream()
.filter(ownerRefMatches)
.collect(toList());
if (hazelcastDeployments.isEmpty()) {
client.apps().deployments().create(newDeployment(resource));
} else {
for (Deployment deployment : hazelcastDeployments) {
setSize(deployment, resource);
client.apps().deployments().createOrReplace(deployment);
}
}
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
private Deployment newDeployment(HazelcastResource resource) {
Deployment deployment = client.apps().deployments().load(getClass().getResourceAsStream("/deployment.yaml")).get();
setSize(deployment, resource);
deployment.getMetadata().getOwnerReferences().get(0).setUid(resource.getMetadata().getUid());
deployment.getMetadata().getOwnerReferences().get(0).setName(resource.getMetadata().getName());
return deployment;
}
private void setSize(Deployment deployment, HazelcastResource resource) {
deployment.getSpec().setReplicas(resource.getSpec().getSize());
}
}
@ApplicationScoped
public class HazelcastResourceCache {
private final Map<String, HazelcastResource> cache = new ConcurrentHashMap<>();
@Inject
private NonNamespaceOperation<HazelcastResource, HazelcastResourceList, HazelcastResourceDoneable, Resource<HazelcastResource, HazelcastResourceDoneable>> crClient;
private Executor executor = Executors.newSingleThreadExecutor();
public HazelcastResource get(String uid) {
return cache.get(uid);
}
public void listThenWatch(BiConsumer<Watcher.Action, String> callback) {
try {
// list
crClient
.list()
.getItems()
.forEach(resource -> {
cache.put(resource.getMetadata().getUid(), resource);
String uid = resource.getMetadata().getUid();
executor.execute(() -> callback.accept(Watcher.Action.ADDED, uid));
}
);
// watch
crClient.watch(new Watcher() {
@Override
public void eventReceived(Action action, HazelcastResource resource) {
try {
String uid = resource.getMetadata().getUid();
if (cache.containsKey(uid)) {
int knownResourceVersion = Integer.parseInt(cache.get(uid).getMetadata().getResourceVersion());
int receivedResourceVersion = Integer.parseInt(resource.getMetadata().getResourceVersion());
if (knownResourceVersion > receivedResourceVersion) {
return;
}
}
System.out.println("received " + action + " for resource " + resource);
if (action == Action.ADDED || action == Action.MODIFIED) {
cache.put(uid, resource);
} else if (action == Action.DELETED) {
cache.remove(uid);
} else {
System.err.println("Received unexpected " + action + " event for " + resource);
System.exit(-1);
}
executor.execute(() -> callback.accept(action, uid));
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
@Override
public void onClose(KubernetesClientException cause) {
cause.printStackTrace();
System.exit(-1);
}
});
} catch (Exception e) {
e.printStackTrace();
System.exit(-1);
}
}
}
Java + Quarkus: Create Operator
public class HazelcastResource extends CustomResource {
private HazelcastResourceSpec spec;
public HazelcastResourceSpec getSpec() {
return spec;
}
public void setSpec(HazelcastResourceSpec spec) {
this.spec = spec;
}
@Override
public String toString() {
String name = getMetadata() != null ?
getMetadata().getName() : "unknown";
String version = getMetadata() != null ?
getMetadata().getResourceVersion() : "unknown";
return "name=" + name + " version=" + version + "
value=" + spec;
}
}
Java + Quarkus: Create Operator
public class HazelcastResource extends CustomResource {
private HazelcastResourceSpec spec;
public HazelcastResourceSpec getSpec() {
return spec;
}
public void setSpec(HazelcastResourceSpec spec) {
this.spec = spec;
}
@Override
public String toString() {
String name = getMetadata() != null ?
getMetadata().getName() : "unknown";
String version = getMetadata() != null ?
getMetadata().getResourceVersion() : "unknown";
return "name=" + name + " version=" + version + "
value=" + spec;
}
}
public class HazelcastResourceList extends
CustomResourceList<HazelcastResource> {
// empty
}
Java + Quarkus: Create Operator
public class HazelcastResource extends CustomResource {
private HazelcastResourceSpec spec;
public HazelcastResourceSpec getSpec() {
return spec;
}
public void setSpec(HazelcastResourceSpec spec) {
this.spec = spec;
}
@Override
public String toString() {
String name = getMetadata() != null ?
getMetadata().getName() : "unknown";
String version = getMetadata() != null ?
getMetadata().getResourceVersion() : "unknown";
return "name=" + name + " version=" + version + "
value=" + spec;
}
}
@JsonDeserialize
@RegisterForReflection
public class HazelcastResourceSpec {
@JsonProperty("size")
private Integer size;
public Integer getSize() {
return size;
}
@Override
public String toString() {
return "size=" + size;
}
}
public class HazelcastResourceList extends
CustomResourceList<HazelcastResource> {
// empty
}
Java + Quarkus: Create Operator
public class HazelcastResource extends CustomResource {
private HazelcastResourceSpec spec;
public HazelcastResourceSpec getSpec() {
return spec;
}
public void setSpec(HazelcastResourceSpec spec) {
this.spec = spec;
}
@Override
public String toString() {
String name = getMetadata() != null ?
getMetadata().getName() : "unknown";
String version = getMetadata() != null ?
getMetadata().getResourceVersion() : "unknown";
return "name=" + name + " version=" + version + "
value=" + spec;
}
}
@JsonDeserialize
@RegisterForReflection
public class HazelcastResourceSpec {
@JsonProperty("size")
private Integer size;
public Integer getSize() {
return size;
}
@Override
public String toString() {
return "size=" + size;
}
}
public class HazelcastResourceDoneable extends
CustomResourceDoneable<HazelcastResource> {
public HazelcastResourceDoneable(HazelcastResource resource,
Function<HazelcastResource, HazelcastResource> function) {
super(resource, function);
}
}
public class HazelcastResourceList extends
CustomResourceList<HazelcastResource> {
// empty
}
Build Docker image
$ mvn package && docker build -t <user>/hazelcast-operator .
Build native Docker image
$ mvn package -Pnative -DskipTests -Dnative-image.docker-build=true
$ docker build -t <user>/hazelcast-operator .
Common Operator Steps: push, install, and use
$ docker push <user>/hazelcast-operator
$ kubectl apply -f hazelcast.crd.yaml
$ kubectl apply -f role.yaml
$ kubectl apply -f role_binding.yaml
$ kubectl apply -f operator.yaml
$ kubectl apply -f hazelcast.yaml
Java + Quarkus: Build, Install, Use Operator
What does "Bare Programming Language" mean to You?
● Always means writing more code
● Check if your language has a good
Kubernetes client library
● No limits on the functionality
● Only reason: single programming
language in your organization
Summary
Which tool
should I use for
my operator?
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Build your operator with the right tool
Hint 1: If you already have a Helm chart for your software and
you don’t need any complex capability levels
Hint 1: If you already have a Helm chart for your software and
you don’t need any complex capability levels
Operator SDK: Helm
Hint 2: If you want to create your operator quickly and you
don’t need any complex capability levels
Hint 2: If you want to create your operator quickly and you
don’t need any complex capability levels
Operator SDK: Helm
Hint 3: If you want complex features or/and be flexible about
any future implementations
Hint 3: If you want complex features or/and be flexible about
any future implementations
Operator SDK: Go
Hint 4: If you want to keep a single programming language in
your organization
Hint 4: If you want to keep a single programming language in
your organization
● If a popular Operator Framework exists for your language
or/and you want to contribute to it
Hint 4: If you want to keep a single programming language in
your organization
● If a popular Operator Framework exists for your language
or/and you want to contribute to it
Operator Framework
Hint 4: If you want to keep a single programming language in
your organization
● If a popular Operator Framework exists for your language
or/and you want to contribute to it
● If no popular Operator Framework exists for your
programming language
Operator Framework
Hint 4: If you want to keep a single programming language in
your organization
● If a popular Operator Framework exists for your language
or/and you want to contribute to it
● If no popular Operator Framework exists for your
programming language
Operator Framework
Bare Programming Language
Hint 5: If none of the mentioned
Hint 5: If none of the mentioned
Operator SDK: Go
Resources
● Code for this presentation:
https://github.com/leszko/build-your-operator
● Operator SDK:
https://sdk.operatorframework.io/
● Java + Quarkus operator description:
https://www.instana.com/blog/writing-a-kubernetes-operator-in-jav
a-part-1/
● KOPF (Kubernetes Operators Framework):
https://kopf.readthedocs.io/en/stable/
Thank You!
Rafał Leszko
@RafalLeszko
rafalleszko.com
1 of 92

Recommended

Manage Pulsar Cluster Lifecycles with Kubernetes Operators - Pulsar Summit NA... by
Manage Pulsar Cluster Lifecycles with Kubernetes Operators - Pulsar Summit NA...Manage Pulsar Cluster Lifecycles with Kubernetes Operators - Pulsar Summit NA...
Manage Pulsar Cluster Lifecycles with Kubernetes Operators - Pulsar Summit NA...StreamNative
559 views35 slides
The Kubernetes Effect by
The Kubernetes EffectThe Kubernetes Effect
The Kubernetes EffectBilgin Ibryam
6.1K views33 slides
Optimizing {Java} Application Performance on Kubernetes by
Optimizing {Java} Application Performance on KubernetesOptimizing {Java} Application Performance on Kubernetes
Optimizing {Java} Application Performance on KubernetesDinakar Guniguntala
422 views15 slides
AWS Lambda and serverless Java | DevNation Live by
AWS Lambda and serverless Java | DevNation LiveAWS Lambda and serverless Java | DevNation Live
AWS Lambda and serverless Java | DevNation LiveRed Hat Developers
7.3K views26 slides
Serverless and Servicefull Applications - Where Microservices complements Ser... by
Serverless and Servicefull Applications - Where Microservices complements Ser...Serverless and Servicefull Applications - Where Microservices complements Ser...
Serverless and Servicefull Applications - Where Microservices complements Ser...Red Hat Developers
1.9K views47 slides
Docker+java by
Docker+javaDocker+java
Docker+javaDPC Consulting Ltd
1.2K views30 slides

More Related Content

What's hot

Microservices and modularity with java by
Microservices and modularity with javaMicroservices and modularity with java
Microservices and modularity with javaDPC Consulting Ltd
1.2K views48 slides
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis... by
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...Oleg Shalygin
2.1K views31 slides
Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet... by
Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet...Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet...
Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet...Jakob Karalus
582 views21 slides
The Kubernetes Operator Pattern - ContainerConf Nov 2017 by
The Kubernetes Operator Pattern - ContainerConf Nov 2017The Kubernetes Operator Pattern - ContainerConf Nov 2017
The Kubernetes Operator Pattern - ContainerConf Nov 2017Jakob Karalus
3.2K views24 slides
Cloud Native User Group: Shift-Left Testing IaC With PaC by
Cloud Native User Group: Shift-Left Testing IaC With PaCCloud Native User Group: Shift-Left Testing IaC With PaC
Cloud Native User Group: Shift-Left Testing IaC With PaCsmalltown
657 views53 slides
Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019 by
Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019
Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019confluent
4K views117 slides

What's hot(20)

GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis... by Oleg Shalygin
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
GCP - Continuous Integration and Delivery into Kubernetes with GitHub, Travis...
Oleg Shalygin2.1K views
Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet... by Jakob Karalus
Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet...Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet...
Managing Stateful Services with the Operator Pattern in Kubernetes - Kubernet...
Jakob Karalus582 views
The Kubernetes Operator Pattern - ContainerConf Nov 2017 by Jakob Karalus
The Kubernetes Operator Pattern - ContainerConf Nov 2017The Kubernetes Operator Pattern - ContainerConf Nov 2017
The Kubernetes Operator Pattern - ContainerConf Nov 2017
Jakob Karalus3.2K views
Cloud Native User Group: Shift-Left Testing IaC With PaC by smalltown
Cloud Native User Group: Shift-Left Testing IaC With PaCCloud Native User Group: Shift-Left Testing IaC With PaC
Cloud Native User Group: Shift-Left Testing IaC With PaC
smalltown 657 views
Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019 by confluent
Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019
Kafka on Kubernetes: Keeping It Simple (Nikki Thean, Etsy) Kafka Summit SF 2019
confluent4K views
KUBEBOOT - SPRING BOOT DEPLOYMENT ON KUBERNETES HAS NEVER BEEN SO EASY by Red Hat Developers
KUBEBOOT - SPRING BOOT DEPLOYMENT ON KUBERNETES HAS NEVER BEEN SO EASYKUBEBOOT - SPRING BOOT DEPLOYMENT ON KUBERNETES HAS NEVER BEEN SO EASY
KUBEBOOT - SPRING BOOT DEPLOYMENT ON KUBERNETES HAS NEVER BEEN SO EASY
Red Hat Developers6.1K views
Spark day 2017 - Spark on Kubernetes by Yousun Jeong
Spark day 2017 - Spark on KubernetesSpark day 2017 - Spark on Kubernetes
Spark day 2017 - Spark on Kubernetes
Yousun Jeong2.6K views
Creating a Kubernetes Operator in Java by Rudy De Busscher
Creating a Kubernetes Operator in JavaCreating a Kubernetes Operator in Java
Creating a Kubernetes Operator in Java
Rudy De Busscher140 views
Simple tweaks to get the most out of your JVM by Jamie Coleman
Simple tweaks to get the most out of your JVMSimple tweaks to get the most out of your JVM
Simple tweaks to get the most out of your JVM
Jamie Coleman140 views
Cache first cloud native microservices by Mesut Celik
Cache first cloud native microservicesCache first cloud native microservices
Cache first cloud native microservices
Mesut Celik164 views
Webcast - Making kubernetes production ready by Applatix
Webcast - Making kubernetes production readyWebcast - Making kubernetes production ready
Webcast - Making kubernetes production ready
Applatix1.5K views
Architectural patterns for caching microservices by Rafał Leszko
Architectural patterns for caching microservicesArchitectural patterns for caching microservices
Architectural patterns for caching microservices
Rafał Leszko216 views
2016 08-30 Kubernetes talk for Waterloo DevOps by craigbox
2016 08-30 Kubernetes talk for Waterloo DevOps2016 08-30 Kubernetes talk for Waterloo DevOps
2016 08-30 Kubernetes talk for Waterloo DevOps
craigbox613 views
DCEU 18: Docker Container Networking by Docker, Inc.
DCEU 18: Docker Container NetworkingDCEU 18: Docker Container Networking
DCEU 18: Docker Container Networking
Docker, Inc.821 views
Friends don't let friends do dual writes: Outbox pattern with OpenShift Strea... by Red Hat Developers
Friends don't let friends do dual writes: Outbox pattern with OpenShift Strea...Friends don't let friends do dual writes: Outbox pattern with OpenShift Strea...
Friends don't let friends do dual writes: Outbox pattern with OpenShift Strea...
Red Hat Developers8.8K views

Similar to Build your operator with the right tool

Build Your Kubernetes Operator with the Right Tool! by
Build Your Kubernetes Operator with the Right Tool!Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!Rafał Leszko
193 views92 slides
Openshift operator insight by
Openshift operator insightOpenshift operator insight
Openshift operator insightRyan ZhangCheng
50 views81 slides
Kubernetes - training micro-dragons without getting burnt by
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burntAmir Moghimi
952 views22 slides
DCEU 18: Docker Containers in a Serverless World by
DCEU 18: Docker Containers in a Serverless WorldDCEU 18: Docker Containers in a Serverless World
DCEU 18: Docker Containers in a Serverless WorldDocker, Inc.
437 views34 slides
DevEx | there’s no place like k3s by
DevEx | there’s no place like k3sDevEx | there’s no place like k3s
DevEx | there’s no place like k3sHaggai Philip Zagury
236 views36 slides
Scaling docker with kubernetes by
Scaling docker with kubernetesScaling docker with kubernetes
Scaling docker with kubernetesLiran Cohen
2.4K views79 slides

Similar to Build your operator with the right tool(20)

Build Your Kubernetes Operator with the Right Tool! by Rafał Leszko
Build Your Kubernetes Operator with the Right Tool!Build Your Kubernetes Operator with the Right Tool!
Build Your Kubernetes Operator with the Right Tool!
Rafał Leszko193 views
Kubernetes - training micro-dragons without getting burnt by Amir Moghimi
Kubernetes -  training micro-dragons without getting burntKubernetes -  training micro-dragons without getting burnt
Kubernetes - training micro-dragons without getting burnt
Amir Moghimi952 views
DCEU 18: Docker Containers in a Serverless World by Docker, Inc.
DCEU 18: Docker Containers in a Serverless WorldDCEU 18: Docker Containers in a Serverless World
DCEU 18: Docker Containers in a Serverless World
Docker, Inc.437 views
Scaling docker with kubernetes by Liran Cohen
Scaling docker with kubernetesScaling docker with kubernetes
Scaling docker with kubernetes
Liran Cohen2.4K views
Kubernetes: The Next Research Platform by Bob Killen
Kubernetes: The Next Research PlatformKubernetes: The Next Research Platform
Kubernetes: The Next Research Platform
Bob Killen1.9K views
I Just Want to Run My Code: Waypoint, Nomad, and Other Things by Michael Lange
I Just Want to Run My Code: Waypoint, Nomad, and Other ThingsI Just Want to Run My Code: Waypoint, Nomad, and Other Things
I Just Want to Run My Code: Waypoint, Nomad, and Other Things
Michael Lange35 views
K8s in 3h - Kubernetes Fundamentals Training by Piotr Perzyna
K8s in 3h - Kubernetes Fundamentals TrainingK8s in 3h - Kubernetes Fundamentals Training
K8s in 3h - Kubernetes Fundamentals Training
Piotr Perzyna397 views
Get you Java application ready for Kubernetes ! by Anthony Dahanne
Get you Java application ready for Kubernetes !Get you Java application ready for Kubernetes !
Get you Java application ready for Kubernetes !
Anthony Dahanne955 views
Kubernetes: training micro-dragons for a serious battle by Amir Moghimi
Kubernetes: training micro-dragons for a serious battleKubernetes: training micro-dragons for a serious battle
Kubernetes: training micro-dragons for a serious battle
Amir Moghimi485 views
AWS ElasticBeanstalk and Docker by kloia
AWS ElasticBeanstalk and Docker AWS ElasticBeanstalk and Docker
AWS ElasticBeanstalk and Docker
kloia675 views
Exploring MySQL Operator for Kubernetes in Python by Ivan Ma
Exploring MySQL Operator for Kubernetes in PythonExploring MySQL Operator for Kubernetes in Python
Exploring MySQL Operator for Kubernetes in Python
Ivan Ma36 views
Cloud-native applications with Java and Kubernetes - Yehor Volkov by Kuberton
 Cloud-native applications with Java and Kubernetes - Yehor Volkov Cloud-native applications with Java and Kubernetes - Yehor Volkov
Cloud-native applications with Java and Kubernetes - Yehor Volkov
Kuberton393 views
From development environments to production deployments with Docker, Compose,... by Jérôme Petazzoni
From development environments to production deployments with Docker, Compose,...From development environments to production deployments with Docker, Compose,...
From development environments to production deployments with Docker, Compose,...
Jérôme Petazzoni33K views
Introduction to JIB and Google Cloud Run by Saiyam Pathak
Introduction to JIB and Google Cloud RunIntroduction to JIB and Google Cloud Run
Introduction to JIB and Google Cloud Run
Saiyam Pathak335 views
Kubernetes for the PHP developer by Paul Czarkowski
Kubernetes for the PHP developerKubernetes for the PHP developer
Kubernetes for the PHP developer
Paul Czarkowski362 views
Knative build for open whisk runtimes phase 1 - 2018-02-20 by Matt Rutkowski
Knative build for open whisk runtimes   phase 1 - 2018-02-20Knative build for open whisk runtimes   phase 1 - 2018-02-20
Knative build for open whisk runtimes phase 1 - 2018-02-20
Matt Rutkowski142 views
ILM - Pipeline in the cloud by Aaron Carey
ILM - Pipeline in the cloudILM - Pipeline in the cloud
ILM - Pipeline in the cloud
Aaron Carey10.6K views
Scala, docker and testing, oh my! mario camou by J On The Beach
Scala, docker and testing, oh my! mario camouScala, docker and testing, oh my! mario camou
Scala, docker and testing, oh my! mario camou
J On The Beach2.8K views

More from Rafał Leszko

Mutation Testing with PIT by
Mutation Testing with PITMutation Testing with PIT
Mutation Testing with PITRafał Leszko
163 views122 slides
Distributed Locking in Kubernetes by
Distributed Locking in KubernetesDistributed Locking in Kubernetes
Distributed Locking in KubernetesRafał Leszko
2K views90 slides
Architectural patterns for high performance microservices in kubernetes by
Architectural patterns for high performance microservices in kubernetesArchitectural patterns for high performance microservices in kubernetes
Architectural patterns for high performance microservices in kubernetesRafał Leszko
377 views90 slides
Architectural caching patterns for kubernetes by
Architectural caching patterns for kubernetesArchitectural caching patterns for kubernetes
Architectural caching patterns for kubernetesRafał Leszko
447 views88 slides
Mutation testing with PIT by
Mutation testing with PITMutation testing with PIT
Mutation testing with PITRafał Leszko
140 views122 slides
[jLove 2020] Where is my cache architectural patterns for caching microservi... by
[jLove 2020] Where is my cache  architectural patterns for caching microservi...[jLove 2020] Where is my cache  architectural patterns for caching microservi...
[jLove 2020] Where is my cache architectural patterns for caching microservi...Rafał Leszko
203 views86 slides

More from Rafał Leszko(20)

Mutation Testing with PIT by Rafał Leszko
Mutation Testing with PITMutation Testing with PIT
Mutation Testing with PIT
Rafał Leszko163 views
Distributed Locking in Kubernetes by Rafał Leszko
Distributed Locking in KubernetesDistributed Locking in Kubernetes
Distributed Locking in Kubernetes
Rafał Leszko2K views
Architectural patterns for high performance microservices in kubernetes by Rafał Leszko
Architectural patterns for high performance microservices in kubernetesArchitectural patterns for high performance microservices in kubernetes
Architectural patterns for high performance microservices in kubernetes
Rafał Leszko377 views
Architectural caching patterns for kubernetes by Rafał Leszko
Architectural caching patterns for kubernetesArchitectural caching patterns for kubernetes
Architectural caching patterns for kubernetes
Rafał Leszko447 views
Mutation testing with PIT by Rafał Leszko
Mutation testing with PITMutation testing with PIT
Mutation testing with PIT
Rafał Leszko140 views
[jLove 2020] Where is my cache architectural patterns for caching microservi... by Rafał Leszko
[jLove 2020] Where is my cache  architectural patterns for caching microservi...[jLove 2020] Where is my cache  architectural patterns for caching microservi...
[jLove 2020] Where is my cache architectural patterns for caching microservi...
Rafał Leszko203 views
Where is my cache architectural patterns for caching microservices by example by Rafał Leszko
Where is my cache  architectural patterns for caching microservices by exampleWhere is my cache  architectural patterns for caching microservices by example
Where is my cache architectural patterns for caching microservices by example
Rafał Leszko357 views
Architectural caching patterns for kubernetes by Rafał Leszko
Architectural caching patterns for kubernetesArchitectural caching patterns for kubernetes
Architectural caching patterns for kubernetes
Rafał Leszko258 views
5 levels of high availability from multi instance to hybrid cloud by Rafał Leszko
5 levels of high availability  from multi instance to hybrid cloud5 levels of high availability  from multi instance to hybrid cloud
5 levels of high availability from multi instance to hybrid cloud
Rafał Leszko155 views
Where is my cache? Architectural patterns for caching microservices by example by Rafał Leszko
Where is my cache? Architectural patterns for caching microservices by exampleWhere is my cache? Architectural patterns for caching microservices by example
Where is my cache? Architectural patterns for caching microservices by example
Rafał Leszko460 views
5 Levels of High Availability: From Multi-instance to Hybrid Cloud by Rafał Leszko
5 Levels of High Availability: From Multi-instance to Hybrid Cloud5 Levels of High Availability: From Multi-instance to Hybrid Cloud
5 Levels of High Availability: From Multi-instance to Hybrid Cloud
Rafał Leszko516 views
Where is my cache architectural patterns for caching microservices by example by Rafał Leszko
Where is my cache architectural patterns for caching microservices by exampleWhere is my cache architectural patterns for caching microservices by example
Where is my cache architectural patterns for caching microservices by example
Rafał Leszko92 views
Where is my cache architectural patterns for caching microservices by example by Rafał Leszko
Where is my cache architectural patterns for caching microservices by exampleWhere is my cache architectural patterns for caching microservices by example
Where is my cache architectural patterns for caching microservices by example
Rafał Leszko728 views
Where is my cache? Architectural patterns for caching microservices by example by Rafał Leszko
Where is my cache? Architectural patterns for caching microservices by exampleWhere is my cache? Architectural patterns for caching microservices by example
Where is my cache? Architectural patterns for caching microservices by example
Rafał Leszko556 views
[DevopsDays India 2019] Where is my cache? Architectural patterns for caching... by Rafał Leszko
[DevopsDays India 2019] Where is my cache? Architectural patterns for caching...[DevopsDays India 2019] Where is my cache? Architectural patterns for caching...
[DevopsDays India 2019] Where is my cache? Architectural patterns for caching...
Rafał Leszko344 views
Where is my cache? Architectural patterns for caching microservices by example by Rafał Leszko
Where is my cache? Architectural patterns for caching microservices by exampleWhere is my cache? Architectural patterns for caching microservices by example
Where is my cache? Architectural patterns for caching microservices by example
Rafał Leszko510 views
Stream Processing in the Cloud - Athens Kubernetes Meetup 16.07.2019 by Rafał Leszko
Stream Processing in the Cloud - Athens Kubernetes Meetup 16.07.2019Stream Processing in the Cloud - Athens Kubernetes Meetup 16.07.2019
Stream Processing in the Cloud - Athens Kubernetes Meetup 16.07.2019
Rafał Leszko138 views
Stream Processing with Hazelcast Jet - Voxxed Days Thessaloniki 19.11.2018 by Rafał Leszko
Stream Processing with Hazelcast Jet - Voxxed Days Thessaloniki 19.11.2018Stream Processing with Hazelcast Jet - Voxxed Days Thessaloniki 19.11.2018
Stream Processing with Hazelcast Jet - Voxxed Days Thessaloniki 19.11.2018
Rafał Leszko1K views
Mutation Testing - Voxxed Days Cluj-Napoca 2017 by Rafał Leszko
Mutation Testing - Voxxed Days Cluj-Napoca 2017Mutation Testing - Voxxed Days Cluj-Napoca 2017
Mutation Testing - Voxxed Days Cluj-Napoca 2017
Rafał Leszko206 views
Continuous Delivery - Voxxed Days Cluj-Napoca 2017 by Rafał Leszko
Continuous Delivery - Voxxed Days Cluj-Napoca 2017Continuous Delivery - Voxxed Days Cluj-Napoca 2017
Continuous Delivery - Voxxed Days Cluj-Napoca 2017
Rafał Leszko261 views

Recently uploaded

Quality Assurance by
Quality Assurance Quality Assurance
Quality Assurance interworksoftware2
8 views6 slides
Winter Projects GDSC IITK by
Winter Projects GDSC IITKWinter Projects GDSC IITK
Winter Projects GDSC IITKSahilSingh368445
416 views60 slides
aATP - New Correlation Confirmation Feature.pptx by
aATP - New Correlation Confirmation Feature.pptxaATP - New Correlation Confirmation Feature.pptx
aATP - New Correlation Confirmation Feature.pptxEsatEsenek1
222 views6 slides
tecnologia18.docx by
tecnologia18.docxtecnologia18.docx
tecnologia18.docxnosi6702
6 views5 slides
What is API by
What is APIWhat is API
What is APIartembondar5
15 views15 slides
Ports-and-Adapters Architecture for Embedded HMI by
Ports-and-Adapters Architecture for Embedded HMIPorts-and-Adapters Architecture for Embedded HMI
Ports-and-Adapters Architecture for Embedded HMIBurkhard Stubert
35 views19 slides

Recently uploaded(20)

aATP - New Correlation Confirmation Feature.pptx by EsatEsenek1
aATP - New Correlation Confirmation Feature.pptxaATP - New Correlation Confirmation Feature.pptx
aATP - New Correlation Confirmation Feature.pptx
EsatEsenek1222 views
tecnologia18.docx by nosi6702
tecnologia18.docxtecnologia18.docx
tecnologia18.docx
nosi67026 views
Ports-and-Adapters Architecture for Embedded HMI by Burkhard Stubert
Ports-and-Adapters Architecture for Embedded HMIPorts-and-Adapters Architecture for Embedded HMI
Ports-and-Adapters Architecture for Embedded HMI
Burkhard Stubert35 views
Google Solutions Challenge 2024 Talk pdf by MohdAbdulAleem4
Google Solutions Challenge 2024 Talk pdfGoogle Solutions Challenge 2024 Talk pdf
Google Solutions Challenge 2024 Talk pdf
MohdAbdulAleem434 views
Top-5-production-devconMunich-2023-v2.pptx by Tier1 app
Top-5-production-devconMunich-2023-v2.pptxTop-5-production-devconMunich-2023-v2.pptx
Top-5-production-devconMunich-2023-v2.pptx
Tier1 app9 views
How to build dyanmic dashboards and ensure they always work by Wiiisdom
How to build dyanmic dashboards and ensure they always workHow to build dyanmic dashboards and ensure they always work
How to build dyanmic dashboards and ensure they always work
Wiiisdom16 views
University of Borås-full talk-2023-12-09.pptx by Mahdi_Fahmideh
University of Borås-full talk-2023-12-09.pptxUniversity of Borås-full talk-2023-12-09.pptx
University of Borås-full talk-2023-12-09.pptx
Mahdi_Fahmideh12 views
Bootstrapping vs Venture Capital.pptx by Zeljko Svedic
Bootstrapping vs Venture Capital.pptxBootstrapping vs Venture Capital.pptx
Bootstrapping vs Venture Capital.pptx
Zeljko Svedic16 views
predicting-m3-devopsconMunich-2023.pptx by Tier1 app
predicting-m3-devopsconMunich-2023.pptxpredicting-m3-devopsconMunich-2023.pptx
predicting-m3-devopsconMunich-2023.pptx
Tier1 app10 views
Supercharging your Python Development Environment with VS Code and Dev Contai... by Dawn Wages
Supercharging your Python Development Environment with VS Code and Dev Contai...Supercharging your Python Development Environment with VS Code and Dev Contai...
Supercharging your Python Development Environment with VS Code and Dev Contai...
Dawn Wages5 views

Build your operator with the right tool

  • 1. Build Your Operator With the Right Tool Rafał Leszko @RafalLeszko rafalleszko.com Hazelcast
  • 2. About me ● Integration Team Lead at Hazelcast ● Worked at Google and CERN ● Author of the book "Continuous Delivery with Docker and Jenkins" ● Trainer and conference speaker ● Live in Kraków, Poland
  • 3. About Hazelcast ● Distributed Company ● Open Source Software ● 140+ Employees ● Products: ○ Hazelcast IMDG ○ Hazelcast Jet ○ Hazelcast Cloud @Hazelcast
  • 4. ● Introduction ● Tools for building Operators ○ Operator SDK ■ Helm ■ Ansible ■ Go ○ Operator Frameworks: KOPF, Java Operator SDK, ... ○ Bare Programming Language: Java, Kotlin, C#, ... ● Summary Agenda
  • 7. Kubernetes Operator Operator is an application that watches a custom Kubernetes resource and performs some operations upon its changes.
  • 8. apiVersion: hazelcast.my.domain/v1 kind: Hazelcast metadata: name: hazelcast-sample spec: size: 1 Resource (hazelcast.yaml)
  • 9. apiVersion: hazelcast.my.domain/v1 kind: Hazelcast metadata: name: hazelcast-sample spec: size: 1 $ kubectl apply -f hazelcast.yaml Resource (hazelcast.yaml)
  • 12. Operator Similarities Step 1: Implement the operator logic
  • 13. Operator Similarities Step 1: Implement the operator logic Step 2: Dockerize your operator $ docker build -t <user>/hazelcast-operator . $ docker push <user>/hazelcast-operator
  • 14. Operator Similarities Step 1: Implement the operator logic Step 2: Dockerize your operator $ docker build -t <user>/hazelcast-operator . $ docker push <user>/hazelcast-operator Step 3: Create CRD (Custom Resource Definition) $ kubectl apply -f hazelast.crd.yaml
  • 16. Operator Similarities Step 4: Create RBAC (Role and Role Binding) $ kubectl apply -f role.yaml $ kubectl apply -f role_binding.yaml
  • 17. Operator Similarities Step 4: Create RBAC (Role and Role Binding) $ kubectl apply -f role.yaml $ kubectl apply -f role_binding.yaml Step 5: Deploy the operator $ kubectl apply -f operator.yaml
  • 18. Operator Similarities Step 4: Create RBAC (Role and Role Binding) $ kubectl apply -f role.yaml $ kubectl apply -f role_binding.yaml Step 5: Deploy the operator $ kubectl apply -f operator.yaml Step 6: Create your custom resource $ kubectl apply -f hazelcast.yaml
  • 19. Operator Similarities Step 1: Implement the operator logic Step 2: Dockerize your operator Step 3: Create CRD (Custom Resource Definition) Step 4: Create RBAC (Role and Role Binding) Step 5: Deploy the operator Step 6: Create your custom resource
  • 20. ● Introduction ✔ ● Tools for building Operators ○ Operator SDK ■ Helm ■ Ansible ■ Go ○ Operator Frameworks: KOPF, Java Operator SDK, ... ○ Bare Programming Language: Java, Kotlin, C#, ... ● Summary Agenda
  • 22. Helm is a package manager for Kubernetes. It allows you to: ● create templated Kubernetes configurations ● package them into a Helm chart ● render them using parameters defined in values.yaml
  • 23. Helm: Create Helm Chart $ helm create chart # chart/templates/deployment.yaml apiVersion: apps/v1 kind: Deployment metadata: name: {{ include "hazelcast.fullname" . }} spec: replicas: {{ .Values.size }} selector: matchLabels: app: hazelcast # chart/values.yaml size: 1 template: metadata: labels: app: hazelcast spec: containers: - name: hazelcast image: "hazelcast/hazelcast"
  • 24. Generate Hazelcast Operator $ operator-sdk init --plugins=helm $ operator-sdk create api --group=hazelcast --version=v1 --helm-chart=./chart Common Operator Steps: build, install, and use $ docker build -t <user>/hazelcast-operator . $ docker push <user>/hazelcast-operator $ make install $ make deploy IMG=<user>/hazelcast-operator $ kubectl apply -f config/samples/hazelcast_v1_hazelcast.yaml Helm: Generate Operator
  • 25. Operator SDK: Operator Capability Levels
  • 26. What does "Operator SDK: Helm" mean to You? ● Implementation is declarative and simple ● If you already have a Helm chart, then no work at all ● Limited to the features available in Helm ● Operator manifest/configuration files are automatically generated
  • 28. Ansible is a very powerful tool for IT automation. It allows you to: ● create tasks in a declarative way ● perform complex DevOps tasks using simple YAML files ● interact with Kubernetes API using the community.kubernetes.k8s plugin
  • 29. Ansible: Create Operator # roles/hazelcast/tasks/main.yml --- - name: start hazelcast community.kubernetes.k8s: definition: kind: Deployment apiVersion: apps/v1 metadata: name: hazelcast namespace: '{{ansible_operator_meta.namespace}}' spec: replicas: "{{size}}" selector: matchLabels: app: hazelcast template: metadata: labels: app: hazelcast spec: containers: - name: hazelcast image: "hazelcast/hazelcast" $ operator-sdk init --plugins=ansible $ operator-sdk create api --group hazelcast --version v1 --kind Hazelcast --generate-role
  • 30. Common Operator Steps: build, install, and use $ docker build -t <user>/hazelcast-operator . $ docker push <user>/hazelcast-operator $ make install $ make deploy IMG=<user>/hazelcast-operator $ kubectl apply -f config/samples/hazelcast_v1_hazelcast.yaml Ansible: Build, Install, Use Operator
  • 31. Operator SDK: Operator Capability Levels
  • 32. What does "Operator SDK: Ansible" mean to You? ● Implementation is declarative and therefore concise and human-readable ● YAML configuration is executed via the community.kubernetes.k8s plugin ● Ansible covers all capability levels ● Operator manifest/configuration files are automatically generated
  • 34. Go is a general-purpose programming language. Advantages: ● Kubernete is written in Go ● good Kubernetes client library ● performance
  • 35. Go: Create Operator // controllers/hazelcast_controller.go // +kubebuilder:rbac:groups=hazelcast.my.domain,resources=hazelcasts,verbs=get;list… func (r *HazelcastReconciler) Reconcile(req ctrl.Request) (ctrl.Result, error) { ... hazelcast := &hazelcastv1.Hazelcast{} err := r.Get(ctx, req.NamespacedName, hazelcast) ... found := &appsv1.Deployment{} err = r.Get(ctx, types.NamespacedName{Name: hazelcast.Name, Namespace: hazelcast.Namespace}, found) if err != nil && errors.IsNotFound(err) { dep := r.deploymentForHazelcast(hazelcast) } ... } $ operator-sdk init --repo=github.com/<user>/hazelcast-operator $ operator-sdk create api --version v1 --group=hazelcast --kind Hazelcast --resource=true --controller=true
  • 36. Go: Create Operator // controllers/hazelcast_controller.go ... Spec: appsv1.DeploymentSpec{ Replicas: &replicas, Selector: &metav1.LabelSelector{ MatchLabels: ls, }, Template: corev1.PodTemplateSpec{ ObjectMeta: metav1.ObjectMeta{ Labels: ls, }, Spec: corev1.PodSpec{ Containers: []corev1.Container{{ Image: "hazelcast/hazelcast", Name: "hazelcast", }}, }, }, }, } // api/v1/hazelcast_types.go type HazelcastSpec struct { Size int32 `json:"size,omitempty"` }
  • 37. Common Operator Steps: build, install, and use $ docker build -t <user>/hazelcast-operator . $ docker push <user>/hazelcast-operator $ make install $ make deploy IMG=<user>/hazelcast-operator $ kubectl apply -f config/samples/hazelcast_v1_hazelcast.yaml Go: Build, Install, Use Operator
  • 38. What does "Operator SDK: Go" mean to You? ● Implementation is imperative and requires more work and caution ● Go language is well integrated with Kubernetes ● No limits on the functionality ● Operator boilerplate files are automatically generated
  • 39. ● Introduction ✔ ● Tools for building Operators ○ Operator SDK ✔ ■ Helm ✔ ■ Ansible ✔ ■ Go ✔ ○ Operator Frameworks: KOPF, Java Operator SDK, ... ○ Bare Programming Language: Java, Kotlin, C#, ... ● Summary Agenda
  • 41. KOPF C# Operator SDK Java Operator SDK NodeJS Operator Framework Roperator
  • 42. KOPF C# Operator SDK Java Operator SDK NodeJS Operator Framework Roperator
  • 43. KOPF C# Operator SDK Java Operator SDK NodeJS Operator Framework Roperator
  • 44. KOPF C# Operator SDK Java Operator SDK NodeJS Operator Framework Roperator
  • 45. KOPF: Create Operator 1. Implement configuration and manifest files ● Dockerfile ● hazelcast.crd.yaml ● role.yaml, role_binding.yaml ● operator.yaml ● hazelcast.yaml 2: Implement operator logic in operator.py
  • 46. KOPF: Create Operator @kopf.on.create('hazelcast.my.domain','v1','hazelcasts') def create_fn(spec, **kwargs): doc = create_deployment(spec) kopf.adopt(doc) api = pykube.HTTPClient(pykube.KubeConfig.from_env()) deployment = pykube.Deployment(api, doc) deployment.create() api.session.close() return {'children': [deployment.metadata['uid']]} def create_deployment(spec): return yaml.safe_load(f""" apiVersion: apps/v1 kind: Deployment metadata: name: hazelcast spec: replicas: {spec.get('size', 1)} selector: matchLabels: app: hazelcast template: metadata: labels: app: hazelcast spec: containers: - name: hazelcast image: "hazelcast/hazelcast" """)
  • 47. Common Operator Steps: build, install, and use $ docker build -t <user>/hazelcast-operator . $ docker push <user>/hazelcast-operator $ kubectl apply -f hazelcast.crd.yaml $ kubectl apply -f role.yaml $ kubectl apply -f role_binding.yaml $ kubectl apply -f operator.yaml $ kubectl apply -f hazelcast.yaml KOPF: Build, Install, Use Operator
  • 48. What does "Operator Framework" mean to You? ● Less developed and popular than Operator SDK ● No project scaffolding and boilerplate code generation ● No limits on the functionality ● Kubernetes clients are usually inferior to the Go Kubernetes client
  • 49. ● Introduction ✔ ● Tools for building Operators ○ Operator SDK ✔ ■ Helm ✔ ■ Ansible ✔ ■ Go ✔ ○ Operator Frameworks: KOPF, Java Operator SDK, … ✔ ○ Bare Programming Language: Java, Kotlin, C#, ... ● Summary Agenda
  • 52. Java + Quarkus: Create Operator 1. Implement configuration and manifest files ● hazelcast.crd.yaml ● role.yaml, role_binding.yaml ● operator.yaml ● hazelcast.yaml 2: Implement Java classes with the operator logic
  • 53. Java + Quarkus: Create Operator List hazelcastDeployments = client.apps().deployments().list().getItems().stream() .filter(ownerRefMatches) .collect(toList()); if (hazelcastDeployments.isEmpty()) { client.apps().deployments().create(newDeployment(resource)); } else { for (Deployment deployment : hazelcastDeployments) { setSize(deployment, resource); client.apps().deployments().createOrReplace(deployment); } }
  • 54. Java + Quarkus: Create Operator public class ClientProvider { @Produces @Singleton @Named("namespace") private String findNamespace() throws IOException { return new String(Files.readAllBytes(Paths.get("/var/run/secrets/kubernetes.io/serviceaccount/namespace"))); } @Produces @Singleton KubernetesClient newClient(@Named("namespace") String namespace) { return new DefaultKubernetesClient().inNamespace(namespace); } @Produces @Singleton NonNamespaceOperation<HazelcastResource, HazelcastResourceList, HazelcastResourceDoneable, Resource<HazelcastResource, HazelcastResourceDoneable>> makeCustomResourceClient( KubernetesClient defaultClient, @Named("namespace") String namespace) { KubernetesDeserializer.registerCustomKind("hazelcast.my.domain/v1", "Hazelcast", HazelcastResource.class); CustomResourceDefinition crd = defaultClient .customResourceDefinitions() .list() .getItems() .stream() .filter(d -> "hazelcasts.hazelcast.my.domain".equals(d.getMetadata().getName())) .findAny() .orElseThrow( () -> new RuntimeException( "Deployment error: Custom resource definition "hazelcasts.hazelcast.my.domain" not found.")); return defaultClient .customResources(crd, HazelcastResource.class, HazelcastResourceList.class, HazelcastResourceDoneable.class) .inNamespace(namespace); } }
  • 55. Java + Quarkus: Create Operator @ApplicationScoped public class DeploymentInstaller { @Inject private KubernetesClient client; @Inject private HazelcastResourceCache cache; void onStartup(@Observes StartupEvent _ev) { new Thread(this::runWatch).start(); } private void runWatch() { cache.listThenWatch(this::handleEvent); } private void handleEvent(Watcher.Action action, String uid) { try { HazelcastResource resource = cache.get(uid); if (resource == null) { return; } Predicate ownerRefMatches = deployments -> deployments.getMetadata().getOwnerReferences().stream() .anyMatch(ownerReference -> ownerReference.getUid().equals(uid)); List hazelcastDeployments = client.apps().deployments().list().getItems().stream() .filter(ownerRefMatches) .collect(toList()); if (hazelcastDeployments.isEmpty()) { client.apps().deployments().create(newDeployment(resource)); } else { for (Deployment deployment : hazelcastDeployments) { setSize(deployment, resource); client.apps().deployments().createOrReplace(deployment); } } } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } private Deployment newDeployment(HazelcastResource resource) { Deployment deployment = client.apps().deployments().load(getClass().getResourceAsStream("/deployment.yaml")).get(); setSize(deployment, resource); deployment.getMetadata().getOwnerReferences().get(0).setUid(resource.getMetadata().getUid()); deployment.getMetadata().getOwnerReferences().get(0).setName(resource.getMetadata().getName()); return deployment; } private void setSize(Deployment deployment, HazelcastResource resource) { deployment.getSpec().setReplicas(resource.getSpec().getSize()); } }
  • 56. Java + Quarkus: Create Operator @ApplicationScoped public class DeploymentInstaller { @Inject private KubernetesClient client; @Inject private HazelcastResourceCache cache; void onStartup(@Observes StartupEvent _ev) { new Thread(this::runWatch).start(); } private void runWatch() { cache.listThenWatch(this::handleEvent); } private void handleEvent(Watcher.Action action, String uid) { try { HazelcastResource resource = cache.get(uid); if (resource == null) { return; } Predicate ownerRefMatches = deployments -> deployments.getMetadata().getOwnerReferences().stream() .anyMatch(ownerReference -> ownerReference.getUid().equals(uid)); List hazelcastDeployments = client.apps().deployments().list().getItems().stream() .filter(ownerRefMatches) .collect(toList()); if (hazelcastDeployments.isEmpty()) { client.apps().deployments().create(newDeployment(resource)); } else { for (Deployment deployment : hazelcastDeployments) { setSize(deployment, resource); client.apps().deployments().createOrReplace(deployment); } } } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } private Deployment newDeployment(HazelcastResource resource) { Deployment deployment = client.apps().deployments().load(getClass().getResourceAsStream("/deployment.yaml")).get(); setSize(deployment, resource); deployment.getMetadata().getOwnerReferences().get(0).setUid(resource.getMetadata().getUid()); deployment.getMetadata().getOwnerReferences().get(0).setName(resource.getMetadata().getName()); return deployment; } private void setSize(Deployment deployment, HazelcastResource resource) { deployment.getSpec().setReplicas(resource.getSpec().getSize()); } } @ApplicationScoped public class HazelcastResourceCache { private final Map<String, HazelcastResource> cache = new ConcurrentHashMap<>(); @Inject private NonNamespaceOperation<HazelcastResource, HazelcastResourceList, HazelcastResourceDoneable, Resource<HazelcastResource, HazelcastResourceDoneable>> crClient; private Executor executor = Executors.newSingleThreadExecutor(); public HazelcastResource get(String uid) { return cache.get(uid); } public void listThenWatch(BiConsumer<Watcher.Action, String> callback) { try { // list crClient .list() .getItems() .forEach(resource -> { cache.put(resource.getMetadata().getUid(), resource); String uid = resource.getMetadata().getUid(); executor.execute(() -> callback.accept(Watcher.Action.ADDED, uid)); } ); // watch crClient.watch(new Watcher() { @Override public void eventReceived(Action action, HazelcastResource resource) { try { String uid = resource.getMetadata().getUid(); if (cache.containsKey(uid)) { int knownResourceVersion = Integer.parseInt(cache.get(uid).getMetadata().getResourceVersion()); int receivedResourceVersion = Integer.parseInt(resource.getMetadata().getResourceVersion()); if (knownResourceVersion > receivedResourceVersion) { return; } } System.out.println("received " + action + " for resource " + resource); if (action == Action.ADDED || action == Action.MODIFIED) { cache.put(uid, resource); } else if (action == Action.DELETED) { cache.remove(uid); } else { System.err.println("Received unexpected " + action + " event for " + resource); System.exit(-1); } executor.execute(() -> callback.accept(action, uid)); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } @Override public void onClose(KubernetesClientException cause) { cause.printStackTrace(); System.exit(-1); } }); } catch (Exception e) { e.printStackTrace(); System.exit(-1); } } }
  • 57. Java + Quarkus: Create Operator public class HazelcastResource extends CustomResource { private HazelcastResourceSpec spec; public HazelcastResourceSpec getSpec() { return spec; } public void setSpec(HazelcastResourceSpec spec) { this.spec = spec; } @Override public String toString() { String name = getMetadata() != null ? getMetadata().getName() : "unknown"; String version = getMetadata() != null ? getMetadata().getResourceVersion() : "unknown"; return "name=" + name + " version=" + version + " value=" + spec; } }
  • 58. Java + Quarkus: Create Operator public class HazelcastResource extends CustomResource { private HazelcastResourceSpec spec; public HazelcastResourceSpec getSpec() { return spec; } public void setSpec(HazelcastResourceSpec spec) { this.spec = spec; } @Override public String toString() { String name = getMetadata() != null ? getMetadata().getName() : "unknown"; String version = getMetadata() != null ? getMetadata().getResourceVersion() : "unknown"; return "name=" + name + " version=" + version + " value=" + spec; } } public class HazelcastResourceList extends CustomResourceList<HazelcastResource> { // empty }
  • 59. Java + Quarkus: Create Operator public class HazelcastResource extends CustomResource { private HazelcastResourceSpec spec; public HazelcastResourceSpec getSpec() { return spec; } public void setSpec(HazelcastResourceSpec spec) { this.spec = spec; } @Override public String toString() { String name = getMetadata() != null ? getMetadata().getName() : "unknown"; String version = getMetadata() != null ? getMetadata().getResourceVersion() : "unknown"; return "name=" + name + " version=" + version + " value=" + spec; } } @JsonDeserialize @RegisterForReflection public class HazelcastResourceSpec { @JsonProperty("size") private Integer size; public Integer getSize() { return size; } @Override public String toString() { return "size=" + size; } } public class HazelcastResourceList extends CustomResourceList<HazelcastResource> { // empty }
  • 60. Java + Quarkus: Create Operator public class HazelcastResource extends CustomResource { private HazelcastResourceSpec spec; public HazelcastResourceSpec getSpec() { return spec; } public void setSpec(HazelcastResourceSpec spec) { this.spec = spec; } @Override public String toString() { String name = getMetadata() != null ? getMetadata().getName() : "unknown"; String version = getMetadata() != null ? getMetadata().getResourceVersion() : "unknown"; return "name=" + name + " version=" + version + " value=" + spec; } } @JsonDeserialize @RegisterForReflection public class HazelcastResourceSpec { @JsonProperty("size") private Integer size; public Integer getSize() { return size; } @Override public String toString() { return "size=" + size; } } public class HazelcastResourceDoneable extends CustomResourceDoneable<HazelcastResource> { public HazelcastResourceDoneable(HazelcastResource resource, Function<HazelcastResource, HazelcastResource> function) { super(resource, function); } } public class HazelcastResourceList extends CustomResourceList<HazelcastResource> { // empty }
  • 61. Build Docker image $ mvn package && docker build -t <user>/hazelcast-operator . Build native Docker image $ mvn package -Pnative -DskipTests -Dnative-image.docker-build=true $ docker build -t <user>/hazelcast-operator . Common Operator Steps: push, install, and use $ docker push <user>/hazelcast-operator $ kubectl apply -f hazelcast.crd.yaml $ kubectl apply -f role.yaml $ kubectl apply -f role_binding.yaml $ kubectl apply -f operator.yaml $ kubectl apply -f hazelcast.yaml Java + Quarkus: Build, Install, Use Operator
  • 62. What does "Bare Programming Language" mean to You? ● Always means writing more code ● Check if your language has a good Kubernetes client library ● No limits on the functionality ● Only reason: single programming language in your organization
  • 64. Which tool should I use for my operator?
  • 78. Hint 1: If you already have a Helm chart for your software and you don’t need any complex capability levels
  • 79. Hint 1: If you already have a Helm chart for your software and you don’t need any complex capability levels Operator SDK: Helm
  • 80. Hint 2: If you want to create your operator quickly and you don’t need any complex capability levels
  • 81. Hint 2: If you want to create your operator quickly and you don’t need any complex capability levels Operator SDK: Helm
  • 82. Hint 3: If you want complex features or/and be flexible about any future implementations
  • 83. Hint 3: If you want complex features or/and be flexible about any future implementations Operator SDK: Go
  • 84. Hint 4: If you want to keep a single programming language in your organization
  • 85. Hint 4: If you want to keep a single programming language in your organization ● If a popular Operator Framework exists for your language or/and you want to contribute to it
  • 86. Hint 4: If you want to keep a single programming language in your organization ● If a popular Operator Framework exists for your language or/and you want to contribute to it Operator Framework
  • 87. Hint 4: If you want to keep a single programming language in your organization ● If a popular Operator Framework exists for your language or/and you want to contribute to it ● If no popular Operator Framework exists for your programming language Operator Framework
  • 88. Hint 4: If you want to keep a single programming language in your organization ● If a popular Operator Framework exists for your language or/and you want to contribute to it ● If no popular Operator Framework exists for your programming language Operator Framework Bare Programming Language
  • 89. Hint 5: If none of the mentioned
  • 90. Hint 5: If none of the mentioned Operator SDK: Go
  • 91. Resources ● Code for this presentation: https://github.com/leszko/build-your-operator ● Operator SDK: https://sdk.operatorframework.io/ ● Java + Quarkus operator description: https://www.instana.com/blog/writing-a-kubernetes-operator-in-jav a-part-1/ ● KOPF (Kubernetes Operators Framework): https://kopf.readthedocs.io/en/stable/