Skip to content

Commit 34afc26

Browse files
committed
Add OSDK Helm docs
1 parent 709484b commit 34afc26

12 files changed

+513
-30
lines changed

_topic_map.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,14 @@ Distros: openshift-*
126126
Topics:
127127
- Name: Getting started with the Operator SDK
128128
File: osdk-getting-started
129-
- Name: Operator SDK CLI Reference
129+
- Name: Operators based on Helm charts
130+
File: osdk-helm
131+
- Name: Operator SDK CLI reference
130132
File: osdk-cli-reference
131133
- Name: Migrating to Operator SDK v0.1.0
132134
File: migrating-to-osdk-v0-1-0
135+
- Name: Appendices
136+
File: operators-appendices
133137
---
134138
Name: Aggregated EFK Logging
135139
Dir: logging

modules/about-operator-sdk.adoc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
//
33
// * operators/osdk-getting-started.adoc
44

5-
[id='about-opreator-sdk-{context}']
5+
[id='about-operator-sdk-{context}']
66
= About the Operator SDK
77

88
The link:https://coreos.com/operators/[Operator Framework] is an open source

modules/building-memcached-operator-using-osdk.adoc

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,9 @@ using tools and libraries provided by the SDK.
1818

1919
- Operator SDK CLI installed on the development workstation
2020
- Operator Lifecycle Manager (OLM) installed on a Kubernetes-based cluster (v1.8
21-
or above to support the `apps/v1beta2` API group), for example {product-title}
22-
3.11 with Technology Preview OLM enabled
23-
- Access to the cluster using an account with cluster-admin permissions
24-
- link:https://kubernetes.io/docs/tasks/tools/install-kubectl/[`kubectl`] v1.11.0+
21+
or above to support the `apps/v1beta2` API group), for example {product-title} 4.0
22+
- Access to the cluster using an account with `cluster-admin` permissions
23+
- link:https://kubernetes.io/docs/tasks/tools/install-kubectl/[`kubectl`] v1.11.3+
2524
(can alternatively use `oc`)
2625

2726
.Procedure
@@ -38,7 +37,7 @@ $ cd memcached-operator
3837
+
3938
[TIP]
4039
====
41-
See xref:operator-project-scaffolding-layout_osdk-getting-started[Appendices] to
40+
See xref:operators-appendices.adoc#operator-project-scaffolding-layout_operator-appendices[Appendices] to
4241
learn about the project directory structure created by the previous commands.
4342
====
4443

