|
3 | 3 |  |
4 | 4 | [](https://discord.com/channels/723455000604573736) |
5 | 5 |
|
6 | | -Build Kubernetes Operators in Java without hassle. Inspired |
7 | | -by [operator-sdk](https://github.com/operator-framework/operator-sdk). |
| 6 | +#Build Kubernetes Operators in Java Without Hassle |
8 | 7 |
|
9 | | -Our webpage with documentation is getting better every day: https://javaoperatorsdk.io/ |
| 8 | +## Documentation |
10 | 9 |
|
11 | | -**!! NOTE the main branch now contains source code for v2, which is under development, for actual |
12 | | -version see [v1 branch](https://github.com/java-operator-sdk/java-operator-sdk/tree/v1) !!** |
| 10 | +Documentation can be found on the **[JOSDK WebSite](https://javaoperatorsdk.io/)**. |
13 | 11 |
|
14 | | -Table of Contents |
15 | | -========== |
| 12 | +It's getting better every day! :) |
16 | 13 |
|
17 | | -1. [Features](#Features) |
18 | | -1. [Why build your own Operator?](#Why-build-your-own-Operator) |
19 | | -1. [Roadmap and Release Notes](#Roadmap-and-Release-Notes) |
20 | | -1. [Join us on Discord!](#Join-us-on-Discord) |
21 | | -1. [Usage](#Usage) |
| 14 | +## Contact us |
22 | 15 |
|
23 | | -## Features |
| 16 | +Join us on [Discord](https://discord.gg/DacEhAy) or feel free to ask any question on |
| 17 | +[Kubernetes Slack Operator Channel](https://kubernetes.slack.com/archives/CAW0GV7A5) |
| 18 | + |
| 19 | +## How to Contribute |
| 20 | + |
| 21 | +See the [contribution](https://javaoperatorsdk.io/docs/contributing) guide on the website. |
| 22 | + |
| 23 | +## What is Java Operator SDK |
| 24 | + |
| 25 | +Java Operator SDK is a higher level framework and related tooling to support writing Kubernetes Operators in Java. |
| 26 | +It makes it use to utilize best practices and patters of an Operator development. Features include: |
24 | 27 |
|
25 | 28 | * Framework for handling Kubernetes API events |
26 | 29 | * Automatic registration of Custom Resource watches |
27 | 30 | * Retry action on failure |
28 | 31 | * Smart event scheduling (only handle the latest event for the same resource) |
29 | 32 | * Handling Observed Generations automatically |
30 | | -* for all see [features](https://javaoperatorsdk.io/docs/features) section on the webpage |
31 | | - |
32 | | -Check out |
33 | | -this [blog post](https://csviri.medium.com/deep-dive-building-a-kubernetes-operator-sdk-for-java-developers-5008218822cb) |
34 | | -about the non-trivial yet common problems needed to be solved for every operator. In case you are interested how to |
35 | | -handle more complex scenarios take a look |
36 | | -on [event sources](https://csviri.medium.com/java-operator-sdk-introduction-to-event-sources-a1aab5af4b7b) |
37 | | -. |
38 | | - |
39 | | -## Why build your own Operator? |
40 | | - |
41 | | -* Infrastructure automation using the power and flexibility of Java. |
42 | | - See [blog post](https://blog.container-solutions.com/cloud-native-java-infrastructure-automation-with-kubernetes-operators) |
43 | | - . |
44 | | -* Provisioning of complex applications - avoiding Helm chart hell |
45 | | -* Integration with Cloud services - e.g. Secret stores |
46 | | -* Safer deployment of applications - only expose cluster to users by Custom Resources |
47 | | - |
48 | | -#### Overview of the 1.9.0 changes |
49 | | - |
50 | | -- The Spring Boot starters have been moved to their own repositories and are now found at: |
51 | | - - https://github.com/java-operator-sdk/operator-framework-spring-boot-starter |
52 | | - - https://github.com/java-operator-sdk/operator-framework-spring-boot-starter-test |
53 | | -- Updated Fabric8 client to version 5.4.0 |
54 | | -- It is now possible to configure the controllers to not automatically add finalizers to resources. See the `Controller` |
55 | | - annotation documentation for more details. |
56 | | -- Added the possibility to configure how many seconds the SDK will wait before terminating reconciliation threads when a |
57 | | - shut down is requested |
58 | | - |
59 | | -#### Overview of the 1.8.0 changes |
60 | | - |
61 | | -- The quarkus extension has been moved to the quarkiverse and is now found at |
62 | | - https://github.com/quarkiverse/quarkus-operator-sdk |
63 | | - |
64 | | -##### Overview of the 1.7.0 changes |
65 | | - |
66 | | -- `Doneable` classes have been removed along with all the involved complexity |
67 | | -- `Controller` annotation has been simplified: the `crdName` field has been removed as that value is computed from the |
68 | | - associated custom resource implementation |
69 | | -- Custom Resource implementation classes now need to be annotated with `Group` and `Version` |
70 | | - annotations so that they can be identified properly. Optionally, they can also be annotated with |
71 | | - `Kind` (if the name of the implementation class doesn't match the desired kind) and `Plural` if the plural version |
72 | | - cannot be automatically computed (or the default computed version doesn't match your expectations). |
73 | | -- The `CustomResource` class that needs to be extended is now parameterized with spec and status types, so you can have |
74 | | - an empty default implementation that does what you'd expect. If you don't need a status, using `Void` for the |
75 | | - associated type should work. |
76 | | -- Custom Resources that are namespace-scoped need to implement the `Namespaced` interface so that the client can |
77 | | - generate the proper URLs. This means, in particular, that `CustomResource` |
78 | | - implementations that do **not** implement `Namespaced` are considered cluster-scoped. As a consequence, |
79 | | - the `isClusterScoped` method/field has been removed from the appropriate classes (`Controller` annotation, in |
80 | | - particular) as this is now inferred from the `CustomResource` |
81 | | - type associated with your `Controller`. |
82 | | - |
83 | | -Many of these changes might not be immediately apparent but will result in `404` errors when connecting to the cluster. |
84 | | -Please check that the Custom Resource implementations are properly annotated and that the value corresponds to your CRD |
85 | | -manifest. If the namespace appear to be missing in your request URL, don't forget that namespace-scoped Custom Resources |
86 | | -need to implement the `Namescaped` interface. |
87 | | - |
88 | | -## Join us on Discord! |
89 | | - |
90 | | -[Discord Invite Link](https://discord.gg/DacEhAy) |
91 | | - |
92 | | -## Usage |
93 | | - |
94 | | -We have several simple Operators under the [smoke-test-samples](smoke-test-samples) directory: |
95 | | - |
96 | | -* *pure-java*: Minimal Operator implementation which only parses the Custom Resource and prints to stdout. Implemented |
97 | | - with and without Spring Boot support. The two samples share the common module. |
98 | | -* *spring-boot-plain*: Sample showing integration with Spring Boot. |
99 | | - |
100 | | -There are also more complete samples in the standalone [sample-operators](sample-operators): |
101 | | - |
102 | | -* *webserver*: Simple example creating an NGINX webserver from a Custom Resource containing HTML code. |
103 | | -* *mysql-schema*: Operator managing schemas in a MySQL database. |
104 | | -* *tomcat*: Operator with two controllers, managing Tomcat instances and Webapps for these. |
105 | | - |
106 | | -Add [dependency](https://search.maven.org/search?q=a:operator-framework) to your project with Maven: |
107 | | - |
108 | | -```xml |
109 | | - |
110 | | -<dependency> |
111 | | - <groupId>io.javaoperatorsdk</groupId> |
112 | | - <artifactId>operator-framework</artifactId> |
113 | | - <version>{see https://search.maven.org/search?q=a:operator-framework for latest version}</version> |
114 | | -</dependency> |
115 | | -``` |
116 | | - |
117 | | -Or alternatively with Gradle, which also requires declaring the SDK as an annotation processor to generate the mappings |
118 | | -between controllers and custom resource classes: |
119 | | - |
120 | | -```groovy |
121 | | -dependencies { |
122 | | - implementation "io.javaoperatorsdk:operator-framework:${javaOperatorVersion}" |
123 | | - annotationProcessor "io.javaoperatorsdk:operator-framework:${javaOperatorVersion}" |
124 | | -} |
125 | | -``` |
126 | | - |
127 | | -Once you've added the dependency, define a main method initializing the Operator and registering a controller. |
128 | | - |
129 | | -```java |
130 | | -public class Runner { |
131 | | - |
132 | | - public static void main(String[] args) { |
133 | | - Operator operator = new Operator(DefaultConfigurationService.instance()); |
134 | | - operator.register(new WebPageReconciler()); |
135 | | - operator.start(); |
136 | | - } |
137 | | -} |
138 | | -``` |
139 | | - |
140 | | -The Controller implements the business logic and describes all the classes needed to handle the CRD. |
141 | | - |
142 | | -```java |
143 | | - |
144 | | -@ControllerConfiguration |
145 | | -public class WebPageReconciler implements Reconciler<WebPage> { |
146 | | - |
147 | | - // Return the changed resource, so it gets updated. See javadoc for details. |
148 | | - @Override |
149 | | - public UpdateControl<WebPage> reconcile(WebPage resource, |
150 | | - Context context) { |
151 | | - // ... your logic ... |
152 | | - return UpdateControl.updateStatus(resource); |
153 | | - } |
154 | | -} |
155 | | -``` |
156 | | - |
157 | | -A sample custom resource POJO representation |
158 | | - |
159 | | -```java |
160 | | - |
161 | | -@Group("sample.javaoperatorsdk") |
162 | | -@Version("v1") |
163 | | -public class WebPage extends CustomResource<WebPageSpec, WebPageStatus> implements |
164 | | - Namespaced { |
165 | | - |
166 | | -} |
167 | | - |
168 | | -public class WebPageSpec { |
169 | | - |
170 | | - private String html; |
171 | | - |
172 | | - public String getHtml() { |
173 | | - return html; |
174 | | - } |
175 | | - |
176 | | - public void setHtml(String html) { |
177 | | - this.html = html; |
178 | | - } |
179 | | -} |
180 | | -``` |
181 | | - |
182 | | -### Deactivating CustomResource implementations validation |
183 | | - |
184 | | -The operator will, by default, query the deployed CRDs to check that the `CustomResource` |
185 | | -implementations match what is known to the cluster. This requires an additional query to the cluster and, sometimes, |
186 | | -elevated privileges for the operator to be able to read the CRDs from the cluster. This validation is mostly meant to |
187 | | -help users new to operator development get started and avoid common mistakes. Advanced users or production deployments |
188 | | -might want to skip this step. This is done by setting the `CHECK_CRD_ENV_KEY` environment variable to `false`. |
189 | | - |
190 | | -### Automatic generation of CRDs |
191 | | - |
192 | | -To automatically generate CRD manifests from your annotated Custom Resource classes, you only need to add the following |
193 | | -dependencies to your project: |
194 | | - |
195 | | -```xml |
196 | | - |
197 | | -<dependency> |
198 | | - <groupId>io.fabric8</groupId> |
199 | | - <artifactId>crd-generator-apt</artifactId> |
200 | | - <scope>provided</scope> |
201 | | -</dependency> |
202 | | -``` |
203 | | - |
204 | | -The CRD will be generated in `target/classes/META-INF/fabric8` (or in `target/test-classes/META-INF/fabric8`, if you use |
205 | | -the `test` scope) with the CRD name suffixed by the generated spec version. For example, a CR using |
206 | | -the `java-operator-sdk.io` group with a `mycrs` plural form will result in 2 files: |
207 | | - |
208 | | -- `mycrs.java-operator-sdk.io-v1.yml` |
209 | | -- `mycrs.java-operator-sdk.io-v1beta1.yml` |
210 | | - |
211 | | -**NOTE:** |
212 | | -> Quarkus users using the `quarkus-operator-sdk` extension do not need to add any extra dependency to get their CRD generated as this is handled by the extension itself. |
213 | | -
|
214 | | -### Quarkus |
215 | | - |
216 | | -A [Quarkus](https://quarkus.io) extension is also provided to ease the development of Quarkus-based operators. |
217 | | - |
218 | | -Add [this dependency](https://search.maven.org/search?q=a:quarkus-operator-sdk) |
219 | | -to your project: |
220 | | - |
221 | | -```xml |
222 | | - |
223 | | -<dependency> |
224 | | - <groupId>io.quarkiverse.operatorsdk</groupId> |
225 | | - <artifactId>quarkus-operator-sdk</artifactId> |
226 | | - <version>{see https://search.maven.org/search?q=a:quarkus-operator-sdk for latest version} |
227 | | - </version> |
228 | | -</dependency> |
229 | | -``` |
230 | | - |
231 | | -Create an Application, Quarkus will automatically create and inject a `KubernetesClient` ( |
232 | | -or `OpenShiftClient`), `Operator`, `ConfigurationService` and `ResourceController` instances that your application can |
233 | | -use. Below, you can see the minimal code you need to write to get your operator and controllers up and running: |
234 | | - |
235 | | -```java |
236 | | - |
237 | | -@QuarkusMain |
238 | | -public class QuarkusOperator implements QuarkusApplication { |
239 | | - |
240 | | - @Inject |
241 | | - Operator operator; |
242 | | - |
243 | | - public static void main(String... args) { |
244 | | - Quarkus.run(QuarkusOperator.class, args); |
245 | | - } |
246 | | - |
247 | | - @Override |
248 | | - public int run(String... args) throws Exception { |
249 | | - operator.start(); |
250 | | - Quarkus.waitForExit(); |
251 | | - return 0; |
252 | | - } |
253 | | -} |
254 | | -``` |
255 | | - |
256 | | -### Spring Boot |
257 | | - |
258 | | -You can also let Spring Boot wire your application together and automatically register the controllers. |
259 | | - |
260 | | -Add [this dependency](https://search.maven.org/search?q=a:operator-framework-spring-boot-starter) to your project: |
261 | | - |
262 | | -```xml |
263 | | - |
264 | | -<dependency> |
265 | | - <groupId>io.javaoperatorsdk</groupId> |
266 | | - <artifactId>operator-framework-spring-boot-starter</artifactId> |
267 | | - <version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for |
268 | | - latest version} |
269 | | - </version> |
270 | | -</dependency> |
271 | | -``` |
272 | | - |
273 | | -Create an Application |
274 | | - |
275 | | -```java |
276 | | - |
277 | | -@SpringBootApplication |
278 | | -public class Application { |
279 | | - |
280 | | - public static void main(String[] args) { |
281 | | - SpringApplication.run(Application.class, args); |
282 | | - } |
283 | | -} |
284 | | -``` |
285 | | - |
286 | | -#### Spring Boot test support |
| 33 | +* Support For Intelligent Error Handling |
287 | 34 |
|
288 | | -Adding the following dependency would let you mock the operator for the tests where loading the spring container is |
289 | | -necessary, but it doesn't need real access to a Kubernetes cluster. |
| 35 | +For all features and their usage see the [related section on the website](https://javaoperatorsdk.io/docs/features). |
290 | 36 |
|
291 | | -```xml |
| 37 | +## Related Projects |
292 | 38 |
|
293 | | -<dependency> |
294 | | - <groupId>io.javaoperatorsdk</groupId> |
295 | | - <artifactId>operator-framework-spring-boot-starter-test</artifactId> |
296 | | - <version>{see https://search.maven.org/search?q=a:operator-framework-spring-boot-starter for |
297 | | - latest version} |
298 | | - </version> |
299 | | -</dependency> |
300 | | -``` |
| 39 | +Operator SDK plugin: https://github.com/operator-framework/java-operator-plugins |
301 | 40 |
|
302 | | -Mock the operator: |
| 41 | +Quarkus Extension: https://github.com/quarkiverse/quarkus-operator-sdk |
303 | 42 |
|
304 | | -```java |
305 | 43 |
|
306 | | -@SpringBootTest |
307 | | -@EnableMockOperator |
308 | | -public class SpringBootStarterSampleApplicationTest { |
309 | 44 |
|
310 | | - @Test |
311 | | - void contextLoads() { |
312 | | - } |
313 | | -} |
314 | | -``` |
0 commit comments