github.skymusic.top/operator-framework/operator-sdk@v0.8.2/doc/helm/user-guide.md (about) 1 # User Guide 2 3 This guide walks through an example of building a simple nginx-operator powered by Helm using tools and libraries provided by the Operator SDK. 4 5 ## Prerequisites 6 7 - [git][git_tool] 8 - [docker][docker_tool] version 17.03+. 9 - [kubectl][kubectl_tool] version v1.11.3+. 10 - [dep][dep_tool] version v0.5.0+. (Optional if you aren't installing from source) 11 - [go][go_tool] version v1.12+. (Optional if you aren't installing from source) 12 - Access to a Kubernetes v1.11.3+ cluster. 13 14 **Note**: This guide uses [minikube][minikube_tool] version v0.25.0+ as the 15 local Kubernetes cluster and [quay.io][quay_link] for the public registry. 16 17 ## Install the Operator SDK CLI 18 19 Follow the steps in the [installation guide][install_guide] to learn how to install the Operator SDK CLI tool. 20 21 ## Create a new project 22 23 Use the CLI to create a new Helm-based nginx-operator project: 24 25 ```sh 26 operator-sdk new nginx-operator --api-version=example.com/v1alpha1 --kind=Nginx --type=helm 27 cd nginx-operator 28 ``` 29 30 This creates the nginx-operator project specifically for watching the 31 Nginx resource with APIVersion `example.com/v1alpha1` and Kind 32 `Nginx`. 33 34 For Helm-based projects, `operator-sdk new` also generates the RBAC rules 35 in `deploy/role.yaml` based on the resources that would be deployed by the 36 chart's default manifest. Be sure to double check that the rules generated 37 in `deploy/role.yaml` meet the operator's permission requirements. 38 39 To learn more about the project directory structure, see the 40 [project layout][layout_doc] doc. 41 42 ### Use an existing chart 43 44 Instead of creating your project with a boilerplate Helm chart, you can also use `--helm-chart`, `--helm-chart-repo`, and `--helm-chart-version` to use an existing chart, either from your local filesystem or a remote chart repository. 45 46 If `--helm-chart` is specified, `--api-version` and `--kind` become optional. If left unset, the SDK will default `--api-version` to `charts.helm.k8s.io/v1alpha1` and will deduce `--kind` from the specified chart. 47 48 If `--helm-chart` is a local chart archive or directory, it will be validated and unpacked or copied into the project. 49 50 Otherwise, the SDK will attempt to fetch the specified helm chart from a remote repository. 51 52 If a custom repository URL is not specified by `--helm-chart-repo`, the following chart reference formats are supported: 53 54 - `<repoName>/<chartName>`: Fetch the helm chart named `chartName` from the helm 55 chart repository named `repoName`, as specified in the 56 $HELM_HOME/repositories/repositories.yaml file. 57 58 - `<url>`: Fetch the helm chart archive at the specified URL. 59 60 If a custom repository URL is specified by `--helm-chart-repo`, the only supported format for `--helm-chart` is: 61 62 - `<chartName>`: Fetch the helm chart named `chartName` in the helm chart repository 63 specified by the `--helm-chart-repo` URL. 64 65 If `--helm-chart-version` is not set, the SDK will fetch the latest available version of the helm chart. Otherwise, it will fetch the specified version. `--helm-chart-version` is not used when `--helm-chart` itself refers to a specific version, for example when it is a local path or a URL. 66 67 ### Operator scope 68 69 Read the [operator scope][operator_scope] documentation on how to run your operator as namespace-scoped vs cluster-scoped. 70 71 72 ## Customize the operator logic 73 74 For this example the nginx-operator will execute the following 75 reconciliation logic for each `Nginx` Custom Resource (CR): 76 77 - Create a nginx Deployment if it doesn't exist 78 - Create a nginx Service if it doesn't exist 79 - Create a nginx Ingress if it is enabled and doesn't exist 80 - Ensure that the Deployment, Service, and optional Ingress match the desired configuration (e.g. replica count, image, service type, etc) as specified by the `Nginx` CR 81 82 ### Watch the Nginx CR 83 84 By default, the nginx-operator watches `Nginx` resource events as shown 85 in `watches.yaml` and executes Helm releases using the specified chart: 86 87 ```yaml 88 --- 89 - version: v1alpha1 90 group: example.com 91 kind: Nginx 92 chart: /opt/helm/helm-charts/nginx 93 ``` 94 95 ### Reviewing the Nginx Helm Chart 96 97 When a Helm operator project is created, the SDK creates an example Helm chart 98 that contains a set of templates for a simple Nginx release. 99 100 For this example, we have templates for deployment, service, and ingress 101 resources, along with a NOTES.txt template, which Helm chart developers use 102 to convey helpful information about a release. 103 104 If you aren't already familiar with Helm Charts, take a moment to review 105 the [Helm Chart developer documentation][helm_charts]. 106 107 ### Understanding the Nginx CR spec 108 109 Helm uses a concept called [values][helm_values] to provide customizations 110 to a Helm chart's defaults, which are defined in the Helm chart's `values.yaml` 111 file. 112 113 Overriding these defaults is as simple as setting the desired values in the CR 114 spec. Let's use the number of replicas as an example. 115 116 First, inspecting `helm-charts/nginx/values.yaml`, we see that the chart has a 117 value called `replicaCount` and it is set to `1` by default. If we want to have 118 2 nginx instances in our deployment, we would need to make sure our CR spec 119 contained `replicaCount: 2`. 120 121 Update `deploy/crds/example_v1alpha1_nginx_cr.yaml` to look like the following: 122 123 ```yaml 124 apiVersion: example.com/v1alpha1 125 kind: Nginx 126 metadata: 127 name: example-nginx 128 spec: 129 replicaCount: 2 130 ``` 131 132 Similarly, we see that the default service port is set to `80`, but we would 133 like to use `8080`, so we'll again update `deploy/crds/example_v1alpha1_nginx_cr.yaml` 134 by adding the service port override: 135 136 ```yaml 137 apiVersion: example.com/v1alpha1 138 kind: Nginx 139 metadata: 140 name: example-nginx 141 spec: 142 replicaCount: 2 143 service: 144 port: 8080 145 ``` 146 147 As you may have noticed, the Helm operator simply applies the entire spec as if 148 it was the contents of a values file, just like `helm install -f ./overrides.yaml` 149 works. 150 151 ## Build and run the operator 152 153 Before running the operator, Kubernetes needs to know about the new custom 154 resource definition the operator will be watching. 155 156 Deploy the CRD: 157 158 ```sh 159 kubectl create -f deploy/crds/example_v1alpha1_nginx_crd.yaml 160 ``` 161 162 Once this is done, there are two ways to run the operator: 163 164 - As a pod inside a Kubernetes cluster 165 - As a go program outside the cluster using `operator-sdk` 166 167 ### 1. Run as a pod inside a Kubernetes cluster 168 169 Running as a pod inside a Kubernetes cluster is preferred for production use. 170 171 Build the nginx-operator image and push it to a registry: 172 173 ```sh 174 operator-sdk build quay.io/example/nginx-operator:v0.0.1 175 docker push quay.io/example/nginx-operator:v0.0.1 176 ``` 177 178 Kubernetes deployment manifests are generated in `deploy/operator.yaml`. The 179 deployment image in this file needs to be modified from the placeholder 180 `REPLACE_IMAGE` to the previous built image. To do this run: 181 182 ```sh 183 sed -i 's|REPLACE_IMAGE|quay.io/example/nginx-operator:v0.0.1|g' deploy/operator.yaml 184 ``` 185 186 If you created your operator using `--cluster-scoped=true`, update the service account namespace in the generated `ClusterRoleBinding` to match where you are deploying your operator. 187 188 ```sh 189 export OPERATOR_NAMESPACE=$(kubectl config view --minify -o jsonpath='{.contexts[0].context.namespace}') 190 sed -i "s|REPLACE_NAMESPACE|$OPERATOR_NAMESPACE|g" deploy/role_binding.yaml 191 ``` 192 193 **Note** 194 If you are performing these steps on OSX, use the following commands instead: 195 196 ```sh 197 sed -i "" 's|REPLACE_IMAGE|quay.io/example/nginx-operator:v0.0.1|g' deploy/operator.yaml 198 sed -i "" "s|REPLACE_NAMESPACE|$OPERATOR_NAMESPACE|g" deploy/role_binding.yaml 199 ``` 200 201 Deploy the nginx-operator: 202 203 ```sh 204 kubectl create -f deploy/service_account.yaml 205 kubectl create -f deploy/role.yaml 206 kubectl create -f deploy/role_binding.yaml 207 kubectl create -f deploy/operator.yaml 208 ``` 209 210 Verify that the nginx-operator is up and running: 211 212 ```sh 213 $ kubectl get deployment 214 NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE 215 nginx-operator 1 1 1 1 1m 216 ``` 217 218 ### 2. Run outside the cluster 219 220 This method is preferred during the development cycle to speed up deployment and testing. 221 222 It is important that the `chart` path referenced in `watches.yaml` exists 223 on your machine. By default, the `watches.yaml` file is scaffolded to work with 224 an operator image built with `operator-sdk build`. When developing and 225 testing your operator with `operator-sdk up local`, the SDK will look in your 226 local filesystem for this path. The SDK team recommends creating a symlink at 227 this location to point to your helm chart's path: 228 229 ```sh 230 sudo mkdir -p /opt/helm/helm-charts 231 sudo ln -s $PWD/helm-charts/nginx /opt/helm/helm-charts/nginx 232 ``` 233 234 Run the operator locally with the default Kubernetes config file present at 235 `$HOME/.kube/config`: 236 237 ```sh 238 $ operator-sdk up local 239 INFO[0000] Go Version: go1.10.3 240 INFO[0000] Go OS/Arch: linux/amd64 241 INFO[0000] operator-sdk Version: v0.1.1+git 242 ``` 243 244 Run the operator locally with a provided Kubernetes config file: 245 246 ```sh 247 $ operator-sdk up local --kubeconfig=<path_to_config> 248 INFO[0000] Go Version: go1.10.3 249 INFO[0000] Go OS/Arch: linux/amd64 250 INFO[0000] operator-sdk Version: v0.2.0+git 251 ``` 252 253 ## Deploy the Nginx custom resource 254 255 Apply the nginx CR that we modified earlier: 256 257 ```sh 258 kubectl apply -f deploy/crds/example_v1alpha1_nginx_cr.yaml 259 ``` 260 261 Ensure that the nginx-operator creates the deployment for the CR: 262 263 ```sh 264 $ kubectl get deployment 265 NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE 266 example-nginx-b9phnoz9spckcrua7ihrbkrt1 2 2 2 2 1m 267 ``` 268 269 Check the pods to confirm 2 replicas were created: 270 271 ```sh 272 $ kubectl get pods 273 NAME READY STATUS RESTARTS AGE 274 example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-fjcr9 1/1 Running 0 1m 275 example-nginx-b9phnoz9spckcrua7ihrbkrt1-f8f9c875d-ljbzl 1/1 Running 0 1m 276 ``` 277 278 Check that the service port is set to `8080`: 279 280 ```sh 281 $ kubectl get service 282 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 283 example-nginx-b9phnoz9spckcrua7ihrbkrt1 ClusterIP 10.96.26.3 <none> 8080/TCP 1m 284 ``` 285 286 ### Update the replicaCount and remove the port 287 288 Change the `spec.replicaCount` field from 2 to 3, remove the `spec.service` 289 field, and apply the change: 290 291 ```sh 292 $ cat deploy/crds/example_v1alpha1_nginx_cr.yaml 293 apiVersion: "example.com/v1alpha1" 294 kind: "Nginx" 295 metadata: 296 name: "example-nginx" 297 spec: 298 replicaCount: 3 299 300 $ kubectl apply -f deploy/crds/example_v1alpha1_nginx_cr.yaml 301 ``` 302 303 Confirm that the operator changes the deployment size: 304 305 ```sh 306 $ kubectl get deployment 307 NAME DESIRED CURRENT UP-TO-DATE AVAILABLE AGE 308 example-nginx-b9phnoz9spckcrua7ihrbkrt1 3 3 3 3 1m 309 ``` 310 311 Check that the service port is set to the default (`80`): 312 313 ```sh 314 $ kubectl get service 315 NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE 316 example-nginx-b9phnoz9spckcrua7ihrbkrt1 ClusterIP 10.96.26.3 <none> 80/TCP 1m 317 ``` 318 319 ### Cleanup 320 321 Clean up the resources: 322 323 ```sh 324 kubectl delete -f deploy/crds/example_v1alpha1_nginx_cr.yaml 325 kubectl delete -f deploy/operator.yaml 326 kubectl delete -f deploy/role_binding.yaml 327 kubectl delete -f deploy/role.yaml 328 kubectl delete -f deploy/service_account.yaml 329 kubectl delete -f deploy/crds/example_v1alpha1_nginx_crd.yaml 330 ``` 331 332 [operator_scope]:./../operator-scope.md 333 [install_guide]: ../user/install-operator-sdk.md 334 [layout_doc]:./project_layout.md 335 [homebrew_tool]:https://brew.sh/ 336 [dep_tool]:https://golang.github.io/dep/docs/installation.html 337 [git_tool]:https://git-scm.com/downloads 338 [go_tool]:https://golang.org/dl/ 339 [docker_tool]:https://docs.docker.com/install/ 340 [kubectl_tool]:https://kubernetes.io/docs/tasks/tools/install-kubectl/ 341 [minikube_tool]:https://github.com/kubernetes/minikube#installation 342 [helm_charts]:https://helm.sh/docs/developing_charts/ 343 [helm_values]:https://helm.sh/docs/using_helm/#customizing-the-chart-before-installing 344 [quay_link]:https://quay.io