Lines changed: 350 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,350 @@
1+
// Module included in the following assemblies:
2+
//
3+
// * operators/osdk-helm.adoc
4+
5+
[id='building-operator-with-helm-using-osdk_{context}']
6+
= Building an Operator with Helm charts using the Operator SDK
7+
8+
This procedure walks through an example of building a simple Nginx Operator
9+
powered by a Helm chart using tools and libraries provided by the Operator SDK.
10+
11+
[TIP]
12+
====
13+
It is best practice to build a new Operator for each chart. This can allow for
14+
more native-behaving Kubernetes APIs (e.g., `oc get Nginx`) and flexibility if
15+
you ever want to write a fully-fledged Operator in Go, migrating away from a
16+
Helm-based Operator.
17+
====
18+
19+
.Prerequisites
20+
21+
- Operator SDK CLI installed on the development workstation
22+
- Access to a Kubernetes-based cluster v1.11.3+ (for example {product-title} 4.0)
23+
using an account with `cluster-admin` permissions
24+
- link:https://kubernetes.io/docs/tasks/tools/install-kubectl/[`kubectl`] v1.11.3+
25+
(can alternatively use `oc`)
26+
27+
.Procedure
28+
29+
. *Create a new project.*
30+
+
31+
To create a new Helm-based, namespace-scoped `nginx-operator` project, use the
32+
`operator-sdk new` command:
33+
+
34+
----
35+
$ operator-sdk new nginx-operator \
36+
--api-version=example.com/v1alpha1 --kind=Nginx --type=helm
37+
$ cd nginx-operator
38+
----
39+
+
40+
[TIP]
41+
====
42+
See
43+
xref:operators-appendices.adoc#operator-project-scaffolding-layout_operator-appendices[Appendices]
44+
to learn about the project directory structure created by the previous commands.
45+
====
46+
+
47+
This creates the `nginx-operator` project specifically for watching the Nginx
48+
resource with APIVersion `example.com/v1apha1` and Kind `Nginx`.
49+
+
50+
.Operator scope
51+
+
52+
A namespace-scoped Operator (the default) watches and manages resources in a
53+
single namespace, whereas a cluster-scoped operator watches and manages
54+
resources cluster-wide. Namespace-scoped operators are preferred because of
55+
their flexibility. They enable decoupled upgrades, namespace isolation for
56+
failures and monitoring, and differing API definitions.
57+
+
58+
However, there are use cases where a cluster-scoped operator may make sense. For
59+
example, the `cert-manager` operator is often deployed with cluster-scoped
60+
permissions and watches so that it can manage issuing certificates for an entire
61+
cluster.
62+
+
63+
If you would like to create your `nginx-operator` project to be cluster-scoped,
64+
use the following `operator-sdk new` command instead:
65+
+
66+
----
67+
$ operator-sdk new nginx-operator \
68+
--cluster-scoped --api-version=example.com/v1alpha1 \
69+
--kind=Nginx --type=helm
70+
----
71+
+
72+
Using the `--cluster-scoped` flag will scaffold the new Operator with the
73+
following modifications:
74+
+
75+
--
76+
* `deploy/operator.yaml`: Set `WATCH_NAMESPACE=""` instead of setting it to the
77+
Pod's namespace.
78+
* `deploy/role.yaml`: Use `ClusterRole` instead of `Role`.
79+
* `deploy/role_binding.yaml`:
80+
** Use `ClusterRoleBinding` instead of `RoleBinding`.
81+
** Set the subject namespace to `REPLACE_NAMESPACE`. This must be changed to the
82+
namespace in which the Operator is deployed.
83+
--
84+
85+
. *Customize the Operator logic.*
86+
+
87+
For this example, the `nginx-operator` executes the following reconciliation
88+
logic for each Nginx Custom Resource (CR):
89+
+
90+
--
91+
* Create a Nginx Deployment if it does not exist.
92+
* Create a Nginx Service if it does not exist.
93+
* Create a Nginx Ingress if it is enabled and does not exist.
94+
* Ensure that the Deployment, Service, and optional Ingress match the desired
95+
configuration (e.g., replica count, image, service type) as specified by the
96+
Nginx CR.
97+
--
98+
+
99+
By default, the `nginx-operator` watches `Nginx` resource events as shown in the
100+
`watches.yaml` file and executes Helm releases using the specified chart:
101+
+
102+
----
103+
---
104+
- version: v1alpha1
105+
group: example.com
106+
kind: Nginx
107+
chart: /opt/helm/helm-charts/nginx
108+
----
109+
110+
.. *Review the Nginx Helm chart.*
111+
+
112+
When a Helm Operator project is created, the Operator SDK creates an example Helm chart that contains a set of templates for a simple Nginx release.
113+
+
114+
For this example, templates are available for Deployment, Service, and Ingress
115+
resources, along with a `NOTES.txt` template, which Helm chart developers use to
116+
convey helpful information about a release.
117+
+
118+
If you are not already familiar with Helm Charts, take a moment to review the
119+
link:https://docs.helm.sh/developing_charts/[Helm Chart developer documentation].
120+
121+
.. *Understand the Nginx CR spec.*
122+
+
123+
Helm uses a concept called
124+
link:https://docs.helm.sh/using_helm/#customizing-the-chart-before-installing[values]
125+
to provide customizations to a Helm chart's defaults, which are defined in the
126+
Helm chart's `values.yaml` file.
127+
+
128+
Override these defaults by setting the desired values in the CR spec. You can
129+
use the number of replicas as an example:
130+
131+
... First, inspect the `helm-charts/nginx/values.yaml` file to find that the chart
132+
has a value called `replicaCount` and it is set to `1` by default. To have 2
133+
Nginx instances in your deployment, your CR spec must contain `replicaCount: 2`.
134+
+
135+
Update the `deploy/crds/example_v1alpha1_nginx_cr.yaml` file to look like the
136+
following:
137+
+
138+
----
139+
apiVersion: example.com/v1alpha1
140+
kind: Nginx
141+
metadata:
142+
name: example-nginx
143+
spec:
144+
replicaCount: 2
145+
----
146+
147+
... Similarly, the default service port is set to `80`. To instead use `8080`,
148+
update the `deploy/crds/example_v1alpha1_nginx_cr.yaml` file again by adding the
149+
service port override:
150+
+
151+
----
152+
apiVersion: example.com/v1alpha1
153+
kind: Nginx
154+
metadata:
155+
name: example-nginx
156+
spec:
157+
replicaCount: 2
158+
service:
159+
port: 8080
160+
----
161+
+
162+
The Helm Operator applies the entire spec as if it was the contents of a values
163+
file, just like the `helm install -f ./overrides.yaml` command works.
164+
165+
. *Deploy the CRD.*
166+
+
167+
Before running the Operator, Kubernetes needs to know about the new custom
168+
resource definition (CRD) the operator will be watching. Deploy the following CRD:
169+
+
170+
----
171+
$ kubectl create -f deploy/crds/example_v1alpha1_nginx_crd.yaml
172+
----
173+
174+
. *Build and run the Operator.*
175+
+
176+
There are two ways to build and run the Operator:
177+
+
178+
--
179+
* As a Pod inside a Kubernetes cluster.
180+
* As a Go program outside the cluster using the `operator-sdk up` command.
181+
--
182+
+
183+
Choose one of the following methods.
184+
185+
.. _Option 1:_ Run as a Pod inside a Kubernetes cluster. This is the preferred
186+
method for production use.
187+
+
188+
Build the `nginx-operator` image and push it to a registry:
189+
+
190+
----
191+
$ operator-sdk build quay.io/example/nginx-operator:v0.0.1
192+
$ docker push quay.io/example/nginx-operator:v0.0.1
193+
----
194+
+
195+
Kubernetes deployment manifests are generated in the `deploy/operator.yaml`
196+
file. The deployment image in this file needs to be modified from the
197+
placeholder `REPLACE_IMAGE` to the previous built image. To do this, run:
198+
+
199+
----
200+
$ sed -i 's|REPLACE_IMAGE|quay.io/example/nginx-operator:v0.0.1|g' deploy/operator.yaml
201+
----
202+
+
203+
If you created your Operator using the `--cluster-scoped=true` flag, update the
204+
service account namespace in the generated `ClusterRoleBinding` to match where
205+
you are deploying your Operator:
206+
+
207+
----
208+
$ export OPERATOR_NAMESPACE=$(kubectl config view --minify -o jsonpath='{.contexts[0].context.namespace}')
209+
$ sed -i "s|REPLACE_NAMESPACE|$OPERATOR_NAMESPACE|g" deploy/role_binding.yaml
210+
----
211+
+
212+
[NOTE]
213+
====
214+
If you are performing these steps on OSX, use the following commands instead:
215+
216+
----
217+
$ sed -i "" 's|REPLACE_IMAGE|quay.io/example/nginx-operator:v0.0.1|g' deploy/operator.yaml
218+
$ sed -i "" "s|REPLACE_NAMESPACE|$OPERATOR_NAMESPACE|g" deploy/role_binding.yaml
219+
----
220+
====
221+
+
222+
Deploy the `nginx-operator`:
223+
+
224+
----
225+
$ kubectl create -f deploy/service_account.yaml
226+
$ kubectl create -f deploy/role.yaml
227+
$ kubectl create -f deploy/role_binding.yaml
228+
$ kubectl create -f deploy/operator.yaml
229+
----
230+
+
231+
Verify that the `nginx-operator` is up and running:
232+
+
233+
----
234+
$ kubectl get deployment
235+
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
236+
nginx-operator 1 1 1 1 1m
237+
----
238+
239+
.. _Option 2:_ Run outside the cluster. This method is preferred during the
240+
development cycle to speed up deployment and testing.
241+
+
242+
It is important that the chart path referenced in the `watches.yaml` file exists
243+
on your machine. By default, the `watches.yaml` file is scaffolded to work with
244+
an Operator image built with the `operator-sdk build` command. When developing
245+
and testing your operator with the `operator-sdk up local` command, the SDK
246+
looks in your local file system for this path.
247+
+
248+
It is recommend to create a symlink at this location to point to your Helm
249+
chart's path:
250+
+
251+
----
252+
$ sudo mkdir -p /opt/helm/helm-charts
253+
$ sudo ln -s $PWD/helm-charts/nginx /opt/helm/helm-charts/nginx
254+
----
255+
+
256+
To run the Operator locally with the default Kubernetes configuration file
257+
present at `$HOME/.kube/config`:
258+
+
259+
----
260+
$ operator-sdk up local
261+
INFO[0000] Go Version: go1.10.3
262+
INFO[0000] Go OS/Arch: linux/amd64
263+
INFO[0000] operator-sdk Version: v0.3.0+git
264+
----
265+
+
266+
To run the Operator locally with a provided Kubernetes configuration file:
267+
+
268+
----
269+
$ operator-sdk up local --kubeconfig=<path_to_config>
270+
INFO[0000] Go Version: go1.10.3
271+
INFO[0000] Go OS/Arch: linux/amd64
272+
INFO[0000] operator-sdk Version: v0.3.0+git
273+
----
274+
275+
. *Deploy the Nginx custom resource.*
276+
+
277+
Apply the Nginx CR that you modified earlier:
278+
+
279+
----
280+
$ kubectl apply -f deploy/crds/example_v1alpha1_nginx_cr.yaml
281+
----
282+
+
283+
Ensure that the `nginx-operator` creates the Deployment for the CR:
284+
+
285+
----
286+
$ kubectl get deployment
287+
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
288+
example-nginx-b9phnoz9spckcrua7ihrbkrt1 2 2 2 2 1m
289+
----
290+
+
291+
Check the Pods to confirm two replicas were created:
292+
+
293+
----
294+
$ kubectl get pods
295+
NAME READY STATUS RESTARTS AGE
296+
example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-fjcr9 1/1 Running 0 1m
297+
example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-ljbzl 1/1 Running 0 1m
298+
----
299+
+
300+
Check that the Service port is set to `8080`:
301+
+
302+
----
303+
$ kubectl get service
304+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
305+
example-nginx-b9phnoz9spckcrua7ihrbkrt1 ClusterIP 10.96.26.3 <none> 8080/TCP 1m
306+
----
307+
308+
. *Update the `replicaCount` and remove the port.*
309+
+
310+
Change the `spec.replicaCount` field from `2` to `3`, remove the `spec.service`
311+
field, and apply the change:
312+
+
313+
----
314+
$ cat deploy/crds/example_v1alpha1_nginx_cr.yaml
315+
apiVersion: "example.com/v1alpha1"
316+
kind: "Nginx"
317+
metadata:
318+
name: "example-nginx"
319+
spec:
320+
replicaCount: 3
321+
322+
$ kubectl apply -f deploy/crds/example_v1alpha1_nginx_cr.yaml
323+
----
324+
+
325+
Confirm that the Operator changes the Deployment size:
326+
+
327+
----
328+
$ kubectl get deployment
329+
NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE
330+
example-nginx-b9phnoz9spckcrua7ihrbkrt1 3 3 3 3 1m
331+
----
332+
+
333+
Check that the Service port is set to the default `80`:
334+
+
335+
----
336+
$ kubectl get service
337+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
338+
example-nginx-b9phnoz9spckcrua7ihrbkrt1 ClusterIP 10.96.26.3 <none> 80/TCP 1m
339+
----
340+
341+
. *Clean up the resources:*
342+
+
343+
----
344+
$ kubectl delete -f deploy/crds/example_v1alpha1_nginx_cr.yaml
345+
$ kubectl delete -f deploy/operator.yaml
346+
$ kubectl delete -f deploy/role_binding.yaml
347+
$ kubectl delete -f deploy/role.yaml
348+
$ kubectl delete -f deploy/service_account.yaml
349+
$ kubectl delete -f deploy/crds/example_v1alpha1_nginx_cr.yaml
350+
----

0 commit comments

Comments
 (0)